@elizaos/plugin-sql 1.0.0-beta.44 → 1.0.0-beta.46

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 CHANGED
@@ -1,27 +1,1223 @@
1
- import{a as x,b as ge,c as ye}from"./chunk-K7ZVMPCJ.js";import*as ke from"node:os";import{logger as Le}from"@elizaos/core";import{logger as Ce}from"@elizaos/core";import{drizzle as Bt}from"drizzle-orm/pglite";import{DatabaseAdapter as _t,logger as o,stringToUuid as Pt}from"@elizaos/core";import{and as w,cosineDistance as Nt,count as Mt,desc as z,eq as n,gte as xe,inArray as D,lte as St,or as vt,sql as M,not as qt}from"drizzle-orm";import{v4 as O}from"uuid";import{sql as Ee}from"drizzle-orm";import{check as rt,foreignKey as nt,index as it,pgTable as at,uuid as Te,vector as F}from"drizzle-orm/pg-core";import{VECTOR_DIMS as v}from"@elizaos/core";import{relations as Ye,sql as k}from"drizzle-orm";import{boolean as Qe,check as De,foreignKey as V,index as G,jsonb as Ue,pgTable as et,text as tt,uuid as H}from"drizzle-orm/pg-core";import{sql as C}from"drizzle-orm";import{boolean as Oe,jsonb as $,pgTable as Fe,text as ne,unique as je,uuid as ze}from"drizzle-orm/pg-core";import{customType as he}from"drizzle-orm/pg-core";var kt=he({dataType(){return"jsonb"},toDriver(m){return JSON.stringify(m)},fromDriver(m){return JSON.stringify(m)}}),T=he({dataType(){return"timestamptz"},toDriver(m){return new Date(m).toISOString()},fromDriver(m){return new Date(m).getTime()}});var b=Fe("agents",{id:ze("id").primaryKey().defaultRandom(),enabled:Oe("enabled").default(!0).notNull(),createdAt:T("createdAt").default(C`now()`).notNull(),updatedAt:T("updatedAt").default(C`now()`).notNull(),name:ne("name"),username:ne("username"),system:ne("system"),bio:$("bio").$type().notNull(),messageExamples:$("message_examples").$type().default(C`'[]'::jsonb`),postExamples:$("post_examples").$type().default(C`'[]'::jsonb`),topics:$("topics").$type().default(C`'[]'::jsonb`),adjectives:$("adjectives").$type().default(C`'[]'::jsonb`),knowledge:$("knowledge").$type().default(C`'[]'::jsonb`),plugins:$("plugins").$type().default(C`'[]'::jsonb`),settings:$("settings").$type().default(C`'{}'::jsonb`),style:$("style").$type().default(C`'{}'::jsonb`)},m=>({nameUnique:je("name_unique").on(m.name)}));import{sql as ie}from"drizzle-orm";import{jsonb as Je,pgTable as We,text as Ke,unique as Ge,uuid as Ie}from"drizzle-orm/pg-core";var h=We("entities",{id:Ie("id").notNull().primaryKey(),agentId:Ie("agentId").notNull().references(()=>b.id,{onDelete:"cascade"}),createdAt:T("createdAt").default(ie`now()`).notNull(),names:Ke("names").array().default(ie`'{}'::text[]`),metadata:Je("metadata").default(ie`'{}'::jsonb`)},m=>({idAgentIdUnique:Ge("id_agent_id_unique").on(m.id,m.agentId)}));import{sql as we}from"drizzle-orm";import{jsonb as Ve,pgTable as Ze,text as K,uuid as ae}from"drizzle-orm/pg-core";import{sql as be}from"drizzle-orm";import{jsonb as He,pgTable as Xe,text as fe,uuid as pe}from"drizzle-orm/pg-core";var E=Xe("worlds",{id:pe("id").notNull().primaryKey().default(be`gen_random_uuid()`),agentId:pe("agentId").notNull().references(()=>b.id,{onDelete:"cascade"}),name:fe("name").notNull(),metadata:He("metadata"),serverId:fe("serverId").notNull(),createdAt:T("createdAt").default(be`now()`).notNull()});var c=Ze("rooms",{id:ae("id").notNull().primaryKey().default(we`gen_random_uuid()`),agentId:ae("agentId").references(()=>b.id,{onDelete:"cascade"}),source:K("source").notNull(),type:K("type").notNull(),serverId:K("serverId"),worldId:ae("worldId").references(()=>E.id,{onDelete:"cascade"}),name:K("name"),metadata:Ve("metadata"),channelId:K("channelId"),createdAt:T("createdAt").default(we`now()`).notNull()});var a=et("memories",{id:H("id").primaryKey().notNull(),type:tt("type").notNull(),createdAt:T("createdAt").default(k`now()`).notNull(),content:Ue("content").notNull(),entityId:H("entityId").references(()=>h.id,{onDelete:"cascade"}),agentId:H("agentId").references(()=>b.id,{onDelete:"cascade"}),roomId:H("roomId").references(()=>c.id,{onDelete:"cascade"}),worldId:H("worldId").references(()=>E.id,{onDelete:"set null"}),unique:Qe("unique").default(!0).notNull(),metadata:Ue("metadata").default({}).notNull()},m=>[G("idx_memories_type_room").on(m.type,m.roomId),G("idx_memories_world_id").on(m.worldId),V({name:"fk_room",columns:[m.roomId],foreignColumns:[c.id]}).onDelete("cascade"),V({name:"fk_user",columns:[m.entityId],foreignColumns:[h.id]}).onDelete("cascade"),V({name:"fk_agent",columns:[m.agentId],foreignColumns:[b.id]}).onDelete("cascade"),V({name:"fk_world",columns:[m.worldId],foreignColumns:[E.id]}).onDelete("set null"),G("idx_memories_metadata_type").on(k`((metadata->>'type'))`),G("idx_memories_document_id").on(k`((metadata->>'documentId'))`),G("idx_fragments_order").on(k`((metadata->>'documentId'))`,k`((metadata->>'position'))`),De("fragment_metadata_check",k`
1
+ import {
2
+ PGliteClientManager,
3
+ PostgresConnectionManager,
4
+ __name
5
+ } from "./chunk-EYE2J2N6.js";
6
+
7
+ // src/index.ts
8
+ import * as os from "node:os";
9
+ import { logger as logger4 } from "@elizaos/core";
10
+
11
+ // src/pglite/adapter.ts
12
+ import { logger as logger2 } from "@elizaos/core";
13
+ import { drizzle } from "drizzle-orm/pglite";
14
+
15
+ // src/base.ts
16
+ import {
17
+ DatabaseAdapter,
18
+ logger,
19
+ stringToUuid
20
+ } from "@elizaos/core";
21
+ import {
22
+ and,
23
+ cosineDistance,
24
+ count,
25
+ desc,
26
+ eq,
27
+ gte,
28
+ inArray,
29
+ lte,
30
+ or,
31
+ sql as sql12,
32
+ not
33
+ } from "drizzle-orm";
34
+ import { v4 } from "uuid";
35
+
36
+ // src/schema/embedding.ts
37
+ import { sql as sql6 } from "drizzle-orm";
38
+ import { check as check2, foreignKey as foreignKey2, index as index2, pgTable as pgTable6, uuid as uuid6, vector as vector2 } from "drizzle-orm/pg-core";
39
+ import { VECTOR_DIMS } from "@elizaos/core";
40
+
41
+ // src/schema/memory.ts
42
+ import { relations, sql as sql5 } from "drizzle-orm";
43
+ import {
44
+ boolean as boolean2,
45
+ check,
46
+ foreignKey,
47
+ index,
48
+ jsonb as jsonb5,
49
+ pgTable as pgTable5,
50
+ text as text5,
51
+ uuid as uuid5
52
+ } from "drizzle-orm/pg-core";
53
+
54
+ // src/schema/agent.ts
55
+ import { sql } from "drizzle-orm";
56
+ import { boolean, jsonb, pgTable, text, unique, uuid } from "drizzle-orm/pg-core";
57
+
58
+ // src/schema/types.ts
59
+ import { customType } from "drizzle-orm/pg-core";
60
+ var stringJsonb = customType({
61
+ dataType() {
62
+ return "jsonb";
63
+ },
64
+ toDriver(value) {
65
+ return JSON.stringify(value);
66
+ },
67
+ fromDriver(value) {
68
+ return JSON.stringify(value);
69
+ }
70
+ });
71
+ var numberTimestamp = customType({
72
+ dataType() {
73
+ return "timestamptz";
74
+ },
75
+ toDriver(value) {
76
+ return new Date(value).toISOString();
77
+ },
78
+ fromDriver(value) {
79
+ return new Date(value).getTime();
80
+ }
81
+ });
82
+
83
+ // src/schema/agent.ts
84
+ var agentTable = pgTable(
85
+ "agents",
86
+ {
87
+ id: uuid("id").primaryKey().defaultRandom(),
88
+ enabled: boolean("enabled").default(true).notNull(),
89
+ createdAt: numberTimestamp("createdAt").default(sql`now()`).notNull(),
90
+ updatedAt: numberTimestamp("updatedAt").default(sql`now()`).notNull(),
91
+ // Character
92
+ name: text("name"),
93
+ username: text("username"),
94
+ system: text("system"),
95
+ bio: jsonb("bio").$type().notNull(),
96
+ messageExamples: jsonb("message_examples").$type().default(sql`'[]'::jsonb`),
97
+ postExamples: jsonb("post_examples").$type().default(sql`'[]'::jsonb`),
98
+ topics: jsonb("topics").$type().default(sql`'[]'::jsonb`),
99
+ adjectives: jsonb("adjectives").$type().default(sql`'[]'::jsonb`),
100
+ knowledge: jsonb("knowledge").$type().default(sql`'[]'::jsonb`),
101
+ plugins: jsonb("plugins").$type().default(sql`'[]'::jsonb`),
102
+ settings: jsonb("settings").$type().default(sql`'{}'::jsonb`),
103
+ style: jsonb("style").$type().default(sql`'{}'::jsonb`)
104
+ },
105
+ (table) => {
106
+ return {
107
+ nameUnique: unique("name_unique").on(table.name)
108
+ };
109
+ }
110
+ );
111
+
112
+ // src/schema/entity.ts
113
+ import { sql as sql2 } from "drizzle-orm";
114
+ import { jsonb as jsonb2, pgTable as pgTable2, text as text2, unique as unique2, uuid as uuid2 } from "drizzle-orm/pg-core";
115
+ var entityTable = pgTable2(
116
+ "entities",
117
+ {
118
+ id: uuid2("id").notNull().primaryKey(),
119
+ agentId: uuid2("agentId").notNull().references(() => agentTable.id, {
120
+ onDelete: "cascade"
121
+ }),
122
+ createdAt: numberTimestamp("createdAt").default(sql2`now()`).notNull(),
123
+ names: text2("names").array().default(sql2`'{}'::text[]`),
124
+ metadata: jsonb2("metadata").default(sql2`'{}'::jsonb`)
125
+ },
126
+ (table) => {
127
+ return {
128
+ idAgentIdUnique: unique2("id_agent_id_unique").on(table.id, table.agentId)
129
+ };
130
+ }
131
+ );
132
+
133
+ // src/schema/room.ts
134
+ import { sql as sql4 } from "drizzle-orm";
135
+ import { jsonb as jsonb4, pgTable as pgTable4, text as text4, uuid as uuid4 } from "drizzle-orm/pg-core";
136
+
137
+ // src/schema/world.ts
138
+ import { sql as sql3 } from "drizzle-orm";
139
+ import { jsonb as jsonb3, pgTable as pgTable3, text as text3, uuid as uuid3 } from "drizzle-orm/pg-core";
140
+ var worldTable = pgTable3("worlds", {
141
+ id: uuid3("id").notNull().primaryKey().default(sql3`gen_random_uuid()`),
142
+ agentId: uuid3("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
143
+ name: text3("name").notNull(),
144
+ metadata: jsonb3("metadata"),
145
+ serverId: text3("serverId").notNull(),
146
+ createdAt: numberTimestamp("createdAt").default(sql3`now()`).notNull()
147
+ });
148
+
149
+ // src/schema/room.ts
150
+ var roomTable = pgTable4("rooms", {
151
+ id: uuid4("id").notNull().primaryKey().default(sql4`gen_random_uuid()`),
152
+ agentId: uuid4("agentId").references(() => agentTable.id, {
153
+ onDelete: "cascade"
154
+ }),
155
+ source: text4("source").notNull(),
156
+ type: text4("type").notNull(),
157
+ serverId: text4("serverId"),
158
+ worldId: uuid4("worldId").references(() => worldTable.id, {
159
+ onDelete: "cascade"
160
+ }),
161
+ name: text4("name"),
162
+ metadata: jsonb4("metadata"),
163
+ channelId: text4("channelId"),
164
+ createdAt: numberTimestamp("createdAt").default(sql4`now()`).notNull()
165
+ });
166
+
167
+ // src/schema/memory.ts
168
+ var memoryTable = pgTable5(
169
+ "memories",
170
+ {
171
+ id: uuid5("id").primaryKey().notNull(),
172
+ type: text5("type").notNull(),
173
+ createdAt: numberTimestamp("createdAt").default(sql5`now()`).notNull(),
174
+ content: jsonb5("content").notNull(),
175
+ entityId: uuid5("entityId").references(() => entityTable.id, {
176
+ onDelete: "cascade"
177
+ }),
178
+ agentId: uuid5("agentId").references(() => agentTable.id, {
179
+ onDelete: "cascade"
180
+ }),
181
+ roomId: uuid5("roomId").references(() => roomTable.id, {
182
+ onDelete: "cascade"
183
+ }),
184
+ worldId: uuid5("worldId").references(() => worldTable.id, {
185
+ onDelete: "set null"
186
+ }),
187
+ unique: boolean2("unique").default(true).notNull(),
188
+ metadata: jsonb5("metadata").default({}).notNull()
189
+ },
190
+ (table) => [
191
+ index("idx_memories_type_room").on(table.type, table.roomId),
192
+ index("idx_memories_world_id").on(table.worldId),
193
+ foreignKey({
194
+ name: "fk_room",
195
+ columns: [table.roomId],
196
+ foreignColumns: [roomTable.id]
197
+ }).onDelete("cascade"),
198
+ foreignKey({
199
+ name: "fk_user",
200
+ columns: [table.entityId],
201
+ foreignColumns: [entityTable.id]
202
+ }).onDelete("cascade"),
203
+ foreignKey({
204
+ name: "fk_agent",
205
+ columns: [table.agentId],
206
+ foreignColumns: [agentTable.id]
207
+ }).onDelete("cascade"),
208
+ foreignKey({
209
+ name: "fk_world",
210
+ columns: [table.worldId],
211
+ foreignColumns: [worldTable.id]
212
+ }).onDelete("set null"),
213
+ index("idx_memories_metadata_type").on(sql5`((metadata->>'type'))`),
214
+ index("idx_memories_document_id").on(sql5`((metadata->>'documentId'))`),
215
+ index("idx_fragments_order").on(
216
+ sql5`((metadata->>'documentId'))`,
217
+ sql5`((metadata->>'position'))`
218
+ ),
219
+ check(
220
+ "fragment_metadata_check",
221
+ sql5`
2
222
  CASE
3
223
  WHEN metadata->>'type' = 'fragment' THEN
4
224
  metadata ? 'documentId' AND
5
225
  metadata ? 'position'
6
226
  ELSE true
7
227
  END
8
- `),De("document_metadata_check",k`
228
+ `
229
+ ),
230
+ check(
231
+ "document_metadata_check",
232
+ sql5`
9
233
  CASE
10
234
  WHEN metadata->>'type' = 'document' THEN
11
235
  metadata ? 'timestamp'
12
236
  ELSE true
13
237
  END
14
- `)]),br=Ye(a,({one:m})=>({embedding:m(l)}));var L={[v.SMALL]:"dim384",[v.MEDIUM]:"dim512",[v.LARGE]:"dim768",[v.XL]:"dim1024",[v.XXL]:"dim1536",[v.XXXL]:"dim3072"},l=at("embeddings",{id:Te("id").primaryKey().defaultRandom().notNull(),memoryId:Te("memory_id").references(()=>a.id),createdAt:T("created_at").default(Ee`now()`).notNull(),dim384:F("dim_384",{dimensions:v.SMALL}),dim512:F("dim_512",{dimensions:v.MEDIUM}),dim768:F("dim_768",{dimensions:v.LARGE}),dim1024:F("dim_1024",{dimensions:v.XL}),dim1536:F("dim_1536",{dimensions:v.XXL}),dim3072:F("dim_3072",{dimensions:v.XXXL})},m=>[rt("embedding_source_check",Ee`"memory_id" IS NOT NULL`),it("idx_embedding_memory").on(m.memoryId),nt({name:"fk_embedding_memory",columns:[m.memoryId],foreignColumns:[a.id]}).onDelete("cascade")]);import{sql as Ae}from"drizzle-orm";import{jsonb as ot,pgTable as st,text as dt,unique as mt,uuid as _e}from"drizzle-orm/pg-core";var S=st("cache",{id:_e("id").notNull().primaryKey().default(Ae`gen_random_uuid()`),key:dt("key").notNull(),agentId:_e("agentId").notNull().references(()=>b.id,{onDelete:"cascade"}),value:ot("value").notNull(),createdAt:T("createdAt").default(Ae`now()`).notNull(),expiresAt:T("expiresAt")},m=>[mt("cache_key_agent_unique").on(m.key,m.agentId)]);import{sql as Pe}from"drizzle-orm";import{jsonb as ct,pgTable as lt,text as ut,uuid as j}from"drizzle-orm/pg-core";var f=lt("components",{id:j("id").primaryKey().defaultRandom(),entityId:j("entityId").notNull().references(()=>h.id,{onDelete:"cascade"}),agentId:j("agentId").notNull().references(()=>b.id,{onDelete:"cascade"}),roomId:j("roomId").notNull().references(()=>c.id,{onDelete:"cascade"}),worldId:j("worldId").references(()=>E.id,{onDelete:"cascade"}),sourceEntityId:j("sourceEntityId").references(()=>h.id,{onDelete:"cascade"}),type:ut("type").notNull(),data:ct("data").default(Pe`'{}'::jsonb`),createdAt:T("createdAt").default(Pe`now()`).notNull()});import{sql as gt}from"drizzle-orm";import{foreignKey as Ne,jsonb as yt,pgTable as ht,text as It,uuid as oe}from"drizzle-orm/pg-core";var N=ht("logs",{id:oe("id").defaultRandom().notNull(),createdAt:T("createdAt").default(gt`now()`).notNull(),entityId:oe("entityId").notNull().references(()=>h.id),body:yt("body").notNull(),type:It("type").notNull(),roomId:oe("roomId").notNull().references(()=>c.id)},m=>[Ne({name:"fk_room",columns:[m.roomId],foreignColumns:[c.id]}).onDelete("cascade"),Ne({name:"fk_user",columns:[m.entityId],foreignColumns:[h.id]}).onDelete("cascade")]);import{sql as Me}from"drizzle-orm";import{foreignKey as Se,index as ve,pgTable as bt,text as ft,uuid as Z}from"drizzle-orm/pg-core";var u=bt("participants",{id:Z("id").notNull().primaryKey().default(Me`gen_random_uuid()`),createdAt:T("createdAt").default(Me`now()`).notNull(),entityId:Z("entityId").references(()=>h.id,{onDelete:"cascade"}),roomId:Z("roomId").references(()=>c.id,{onDelete:"cascade"}),agentId:Z("agentId").references(()=>b.id,{onDelete:"cascade"}),roomState:ft("roomState")},m=>[ve("idx_participants_user").on(m.entityId),ve("idx_participants_room").on(m.roomId),Se({name:"fk_room",columns:[m.roomId],foreignColumns:[c.id]}).onDelete("cascade"),Se({name:"fk_user",columns:[m.entityId],foreignColumns:[h.id]}).onDelete("cascade")]);import{sql as qe}from"drizzle-orm";import{foreignKey as Be,index as pt,jsonb as wt,pgTable as Dt,text as Ut,unique as Et,uuid as Y}from"drizzle-orm/pg-core";var _=Dt("relationships",{id:Y("id").notNull().primaryKey().default(qe`gen_random_uuid()`),createdAt:T("createdAt").default(qe`now()`).notNull(),sourceEntityId:Y("sourceEntityId").notNull().references(()=>h.id,{onDelete:"cascade"}),targetEntityId:Y("targetEntityId").notNull().references(()=>h.id,{onDelete:"cascade"}),agentId:Y("agentId").notNull().references(()=>b.id,{onDelete:"cascade"}),tags:Ut("tags").array(),metadata:wt("metadata")},m=>[pt("idx_relationships_users").on(m.sourceEntityId,m.targetEntityId),Et("unique_relationship").on(m.sourceEntityId,m.targetEntityId,m.agentId),Be({name:"fk_user_a",columns:[m.sourceEntityId],foreignColumns:[h.id]}).onDelete("cascade"),Be({name:"fk_user_b",columns:[m.targetEntityId],foreignColumns:[h.id]}).onDelete("cascade")]);import{jsonb as Tt,pgTable as At,text as se,timestamp as Re,uuid as Q}from"drizzle-orm/pg-core";var P=At("tasks",{id:Q("id").primaryKey().defaultRandom(),name:se("name").notNull(),description:se("description").notNull(),roomId:Q("room_id"),worldId:Q("world_id"),agentId:Q("agent_id").notNull(),tags:se("tags").array(),metadata:Tt("metadata"),createdAt:Re("created_at").defaultNow(),updatedAt:Re("updated_at").defaultNow()});var de=class de extends _t{constructor(e){super();this.maxRetries=3;this.baseDelay=1e3;this.maxDelay=1e4;this.jitterMax=1e3;this.embeddingDimension=L[384];this.agentId=e}async withRetry(e){let t=new Error("Unknown error");for(let r=1;r<=this.maxRetries;r++)try{return await e()}catch(i){if(t=i,r<this.maxRetries){let s=Math.min(this.baseDelay*2**(r-1),this.maxDelay),d=Math.random()*this.jitterMax,y=s+d;o.warn(`Database operation failed (attempt ${r}/${this.maxRetries}):`,{error:i instanceof Error?i.message:String(i),nextRetryIn:`${(y/1e3).toFixed(1)}s`}),await new Promise(I=>setTimeout(I,y))}else throw o.error("Max retry attempts reached:",{error:i instanceof Error?i.message:String(i),totalAttempts:r}),i instanceof Error?i:new Error(String(i))}throw t}async ensureAgentExists(e){if(!e.name)throw new Error("Agent name is required");let r=(await this.getAgents()).find(i=>i.name===e.name);return r||(e.id=Pt(e.name??O()),await this.createAgent(e),e)}async ensureEmbeddingDimension(e){let t=await this.db.select({embedding:l}).from(a).innerJoin(l,n(l.memoryId,a.id)).where(n(a.agentId,this.agentId)).limit(1);if(t.length>0){let r=Object.entries(L).find(([i,s])=>t[0].embedding[s]!==null)}this.embeddingDimension=L[e]}async getAgent(e){return this.withDatabase(async()=>{let t=await this.db.select().from(b).where(n(b.id,e)).limit(1);return t.length===0?null:t[0]})}async getAgents(){return this.withDatabase(async()=>await this.db.select().from(b))}async createAgent(e){return this.withDatabase(async()=>{try{return await this.db.transaction(async t=>{await t.insert(b).values({...e})}),o.debug("Agent created successfully:",{agentId:e.id}),!0}catch(t){return o.error("Error creating agent:",{error:t instanceof Error?t.message:String(t),agentId:e.id,agent:e}),!1}})}async updateAgent(e,t){return this.withDatabase(async()=>{try{if(!e)throw new Error("Agent ID is required for update");return await this.db.transaction(async r=>{t?.settings&&(t.settings=await this.mergeAgentSettings(r,e,t.settings)),await r.update(b).set({...t,updatedAt:Date.now()}).where(n(b.id,e))}),o.debug("Agent updated successfully:",{agentId:e}),!0}catch(r){return o.error("Error updating agent:",{error:r instanceof Error?r.message:String(r),agentId:e,agent:t}),!1}})}async mergeAgentSettings(e,t,r){let i=await e.select({settings:b.settings}).from(b).where(n(b.id,t)).limit(1);if(i.length===0||!i[0].settings)return r;let s=i[0].settings;if(r.secrets){let d=s.secrets||{},y=r.secrets,I={...d};for(let[R,A]of Object.entries(y))A===null?delete I[R]:I[R]=A;r.secrets=I}return{...s,...r}}async deleteAgent(e){return o.debug(`[DB] Starting deletion of agent with ID: ${e}`),this.withDatabase(async()=>{try{return o.debug(`[DB] Beginning database transaction for deleting agent: ${e}`),await new Promise((r,i)=>{let s=setTimeout(()=>{o.error(`[DB] Transaction timeout reached for agent deletion: ${e}`),i(new Error("Database transaction timeout"))},3e4);this.db.transaction(async d=>{try{o.debug(`[DB] Fetching entities for agent: ${e}`);let I=(await d.select({entityId:h.id}).from(h).where(n(h.agentId,e))).map(g=>g.entityId);o.debug(`[DB] Found ${I.length} entities to delete for agent ${e}`),o.debug(`[DB] Fetching rooms for agent: ${e}`);let A=(await d.select({roomId:c.id}).from(c).where(n(c.agentId,e))).map(g=>g.roomId);if(o.debug(`[DB] Found ${A.length} rooms for agent ${e}`),o.debug("[DB] Explicitly deleting ALL logs with matching entityIds and roomIds"),I.length>0){o.debug(`[DB] Deleting logs for ${I.length} entities (first batch)`);let g=50;for(let p=0;p<I.length;p+=g){let q=I.slice(p,p+g);o.debug(`[DB] Processing entity logs batch ${p/g+1} with ${q.length} entities`),await d.delete(N).where(D(N.entityId,q))}o.debug("[DB] Entity logs deletion completed successfully")}if(A.length>0){o.debug(`[DB] Deleting logs for ${A.length} rooms (first batch)`);let g=50;for(let p=0;p<A.length;p+=g){let q=A.slice(p,p+g);o.debug(`[DB] Processing room logs batch ${p/g+1} with ${q.length} rooms`),await d.delete(N).where(D(N.roomId,q))}o.debug("[DB] Room logs deletion completed successfully")}let U=[];I.length>0&&(o.debug("[DB] Finding memories belonging to entities"),U=(await d.select({id:a.id}).from(a).where(D(a.entityId,I))).map(p=>p.id),o.debug(`[DB] Found ${U.length} memories belonging to entities`)),o.debug("[DB] Finding memories belonging to agent directly");let X=await d.select({id:a.id}).from(a).where(n(a.agentId,e));if(U=[...U,...X.map(g=>g.id)],o.debug(`[DB] Found total of ${U.length} memories to delete`),A.length>0){o.debug("[DB] Finding memories belonging to rooms");let g=await d.select({id:a.id}).from(a).where(D(a.roomId,A));U=[...U,...g.map(p=>p.id)],o.debug(`[DB] Updated total to ${U.length} memories to delete`)}if(U.length>0){o.debug(`[DB] Deleting embeddings for ${U.length} memories`);let g=100;for(let p=0;p<U.length;p+=g){let q=U.slice(p,p+g);await d.delete(l).where(D(l.memoryId,q))}o.debug("[DB] Embeddings deleted successfully")}if(U.length>0){o.debug(`[DB] Deleting ${U.length} memories`);let g=100;for(let p=0;p<U.length;p+=g){let q=U.slice(p,p+g);await d.delete(a).where(D(a.id,q))}o.debug("[DB] Memories deleted successfully")}I.length>0&&(o.debug("[DB] Deleting components for entities"),await d.delete(f).where(D(f.entityId,I)),o.debug("[DB] Components deleted successfully")),I.length>0&&(o.debug("[DB] Deleting source entity references in components"),await d.delete(f).where(D(f.sourceEntityId,I)),o.debug("[DB] Source entity references deleted successfully")),A.length>0&&(o.debug("[DB] Deleting participations for rooms"),await d.delete(u).where(D(u.roomId,A)),o.debug("[DB] Participations deleted for rooms")),o.debug("[DB] Deleting agent participations"),await d.delete(u).where(n(u.agentId,e)),o.debug("[DB] Agent participations deleted"),A.length>0&&(o.debug("[DB] Deleting rooms"),await d.delete(c).where(D(c.id,A)),o.debug("[DB] Rooms deleted successfully")),o.debug("[DB] Deleting cache entries"),await d.delete(S).where(n(S.agentId,e)),o.debug("[DB] Cache entries deleted successfully"),o.debug("[DB] Deleting relationships"),I.length>0&&(await d.delete(_).where(D(_.sourceEntityId,I)),await d.delete(_).where(D(_.targetEntityId,I))),await d.delete(_).where(n(_.agentId,e)),o.debug("[DB] Relationships deleted successfully"),I.length>0&&(o.debug("[DB] Deleting entities"),await d.delete(h).where(n(h.agentId,e)),o.debug("[DB] Entities deleted successfully")),o.debug("[DB] Checking for world references");let re=await d.select({id:E.id}).from(E).where(n(E.agentId,e));if(re.length>0){let g=await d.select({newAgentId:b.id}).from(b).where(qt(n(b.id,e))).limit(1);if(g.length>0)await d.update(E).set({agentId:g[0].newAgentId}).where(n(E.agentId,e));else{let p=re.map(q=>q.id);o.debug(`[DB] Found ${p.length} worlds to delete`),await d.delete(E).where(D(E.id,p)),o.debug("[DB] Worlds deleted successfully")}}else o.debug("[DB] No worlds found for this agent");o.debug(`[DB] Deleting agent ${e}`),await d.delete(b).where(n(b.id,e)),o.debug("[DB] Agent deleted successfully"),r(!0)}catch(y){o.error("[DB] Error in transaction:",y),i(y)}}).catch(d=>{clearTimeout(s),i(d)})}),o.success(`[DB] Agent ${e} successfully deleted`),!0}catch(t){throw o.error(`[DB] Error in database transaction for agent deletion ${e}:`,t),t instanceof Error&&(o.error(`[DB] Error name: ${t.name}, message: ${t.message}`),o.error(`[DB] Error stack: ${t.stack}`)),t}})}async countAgents(){return this.withDatabase(async()=>{try{return(await this.db.select({count:Mt()}).from(b))[0]?.count||0}catch(e){return o.error("Error counting agents:",{error:e instanceof Error?e.message:String(e)}),0}})}async cleanupAgents(){return this.withDatabase(async()=>{try{await this.db.delete(b),o.success("Successfully cleaned up agent table")}catch(e){throw o.error("Error cleaning up agent table:",{error:e instanceof Error?e.message:String(e)}),e}})}async getEntityById(e){return this.withDatabase(async()=>{let t=await this.db.select({entity:h,components:f}).from(h).leftJoin(f,n(f.entityId,h.id)).where(n(h.id,e));if(t.length===0)return null;let r=t[0].entity;return r.components=t.filter(i=>i.components).map(i=>i.components),r})}async getEntitiesForRoom(e,t){return this.withDatabase(async()=>{let r=this.db.select({entity:h,...t&&{components:f}}).from(u).leftJoin(h,w(n(u.entityId,h.id),n(h.agentId,this.agentId)));t&&r.leftJoin(f,n(f.entityId,h.id));let i=await r.where(n(u.roomId,e)),s=new Map;for(let d of i){if(!d.entity)continue;let y=d.entity.id;if(!s.has(y)){let I={...d.entity,components:t?[]:void 0};s.set(y,I)}if(t&&d.components){let I=s.get(y);I&&(I.components||(I.components=[]),I.components.push(d.components))}}return Array.from(s.values())})}async createEntity(e){return this.withDatabase(async()=>{try{return await this.db.transaction(async t=>(await t.insert(h).values(e),o.debug("Entity created successfully:",{entity:e}),!0))}catch(t){return o.error("Error creating entity:",{error:t instanceof Error?t.message:String(t),entityId:e.id,name:e.metadata?.name}),o.trace(t),!1}})}async ensureEntityExists(e){if(!e.id)return o.error("Entity ID is required for ensureEntityExists"),!1;try{return await this.getEntityById(e.id)?!0:await this.createEntity(e)}catch(t){return o.error("Error ensuring entity exists:",{error:t instanceof Error?t.message:String(t),entityId:e.id}),!1}}async updateEntity(e){return this.withDatabase(async()=>{await this.db.update(h).set(e).where(w(n(h.id,e.id),n(h.agentId,e.agentId)))})}async getComponent(e,t,r,i){return this.withDatabase(async()=>{let s=[n(f.entityId,e),n(f.type,t)];r&&s.push(n(f.worldId,r)),i&&s.push(n(f.sourceEntityId,i));let d=await this.db.select().from(f).where(w(...s));return d.length>0?d[0]:null})}async getComponents(e,t,r){return this.withDatabase(async()=>{let i=[n(f.entityId,e)];return t&&i.push(n(f.worldId,t)),r&&i.push(n(f.sourceEntityId,r)),await this.db.select({id:f.id,entityId:f.entityId,type:f.type,data:f.data,worldId:f.worldId,sourceEntityId:f.sourceEntityId,createdAt:f.createdAt}).from(f).where(w(...i))})}async createComponent(e){return this.withDatabase(async()=>(await this.db.insert(f).values(e),!0))}async updateComponent(e){return this.withDatabase(async()=>{await this.db.update(f).set(e).where(n(f.id,e.id))})}async deleteComponent(e){return this.withDatabase(async()=>{await this.db.delete(f).where(n(f.id,e))})}async getMemories(e){let{entityId:t,agentId:r,roomId:i,worldId:s,tableName:d,count:y,unique:I,start:R,end:A}=e;if(!d)throw new Error("tableName is required");return this.withDatabase(async()=>{let U=[n(a.type,d)];R&&U.push(xe(a.createdAt,R)),t&&U.push(n(a.entityId,t)),i&&U.push(n(a.roomId,i)),s&&U.push(n(a.worldId,s)),A&&U.push(St(a.createdAt,A)),I&&U.push(n(a.unique,!0)),r&&U.push(n(a.agentId,r));let X=this.db.select({memory:{id:a.id,type:a.type,createdAt:a.createdAt,content:a.content,entityId:a.entityId,agentId:a.agentId,roomId:a.roomId,unique:a.unique,metadata:a.metadata},embedding:l[this.embeddingDimension]}).from(a).leftJoin(l,n(l.memoryId,a.id)).where(w(...U)).orderBy(z(a.createdAt));return(e.count?await X.limit(e.count):await X).map(g=>({id:g.memory.id,type:g.memory.type,createdAt:g.memory.createdAt,content:typeof g.memory.content=="string"?JSON.parse(g.memory.content):g.memory.content,entityId:g.memory.entityId,agentId:g.memory.agentId,roomId:g.memory.roomId,unique:g.memory.unique,metadata:g.memory.metadata,embedding:g.embedding?Array.from(g.embedding):void 0}))})}async getMemoriesByRoomIds(e){return this.withDatabase(async()=>{if(e.roomIds.length===0)return[];let t=[n(a.type,e.tableName),D(a.roomId,e.roomIds)];t.push(n(a.agentId,this.agentId));let r=this.db.select({id:a.id,type:a.type,createdAt:a.createdAt,content:a.content,entityId:a.entityId,agentId:a.agentId,roomId:a.roomId,unique:a.unique,metadata:a.metadata}).from(a).where(w(...t)).orderBy(z(a.createdAt));return(e.limit?await r.limit(e.limit):await r).map(s=>({id:s.id,createdAt:s.createdAt,content:typeof s.content=="string"?JSON.parse(s.content):s.content,entityId:s.entityId,agentId:s.agentId,roomId:s.roomId,unique:s.unique,metadata:s.metadata}))})}async getMemoryById(e){return this.withDatabase(async()=>{let t=await this.db.select({memory:a,embedding:l[this.embeddingDimension]}).from(a).leftJoin(l,n(a.id,l.memoryId)).where(n(a.id,e)).limit(1);if(t.length===0)return null;let r=t[0];return{id:r.memory.id,createdAt:r.memory.createdAt,content:typeof r.memory.content=="string"?JSON.parse(r.memory.content):r.memory.content,entityId:r.memory.entityId,agentId:r.memory.agentId,roomId:r.memory.roomId,unique:r.memory.unique,embedding:r.embedding??void 0}})}async getMemoriesByIds(e,t){return this.withDatabase(async()=>{if(e.length===0)return[];let r=[D(a.id,e)];return t&&r.push(n(a.type,t)),(await this.db.select({memory:a,embedding:l[this.embeddingDimension]}).from(a).leftJoin(l,n(l.memoryId,a.id)).where(w(...r)).orderBy(z(a.createdAt))).map(s=>({id:s.memory.id,createdAt:s.memory.createdAt,content:typeof s.memory.content=="string"?JSON.parse(s.memory.content):s.memory.content,entityId:s.memory.entityId,agentId:s.memory.agentId,roomId:s.memory.roomId,unique:s.memory.unique,metadata:s.memory.metadata,embedding:s.embedding??void 0}))})}async getCachedEmbeddings(e){return this.withDatabase(async()=>{try{return(await this.db.execute(M`
238
+ `
239
+ )
240
+ ]
241
+ );
242
+ var memoryRelations = relations(memoryTable, ({ one }) => ({
243
+ embedding: one(embeddingTable)
244
+ }));
245
+
246
+ // src/schema/embedding.ts
247
+ var DIMENSION_MAP = {
248
+ [VECTOR_DIMS.SMALL]: "dim384",
249
+ [VECTOR_DIMS.MEDIUM]: "dim512",
250
+ [VECTOR_DIMS.LARGE]: "dim768",
251
+ [VECTOR_DIMS.XL]: "dim1024",
252
+ [VECTOR_DIMS.XXL]: "dim1536",
253
+ [VECTOR_DIMS.XXXL]: "dim3072"
254
+ };
255
+ var embeddingTable = pgTable6(
256
+ "embeddings",
257
+ {
258
+ id: uuid6("id").primaryKey().defaultRandom().notNull(),
259
+ memoryId: uuid6("memory_id").references(() => memoryTable.id),
260
+ createdAt: numberTimestamp("created_at").default(sql6`now()`).notNull(),
261
+ dim384: vector2("dim_384", { dimensions: VECTOR_DIMS.SMALL }),
262
+ dim512: vector2("dim_512", { dimensions: VECTOR_DIMS.MEDIUM }),
263
+ dim768: vector2("dim_768", { dimensions: VECTOR_DIMS.LARGE }),
264
+ dim1024: vector2("dim_1024", { dimensions: VECTOR_DIMS.XL }),
265
+ dim1536: vector2("dim_1536", { dimensions: VECTOR_DIMS.XXL }),
266
+ dim3072: vector2("dim_3072", { dimensions: VECTOR_DIMS.XXXL })
267
+ },
268
+ (table) => [
269
+ check2("embedding_source_check", sql6`"memory_id" IS NOT NULL`),
270
+ index2("idx_embedding_memory").on(table.memoryId),
271
+ foreignKey2({
272
+ name: "fk_embedding_memory",
273
+ columns: [table.memoryId],
274
+ foreignColumns: [memoryTable.id]
275
+ }).onDelete("cascade")
276
+ ]
277
+ );
278
+
279
+ // src/schema/cache.ts
280
+ import { sql as sql7 } from "drizzle-orm";
281
+ import { jsonb as jsonb6, pgTable as pgTable7, text as text6, unique as unique4, uuid as uuid7 } from "drizzle-orm/pg-core";
282
+ var cacheTable = pgTable7(
283
+ "cache",
284
+ {
285
+ id: uuid7("id").notNull().primaryKey().default(sql7`gen_random_uuid()`),
286
+ key: text6("key").notNull(),
287
+ agentId: uuid7("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
288
+ value: jsonb6("value").notNull(),
289
+ createdAt: numberTimestamp("createdAt").default(sql7`now()`).notNull(),
290
+ expiresAt: numberTimestamp("expiresAt")
291
+ },
292
+ (table) => [unique4("cache_key_agent_unique").on(table.key, table.agentId)]
293
+ );
294
+
295
+ // src/schema/component.ts
296
+ import { sql as sql8 } from "drizzle-orm";
297
+ import { jsonb as jsonb7, pgTable as pgTable8, text as text7, uuid as uuid8 } from "drizzle-orm/pg-core";
298
+ var componentTable = pgTable8("components", {
299
+ id: uuid8("id").primaryKey().defaultRandom(),
300
+ entityId: uuid8("entityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
301
+ agentId: uuid8("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
302
+ roomId: uuid8("roomId").notNull().references(() => roomTable.id, { onDelete: "cascade" }),
303
+ worldId: uuid8("worldId").references(() => worldTable.id, {
304
+ onDelete: "cascade"
305
+ }),
306
+ sourceEntityId: uuid8("sourceEntityId").references(() => entityTable.id, {
307
+ onDelete: "cascade"
308
+ }),
309
+ type: text7("type").notNull(),
310
+ data: jsonb7("data").default(sql8`'{}'::jsonb`),
311
+ createdAt: numberTimestamp("createdAt").default(sql8`now()`).notNull()
312
+ });
313
+
314
+ // src/schema/log.ts
315
+ import { sql as sql9 } from "drizzle-orm";
316
+ import { foreignKey as foreignKey3, jsonb as jsonb8, pgTable as pgTable9, text as text8, uuid as uuid9 } from "drizzle-orm/pg-core";
317
+ var logTable = pgTable9(
318
+ "logs",
319
+ {
320
+ id: uuid9("id").defaultRandom().notNull(),
321
+ createdAt: numberTimestamp("createdAt").default(sql9`now()`).notNull(),
322
+ entityId: uuid9("entityId").notNull().references(() => entityTable.id),
323
+ body: jsonb8("body").notNull(),
324
+ type: text8("type").notNull(),
325
+ roomId: uuid9("roomId").notNull().references(() => roomTable.id)
326
+ },
327
+ (table) => [
328
+ foreignKey3({
329
+ name: "fk_room",
330
+ columns: [table.roomId],
331
+ foreignColumns: [roomTable.id]
332
+ }).onDelete("cascade"),
333
+ foreignKey3({
334
+ name: "fk_user",
335
+ columns: [table.entityId],
336
+ foreignColumns: [entityTable.id]
337
+ }).onDelete("cascade")
338
+ ]
339
+ );
340
+
341
+ // src/schema/participant.ts
342
+ import { sql as sql10 } from "drizzle-orm";
343
+ import { foreignKey as foreignKey4, index as index3, pgTable as pgTable10, text as text9, uuid as uuid10 } from "drizzle-orm/pg-core";
344
+ var participantTable = pgTable10(
345
+ "participants",
346
+ {
347
+ id: uuid10("id").notNull().primaryKey().default(sql10`gen_random_uuid()`),
348
+ createdAt: numberTimestamp("createdAt").default(sql10`now()`).notNull(),
349
+ entityId: uuid10("entityId").references(() => entityTable.id, {
350
+ onDelete: "cascade"
351
+ }),
352
+ roomId: uuid10("roomId").references(() => roomTable.id, {
353
+ onDelete: "cascade"
354
+ }),
355
+ agentId: uuid10("agentId").references(() => agentTable.id, {
356
+ onDelete: "cascade"
357
+ }),
358
+ roomState: text9("roomState")
359
+ },
360
+ (table) => [
361
+ // unique("participants_user_room_agent_unique").on(table.entityId, table.roomId, table.agentId),
362
+ index3("idx_participants_user").on(table.entityId),
363
+ index3("idx_participants_room").on(table.roomId),
364
+ foreignKey4({
365
+ name: "fk_room",
366
+ columns: [table.roomId],
367
+ foreignColumns: [roomTable.id]
368
+ }).onDelete("cascade"),
369
+ foreignKey4({
370
+ name: "fk_user",
371
+ columns: [table.entityId],
372
+ foreignColumns: [entityTable.id]
373
+ }).onDelete("cascade")
374
+ ]
375
+ );
376
+
377
+ // src/schema/relationship.ts
378
+ import { sql as sql11 } from "drizzle-orm";
379
+ import { foreignKey as foreignKey5, index as index4, jsonb as jsonb9, pgTable as pgTable11, text as text10, unique as unique6, uuid as uuid11 } from "drizzle-orm/pg-core";
380
+ var relationshipTable = pgTable11(
381
+ "relationships",
382
+ {
383
+ id: uuid11("id").notNull().primaryKey().default(sql11`gen_random_uuid()`),
384
+ createdAt: numberTimestamp("createdAt").default(sql11`now()`).notNull(),
385
+ sourceEntityId: uuid11("sourceEntityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
386
+ targetEntityId: uuid11("targetEntityId").notNull().references(() => entityTable.id, { onDelete: "cascade" }),
387
+ agentId: uuid11("agentId").notNull().references(() => agentTable.id, { onDelete: "cascade" }),
388
+ tags: text10("tags").array(),
389
+ metadata: jsonb9("metadata")
390
+ },
391
+ (table) => [
392
+ index4("idx_relationships_users").on(table.sourceEntityId, table.targetEntityId),
393
+ unique6("unique_relationship").on(table.sourceEntityId, table.targetEntityId, table.agentId),
394
+ foreignKey5({
395
+ name: "fk_user_a",
396
+ columns: [table.sourceEntityId],
397
+ foreignColumns: [entityTable.id]
398
+ }).onDelete("cascade"),
399
+ foreignKey5({
400
+ name: "fk_user_b",
401
+ columns: [table.targetEntityId],
402
+ foreignColumns: [entityTable.id]
403
+ }).onDelete("cascade")
404
+ ]
405
+ );
406
+
407
+ // src/schema/tasks.ts
408
+ import { jsonb as jsonb10, pgTable as pgTable12, text as text11, timestamp, uuid as uuid12 } from "drizzle-orm/pg-core";
409
+ var taskTable = pgTable12("tasks", {
410
+ id: uuid12("id").primaryKey().defaultRandom(),
411
+ name: text11("name").notNull(),
412
+ description: text11("description").notNull(),
413
+ roomId: uuid12("room_id"),
414
+ worldId: uuid12("world_id"),
415
+ agentId: uuid12("agent_id").notNull(),
416
+ tags: text11("tags").array(),
417
+ metadata: jsonb10("metadata"),
418
+ createdAt: timestamp("created_at").defaultNow(),
419
+ updatedAt: timestamp("updated_at").defaultNow()
420
+ });
421
+
422
+ // src/base.ts
423
+ var BaseDrizzleAdapter = class extends DatabaseAdapter {
424
+ static {
425
+ __name(this, "BaseDrizzleAdapter");
426
+ }
427
+ maxRetries = 3;
428
+ baseDelay = 1e3;
429
+ maxDelay = 1e4;
430
+ jitterMax = 1e3;
431
+ embeddingDimension = DIMENSION_MAP[384];
432
+ agentId;
433
+ /**
434
+ * Constructor for creating a new instance of Agent with the specified agentId.
435
+ *
436
+ * @param {UUID} agentId - The unique identifier for the agent.
437
+ */
438
+ constructor(agentId) {
439
+ super();
440
+ this.agentId = agentId;
441
+ }
442
+ /**
443
+ * Executes the given operation with retry logic.
444
+ * @template T
445
+ * @param {() => Promise<T>} operation - The operation to be executed.
446
+ * @returns {Promise<T>} A promise that resolves with the result of the operation.
447
+ */
448
+ async withRetry(operation) {
449
+ let lastError = new Error("Unknown error");
450
+ for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
451
+ try {
452
+ return await operation();
453
+ } catch (error) {
454
+ lastError = error;
455
+ if (attempt < this.maxRetries) {
456
+ const backoffDelay = Math.min(this.baseDelay * 2 ** (attempt - 1), this.maxDelay);
457
+ const jitter = Math.random() * this.jitterMax;
458
+ const delay = backoffDelay + jitter;
459
+ logger.warn(`Database operation failed (attempt ${attempt}/${this.maxRetries}):`, {
460
+ error: error instanceof Error ? error.message : String(error),
461
+ nextRetryIn: `${(delay / 1e3).toFixed(1)}s`
462
+ });
463
+ await new Promise((resolve) => setTimeout(resolve, delay));
464
+ } else {
465
+ logger.error("Max retry attempts reached:", {
466
+ error: error instanceof Error ? error.message : String(error),
467
+ totalAttempts: attempt
468
+ });
469
+ throw error instanceof Error ? error : new Error(String(error));
470
+ }
471
+ }
472
+ }
473
+ throw lastError;
474
+ }
475
+ /**
476
+ * Asynchronously ensures that an agent exists by checking if an agent with the same name already exists in the system.
477
+ * If the agent does not exist, it will be created with the provided data.
478
+ *
479
+ * @param {Partial<Agent>} agent - The partial data of the agent to ensure its existence.
480
+ * @returns {Promise<void>} - A promise that resolves when the agent is successfully ensured.
481
+ * @throws {Error} - If the agent name is not provided or if there is an issue creating the agent.
482
+ */
483
+ async ensureAgentExists(agent) {
484
+ if (!agent.name) {
485
+ throw new Error("Agent name is required");
486
+ }
487
+ const agents = await this.getAgents();
488
+ const existingAgent = agents.find(
489
+ (a) => a.name === agent.name
490
+ );
491
+ if (existingAgent) {
492
+ return existingAgent;
493
+ }
494
+ agent.id = stringToUuid(agent.name ?? v4());
495
+ await this.createAgent(agent);
496
+ return agent;
497
+ }
498
+ /**
499
+ * Asynchronously ensures that the given embedding dimension is valid for the agent.
500
+ *
501
+ * @param {number} dimension - The dimension to ensure for the embedding.
502
+ * @returns {Promise<void>} - Resolves once the embedding dimension is ensured.
503
+ */
504
+ async ensureEmbeddingDimension(dimension) {
505
+ const existingMemory = await this.db.select({
506
+ embedding: embeddingTable
507
+ }).from(memoryTable).innerJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(eq(memoryTable.agentId, this.agentId)).limit(1);
508
+ if (existingMemory.length > 0) {
509
+ const usedDimension = Object.entries(DIMENSION_MAP).find(
510
+ ([_, colName]) => existingMemory[0].embedding[colName] !== null
511
+ );
512
+ }
513
+ this.embeddingDimension = DIMENSION_MAP[dimension];
514
+ }
515
+ /**
516
+ * Asynchronously retrieves an agent by their ID from the database.
517
+ * @param {UUID} agentId - The ID of the agent to retrieve.
518
+ * @returns {Promise<Agent | null>} A promise that resolves to the retrieved agent or null if not found.
519
+ */
520
+ async getAgent(agentId) {
521
+ return this.withDatabase(async () => {
522
+ const result = await this.db.select().from(agentTable).where(eq(agentTable.id, agentId)).limit(1);
523
+ if (result.length === 0) return null;
524
+ return result[0];
525
+ });
526
+ }
527
+ /**
528
+ * Asynchronously retrieves a list of agents from the database.
529
+ *
530
+ * @returns {Promise<Agent[]>} A Promise that resolves to an array of Agent objects.
531
+ */
532
+ async getAgents() {
533
+ return this.withDatabase(async () => {
534
+ const result = await this.db.select().from(agentTable);
535
+ return result;
536
+ });
537
+ }
538
+ /**
539
+ * Asynchronously creates a new agent record in the database.
540
+ *
541
+ * @param {Partial<Agent>} agent The agent object to be created.
542
+ * @returns {Promise<boolean>} A promise that resolves to a boolean indicating the success of the operation.
543
+ */
544
+ async createAgent(agent) {
545
+ return this.withDatabase(async () => {
546
+ try {
547
+ await this.db.transaction(async (tx) => {
548
+ await tx.insert(agentTable).values({
549
+ ...agent
550
+ });
551
+ });
552
+ logger.debug("Agent created successfully:", {
553
+ agentId: agent.id
554
+ });
555
+ return true;
556
+ } catch (error) {
557
+ logger.error("Error creating agent:", {
558
+ error: error instanceof Error ? error.message : String(error),
559
+ agentId: agent.id,
560
+ agent
561
+ });
562
+ return false;
563
+ }
564
+ });
565
+ }
566
+ /**
567
+ * Updates an agent in the database with the provided agent ID and data.
568
+ * @param {UUID} agentId - The unique identifier of the agent to update.
569
+ * @param {Partial<Agent>} agent - The partial agent object containing the fields to update.
570
+ * @returns {Promise<boolean>} - A boolean indicating if the agent was successfully updated.
571
+ */
572
+ async updateAgent(agentId, agent) {
573
+ return this.withDatabase(async () => {
574
+ try {
575
+ if (!agentId) {
576
+ throw new Error("Agent ID is required for update");
577
+ }
578
+ await this.db.transaction(async (tx) => {
579
+ if (agent?.settings) {
580
+ agent.settings = await this.mergeAgentSettings(tx, agentId, agent.settings);
581
+ }
582
+ await tx.update(agentTable).set({
583
+ ...agent,
584
+ updatedAt: Date.now()
585
+ }).where(eq(agentTable.id, agentId));
586
+ });
587
+ logger.debug("Agent updated successfully:", {
588
+ agentId
589
+ });
590
+ return true;
591
+ } catch (error) {
592
+ logger.error("Error updating agent:", {
593
+ error: error instanceof Error ? error.message : String(error),
594
+ agentId,
595
+ agent
596
+ });
597
+ return false;
598
+ }
599
+ });
600
+ }
601
+ /**
602
+ * Merges updated agent settings with existing settings in the database,
603
+ * with special handling for nested objects like secrets.
604
+ * @param tx - The database transaction
605
+ * @param agentId - The ID of the agent
606
+ * @param updatedSettings - The settings object with updates
607
+ * @returns The merged settings object
608
+ * @private
609
+ */
610
+ async mergeAgentSettings(tx, agentId, updatedSettings) {
611
+ const currentAgent = await tx.select({ settings: agentTable.settings }).from(agentTable).where(eq(agentTable.id, agentId)).limit(1);
612
+ if (currentAgent.length === 0 || !currentAgent[0].settings) {
613
+ return updatedSettings;
614
+ }
615
+ const currentSettings = currentAgent[0].settings;
616
+ if (updatedSettings.secrets) {
617
+ const currentSecrets = currentSettings.secrets || {};
618
+ const updatedSecrets = updatedSettings.secrets;
619
+ const mergedSecrets = { ...currentSecrets };
620
+ for (const [key, value] of Object.entries(updatedSecrets)) {
621
+ if (value === null) {
622
+ delete mergedSecrets[key];
623
+ } else {
624
+ mergedSecrets[key] = value;
625
+ }
626
+ }
627
+ updatedSettings.secrets = mergedSecrets;
628
+ }
629
+ return {
630
+ ...currentSettings,
631
+ ...updatedSettings
632
+ };
633
+ }
634
+ /**
635
+ * Asynchronously deletes an agent with the specified UUID and all related entries.
636
+ *
637
+ * @param {UUID} agentId - The UUID of the agent to be deleted.
638
+ * @returns {Promise<boolean>} - A boolean indicating if the deletion was successful.
639
+ */
640
+ async deleteAgent(agentId) {
641
+ logger.debug(`[DB] Starting deletion of agent with ID: ${agentId}`);
642
+ return this.withDatabase(async () => {
643
+ try {
644
+ logger.debug(`[DB] Beginning database transaction for deleting agent: ${agentId}`);
645
+ const deletePromise = new Promise((resolve, reject) => {
646
+ const timeoutId = setTimeout(() => {
647
+ logger.error(`[DB] Transaction timeout reached for agent deletion: ${agentId}`);
648
+ reject(new Error("Database transaction timeout"));
649
+ }, 3e4);
650
+ this.db.transaction(async (tx) => {
651
+ try {
652
+ logger.debug(`[DB] Fetching entities for agent: ${agentId}`);
653
+ const entities = await tx.select({ entityId: entityTable.id }).from(entityTable).where(eq(entityTable.agentId, agentId));
654
+ const entityIds = entities.map((e) => e.entityId);
655
+ logger.debug(
656
+ `[DB] Found ${entityIds.length} entities to delete for agent ${agentId}`
657
+ );
658
+ logger.debug(`[DB] Fetching rooms for agent: ${agentId}`);
659
+ const rooms = await tx.select({ roomId: roomTable.id }).from(roomTable).where(eq(roomTable.agentId, agentId));
660
+ const roomIds = rooms.map((r) => r.roomId);
661
+ logger.debug(`[DB] Found ${roomIds.length} rooms for agent ${agentId}`);
662
+ logger.debug(
663
+ `[DB] Explicitly deleting ALL logs with matching entityIds and roomIds`
664
+ );
665
+ if (entityIds.length > 0) {
666
+ logger.debug(`[DB] Deleting logs for ${entityIds.length} entities (first batch)`);
667
+ const BATCH_SIZE = 50;
668
+ for (let i = 0; i < entityIds.length; i += BATCH_SIZE) {
669
+ const batch = entityIds.slice(i, i + BATCH_SIZE);
670
+ logger.debug(
671
+ `[DB] Processing entity logs batch ${i / BATCH_SIZE + 1} with ${batch.length} entities`
672
+ );
673
+ await tx.delete(logTable).where(inArray(logTable.entityId, batch));
674
+ }
675
+ logger.debug(`[DB] Entity logs deletion completed successfully`);
676
+ }
677
+ if (roomIds.length > 0) {
678
+ logger.debug(`[DB] Deleting logs for ${roomIds.length} rooms (first batch)`);
679
+ const BATCH_SIZE = 50;
680
+ for (let i = 0; i < roomIds.length; i += BATCH_SIZE) {
681
+ const batch = roomIds.slice(i, i + BATCH_SIZE);
682
+ logger.debug(
683
+ `[DB] Processing room logs batch ${i / BATCH_SIZE + 1} with ${batch.length} rooms`
684
+ );
685
+ await tx.delete(logTable).where(inArray(logTable.roomId, batch));
686
+ }
687
+ logger.debug(`[DB] Room logs deletion completed successfully`);
688
+ }
689
+ let memoryIds = [];
690
+ if (entityIds.length > 0) {
691
+ logger.debug(`[DB] Finding memories belonging to entities`);
692
+ const memories = await tx.select({ id: memoryTable.id }).from(memoryTable).where(inArray(memoryTable.entityId, entityIds));
693
+ memoryIds = memories.map((m) => m.id);
694
+ logger.debug(`[DB] Found ${memoryIds.length} memories belonging to entities`);
695
+ }
696
+ logger.debug(`[DB] Finding memories belonging to agent directly`);
697
+ const agentMemories = await tx.select({ id: memoryTable.id }).from(memoryTable).where(eq(memoryTable.agentId, agentId));
698
+ memoryIds = [...memoryIds, ...agentMemories.map((m) => m.id)];
699
+ logger.debug(`[DB] Found total of ${memoryIds.length} memories to delete`);
700
+ if (roomIds.length > 0) {
701
+ logger.debug(`[DB] Finding memories belonging to rooms`);
702
+ const roomMemories = await tx.select({ id: memoryTable.id }).from(memoryTable).where(inArray(memoryTable.roomId, roomIds));
703
+ memoryIds = [...memoryIds, ...roomMemories.map((m) => m.id)];
704
+ logger.debug(`[DB] Updated total to ${memoryIds.length} memories to delete`);
705
+ }
706
+ if (memoryIds.length > 0) {
707
+ logger.debug(`[DB] Deleting embeddings for ${memoryIds.length} memories`);
708
+ const BATCH_SIZE = 100;
709
+ for (let i = 0; i < memoryIds.length; i += BATCH_SIZE) {
710
+ const batch = memoryIds.slice(i, i + BATCH_SIZE);
711
+ await tx.delete(embeddingTable).where(inArray(embeddingTable.memoryId, batch));
712
+ }
713
+ logger.debug(`[DB] Embeddings deleted successfully`);
714
+ }
715
+ if (memoryIds.length > 0) {
716
+ logger.debug(`[DB] Deleting ${memoryIds.length} memories`);
717
+ const BATCH_SIZE = 100;
718
+ for (let i = 0; i < memoryIds.length; i += BATCH_SIZE) {
719
+ const batch = memoryIds.slice(i, i + BATCH_SIZE);
720
+ await tx.delete(memoryTable).where(inArray(memoryTable.id, batch));
721
+ }
722
+ logger.debug(`[DB] Memories deleted successfully`);
723
+ }
724
+ if (entityIds.length > 0) {
725
+ logger.debug(`[DB] Deleting components for entities`);
726
+ await tx.delete(componentTable).where(inArray(componentTable.entityId, entityIds));
727
+ logger.debug(`[DB] Components deleted successfully`);
728
+ }
729
+ if (entityIds.length > 0) {
730
+ logger.debug(`[DB] Deleting source entity references in components`);
731
+ await tx.delete(componentTable).where(inArray(componentTable.sourceEntityId, entityIds));
732
+ logger.debug(`[DB] Source entity references deleted successfully`);
733
+ }
734
+ if (roomIds.length > 0) {
735
+ logger.debug(`[DB] Deleting participations for rooms`);
736
+ await tx.delete(participantTable).where(inArray(participantTable.roomId, roomIds));
737
+ logger.debug(`[DB] Participations deleted for rooms`);
738
+ }
739
+ logger.debug(`[DB] Deleting agent participations`);
740
+ await tx.delete(participantTable).where(eq(participantTable.agentId, agentId));
741
+ logger.debug(`[DB] Agent participations deleted`);
742
+ if (roomIds.length > 0) {
743
+ logger.debug(`[DB] Deleting rooms`);
744
+ await tx.delete(roomTable).where(inArray(roomTable.id, roomIds));
745
+ logger.debug(`[DB] Rooms deleted successfully`);
746
+ }
747
+ logger.debug(`[DB] Deleting cache entries`);
748
+ await tx.delete(cacheTable).where(eq(cacheTable.agentId, agentId));
749
+ logger.debug(`[DB] Cache entries deleted successfully`);
750
+ logger.debug(`[DB] Deleting relationships`);
751
+ if (entityIds.length > 0) {
752
+ await tx.delete(relationshipTable).where(inArray(relationshipTable.sourceEntityId, entityIds));
753
+ await tx.delete(relationshipTable).where(inArray(relationshipTable.targetEntityId, entityIds));
754
+ }
755
+ await tx.delete(relationshipTable).where(eq(relationshipTable.agentId, agentId));
756
+ logger.debug(`[DB] Relationships deleted successfully`);
757
+ if (entityIds.length > 0) {
758
+ logger.debug(`[DB] Deleting entities`);
759
+ await tx.delete(entityTable).where(eq(entityTable.agentId, agentId));
760
+ logger.debug(`[DB] Entities deleted successfully`);
761
+ }
762
+ logger.debug(`[DB] Checking for world references`);
763
+ const worlds = await tx.select({ id: worldTable.id }).from(worldTable).where(eq(worldTable.agentId, agentId));
764
+ if (worlds.length > 0) {
765
+ const newAgent = await tx.select({ newAgentId: agentTable.id }).from(agentTable).where(not(eq(agentTable.id, agentId))).limit(1);
766
+ if (newAgent.length > 0) {
767
+ await tx.update(worldTable).set({ agentId: newAgent[0].newAgentId }).where(eq(worldTable.agentId, agentId));
768
+ } else {
769
+ const worldIds = worlds.map((w) => w.id);
770
+ logger.debug(`[DB] Found ${worldIds.length} worlds to delete`);
771
+ await tx.delete(worldTable).where(inArray(worldTable.id, worldIds));
772
+ logger.debug(`[DB] Worlds deleted successfully`);
773
+ }
774
+ } else {
775
+ logger.debug(`[DB] No worlds found for this agent`);
776
+ }
777
+ logger.debug(`[DB] Deleting agent ${agentId}`);
778
+ await tx.delete(agentTable).where(eq(agentTable.id, agentId));
779
+ logger.debug(`[DB] Agent deleted successfully`);
780
+ resolve(true);
781
+ } catch (error) {
782
+ logger.error(`[DB] Error in transaction:`, error);
783
+ reject(error);
784
+ }
785
+ }).catch((transactionError) => {
786
+ clearTimeout(timeoutId);
787
+ reject(transactionError);
788
+ });
789
+ });
790
+ await deletePromise;
791
+ logger.success(`[DB] Agent ${agentId} successfully deleted`);
792
+ return true;
793
+ } catch (error) {
794
+ logger.error(`[DB] Error in database transaction for agent deletion ${agentId}:`, error);
795
+ if (error instanceof Error) {
796
+ logger.error(`[DB] Error name: ${error.name}, message: ${error.message}`);
797
+ logger.error(`[DB] Error stack: ${error.stack}`);
798
+ }
799
+ throw error;
800
+ }
801
+ });
802
+ }
803
+ /**
804
+ * Count all agents in the database
805
+ * Used primarily for maintenance and cleanup operations
806
+ */
807
+ /**
808
+ * Asynchronously counts the number of agents in the database.
809
+ * @returns {Promise<number>} A Promise that resolves to the number of agents in the database.
810
+ */
811
+ async countAgents() {
812
+ return this.withDatabase(async () => {
813
+ try {
814
+ const result = await this.db.select({ count: count() }).from(agentTable);
815
+ return result[0]?.count || 0;
816
+ } catch (error) {
817
+ logger.error("Error counting agents:", {
818
+ error: error instanceof Error ? error.message : String(error)
819
+ });
820
+ return 0;
821
+ }
822
+ });
823
+ }
824
+ /**
825
+ * Clean up the agents table by removing all agents
826
+ * This is used during server startup to ensure no orphaned agents exist
827
+ * from previous crashes or improper shutdowns
828
+ */
829
+ async cleanupAgents() {
830
+ return this.withDatabase(async () => {
831
+ try {
832
+ await this.db.delete(agentTable);
833
+ logger.success("Successfully cleaned up agent table");
834
+ } catch (error) {
835
+ logger.error("Error cleaning up agent table:", {
836
+ error: error instanceof Error ? error.message : String(error)
837
+ });
838
+ throw error;
839
+ }
840
+ });
841
+ }
842
+ /**
843
+ * Asynchronously retrieves an entity and its components by entity ID.
844
+ * @param {UUID} entityId - The unique identifier of the entity to retrieve.
845
+ * @returns {Promise<Entity | null>} A Promise that resolves to the entity with its components if found, null otherwise.
846
+ */
847
+ async getEntityById(entityId) {
848
+ return this.withDatabase(async () => {
849
+ const result = await this.db.select({
850
+ entity: entityTable,
851
+ components: componentTable
852
+ }).from(entityTable).leftJoin(componentTable, eq(componentTable.entityId, entityTable.id)).where(eq(entityTable.id, entityId));
853
+ if (result.length === 0) return null;
854
+ const entity = result[0].entity;
855
+ entity.components = result.filter((row) => row.components).map((row) => row.components);
856
+ return entity;
857
+ });
858
+ }
859
+ /**
860
+ * Asynchronously retrieves all entities for a given room, optionally including their components.
861
+ * @param {UUID} roomId - The unique identifier of the room to get entities for
862
+ * @param {boolean} [includeComponents] - Whether to include component data for each entity
863
+ * @returns {Promise<Entity[]>} A Promise that resolves to an array of entities in the room
864
+ */
865
+ async getEntitiesForRoom(roomId, includeComponents) {
866
+ return this.withDatabase(async () => {
867
+ const query = this.db.select({
868
+ entity: entityTable,
869
+ ...includeComponents && { components: componentTable }
870
+ }).from(participantTable).leftJoin(
871
+ entityTable,
872
+ and(eq(participantTable.entityId, entityTable.id), eq(entityTable.agentId, this.agentId))
873
+ );
874
+ if (includeComponents) {
875
+ query.leftJoin(componentTable, eq(componentTable.entityId, entityTable.id));
876
+ }
877
+ const result = await query.where(eq(participantTable.roomId, roomId));
878
+ const entitiesByIdMap = /* @__PURE__ */ new Map();
879
+ for (const row of result) {
880
+ if (!row.entity) continue;
881
+ const entityId = row.entity.id;
882
+ if (!entitiesByIdMap.has(entityId)) {
883
+ const entity = {
884
+ ...row.entity,
885
+ components: includeComponents ? [] : void 0
886
+ };
887
+ entitiesByIdMap.set(entityId, entity);
888
+ }
889
+ if (includeComponents && row.components) {
890
+ const entity = entitiesByIdMap.get(entityId);
891
+ if (entity) {
892
+ if (!entity.components) {
893
+ entity.components = [];
894
+ }
895
+ entity.components.push(row.components);
896
+ }
897
+ }
898
+ }
899
+ return Array.from(entitiesByIdMap.values());
900
+ });
901
+ }
902
+ /**
903
+ * Asynchronously creates a new entity in the database.
904
+ * @param {Entity} entity - The entity object to be created.
905
+ * @returns {Promise<boolean>} A Promise that resolves to a boolean indicating the success of the operation.
906
+ */
907
+ async createEntity(entity) {
908
+ return this.withDatabase(async () => {
909
+ try {
910
+ return await this.db.transaction(async (tx) => {
911
+ await tx.insert(entityTable).values(entity);
912
+ logger.debug("Entity created successfully:", {
913
+ entity
914
+ });
915
+ return true;
916
+ });
917
+ } catch (error) {
918
+ logger.error("Error creating entity:", {
919
+ error: error instanceof Error ? error.message : String(error),
920
+ entityId: entity.id,
921
+ name: entity.metadata?.name
922
+ });
923
+ logger.trace(error);
924
+ return false;
925
+ }
926
+ });
927
+ }
928
+ /**
929
+ * Asynchronously ensures an entity exists, creating it if it doesn't
930
+ * @param entity The entity to ensure exists
931
+ * @returns Promise resolving to boolean indicating success
932
+ */
933
+ async ensureEntityExists(entity) {
934
+ if (!entity.id) {
935
+ logger.error("Entity ID is required for ensureEntityExists");
936
+ return false;
937
+ }
938
+ try {
939
+ const existingEntity = await this.getEntityById(entity.id);
940
+ if (!existingEntity) {
941
+ return await this.createEntity(entity);
942
+ }
943
+ return true;
944
+ } catch (error) {
945
+ logger.error("Error ensuring entity exists:", {
946
+ error: error instanceof Error ? error.message : String(error),
947
+ entityId: entity.id
948
+ });
949
+ return false;
950
+ }
951
+ }
952
+ /**
953
+ * Asynchronously updates an entity in the database.
954
+ * @param {Entity} entity - The entity object to be updated.
955
+ * @returns {Promise<void>} A Promise that resolves when the entity is updated.
956
+ */
957
+ async updateEntity(entity) {
958
+ return this.withDatabase(async () => {
959
+ await this.db.update(entityTable).set(entity).where(and(eq(entityTable.id, entity.id), eq(entityTable.agentId, entity.agentId)));
960
+ });
961
+ }
962
+ async getComponent(entityId, type, worldId, sourceEntityId) {
963
+ return this.withDatabase(async () => {
964
+ const conditions = [eq(componentTable.entityId, entityId), eq(componentTable.type, type)];
965
+ if (worldId) {
966
+ conditions.push(eq(componentTable.worldId, worldId));
967
+ }
968
+ if (sourceEntityId) {
969
+ conditions.push(eq(componentTable.sourceEntityId, sourceEntityId));
970
+ }
971
+ const result = await this.db.select().from(componentTable).where(and(...conditions));
972
+ return result.length > 0 ? result[0] : null;
973
+ });
974
+ }
975
+ /**
976
+ * Asynchronously retrieves all components for a given entity, optionally filtered by world and source entity.
977
+ * @param {UUID} entityId - The unique identifier of the entity to retrieve components for
978
+ * @param {UUID} [worldId] - Optional world ID to filter components by
979
+ * @param {UUID} [sourceEntityId] - Optional source entity ID to filter components by
980
+ * @returns {Promise<Component[]>} A Promise that resolves to an array of components
981
+ */
982
+ async getComponents(entityId, worldId, sourceEntityId) {
983
+ return this.withDatabase(async () => {
984
+ const conditions = [eq(componentTable.entityId, entityId)];
985
+ if (worldId) {
986
+ conditions.push(eq(componentTable.worldId, worldId));
987
+ }
988
+ if (sourceEntityId) {
989
+ conditions.push(eq(componentTable.sourceEntityId, sourceEntityId));
990
+ }
991
+ const result = await this.db.select({
992
+ id: componentTable.id,
993
+ entityId: componentTable.entityId,
994
+ type: componentTable.type,
995
+ data: componentTable.data,
996
+ worldId: componentTable.worldId,
997
+ sourceEntityId: componentTable.sourceEntityId,
998
+ createdAt: componentTable.createdAt
999
+ }).from(componentTable).where(and(...conditions));
1000
+ return result;
1001
+ });
1002
+ }
1003
+ /**
1004
+ * Asynchronously creates a new component in the database.
1005
+ * @param {Component} component - The component object to be created.
1006
+ * @returns {Promise<boolean>} A Promise that resolves to a boolean indicating the success of the operation.
1007
+ */
1008
+ async createComponent(component) {
1009
+ return this.withDatabase(async () => {
1010
+ await this.db.insert(componentTable).values(component);
1011
+ return true;
1012
+ });
1013
+ }
1014
+ /**
1015
+ * Asynchronously updates an existing component in the database.
1016
+ * @param {Component} component - The component object to be updated.
1017
+ * @returns {Promise<void>} A Promise that resolves when the component is updated.
1018
+ */
1019
+ async updateComponent(component) {
1020
+ return this.withDatabase(async () => {
1021
+ await this.db.update(componentTable).set(component).where(eq(componentTable.id, component.id));
1022
+ });
1023
+ }
1024
+ /**
1025
+ * Asynchronously deletes a component from the database.
1026
+ * @param {UUID} componentId - The unique identifier of the component to delete.
1027
+ * @returns {Promise<void>} A Promise that resolves when the component is deleted.
1028
+ */
1029
+ async deleteComponent(componentId) {
1030
+ return this.withDatabase(async () => {
1031
+ await this.db.delete(componentTable).where(eq(componentTable.id, componentId));
1032
+ });
1033
+ }
1034
+ /**
1035
+ * Asynchronously retrieves memories from the database based on the provided parameters.
1036
+ * @param {Object} params - The parameters for retrieving memories.
1037
+ * @param {UUID} params.roomId - The ID of the room to retrieve memories for.
1038
+ * @param {number} [params.count] - The maximum number of memories to retrieve.
1039
+ * @param {boolean} [params.unique] - Whether to retrieve unique memories only.
1040
+ * @param {string} [params.tableName] - The name of the table to retrieve memories from.
1041
+ * @param {number} [params.start] - The start date to retrieve memories from.
1042
+ * @param {number} [params.end] - The end date to retrieve memories from.
1043
+ * @returns {Promise<Memory[]>} A Promise that resolves to an array of memories.
1044
+ */
1045
+ async getMemories(params) {
1046
+ const { entityId, agentId, roomId, worldId, tableName, count: count2, unique: unique7, start, end } = params;
1047
+ if (!tableName) throw new Error("tableName is required");
1048
+ return this.withDatabase(async () => {
1049
+ const conditions = [eq(memoryTable.type, tableName)];
1050
+ if (start) {
1051
+ conditions.push(gte(memoryTable.createdAt, start));
1052
+ }
1053
+ if (entityId) {
1054
+ conditions.push(eq(memoryTable.entityId, entityId));
1055
+ }
1056
+ if (roomId) {
1057
+ conditions.push(eq(memoryTable.roomId, roomId));
1058
+ }
1059
+ if (worldId) {
1060
+ conditions.push(eq(memoryTable.worldId, worldId));
1061
+ }
1062
+ if (end) {
1063
+ conditions.push(lte(memoryTable.createdAt, end));
1064
+ }
1065
+ if (unique7) {
1066
+ conditions.push(eq(memoryTable.unique, true));
1067
+ }
1068
+ if (agentId) {
1069
+ conditions.push(eq(memoryTable.agentId, agentId));
1070
+ }
1071
+ const query = this.db.select({
1072
+ memory: {
1073
+ id: memoryTable.id,
1074
+ type: memoryTable.type,
1075
+ createdAt: memoryTable.createdAt,
1076
+ content: memoryTable.content,
1077
+ entityId: memoryTable.entityId,
1078
+ agentId: memoryTable.agentId,
1079
+ roomId: memoryTable.roomId,
1080
+ unique: memoryTable.unique,
1081
+ metadata: memoryTable.metadata
1082
+ },
1083
+ embedding: embeddingTable[this.embeddingDimension]
1084
+ }).from(memoryTable).leftJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(and(...conditions)).orderBy(desc(memoryTable.createdAt));
1085
+ const rows = params.count ? await query.limit(params.count) : await query;
1086
+ return rows.map((row) => ({
1087
+ id: row.memory.id,
1088
+ type: row.memory.type,
1089
+ createdAt: row.memory.createdAt,
1090
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
1091
+ entityId: row.memory.entityId,
1092
+ agentId: row.memory.agentId,
1093
+ roomId: row.memory.roomId,
1094
+ unique: row.memory.unique,
1095
+ metadata: row.memory.metadata,
1096
+ embedding: row.embedding ? Array.from(row.embedding) : void 0
1097
+ }));
1098
+ });
1099
+ }
1100
+ /**
1101
+ * Asynchronously retrieves memories from the database based on the provided parameters.
1102
+ * @param {Object} params - The parameters for retrieving memories.
1103
+ * @param {UUID[]} params.roomIds - The IDs of the rooms to retrieve memories for.
1104
+ * @param {string} params.tableName - The name of the table to retrieve memories from.
1105
+ * @param {number} [params.limit] - The maximum number of memories to retrieve.
1106
+ * @returns {Promise<Memory[]>} A Promise that resolves to an array of memories.
1107
+ */
1108
+ async getMemoriesByRoomIds(params) {
1109
+ return this.withDatabase(async () => {
1110
+ if (params.roomIds.length === 0) return [];
1111
+ const conditions = [
1112
+ eq(memoryTable.type, params.tableName),
1113
+ inArray(memoryTable.roomId, params.roomIds)
1114
+ ];
1115
+ conditions.push(eq(memoryTable.agentId, this.agentId));
1116
+ const query = this.db.select({
1117
+ id: memoryTable.id,
1118
+ type: memoryTable.type,
1119
+ createdAt: memoryTable.createdAt,
1120
+ content: memoryTable.content,
1121
+ entityId: memoryTable.entityId,
1122
+ agentId: memoryTable.agentId,
1123
+ roomId: memoryTable.roomId,
1124
+ unique: memoryTable.unique,
1125
+ metadata: memoryTable.metadata
1126
+ }).from(memoryTable).where(and(...conditions)).orderBy(desc(memoryTable.createdAt));
1127
+ const rows = params.limit ? await query.limit(params.limit) : await query;
1128
+ return rows.map((row) => ({
1129
+ id: row.id,
1130
+ createdAt: row.createdAt,
1131
+ content: typeof row.content === "string" ? JSON.parse(row.content) : row.content,
1132
+ entityId: row.entityId,
1133
+ agentId: row.agentId,
1134
+ roomId: row.roomId,
1135
+ unique: row.unique,
1136
+ metadata: row.metadata
1137
+ }));
1138
+ });
1139
+ }
1140
+ /**
1141
+ * Asynchronously retrieves a memory by its unique identifier.
1142
+ * @param {UUID} id - The unique identifier of the memory to retrieve.
1143
+ * @returns {Promise<Memory | null>} A Promise that resolves to the memory if found, null otherwise.
1144
+ */
1145
+ async getMemoryById(id) {
1146
+ return this.withDatabase(async () => {
1147
+ const result = await this.db.select({
1148
+ memory: memoryTable,
1149
+ embedding: embeddingTable[this.embeddingDimension]
1150
+ }).from(memoryTable).leftJoin(embeddingTable, eq(memoryTable.id, embeddingTable.memoryId)).where(eq(memoryTable.id, id)).limit(1);
1151
+ if (result.length === 0) return null;
1152
+ const row = result[0];
1153
+ return {
1154
+ id: row.memory.id,
1155
+ createdAt: row.memory.createdAt,
1156
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
1157
+ entityId: row.memory.entityId,
1158
+ agentId: row.memory.agentId,
1159
+ roomId: row.memory.roomId,
1160
+ unique: row.memory.unique,
1161
+ embedding: row.embedding ?? void 0
1162
+ };
1163
+ });
1164
+ }
1165
+ /**
1166
+ * Asynchronously retrieves memories from the database based on the provided parameters.
1167
+ * @param {Object} params - The parameters for retrieving memories.
1168
+ * @param {UUID[]} params.memoryIds - The IDs of the memories to retrieve.
1169
+ * @param {string} [params.tableName] - The name of the table to retrieve memories from.
1170
+ * @returns {Promise<Memory[]>} A Promise that resolves to an array of memories.
1171
+ */
1172
+ async getMemoriesByIds(memoryIds, tableName) {
1173
+ return this.withDatabase(async () => {
1174
+ if (memoryIds.length === 0) return [];
1175
+ const conditions = [inArray(memoryTable.id, memoryIds)];
1176
+ if (tableName) {
1177
+ conditions.push(eq(memoryTable.type, tableName));
1178
+ }
1179
+ const rows = await this.db.select({
1180
+ memory: memoryTable,
1181
+ embedding: embeddingTable[this.embeddingDimension]
1182
+ }).from(memoryTable).leftJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(and(...conditions)).orderBy(desc(memoryTable.createdAt));
1183
+ return rows.map((row) => ({
1184
+ id: row.memory.id,
1185
+ createdAt: row.memory.createdAt,
1186
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
1187
+ entityId: row.memory.entityId,
1188
+ agentId: row.memory.agentId,
1189
+ roomId: row.memory.roomId,
1190
+ unique: row.memory.unique,
1191
+ metadata: row.memory.metadata,
1192
+ embedding: row.embedding ?? void 0
1193
+ }));
1194
+ });
1195
+ }
1196
+ /**
1197
+ * Asynchronously retrieves cached embeddings from the database based on the provided parameters.
1198
+ * @param {Object} opts - The parameters for retrieving cached embeddings.
1199
+ * @param {string} opts.query_table_name - The name of the table to retrieve embeddings from.
1200
+ * @param {number} opts.query_threshold - The threshold for the levenshtein distance.
1201
+ * @param {string} opts.query_input - The input string to search for.
1202
+ * @param {string} opts.query_field_name - The name of the field to retrieve embeddings from.
1203
+ * @param {string} opts.query_field_sub_name - The name of the sub-field to retrieve embeddings from.
1204
+ * @param {number} opts.query_match_count - The maximum number of matches to retrieve.
1205
+ * @returns {Promise<{ embedding: number[]; levenshtein_score: number }[]>} A Promise that resolves to an array of cached embeddings.
1206
+ */
1207
+ async getCachedEmbeddings(opts) {
1208
+ return this.withDatabase(async () => {
1209
+ try {
1210
+ const results = await this.db.execute(sql12`
15
1211
  WITH content_text AS (
16
1212
  SELECT
17
1213
  m.id,
18
1214
  COALESCE(
19
- m.content->>${e.query_field_sub_name},
1215
+ m.content->>${opts.query_field_sub_name},
20
1216
  ''
21
1217
  ) as content_text
22
1218
  FROM memories m
23
- WHERE m.type = ${e.query_table_name}
24
- AND m.content->>${e.query_field_sub_name} IS NOT NULL
1219
+ WHERE m.type = ${opts.query_table_name}
1220
+ AND m.content->>${opts.query_field_sub_name} IS NOT NULL
25
1221
  ),
26
1222
  embedded_text AS (
27
1223
  SELECT
@@ -40,10 +1236,1287 @@ import{a as x,b as ge,c as ye}from"./chunk-K7ZVMPCJ.js";import*as ke from"node:o
40
1236
  )
41
1237
  SELECT
42
1238
  embedding,
43
- levenshtein(${e.query_input}, content_text) as levenshtein_score
1239
+ levenshtein(${opts.query_input}, content_text) as levenshtein_score
44
1240
  FROM embedded_text
45
- WHERE levenshtein(${e.query_input}, content_text) <= ${e.query_threshold}
1241
+ WHERE levenshtein(${opts.query_input}, content_text) <= ${opts.query_threshold}
46
1242
  ORDER BY levenshtein_score
47
- LIMIT ${e.query_match_count}
48
- `)).rows.map(r=>({embedding:Array.isArray(r.embedding)?r.embedding:typeof r.embedding=="string"?JSON.parse(r.embedding):[],levenshtein_score:Number(r.levenshtein_score)})).filter(r=>Array.isArray(r.embedding))}catch(t){if(o.error("Error in getCachedEmbeddings:",{error:t instanceof Error?t.message:String(t),tableName:e.query_table_name,fieldName:e.query_field_name}),t instanceof Error&&t.message==="levenshtein argument exceeds maximum length of 255 characters")return[];throw t}})}async log(e){return this.withDatabase(async()=>{try{await this.db.transaction(async t=>{await t.insert(N).values({body:M`${e.body}::jsonb`,entityId:e.entityId,roomId:e.roomId,type:e.type})})}catch(t){throw o.error("Failed to create log entry:",{error:t instanceof Error?t.message:String(t),type:e.type,roomId:e.roomId,entityId:e.entityId}),t}})}async getLogs(e){let{entityId:t,roomId:r,type:i,count:s,offset:d}=e;return this.withDatabase(async()=>await this.db.select().from(N).where(w(n(N.entityId,t),r?n(N.roomId,r):void 0,i?n(N.type,i):void 0)).orderBy(z(N.createdAt)).limit(s??10).offset(d??0))}async deleteLog(e){return this.withDatabase(async()=>{await this.db.delete(N).where(n(N.id,e))})}async searchMemories(e){return await this.searchMemoriesByEmbedding(e.embedding,{match_threshold:e.match_threshold,count:e.count,roomId:e.roomId,worldId:e.worldId,entityId:e.entityId,unique:e.unique,tableName:e.tableName})}async searchMemoriesByEmbedding(e,t){return this.withDatabase(async()=>{let r=e.map(y=>Number.isFinite(y)?Number(y.toFixed(6)):0),i=M`1 - (${Nt(l[this.embeddingDimension],r)})`,s=[n(a.type,t.tableName)];return t.unique&&s.push(n(a.unique,!0)),s.push(n(a.agentId,this.agentId)),t.roomId&&s.push(n(a.roomId,t.roomId)),t.worldId&&s.push(n(a.worldId,t.worldId)),t.entityId&&s.push(n(a.entityId,t.entityId)),t.match_threshold&&s.push(xe(i,t.match_threshold)),(await this.db.select({memory:a,similarity:i,embedding:l[this.embeddingDimension]}).from(l).innerJoin(a,n(a.id,l.memoryId)).where(w(...s)).orderBy(z(i)).limit(t.count??10)).map(y=>({id:y.memory.id,type:y.memory.type,createdAt:y.memory.createdAt,content:typeof y.memory.content=="string"?JSON.parse(y.memory.content):y.memory.content,entityId:y.memory.entityId,agentId:y.memory.agentId,roomId:y.memory.roomId,worldId:y.memory.worldId,unique:y.memory.unique,metadata:y.memory.metadata,embedding:y.embedding??void 0,similarity:y.similarity}))})}async createMemory(e,t){o.debug("DrizzleAdapter createMemory:",{memoryId:e.id,embeddingLength:e.embedding?.length,contentLength:e.content?.text?.length});let r=e.id??O();if(await this.getMemoryById(r))return o.debug("Memory already exists, skipping creation:",{memoryId:r}),r;let s=!0;e.embedding&&Array.isArray(e.embedding)&&(s=(await this.searchMemoriesByEmbedding(e.embedding,{tableName:t,roomId:e.roomId,worldId:e.worldId,entityId:e.entityId,match_threshold:.95,count:1})).length===0);let d=typeof e.content=="string"?JSON.parse(e.content):e.content;return await this.db.transaction(async y=>{if(await y.insert(a).values([{id:r,type:t,content:M`${d}::jsonb`,metadata:M`${e.metadata||{}}::jsonb`,entityId:e.entityId,roomId:e.roomId,worldId:e.worldId,agentId:e.agentId,unique:e.unique??s,createdAt:e.createdAt}]),e.embedding&&Array.isArray(e.embedding)){let I={id:O(),memoryId:r,createdAt:e.createdAt},R=e.embedding.map(A=>Number.isFinite(A)?Number(A.toFixed(6)):0);I[this.embeddingDimension]=R,await y.insert(l).values([I])}}),r}async updateMemory(e){return this.withDatabase(async()=>{try{return o.debug("Updating memory:",{memoryId:e.id,hasEmbedding:!!e.embedding}),await this.db.transaction(async t=>{if(e.content){let r=typeof e.content=="string"?JSON.parse(e.content):e.content;await t.update(a).set({content:M`${r}::jsonb`,...e.metadata&&{metadata:M`${e.metadata}::jsonb`}}).where(n(a.id,e.id))}else e.metadata&&await t.update(a).set({metadata:M`${e.metadata}::jsonb`}).where(n(a.id,e.id));if(e.embedding&&Array.isArray(e.embedding)){let r=e.embedding.map(s=>Number.isFinite(s)?Number(s.toFixed(6)):0);if((await t.select({id:l.id}).from(l).where(n(l.memoryId,e.id)).limit(1)).length>0){let s={};s[this.embeddingDimension]=r,await t.update(l).set(s).where(n(l.memoryId,e.id))}else{let s={id:O(),memoryId:e.id,createdAt:Date.now()};s[this.embeddingDimension]=r,await t.insert(l).values([s])}}}),o.debug("Memory updated successfully:",{memoryId:e.id}),!0}catch(t){return o.error("Error updating memory:",{error:t instanceof Error?t.message:String(t),memoryId:e.id}),!1}})}async deleteMemory(e){return this.withDatabase(async()=>{await this.db.transaction(async t=>{await this.deleteMemoryFragments(t,e),await t.delete(l).where(n(l.memoryId,e)),await t.delete(a).where(n(a.id,e))}),o.debug("Memory and related fragments removed successfully:",{memoryId:e})})}async deleteMemoryFragments(e,t){let r=await this.getMemoryFragments(e,t);if(r.length>0){let i=r.map(s=>s.id);await e.delete(l).where(D(l.memoryId,i)),await e.delete(a).where(D(a.id,i)),o.debug("Deleted related fragments:",{documentId:t,fragmentCount:r.length})}}async getMemoryFragments(e,t){return await e.select({id:a.id}).from(a).where(w(n(a.agentId,this.agentId),M`${a.metadata}->>'documentId' = ${t}`))}async deleteAllMemories(e,t){return this.withDatabase(async()=>{await this.db.transaction(async r=>{let i=await r.select({id:a.id}).from(a).where(w(n(a.roomId,e),n(a.type,t)));i.length>0&&(await r.delete(l).where(D(l.memoryId,i.map(s=>s.id))),await r.delete(a).where(w(n(a.roomId,e),n(a.type,t))))}),o.debug("All memories removed successfully:",{roomId:e,tableName:t})})}async countMemories(e,t=!0,r=""){if(!r)throw new Error("tableName is required");return this.withDatabase(async()=>{let i=[n(a.roomId,e),n(a.type,r)];t&&i.push(n(a.unique,!0));let s=await this.db.select({count:M`count(*)`}).from(a).where(w(...i));return Number(s[0]?.count??0)})}async getRoom(e){return this.withDatabase(async()=>{let t=await this.db.select({id:c.id,channelId:c.channelId,agentId:c.agentId,serverId:c.serverId,worldId:c.worldId,type:c.type,source:c.source}).from(c).where(w(n(c.id,e),n(c.agentId,this.agentId))).limit(1);return t.length===0?null:t[0]})}async getRooms(e){return this.withDatabase(async()=>await this.db.select().from(c).where(n(c.worldId,e)))}async updateRoom(e){return this.withDatabase(async()=>{await this.db.update(c).set({...e,agentId:this.agentId}).where(n(c.id,e.id))})}async createRoom({id:e,name:t,agentId:r,source:i,type:s,channelId:d,serverId:y,worldId:I,metadata:R}){return this.withDatabase(async()=>{let A=e||O();return await this.db.insert(c).values({id:A,name:t,agentId:r,source:i,type:s,channelId:d,serverId:y,worldId:I,metadata:R}).onConflictDoNothing({target:c.id}),A})}async deleteRoom(e){if(!e)throw new Error("Room ID is required");return this.withDatabase(async()=>{await this.db.transaction(async t=>{await t.delete(c).where(n(c.id,e))})})}async getRoomsForParticipant(e){return this.withDatabase(async()=>(await this.db.select({roomId:u.roomId}).from(u).innerJoin(c,n(u.roomId,c.id)).where(w(n(u.entityId,e),n(c.agentId,this.agentId)))).map(r=>r.roomId))}async getRoomsForParticipants(e){return this.withDatabase(async()=>(await this.db.selectDistinct({roomId:u.roomId}).from(u).innerJoin(c,n(u.roomId,c.id)).where(w(D(u.entityId,e),n(c.agentId,this.agentId)))).map(r=>r.roomId))}async addParticipant(e,t){return this.withDatabase(async()=>{try{return await this.db.insert(u).values({entityId:e,roomId:t,agentId:this.agentId}).onConflictDoNothing(),!0}catch(r){return o.error("Error adding participant",{error:r instanceof Error?r.message:String(r),entityId:e,roomId:t,agentId:this.agentId}),!1}})}async removeParticipant(e,t){return this.withDatabase(async()=>{try{let i=(await this.db.transaction(async s=>await s.delete(u).where(w(n(u.entityId,e),n(u.roomId,t))).returning())).length>0;return o.debug(`Participant ${i?"removed":"not found"}:`,{entityId:e,roomId:t,removed:i}),i}catch(r){return o.error("Failed to remove participant:",{error:r instanceof Error?r.message:String(r),entityId:e,roomId:t}),!1}})}async getParticipantsForEntity(e){return this.withDatabase(async()=>{let t=await this.db.select({id:u.id,entityId:u.entityId,roomId:u.roomId}).from(u).where(n(u.entityId,e)),r=await this.getEntityById(e);return r?t.map(i=>({id:i.id,entity:r})):[]})}async getParticipantsForRoom(e){return this.withDatabase(async()=>(await this.db.select({entityId:u.entityId}).from(u).where(n(u.roomId,e))).map(r=>r.entityId))}async getParticipantUserState(e,t){return this.withDatabase(async()=>(await this.db.select({roomState:u.roomState}).from(u).where(w(n(u.roomId,e),n(u.entityId,t),n(u.agentId,this.agentId))).limit(1))[0]?.roomState??null)}async setParticipantUserState(e,t,r){return this.withDatabase(async()=>{try{await this.db.transaction(async i=>{await i.update(u).set({roomState:r}).where(w(n(u.roomId,e),n(u.entityId,t),n(u.agentId,this.agentId)))})}catch(i){throw o.error("Failed to set participant user state:",{roomId:e,entityId:t,state:r,error:i instanceof Error?i.message:String(i)}),i}})}async createRelationship(e){return this.withDatabase(async()=>{let r={id:O(),sourceEntityId:e.sourceEntityId,targetEntityId:e.targetEntityId,agentId:this.agentId,tags:e.tags||[],metadata:e.metadata||{}};try{return await this.db.insert(_).values(r),!0}catch(i){return o.error("Error creating relationship:",{error:i instanceof Error?i.message:String(i),saveParams:r}),!1}})}async updateRelationship(e){return this.withDatabase(async()=>{try{await this.db.update(_).set({tags:e.tags||[],metadata:e.metadata||{}}).where(n(_.id,e.id))}catch(t){throw o.error("Error updating relationship:",{error:t instanceof Error?t.message:String(t),relationship:e}),t}})}async getRelationship(e){return this.withDatabase(async()=>{try{let t=await this.db.select().from(_).where(w(n(_.sourceEntityId,e.sourceEntityId),n(_.targetEntityId,e.targetEntityId),n(_.agentId,this.agentId))).limit(1);return t.length===0?null:{id:t[0].id,sourceEntityId:t[0].sourceEntityId,targetEntityId:t[0].targetEntityId,agentId:t[0].agentId,tags:t[0].tags||[],metadata:t[0].metadata||{},createdAt:t[0].createdAt?.toString()}}catch(t){return o.error("Error getting relationship:",{error:t instanceof Error?t.message:String(t),params:e}),null}})}async getRelationships(e){return this.withDatabase(async()=>{try{let t=this.db.select().from(_).where(w(vt(n(_.sourceEntityId,e.entityId),n(_.targetEntityId,e.entityId)),n(_.agentId,this.agentId)));if(e.tags&&e.tags.length>0){let i=e.tags.map(s=>`'${s.replace(/'/g,"''")}'`).join(", ");t=t.where(M`${_.tags} @> ARRAY[${M.raw(i)}]::text[]`)}return(await t).map(i=>({id:i.id,sourceEntityId:i.sourceEntityId,targetEntityId:i.targetEntityId,agentId:i.agentId,tags:i.tags||[],metadata:i.metadata||{},createdAt:i.createdAt?.toString()}))}catch(t){return o.error("Error getting relationships:",{error:t instanceof Error?t.message:String(t),params:e}),[]}})}async getCache(e){return this.withDatabase(async()=>{try{return(await this.db.select().from(S).where(w(n(S.agentId,this.agentId),n(S.key,e))))[0]?.value}catch(t){o.error("Error fetching cache",{error:t instanceof Error?t.message:String(t),key:e,agentId:this.agentId});return}})}async setCache(e,t){return this.withDatabase(async()=>{try{return await this.db.transaction(async r=>{await r.insert(S).values({key:e,agentId:this.agentId,value:t}).onConflictDoUpdate({target:[S.key,S.agentId],set:{value:t}})}),!0}catch(r){return o.error("Error setting cache",{error:r instanceof Error?r.message:String(r),key:e,agentId:this.agentId}),!1}})}async deleteCache(e){return this.withDatabase(async()=>{try{return await this.db.transaction(async t=>{await t.delete(S).where(w(n(S.agentId,this.agentId),n(S.key,e)))}),!0}catch(t){return o.error("Error deleting cache",{error:t instanceof Error?t.message:String(t),key:e,agentId:this.agentId}),!1}})}async createWorld(e){return this.withDatabase(async()=>{let t=e.id||O();return await this.db.insert(E).values({...e,id:t}),t})}async getWorld(e){return this.withDatabase(async()=>(await this.db.select().from(E).where(n(E.id,e)))[0])}async getAllWorlds(){return this.withDatabase(async()=>await this.db.select().from(E).where(n(E.agentId,this.agentId)))}async updateWorld(e){return this.withDatabase(async()=>{await this.db.update(E).set(e).where(n(E.id,e.id))})}async removeWorld(e){return this.withDatabase(async()=>{await this.db.delete(E).where(n(E.id,e))})}async createTask(e){return this.withRetry(async()=>this.withDatabase(async()=>{let t=new Date,r=e.metadata||{},i={id:e.id,name:e.name,description:e.description,roomId:e.roomId,worldId:e.worldId,tags:e.tags,metadata:r,createdAt:t,updatedAt:t,agentId:this.agentId};return(await this.db.insert(P).values(i).returning({id:P.id}))[0].id}))}async getTasks(e){return this.withRetry(async()=>this.withDatabase(async()=>{let t=this.db.select().from(P).where(n(P.agentId,this.agentId));if(e.roomId&&(t=t.where(n(P.roomId,e.roomId))),e.tags&&e.tags.length>0){let i=e.tags.map(s=>`'${s.replace(/'/g,"''")}'`).join(", ");t=t.where(M`${P.tags} @> ARRAY[${M.raw(i)}]::text[]`)}return(await t).map(i=>({id:i.id,name:i.name,description:i.description,roomId:i.roomId,worldId:i.worldId,tags:i.tags,metadata:i.metadata}))}))}async getTasksByName(e){return this.withRetry(async()=>this.withDatabase(async()=>(await this.db.select().from(P).where(w(n(P.name,e),n(P.agentId,this.agentId)))).map(r=>({id:r.id,name:r.name,description:r.description,roomId:r.roomId,worldId:r.worldId,tags:r.tags||[],metadata:r.metadata||{}}))))}async getTask(e){return this.withRetry(async()=>this.withDatabase(async()=>{let t=await this.db.select().from(P).where(w(n(P.id,e),n(P.agentId,this.agentId))).limit(1);if(t.length===0)return null;let r=t[0];return{id:r.id,name:r.name,description:r.description,roomId:r.roomId,worldId:r.worldId,tags:r.tags||[],metadata:r.metadata||{}}}))}async updateTask(e,t){await this.withRetry(async()=>{await this.withDatabase(async()=>{let r={};if(t.name!==void 0&&(r.name=t.name),t.description!==void 0&&(r.description=t.description),t.roomId!==void 0&&(r.roomId=t.roomId),t.worldId!==void 0&&(r.worldId=t.worldId),t.tags!==void 0&&(r.tags=t.tags),t.updatedAt=Date.now(),t.metadata){let i=await this.getTask(e);if(i){let d={...i.metadata||{},...t.metadata};r.metadata=d}else r.metadata={...t.metadata}}await this.db.update(P).set(r).where(w(n(P.id,e),n(P.agentId,this.agentId)))})})}async deleteTask(e){await this.withRetry(async()=>{await this.withDatabase(async()=>{await this.db.delete(P).where(w(n(P.id,e),n(P.agentId,this.agentId)))})})}async getMemoriesByServerId(e){return this.withDatabase(async()=>{let t=await this.db.select({roomId:c.id}).from(c).where(n(c.serverId,e.serverId));if(t.length===0)return[];let r=t.map(d=>d.roomId),i=this.db.select({memory:a,embedding:l[this.embeddingDimension]}).from(a).leftJoin(l,n(l.memoryId,a.id)).where(D(a.roomId,r)).orderBy(z(a.createdAt));return(e.count?await i.limit(e.count):await i).map(d=>({id:d.memory.id,type:d.memory.type,createdAt:d.memory.createdAt,content:typeof d.memory.content=="string"?JSON.parse(d.memory.content):d.memory.content,entityId:d.memory.entityId,agentId:d.memory.agentId,roomId:d.memory.roomId,unique:d.memory.unique,embedding:d.embedding??void 0}))})}async deleteRoomsByServerId(e){return this.withDatabase(async()=>{await this.db.transaction(async t=>{let r=await t.select({roomId:c.id}).from(c).where(n(c.serverId,e));if(r.length===0)return;let i=r.map(s=>s.roomId);await t.delete(l).where(D(l.memoryId,t.select({id:a.id}).from(a).where(D(a.roomId,i)))),await t.delete(a).where(D(a.roomId,i)),await t.delete(u).where(D(u.roomId,i)),await t.delete(N).where(D(N.roomId,i)),await t.delete(c).where(D(c.id,i))}),o.debug("Rooms and related logs deleted successfully for server:",{serverId:e})})}};x(de,"BaseDrizzleAdapter");var J=de;var me=class me extends J{constructor(e,t){super(e);this.embeddingDimension=L[384];this.manager=t,this.db=Bt(this.manager.getConnection())}async withDatabase(e){return this.manager.isShuttingDown()?(Ce.warn("Database is shutting down"),null):e()}async init(){try{await this.manager.runMigrations()}catch(e){throw Ce.error("Failed to initialize database:",e),e}}async close(){await this.manager.close()}};x(me,"PgliteDatabaseAdapter");var ee=me;import{logger as $e}from"@elizaos/core";import{drizzle as Rt}from"drizzle-orm/node-postgres";var ce=class ce extends J{constructor(e,t){super(e);this.manager=t;this.embeddingDimension=L[384];this.manager=t}async withDatabase(e){return await this.withRetry(async()=>{let t=await this.manager.getClient();try{let r=Rt(t);return this.db=r,await e()}finally{t.release()}})}async init(){try{await this.manager.runMigrations(),$e.debug("PgDatabaseAdapter initialized successfully")}catch(e){throw $e.error("Failed to initialize PgDatabaseAdapter:",e),e}}async close(){await this.manager.close()}};x(ce,"PgDatabaseAdapter");var te=ce;var le=Symbol.for("@elizaos/plugin-sql/global-singletons"),ue=global;ue[le]||(ue[le]={});var W=ue[le];function xt(m){return m&&typeof m=="string"&&m.startsWith("~")?m.replace(/^~/,ke.homedir()):m}x(xt,"expandTildePath");function Ct(m,B){if(m.dataDir&&(m.dataDir=xt(m.dataDir)),m.postgresUrl)return W.postgresConnectionManager||(W.postgresConnectionManager=new ye(m.postgresUrl)),new te(B,W.postgresConnectionManager);let e=m.dataDir??"./elizadb";return W.pgLiteClientManager||(W.pgLiteClientManager=new ge({dataDir:e})),new ee(B,W.pgLiteClientManager)}x(Ct,"createDatabaseAdapter");var $t={name:"sql",description:"SQL database adapter plugin using Drizzle ORM",init:x(async(m,B)=>{let e={dataDir:B.getSetting("PGLITE_DATA_DIR")??"./pglite",postgresUrl:B.getSetting("POSTGRES_URL")};try{let t=Ct(e,B.agentId);Le.success("Database connection established successfully"),B.registerDatabaseAdapter(t)}catch(t){throw Le.error("Failed to initialize database:",t),t}},"init")},Wn=$t;export{Ct as createDatabaseAdapter,Wn as default};
1243
+ LIMIT ${opts.query_match_count}
1244
+ `);
1245
+ return results.rows.map((row) => ({
1246
+ embedding: Array.isArray(row.embedding) ? row.embedding : typeof row.embedding === "string" ? JSON.parse(row.embedding) : [],
1247
+ levenshtein_score: Number(row.levenshtein_score)
1248
+ })).filter((row) => Array.isArray(row.embedding));
1249
+ } catch (error) {
1250
+ logger.error("Error in getCachedEmbeddings:", {
1251
+ error: error instanceof Error ? error.message : String(error),
1252
+ tableName: opts.query_table_name,
1253
+ fieldName: opts.query_field_name
1254
+ });
1255
+ if (error instanceof Error && error.message === "levenshtein argument exceeds maximum length of 255 characters") {
1256
+ return [];
1257
+ }
1258
+ throw error;
1259
+ }
1260
+ });
1261
+ }
1262
+ /**
1263
+ * Asynchronously logs an event in the database.
1264
+ * @param {Object} params - The parameters for logging an event.
1265
+ * @param {Object} params.body - The body of the event to log.
1266
+ * @param {UUID} params.entityId - The ID of the entity associated with the event.
1267
+ * @param {UUID} params.roomId - The ID of the room associated with the event.
1268
+ * @param {string} params.type - The type of the event to log.
1269
+ * @returns {Promise<void>} A Promise that resolves when the event is logged.
1270
+ */
1271
+ async log(params) {
1272
+ return this.withDatabase(async () => {
1273
+ try {
1274
+ await this.db.transaction(async (tx) => {
1275
+ await tx.insert(logTable).values({
1276
+ body: sql12`${params.body}::jsonb`,
1277
+ entityId: params.entityId,
1278
+ roomId: params.roomId,
1279
+ type: params.type
1280
+ });
1281
+ });
1282
+ } catch (error) {
1283
+ logger.error("Failed to create log entry:", {
1284
+ error: error instanceof Error ? error.message : String(error),
1285
+ type: params.type,
1286
+ roomId: params.roomId,
1287
+ entityId: params.entityId
1288
+ });
1289
+ throw error;
1290
+ }
1291
+ });
1292
+ }
1293
+ /**
1294
+ * Asynchronously retrieves logs from the database based on the provided parameters.
1295
+ * @param {Object} params - The parameters for retrieving logs.
1296
+ * @param {UUID} params.entityId - The ID of the entity associated with the logs.
1297
+ * @param {UUID} [params.roomId] - The ID of the room associated with the logs.
1298
+ * @param {string} [params.type] - The type of the logs to retrieve.
1299
+ * @param {number} [params.count] - The maximum number of logs to retrieve.
1300
+ * @param {number} [params.offset] - The offset to retrieve logs from.
1301
+ * @returns {Promise<Log[]>} A Promise that resolves to an array of logs.
1302
+ */
1303
+ async getLogs(params) {
1304
+ const { entityId, roomId, type, count: count2, offset } = params;
1305
+ return this.withDatabase(async () => {
1306
+ const result = await this.db.select().from(logTable).where(
1307
+ and(
1308
+ eq(logTable.entityId, entityId),
1309
+ roomId ? eq(logTable.roomId, roomId) : void 0,
1310
+ type ? eq(logTable.type, type) : void 0
1311
+ )
1312
+ ).orderBy(desc(logTable.createdAt)).limit(count2 ?? 10).offset(offset ?? 0);
1313
+ return result;
1314
+ });
1315
+ }
1316
+ /**
1317
+ * Asynchronously deletes a log from the database based on the provided parameters.
1318
+ * @param {UUID} logId - The ID of the log to delete.
1319
+ * @returns {Promise<void>} A Promise that resolves when the log is deleted.
1320
+ */
1321
+ async deleteLog(logId) {
1322
+ return this.withDatabase(async () => {
1323
+ await this.db.delete(logTable).where(eq(logTable.id, logId));
1324
+ });
1325
+ }
1326
+ /**
1327
+ * Asynchronously searches for memories in the database based on the provided parameters.
1328
+ * @param {Object} params - The parameters for searching for memories.
1329
+ * @param {string} params.tableName - The name of the table to search for memories in.
1330
+ * @param {number[]} params.embedding - The embedding to search for.
1331
+ * @param {number} [params.match_threshold] - The threshold for the cosine distance.
1332
+ * @param {number} [params.count] - The maximum number of memories to retrieve.
1333
+ * @param {boolean} [params.unique] - Whether to retrieve unique memories only.
1334
+ * @param {string} [params.query] - Optional query string for potential reranking.
1335
+ * @param {UUID} [params.roomId] - Optional room ID to filter by.
1336
+ * @param {UUID} [params.worldId] - Optional world ID to filter by.
1337
+ * @param {UUID} [params.entityId] - Optional entity ID to filter by.
1338
+ * @returns {Promise<Memory[]>} A Promise that resolves to an array of memories.
1339
+ */
1340
+ async searchMemories(params) {
1341
+ return await this.searchMemoriesByEmbedding(params.embedding, {
1342
+ match_threshold: params.match_threshold,
1343
+ count: params.count,
1344
+ // Pass direct scope fields down
1345
+ roomId: params.roomId,
1346
+ worldId: params.worldId,
1347
+ entityId: params.entityId,
1348
+ unique: params.unique,
1349
+ tableName: params.tableName
1350
+ });
1351
+ }
1352
+ /**
1353
+ * Asynchronously searches for memories in the database based on the provided parameters.
1354
+ * @param {number[]} embedding - The embedding to search for.
1355
+ * @param {Object} params - The parameters for searching for memories.
1356
+ * @param {number} [params.match_threshold] - The threshold for the cosine distance.
1357
+ * @param {number} [params.count] - The maximum number of memories to retrieve.
1358
+ * @param {UUID} [params.roomId] - Optional room ID to filter by.
1359
+ * @param {UUID} [params.worldId] - Optional world ID to filter by.
1360
+ * @param {UUID} [params.entityId] - Optional entity ID to filter by.
1361
+ * @param {boolean} [params.unique] - Whether to retrieve unique memories only.
1362
+ * @param {string} [params.tableName] - The name of the table to search for memories in.
1363
+ * @returns {Promise<Memory[]>} A Promise that resolves to an array of memories.
1364
+ */
1365
+ async searchMemoriesByEmbedding(embedding, params) {
1366
+ return this.withDatabase(async () => {
1367
+ const cleanVector = embedding.map((n) => Number.isFinite(n) ? Number(n.toFixed(6)) : 0);
1368
+ const similarity = sql12`1 - (${cosineDistance(
1369
+ embeddingTable[this.embeddingDimension],
1370
+ cleanVector
1371
+ )})`;
1372
+ const conditions = [eq(memoryTable.type, params.tableName)];
1373
+ if (params.unique) {
1374
+ conditions.push(eq(memoryTable.unique, true));
1375
+ }
1376
+ conditions.push(eq(memoryTable.agentId, this.agentId));
1377
+ if (params.roomId) {
1378
+ conditions.push(eq(memoryTable.roomId, params.roomId));
1379
+ }
1380
+ if (params.worldId) {
1381
+ conditions.push(eq(memoryTable.worldId, params.worldId));
1382
+ }
1383
+ if (params.entityId) {
1384
+ conditions.push(eq(memoryTable.entityId, params.entityId));
1385
+ }
1386
+ if (params.match_threshold) {
1387
+ conditions.push(gte(similarity, params.match_threshold));
1388
+ }
1389
+ const results = await this.db.select({
1390
+ memory: memoryTable,
1391
+ similarity,
1392
+ embedding: embeddingTable[this.embeddingDimension]
1393
+ }).from(embeddingTable).innerJoin(memoryTable, eq(memoryTable.id, embeddingTable.memoryId)).where(and(...conditions)).orderBy(desc(similarity)).limit(params.count ?? 10);
1394
+ return results.map((row) => ({
1395
+ id: row.memory.id,
1396
+ type: row.memory.type,
1397
+ createdAt: row.memory.createdAt,
1398
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
1399
+ entityId: row.memory.entityId,
1400
+ agentId: row.memory.agentId,
1401
+ roomId: row.memory.roomId,
1402
+ worldId: row.memory.worldId,
1403
+ // Include worldId
1404
+ unique: row.memory.unique,
1405
+ metadata: row.memory.metadata,
1406
+ embedding: row.embedding ?? void 0,
1407
+ similarity: row.similarity
1408
+ }));
1409
+ });
1410
+ }
1411
+ /**
1412
+ * Asynchronously creates a new memory in the database.
1413
+ * @param {Memory & { metadata?: MemoryMetadata }} memory - The memory object to create.
1414
+ * @param {string} tableName - The name of the table to create the memory in.
1415
+ * @returns {Promise<UUID>} A Promise that resolves to the ID of the created memory.
1416
+ */
1417
+ async createMemory(memory, tableName) {
1418
+ logger.debug("DrizzleAdapter createMemory:", {
1419
+ memoryId: memory.id,
1420
+ embeddingLength: memory.embedding?.length,
1421
+ contentLength: memory.content?.text?.length
1422
+ });
1423
+ const memoryId = memory.id ?? v4();
1424
+ const existing = await this.getMemoryById(memoryId);
1425
+ if (existing) {
1426
+ logger.debug("Memory already exists, skipping creation:", {
1427
+ memoryId
1428
+ });
1429
+ return memoryId;
1430
+ }
1431
+ let isUnique = true;
1432
+ if (memory.embedding && Array.isArray(memory.embedding)) {
1433
+ const similarMemories = await this.searchMemoriesByEmbedding(memory.embedding, {
1434
+ tableName,
1435
+ // Use the scope fields from the memory object for similarity check
1436
+ roomId: memory.roomId,
1437
+ worldId: memory.worldId,
1438
+ entityId: memory.entityId,
1439
+ match_threshold: 0.95,
1440
+ count: 1
1441
+ });
1442
+ isUnique = similarMemories.length === 0;
1443
+ }
1444
+ const contentToInsert = typeof memory.content === "string" ? JSON.parse(memory.content) : memory.content;
1445
+ await this.db.transaction(async (tx) => {
1446
+ await tx.insert(memoryTable).values([
1447
+ {
1448
+ id: memoryId,
1449
+ type: tableName,
1450
+ content: sql12`${contentToInsert}::jsonb`,
1451
+ metadata: sql12`${memory.metadata || {}}::jsonb`,
1452
+ entityId: memory.entityId,
1453
+ roomId: memory.roomId,
1454
+ worldId: memory.worldId,
1455
+ // Include worldId
1456
+ agentId: memory.agentId,
1457
+ unique: memory.unique ?? isUnique,
1458
+ createdAt: memory.createdAt
1459
+ }
1460
+ ]);
1461
+ if (memory.embedding && Array.isArray(memory.embedding)) {
1462
+ const embeddingValues = {
1463
+ id: v4(),
1464
+ memoryId,
1465
+ createdAt: memory.createdAt
1466
+ };
1467
+ const cleanVector = memory.embedding.map(
1468
+ (n) => Number.isFinite(n) ? Number(n.toFixed(6)) : 0
1469
+ );
1470
+ embeddingValues[this.embeddingDimension] = cleanVector;
1471
+ await tx.insert(embeddingTable).values([embeddingValues]);
1472
+ }
1473
+ });
1474
+ return memoryId;
1475
+ }
1476
+ /**
1477
+ * Updates an existing memory in the database.
1478
+ * @param memory The memory object with updated content and optional embedding
1479
+ * @returns Promise resolving to boolean indicating success
1480
+ */
1481
+ async updateMemory(memory) {
1482
+ return this.withDatabase(async () => {
1483
+ try {
1484
+ logger.debug("Updating memory:", {
1485
+ memoryId: memory.id,
1486
+ hasEmbedding: !!memory.embedding
1487
+ });
1488
+ await this.db.transaction(async (tx) => {
1489
+ if (memory.content) {
1490
+ const contentToUpdate = typeof memory.content === "string" ? JSON.parse(memory.content) : memory.content;
1491
+ await tx.update(memoryTable).set({
1492
+ content: sql12`${contentToUpdate}::jsonb`,
1493
+ ...memory.metadata && { metadata: sql12`${memory.metadata}::jsonb` }
1494
+ }).where(eq(memoryTable.id, memory.id));
1495
+ } else if (memory.metadata) {
1496
+ await tx.update(memoryTable).set({
1497
+ metadata: sql12`${memory.metadata}::jsonb`
1498
+ }).where(eq(memoryTable.id, memory.id));
1499
+ }
1500
+ if (memory.embedding && Array.isArray(memory.embedding)) {
1501
+ const cleanVector = memory.embedding.map(
1502
+ (n) => Number.isFinite(n) ? Number(n.toFixed(6)) : 0
1503
+ );
1504
+ const existingEmbedding = await tx.select({ id: embeddingTable.id }).from(embeddingTable).where(eq(embeddingTable.memoryId, memory.id)).limit(1);
1505
+ if (existingEmbedding.length > 0) {
1506
+ const updateValues = {};
1507
+ updateValues[this.embeddingDimension] = cleanVector;
1508
+ await tx.update(embeddingTable).set(updateValues).where(eq(embeddingTable.memoryId, memory.id));
1509
+ } else {
1510
+ const embeddingValues = {
1511
+ id: v4(),
1512
+ memoryId: memory.id,
1513
+ createdAt: Date.now()
1514
+ };
1515
+ embeddingValues[this.embeddingDimension] = cleanVector;
1516
+ await tx.insert(embeddingTable).values([embeddingValues]);
1517
+ }
1518
+ }
1519
+ });
1520
+ logger.debug("Memory updated successfully:", {
1521
+ memoryId: memory.id
1522
+ });
1523
+ return true;
1524
+ } catch (error) {
1525
+ logger.error("Error updating memory:", {
1526
+ error: error instanceof Error ? error.message : String(error),
1527
+ memoryId: memory.id
1528
+ });
1529
+ return false;
1530
+ }
1531
+ });
1532
+ }
1533
+ /**
1534
+ * Asynchronously deletes a memory from the database based on the provided parameters.
1535
+ * @param {UUID} memoryId - The ID of the memory to delete.
1536
+ * @returns {Promise<void>} A Promise that resolves when the memory is deleted.
1537
+ */
1538
+ async deleteMemory(memoryId) {
1539
+ return this.withDatabase(async () => {
1540
+ await this.db.transaction(async (tx) => {
1541
+ await this.deleteMemoryFragments(tx, memoryId);
1542
+ await tx.delete(embeddingTable).where(eq(embeddingTable.memoryId, memoryId));
1543
+ await tx.delete(memoryTable).where(eq(memoryTable.id, memoryId));
1544
+ });
1545
+ logger.debug("Memory and related fragments removed successfully:", {
1546
+ memoryId
1547
+ });
1548
+ });
1549
+ }
1550
+ /**
1551
+ * Deletes all memory fragments that reference a specific document memory
1552
+ * @param tx The database transaction
1553
+ * @param documentId The UUID of the document memory whose fragments should be deleted
1554
+ * @private
1555
+ */
1556
+ async deleteMemoryFragments(tx, documentId) {
1557
+ const fragmentsToDelete = await this.getMemoryFragments(tx, documentId);
1558
+ if (fragmentsToDelete.length > 0) {
1559
+ const fragmentIds = fragmentsToDelete.map((f) => f.id);
1560
+ await tx.delete(embeddingTable).where(inArray(embeddingTable.memoryId, fragmentIds));
1561
+ await tx.delete(memoryTable).where(inArray(memoryTable.id, fragmentIds));
1562
+ logger.debug("Deleted related fragments:", {
1563
+ documentId,
1564
+ fragmentCount: fragmentsToDelete.length
1565
+ });
1566
+ }
1567
+ }
1568
+ /**
1569
+ * Retrieves all memory fragments that reference a specific document memory
1570
+ * @param tx The database transaction
1571
+ * @param documentId The UUID of the document memory whose fragments should be retrieved
1572
+ * @returns An array of memory fragments
1573
+ * @private
1574
+ */
1575
+ async getMemoryFragments(tx, documentId) {
1576
+ const fragments = await tx.select({ id: memoryTable.id }).from(memoryTable).where(
1577
+ and(
1578
+ eq(memoryTable.agentId, this.agentId),
1579
+ sql12`${memoryTable.metadata}->>'documentId' = ${documentId}`
1580
+ )
1581
+ );
1582
+ return fragments;
1583
+ }
1584
+ /**
1585
+ * Asynchronously deletes all memories from the database based on the provided parameters.
1586
+ * @param {UUID} roomId - The ID of the room to delete memories from.
1587
+ * @param {string} tableName - The name of the table to delete memories from.
1588
+ * @returns {Promise<void>} A Promise that resolves when the memories are deleted.
1589
+ */
1590
+ async deleteAllMemories(roomId, tableName) {
1591
+ return this.withDatabase(async () => {
1592
+ await this.db.transaction(async (tx) => {
1593
+ const memoryIds = await tx.select({ id: memoryTable.id }).from(memoryTable).where(and(eq(memoryTable.roomId, roomId), eq(memoryTable.type, tableName)));
1594
+ if (memoryIds.length > 0) {
1595
+ await tx.delete(embeddingTable).where(
1596
+ inArray(
1597
+ embeddingTable.memoryId,
1598
+ memoryIds.map((m) => m.id)
1599
+ )
1600
+ );
1601
+ await tx.delete(memoryTable).where(and(eq(memoryTable.roomId, roomId), eq(memoryTable.type, tableName)));
1602
+ }
1603
+ });
1604
+ logger.debug("All memories removed successfully:", {
1605
+ roomId,
1606
+ tableName
1607
+ });
1608
+ });
1609
+ }
1610
+ /**
1611
+ * Asynchronously counts the number of memories in the database based on the provided parameters.
1612
+ * @param {UUID} roomId - The ID of the room to count memories in.
1613
+ * @param {boolean} [unique] - Whether to count unique memories only.
1614
+ * @param {string} [tableName] - The name of the table to count memories in.
1615
+ * @returns {Promise<number>} A Promise that resolves to the number of memories.
1616
+ */
1617
+ async countMemories(roomId, unique7 = true, tableName = "") {
1618
+ if (!tableName) throw new Error("tableName is required");
1619
+ return this.withDatabase(async () => {
1620
+ const conditions = [eq(memoryTable.roomId, roomId), eq(memoryTable.type, tableName)];
1621
+ if (unique7) {
1622
+ conditions.push(eq(memoryTable.unique, true));
1623
+ }
1624
+ const result = await this.db.select({ count: sql12`count(*)` }).from(memoryTable).where(and(...conditions));
1625
+ return Number(result[0]?.count ?? 0);
1626
+ });
1627
+ }
1628
+ /**
1629
+ * Asynchronously retrieves a room from the database based on the provided parameters.
1630
+ * @param {UUID} roomId - The ID of the room to retrieve.
1631
+ * @returns {Promise<Room | null>} A Promise that resolves to the room if found, null otherwise.
1632
+ */
1633
+ async getRoom(roomId) {
1634
+ return this.withDatabase(async () => {
1635
+ const result = await this.db.select({
1636
+ id: roomTable.id,
1637
+ channelId: roomTable.channelId,
1638
+ agentId: roomTable.agentId,
1639
+ serverId: roomTable.serverId,
1640
+ worldId: roomTable.worldId,
1641
+ type: roomTable.type,
1642
+ source: roomTable.source
1643
+ }).from(roomTable).where(and(eq(roomTable.id, roomId), eq(roomTable.agentId, this.agentId))).limit(1);
1644
+ if (result.length === 0) return null;
1645
+ return result[0];
1646
+ });
1647
+ }
1648
+ /**
1649
+ * Asynchronously retrieves all rooms from the database based on the provided parameters.
1650
+ * @param {UUID} worldId - The ID of the world to retrieve rooms from.
1651
+ * @returns {Promise<Room[]>} A Promise that resolves to an array of rooms.
1652
+ */
1653
+ async getRooms(worldId) {
1654
+ return this.withDatabase(async () => {
1655
+ const result = await this.db.select().from(roomTable).where(eq(roomTable.worldId, worldId));
1656
+ return result;
1657
+ });
1658
+ }
1659
+ /**
1660
+ * Asynchronously updates a room in the database based on the provided parameters.
1661
+ * @param {Room} room - The room object to update.
1662
+ * @returns {Promise<void>} A Promise that resolves when the room is updated.
1663
+ */
1664
+ async updateRoom(room) {
1665
+ return this.withDatabase(async () => {
1666
+ await this.db.update(roomTable).set({ ...room, agentId: this.agentId }).where(eq(roomTable.id, room.id));
1667
+ });
1668
+ }
1669
+ /**
1670
+ * Asynchronously creates a new room in the database based on the provided parameters.
1671
+ * @param {Room} room - The room object to create.
1672
+ * @returns {Promise<UUID>} A Promise that resolves to the ID of the created room.
1673
+ */
1674
+ async createRoom({
1675
+ id,
1676
+ name,
1677
+ agentId,
1678
+ source,
1679
+ type,
1680
+ channelId,
1681
+ serverId,
1682
+ worldId,
1683
+ metadata
1684
+ }) {
1685
+ return this.withDatabase(async () => {
1686
+ const newRoomId = id || v4();
1687
+ await this.db.insert(roomTable).values({
1688
+ id: newRoomId,
1689
+ name,
1690
+ agentId,
1691
+ source,
1692
+ type,
1693
+ channelId,
1694
+ serverId,
1695
+ worldId,
1696
+ metadata
1697
+ }).onConflictDoNothing({ target: roomTable.id });
1698
+ return newRoomId;
1699
+ });
1700
+ }
1701
+ /**
1702
+ * Asynchronously deletes a room from the database based on the provided parameters.
1703
+ * @param {UUID} roomId - The ID of the room to delete.
1704
+ * @returns {Promise<void>} A Promise that resolves when the room is deleted.
1705
+ */
1706
+ async deleteRoom(roomId) {
1707
+ if (!roomId) throw new Error("Room ID is required");
1708
+ return this.withDatabase(async () => {
1709
+ await this.db.transaction(async (tx) => {
1710
+ await tx.delete(roomTable).where(eq(roomTable.id, roomId));
1711
+ });
1712
+ });
1713
+ }
1714
+ /**
1715
+ * Asynchronously retrieves all rooms for a participant from the database based on the provided parameters.
1716
+ * @param {UUID} entityId - The ID of the entity to retrieve rooms for.
1717
+ * @returns {Promise<UUID[]>} A Promise that resolves to an array of room IDs.
1718
+ */
1719
+ async getRoomsForParticipant(entityId) {
1720
+ return this.withDatabase(async () => {
1721
+ const result = await this.db.select({ roomId: participantTable.roomId }).from(participantTable).innerJoin(roomTable, eq(participantTable.roomId, roomTable.id)).where(and(eq(participantTable.entityId, entityId), eq(roomTable.agentId, this.agentId)));
1722
+ return result.map((row) => row.roomId);
1723
+ });
1724
+ }
1725
+ /**
1726
+ * Asynchronously retrieves all rooms for a list of participants from the database based on the provided parameters.
1727
+ * @param {UUID[]} entityIds - The IDs of the entities to retrieve rooms for.
1728
+ * @returns {Promise<UUID[]>} A Promise that resolves to an array of room IDs.
1729
+ */
1730
+ async getRoomsForParticipants(entityIds) {
1731
+ return this.withDatabase(async () => {
1732
+ const result = await this.db.selectDistinct({ roomId: participantTable.roomId }).from(participantTable).innerJoin(roomTable, eq(participantTable.roomId, roomTable.id)).where(
1733
+ and(inArray(participantTable.entityId, entityIds), eq(roomTable.agentId, this.agentId))
1734
+ );
1735
+ return result.map((row) => row.roomId);
1736
+ });
1737
+ }
1738
+ /**
1739
+ * Asynchronously adds a participant to a room in the database based on the provided parameters.
1740
+ * @param {UUID} entityId - The ID of the entity to add to the room.
1741
+ * @param {UUID} roomId - The ID of the room to add the entity to.
1742
+ * @returns {Promise<boolean>} A Promise that resolves to a boolean indicating whether the participant was added successfully.
1743
+ */
1744
+ async addParticipant(entityId, roomId) {
1745
+ return this.withDatabase(async () => {
1746
+ try {
1747
+ await this.db.insert(participantTable).values({
1748
+ entityId,
1749
+ roomId,
1750
+ agentId: this.agentId
1751
+ }).onConflictDoNothing();
1752
+ return true;
1753
+ } catch (error) {
1754
+ logger.error("Error adding participant", {
1755
+ error: error instanceof Error ? error.message : String(error),
1756
+ entityId,
1757
+ roomId,
1758
+ agentId: this.agentId
1759
+ });
1760
+ return false;
1761
+ }
1762
+ });
1763
+ }
1764
+ /**
1765
+ * Asynchronously removes a participant from a room in the database based on the provided parameters.
1766
+ * @param {UUID} entityId - The ID of the entity to remove from the room.
1767
+ * @param {UUID} roomId - The ID of the room to remove the entity from.
1768
+ * @returns {Promise<boolean>} A Promise that resolves to a boolean indicating whether the participant was removed successfully.
1769
+ */
1770
+ async removeParticipant(entityId, roomId) {
1771
+ return this.withDatabase(async () => {
1772
+ try {
1773
+ const result = await this.db.transaction(async (tx) => {
1774
+ return await tx.delete(participantTable).where(
1775
+ and(eq(participantTable.entityId, entityId), eq(participantTable.roomId, roomId))
1776
+ ).returning();
1777
+ });
1778
+ const removed = result.length > 0;
1779
+ logger.debug(`Participant ${removed ? "removed" : "not found"}:`, {
1780
+ entityId,
1781
+ roomId,
1782
+ removed
1783
+ });
1784
+ return removed;
1785
+ } catch (error) {
1786
+ logger.error("Failed to remove participant:", {
1787
+ error: error instanceof Error ? error.message : String(error),
1788
+ entityId,
1789
+ roomId
1790
+ });
1791
+ return false;
1792
+ }
1793
+ });
1794
+ }
1795
+ /**
1796
+ * Asynchronously retrieves all participants for an entity from the database based on the provided parameters.
1797
+ * @param {UUID} entityId - The ID of the entity to retrieve participants for.
1798
+ * @returns {Promise<Participant[]>} A Promise that resolves to an array of participants.
1799
+ */
1800
+ async getParticipantsForEntity(entityId) {
1801
+ return this.withDatabase(async () => {
1802
+ const result = await this.db.select({
1803
+ id: participantTable.id,
1804
+ entityId: participantTable.entityId,
1805
+ roomId: participantTable.roomId
1806
+ }).from(participantTable).where(eq(participantTable.entityId, entityId));
1807
+ const entity = await this.getEntityById(entityId);
1808
+ if (!entity) {
1809
+ return [];
1810
+ }
1811
+ return result.map((row) => ({
1812
+ id: row.id,
1813
+ entity
1814
+ }));
1815
+ });
1816
+ }
1817
+ /**
1818
+ * Asynchronously retrieves all participants for a room from the database based on the provided parameters.
1819
+ * @param {UUID} roomId - The ID of the room to retrieve participants for.
1820
+ * @returns {Promise<UUID[]>} A Promise that resolves to an array of entity IDs.
1821
+ */
1822
+ async getParticipantsForRoom(roomId) {
1823
+ return this.withDatabase(async () => {
1824
+ const result = await this.db.select({ entityId: participantTable.entityId }).from(participantTable).where(eq(participantTable.roomId, roomId));
1825
+ return result.map((row) => row.entityId);
1826
+ });
1827
+ }
1828
+ /**
1829
+ * Asynchronously retrieves the user state for a participant in a room from the database based on the provided parameters.
1830
+ * @param {UUID} roomId - The ID of the room to retrieve the participant's user state for.
1831
+ * @param {UUID} entityId - The ID of the entity to retrieve the user state for.
1832
+ * @returns {Promise<"FOLLOWED" | "MUTED" | null>} A Promise that resolves to the participant's user state.
1833
+ */
1834
+ async getParticipantUserState(roomId, entityId) {
1835
+ return this.withDatabase(async () => {
1836
+ const result = await this.db.select({ roomState: participantTable.roomState }).from(participantTable).where(
1837
+ and(
1838
+ eq(participantTable.roomId, roomId),
1839
+ eq(participantTable.entityId, entityId),
1840
+ eq(participantTable.agentId, this.agentId)
1841
+ )
1842
+ ).limit(1);
1843
+ return result[0]?.roomState ?? null;
1844
+ });
1845
+ }
1846
+ /**
1847
+ * Asynchronously sets the user state for a participant in a room in the database based on the provided parameters.
1848
+ * @param {UUID} roomId - The ID of the room to set the participant's user state for.
1849
+ * @param {UUID} entityId - The ID of the entity to set the user state for.
1850
+ * @param {string} state - The state to set the participant's user state to.
1851
+ * @returns {Promise<void>} A Promise that resolves when the participant's user state is set.
1852
+ */
1853
+ async setParticipantUserState(roomId, entityId, state) {
1854
+ return this.withDatabase(async () => {
1855
+ try {
1856
+ await this.db.transaction(async (tx) => {
1857
+ await tx.update(participantTable).set({ roomState: state }).where(
1858
+ and(
1859
+ eq(participantTable.roomId, roomId),
1860
+ eq(participantTable.entityId, entityId),
1861
+ eq(participantTable.agentId, this.agentId)
1862
+ )
1863
+ );
1864
+ });
1865
+ } catch (error) {
1866
+ logger.error("Failed to set participant user state:", {
1867
+ roomId,
1868
+ entityId,
1869
+ state,
1870
+ error: error instanceof Error ? error.message : String(error)
1871
+ });
1872
+ throw error;
1873
+ }
1874
+ });
1875
+ }
1876
+ /**
1877
+ * Asynchronously creates a new relationship in the database based on the provided parameters.
1878
+ * @param {Object} params - The parameters for creating a new relationship.
1879
+ * @param {UUID} params.sourceEntityId - The ID of the source entity.
1880
+ * @param {UUID} params.targetEntityId - The ID of the target entity.
1881
+ * @param {string[]} [params.tags] - The tags for the relationship.
1882
+ * @param {Object} [params.metadata] - The metadata for the relationship.
1883
+ * @returns {Promise<boolean>} A Promise that resolves to a boolean indicating whether the relationship was created successfully.
1884
+ */
1885
+ async createRelationship(params) {
1886
+ return this.withDatabase(async () => {
1887
+ const id = v4();
1888
+ const saveParams = {
1889
+ id,
1890
+ sourceEntityId: params.sourceEntityId,
1891
+ targetEntityId: params.targetEntityId,
1892
+ agentId: this.agentId,
1893
+ tags: params.tags || [],
1894
+ metadata: params.metadata || {}
1895
+ };
1896
+ try {
1897
+ await this.db.insert(relationshipTable).values(saveParams);
1898
+ return true;
1899
+ } catch (error) {
1900
+ logger.error("Error creating relationship:", {
1901
+ error: error instanceof Error ? error.message : String(error),
1902
+ saveParams
1903
+ });
1904
+ return false;
1905
+ }
1906
+ });
1907
+ }
1908
+ /**
1909
+ * Asynchronously updates an existing relationship in the database based on the provided parameters.
1910
+ * @param {Relationship} relationship - The relationship object to update.
1911
+ * @returns {Promise<void>} A Promise that resolves when the relationship is updated.
1912
+ */
1913
+ async updateRelationship(relationship) {
1914
+ return this.withDatabase(async () => {
1915
+ try {
1916
+ await this.db.update(relationshipTable).set({
1917
+ tags: relationship.tags || [],
1918
+ metadata: relationship.metadata || {}
1919
+ }).where(eq(relationshipTable.id, relationship.id));
1920
+ } catch (error) {
1921
+ logger.error("Error updating relationship:", {
1922
+ error: error instanceof Error ? error.message : String(error),
1923
+ relationship
1924
+ });
1925
+ throw error;
1926
+ }
1927
+ });
1928
+ }
1929
+ /**
1930
+ * Asynchronously retrieves a relationship from the database based on the provided parameters.
1931
+ * @param {Object} params - The parameters for retrieving a relationship.
1932
+ * @param {UUID} params.sourceEntityId - The ID of the source entity.
1933
+ * @param {UUID} params.targetEntityId - The ID of the target entity.
1934
+ * @returns {Promise<Relationship | null>} A Promise that resolves to the relationship if found, null otherwise.
1935
+ */
1936
+ async getRelationship(params) {
1937
+ return this.withDatabase(async () => {
1938
+ try {
1939
+ const result = await this.db.select().from(relationshipTable).where(
1940
+ and(
1941
+ eq(relationshipTable.sourceEntityId, params.sourceEntityId),
1942
+ eq(relationshipTable.targetEntityId, params.targetEntityId),
1943
+ eq(relationshipTable.agentId, this.agentId)
1944
+ )
1945
+ ).limit(1);
1946
+ if (result.length === 0) {
1947
+ return null;
1948
+ }
1949
+ return {
1950
+ id: result[0].id,
1951
+ sourceEntityId: result[0].sourceEntityId,
1952
+ targetEntityId: result[0].targetEntityId,
1953
+ agentId: result[0].agentId,
1954
+ tags: result[0].tags || [],
1955
+ metadata: result[0].metadata || {},
1956
+ createdAt: result[0].createdAt?.toString()
1957
+ };
1958
+ } catch (error) {
1959
+ logger.error("Error getting relationship:", {
1960
+ error: error instanceof Error ? error.message : String(error),
1961
+ params
1962
+ });
1963
+ return null;
1964
+ }
1965
+ });
1966
+ }
1967
+ /**
1968
+ * Asynchronously retrieves all relationships from the database based on the provided parameters.
1969
+ * @param {Object} params - The parameters for retrieving relationships.
1970
+ * @param {UUID} params.entityId - The ID of the entity to retrieve relationships for.
1971
+ * @param {string[]} [params.tags] - The tags to filter relationships by.
1972
+ * @returns {Promise<Relationship[]>} A Promise that resolves to an array of relationships.
1973
+ */
1974
+ async getRelationships(params) {
1975
+ return this.withDatabase(async () => {
1976
+ try {
1977
+ let query = this.db.select().from(relationshipTable).where(
1978
+ and(
1979
+ or(
1980
+ eq(relationshipTable.sourceEntityId, params.entityId),
1981
+ eq(relationshipTable.targetEntityId, params.entityId)
1982
+ ),
1983
+ eq(relationshipTable.agentId, this.agentId)
1984
+ )
1985
+ );
1986
+ if (params.tags && params.tags.length > 0) {
1987
+ const tagParams = params.tags.map((tag) => `'${tag.replace(/'/g, "''")}'`).join(", ");
1988
+ query = query.where(
1989
+ sql12`${relationshipTable.tags} @> ARRAY[${sql12.raw(tagParams)}]::text[]`
1990
+ );
1991
+ }
1992
+ const results = await query;
1993
+ return results.map((result) => ({
1994
+ id: result.id,
1995
+ sourceEntityId: result.sourceEntityId,
1996
+ targetEntityId: result.targetEntityId,
1997
+ agentId: result.agentId,
1998
+ tags: result.tags || [],
1999
+ metadata: result.metadata || {},
2000
+ createdAt: result.createdAt?.toString()
2001
+ }));
2002
+ } catch (error) {
2003
+ logger.error("Error getting relationships:", {
2004
+ error: error instanceof Error ? error.message : String(error),
2005
+ params
2006
+ });
2007
+ return [];
2008
+ }
2009
+ });
2010
+ }
2011
+ /**
2012
+ * Asynchronously retrieves a cache value from the database based on the provided key.
2013
+ * @param {string} key - The key to retrieve the cache value for.
2014
+ * @returns {Promise<T | undefined>} A Promise that resolves to the cache value if found, undefined otherwise.
2015
+ */
2016
+ async getCache(key) {
2017
+ return this.withDatabase(async () => {
2018
+ try {
2019
+ const result = await this.db.select().from(cacheTable).where(and(eq(cacheTable.agentId, this.agentId), eq(cacheTable.key, key)));
2020
+ return result[0]?.value;
2021
+ } catch (error) {
2022
+ logger.error("Error fetching cache", {
2023
+ error: error instanceof Error ? error.message : String(error),
2024
+ key,
2025
+ agentId: this.agentId
2026
+ });
2027
+ return void 0;
2028
+ }
2029
+ });
2030
+ }
2031
+ /**
2032
+ * Asynchronously sets a cache value in the database based on the provided key and value.
2033
+ * @param {string} key - The key to set the cache value for.
2034
+ * @param {T} value - The value to set in the cache.
2035
+ * @returns {Promise<boolean>} A Promise that resolves to a boolean indicating whether the cache value was set successfully.
2036
+ */
2037
+ async setCache(key, value) {
2038
+ return this.withDatabase(async () => {
2039
+ try {
2040
+ await this.db.transaction(async (tx) => {
2041
+ await tx.insert(cacheTable).values({
2042
+ key,
2043
+ agentId: this.agentId,
2044
+ value
2045
+ }).onConflictDoUpdate({
2046
+ target: [cacheTable.key, cacheTable.agentId],
2047
+ set: {
2048
+ value
2049
+ }
2050
+ });
2051
+ });
2052
+ return true;
2053
+ } catch (error) {
2054
+ logger.error("Error setting cache", {
2055
+ error: error instanceof Error ? error.message : String(error),
2056
+ key,
2057
+ agentId: this.agentId
2058
+ });
2059
+ return false;
2060
+ }
2061
+ });
2062
+ }
2063
+ /**
2064
+ * Asynchronously deletes a cache value from the database based on the provided key.
2065
+ * @param {string} key - The key to delete the cache value for.
2066
+ * @returns {Promise<boolean>} A Promise that resolves to a boolean indicating whether the cache value was deleted successfully.
2067
+ */
2068
+ async deleteCache(key) {
2069
+ return this.withDatabase(async () => {
2070
+ try {
2071
+ await this.db.transaction(async (tx) => {
2072
+ await tx.delete(cacheTable).where(and(eq(cacheTable.agentId, this.agentId), eq(cacheTable.key, key)));
2073
+ });
2074
+ return true;
2075
+ } catch (error) {
2076
+ logger.error("Error deleting cache", {
2077
+ error: error instanceof Error ? error.message : String(error),
2078
+ key,
2079
+ agentId: this.agentId
2080
+ });
2081
+ return false;
2082
+ }
2083
+ });
2084
+ }
2085
+ /**
2086
+ * Asynchronously creates a new world in the database based on the provided parameters.
2087
+ * @param {World} world - The world object to create.
2088
+ * @returns {Promise<UUID>} A Promise that resolves to the ID of the created world.
2089
+ */
2090
+ async createWorld(world) {
2091
+ return this.withDatabase(async () => {
2092
+ const newWorldId = world.id || v4();
2093
+ await this.db.insert(worldTable).values({
2094
+ ...world,
2095
+ id: newWorldId
2096
+ });
2097
+ return newWorldId;
2098
+ });
2099
+ }
2100
+ /**
2101
+ * Asynchronously retrieves a world from the database based on the provided parameters.
2102
+ * @param {UUID} id - The ID of the world to retrieve.
2103
+ * @returns {Promise<World | null>} A Promise that resolves to the world if found, null otherwise.
2104
+ */
2105
+ async getWorld(id) {
2106
+ return this.withDatabase(async () => {
2107
+ const result = await this.db.select().from(worldTable).where(eq(worldTable.id, id));
2108
+ return result[0];
2109
+ });
2110
+ }
2111
+ /**
2112
+ * Asynchronously retrieves all worlds from the database based on the provided parameters.
2113
+ * @returns {Promise<World[]>} A Promise that resolves to an array of worlds.
2114
+ */
2115
+ async getAllWorlds() {
2116
+ return this.withDatabase(async () => {
2117
+ const result = await this.db.select().from(worldTable).where(eq(worldTable.agentId, this.agentId));
2118
+ return result;
2119
+ });
2120
+ }
2121
+ /**
2122
+ * Asynchronously updates an existing world in the database based on the provided parameters.
2123
+ * @param {World} world - The world object to update.
2124
+ * @returns {Promise<void>} A Promise that resolves when the world is updated.
2125
+ */
2126
+ async updateWorld(world) {
2127
+ return this.withDatabase(async () => {
2128
+ await this.db.update(worldTable).set(world).where(eq(worldTable.id, world.id));
2129
+ });
2130
+ }
2131
+ /**
2132
+ * Asynchronously removes a world from the database based on the provided parameters.
2133
+ * @param {UUID} id - The ID of the world to remove.
2134
+ * @returns {Promise<void>} A Promise that resolves when the world is removed.
2135
+ */
2136
+ async removeWorld(id) {
2137
+ return this.withDatabase(async () => {
2138
+ await this.db.delete(worldTable).where(eq(worldTable.id, id));
2139
+ });
2140
+ }
2141
+ /**
2142
+ * Asynchronously creates a new task in the database based on the provided parameters.
2143
+ * @param {Task} task - The task object to create.
2144
+ * @returns {Promise<UUID>} A Promise that resolves to the ID of the created task.
2145
+ */
2146
+ async createTask(task) {
2147
+ return this.withRetry(async () => {
2148
+ return this.withDatabase(async () => {
2149
+ const now = /* @__PURE__ */ new Date();
2150
+ const metadata = task.metadata || {};
2151
+ const values = {
2152
+ id: task.id,
2153
+ name: task.name,
2154
+ description: task.description,
2155
+ roomId: task.roomId,
2156
+ worldId: task.worldId,
2157
+ tags: task.tags,
2158
+ metadata,
2159
+ createdAt: now,
2160
+ updatedAt: now,
2161
+ agentId: this.agentId
2162
+ };
2163
+ const result = await this.db.insert(taskTable).values(values).returning({ id: taskTable.id });
2164
+ return result[0].id;
2165
+ });
2166
+ });
2167
+ }
2168
+ /**
2169
+ * Asynchronously retrieves tasks based on specified parameters.
2170
+ * @param params Object containing optional roomId and tags to filter tasks
2171
+ * @returns Promise resolving to an array of Task objects
2172
+ */
2173
+ async getTasks(params) {
2174
+ return this.withRetry(async () => {
2175
+ return this.withDatabase(async () => {
2176
+ let query = this.db.select().from(taskTable).where(eq(taskTable.agentId, this.agentId));
2177
+ if (params.roomId) {
2178
+ query = query.where(eq(taskTable.roomId, params.roomId));
2179
+ }
2180
+ if (params.tags && params.tags.length > 0) {
2181
+ const tagParams = params.tags.map((tag) => `'${tag.replace(/'/g, "''")}'`).join(", ");
2182
+ query = query.where(sql12`${taskTable.tags} @> ARRAY[${sql12.raw(tagParams)}]::text[]`);
2183
+ }
2184
+ const result = await query;
2185
+ return result.map((row) => ({
2186
+ id: row.id,
2187
+ name: row.name,
2188
+ description: row.description,
2189
+ roomId: row.roomId,
2190
+ worldId: row.worldId,
2191
+ tags: row.tags,
2192
+ metadata: row.metadata
2193
+ }));
2194
+ });
2195
+ });
2196
+ }
2197
+ /**
2198
+ * Asynchronously retrieves a specific task by its name.
2199
+ * @param name The name of the task to retrieve
2200
+ * @returns Promise resolving to the Task object if found, null otherwise
2201
+ */
2202
+ async getTasksByName(name) {
2203
+ return this.withRetry(async () => {
2204
+ return this.withDatabase(async () => {
2205
+ const result = await this.db.select().from(taskTable).where(and(eq(taskTable.name, name), eq(taskTable.agentId, this.agentId)));
2206
+ return result.map((row) => ({
2207
+ id: row.id,
2208
+ name: row.name,
2209
+ description: row.description,
2210
+ roomId: row.roomId,
2211
+ worldId: row.worldId,
2212
+ tags: row.tags || [],
2213
+ metadata: row.metadata || {}
2214
+ }));
2215
+ });
2216
+ });
2217
+ }
2218
+ /**
2219
+ * Asynchronously retrieves a specific task by its ID.
2220
+ * @param id The UUID of the task to retrieve
2221
+ * @returns Promise resolving to the Task object if found, null otherwise
2222
+ */
2223
+ async getTask(id) {
2224
+ return this.withRetry(async () => {
2225
+ return this.withDatabase(async () => {
2226
+ const result = await this.db.select().from(taskTable).where(and(eq(taskTable.id, id), eq(taskTable.agentId, this.agentId))).limit(1);
2227
+ if (result.length === 0) {
2228
+ return null;
2229
+ }
2230
+ const row = result[0];
2231
+ return {
2232
+ id: row.id,
2233
+ name: row.name,
2234
+ description: row.description,
2235
+ roomId: row.roomId,
2236
+ worldId: row.worldId,
2237
+ tags: row.tags || [],
2238
+ metadata: row.metadata || {}
2239
+ };
2240
+ });
2241
+ });
2242
+ }
2243
+ /**
2244
+ * Asynchronously updates an existing task in the database.
2245
+ * @param id The UUID of the task to update
2246
+ * @param task Partial Task object containing the fields to update
2247
+ * @returns Promise resolving when the update is complete
2248
+ */
2249
+ async updateTask(id, task) {
2250
+ await this.withRetry(async () => {
2251
+ await this.withDatabase(async () => {
2252
+ const updateValues = {};
2253
+ if (task.name !== void 0) updateValues.name = task.name;
2254
+ if (task.description !== void 0) updateValues.description = task.description;
2255
+ if (task.roomId !== void 0) updateValues.roomId = task.roomId;
2256
+ if (task.worldId !== void 0) updateValues.worldId = task.worldId;
2257
+ if (task.tags !== void 0) updateValues.tags = task.tags;
2258
+ task.updatedAt = Date.now();
2259
+ if (task.metadata) {
2260
+ const currentTask = await this.getTask(id);
2261
+ if (currentTask) {
2262
+ const currentMetadata = currentTask.metadata || {};
2263
+ const newMetadata = {
2264
+ ...currentMetadata,
2265
+ ...task.metadata
2266
+ };
2267
+ updateValues.metadata = newMetadata;
2268
+ } else {
2269
+ updateValues.metadata = {
2270
+ ...task.metadata
2271
+ };
2272
+ }
2273
+ }
2274
+ await this.db.update(taskTable).set(updateValues).where(and(eq(taskTable.id, id), eq(taskTable.agentId, this.agentId)));
2275
+ });
2276
+ });
2277
+ }
2278
+ /**
2279
+ * Asynchronously deletes a task from the database.
2280
+ * @param id The UUID of the task to delete
2281
+ * @returns Promise resolving when the deletion is complete
2282
+ */
2283
+ async deleteTask(id) {
2284
+ await this.withRetry(async () => {
2285
+ await this.withDatabase(async () => {
2286
+ await this.db.delete(taskTable).where(and(eq(taskTable.id, id), eq(taskTable.agentId, this.agentId)));
2287
+ });
2288
+ });
2289
+ }
2290
+ /**
2291
+ * Asynchronously retrieves group chat memories from all rooms under a given server.
2292
+ * It fetches all room IDs associated with the `serverId`, then retrieves memories
2293
+ * from those rooms in descending order (latest to oldest), with an optional count limit.
2294
+ *
2295
+ * @param {Object} params - Parameters for fetching memories.
2296
+ * @param {UUID} params.serverId - The server ID to fetch memories for.
2297
+ * @param {number} [params.count] - The maximum number of memories to retrieve.
2298
+ * @returns {Promise<Memory[]>} - A promise that resolves to an array of memory objects.
2299
+ */
2300
+ async getMemoriesByServerId(params) {
2301
+ return this.withDatabase(async () => {
2302
+ const roomIdsResult = await this.db.select({ roomId: roomTable.id }).from(roomTable).where(eq(roomTable.serverId, params.serverId));
2303
+ if (roomIdsResult.length === 0) return [];
2304
+ const roomIds = roomIdsResult.map((row) => row.roomId);
2305
+ const query = this.db.select({
2306
+ memory: memoryTable,
2307
+ embedding: embeddingTable[this.embeddingDimension]
2308
+ }).from(memoryTable).leftJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)).where(inArray(memoryTable.roomId, roomIds)).orderBy(desc(memoryTable.createdAt));
2309
+ const rows = params.count ? await query.limit(params.count) : await query;
2310
+ return rows.map((row) => ({
2311
+ id: row.memory.id,
2312
+ type: row.memory.type,
2313
+ createdAt: row.memory.createdAt,
2314
+ content: typeof row.memory.content === "string" ? JSON.parse(row.memory.content) : row.memory.content,
2315
+ entityId: row.memory.entityId,
2316
+ agentId: row.memory.agentId,
2317
+ roomId: row.memory.roomId,
2318
+ unique: row.memory.unique,
2319
+ embedding: row.embedding ?? void 0
2320
+ }));
2321
+ });
2322
+ }
2323
+ /**
2324
+ * Asynchronously deletes all rooms associated with a specific serverId.
2325
+ * @param {UUID} serverId - The server ID to delete rooms for.
2326
+ * @returns {Promise<void>} A Promise that resolves when the rooms are deleted.
2327
+ */
2328
+ async deleteRoomsByServerId(serverId) {
2329
+ return this.withDatabase(async () => {
2330
+ await this.db.transaction(async (tx) => {
2331
+ const roomIdsResult = await tx.select({ roomId: roomTable.id }).from(roomTable).where(eq(roomTable.serverId, serverId));
2332
+ if (roomIdsResult.length === 0) return;
2333
+ const roomIds = roomIdsResult.map((row) => row.roomId);
2334
+ await tx.delete(embeddingTable).where(
2335
+ inArray(
2336
+ embeddingTable.memoryId,
2337
+ tx.select({ id: memoryTable.id }).from(memoryTable).where(inArray(memoryTable.roomId, roomIds))
2338
+ )
2339
+ );
2340
+ await tx.delete(memoryTable).where(inArray(memoryTable.roomId, roomIds));
2341
+ await tx.delete(participantTable).where(inArray(participantTable.roomId, roomIds));
2342
+ await tx.delete(logTable).where(inArray(logTable.roomId, roomIds));
2343
+ await tx.delete(roomTable).where(inArray(roomTable.id, roomIds));
2344
+ });
2345
+ logger.debug("Rooms and related logs deleted successfully for server:", {
2346
+ serverId
2347
+ });
2348
+ });
2349
+ }
2350
+ };
2351
+
2352
+ // src/pglite/adapter.ts
2353
+ var PgliteDatabaseAdapter = class extends BaseDrizzleAdapter {
2354
+ static {
2355
+ __name(this, "PgliteDatabaseAdapter");
2356
+ }
2357
+ manager;
2358
+ embeddingDimension = DIMENSION_MAP[384];
2359
+ /**
2360
+ * Constructor for creating an instance of a class.
2361
+ * @param {UUID} agentId - The unique identifier for the agent.
2362
+ * @param {PGliteClientManager} manager - The manager for the PGlite client.
2363
+ */
2364
+ constructor(agentId, manager) {
2365
+ super(agentId);
2366
+ this.manager = manager;
2367
+ this.db = drizzle(this.manager.getConnection());
2368
+ }
2369
+ /**
2370
+ * Asynchronously runs the provided database operation while checking if the database manager is currently shutting down.
2371
+ * If the database manager is shutting down, a warning is logged and null is returned.
2372
+ *
2373
+ * @param {Function} operation - The database operation to be performed.
2374
+ * @returns {Promise<T>} A promise that resolves with the result of the database operation.
2375
+ */
2376
+ async withDatabase(operation) {
2377
+ if (this.manager.isShuttingDown()) {
2378
+ logger2.warn("Database is shutting down");
2379
+ return null;
2380
+ }
2381
+ return operation();
2382
+ }
2383
+ /**
2384
+ * Asynchronously initializes the database by running migrations using the manager.
2385
+ *
2386
+ * @returns {Promise<void>} A Promise that resolves when the database initialization is complete.
2387
+ */
2388
+ async init() {
2389
+ try {
2390
+ await this.manager.runMigrations();
2391
+ } catch (error) {
2392
+ logger2.error("Failed to initialize database:", error);
2393
+ throw error;
2394
+ }
2395
+ }
2396
+ /**
2397
+ * Asynchronously closes the manager.
2398
+ */
2399
+ async close() {
2400
+ await this.manager.close();
2401
+ }
2402
+ };
2403
+
2404
+ // src/pg/adapter.ts
2405
+ import { logger as logger3 } from "@elizaos/core";
2406
+ import { drizzle as drizzle2 } from "drizzle-orm/node-postgres";
2407
+ var PgDatabaseAdapter = class extends BaseDrizzleAdapter {
2408
+ /**
2409
+ * Constructor for creating a new instance of a class.
2410
+ * @param {UUID} agentId - The unique identifier for the agent.
2411
+ * @param {PostgresConnectionManager} manager - The Postgres connection manager for the instance.
2412
+ */
2413
+ constructor(agentId, manager) {
2414
+ super(agentId);
2415
+ this.manager = manager;
2416
+ this.manager = manager;
2417
+ }
2418
+ static {
2419
+ __name(this, "PgDatabaseAdapter");
2420
+ }
2421
+ embeddingDimension = DIMENSION_MAP[384];
2422
+ /**
2423
+ * Executes the provided operation with a database connection.
2424
+ *
2425
+ * @template T
2426
+ * @param {() => Promise<T>} operation - The operation to be executed with the database connection.
2427
+ * @returns {Promise<T>} A promise that resolves with the result of the operation.
2428
+ */
2429
+ async withDatabase(operation) {
2430
+ return await this.withRetry(async () => {
2431
+ const client = await this.manager.getClient();
2432
+ try {
2433
+ const db = drizzle2(client);
2434
+ this.db = db;
2435
+ return await operation();
2436
+ } finally {
2437
+ client.release();
2438
+ }
2439
+ });
2440
+ }
2441
+ /**
2442
+ * Asynchronously initializes the PgDatabaseAdapter by running migrations using the manager.
2443
+ * Logs a success message if initialization is successful, otherwise logs an error message.
2444
+ *
2445
+ * @returns {Promise<void>} A promise that resolves when initialization is complete.
2446
+ */
2447
+ async init() {
2448
+ try {
2449
+ await this.manager.runMigrations();
2450
+ logger3.debug("PgDatabaseAdapter initialized successfully");
2451
+ } catch (error) {
2452
+ logger3.error("Failed to initialize PgDatabaseAdapter:", error);
2453
+ throw error;
2454
+ }
2455
+ }
2456
+ /**
2457
+ * Asynchronously closes the manager associated with this instance.
2458
+ *
2459
+ * @returns A Promise that resolves once the manager is closed.
2460
+ */
2461
+ async close() {
2462
+ await this.manager.close();
2463
+ }
2464
+ };
2465
+
2466
+ // src/index.ts
2467
+ var GLOBAL_SINGLETONS = Symbol.for("@elizaos/plugin-sql/global-singletons");
2468
+ var globalSymbols = global;
2469
+ if (!globalSymbols[GLOBAL_SINGLETONS]) {
2470
+ globalSymbols[GLOBAL_SINGLETONS] = {};
2471
+ }
2472
+ var globalSingletons = globalSymbols[GLOBAL_SINGLETONS];
2473
+ function expandTildePath(filepath) {
2474
+ if (filepath && typeof filepath === "string" && filepath.startsWith("~")) {
2475
+ return filepath.replace(/^~/, os.homedir());
2476
+ }
2477
+ return filepath;
2478
+ }
2479
+ __name(expandTildePath, "expandTildePath");
2480
+ function createDatabaseAdapter(config, agentId) {
2481
+ if (config.dataDir) {
2482
+ config.dataDir = expandTildePath(config.dataDir);
2483
+ }
2484
+ if (config.postgresUrl) {
2485
+ if (!globalSingletons.postgresConnectionManager) {
2486
+ globalSingletons.postgresConnectionManager = new PostgresConnectionManager(
2487
+ config.postgresUrl
2488
+ );
2489
+ }
2490
+ return new PgDatabaseAdapter(agentId, globalSingletons.postgresConnectionManager);
2491
+ }
2492
+ const dataDir = config.dataDir ?? "./elizadb";
2493
+ if (!globalSingletons.pgLiteClientManager) {
2494
+ globalSingletons.pgLiteClientManager = new PGliteClientManager({ dataDir });
2495
+ }
2496
+ return new PgliteDatabaseAdapter(agentId, globalSingletons.pgLiteClientManager);
2497
+ }
2498
+ __name(createDatabaseAdapter, "createDatabaseAdapter");
2499
+ var sqlPlugin = {
2500
+ name: "sql",
2501
+ description: "SQL database adapter plugin using Drizzle ORM",
2502
+ init: /* @__PURE__ */ __name(async (_, runtime) => {
2503
+ const config = {
2504
+ dataDir: runtime.getSetting("PGLITE_DATA_DIR") ?? "./pglite",
2505
+ postgresUrl: runtime.getSetting("POSTGRES_URL")
2506
+ };
2507
+ try {
2508
+ const db = createDatabaseAdapter(config, runtime.agentId);
2509
+ logger4.success("Database connection established successfully");
2510
+ runtime.registerDatabaseAdapter(db);
2511
+ } catch (error) {
2512
+ logger4.error("Failed to initialize database:", error);
2513
+ throw error;
2514
+ }
2515
+ }, "init")
2516
+ };
2517
+ var index_default = sqlPlugin;
2518
+ export {
2519
+ createDatabaseAdapter,
2520
+ index_default as default
2521
+ };
49
2522
  //# sourceMappingURL=index.js.map