@elizaos/plugin-sql 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -106,7 +106,9 @@ var PGliteClientManager = class {
106
106
  async initialize() {
107
107
  try {
108
108
  await this.client.waitReady;
109
- logger.info("PGlite client initialized successfully");
109
+ await this.client.query("CREATE EXTENSION IF NOT EXISTS vector;");
110
+ await this.client.query("CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;");
111
+ logger.info("PGlite client initialized and extensions ensured successfully");
110
112
  } catch (error) {
111
113
  logger.error("Failed to initialize PGlite client:", error);
112
114
  throw error;
@@ -342,6 +344,12 @@ var PostgresConnectionManager = class {
342
344
  migrationsSchema: "public"
343
345
  });
344
346
  } catch (error) {
347
+ if (error instanceof Error && error.message.includes("already exists")) {
348
+ logger2.info(
349
+ "Database migrations already applied - if you need to upgrade, you will need to manually migrate or reset your database"
350
+ );
351
+ return;
352
+ }
345
353
  logger2.error("Failed to run database migrations (pg):", error);
346
354
  }
347
355
  }
@@ -390,4 +398,4 @@ export {
390
398
  PostgresConnectionManager,
391
399
  resolvePgliteDir
392
400
  };
393
- //# sourceMappingURL=chunk-QOV7MUNF.js.map
401
+ //# sourceMappingURL=chunk-74FVWTXP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pglite/manager.ts","../src/pg/manager.ts","../src/utils.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 logger.warn('Forced database connection closure complete.');\n if (process.env.NODE_ENV !== 'test') {\n process.exit(1);\n }\n });\n }, this.shutdownTimeout);\n\n try {\n await this.client.close();\n clearTimeout(timeout);\n logger.info('PGlite client shutdown completed successfully');\n if (process.env.NODE_ENV !== 'test') {\n process.exit(0);\n }\n } catch (error) {\n logger.error('Error during graceful shutdown:', error);\n if (process.env.NODE_ENV !== 'test') {\n process.exit(1);\n } else {\n throw error;\n }\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 // Explicitly create extensions\n await this.client.query('CREATE EXTENSION IF NOT EXISTS vector;');\n await this.client.query('CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;');\n logger.info('PGlite client initialized and extensions ensured 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 packageJsonUrl = await import.meta.resolve('@elizaos/plugin-sql/package.json');\n const packageJsonPath = fileURLToPath(packageJsonUrl);\n const packageRoot = pathDirname(packageJsonPath);\n const migrationsPath = pathResolve(packageRoot, 'drizzle/migrations');\n logger.debug(\n `Resolved migrations path (pglite) using import.meta.resolve: ${migrationsPath}`\n );\n\n await migrate(db, {\n migrationsFolder: migrationsPath,\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 packageJsonUrl = await import.meta.resolve('@elizaos/plugin-sql/package.json');\n const packageJsonPath = fileURLToPath(packageJsonUrl);\n const packageRoot = path.dirname(packageJsonPath);\n const migrationsPath = path.resolve(packageRoot, 'drizzle/migrations');\n logger.debug(`Resolved migrations path (pg) using import.meta.resolve: ${migrationsPath}`);\n\n await migrate(db, {\n migrationsFolder: migrationsPath,\n migrationsSchema: 'public',\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('already exists')) {\n logger.info(\n 'Database migrations already applied - if you need to upgrade, you will need to manually migrate or reset your database'\n );\n return;\n }\n logger.error('Failed to run database migrations (pg):', error);\n }\n }\n}\n","import dotenv from 'dotenv';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Expands a file path starting with `~` to the project directory.\n *\n * @param filepath - The path to expand.\n * @returns The expanded path.\n */\nexport function expandTildePath(filepath: string): string {\n if (filepath && filepath.startsWith('~')) {\n return path.join(process.cwd(), filepath.slice(1));\n }\n return filepath;\n}\n\n/**\n * Resolves the path to the nearest `.env` file.\n *\n * If no `.env` file is found when traversing up from the starting directory,\n * a path to `.env` in the starting directory is returned.\n *\n * @param startDir - The directory to start searching from. Defaults to the\n * current working directory.\n * @returns The resolved path to the `.env` file.\n */\nexport function resolveEnvFile(startDir: string = process.cwd()): string {\n let currentDir = startDir;\n\n while (true) {\n const candidate = path.join(currentDir, '.env');\n if (existsSync(candidate)) {\n return candidate;\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n break;\n }\n currentDir = parentDir;\n }\n\n return path.join(startDir, '.env');\n}\n\n/**\n * Resolves the directory used for PGlite database storage.\n *\n * Resolution order:\n * 1. The `dir` argument if provided.\n * 2. The `PGLITE_DATA_DIR` environment variable.\n * 3. The `fallbackDir` argument if provided.\n * 4. `./.elizadb` relative to the current working directory.\n *\n * @param dir - Optional directory preference.\n * @param fallbackDir - Optional fallback directory when env var is not set.\n * @returns The resolved data directory with any tilde expanded.\n */\nexport function resolvePgliteDir(dir?: string, fallbackDir?: string): string {\n const envPath = resolveEnvFile();\n if (existsSync(envPath)) {\n dotenv.config({ path: envPath });\n }\n\n const base =\n dir ?? process.env.PGLITE_DATA_DIR ?? fallbackDir ?? path.join(process.cwd(), '.elizadb');\n return expandTildePath(base);\n}\n"],"mappings":"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","names":["fileURLToPath","logger","drizzle","migrate","logger","drizzle","fileURLToPath","migrate","path","path"]}
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  PostgresConnectionManager,
4
4
  __name,
