@elizaos/plugin-sql 1.6.5 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5765,6 +5765,14 @@ var init_server = __esm(() => {
5765
5765
  });
5766
5766
  });
5767
5767
 
5768
+ // src/types.ts
5769
+ function getDb(adapter) {
5770
+ return adapter.db;
5771
+ }
5772
+ function getRow(result, index2 = 0) {
5773
+ return result.rows[index2];
5774
+ }
5775
+
5768
5776
  // src/runtime-migrator/storage/migration-tracker.ts
5769
5777
  class MigrationTracker {
5770
5778
  db;
@@ -5804,12 +5812,12 @@ class MigrationTracker {
5804
5812
  `);
5805
5813
  }
5806
5814
  async getLastMigration(pluginName) {
5807
- const result = await this.db.execute(sql`SELECT id, hash, created_at
5808
- FROM migrations._migrations
5809
- WHERE plugin_name = ${pluginName}
5810
- ORDER BY created_at DESC
5815
+ const result = await this.db.execute(sql`SELECT id, hash, created_at
5816
+ FROM migrations._migrations
5817
+ WHERE plugin_name = ${pluginName}
5818
+ ORDER BY created_at DESC
5811
5819
  LIMIT 1`);
5812
- return result.rows[0] || null;
5820
+ return getRow(result) || null;
5813
5821
  }
5814
5822
  async recordMigration(pluginName, hash, createdAt) {
5815
5823
  await this.db.execute(sql`INSERT INTO migrations._migrations (plugin_name, hash, created_at)
@@ -5833,7 +5841,7 @@ class JournalStorage {
5833
5841
  if (result.rows.length === 0) {
5834
5842
  return null;
5835
5843
  }
5836
- const row = result.rows[0];
5844
+ const row = getRow(result);
5837
5845
  return {
5838
5846
  version: row.version,
5839
5847
  dialect: row.dialect,
@@ -7488,48 +7496,15 @@ class RuntimeMigrator {
7488
7496
  return value >= MIN_BIGINT && value <= MAX_BIGINT;
7489
7497
  }
7490
7498
  isRealPostgresDatabase(connectionUrl) {
7491
- if (!connectionUrl || connectionUrl.trim() === "") {
7499
+ if (!connectionUrl?.trim())
7492
7500
  return false;
7493
- }
7494
- const trimmedUrl = connectionUrl.trim();
7495
- const url = trimmedUrl.toLowerCase();
7496
- const originalUrl = trimmedUrl;
7497
- const nonPostgresSchemes = [
7498
- "mysql://",
7499
- "mysqli://",
7500
- "mariadb://",
7501
- "mongodb://",
7502
- "mongodb+srv://"
7503
- ];
7504
- for (const scheme of nonPostgresSchemes) {
7505
- if (url.startsWith(scheme)) {
7506
- return false;
7507
- }
7508
- }
7509
- const excludePatterns = [
7510
- ":memory:",
7511
- "pglite://",
7512
- "/pglite",
7513
- "sqlite://",
7514
- "sqlite3://",
7515
- ".sqlite",
7516
- ".sqlite3",
7517
- "file::memory:",
7518
- "file:"
7519
- ];
7520
- const urlWithoutQuery = url.split("?")[0];
7521
- if (urlWithoutQuery.endsWith(".db") || urlWithoutQuery.endsWith(".sqlite") || urlWithoutQuery.endsWith(".sqlite3")) {
7501
+ const url = connectionUrl.trim().toLowerCase();
7502
+ const nonPgSchemes = ["mysql://", "mysqli://", "mariadb://", "mongodb://", "mongodb+srv://"];
7503
+ if (nonPgSchemes.some((s) => url.startsWith(s)))
7522
7504
  return false;
7523
- }
7524
- for (const pattern of excludePatterns) {
7525
- if (url.includes(pattern)) {
7526
- if (pattern === "file:" && url.includes("postgres")) {
7527
- continue;
7528
- }
7529
- return false;
7530
- }
7531
- }
7532
- const postgresSchemes = [
7505
+ if (url.includes(":memory:"))
7506
+ return false;
7507
+ const pgSchemes = [
7533
7508
  "postgres://",
7534
7509
  "postgresql://",
7535
7510
  "postgis://",
@@ -7541,12 +7516,17 @@ class RuntimeMigrator {
7541
7516
  "timescaledb://",
7542
7517
  "yugabyte://"
7543
7518
  ];
7544
- for (const scheme of postgresSchemes) {
7545
- if (url.startsWith(scheme)) {
7546
- return true;
7547
- }
7548
- }
7549
- const connectionParams = [
7519
+ if (pgSchemes.some((s) => url.startsWith(s)))
7520
+ return true;
7521
+ const excludePatterns = ["pglite", "sqlite"];
7522
+ const urlBase = url.split("?")[0];
7523
+ if (excludePatterns.some((p) => url.includes(p)))
7524
+ return false;
7525
+ if (/\.(db|sqlite|sqlite3)$/.test(urlBase))
7526
+ return false;
7527
+ if (url.includes("localhost") || url.includes("127.0.0.1"))
7528
+ return true;
7529
+ const connParams = [
7550
7530
  "host=",
7551
7531
  "dbname=",
7552
7532
  "sslmode=",
@@ -7558,126 +7538,60 @@ class RuntimeMigrator {
7558
7538
  "options=",
7559
7539
  "sslcert=",
7560
7540
  "sslkey=",
7561
- "sslrootcert="
7541
+ "sslrootcert=",
7542
+ "fallback_application_name=",
7543
+ "keepalives=",
7544
+ "target_session_attrs="
7562
7545
  ];
7563
- for (const param of connectionParams) {
7564
- if (url.includes(param)) {
7565
- return true;
7566
- }
7567
- }
7568
- if (url.includes("@") && (url.includes("postgres") || /:\d{4,5}/.test(url))) {
7546
+ if (connParams.some((p) => url.includes(p)))
7569
7547
  return true;
7570
- }
7571
- const postgresPorts = [
7572
- ":5432",
7573
- ":5433",
7574
- ":5434",
7575
- ":25060",
7576
- ":26257",
7577
- ":6432",
7578
- ":9999",
7579
- ":8432"
7580
- ];
7581
- for (const port of postgresPorts) {
7582
- if (url.includes(port)) {
7583
- return true;
7584
- }
7585
- }
7586
- const cloudProviderPatterns = [
7548
+ if (url.includes("@") && (url.includes("postgres") || /:\d{4,5}/.test(url)))
7549
+ return true;
7550
+ if (/:(5432|5433|5434|6432|8432|9999|25060|26257)\b/.test(url))
7551
+ return true;
7552
+ const cloudPatterns = [
7587
7553
  "amazonaws.com",
7588
- "rds.amazonaws.com",
7589
7554
  ".rds.",
7590
- "redshift.amazonaws.com",
7591
7555
  "azure.com",
7592
7556
  "database.azure.com",
7593
- "postgres.database.azure.com",
7594
7557
  "googleusercontent",
7595
7558
  "cloudsql",
7596
- "cloud.google.com",
7597
7559
  "supabase",
7598
- ".supabase.co",
7599
- ".supabase.com",
7600
- "pooler.supabase",
7601
7560
  "neon.tech",
7602
- ".neon.tech",
7603
7561
  "neon.build",
7604
7562
  "railway.app",
7605
- ".railway.app",
7606
7563
  "railway.internal",
7607
7564
  "render.com",
7608
- ".render.com",
7609
7565
  "onrender.com",
7610
- "heroku.com",
7611
- "herokuapp.com",
7612
- ".heroku.com",
7566
+ "heroku",
7613
7567
  "timescale",
7614
- "timescaledb",
7615
7568
  ".tsdb.cloud",
7616
7569
  "cockroachlabs",
7617
7570
  "cockroachdb.cloud",
7618
7571
  ".crdb.io",
7619
- "digitalocean.com",
7572
+ "digitalocean",
7620
7573
  "db.ondigitalocean",
7621
7574
  "do-user-",
7622
- ".db.ondigitalocean.com",
7623
7575
  "aiven",
7624
- "aivencloud",
7625
- ".aiven.io",
7626
- ".aivencloud.com",
7627
7576
  "crunchydata",
7628
- ".crunchydata.com",
7629
7577
  "elephantsql",
7630
- ".elephantsql.com",
7631
7578
  "yugabyte",
7632
- ".yugabyte.cloud",
7633
7579
  "scaleway",
7634
7580
  ".rdb.fr-par.scw.cloud",
7635
7581
  "vercel-storage",
7636
- ".postgres.vercel-storage.com",
7637
7582
  "psdb.cloud",
7638
- ".psdb.cloud",
7639
7583
  "xata.sh",
7640
- ".xata.sh",
7641
7584
  "fly.dev",
7642
- ".fly.dev",
7643
7585
  "fly.io"
7644
7586
  ];
7645
- for (const pattern of cloudProviderPatterns) {
7646
- if (url.includes(pattern)) {
7647
- return true;
7648
- }
7649
- }
7650
- const ipv4PortPattern = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}\b/;
7651
- if (ipv4PortPattern.test(originalUrl)) {
7587
+ if (cloudPatterns.some((p) => url.includes(p)))
7652
7588
  return true;
7653
- }
7654
- const ipv6Pattern = /\[[0-9a-f:]+\](:\d{1,5})?/i;
7655
- if (ipv6Pattern.test(originalUrl)) {
7589
+ if (/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}/.test(url))
7656
7590
  return true;
7657
- }
7658
- const hostPortDbPattern = /^[a-z0-9.-]+:\d{1,5}\/[a-z0-9_-]+/i;
7659
- if (hostPortDbPattern.test(originalUrl)) {
7591
+ if (/\[[0-9a-f:]+\](:\d{1,5})?/i.test(connectionUrl))
7592
+ return true;
7593
+ if (/^[a-z0-9_.-]+:\d{1,5}\/[a-z0-9_-]+/i.test(connectionUrl))
7660
7594
  return true;
7661
- }
7662
- if (url.includes("?") || url.includes("&")) {
7663
- const postgresQueryParams = [
7664
- "sslmode=",
7665
- "sslcert=",
7666
- "sslkey=",
7667
- "sslrootcert=",
7668
- "connect_timeout=",
7669
- "application_name=",
7670
- "options=",
7671
- "fallback_application_name=",
7672
- "keepalives=",
7673
- "target_session_attrs="
7674
- ];
7675
- for (const param of postgresQueryParams) {
7676
- if (url.includes(param)) {
7677
- return true;
7678
- }
7679
- }
7680
- }
7681
7595
  logger6.debug({ src: "plugin:sql", urlPreview: url.substring(0, 50) }, "Connection string did not match any PostgreSQL patterns");
7682
7596
  return false;
7683
7597
  }
@@ -7702,7 +7616,7 @@ class RuntimeMigrator {
7702
7616
  logger6.debug({ src: "plugin:sql", pluginName }, "Using PostgreSQL advisory locks");
7703
7617
  const lockIdStr = lockId.toString();
7704
7618
  const lockResult = await this.db.execute(sql`SELECT pg_try_advisory_lock(CAST(${lockIdStr} AS bigint)) as acquired`);
7705
- lockAcquired = lockResult.rows[0]?.acquired === true;
7619
+ lockAcquired = getRow(lockResult)?.acquired === true;
7706
7620
  if (!lockAcquired) {
7707
7621
  logger6.info({ src: "plugin:sql", pluginName }, "Migration already in progress, waiting for lock");
7708
7622
  await this.db.execute(sql`SELECT pg_advisory_lock(CAST(${lockIdStr} AS bigint))`);
@@ -7743,13 +7657,33 @@ class RuntimeMigrator {
7743
7657
  logger6.info({ src: "plugin:sql", pluginName }, "No snapshot found but tables exist in database, introspecting");
7744
7658
  const schemaName = this.getExpectedSchemaName(pluginName);
7745
7659
  const introspectedSnapshot = await this.introspector.introspectSchema(schemaName);
7746
- if (Object.keys(introspectedSnapshot.tables).length > 0) {
7747
- await this.snapshotStorage.saveSnapshot(pluginName, 0, introspectedSnapshot);
7660
+ const expectedTableNames = new Set;
7661
+ for (const tableKey of Object.keys(currentSnapshot.tables)) {
7662
+ const tableData = currentSnapshot.tables[tableKey];
7663
+ const tableName = tableData.name || tableKey.split(".").pop();
7664
+ expectedTableNames.add(tableName);
7665
+ }
7666
+ const filteredTables = {};
7667
+ for (const tableKey of Object.keys(introspectedSnapshot.tables)) {
7668
+ const tableData = introspectedSnapshot.tables[tableKey];
7669
+ const tableName = tableData.name || tableKey.split(".").pop();
7670
+ if (expectedTableNames.has(tableName)) {
7671
+ filteredTables[tableKey] = tableData;
7672
+ } else {
7673
+ logger6.debug({ src: "plugin:sql", pluginName, tableName }, "Ignoring table from introspection (not in current schema)");
7674
+ }
7675
+ }
7676
+ const filteredSnapshot = {
7677
+ ...introspectedSnapshot,
7678
+ tables: filteredTables
7679
+ };
7680
+ if (Object.keys(filteredSnapshot.tables).length > 0) {
7681
+ await this.snapshotStorage.saveSnapshot(pluginName, 0, filteredSnapshot);
7748
7682
  await this.journalStorage.updateJournal(pluginName, 0, `introspected_${Date.now()}`, true);
7749
- const introspectedHash = hashSnapshot(introspectedSnapshot);
7750
- await this.migrationTracker.recordMigration(pluginName, introspectedHash, Date.now());
7683
+ const filteredHash = hashSnapshot(filteredSnapshot);
7684
+ await this.migrationTracker.recordMigration(pluginName, filteredHash, Date.now());
7751
7685
  logger6.info({ src: "plugin:sql", pluginName }, "Created initial snapshot from existing database");
7752
- previousSnapshot = introspectedSnapshot;
7686
+ previousSnapshot = filteredSnapshot;
7753
7687
  }
7754
7688
  }
7755
7689
  }
@@ -7932,14 +7866,63 @@ var init_runtime_migrator2 = __esm(() => {
7932
7866
  // src/migrations.ts
7933
7867
  import { logger as logger7 } from "@elizaos/core";
7934
7868
  async function migrateToEntityRLS(adapter) {
7935
- const db2 = adapter.db;
7869
+ const db2 = getDb(adapter);
7936
7870
  try {
7937
7871
  await db2.execute(sql`SELECT 1 FROM pg_tables LIMIT 1`);
7938
7872
  } catch {
7939
7873
  logger7.debug("[Migration] ⊘ Not PostgreSQL, skipping PostgreSQL-specific migrations");
7940
7874
  return;
7941
7875
  }
7942
- logger7.info("[Migration] Starting develop → feat/entity-rls migration...");
7876
+ let schemaAlreadyMigrated = false;
7877
+ try {
7878
+ const migrationCheck = await db2.execute(sql`
7879
+ SELECT column_name FROM information_schema.columns
7880
+ WHERE table_schema = 'public'
7881
+ AND table_name = 'rooms'
7882
+ AND column_name = 'agent_id'
7883
+ `);
7884
+ if (migrationCheck.rows && migrationCheck.rows.length > 0) {
7885
+ schemaAlreadyMigrated = true;
7886
+ logger7.debug("[Migration] ⊘ Schema already migrated (snake_case columns exist)");
7887
+ }
7888
+ } catch {
7889
+ logger7.debug("[Migration] → rooms table not found, will be created by RuntimeMigrator");
7890
+ return;
7891
+ }
7892
+ if (schemaAlreadyMigrated) {
7893
+ const dataIsolationEnabled = process.env.ENABLE_DATA_ISOLATION === "true";
7894
+ if (dataIsolationEnabled) {
7895
+ logger7.debug("[Migration] ⊘ Schema already migrated, RLS enabled - nothing to do");
7896
+ return;
7897
+ }
7898
+ logger7.debug("[Migration] → Schema migrated but RLS disabled, cleaning up...");
7899
+ try {
7900
+ const tablesWithRls = await db2.execute(sql`
7901
+ SELECT c.relname as tablename
7902
+ FROM pg_class c
7903
+ JOIN pg_namespace n ON n.oid = c.relnamespace
7904
+ WHERE n.nspname = 'public'
7905
+ AND c.relkind = 'r'
7906
+ AND c.relrowsecurity = true
7907
+ ORDER BY c.relname
7908
+ `);
7909
+ if (tablesWithRls.rows && tablesWithRls.rows.length > 0) {
7910
+ for (const row of tablesWithRls.rows) {
7911
+ const tableName = row.tablename;
7912
+ try {
7913
+ await db2.execute(sql.raw(`ALTER TABLE "${tableName}" DISABLE ROW LEVEL SECURITY`));
7914
+ } catch {}
7915
+ }
7916
+ logger7.debug(`[Migration] ✓ RLS cleanup completed (${tablesWithRls.rows.length} tables)`);
7917
+ } else {
7918
+ logger7.debug("[Migration] ⊘ No tables with RLS to clean up");
7919
+ }
7920
+ } catch {
7921
+ logger7.debug("[Migration] ⊘ Could not perform RLS cleanup");
7922
+ }
7923
+ return;
7924
+ }
7925
+ logger7.info("[Migration] Starting pre-1.6.5 → 1.6.5+ schema migration...");
7943
7926
  try {
7944
7927
  logger7.debug("[Migration] → Clearing RuntimeMigrator snapshot cache...");
7945
7928
  try {
@@ -7948,27 +7931,34 @@ async function migrateToEntityRLS(adapter) {
7948
7931
  } catch (error) {
7949
7932
  logger7.debug("[Migration] ⊘ No snapshot cache to clear (migrations schema not yet created)");
7950
7933
  }
7951
- logger7.debug("[Migration] → Disabling Row Level Security on all tables...");
7934
+ logger7.debug("[Migration] → Checking for Row Level Security to disable...");
7952
7935
  try {
7953
- const tablesResult = await db2.execute(sql`
7954
- SELECT tablename
7955
- FROM pg_tables
7956
- WHERE schemaname = 'public'
7957
- ORDER BY tablename
7936
+ const tablesWithRls = await db2.execute(sql`
7937
+ SELECT c.relname as tablename
7938
+ FROM pg_class c
7939
+ JOIN pg_namespace n ON n.oid = c.relnamespace
7940
+ WHERE n.nspname = 'public'
7941
+ AND c.relkind = 'r'
7942
+ AND c.relrowsecurity = true
7943
+ ORDER BY c.relname
7958
7944
  `);
7959
- for (const row of tablesResult.rows || []) {
7960
- const tableName = row.tablename;
7961
- try {
7962
- await db2.execute(sql.raw(`ALTER TABLE "${tableName}" DISABLE ROW LEVEL SECURITY`));
7963
- logger7.debug(`[Migration] Disabled RLS on ${tableName}`);
7964
- } catch (error) {
7965
- logger7.debug(`[Migration] Could not disable RLS on ${tableName}`);
7945
+ if (tablesWithRls.rows && tablesWithRls.rows.length > 0) {
7946
+ for (const row of tablesWithRls.rows) {
7947
+ const tableName = row.tablename;
7948
+ try {
7949
+ await db2.execute(sql.raw(`ALTER TABLE "${tableName}" DISABLE ROW LEVEL SECURITY`));
7950
+ logger7.debug(`[Migration] Disabled RLS on ${tableName}`);
7951
+ } catch (error) {
7952
+ logger7.debug(`[Migration] ⊘ Could not disable RLS on ${tableName}`);
7953
+ }
7966
7954
  }
7955
+ } else {
7956
+ logger7.debug("[Migration] ⊘ No tables with RLS enabled");
7967
7957
  }
7968
7958
  } catch (error) {
7969
- logger7.debug("[Migration] ⊘ Could not disable RLS (may not have permissions)");
7959
+ logger7.debug("[Migration] ⊘ Could not check RLS (may not have permissions)");
7970
7960
  }
7971
- logger7.debug("[Migration] → Handling server_id → message_server_id migrations...");
7961
+ logger7.debug("[Migration] → Handling serverId/server_id → message_server_id migrations...");
7972
7962
  const tablesToMigrate = ["channels", "worlds", "rooms"];
7973
7963
  for (const tableName of tablesToMigrate) {
7974
7964
  try {
@@ -7977,34 +7967,49 @@ async function migrateToEntityRLS(adapter) {
7977
7967
  FROM information_schema.columns
7978
7968
  WHERE table_schema = 'public'
7979
7969
  AND table_name = ${tableName}
7980
- AND column_name IN ('server_id', 'message_server_id')
7970
+ AND column_name IN ('server_id', 'serverId', 'message_server_id')
7981
7971
  ORDER BY column_name
7982
7972
  `);
7983
7973
  const columns2 = columnsResult.rows || [];
7984
- const serverId = columns2.find((c) => c.column_name === "server_id");
7974
+ const serverIdSnake = columns2.find((c) => c.column_name === "server_id");
7975
+ const serverIdCamel = columns2.find((c) => c.column_name === "serverId");
7985
7976
  const messageServerId = columns2.find((c) => c.column_name === "message_server_id");
7977
+ const serverId = serverIdSnake || serverIdCamel;
7978
+ const oldColumnName = serverIdSnake ? "server_id" : "serverId";
7986
7979
  if (serverId && !messageServerId) {
7987
- logger7.debug(`[Migration] → Renaming ${tableName}.server_id to message_server_id...`);
7988
- await db2.execute(sql.raw(`ALTER TABLE "${tableName}" RENAME COLUMN "server_id" TO "message_server_id"`));
7989
- logger7.debug(`[Migration] ✓ Renamed ${tableName}.server_id → message_server_id`);
7980
+ logger7.debug(`[Migration] → Renaming ${tableName}.${oldColumnName} to message_server_id...`);
7981
+ await db2.execute(sql.raw(`ALTER TABLE "${tableName}" RENAME COLUMN "${oldColumnName}" TO "message_server_id"`));
7982
+ logger7.debug(`[Migration] ✓ Renamed ${tableName}.${oldColumnName} → message_server_id`);
7990
7983
  if (serverId.data_type === "text") {
7991
7984
  try {
7992
7985
  logger7.debug(`[Migration] → Dropping DEFAULT constraint on ${tableName}.message_server_id...`);
7993
7986
  await db2.execute(sql.raw(`ALTER TABLE "${tableName}" ALTER COLUMN "message_server_id" DROP DEFAULT`));
7994
7987
  logger7.debug(`[Migration] ✓ Dropped DEFAULT constraint`);
7988
+ } catch {
7989
+ logger7.debug(`[Migration] ⊘ No DEFAULT constraint to drop on ${tableName}.message_server_id`);
7990
+ }
7991
+ try {
7995
7992
  logger7.debug(`[Migration] → Converting ${tableName}.message_server_id from text to uuid...`);
7996
- await db2.execute(sql.raw(`ALTER TABLE "${tableName}" ALTER COLUMN "message_server_id" TYPE uuid USING "message_server_id"::uuid`));
7993
+ await db2.execute(sql.raw(`
7994
+ ALTER TABLE "${tableName}"
7995
+ ALTER COLUMN "message_server_id" TYPE uuid
7996
+ USING CASE
7997
+ WHEN "message_server_id" IS NULL THEN NULL
7998
+ WHEN "message_server_id" = '' THEN NULL
7999
+ WHEN "message_server_id" ~ '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
8000
+ THEN "message_server_id"::uuid
8001
+ ELSE md5("message_server_id")::uuid
8002
+ END
8003
+ `));
7997
8004
  logger7.debug(`[Migration] ✓ Converted ${tableName}.message_server_id to uuid`);
7998
8005
  } catch (convertError) {
7999
- logger7.warn(`[Migration] ⚠️ Could not convert ${tableName}.message_server_id to uuid - data may not be valid UUIDs`);
8000
- logger7.debug(`[Migration] → Setting invalid UUIDs to NULL in ${tableName}.message_server_id...`);
8001
- await db2.execute(sql.raw(`ALTER TABLE "${tableName}" ALTER COLUMN "message_server_id" TYPE uuid USING CASE WHEN "message_server_id" ~ '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' THEN "message_server_id"::uuid ELSE NULL END`));
8006
+ logger7.warn(`[Migration] ⚠️ Could not convert ${tableName}.message_server_id to uuid: ${convertError}`);
8002
8007
  }
8003
8008
  }
8004
8009
  if (tableName === "channels") {
8005
8010
  const nullCountResult = await db2.execute(sql.raw(`SELECT COUNT(*) as count FROM "${tableName}" WHERE "message_server_id" IS NULL`));
8006
8011
  const nullCount = nullCountResult.rows?.[0]?.count;
8007
- if (nullCount && parseInt(nullCount) > 0) {
8012
+ if (nullCount && parseInt(nullCount, 10) > 0) {
8008
8013
  logger7.warn(`[Migration] ⚠️ ${tableName} has ${nullCount} rows with NULL message_server_id - these will be deleted`);
8009
8014
  await db2.execute(sql.raw(`DELETE FROM "${tableName}" WHERE "message_server_id" IS NULL`));
8010
8015
  logger7.debug(`[Migration] ✓ Deleted ${nullCount} rows with NULL message_server_id from ${tableName}`);
@@ -8014,9 +8019,9 @@ async function migrateToEntityRLS(adapter) {
8014
8019
  logger7.debug(`[Migration] ✓ Set ${tableName}.message_server_id NOT NULL`);
8015
8020
  }
8016
8021
  } else if (serverId && messageServerId) {
8017
- logger7.debug(`[Migration] → ${tableName} has both columns, dropping server_id...`);
8018
- await db2.execute(sql.raw(`ALTER TABLE "${tableName}" DROP COLUMN "server_id" CASCADE`));
8019
- logger7.debug(`[Migration] ✓ Dropped ${tableName}.server_id (will be re-added by RuntimeMigrator for RLS)`);
8022
+ logger7.debug(`[Migration] → ${tableName} has both columns, dropping ${oldColumnName}...`);
8023
+ await db2.execute(sql.raw(`ALTER TABLE "${tableName}" DROP COLUMN "${oldColumnName}" CASCADE`));
8024
+ logger7.debug(`[Migration] ✓ Dropped ${tableName}.${oldColumnName}`);
8020
8025
  } else if (!serverId && messageServerId) {
8021
8026
  if (messageServerId.data_type === "text") {
8022
8027
  logger7.debug(`[Migration] → ${tableName}.message_server_id exists but is TEXT, needs UUID conversion...`);
@@ -8077,6 +8082,67 @@ async function migrateToEntityRLS(adapter) {
8077
8082
  } catch (error) {
8078
8083
  logger7.debug("[Migration] ⊘ Could not drop server_id columns (may not have permissions)");
8079
8084
  }
8085
+ logger7.debug("[Migration] → Checking agents.owner_id → server_id rename...");
8086
+ try {
8087
+ const agentsColumnsResult = await db2.execute(sql`
8088
+ SELECT column_name
8089
+ FROM information_schema.columns
8090
+ WHERE table_schema = 'public'
8091
+ AND table_name = 'agents'
8092
+ AND column_name IN ('owner_id', 'server_id')
8093
+ ORDER BY column_name
8094
+ `);
8095
+ const agentsColumns = agentsColumnsResult.rows || [];
8096
+ const hasOwnerId = agentsColumns.some((c) => c.column_name === "owner_id");
8097
+ const hasServerId = agentsColumns.some((c) => c.column_name === "server_id");
8098
+ if (hasOwnerId && !hasServerId) {
8099
+ logger7.debug("[Migration] → Renaming agents.owner_id to server_id...");
8100
+ await db2.execute(sql.raw(`ALTER TABLE "agents" RENAME COLUMN "owner_id" TO "server_id"`));
8101
+ logger7.debug("[Migration] ✓ Renamed agents.owner_id → server_id");
8102
+ } else if (hasOwnerId && hasServerId) {
8103
+ logger7.debug("[Migration] → Both owner_id and server_id exist, dropping owner_id...");
8104
+ await db2.execute(sql.raw(`ALTER TABLE "agents" DROP COLUMN "owner_id" CASCADE`));
8105
+ logger7.debug("[Migration] ✓ Dropped agents.owner_id");
8106
+ } else {
8107
+ logger7.debug("[Migration] ⊘ agents table already has server_id (or no owner_id), skipping");
8108
+ }
8109
+ } catch (error) {
8110
+ logger7.debug("[Migration] ⊘ Could not check/migrate agents.owner_id");
8111
+ }
8112
+ logger7.debug("[Migration] → Checking for owners → servers data migration...");
8113
+ try {
8114
+ const ownersTableResult = await db2.execute(sql`
8115
+ SELECT table_name
8116
+ FROM information_schema.tables
8117
+ WHERE table_schema = 'public'
8118
+ AND table_name = 'owners'
8119
+ `);
8120
+ if (ownersTableResult.rows && ownersTableResult.rows.length > 0) {
8121
+ logger7.debug("[Migration] → Ensuring servers table exists...");
8122
+ await db2.execute(sql.raw(`
8123
+ CREATE TABLE IF NOT EXISTS "servers" (
8124
+ "id" uuid PRIMARY KEY,
8125
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
8126
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
8127
+ )
8128
+ `));
8129
+ logger7.debug("[Migration] → Migrating owners data to servers...");
8130
+ await db2.execute(sql.raw(`
8131
+ INSERT INTO "servers" ("id", "created_at", "updated_at")
8132
+ SELECT "id", COALESCE("created_at", now()), COALESCE("updated_at", now())
8133
+ FROM "owners"
8134
+ ON CONFLICT ("id") DO NOTHING
8135
+ `));
8136
+ logger7.debug("[Migration] ✓ Migrated owners data to servers");
8137
+ logger7.debug("[Migration] → Dropping obsolete owners table...");
8138
+ await db2.execute(sql.raw(`DROP TABLE IF EXISTS "owners" CASCADE`));
8139
+ logger7.debug("[Migration] ✓ Dropped obsolete owners table");
8140
+ } else {
8141
+ logger7.debug("[Migration] ⊘ owners table not found, skipping");
8142
+ }
8143
+ } catch (error) {
8144
+ logger7.warn(`[Migration] ⚠️ Could not migrate owners → servers: ${error}`);
8145
+ }
8080
8146
  logger7.debug("[Migration] → Checking server_agents table rename...");
8081
8147
  try {
8082
8148
  const tablesResult = await db2.execute(sql`
@@ -8181,7 +8247,87 @@ async function migrateToEntityRLS(adapter) {
8181
8247
  } catch (error) {
8182
8248
  logger7.debug("[Migration] ⊘ Could not drop indexes (may not have permissions)");
8183
8249
  }
8184
- logger7.info("[Migration] Migration complete - develop to feat/entity-rls migration finished");
8250
+ logger7.debug("[Migration] Starting camelCase snake_case column renames...");
8251
+ const columnRenames = [
8252
+ { table: "rooms", from: "agentId", to: "agent_id" },
8253
+ { table: "rooms", from: "worldId", to: "world_id" },
8254
+ { table: "rooms", from: "channelId", to: "channel_id" },
8255
+ { table: "rooms", from: "createdAt", to: "created_at" },
8256
+ { table: "worlds", from: "agentId", to: "agent_id" },
8257
+ { table: "worlds", from: "createdAt", to: "created_at" },
8258
+ { table: "memories", from: "createdAt", to: "created_at" },
8259
+ { table: "memories", from: "entityId", to: "entity_id" },
8260
+ { table: "memories", from: "agentId", to: "agent_id" },
8261
+ { table: "memories", from: "roomId", to: "room_id" },
8262
+ { table: "memories", from: "worldId", to: "world_id" },
8263
+ { table: "components", from: "entityId", to: "entity_id" },
8264
+ { table: "components", from: "agentId", to: "agent_id" },
8265
+ { table: "components", from: "roomId", to: "room_id" },
8266
+ { table: "components", from: "worldId", to: "world_id" },
8267
+ { table: "components", from: "sourceEntityId", to: "source_entity_id" },
8268
+ { table: "components", from: "createdAt", to: "created_at" },
8269
+ { table: "participants", from: "entityId", to: "entity_id" },
8270
+ { table: "participants", from: "roomId", to: "room_id" },
8271
+ { table: "participants", from: "agentId", to: "agent_id" },
8272
+ { table: "participants", from: "roomState", to: "room_state" },
8273
+ { table: "participants", from: "createdAt", to: "created_at" },
8274
+ { table: "relationships", from: "sourceEntityId", to: "source_entity_id" },
8275
+ { table: "relationships", from: "targetEntityId", to: "target_entity_id" },
8276
+ { table: "relationships", from: "agentId", to: "agent_id" },
8277
+ { table: "relationships", from: "createdAt", to: "created_at" },
8278
+ { table: "logs", from: "entityId", to: "entity_id" },
8279
+ { table: "logs", from: "roomId", to: "room_id" },
8280
+ { table: "logs", from: "createdAt", to: "created_at" },
8281
+ { table: "tasks", from: "roomId", to: "room_id" },
8282
+ { table: "tasks", from: "worldId", to: "world_id" },
8283
+ { table: "tasks", from: "entityId", to: "entity_id" },
8284
+ { table: "tasks", from: "createdAt", to: "created_at" },
8285
+ { table: "tasks", from: "updatedAt", to: "updated_at" },
8286
+ { table: "agents", from: "createdAt", to: "created_at" },
8287
+ { table: "agents", from: "updatedAt", to: "updated_at" },
8288
+ { table: "entities", from: "agentId", to: "agent_id" },
8289
+ { table: "entities", from: "createdAt", to: "created_at" },
8290
+ { table: "embeddings", from: "memoryId", to: "memory_id" },
8291
+ { table: "embeddings", from: "createdAt", to: "created_at" },
8292
+ { table: "cache", from: "agentId", to: "agent_id" },
8293
+ { table: "cache", from: "createdAt", to: "created_at" },
8294
+ { table: "cache", from: "expiresAt", to: "expires_at" }
8295
+ ];
8296
+ for (const rename of columnRenames) {
8297
+ try {
8298
+ const tableExistsResult = await db2.execute(sql`
8299
+ SELECT 1 FROM information_schema.tables
8300
+ WHERE table_schema = 'public' AND table_name = ${rename.table}
8301
+ `);
8302
+ if (!tableExistsResult.rows || tableExistsResult.rows.length === 0) {
8303
+ continue;
8304
+ }
8305
+ const columnsResult = await db2.execute(sql`
8306
+ SELECT column_name
8307
+ FROM information_schema.columns
8308
+ WHERE table_schema = 'public'
8309
+ AND table_name = ${rename.table}
8310
+ AND column_name IN (${rename.from}, ${rename.to})
8311
+ ORDER BY column_name
8312
+ `);
8313
+ const columns2 = columnsResult.rows || [];
8314
+ const hasOldColumn = columns2.some((c) => c.column_name === rename.from);
8315
+ const hasNewColumn = columns2.some((c) => c.column_name === rename.to);
8316
+ if (hasOldColumn && !hasNewColumn) {
8317
+ logger7.debug(`[Migration] → Renaming ${rename.table}.${rename.from} to ${rename.to}...`);
8318
+ await db2.execute(sql.raw(`ALTER TABLE "${rename.table}" RENAME COLUMN "${rename.from}" TO "${rename.to}"`));
8319
+ logger7.debug(`[Migration] ✓ Renamed ${rename.table}.${rename.from} → ${rename.to}`);
8320
+ } else if (hasOldColumn && hasNewColumn) {
8321
+ logger7.debug(`[Migration] → Both columns exist, dropping ${rename.table}.${rename.from}...`);
8322
+ await db2.execute(sql.raw(`ALTER TABLE "${rename.table}" DROP COLUMN "${rename.from}" CASCADE`));
8323
+ logger7.debug(`[Migration] ✓ Dropped ${rename.table}.${rename.from}`);
8324
+ }
8325
+ } catch (error) {
8326
+ logger7.debug(`[Migration] ⊘ Could not process ${rename.table}.${rename.from}: ${error}`);
8327
+ }
8328
+ }
8329
+ logger7.debug("[Migration] ✓ Completed camelCase → snake_case column renames");
8330
+ logger7.info("[Migration] ✓ Migration complete - pre-1.6.5 → 1.6.5+ schema migration finished");
8185
8331
  } catch (error) {
8186
8332
  logger7.error("[Migration] Migration failed:", String(error));
8187
8333
  throw error;
@@ -8194,7 +8340,7 @@ var init_migrations = __esm(() => {
8194
8340
  // src/rls.ts
8195
8341
  import { logger as logger8, validateUuid } from "@elizaos/core";
8196
8342
  async function installRLSFunctions(adapter) {
8197
- const db2 = adapter.db;
8343
+ const db2 = getDb(adapter);
8198
8344
  await db2.execute(sql`
8199
8345
  CREATE TABLE IF NOT EXISTS servers (
8200
8346
  id UUID PRIMARY KEY,
@@ -8310,7 +8456,7 @@ async function installRLSFunctions(adapter) {
8310
8456
  await installEntityRLS(adapter);
8311
8457
  }
8312
8458
  async function getOrCreateRlsServer(adapter, serverId) {
8313
- const db2 = adapter.db;
8459
+ const db2 = getDb(adapter);
8314
8460
  await db2.insert(serverTable).values({
8315
8461
  id: serverId
8316
8462
  }).onConflictDoNothing();
@@ -8321,7 +8467,7 @@ async function setServerContext(adapter, serverId) {
8321
8467
  if (!validateUuid(serverId)) {
8322
8468
  throw new Error(`Invalid server ID format: ${serverId}. Must be a valid UUID.`);
8323
8469
  }
8324
- const db2 = adapter.db;
8470
+ const db2 = getDb(adapter);
8325
8471
  const servers = await db2.select().from(serverTable).where(eq(serverTable.id, serverId));
8326
8472
  if (servers.length === 0) {
8327
8473
  throw new Error(`Server ${serverId} does not exist`);
@@ -8333,7 +8479,7 @@ async function assignAgentToServer(adapter, agentId, serverId) {
8333
8479
  logger8.warn(`[Data Isolation] Cannot assign agent to server: invalid agentId (${agentId}) or serverId (${serverId})`);
8334
8480
  return;
8335
8481
  }
8336
- const db2 = adapter.db;
8482
+ const db2 = getDb(adapter);
8337
8483
  const agents = await db2.select().from(agentTable).where(eq(agentTable.id, agentId));
8338
8484
  if (agents.length > 0) {
8339
8485
  const agent = agents[0];
@@ -8353,7 +8499,7 @@ async function assignAgentToServer(adapter, agentId, serverId) {
8353
8499
  }
8354
8500
  }
8355
8501
  async function applyRLSToNewTables(adapter) {
8356
- const db2 = adapter.db;
8502
+ const db2 = getDb(adapter);
8357
8503
  try {
8358
8504
  await db2.execute(sql`SELECT apply_rls_to_all_tables()`);
8359
8505
  logger8.info({ src: "plugin:sql" }, "RLS applied to all tables");
@@ -8362,7 +8508,7 @@ async function applyRLSToNewTables(adapter) {
8362
8508
  }
8363
8509
  }
8364
8510
  async function uninstallRLS(adapter) {
8365
- const db2 = adapter.db;
8511
+ const db2 = getDb(adapter);
8366
8512
  try {
8367
8513
  const checkResult = await db2.execute(sql`
8368
8514
  SELECT EXISTS (
@@ -8436,7 +8582,7 @@ async function uninstallRLS(adapter) {
8436
8582
  }
8437
8583
  }
8438
8584
  async function installEntityRLS(adapter) {
8439
- const db2 = adapter.db;
8585
+ const db2 = getDb(adapter);
8440
8586
  logger8.info("[Entity RLS] Installing entity RLS functions and policies...");
8441
8587
  await db2.execute(sql`
8442
8588
  CREATE OR REPLACE FUNCTION current_entity_id()
@@ -8477,26 +8623,26 @@ async function installEntityRLS(adapter) {
8477
8623
  BEGIN
8478
8624
  full_table_name := schema_name || '.' || table_name;
8479
8625
 
8480
- -- Check which columns exist (using camelCase as per schema definition)
8626
+ -- Check which columns exist
8481
8627
  SELECT EXISTS (
8482
8628
  SELECT 1 FROM information_schema.columns
8483
8629
  WHERE information_schema.columns.table_schema = schema_name
8484
8630
  AND information_schema.columns.table_name = add_entity_isolation.table_name
8485
- AND information_schema.columns.column_name = 'entityId'
8631
+ AND information_schema.columns.column_name = 'entity_id'
8486
8632
  ) INTO has_entity_id;
8487
8633
 
8488
8634
  SELECT EXISTS (
8489
8635
  SELECT 1 FROM information_schema.columns
8490
8636
  WHERE information_schema.columns.table_schema = schema_name
8491
8637
  AND information_schema.columns.table_name = add_entity_isolation.table_name
8492
- AND information_schema.columns.column_name = 'authorId'
8638
+ AND information_schema.columns.column_name = 'author_id'
8493
8639
  ) INTO has_author_id;
8494
8640
 
8495
8641
  SELECT EXISTS (
8496
8642
  SELECT 1 FROM information_schema.columns
8497
8643
  WHERE information_schema.columns.table_schema = schema_name
8498
8644
  AND information_schema.columns.table_name = add_entity_isolation.table_name
8499
- AND information_schema.columns.column_name = 'roomId'
8645
+ AND information_schema.columns.column_name = 'room_id'
8500
8646
  ) INTO has_room_id;
8501
8647
 
8502
8648
  -- Skip if no entity-related columns
@@ -8506,20 +8652,20 @@ async function installEntityRLS(adapter) {
8506
8652
  END IF;
8507
8653
 
8508
8654
  -- Determine which column to use for entity filtering
8509
- -- Priority: roomId (shared access via participants) > entityId/authorId (direct access)
8655
+ -- Priority: room_id (shared access via participants) > entity_id/author_id (direct access)
8510
8656
  --
8511
- -- SPECIAL CASE: participants table must use direct entityId to avoid infinite recursion
8657
+ -- SPECIAL CASE: participants table must use direct entity_id to avoid infinite recursion
8512
8658
  IF table_name = 'participants' AND has_entity_id THEN
8513
- entity_column_name := 'entityId';
8659
+ entity_column_name := 'entity_id';
8514
8660
  room_column_name := NULL;
8515
8661
  ELSIF has_room_id THEN
8516
- room_column_name := 'roomId';
8662
+ room_column_name := 'room_id';
8517
8663
  entity_column_name := NULL;
8518
8664
  ELSIF has_entity_id THEN
8519
- entity_column_name := 'entityId';
8665
+ entity_column_name := 'entity_id';
8520
8666
  room_column_name := NULL;
8521
8667
  ELSIF has_author_id THEN
8522
- entity_column_name := 'authorId';
8668
+ entity_column_name := 'author_id';
8523
8669
  room_column_name := NULL;
8524
8670
  ELSE
8525
8671
  entity_column_name := NULL;
@@ -8533,11 +8679,11 @@ async function installEntityRLS(adapter) {
8533
8679
  -- Drop existing entity policies if present
8534
8680
  EXECUTE format('DROP POLICY IF EXISTS entity_isolation_policy ON %I.%I', schema_name, table_name);
8535
8681
 
8536
- -- CASE 1: Table has roomId or channelId (shared access via participants)
8682
+ -- CASE 1: Table has room_id (shared access via participants)
8537
8683
  IF room_column_name IS NOT NULL THEN
8538
8684
  -- Determine the corresponding column name in participants table
8539
- -- If the table has roomId, look for roomId in participants.roomId
8540
- -- participants table uses: entityId (for participant), roomId (for room)
8685
+ -- If the table has room_id, look for room_id in participants.room_id
8686
+ -- participants table uses: entity_id (for participant), room_id (for room)
8541
8687
  -- RESTRICTIVE: Must pass BOTH server RLS AND entity RLS (combined with AND)
8542
8688
 
8543
8689
  -- Build policy with or without NULL check based on require_entity parameter
@@ -8549,21 +8695,21 @@ async function installEntityRLS(adapter) {
8549
8695
  USING (
8550
8696
  current_entity_id() IS NOT NULL
8551
8697
  AND %I IN (
8552
- SELECT "roomId"
8698
+ SELECT room_id
8553
8699
  FROM participants
8554
- WHERE "entityId" = current_entity_id()
8700
+ WHERE entity_id = current_entity_id()
8555
8701
  )
8556
8702
  )
8557
8703
  WITH CHECK (
8558
8704
  current_entity_id() IS NOT NULL
8559
8705
  AND %I IN (
8560
- SELECT "roomId"
8706
+ SELECT room_id
8561
8707
  FROM participants
8562
- WHERE "entityId" = current_entity_id()
8708
+ WHERE entity_id = current_entity_id()
8563
8709
  )
8564
8710
  )
8565
8711
  ', schema_name, table_name, room_column_name, room_column_name);
8566
- RAISE NOTICE '[Entity RLS] Applied STRICT RESTRICTIVE to %.% (via % → participants.roomId, entity REQUIRED)', schema_name, table_name, room_column_name;
8712
+ RAISE NOTICE '[Entity RLS] Applied STRICT RESTRICTIVE to %.% (via % → participants.room_id, entity REQUIRED)', schema_name, table_name, room_column_name;
8567
8713
  ELSE
8568
8714
  -- PERMISSIVE MODE: NULL entity_id allows system/admin access
8569
8715
  EXECUTE format('
@@ -8572,21 +8718,21 @@ async function installEntityRLS(adapter) {
8572
8718
  USING (
8573
8719
  current_entity_id() IS NULL
8574
8720
  OR %I IN (
8575
- SELECT "roomId"
8721
+ SELECT room_id
8576
8722
  FROM participants
8577
- WHERE "entityId" = current_entity_id()
8723
+ WHERE entity_id = current_entity_id()
8578
8724
  )
8579
8725
  )
8580
8726
  WITH CHECK (
8581
8727
  current_entity_id() IS NULL
8582
8728
  OR %I IN (
8583
- SELECT "roomId"
8729
+ SELECT room_id
8584
8730
  FROM participants
8585
- WHERE "entityId" = current_entity_id()
8731
+ WHERE entity_id = current_entity_id()
8586
8732
  )
8587
8733
  )
8588
8734
  ', schema_name, table_name, room_column_name, room_column_name);
8589
- RAISE NOTICE '[Entity RLS] Applied PERMISSIVE RESTRICTIVE to %.% (via % → participants.roomId, NULL allowed)', schema_name, table_name, room_column_name;
8735
+ RAISE NOTICE '[Entity RLS] Applied PERMISSIVE RESTRICTIVE to %.% (via % → participants.room_id, NULL allowed)', schema_name, table_name, room_column_name;
8590
8736
  END IF;
8591
8737
 
8592
8738
  -- CASE 2: Table has direct entity_id or author_id column
@@ -8684,7 +8830,7 @@ async function installEntityRLS(adapter) {
8684
8830
  logger8.info("[Entity RLS] Entity RLS functions installed successfully");
8685
8831
  }
8686
8832
  async function applyEntityRLSToAllTables(adapter) {
8687
- const db2 = adapter.db;
8833
+ const db2 = getDb(adapter);
8688
8834
  try {
8689
8835
  await db2.execute(sql`SELECT apply_entity_rls_to_all_tables()`);
8690
8836
  logger8.info("[Entity RLS] Applied entity RLS to all eligible tables");
@@ -8693,7 +8839,7 @@ async function applyEntityRLSToAllTables(adapter) {
8693
8839
  }
8694
8840
  }
8695
8841
  async function uninstallEntityRLS(adapter) {
8696
- const db2 = adapter.db;
8842
+ const db2 = getDb(adapter);
8697
8843
  logger8.info("[Entity RLS] Removing entity RLS policies and functions...");
8698
8844
  try {
8699
8845
  const tablesResult = await db2.execute(sql`
@@ -8706,7 +8852,7 @@ async function uninstallEntityRLS(adapter) {
8706
8852
  const schemaName = row.schemaname;
8707
8853
  const tableName = row.tablename;
8708
8854
  try {
8709
- await db2.execute(sql.raw(`DROP POLICY IF EXISTS entity_isolation_policy ON ${schemaName}.${tableName}`));
8855
+ await db2.execute(sql.raw(`DROP POLICY IF EXISTS entity_isolation_policy ON "${schemaName}"."${tableName}"`));
8710
8856
  logger8.debug(`[Entity RLS] Dropped entity_isolation_policy from ${schemaName}.${tableName}`);
8711
8857
  } catch (error) {
8712
8858
  logger8.debug(`[Entity RLS] No entity policy on ${schemaName}.${tableName}`);
@@ -8741,15 +8887,17 @@ class DatabaseMigrationService {
8741
8887
  constructor() {}
8742
8888
  async initializeWithDatabase(db2) {
8743
8889
  this.db = db2;
8744
- await migrateToEntityRLS({ db: db2 });
8890
+ const adapterWrapper = { db: db2 };
8891
+ await migrateToEntityRLS(adapterWrapper);
8745
8892
  this.migrator = new RuntimeMigrator(db2);
8746
8893
  await this.migrator.initialize();
8747
8894
  logger9.info({ src: "plugin:sql" }, "DatabaseMigrationService initialized");
8748
8895
  }
8749
8896
  discoverAndRegisterPluginSchemas(plugins) {
8750
8897
  for (const plugin of plugins) {
8751
- if (plugin.schema) {
8752
- this.registeredSchemas.set(plugin.name, plugin.schema);
8898
+ const pluginWithSchema = plugin;
8899
+ if (pluginWithSchema.schema) {
8900
+ this.registeredSchemas.set(plugin.name, pluginWithSchema.schema);
8753
8901
  }
8754
8902
  }
8755
8903
  logger9.info({
@@ -8803,9 +8951,10 @@ class DatabaseMigrationService {
8803
8951
  if (dataIsolationEnabled) {
8804
8952
  try {
8805
8953
  logger9.info({ src: "plugin:sql" }, "Re-applying Row Level Security...");
8806
- await installRLSFunctions({ db: this.db });
8807
- await applyRLSToNewTables({ db: this.db });
8808
- await applyEntityRLSToAllTables({ db: this.db });
8954
+ const adapterWrapper = { db: this.db };
8955
+ await installRLSFunctions(adapterWrapper);
8956
+ await applyRLSToNewTables(adapterWrapper);
8957
+ await applyEntityRLSToAllTables(adapterWrapper);
8809
8958
  logger9.info({ src: "plugin:sql" }, "RLS re-applied successfully");
8810
8959
  } catch (rlsError) {
8811
8960
  const errorMsg = rlsError instanceof Error ? rlsError.message : String(rlsError);
@@ -9089,13 +9238,13 @@ init_pg_core();
9089
9238
  init_agent();
9090
9239
  var roomTable = pgTable("rooms", {
9091
9240
  id: uuid("id").notNull().primaryKey().default(sql`gen_random_uuid()`),
9092
- agentId: uuid("agentId").references(() => agentTable.id, {
9241
+ agentId: uuid("agent_id").references(() => agentTable.id, {
9093
9242
  onDelete: "cascade"
9094
9243
  }),
9095
9244
  source: text("source").notNull(),
9096
9245
  type: text("type").notNull(),
9097
9246
  messageServerId: uuid("message_server_id"),
9098
- worldId: uuid("worldId"),
9247
+ worldId: uuid("world_id"),
9099
9248
  name: text("name"),
9100
9249
  metadata: jsonb("metadata"),
9101
9250
  channelId: text("channel_id"),
@@ -9106,18 +9255,18 @@ var roomTable = pgTable("rooms", {
9106
9255
  var memoryTable = pgTable("memories", {
9107
9256
  id: uuid("id").primaryKey().notNull(),
9108
9257
  type: text("type").notNull(),
9109
- createdAt: timestamp("createdAt").default(sql`now()`).notNull(),
9258
+ createdAt: timestamp("created_at").default(sql`now()`).notNull(),
9110
9259
  content: jsonb("content").notNull(),
9111
- entityId: uuid("entityId").references(() => entityTable.id, {
9260
+ entityId: uuid("entity_id").references(() => entityTable.id, {
9112
9261
  onDelete: "cascade"
9113
9262
  }),
9114
- agentId: uuid("agentId").references(() => agentTable.id, {
9263
+ agentId: uuid("agent_id").references(() => agentTable.id, {
9115
9264
  onDelete: "cascade"
9116
9265
  }).notNull(),
9117
- roomId: uuid("roomId").references(() => roomTable.id, {
9266
+ roomId: uuid("room_id").references(() => roomTable.id, {
9118
9267
  onDelete: "cascade"
9119
9268
  }),
9120
- worldId: uuid("worldId"),
9269
+ worldId: uuid("world_id"),
9121
9270
  unique: boolean("unique").default(true).notNull(),
9122
9271
  metadata: jsonb("metadata").default({}).notNull()
9123
9272
  }, (table3) => [
@@ -9236,7 +9385,7 @@ init_pg_core();
9236
9385
  init_agent();
9237
9386
  var worldTable = pgTable("worlds", {
9238
9387
  id: uuid("id").notNull().primaryKey().default(sql`gen_random_uuid()`),
9239
- agentId: uuid("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
9388
+ agentId: uuid("agent_id").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
9240
9389
  name: text("name").notNull(),
9241
9390
  metadata: jsonb("metadata"),
9242
9391
  messageServerId: uuid("message_server_id"),
@@ -9246,14 +9395,16 @@ var worldTable = pgTable("worlds", {
9246
9395
  // src/schema/component.ts
9247
9396
  var componentTable = pgTable("components", {
9248
9397
  id: uuid("id").primaryKey().default(sql`gen_random_uuid()`).notNull(),
9249
- entityId: uuid("entityId").references(() => entityTable.id, { onDelete: "cascade" }).notNull(),
9250
- agentId: uuid("agentId").references(() => agentTable.id, { onDelete: "cascade" }).notNull(),
9251
- roomId: uuid("roomId").references(() => roomTable.id, { onDelete: "cascade" }).notNull(),
9252
- worldId: uuid("worldId").references(() => worldTable.id, { onDelete: "cascade" }),
9253
- sourceEntityId: uuid("sourceEntityId").references(() => entityTable.id, { onDelete: "cascade" }),
9398
+ entityId: uuid("entity_id").references(() => entityTable.id, { onDelete: "cascade" }).notNull(),
9399
+ agentId: uuid("agent_id").references(() => agentTable.id, { onDelete: "cascade" }).notNull(),
9400
+ roomId: uuid("room_id").references(() => roomTable.id, { onDelete: "cascade" }).notNull(),
9401
+ worldId: uuid("world_id").references(() => worldTable.id, { onDelete: "cascade" }),
9402
+ sourceEntityId: uuid("source_entity_id").references(() => entityTable.id, {
9403
+ onDelete: "cascade"
9404
+ }),
9254
9405
  type: text("type").notNull(),
9255
9406
  data: jsonb("data").default(sql`'{}'::jsonb`),
9256
- createdAt: timestamp("createdAt").default(sql`now()`).notNull()
9407
+ createdAt: timestamp("created_at").default(sql`now()`).notNull()
9257
9408
  });
9258
9409
  // src/schema/log.ts
9259
9410
  init_drizzle_orm();
@@ -9261,10 +9412,10 @@ init_pg_core();
9261
9412
  var logTable = pgTable("logs", {
9262
9413
  id: uuid("id").defaultRandom().notNull(),
9263
9414
  createdAt: timestamp("created_at", { withTimezone: true }).default(sql`now()`).notNull(),
9264
- entityId: uuid("entityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
9415
+ entityId: uuid("entity_id").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
9265
9416
  body: jsonb("body").notNull(),
9266
9417
  type: text("type").notNull(),
9267
- roomId: uuid("roomId").notNull().references(() => roomTable.id, { onDelete: "cascade" })
9418
+ roomId: uuid("room_id").notNull().references(() => roomTable.id, { onDelete: "cascade" })
9268
9419
  }, (table3) => [
9269
9420
  foreignKey({
9270
9421
  name: "fk_room",
@@ -9288,16 +9439,16 @@ init_agent();
9288
9439
  var participantTable = pgTable("participants", {
9289
9440
  id: uuid("id").notNull().primaryKey().default(sql`gen_random_uuid()`),
9290
9441
  createdAt: timestamp("created_at", { withTimezone: true }).default(sql`now()`).notNull(),
9291
- entityId: uuid("entityId").references(() => entityTable.id, {
9442
+ entityId: uuid("entity_id").references(() => entityTable.id, {
9292
9443
  onDelete: "cascade"
9293
9444
  }),
9294
- roomId: uuid("roomId").references(() => roomTable.id, {
9445
+ roomId: uuid("room_id").references(() => roomTable.id, {
9295
9446
  onDelete: "cascade"
9296
9447
  }),
9297
- agentId: uuid("agentId").references(() => agentTable.id, {
9448
+ agentId: uuid("agent_id").references(() => agentTable.id, {
9298
9449
  onDelete: "cascade"
9299
9450
  }),
9300
- roomState: text("roomState")
9451
+ roomState: text("room_state")
9301
9452
  }, (table3) => [
9302
9453
  index("idx_participants_user").on(table3.entityId),
9303
9454
  index("idx_participants_room").on(table3.roomId),
@@ -9319,9 +9470,9 @@ init_agent();
9319
9470
  var relationshipTable = pgTable("relationships", {
9320
9471
  id: uuid("id").notNull().primaryKey().default(sql`gen_random_uuid()`),
9321
9472
  createdAt: timestamp("created_at", { withTimezone: true }).default(sql`now()`).notNull(),
9322
- sourceEntityId: uuid("sourceEntityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
9323
- targetEntityId: uuid("targetEntityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
9324
- agentId: uuid("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
9473
+ sourceEntityId: uuid("source_entity_id").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
9474
+ targetEntityId: uuid("target_entity_id").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
9475
+ agentId: uuid("agent_id").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
9325
9476
  tags: text("tags").array(),
9326
9477
  metadata: jsonb("metadata")
9327
9478
  }, (table3) => [
@@ -9346,10 +9497,10 @@ var taskTable = pgTable("tasks", {
9346
9497
  id: uuid("id").primaryKey().defaultRandom(),
9347
9498
  name: text("name").notNull(),
9348
9499
  description: text("description"),
9349
- roomId: uuid("roomId"),
9350
- worldId: uuid("worldId"),
9351
- entityId: uuid("entityId"),
9352
- agentId: uuid("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
9500
+ roomId: uuid("room_id"),
9501
+ worldId: uuid("world_id"),
9502
+ entityId: uuid("entity_id"),
9503
+ agentId: uuid("agent_id").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
9353
9504
  tags: text("tags").array().default(sql`'{}'::text[]`),
9354
9505
  metadata: jsonb("metadata").default(sql`'{}'::jsonb`),
9355
9506
  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
@@ -9497,7 +9648,11 @@ class BaseDrizzleAdapter extends DatabaseAdapter {
9497
9648
  return this.withDatabase(async () => {
9498
9649
  const existingMemory = await this.db.select().from(memoryTable).innerJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(eq(memoryTable.agentId, this.agentId)).limit(1);
9499
9650
  if (existingMemory.length > 0) {
9500
- Object.entries(DIMENSION_MAP).find(([_, colName]) => existingMemory[0].embeddings[colName] !== null);
9651
+ const joinedResult = existingMemory[0];
9652
+ Object.entries(DIMENSION_MAP).find(([_, colName]) => {
9653
+ const embeddingCol = colName;
9654
+ return joinedResult.embeddings[embeddingCol] !== null;
9655
+ });
9501
9656
  }
9502
9657
  this.embeddingDimension = DIMENSION_MAP[dimension];
9503
9658
  });
@@ -9636,7 +9791,7 @@ class BaseDrizzleAdapter extends DatabaseAdapter {
9636
9791
  return output;
9637
9792
  };
9638
9793
  const finalSettings = deepMerge(currentSettings, updatedSettings);
9639
- return finalSettings === undefined ? {} : finalSettings;
9794
+ return finalSettings ?? {};
9640
9795
  }
9641
9796
  async deleteAgent(agentId) {
9642
9797
  return this.withDatabase(async () => {
@@ -10203,6 +10358,7 @@ class BaseDrizzleAdapter extends DatabaseAdapter {
10203
10358
  id: log.id,
10204
10359
  entityId: log.entityId,
10205
10360
  roomId: log.roomId,
10361
+ type: log.type,
10206
10362
  body: log.body,
10207
10363
  createdAt: new Date(log.createdAt)
10208
10364
  }));
@@ -11015,7 +11171,7 @@ class BaseDrizzleAdapter extends DatabaseAdapter {
11015
11171
  return this.withRetry(async () => {
11016
11172
  return this.withDatabase(async () => {
11017
11173
  const result = await this.db.select().from(taskTable).where(and(eq(taskTable.agentId, this.agentId), ...params.roomId ? [eq(taskTable.roomId, params.roomId)] : [], ...params.tags && params.tags.length > 0 ? [
11018
- sql`${taskTable.tags} @> ARRAY[${sql.raw(params.tags.map((t) => `'${t.replace(/'/g, "''")}'`).join(", "))}]::text[]`
11174
+ sql`${taskTable.tags} @> ARRAY[${sql.join(params.tags.map((t) => sql`${t}`), sql`, `)}]::text[]`
11019
11175
  ] : []));
11020
11176
  return result.map((row) => ({
11021
11177
  id: row.id,
@@ -11079,11 +11235,14 @@ class BaseDrizzleAdapter extends DatabaseAdapter {
11079
11235
  updateValues.worldId = task.worldId;
11080
11236
  if (task.tags !== undefined)
11081
11237
  updateValues.tags = task.tags;
11082
- updateValues.updatedAt = new Date;
11238
+ const dbUpdateValues = {
11239
+ ...updateValues,
11240
+ updatedAt: new Date
11241
+ };
11083
11242
  if (task.metadata !== undefined) {
11084
- updateValues.metadata = task.metadata;
11243
+ dbUpdateValues.metadata = task.metadata;
11085
11244
  }
11086
- await this.db.update(taskTable).set(updateValues).where(and(eq(taskTable.id, id), eq(taskTable.agentId, this.agentId)));
11245
+ await this.db.update(taskTable).set(dbUpdateValues).where(and(eq(taskTable.id, id), eq(taskTable.agentId, this.agentId)));
11087
11246
  });
11088
11247
  });
11089
11248
  }
@@ -11548,6 +11707,11 @@ class PGliteClientManager {
11548
11707
  async initialize() {}
11549
11708
  async close() {
11550
11709
  this.shuttingDown = true;
11710
+ if (this.client) {
11711
+ try {
11712
+ await this.client.close();
11713
+ } catch {}
11714
+ }
11551
11715
  }
11552
11716
  setupShutdownHandlers() {}
11553
11717
  }
@@ -11935,9 +12099,6 @@ class PgDatabaseAdapter extends BaseDrizzleAdapter {
11935
12099
  getMemoryById(memoryId) {
11936
12100
  return super.getMemoryById(memoryId);
11937
12101
  }
11938
- searchMemories(params) {
11939
- return super.searchMemories(params);
11940
- }
11941
12102
  updateMemory(memory) {
11942
12103
  return super.updateMemory(memory);
11943
12104
  }
@@ -12000,21 +12161,18 @@ class PostgresConnectionManager {
12000
12161
  }
12001
12162
  }
12002
12163
  async withEntityContext(entityId, callback) {
12164
+ const dataIsolationEnabled = process.env.ENABLE_DATA_ISOLATION === "true";
12003
12165
  return await this.db.transaction(async (tx) => {
12004
- if (entityId) {
12166
+ if (dataIsolationEnabled && entityId) {
12005
12167
  try {
12006
- await tx.execute(sql.raw(`SET LOCAL app.entity_id = '${entityId}'`));
12168
+ await tx.execute(sql`SET LOCAL app.entity_id = ${entityId}`);
12007
12169
  logger13.debug(`[Entity Context] Set app.entity_id = ${entityId}`);
12008
12170
  } catch (error) {
12009
12171
  const errorMessage = error instanceof Error ? error.message : String(error);
12010
- if (errorMessage.includes("unrecognized configuration parameter") || errorMessage.includes("app.entity_id")) {
12011
- logger13.debug("[Entity Context] Entity RLS not enabled, executing without entity context");
12012
- } else {
12013
- logger13.error({ error, entityId }, "[Entity Context] Critical error setting entity context - this may indicate a configuration issue");
12014
- logger13.warn("[Entity Context] Continuing without entity context due to error - data isolation may be compromised");
12015
- }
12172
+ logger13.error({ error, entityId }, `[Entity Context] Failed to set entity context: ${errorMessage}`);
12173
+ throw error;
12016
12174
  }
12017
- } else {
12175
+ } else if (!dataIsolationEnabled) {} else {
12018
12176
  logger13.debug("[Entity Context] No entity context set (server operation)");
12019
12177
  }
12020
12178
  return await callback(tx);
@@ -12143,10 +12301,10 @@ var plugin = {
12143
12301
  return;
12144
12302
  }
12145
12303
  const postgresUrl = runtime.getSetting("POSTGRES_URL");
12146
- const dataDir = runtime.getSetting("PGLITE_DATA_DIR") || undefined;
12304
+ const dataDir = runtime.getSetting("PGLITE_DATA_DIR");
12147
12305
  const dbAdapter = createDatabaseAdapter({
12148
- dataDir,
12149
- postgresUrl
12306
+ dataDir: typeof dataDir === "string" ? dataDir : undefined,
12307
+ postgresUrl: typeof postgresUrl === "string" ? postgresUrl : undefined
12150
12308
  }, runtime.agentId);
12151
12309
  runtime.registerDatabaseAdapter(dbAdapter);
12152
12310
  runtime.logger.info({ src: "plugin:sql", agentId: runtime.agentId }, "Database adapter created and registered");
@@ -12166,5 +12324,5 @@ export {
12166
12324
  DatabaseMigrationService
12167
12325
  };
12168
12326
 
12169
- //# debugId=EA546D2333E8154064756E2164756E21
12327
+ //# debugId=D2C87E4D9A59EC5564756E2164756E21
12170
12328
  //# sourceMappingURL=index.node.js.map