@elizaos/plugin-sql 1.0.0-beta.0 → 1.0.0-beta.12

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Shaw Walters, aka Moon aka @lalalune
3
+ Copyright (c) 2025 Shaw Walters and elizaOS Contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,5 @@
1
- import {
2
- __name
3
- } from "./chunk-I3JSTNED.js";
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
3
 
5
4
  // src/pglite/manager.ts
6
5
  import { dirname as pathDirname, resolve as pathResolve } from "node:path";
@@ -138,7 +137,8 @@ var PGliteClientManager = class {
138
137
  const __filename = fileURLToPath(import.meta.url);
139
138
  const __dirname = pathDirname(__filename);
140
139
  await migrate(db, {
141
- migrationsFolder: pathResolve(__dirname, "../drizzle/migrations")
140
+ migrationsFolder: pathResolve(__dirname, "../drizzle/migrations"),
141
+ migrationsSchema: "public"
142
142
  });
143
143
  } catch (error) {
144
144
  logger.error("Failed to run database migrations (pglite):", error);
@@ -147,10 +147,11 @@ var PGliteClientManager = class {
147
147
  };
148
148
 
149
149
  // src/pg/manager.ts
150
+ import path from "node:path";
151
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
150
152
  import { logger as logger2 } from "@elizaos/core";
151
153
  import { drizzle as drizzle2 } from "drizzle-orm/node-postgres";
152
- import { dirname as pathDirname2, resolve as pathResolve2 } from "node:path";
153
- import { fileURLToPath as fileURLToPath2 } from "node:url";
154
+ import { migrate as migrate2 } from "drizzle-orm/node-postgres/migrator";
154
155
  import pkg from "pg";
155
156
  var { Pool } = pkg;
156
157
  var PostgresConnectionManager = class {
@@ -164,7 +165,7 @@ var PostgresConnectionManager = class {
164
165
  * Constructor for creating a connection pool.
165
166
  * @param {string} connectionString - The connection string used to connect to the database.
166
167
  */
167
- constructor(db, connectionString) {
168
+ constructor(connectionString) {
168
169
  const defaultConfig = {
169
170
  max: 20,
170
171
  idleTimeoutMillis: 3e4,
@@ -179,6 +180,7 @@ var PostgresConnectionManager = class {
179
180
  this.handlePoolError(err);
180
181
  });
181
182
  this.setupPoolErrorHandling();
183
+ this.testConnection();
182
184
  }
183
185
  /**
184
186
  * Handles a pool error by attempting to reconnect the pool.
@@ -278,6 +280,8 @@ var PostgresConnectionManager = class {
278
280
  */
279
281
  async initialize() {
280
282
  try {
283
+ await this.testConnection();
284
+ logger2.debug("PostgreSQL connection manager initialized successfully");
281
285
  } catch (error) {
282
286
  logger2.error("Failed to initialize connection manager:", error);
283
287
  throw error;
@@ -303,37 +307,32 @@ var PostgresConnectionManager = class {
303
307
  }
304
308
  }
305
309
  /**
306
- * Asynchronously runs database migrations using the Drizzle library and ensures
307
- * the database schema is always up to date with the current schema definition.
310
+ * Asynchronously runs database migrations using the Drizzle library.
308
311
  *
309
- * First applies existing migrations, then uses drizzle-kit push to ensure
310
- * the database schema matches the current schema definition.
312
+ * Drizzle will first check if the migrations are already applied.
313
+ * If there is a diff between database schema and migrations, it will apply the migrations.
314
+ * If they are already applied, it will skip them.
311
315
  *
312
- * @returns {Promise<void>} A Promise that resolves once the schema updates are completed successfully.
316
+ * @returns {Promise<void>} A Promise that resolves once the migrations are completed successfully.
313
317
  */
314
318
  async runMigrations() {
315
- const { existsSync } = await import("fs");
316
- const db = drizzle2(this.pool);
317
- const packagePath = (await import.meta.resolve("@elizaos/plugin-sql")).replace("file://", "");
318
- const packageMigrationsPath = pathResolve2(pathDirname2(packagePath), "../drizzle/migrations");
319
- console.log("packageMigrationsPath", packageMigrationsPath);
320
- const __filename = fileURLToPath2(import.meta.url);
321
- const __dirname = pathDirname2(__filename);
322
- const appMigrationPath = pathResolve2(__dirname, "../drizzle/migrations");
323
- console.log("appMigrationPath", appMigrationPath);
324
- const migrationsFolder = existsSync(packageMigrationsPath) ? packageMigrationsPath : appMigrationPath;
325
- console.log("migrationsFolder", migrationsFolder);
326
- const { execa } = await import("./execa-I2XBH3EI.js");
327
- await execa("npx", ["drizzle-kit", "push"], {
328
- cwd: migrationsFolder
329
- });
330
- console.log("migrated");
331
- await new Promise((resolve) => setTimeout(resolve, 2e3));
319
+ try {
320
+ const db = drizzle2(this.pool);
321
+ const __filename = fileURLToPath2(import.meta.url);
322
+ const __dirname = path.dirname(__filename);
323
+ await migrate2(db, {
324
+ migrationsFolder: path.resolve(__dirname, "../drizzle/migrations"),
325
+ migrationsSchema: "public"
326
+ });
327
+ } catch (error) {
328
+ logger2.error("Failed to run database migrations (pg):", error);
329
+ }
332
330
  }
333
331
  };
334
332
 
335
333
  export {
334
+ __name,
336
335
  PGliteClientManager,
337
336
  PostgresConnectionManager
338
337
  };
339
- //# sourceMappingURL=chunk-PSEXCDLP.js.map
338
+ //# sourceMappingURL=chunk-ROCRMD5N.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pglite/manager.ts","../src/pg/manager.ts"],"sourceRoot":"./","sourcesContent":["import { dirname as pathDirname, resolve as pathResolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { PGlite, type PGliteOptions } from '@electric-sql/pglite';\nimport { fuzzystrmatch } from '@electric-sql/pglite/contrib/fuzzystrmatch';\nimport { vector } from '@electric-sql/pglite/vector';\nimport { logger } from '@elizaos/core';\nimport { drizzle } from 'drizzle-orm/pglite';\nimport { migrate } from 'drizzle-orm/pglite/migrator';\nimport type { IDatabaseClientManager } from '../types';\n\n/**\n * Class representing a database client manager for PGlite.\n * @implements { IDatabaseClientManager }\n */\nexport class PGliteClientManager implements IDatabaseClientManager<PGlite> {\n private client: PGlite;\n private shuttingDown = false;\n private readonly shutdownTimeout = 500;\n\n /**\n * Constructor for creating a new instance of PGlite with the provided options.\n * Initializes the PGlite client with additional extensions.\n * @param {PGliteOptions} options - The options to configure the PGlite client.\n */\n constructor(options: PGliteOptions) {\n this.client = new PGlite({\n ...options,\n extensions: {\n vector,\n fuzzystrmatch,\n },\n });\n this.setupShutdownHandlers();\n }\n\n /**\n * Retrieves the PostgreSQL lite connection.\n *\n * @returns {PGlite} The PostgreSQL lite connection.\n * @throws {Error} If the client manager is currently shutting down.\n */\n public getConnection(): PGlite {\n if (this.shuttingDown) {\n throw new Error('Client manager is shutting down');\n }\n return this.client;\n }\n\n /**\n * Initiates a graceful shutdown of the PGlite client.\n * Checks if the client is already in the process of shutting down.\n * Logs the start of shutdown process and sets shuttingDown flag to true.\n * Sets a timeout for the shutdown process and forces closure of database connection if timeout is reached.\n * Handles the shutdown process, closes the client connection, clears the timeout, and logs the completion of shutdown.\n * Logs any errors that occur during the shutdown process.\n */\n private async gracefulShutdown() {\n if (this.shuttingDown) {\n return;\n }\n\n this.shuttingDown = true;\n logger.info('Starting graceful shutdown of PGlite client...');\n\n const timeout = setTimeout(() => {\n logger.warn('Shutdown timeout reached, forcing database connection closure...');\n this.client.close().finally(() => {\n process.exit(1);\n });\n }, this.shutdownTimeout);\n\n try {\n await this.client.close();\n clearTimeout(timeout);\n logger.info('PGlite client shutdown completed successfully');\n process.exit(0);\n } catch (error) {\n logger.error('Error during graceful shutdown:', error);\n process.exit(1);\n }\n }\n\n /**\n * Sets up shutdown handlers for SIGINT, SIGTERM, and beforeExit events to gracefully shutdown the application.\n * @private\n */\n private setupShutdownHandlers() {\n process.on('SIGINT', async () => {\n await this.gracefulShutdown();\n });\n\n process.on('SIGTERM', async () => {\n await this.gracefulShutdown();\n });\n\n process.on('beforeExit', async () => {\n await this.gracefulShutdown();\n });\n }\n\n /**\n * Initializes the client for PGlite.\n *\n * @returns {Promise<void>} A Promise that resolves when the client is initialized successfully\n */\n public async initialize(): Promise<void> {\n try {\n await this.client.waitReady;\n logger.info('PGlite client initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize PGlite client:', error);\n throw error;\n }\n }\n\n /**\n * Asynchronously closes the resource. If the resource is not already shutting down,\n * it performs a graceful shutdown before closing.\n *\n * @returns A promise that resolves once the resource has been closed.\n */\n public async close(): Promise<void> {\n if (!this.shuttingDown) {\n await this.gracefulShutdown();\n }\n }\n\n /**\n * Check if the system is currently shutting down.\n *\n * @returns {boolean} True if the system is shutting down, false otherwise.\n */\n public isShuttingDown(): boolean {\n return this.shuttingDown;\n }\n\n /**\n * Asynchronously runs database migrations using Drizzle.\n *\n * Drizzle will first check if the migrations are already applied.\n * If there is a diff between database schema and migrations, it will apply the migrations.\n * If they are already applied, it will skip them.\n *\n * @returns {Promise<void>} A Promise that resolves once the migrations are completed successfully.\n */\n async runMigrations(): Promise<void> {\n try {\n const db = drizzle(this.client);\n\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = pathDirname(__filename);\n\n await migrate(db, {\n migrationsFolder: pathResolve(__dirname, '../drizzle/migrations'),\n migrationsSchema: 'public',\n });\n } catch (error) {\n logger.error('Failed to run database migrations (pglite):', error);\n }\n }\n}\n","import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { logger } from '@elizaos/core';\nimport { drizzle } from 'drizzle-orm/node-postgres';\nimport { migrate } from 'drizzle-orm/node-postgres/migrator';\nimport pkg, { type Pool as PgPool } from 'pg';\nimport type { IDatabaseClientManager } from '../types';\n\nconst { Pool } = pkg;\n\n/**\n * Manages connections to a PostgreSQL database using a connection pool.\n * Implements IDatabaseClientManager interface.\n */\n\nexport class PostgresConnectionManager implements IDatabaseClientManager<PgPool> {\n private pool: PgPool;\n private isShuttingDown = false;\n private readonly connectionTimeout: number = 5000;\n\n /**\n * Constructor for creating a connection pool.\n * @param {string} connectionString - The connection string used to connect to the database.\n */\n constructor(connectionString: string) {\n const defaultConfig = {\n max: 20,\n idleTimeoutMillis: 30000,\n connectionTimeoutMillis: this.connectionTimeout,\n };\n\n this.pool = new Pool({\n ...defaultConfig,\n connectionString,\n });\n\n this.pool.on('error', (err) => {\n logger.error('Unexpected pool error', err);\n this.handlePoolError(err);\n });\n\n this.setupPoolErrorHandling();\n this.testConnection();\n }\n\n /**\n * Handles a pool error by attempting to reconnect the pool.\n *\n * @param {Error} error The error that occurred in the pool.\n * @throws {Error} If failed to reconnect the pool.\n */\n private async handlePoolError(error: Error) {\n logger.error('Pool error occurred, attempting to reconnect', {\n error: error.message,\n });\n\n try {\n await this.pool.end();\n\n this.pool = new Pool({\n ...this.pool.options,\n connectionTimeoutMillis: this.connectionTimeout,\n });\n\n await this.testConnection();\n logger.success('Pool reconnection successful');\n } catch (reconnectError) {\n logger.error('Failed to reconnect pool', {\n error: reconnectError instanceof Error ? reconnectError.message : String(reconnectError),\n });\n throw reconnectError;\n }\n }\n\n /**\n * Asynchronously tests the database connection by executing a query to get the current timestamp.\n *\n * @returns {Promise<boolean>} - A Promise that resolves to true if the database connection test is successful.\n */\n async testConnection(): Promise<boolean> {\n let client: pkg.PoolClient | null = null;\n try {\n client = await this.pool.connect();\n const result = await client.query('SELECT NOW()');\n logger.success('Database connection test successful:', result.rows[0]);\n return true;\n } catch (error) {\n logger.error('Database connection test failed:', error);\n throw new Error(`Failed to connect to database: ${(error as Error).message}`);\n } finally {\n if (client) client.release();\n }\n }\n\n /**\n * Sets up event listeners to handle pool cleanup on SIGINT, SIGTERM, and beforeExit events.\n */\n private setupPoolErrorHandling() {\n process.on('SIGINT', async () => {\n await this.cleanup();\n process.exit(0);\n });\n\n process.on('SIGTERM', async () => {\n await this.cleanup();\n process.exit(0);\n });\n\n process.on('beforeExit', async () => {\n await this.cleanup();\n });\n }\n\n /**\n * Get the connection pool.\n * @returns {PgPool} The connection pool\n * @throws {Error} If the connection manager is shutting down or an error occurs when trying to get the connection from the pool\n */\n public getConnection(): PgPool {\n if (this.isShuttingDown) {\n throw new Error('Connection manager is shutting down');\n }\n\n try {\n return this.pool;\n } catch (error) {\n logger.error('Failed to get connection from pool:', error);\n throw error;\n }\n }\n\n /**\n * Asynchronously acquires a database client from the connection pool.\n *\n * @returns {Promise<pkg.PoolClient>} A Promise that resolves with the acquired database client.\n * @throws {Error} If an error occurs while acquiring the database client.\n */\n public async getClient(): Promise<pkg.PoolClient> {\n try {\n return await this.pool.connect();\n } catch (error) {\n logger.error('Failed to acquire a database client:', error);\n throw error;\n }\n }\n\n /**\n * Initializes the PostgreSQL connection manager by testing the connection and logging the result.\n *\n * @returns {Promise<void>} A Promise that resolves once the manager is successfully initialized\n * @throws {Error} If there is an error initializing the connection manager\n */\n public async initialize(): Promise<void> {\n try {\n await this.testConnection();\n logger.debug('PostgreSQL connection manager initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize connection manager:', error);\n throw error;\n }\n }\n\n /**\n * Asynchronously close the current process by executing a cleanup function.\n * @returns A promise that resolves once the cleanup is complete.\n */\n public async close(): Promise<void> {\n await this.cleanup();\n }\n\n /**\n * Cleans up and closes the database pool.\n * @returns {Promise<void>} A Promise that resolves when the database pool is closed.\n */\n async cleanup(): Promise<void> {\n try {\n await this.pool.end();\n logger.info('Database pool closed');\n } catch (error) {\n logger.error('Error closing database pool:', error);\n }\n }\n\n /**\n * Asynchronously runs database migrations using the Drizzle library.\n *\n * Drizzle will first check if the migrations are already applied.\n * If there is a diff between database schema and migrations, it will apply the migrations.\n * If they are already applied, it will skip them.\n *\n * @returns {Promise<void>} A Promise that resolves once the migrations are completed successfully.\n */\n async runMigrations(): Promise<void> {\n try {\n const db = drizzle(this.pool);\n\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n await migrate(db, {\n migrationsFolder: path.resolve(__dirname, '../drizzle/migrations'),\n migrationsSchema: 'public',\n });\n } catch (error) {\n logger.error('Failed to run database migrations (pg):', error);\n }\n }\n}\n"],"mappings":"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","names":["fileURLToPath","logger","drizzle","migrate","logger","drizzle","fileURLToPath","migrate"]}
package/dist/index.js CHANGED
@@ -1,10 +1,8 @@
1
1
  import {
2
2
  PGliteClientManager,
3
- PostgresConnectionManager
4
- } from "./chunk-PSEXCDLP.js";
5
- import {
3
+ PostgresConnectionManager,
6
4
  __name
7
- } from "./chunk-I3JSTNED.js";
5
+ } from "./chunk-ROCRMD5N.js";
8
6
 
9
7
  // src/index.ts
10
8
  import * as os from "node:os";
@@ -29,7 +27,8 @@ import {
29
27
  inArray,
30
28
  lte,
31
29
  or,
32
- sql as sql12
30
+ sql as sql12,
31
+ not
33
32
  } from "drizzle-orm";
34
33
  import { v4 } from "uuid";
35
34
 
@@ -571,6 +570,9 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
571
570
  throw new Error("Agent ID is required for update");
572
571
  }
573
572
  await this.db.transaction(async (tx) => {
573
+ if (agent.settings) {
574
+ agent.settings = await this.mergeAgentSettings(tx, agentId, agent.settings);
575
+ }
574
576
  await tx.update(agentTable).set({
575
577
  ...agent,
576
578
  updatedAt: Date.now()
@@ -590,6 +592,39 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
590
592
  }
591
593
  });
592
594
  }
595
+ /**
596
+ * Merges updated agent settings with existing settings in the database,
597
+ * with special handling for nested objects like secrets.
598
+ * @param tx - The database transaction
599
+ * @param agentId - The ID of the agent
600
+ * @param updatedSettings - The settings object with updates
601
+ * @returns The merged settings object
602
+ * @private
603
+ */
604
+ async mergeAgentSettings(tx, agentId, updatedSettings) {
605
+ const currentAgent = await tx.select({ settings: agentTable.settings }).from(agentTable).where(eq(agentTable.id, agentId)).limit(1);
606
+ if (currentAgent.length === 0 || !currentAgent[0].settings) {
607
+ return updatedSettings;
608
+ }
609
+ const currentSettings = currentAgent[0].settings;
610
+ if (updatedSettings.secrets) {
611
+ const currentSecrets = currentSettings.secrets || {};
612
+ const updatedSecrets = updatedSettings.secrets;
613
+ const mergedSecrets = { ...currentSecrets };
614
+ for (const [key, value] of Object.entries(updatedSecrets)) {
615
+ if (value === null) {
616
+ delete mergedSecrets[key];
617
+ } else {
618
+ mergedSecrets[key] = value;
619
+ }
620
+ }
621
+ updatedSettings.secrets = mergedSecrets;
622
+ }
623
+ return {
624
+ ...currentSettings,
625
+ ...updatedSettings
626
+ };
627
+ }
593
628
  /**
594
629
  * Asynchronously deletes an agent with the specified UUID and all related entries.
595
630
  *
@@ -599,6 +634,42 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
599
634
  async deleteAgent(agentId) {
600
635
  return this.withDatabase(async () => {
601
636
  await this.db.transaction(async (tx) => {
637
+ const entities = await this.db.select({ entityId: entityTable.id }).from(entityTable).where(eq(entityTable.agentId, agentId));
638
+ const entityIds = entities.map((e) => e.entityId);
639
+ let memoryIds = [];
640
+ if (entityIds.length > 0) {
641
+ const entityMemories = await this.db.select({ memoryId: memoryTable.id }).from(memoryTable).where(inArray(memoryTable.entityId, entityIds));
642
+ memoryIds = entityMemories.map((m) => m.memoryId);
643
+ }
644
+ const agentMemories = await this.db.select({ memoryId: memoryTable.id }).from(memoryTable).where(eq(memoryTable.agentId, agentId));
645
+ memoryIds.push(...agentMemories.map((m) => m.memoryId));
646
+ if (memoryIds.length > 0) {
647
+ await tx.delete(embeddingTable).where(inArray(embeddingTable.memoryId, memoryIds));
648
+ await tx.delete(memoryTable).where(inArray(memoryTable.id, memoryIds));
649
+ }
650
+ const rooms = await this.db.select({ roomId: roomTable.id }).from(roomTable).where(eq(roomTable.agentId, agentId));
651
+ const roomIds = rooms.map((r) => r.roomId);
652
+ if (entityIds.length > 0) {
653
+ await tx.delete(logTable).where(inArray(logTable.entityId, entityIds));
654
+ await tx.delete(participantTable).where(inArray(participantTable.entityId, entityIds));
655
+ }
656
+ if (roomIds.length > 0) {
657
+ await tx.delete(logTable).where(inArray(logTable.roomId, roomIds));
658
+ await tx.delete(participantTable).where(inArray(participantTable.roomId, roomIds));
659
+ }
660
+ await tx.delete(participantTable).where(eq(participantTable.agentId, agentId));
661
+ if (roomIds.length > 0) {
662
+ await tx.delete(roomTable).where(inArray(roomTable.id, roomIds));
663
+ }
664
+ await tx.delete(cacheTable).where(eq(cacheTable.agentId, agentId));
665
+ await tx.delete(relationshipTable).where(eq(relationshipTable.agentId, agentId));
666
+ await tx.delete(entityTable).where(eq(entityTable.agentId, agentId));
667
+ const newAgent = await this.db.select({ newAgentId: agentTable.id }).from(agentTable).where(not(eq(agentTable.id, agentId))).limit(1);
668
+ if (newAgent.length > 0) {
669
+ await tx.update(worldTable).set({ agentId: newAgent[0].newAgentId }).where(eq(worldTable.agentId, agentId));
670
+ } else {
671
+ await tx.delete(worldTable).where(eq(worldTable.agentId, agentId));
672
+ }
602
673
  await tx.delete(agentTable).where(eq(agentTable.id, agentId));
603
674
  });
604
675
  return true;
@@ -712,6 +783,13 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
712
783
  return this.withDatabase(async () => {
713
784
  try {
714
785
  return await this.db.transaction(async (tx) => {
786
+ const existingEntity = await this.getEntityById(entity.id);
787
+ if (existingEntity) {
788
+ logger.debug("Entity already exists:", {
789
+ entity
790
+ });
791
+ return true;
792
+ }
715
793
  await tx.insert(entityTable).values(entity);
716
794
  logger.debug("Entity created successfully:", {
717
795
  entity
@@ -1446,7 +1524,16 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1446
1524
  * @param {Room} room - The room object to create.
1447
1525
  * @returns {Promise<UUID>} A Promise that resolves to the ID of the created room.
1448
1526
  */
1449
- async createRoom({ id, name, source, type, channelId, serverId, worldId }) {
1527
+ async createRoom({
1528
+ id,
1529
+ name,
1530
+ source,
1531
+ type,
1532
+ channelId,
1533
+ serverId,
1534
+ worldId,
1535
+ metadata
1536
+ }) {
1450
1537
  return this.withDatabase(async () => {
1451
1538
  const newRoomId = id || v4();
1452
1539
  await this.db.insert(roomTable).values({
@@ -1457,7 +1544,8 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1457
1544
  type,
1458
1545
  channelId,
1459
1546
  serverId,
1460
- worldId
1547
+ worldId,
1548
+ metadata
1461
1549
  }).onConflictDoNothing({ target: roomTable.id });
1462
1550
  return newRoomId;
1463
1551
  });
@@ -1585,9 +1673,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1585
1673
  */
1586
1674
  async getParticipantsForRoom(roomId) {
1587
1675
  return this.withDatabase(async () => {
1588
- const result = await this.db.select({ entityId: participantTable.entityId }).from(participantTable).where(
1589
- and(eq(participantTable.roomId, roomId), eq(participantTable.agentId, this.agentId))
1590
- );
1676
+ const result = await this.db.select({ entityId: participantTable.entityId }).from(participantTable).where(eq(participantTable.roomId, roomId));
1591
1677
  return result.map((row) => row.entityId);
1592
1678
  });
1593
1679
  }
@@ -2053,6 +2139,66 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
2053
2139
  });
2054
2140
  });
