@axiom-lattice/pg-stores 1.0.82 → 1.0.84

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.
Files changed (34) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +16 -0
  3. package/dist/index.d.mts +124 -44
  4. package/dist/index.d.ts +124 -44
  5. package/dist/index.js +472 -162
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +472 -162
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +3 -3
  10. package/scripts/check-migration-versions.mjs +42 -9
  11. package/src/createPgStoreConfig.ts +97 -3
  12. package/src/migrations/migration.ts +91 -60
  13. package/src/stores/ChannelBindingStore.ts +21 -3
  14. package/src/stores/ChannelIdentityMappingStore.ts +21 -3
  15. package/src/stores/MenuStore.ts +21 -3
  16. package/src/stores/PostgreSQLA2AApiKeyStore.ts +21 -3
  17. package/src/stores/PostgreSQLAssistantStore.ts +19 -3
  18. package/src/stores/PostgreSQLChannelInstallationStore.ts +21 -3
  19. package/src/stores/PostgreSQLDatabaseConfigStore.ts +23 -4
  20. package/src/stores/PostgreSQLEvalStore.ts +15 -3
  21. package/src/stores/PostgreSQLMcpServerConfigStore.ts +23 -4
  22. package/src/stores/PostgreSQLMetricsServerConfigStore.ts +23 -4
  23. package/src/stores/PostgreSQLProjectStore.ts +19 -3
  24. package/src/stores/PostgreSQLScheduleStorage.ts +21 -4
  25. package/src/stores/PostgreSQLSkillStore.ts +14 -3
  26. package/src/stores/PostgreSQLTaskStore.ts +14 -3
  27. package/src/stores/PostgreSQLTenantStore.ts +19 -3
  28. package/src/stores/PostgreSQLThreadStore.ts +19 -3
  29. package/src/stores/PostgreSQLUserStore.ts +18 -4
  30. package/src/stores/PostgreSQLUserTenantLinkStore.ts +18 -4
  31. package/src/stores/PostgreSQLWorkflowTrackingStore.ts +18 -4
  32. package/src/stores/PostgreSQLWorkspaceStore.ts +19 -3
  33. package/src/stores/PostgresSharedResourceStore.ts +21 -3
  34. package/src/stores/ThreadMessageQueueStore.ts +14 -3
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ __export(index_exports, {
34
34
  ChannelIdentityMappingStore: () => ChannelIdentityMappingStore,
35
35
  MenuStore: () => MenuStore,
36
36
  MigrationManager: () => MigrationManager,
37
- Pool: () => import_pg23.Pool,
37
+ Pool: () => import_pg24.Pool,
38
38
  PostgreSQLA2AApiKeyStore: () => PostgreSQLA2AApiKeyStore,
39
39
  PostgreSQLAssistantStore: () => PostgreSQLAssistantStore,
40
40
  PostgreSQLChannelInstallationStore: () => PostgreSQLChannelInstallationStore,
@@ -95,10 +95,10 @@ __export(index_exports, {
95
95
  safeParse: () => safeParse
96
96
  });
97
97
  module.exports = __toCommonJS(index_exports);
98
- var import_pg23 = require("pg");
98
+ var import_pg24 = require("pg");
99
99
 
100
- // src/stores/PostgreSQLThreadStore.ts
101
- var import_pg = require("pg");
100
+ // src/createPgStoreConfig.ts
101
+ var import_pg21 = require("pg");
102
102
 
103
103
  // src/migrations/migration.ts
104
104
  var MigrationManager = class {
@@ -107,39 +107,68 @@ var MigrationManager = class {
107
107
  this.pool = pool;
108
108
  }
109
109
  /**
110
- * Register a migration
110
+ * Register a migration.
111
+ * Duplicate names are rejected immediately (name = identity).
112
+ * Duplicate versions are allowed (version = ordering only).
111
113
  */
112
114
  register(migration) {
115
+ const existing = this.migrations.find((m) => m.name === migration.name);
116
+ if (existing) {
117
+ throw new Error(
118
+ `Migration name conflict: "${migration.name}" v${migration.version} collides with existing registration at v${existing.version}`
119
+ );
120
+ }
113
121
  this.migrations.push(migration);
114
122
  this.migrations.sort((a, b) => a.version - b.version);
115
123
  }
116
124
  /**
117
- * Initialize migrations table if it doesn't exist
125
+ * Ensure the tracking table exists with the correct schema.
126
+ * Handles migration from old schema (PK on version) to new schema (PK on name).
118
127
  */
119
128
  async ensureMigrationsTable(client) {
120
- await client.query(`
121
- CREATE TABLE IF NOT EXISTS lattice_schema_migrations (
122
- version INTEGER PRIMARY KEY,
123
- name VARCHAR(255) NOT NULL,
124
- applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
129
+ const tableExists = await client.query(`
130
+ SELECT EXISTS (
131
+ SELECT FROM information_schema.tables
132
+ WHERE table_name = 'lattice_schema_migrations'
125
133
  )
126
134
  `);
135
+ if (!tableExists.rows[0].exists) {
136
+ await client.query(`
137
+ CREATE TABLE lattice_schema_migrations (
138
+ name VARCHAR(255) PRIMARY KEY,
139
+ version INTEGER NOT NULL,
140
+ applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
141
+ )
142
+ `);
143
+ return;
144
+ }
145
+ const pkCheck = await client.query(`
146
+ SELECT a.attname AS column_name, con.conname AS constraint_name
147
+ FROM pg_index i
148
+ JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
149
+ JOIN pg_constraint con ON con.conindid = i.indexrelid
150
+ WHERE i.indrelid = 'lattice_schema_migrations'::regclass
151
+ AND i.indisprimary
152
+ `);
153
+ const pkColumn = pkCheck.rows[0]?.column_name;
154
+ const constraintName = pkCheck.rows[0]?.constraint_name;
155
+ if (pkColumn === "version" && constraintName) {
156
+ await client.query(
157
+ `ALTER TABLE lattice_schema_migrations DROP CONSTRAINT ${constraintName}`
158
+ );
159
+ await client.query(
160
+ `ALTER TABLE lattice_schema_migrations ADD PRIMARY KEY (name)`
161
+ );
162
+ }
127
163
  }
128
164
  /**
129
- * Get applied migrations from database
165
+ * Get the set of already-applied migration names from the tracking table.
130
166
  */
131
- async getAppliedMigrations(client) {
132
- await client.query(`
133
- CREATE TABLE IF NOT EXISTS lattice_schema_migrations (
134
- version INTEGER PRIMARY KEY,
135
- name VARCHAR(255) NOT NULL,
136
- applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
137
- )
138
- `);
167
+ async getAppliedNames(client) {
139
168
  const result = await client.query(
140
- "SELECT version, name, applied_at FROM lattice_schema_migrations ORDER BY version"
169
+ "SELECT name, version, applied_at FROM lattice_schema_migrations ORDER BY version"
141
170
  );
142
- return result.rows;
171
+ return new Set(result.rows.map((r) => r.name));
143
172
  }
144
173
  /**
145
174
  * Apply pending migrations
@@ -153,10 +182,9 @@ var MigrationManager = class {
153
182
  try {
154
183
  await client.query("BEGIN");
155
184
  await this.ensureMigrationsTable(client);
156
- const appliedMigrations = await this.getAppliedMigrations(client);
157
- const appliedVersions = new Set(appliedMigrations.map((m) => m.version));
185
+ const appliedNames = await this.getAppliedNames(client);
158
186
  const pendingMigrations = this.migrations.filter(
159
- (m) => !appliedVersions.has(m.version)
187
+ (m) => !appliedNames.has(m.name)
160
188
  );
161
189
  if (pendingMigrations.length === 0) {
162
190
  console.log("No pending migrations");
@@ -165,12 +193,12 @@ var MigrationManager = class {
165
193
  }
166
194
  for (const migration of pendingMigrations) {
167
195
  console.log(
168
- `Applying migration ${migration.version}: ${migration.name}`
196
+ `Applying migration v${migration.version}: ${migration.name}`
169
197
  );
170
198
  await migration.up(client);
171
199
  await client.query(
172
- "INSERT INTO lattice_schema_migrations (version, name) VALUES ($1, $2) ON CONFLICT (version) DO NOTHING",
173
- [migration.version, migration.name]
200
+ "INSERT INTO lattice_schema_migrations (name, version) VALUES ($1, $2) ON CONFLICT (name) DO NOTHING",
201
+ [migration.name, migration.version]
174
202
  );
175
203
  }
176
204
  await client.query("COMMIT");
@@ -186,34 +214,37 @@ var MigrationManager = class {
186
214
  }
187
215
  }
188
216
  /**
189
- * Rollback last migration
217
+ * Rollback the last-applied migration (highest version).
190
218
  */
191
219
  async rollback() {
192
220
  const client = await this.pool.connect();
193
221
  try {
194
222
  await client.query("BEGIN");
195
- const appliedMigrations = await this.getAppliedMigrations(client);
196
- if (appliedMigrations.length === 0) {
223
+ await this.ensureMigrationsTable(client);
224
+ const result = await client.query(
225
+ "SELECT name, version FROM lattice_schema_migrations ORDER BY version DESC LIMIT 1"
226
+ );
227
+ if (result.rows.length === 0) {
197
228
  console.log("No migrations to rollback");
198
229
  await client.query("COMMIT");
199
230
  return;
200
231
  }
201
- const lastMigration = appliedMigrations[appliedMigrations.length - 1];
232
+ const lastApplied = result.rows[0];
202
233
  const migration = this.migrations.find(
203
- (m) => m.version === lastMigration.version
234
+ (m) => m.name === lastApplied.name
204
235
  );
205
236
  if (!migration || !migration.down) {
206
237
  throw new Error(
207
- `Migration ${lastMigration.version} does not have a down migration`
238
+ `Migration "${lastApplied.name}" (v${lastApplied.version}) does not have a down migration`
208
239
  );
209
240
  }
210
241
  console.log(
211
- `Rolling back migration ${lastMigration.version}: ${lastMigration.name}`
242
+ `Rolling back migration v${lastApplied.version}: ${lastApplied.name}`
212
243
  );
213
244
  await migration.down(client);
214
245
  await client.query(
215
- "DELETE FROM lattice_schema_migrations WHERE version = $1",
216
- [lastMigration.version]
246
+ "DELETE FROM lattice_schema_migrations WHERE name = $1",
247
+ [lastApplied.name]
217
248
  );
218
249
  await client.query("COMMIT");
219
250
  console.log("Rollback completed");
@@ -225,22 +256,25 @@ var MigrationManager = class {
225
256
  }
226
257
  }
227
258
  /**
228
- * Get current migration version
259
+ * Get the highest applied migration version.
229
260
  */
230
261
  async getCurrentVersion() {
231
262
  const client = await this.pool.connect();
232
263
  try {
233
- const appliedMigrations = await this.getAppliedMigrations(client);
234
- if (appliedMigrations.length === 0) {
235
- return 0;
236
- }
237
- return Math.max(...appliedMigrations.map((m) => m.version));
264
+ await this.ensureMigrationsTable(client);
265
+ const result = await client.query(
266
+ "SELECT COALESCE(MAX(version), 0) AS max FROM lattice_schema_migrations"
267
+ );
268
+ return result.rows[0]?.max ?? 0;
238
269
  } finally {
239
270
  client.release();
240
271
  }
241
272
  }
242
273
  };
243
274
 
275
+ // src/stores/PostgreSQLThreadStore.ts
276
+ var import_pg = require("pg");
277
+
244
278
  // src/migrations/thread_migrations.ts
245
279
  var createThreadsTable = {
246
280
  version: 1,
@@ -381,10 +415,18 @@ var PostgreSQLThreadStore = class {
381
415
  this.initialized = false;
382
416
  this.ownsPool = true;
383
417
  this.initPromise = null;
418
+ if (options.pool) {
419
+ this.pool = options.pool;
420
+ this.ownsPool = false;
421
+ this.initialized = true;
422
+ return;
423
+ }
384
424
  if (typeof options.poolConfig === "string") {
385
425
  this.pool = new import_pg.Pool({ connectionString: options.poolConfig });
386
- } else {
426
+ } else if (options.poolConfig) {
387
427
  this.pool = new import_pg.Pool(options.poolConfig);
428
+ } else {
429
+ throw new Error("Either pool or poolConfig must be provided");
388
430
  }
389
431
  this.migrationManager = new MigrationManager(this.pool);
390
432
  this.migrationManager.register(createThreadsTable);
@@ -727,10 +769,18 @@ var PostgreSQLAssistantStore = class {
727
769
  this.initialized = false;
728
770
  this.ownsPool = true;
729
771
  this.initPromise = null;
772
+ if (options.pool) {
773
+ this.pool = options.pool;
774
+ this.ownsPool = false;
775
+ this.initialized = true;
776
+ return;
777
+ }
730
778
  if (typeof options.poolConfig === "string") {
731
779
  this.pool = new import_pg2.Pool({ connectionString: options.poolConfig });
732
- } else {
780
+ } else if (options.poolConfig) {
733
781
  this.pool = new import_pg2.Pool(options.poolConfig);
782
+ } else {
783
+ throw new Error("Either pool or poolConfig must be provided");
734
784
  }
735
785
  this.migrationManager = new MigrationManager(this.pool);
736
786
  this.migrationManager.register(createAssistantsTable);
@@ -1007,11 +1057,20 @@ var import_core = require("@axiom-lattice/core");
1007
1057
  var PostgreSQLDatabaseConfigStore = class {
1008
1058
  constructor(options) {
1009
1059
  this.initialized = false;
1060
+ this.ownsPool = true;
1010
1061
  this.initPromise = null;
1062
+ if (options.pool) {
1063
+ this.pool = options.pool;
1064
+ this.ownsPool = false;
1065
+ this.initialized = true;
1066
+ return;
1067
+ }
1011
1068
  if (typeof options.poolConfig === "string") {
1012
1069
  this.pool = new import_pg3.Pool({ connectionString: options.poolConfig });
1013
- } else {
1070
+ } else if (options.poolConfig) {
1014
1071
  this.pool = new import_pg3.Pool(options.poolConfig);
1072
+ } else {
1073
+ throw new Error("Either pool or poolConfig must be provided");
1015
1074
  }
1016
1075
  this.migrationManager = new MigrationManager(this.pool);
1017
1076
  this.migrationManager.register(createDatabaseConfigsTable);
@@ -1230,7 +1289,9 @@ var PostgreSQLDatabaseConfigStore = class {
1230
1289
  * Dispose resources and close the connection pool
1231
1290
  */
1232
1291
  async dispose() {
1233
- await this.pool.end();
1292
+ if (this.ownsPool && this.pool) {
1293
+ await this.pool.end();
1294
+ }
1234
1295
  }
1235
1296
  /**
1236
1297
  * Ensure store is initialized
@@ -1321,11 +1382,20 @@ var import_core2 = require("@axiom-lattice/core");
1321
1382
  var PostgreSQLMetricsServerConfigStore = class {
1322
1383
  constructor(options) {
1323
1384
  this.initialized = false;
1385
+ this.ownsPool = true;
1324
1386
  this.initPromise = null;
1387
+ if (options.pool) {
1388
+ this.pool = options.pool;
1389
+ this.ownsPool = false;
1390
+ this.initialized = true;
1391
+ return;
1392
+ }
1325
1393
  if (typeof options.poolConfig === "string") {
1326
1394
  this.pool = new import_pg4.Pool({ connectionString: options.poolConfig });
1327
- } else {
1395
+ } else if (options.poolConfig) {
1328
1396
  this.pool = new import_pg4.Pool(options.poolConfig);
1397
+ } else {
1398
+ throw new Error("Either pool or poolConfig must be provided");
1329
1399
  }
1330
1400
  this.migrationManager = new MigrationManager(this.pool);
1331
1401
  this.migrationManager.register(createMetricsConfigsTable);
@@ -1544,7 +1614,9 @@ var PostgreSQLMetricsServerConfigStore = class {
1544
1614
  * Dispose resources and close the connection pool
1545
1615
  */
1546
1616
  async dispose() {
1547
- await this.pool.end();
1617
+ if (this.ownsPool && this.pool) {
1618
+ await this.pool.end();
1619
+ }
1548
1620
  }
1549
1621
  /**
1550
1622
  * Ensure store is initialized
@@ -1654,11 +1726,20 @@ var import_core3 = require("@axiom-lattice/core");
1654
1726
  var PostgreSQLMcpServerConfigStore = class {
1655
1727
  constructor(options) {
1656
1728
  this.initialized = false;
1729
+ this.ownsPool = true;
1657
1730
  this.initPromise = null;
1731
+ if (options.pool) {
1732
+ this.pool = options.pool;
1733
+ this.ownsPool = false;
1734
+ this.initialized = true;
1735
+ return;
1736
+ }
1658
1737
  if (typeof options.poolConfig === "string") {
1659
1738
  this.pool = new import_pg5.Pool({ connectionString: options.poolConfig });
1660
- } else {
1739
+ } else if (options.poolConfig) {
1661
1740
  this.pool = new import_pg5.Pool(options.poolConfig);
1741
+ } else {
1742
+ throw new Error("Either pool or poolConfig must be provided");
1662
1743
  }
1663
1744
  this.migrationManager = new MigrationManager(this.pool);
1664
1745
  this.migrationManager.register(createMcpServerConfigsTable);
@@ -1893,7 +1974,9 @@ var PostgreSQLMcpServerConfigStore = class {
1893
1974
  * Dispose resources and close the connection pool
1894
1975
  */
1895
1976
  async dispose() {
1896
- await this.pool.end();
1977
+ if (this.ownsPool && this.pool) {
1978
+ await this.pool.end();
1979
+ }
1897
1980
  }
1898
1981
  /**
1899
1982
  * Ensure store is initialized
@@ -1994,10 +2077,18 @@ var PostgreSQLWorkspaceStore = class {
1994
2077
  constructor(options) {
1995
2078
  this.initialized = false;
1996
2079
  this.ownsPool = true;
2080
+ if (options.pool) {
2081
+ this.pool = options.pool;
2082
+ this.ownsPool = false;
2083
+ this.initialized = true;
2084
+ return;
2085
+ }
1997
2086
  if (typeof options.poolConfig === "string") {
1998
2087
  this.pool = new import_pg6.Pool({ connectionString: options.poolConfig });
1999
- } else {
2088
+ } else if (options.poolConfig) {
2000
2089
  this.pool = new import_pg6.Pool(options.poolConfig);
2090
+ } else {
2091
+ throw new Error("Either pool or poolConfig must be provided");
2001
2092
  }
2002
2093
  this.migrationManager = new MigrationManager(this.pool);
2003
2094
  this.migrationManager.register(createWorkspacesTable);
@@ -2237,10 +2328,18 @@ var PostgreSQLProjectStore = class {
2237
2328
  constructor(options) {
2238
2329
  this.initialized = false;
2239
2330
  this.ownsPool = true;
2331
+ if (options.pool) {
2332
+ this.pool = options.pool;
2333
+ this.ownsPool = false;
2334
+ this.initialized = true;
2335
+ return;
2336
+ }
2240
2337
  if (typeof options.poolConfig === "string") {
2241
2338
  this.pool = new import_pg7.Pool({ connectionString: options.poolConfig });
2242
- } else {
2339
+ } else if (options.poolConfig) {
2243
2340
  this.pool = new import_pg7.Pool(options.poolConfig);
2341
+ } else {
2342
+ throw new Error("Either pool or poolConfig must be provided");
2244
2343
  }
2245
2344
  this.migrationManager = new MigrationManager(this.pool);
2246
2345
  this.migrationManager.register(createProjectsTable);
@@ -2487,10 +2586,19 @@ var addUserStatusColumn = {
2487
2586
  var PostgreSQLUserStore = class {
2488
2587
  constructor(options) {
2489
2588
  this.initialized = false;
2589
+ this.ownsPool = true;
2590
+ if (options.pool) {
2591
+ this.pool = options.pool;
2592
+ this.ownsPool = false;
2593
+ this.initialized = true;
2594
+ return;
2595
+ }
2490
2596
  if (typeof options.poolConfig === "string") {
2491
2597
  this.pool = new import_pg8.Pool({ connectionString: options.poolConfig });
2492
- } else {
2598
+ } else if (options.poolConfig) {
2493
2599
  this.pool = new import_pg8.Pool(options.poolConfig);
2600
+ } else {
2601
+ throw new Error("Either pool or poolConfig must be provided");
2494
2602
  }
2495
2603
  this.migrationManager = new MigrationManager(this.pool);
2496
2604
  this.migrationManager.register(createUsersTable);
@@ -2503,7 +2611,9 @@ var PostgreSQLUserStore = class {
2503
2611
  }
2504
2612
  }
2505
2613
  async dispose() {
2506
- await this.pool.end();
2614
+ if (this.ownsPool && this.pool) {
2615
+ await this.pool.end();
2616
+ }
2507
2617
  }
2508
2618
  async initialize() {
2509
2619
  if (this.initialized) return;
@@ -2676,10 +2786,18 @@ var PostgreSQLTenantStore = class {
2676
2786
  constructor(options) {
2677
2787
  this.initialized = false;
2678
2788
  this.ownsPool = true;
2789
+ if (options.pool) {
2790
+ this.pool = options.pool;
2791
+ this.ownsPool = false;
2792
+ this.initialized = true;
2793
+ return;
2794
+ }
2679
2795
  if (typeof options.poolConfig === "string") {
2680
2796
  this.pool = new import_pg9.Pool({ connectionString: options.poolConfig });
2681
- } else {
2797
+ } else if (options.poolConfig) {
2682
2798
  this.pool = new import_pg9.Pool(options.poolConfig);
2799
+ } else {
2800
+ throw new Error("Either pool or poolConfig must be provided");
2683
2801
  }
2684
2802
  this.migrationManager = new MigrationManager(this.pool);
2685
2803
  this.migrationManager.register(createTenantsTable);
@@ -2929,10 +3047,19 @@ var migrateRemoveTenantIdFromUsers = {
2929
3047
  var PostgreSQLUserTenantLinkStore = class {
2930
3048
  constructor(options) {
2931
3049
  this.initialized = false;
3050
+ this.ownsPool = true;
3051
+ if (options.pool) {
3052
+ this.pool = options.pool;
3053
+ this.ownsPool = false;
3054
+ this.initialized = true;
3055
+ return;
3056
+ }
2932
3057
  if (typeof options.poolConfig === "string") {
2933
3058
  this.pool = new import_pg10.Pool({ connectionString: options.poolConfig });
2934
- } else {
3059
+ } else if (options.poolConfig) {
2935
3060
  this.pool = new import_pg10.Pool(options.poolConfig);
3061
+ } else {
3062
+ throw new Error("Either pool or poolConfig must be provided");
2936
3063
  }
2937
3064
  this.migrationManager = new MigrationManager(this.pool);
2938
3065
  this.migrationManager.register(createUserTenantLinkTable);
@@ -2945,7 +3072,9 @@ var PostgreSQLUserTenantLinkStore = class {
2945
3072
  }
2946
3073
  }
2947
3074
  async dispose() {
2948
- await this.pool.end();
3075
+ if (this.ownsPool && this.pool) {
3076
+ await this.pool.end();
3077
+ }
2949
3078
  }
2950
3079
  async initialize() {
2951
3080
  if (this.initialized) return;
@@ -3174,11 +3303,20 @@ var addStepThreadId = {
3174
3303
  var PostgreSQLWorkflowTrackingStore = class {
3175
3304
  constructor(options) {
3176
3305
  this.initialized = false;
3306
+ this.ownsPool = true;
3177
3307
  this.initPromise = null;
3308
+ if (options.pool) {
3309
+ this.pool = options.pool;
3310
+ this.ownsPool = false;
3311
+ this.initialized = true;
3312
+ return;
3313
+ }
3178
3314
  if (typeof options.poolConfig === "string") {
3179
3315
  this.pool = new import_pg11.Pool({ connectionString: options.poolConfig });
3180
- } else {
3316
+ } else if (options.poolConfig) {
3181
3317
  this.pool = new import_pg11.Pool(options.poolConfig);
3318
+ } else {
3319
+ throw new Error("Either pool or poolConfig must be provided");
3182
3320
  }
3183
3321
  this.migrationManager = new MigrationManager(this.pool);
3184
3322
  this.migrationManager.register(createWorkflowTrackingTables);
@@ -3191,7 +3329,9 @@ var PostgreSQLWorkflowTrackingStore = class {
3191
3329
  }
3192
3330
  }
3193
3331
  async dispose() {
3194
- await this.pool.end();
3332
+ if (this.ownsPool && this.pool) {
3333
+ await this.pool.end();
3334
+ }
3195
3335
  }
3196
3336
  async initialize() {
3197
3337
  if (this.initialized) return;
@@ -3680,10 +3820,18 @@ var PostgreSQLEvalStore = class {
3680
3820
  this.initialized = false;
3681
3821
  this.ownsPool = true;
3682
3822
  this.initPromise = null;
3823
+ if (options.pool) {
3824
+ this.pool = options.pool;
3825
+ this.ownsPool = false;
3826
+ this.initialized = true;
3827
+ return;
3828
+ }
3683
3829
  if (typeof options.poolConfig === "string") {
3684
3830
  this.pool = new import_pg12.Pool({ connectionString: options.poolConfig });
3685
- } else {
3831
+ } else if (options.poolConfig) {
3686
3832
  this.pool = new import_pg12.Pool(options.poolConfig);
3833
+ } else {
3834
+ throw new Error("Either pool or poolConfig must be provided");
3687
3835
  }
3688
3836
  this.migrationManager = new MigrationManager(this.pool);
3689
3837
  for (const m of evalMigrations) {
@@ -4546,10 +4694,18 @@ var ThreadMessageQueueStore = class {
4546
4694
  this.ownsPool = true;
4547
4695
  this.initialized = false;
4548
4696
  this.initPromise = null;
4697
+ if (options.pool) {
4698
+ this.pool = options.pool;
4699
+ this.ownsPool = false;
4700
+ this.initialized = true;
4701
+ return;
4702
+ }
4549
4703
  if (typeof options.poolConfig === "string") {
4550
4704
  this.pool = new import_pg13.Pool({ connectionString: options.poolConfig });
4551
- } else {
4705
+ } else if (options.poolConfig) {
4552
4706
  this.pool = new import_pg13.Pool(options.poolConfig);
4707
+ } else {
4708
+ throw new Error("Either pool or poolConfig must be provided");
4553
4709
  }
4554
4710
  this.migrationManager = new MigrationManager(this.pool);
4555
4711
  this.migrationManager.register(createThreadMessageQueueTable);
@@ -4788,8 +4944,17 @@ var createChannelBindingsTable = {
4788
4944
  var ChannelBindingStore = class {
4789
4945
  constructor(options) {
4790
4946
  this.initialized = false;
4947
+ this.ownsPool = true;
4791
4948
  this.initPromise = null;
4792
- this.pool = typeof options.poolConfig === "string" ? new import_pg14.Pool({ connectionString: options.poolConfig }) : new import_pg14.Pool(options.poolConfig);
4949
+ if (options.pool) {
4950
+ this.pool = options.pool;
4951
+ this.ownsPool = false;
4952
+ this.initialized = true;
4953
+ return;
4954
+ }
4955
+ this.pool = typeof options.poolConfig === "string" ? new import_pg14.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg14.Pool(options.poolConfig) : (() => {
4956
+ throw new Error("Either pool or poolConfig must be provided");
4957
+ })();
4793
4958
  this.migrationManager = new MigrationManager(this.pool);
4794
4959
  this.migrationManager.register(createChannelBindingsTable);
4795
4960
  if (options.autoMigrate !== false) {
@@ -4812,6 +4977,11 @@ var ChannelBindingStore = class {
4812
4977
  })();
4813
4978
  return this.initPromise;
4814
4979
  }
4980
+ async dispose() {
4981
+ if (this.ownsPool && this.pool) {
4982
+ await this.pool.end();
4983
+ }
4984
+ }
4815
4985
  async resolve(params) {
4816
4986
  await this.ensureInitialized();
4817
4987
  const result = await this.pool.query(
@@ -5035,8 +5205,17 @@ var import_core4 = require("@axiom-lattice/core");
5035
5205
  var PostgreSQLChannelInstallationStore = class {
5036
5206
  constructor(options) {
5037
5207
  this.initialized = false;
5208
+ this.ownsPool = true;
5038
5209
  this.initPromise = null;
5039
- this.pool = typeof options.poolConfig === "string" ? new import_pg15.Pool({ connectionString: options.poolConfig }) : new import_pg15.Pool(options.poolConfig);
5210
+ if (options.pool) {
5211
+ this.pool = options.pool;
5212
+ this.ownsPool = false;
5213
+ this.initialized = true;
5214
+ return;
5215
+ }
5216
+ this.pool = typeof options.poolConfig === "string" ? new import_pg15.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg15.Pool(options.poolConfig) : (() => {
5217
+ throw new Error("Either pool or poolConfig must be provided");
5218
+ })();
5040
5219
  this.migrationManager = new MigrationManager(this.pool);
5041
5220
  this.migrationManager.register(createChannelInstallationsTable);
5042
5221
  this.migrationManager.register(alterChannelInstallationsTable);
@@ -5067,6 +5246,11 @@ var PostgreSQLChannelInstallationStore = class {
5067
5246
  })();
5068
5247
  return this.initPromise;
5069
5248
  }
5249
+ async dispose() {
5250
+ if (this.ownsPool && this.pool) {
5251
+ await this.pool.end();
5252
+ }
5253
+ }
5070
5254
  async getInstallationById(installationId) {
5071
5255
  await this.ensureInitialized();
5072
5256
  const result = await this.pool.query(
@@ -5311,8 +5495,17 @@ function mapRowToRecord(row) {
5311
5495
  var PostgreSQLA2AApiKeyStore = class {
5312
5496
  constructor(options) {
5313
5497
  this.initialized = false;
5498
+ this.ownsPool = true;
5314
5499
  this.initPromise = null;
5315
- this.pool = typeof options.poolConfig === "string" ? new import_pg16.Pool({ connectionString: options.poolConfig }) : new import_pg16.Pool(options.poolConfig);
5500
+ if (options.pool) {
5501
+ this.pool = options.pool;
5502
+ this.ownsPool = false;
5503
+ this.initialized = true;
5504
+ return;
5505
+ }
5506
+ this.pool = typeof options.poolConfig === "string" ? new import_pg16.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg16.Pool(options.poolConfig) : (() => {
5507
+ throw new Error("Either pool or poolConfig must be provided");
5508
+ })();
5316
5509
  this.migrationManager = new MigrationManager(this.pool);
5317
5510
  this.migrationManager.register(createA2AApiKeysTable);
5318
5511
  if (options.autoMigrate !== false) {
@@ -5335,6 +5528,11 @@ var PostgreSQLA2AApiKeyStore = class {
5335
5528
  })();
5336
5529
  return this.initPromise;
5337
5530
  }
5531
+ async dispose() {
5532
+ if (this.ownsPool && this.pool) {
5533
+ await this.pool.end();
5534
+ }
5535
+ }
5338
5536
  async ensureInitialized() {
5339
5537
  if (!this.initialized) await this.initialize();
5340
5538
  }
@@ -5598,10 +5796,19 @@ var addScheduleTenantId = {
5598
5796
  var PostgreSQLScheduleStorage = class {
5599
5797
  constructor(options) {
5600
5798
  this.initialized = false;
5799
+ this.ownsPool = true;
5800
+ if (options.pool) {
5801
+ this.pool = options.pool;
5802
+ this.ownsPool = false;
5803
+ this.initialized = true;
5804
+ return;
5805
+ }
5601
5806
  if (typeof options.poolConfig === "string") {
5602
5807
  this.pool = new import_pg17.Pool({ connectionString: options.poolConfig });
5603
- } else {
5808
+ } else if (options.poolConfig) {
5604
5809
  this.pool = new import_pg17.Pool(options.poolConfig);
5810
+ } else {
5811
+ throw new Error("Either pool or poolConfig must be provided");
5605
5812
  }
5606
5813
  this.migrationManager = new MigrationManager(this.pool);
5607
5814
  this.migrationManager.register(createScheduledTasksTable);
@@ -5617,7 +5824,7 @@ var PostgreSQLScheduleStorage = class {
5617
5824
  * Dispose resources and close the connection pool
5618
5825
  */
5619
5826
  async dispose() {
5620
- if (this.pool) {
5827
+ if (this.ownsPool && this.pool) {
5621
5828
  await this.pool.end();
5622
5829
  }
5623
5830
  }
@@ -6111,10 +6318,18 @@ var PostgreSQLTaskStore = class {
6111
6318
  this.initialized = false;
6112
6319
  this.ownsPool = true;
6113
6320
  this.initPromise = null;
6321
+ if (options.pool) {
6322
+ this.pool = options.pool;
6323
+ this.ownsPool = false;
6324
+ this.initialized = true;
6325
+ return;
6326
+ }
6114
6327
  if (typeof options.poolConfig === "string") {
6115
6328
  this.pool = new import_pg18.Pool({ connectionString: options.poolConfig });
6116
- } else {
6329
+ } else if (options.poolConfig) {
6117
6330
  this.pool = new import_pg18.Pool(options.poolConfig);
6331
+ } else {
6332
+ throw new Error("Either pool or poolConfig must be provided");
6118
6333
  }
6119
6334
  this.migrationManager = new MigrationManager(this.pool);
6120
6335
  this.migrationManager.register(createTasksTable);
@@ -6378,8 +6593,17 @@ var addFileContentType = {
6378
6593
  var MenuStore = class {
6379
6594
  constructor(options) {
6380
6595
  this.initialized = false;
6596
+ this.ownsPool = true;
6381
6597
  this.initPromise = null;
6382
- this.pool = typeof options.poolConfig === "string" ? new import_pg19.Pool({ connectionString: options.poolConfig }) : new import_pg19.Pool(options.poolConfig);
6598
+ if (options.pool) {
6599
+ this.pool = options.pool;
6600
+ this.ownsPool = false;
6601
+ this.initialized = true;
6602
+ return;
6603
+ }
6604
+ this.pool = typeof options.poolConfig === "string" ? new import_pg19.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg19.Pool(options.poolConfig) : (() => {
6605
+ throw new Error("Either pool or poolConfig must be provided");
6606
+ })();
6383
6607
  this.migrationManager = new MigrationManager(this.pool);
6384
6608
  this.migrationManager.register(createMenuItemsTable);
6385
6609
  this.migrationManager.register(addFileContentType);
@@ -6403,6 +6627,11 @@ var MenuStore = class {
6403
6627
  })();
6404
6628
  return this.initPromise;
6405
6629
  }
6630
+ async dispose() {
6631
+ if (this.ownsPool && this.pool) {
6632
+ await this.pool.end();
6633
+ }
6634
+ }
6406
6635
  async list(params) {
6407
6636
  await this.ensureInitialized();
6408
6637
  const conditions = ["tenant_id = $1"];
@@ -6573,8 +6802,17 @@ var createSharedResourcesTable = {
6573
6802
  var PostgresSharedResourceStore = class {
6574
6803
  constructor(options) {
6575
6804
  this.initialized = false;
6805
+ this.ownsPool = true;
6576
6806
  this.initPromise = null;
6577
- this.pool = typeof options.poolConfig === "string" ? new import_pg20.Pool({ connectionString: options.poolConfig }) : new import_pg20.Pool(options.poolConfig);
6807
+ if (options.pool) {
6808
+ this.pool = options.pool;
6809
+ this.ownsPool = false;
6810
+ this.initialized = true;
6811
+ return;
6812
+ }
6813
+ this.pool = typeof options.poolConfig === "string" ? new import_pg20.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg20.Pool(options.poolConfig) : (() => {
6814
+ throw new Error("Either pool or poolConfig must be provided");
6815
+ })();
6578
6816
  this.migrationManager = new MigrationManager(this.pool);
6579
6817
  this.migrationManager.register(createSharedResourcesTable);
6580
6818
  if (options.autoMigrate !== false) {
@@ -6600,6 +6838,11 @@ var PostgresSharedResourceStore = class {
6600
6838
  })();
6601
6839
  return this.initPromise;
6602
6840
  }
6841
+ async dispose() {
6842
+ if (this.ownsPool && this.pool) {
6843
+ await this.pool.end();
6844
+ }
6845
+ }
6603
6846
  async findByToken(token) {
6604
6847
  await this.ensureInitialized();
6605
6848
  const { rows } = await this.pool.query(
@@ -6737,39 +6980,6 @@ var PostgresSharedResourceStore = class {
6737
6980
 
6738
6981
  // src/createPgStoreConfig.ts
6739
6982
  var import_langgraph_checkpoint_postgres = require("@langchain/langgraph-checkpoint-postgres");
6740
- function createPgStoreConfig(connectionString) {
6741
- const opts = { poolConfig: connectionString, autoMigrate: true };
6742
- const checkpoint = import_langgraph_checkpoint_postgres.PostgresSaver.fromConnString(connectionString);
6743
- checkpoint.setup().catch((err) => {
6744
- console.error("[pg-stores] Failed to setup checkpoint table:", err.message || err);
6745
- });
6746
- return {
6747
- workspace: new PostgreSQLWorkspaceStore(opts),
6748
- project: new PostgreSQLProjectStore(opts),
6749
- eval: new PostgreSQLEvalStore(opts),
6750
- user: new PostgreSQLUserStore(opts),
6751
- tenant: new PostgreSQLTenantStore(opts),
6752
- userTenantLink: new PostgreSQLUserTenantLinkStore(opts),
6753
- channelBinding: new ChannelBindingStore(opts),
6754
- channelInstallation: new PostgreSQLChannelInstallationStore(opts),
6755
- thread: new PostgreSQLThreadStore(opts),
6756
- database: new PostgreSQLDatabaseConfigStore(opts),
6757
- metrics: new PostgreSQLMetricsServerConfigStore(opts),
6758
- mcp: new PostgreSQLMcpServerConfigStore(opts),
6759
- assistant: new PostgreSQLAssistantStore(opts),
6760
- workflowTracking: new PostgreSQLWorkflowTrackingStore(opts),
6761
- threadMessageQueue: new ThreadMessageQueueStore(opts),
6762
- task: new PostgreSQLTaskStore(opts),
6763
- a2aApiKey: new PostgreSQLA2AApiKeyStore(opts),
6764
- schedule: new PostgreSQLScheduleStorage(opts),
6765
- menu: new MenuStore(opts),
6766
- sharedResource: new PostgresSharedResourceStore(opts),
6767
- checkpoint
6768
- };
6769
- }
6770
-
6771
- // src/stores/PostgreSQLSkillStore.ts
6772
- var import_pg21 = require("pg");
6773
6983
 
6774
6984
  // src/migrations/skill_migrations.ts
6775
6985
  var createSkillsTable = {
@@ -6924,16 +7134,157 @@ var changeSkillPrimaryKey = {
6924
7134
  }
6925
7135
  };
6926
7136
 
7137
+ // src/migrations/channel_identity_mapping_migration.ts
7138
+ var createChannelIdentityMappingTables = {
7139
+ version: 20,
7140
+ name: "create_channel_identity_mapping_tables",
7141
+ up: async (client) => {
7142
+ await client.query(`
7143
+ CREATE TABLE IF NOT EXISTS channel_identity_mappings (
7144
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
7145
+ channel VARCHAR(50) NOT NULL,
7146
+ channel_app_id VARCHAR(255) NOT NULL,
7147
+ tenant_id VARCHAR(255) NOT NULL,
7148
+ assistant_id VARCHAR(255) NOT NULL,
7149
+ mapping_mode VARCHAR(20) NOT NULL CHECK (mapping_mode IN ('user', 'group', 'hybrid')),
7150
+ external_subject_type VARCHAR(20) NOT NULL CHECK (external_subject_type IN ('user', 'chat')),
7151
+ external_subject_key VARCHAR(512) NOT NULL,
7152
+ lark_open_id VARCHAR(255),
7153
+ lark_chat_id VARCHAR(255) NOT NULL,
7154
+ lark_message_id VARCHAR(255),
7155
+ thread_id VARCHAR(255) NOT NULL,
7156
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7157
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7158
+ last_activity_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7159
+ UNIQUE (channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7160
+ )
7161
+ `);
7162
+ await client.query(`
7163
+ CREATE INDEX IF NOT EXISTS idx_channel_identity_lookup
7164
+ ON channel_identity_mappings(channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7165
+ `);
7166
+ await client.query(`
7167
+ CREATE INDEX IF NOT EXISTS idx_channel_identity_thread
7168
+ ON channel_identity_mappings(thread_id, tenant_id)
7169
+ `);
7170
+ await client.query(`
7171
+ CREATE TABLE IF NOT EXISTS channel_inbound_message_receipts (
7172
+ channel VARCHAR(50) NOT NULL,
7173
+ channel_app_id VARCHAR(255) NOT NULL,
7174
+ external_message_id VARCHAR(255) NOT NULL,
7175
+ tenant_id VARCHAR(255) NOT NULL,
7176
+ status VARCHAR(20) NOT NULL DEFAULT 'processing' CHECK (status IN ('processing', 'completed', 'failed')),
7177
+ thread_id VARCHAR(255),
7178
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7179
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7180
+ PRIMARY KEY (channel, channel_app_id, external_message_id)
7181
+ )
7182
+ `);
7183
+ },
7184
+ down: async (client) => {
7185
+ await client.query("DROP TABLE IF EXISTS channel_inbound_message_receipts");
7186
+ await client.query("DROP INDEX IF EXISTS idx_channel_identity_thread");
7187
+ await client.query("DROP INDEX IF EXISTS idx_channel_identity_lookup");
7188
+ await client.query("DROP TABLE IF EXISTS channel_identity_mappings");
7189
+ }
7190
+ };
7191
+
7192
+ // src/createPgStoreConfig.ts
7193
+ async function createPgStoreConfig(connectionString) {
7194
+ const pool = new import_pg21.Pool({ connectionString });
7195
+ const mm = new MigrationManager(pool);
7196
+ mm.register(createThreadsTable);
7197
+ mm.register(createScheduledTasksTable);
7198
+ mm.register(createAssistantsTable);
7199
+ mm.register(createSkillsTable);
7200
+ mm.register(createWorkspacesTable);
7201
+ mm.register(createProjectsTable);
7202
+ mm.register(createUsersTable);
7203
+ mm.register(createTenantsTable);
7204
+ mm.register(addUserStatusColumn);
7205
+ mm.register(createUserTenantLinkTable);
7206
+ mm.register(migrateRemoveTenantIdFromUsers);
7207
+ mm.register(createMetricsConfigsTable);
7208
+ mm.register(createMcpServerConfigsTable);
7209
+ mm.register(addAssistantTenantId);
7210
+ mm.register(addSkillTenantId);
7211
+ mm.register(changeSkillPrimaryKey);
7212
+ mm.register(addScheduleTenantId);
7213
+ mm.register(changeThreadPrimaryKey);
7214
+ mm.register(createChannelIdentityMappingTables);
7215
+ mm.register(createChannelInstallationsTable);
7216
+ mm.register(addThreadTenantId);
7217
+ mm.register(addProjectConfigColumn);
7218
+ mm.register(createThreadMessageQueueTable);
7219
+ mm.register(addPriorityAndCommandColumns);
7220
+ mm.register(alterMessageQueueIdColumn);
7221
+ mm.register(createWorkflowTrackingTables);
7222
+ for (const m of evalMigrations) {
7223
+ mm.register(m);
7224
+ }
7225
+ mm.register(alterChannelInstallationsTable);
7226
+ mm.register(createChannelBindingsTable);
7227
+ mm.register(createDatabaseConfigsTable);
7228
+ mm.register(changeAssistantPrimaryKey);
7229
+ mm.register(addStepThreadId);
7230
+ mm.register(addCustomRunConfigColumn);
7231
+ mm.register(createA2AApiKeysTable);
7232
+ mm.register(addWorkspaceProjectToQueue);
7233
+ mm.register(addAssistantOwnerUserId);
7234
+ mm.register(createTasksTable);
7235
+ mm.register(createMenuItemsTable);
7236
+ mm.register(createSharedResourcesTable);
7237
+ mm.register(addFileContentType);
7238
+ await mm.migrate();
7239
+ const checkpoint = import_langgraph_checkpoint_postgres.PostgresSaver.fromConnString(connectionString);
7240
+ checkpoint.setup().catch((err) => {
7241
+ console.error("[pg-stores] Failed to setup checkpoint table:", err.message || err);
7242
+ });
7243
+ const opts = { pool };
7244
+ return {
7245
+ workspace: new PostgreSQLWorkspaceStore(opts),
7246
+ project: new PostgreSQLProjectStore(opts),
7247
+ eval: new PostgreSQLEvalStore(opts),
7248
+ user: new PostgreSQLUserStore(opts),
7249
+ tenant: new PostgreSQLTenantStore(opts),
7250
+ userTenantLink: new PostgreSQLUserTenantLinkStore(opts),
7251
+ channelBinding: new ChannelBindingStore(opts),
7252
+ channelInstallation: new PostgreSQLChannelInstallationStore(opts),
7253
+ thread: new PostgreSQLThreadStore(opts),
7254
+ database: new PostgreSQLDatabaseConfigStore(opts),
7255
+ metrics: new PostgreSQLMetricsServerConfigStore(opts),
7256
+ mcp: new PostgreSQLMcpServerConfigStore(opts),
7257
+ assistant: new PostgreSQLAssistantStore(opts),
7258
+ workflowTracking: new PostgreSQLWorkflowTrackingStore(opts),
7259
+ threadMessageQueue: new ThreadMessageQueueStore(opts),
7260
+ task: new PostgreSQLTaskStore(opts),
7261
+ a2aApiKey: new PostgreSQLA2AApiKeyStore(opts),
7262
+ schedule: new PostgreSQLScheduleStorage(opts),
7263
+ menu: new MenuStore(opts),
7264
+ sharedResource: new PostgresSharedResourceStore(opts),
7265
+ checkpoint
7266
+ };
7267
+ }
7268
+
6927
7269
  // src/stores/PostgreSQLSkillStore.ts
7270
+ var import_pg22 = require("pg");
6928
7271
  var PostgreSQLSkillStore = class {
6929
7272
  constructor(options) {
6930
7273
  this.initialized = false;
6931
7274
  this.ownsPool = true;
6932
7275
  this.initPromise = null;
7276
+ if (options.pool) {
7277
+ this.pool = options.pool;
7278
+ this.ownsPool = false;
7279
+ this.initialized = true;
7280
+ return;
7281
+ }
6933
7282
  if (typeof options.poolConfig === "string") {
6934
- this.pool = new import_pg21.Pool({ connectionString: options.poolConfig });
7283
+ this.pool = new import_pg22.Pool({ connectionString: options.poolConfig });
7284
+ } else if (options.poolConfig) {
7285
+ this.pool = new import_pg22.Pool(options.poolConfig);
6935
7286
  } else {
6936
- this.pool = new import_pg21.Pool(options.poolConfig);
7287
+ throw new Error("Either pool or poolConfig must be provided");
6937
7288
  }
6938
7289
  this.migrationManager = new MigrationManager(this.pool);
6939
7290
  this.migrationManager.register(createSkillsTable);
@@ -7231,68 +7582,22 @@ var PostgreSQLSkillStore = class {
7231
7582
  }
7232
7583
  };
7233
7584
 
7234
- // src/migrations/channel_identity_mapping_migration.ts
7235
- var createChannelIdentityMappingTables = {
7236
- version: 20,
7237
- name: "create_channel_identity_mapping_tables",
7238
- up: async (client) => {
7239
- await client.query(`
7240
- CREATE TABLE IF NOT EXISTS channel_identity_mappings (
7241
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
7242
- channel VARCHAR(50) NOT NULL,
7243
- channel_app_id VARCHAR(255) NOT NULL,
7244
- tenant_id VARCHAR(255) NOT NULL,
7245
- assistant_id VARCHAR(255) NOT NULL,
7246
- mapping_mode VARCHAR(20) NOT NULL CHECK (mapping_mode IN ('user', 'group', 'hybrid')),
7247
- external_subject_type VARCHAR(20) NOT NULL CHECK (external_subject_type IN ('user', 'chat')),
7248
- external_subject_key VARCHAR(512) NOT NULL,
7249
- lark_open_id VARCHAR(255),
7250
- lark_chat_id VARCHAR(255) NOT NULL,
7251
- lark_message_id VARCHAR(255),
7252
- thread_id VARCHAR(255) NOT NULL,
7253
- created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7254
- updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7255
- last_activity_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7256
- UNIQUE (channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7257
- )
7258
- `);
7259
- await client.query(`
7260
- CREATE INDEX IF NOT EXISTS idx_channel_identity_lookup
7261
- ON channel_identity_mappings(channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7262
- `);
7263
- await client.query(`
7264
- CREATE INDEX IF NOT EXISTS idx_channel_identity_thread
7265
- ON channel_identity_mappings(thread_id, tenant_id)
7266
- `);
7267
- await client.query(`
7268
- CREATE TABLE IF NOT EXISTS channel_inbound_message_receipts (
7269
- channel VARCHAR(50) NOT NULL,
7270
- channel_app_id VARCHAR(255) NOT NULL,
7271
- external_message_id VARCHAR(255) NOT NULL,
7272
- tenant_id VARCHAR(255) NOT NULL,
7273
- status VARCHAR(20) NOT NULL DEFAULT 'processing' CHECK (status IN ('processing', 'completed', 'failed')),
7274
- thread_id VARCHAR(255),
7275
- created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7276
- updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7277
- PRIMARY KEY (channel, channel_app_id, external_message_id)
7278
- )
7279
- `);
7280
- },
7281
- down: async (client) => {
7282
- await client.query("DROP TABLE IF EXISTS channel_inbound_message_receipts");
7283
- await client.query("DROP INDEX IF EXISTS idx_channel_identity_thread");
7284
- await client.query("DROP INDEX IF EXISTS idx_channel_identity_lookup");
7285
- await client.query("DROP TABLE IF EXISTS channel_identity_mappings");
7286
- }
7287
- };
7288
-
7289
7585
  // src/stores/ChannelIdentityMappingStore.ts
7290
- var import_pg22 = require("pg");
7586
+ var import_pg23 = require("pg");
7291
7587
  var ChannelIdentityMappingStore = class {
7292
7588
  constructor(options) {
7293
7589
  this.initialized = false;
7590
+ this.ownsPool = true;
7294
7591
  this.initPromise = null;
7295
- this.pool = typeof options.poolConfig === "string" ? new import_pg22.Pool({ connectionString: options.poolConfig }) : new import_pg22.Pool(options.poolConfig);
7592
+ if (options.pool) {
7593
+ this.pool = options.pool;
7594
+ this.ownsPool = false;
7595
+ this.initialized = true;
7596
+ return;
7597
+ }
7598
+ this.pool = typeof options.poolConfig === "string" ? new import_pg23.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg23.Pool(options.poolConfig) : (() => {
7599
+ throw new Error("Either pool or poolConfig must be provided");
7600
+ })();
7296
7601
  this.migrationManager = new MigrationManager(this.pool);
7297
7602
  this.migrationManager.register(createChannelIdentityMappingTables);
7298
7603
  if (options.autoMigrate !== false) {
@@ -7319,6 +7624,11 @@ var ChannelIdentityMappingStore = class {
7319
7624
  })();
7320
7625
  return this.initPromise;
7321
7626
  }
7627
+ async dispose() {
7628
+ if (this.ownsPool && this.pool) {
7629
+ await this.pool.end();
7630
+ }
7631
+ }
7322
7632
  async createMapping(input) {
7323
7633
  await this.ensureInitialized();
7324
7634
  const result = await this.pool.query(