5
5
  resolvePgliteDir
6
- } from "./chunk-QOV7MUNF.js";
6
+ } from "./chunk-74FVWTXP.js";
7
7
 
8
8
  // src/index.ts
9
9
  import { logger as logger4 } from "@elizaos/core";
@@ -16,9 +16,22 @@ import { drizzle } from "drizzle-orm/pglite";
16
16
  import {
17
17
  DatabaseAdapter,
18
18
  logger,
19
- stringToUuid
19
+ stringToUuid,
20
+ ChannelType
20
21
  } from "@elizaos/core";
21
- import { and, cosineDistance, count, desc, eq, gte, inArray, lte, or, sql as sql13 } from "drizzle-orm";
22
+ import {
23
+ and,
24
+ cosineDistance,
25
+ count,
26
+ desc,
27
+ eq,
28
+ gte,
29
+ inArray,
30
+ lte,
31
+ lt,
32
+ or,
33
+ sql as sql16
34
+ } from "drizzle-orm";
22
35
  import { v4 } from "uuid";
23
36
 
24
37
  // src/schema/embedding.ts
@@ -412,6 +425,86 @@ var taskTable = pgTable12("tasks", {
412
425
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
413
426
  });
414
427
 
428
+ // src/schema/messageServer.ts
429
+ import { pgTable as pgTable13, text as text12, jsonb as jsonb11, timestamp as timestamp2 } from "drizzle-orm/pg-core";
430
+ import { sql as sql13 } from "drizzle-orm";
431
+ var messageServerTable = pgTable13("message_servers", {
432
+ id: text12("id").primaryKey(),
433
+ // UUID stored as text
434
+ name: text12("name").notNull(),
435
+ sourceType: text12("source_type").notNull(),
436
+ sourceId: text12("source_id"),
437
+ metadata: jsonb11("metadata"),
438
+ createdAt: timestamp2("created_at", { mode: "date" }).default(sql13`CURRENT_TIMESTAMP`).notNull(),
439
+ updatedAt: timestamp2("updated_at", { mode: "date" }).default(sql13`CURRENT_TIMESTAMP`).notNull()
440
+ });
441
+
442
+ // src/schema/channel.ts
443
+ import { pgTable as pgTable14, text as text13, jsonb as jsonb12, timestamp as timestamp3 } from "drizzle-orm/pg-core";
444
+ import { sql as sql14 } from "drizzle-orm";
445
+ var channelTable = pgTable14("channels", {
446
+ id: text13("id").primaryKey(),
447
+ // UUID stored as text
448
+ messageServerId: text13("server_id").notNull().references(() => messageServerTable.id, { onDelete: "cascade" }),
449
+ name: text13("name").notNull(),
450
+ type: text13("type").notNull(),
451
+ // Store ChannelType enum values as text
452
+ sourceType: text13("source_type"),
453
+ sourceId: text13("source_id"),
454
+ topic: text13("topic"),
455
+ metadata: jsonb12("metadata"),
456
+ createdAt: timestamp3("created_at", { mode: "date" }).default(sql14`CURRENT_TIMESTAMP`).notNull(),
457
+ updatedAt: timestamp3("updated_at", { mode: "date" }).default(sql14`CURRENT_TIMESTAMP`).notNull()
458
+ });
459
+
460
+ // src/schema/message.ts
461
+ import { pgTable as pgTable15, text as text14, jsonb as jsonb13, timestamp as timestamp4 } from "drizzle-orm/pg-core";
462
+ import { sql as sql15 } from "drizzle-orm";
463
+ var messageTable = pgTable15("central_messages", {
464
+ id: text14("id").primaryKey(),
465
+ // UUID stored as text
466
+ channelId: text14("channel_id").notNull().references(() => channelTable.id, { onDelete: "cascade" }),
467
+ authorId: text14("author_id").notNull(),
468
+ content: text14("content").notNull(),
469
+ rawMessage: jsonb13("raw_message"),
470
+ inReplyToRootMessageId: text14("in_reply_to_root_message_id").references(() => messageTable.id, {
471
+ onDelete: "set null"
472
+ }),
473
+ sourceType: text14("source_type"),
474
+ sourceId: text14("source_id"),
475
+ metadata: jsonb13("metadata"),
476
+ createdAt: timestamp4("created_at", { mode: "date" }).default(sql15`CURRENT_TIMESTAMP`).notNull(),
477
+ updatedAt: timestamp4("updated_at", { mode: "date" }).default(sql15`CURRENT_TIMESTAMP`).notNull()
478
+ });
479
+
480
+ // src/schema/channelParticipant.ts
481
+ import { pgTable as pgTable16, text as text15, primaryKey } from "drizzle-orm/pg-core";
482
+ var channelParticipantsTable = pgTable16(
483
+ "channel_participants",
484
+ {
485
+ channelId: text15("channel_id").notNull().references(() => channelTable.id, { onDelete: "cascade" }),
486
+ userId: text15("user_id").notNull()
487
+ // This is a central UUID (can be an agentId or a dedicated central user ID)
488
+ },
489
+ (table) => ({
490
+ pk: primaryKey({ columns: [table.channelId, table.userId] })
491
+ })
492
+ );
493
+
494
+ // src/schema/serverAgent.ts
495
+ import { pgTable as pgTable17, text as text16, primaryKey as primaryKey2 } from "drizzle-orm/pg-core";
496
+ var serverAgentsTable = pgTable17(
497
+ "server_agents",
498
+ {
499
+ serverId: text16("server_id").notNull().references(() => messageServerTable.id, { onDelete: "cascade" }),
500
+ agentId: text16("agent_id").notNull()
501
+ // This is the agent's UUID
502
+ },
503
+ (table) => ({
504
+ pk: primaryKey2({ columns: [table.serverId, table.agentId] })
505
+ })
506
+ );
507
+
415
508
  // src/base.ts