2055
2141
  }
2142
+ /**
2143
+ * Asynchronously retrieves group chat memories from all rooms under a given server.
2144
+ * It fetches all room IDs associated with the `serverId`, then retrieves memories
2145
+ * from those rooms in descending order (latest to oldest), with an optional count limit.
2146
+ *
2147
+ * @param {Object} params - Parameters for fetching memories.
2148
+ * @param {UUID} params.serverId - The server ID to fetch memories for.
2149
+ * @param {number} [params.count] - The maximum number of memories to retrieve.
2150
+ * @returns {Promise<Memory[]>} - A promise that resolves to an array of memory objects.
2151
+ */
2152
+ async getMemoriesByServerId(params) {
2153
+ return this.withDatabase(async () => {
2154
+ const roomIdsResult = await this.db.select({ roomId: roomTable.id }).from(roomTable).where(eq(roomTable.serverId, params.serverId));
2155
+ if (roomIdsResult.length === 0) return [];
2156
+ const roomIds = roomIdsResult.map((row) => row.roomId);
2157
+ const query = this.db.select({
2158
+ memory: memoryTable,
2159
+ embedding: embeddingTable[this.embeddingDimension]
2160
+ }).from(memoryTable).leftJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(inArray(memoryTable.roomId, roomIds)).orderBy(desc(memoryTable.createdAt));
2161
+ const rows = params.count ? await query.limit(params.count) : await query;
2162
+ return rows.map((row) => ({
2163
+ id: row.memory.id,
2164
+ type: row.memory.type,
2165
+ createdAt: row.memory.createdAt,
2166
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
2167
+ entityId: row.memory.entityId,
2168
+ agentId: row.memory.agentId,
2169
+ roomId: row.memory.roomId,
2170
+ unique: row.memory.unique,
2171
+ embedding: row.embedding ?? void 0
2172
+ }));
2173
+ });
2174
+ }
2175
+ /**
2176
+ * Asynchronously deletes all rooms associated with a specific serverId.
2177
+ * @param {UUID} serverId - The server ID to delete rooms for.
2178
+ * @returns {Promise<void>} A Promise that resolves when the rooms are deleted.
2179
+ */
2180
+ async deleteRoomsByServerId(serverId) {
2181
+ return this.withDatabase(async () => {
2182
+ await this.db.transaction(async (tx) => {
2183
+ const roomIdsResult = await tx.select({ roomId: roomTable.id }).from(roomTable).where(eq(roomTable.serverId, serverId));
2184
+ if (roomIdsResult.length === 0) return;
2185
+ const roomIds = roomIdsResult.map((row) => row.roomId);
2186
+ await tx.delete(embeddingTable).where(
2187
+ inArray(
2188
+ embeddingTable.memoryId,
2189
+ tx.select({ id: memoryTable.id }).from(memoryTable).where(inArray(memoryTable.roomId, roomIds))
2190
+ )
2191
+ );
2192
+ await tx.delete(memoryTable).where(inArray(memoryTable.roomId, roomIds));
2193
+ await tx.delete(participantTable).where(inArray(participantTable.roomId, roomIds));
2194
+ await tx.delete(logTable).where(inArray(logTable.roomId, roomIds));
2195
+ await tx.delete(roomTable).where(inArray(roomTable.id, roomIds));
2196
+ });
2197
+ logger.debug("Rooms and related logs deleted successfully for server:", {
2198
+ serverId
2199
+ });
2200
+ });
2201
+ }
2056
2202
  };
2057
2203
 
2058
2204
  // src/pglite/adapter.ts
@@ -2170,7 +2316,6 @@ var PgDatabaseAdapter = class extends BaseDrizzleAdapter {
2170
2316
  };
2171
2317
 
2172
2318
  // src/index.ts
2173
- import { Pool } from "pg";
2174
2319
  var GLOBAL_SINGLETONS = Symbol.for("@elizaos/plugin-sql/global-singletons");
2175
2320
  var globalSymbols = global;
2176
2321
  if (!globalSymbols[GLOBAL_SINGLETONS]) {
@@ -2189,10 +2334,8 @@ function createDatabaseAdapter(config, agentId) {
2189
2334
  config.dataDir = expandTildePath(config.dataDir);
2190
2335
  }
2191
2336
  if (config.postgresUrl) {
2192
- const pool = new Pool({ connectionString: config.postgresUrl });
2193
2337
  if (!globalSingletons.postgresConnectionManager) {
2194
2338
  globalSingletons.postgresConnectionManager = new PostgresConnectionManager(
2195
- pool,
2196
2339
  config.postgresUrl
2197
2340
  );
2198
2341
  }