import {GRAPH_ENTITY_TYPE_DEFINITIONS,GRAPH_RELATION_TYPE_DEFINITIONS}from'@easbot/types';export{GRAPH_ENTITY_TYPE_DEFINITIONS,GRAPH_RELATION_TYPE_DEFINITIONS}from'@easbot/types';import*as P from'jieba-wasm';import {Log,loadTextFile,Filesystem,formatLocalISO}from'@easbot/utils';import Oe from'better-sqlite3';import {randomBytes,createHash}from'crypto';import A from'fs/promises';import M from'path';import {promises}from'fs';import {embed,embedMany,streamText}from'ai';var be=Object.defineProperty;var Re=(g,e,t)=>e in g?be(g,e,{enumerable:true,configurable:true,writable:true,value:t}):g[e]=t;var b=(g,e,t)=>Re(g,typeof e!="symbol"?e+"":e,t);var te=["user_preference","task_context","technical_fact","decision","relationship","reminder","error_pattern","workflow","exploration_finding","experience_summary","tool_usage","skill_creation","test","other"],k=class extends Error{constructor(t,r,n){super(t,{cause:n});b(this,"code",r);b(this,"cause",n);this.name="MemoryError";}},N=class extends k{constructor(e,t){super(e,"MEMORY_VALIDATION_ERROR",t),this.name="MemoryValidationError";}},j=class extends k{constructor(e){super(`Memory not found: ${e}`,"MEMORY_NOT_FOUND"),this.name="MemoryNotFoundError";}},B=class extends k{constructor(e){super(e,"MEMORY_PERMISSION_ERROR"),this.name="MemoryPermissionError";}},R=class extends k{constructor(e,t){super(e,"MEMORY_DATABASE_ERROR",t),this.name="MemoryDatabaseError";}},O=class extends k{constructor(e,t){super(e,"MEMORY_FILE_ERROR",t),this.name="MemoryFileError";}},G=class extends k{constructor(e,t){super(e,"MEMORY_SEARCH_ERROR",t),this.name="MemorySearchError";}},Y=class extends k{constructor(e,t){super(e,"MEMORY_EMBEDDING_ERROR",t),this.name="MemoryEmbeddingError";}},Te=(c=>(c.VALIDATION_ERROR="MEMORY_VALIDATION_ERROR",c.NOT_FOUND="MEMORY_NOT_FOUND",c.PERMISSION_ERROR="MEMORY_PERMISSION_ERROR",c.DATABASE_ERROR="MEMORY_DATABASE_ERROR",c.FILE_ERROR="MEMORY_FILE_ERROR",c.SEARCH_ERROR="MEMORY_SEARCH_ERROR",c.EMBEDDING_ERROR="MEMORY_EMBEDDING_ERROR",c))(Te||{});var w=Log.create({service:"memory.tokenizer"}),x=false,Ae=loadTextFile("./assets/jieba_dict.txt",import.meta.url);async function ae(g){if(!x)try{w.debug("Initializing jieba tokenizer");let e=Ae();if(P.with_dict(e),w.debug("Built-in dictionary loaded"),g?.dictPath&&g.dictPath.length>0)for(let t of g.dictPath)await Se(t);x=!0,w.debug("Jieba tokenizer initialized successfully");}catch(e){w.error("Failed to initialize jieba tokenizer",{error:String(e)}),w.warn("Using fallback tokenization (space-based)");}}async function Se(g){if(!x)throw new Error("Tokenizer not initialized");try{let e=await Filesystem.readText(g);w.debug("Loading custom dictionary",{dictPath:g}),P.with_dict(e),w.debug("Custom dictionary loaded successfully",{dictPath:g});}catch(e){w.warn("Failed to load custom dictionary",{dictPath:g,error:String(e)});}}function Ie(g){if(!x)return g.split(/\s+/).filter(Boolean);try{return P.cut(g)}catch(e){return w.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Ne(g){if(!x)return g.split(/\s+/).filter(Boolean);try{return P.cut_for_search(g)}catch(e){return w.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function tt(g,e,t){if(x)try{P.add_word(g,e,t),w.debug("Word added to dictionary",{word:g,freq:e,tag:t});}catch(r){w.warn("Failed to add word",{word:g,error:String(r)});}}function rt(){return x}async function nt(){x=false,w.debug("Tokenizer closed");}function ie(g){if(!x)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ie(g).join(" ")}catch(e){return w.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}function de(g){if(!x)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ne(g).join(" ")}catch(e){return w.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}var X=class{constructor(e){b(this,"db",null);b(this,"storagePath");b(this,"initialized",false);b(this,"initPromise",null);this.storagePath=Filesystem.normalize(e);}async initialize(){if(!this.initialized){if(this.initPromise){await this.initPromise;return}this.initPromise=this.doInitialize(),await this.initPromise,this.initialized=true;}}async doInitialize(){try{this.db=await this.openDatabaseAsync(),this.createTables(),this.db.pragma("foreign_keys = ON");}catch(e){throw new R(`Database initialization failed: ${e.message}`,e)}}async openDatabaseAsync(){return new Promise((e,t)=>{setImmediate(()=>{try{let r=new Oe(this.storagePath);r.pragma("journal_mode = WAL"),r.pragma("synchronous = NORMAL"),r.pragma("cache_size = -64000"),r.pragma("temp_store = MEMORY"),e(r);}catch(r){t(r);}});})}createTables(){if(!this.db)throw new R("Database not initialized");let e=this.db;e.exec(`
      CREATE TABLE IF NOT EXISTS memory_facts (
        id TEXT PRIMARY KEY,
        agent_id TEXT NOT NULL,
        session_id TEXT,
        msg_id TEXT,
        parent_msg_id TEXT,
        content TEXT NOT NULL,
        category TEXT NOT NULL,
        importance INTEGER NOT NULL CHECK(importance >= 1 AND importance <= 10),
        source TEXT NOT NULL CHECK(source IN ('session_self_write', 'historical')),
        tags TEXT,
        node_ids TEXT,
        file_path TEXT,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
        updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
        UNIQUE(session_id, msg_id)
      )
    `),e.exec("CREATE INDEX IF NOT EXISTS idx_memory_facts_agent_id ON memory_facts(agent_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_memory_facts_agent_category ON memory_facts(agent_id, category)"),e.exec("CREATE INDEX IF NOT EXISTS idx_memory_facts_agent_importance ON memory_facts(agent_id, importance DESC)"),e.exec("CREATE INDEX IF NOT EXISTS idx_memory_facts_created_at ON memory_facts(created_at)"),e.exec(`
      CREATE TABLE IF NOT EXISTS memory_vectors (
        fact_id TEXT PRIMARY KEY,
        embedding BLOB NOT NULL,
        FOREIGN KEY (fact_id) REFERENCES memory_facts(id) ON DELETE CASCADE
      )
    `),e.exec(`
      CREATE TABLE IF NOT EXISTS embedding_cache (
        content_hash TEXT PRIMARY KEY,
        embedding BLOB NOT NULL,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `),e.exec(`
      CREATE VIRTUAL TABLE IF NOT EXISTS memory_facts_fts USING fts5(
        fact_id UNINDEXED,
        agent_id UNINDEXED,
        content,
        tags,
        tokenize='porter unicode61'
      )
    `),e.exec(`
      CREATE TABLE IF NOT EXISTS nodes (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        type TEXT NOT NULL,
        properties TEXT,
        createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
        updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `),e.exec("CREATE INDEX IF NOT EXISTS idx_nodes_name ON nodes(name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(type)"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_nodes_name_type ON nodes(name, type)"),e.exec(`
      CREATE TABLE IF NOT EXISTS edges (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        source INTEGER NOT NULL,
        target INTEGER NOT NULL,
        relation TEXT NOT NULL,
        properties TEXT,
        createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (source) REFERENCES nodes(id) ON DELETE CASCADE,
        FOREIGN KEY (target) REFERENCES nodes(id) ON DELETE CASCADE
      )
    `),e.exec("CREATE INDEX IF NOT EXISTS idx_edges_source ON edges(source)"),e.exec("CREATE INDEX IF NOT EXISTS idx_edges_target ON edges(target)"),e.exec("CREATE INDEX IF NOT EXISTS idx_edges_relation ON edges(relation)"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_edges_unique ON edges(source, target, relation)"),e.exec(`
      CREATE TABLE IF NOT EXISTS meta (
        key TEXT PRIMARY KEY,
        value TEXT
      )
    `);}query(e,t){if(!this.db)throw new R("Database not initialized. Call initialize() first.");try{let r=this.db.prepare(e);return t?r.all(...t):r.all()}catch(r){throw new R(`Query failed: ${r.message}`,r)}}run(e,t){if(!this.db)throw new R("Database not initialized. Call initialize() first.");try{let r=this.db.prepare(e),n=t?r.run(...t):r.run();return {lastID:Number(n.lastInsertRowid),changes:n.changes}}catch(r){throw new R(`Write failed: ${r.message}`,r)}}transaction(e){if(!this.db)throw new R("Database not initialized. Call initialize() first.");return this.db.transaction(e)()}prepare(e){if(!this.db)throw new R("Database not initialized. Call initialize() first.");return this.db.prepare(e)}exec(e){if(!this.db)throw new R("Database not initialized. Call initialize() first.");this.db.exec(e);}getDb(){if(!this.db)throw new R("Database not initialized. Call initialize() first.");return this.db}getPath(){return this.storagePath}close(){this.db&&(this.db.close(),this.db=null,this.initialized=false);}healthCheck(){try{return this.db?(this.db.prepare("SELECT 1").get(),!0):!1}catch{return  false}}getMeta(e){if(!this.db)throw new Error("Database not initialized");return this.db.prepare("SELECT value FROM meta WHERE key = ?").get(e)?.value??null}setMeta(e,t){if(!this.db)throw new Error("Database not initialized");this.db.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)").run(e,t);}};var Fe=["id","agentId","category","importance"],q="---",L=class g{static generateId(){let e=Date.now(),t=randomBytes(3).toString("hex");return `mem_${e}_${t}`}static serialize(e){let t=new Date(e.createdAt),r=e.updatedAt?new Date(e.updatedAt):new Date,n={id:e.id,agentId:e.agentId,category:e.category,importance:e.importance,createdAt:formatLocalISO(t),updatedAt:formatLocalISO(r),source:e.source};e.sessionId&&(n.sessionId=e.sessionId),e.msgId&&(n.msgId=e.msgId),e.parentMsgId&&(n.parentMsgId=e.parentMsgId),e.tags&&e.tags.length>0&&(n.tags=e.tags),e.nodeIds&&e.nodeIds.length>0&&(n.nodeIds=e.nodeIds),e.filePath&&(n.filePath=e.filePath);let i=Object.entries(n).map(([a,c])=>Array.isArray(c)?`${a}: [${c.join(", ")}]`:`${a}: ${c}`);return [q,...i,q,"",e.content.trim(),""].join(`
`)}static serializeFile(e){return e.map(t=>g.serialize(t)).join(`
`)}static parse(e){let t=[],r=e.split(`
`),n=0;for(;n<r.length;){if(r[n]?.trim()!==q){n++;continue}let i=n+1,a=-1;for(let l=i;l<r.length;l++)if(r[l]?.trim()===q){a=l;break}if(a===-1){n++;continue}let c=r.slice(i,a),o=g.parseFrontmatter(c);g.validateFrontmatter(o);let m=a+1,d=r.length;for(let l=m;l<r.length;l++)if(r[l]?.trim()===q){d=l;break}let s=r.slice(m,d).join(`
`).trim(),u={id:String(o.id),agentId:String(o.agentId),category:o.category,importance:Number(o.importance),source:o.source??"session_self_write",content:s,createdAt:o.createdAt?new Date(String(o.createdAt)).toISOString():new Date().toISOString(),updatedAt:o.updatedAt?new Date(String(o.updatedAt)).toISOString():new Date().toISOString()};o.sessionId&&(u.sessionId=String(o.sessionId)),o.msgId&&(u.msgId=String(o.msgId)),o.parentMsgId&&(u.parentMsgId=String(o.parentMsgId)),o.filePath&&(u.filePath=String(o.filePath)),o.tags&&(u.tags=g.parseArrayField(o.tags)),o.nodeIds&&(u.nodeIds=g.parseArrayField(o.nodeIds).map(Number).filter(l=>!Number.isNaN(l))),t.push(u),n=d;}return t}static parseFrontmatter(e){let t={};for(let r of e){let n=r.indexOf(":");if(n===-1)continue;let i=r.slice(0,n).trim(),a=r.slice(n+1).trim();if(i)if(a.startsWith("[")&&a.endsWith("]")){let c=a.slice(1,-1).trim();t[i]=c?c.split(",").map(o=>o.trim()).filter(Boolean):[];}else t[i]=a;}return t}static validateFrontmatter(e){for(let n of Fe)if(e[n]===void 0||e[n]==="")throw new N(`Missing required field in memory frontmatter: ${n}`);let t=e.category;if(!te.includes(t))throw new N(`Invalid category: "${t}". Valid values: ${te.join(", ")}`);let r=Number(e.importance);if(Number.isNaN(r)||r<1||r>10)throw new N(`Invalid importance: "${e.importance}". Must be an integer between 1 and 10.`)}static parseArrayField(e){if(Array.isArray(e))return e.map(String);if(typeof e=="string"){let t=e.trim();if(t.startsWith("[")&&t.endsWith("]")){let r=t.slice(1,-1).trim();return r?r.split(",").map(n=>n.trim()).filter(Boolean):[]}return t?[t]:[]}return []}};var me="MEMORY.md",ge="active",xe="archive",_=class g{static getMemoryMdPath(e){return M.join(e,me)}static getActiveFilePath(e,t,r){let n=r??new Date,i=n.getFullYear(),a=String(n.getMonth()+1).padStart(2,"0"),c=String(n.getDate()).padStart(2,"0"),o=`${i}-${a}-${c}`;return M.join(e,ge,t,`${o}.md`)}static getArchiveFilePath(e,t,r,n){let i=new Date(r),a=`${i.getFullYear()}-${String(i.getMonth()+1).padStart(2,"0")}`;return M.join(e,xe,a,t,n)}static async readMemoryMd(e){let t=g.getMemoryMdPath(e);try{return await A.readFile(t,"utf-8")}catch(r){if(r.code==="ENOENT")return null;throw new O(`Failed to read MEMORY.md: ${r.message}`,r)}}static async write(e,t){let r=g.getActiveFilePath(e,t.category);if(M.basename(r)===me)throw new B("Writing to MEMORY.md is not allowed. MEMORY.md is read-only.");try{await A.mkdir(M.dirname(r),{recursive:!0});let n=L.serialize(t),i="";try{i=await A.readFile(r,"utf-8");}catch{}let a=i.length>0&&!i.endsWith(`
`)?`
`:"";return await A.writeFile(r,`${i}${a}${n}`,"utf-8"),Filesystem.normalize(r)}catch(n){throw n instanceof B?n:new O(`Failed to write memory to ${r}: ${n.message}`,n)}}static async read(e){try{let t=await A.readFile(e,"utf-8");return L.parse(t)}catch(t){if(t.code==="ENOENT")return [];throw new O(`Failed to read memory file ${e}: ${t.message}`,t)}}static async delete(e,t){try{let r=await g.read(e),n=r.filter(i=>i.id!==t);if(n.length===r.length)return;n.length===0?await A.unlink(e).catch(()=>{}):await A.writeFile(e,L.serializeFile(n),"utf-8");}catch(r){throw r instanceof O?r:new O(`Failed to delete memory ${t} from ${e}: ${r.message}`,r)}}static async update(e,t,r){try{let n=await g.read(e),i=n.findIndex(c=>c.id===t);if(i===-1)return;let a={...n[i],...r,updatedAt:new Date().toISOString()};n[i]=a,await A.writeFile(e,L.serializeFile(n),"utf-8");}catch(n){throw n instanceof O?n:new O(`Failed to update memory ${t} in ${e}: ${n.message}`,n)}}static async listActiveFiles(e){let t=M.join(e,ge),r=[];try{await g.scanDir(t,r);}catch(n){if(n.code==="ENOENT")return [];throw new O(`Failed to list active memory files: ${n.message}`,n)}return r}static async scanDir(e,t){let r=await A.readdir(e,{withFileTypes:true});for(let n of r){let i=M.join(e,n.name);n.isDirectory()?await g.scanDir(i,t):n.isFile()&&n.name.endsWith(".md")&&t.push(i);}}};var H=class{constructor(e,t){b(this,"db");b(this,"config");this.db=e,this.config=t;}async archive(){let t=(this.config.archiveDays??30)*864e5,r=Date.now(),n=[],i=await _.listActiveFiles(this.config.workspaceDir);for(let a of i){let c=await _.read(a);if(c.length===0)continue;let o=c[0]?.createdAt,m=o?new Date(o).getTime():r;if(r-m<=t)continue;let d=c[0]?.category;if(!d)continue;let s=M.basename(a),u=_.getArchiveFilePath(this.config.workspaceDir,d,m,s);await promises.mkdir(M.dirname(u),{recursive:true}),await promises.rename(a,u);let l=Filesystem.normalize(u),p=Filesystem.normalize(a);this.db.prepare("UPDATE memory_facts SET file_path = ? WHERE file_path = ?").run(l,p),n.push({source:a,target:u,timestamp:r});}return {archivedCount:n.length,records:n}}};var K=Log.create({service:"memory.graph-store"}),J=class{constructor(e){b(this,"db");this.db=e;}async upsertNode(e,t,r){let n=Date.now(),i=this.db.prepare("SELECT id FROM nodes WHERE name = ? AND type = ?").get(e,t);if(i)return this.db.prepare("UPDATE nodes SET properties = ?, updatedAt = ? WHERE id = ?").run(JSON.stringify(r??{}),n,i.id),i.id;let a=this.db.prepare("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)").run(e,t,JSON.stringify(r??{}),n,n);return Number(a.lastInsertRowid)}async deleteNode(e){this.db.prepare("DELETE FROM nodes WHERE id = ?").run(e);}async upsertEdge(e,t,r,n){let i=this.db.prepare("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)").run(e,t,r,JSON.stringify(n??{}),Date.now());return Number(i.lastInsertRowid)}async queryNodes(e={}){let t="SELECT id, name, type, properties, createdAt, updatedAt FROM nodes",r=[],n=[];if(e.ids&&e.ids.length>0){let a=e.ids.map(c=>typeof c=="string"?parseInt(c,10):c).filter(c=>!Number.isNaN(c));n.push(`id IN (${a.map(()=>"?").join(", ")})`),r.push(...a);}e.name&&(n.push("name LIKE ?"),r.push(`%${e.name}%`)),e.type&&(n.push("type = ?"),r.push(e.type)),n.length>0&&(t+=` WHERE ${n.join(" AND ")}`),t+=" ORDER BY id",e.limit&&(t+=" LIMIT ?",r.push(e.limit)),K.debug("queryNodes",{sql:t,params:r,filter:e});let i=this.db.prepare(t).all(...r);return K.debug("queryNodes result",{count:i.length}),i.map(a=>({id:a.id,name:a.name,type:a.type,properties:a.properties?JSON.parse(a.properties):void 0,createdAt:a.createdAt,updatedAt:a.updatedAt}))}async queryEdges(e={}){let t="SELECT id, source, target, relation, properties, createdAt FROM edges",r=[],n=[];if(e.ids&&e.ids.length>0&&(n.push(`id IN (${e.ids.map(()=>"?").join(", ")})`),r.push(...e.ids)),e.source!==void 0&&(n.push("source = ?"),r.push(e.source)),e.target!==void 0&&(n.push("target = ?"),r.push(e.target)),e.sourceOrTarget&&e.sourceOrTarget.length>0){let m=e.sourceOrTarget.map(d=>typeof d=="string"?parseInt(d,10):d).filter(d=>!Number.isNaN(d));n.push(`(source IN (${m.map(()=>"?").join(", ")}) OR target IN (${m.map(()=>"?").join(", ")}))`),r.push(...m,...m);}e.relation&&(n.push("relation = ?"),r.push(e.relation)),n.length>0&&(t+=` WHERE ${n.join(" AND ")}`),t+=" ORDER BY id",e.limit&&(t+=" LIMIT ?",r.push(e.limit)),K.debug("queryEdges",{sql:t,params:r,filter:e});let i=this.db.prepare(t).all(...r);K.debug("queryEdges result",{count:i.length});let a=[...new Set(i.map(m=>m.target))],c=a.length>0?await this.queryNodes({ids:a,limit:a.length}):[],o=new Map(c.map(m=>[m.id,m]));return i.map(m=>{let d={id:m.id,source:m.source,target:m.target,relation:m.relation,properties:m.properties?JSON.parse(m.properties):void 0,createdAt:m.createdAt},s=o.get(m.target);return s&&(d.targetNode=s),d})}async queryNeighbors(e,t=1,r){let n=new Set,i=[{id:e,level:0}],a=[],c=r?.maxEdgesPerNode??50;for(;i.length>0;){let o=i.shift();if(!o)break;if(n.has(o.id)||o.level>t)continue;n.add(o.id);let d=(await this.queryNodes({ids:[o.id],limit:1}))[0];if(!d)continue;let s=await this.queryEdges({sourceOrTarget:[o.id],limit:c});if(a.push({...d,edges:s}),o.level<t)for(let u of s){let l=u.source===o.id?u.target:u.source;n.has(l)||i.push({id:l,level:o.level+1});}}return a}};var z;(d=>{let g=null;function e(s){t()||(g={models:s.models,options:s.options??{}});}d.init=e;function t(){return g!==null}d.isInitialized=t;function r(){return g?{embedding:!!g.models.embeddingLlm,graph:!!g.models.graphLlm}:{embedding:false,graph:false}}d.capabilities=r;async function n(s){let l=c().models.embeddingLlm;if(!l)throw new Error("embeddingLlm model is not configured.");try{let p=await embed({model:l,value:s});return new Float32Array(p.embedding)}catch(p){let E=l.doEmbed;if(typeof E!="function")throw new Error("embeddingLlm model does not support embedding generation.",{cause:p});let S=(await E({values:[s]}))?.embeddings?.[0];if(!S||!Array.isArray(S))throw new Error("embeddingLlm model returned invalid embedding result.",{cause:p});return new Float32Array(S)}}d.embedText=n;async function i(s){let l=c().models.embeddingLlm;if(!l)throw new Error("embeddingLlm model is not configured.");try{return (await embedMany({model:l,values:s})).embeddings.map(E=>new Float32Array(E))}catch{return ((await l.doEmbed?.({values:s}))?.embeddings??[]).map(E=>new Float32Array(E))}}d.embedTexts=i;async function a(s,u){let l=c(),p=l.models.graphLlm;if(!p)throw new Error("llm model is not configured.");try{return (await streamText({model:p,prompt:s,maxOutputTokens:u?.maxOutputTokens??l.options.graph?.maxOutputTokens,temperature:u?.temperature??l.options.graph?.temperature})).text}catch{return (await p.doGenerate?.({prompt:[{role:"user",content:[{type:"text",text:s}]}],maxOutputTokens:u?.maxOutputTokens??l.options.graph?.maxOutputTokens}))?.content?.find(D=>D.type==="text")?.text??""}}d.generate=a;let c=()=>{if(!g)throw new Error("Llm is not initialized. Please call Llm.init() first.");return g};d.embed=n,d.embedMany=i;})(z||(z={}));var Q=class{constructor(e,t){b(this,"db");b(this,"config");b(this,"embeddingModel");this.db=e,this.config=t,this.embeddingModel=t.embeddingLlm,this.embeddingModel&&z.init({models:{embeddingLlm:this.embeddingModel,graphLlm:t.graphLlm}});}async search(e,t){if(!e.trim())return [];if(!t?.agentId)return [];let r=t.maxResults??this.config.search.maxResults,n=await this.hybridSearch(e,{...t,maxResults:r*2});return n.length===0?[]:n.slice(0,r)}async hybridSearch(e,t){let{maxResults:r=this.config.search.maxResults,minScore:n=this.config.search.minScore,vectorWeight:i=this.config.search.hybrid.vectorWeight,textWeight:a=this.config.search.hybrid.textWeight,enableEmbedding:c=true}=t??{},m=c&&!!this.embeddingModel?await this.embed(e):null,d=["mf.agent_id = ?"],s=[t?.agentId];t?.category&&(d.push("mf.category = ?"),s.push(t.category)),t?.minImportance!==void 0&&(d.push("mf.importance >= ?"),s.push(t.minImportance)),t?.source&&(d.push("mf.source = ?"),s.push(t.source)),t?.fromTime!==void 0&&(d.push("mf.created_at >= ?"),s.push(t.fromTime)),t?.toTime!==void 0&&(d.push("mf.created_at <= ?"),s.push(t.toTime));let u=d.join(" AND "),[l,p]=await Promise.all([m?this.vectorSearch(m,u,s,r,n,t?.candidateFactIds):Promise.resolve([]),this.ftsSearch(e,u,s,r,n)]),E=m?i:0,D=m?a:1;return this.mergeResults(l,p,E,D,u,s,n)}async vectorSearch(e,t,r,n,i,a){if(!this.embeddingModel)return [];try{let c;if(a&&a.length>0){let m=a.map(()=>"?").join(",");c=this.db.prepare(`
          SELECT mf.id, mv.embedding
          FROM memory_facts mf
          JOIN memory_vectors mv ON mf.id = mv.fact_id
          WHERE ${t} AND mf.id IN (${m})
        `).all(...r,...a);}else c=this.db.prepare(`
          SELECT mf.id, mv.embedding
          FROM memory_facts mf
          JOIN memory_vectors mv ON mf.id = mv.fact_id
          WHERE ${t}
          LIMIT ?
        `).all(...r,Math.max(n*100,1e3));let o=[];for(let m of c){let d=new Float32Array(m.embedding.buffer,m.embedding.byteOffset,m.embedding.length/4),s=this.cosineSimilarity(e,d);o.push({id:m.id,score:s});}return o.sort((m,d)=>d.score-m.score).slice(0,n)}catch(c){throw new G(`\u5411\u91CF\u641C\u7D22\u5931\u8D25: ${c instanceof Error?c.message:String(c)}`,c instanceof Error?c:void 0)}}async ftsSearch(e,t,r,n,i){let a=()=>[];try{let o=(de(e).trim()||e.trim()).split(/\s+/).filter(s=>s.length>0).map(s=>`"${s.replace(/"/g,'""')}"`).join(" "),m=this.db.prepare(`
        SELECT mf.id, bm25(memory_facts_fts) as score
        FROM memory_facts mf
        JOIN memory_facts_fts ON mf.id = memory_facts_fts.fact_id
        WHERE ${t} AND memory_facts_fts.content MATCH ?
        ORDER BY score DESC
        LIMIT ?
      `).all(...r,o,n);if(m.length===0)return a();let d=Math.max(...m.map(s=>Math.abs(s.score)),1);return m.map(s=>({id:s.id,score:1-Math.abs(s.score)/d})).filter(s=>s.score>=0)}catch{return a()}}async mergeResults(e,t,r,n,i,a,c){let o=r+n,m=r/o,d=n/o,s=new Map;for(let h of e)s.set(h.id,h.score*m);for(let h of t){let T=s.get(h.id)||0;s.set(h.id,T+h.score*d);}let u=Array.from(s.entries()).map(([h,T])=>({id:h,score:T})).sort((h,T)=>T.score-h.score).map(h=>h.id);if(u.length===0)return [];let l=u.map(()=>"?").join(","),p=this.db.prepare(`
      SELECT
        mf.id as memoryId,
        mf.category,
        mf.importance,
        mf.agent_id as agentId,
        SUBSTR(mf.content, 1, 200) as snippet,
        mf.created_at as createdAt,
        mf.source,
        mf.file_path as filePath,
        mf.node_ids
      FROM memory_facts mf
      WHERE mf.id IN (${l})
    `).all(...u),E=[],D=new Map;for(let h of p)if(h.node_ids)try{let T=JSON.parse(h.node_ids);D.set(h.memoryId,T),E.push(...T);}catch{}let S=Array.from(new Set(E)),$=new Map,I=new Map;if(S.length>0){let h=S.map(()=>"?").join(", "),T=this.db.prepare(`SELECT id, name, type FROM nodes WHERE id IN (${h})`).all(...S);for(let y of T)$.set(y.id,y);let V=this.db.prepare(`SELECT e.id, e.source, e.target, e.relation, e.properties, e.createdAt, n.name as targetName, n.type as targetType
         FROM edges e JOIN nodes n ON n.id = e.target
         WHERE e.source IN (${h})`).all(...S);for(let y of V){let W=I.get(y.source)??[];W.push({id:y.id,source:y.source,target:y.target,relation:y.relation,properties:y.properties?JSON.parse(y.properties):void 0,createdAt:y.createdAt,targetNode:{id:y.target,name:y.targetName,type:y.targetType,createdAt:y.createdAt,updatedAt:y.createdAt}}),I.set(y.source,W);}let ee=this.db.prepare(`SELECT e.id, e.source, e.target, e.relation, e.properties, e.createdAt, n.name as sourceName, n.type as sourceType
         FROM edges e JOIN nodes n ON n.id = e.source
         WHERE e.target IN (${h})`).all(...S);for(let y of ee){let W=I.get(y.target)??[];W.push({id:y.id,source:y.source,target:y.target,relation:y.relation,properties:y.properties?JSON.parse(y.properties):void 0,createdAt:y.createdAt,targetNode:{id:y.source,name:y.sourceName,type:y.sourceType,createdAt:y.createdAt,updatedAt:y.createdAt}}),I.set(y.target,W);}}return p.map(h=>{let T=D.get(h.memoryId)??[],V=T.length>0?T.flatMap(se=>{let oe=$.get(se);return oe?[{...oe,edges:I.get(se)}]:[]}):void 0,ee=s.get(h.memoryId)??0,y=new Date(h.createdAt),W=(Date.now()-y.getTime())/864e5,ye=Math.exp(-0.05*W),fe=(h.importance-1)/9,Ee=.4*ee+.3*ye+.3*fe;return {memoryId:h.memoryId,category:h.category,importance:h.importance,agentId:h.agentId,snippet:h.snippet,score:Ee,createdAt:h.createdAt,source:h.source,filePath:h.filePath,nodes:(V?.length??0)>0?V:void 0}}).filter(h=>h.score>=c).sort((h,T)=>T.score-h.score)}async embed(e){if(!this.embeddingModel)throw new Y("Embedding \u6A21\u578B\u672A\u914D\u7F6E\uFF0C\u65E0\u6CD5\u751F\u6210\u5411\u91CF");try{return await z.embedText(e)}catch(t){throw new Y(`\u751F\u6210\u5411\u91CF\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`,t instanceof Error?t:void 0)}}cosineSimilarity(e,t){if(e.length!==t.length||e.length===0)return 0;let r=0,n=0,i=0;for(let a=0;a<e.length;a++){let c=e[a],o=t[a];r+=c*o,n+=c*c,i+=o*o;}return r/(Math.sqrt(n)*Math.sqrt(i))}};var f=Log.create({service:"memory.system"}),Ue=.7,je=.3,Be=10;var Ye=new Set(GRAPH_ENTITY_TYPE_DEFINITIONS.map(g=>g.type)),Xe=new Set(GRAPH_RELATION_TYPE_DEFINITIONS.map(g=>g.type)),Z=class{constructor(e){b(this,"config");b(this,"db");b(this,"archiver",null);b(this,"searchEngine",null);b(this,"graphStore",null);b(this,"embeddingModel");b(this,"vectorDims");e.search?.hybrid;this.config={workspaceDir:e.workspaceDir,database:e.database,archiveDays:e.archiveDays??30,search:{maxResults:e.search?.maxResults??Be,minScore:e.search?.minScore??.3,hybrid:{enabled:e.search?.hybrid?.enabled??true,vectorWeight:e.search?.hybrid?.vectorWeight??Ue,textWeight:e.search?.hybrid?.textWeight??je}},embedding:e.embedding??{},tokenizer:e.tokenizer??{},indexer:e.indexer??{batchSize:50,ignorePatterns:[],incremental:false},logDir:e.logDir??"",graphLlm:e.graphLlm,embeddingLlm:e.embeddingLlm},this.embeddingModel=e.embeddingLlm,this.db=new X(e.database.path),this.embeddingModel&&z.init({models:{embeddingLlm:this.embeddingModel,graphLlm:this.config.graphLlm}});}async initialize(){await A.mkdir(M.dirname(this.config.database.path),{recursive:true}),await A.mkdir(M.join(this.config.workspaceDir,"active"),{recursive:true}),await A.mkdir(M.join(this.config.workspaceDir,"archive"),{recursive:true}),await this.db.initialize(),this.archiver=new H(this.db.getDb(),this.config),this.graphStore=new J(this.db.getDb()),this.searchEngine=new Q(this.db.getDb(),this.config);let e=this.db.query("SELECT value FROM meta WHERE key = ?",["vectorDims"]);e[0]&&(this.vectorDims=parseInt(e[0].value,10));let t=[["version","1.0.0"],["createdAt",new Date().toISOString()]];for(let[r,n]of t)this.db.run("INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)",[r,n]);await ae({dictPath:this.config.tokenizer.dictPath}).catch(r=>{f.warn("Tokenizer initialization failed, using fallback",{error:String(r)});}),f.info("Memory system initialized",{workspaceDir:this.config.workspaceDir,dbPath:this.config.database.path}),f.debug("Memory system detail",{workspaceDir:this.config.workspaceDir,dbPath:this.config.database.path,embeddingEnabled:!!this.embeddingModel,graphLlmEnabled:!!this.config.graphLlm,archiveDays:this.config.archiveDays,hybridSearch:this.config.search.hybrid.enabled,vectorWeight:this.config.search.hybrid.vectorWeight,textWeight:this.config.search.hybrid.textWeight});}async remember(e){if(!e.agentId?.trim())throw new N("agentId is required for remember operation");let t=new Date().toISOString(),r=L.generateId(),n=_.getActiveFilePath(this.config.workspaceDir,e.category),i={...e,id:r,source:"session_self_write",createdAt:t,updatedAt:t,filePath:Filesystem.normalize(n)};_.write(this.config.workspaceDir,i).then(u=>{f.debug("Memory written to file",{id:r,filePath:u});}).catch(u=>{f.warn("Failed to write memory to file",{id:r,error:String(u)});});let a=[],c=this.config,o=this.extractEntities(i.content);if(a=this.storeEntitiesAndRelations(o.entities,o.relations).nodeIds,c.graphLlm){let u=i.content,l=i.agentId,p=i.id;f.debug("Scheduling background LLM extraction",{id:p,contentLength:u.length}),this.extractEntitiesWithLlm(u).then(E=>{f.debug("Background LLM extraction completed",{id:p,entities:E.entities.length,relations:E.relations.length}),this.mergeEntitiesAndRelations(p,l,E.entities,E.relations);}).catch(E=>{f.warn("Background graph extraction failed",{id:p,error:String(E)});});}i.nodeIds=a;let d=await this.embed(i.content),s=d?Buffer.from(d.buffer,d.byteOffset,d.byteLength):null;return this.db.transaction(()=>{this.db.run(`INSERT OR REPLACE INTO memory_facts
          (id, agent_id, session_id, msg_id, parent_msg_id, content, category, importance,
           source, tags, node_ids, file_path, created_at, updated_at)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[i.id,i.agentId,i.sessionId??null,i.msgId??null,i.parentMsgId??null,i.content,i.category,i.importance,i.source,i.tags?JSON.stringify(i.tags):null,i.nodeIds?JSON.stringify(i.nodeIds):null,i.filePath?i.filePath:null,i.createdAt,i.updatedAt]),s&&this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[i.id,s]),this.writeFts(i.id,i.agentId,i.content,i.tags);}),f.info("Memory stored",{id:i.id,category:i.category,agentId:i.agentId,nodeCount:a.length}),i}async query(e,t){if(!t?.agentId?.trim())throw new N("agentId is required for query operation");return this.getSearchEngine().search(e,t)}async queryEdgesByNodeId(e,t){if(!this.graphStore)return {nodes:[],edges:[]};let r=Math.min(Math.max(t?.maxDepth??2,1),3),n=await this.graphStore.queryNeighbors(e,r,{maxEdgesPerNode:t?.maxEdgesPerNode??20}),i=n.find(a=>a.id===e);return {node:i?{id:i.id,name:i.name,type:i.type}:void 0,nodes:n.map(a=>a),edges:n.flatMap(a=>a.edges??[])}}async forget(e,t){if(!e?.trim())throw new N("agentId is required for forget operation");let r=this.db.query("SELECT file_path, node_ids, content FROM memory_facts WHERE id = ? AND agent_id = ?",[t,e]);if(r.length===0)throw new j(t);let n=r[0]?.file_path,i=r[0]?.node_ids?JSON.parse(r[0].node_ids):[],a=r[0]?.content,c=a?createHash("sha256").update(a).digest("hex"):null,o=new Set;if(i.length>0){i.map(()=>"?").join(",");let s=this.db.query("SELECT node_ids FROM memory_facts WHERE id != ? AND agent_id = ? AND node_ids IS NOT NULL",[t,e]);for(let u of s)if(u.node_ids){let l=JSON.parse(u.node_ids);for(let p of l)o.add(p);}}let m=i.filter(d=>!o.has(d));if(this.db.transaction(()=>{if(this.db.run("DELETE FROM memory_facts WHERE id = ? AND agent_id = ?",[t,e]),this.db.run("DELETE FROM memory_facts_fts WHERE fact_id = ?",[t]),m.length>0){let d=m.map(()=>"?").join(",");this.db.run(`DELETE FROM nodes WHERE id IN (${d})`,m);}c&&this.db.run("DELETE FROM embedding_cache WHERE content_hash = ?",[c]);}),n){let d=M.isAbsolute(n)?n:M.join(this.config.workspaceDir,n);await _.delete(d,t).catch(s=>{f.warn("Failed to delete memory from file",{memoryId:t,filePath:n,error:String(s)});});}f.info("Memory deleted",{memoryId:t,agentId:e,orphanNodes:m.length});}async update(e,t,r){if(!e?.trim())throw new N("agentId is required for update operation");let n=this.db.query("SELECT * FROM memory_facts WHERE id = ? AND agent_id = ?",[t,e]);if(n.length===0)throw new j(t);let i=n[0],a=new Date().toISOString(),c=r.content??i.content,o=r.importance??i.importance,m=r.tags??(i.tags?JSON.parse(i.tags):void 0),d=r.content?await this.embed(c).then(u=>u?Buffer.from(u.buffer,u.byteOffset,u.byteLength):null):null;if(this.db.transaction(()=>{this.db.run(`UPDATE memory_facts SET content = ?, importance = ?, tags = ?, updated_at = ?
         WHERE id = ? AND agent_id = ?`,[c,o,m?JSON.stringify(m):null,a,t,e]),d&&this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[t,d]),this.writeFts(t,e,c,m);}),i.file_path){let u=M.isAbsolute(i.file_path)?i.file_path:M.join(this.config.workspaceDir,i.file_path);await _.update(u,t,r).catch(l=>{f.warn("Failed to update memory in file",{memoryId:t,error:String(l)});});}let s={id:i.id,agentId:i.agent_id,sessionId:i.session_id??void 0,msgId:i.msg_id??void 0,parentMsgId:i.parent_msg_id??void 0,content:c,category:i.category,importance:o,source:i.source,tags:m,nodeIds:i.node_ids?JSON.parse(i.node_ids):void 0,filePath:i.file_path??void 0,createdAt:String(i.created_at),updatedAt:a};return f.info("Memory updated",{memoryId:t,agentId:e}),s}async listAgentIds(){return this.db.query("SELECT DISTINCT agent_id FROM memory_facts ORDER BY agent_id").map(t=>t.agent_id)}async queryForSummary(e,t={}){if(!e?.trim())return [];let{limit:r=10,category:n,fromTime:i,toTime:a}=t,c=["agent_id = ?"],o=[e];if(n&&(c.push("category = ?"),o.push(n)),i){let s=new Date(i).getTime();Number.isNaN(s)||(c.push("created_at >= ?"),o.push(s));}if(a){let s=new Date(a).getTime();Number.isNaN(s)||(c.push("created_at <= ?"),o.push(s));}let m=c.join(" AND ");return this.db.query(`SELECT * FROM memory_facts
       WHERE ${m}
       ORDER BY importance DESC, created_at DESC
       LIMIT ?`,[...o,r]).map(s=>({id:s.id,agentId:s.agent_id,sessionId:s.session_id??void 0,msgId:s.msg_id??void 0,parentMsgId:s.parent_msg_id??void 0,content:s.content,category:s.category,importance:s.importance,source:s.source,tags:s.tags?JSON.parse(s.tags):void 0,nodeIds:s.node_ids?JSON.parse(s.node_ids):void 0,filePath:s.file_path??void 0,createdAt:String(s.created_at),updatedAt:String(s.updated_at)}))}async archive(){await this.getArchiver().archive();}async cleanupOrphanRecords(){let e=this.db.transaction(()=>{let t=this.db.run("DELETE FROM memory_facts_fts WHERE fact_id NOT IN (SELECT id FROM memory_facts)"),r=this.db.run("DELETE FROM memory_vectors WHERE fact_id NOT IN (SELECT id FROM memory_facts)"),n=this.db.run("DELETE FROM embedding_cache WHERE content_hash NOT IN (SELECT content_hash FROM memory_facts)");return {orphanFts:t.changes,orphanVectors:r.changes,orphanCache:n.changes}});(e.orphanFts>0||e.orphanVectors>0||e.orphanCache>0)&&f.info("Cleaned orphan records",e);}async clear(){this.db.transaction(()=>{this.db.run("DELETE FROM memory_facts"),this.db.run("DELETE FROM memory_vectors"),this.db.run("DELETE FROM embedding_cache"),this.db.run("DELETE FROM memory_facts_fts"),this.db.run("DELETE FROM nodes"),this.db.run("DELETE FROM edges");});try{let e=await _.listActiveFiles(this.config.workspaceDir);for(let t of e)await A.rm(t,{force:!0}).catch(()=>{});}catch(e){f.warn("Failed to clean memory files",{error:String(e)});}f.info("Memory system cleared");}async close(){this.db.close(),f.info("Memory system closed");}async getStatus(){try{let e=this.db.query("SELECT COUNT(*) as c FROM memory_facts"),t=this.db.query("SELECT COUNT(*) as c FROM graph_nodes"),r=this.db.query("SELECT COUNT(*) as c FROM graph_edges"),n=this.db.query("SELECT key, value FROM meta"),i={};for(let a of n)i[a.key]=a.value;return {dbPath:this.config.database.path,workspaceDir:this.config.workspaceDir,factsCount:e[0]?.c??0,nodesCount:t[0]?.c??0,edgesCount:r[0]?.c??0,embeddingLlmAvailable:!!this.config.embeddingLlm,graphLlmAvailable:!!this.config.graphLlm,healthy:!0,meta:i}}catch{return {dbPath:this.config.database.path,workspaceDir:this.config.workspaceDir,factsCount:0,nodesCount:0,edgesCount:0,embeddingLlmAvailable:false,graphLlmAvailable:false,healthy:false,meta:{}}}}async sync(){let e={synced:0,created:0,updated:0,errors:[]};await this.hasMemoryFiles()||await this.clearFiles();let r=this.db.query("SELECT * FROM memory_facts ORDER BY category, created_at ASC",[]),n=new Map;for(let c of r){let o=c.category,m=new Date(c.created_at),s=`${`${m.getFullYear()}-${String(m.getMonth()+1).padStart(2,"0")}-${String(m.getDate()).padStart(2,"0")}`}.md`,u=`${o}/${s}`;if(!n.has(u)){let l=M.join(this.config.workspaceDir,"active",o,s);n.set(u,{path:l,facts:[]});}n.get(u).facts.push(c);}for(let[c,{path:o,facts:m}]of n)try{let d=M.dirname(o);await A.mkdir(d,{recursive:!0});let s=m.map(l=>{let p=this.rowToFact(l);return L.serialize(p)}).join(`
`);if(await A.access(o).then(()=>!0).catch(()=>!1)){if((await A.readFile(o,"utf-8")).trim()===s.trim()){e.synced++;continue}e.updated++;}else e.created++;await A.writeFile(o,s,"utf-8"),e.synced++;}catch(d){let s=d instanceof Error?d.message:String(d);e.errors.push(`Failed to sync ${c}: ${s}`),f.warn("Memory file sync failed",{key:c,error:s});}f.info("Memory sync completed",{synced:e.synced,created:e.created,updated:e.updated,errors:e.errors.length});let i=new Date().toISOString();this.db.setMeta("lastSync",i);let a={timestamp:i,success:e.errors.length===0,synced:e.synced,created:e.created,updated:e.updated,errorCount:e.errors.length,errors:e.errors};return this.db.setMeta("lastSyncResult",JSON.stringify(a)),e}async hasMemoryFiles(){let e=[M.join(this.config.workspaceDir,"active"),M.join(this.config.workspaceDir,"archive")];for(let t of e)try{let r=await A.readdir(t,{withFileTypes:!0});for(let n of r){let i=M.join(t,n.name);if(n.isDirectory()){if((await A.readdir(i,{withFileTypes:!0})).length>0)return !0}else if(n.name.endsWith(".md"))return !0}}catch(r){if(r.code==="ENOENT")continue;throw r}return  false}async clearFiles(){let e=[M.join(this.config.workspaceDir,"active"),M.join(this.config.workspaceDir,"archive")];for(let t of e)try{let r=await A.readdir(t,{withFileTypes:!0});for(let n of r){let i=M.join(t,n.name);n.isDirectory()?await A.rm(i,{recursive:!0,force:!0}):n.name.endsWith(".md")&&await A.unlink(i);}}catch(r){if(r.code!=="ENOENT")throw r}f.info("Memory files cleared");}rowToFact(e){return {id:e.id,agentId:e.agent_id,sessionId:e.session_id??void 0,msgId:e.msg_id??void 0,parentMsgId:e.parent_msg_id??void 0,content:e.content,category:e.category,importance:e.importance,source:e.source,tags:e.tags?JSON.parse(e.tags):void 0,nodeIds:e.node_ids?JSON.parse(e.node_ids):void 0,filePath:e.file_path??void 0,createdAt:new Date(e.created_at).toISOString(),updatedAt:new Date(e.updated_at).toISOString()}}extractEntities(e){let t=[],r=[],n=new Set,i=new Set,a=/([A-Za-z][\w.-]{1,80})\s+(is_a|part_of|has_attribute|located_in|occurs_in|causes|influences|owned_by|member_of|uses|depends_on|related_to)\s+([A-Za-z][\w.-]{1,80})/g;for(let o of e.matchAll(a)){let m=this.sanitizeEntityToken(o[1]??""),d=(o[2]??"related_to").trim(),s=this.sanitizeEntityToken(o[3]??"");if(!m||!s||m===s)continue;let u=m.toLowerCase();n.has(u)||(n.add(u),t.push({name:m,type:this.inferEntityType(m),properties:{source:"rule_extracted"}}));let l=s.toLowerCase();n.has(l)||(n.add(l),t.push({name:s,type:this.inferEntityType(s),properties:{source:"rule_extracted"}}));let p=`${u}|${l}|${d}`;i.has(p)||(i.add(p),r.push({source:m,target:s,relation:d,properties:void 0}));}let c=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[];for(let o of c){let m=this.sanitizeEntityToken(o);if(!m)continue;let d=m.toLowerCase();n.has(d)||(n.add(d),t.push({name:m,type:this.inferEntityType(m),properties:{source:"keyword_extracted"}}));}return {entities:t,relations:r}}async extractEntitiesWithLlm(e){if(!this.config.graphLlm)return this.extractEntities(e);try{let r=this.buildEntityExtractionPrompt(e);f.debug("LLM extracting entities...",{contentLength:e.length});let n=await z.generate(r,{maxOutputTokens:2e3});f.debug("LLM extraction result",{resultLength:n.length,result:n.slice(0,200)});let i=this.parseEntityExtractionResult(n);return f.debug("Parsed entities",{entityCount:i.entities.length,relationCount:i.relations.length}),i}catch(r){return f.warn("LLM entity extraction failed, falling back to simple extraction",{error:String(r)}),this.extractEntities(e)}}buildEntityExtractionPrompt(e){let t=GRAPH_ENTITY_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
`),r=GRAPH_RELATION_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
`),n=e.slice(0,1e3);return `You are an information extraction engine for a general-purpose memory graph.

Extract entities and directed relations from the text.

Entity type taxonomy:
${t}

Relation type taxonomy:
${r}

Extraction rules:
- Output valid JSON only. Do not include markdown, prose, or code fences.
- Use canonical, concise entity names (deduplicated, case-insensitive).
- Prefer specific entity types over "keyword".
- Include relation only if both source and target entities are present in the entities list.
- Do not invent facts not grounded in the input text.
- Keep relation direction meaningful (source -> target).
- entity properties should contain short factual attributes only (plain JSON object).
- relation properties: Optional. Add properties only when the relation has meaningful attributes (e.g., confidence, weight, context). If no meaningful properties, use empty object {}.

Return this exact JSON shape:
{
  "entities": [
    { "name": "string", "type": "one_of_entity_types", "properties": {} }
  ],
  "relations": [
    { "source": "entity_name", "target": "entity_name", "relation": "one_of_relation_types", "properties": {} }
  ]
}

Input text:
${n}`}storeEntitiesAndRelations(e,t){if(e.length===0)return {nodeIds:[]};let r=new Map,n=new Date().toISOString(),i=e.map(()=>"?").join(","),a=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${i})`,e.map(o=>o.name)),c=new Map(a.map(o=>[`${o.name}::${o.type}`,o.id]));return this.db.transaction(()=>{for(let o of e){let m=`${o.name}::${o.type}`,d=c.get(m);if(d!==void 0)this.db.run("UPDATE nodes SET properties = ?, updatedAt = ? WHERE id = ?",[JSON.stringify(o.properties),n,d]),r.set(o.name,d);else {let s=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[o.name,o.type,JSON.stringify(o.properties),n,n]);s.lastID>0&&r.set(o.name,s.lastID);}}for(let o of t){let m=r.get(o.source),d=r.get(o.target);if(m&&d){let s=o.properties?JSON.stringify(o.properties):"{}";this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[m,d,o.relation,s,n]);}}}),{nodeIds:Array.from(r.values())}}mergeEntitiesAndRelations(e,t,r,n){if(r.length===0&&n.length===0)return;let i=new Map,a=new Date().toISOString(),c=r.map(()=>"?").join(","),o=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${c})`,r.map(d=>d.name)),m=new Map(o.map(d=>[`${d.name}::${d.type}`,d.id]));this.db.transaction(()=>{for(let s of r){let u=`${s.name}::${s.type}`,l=m.get(u);if(l!==void 0)i.set(s.name,l);else {let p=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[s.name,s.type,JSON.stringify(s.properties),a,a]);p.lastID>0&&i.set(s.name,p.lastID);}}for(let s of n){let u=i.get(s.source),l=i.get(s.target);if(u&&l){let p=s.properties?JSON.stringify(s.properties):"{}";this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[u,l,s.relation,p,a]);}}let d=Array.from(i.values());d.length>0&&this.db.run("UPDATE memory_facts SET node_ids = ? WHERE id = ?",[JSON.stringify(d),e]);});}async embed(e){if(!this.embeddingModel)return null;let t=createHash("sha256").update(e).digest("hex"),r=this.db.query("SELECT embedding FROM embedding_cache WHERE content_hash = ?",[t])[0];if(r)return new Float32Array(r.embedding.buffer,r.embedding.byteOffset,r.embedding.byteLength/4);try{let i=(await this.embeddingModel.doEmbed({values:[e]})).embeddings[0];if(!i||i.length===0)return null;let a=new Float32Array(i),c=Buffer.from(a.buffer,a.byteOffset,a.byteLength);return this.db.run("INSERT OR REPLACE INTO embedding_cache (content_hash, embedding) VALUES (?, ?)",[t,c]),this.vectorDims===void 0&&(this.vectorDims=i.length,this.db.run("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)",["vectorDims",String(i.length)])),a}catch(n){return f.warn("Embedding failed",{error:String(n)}),null}}async embedAndStore(e,t){let r=await this.embed(t);if(!r)return;let n=Buffer.from(r.buffer,r.byteOffset,r.byteLength);try{this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[e,n]);}catch(i){f.warn("Vector store failed (fact may not exist yet)",{factId:e,error:String(i)});}}writeVector(e,t){try{this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[e,t]);}catch(r){f.warn("Vector write failed",{factId:e,error:String(r)});}}writeFts(e,t,r,n){try{let i=ie(r),a=n?ie(n.join(" ")):"";this.db.run("DELETE FROM memory_facts_fts WHERE fact_id = ?",[e]),this.db.run("INSERT INTO memory_facts_fts (fact_id, agent_id, content, tags) VALUES (?, ?, ?, ?)",[e,t,i,a]);}catch(i){f.warn("FTS index write failed",{factId:e,error:String(i)});}}parseEntityExtractionResult(e){try{let t=e.match(/\{[\s\S]*\}/);if(t){let r=JSON.parse(t[0]);return this.normalizeExtractionResult(r)}}catch(t){f.debug("Failed to parse entity extraction result",{error:String(t)});}return {entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,r=Array.isArray(t.entities)?t.entities:[],n=Array.isArray(t.relations)?t.relations:[],i=[],a=new Set,c=new Map;for(let d of r){let s=typeof d?.name=="string"?d.name.trim():"";if(!s)continue;let u=s.toLowerCase();if(a.has(u))continue;a.add(u),c.set(u,s);let l=typeof d?.type=="string"?d.type.trim():"",p=Ye.has(l)?l:"keyword",E=d?.properties&&typeof d.properties=="object"&&!Array.isArray(d.properties)?d.properties:{};i.push({name:s,type:p,properties:E});}let o=[],m=new Set;for(let d of n){let s=typeof d?.source=="string"?d.source.trim():"",u=typeof d?.target=="string"?d.target.trim():"";if(!s||!u)continue;let l=c.get(s.toLowerCase()),p=c.get(u.toLowerCase());if(!l||!p||l===p)continue;let E=typeof d?.relation=="string"?d.relation.trim():"",D=Xe.has(E)?E:"related_to",S=`${l.toLowerCase()}|${p.toLowerCase()}|${D}`;if(m.has(S))continue;m.add(S);let $=d?.properties,I;if($&&typeof $=="object"&&!Array.isArray($))try{I=$,Object.keys(I).length===0&&(I=void 0);}catch{I=void 0;}o.push({source:l,target:p,relation:D,properties:I});}return {entities:i,relations:o}}sanitizeEntityToken(e){return e.trim().replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu,"").replace(/\s+/g," ").slice(0,120)}inferEntityType(e){let t=e.toLowerCase();return /(\.md|\.ts|\.json|readme|doc|spec|guideline)/i.test(e)?"document":/(api|service|system|engine|pipeline|server|db|database|memorysystem|contextengine)/i.test(e)?"process":/(team|group|org|company|inc|ltd|corp)/i.test(e)?"organization":/(deadline|date|day|week|month|year|q[1-4]|sprint)/i.test(e)?"time":/(score|rate|ratio|latency|accuracy|recall|precision|throughput|kpi)/i.test(e)?"metric":/(task|issue|ticket|todo|action)/i.test(e)?"task":/(event|incident|release|meeting|migration|launch)/i.test(e)?"event":/(process|workflow|procedure|flow|lifecycle)/i.test(e)?"process":/(file|model|dataset|artifact|resource|tool|sdk|ollama|sqlite|embedding|vector|fts)/i.test(e)?"object":/(concept|principle|policy|method|pattern|strategy)/i.test(e)?"concept":/[A-Z]/.test(e)&&t!==e?"object":"keyword"}getSearchEngine(){if(!this.searchEngine)throw new R("Memory system not initialized. Call initialize() first.");return this.searchEngine}getGraphStore(){if(!this.graphStore)throw new R("Memory system not initialized. Call initialize() first.");return this.graphStore}getArchiver(){if(!this.archiver)throw new R("Memory system not initialized. Call initialize() first.");return this.archiver}};async function qe(g){let e=new Z(g);return await e.initialize(),e}export{J as GraphStore,te as MEMORY_CATEGORIES,H as MemoryArchiver,R as MemoryDatabaseError,X as MemoryDatabaseManager,Y as MemoryEmbeddingError,k as MemoryError,Te as MemoryErrorCode,O as MemoryFileError,_ as MemoryFileManager,L as MemoryFormatter,j as MemoryNotFoundError,B as MemoryPermissionError,G as MemorySearchError,Z as MemorySystem,N as MemoryValidationError,tt as addWord,nt as closeTokenizer,qe as createMemorySystem,ae as initTokenizer,rt as isInitialized,Se as loadCustomDict,ie as toFtsTokens,de as toFtsTokensForSearch,Ie as tokenize,Ne as tokenizeForSearch};