@elizaos/plugin-sql 1.6.5 → 1.7.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.browser.js +403 -239
- package/dist/browser/index.browser.js.map +22 -21
- package/dist/browser/tsconfig.build.tsbuildinfo +1 -1
- package/dist/node/index.node.js +418 -260
- package/dist/node/index.node.js.map +24 -23
- package/dist/node/tsconfig.build.node.tsbuildinfo +1 -1
- package/package.json +11 -7
package/dist/node/index.node.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
7499
|
+
if (!connectionUrl?.trim())
|
|
7492
7500
|
return false;
|
|
7493
|
-
|
|
7494
|
-
const
|
|
7495
|
-
|
|
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
|
-
|
|
7525
|
-
|
|
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
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
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
|
-
|
|
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
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
7659
|
-
if (
|
|
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
|
|
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
|
-
|
|
7747
|
-
|
|
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
|
|
7750
|
-
await this.migrationTracker.recordMigration(pluginName,
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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] →
|
|
7934
|
+
logger7.debug("[Migration] → Checking for Row Level Security to disable...");
|
|
7952
7935
|
try {
|
|
7953
|
-
const
|
|
7954
|
-
SELECT tablename
|
|
7955
|
-
FROM
|
|
7956
|
-
|
|
7957
|
-
|
|
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
|
-
|
|
7960
|
-
const
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
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
|
|
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
|
|
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}
|
|
7988
|
-
await db2.execute(sql.raw(`ALTER TABLE "${tableName}" RENAME COLUMN "
|
|
7989
|
-
logger7.debug(`[Migration] ✓ Renamed ${tableName}
|
|
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(`
|
|
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
|
|
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
|
|
8018
|
-
await db2.execute(sql.raw(`ALTER TABLE "${tableName}" DROP COLUMN "
|
|
8019
|
-
logger7.debug(`[Migration] ✓ Dropped ${tableName}
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 = '
|
|
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 = '
|
|
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 = '
|
|
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:
|
|
8655
|
+
-- Priority: room_id (shared access via participants) > entity_id/author_id (direct access)
|
|
8510
8656
|
--
|
|
8511
|
-
-- SPECIAL CASE: participants table must use direct
|
|
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 := '
|
|
8659
|
+
entity_column_name := 'entity_id';
|
|
8514
8660
|
room_column_name := NULL;
|
|
8515
8661
|
ELSIF has_room_id THEN
|
|
8516
|
-
room_column_name := '
|
|
8662
|
+
room_column_name := 'room_id';
|
|
8517
8663
|
entity_column_name := NULL;
|
|
8518
8664
|
ELSIF has_entity_id THEN
|
|
8519
|
-
entity_column_name := '
|
|
8665
|
+
entity_column_name := 'entity_id';
|
|
8520
8666
|
room_column_name := NULL;
|
|
8521
8667
|
ELSIF has_author_id THEN
|
|
8522
|
-
entity_column_name := '
|
|
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
|
|
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
|
|
8540
|
-
-- participants table uses:
|
|
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
|
|
8698
|
+
SELECT room_id
|
|
8553
8699
|
FROM participants
|
|
8554
|
-
WHERE
|
|
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
|
|
8706
|
+
SELECT room_id
|
|
8561
8707
|
FROM participants
|
|
8562
|
-
WHERE
|
|
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.
|
|
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
|
|
8721
|
+
SELECT room_id
|
|
8576
8722
|
FROM participants
|
|
8577
|
-
WHERE
|
|
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
|
|
8729
|
+
SELECT room_id
|
|
8584
8730
|
FROM participants
|
|
8585
|
-
WHERE
|
|
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.
|
|
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
|
|
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
|
|
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}
|
|
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
|
-
|
|
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
|
-
|
|
8752
|
-
|
|
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
|
-
|
|
8807
|
-
await
|
|
8808
|
-
await
|
|
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("
|
|
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("
|
|
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("
|
|
9258
|
+
createdAt: timestamp("created_at").default(sql`now()`).notNull(),
|
|
9110
9259
|
content: jsonb("content").notNull(),
|
|
9111
|
-
entityId: uuid("
|
|
9260
|
+
entityId: uuid("entity_id").references(() => entityTable.id, {
|
|
9112
9261
|
onDelete: "cascade"
|
|
9113
9262
|
}),
|
|
9114
|
-
agentId: uuid("
|
|
9263
|
+
agentId: uuid("agent_id").references(() => agentTable.id, {
|
|
9115
9264
|
onDelete: "cascade"
|
|
9116
9265
|
}).notNull(),
|
|
9117
|
-
roomId: uuid("
|
|
9266
|
+
roomId: uuid("room_id").references(() => roomTable.id, {
|
|
9118
9267
|
onDelete: "cascade"
|
|
9119
9268
|
}),
|
|
9120
|
-
worldId: uuid("
|
|
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("
|
|
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("
|
|
9250
|
-
agentId: uuid("
|
|
9251
|
-
roomId: uuid("
|
|
9252
|
-
worldId: uuid("
|
|
9253
|
-
sourceEntityId: uuid("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
9442
|
+
entityId: uuid("entity_id").references(() => entityTable.id, {
|
|
9292
9443
|
onDelete: "cascade"
|
|
9293
9444
|
}),
|
|
9294
|
-
roomId: uuid("
|
|
9445
|
+
roomId: uuid("room_id").references(() => roomTable.id, {
|
|
9295
9446
|
onDelete: "cascade"
|
|
9296
9447
|
}),
|
|
9297
|
-
agentId: uuid("
|
|
9448
|
+
agentId: uuid("agent_id").references(() => agentTable.id, {
|
|
9298
9449
|
onDelete: "cascade"
|
|
9299
9450
|
}),
|
|
9300
|
-
roomState: text("
|
|
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("
|
|
9323
|
-
targetEntityId: uuid("
|
|
9324
|
-
agentId: uuid("
|
|
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("
|
|
9350
|
-
worldId: uuid("
|
|
9351
|
-
entityId: uuid("
|
|
9352
|
-
agentId: uuid("
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
11238
|
+
const dbUpdateValues = {
|
|
11239
|
+
...updateValues,
|
|
11240
|
+
updatedAt: new Date
|
|
11241
|
+
};
|
|
11083
11242
|
if (task.metadata !== undefined) {
|
|
11084
|
-
|
|
11243
|
+
dbUpdateValues.metadata = task.metadata;
|
|
11085
11244
|
}
|
|
11086
|
-
await this.db.update(taskTable).set(
|
|
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
|
|
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
|
-
|
|
12011
|
-
|
|
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")
|
|
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=
|
|
12327
|
+
//# debugId=D2C87E4D9A59EC5564756E2164756E21
|
|
12170
12328
|
//# sourceMappingURL=index.node.js.map
|