@elizaos/plugin-sql 1.0.0-alpha.1

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/index.js ADDED
@@ -0,0 +1,2177 @@
1
+ // src/index.ts
2
+ import {
3
+ logger as logger6
4
+ } from "@elizaos/core";
5
+
6
+ // src/pg-lite/adapter.ts
7
+ import { logger as logger2 } from "@elizaos/core";
8
+ import { drizzle } from "drizzle-orm/pglite";
9
+
10
+ // src/base.ts
11
+ import {
12
+ DatabaseAdapter,
13
+ logger
14
+ } from "@elizaos/core";
15
+ import {
16
+ and,
17
+ cosineDistance,
18
+ count,
19
+ desc,
20
+ eq,
21
+ gte,
22
+ inArray,
23
+ lte,
24
+ or,
25
+ sql as sql13
26
+ } from "drizzle-orm";
27
+ import { v4 } from "uuid";
28
+
29
+ // src/schema/embedding.ts
30
+ import {
31
+ pgTable as pgTable6,
32
+ uuid as uuid6,
33
+ vector as vector2,
34
+ index as index2,
35
+ foreignKey as foreignKey2,
36
+ check as check2
37
+ } from "drizzle-orm/pg-core";
38
+ import { sql as sql6 } from "drizzle-orm";
39
+
40
+ // src/schema/types.ts
41
+ import { customType } from "drizzle-orm/pg-core";
42
+ var stringJsonb = customType({
43
+ dataType() {
44
+ return "jsonb";
45
+ },
46
+ toDriver(value) {
47
+ return JSON.stringify(value);
48
+ },
49
+ fromDriver(value) {
50
+ return JSON.stringify(value);
51
+ }
52
+ });
53
+ var numberTimestamp = customType(
54
+ {
55
+ dataType() {
56
+ return "timestamptz";
57
+ },
58
+ toDriver(value) {
59
+ return new Date(value).toISOString();
60
+ },
61
+ fromDriver(value) {
62
+ return new Date(value).getTime();
63
+ }
64
+ }
65
+ );
66
+
67
+ // src/schema/memory.ts
68
+ import {
69
+ pgTable as pgTable5,
70
+ uuid as uuid5,
71
+ text as text5,
72
+ jsonb as jsonb5,
73
+ index,
74
+ boolean as boolean2,
75
+ foreignKey,
76
+ check
77
+ } from "drizzle-orm/pg-core";
78
+ import { relations, sql as sql5 } from "drizzle-orm";
79
+
80
+ // src/schema/entity.ts
81
+ import { sql as sql2 } from "drizzle-orm";
82
+ import { jsonb as jsonb2, pgTable as pgTable2, text as text2, unique as unique2, uuid as uuid2 } from "drizzle-orm/pg-core";
83
+
84
+ // src/schema/agent.ts
85
+ import {
86
+ boolean,
87
+ jsonb,
88
+ pgTable,
89
+ text,
90
+ uuid,
91
+ unique
92
+ } from "drizzle-orm/pg-core";
93
+ import { sql } from "drizzle-orm";
94
+ var agentTable = pgTable(
95
+ "agents",
96
+ {
97
+ id: uuid("id").primaryKey().defaultRandom(),
98
+ createdAt: numberTimestamp("createdAt").default(sql`now()`).notNull(),
99
+ updatedAt: numberTimestamp("updatedAt").default(sql`now()`).notNull(),
100
+ enabled: boolean("enabled").default(true).notNull(),
101
+ // Character
102
+ name: text("name"),
103
+ username: text("username"),
104
+ system: text("system"),
105
+ bio: jsonb("bio").$type().notNull(),
106
+ messageExamples: jsonb("message_examples").$type().default(sql`'[]'::jsonb`),
107
+ postExamples: jsonb("post_examples").$type().default(sql`'[]'::jsonb`),
108
+ topics: jsonb("topics").$type().default(sql`'[]'::jsonb`),
109
+ adjectives: jsonb("adjectives").$type().default(sql`'[]'::jsonb`),
110
+ knowledge: jsonb("knowledge").$type().default(sql`'[]'::jsonb`),
111
+ plugins: jsonb("plugins").$type().default(sql`'[]'::jsonb`),
112
+ settings: jsonb("settings").$type().default(sql`'{}'::jsonb`),
113
+ style: jsonb("style").$type().default(sql`'{}'::jsonb`)
114
+ },
115
+ (table) => {
116
+ return {
117
+ nameUnique: unique("name_unique").on(table.name)
118
+ };
119
+ }
120
+ );
121
+
122
+ // src/schema/entity.ts
123
+ var entityTable = pgTable2(
124
+ "entities",
125
+ {
126
+ id: uuid2("id").notNull().primaryKey(),
127
+ agentId: uuid2("agentId").notNull().references(() => agentTable.id, {
128
+ onDelete: "cascade"
129
+ }),
130
+ createdAt: numberTimestamp("createdAt").default(sql2`now()`).notNull(),
131
+ names: text2("names").array().default(sql2`'{}'::text[]`),
132
+ metadata: jsonb2("metadata").default(sql2`'{}'::jsonb`)
133
+ },
134
+ (table) => {
135
+ return {
136
+ idAgentIdUnique: unique2("id_agent_id_unique").on(table.id, table.agentId)
137
+ };
138
+ }
139
+ );
140
+
141
+ // src/schema/room.ts
142
+ import { sql as sql4 } from "drizzle-orm";
143
+ import { jsonb as jsonb4, pgTable as pgTable4, text as text4, uuid as uuid4 } from "drizzle-orm/pg-core";
144
+
145
+ // src/schema/worldTable.ts
146
+ import { jsonb as jsonb3, pgTable as pgTable3, text as text3, uuid as uuid3 } from "drizzle-orm/pg-core";
147
+ import { sql as sql3 } from "drizzle-orm";
148
+ var worldTable = pgTable3("worlds", {
149
+ id: uuid3("id").notNull().primaryKey().default(sql3`gen_random_uuid()`),
150
+ agentId: uuid3("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
151
+ name: text3("name").notNull(),
152
+ metadata: jsonb3("metadata"),
153
+ serverId: text3("serverId").notNull(),
154
+ createdAt: numberTimestamp("createdAt").default(sql3`now()`).notNull()
155
+ });
156
+
157
+ // src/schema/room.ts
158
+ var roomTable = pgTable4("rooms", {
159
+ id: uuid4("id").notNull().primaryKey().default(sql4`gen_random_uuid()`),
160
+ agentId: uuid4("agentId").references(() => agentTable.id, {
161
+ onDelete: "cascade"
162
+ }),
163
+ source: text4("source").notNull(),
164
+ type: text4("type").notNull(),
165
+ serverId: text4("serverId"),
166
+ worldId: uuid4("worldId").references(() => worldTable.id, {
167
+ onDelete: "cascade"
168
+ }),
169
+ name: text4("name"),
170
+ metadata: jsonb4("metadata"),
171
+ channelId: text4("channelId"),
172
+ createdAt: numberTimestamp("createdAt").default(sql4`now()`).notNull()
173
+ });
174
+
175
+ // src/schema/memory.ts
176
+ var memoryTable = pgTable5(
177
+ "memories",
178
+ {
179
+ id: uuid5("id").primaryKey().notNull(),
180
+ type: text5("type").notNull(),
181
+ createdAt: numberTimestamp("createdAt").default(sql5`now()`).notNull(),
182
+ content: jsonb5("content").notNull(),
183
+ entityId: uuid5("entityId").references(() => entityTable.id, {
184
+ onDelete: "cascade"
185
+ }),
186
+ agentId: uuid5("agentId").references(() => agentTable.id, {
187
+ onDelete: "cascade"
188
+ }),
189
+ roomId: uuid5("roomId").references(() => roomTable.id, {
190
+ onDelete: "cascade"
191
+ }),
192
+ unique: boolean2("unique").default(true).notNull(),
193
+ metadata: jsonb5("metadata").default({}).notNull()
194
+ },
195
+ (table) => [
196
+ index("idx_memories_type_room").on(table.type, table.roomId),
197
+ foreignKey({
198
+ name: "fk_room",
199
+ columns: [table.roomId],
200
+ foreignColumns: [roomTable.id]
201
+ }).onDelete("cascade"),
202
+ foreignKey({
203
+ name: "fk_user",
204
+ columns: [table.entityId],
205
+ foreignColumns: [entityTable.id]
206
+ }).onDelete("cascade"),
207
+ foreignKey({
208
+ name: "fk_agent",
209
+ columns: [table.agentId],
210
+ foreignColumns: [entityTable.id]
211
+ }).onDelete("cascade"),
212
+ index("idx_memories_metadata_type").on(sql5`((metadata->>'type'))`),
213
+ index("idx_memories_document_id").on(sql5`((metadata->>'documentId'))`),
214
+ index("idx_fragments_order").on(
215
+ sql5`((metadata->>'documentId'))`,
216
+ sql5`((metadata->>'position'))`
217
+ ),
218
+ check(
219
+ "fragment_metadata_check",
220
+ sql5`
221
+ CASE
222
+ WHEN metadata->>'type' = 'fragment' THEN
223
+ metadata ? 'documentId' AND
224
+ metadata ? 'position'
225
+ ELSE true
226
+ END
227
+ `
228
+ ),
229
+ check(
230
+ "document_metadata_check",
231
+ sql5`
232
+ CASE
233
+ WHEN metadata->>'type' = 'document' THEN
234
+ metadata ? 'timestamp'
235
+ ELSE true
236
+ END
237
+ `
238
+ )
239
+ ]
240
+ );
241
+ var memoryRelations = relations(memoryTable, ({ one }) => ({
242
+ embedding: one(embeddingTable)
243
+ }));
244
+
245
+ // src/schema/embedding.ts
246
+ var VECTOR_DIMS = {
247
+ SMALL: 384,
248
+ MEDIUM: 512,
249
+ LARGE: 768,
250
+ XL: 1024,
251
+ XXL: 1536,
252
+ XXXL: 3072
253
+ };
254
+ var DIMENSION_MAP = {
255
+ [VECTOR_DIMS.SMALL]: "dim384",
256
+ [VECTOR_DIMS.MEDIUM]: "dim512",
257
+ [VECTOR_DIMS.LARGE]: "dim768",
258
+ [VECTOR_DIMS.XL]: "dim1024",
259
+ [VECTOR_DIMS.XXL]: "dim1536",
260
+ [VECTOR_DIMS.XXXL]: "dim3072"
261
+ };
262
+ var embeddingTable = pgTable6(
263
+ "embeddings",
264
+ {
265
+ id: uuid6("id").primaryKey().defaultRandom().notNull(),
266
+ memoryId: uuid6("memory_id").references(() => memoryTable.id),
267
+ createdAt: numberTimestamp("created_at").default(sql6`now()`).notNull(),
268
+ dim384: vector2("dim_384", { dimensions: VECTOR_DIMS.SMALL }),
269
+ dim512: vector2("dim_512", { dimensions: VECTOR_DIMS.MEDIUM }),
270
+ dim768: vector2("dim_768", { dimensions: VECTOR_DIMS.LARGE }),
271
+ dim1024: vector2("dim_1024", { dimensions: VECTOR_DIMS.XL }),
272
+ dim1536: vector2("dim_1536", { dimensions: VECTOR_DIMS.XXL }),
273
+ dim3072: vector2("dim_3072", { dimensions: VECTOR_DIMS.XXXL })
274
+ },
275
+ (table) => [
276
+ check2("embedding_source_check", sql6`"memory_id" IS NOT NULL`),
277
+ index2("idx_embedding_memory").on(table.memoryId),
278
+ foreignKey2({
279
+ name: "fk_embedding_memory",
280
+ columns: [table.memoryId],
281
+ foreignColumns: [memoryTable.id]
282
+ }).onDelete("cascade")
283
+ ]
284
+ );
285
+
286
+ // src/schema/cache.ts
287
+ import { sql as sql7 } from "drizzle-orm";
288
+ import { jsonb as jsonb6, pgTable as pgTable7, text as text6, unique as unique4, uuid as uuid7 } from "drizzle-orm/pg-core";
289
+ var cacheTable = pgTable7(
290
+ "cache",
291
+ {
292
+ id: uuid7("id").notNull().primaryKey().default(sql7`gen_random_uuid()`),
293
+ key: text6("key").notNull(),
294
+ agentId: uuid7("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
295
+ value: jsonb6("value").notNull(),
296
+ createdAt: numberTimestamp("createdAt").default(sql7`now()`).notNull(),
297
+ expiresAt: numberTimestamp("expiresAt")
298
+ },
299
+ (table) => [unique4("cache_key_agent_unique").on(table.key, table.agentId)]
300
+ );
301
+
302
+ // src/schema/component.ts
303
+ import { pgTable as pgTable8, uuid as uuid8, jsonb as jsonb7, text as text7 } from "drizzle-orm/pg-core";
304
+ import { sql as sql8 } from "drizzle-orm";
305
+ var componentTable = pgTable8("components", {
306
+ id: uuid8("id").primaryKey().defaultRandom(),
307
+ entityId: uuid8("entityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
308
+ agentId: uuid8("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
309
+ roomId: uuid8("roomId").notNull().references(() => roomTable.id, { onDelete: "cascade" }),
310
+ worldId: uuid8("worldId").references(() => worldTable.id, {
311
+ onDelete: "cascade"
312
+ }),
313
+ sourceEntityId: uuid8("sourceEntityId").references(() => entityTable.id, {
314
+ onDelete: "cascade"
315
+ }),
316
+ type: text7("type").notNull(),
317
+ data: jsonb7("data").default(sql8`'{}'::jsonb`),
318
+ createdAt: numberTimestamp("createdAt").default(sql8`now()`).notNull()
319
+ });
320
+
321
+ // src/schema/goal.ts
322
+ import { pgTable as pgTable9, uuid as uuid9, text as text8, jsonb as jsonb8, foreignKey as foreignKey3 } from "drizzle-orm/pg-core";
323
+ import { sql as sql9 } from "drizzle-orm";
324
+ var goalTable = pgTable9(
325
+ "goals",
326
+ {
327
+ id: uuid9("id").notNull().primaryKey().default(sql9`gen_random_uuid()`),
328
+ createdAt: numberTimestamp("createdAt").default(sql9`now()`).notNull(),
329
+ entityId: uuid9("entityId").references(() => entityTable.id, {
330
+ onDelete: "cascade"
331
+ }),
332
+ agentId: uuid9("agentId").references(() => agentTable.id, {
333
+ onDelete: "cascade"
334
+ }),
335
+ name: text8("name"),
336
+ status: text8("status"),
337
+ description: text8("description"),
338
+ roomId: uuid9("roomId").references(() => roomTable.id, {
339
+ onDelete: "cascade"
340
+ }),
341
+ objectives: jsonb8("objectives").default("[]").notNull()
342
+ },
343
+ (table) => [
344
+ foreignKey3({
345
+ name: "fk_room",
346
+ columns: [table.roomId],
347
+ foreignColumns: [roomTable.id]
348
+ }).onDelete("cascade"),
349
+ foreignKey3({
350
+ name: "fk_user",
351
+ columns: [table.entityId],
352
+ foreignColumns: [entityTable.id]
353
+ }).onDelete("cascade")
354
+ ]
355
+ );
356
+
357
+ // src/schema/log.ts
358
+ import { pgTable as pgTable10, uuid as uuid10, text as text9, jsonb as jsonb9, foreignKey as foreignKey4 } from "drizzle-orm/pg-core";
359
+ import { sql as sql10 } from "drizzle-orm";
360
+ var logTable = pgTable10(
361
+ "logs",
362
+ {
363
+ id: uuid10("id").defaultRandom().notNull(),
364
+ createdAt: numberTimestamp("createdAt").default(sql10`now()`).notNull(),
365
+ entityId: uuid10("entityId").notNull().references(() => entityTable.id),
366
+ body: jsonb9("body").notNull(),
367
+ type: text9("type").notNull(),
368
+ roomId: uuid10("roomId").notNull().references(() => roomTable.id)
369
+ },
370
+ (table) => [
371
+ foreignKey4({
372
+ name: "fk_room",
373
+ columns: [table.roomId],
374
+ foreignColumns: [roomTable.id]
375
+ }).onDelete("cascade"),
376
+ foreignKey4({
377
+ name: "fk_user",
378
+ columns: [table.entityId],
379
+ foreignColumns: [entityTable.id]
380
+ }).onDelete("cascade")
381
+ ]
382
+ );
383
+
384
+ // src/schema/participant.ts
385
+ import {
386
+ pgTable as pgTable11,
387
+ uuid as uuid11,
388
+ text as text10,
389
+ index as index3,
390
+ foreignKey as foreignKey5
391
+ } from "drizzle-orm/pg-core";
392
+ import { sql as sql11 } from "drizzle-orm";
393
+ var participantTable = pgTable11(
394
+ "participants",
395
+ {
396
+ id: uuid11("id").notNull().primaryKey().default(sql11`gen_random_uuid()`),
397
+ createdAt: numberTimestamp("createdAt").default(sql11`now()`).notNull(),
398
+ entityId: uuid11("entityId").references(() => entityTable.id, {
399
+ onDelete: "cascade"
400
+ }),
401
+ roomId: uuid11("roomId").references(() => roomTable.id, {
402
+ onDelete: "cascade"
403
+ }),
404
+ agentId: uuid11("agentId").references(() => agentTable.id, {
405
+ onDelete: "cascade"
406
+ }),
407
+ roomState: text10("roomState")
408
+ },
409
+ (table) => [
410
+ // unique("participants_user_room_agent_unique").on(table.entityId, table.roomId, table.agentId),
411
+ index3("idx_participants_user").on(table.entityId),
412
+ index3("idx_participants_room").on(table.roomId),
413
+ foreignKey5({
414
+ name: "fk_room",
415
+ columns: [table.roomId],
416
+ foreignColumns: [roomTable.id]
417
+ }).onDelete("cascade"),
418
+ foreignKey5({
419
+ name: "fk_user",
420
+ columns: [table.entityId],
421
+ foreignColumns: [entityTable.id]
422
+ }).onDelete("cascade")
423
+ ]
424
+ );
425
+
426
+ // src/schema/relationship.ts
427
+ import { sql as sql12 } from "drizzle-orm";
428
+ import {
429
+ foreignKey as foreignKey6,
430
+ index as index4,
431
+ jsonb as jsonb10,
432
+ pgTable as pgTable12,
433
+ text as text11,
434
+ unique as unique6,
435
+ uuid as uuid12
436
+ } from "drizzle-orm/pg-core";
437
+ var relationshipTable = pgTable12(
438
+ "relationships",
439
+ {
440
+ id: uuid12("id").notNull().primaryKey().default(sql12`gen_random_uuid()`),
441
+ createdAt: numberTimestamp("createdAt").default(sql12`now()`).notNull(),
442
+ sourceEntityId: uuid12("sourceEntityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
443
+ targetEntityId: uuid12("targetEntityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
444
+ agentId: uuid12("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
445
+ tags: text11("tags").array(),
446
+ metadata: jsonb10("metadata")
447
+ },
448
+ (table) => [
449
+ index4("idx_relationships_users").on(
450
+ table.sourceEntityId,
451
+ table.targetEntityId
452
+ ),
453
+ unique6("unique_relationship").on(
454
+ table.sourceEntityId,
455
+ table.targetEntityId,
456
+ table.agentId
457
+ ),
458
+ foreignKey6({
459
+ name: "fk_user_a",
460
+ columns: [table.sourceEntityId],
461
+ foreignColumns: [entityTable.id]
462
+ }).onDelete("cascade"),
463
+ foreignKey6({
464
+ name: "fk_user_b",
465
+ columns: [table.targetEntityId],
466
+ foreignColumns: [entityTable.id]
467
+ }).onDelete("cascade")
468
+ ]
469
+ );
470
+
471
+ // src/schema/tasks.ts
472
+ import { jsonb as jsonb11, pgTable as pgTable13, text as text12, timestamp, uuid as uuid13 } from "drizzle-orm/pg-core";
473
+ var taskTable = pgTable13("tasks", {
474
+ id: uuid13("id").primaryKey().defaultRandom(),
475
+ name: text12("name").notNull(),
476
+ description: text12("description").notNull(),
477
+ roomId: uuid13("room_id"),
478
+ worldId: uuid13("world_id"),
479
+ agentId: uuid13("agent_id").notNull(),
480
+ tags: text12("tags").array(),
481
+ metadata: jsonb11("metadata"),
482
+ createdAt: timestamp("created_at").defaultNow(),
483
+ updatedAt: timestamp("updated_at").defaultNow()
484
+ });
485
+
486
+ // src/base.ts
487
+ var BaseDrizzleAdapter = class extends DatabaseAdapter {
488
+ maxRetries = 3;
489
+ baseDelay = 1e3;
490
+ maxDelay = 1e4;
491
+ jitterMax = 1e3;
492
+ embeddingDimension = DIMENSION_MAP[384];
493
+ agentId;
494
+ constructor(agentId) {
495
+ super();
496
+ this.agentId = agentId;
497
+ }
498
+ async withRetry(operation) {
499
+ let lastError = new Error("Unknown error");
500
+ for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
501
+ try {
502
+ return await operation();
503
+ } catch (error) {
504
+ lastError = error;
505
+ if (attempt < this.maxRetries) {
506
+ const backoffDelay = Math.min(
507
+ this.baseDelay * 2 ** (attempt - 1),
508
+ this.maxDelay
509
+ );
510
+ const jitter = Math.random() * this.jitterMax;
511
+ const delay = backoffDelay + jitter;
512
+ logger.warn(
513
+ `Database operation failed (attempt ${attempt}/${this.maxRetries}):`,
514
+ {
515
+ error: error instanceof Error ? error.message : String(error),
516
+ nextRetryIn: `${(delay / 1e3).toFixed(1)}s`
517
+ }
518
+ );
519
+ console.trace("****** Database operation failure source");
520
+ await new Promise((resolve) => setTimeout(resolve, delay));
521
+ } else {
522
+ logger.error("Max retry attempts reached:", {
523
+ error: error instanceof Error ? error.message : String(error),
524
+ totalAttempts: attempt
525
+ });
526
+ throw error instanceof Error ? error : new Error(String(error));
527
+ }
528
+ }
529
+ }
530
+ throw lastError;
531
+ }
532
+ async ensureAgentExists(agent) {
533
+ if (!agent.name) {
534
+ throw new Error("Agent name is required");
535
+ }
536
+ const agents = await this.getAgents();
537
+ const existingAgent = agents.find(
538
+ (a) => a.name === agent.name
539
+ );
540
+ if (!existingAgent) {
541
+ await this.createAgent(agent);
542
+ }
543
+ }
544
+ async ensureEmbeddingDimension(dimension) {
545
+ const existingMemory = await this.db.select({
546
+ embedding: embeddingTable
547
+ }).from(memoryTable).innerJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(eq(memoryTable.agentId, this.agentId)).limit(1);
548
+ if (existingMemory.length > 0) {
549
+ const usedDimension = Object.entries(DIMENSION_MAP).find(
550
+ ([_, colName]) => existingMemory[0].embedding[colName] !== null
551
+ );
552
+ if (usedDimension && usedDimension[1] !== DIMENSION_MAP[dimension]) {
553
+ throw new Error("Cannot change embedding dimension for agent");
554
+ }
555
+ }
556
+ this.embeddingDimension = DIMENSION_MAP[dimension];
557
+ }
558
+ async getAgent(agentId) {
559
+ return this.withDatabase(async () => {
560
+ const result = await this.db.select().from(agentTable).where(eq(agentTable.id, agentId)).limit(1);
561
+ if (result.length === 0) return null;
562
+ return result[0];
563
+ });
564
+ }
565
+ async getAgents() {
566
+ return this.withDatabase(async () => {
567
+ const result = await this.db.select().from(agentTable);
568
+ return result;
569
+ });
570
+ }
571
+ async createAgent(agent) {
572
+ return this.withDatabase(async () => {
573
+ try {
574
+ await this.db.transaction(async (tx) => {
575
+ await tx.insert(agentTable).values({
576
+ ...agent
577
+ });
578
+ });
579
+ logger.debug("Agent created successfully:", {
580
+ agentId: agent.id
581
+ });
582
+ return true;
583
+ } catch (error) {
584
+ logger.error("Error creating agent:", {
585
+ error: error instanceof Error ? error.message : String(error),
586
+ agentId: agent.id,
587
+ agent
588
+ });
589
+ return false;
590
+ }
591
+ });
592
+ }
593
+ async updateAgent(agentId, agent) {
594
+ return this.withDatabase(async () => {
595
+ try {
596
+ if (!agent.id) {
597
+ throw new Error("Agent ID is required for update");
598
+ }
599
+ await this.db.transaction(async (tx) => {
600
+ await tx.update(agentTable).set({
601
+ ...agent,
602
+ updatedAt: Date.now()
603
+ }).where(eq(agentTable.id, agentId));
604
+ });
605
+ logger.debug("Agent updated successfully:", {
606
+ agentId
607
+ });
608
+ return true;
609
+ } catch (error) {
610
+ logger.error("Error updating agent:", {
611
+ error: error instanceof Error ? error.message : String(error),
612
+ agentId,
613
+ agent
614
+ });
615
+ return false;
616
+ }
617
+ });
618
+ }
619
+ async deleteAgent(agentId) {
620
+ return this.withDatabase(async () => {
621
+ await this.db.transaction(async (tx) => {
622
+ await tx.delete(agentTable).where(eq(agentTable.id, agentId));
623
+ });
624
+ return true;
625
+ });
626
+ }
627
+ /**
628
+ * Count all agents in the database
629
+ * Used primarily for maintenance and cleanup operations
630
+ */
631
+ async countAgents() {
632
+ return this.withDatabase(async () => {
633
+ try {
634
+ const result = await this.db.select({ count: count() }).from(agentTable);
635
+ return result[0]?.count || 0;
636
+ } catch (error) {
637
+ logger.error("Error counting agents:", {
638
+ error: error instanceof Error ? error.message : String(error)
639
+ });
640
+ return 0;
641
+ }
642
+ });
643
+ }
644
+ /**
645
+ * Clean up the agents table by removing all agents
646
+ * This is used during server startup to ensure no orphaned agents exist
647
+ * from previous crashes or improper shutdowns
648
+ */
649
+ async cleanupAgents() {
650
+ return this.withDatabase(async () => {
651
+ try {
652
+ await this.db.delete(agentTable);
653
+ logger.success("Successfully cleaned up agent table");
654
+ } catch (error) {
655
+ logger.error("Error cleaning up agent table:", {
656
+ error: error instanceof Error ? error.message : String(error)
657
+ });
658
+ throw error;
659
+ }
660
+ });
661
+ }
662
+ async getEntityById(entityId) {
663
+ return this.withDatabase(async () => {
664
+ const result = await this.db.select({
665
+ entity: entityTable,
666
+ components: componentTable
667
+ }).from(entityTable).leftJoin(componentTable, eq(componentTable.entityId, entityTable.id)).where(
668
+ and(
669
+ eq(entityTable.id, entityId),
670
+ eq(entityTable.agentId, this.agentId)
671
+ )
672
+ );
673
+ if (result.length === 0) return null;
674
+ const entity = result[0].entity;
675
+ entity.components = result.filter((row) => row.components).map((row) => row.components);
676
+ return entity;
677
+ });
678
+ }
679
+ async getEntitiesForRoom(roomId, includeComponents) {
680
+ return this.withDatabase(async () => {
681
+ const query = this.db.select({
682
+ entity: entityTable,
683
+ ...includeComponents && { components: componentTable }
684
+ }).from(participantTable).leftJoin(
685
+ entityTable,
686
+ and(
687
+ eq(participantTable.entityId, entityTable.id),
688
+ eq(entityTable.agentId, this.agentId)
689
+ )
690
+ );
691
+ if (includeComponents) {
692
+ query.leftJoin(
693
+ componentTable,
694
+ eq(componentTable.entityId, entityTable.id)
695
+ );
696
+ }
697
+ const result = await query.where(eq(participantTable.roomId, roomId));
698
+ const entitiesByIdMap = /* @__PURE__ */ new Map();
699
+ for (const row of result) {
700
+ if (!row.entity) continue;
701
+ const entityId = row.entity.id;
702
+ if (!entitiesByIdMap.has(entityId)) {
703
+ const entity = {
704
+ ...row.entity,
705
+ components: includeComponents ? [] : void 0
706
+ };
707
+ entitiesByIdMap.set(entityId, entity);
708
+ }
709
+ if (includeComponents && row.components) {
710
+ const entity = entitiesByIdMap.get(entityId);
711
+ if (entity) {
712
+ if (!entity.components) {
713
+ entity.components = [];
714
+ }
715
+ entity.components.push(row.components);
716
+ }
717
+ }
718
+ }
719
+ return Array.from(entitiesByIdMap.values());
720
+ });
721
+ }
722
+ async createEntity(entity) {
723
+ return this.withDatabase(async () => {
724
+ try {
725
+ return await this.db.transaction(async (tx) => {
726
+ await tx.insert(entityTable).values(entity);
727
+ logger.debug("Entity created successfully:", {
728
+ entity
729
+ });
730
+ return true;
731
+ });
732
+ } catch (error) {
733
+ logger.error("Error creating account:", {
734
+ error: error instanceof Error ? error.message : String(error),
735
+ entityId: entity.id,
736
+ name: entity.metadata?.name
737
+ });
738
+ return false;
739
+ }
740
+ });
741
+ }
742
+ /**
743
+ * Ensures an entity exists, creating it if it doesn't
744
+ * @param entity The entity to ensure exists
745
+ * @returns Promise resolving to boolean indicating success
746
+ */
747
+ async ensureEntityExists(entity) {
748
+ if (!entity.id) {
749
+ logger.error("Entity ID is required for ensureEntityExists");
750
+ return false;
751
+ }
752
+ try {
753
+ const existingEntity = await this.getEntityById(entity.id);
754
+ if (!existingEntity) {
755
+ return await this.createEntity(entity);
756
+ }
757
+ return true;
758
+ } catch (error) {
759
+ logger.error("Error ensuring entity exists:", {
760
+ error: error instanceof Error ? error.message : String(error),
761
+ entityId: entity.id
762
+ });
763
+ return false;
764
+ }
765
+ }
766
+ async updateEntity(entity) {
767
+ return this.withDatabase(async () => {
768
+ await this.db.update(entityTable).set(entity).where(
769
+ and(
770
+ eq(entityTable.id, entity.id),
771
+ eq(entityTable.agentId, entity.agentId)
772
+ )
773
+ );
774
+ });
775
+ }
776
+ async getComponent(entityId, type, worldId, sourceEntityId) {
777
+ return this.withDatabase(async () => {
778
+ const conditions = [
779
+ eq(componentTable.entityId, entityId),
780
+ eq(componentTable.type, type)
781
+ ];
782
+ if (worldId) {
783
+ conditions.push(eq(componentTable.worldId, worldId));
784
+ }
785
+ if (sourceEntityId) {
786
+ conditions.push(eq(componentTable.sourceEntityId, sourceEntityId));
787
+ }
788
+ const result = await this.db.select().from(componentTable).where(and(...conditions));
789
+ return result.length > 0 ? result[0] : null;
790
+ });
791
+ }
792
+ async getComponents(entityId, worldId, sourceEntityId) {
793
+ return this.withDatabase(async () => {
794
+ const conditions = [eq(componentTable.entityId, entityId)];
795
+ if (worldId) {
796
+ conditions.push(eq(componentTable.worldId, worldId));
797
+ }
798
+ if (sourceEntityId) {
799
+ conditions.push(eq(componentTable.sourceEntityId, sourceEntityId));
800
+ }
801
+ const result = await this.db.select({
802
+ id: componentTable.id,
803
+ entityId: componentTable.entityId,
804
+ type: componentTable.type,
805
+ data: componentTable.data,
806
+ worldId: componentTable.worldId,
807
+ sourceEntityId: componentTable.sourceEntityId,
808
+ createdAt: componentTable.createdAt
809
+ }).from(componentTable).where(and(...conditions));
810
+ return result;
811
+ });
812
+ }
813
+ async createComponent(component) {
814
+ return this.withDatabase(async () => {
815
+ await this.db.insert(componentTable).values(component);
816
+ return true;
817
+ });
818
+ }
819
+ async updateComponent(component) {
820
+ return this.withDatabase(async () => {
821
+ await this.db.update(componentTable).set(component).where(eq(componentTable.id, component.id));
822
+ });
823
+ }
824
+ async deleteComponent(componentId) {
825
+ return this.withDatabase(async () => {
826
+ await this.db.delete(componentTable).where(eq(componentTable.id, componentId));
827
+ });
828
+ }
829
+ async getMemories(params) {
830
+ if (!params.tableName) throw new Error("tableName is required");
831
+ if (!params.roomId) throw new Error("roomId is required");
832
+ return this.withDatabase(async () => {
833
+ const conditions = [
834
+ eq(memoryTable.type, params.tableName),
835
+ eq(memoryTable.roomId, params.roomId)
836
+ ];
837
+ if (params.start) {
838
+ conditions.push(gte(memoryTable.createdAt, params.start));
839
+ }
840
+ if (params.end) {
841
+ conditions.push(lte(memoryTable.createdAt, params.end));
842
+ }
843
+ if (params.unique) {
844
+ conditions.push(eq(memoryTable.unique, true));
845
+ }
846
+ conditions.push(eq(memoryTable.agentId, this.agentId));
847
+ const query = this.db.select({
848
+ memory: {
849
+ id: memoryTable.id,
850
+ type: memoryTable.type,
851
+ createdAt: memoryTable.createdAt,
852
+ content: memoryTable.content,
853
+ entityId: memoryTable.entityId,
854
+ agentId: memoryTable.agentId,
855
+ roomId: memoryTable.roomId,
856
+ unique: memoryTable.unique
857
+ },
858
+ embedding: embeddingTable[this.embeddingDimension]
859
+ }).from(memoryTable).leftJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(and(...conditions)).orderBy(desc(memoryTable.createdAt));
860
+ const rows = params.count ? await query.limit(params.count) : await query;
861
+ return rows.map((row) => ({
862
+ id: row.memory.id,
863
+ type: row.memory.type,
864
+ createdAt: row.memory.createdAt,
865
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
866
+ entityId: row.memory.entityId,
867
+ agentId: row.memory.agentId,
868
+ roomId: row.memory.roomId,
869
+ unique: row.memory.unique,
870
+ embedding: row.embedding ? Array.from(row.embedding) : void 0
871
+ }));
872
+ });
873
+ }
874
+ async getMemoriesByRoomIds(params) {
875
+ return this.withDatabase(async () => {
876
+ if (params.roomIds.length === 0) return [];
877
+ const conditions = [
878
+ eq(memoryTable.type, params.tableName),
879
+ inArray(memoryTable.roomId, params.roomIds)
880
+ ];
881
+ conditions.push(eq(memoryTable.agentId, this.agentId));
882
+ const query = this.db.select({
883
+ id: memoryTable.id,
884
+ type: memoryTable.type,
885
+ createdAt: memoryTable.createdAt,
886
+ content: memoryTable.content,
887
+ entityId: memoryTable.entityId,
888
+ agentId: memoryTable.agentId,
889
+ roomId: memoryTable.roomId,
890
+ unique: memoryTable.unique
891
+ }).from(memoryTable).where(and(...conditions)).orderBy(desc(memoryTable.createdAt));
892
+ const rows = params.limit ? await query.limit(params.limit) : await query;
893
+ return rows.map((row) => ({
894
+ id: row.id,
895
+ createdAt: row.createdAt,
896
+ content: typeof row.content === "string" ? JSON.parse(row.content) : row.content,
897
+ entityId: row.entityId,
898
+ agentId: row.agentId,
899
+ roomId: row.roomId,
900
+ unique: row.unique
901
+ }));
902
+ });
903
+ }
904
+ async getMemoryById(id) {
905
+ return this.withDatabase(async () => {
906
+ const result = await this.db.select({
907
+ memory: memoryTable,
908
+ embedding: embeddingTable[this.embeddingDimension]
909
+ }).from(memoryTable).leftJoin(embeddingTable, eq(memoryTable.id, embeddingTable.memoryId)).where(eq(memoryTable.id, id)).limit(1);
910
+ if (result.length === 0) return null;
911
+ const row = result[0];
912
+ return {
913
+ id: row.memory.id,
914
+ createdAt: row.memory.createdAt,
915
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
916
+ entityId: row.memory.entityId,
917
+ agentId: row.memory.agentId,
918
+ roomId: row.memory.roomId,
919
+ unique: row.memory.unique,
920
+ embedding: row.embedding ?? void 0
921
+ };
922
+ });
923
+ }
924
+ async getMemoriesByIds(memoryIds, tableName) {
925
+ return this.withDatabase(async () => {
926
+ if (memoryIds.length === 0) return [];
927
+ const conditions = [inArray(memoryTable.id, memoryIds)];
928
+ if (tableName) {
929
+ conditions.push(eq(memoryTable.type, tableName));
930
+ }
931
+ const rows = await this.db.select({
932
+ memory: memoryTable,
933
+ embedding: embeddingTable[this.embeddingDimension]
934
+ }).from(memoryTable).leftJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(and(...conditions)).orderBy(desc(memoryTable.createdAt));
935
+ return rows.map((row) => ({
936
+ id: row.memory.id,
937
+ createdAt: row.memory.createdAt,
938
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
939
+ entityId: row.memory.entityId,
940
+ agentId: row.memory.agentId,
941
+ roomId: row.memory.roomId,
942
+ unique: row.memory.unique,
943
+ embedding: row.embedding ?? void 0
944
+ }));
945
+ });
946
+ }
947
+ async getCachedEmbeddings(opts) {
948
+ return this.withDatabase(async () => {
949
+ try {
950
+ const results = await this.db.execute(sql13`
951
+ WITH content_text AS (
952
+ SELECT
953
+ m.id,
954
+ COALESCE(
955
+ m.content->>${opts.query_field_sub_name},
956
+ ''
957
+ ) as content_text
958
+ FROM memories m
959
+ WHERE m.type = ${opts.query_table_name}
960
+ AND m.content->>${opts.query_field_sub_name} IS NOT NULL
961
+ ),
962
+ embedded_text AS (
963
+ SELECT
964
+ ct.content_text,
965
+ COALESCE(
966
+ e.dim_384,
967
+ e.dim_512,
968
+ e.dim_768,
969
+ e.dim_1024,
970
+ e.dim_1536,
971
+ e.dim_3072
972
+ ) as embedding
973
+ FROM content_text ct
974
+ LEFT JOIN embeddings e ON e.memory_id = ct.id
975
+ WHERE e.memory_id IS NOT NULL
976
+ )
977
+ SELECT
978
+ embedding,
979
+ levenshtein(${opts.query_input}, content_text) as levenshtein_score
980
+ FROM embedded_text
981
+ WHERE levenshtein(${opts.query_input}, content_text) <= ${opts.query_threshold}
982
+ ORDER BY levenshtein_score
983
+ LIMIT ${opts.query_match_count}
984
+ `);
985
+ return results.rows.map((row) => ({
986
+ embedding: Array.isArray(row.embedding) ? row.embedding : typeof row.embedding === "string" ? JSON.parse(row.embedding) : [],
987
+ levenshtein_score: Number(row.levenshtein_score)
988
+ })).filter((row) => Array.isArray(row.embedding));
989
+ } catch (error) {
990
+ logger.error("Error in getCachedEmbeddings:", {
991
+ error: error instanceof Error ? error.message : String(error),
992
+ tableName: opts.query_table_name,
993
+ fieldName: opts.query_field_name
994
+ });
995
+ if (error instanceof Error && error.message === "levenshtein argument exceeds maximum length of 255 characters") {
996
+ return [];
997
+ }
998
+ throw error;
999
+ }
1000
+ });
1001
+ }
1002
+ async log(params) {
1003
+ return this.withDatabase(async () => {
1004
+ try {
1005
+ await this.db.transaction(async (tx) => {
1006
+ await tx.insert(logTable).values({
1007
+ body: sql13`${params.body}::jsonb`,
1008
+ entityId: params.entityId,
1009
+ roomId: params.roomId,
1010
+ type: params.type
1011
+ });
1012
+ });
1013
+ } catch (error) {
1014
+ logger.error("Failed to create log entry:", {
1015
+ error: error instanceof Error ? error.message : String(error),
1016
+ type: params.type,
1017
+ roomId: params.roomId,
1018
+ entityId: params.entityId
1019
+ });
1020
+ throw error;
1021
+ }
1022
+ });
1023
+ }
1024
+ async searchMemories(params) {
1025
+ return await this.searchMemoriesByEmbedding(params.embedding, {
1026
+ match_threshold: params.match_threshold,
1027
+ count: params.count,
1028
+ roomId: params.roomId,
1029
+ unique: params.unique,
1030
+ tableName: params.tableName
1031
+ });
1032
+ }
1033
+ async updateGoalStatus(params) {
1034
+ return this.withDatabase(async () => {
1035
+ try {
1036
+ await this.db.transaction(async (tx) => {
1037
+ await tx.update(goalTable).set({
1038
+ status: params.status
1039
+ }).where(eq(goalTable.id, params.goalId));
1040
+ });
1041
+ } catch (error) {
1042
+ logger.error("Failed to update goal status:", {
1043
+ goalId: params.goalId,
1044
+ status: params.status,
1045
+ error: error instanceof Error ? error.message : String(error)
1046
+ });
1047
+ throw error;
1048
+ }
1049
+ });
1050
+ }
1051
+ async searchMemoriesByEmbedding(embedding, params) {
1052
+ return this.withDatabase(async () => {
1053
+ const cleanVector = embedding.map(
1054
+ (n) => Number.isFinite(n) ? Number(n.toFixed(6)) : 0
1055
+ );
1056
+ const similarity = sql13`1 - (${cosineDistance(
1057
+ embeddingTable[this.embeddingDimension],
1058
+ cleanVector
1059
+ )})`;
1060
+ const conditions = [eq(memoryTable.type, params.tableName)];
1061
+ if (params.unique) {
1062
+ conditions.push(eq(memoryTable.unique, true));
1063
+ }
1064
+ conditions.push(eq(memoryTable.agentId, this.agentId));
1065
+ if (params.roomId) {
1066
+ conditions.push(eq(memoryTable.roomId, params.roomId));
1067
+ }
1068
+ if (params.match_threshold) {
1069
+ conditions.push(gte(similarity, params.match_threshold));
1070
+ }
1071
+ const results = await this.db.select({
1072
+ memory: memoryTable,
1073
+ similarity,
1074
+ embedding: embeddingTable[this.embeddingDimension]
1075
+ }).from(embeddingTable).innerJoin(memoryTable, eq(memoryTable.id, embeddingTable.memoryId)).where(and(...conditions)).orderBy(desc(similarity)).limit(params.count ?? 10);
1076
+ return results.map((row) => ({
1077
+ id: row.memory.id,
1078
+ type: row.memory.type,
1079
+ createdAt: row.memory.createdAt,
1080
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
1081
+ entityId: row.memory.entityId,
1082
+ agentId: row.memory.agentId,
1083
+ roomId: row.memory.roomId,
1084
+ unique: row.memory.unique,
1085
+ embedding: row.embedding ?? void 0,
1086
+ similarity: row.similarity
1087
+ }));
1088
+ });
1089
+ }
1090
+ async createMemory(memory, tableName) {
1091
+ logger.debug("DrizzleAdapter createMemory:", {
1092
+ memoryId: memory.id,
1093
+ embeddingLength: memory.embedding?.length,
1094
+ contentLength: memory.content?.text?.length
1095
+ });
1096
+ let isUnique = true;
1097
+ if (memory.embedding && Array.isArray(memory.embedding)) {
1098
+ const similarMemories = await this.searchMemoriesByEmbedding(
1099
+ memory.embedding,
1100
+ {
1101
+ tableName,
1102
+ roomId: memory.roomId,
1103
+ match_threshold: 0.95,
1104
+ count: 1
1105
+ }
1106
+ );
1107
+ isUnique = similarMemories.length === 0;
1108
+ }
1109
+ const contentToInsert = typeof memory.content === "string" ? JSON.parse(memory.content) : memory.content;
1110
+ const memoryId = memory.id ?? v4();
1111
+ await this.db.transaction(async (tx) => {
1112
+ await tx.insert(memoryTable).values([
1113
+ {
1114
+ id: memoryId,
1115
+ type: tableName,
1116
+ content: sql13`${contentToInsert}::jsonb`,
1117
+ metadata: sql13`${memory.metadata || {}}::jsonb`,
1118
+ entityId: memory.entityId,
1119
+ roomId: memory.roomId,
1120
+ agentId: memory.agentId,
1121
+ unique: memory.unique ?? isUnique,
1122
+ createdAt: memory.createdAt
1123
+ }
1124
+ ]);
1125
+ if (memory.embedding && Array.isArray(memory.embedding)) {
1126
+ const embeddingValues = {
1127
+ id: v4(),
1128
+ memoryId,
1129
+ createdAt: memory.createdAt
1130
+ };
1131
+ const cleanVector = memory.embedding.map(
1132
+ (n) => Number.isFinite(n) ? Number(n.toFixed(6)) : 0
1133
+ );
1134
+ embeddingValues[this.embeddingDimension] = cleanVector;
1135
+ await tx.insert(embeddingTable).values([embeddingValues]);
1136
+ }
1137
+ });
1138
+ return memoryId;
1139
+ }
1140
+ async removeMemory(memoryId, tableName) {
1141
+ return this.withDatabase(async () => {
1142
+ await this.db.transaction(async (tx) => {
1143
+ await tx.delete(embeddingTable).where(eq(embeddingTable.memoryId, memoryId));
1144
+ await tx.delete(memoryTable).where(
1145
+ and(eq(memoryTable.id, memoryId), eq(memoryTable.type, tableName))
1146
+ );
1147
+ });
1148
+ logger.debug("Memory removed successfully:", {
1149
+ memoryId,
1150
+ tableName
1151
+ });
1152
+ });
1153
+ }
1154
+ async removeAllMemories(roomId, tableName) {
1155
+ return this.withDatabase(async () => {
1156
+ await this.db.transaction(async (tx) => {
1157
+ const memoryIds = await tx.select({ id: memoryTable.id }).from(memoryTable).where(
1158
+ and(
1159
+ eq(memoryTable.roomId, roomId),
1160
+ eq(memoryTable.type, tableName)
1161
+ )
1162
+ );
1163
+ if (memoryIds.length > 0) {
1164
+ await tx.delete(embeddingTable).where(
1165
+ inArray(
1166
+ embeddingTable.memoryId,
1167
+ memoryIds.map((m) => m.id)
1168
+ )
1169
+ );
1170
+ await tx.delete(memoryTable).where(
1171
+ and(
1172
+ eq(memoryTable.roomId, roomId),
1173
+ eq(memoryTable.type, tableName)
1174
+ )
1175
+ );
1176
+ }
1177
+ });
1178
+ logger.debug("All memories removed successfully:", {
1179
+ roomId,
1180
+ tableName
1181
+ });
1182
+ });
1183
+ }
1184
+ async countMemories(roomId, unique7 = true, tableName = "") {
1185
+ if (!tableName) throw new Error("tableName is required");
1186
+ return this.withDatabase(async () => {
1187
+ const conditions = [
1188
+ eq(memoryTable.roomId, roomId),
1189
+ eq(memoryTable.type, tableName)
1190
+ ];
1191
+ if (unique7) {
1192
+ conditions.push(eq(memoryTable.unique, true));
1193
+ }
1194
+ const result = await this.db.select({ count: sql13`count(*)` }).from(memoryTable).where(and(...conditions));
1195
+ return Number(result[0]?.count ?? 0);
1196
+ });
1197
+ }
1198
+ async getGoals(params) {
1199
+ return this.withDatabase(async () => {
1200
+ const conditions = [eq(goalTable.roomId, params.roomId)];
1201
+ if (params.entityId) {
1202
+ conditions.push(eq(goalTable.entityId, params.entityId));
1203
+ }
1204
+ if (params.onlyInProgress) {
1205
+ conditions.push(eq(goalTable.status, "IN_PROGRESS"));
1206
+ }
1207
+ const query = this.db.select().from(goalTable).where(and(...conditions)).orderBy(desc(goalTable.createdAt));
1208
+ const result = await (params.count ? query.limit(params.count) : query);
1209
+ return result.map((row) => ({
1210
+ id: row.id,
1211
+ roomId: row.roomId,
1212
+ entityId: row.entityId,
1213
+ name: row.name ?? "",
1214
+ status: row.status ?? "NOT_STARTED",
1215
+ description: row.description ?? "",
1216
+ objectives: row.objectives,
1217
+ createdAt: row.createdAt
1218
+ }));
1219
+ });
1220
+ }
1221
+ async updateGoal(goal) {
1222
+ return this.withDatabase(async () => {
1223
+ try {
1224
+ await this.db.transaction(async (tx) => {
1225
+ await tx.update(goalTable).set({
1226
+ name: goal.name,
1227
+ status: goal.status,
1228
+ objectives: goal.objectives
1229
+ }).where(eq(goalTable.id, goal.id));
1230
+ });
1231
+ } catch (error) {
1232
+ logger.error("Failed to update goal:", {
1233
+ error: error instanceof Error ? error.message : String(error),
1234
+ goalId: goal.id,
1235
+ status: goal.status
1236
+ });
1237
+ throw error;
1238
+ }
1239
+ });
1240
+ }
1241
+ async createGoal(goal) {
1242
+ return this.withDatabase(async () => {
1243
+ try {
1244
+ await this.db.transaction(async (tx) => {
1245
+ await tx.insert(goalTable).values({
1246
+ id: goal.id ?? v4(),
1247
+ roomId: goal.roomId,
1248
+ entityId: goal.entityId,
1249
+ name: goal.name,
1250
+ status: goal.status,
1251
+ objectives: sql13`${goal.objectives}::jsonb`
1252
+ });
1253
+ });
1254
+ } catch (error) {
1255
+ logger.error("Failed to update goal:", {
1256
+ goalId: goal.id,
1257
+ error: error instanceof Error ? error.message : String(error),
1258
+ status: goal.status
1259
+ });
1260
+ throw error;
1261
+ }
1262
+ });
1263
+ }
1264
+ async removeGoal(goalId) {
1265
+ if (!goalId) throw new Error("Goal ID is required");
1266
+ return this.withDatabase(async () => {
1267
+ try {
1268
+ await this.db.transaction(async (tx) => {
1269
+ await tx.delete(goalTable).where(eq(goalTable.id, goalId));
1270
+ });
1271
+ logger.debug("Goal removal attempt:", {
1272
+ goalId,
1273
+ removed: true
1274
+ });
1275
+ } catch (error) {
1276
+ logger.error("Failed to remove goal:", {
1277
+ error: error instanceof Error ? error.message : String(error),
1278
+ goalId
1279
+ });
1280
+ throw error;
1281
+ }
1282
+ });
1283
+ }
1284
+ async removeAllGoals(roomId) {
1285
+ return this.withDatabase(async () => {
1286
+ await this.db.transaction(async (tx) => {
1287
+ await tx.delete(goalTable).where(eq(goalTable.roomId, roomId));
1288
+ });
1289
+ });
1290
+ }
1291
+ async getRoom(roomId) {
1292
+ return this.withDatabase(async () => {
1293
+ const result = await this.db.select({
1294
+ id: roomTable.id,
1295
+ channelId: roomTable.channelId,
1296
+ agentId: roomTable.agentId,
1297
+ serverId: roomTable.serverId,
1298
+ worldId: roomTable.worldId,
1299
+ type: roomTable.type,
1300
+ source: roomTable.source
1301
+ }).from(roomTable).where(
1302
+ and(eq(roomTable.id, roomId), eq(roomTable.agentId, this.agentId))
1303
+ ).limit(1);
1304
+ if (result.length === 0) return null;
1305
+ return result[0];
1306
+ });
1307
+ }
1308
+ async getRooms(worldId) {
1309
+ return this.withDatabase(async () => {
1310
+ const result = await this.db.select().from(roomTable).where(eq(roomTable.worldId, worldId));
1311
+ return result;
1312
+ });
1313
+ }
1314
+ async updateRoom(room) {
1315
+ return this.withDatabase(async () => {
1316
+ await this.db.update(roomTable).set({ ...room, agentId: this.agentId }).where(eq(roomTable.id, room.id));
1317
+ });
1318
+ }
1319
+ async createRoom({
1320
+ id,
1321
+ name,
1322
+ source,
1323
+ type,
1324
+ channelId,
1325
+ serverId,
1326
+ worldId
1327
+ }) {
1328
+ return this.withDatabase(async () => {
1329
+ const newRoomId = id || v4();
1330
+ await this.db.insert(roomTable).values({
1331
+ id: newRoomId,
1332
+ name,
1333
+ agentId: this.agentId,
1334
+ source,
1335
+ type,
1336
+ channelId,
1337
+ serverId,
1338
+ worldId
1339
+ }).onConflictDoNothing({ target: roomTable.id });
1340
+ return newRoomId;
1341
+ });
1342
+ }
1343
+ async deleteRoom(roomId) {
1344
+ if (!roomId) throw new Error("Room ID is required");
1345
+ return this.withDatabase(async () => {
1346
+ await this.db.transaction(async (tx) => {
1347
+ await tx.delete(roomTable).where(eq(roomTable.id, roomId));
1348
+ });
1349
+ });
1350
+ }
1351
+ async getRoomsForParticipant(entityId) {
1352
+ return this.withDatabase(async () => {
1353
+ const result = await this.db.select({ roomId: participantTable.roomId }).from(participantTable).innerJoin(roomTable, eq(participantTable.roomId, roomTable.id)).where(
1354
+ and(
1355
+ eq(participantTable.entityId, entityId),
1356
+ eq(roomTable.agentId, this.agentId)
1357
+ )
1358
+ );
1359
+ return result.map((row) => row.roomId);
1360
+ });
1361
+ }
1362
+ async getRoomsForParticipants(entityIds) {
1363
+ return this.withDatabase(async () => {
1364
+ const result = await this.db.selectDistinct({ roomId: participantTable.roomId }).from(participantTable).innerJoin(roomTable, eq(participantTable.roomId, roomTable.id)).where(
1365
+ and(
1366
+ inArray(participantTable.entityId, entityIds),
1367
+ eq(roomTable.agentId, this.agentId)
1368
+ )
1369
+ );
1370
+ return result.map((row) => row.roomId);
1371
+ });
1372
+ }
1373
+ async addParticipant(entityId, roomId) {
1374
+ return this.withDatabase(async () => {
1375
+ try {
1376
+ await this.db.insert(participantTable).values({
1377
+ entityId,
1378
+ roomId,
1379
+ agentId: this.agentId
1380
+ }).onConflictDoNothing();
1381
+ return true;
1382
+ } catch (error) {
1383
+ logger.error("Error adding participant", {
1384
+ error: error instanceof Error ? error.message : String(error),
1385
+ entityId,
1386
+ roomId,
1387
+ agentId: this.agentId
1388
+ });
1389
+ return false;
1390
+ }
1391
+ });
1392
+ }
1393
+ async removeParticipant(entityId, roomId) {
1394
+ return this.withDatabase(async () => {
1395
+ try {
1396
+ const result = await this.db.transaction(async (tx) => {
1397
+ return await tx.delete(participantTable).where(
1398
+ and(
1399
+ eq(participantTable.entityId, entityId),
1400
+ eq(participantTable.roomId, roomId)
1401
+ )
1402
+ ).returning();
1403
+ });
1404
+ const removed = result.length > 0;
1405
+ logger.debug(`Participant ${removed ? "removed" : "not found"}:`, {
1406
+ entityId,
1407
+ roomId,
1408
+ removed
1409
+ });
1410
+ return removed;
1411
+ } catch (error) {
1412
+ logger.error("Failed to remove participant:", {
1413
+ error: error instanceof Error ? error.message : String(error),
1414
+ entityId,
1415
+ roomId
1416
+ });
1417
+ return false;
1418
+ }
1419
+ });
1420
+ }
1421
+ async getParticipantsForEntity(entityId) {
1422
+ return this.withDatabase(async () => {
1423
+ const result = await this.db.select({
1424
+ id: participantTable.id,
1425
+ entityId: participantTable.entityId,
1426
+ roomId: participantTable.roomId
1427
+ }).from(participantTable).where(eq(participantTable.entityId, entityId));
1428
+ const entity = await this.getEntityById(entityId);
1429
+ if (!entity) {
1430
+ return [];
1431
+ }
1432
+ return result.map((row) => ({
1433
+ id: row.id,
1434
+ entity
1435
+ }));
1436
+ });
1437
+ }
1438
+ async getParticipantsForRoom(roomId) {
1439
+ return this.withDatabase(async () => {
1440
+ const result = await this.db.select({ entityId: participantTable.entityId }).from(participantTable).where(
1441
+ and(
1442
+ eq(participantTable.roomId, roomId),
1443
+ eq(participantTable.agentId, this.agentId)
1444
+ )
1445
+ );
1446
+ return result.map((row) => row.entityId);
1447
+ });
1448
+ }
1449
+ async getParticipantUserState(roomId, entityId) {
1450
+ return this.withDatabase(async () => {
1451
+ const result = await this.db.select({ roomState: participantTable.roomState }).from(participantTable).where(
1452
+ and(
1453
+ eq(participantTable.roomId, roomId),
1454
+ eq(participantTable.entityId, entityId),
1455
+ eq(participantTable.agentId, this.agentId)
1456
+ )
1457
+ ).limit(1);
1458
+ return result[0]?.roomState ?? null;
1459
+ });
1460
+ }
1461
+ async setParticipantUserState(roomId, entityId, state) {
1462
+ return this.withDatabase(async () => {
1463
+ try {
1464
+ await this.db.transaction(async (tx) => {
1465
+ await tx.update(participantTable).set({ roomState: state }).where(
1466
+ and(
1467
+ eq(participantTable.roomId, roomId),
1468
+ eq(participantTable.entityId, entityId),
1469
+ eq(participantTable.agentId, this.agentId)
1470
+ )
1471
+ );
1472
+ });
1473
+ } catch (error) {
1474
+ logger.error("Failed to set participant user state:", {
1475
+ roomId,
1476
+ entityId,
1477
+ state,
1478
+ error: error instanceof Error ? error.message : String(error)
1479
+ });
1480
+ throw error;
1481
+ }
1482
+ });
1483
+ }
1484
+ async createRelationship(params) {
1485
+ return this.withDatabase(async () => {
1486
+ const id = v4();
1487
+ const saveParams = {
1488
+ id,
1489
+ sourceEntityId: params.sourceEntityId,
1490
+ targetEntityId: params.targetEntityId,
1491
+ agentId: this.agentId,
1492
+ tags: params.tags || [],
1493
+ metadata: params.metadata || {}
1494
+ };
1495
+ try {
1496
+ await this.db.insert(relationshipTable).values(saveParams);
1497
+ return true;
1498
+ } catch (error) {
1499
+ logger.error("Error creating relationship:", {
1500
+ error: error instanceof Error ? error.message : String(error),
1501
+ saveParams
1502
+ });
1503
+ return false;
1504
+ }
1505
+ });
1506
+ }
1507
+ async updateRelationship(relationship) {
1508
+ return this.withDatabase(async () => {
1509
+ try {
1510
+ await this.db.update(relationshipTable).set({
1511
+ tags: relationship.tags || [],
1512
+ metadata: relationship.metadata || {}
1513
+ }).where(eq(relationshipTable.id, relationship.id));
1514
+ } catch (error) {
1515
+ logger.error("Error updating relationship:", {
1516
+ error: error instanceof Error ? error.message : String(error),
1517
+ relationship
1518
+ });
1519
+ throw error;
1520
+ }
1521
+ });
1522
+ }
1523
+ async getRelationship(params) {
1524
+ return this.withDatabase(async () => {
1525
+ try {
1526
+ const result = await this.db.select().from(relationshipTable).where(
1527
+ and(
1528
+ eq(relationshipTable.sourceEntityId, params.sourceEntityId),
1529
+ eq(relationshipTable.targetEntityId, params.targetEntityId),
1530
+ eq(relationshipTable.agentId, this.agentId)
1531
+ )
1532
+ ).limit(1);
1533
+ if (result.length === 0) {
1534
+ return null;
1535
+ }
1536
+ return {
1537
+ id: result[0].id,
1538
+ sourceEntityId: result[0].sourceEntityId,
1539
+ targetEntityId: result[0].targetEntityId,
1540
+ agentId: result[0].agentId,
1541
+ tags: result[0].tags || [],
1542
+ metadata: result[0].metadata || {},
1543
+ createdAt: result[0].createdAt?.toString()
1544
+ };
1545
+ } catch (error) {
1546
+ logger.error("Error getting relationship:", {
1547
+ error: error instanceof Error ? error.message : String(error),
1548
+ params
1549
+ });
1550
+ return null;
1551
+ }
1552
+ });
1553
+ }
1554
+ async getRelationships(params) {
1555
+ return this.withDatabase(async () => {
1556
+ try {
1557
+ let query = this.db.select().from(relationshipTable).where(
1558
+ and(
1559
+ or(
1560
+ eq(relationshipTable.sourceEntityId, params.entityId),
1561
+ eq(relationshipTable.targetEntityId, params.entityId)
1562
+ ),
1563
+ eq(relationshipTable.agentId, this.agentId)
1564
+ )
1565
+ );
1566
+ if (params.tags && params.tags.length > 0) {
1567
+ const tagParams = params.tags.map((tag) => `'${tag.replace(/'/g, "''")}'`).join(", ");
1568
+ query = query.where(
1569
+ sql13`${relationshipTable.tags} @> ARRAY[${sql13.raw(tagParams)}]::text[]`
1570
+ );
1571
+ }
1572
+ const results = await query;
1573
+ return results.map((result) => ({
1574
+ id: result.id,
1575
+ sourceEntityId: result.sourceEntityId,
1576
+ targetEntityId: result.targetEntityId,
1577
+ agentId: result.agentId,
1578
+ tags: result.tags || [],
1579
+ metadata: result.metadata || {},
1580
+ createdAt: result.createdAt?.toString()
1581
+ }));
1582
+ } catch (error) {
1583
+ logger.error("Error getting relationships:", {
1584
+ error: error instanceof Error ? error.message : String(error),
1585
+ params
1586
+ });
1587
+ return [];
1588
+ }
1589
+ });
1590
+ }
1591
+ async getCache(key) {
1592
+ return this.withDatabase(async () => {
1593
+ try {
1594
+ const result = await this.db.select().from(cacheTable).where(
1595
+ and(eq(cacheTable.agentId, this.agentId), eq(cacheTable.key, key))
1596
+ );
1597
+ return result[0]?.value;
1598
+ } catch (error) {
1599
+ logger.error("Error fetching cache", {
1600
+ error: error instanceof Error ? error.message : String(error),
1601
+ key,
1602
+ agentId: this.agentId
1603
+ });
1604
+ return void 0;
1605
+ }
1606
+ });
1607
+ }
1608
+ async setCache(key, value) {
1609
+ return this.withDatabase(async () => {
1610
+ try {
1611
+ await this.db.transaction(async (tx) => {
1612
+ await tx.insert(cacheTable).values({
1613
+ key,
1614
+ agentId: this.agentId,
1615
+ value
1616
+ }).onConflictDoUpdate({
1617
+ target: [cacheTable.key, cacheTable.agentId],
1618
+ set: {
1619
+ value
1620
+ }
1621
+ });
1622
+ });
1623
+ return true;
1624
+ } catch (error) {
1625
+ logger.error("Error setting cache", {
1626
+ error: error instanceof Error ? error.message : String(error),
1627
+ key,
1628
+ agentId: this.agentId
1629
+ });
1630
+ return false;
1631
+ }
1632
+ });
1633
+ }
1634
+ async deleteCache(key) {
1635
+ return this.withDatabase(async () => {
1636
+ try {
1637
+ await this.db.transaction(async (tx) => {
1638
+ await tx.delete(cacheTable).where(
1639
+ and(
1640
+ eq(cacheTable.agentId, this.agentId),
1641
+ eq(cacheTable.key, key)
1642
+ )
1643
+ );
1644
+ });
1645
+ return true;
1646
+ } catch (error) {
1647
+ logger.error("Error deleting cache", {
1648
+ error: error instanceof Error ? error.message : String(error),
1649
+ key,
1650
+ agentId: this.agentId
1651
+ });
1652
+ return false;
1653
+ }
1654
+ });
1655
+ }
1656
+ async createWorld(world) {
1657
+ return this.withDatabase(async () => {
1658
+ const newWorldId = world.id || v4();
1659
+ await this.db.insert(worldTable).values({
1660
+ ...world,
1661
+ id: newWorldId
1662
+ });
1663
+ return newWorldId;
1664
+ });
1665
+ }
1666
+ async getWorld(id) {
1667
+ return this.withDatabase(async () => {
1668
+ const result = await this.db.select().from(worldTable).where(eq(worldTable.id, id));
1669
+ return result[0];
1670
+ });
1671
+ }
1672
+ async getAllWorlds() {
1673
+ return this.withDatabase(async () => {
1674
+ const result = await this.db.select().from(worldTable).where(eq(worldTable.agentId, this.agentId));
1675
+ return result;
1676
+ });
1677
+ }
1678
+ async updateWorld(world) {
1679
+ return this.withDatabase(async () => {
1680
+ await this.db.update(worldTable).set(world).where(eq(worldTable.id, world.id));
1681
+ });
1682
+ }
1683
+ async removeWorld(id) {
1684
+ return this.withDatabase(async () => {
1685
+ await this.db.delete(worldTable).where(eq(worldTable.id, id));
1686
+ });
1687
+ }
1688
+ /**
1689
+ * Creates a new task in the database.
1690
+ * @param task The task object to create
1691
+ * @returns Promise resolving to the UUID of the created task
1692
+ */
1693
+ async createTask(task) {
1694
+ return this.withRetry(async () => {
1695
+ return this.withDatabase(async () => {
1696
+ const now = /* @__PURE__ */ new Date();
1697
+ const metadata = task.metadata || {};
1698
+ const values = {
1699
+ id: task.id,
1700
+ name: task.name,
1701
+ description: task.description,
1702
+ roomId: task.roomId,
1703
+ worldId: task.worldId,
1704
+ tags: task.tags,
1705
+ metadata,
1706
+ createdAt: now,
1707
+ updatedAt: now,
1708
+ agentId: this.agentId
1709
+ };
1710
+ const result = await this.db.insert(taskTable).values(values).returning({ id: taskTable.id });
1711
+ return result[0].id;
1712
+ });
1713
+ });
1714
+ }
1715
+ /**
1716
+ * Retrieves tasks based on specified parameters.
1717
+ * @param params Object containing optional roomId and tags to filter tasks
1718
+ * @returns Promise resolving to an array of Task objects
1719
+ */
1720
+ async getTasks(params) {
1721
+ return this.withRetry(async () => {
1722
+ return this.withDatabase(async () => {
1723
+ let query = this.db.select().from(taskTable).where(eq(taskTable.agentId, this.agentId));
1724
+ if (params.roomId) {
1725
+ query = query.where(eq(taskTable.roomId, params.roomId));
1726
+ }
1727
+ if (params.tags && params.tags.length > 0) {
1728
+ const tagParams = params.tags.map((tag) => `'${tag.replace(/'/g, "''")}'`).join(", ");
1729
+ query = query.where(
1730
+ sql13`${taskTable.tags} @> ARRAY[${sql13.raw(tagParams)}]::text[]`
1731
+ );
1732
+ }
1733
+ const result = await query;
1734
+ return result.map((row) => ({
1735
+ id: row.id,
1736
+ name: row.name,
1737
+ description: row.description,
1738
+ roomId: row.roomId,
1739
+ worldId: row.worldId,
1740
+ tags: row.tags,
1741
+ metadata: row.metadata
1742
+ }));
1743
+ });
1744
+ });
1745
+ }
1746
+ /**
1747
+ * Retrieves a specific task by its name.
1748
+ * @param name The name of the task to retrieve
1749
+ * @returns Promise resolving to the Task object if found, null otherwise
1750
+ */
1751
+ async getTasksByName(name) {
1752
+ return this.withRetry(async () => {
1753
+ return this.withDatabase(async () => {
1754
+ const result = await this.db.select().from(taskTable).where(
1755
+ and(eq(taskTable.name, name), eq(taskTable.agentId, this.agentId))
1756
+ );
1757
+ return result.map((row) => ({
1758
+ id: row.id,
1759
+ name: row.name,
1760
+ description: row.description,
1761
+ roomId: row.roomId,
1762
+ worldId: row.worldId,
1763
+ tags: row.tags || [],
1764
+ metadata: row.metadata || {}
1765
+ }));
1766
+ });
1767
+ });
1768
+ }
1769
+ /**
1770
+ * Retrieves a specific task by its ID.
1771
+ * @param id The UUID of the task to retrieve
1772
+ * @returns Promise resolving to the Task object if found, null otherwise
1773
+ */
1774
+ async getTask(id) {
1775
+ return this.withRetry(async () => {
1776
+ return this.withDatabase(async () => {
1777
+ const result = await this.db.select().from(taskTable).where(and(eq(taskTable.id, id), eq(taskTable.agentId, this.agentId))).limit(1);
1778
+ if (result.length === 0) {
1779
+ return null;
1780
+ }
1781
+ const row = result[0];
1782
+ return {
1783
+ id: row.id,
1784
+ name: row.name,
1785
+ description: row.description,
1786
+ roomId: row.roomId,
1787
+ worldId: row.worldId,
1788
+ tags: row.tags || [],
1789
+ metadata: row.metadata || {}
1790
+ };
1791
+ });
1792
+ });
1793
+ }
1794
+ /**
1795
+ * Updates an existing task in the database.
1796
+ * @param id The UUID of the task to update
1797
+ * @param task Partial Task object containing the fields to update
1798
+ * @returns Promise resolving when the update is complete
1799
+ */
1800
+ async updateTask(id, task) {
1801
+ await this.withRetry(async () => {
1802
+ await this.withDatabase(async () => {
1803
+ const updateValues = {};
1804
+ if (task.name !== void 0) updateValues.name = task.name;
1805
+ if (task.description !== void 0)
1806
+ updateValues.description = task.description;
1807
+ if (task.roomId !== void 0) updateValues.roomId = task.roomId;
1808
+ if (task.worldId !== void 0) updateValues.worldId = task.worldId;
1809
+ if (task.tags !== void 0) updateValues.tags = task.tags;
1810
+ task.updatedAt = Date.now();
1811
+ if (task.metadata) {
1812
+ const currentTask = await this.getTask(id);
1813
+ if (currentTask) {
1814
+ const currentMetadata = currentTask.metadata || {};
1815
+ const newMetadata = {
1816
+ ...currentMetadata,
1817
+ ...task.metadata
1818
+ };
1819
+ updateValues.metadata = newMetadata;
1820
+ } else {
1821
+ updateValues.metadata = {
1822
+ ...task.metadata
1823
+ };
1824
+ }
1825
+ }
1826
+ await this.db.update(taskTable).set(updateValues).where(
1827
+ and(eq(taskTable.id, id), eq(taskTable.agentId, this.agentId))
1828
+ );
1829
+ });
1830
+ });
1831
+ }
1832
+ /**
1833
+ * Deletes a task from the database.
1834
+ * @param id The UUID of the task to delete
1835
+ * @returns Promise resolving when the deletion is complete
1836
+ */
1837
+ async deleteTask(id) {
1838
+ await this.withRetry(async () => {
1839
+ await this.withDatabase(async () => {
1840
+ await this.db.delete(taskTable).where(
1841
+ and(eq(taskTable.id, id), eq(taskTable.agentId, this.agentId))
1842
+ );
1843
+ });
1844
+ });
1845
+ }
1846
+ };
1847
+
1848
+ // src/pg-lite/adapter.ts
1849
+ var PgliteDatabaseAdapter = class extends BaseDrizzleAdapter {
1850
+ manager;
1851
+ embeddingDimension = DIMENSION_MAP[384];
1852
+ constructor(agentId, manager) {
1853
+ super(agentId);
1854
+ this.manager = manager;
1855
+ this.db = drizzle(this.manager.getConnection());
1856
+ }
1857
+ async withDatabase(operation) {
1858
+ if (this.manager.isShuttingDown()) {
1859
+ logger2.warn("Database is shutting down");
1860
+ return null;
1861
+ }
1862
+ return operation();
1863
+ }
1864
+ async init() {
1865
+ try {
1866
+ await this.manager.runMigrations();
1867
+ } catch (error) {
1868
+ logger2.error("Failed to initialize database:", error);
1869
+ throw error;
1870
+ }
1871
+ }
1872
+ async close() {
1873
+ await this.manager.close();
1874
+ }
1875
+ };
1876
+
1877
+ // src/pg-lite/manager.ts
1878
+ import { PGlite } from "@electric-sql/pglite";
1879
+ import { vector as vector3 } from "@electric-sql/pglite/vector";
1880
+ import { fuzzystrmatch } from "@electric-sql/pglite/contrib/fuzzystrmatch";
1881
+ import { logger as logger3 } from "@elizaos/core";
1882
+ import { migrate } from "drizzle-orm/pglite/migrator";
1883
+ import { fileURLToPath } from "node:url";
1884
+ import path from "node:path";
1885
+ import { drizzle as drizzle2 } from "drizzle-orm/pglite";
1886
+ var __filename = fileURLToPath(import.meta.url);
1887
+ var __dirname = path.dirname(__filename);
1888
+ var PGliteClientManager = class {
1889
+ client;
1890
+ shuttingDown = false;
1891
+ shutdownTimeout = 800;
1892
+ constructor(options) {
1893
+ this.client = new PGlite({
1894
+ ...options,
1895
+ extensions: {
1896
+ vector: vector3,
1897
+ fuzzystrmatch
1898
+ }
1899
+ });
1900
+ this.setupShutdownHandlers();
1901
+ }
1902
+ getConnection() {
1903
+ if (this.shuttingDown) {
1904
+ throw new Error("Client manager is shutting down");
1905
+ }
1906
+ return this.client;
1907
+ }
1908
+ async gracefulShutdown() {
1909
+ if (this.shuttingDown) {
1910
+ return;
1911
+ }
1912
+ this.shuttingDown = true;
1913
+ logger3.info("Starting graceful shutdown of PGlite client...");
1914
+ const timeout = setTimeout(() => {
1915
+ logger3.warn(
1916
+ "Shutdown timeout reached, forcing database connection closure..."
1917
+ );
1918
+ this.client.close().finally(() => {
1919
+ process.exit(1);
1920
+ });
1921
+ }, this.shutdownTimeout);
1922
+ try {
1923
+ await new Promise((resolve) => setTimeout(resolve, this.shutdownTimeout));
1924
+ await this.client.close();
1925
+ clearTimeout(timeout);
1926
+ logger3.info("PGlite client shutdown completed successfully");
1927
+ process.exit(0);
1928
+ } catch (error) {
1929
+ logger3.error("Error during graceful shutdown:", error);
1930
+ process.exit(1);
1931
+ }
1932
+ }
1933
+ setupShutdownHandlers() {
1934
+ process.on("SIGINT", async () => {
1935
+ await this.gracefulShutdown();
1936
+ });
1937
+ process.on("SIGTERM", async () => {
1938
+ await this.gracefulShutdown();
1939
+ });
1940
+ process.on("beforeExit", async () => {
1941
+ await this.gracefulShutdown();
1942
+ });
1943
+ }
1944
+ async initialize() {
1945
+ try {
1946
+ await this.client.waitReady;
1947
+ logger3.info("PGlite client initialized successfully");
1948
+ } catch (error) {
1949
+ logger3.error("Failed to initialize PGlite client:", error);
1950
+ throw error;
1951
+ }
1952
+ }
1953
+ async close() {
1954
+ if (!this.shuttingDown) {
1955
+ await this.gracefulShutdown();
1956
+ }
1957
+ }
1958
+ isShuttingDown() {
1959
+ return this.shuttingDown;
1960
+ }
1961
+ async runMigrations() {
1962
+ try {
1963
+ const db = drizzle2(this.client);
1964
+ await migrate(db, {
1965
+ migrationsFolder: path.resolve(__dirname, "../drizzle/migrations")
1966
+ });
1967
+ logger3.info("Migrations completed successfully!");
1968
+ } catch (error) {
1969
+ logger3.error("Failed to run database migrations:", error);
1970
+ }
1971
+ }
1972
+ };
1973
+
1974
+ // src/pg/adapter.ts
1975
+ import { logger as logger4 } from "@elizaos/core";
1976
+ import { drizzle as drizzle3 } from "drizzle-orm/node-postgres";
1977
+ var PgDatabaseAdapter = class extends BaseDrizzleAdapter {
1978
+ constructor(agentId, manager) {
1979
+ super(agentId);
1980
+ this.manager = manager;
1981
+ this.manager = manager;
1982
+ }
1983
+ embeddingDimension = DIMENSION_MAP[384];
1984
+ async withDatabase(operation) {
1985
+ return await this.withRetry(async () => {
1986
+ const client = await this.manager.getClient();
1987
+ try {
1988
+ const db = drizzle3(client);
1989
+ this.db = db;
1990
+ return await operation();
1991
+ } finally {
1992
+ client.release();
1993
+ }
1994
+ });
1995
+ }
1996
+ async init() {
1997
+ try {
1998
+ await this.manager.runMigrations();
1999
+ logger4.info("PgDatabaseAdapter initialized successfully");
2000
+ } catch (error) {
2001
+ logger4.error("Failed to initialize PgDatabaseAdapter:", error);
2002
+ throw error;
2003
+ }
2004
+ }
2005
+ async close() {
2006
+ await this.manager.close();
2007
+ }
2008
+ };
2009
+
2010
+ // src/pg/manager.ts
2011
+ import pkg from "pg";
2012
+ import { logger as logger5 } from "@elizaos/core";
2013
+ import { migrate as migrate2 } from "drizzle-orm/node-postgres/migrator";
2014
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
2015
+ import path2 from "node:path";
2016
+ import { drizzle as drizzle4 } from "drizzle-orm/node-postgres";
2017
+ var { Pool } = pkg;
2018
+ var __filename2 = fileURLToPath2(import.meta.url);
2019
+ var __dirname2 = path2.dirname(__filename2);
2020
+ var PostgresConnectionManager = class {
2021
+ pool;
2022
+ isShuttingDown = false;
2023
+ connectionTimeout = 5e3;
2024
+ constructor(connectionString) {
2025
+ const defaultConfig = {
2026
+ max: 20,
2027
+ idleTimeoutMillis: 3e4,
2028
+ connectionTimeoutMillis: this.connectionTimeout
2029
+ };
2030
+ this.pool = new Pool({
2031
+ ...defaultConfig,
2032
+ connectionString
2033
+ });
2034
+ this.pool.on("error", (err) => {
2035
+ logger5.error("Unexpected pool error", err);
2036
+ this.handlePoolError(err);
2037
+ });
2038
+ this.setupPoolErrorHandling();
2039
+ this.testConnection();
2040
+ }
2041
+ async handlePoolError(error) {
2042
+ logger5.error("Pool error occurred, attempting to reconnect", {
2043
+ error: error.message
2044
+ });
2045
+ try {
2046
+ await this.pool.end();
2047
+ this.pool = new Pool({
2048
+ ...this.pool.options,
2049
+ connectionTimeoutMillis: this.connectionTimeout
2050
+ });
2051
+ await this.testConnection();
2052
+ logger5.success("Pool reconnection successful");
2053
+ } catch (reconnectError) {
2054
+ logger5.error("Failed to reconnect pool", {
2055
+ error: reconnectError instanceof Error ? reconnectError.message : String(reconnectError)
2056
+ });
2057
+ throw reconnectError;
2058
+ }
2059
+ }
2060
+ async testConnection() {
2061
+ let client;
2062
+ try {
2063
+ client = await this.pool.connect();
2064
+ const result = await client.query("SELECT NOW()");
2065
+ logger5.success("Database connection test successful:", result.rows[0]);
2066
+ return true;
2067
+ } catch (error) {
2068
+ logger5.error("Database connection test failed:", error);
2069
+ throw new Error(
2070
+ `Failed to connect to database: ${error.message}`
2071
+ );
2072
+ } finally {
2073
+ if (client) client.release();
2074
+ }
2075
+ }
2076
+ setupPoolErrorHandling() {
2077
+ process.on("SIGINT", async () => {
2078
+ await this.cleanup();
2079
+ process.exit(0);
2080
+ });
2081
+ process.on("SIGTERM", async () => {
2082
+ await this.cleanup();
2083
+ process.exit(0);
2084
+ });
2085
+ process.on("beforeExit", async () => {
2086
+ await this.cleanup();
2087
+ });
2088
+ }
2089
+ getConnection() {
2090
+ if (this.isShuttingDown) {
2091
+ throw new Error("Connection manager is shutting down");
2092
+ }
2093
+ try {
2094
+ return this.pool;
2095
+ } catch (error) {
2096
+ logger5.error("Failed to get connection from pool:", error);
2097
+ throw error;
2098
+ }
2099
+ }
2100
+ async getClient() {
2101
+ try {
2102
+ return await this.pool.connect();
2103
+ } catch (error) {
2104
+ logger5.error("Failed to acquire a database client:", error);
2105
+ throw error;
2106
+ }
2107
+ }
2108
+ async initialize() {
2109
+ try {
2110
+ await this.testConnection();
2111
+ logger5.info("PostgreSQL connection manager initialized successfully");
2112
+ } catch (error) {
2113
+ logger5.error("Failed to initialize connection manager:", error);
2114
+ throw error;
2115
+ }
2116
+ }
2117
+ async close() {
2118
+ await this.cleanup();
2119
+ }
2120
+ async cleanup() {
2121
+ try {
2122
+ await this.pool.end();
2123
+ logger5.info("Database pool closed");
2124
+ } catch (error) {
2125
+ logger5.error("Error closing database pool:", error);
2126
+ }
2127
+ }
2128
+ async runMigrations() {
2129
+ try {
2130
+ const db = drizzle4(this.pool);
2131
+ await migrate2(db, {
2132
+ migrationsFolder: path2.resolve(__dirname2, "../drizzle/migrations")
2133
+ });
2134
+ logger5.info("Migrations completed successfully!");
2135
+ } catch (error) {
2136
+ logger5.error("Failed to run database migrations:", error);
2137
+ }
2138
+ }
2139
+ };
2140
+
2141
+ // src/index.ts
2142
+ var pgLiteClientManager;
2143
+ function createDatabaseAdapter(config, agentId) {
2144
+ if (config.postgresUrl) {
2145
+ const manager = new PostgresConnectionManager(config.postgresUrl);
2146
+ return new PgDatabaseAdapter(agentId, manager);
2147
+ }
2148
+ const dataDir = config.dataDir ?? "../../pgLite";
2149
+ if (!pgLiteClientManager) {
2150
+ pgLiteClientManager = new PGliteClientManager({ dataDir });
2151
+ }
2152
+ return new PgliteDatabaseAdapter(agentId, pgLiteClientManager);
2153
+ }
2154
+ var drizzlePlugin = {
2155
+ name: "drizzle",
2156
+ description: "Database adapter plugin using Drizzle ORM",
2157
+ init: async (_, runtime) => {
2158
+ const config = {
2159
+ dataDir: runtime.getSetting("PGLITE_DATA_DIR"),
2160
+ postgresUrl: runtime.getSetting("POSTGRES_URL")
2161
+ };
2162
+ try {
2163
+ const db = createDatabaseAdapter(config, runtime.agentId);
2164
+ logger6.success("Database connection established successfully");
2165
+ runtime.registerDatabaseAdapter(db);
2166
+ } catch (error) {
2167
+ logger6.error("Failed to initialize database:", error);
2168
+ throw error;
2169
+ }
2170
+ }
2171
+ };
2172
+ var index_default = drizzlePlugin;
2173
+ export {
2174
+ createDatabaseAdapter,
2175
+ index_default as default
2176
+ };
2177
+ //# sourceMappingURL=index.js.map