@axiom-lattice/pg-stores 1.0.83 → 1.0.85

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 +19 -0
  3. package/dist/index.d.mts +124 -44
  4. package/dist/index.d.ts +124 -44
  5. package/dist/index.js +477 -162
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +477 -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 +100 -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,73 @@ 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
+ DELETE FROM lattice_schema_migrations a
158
+ USING lattice_schema_migrations b
159
+ WHERE a.name = b.name AND a.version < b.version
160
+ `);
161
+ await client.query(
162
+ `ALTER TABLE lattice_schema_migrations DROP CONSTRAINT ${constraintName}`
163
+ );
164
+ await client.query(
165
+ `ALTER TABLE lattice_schema_migrations ADD PRIMARY KEY (name)`
166
+ );
167
+ }
127
168
  }
128
169
  /**
129
- * Get applied migrations from database
170
+ * Get the set of already-applied migration names from the tracking table.
130
171
  */
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
- `);
172
+ async getAppliedNames(client) {
139
173
  const result = await client.query(
140
- "SELECT version, name, applied_at FROM lattice_schema_migrations ORDER BY version"
174
+ "SELECT name, version, applied_at FROM lattice_schema_migrations ORDER BY version"
141
175
  );
142
- return result.rows;
176
+ return new Set(result.rows.map((r) => r.name));
143
177
  }
144
178
  /**
145
179
  * Apply pending migrations
@@ -153,10 +187,9 @@ var MigrationManager = class {
153
187
  try {
154
188
  await client.query("BEGIN");
155
189
  await this.ensureMigrationsTable(client);
156
- const appliedMigrations = await this.getAppliedMigrations(client);
157
- const appliedVersions = new Set(appliedMigrations.map((m) => m.version));
190
+ const appliedNames = await this.getAppliedNames(client);
158
191
  const pendingMigrations = this.migrations.filter(
159
- (m) => !appliedVersions.has(m.version)
192
+ (m) => !appliedNames.has(m.name)
160
193
  );
161
194
  if (pendingMigrations.length === 0) {
162
195
  console.log("No pending migrations");
@@ -165,12 +198,12 @@ var MigrationManager = class {
165
198
  }
166
199
  for (const migration of pendingMigrations) {
167
200
  console.log(
168
- `Applying migration ${migration.version}: ${migration.name}`
201
+ `Applying migration v${migration.version}: ${migration.name}`
169
202
  );
170
203
  await migration.up(client);
171
204
  await client.query(
172
- "INSERT INTO lattice_schema_migrations (version, name) VALUES ($1, $2) ON CONFLICT (version) DO NOTHING",
173
- [migration.version, migration.name]
205
+ "INSERT INTO lattice_schema_migrations (name, version) VALUES ($1, $2) ON CONFLICT (name) DO NOTHING",
206
+ [migration.name, migration.version]
174
207
  );
175
208
  }
176
209
  await client.query("COMMIT");
@@ -186,34 +219,37 @@ var MigrationManager = class {
186
219
  }
187
220
  }
188
221
  /**
189
- * Rollback last migration
222
+ * Rollback the last-applied migration (highest version).
190
223
  */
191
224
  async rollback() {
192
225
  const client = await this.pool.connect();
193
226
  try {
194
227
  await client.query("BEGIN");
195
- const appliedMigrations = await this.getAppliedMigrations(client);
196
- if (appliedMigrations.length === 0) {
228
+ await this.ensureMigrationsTable(client);
229
+ const result = await client.query(
230
+ "SELECT name, version FROM lattice_schema_migrations ORDER BY version DESC LIMIT 1"
231
+ );
232
+ if (result.rows.length === 0) {
197
233
  console.log("No migrations to rollback");
198
234
  await client.query("COMMIT");
199
235
  return;
200
236
  }
201
- const lastMigration = appliedMigrations[appliedMigrations.length - 1];
237
+ const lastApplied = result.rows[0];
202
238
  const migration = this.migrations.find(
203
- (m) => m.version === lastMigration.version
239
+ (m) => m.name === lastApplied.name
204
240
  );
205
241
  if (!migration || !migration.down) {
206
242
  throw new Error(
207
- `Migration ${lastMigration.version} does not have a down migration`
243
+ `Migration "${lastApplied.name}" (v${lastApplied.version}) does not have a down migration`
208
244
  );
209
245
  }
210
246
  console.log(
211
- `Rolling back migration ${lastMigration.version}: ${lastMigration.name}`
247
+ `Rolling back migration v${lastApplied.version}: ${lastApplied.name}`
212
248
  );
213
249
  await migration.down(client);
214
250
  await client.query(
215
- "DELETE FROM lattice_schema_migrations WHERE version = $1",
216
- [lastMigration.version]
251
+ "DELETE FROM lattice_schema_migrations WHERE name = $1",
252
+ [lastApplied.name]
217
253
  );
218
254
  await client.query("COMMIT");
219
255
  console.log("Rollback completed");
@@ -225,22 +261,25 @@ var MigrationManager = class {
225
261
  }
226
262
  }
227
263
  /**
228
- * Get current migration version
264
+ * Get the highest applied migration version.
229
265
  */
230
266
  async getCurrentVersion() {
231
267
  const client = await this.pool.connect();
232
268
  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));
269
+ await this.ensureMigrationsTable(client);
270
+ const result = await client.query(
271
+ "SELECT COALESCE(MAX(version), 0) AS max FROM lattice_schema_migrations"
272
+ );
273
+ return result.rows[0]?.max ?? 0;
238
274
  } finally {
239
275
  client.release();
240
276
  }
