@elizaos/plugin-sql 1.0.0-beta.3 → 1.0.0-beta.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Shaw Walters, aka Moon aka @lalalune
3
+ Copyright (c) 2025 Shaw Walters and elizaOS Contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ import { v4 } from "uuid";
34
34
  // src/schema/embedding.ts
35
35
  import { sql as sql6 } from "drizzle-orm";
36
36
  import { check as check2, foreignKey as foreignKey2, index as index2, pgTable as pgTable6, uuid as uuid6, vector as vector2 } from "drizzle-orm/pg-core";
37
+ import { VECTOR_DIMS } from "@elizaos/core";
37
38
 
38
39
  // src/schema/memory.ts
39
40
  import { relations, sql as sql5 } from "drizzle-orm";
@@ -232,14 +233,6 @@ var memoryRelations = relations(memoryTable, ({ one }) => ({
232
233
  }));
233
234
 
234
235
  // src/schema/embedding.ts
235
- var VECTOR_DIMS = {
236
- SMALL: 384,
237
- MEDIUM: 512,
238
- LARGE: 768,
239
- XL: 1024,
240
- XXL: 1536,
241
- XXXL: 3072
242
- };
243
236
  var DIMENSION_MAP = {
244
237
  [VECTOR_DIMS.SMALL]: "dim384",
245
238
  [VECTOR_DIMS.MEDIUM]: "dim512",
@@ -484,9 +477,12 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
484
477
  const existingAgent = agents.find(
485
478
  (a) => a.name === agent.name
486
479
  );
487
- if (!existingAgent) {
488
- await this.createAgent(agent);
480
+ if (existingAgent) {
481
+ return existingAgent;
489
482
  }
483
+ agent.id = agent.id || v4();
484
+ await this.createAgent(agent);
485
+ return agent;
490
486
  }
491
487
  /**
492
488
  * Asynchronously ensures that the given embedding dimension is valid for the agent.
@@ -565,10 +561,13 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
565
561
  async updateAgent(agentId, agent) {
566
562
  return this.withDatabase(async () => {
567
563
  try {
568
- if (!agent.id) {
564
+ if (!agentId) {
569
565
  throw new Error("Agent ID is required for update");
570
566
  }
571
567
  await this.db.transaction(async (tx) => {
568
+ if (agent?.settings) {
569
+ agent.settings = await this.mergeAgentSettings(tx, agentId, agent.settings);
570
+ }
572
571
  await tx.update(agentTable).set({
573
572
  ...agent,
574
573
  updatedAt: Date.now()
@@ -588,6 +587,39 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
588
587
  }
589
588
  });
590
589
  }
590
+ /**
591
+ * Merges updated agent settings with existing settings in the database,
592
+ * with special handling for nested objects like secrets.
593
+ * @param tx - The database transaction
594
+ * @param agentId - The ID of the agent
595
+ * @param updatedSettings - The settings object with updates
596
+ * @returns The merged settings object
597
+ * @private
598
+ */
599
+ async mergeAgentSettings(tx, agentId, updatedSettings) {
600
+ const currentAgent = await tx.select({ settings: agentTable.settings }).from(agentTable).where(eq(agentTable.id, agentId)).limit(1);
601
+ if (currentAgent.length === 0 || !currentAgent[0].settings) {
602
+ return updatedSettings;
603
+ }
604
+ const currentSettings = currentAgent[0].settings;
605
+ if (updatedSettings.secrets) {
606
+ const currentSecrets = currentSettings.secrets || {};
607
+ const updatedSecrets = updatedSettings.secrets;
608
+ const mergedSecrets = { ...currentSecrets };
609
+ for (const [key, value] of Object.entries(updatedSecrets)) {
610
+ if (value === null) {
611
+ delete mergedSecrets[key];
612
+ } else {
613
+ mergedSecrets[key] = value;
614
+ }
615
+ }
616
+ updatedSettings.secrets = mergedSecrets;
617
+ }
618
+ return {
619
+ ...currentSettings,
620
+ ...updatedSettings
621
+ };
622
+ }
591
623
  /**
592
624
  * Asynchronously deletes an agent with the specified UUID and all related entries.
593
625
  *
@@ -595,11 +627,161 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
595
627
  * @returns {Promise<boolean>} - A boolean indicating if the deletion was successful.
596
628
  */
597
629
  async deleteAgent(agentId) {
630
+ logger.debug(`[DB] Starting deletion of agent with ID: ${agentId}`);
598
631
  return this.withDatabase(async () => {
599
- await this.db.transaction(async (tx) => {
600
- await tx.delete(agentTable).where(eq(agentTable.id, agentId));
601
- });
602
- return true;
632
+ try {
633
+ logger.debug(`[DB] Beginning database transaction for deleting agent: ${agentId}`);
634
+ const deletePromise = new Promise((resolve, reject) => {
635
+ const timeoutId = setTimeout(() => {
636
+ logger.error(`[DB] Transaction timeout reached for agent deletion: ${agentId}`);
637
+ reject(new Error("Database transaction timeout"));
638
+ }, 3e4);
639
+ this.db.transaction(async (tx) => {
640
+ try {
641
+ logger.debug(`[DB] Fetching entities for agent: ${agentId}`);
642
+ const entities = await tx.select({ entityId: entityTable.id }).from(entityTable).where(eq(entityTable.agentId, agentId));
643
+ const entityIds = entities.map((e) => e.entityId);
644
+ logger.debug(
645
+ `[DB] Found ${entityIds.length} entities to delete for agent ${agentId}`
646
+ );
647
+ logger.debug(`[DB] Fetching rooms for agent: ${agentId}`);
648
+ const rooms = await tx.select({ roomId: roomTable.id }).from(roomTable).where(eq(roomTable.agentId, agentId));
649
+ const roomIds = rooms.map((r) => r.roomId);
650
+ logger.debug(`[DB] Found ${roomIds.length} rooms for agent ${agentId}`);
651
+ logger.debug(
652
+ `[DB] Explicitly deleting ALL logs with matching entityIds and roomIds`
653
+ );
654
+ if (entityIds.length > 0) {
655
+ logger.debug(`[DB] Deleting logs for ${entityIds.length} entities (first batch)`);
656
+ const BATCH_SIZE = 50;
657
+ for (let i = 0; i < entityIds.length; i += BATCH_SIZE) {
658
+ const batch = entityIds.slice(i, i + BATCH_SIZE);
659
+ logger.debug(
660
+ `[DB] Processing entity logs batch ${i / BATCH_SIZE + 1} with ${batch.length} entities`
661
+ );
662
+ await tx.delete(logTable).where(inArray(logTable.entityId, batch));
663
+ }
664
+ logger.debug(`[DB] Entity logs deletion completed successfully`);
665
+ }
666
+ if (roomIds.length > 0) {
667
+ logger.debug(`[DB] Deleting logs for ${roomIds.length} rooms (first batch)`);
668
+ const BATCH_SIZE = 50;
669
+ for (let i = 0; i < roomIds.length; i += BATCH_SIZE) {
670
+ const batch = roomIds.slice(i, i + BATCH_SIZE);
671
+ logger.debug(
672
+ `[DB] Processing room logs batch ${i / BATCH_SIZE + 1} with ${batch.length} rooms`
673
+ );
674
+ await tx.delete(logTable).where(inArray(logTable.roomId, batch));
675
+ }
676
+ logger.debug(`[DB] Room logs deletion completed successfully`);
677
+ }
678
+ let memoryIds = [];
679
+ if (entityIds.length > 0) {
680
+ logger.debug(`[DB] Finding memories belonging to entities`);
681
+ const memories = await tx.select({ id: memoryTable.id }).from(memoryTable).where(inArray(memoryTable.entityId, entityIds));
682
+ memoryIds = memories.map((m) => m.id);
683
+ logger.debug(`[DB] Found ${memoryIds.length} memories belonging to entities`);
684
+ }
685
+ logger.debug(`[DB] Finding memories belonging to agent directly`);
686
+ const agentMemories = await tx.select({ id: memoryTable.id }).from(memoryTable).where(eq(memoryTable.agentId, agentId));
687
+ memoryIds = [...memoryIds, ...agentMemories.map((m) => m.id)];
688
+ logger.debug(`[DB] Found total of ${memoryIds.length} memories to delete`);
689
+ if (roomIds.length > 0) {
690
+ logger.debug(`[DB] Finding memories belonging to rooms`);
691
+ const roomMemories = await tx.select({ id: memoryTable.id }).from(memoryTable).where(inArray(memoryTable.roomId, roomIds));
692
+ memoryIds = [...memoryIds, ...roomMemories.map((m) => m.id)];
693
+ logger.debug(`[DB] Updated total to ${memoryIds.length} memories to delete`);
694
+ }
695
+ if (memoryIds.length > 0) {
696
+ logger.debug(`[DB] Deleting embeddings for ${memoryIds.length} memories`);
697
+ const BATCH_SIZE = 100;
698
+ for (let i = 0; i < memoryIds.length; i += BATCH_SIZE) {
699
+ const batch = memoryIds.slice(i, i + BATCH_SIZE);
700
+ await tx.delete(embeddingTable).where(inArray(embeddingTable.memoryId, batch));
701
+ }
702
+ logger.debug(`[DB] Embeddings deleted successfully`);
703
+ }
704
+ if (memoryIds.length > 0) {
705
+ logger.debug(`[DB] Deleting ${memoryIds.length} memories`);
706
+ const BATCH_SIZE = 100;
707
+ for (let i = 0; i < memoryIds.length; i += BATCH_SIZE) {
708
+ const batch = memoryIds.slice(i, i + BATCH_SIZE);
709
+ await tx.delete(memoryTable).where(inArray(memoryTable.id, batch));
710
+ }
711
+ logger.debug(`[DB] Memories deleted successfully`);
712
+ }
713
+ if (entityIds.length > 0) {
714
+ logger.debug(`[DB] Deleting components for entities`);
715
+ await tx.delete(componentTable).where(inArray(componentTable.entityId, entityIds));
716
+ logger.debug(`[DB] Components deleted successfully`);
717
+ }
718
+ if (entityIds.length > 0) {
719
+ logger.debug(`[DB] Deleting source entity references in components`);
720
+ await tx.delete(componentTable).where(inArray(componentTable.sourceEntityId, entityIds));
721
+ logger.debug(`[DB] Source entity references deleted successfully`);
722
+ }
723
+ if (roomIds.length > 0) {
724
+ logger.debug(`[DB] Deleting participations for rooms`);
725
+ await tx.delete(participantTable).where(inArray(participantTable.roomId, roomIds));
726
+ logger.debug(`[DB] Participations deleted for rooms`);
727
+ }
728
+ logger.debug(`[DB] Deleting agent participations`);
729
+ await tx.delete(participantTable).where(eq(participantTable.agentId, agentId));
730
+ logger.debug(`[DB] Agent participations deleted`);
731
+ if (roomIds.length > 0) {
732
+ logger.debug(`[DB] Deleting rooms`);
733
+ await tx.delete(roomTable).where(inArray(roomTable.id, roomIds));
734
+ logger.debug(`[DB] Rooms deleted successfully`);
735
+ }
736
+ logger.debug(`[DB] Deleting cache entries`);
737
+ await tx.delete(cacheTable).where(eq(cacheTable.agentId, agentId));
738
+ logger.debug(`[DB] Cache entries deleted successfully`);
739
+ logger.debug(`[DB] Deleting relationships`);
740
+ if (entityIds.length > 0) {
741
+ await tx.delete(relationshipTable).where(inArray(relationshipTable.sourceEntityId, entityIds));
742
+ await tx.delete(relationshipTable).where(inArray(relationshipTable.targetEntityId, entityIds));
743
+ }
744
+ await tx.delete(relationshipTable).where(eq(relationshipTable.agentId, agentId));
745
+ logger.debug(`[DB] Relationships deleted successfully`);
746
+ if (entityIds.length > 0) {
747
+ logger.debug(`[DB] Deleting entities`);
748
+ await tx.delete(entityTable).where(eq(entityTable.agentId, agentId));
749
+ logger.debug(`[DB] Entities deleted successfully`);
750
+ }
751
+ logger.debug(`[DB] Checking for world references`);
752
+ const worlds = await tx.select({ id: worldTable.id }).from(worldTable).where(eq(worldTable.agentId, agentId));
753
+ if (worlds.length > 0) {
754
+ const worldIds = worlds.map((w) => w.id);
755
+ logger.debug(`[DB] Found ${worldIds.length} worlds to delete`);
756
+ await tx.delete(worldTable).where(inArray(worldTable.id, worldIds));
757
+ logger.debug(`[DB] Worlds deleted successfully`);
758
+ } else {
759
+ logger.debug(`[DB] No worlds found for this agent`);
760
+ }
761
+ logger.debug(`[DB] Deleting agent ${agentId}`);
762
+ await tx.delete(agentTable).where(eq(agentTable.id, agentId));
763
+ logger.debug(`[DB] Agent deleted successfully`);
764
+ resolve(true);
765
+ } catch (error) {
766
+ logger.error(`[DB] Error in transaction:`, error);
767
+ reject(error);
768
+ }
769
+ }).catch((transactionError) => {
770
+ clearTimeout(timeoutId);
771
+ reject(transactionError);
772
+ });
773
+ });
774
+ await deletePromise;
775
+ logger.success(`[DB] Agent ${agentId} successfully deleted`);
776
+ return true;
777
+ } catch (error) {
778
+ logger.error(`[DB] Error in database transaction for agent deletion ${agentId}:`, error);
779
+ if (error instanceof Error) {
780
+ logger.error(`[DB] Error name: ${error.name}, message: ${error.message}`);
781
+ logger.error(`[DB] Error stack: ${error.stack}`);
782
+ }
783
+ throw error;
784
+ }
603
785
  });
604
786
  }
605
787
  /**
@@ -651,7 +833,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
651
833
  const result = await this.db.select({
652
834
  entity: entityTable,
653
835
  components: componentTable
654
- }).from(entityTable).leftJoin(componentTable, eq(componentTable.entityId, entityTable.id)).where(and(eq(entityTable.id, entityId), eq(entityTable.agentId, this.agentId)));
836
+ }).from(entityTable).leftJoin(componentTable, eq(componentTable.entityId, entityTable.id)).where(eq(entityTable.id, entityId));
655
837
  if (result.length === 0) return null;
656
838
  const entity = result[0].entity;
657
839
  entity.components = result.filter((row) => row.components).map((row) => row.components);
@@ -1205,6 +1387,14 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1205
1387
  embeddingLength: memory.embedding?.length,
1206
1388
  contentLength: memory.content?.text?.length
1207
1389
  });
1390
+ const memoryId = memory.id ?? v4();
1391
+ const existing = await this.getMemoryById(memoryId);
1392
+ if (existing) {
1393
+ logger.debug("Memory already exists, skipping creation:", {
1394
+ memoryId
1395
+ });
1396
+ return memoryId;
1397
+ }
1208
1398
  let isUnique = true;
1209
1399
  if (memory.embedding && Array.isArray(memory.embedding)) {
1210
1400
  const similarMemories = await this.searchMemoriesByEmbedding(memory.embedding, {
@@ -1216,7 +1406,6 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1216
1406
  isUnique = similarMemories.length === 0;
1217
1407
  }
1218
1408
  const contentToInsert = typeof memory.content === "string" ? JSON.parse(memory.content) : memory.content;
1219
- const memoryId = memory.id ?? v4();
1220
1409
  await this.db.transaction(async (tx) => {
1221
1410
  await tx.insert(memoryTable).values([
1222
1411
  {
@@ -1447,6 +1636,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1447
1636
  async createRoom({
1448
1637
  id,
1449
1638
  name,
1639
+ agentId,
1450
1640
  source,
1451
1641
  type,
1452
1642
  channelId,
@@ -1459,7 +1649,7 @@ var BaseDrizzleAdapter = class extends DatabaseAdapter {
1459
1649
  await this.db.insert(roomTable).values({
1460
1650
  id: newRoomId,
1461
1651
  name,
1462
- agentId: this.agentId,
1652
+ agentId,
1463
1653
  source,
1464
1654
  type,
1465
1655
  channelId,