416
509
  var BaseDrizzleAdapter = class extends DatabaseAdapter {
417
510
  static {
@@ -1267,7 +1360,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1267
1360
  async getCachedEmbeddings(opts) {
1268
1361
  return this.withDatabase(async () => {
1269
1362
  try {
1270
- const results = await this.db.execute(sql13`
1363
+ const results = await this.db.execute(sql16`
1271
1364
  WITH content_text AS (
1272
1365
  SELECT
1273
1366
  m.id,
@@ -1335,7 +1428,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1335
1428
  const jsonString = JSON.stringify(sanitizedBody);
1336
1429
  await this.db.transaction(async (tx) => {
1337
1430
  await tx.insert(logTable).values({
1338
- body: sql13`${jsonString}::jsonb`,
1431
+ body: sql16`${jsonString}::jsonb`,
1339
1432
  entityId: params.entityId,
1340
1433
  roomId: params.roomId,
1341
1434
  type: params.type
@@ -1464,7 +1557,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1464
1557
  async searchMemoriesByEmbedding(embedding, params) {
1465
1558
  return this.withDatabase(async () => {
1466
1559
  const cleanVector = embedding.map((n) => Number.isFinite(n) ? Number(n.toFixed(6)) : 0);
1467
- const similarity = sql13`1 - (${cosineDistance(
1560
+ const similarity = sql16`1 - (${cosineDistance(
1468
1561
  embeddingTable[this.embeddingDimension],
1469
1562
  cleanVector
1470
1563
  )})`;
@@ -1546,8 +1639,8 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1546
1639
  {
1547
1640
  id: memoryId,
1548
1641
  type: tableName,
1549
- content: sql13`${contentToInsert}::jsonb`,
1550
- metadata: sql13`${memory.metadata || {}}::jsonb`,
1642
+ content: sql16`${contentToInsert}::jsonb`,
1643
+ metadata: sql16`${memory.metadata || {}}::jsonb`,
1551
1644
  entityId: memory.entityId,
1552
1645
  roomId: memory.roomId,
1553
1646
  worldId: memory.worldId,
@@ -1588,12 +1681,12 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1588
1681
  if (memory.content) {
1589
1682
  const contentToUpdate = typeof memory.content === "string" ? JSON.parse(memory.content) : memory.content;
1590
1683
  await tx.update(memoryTable).set({
1591
- content: sql13`${contentToUpdate}::jsonb`,
1592
- ...memory.metadata && { metadata: sql13`${memory.metadata}::jsonb` }
1684
+ content: sql16`${contentToUpdate}::jsonb`,
1685
+ ...memory.metadata && { metadata: sql16`${memory.metadata}::jsonb` }
1593
1686
  }).where(eq(memoryTable.id, memory.id));
1594
1687
  } else if (memory.metadata) {
1595
1688
  await tx.update(memoryTable).set({
1596
- metadata: sql13`${memory.metadata}::jsonb`
1689
+ metadata: sql16`${memory.metadata}::jsonb`
1597
1690
  }).where(eq(memoryTable.id, memory.id));
1598
1691
  }
1599
1692
  if (memory.embedding && Array.isArray(memory.embedding)) {
@@ -1675,7 +1768,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1675
1768
  const fragments = await tx.select({ id: memoryTable.id }).from(memoryTable).where(
1676
1769
  and(
1677
1770
  eq(memoryTable.agentId, this.agentId),
1678
- sql13`${memoryTable.metadata}->>'documentId' = ${documentId}`
1771
+ sql16`${memoryTable.metadata}->>'documentId' = ${documentId}`
1679
1772
  )
1680
1773
  );
1681
1774
  return fragments.map((f) => ({ id: f.id }));
@@ -1720,7 +1813,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1720
1813
  if (unique7) {
1721
1814
  conditions.push(eq(memoryTable.unique, true));
1722
1815
  }
1723
- const result = await this.db.select({ count: sql13`count(*)` }).from(memoryTable).where(and(...conditions));
1816
+ const result = await this.db.select({ count: sql16`count(*)` }).from(memoryTable).where(and(...conditions));
1724
1817
  return Number(result[0]?.count ?? 0);
1725
1818
  });
1726
1819
  }
@@ -2113,7 +2206,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
2113
2206
  ),
2114
2207
  eq(relationshipTable.agentId, this.agentId),
2115
2208
  ...params.tags && params.tags.length > 0 ? [
2116
- sql13`${relationshipTable.tags} @> ARRAY[${sql13.raw(
2209
+ sql16`${relationshipTable.tags} @> ARRAY[${sql16.raw(
2117
2210
  params.tags.map((tag) => `'${tag.replace(/'/g, "''")}'`).join(", ")
2118
2211
  )}]::text[]`
2119
2212
  ] : []
@@ -2304,7 +2397,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
2304
2397
  eq(taskTable.agentId, this.agentId),
2305
2398
  ...params.roomId ? [eq(taskTable.roomId, params.roomId)] : [],
2306
2399
  ...params.tags && params.tags.length > 0 ? [
2307
- sql13`${taskTable.tags} @> ARRAY[${sql13.raw(
2400
+ sql16`${taskTable.tags} @> ARRAY[${sql16.raw(
2308
2401
  params.tags.map((t) => `'${t.replace(/'/g, "''")}'`).join(", ")
2309
2402
  )}]::text[]`
2310
2403
  ] : []
@@ -2458,6 +2551,296 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
2458
2551
  }
2459
2552
  });
2460
2553
  }
2554
+ // Message Server Database Operations
2555
+ /**
2556
+ * Creates a new message server in the central database
2557
+ */
2558
+ async createMessageServer(data) {
2559
+ return this.withDatabase(async () => {
2560
+ const newId = data.id || v4();
2561
+ const now = /* @__PURE__ */ new Date();
2562
+ const serverToInsert = {
2563
+ id: newId,
2564
+ name: data.name,
2565
+ sourceType: data.sourceType,
2566
+ sourceId: data.sourceId,
2567
+ metadata: data.metadata,
2568
+ createdAt: now,
2569
+ updatedAt: now
2570
+ };
2571
+ await this.db.insert(messageServerTable).values(serverToInsert).onConflictDoNothing();
2572
+ if (data.id) {
2573
+ const existing = await this.db.select().from(messageServerTable).where(eq(messageServerTable.id, data.id)).limit(1);
2574
+ if (existing.length > 0) {
2575
+ return {
2576
+ id: existing[0].id,
2577
+ name: existing[0].name,
2578
+ sourceType: existing[0].sourceType,
2579
+ sourceId: existing[0].sourceId || void 0,
2580
+ metadata: existing[0].metadata || void 0,
2581
+ createdAt: existing[0].createdAt,
2582
+ updatedAt: existing[0].updatedAt
2583
+ };
2584
+ }
2585
+ }
2586
+ return serverToInsert;
2587
+ });
2588
+ }
2589
+ /**
2590
+ * Gets all message servers
2591
+ */
2592
+ async getMessageServers() {
2593
+ return this.withDatabase(async () => {
2594
+ const results = await this.db.select().from(messageServerTable);
2595
+ return results.map((r) => ({
2596
+ id: r.id,
2597
+ name: r.name,
2598
+ sourceType: r.sourceType,
2599
+ sourceId: r.sourceId || void 0,
2600
+ metadata: r.metadata || void 0,
2601
+ createdAt: r.createdAt,
2602
+ updatedAt: r.updatedAt
2603
+ }));
2604
+ });
2605
+ }
2606
+ /**
2607
+ * Gets a message server by ID
2608
+ */
2609
+ async getMessageServerById(serverId) {
2610
+ return this.withDatabase(async () => {
2611
+ const results = await this.db.select().from(messageServerTable).where(eq(messageServerTable.id, serverId)).limit(1);
2612
+ return results.length > 0 ? {
2613
+ id: results[0].id,
2614
+ name: results[0].name,
2615
+ sourceType: results[0].sourceType,
2616
+ sourceId: results[0].sourceId || void 0,
2617
+ metadata: results[0].metadata || void 0,
2618
+ createdAt: results[0].createdAt,
2619
+ updatedAt: results[0].updatedAt
2620
+ } : null;
2621
+ });
2622
+ }
2623
+ /**
2624
+ * Creates a new channel
2625
+ */
2626
+ async createChannel(data, participantIds) {
2627
+ return this.withDatabase(async () => {
2628
+ const newId = data.id || v4();
2629
+ const now = /* @__PURE__ */ new Date();
2630
+ const channelToInsert = {
2631
+ id: newId,
2632
+ messageServerId: data.messageServerId,
2633
+ name: data.name,
2634
+ type: data.type,
2635
+ sourceType: data.sourceType,
2636
+ sourceId: data.sourceId,
2637
+ topic: data.topic,
2638
+ metadata: data.metadata,
2639
+ createdAt: now,
2640
+ updatedAt: now
2641
+ };
2642
+ await this.db.transaction(async (tx) => {
2643
+ await tx.insert(channelTable).values(channelToInsert);
2644
+ if (participantIds && participantIds.length > 0) {
2645
+ const participantValues = participantIds.map((userId) => ({
2646
+ channelId: newId,
2647
+ userId
2648
+ }));
2649
+ await tx.insert(channelParticipantsTable).values(participantValues).onConflictDoNothing();
2650
+ }
2651
+ });
2652
+ return channelToInsert;
2653
+ });
2654
+ }
2655
+ /**
2656
+ * Gets channels for a server
2657
+ */
2658
+ async getChannelsForServer(serverId) {
2659
+ return this.withDatabase(async () => {
2660
+ const results = await this.db.select().from(channelTable).where(eq(channelTable.messageServerId, serverId));
2661
+ return results.map((r) => ({
2662
+ id: r.id,
2663
+ messageServerId: r.messageServerId,
2664
+ name: r.name,
2665
+ type: r.type,
2666
+ sourceType: r.sourceType || void 0,
2667
+ sourceId: r.sourceId || void 0,
2668
+ topic: r.topic || void 0,
2669
+ metadata: r.metadata || void 0,
2670
+ createdAt: r.createdAt,
2671
+ updatedAt: r.updatedAt
2672
+ }));
2673
+ });
2674
+ }
2675
+ /**
2676
+ * Gets channel details
2677
+ */
2678
+ async getChannelDetails(channelId) {
2679
+ return this.withDatabase(async () => {
2680
+ const results = await this.db.select().from(channelTable).where(eq(channelTable.id, channelId)).limit(1);
2681
+ return results.length > 0 ? {
2682
+ id: results[0].id,
2683
+ messageServerId: results[0].messageServerId,
2684
+ name: results[0].name,
2685
+ type: results[0].type,
2686
+ sourceType: results[0].sourceType || void 0,
2687
+ sourceId: results[0].sourceId || void 0,
2688
+ topic: results[0].topic || void 0,
2689
+ metadata: results[0].metadata || void 0,
2690
+ createdAt: results[0].createdAt,
2691
+ updatedAt: results[0].updatedAt
2692
+ } : null;
2693
+ });
2694
+ }
2695
+ /**
2696
+ * Creates a message
2697
+ */
2698
+ async createMessage(data) {
2699
+ return this.withDatabase(async () => {
2700
+ const newId = v4();
2701
+ const now = /* @__PURE__ */ new Date();
2702
+ const messageToInsert = {
2703
+ id: newId,
2704
+ channelId: data.channelId,
2705
+ authorId: data.authorId,
2706
+ content: data.content,
2707
+ rawMessage: data.rawMessage,
2708
+ sourceType: data.sourceType,
2709
+ sourceId: data.sourceId,
2710
+ metadata: data.metadata,
2711
+ inReplyToRootMessageId: data.inReplyToRootMessageId,
2712
+ createdAt: now,
2713
+ updatedAt: now
2714
+ };
2715
+ await this.db.insert(messageTable).values(messageToInsert);
2716
+ return messageToInsert;
2717
+ });
2718
+ }
2719
+ /**
2720
+ * Gets messages for a channel
2721
+ */
2722
+ async getMessagesForChannel(channelId, limit = 50, beforeTimestamp) {
2723
+ return this.withDatabase(async () => {
2724
+ const conditions = [eq(messageTable.channelId, channelId)];
2725
+ if (beforeTimestamp) {
2726
+ conditions.push(lt(messageTable.createdAt, beforeTimestamp));
2727
+ }
2728
+ const query = this.db.select().from(messageTable).where(and(...conditions)).orderBy(desc(messageTable.createdAt)).limit(limit);
2729
+ const results = await query;
2730
+ return results.map((r) => ({
2731
+ id: r.id,
2732
+ channelId: r.channelId,
2733
+ authorId: r.authorId,
2734
+ content: r.content,
2735
+ rawMessage: r.rawMessage || void 0,
2736
+ sourceType: r.sourceType || void 0,
2737
+ sourceId: r.sourceId || void 0,
2738
+ metadata: r.metadata || void 0,
2739
+ inReplyToRootMessageId: r.inReplyToRootMessageId,
2740
+ createdAt: r.createdAt,
2741
+ updatedAt: r.updatedAt
2742
+ }));
2743
+ });
2744
+ }
2745
+ /**
2746
+ * Deletes a message
2747
+ */
2748
+ async deleteMessage(messageId) {
2749
+ return this.withDatabase(async () => {
2750
+ await this.db.delete(messageTable).where(eq(messageTable.id, messageId));
2751
+ });
2752
+ }
2753
+ /**
2754
+ * Adds participants to a channel
2755
+ */
2756
+ async addChannelParticipants(channelId, userIds) {
2757
+ return this.withDatabase(async () => {
2758
+ if (!userIds || userIds.length === 0) return;
2759
+ const participantValues = userIds.map((userId) => ({
2760
+ channelId,
2761
+ userId
2762
+ }));
2763
+ await this.db.insert(channelParticipantsTable).values(participantValues).onConflictDoNothing();
2764
+ });
2765
+ }
2766
+ /**
2767
+ * Gets participants for a channel
2768
+ */
2769
+ async getChannelParticipants(channelId) {
2770
+ return this.withDatabase(async () => {
2771
+ const results = await this.db.select({ userId: channelParticipantsTable.userId }).from(channelParticipantsTable).where(eq(channelParticipantsTable.channelId, channelId));
2772
+ return results.map((r) => r.userId);
2773
+ });
2774
+ }
2775
+ /**
2776
+ * Adds an agent to a server
2777
+ */
2778
+ async addAgentToServer(serverId, agentId) {
2779
+ return this.withDatabase(async () => {
2780
+ await this.db.insert(serverAgentsTable).values({
2781
+ serverId,
2782
+ agentId
2783
+ }).onConflictDoNothing();
2784
+ });
2785
+ }
2786
+ /**
2787
+ * Gets agents for a server
2788
+ */
2789
+ async getAgentsForServer(serverId) {
2790
+ return this.withDatabase(async () => {
2791
+ const results = await this.db.select({ agentId: serverAgentsTable.agentId }).from(serverAgentsTable).where(eq(serverAgentsTable.serverId, serverId));
2792
+ return results.map((r) => r.agentId);
2793
+ });
2794
+ }
2795
+ /**
2796
+ * Removes an agent from a server
2797
+ */
2798
+ async removeAgentFromServer(serverId, agentId) {
2799
+ return this.withDatabase(async () => {
2800
+ await this.db.delete(serverAgentsTable).where(
2801
+ and(eq(serverAgentsTable.serverId, serverId), eq(serverAgentsTable.agentId, agentId))
2802
+ );
2803
+ });
2804
+ }
2805
+ /**
2806
+ * Finds or creates a DM channel between two users
2807
+ */
2808
+ async findOrCreateDmChannel(user1Id, user2Id, messageServerId) {
2809
+ return this.withDatabase(async () => {
2810
+ const ids = [user1Id, user2Id].sort();
2811
+ const dmChannelName = `DM-${ids[0]}-${ids[1]}`;
2812
+ const existingChannels = await this.db.select().from(channelTable).where(
2813
+ and(
2814
+ eq(channelTable.type, ChannelType.DM),
2815
+ eq(channelTable.name, dmChannelName),
2816
+ eq(channelTable.messageServerId, messageServerId)
2817
+ )
2818
+ ).limit(1);
2819
+ if (existingChannels.length > 0) {
2820
+ return {
2821
+ id: existingChannels[0].id,
2822
+ messageServerId: existingChannels[0].messageServerId,
2823
+ name: existingChannels[0].name,
2824
+ type: existingChannels[0].type,
2825
+ sourceType: existingChannels[0].sourceType || void 0,
2826
+ sourceId: existingChannels[0].sourceId || void 0,
2827
+ topic: existingChannels[0].topic || void 0,
2828
+ metadata: existingChannels[0].metadata || void 0,
2829
+ createdAt: existingChannels[0].createdAt,
2830
+ updatedAt: existingChannels[0].updatedAt
2831
+ };
2832
+ }
2833
+ return this.createChannel(
2834
+ {
2835
+ messageServerId,
2836
+ name: dmChannelName,
2837
+ type: ChannelType.DM,
2838
+ metadata: { user1: ids[0], user2: ids[1] }
2839
+ },
2840
+ ids
2841
+ );
2842
+ });
2843
+ }
2461
2844
  };
2462
2845
 
2463
2846
  // src/pglite/adapter.ts