@axiom-lattice/pg-stores 3.3.4 → 3.3.6

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 (29) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +20 -0
  3. package/dist/index.d.mts +6 -4
  4. package/dist/index.d.ts +6 -4
  5. package/dist/index.js +153 -71
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +160 -78
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +2 -2
  10. package/scripts/verify-model-provider-migrations.ts +214 -0
  11. package/scripts/verify-store.ts +232 -0
  12. package/src/__tests__/PostgreSQLA2AApiKeyStore.test.ts +41 -4
  13. package/src/__tests__/PostgreSQLChannelInstallationStore.test.ts +48 -4
  14. package/src/__tests__/PostgreSQLConnectionStore.integration.test.ts +60 -1
  15. package/src/__tests__/PostgreSQLDatabaseConfigStore.test.ts +53 -0
  16. package/src/__tests__/PostgreSQLMcpServerConfigStore.test.ts +43 -0
  17. package/src/__tests__/PostgreSQLMetricsServerConfigStore.test.ts +59 -0
  18. package/src/__tests__/PostgreSQLModelProviderStore.test.ts +58 -0
  19. package/src/__tests__/PostgreSQLProjectRoomMessageStore.correlatedInterrupt.integration.test.ts +74 -0
  20. package/src/__tests__/PostgreSQLProjectRoomMessageStore.test.ts +23 -0
  21. package/src/createPgStoreConfig.ts +6 -1
  22. package/src/migrations/connection_config_migrations.ts +56 -0
  23. package/src/migrations/model_provider_migrations.ts +74 -0
  24. package/src/stores/PostgreSQLA2AApiKeyStore.ts +4 -17
  25. package/src/stores/PostgreSQLChannelInstallationStore.ts +4 -4
  26. package/src/stores/PostgreSQLDatabaseConfigStore.ts +2 -7
  27. package/src/stores/PostgreSQLMcpServerConfigStore.ts +9 -19
  28. package/src/stores/PostgreSQLMetricsServerConfigStore.ts +3 -13
  29. package/src/stores/PostgreSQLModelProviderStore.ts +128 -25
@@ -1,5 +1,5 @@
1
1
 
2
- > @axiom-lattice/pg-stores@3.3.4 build /home/runner/work/agentic/agentic/packages/pg-stores
2
+ > @axiom-lattice/pg-stores@3.3.6 build /home/runner/work/agentic/agentic/packages/pg-stores
3
3
  > tsup src/index.ts --format cjs,esm --dts --sourcemap
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -8,13 +8,13 @@
8
8
  CLI Target: es2020
9
9
  CJS Build start
10
10
  ESM Build start
11
- CJS dist/index.js 443.09 KB
12
- CJS dist/index.js.map 807.74 KB
13
- CJS ⚡️ Build success in 1017ms
14
- ESM dist/index.mjs 434.40 KB
15
- ESM dist/index.mjs.map 807.39 KB
16
- ESM ⚡️ Build success in 1084ms
11
+ CJS dist/index.js 446.36 KB
12
+ CJS dist/index.js.map 818.00 KB
13
+ CJS ⚡️ Build success in 929ms
14
+ ESM dist/index.mjs 437.71 KB
15
+ ESM dist/index.mjs.map 817.68 KB
16
+ ESM ⚡️ Build success in 931ms
17
17
  DTS Build start
18
- DTS ⚡️ Build success in 14116ms
19
- DTS dist/index.d.ts 93.36 KB
20
- DTS dist/index.d.mts 93.36 KB
18
+ DTS ⚡️ Build success in 12265ms
19
+ DTS dist/index.d.ts 93.45 KB
20
+ DTS dist/index.d.mts 93.45 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @axiom-lattice/pg-stores
2
2
 