241
277
  }
242
278
  };
243
279
 
280
+ // src/stores/PostgreSQLThreadStore.ts
281
+ var import_pg = require("pg");
282
+
244
283
  // src/migrations/thread_migrations.ts
245
284
  var createThreadsTable = {
246
285
  version: 1,
@@ -381,10 +420,18 @@ var PostgreSQLThreadStore = class {
381
420
  this.initialized = false;
382
421
  this.ownsPool = true;
383
422
  this.initPromise = null;
423
+ if (options.pool) {
424
+ this.pool = options.pool;
425
+ this.ownsPool = false;
426
+ this.initialized = true;
427
+ return;
428
+ }
384
429
  if (typeof options.poolConfig === "string") {
385
430
  this.pool = new import_pg.Pool({ connectionString: options.poolConfig });
386
- } else {
431
+ } else if (options.poolConfig) {
387
432
  this.pool = new import_pg.Pool(options.poolConfig);
433
+ } else {
434
+ throw new Error("Either pool or poolConfig must be provided");
388
435
  }
389
436
  this.migrationManager = new MigrationManager(this.pool);
390
437
  this.migrationManager.register(createThreadsTable);
@@ -727,10 +774,18 @@ var PostgreSQLAssistantStore = class {
727
774
  this.initialized = false;
728
775
  this.ownsPool = true;
729
776
  this.initPromise = null;
777
+ if (options.pool) {
778
+ this.pool = options.pool;
779
+ this.ownsPool = false;
780
+ this.initialized = true;
781
+ return;
782
+ }
730
783
  if (typeof options.poolConfig === "string") {
731
784
  this.pool = new import_pg2.Pool({ connectionString: options.poolConfig });
732
- } else {
785
+ } else if (options.poolConfig) {
733
786
  this.pool = new import_pg2.Pool(options.poolConfig);
787
+ } else {
788
+ throw new Error("Either pool or poolConfig must be provided");
734
789
  }
735
790
  this.migrationManager = new MigrationManager(this.pool);
736
791
  this.migrationManager.register(createAssistantsTable);
@@ -1007,11 +1062,20 @@ var import_core = require("@axiom-lattice/core");
1007
1062
  var PostgreSQLDatabaseConfigStore = class {
1008
1063
  constructor(options) {
1009
1064
  this.initialized = false;
1065
+ this.ownsPool = true;
1010
1066
  this.initPromise = null;
1067
+ if (options.pool) {
1068
+ this.pool = options.pool;
1069
+ this.ownsPool = false;
1070
+ this.initialized = true;
1071
+ return;
1072
+ }
1011
1073
  if (typeof options.poolConfig === "string") {
1012
1074
  this.pool = new import_pg3.Pool({ connectionString: options.poolConfig });
1013
- } else {
1075
+ } else if (options.poolConfig) {
1014
1076
  this.pool = new import_pg3.Pool(options.poolConfig);
1077
+ } else {
1078
+ throw new Error("Either pool or poolConfig must be provided");
1015
1079
  }
1016
1080
  this.migrationManager = new MigrationManager(this.pool);
1017
1081
  this.migrationManager.register(createDatabaseConfigsTable);
@@ -1230,7 +1294,9 @@ var PostgreSQLDatabaseConfigStore = class {
1230
1294
  * Dispose resources and close the connection pool
1231
1295
  */
1232
1296
  async dispose() {
1233
- await this.pool.end();
1297
+ if (this.ownsPool && this.pool) {
1298
+ await this.pool.end();
1299
+ }
1234
1300
  }
1235
1301
  /**
1236
1302
  * Ensure store is initialized
@@ -1321,11 +1387,20 @@ var import_core2 = require("@axiom-lattice/core");
1321
1387
  var PostgreSQLMetricsServerConfigStore = class {
1322
1388
  constructor(options) {
1323
1389
  this.initialized = false;
1390
+ this.ownsPool = true;
1324
1391
  this.initPromise = null;
1392
+ if (options.pool) {
1393
+ this.pool = options.pool;
1394
+ this.ownsPool = false;
1395
+ this.initialized = true;
1396
+ return;
1397
+ }
1325
1398
  if (typeof options.poolConfig === "string") {
1326
1399
  this.pool = new import_pg4.Pool({ connectionString: options.poolConfig });
1327
- } else {
1400
+ } else if (options.poolConfig) {
1328
1401
  this.pool = new import_pg4.Pool(options.poolConfig);
1402
+ } else {
1403
+ throw new Error("Either pool or poolConfig must be provided");
1329
1404
  }
1330
1405
  this.migrationManager = new MigrationManager(this.pool);
1331
1406
  this.migrationManager.register(createMetricsConfigsTable);
@@ -1544,7 +1619,9 @@ var PostgreSQLMetricsServerConfigStore = class {
1544
1619
  * Dispose resources and close the connection pool
1545
1620
  */
1546
1621
  async dispose() {
1547
- await this.pool.end();
1622
+ if (this.ownsPool && this.pool) {
1623
+ await this.pool.end();
1624
+ }
1548
1625
  }
1549
1626
  /**
1550
1627
  * Ensure store is initialized
@@ -1654,11 +1731,20 @@ var import_core3 = require("@axiom-lattice/core");
1654
1731
  var PostgreSQLMcpServerConfigStore = class {
1655
1732
  constructor(options) {
1656
1733
  this.initialized = false;
1734
+ this.ownsPool = true;
1657
1735
  this.initPromise = null;
1736
+ if (options.pool) {
1737
+ this.pool = options.pool;
1738
+ this.ownsPool = false;
1739
+ this.initialized = true;
1740
+ return;
1741
+ }
1658
1742
  if (typeof options.poolConfig === "string") {
1659
1743
  this.pool = new import_pg5.Pool({ connectionString: options.poolConfig });
1660
- } else {
1744
+ } else if (options.poolConfig) {
1661
1745
  this.pool = new import_pg5.Pool(options.poolConfig);
1746
+ } else {
1747
+ throw new Error("Either pool or poolConfig must be provided");
1662
1748
  }
1663
1749
  this.migrationManager = new MigrationManager(this.pool);
1664
1750
  this.migrationManager.register(createMcpServerConfigsTable);
@@ -1893,7 +1979,9 @@ var PostgreSQLMcpServerConfigStore = class {
1893
1979
  * Dispose resources and close the connection pool
1894
1980
  */
1895
1981
  async dispose() {
1896
- await this.pool.end();
1982
+ if (this.ownsPool && this.pool) {
1983
+ await this.pool.end();
1984
+ }
1897
1985
  }
1898
1986
  /**
1899
1987
  * Ensure store is initialized
@@ -1994,10 +2082,18 @@ var PostgreSQLWorkspaceStore = class {
1994
2082
  constructor(options) {
1995
2083
  this.initialized = false;
1996
2084
  this.ownsPool = true;
2085
+ if (options.pool) {
2086
+ this.pool = options.pool;
2087
+ this.ownsPool = false;
2088
+ this.initialized = true;
2089
+ return;
2090
+ }
1997
2091
  if (typeof options.poolConfig === "string") {
1998
2092
  this.pool = new import_pg6.Pool({ connectionString: options.poolConfig });
1999
- } else {
2093
+ } else if (options.poolConfig) {
2000
2094
  this.pool = new import_pg6.Pool(options.poolConfig);
2095
+ } else {
2096
+ throw new Error("Either pool or poolConfig must be provided");
2001
2097
  }
2002
2098
  this.migrationManager = new MigrationManager(this.pool);
2003
2099
  this.migrationManager.register(createWorkspacesTable);
@@ -2237,10 +2333,18 @@ var PostgreSQLProjectStore = class {
2237
2333
  constructor(options) {
2238
2334
  this.initialized = false;
2239
2335
  this.ownsPool = true;
2336
+ if (options.pool) {
2337
+ this.pool = options.pool;
2338
+ this.ownsPool = false;
2339
+ this.initialized = true;
2340
+ return;
2341
+ }
2240
2342
  if (typeof options.poolConfig === "string") {
2241
2343
  this.pool = new import_pg7.Pool({ connectionString: options.poolConfig });
2242
- } else {
2344
+ } else if (options.poolConfig) {
2243
2345
  this.pool = new import_pg7.Pool(options.poolConfig);
2346
+ } else {
2347
+ throw new Error("Either pool or poolConfig must be provided");
2244
2348
  }
2245
2349
  this.migrationManager = new MigrationManager(this.pool);
2246
2350
  this.migrationManager.register(createProjectsTable);
@@ -2487,10 +2591,19 @@ var addUserStatusColumn = {
2487
2591
  var PostgreSQLUserStore = class {
2488
2592
  constructor(options) {
2489
2593
  this.initialized = false;
2594
+ this.ownsPool = true;
2595
+ if (options.pool) {
2596
+ this.pool = options.pool;
2597
+ this.ownsPool = false;
2598
+ this.initialized = true;
2599
+ return;
2600
+ }
2490
2601
  if (typeof options.poolConfig === "string") {
2491
2602
  this.pool = new import_pg8.Pool({ connectionString: options.poolConfig });
2492
- } else {
2603
+ } else if (options.poolConfig) {
2493
2604
  this.pool = new import_pg8.Pool(options.poolConfig);
2605
+ } else {
2606
+ throw new Error("Either pool or poolConfig must be provided");
2494
2607
  }
2495
2608
  this.migrationManager = new MigrationManager(this.pool);
2496
2609
  this.migrationManager.register(createUsersTable);
@@ -2503,7 +2616,9 @@ var PostgreSQLUserStore = class {
2503
2616
  }
2504
2617
  }
2505
2618
  async dispose() {
2506
- await this.pool.end();
2619
+ if (this.ownsPool && this.pool) {
2620
+ await this.pool.end();
2621
+ }
2507
2622
  }
2508
2623
  async initialize() {
2509
2624
  if (this.initialized) return;
@@ -2676,10 +2791,18 @@ var PostgreSQLTenantStore = class {
2676
2791
  constructor(options) {
2677
2792
  this.initialized = false;
2678
2793
  this.ownsPool = true;
2794
+ if (options.pool) {
2795
+ this.pool = options.pool;
2796
+ this.ownsPool = false;
2797
+ this.initialized = true;
2798
+ return;
2799
+ }
2679
2800
  if (typeof options.poolConfig === "string") {
2680
2801
  this.pool = new import_pg9.Pool({ connectionString: options.poolConfig });
2681
- } else {
2802
+ } else if (options.poolConfig) {
2682
2803
  this.pool = new import_pg9.Pool(options.poolConfig);
2804
+ } else {
2805
+ throw new Error("Either pool or poolConfig must be provided");
2683
2806
  }
2684
2807
  this.migrationManager = new MigrationManager(this.pool);
2685
2808
  this.migrationManager.register(createTenantsTable);
@@ -2929,10 +3052,19 @@ var migrateRemoveTenantIdFromUsers = {
2929
3052
  var PostgreSQLUserTenantLinkStore = class {
2930
3053
  constructor(options) {
2931
3054
  this.initialized = false;
3055
+ this.ownsPool = true;
3056
+ if (options.pool) {
3057
+ this.pool = options.pool;
3058
+ this.ownsPool = false;
3059
+ this.initialized = true;
3060
+ return;
3061
+ }
2932
3062
  if (typeof options.poolConfig === "string") {
2933
3063
  this.pool = new import_pg10.Pool({ connectionString: options.poolConfig });
2934
- } else {
3064
+ } else if (options.poolConfig) {
2935
3065
  this.pool = new import_pg10.Pool(options.poolConfig);
3066
+ } else {
3067
+ throw new Error("Either pool or poolConfig must be provided");
2936
3068
  }
2937
3069
  this.migrationManager = new MigrationManager(this.pool);
2938
3070
  this.migrationManager.register(createUserTenantLinkTable);
@@ -2945,7 +3077,9 @@ var PostgreSQLUserTenantLinkStore = class {
2945
3077
  }
2946
3078
  }
2947
3079
  async dispose() {
2948
- await this.pool.end();
3080
+ if (this.ownsPool && this.pool) {
3081
+ await this.pool.end();
3082
+ }
2949
3083
  }
2950
3084
  async initialize() {
2951
3085
  if (this.initialized) return;
@@ -3174,11 +3308,20 @@ var addStepThreadId = {
3174
3308
  var PostgreSQLWorkflowTrackingStore = class {
3175
3309
  constructor(options) {
3176
3310
  this.initialized = false;
3311
+ this.ownsPool = true;
3177
3312
  this.initPromise = null;
3313
+ if (options.pool) {
3314
+ this.pool = options.pool;
3315
+ this.ownsPool = false;
3316
+ this.initialized = true;
3317
+ return;
3318
+ }
3178
3319
  if (typeof options.poolConfig === "string") {
3179
3320
  this.pool = new import_pg11.Pool({ connectionString: options.poolConfig });
3180
- } else {
3321
+ } else if (options.poolConfig) {
3181
3322
  this.pool = new import_pg11.Pool(options.poolConfig);
3323
+ } else {
3324
+ throw new Error("Either pool or poolConfig must be provided");
3182
3325
  }
3183
3326
  this.migrationManager = new MigrationManager(this.pool);
3184
3327
  this.migrationManager.register(createWorkflowTrackingTables);
@@ -3191,7 +3334,9 @@ var PostgreSQLWorkflowTrackingStore = class {
3191
3334
  }
3192
3335
  }
3193
3336
  async dispose() {
3194
- await this.pool.end();
3337
+ if (this.ownsPool && this.pool) {
3338
+ await this.pool.end();
3339
+ }
3195
3340
  }
3196
3341
  async initialize() {
3197
3342
  if (this.initialized) return;
@@ -3680,10 +3825,18 @@ var PostgreSQLEvalStore = class {
3680
3825
  this.initialized = false;
3681
3826
  this.ownsPool = true;
3682
3827
  this.initPromise = null;
3828
+ if (options.pool) {
3829
+ this.pool = options.pool;
3830
+ this.ownsPool = false;
3831
+ this.initialized = true;
3832
+ return;
3833
+ }
3683
3834
  if (typeof options.poolConfig === "string") {
3684
3835
  this.pool = new import_pg12.Pool({ connectionString: options.poolConfig });
3685
- } else {
3836
+ } else if (options.poolConfig) {
3686
3837
  this.pool = new import_pg12.Pool(options.poolConfig);
3838
+ } else {
3839
+ throw new Error("Either pool or poolConfig must be provided");
3687
3840
  }
3688
3841
  this.migrationManager = new MigrationManager(this.pool);
3689
3842
  for (const m of evalMigrations) {
@@ -4546,10 +4699,18 @@ var ThreadMessageQueueStore = class {
4546
4699
  this.ownsPool = true;
4547
4700
  this.initialized = false;
4548
4701
  this.initPromise = null;
4702
+ if (options.pool) {
4703
+ this.pool = options.pool;
4704
+ this.ownsPool = false;
4705
+ this.initialized = true;
4706
+ return;
4707
+ }
4549
4708
  if (typeof options.poolConfig === "string") {
4550
4709
  this.pool = new import_pg13.Pool({ connectionString: options.poolConfig });
4551
- } else {
4710
+ } else if (options.poolConfig) {
4552
4711
  this.pool = new import_pg13.Pool(options.poolConfig);
4712
+ } else {
4713
+ throw new Error("Either pool or poolConfig must be provided");
4553
4714
  }
4554
4715
  this.migrationManager = new MigrationManager(this.pool);
4555
4716
  this.migrationManager.register(createThreadMessageQueueTable);
@@ -4788,8 +4949,17 @@ var createChannelBindingsTable = {
4788
4949
  var ChannelBindingStore = class {
4789
4950
  constructor(options) {
4790
4951
  this.initialized = false;
4952
+ this.ownsPool = true;
4791
4953
  this.initPromise = null;
4792
- this.pool = typeof options.poolConfig === "string" ? new import_pg14.Pool({ connectionString: options.poolConfig }) : new import_pg14.Pool(options.poolConfig);
4954
+ if (options.pool) {
4955
+ this.pool = options.pool;
4956
+ this.ownsPool = false;
4957
+ this.initialized = true;
4958
+ return;
4959
+ }
4960
+ this.pool = typeof options.poolConfig === "string" ? new import_pg14.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg14.Pool(options.poolConfig) : (() => {
4961
+ throw new Error("Either pool or poolConfig must be provided");
4962
+ })();
4793
4963
  this.migrationManager = new MigrationManager(this.pool);
4794
4964
  this.migrationManager.register(createChannelBindingsTable);
4795
4965
  if (options.autoMigrate !== false) {
@@ -4812,6 +4982,11 @@ var ChannelBindingStore = class {
4812
4982
  })();
4813
4983
  return this.initPromise;
4814
4984
  }
4985
+ async dispose() {
4986
+ if (this.ownsPool && this.pool) {
4987
+ await this.pool.end();
4988
+ }
4989
+ }
4815
4990
  async resolve(params) {
4816
4991
  await this.ensureInitialized();
4817
4992
  const result = await this.pool.query(
@@ -5035,8 +5210,17 @@ var import_core4 = require("@axiom-lattice/core");
5035
5210
  var PostgreSQLChannelInstallationStore = class {
5036
5211
  constructor(options) {
5037
5212
  this.initialized = false;
5213
+ this.ownsPool = true;
5038
5214
  this.initPromise = null;
5039
- this.pool = typeof options.poolConfig === "string" ? new import_pg15.Pool({ connectionString: options.poolConfig }) : new import_pg15.Pool(options.poolConfig);
5215
+ if (options.pool) {
5216
+ this.pool = options.pool;
5217
+ this.ownsPool = false;
5218
+ this.initialized = true;
5219
+ return;
5220
+ }
5221
+ this.pool = typeof options.poolConfig === "string" ? new import_pg15.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg15.Pool(options.poolConfig) : (() => {
5222
+ throw new Error("Either pool or poolConfig must be provided");
5223
+ })();
5040
5224
  this.migrationManager = new MigrationManager(this.pool);
5041
5225
  this.migrationManager.register(createChannelInstallationsTable);
5042
5226
  this.migrationManager.register(alterChannelInstallationsTable);
@@ -5067,6 +5251,11 @@ var PostgreSQLChannelInstallationStore = class {
5067
5251
  })();
5068
5252
  return this.initPromise;
5069
5253
  }
5254
+ async dispose() {
5255
+ if (this.ownsPool && this.pool) {
5256
+ await this.pool.end();
5257
+ }
5258
+ }
5070
5259
  async getInstallationById(installationId) {
5071
5260
  await this.ensureInitialized();
5072
5261
  const result = await this.pool.query(
@@ -5311,8 +5500,17 @@ function mapRowToRecord(row) {
5311
5500
  var PostgreSQLA2AApiKeyStore = class {
5312
5501
  constructor(options) {
5313
5502
  this.initialized = false;
5503
+ this.ownsPool = true;
5314
5504
  this.initPromise = null;
5315
- this.pool = typeof options.poolConfig === "string" ? new import_pg16.Pool({ connectionString: options.poolConfig }) : new import_pg16.Pool(options.poolConfig);
5505
+ if (options.pool) {
5506
+ this.pool = options.pool;
5507
+ this.ownsPool = false;
5508
+ this.initialized = true;
5509
+ return;
5510
+ }
5511
+ this.pool = typeof options.poolConfig === "string" ? new import_pg16.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg16.Pool(options.poolConfig) : (() => {
5512
+ throw new Error("Either pool or poolConfig must be provided");
5513
+ })();
5316
5514
  this.migrationManager = new MigrationManager(this.pool);
5317
5515
  this.migrationManager.register(createA2AApiKeysTable);
5318
5516
  if (options.autoMigrate !== false) {
@@ -5335,6 +5533,11 @@ var PostgreSQLA2AApiKeyStore = class {
5335
5533
  })();
5336
5534
  return this.initPromise;
5337
5535
  }
5536
+ async dispose() {
5537
+ if (this.ownsPool && this.pool) {
5538
+ await this.pool.end();
5539
+ }
5540
+ }
5338
5541
  async ensureInitialized() {
5339
5542
  if (!this.initialized) await this.initialize();
5340
5543
  }
@@ -5598,10 +5801,19 @@ var addScheduleTenantId = {
5598
5801
  var PostgreSQLScheduleStorage = class {
5599
5802
  constructor(options) {
5600
5803
  this.initialized = false;
5804
+ this.ownsPool = true;
5805
+ if (options.pool) {
5806
+ this.pool = options.pool;
5807
+ this.ownsPool = false;
5808
+ this.initialized = true;
5809
+ return;
5810
+ }
5601
5811
  if (typeof options.poolConfig === "string") {
5602
5812
  this.pool = new import_pg17.Pool({ connectionString: options.poolConfig });
5603
- } else {
5813
+ } else if (options.poolConfig) {
5604
5814
  this.pool = new import_pg17.Pool(options.poolConfig);
5815
+ } else {
5816
+ throw new Error("Either pool or poolConfig must be provided");
5605
5817
  }
5606
5818
  this.migrationManager = new MigrationManager(this.pool);
5607
5819
  this.migrationManager.register(createScheduledTasksTable);
@@ -5617,7 +5829,7 @@ var PostgreSQLScheduleStorage = class {
5617
5829
  * Dispose resources and close the connection pool
5618
5830
  */
5619
5831
  async dispose() {
5620
- if (this.pool) {
5832
+ if (this.ownsPool && this.pool) {
5621
5833
  await this.pool.end();
5622
5834
  }
5623
5835
  }
@@ -6111,10 +6323,18 @@ var PostgreSQLTaskStore = class {
6111
6323
  this.initialized = false;
6112
6324
  this.ownsPool = true;
6113
6325
  this.initPromise = null;
6326
+ if (options.pool) {
6327
+ this.pool = options.pool;
6328
+ this.ownsPool = false;
6329
+ this.initialized = true;
6330
+ return;
6331
+ }
6114
6332
  if (typeof options.poolConfig === "string") {
6115
6333
  this.pool = new import_pg18.Pool({ connectionString: options.poolConfig });
6116
- } else {
6334
+ } else if (options.poolConfig) {
6117
6335
  this.pool = new import_pg18.Pool(options.poolConfig);
6336
+ } else {
6337
+ throw new Error("Either pool or poolConfig must be provided");
6118
6338
  }
6119
6339
  this.migrationManager = new MigrationManager(this.pool);
6120
6340
  this.migrationManager.register(createTasksTable);
@@ -6378,8 +6598,17 @@ var addFileContentType = {
6378
6598
  var MenuStore = class {
6379
6599
  constructor(options) {
6380
6600
  this.initialized = false;
6601
+ this.ownsPool = true;
6381
6602
  this.initPromise = null;
6382
- this.pool = typeof options.poolConfig === "string" ? new import_pg19.Pool({ connectionString: options.poolConfig }) : new import_pg19.Pool(options.poolConfig);
6603
+ if (options.pool) {
6604
+ this.pool = options.pool;
6605
+ this.ownsPool = false;
6606
+ this.initialized = true;
6607
+ return;
6608
+ }
6609
+ this.pool = typeof options.poolConfig === "string" ? new import_pg19.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg19.Pool(options.poolConfig) : (() => {
6610
+ throw new Error("Either pool or poolConfig must be provided");
6611
+ })();
6383
6612
  this.migrationManager = new MigrationManager(this.pool);
6384
6613
  this.migrationManager.register(createMenuItemsTable);
6385
6614
  this.migrationManager.register(addFileContentType);
@@ -6403,6 +6632,11 @@ var MenuStore = class {
6403
6632
  })();
6404
6633
  return this.initPromise;
6405
6634
  }
6635
+ async dispose() {
6636
+ if (this.ownsPool && this.pool) {
6637
+ await this.pool.end();
6638
+ }
6639
+ }
6406
6640
  async list(params) {
6407
6641
  await this.ensureInitialized();
6408
6642
  const conditions = ["tenant_id = $1"];
@@ -6573,8 +6807,17 @@ var createSharedResourcesTable = {
6573
6807
  var PostgresSharedResourceStore = class {
6574
6808
  constructor(options) {
6575
6809
  this.initialized = false;
6810
+ this.ownsPool = true;
6576
6811
  this.initPromise = null;
6577
- this.pool = typeof options.poolConfig === "string" ? new import_pg20.Pool({ connectionString: options.poolConfig }) : new import_pg20.Pool(options.poolConfig);
6812
+ if (options.pool) {
6813
+ this.pool = options.pool;
6814
+ this.ownsPool = false;
6815
+ this.initialized = true;
6816
+ return;
6817
+ }
6818
+ this.pool = typeof options.poolConfig === "string" ? new import_pg20.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg20.Pool(options.poolConfig) : (() => {
6819
+ throw new Error("Either pool or poolConfig must be provided");
6820
+ })();
6578
6821
  this.migrationManager = new MigrationManager(this.pool);
6579
6822
  this.migrationManager.register(createSharedResourcesTable);
6580
6823
  if (options.autoMigrate !== false) {
@@ -6600,6 +6843,11 @@ var PostgresSharedResourceStore = class {
6600
6843
  })();
6601
6844
  return this.initPromise;
6602
6845
  }
6846
+ async dispose() {
6847
+ if (this.ownsPool && this.pool) {
6848
+ await this.pool.end();
6849
+ }
6850
+ }
6603
6851
  async findByToken(token) {
6604
6852
  await this.ensureInitialized();
6605
6853
  const { rows } = await this.pool.query(
@@ -6737,39 +6985,6 @@ var PostgresSharedResourceStore = class {
6737
6985
 
6738
6986
  // src/createPgStoreConfig.ts
6739
6987
  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
6988
 
6774
6989
  // src/migrations/skill_migrations.ts
6775
6990
  var createSkillsTable = {
@@ -6924,16 +7139,157 @@ var changeSkillPrimaryKey = {
6924
7139
  }
6925
7140
  };
6926
7141
 
7142
+ // src/migrations/channel_identity_mapping_migration.ts
7143
+ var createChannelIdentityMappingTables = {
7144
+ version: 20,
7145
+ name: "create_channel_identity_mapping_tables",
7146
+ up: async (client) => {
7147
+ await client.query(`
7148
+ CREATE TABLE IF NOT EXISTS channel_identity_mappings (
7149
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
7150
+ channel VARCHAR(50) NOT NULL,
7151
+ channel_app_id VARCHAR(255) NOT NULL,
7152
+ tenant_id VARCHAR(255) NOT NULL,
7153
+ assistant_id VARCHAR(255) NOT NULL,
7154
+ mapping_mode VARCHAR(20) NOT NULL CHECK (mapping_mode IN ('user', 'group', 'hybrid')),
7155
+ external_subject_type VARCHAR(20) NOT NULL CHECK (external_subject_type IN ('user', 'chat')),
7156
+ external_subject_key VARCHAR(512) NOT NULL,
7157
+ lark_open_id VARCHAR(255),
7158
+ lark_chat_id VARCHAR(255) NOT NULL,
7159
+ lark_message_id VARCHAR(255),
7160
+ thread_id VARCHAR(255) NOT NULL,
7161
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7162
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7163
+ last_activity_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7164
+ UNIQUE (channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7165
+ )
7166
+ `);
7167
+ await client.query(`
7168
+ CREATE INDEX IF NOT EXISTS idx_channel_identity_lookup
7169
+ ON channel_identity_mappings(channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
7170
+ `);
7171
+ await client.query(`
7172
+ CREATE INDEX IF NOT EXISTS idx_channel_identity_thread
7173
+ ON channel_identity_mappings(thread_id, tenant_id)
7174
+ `);
7175
+ await client.query(`
7176
+ CREATE TABLE IF NOT EXISTS channel_inbound_message_receipts (
7177
+ channel VARCHAR(50) NOT NULL,
7178
+ channel_app_id VARCHAR(255) NOT NULL,
7179
+ external_message_id VARCHAR(255) NOT NULL,
7180
+ tenant_id VARCHAR(255) NOT NULL,
7181
+ status VARCHAR(20) NOT NULL DEFAULT 'processing' CHECK (status IN ('processing', 'completed', 'failed')),
7182
+ thread_id VARCHAR(255),
7183
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7184
+ updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7185
+ PRIMARY KEY (channel, channel_app_id, external_message_id)
7186
+ )
7187
+ `);
7188
+ },
7189
+ down: async (client) => {
7190
+ await client.query("DROP TABLE IF EXISTS channel_inbound_message_receipts");
7191
+ await client.query("DROP INDEX IF EXISTS idx_channel_identity_thread");
7192
+ await client.query("DROP INDEX IF EXISTS idx_channel_identity_lookup");
7193
+ await client.query("DROP TABLE IF EXISTS channel_identity_mappings");
7194
+ }
7195
+ };
7196
+
7197
+ // src/createPgStoreConfig.ts
7198
+ async function createPgStoreConfig(connectionString) {
7199
+ const pool = new import_pg21.Pool({ connectionString });
7200
+ const mm = new MigrationManager(pool);
7201
+ mm.register(createThreadsTable);
7202
+ mm.register(createScheduledTasksTable);
7203
+ mm.register(createAssistantsTable);
7204
+ mm.register(createSkillsTable);
7205
+ mm.register(createWorkspacesTable);
7206
+ mm.register(createProjectsTable);
7207
+ mm.register(createUsersTable);
7208
+ mm.register(createTenantsTable);
7209
+ mm.register(addUserStatusColumn);
7210
+ mm.register(createUserTenantLinkTable);
7211
+ mm.register(migrateRemoveTenantIdFromUsers);
7212
+ mm.register(createMetricsConfigsTable);
7213
+ mm.register(createMcpServerConfigsTable);
7214
+ mm.register(addAssistantTenantId);
7215
+ mm.register(addSkillTenantId);
7216
+ mm.register(changeSkillPrimaryKey);
7217
+ mm.register(addScheduleTenantId);
7218
+ mm.register(changeThreadPrimaryKey);
7219
+ mm.register(createChannelIdentityMappingTables);
7220
+ mm.register(createChannelInstallationsTable);
7221
+ mm.register(addThreadTenantId);
7222
+ mm.register(addProjectConfigColumn);
7223
+ mm.register(createThreadMessageQueueTable);
7224
+ mm.register(addPriorityAndCommandColumns);
7225
+ mm.register(alterMessageQueueIdColumn);
7226
+ mm.register(createWorkflowTrackingTables);
7227
+ for (const m of evalMigrations) {
7228
+ mm.register(m);
7229
+ }
7230
+ mm.register(alterChannelInstallationsTable);
7231
+ mm.register(createChannelBindingsTable);
7232
+ mm.register(createDatabaseConfigsTable);
7233
+ mm.register(changeAssistantPrimaryKey);
7234
+ mm.register(addStepThreadId);
7235
+ mm.register(addCustomRunConfigColumn);
7236
+ mm.register(createA2AApiKeysTable);
7237
+ mm.register(addWorkspaceProjectToQueue);
7238
+ mm.register(addAssistantOwnerUserId);
7239
+ mm.register(createTasksTable);
7240
+ mm.register(createMenuItemsTable);
7241
+ mm.register(createSharedResourcesTable);
7242
+ mm.register(addFileContentType);
7243
+ await mm.migrate();
7244
+ const checkpoint = import_langgraph_checkpoint_postgres.PostgresSaver.fromConnString(connectionString);
7245
+ checkpoint.setup().catch((err) => {
7246
+ console.error("[pg-stores] Failed to setup checkpoint table:", err.message || err);
7247
+ });
7248
+ const opts = { pool };
7249
+ return {
7250
+ workspace: new PostgreSQLWorkspaceStore(opts),
7251
+ project: new PostgreSQLProjectStore(opts),
7252
+ eval: new PostgreSQLEvalStore(opts),
7253
+ user: new PostgreSQLUserStore(opts),
7254
+ tenant: new PostgreSQLTenantStore(opts),
7255
+ userTenantLink: new PostgreSQLUserTenantLinkStore(opts),
7256
+ channelBinding: new ChannelBindingStore(opts),
7257
+ channelInstallation: new PostgreSQLChannelInstallationStore(opts),
7258
+ thread: new PostgreSQLThreadStore(opts),
7259
+ database: new PostgreSQLDatabaseConfigStore(opts),
7260
+ metrics: new PostgreSQLMetricsServerConfigStore(opts),
7261
+ mcp: new PostgreSQLMcpServerConfigStore(opts),
7262
+ assistant: new PostgreSQLAssistantStore(opts),
7263
+ workflowTracking: new PostgreSQLWorkflowTrackingStore(opts),
7264
+ threadMessageQueue: new ThreadMessageQueueStore(opts),
7265
+ task: new PostgreSQLTaskStore(opts),
7266
+ a2aApiKey: new PostgreSQLA2AApiKeyStore(opts),
7267
+ schedule: new PostgreSQLScheduleStorage(opts),
7268
+ menu: new MenuStore(opts),
7269
+ sharedResource: new PostgresSharedResourceStore(opts),
7270
+ checkpoint
7271
+ };
7272
+ }
7273
+
6927
7274
  // src/stores/PostgreSQLSkillStore.ts
7275
+ var import_pg22 = require("pg");
6928
7276
  var PostgreSQLSkillStore = class {
6929
7277
  constructor(options) {
6930
7278
  this.initialized = false;
6931
7279
  this.ownsPool = true;
6932
7280
  this.initPromise = null;
7281
+ if (options.pool) {
7282
+ this.pool = options.pool;
7283
+ this.ownsPool = false;
7284
+ this.initialized = true;
7285
+ return;
7286
+ }
6933
7287
  if (typeof options.poolConfig === "string") {
6934
- this.pool = new import_pg21.Pool({ connectionString: options.poolConfig });
7288
+ this.pool = new import_pg22.Pool({ connectionString: options.poolConfig });
7289
+ } else if (options.poolConfig) {
7290
+ this.pool = new import_pg22.Pool(options.poolConfig);
6935
7291
  } else {
6936
- this.pool = new import_pg21.Pool(options.poolConfig);
7292
+ throw new Error("Either pool or poolConfig must be provided");
6937
7293
  }
6938
7294
  this.migrationManager = new MigrationManager(this.pool);
6939
7295
  this.migrationManager.register(createSkillsTable);
@@ -7231,68 +7587,22 @@ var PostgreSQLSkillStore = class {
7231
7587
  }
7232
7588
  };
7233
7589
 
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
7590
  // src/stores/ChannelIdentityMappingStore.ts
7290
- var import_pg22 = require("pg");
7591
+ var import_pg23 = require("pg");
7291
7592
  var ChannelIdentityMappingStore = class {
7292
7593
  constructor(options) {
7293
7594
  this.initialized = false;
7595
+ this.ownsPool = true;
7294
7596
  this.initPromise = null;
7295
- this.pool = typeof options.poolConfig === "string" ? new import_pg22.Pool({ connectionString: options.poolConfig }) : new import_pg22.Pool(options.poolConfig);
7597
+ if (options.pool) {
7598
+ this.pool = options.pool;
7599
+ this.ownsPool = false;
7600
+ this.initialized = true;
7601
+ return;
7602
+ }
7603
+ this.pool = typeof options.poolConfig === "string" ? new import_pg23.Pool({ connectionString: options.poolConfig }) : options.poolConfig ? new import_pg23.Pool(options.poolConfig) : (() => {
7604
+ throw new Error("Either pool or poolConfig must be provided");
7605
+ })();
7296
7606
  this.migrationManager = new MigrationManager(this.pool);
7297
7607
  this.migrationManager.register(createChannelIdentityMappingTables);
7298
7608
  if (options.autoMigrate !== false) {
@@ -7319,6 +7629,11 @@ var ChannelIdentityMappingStore = class {
7319
7629
  })();
7320
7630
  return this.initPromise;
7321
7631
  }
7632
+ async dispose() {
7633
+ if (this.ownsPool && this.pool) {
7634
+ await this.pool.end();
7635
+ }
7636
+ }
7322
7637
  async createMapping(input) {
7323
7638
  await this.ensureInitialized();
7324
7639
  const result = await this.pool.query(