@elizaos/plugin-sql 1.0.4 → 1.0.5
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/{chunk-QOV7MUNF.js → chunk-74FVWTXP.js} +10 -2
- package/dist/chunk-74FVWTXP.js.map +1 -0
- package/dist/index.js +398 -15
- package/dist/index.js.map +1 -1
- package/dist/migrate.js +1 -1
- package/drizzle/migrations/{0000_snapshot.sql → 0000_thin_madame_web.sql} +55 -1
- package/drizzle/migrations/meta/0000_snapshot.json +556 -70
- package/drizzle/migrations/meta/_journal.json +3 -3
- package/package.json +4 -4
- package/dist/chunk-QOV7MUNF.js.map +0 -1
|
@@ -106,7 +106,9 @@ var PGliteClientManager = class {
|
|
|
106
106
|
async initialize() {
|
|
107
107
|
try {
|
|
108
108
|
await this.client.waitReady;
|
|
109
|
-
|
|
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-
|
|
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-
|
|
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 {
|
|
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(
|
|
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:
|
|
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 =
|
|
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:
|
|
1550
|
-
metadata:
|
|
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:
|
|
1592
|
-
...memory.metadata && { metadata:
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|