3
+ ## 3.3.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [726c98a]
8
+ - @axiom-lattice/core@7.0.0
9
+
10
+ ## 3.3.5
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [cb75780]
15
+ - Updated dependencies [c0f75e2]
16
+ - Updated dependencies [48e3ce3]
17
+ - Updated dependencies [3e923d0]
18
+ - Updated dependencies [99bf609]
19
+ - Updated dependencies [92bffbb]
20
+ - Updated dependencies [a19e0aa]
21
+ - @axiom-lattice/core@6.4.1
22
+
3
23
  ## 3.3.4
4
24
 
5
25
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1045,8 +1045,6 @@ declare class PostgreSQLA2AApiKeyStore implements A2AApiKeyStore {
1045
1045
  initialize(): Promise<void>;
1046
1046
  dispose(): Promise<void>;
1047
1047
  private ensureInitialized;
1048
- /** Map rows that decrypt cleanly; skip rows under an unknown key. */
1049
- private safeMap;
1050
1048
  findByKey(key: string): Promise<A2AApiKeyRecord | null>;
1051
1049
  findById(id: string): Promise<A2AApiKeyRecord | null>;
1052
1050
  list(params: {
@@ -1807,8 +1805,12 @@ declare class PostgreSQLModelProviderStore implements ModelProviderStore {
1807
1805
  * is an independent model.
1808
1806
  *
1809
1807
  * Models the upstream no longer offers are deleted; models that survive are
1810
- * upserted *without* touching `enabled`, so the tenant's enable/disable
1811
- * choice survives a re-discovery. New rows take the column default (enabled).
1808
+ * upserted *without* touching `enabled` or `extra`, so the tenant's choices
1809
+ * survive a re-discovery. New rows take the column defaults.
1810
+ *
1811
+ * The default model is the exception to the delete: it is kept and flagged
1812
+ * `stale` instead, because deleting it would take the tenant's default away
1813
+ * with no confirmation.
1812
1814
  */
1813
1815
  replaceProviderModels(tenantId: string, providerId: string, models: ProviderModelInput[]): Promise<string[]>;
1814
1816
  /**
package/dist/index.d.ts CHANGED
@@ -1045,8 +1045,6 @@ declare class PostgreSQLA2AApiKeyStore implements A2AApiKeyStore {
1045
1045
  initialize(): Promise<void>;
1046
1046
  dispose(): Promise<void>;
1047
1047
  private ensureInitialized;
1048
- /** Map rows that decrypt cleanly; skip rows under an unknown key. */
1049
- private safeMap;
1050
1048
  findByKey(key: string): Promise<A2AApiKeyRecord | null>;
1051
1049
  findById(id: string): Promise<A2AApiKeyRecord | null>;
1052
1050
  list(params: {
@@ -1807,8 +1805,12 @@ declare class PostgreSQLModelProviderStore implements ModelProviderStore {
1807
1805
  * is an independent model.
1808
1806
  *
1809
1807
  * Models the upstream no longer offers are deleted; models that survive are
1810
- * upserted *without* touching `enabled`, so the tenant's enable/disable
1811
- * choice survives a re-discovery. New rows take the column default (enabled).
1808
+ * upserted *without* touching `enabled` or `extra`, so the tenant's choices
1809
+ * survive a re-discovery. New rows take the column defaults.
1810
+ *
1811
+ * The default model is the exception to the delete: it is kept and flagged
1812
+ * `stale` instead, because deleting it would take the tenant's default away
1813
+ * with no confirmation.
1812
1814
  */
1813
1815
  replaceProviderModels(tenantId: string, providerId: string, models: ProviderModelInput[]): Promise<string[]>;
1814
1816
  /**
package/dist/index.js CHANGED
@@ -1349,12 +1349,7 @@ var PostgreSQLDatabaseConfigStore = class {
1349
1349
  mapRowToEntry(row) {
1350
1350
  const config = typeof row.config === "string" ? JSON.parse(row.config) : row.config;
1351
1351
  if (config.password) {
1352
- try {
1353
- config.password = (0, import_core.decrypt)(config.password);
1354
- } catch (error) {
1355
- console.error("Failed to decrypt database password:", error);
1356
- throw new Error("Failed to decrypt database configuration");
1357
- }
1352
+ config.password = (0, import_core.safeDecrypt)(config.password);
1358
1353
  }
1359
1354
  return {
1360
1355
  id: row.id,
@@ -1786,20 +1781,10 @@ var PostgreSQLMetricsServerConfigStore = class {
1786
1781
  mapRowToEntry(row) {
1787
1782
  const config = typeof row.config === "string" ? JSON.parse(row.config) : row.config;
1788
1783
  if (config.apiKey) {
1789
- try {
1790
- config.apiKey = (0, import_core3.decrypt)(config.apiKey);
1791
- } catch (error) {
1792
- console.error("Failed to decrypt apiKey:", error);
1793
- throw new Error("Failed to decrypt metrics server configuration");
1794
- }
1784
+ config.apiKey = (0, import_core3.safeDecrypt)(config.apiKey);
1795
1785
  }
1796
1786
  if (config.password) {
1797
- try {
1798
- config.password = (0, import_core3.decrypt)(config.password);
1799
- } catch (error) {
1800
- console.error("Failed to decrypt password:", error);
1801
- throw new Error("Failed to decrypt metrics server configuration");
1802
- }
1787
+ config.password = (0, import_core3.safeDecrypt)(config.password);
1803
1788
  }
1804
1789
  return {
1805
1790
  id: row.id,
@@ -2146,28 +2131,18 @@ var PostgreSQLMcpServerConfigStore = class {
2146
2131
  mapRowToEntry(row) {
2147
2132
  const config = typeof row.config === "string" ? JSON.parse(row.config) : row.config;
2148
2133
  if (config.env && row.is_env_encrypted) {
2149
- try {
2150
- const decryptedEnv = {};
2151
- for (const [key, value] of Object.entries(config.env)) {
2152
- decryptedEnv[key] = (0, import_core4.decrypt)(value);
2153
- }
2154
- config.env = decryptedEnv;
2155
- } catch (error) {
2156
- console.error("Failed to decrypt MCP server env:", error);
2157
- throw new Error("Failed to decrypt MCP server configuration");
2134
+ const decryptedEnv = {};
2135
+ for (const [key, value] of Object.entries(config.env)) {
2136
+ decryptedEnv[key] = (0, import_core4.safeDecrypt)(value);
2158
2137
  }
2138
+ config.env = decryptedEnv;
2159
2139
  }
2160
2140
  if (config.headers && row.is_env_encrypted) {
2161
- try {
2162
- const decryptedHeaders = {};
2163
- for (const [key, value] of Object.entries(config.headers)) {
2164
- decryptedHeaders[key] = (0, import_core4.decrypt)(value);
2165
- }
2166
- config.headers = decryptedHeaders;
2167
- } catch (error) {
2168
- console.error("Failed to decrypt MCP server headers:", error);
2169
- throw new Error("Failed to decrypt MCP server configuration");
2141
+ const decryptedHeaders = {};
2142
+ for (const [key, value] of Object.entries(config.headers)) {
2143
+ decryptedHeaders[key] = (0, import_core4.safeDecrypt)(value);
2170
2144
  }
2145
+ config.headers = decryptedHeaders;
2171
2146
  }
2172
2147
  return {
2173
2148
  id: row.id,
@@ -6281,9 +6256,9 @@ var PostgreSQLChannelInstallationStore = class {
6281
6256
  decryptSecrets(config) {
6282
6257
  return {
6283
6258
  ...config,
6284
- ...typeof config.appSecret === "string" ? { appSecret: (0, import_core5.decrypt)(config.appSecret) } : {},
6285
- ...typeof config.verificationToken === "string" ? { verificationToken: (0, import_core5.decrypt)(config.verificationToken) } : {},
6286
- ...typeof config.encryptKey === "string" ? { encryptKey: (0, import_core5.decrypt)(config.encryptKey) } : {}
6259
+ ...typeof config.appSecret === "string" ? { appSecret: (0, import_core5.safeDecrypt)(config.appSecret) } : {},
6260
+ ...typeof config.verificationToken === "string" ? { verificationToken: (0, import_core5.safeDecrypt)(config.verificationToken) } : {},
6261
+ ...typeof config.encryptKey === "string" ? { encryptKey: (0, import_core5.safeDecrypt)(config.encryptKey) } : {}
6287
6262
  };
6288
6263
  }
6289
6264
  };
@@ -6369,7 +6344,7 @@ function generateApiKey() {
6369
6344
  function mapRowToRecord(row) {
6370
6345
  return {
6371
6346
  id: row.id,
6372
- key: (0, import_core6.decrypt)(row.key_value),
6347
+ key: (0, import_core6.safeDecrypt)(row.key_value),
6373
6348
  tenantId: row.tenant_id,
6374
6349
  projectId: row.project_id,
6375
6350
  assistantIds: row.assistant_ids ?? void 0,
@@ -6426,17 +6401,6 @@ var PostgreSQLA2AApiKeyStore = class {
6426
6401
  async ensureInitialized() {
6427
6402
  if (!this.initialized) await this.initialize();
6428
6403
  }
6429
- /** Map rows that decrypt cleanly; skip rows under an unknown key. */
6430
- safeMap(rows) {
6431
- const out = [];
6432
- for (const row of rows) {
6433
- try {
6434
- out.push(mapRowToRecord(row));
6435
- } catch {
6436
- }
6437
- }
6438
- return out;
6439
- }
6440
6404
  async findByKey(key) {
6441
6405
  await this.ensureInitialized();
6442
6406
  const all = await this.pool.query(
@@ -6473,13 +6437,13 @@ var PostgreSQLA2AApiKeyStore = class {
6473
6437
  `SELECT * FROM lattice_a2a_api_keys WHERE tenant_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3`,
6474
6438
  [params.tenantId, limit, offset]
6475
6439
  );
6476
- return this.safeMap(result2.rows);
6440
+ return result2.rows.map((row) => mapRowToRecord(row));
6477
6441
  }
6478
6442
  const result = await this.pool.query(
6479
6443
  `SELECT * FROM lattice_a2a_api_keys ORDER BY created_at DESC LIMIT $1 OFFSET $2`,
6480
6444
  [limit, offset]
6481
6445
  );
6482
- return this.safeMap(result.rows);
6446
+ return result.rows.map((row) => mapRowToRecord(row));
6483
6447
  }
6484
6448
  async create(input) {
6485
6449
  await this.ensureInitialized();
@@ -9909,6 +9873,7 @@ var createChannelIdentityMappingTables = {
9909
9873
  };
9910
9874
 
9911
9875
  // src/migrations/connection_config_migrations.ts
9876
+ var import_core8 = require("@axiom-lattice/core");
9912
9877
  var createConnectionConfigsTable = {
9913
9878
  version: 160,
9914
9879
  name: "create_connection_configs_table",
@@ -9963,6 +9928,38 @@ var addConnectionSecretFields = {
9963
9928
  `);
9964
9929
  }
9965
9930
  };
9931
+ var reencryptLegacyConnectionSecrets = {
9932
+ version: 191,
9933
+ name: "reencrypt_legacy_connection_secrets",
9934
+ up: async (client) => {
9935
+ const result = await client.query(
9936
+ `SELECT id, tenant_id, config, secret_fields
9937
+ FROM lattice_connection_configs
9938
+ WHERE secret_fields IS NOT NULL`
9939
+ );
9940
+ for (const row of result.rows) {
9941
+ const secretFields = Array.isArray(row.secret_fields) ? row.secret_fields.filter((field) => typeof field === "string") : [];
9942
+ if (secretFields.length === 0) continue;
9943
+ const config = row.config && typeof row.config === "object" ? { ...row.config } : {};
9944
+ let changed = false;
9945
+ for (const field of secretFields) {
9946
+ const value = config[field];
9947
+ if (typeof value === "string" && value.length > 0 && !(0, import_core8.isEncryptedValue)(value)) {
9948
+ config[field] = (0, import_core8.encrypt)(value);
9949
+ changed = true;
9950
+ }
9951
+ }
9952
+ if (changed) {
9953
+ await client.query(
9954
+ `UPDATE lattice_connection_configs
9955
+ SET config = $1::jsonb, updated_at = CURRENT_TIMESTAMP
9956
+ WHERE tenant_id = $2 AND id = $3`,
9957
+ [JSON.stringify(config), row.tenant_id, row.id]
9958
+ );
9959
+ }
9960
+ }
9961
+ }
9962
+ };
9966
9963
 
9967
9964
  // src/migrations/add_share_open_grants.ts
9968
9965
  var addShareOpenGrants = {
@@ -10437,6 +10434,44 @@ var addModelProviderModelStale = {
10437
10434
  `);
10438
10435
  }
10439
10436
  };
10437
+ var addModelProviderModelExtra = {
10438
+ version: 191,
10439
+ name: "add_model_provider_model_extra",
10440
+ up: async (client) => {
10441
+ await client.query(`
10442
+ ALTER TABLE lattice_model_provider_models
10443
+ ADD COLUMN IF NOT EXISTS extra JSONB NOT NULL DEFAULT '{}'::jsonb
10444
+ `);
10445
+ },
10446
+ down: async (client) => {
10447
+ await client.query(`
10448
+ ALTER TABLE lattice_model_provider_models DROP COLUMN IF EXISTS extra
10449
+ `);
10450
+ }
10451
+ };
10452
+ var addModelProviderModelDefault = {
10453
+ version: 192,
10454
+ name: "add_model_provider_model_default",
10455
+ up: async (client) => {
10456
+ await client.query(`
10457
+ ALTER TABLE lattice_model_provider_models
10458
+ ADD COLUMN IF NOT EXISTS is_default BOOLEAN NOT NULL DEFAULT FALSE
10459
+ `);
10460
+ await client.query(`
10461
+ CREATE UNIQUE INDEX IF NOT EXISTS uk_lattice_model_provider_models_tenant_default
10462
+ ON lattice_model_provider_models (tenant_id)
10463
+ WHERE is_default
10464
+ `);
10465
+ },
10466
+ down: async (client) => {
10467
+ await client.query(`
10468
+ DROP INDEX IF EXISTS uk_lattice_model_provider_models_tenant_default
10469
+ `);
10470
+ await client.query(`
10471
+ ALTER TABLE lattice_model_provider_models DROP COLUMN IF EXISTS is_default
10472
+ `);
10473
+ }
10474
+ };
10440
10475
 
10441
10476
  // src/stores/PostgreSQLCapabilityBundleStore.ts
10442
10477
  var import_crypto4 = require("crypto");
@@ -11401,7 +11436,10 @@ var PostgreSQLUserPushSubscriptionStore = class {
11401
11436
 
11402
11437
  // src/stores/PostgreSQLModelProviderStore.ts
11403
11438
  var import_pg27 = require("pg");
11404
- var import_core8 = require("@axiom-lattice/core");
11439
+ var import_core9 = require("@axiom-lattice/core");
11440
+ function extraOrUndefined(value) {
11441
+ return value && Object.keys(value).length > 0 ? value : void 0;
11442
+ }
11405
11443
  var PostgreSQLModelProviderStore = class {
11406
11444
  constructor(options) {
11407
11445
  this.initialized = false;
@@ -11423,6 +11461,10 @@ var PostgreSQLModelProviderStore = class {
11423
11461
  this.migrationManager = new MigrationManager(this.pool);
11424
11462
  this.migrationManager.register(createModelProvidersTable);
11425
11463
  this.migrationManager.register(createModelProviderModelsTable);
11464
+ this.migrationManager.register(addModelProviderApiStyle);
11465
+ this.migrationManager.register(addModelProviderModelStale);
11466
+ this.migrationManager.register(addModelProviderModelExtra);
11467
+ this.migrationManager.register(addModelProviderModelDefault);
11426
11468
  if (options.autoMigrate !== false) {
11427
11469
  this.initialize().catch((error) => {
11428
11470
  console.error("Failed to initialize PostgreSQLModelProviderStore:", error);
@@ -11516,7 +11558,7 @@ var PostgreSQLModelProviderStore = class {
11516
11558
  await this.ensureInitialized();
11517
11559
  const now = /* @__PURE__ */ new Date();
11518
11560
  const nowString = now.toISOString();
11519
- const apiKeyEnc = data.apiKey ? (0, import_core8.encrypt)(data.apiKey) : null;
11561
+ const apiKeyEnc = data.apiKey ? (0, import_core9.encrypt)(data.apiKey) : null;
11520
11562
  const apiKeyHint = data.apiKey ? data.apiKey.slice(-4) : null;
11521
11563
  await this.pool.query(
11522
11564
  `
@@ -11592,7 +11634,7 @@ var PostgreSQLModelProviderStore = class {
11592
11634
  updateData.api_key_enc = null;
11593
11635
  updateData.api_key_hint = null;
11594
11636
  } else if (updates.apiKey) {
11595
- updateData.api_key_enc = (0, import_core8.encrypt)(updates.apiKey);
11637
+ updateData.api_key_enc = (0, import_core9.encrypt)(updates.apiKey);
11596
11638
  updateData.api_key_hint = updates.apiKey.slice(-4);
11597
11639
  }
11598
11640
  if (updates.enabled !== void 0) {
@@ -11669,7 +11711,7 @@ var PostgreSQLModelProviderStore = class {
11669
11711
  const result = providerId ? await this.pool.query(
11670
11712
  `
11671
11713
  SELECT id, tenant_id, provider_id, model_id, display_name, owned_by,
11672
- upstream_created, enabled, stale, discovered_at
11714
+ upstream_created, enabled, stale, extra, is_default, discovered_at
11673
11715
  FROM lattice_model_provider_models
11674
11716
  WHERE tenant_id = $1 AND provider_id = $2
11675
11717
  ORDER BY model_id ASC
@@ -11678,7 +11720,7 @@ var PostgreSQLModelProviderStore = class {
11678
11720
  ) : await this.pool.query(
11679
11721
  `
11680
11722
  SELECT id, tenant_id, provider_id, model_id, display_name, owned_by,
11681
- upstream_created, enabled, discovered_at
11723
+ upstream_created, enabled, stale, extra, is_default, discovered_at
11682
11724
  FROM lattice_model_provider_models
11683
11725
  WHERE tenant_id = $1
11684
11726
  ORDER BY model_id ASC
@@ -11697,7 +11739,7 @@ var PostgreSQLModelProviderStore = class {
11697
11739
  const result = await this.pool.query(
11698
11740
  `
11699
11741
  SELECT id, tenant_id, provider_id, model_id, display_name, owned_by,
11700
- upstream_created, enabled, discovered_at
11742
+ upstream_created, enabled, stale, extra, is_default, discovered_at
11701
11743
  FROM lattice_model_provider_models
11702
11744
  WHERE tenant_id = $1 AND provider_id = $2 AND model_id = $3
11703
11745
  `,
@@ -11716,8 +11758,12 @@ var PostgreSQLModelProviderStore = class {
11716
11758
  * is an independent model.
11717
11759
  *
11718
11760
  * Models the upstream no longer offers are deleted; models that survive are
11719
- * upserted *without* touching `enabled`, so the tenant's enable/disable
11720
- * choice survives a re-discovery. New rows take the column default (enabled).
11761
+ * upserted *without* touching `enabled` or `extra`, so the tenant's choices
11762
+ * survive a re-discovery. New rows take the column defaults.
11763
+ *
11764
+ * The default model is the exception to the delete: it is kept and flagged
11765
+ * `stale` instead, because deleting it would take the tenant's default away
11766
+ * with no confirmation.
11721
11767
  */
11722
11768
  async replaceProviderModels(tenantId, providerId, models) {
11723
11769
  await this.ensureInitialized();
@@ -11726,7 +11772,7 @@ var PostgreSQLModelProviderStore = class {
11726
11772
  await client.query("BEGIN");
11727
11773
  const current = await client.query(
11728
11774
  `
11729
- SELECT model_id, enabled FROM lattice_model_provider_models
11775
+ SELECT model_id, enabled, extra, is_default FROM lattice_model_provider_models
11730
11776
  WHERE tenant_id = $1 AND provider_id = $2
11731
11777
  `,
11732
11778
  [tenantId, providerId]
@@ -11734,6 +11780,12 @@ var PostgreSQLModelProviderStore = class {
11734
11780
  const currentEnabled = new Map(
11735
11781
  current.rows.map((row) => [row.model_id, row.enabled])
11736
11782
  );
11783
+ const currentExtra = new Map(
11784
+ current.rows.map((row) => [row.model_id, row.extra])
11785
+ );
11786
+ const currentIsDefault = new Map(
11787
+ current.rows.map((row) => [row.model_id, row.is_default])
11788
+ );
11737
11789
  const deduped = /* @__PURE__ */ new Map();
11738
11790
  for (const model of models) {
11739
11791
  deduped.set(model.id, model);
@@ -11742,12 +11794,37 @@ var PostgreSQLModelProviderStore = class {
11742
11794
  const effectiveEnabled = rows.map(
11743
11795
  (model) => model.enabled ?? currentEnabled.get(model.id) ?? true
11744
11796
  );
11797
+ const effectiveExtra = rows.map(
11798
+ (model) => model.extra ?? currentExtra.get(model.id) ?? {}
11799
+ );
11800
+ const namesDefault = rows.some((model) => model.isDefault === true);
11801
+ if (namesDefault) {
11802
+ await client.query(
11803
+ `UPDATE lattice_model_provider_models SET is_default = FALSE WHERE tenant_id = $1`,
11804
+ [tenantId]
11805
+ );
11806
+ }
11807
+ const effectiveIsDefault = rows.map(
11808
+ (model) => model.isDefault ?? (namesDefault ? false : currentIsDefault.get(model.id)) ?? false
11809
+ );
11810
+ await client.query(
11811
+ `
11812
+ UPDATE lattice_model_provider_models
11813
+ SET stale = TRUE
11814
+ WHERE tenant_id = $1
11815
+ AND provider_id = $2
11816
+ AND model_id <> ALL($3::text[])
11817
+ AND is_default
11818
+ `,
11819
+ [tenantId, providerId, rows.map((model) => model.id)]
11820
+ );
11745
11821
  await client.query(
11746
11822
  `
11747
11823
  DELETE FROM lattice_model_provider_models
11748
11824
  WHERE tenant_id = $1
11749
11825
  AND provider_id = $2
11750
11826
  AND model_id <> ALL($3::text[])
11827
+ AND NOT is_default
11751
11828
  `,
11752
11829
  [tenantId, providerId, rows.map((model) => model.id)]
11753
11830
  );
@@ -11756,14 +11833,15 @@ var PostgreSQLModelProviderStore = class {
11756
11833
  `
11757
11834
  INSERT INTO lattice_model_provider_models (
11758
11835
  id, tenant_id, provider_id, model_id, display_name, owned_by,
11759
- upstream_created, raw, enabled, stale, discovered_at
11836
+ upstream_created, raw, enabled, stale, extra, is_default, discovered_at
11760
11837
  )
11761
11838
  SELECT * FROM unnest(
11762
11839
  $1::text[], $2::text[], $3::text[], $4::text[], $5::text[],
11763
- $6::text[], $7::timestamp[], $8::jsonb[], $9::boolean[], $10::boolean[], $11::timestamp[]
11840
+ $6::text[], $7::timestamp[], $8::jsonb[], $9::boolean[], $10::boolean[],
11841
+ $11::jsonb[], $12::boolean[], $13::timestamp[]
11764
11842
  ) AS t(
11765
11843
  id, tenant_id, provider_id, model_id, display_name, owned_by,
11766
- upstream_created, raw, enabled, stale, discovered_at
11844
+ upstream_created, raw, enabled, stale, extra, is_default, discovered_at
11767
11845
  )
11768
11846
  ON CONFLICT (tenant_id, provider_id, model_id) DO UPDATE SET
11769
11847
  display_name = EXCLUDED.display_name,
@@ -11772,6 +11850,8 @@ var PostgreSQLModelProviderStore = class {
11772
11850
  raw = EXCLUDED.raw,
11773
11851
  enabled = EXCLUDED.enabled,
11774
11852
  stale = EXCLUDED.stale,
11853
+ extra = EXCLUDED.extra,
11854
+ is_default = EXCLUDED.is_default,
11775
11855
  discovered_at = EXCLUDED.discovered_at
11776
11856
  `,
11777
11857
  [
@@ -11789,6 +11869,8 @@ var PostgreSQLModelProviderStore = class {
11789
11869
  ),
11790
11870
  effectiveEnabled,
11791
11871
  rows.map((model) => model.stale ?? false),
11872
+ effectiveExtra.map((extra) => JSON.stringify(extra)),
11873
+ effectiveIsDefault,
11792
11874
  rows.map(() => (/* @__PURE__ */ new Date()).toISOString())
11793
11875
  ]
11794
11876
  );
@@ -11857,12 +11939,7 @@ var PostgreSQLModelProviderStore = class {
11857
11939
  mapRowToEntry(row) {
11858
11940
  let apiKey;
11859
11941
  if (row.api_key_enc) {
11860
- try {
11861
- apiKey = (0, import_core8.decrypt)(row.api_key_enc);
11862
- } catch (error) {
11863
- console.error("Failed to decrypt model provider API key:", error);
11864
- throw new Error("Failed to decrypt model provider API key");
11865
- }
11942
+ apiKey = (0, import_core9.safeDecrypt)(row.api_key_enc);
11866
11943
  }
11867
11944
  return {
11868
11945
  id: row.id,
@@ -11898,6 +11975,8 @@ var PostgreSQLModelProviderStore = class {
11898
11975
  upstreamCreatedAt: row.upstream_created || void 0,
11899
11976
  enabled: row.enabled,
11900
11977
  stale: row.stale,
11978
+ extra: extraOrUndefined(row.extra),
11979
+ isDefault: row.is_default,
11901
11980
  discoveredAt: row.discovered_at
11902
11981
  };
11903
11982
  }
@@ -12322,8 +12401,11 @@ async function createPgStoreConfig(connectionString) {
12322
12401
  mm.register(createDistributedLeases);
12323
12402
  mm.register(createOutboxTable);
12324
12403
  mm.register(addConnectionSecretFields);
12404
+ mm.register(reencryptLegacyConnectionSecrets);
12325
12405
  mm.register(createPluginDeployments);
12326
12406
  mm.register(dropPluginDeploymentAuthToken);
12407
+ mm.register(addModelProviderModelExtra);
12408
+ mm.register(addModelProviderModelDefault);
12327
12409
  await mm.migrate();
12328
12410
  const checkpoint = import_langgraph_checkpoint_postgres.PostgresSaver.fromConnString(connectionString);
12329
12411
  checkpoint.setup().catch((err) => {