@easbot/memory 0.2.1 → 0.2.2

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.
@@ -0,0 +1 @@
1
+ 'use strict';var chunkOB4DC6HG_cjs=require('./chunk-OB4DC6HG.cjs');Object.defineProperty(exports,"Log",{enumerable:true,get:function(){return chunkOB4DC6HG_cjs.c}});
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var chunkQAB5VLUW_cjs=require('./chunks/chunk-QAB5VLUW.cjs'),types=require('@easbot/types'),x=require('jieba-wasm'),utils=require('@easbot/utils'),Ne=require('better-sqlite3'),crypto=require('crypto'),w=require('fs/promises'),R=require('path'),fs=require('fs'),ai=require('ai');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var x__namespace=/*#__PURE__*/_interopNamespace(x);var Ne__default=/*#__PURE__*/_interopDefault(Ne);var w__default=/*#__PURE__*/_interopDefault(w);var R__default=/*#__PURE__*/_interopDefault(R);var te=["user_preference","task_context","technical_fact","decision","relationship","reminder","error_pattern","workflow","exploration_finding","experience_summary","tool_usage","skill_creation","test","other"],F=class extends Error{constructor(t,n,r){super(t,{cause:r});this.code=n;this.cause=r;this.name="MemoryError";}},S=class extends F{constructor(e,t){super(e,"MEMORY_VALIDATION_ERROR",t),this.name="MemoryValidationError";}},W=class extends F{constructor(e){super(`Memory not found: ${e}`,"MEMORY_NOT_FOUND"),this.name="MemoryNotFoundError";}},j=class extends F{constructor(e){super(e,"MEMORY_PERMISSION_ERROR"),this.name="MemoryPermissionError";}},T=class extends F{constructor(e,t){super(e,"MEMORY_DATABASE_ERROR",t),this.name="MemoryDatabaseError";}},O=class extends F{constructor(e,t){super(e,"MEMORY_FILE_ERROR",t),this.name="MemoryFileError";}},J=class extends F{constructor(e,t){super(e,"MEMORY_SEARCH_ERROR",t),this.name="MemorySearchError";}},B=class extends F{constructor(e,t){super(e,"MEMORY_EMBEDDING_ERROR",t),this.name="MemoryEmbeddingError";}},Te=(m=>(m.VALIDATION_ERROR="MEMORY_VALIDATION_ERROR",m.NOT_FOUND="MEMORY_NOT_FOUND",m.PERMISSION_ERROR="MEMORY_PERMISSION_ERROR",m.DATABASE_ERROR="MEMORY_DATABASE_ERROR",m.FILE_ERROR="MEMORY_FILE_ERROR",m.SEARCH_ERROR="MEMORY_SEARCH_ERROR",m.EMBEDDING_ERROR="MEMORY_EMBEDDING_ERROR",m))(Te||{});var M=chunkQAB5VLUW_cjs.c.create({service:"memory.tokenizer"}),v=false,Me=utils.loadTextFile("./assets/jieba_dict.txt",chunkQAB5VLUW_cjs.b);async function de(g){if(!v)try{M.debug("Initializing jieba tokenizer");let e=Me();if(x__namespace.with_dict(e),M.debug("Built-in dictionary loaded"),g?.dictPath&&g.dictPath.length>0)for(let t of g.dictPath)await we(t);v=!0,M.debug("Jieba tokenizer initialized successfully");}catch(e){M.error("Failed to initialize jieba tokenizer",{error:String(e)}),M.warn("Using fallback tokenization (space-based)");}}async function we(g){if(!v)throw new Error("Tokenizer not initialized");try{let e=await utils.Filesystem.readText(g);M.debug("Loading custom dictionary",{dictPath:g}),x__namespace.with_dict(e),M.debug("Custom dictionary loaded successfully",{dictPath:g});}catch(e){M.warn("Failed to load custom dictionary",{dictPath:g,error:String(e)});}}function Ie(g){if(!v)return g.split(/\s+/).filter(Boolean);try{return x__namespace.cut(g)}catch(e){return M.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Ae(g){if(!v)return g.split(/\s+/).filter(Boolean);try{return x__namespace.cut_for_search(g)}catch(e){return M.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Ve(g,e,t){if(v)try{x__namespace.add_word(g,e,t),M.debug("Word added to dictionary",{word:g,freq:e,tag:t});}catch(n){M.warn("Failed to add word",{word:g,error:String(n)});}}function Je(){return v}async function Ge(){v=false,M.debug("Tokenizer closed");}function ie(g){if(!v)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ie(g).join(" ")}catch(e){return M.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}function ce(g){if(!v)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ae(g).join(" ")}catch(e){return M.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}var Y=class{constructor(e){chunkQAB5VLUW_cjs.a(this,"db",null);chunkQAB5VLUW_cjs.a(this,"storagePath");chunkQAB5VLUW_cjs.a(this,"initialized",false);chunkQAB5VLUW_cjs.a(this,"initPromise",null);this.storagePath=utils.Filesystem.toUnixPath(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 T(`Database initialization failed: ${e.message}`,e)}}async openDatabaseAsync(){return new Promise((e,t)=>{setImmediate(()=>{try{let n=new Ne__default.default(this.storagePath);n.pragma("journal_mode = WAL"),n.pragma("synchronous = NORMAL"),n.pragma("cache_size = -64000"),n.pragma("temp_store = MEMORY"),e(n);}catch(n){t(n);}});})}createTables(){if(!this.db)throw new T("Database not initialized");let e=this.db;e.exec(`
1
+ 'use strict';var chunkOB4DC6HG_cjs=require('./chunks/chunk-OB4DC6HG.cjs'),types=require('@easbot/types'),k=require('jieba-wasm'),utils=require('@easbot/utils'),Ae=require('better-sqlite3'),crypto=require('crypto'),N=require('fs/promises'),T=require('path'),fs=require('fs'),ai=require('ai');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var k__namespace=/*#__PURE__*/_interopNamespace(k);var Ae__default=/*#__PURE__*/_interopDefault(Ae);var N__default=/*#__PURE__*/_interopDefault(N);var T__default=/*#__PURE__*/_interopDefault(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"],x=class extends Error{constructor(t,r,n){super(t,{cause:n});chunkOB4DC6HG_cjs.a(this,"code",r);chunkOB4DC6HG_cjs.a(this,"cause",n);this.name="MemoryError";}},O=class extends x{constructor(e,t){super(e,"MEMORY_VALIDATION_ERROR",t),this.name="MemoryValidationError";}},j=class extends x{constructor(e){super(`Memory not found: ${e}`,"MEMORY_NOT_FOUND"),this.name="MemoryNotFoundError";}},B=class extends x{constructor(e){super(e,"MEMORY_PERMISSION_ERROR"),this.name="MemoryPermissionError";}},R=class extends x{constructor(e,t){super(e,"MEMORY_DATABASE_ERROR",t),this.name="MemoryDatabaseError";}},D=class extends x{constructor(e,t){super(e,"MEMORY_FILE_ERROR",t),this.name="MemoryFileError";}},G=class extends x{constructor(e,t){super(e,"MEMORY_SEARCH_ERROR",t),this.name="MemorySearchError";}},Y=class extends x{constructor(e,t){super(e,"MEMORY_EMBEDDING_ERROR",t),this.name="MemoryEmbeddingError";}},be=(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))(be||{});var _=chunkOB4DC6HG_cjs.c.create({service:"memory.tokenizer"}),F=false,we=utils.loadTextFile("./assets/jieba_dict.txt",chunkOB4DC6HG_cjs.b);async function ae(g){if(!F)try{_.debug("Initializing jieba tokenizer");let e=we();if(k__namespace.with_dict(e),_.debug("Built-in dictionary loaded"),g?.dictPath&&g.dictPath.length>0)for(let t of g.dictPath)await _e(t);F=!0,_.debug("Jieba tokenizer initialized successfully");}catch(e){_.error("Failed to initialize jieba tokenizer",{error:String(e)}),_.warn("Using fallback tokenization (space-based)");}}async function _e(g){if(!F)throw new Error("Tokenizer not initialized");try{let e=await utils.Filesystem.readText(g);_.debug("Loading custom dictionary",{dictPath:g}),k__namespace.with_dict(e),_.debug("Custom dictionary loaded successfully",{dictPath:g});}catch(e){_.warn("Failed to load custom dictionary",{dictPath:g,error:String(e)});}}function Me(g){if(!F)return g.split(/\s+/).filter(Boolean);try{return k__namespace.cut(g)}catch(e){return _.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Ne(g){if(!F)return g.split(/\s+/).filter(Boolean);try{return k__namespace.cut_for_search(g)}catch(e){return _.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Je(g,e,t){if(F)try{k__namespace.add_word(g,e,t),_.debug("Word added to dictionary",{word:g,freq:e,tag:t});}catch(r){_.warn("Failed to add word",{word:g,error:String(r)});}}function Ge(){return F}async function Ke(){F=false,_.debug("Tokenizer closed");}function ie(g){if(!F)return g.split(/\s+/).filter(Boolean).join(" ");try{return Me(g).join(" ")}catch(e){return _.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}function de(g){if(!F)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ne(g).join(" ")}catch(e){return _.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}var X=class{constructor(e){chunkOB4DC6HG_cjs.a(this,"db",null);chunkOB4DC6HG_cjs.a(this,"storagePath");chunkOB4DC6HG_cjs.a(this,"initialized",false);chunkOB4DC6HG_cjs.a(this,"initPromise",null);this.storagePath=utils.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 Ae__default.default(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(`
2
2
  CREATE TABLE IF NOT EXISTS memory_facts (
3
3
  id TEXT PRIMARY KEY,
4
4
  agent_id TEXT NOT NULL,
@@ -61,31 +61,31 @@
61
61
  key TEXT PRIMARY KEY,
62
62
  value TEXT
63
63
  )
64
- `);}query(e,t){if(!this.db)throw new T("Database not initialized. Call initialize() first.");try{let n=this.db.prepare(e);return t?n.all(...t):n.all()}catch(n){throw new T(`Query failed: ${n.message}`,n)}}run(e,t){if(!this.db)throw new T("Database not initialized. Call initialize() first.");try{let n=this.db.prepare(e),r=t?n.run(...t):n.run();return {lastID:Number(r.lastInsertRowid),changes:r.changes}}catch(n){throw new T(`Write failed: ${n.message}`,n)}}transaction(e){if(!this.db)throw new T("Database not initialized. Call initialize() first.");return this.db.transaction(e)()}prepare(e){if(!this.db)throw new T("Database not initialized. Call initialize() first.");return this.db.prepare(e)}exec(e){if(!this.db)throw new T("Database not initialized. Call initialize() first.");this.db.exec(e);}getDb(){if(!this.db)throw new T("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 De=["id","agentId","category","importance"],X="---",D=class g{static generateId(){let e=Date.now(),t=crypto.randomBytes(3).toString("hex");return `mem_${e}_${t}`}static serialize(e){let t=new Date(e.createdAt),n=e.updatedAt?new Date(e.updatedAt):new Date,r={id:e.id,agentId:e.agentId,category:e.category,importance:e.importance,createdAt:utils.formatLocalISO(t),updatedAt:utils.formatLocalISO(n),source:e.source};e.sessionId&&(r.sessionId=e.sessionId),e.msgId&&(r.msgId=e.msgId),e.parentMsgId&&(r.parentMsgId=e.parentMsgId),e.tags&&e.tags.length>0&&(r.tags=e.tags),e.nodeIds&&e.nodeIds.length>0&&(r.nodeIds=e.nodeIds),e.filePath&&(r.filePath=e.filePath);let i=Object.entries(r).map(([s,m])=>Array.isArray(m)?`${s}: [${m.join(", ")}]`:`${s}: ${m}`);return [X,...i,X,"",e.content.trim(),""].join(`
64
+ `);}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 Oe=["id","agentId","category","importance"],q="---",L=class g{static generateId(){let e=Date.now(),t=crypto.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:utils.formatLocalISO(t),updatedAt:utils.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(`
65
65
  `)}static serializeFile(e){return e.map(t=>g.serialize(t)).join(`
66
- `)}static parse(e){let t=[],n=e.split(`
67
- `),r=0;for(;r<n.length;){if(n[r]?.trim()!==X){r++;continue}let i=r+1,s=-1;for(let u=i;u<n.length;u++)if(n[u]?.trim()===X){s=u;break}if(s===-1){r++;continue}let m=n.slice(i,s),o=g.parseFrontmatter(m);g.validateFrontmatter(o);let d=s+1,c=n.length;for(let u=d;u<n.length;u++)if(n[u]?.trim()===X){c=u;break}let a=n.slice(d,c).join(`
68
- `).trim(),l={id:String(o.id),agentId:String(o.agentId),category:o.category,importance:Number(o.importance),source:o.source??"session_self_write",content:a,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&&(l.sessionId=String(o.sessionId)),o.msgId&&(l.msgId=String(o.msgId)),o.parentMsgId&&(l.parentMsgId=String(o.parentMsgId)),o.filePath&&(l.filePath=String(o.filePath)),o.tags&&(l.tags=g.parseArrayField(o.tags)),o.nodeIds&&(l.nodeIds=g.parseArrayField(o.nodeIds).map(Number).filter(u=>!Number.isNaN(u))),t.push(l),r=c;}return t}static parseFrontmatter(e){let t={};for(let n of e){let r=n.indexOf(":");if(r===-1)continue;let i=n.slice(0,r).trim(),s=n.slice(r+1).trim();if(i)if(s.startsWith("[")&&s.endsWith("]")){let m=s.slice(1,-1).trim();t[i]=m?m.split(",").map(o=>o.trim()).filter(Boolean):[];}else t[i]=s;}return t}static validateFrontmatter(e){for(let r of De)if(e[r]===void 0||e[r]==="")throw new S(`Missing required field in memory frontmatter: ${r}`);let t=e.category;if(!te.includes(t))throw new S(`Invalid category: "${t}". Valid values: ${te.join(", ")}`);let n=Number(e.importance);if(Number.isNaN(n)||n<1||n>10)throw new S(`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 n=t.slice(1,-1).trim();return n?n.split(",").map(r=>r.trim()).filter(Boolean):[]}return t?[t]:[]}return []}};var le="MEMORY.md",ue="active",Le="archive",N=class g{static getMemoryMdPath(e){return R__default.default.join(e,le)}static getActiveFilePath(e,t,n){let r=n??new Date,i=r.getFullYear(),s=String(r.getMonth()+1).padStart(2,"0"),m=String(r.getDate()).padStart(2,"0"),o=`${i}-${s}-${m}`;return R__default.default.join(e,ue,t,`${o}.md`)}static getArchiveFilePath(e,t,n,r){let i=new Date(n),s=`${i.getFullYear()}-${String(i.getMonth()+1).padStart(2,"0")}`;return R__default.default.join(e,Le,s,t,r)}static async readMemoryMd(e){let t=g.getMemoryMdPath(e);try{return await w__default.default.readFile(t,"utf-8")}catch(n){if(n.code==="ENOENT")return null;throw new O(`Failed to read MEMORY.md: ${n.message}`,n)}}static async write(e,t){let n=g.getActiveFilePath(e,t.category);utils.Filesystem.toUnixPath(R__default.default.relative(e,n));if(R__default.default.basename(n)===le)throw new j("Writing to MEMORY.md is not allowed. MEMORY.md is read-only.");try{await w__default.default.mkdir(R__default.default.dirname(n),{recursive:!0});let i=D.serialize(t),s="";try{s=await w__default.default.readFile(n,"utf-8");}catch{}let m=s.length>0&&!s.endsWith(`
66
+ `)}static parse(e){let t=[],r=e.split(`
67
+ `),n=0;for(;n<r.length;){if(r[n]?.trim()!==q){n++;continue}let i=n+1,a=-1;for(let u=i;u<r.length;u++)if(r[u]?.trim()===q){a=u;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 u=m;u<r.length;u++)if(r[u]?.trim()===q){d=u;break}let s=r.slice(m,d).join(`
68
+ `).trim(),l={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&&(l.sessionId=String(o.sessionId)),o.msgId&&(l.msgId=String(o.msgId)),o.parentMsgId&&(l.parentMsgId=String(o.parentMsgId)),o.filePath&&(l.filePath=String(o.filePath)),o.tags&&(l.tags=g.parseArrayField(o.tags)),o.nodeIds&&(l.nodeIds=g.parseArrayField(o.nodeIds).map(Number).filter(u=>!Number.isNaN(u))),t.push(l),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 Oe)if(e[n]===void 0||e[n]==="")throw new O(`Missing required field in memory frontmatter: ${n}`);let t=e.category;if(!te.includes(t))throw new O(`Invalid category: "${t}". Valid values: ${te.join(", ")}`);let r=Number(e.importance);if(Number.isNaN(r)||r<1||r>10)throw new O(`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",Le="archive",M=class g{static getMemoryMdPath(e){return T__default.default.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 T__default.default.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 T__default.default.join(e,Le,a,t,n)}static async readMemoryMd(e){let t=g.getMemoryMdPath(e);try{return await N__default.default.readFile(t,"utf-8")}catch(r){if(r.code==="ENOENT")return null;throw new D(`Failed to read MEMORY.md: ${r.message}`,r)}}static async write(e,t){let r=g.getActiveFilePath(e,t.category);if(T__default.default.basename(r)===me)throw new B("Writing to MEMORY.md is not allowed. MEMORY.md is read-only.");try{await N__default.default.mkdir(T__default.default.dirname(r),{recursive:!0});let n=L.serialize(t),i="";try{i=await N__default.default.readFile(r,"utf-8");}catch{}let a=i.length>0&&!i.endsWith(`
69
69
  `)?`
70
- `:"";return await w__default.default.writeFile(n,`${s}${m}${i}`,"utf-8"),utils.Filesystem.normalize(n)}catch(i){throw i instanceof j?i:new O(`Failed to write memory to ${n}: ${i.message}`,i)}}static async read(e){try{let t=await w__default.default.readFile(e,"utf-8");return D.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 n=await g.read(e),r=n.filter(i=>i.id!==t);if(r.length===n.length)return;r.length===0?await w__default.default.unlink(e).catch(()=>{}):await w__default.default.writeFile(e,D.serializeFile(r),"utf-8");}catch(n){throw n instanceof O?n:new O(`Failed to delete memory ${t} from ${e}: ${n.message}`,n)}}static async update(e,t,n){try{let r=await g.read(e),i=r.findIndex(m=>m.id===t);if(i===-1)return;let s={...r[i],...n,updatedAt:new Date().toISOString()};r[i]=s,await w__default.default.writeFile(e,D.serializeFile(r),"utf-8");}catch(r){throw r instanceof O?r:new O(`Failed to update memory ${t} in ${e}: ${r.message}`,r)}}static async listActiveFiles(e){let t=R__default.default.join(e,ue),n=[];try{await g.scanDir(t,n);}catch(r){if(r.code==="ENOENT")return [];throw new O(`Failed to list active memory files: ${r.message}`,r)}return n}static async scanDir(e,t){let n=await w__default.default.readdir(e,{withFileTypes:true});for(let r of n){let i=R__default.default.join(e,r.name);r.isDirectory()?await g.scanDir(i,t):r.isFile()&&r.name.endsWith(".md")&&t.push(i);}}};var q=class{constructor(e,t){chunkQAB5VLUW_cjs.a(this,"db");chunkQAB5VLUW_cjs.a(this,"config");this.db=e,this.config=t;}async archive(){let t=(this.config.archiveDays??30)*864e5,n=Date.now(),r=[],i=await N.listActiveFiles(this.config.workspaceDir);for(let s of i){let m=await N.read(s);if(m.length===0)continue;let o=m[0]?.createdAt,d=o?new Date(o).getTime():n;if(n-d<=t)continue;let c=m[0]?.category;if(!c)continue;let a=R__default.default.basename(s),l=N.getArchiveFilePath(this.config.workspaceDir,c,d,a);await fs.promises.mkdir(R__default.default.dirname(l),{recursive:true}),await fs.promises.rename(s,l);let u=utils.Filesystem.toUnixPath(R__default.default.relative(this.config.workspaceDir,l)),p=utils.Filesystem.toUnixPath(R__default.default.relative(this.config.workspaceDir,s));this.db.prepare("UPDATE memory_facts SET file_path = ? WHERE file_path = ?").run(u,p),r.push({source:s,target:l,timestamp:n});}return {archivedCount:r.length,records:r}}};var K=chunkQAB5VLUW_cjs.c.create({service:"memory.graph-store"}),H=class{constructor(e){chunkQAB5VLUW_cjs.a(this,"db");this.db=e;}async upsertNode(e,t,n){let r=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(n??{}),r,i.id),i.id;let s=this.db.prepare("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)").run(e,t,JSON.stringify(n??{}),r,r);return Number(s.lastInsertRowid)}async deleteNode(e){this.db.prepare("DELETE FROM nodes WHERE id = ?").run(e);}async upsertEdge(e,t,n,r){let i=this.db.prepare("INSERT INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)").run(e,t,n,JSON.stringify(r??{}),Date.now());return Number(i.lastInsertRowid)}async queryNodes(e={}){let t="SELECT id, name, type, properties, createdAt, updatedAt FROM nodes",n=[],r=[];if(e.ids&&e.ids.length>0){let s=e.ids.map(m=>typeof m=="string"?parseInt(m,10):m).filter(m=>!Number.isNaN(m));r.push(`id IN (${s.map(()=>"?").join(", ")})`),n.push(...s);}e.name&&(r.push("name LIKE ?"),n.push(`%${e.name}%`)),e.type&&(r.push("type = ?"),n.push(e.type)),r.length>0&&(t+=` WHERE ${r.join(" AND ")}`),t+=" ORDER BY id",e.limit&&(t+=" LIMIT ?",n.push(e.limit)),K.debug("queryNodes",{sql:t,params:n,filter:e});let i=this.db.prepare(t).all(...n);return K.debug("queryNodes result",{count:i.length}),i.map(s=>({id:s.id,name:s.name,type:s.type,properties:s.properties?JSON.parse(s.properties):void 0,createdAt:s.createdAt,updatedAt:s.updatedAt}))}async queryEdges(e={}){let t="SELECT id, source, target, relation, properties, createdAt FROM edges",n=[],r=[];if(e.ids&&e.ids.length>0&&(r.push(`id IN (${e.ids.map(()=>"?").join(", ")})`),n.push(...e.ids)),e.source!==void 0&&(r.push("source = ?"),n.push(e.source)),e.target!==void 0&&(r.push("target = ?"),n.push(e.target)),e.sourceOrTarget&&e.sourceOrTarget.length>0){let d=e.sourceOrTarget.map(c=>typeof c=="string"?parseInt(c,10):c).filter(c=>!Number.isNaN(c));r.push(`(source IN (${d.map(()=>"?").join(", ")}) OR target IN (${d.map(()=>"?").join(", ")}))`),n.push(...d,...d);}e.relation&&(r.push("relation = ?"),n.push(e.relation)),r.length>0&&(t+=` WHERE ${r.join(" AND ")}`),t+=" ORDER BY id",e.limit&&(t+=" LIMIT ?",n.push(e.limit)),K.debug("queryEdges",{sql:t,params:n,filter:e});let i=this.db.prepare(t).all(...n);K.debug("queryEdges result",{count:i.length});let s=[...new Set(i.map(d=>d.target))],m=s.length>0?await this.queryNodes({ids:s,limit:s.length}):[],o=new Map(m.map(d=>[d.id,d]));return i.map(d=>{let c={id:d.id,source:d.source,target:d.target,relation:d.relation,properties:d.properties?JSON.parse(d.properties):void 0,createdAt:d.createdAt},a=o.get(d.target);return a&&(c.targetNode=a),c})}async queryNeighbors(e,t=1,n){let r=new Set,i=[{id:e,level:0}],s=[],m=n?.maxEdgesPerNode??50;for(;i.length>0;){let o=i.shift();if(!o)break;if(r.has(o.id)||o.level>t)continue;r.add(o.id);let c=(await this.queryNodes({ids:[o.id],limit:1}))[0];if(!c)continue;let a=await this.queryEdges({sourceOrTarget:[o.id],limit:m});if(s.push({...c,edges:a}),o.level<t)for(let l of a){let u=l.source===o.id?l.target:l.source;r.has(u)||i.push({id:u,level:o.level+1});}}return s}};var z;(c=>{let g=null;function e(a){t()||(g={models:a.models,options:a.options??{}});}c.init=e;function t(){return g!==null}c.isInitialized=t;function n(){return g?{embedding:!!g.models.embeddingLlm,graph:!!g.models.graphLlm}:{embedding:false,graph:false}}c.capabilities=n;async function r(a){let u=m().models.embeddingLlm;if(!u)throw new Error("embeddingLlm model is not configured.");try{let p=await ai.embed({model:u,value:a});return new Float32Array(p.embedding)}catch(p){let b=u.doEmbed;if(typeof b!="function")throw new Error("embeddingLlm model does not support embedding generation.",{cause:p});let I=(await b({values:[a]}))?.embeddings?.[0];if(!I||!Array.isArray(I))throw new Error("embeddingLlm model returned invalid embedding result.",{cause:p});return new Float32Array(I)}}c.embedText=r;async function i(a){let u=m().models.embeddingLlm;if(!u)throw new Error("embeddingLlm model is not configured.");try{return (await ai.embedMany({model:u,values:a})).embeddings.map(b=>new Float32Array(b))}catch{return ((await u.doEmbed?.({values:a}))?.embeddings??[]).map(b=>new Float32Array(b))}}c.embedTexts=i;async function s(a,l){let u=m(),p=u.models.graphLlm;if(!p)throw new Error("llm model is not configured.");try{return (await ai.streamText({model:p,prompt:a,maxOutputTokens:l?.maxOutputTokens??u.options.graph?.maxOutputTokens,temperature:l?.temperature??u.options.graph?.temperature})).text}catch{return (await p.doGenerate?.({prompt:[{role:"user",content:[{type:"text",text:a}]}],maxOutputTokens:l?.maxOutputTokens??u.options.graph?.maxOutputTokens}))?.content?.find(L=>L.type==="text")?.text??""}}c.generate=s;let m=()=>{if(!g)throw new Error("Llm is not initialized. Please call Llm.init() first.");return g};c.embed=r,c.embedMany=i;})(z||(z={}));var Q=class{constructor(e,t){chunkQAB5VLUW_cjs.a(this,"db");chunkQAB5VLUW_cjs.a(this,"config");chunkQAB5VLUW_cjs.a(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 n=t.maxResults??this.config.search.maxResults,r=await this.hybridSearch(e,{...t,maxResults:n*2});return r.length===0?[]:r.slice(0,n)}async hybridSearch(e,t){let{maxResults:n=this.config.search.maxResults,minScore:r=this.config.search.minScore,vectorWeight:i=this.config.search.hybrid.vectorWeight,textWeight:s=this.config.search.hybrid.textWeight,enableEmbedding:m=true}=t??{},d=m&&!!this.embeddingModel?await this.embed(e):null,c=["mf.agent_id = ?"],a=[t?.agentId];t?.category&&(c.push("mf.category = ?"),a.push(t.category)),t?.minImportance!==void 0&&(c.push("mf.importance >= ?"),a.push(t.minImportance)),t?.source&&(c.push("mf.source = ?"),a.push(t.source)),t?.fromTime!==void 0&&(c.push("mf.created_at >= ?"),a.push(t.fromTime)),t?.toTime!==void 0&&(c.push("mf.created_at <= ?"),a.push(t.toTime));let l=c.join(" AND "),[u,p]=await Promise.all([d?this.vectorSearch(d,l,a,n,r,t?.candidateFactIds):Promise.resolve([]),this.ftsSearch(e,l,a,n,r)]),b=d?i:0,L=d?s:1;return this.mergeResults(u,p,b,L,l,a,r)}async vectorSearch(e,t,n,r,i,s){if(!this.embeddingModel)return [];try{let m;if(s&&s.length>0){let d=s.map(()=>"?").join(",");m=this.db.prepare(`
70
+ `:"";return await N__default.default.writeFile(r,`${i}${a}${n}`,"utf-8"),utils.Filesystem.normalize(r)}catch(n){throw n instanceof B?n:new D(`Failed to write memory to ${r}: ${n.message}`,n)}}static async read(e){try{let t=await N__default.default.readFile(e,"utf-8");return L.parse(t)}catch(t){if(t.code==="ENOENT")return [];throw new D(`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 N__default.default.unlink(e).catch(()=>{}):await N__default.default.writeFile(e,L.serializeFile(n),"utf-8");}catch(r){throw r instanceof D?r:new D(`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 N__default.default.writeFile(e,L.serializeFile(n),"utf-8");}catch(n){throw n instanceof D?n:new D(`Failed to update memory ${t} in ${e}: ${n.message}`,n)}}static async listActiveFiles(e){let t=T__default.default.join(e,ge),r=[];try{await g.scanDir(t,r);}catch(n){if(n.code==="ENOENT")return [];throw new D(`Failed to list active memory files: ${n.message}`,n)}return r}static async scanDir(e,t){let r=await N__default.default.readdir(e,{withFileTypes:true});for(let n of r){let i=T__default.default.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){chunkOB4DC6HG_cjs.a(this,"db");chunkOB4DC6HG_cjs.a(this,"config");this.db=e,this.config=t;}async archive(){let t=(this.config.archiveDays??30)*864e5,r=Date.now(),n=[],i=await M.listActiveFiles(this.config.workspaceDir);for(let a of i){let c=await M.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=T__default.default.basename(a),l=M.getArchiveFilePath(this.config.workspaceDir,d,m,s);await fs.promises.mkdir(T__default.default.dirname(l),{recursive:true}),await fs.promises.rename(a,l);let u=utils.Filesystem.normalize(l),p=utils.Filesystem.normalize(a);this.db.prepare("UPDATE memory_facts SET file_path = ? WHERE file_path = ?").run(u,p),n.push({source:a,target:l,timestamp:r});}return {archivedCount:n.length,records:n}}};var K=chunkOB4DC6HG_cjs.c.create({service:"memory.graph-store"}),V=class{constructor(e){chunkOB4DC6HG_cjs.a(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 l of s){let u=l.source===o.id?l.target:l.source;n.has(u)||i.push({id:u,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 u=c().models.embeddingLlm;if(!u)throw new Error("embeddingLlm model is not configured.");try{let p=await ai.embed({model:u,value:s});return new Float32Array(p.embedding)}catch(p){let E=u.doEmbed;if(typeof E!="function")throw new Error("embeddingLlm model does not support embedding generation.",{cause:p});let A=(await E({values:[s]}))?.embeddings?.[0];if(!A||!Array.isArray(A))throw new Error("embeddingLlm model returned invalid embedding result.",{cause:p});return new Float32Array(A)}}d.embedText=n;async function i(s){let u=c().models.embeddingLlm;if(!u)throw new Error("embeddingLlm model is not configured.");try{return (await ai.embedMany({model:u,values:s})).embeddings.map(E=>new Float32Array(E))}catch{return ((await u.doEmbed?.({values:s}))?.embeddings??[]).map(E=>new Float32Array(E))}}d.embedTexts=i;async function a(s,l){let u=c(),p=u.models.graphLlm;if(!p)throw new Error("llm model is not configured.");try{return (await ai.streamText({model:p,prompt:s,maxOutputTokens:l?.maxOutputTokens??u.options.graph?.maxOutputTokens,temperature:l?.temperature??u.options.graph?.temperature})).text}catch{return (await p.doGenerate?.({prompt:[{role:"user",content:[{type:"text",text:s}]}],maxOutputTokens:l?.maxOutputTokens??u.options.graph?.maxOutputTokens}))?.content?.find(v=>v.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){chunkOB4DC6HG_cjs.a(this,"db");chunkOB4DC6HG_cjs.a(this,"config");chunkOB4DC6HG_cjs.a(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 l=d.join(" AND "),[u,p]=await Promise.all([m?this.vectorSearch(m,l,s,r,n,t?.candidateFactIds):Promise.resolve([]),this.ftsSearch(e,l,s,r,n)]),E=m?i:0,v=m?a:1;return this.mergeResults(u,p,E,v,l,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(`
71
71
  SELECT mf.id, mv.embedding
72
72
  FROM memory_facts mf
73
73
  JOIN memory_vectors mv ON mf.id = mv.fact_id
74
- WHERE ${t} AND mf.id IN (${d})
75
- `).all(...n,...s);}else m=this.db.prepare(`
74
+ WHERE ${t} AND mf.id IN (${m})
75
+ `).all(...r,...a);}else c=this.db.prepare(`
76
76
  SELECT mf.id, mv.embedding
77
77
  FROM memory_facts mf
78
78
  JOIN memory_vectors mv ON mf.id = mv.fact_id
79
79
  WHERE ${t}
80
80
  LIMIT ?
81
- `).all(...n,Math.max(r*100,1e3));let o=[];for(let d of m){let c=new Float32Array(d.embedding.buffer,d.embedding.byteOffset,d.embedding.length/4),a=this.cosineSimilarity(e,c);o.push({id:d.id,score:a});}return o.sort((d,c)=>c.score-d.score).slice(0,r)}catch(m){throw new J(`\u5411\u91CF\u641C\u7D22\u5931\u8D25: ${m instanceof Error?m.message:String(m)}`,m instanceof Error?m:void 0)}}async ftsSearch(e,t,n,r,i){let s=()=>[];try{let o=(ce(e).trim()||e.trim()).split(/\s+/).filter(a=>a.length>0).map(a=>`"${a.replace(/"/g,'""')}"`).join(" "),d=this.db.prepare(`
81
+ `).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(`
82
82
  SELECT mf.id, bm25(memory_facts_fts) as score
83
83
  FROM memory_facts mf
84
84
  JOIN memory_facts_fts ON mf.id = memory_facts_fts.fact_id
85
85
  WHERE ${t} AND memory_facts_fts.content MATCH ?
86
86
  ORDER BY score DESC
87
87
  LIMIT ?
88
- `).all(...n,o,r);if(d.length===0)return s();let c=Math.max(...d.map(a=>Math.abs(a.score)),1);return d.map(a=>({id:a.id,score:1-Math.abs(a.score)/c})).filter(a=>a.score>=0)}catch{return s()}}async mergeResults(e,t,n,r,i,s,m){let o=n+r,d=n/o,c=r/o,a=new Map;for(let h of e)a.set(h.id,h.score*d);for(let h of t){let _=a.get(h.id)||0;a.set(h.id,_+h.score*c);}let l=Array.from(a.entries()).map(([h,_])=>({id:h,score:_})).sort((h,_)=>_.score-h.score).map(h=>h.id);if(l.length===0)return [];let u=l.map(()=>"?").join(","),p=this.db.prepare(`
88
+ `).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 w=s.get(h.id)||0;s.set(h.id,w+h.score*d);}let l=Array.from(s.entries()).map(([h,w])=>({id:h,score:w})).sort((h,w)=>w.score-h.score).map(h=>h.id);if(l.length===0)return [];let u=l.map(()=>"?").join(","),p=this.db.prepare(`
89
89
  SELECT
90
90
  mf.id as memoryId,
91
91
  mf.category,
@@ -98,21 +98,21 @@
98
98
  mf.node_ids
99
99
  FROM memory_facts mf
100
100
  WHERE mf.id IN (${u})
101
- `).all(...l),b=[],L=new Map;for(let h of p)if(h.node_ids)try{let _=JSON.parse(h.node_ids);L.set(h.memoryId,_),b.push(..._);}catch{}let I=Array.from(new Set(b)),se=new Map,U=new Map;if(I.length>0){let h=I.map(()=>"?").join(", "),_=this.db.prepare(`SELECT id, name, type FROM nodes WHERE id IN (${h})`).all(...I);for(let y of _)se.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
101
+ `).all(...l),E=[],v=new Map;for(let h of p)if(h.node_ids)try{let w=JSON.parse(h.node_ids);v.set(h.memoryId,w),E.push(...w);}catch{}let A=Array.from(new Set(E)),$=new Map,S=new Map;if(A.length>0){let h=A.map(()=>"?").join(", "),w=this.db.prepare(`SELECT id, name, type FROM nodes WHERE id IN (${h})`).all(...A);for(let y of w)$.set(y.id,y);let J=this.db.prepare(`SELECT e.id, e.source, e.target, e.relation, e.properties, e.createdAt, n.name as targetName, n.type as targetType
102
102
  FROM edges e JOIN nodes n ON n.id = e.target
103
- WHERE e.source IN (${h})`).all(...I);for(let y of V){let $=U.get(y.source)??[];$.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}}),U.set(y.source,$);}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
103
+ WHERE e.source IN (${h})`).all(...A);for(let y of J){let W=S.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}}),S.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
104
104
  FROM edges e JOIN nodes n ON n.id = e.source
105
- WHERE e.target IN (${h})`).all(...I);for(let y of ee){let $=U.get(y.target)??[];$.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}}),U.set(y.target,$);}}return p.map(h=>{let _=L.get(h.memoryId)??[],V=_.length>0?_.flatMap(oe=>{let ae=se.get(oe);return ae?[{...ae,edges:U.get(oe)}]:[]}):void 0,ee=a.get(h.memoryId)??0,y=new Date(h.createdAt),$=(Date.now()-y.getTime())/864e5,fe=Math.exp(-0.05*$),Ee=(h.importance-1)/9,be=.4*ee+.3*fe+.3*Ee;return {memoryId:h.memoryId,category:h.category,importance:h.importance,agentId:h.agentId,snippet:h.snippet,score:be,createdAt:h.createdAt,source:h.source,filePath:h.filePath,nodes:(V?.length??0)>0?V:void 0}}).filter(h=>h.score>=m).sort((h,_)=>_.score-h.score)}async embed(e){if(!this.embeddingModel)throw new B("Embedding \u6A21\u578B\u672A\u914D\u7F6E\uFF0C\u65E0\u6CD5\u751F\u6210\u5411\u91CF");try{return await z.embedText(e)}catch(t){throw new B(`\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 n=0,r=0,i=0;for(let s=0;s<e.length;s++){let m=e[s],o=t[s];n+=m*o,r+=m*m,i+=o*o;}return n/(Math.sqrt(r)*Math.sqrt(i))}};var f=chunkQAB5VLUW_cjs.c.create({service:"memory.system"}),ke=.7,Ce=.3,ze=10;var $e=new Set(types.GRAPH_ENTITY_TYPE_DEFINITIONS.map(g=>g.type)),Ue=new Set(types.GRAPH_RELATION_TYPE_DEFINITIONS.map(g=>g.type)),Z=class{constructor(e){chunkQAB5VLUW_cjs.a(this,"config");chunkQAB5VLUW_cjs.a(this,"db");chunkQAB5VLUW_cjs.a(this,"archiver",null);chunkQAB5VLUW_cjs.a(this,"searchEngine",null);chunkQAB5VLUW_cjs.a(this,"graphStore",null);chunkQAB5VLUW_cjs.a(this,"embeddingModel");chunkQAB5VLUW_cjs.a(this,"vectorDims");e.search?.hybrid;this.config={workspaceDir:e.workspaceDir,database:e.database,archiveDays:e.archiveDays??30,search:{maxResults:e.search?.maxResults??ze,minScore:e.search?.minScore??.3,hybrid:{enabled:e.search?.hybrid?.enabled??true,vectorWeight:e.search?.hybrid?.vectorWeight??ke,textWeight:e.search?.hybrid?.textWeight??Ce}},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 Y(e.database.path),this.embeddingModel&&z.init({models:{embeddingLlm:this.embeddingModel,graphLlm:this.config.graphLlm}});}async initialize(){await chunkQAB5VLUW_cjs.c.init({logDir:this.config.logDir??R__default.default.join(this.config.workspaceDir,"logs"),print:process.argv.includes("--print-logs"),dev:false,level:"INFO"}),await w__default.default.mkdir(R__default.default.dirname(this.config.database.path),{recursive:true}),await w__default.default.mkdir(R__default.default.join(this.config.workspaceDir,"active"),{recursive:true}),await w__default.default.mkdir(R__default.default.join(this.config.workspaceDir,"archive"),{recursive:true}),await this.db.initialize(),this.archiver=new q(this.db.getDb(),this.config),this.graphStore=new H(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[n,r]of t)this.db.run("INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)",[n,r]);await de({dictPath:this.config.tokenizer.dictPath}).catch(n=>{f.warn("Tokenizer initialization failed, using fallback",{error:String(n)});}),f.info("Memory system initialized",{workspaceDir:this.config.workspaceDir,dbPath:this.config.database.path});}async remember(e){if(!e.agentId?.trim())throw new S("agentId is required for remember operation");let t=new Date().toISOString(),n=D.generateId(),r={...e,id:n,source:"session_self_write",createdAt:t,updatedAt:t};N.write(this.config.workspaceDir,r).then(a=>{r.filePath=a,f.debug("Memory written to file",{id:n,filePath:a});}).catch(a=>{f.warn("Failed to write memory to file",{id:n,error:String(a)});});let i=[],s=this.config,m=this.extractEntities(r.content);if(i=this.storeEntitiesAndRelations(m.entities,m.relations).nodeIds,s.graphLlm){let a=r.content,l=r.agentId,u=r.id;f.debug("Scheduling background LLM extraction",{id:u,contentLength:a.length}),this.extractEntitiesWithLlm(a).then(p=>{f.debug("Background LLM extraction completed",{id:u,entities:p.entities.length,relations:p.relations.length}),this.mergeEntitiesAndRelations(u,l,p.entities,p.relations);}).catch(p=>{f.warn("Background graph extraction failed",{id:u,error:String(p)});});}r.nodeIds=i;let d=await this.embed(r.content),c=d?Buffer.from(d.buffer,d.byteOffset,d.byteLength):null;return this.db.transaction(()=>{this.db.run(`INSERT OR REPLACE INTO memory_facts
105
+ WHERE e.target IN (${h})`).all(...A);for(let y of ee){let W=S.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}}),S.set(y.target,W);}}return p.map(h=>{let w=v.get(h.memoryId)??[],J=w.length>0?w.flatMap(se=>{let oe=$.get(se);return oe?[{...oe,edges:S.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:(J?.length??0)>0?J:void 0}}).filter(h=>h.score>=c).sort((h,w)=>w.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=chunkOB4DC6HG_cjs.c.create({service:"memory.system"}),Pe=.7,Ce=.3,ze=10;var $e=new Set(types.GRAPH_ENTITY_TYPE_DEFINITIONS.map(g=>g.type)),We=new Set(types.GRAPH_RELATION_TYPE_DEFINITIONS.map(g=>g.type)),Z=class{constructor(e){chunkOB4DC6HG_cjs.a(this,"config");chunkOB4DC6HG_cjs.a(this,"db");chunkOB4DC6HG_cjs.a(this,"archiver",null);chunkOB4DC6HG_cjs.a(this,"searchEngine",null);chunkOB4DC6HG_cjs.a(this,"graphStore",null);chunkOB4DC6HG_cjs.a(this,"embeddingModel");chunkOB4DC6HG_cjs.a(this,"vectorDims");e.search?.hybrid;this.config={workspaceDir:e.workspaceDir,database:e.database,archiveDays:e.archiveDays??30,search:{maxResults:e.search?.maxResults??ze,minScore:e.search?.minScore??.3,hybrid:{enabled:e.search?.hybrid?.enabled??true,vectorWeight:e.search?.hybrid?.vectorWeight??Pe,textWeight:e.search?.hybrid?.textWeight??Ce}},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 chunkOB4DC6HG_cjs.c.init({logDir:this.config.logDir??T__default.default.join(this.config.workspaceDir,"logs"),print:process.argv.includes("--print-logs"),dev:false,level:"INFO"}),await N__default.default.mkdir(T__default.default.dirname(this.config.database.path),{recursive:true}),await N__default.default.mkdir(T__default.default.join(this.config.workspaceDir,"active"),{recursive:true}),await N__default.default.mkdir(T__default.default.join(this.config.workspaceDir,"archive"),{recursive:true}),await this.db.initialize(),this.archiver=new H(this.db.getDb(),this.config),this.graphStore=new V(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 O("agentId is required for remember operation");let t=new Date().toISOString(),r=L.generateId(),n=M.getActiveFilePath(this.config.workspaceDir,e.category),i={...e,id:r,source:"session_self_write",createdAt:t,updatedAt:t,filePath:utils.Filesystem.normalize(n)};M.write(this.config.workspaceDir,i).then(l=>{f.debug("Memory written to file",{id:r,filePath:l});}).catch(l=>{f.warn("Failed to write memory to file",{id:r,error:String(l)});});let a=[],c=this.config,o=this.extractEntities(i.content);if(a=this.storeEntitiesAndRelations(o.entities,o.relations).nodeIds,c.graphLlm){let l=i.content,u=i.agentId,p=i.id;f.debug("Scheduling background LLM extraction",{id:p,contentLength:l.length}),this.extractEntitiesWithLlm(l).then(E=>{f.debug("Background LLM extraction completed",{id:p,entities:E.entities.length,relations:E.relations.length}),this.mergeEntitiesAndRelations(p,u,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
106
106
  (id, agent_id, session_id, msg_id, parent_msg_id, content, category, importance,
107
107
  source, tags, node_ids, file_path, created_at, updated_at)
108
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[r.id,r.agentId,r.sessionId??null,r.msgId??null,r.parentMsgId??null,r.content,r.category,r.importance,r.source,r.tags?JSON.stringify(r.tags):null,r.nodeIds?JSON.stringify(r.nodeIds):null,r.filePath?utils.Filesystem.toUnixPath(r.filePath):null,r.createdAt,r.updatedAt]),c&&this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[r.id,c]),this.writeFts(r.id,r.agentId,r.content,r.tags);}),f.info("Memory stored",{id:r.id,category:r.category,agentId:r.agentId,nodeCount:i.length}),r}async query(e,t){if(!t?.agentId?.trim())throw new S("agentId is required for query operation");return this.getSearchEngine().search(e,t)}async queryEdgesByNodeId(e,t){if(!this.graphStore)return {nodes:[],edges:[]};let n=Math.min(Math.max(t?.maxDepth??2,1),3),r=await this.graphStore.queryNeighbors(e,n,{maxEdgesPerNode:t?.maxEdgesPerNode??20}),i=r.find(s=>s.id===e);return {node:i?{id:i.id,name:i.name,type:i.type}:void 0,nodes:r.map(s=>s),edges:r.flatMap(s=>s.edges??[])}}async forget(e,t){if(!e?.trim())throw new S("agentId is required for forget operation");let n=this.db.query("SELECT file_path, node_ids, content FROM memory_facts WHERE id = ? AND agent_id = ?",[t,e]);if(n.length===0)throw new W(t);let r=n[0]?.file_path,i=n[0]?.node_ids?JSON.parse(n[0].node_ids):[],s=n[0]?.content,m=s?crypto.createHash("sha256").update(s).digest("hex"):null,o=new Set;if(i.length>0){i.map(()=>"?").join(",");let a=this.db.query("SELECT node_ids FROM memory_facts WHERE id != ? AND agent_id = ? AND node_ids IS NOT NULL",[t,e]);for(let l of a)if(l.node_ids){let u=JSON.parse(l.node_ids);for(let p of u)o.add(p);}}let d=i.filter(c=>!o.has(c));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]),d.length>0){let c=d.map(()=>"?").join(",");this.db.run(`DELETE FROM nodes WHERE id IN (${c})`,d);}m&&this.db.run("DELETE FROM embedding_cache WHERE content_hash = ?",[m]);}),r){let c=R__default.default.isAbsolute(r)?r:R__default.default.join(this.config.workspaceDir,r);await N.delete(c,t).catch(a=>{f.warn("Failed to delete memory from file",{memoryId:t,filePath:r,error:String(a)});});}f.info("Memory deleted",{memoryId:t,agentId:e,orphanNodes:d.length});}async update(e,t,n){if(!e?.trim())throw new S("agentId is required for update operation");let r=this.db.query("SELECT * FROM memory_facts WHERE id = ? AND agent_id = ?",[t,e]);if(r.length===0)throw new W(t);let i=r[0],s=new Date().toISOString(),m=n.content??i.content,o=n.importance??i.importance,d=n.tags??(i.tags?JSON.parse(i.tags):void 0),c=n.content?await this.embed(m).then(l=>l?Buffer.from(l.buffer,l.byteOffset,l.byteLength):null):null;if(this.db.transaction(()=>{this.db.run(`UPDATE memory_facts SET content = ?, importance = ?, tags = ?, updated_at = ?
109
- WHERE id = ? AND agent_id = ?`,[m,o,d?JSON.stringify(d):null,s,t,e]),c&&this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[t,c]),this.writeFts(t,e,m,d);}),i.file_path){let l=R__default.default.isAbsolute(i.file_path)?i.file_path:R__default.default.join(this.config.workspaceDir,i.file_path);await N.update(l,t,n).catch(u=>{f.warn("Failed to update memory in file",{memoryId:t,error:String(u)});});}let a={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:m,category:i.category,importance:o,source:i.source,tags:d,nodeIds:i.node_ids?JSON.parse(i.node_ids):void 0,filePath:i.file_path??void 0,createdAt:String(i.created_at),updatedAt:s};return f.info("Memory updated",{memoryId:t,agentId:e}),a}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=10){return e?.trim()?this.db.query(`SELECT * FROM memory_facts
110
- WHERE agent_id = ?
108
+ 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 O("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 O("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?crypto.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 l of s)if(l.node_ids){let u=JSON.parse(l.node_ids);for(let p of u)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=T__default.default.isAbsolute(n)?n:T__default.default.join(this.config.workspaceDir,n);await M.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 O("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(l=>l?Buffer.from(l.buffer,l.byteOffset,l.byteLength):null):null;if(this.db.transaction(()=>{this.db.run(`UPDATE memory_facts SET content = ?, importance = ?, tags = ?, updated_at = ?
109
+ 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 l=T__default.default.isAbsolute(i.file_path)?i.file_path:T__default.default.join(this.config.workspaceDir,i.file_path);await M.update(l,t,r).catch(u=>{f.warn("Failed to update memory in file",{memoryId:t,error:String(u)});});}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
110
+ WHERE ${m}
111
111
  ORDER BY importance DESC, created_at DESC
112
- LIMIT ?`,[e,t]).map(r=>({id:r.id,agentId:r.agent_id,sessionId:r.session_id??void 0,msgId:r.msg_id??void 0,parentMsgId:r.parent_msg_id??void 0,content:r.content,category:r.category,importance:r.importance,source:r.source,tags:r.tags?JSON.parse(r.tags):void 0,nodeIds:r.node_ids?JSON.parse(r.node_ids):void 0,filePath:r.file_path??void 0,createdAt:String(r.created_at),updatedAt:String(r.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)"),n=this.db.run("DELETE FROM memory_vectors WHERE fact_id NOT IN (SELECT id FROM memory_facts)"),r=this.db.run("DELETE FROM embedding_cache WHERE content_hash NOT IN (SELECT content_hash FROM memory_facts)");return {orphanFts:t.changes,orphanVectors:n.changes,orphanCache:r.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 N.listActiveFiles(this.config.workspaceDir);for(let t of e)await w__default.default.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(),await chunkQAB5VLUW_cjs.c.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"),n=this.db.query("SELECT COUNT(*) as c FROM graph_edges"),r=this.db.query("SELECT key, value FROM meta"),i={};for(let s of r)i[s.key]=s.value;return {dbPath:this.config.database.path,workspaceDir:this.config.workspaceDir,factsCount:e[0]?.c??0,nodesCount:t[0]?.c??0,edgesCount:n[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 n=this.db.query("SELECT * FROM memory_facts ORDER BY category, created_at ASC",[]),r=new Map;for(let i of n){let s=i.category,m=new Date(i.created_at),d=`${`${m.getFullYear()}-${String(m.getMonth()+1).padStart(2,"0")}-${String(m.getDate()).padStart(2,"0")}`}.md`,c=`${s}/${d}`;if(!r.has(c)){let a=R__default.default.join(this.config.workspaceDir,"active",s,d);r.set(c,{path:a,facts:[]});}r.get(c).facts.push(i);}for(let[i,{path:s,facts:m}]of r)try{let o=R__default.default.dirname(s);await w__default.default.mkdir(o,{recursive:!0});let d=m.map(a=>{let l=this.rowToFact(a);return D.serialize(l)}).join(`
113
- `);if(await w__default.default.access(s).then(()=>!0).catch(()=>!1)){if((await w__default.default.readFile(s,"utf-8")).trim()===d.trim()){e.synced++;continue}e.updated++;}else e.created++;await w__default.default.writeFile(s,d,"utf-8"),e.synced++;}catch(o){let d=o instanceof Error?o.message:String(o);e.errors.push(`Failed to sync ${i}: ${d}`),f.warn("Memory file sync failed",{key:i,error:d});}return f.info("Memory sync completed",{synced:e.synced,created:e.created,updated:e.updated,errors:e.errors.length}),this.db.setMeta("lastSync",new Date().toISOString()),e}async hasMemoryFiles(){let e=[R__default.default.join(this.config.workspaceDir,"active"),R__default.default.join(this.config.workspaceDir,"archive")];for(let t of e)try{let n=await w__default.default.readdir(t,{withFileTypes:!0});for(let r of n){let i=R__default.default.join(t,r.name);if(r.isDirectory()){if((await w__default.default.readdir(i,{withFileTypes:!0})).length>0)return !0}else if(r.name.endsWith(".md"))return !0}}catch(n){if(n.code==="ENOENT")continue;throw n}return false}async clearFiles(){let e=[R__default.default.join(this.config.workspaceDir,"active"),R__default.default.join(this.config.workspaceDir,"archive")];for(let t of e)try{let n=await w__default.default.readdir(t,{withFileTypes:!0});for(let r of n){let i=R__default.default.join(t,r.name);r.isDirectory()?await w__default.default.rm(i,{recursive:!0,force:!0}):r.name.endsWith(".md")&&await w__default.default.unlink(i);}}catch(n){if(n.code!=="ENOENT")throw n}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=[],n=[],r=new Set,i=new Set,s=/([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(s)){let d=this.sanitizeEntityToken(o[1]??""),c=(o[2]??"related_to").trim(),a=this.sanitizeEntityToken(o[3]??"");if(!d||!a||d===a)continue;let l=d.toLowerCase();r.has(l)||(r.add(l),t.push({name:d,type:this.inferEntityType(d),properties:{source:"rule_extracted"}}));let u=a.toLowerCase();r.has(u)||(r.add(u),t.push({name:a,type:this.inferEntityType(a),properties:{source:"rule_extracted"}}));let p=`${l}|${u}|${c}`;i.has(p)||(i.add(p),n.push({source:d,target:a,relation:c}));}let m=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[];for(let o of m){let d=this.sanitizeEntityToken(o);if(!d)continue;let c=d.toLowerCase();r.has(c)||(r.add(c),t.push({name:d,type:this.inferEntityType(d),properties:{source:"keyword_extracted"}}));}return {entities:t,relations:n}}async extractEntitiesWithLlm(e){if(!this.config.graphLlm)return this.extractEntities(e);try{let n=this.buildEntityExtractionPrompt(e);f.debug("LLM extracting entities...",{contentLength:e.length});let r=await z.generate(n,{maxOutputTokens:2e3});f.debug("LLM extraction result",{resultLength:r.length,result:r.slice(0,200)});let i=this.parseEntityExtractionResult(r);return f.debug("Parsed entities",{entityCount:i.entities.length,relationCount:i.relations.length}),i}catch(n){return f.warn("LLM entity extraction failed, falling back to simple extraction",{error:String(n)}),this.extractEntities(e)}}buildEntityExtractionPrompt(e){let t=types.GRAPH_ENTITY_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
114
- `),n=types.GRAPH_RELATION_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
115
- `),r=e.slice(0,1e3);return `You are an information extraction engine for a general-purpose memory graph.
112
+ 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 M.listActiveFiles(this.config.workspaceDir);for(let t of e)await N__default.default.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(),await chunkOB4DC6HG_cjs.c.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`,l=`${o}/${s}`;if(!n.has(l)){let u=T__default.default.join(this.config.workspaceDir,"active",o,s);n.set(l,{path:u,facts:[]});}n.get(l).facts.push(c);}for(let[c,{path:o,facts:m}]of n)try{let d=T__default.default.dirname(o);await N__default.default.mkdir(d,{recursive:!0});let s=m.map(u=>{let p=this.rowToFact(u);return L.serialize(p)}).join(`
113
+ `);if(await N__default.default.access(o).then(()=>!0).catch(()=>!1)){if((await N__default.default.readFile(o,"utf-8")).trim()===s.trim()){e.synced++;continue}e.updated++;}else e.created++;await N__default.default.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=[T__default.default.join(this.config.workspaceDir,"active"),T__default.default.join(this.config.workspaceDir,"archive")];for(let t of e)try{let r=await N__default.default.readdir(t,{withFileTypes:!0});for(let n of r){let i=T__default.default.join(t,n.name);if(n.isDirectory()){if((await N__default.default.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=[T__default.default.join(this.config.workspaceDir,"active"),T__default.default.join(this.config.workspaceDir,"archive")];for(let t of e)try{let r=await N__default.default.readdir(t,{withFileTypes:!0});for(let n of r){let i=T__default.default.join(t,n.name);n.isDirectory()?await N__default.default.rm(i,{recursive:!0,force:!0}):n.name.endsWith(".md")&&await N__default.default.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 l=m.toLowerCase();n.has(l)||(n.add(l),t.push({name:m,type:this.inferEntityType(m),properties:{source:"rule_extracted"}}));let u=s.toLowerCase();n.has(u)||(n.add(u),t.push({name:s,type:this.inferEntityType(s),properties:{source:"rule_extracted"}}));let p=`${l}|${u}|${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=types.GRAPH_ENTITY_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
114
+ `),r=types.GRAPH_RELATION_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
115
+ `),n=e.slice(0,1e3);return `You are an information extraction engine for a general-purpose memory graph.
116
116
 
117
117
  Extract entities and directed relations from the text.
118
118
 
@@ -120,7 +120,7 @@ Entity type taxonomy:
120
120
  ${t}
121
121
 
122
122
  Relation type taxonomy:
123
- ${n}
123
+ ${r}
124
124
 
125
125
  Extraction rules:
126
126
  - Output valid JSON only. Do not include markdown, prose, or code fences.
@@ -129,7 +129,8 @@ Extraction rules:
129
129
  - Include relation only if both source and target entities are present in the entities list.
130
130
  - Do not invent facts not grounded in the input text.
131
131
  - Keep relation direction meaningful (source -> target).
132
- - properties should contain short factual attributes only (plain JSON object).
132
+ - entity properties should contain short factual attributes only (plain JSON object).
133
+ - relation properties: Optional. Add properties only when the relation has meaningful attributes (e.g., confidence, weight, context). If no meaningful properties, use empty object {}.
133
134
 
134
135
  Return this exact JSON shape:
135
136
  {
@@ -137,9 +138,9 @@ Return this exact JSON shape:
137
138
  { "name": "string", "type": "one_of_entity_types", "properties": {} }
138
139
  ],
139
140
  "relations": [
140
- { "source": "entity_name", "target": "entity_name", "relation": "one_of_relation_types" }
141
+ { "source": "entity_name", "target": "entity_name", "relation": "one_of_relation_types", "properties": {} }
141
142
  ]
142
143
  }
143
144
 
144
145
  Input text:
145
- ${r}`}storeEntitiesAndRelations(e,t){if(e.length===0)return {nodeIds:[]};let n=new Map,r=new Date().toISOString(),i=e.map(()=>"?").join(","),s=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${i})`,e.map(o=>o.name)),m=new Map(s.map(o=>[`${o.name}::${o.type}`,o.id]));return this.db.transaction(()=>{for(let o of e){let d=`${o.name}::${o.type}`,c=m.get(d);if(c!==void 0)this.db.run("UPDATE nodes SET properties = ?, updatedAt = ? WHERE id = ?",[JSON.stringify(o.properties),r,c]),n.set(o.name,c);else {let a=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[o.name,o.type,JSON.stringify(o.properties),r,r]);a.lastID>0&&n.set(o.name,a.lastID);}}for(let o of t){let d=n.get(o.source),c=n.get(o.target);d&&c&&this.db.run("INSERT INTO edges (source, target, relation, createdAt) VALUES (?, ?, ?, ?)",[d,c,o.relation,r]);}}),{nodeIds:Array.from(n.values())}}mergeEntitiesAndRelations(e,t,n,r){if(n.length===0&&r.length===0)return;let i=new Map,s=new Date().toISOString(),m=n.map(()=>"?").join(","),o=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${m})`,n.map(c=>c.name)),d=new Map(o.map(c=>[`${c.name}::${c.type}`,c.id]));this.db.transaction(()=>{for(let a of n){let l=`${a.name}::${a.type}`,u=d.get(l);if(u!==void 0)i.set(a.name,u);else {let p=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[a.name,a.type,JSON.stringify(a.properties),s,s]);p.lastID>0&&i.set(a.name,p.lastID);}}for(let a of r){let l=i.get(a.source),u=i.get(a.target);l&&u&&this.db.run("INSERT INTO edges (source, target, relation, createdAt) VALUES (?, ?, ?, ?)",[l,u,a.relation,s]);}let c=Array.from(i.values());c.length>0&&this.db.run("UPDATE memory_facts SET node_ids = ? WHERE id = ?",[JSON.stringify(c),e]);});}async embed(e){if(!this.embeddingModel)return null;let t=crypto.createHash("sha256").update(e).digest("hex"),n=this.db.query("SELECT embedding FROM embedding_cache WHERE content_hash = ?",[t])[0];if(n)return new Float32Array(n.embedding.buffer,n.embedding.byteOffset,n.embedding.byteLength/4);try{let i=(await this.embeddingModel.doEmbed({values:[e]})).embeddings[0];if(!i||i.length===0)return null;let s=new Float32Array(i),m=Buffer.from(s.buffer,s.byteOffset,s.byteLength);return this.db.run("INSERT OR REPLACE INTO embedding_cache (content_hash, embedding) VALUES (?, ?)",[t,m]),this.vectorDims===void 0&&(this.vectorDims=i.length,this.db.run("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)",["vectorDims",String(i.length)])),s}catch(r){return f.warn("Embedding failed",{error:String(r)}),null}}async embedAndStore(e,t){let n=await this.embed(t);if(!n)return;let r=Buffer.from(n.buffer,n.byteOffset,n.byteLength);try{this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[e,r]);}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(n){f.warn("Vector write failed",{factId:e,error:String(n)});}}writeFts(e,t,n,r){try{let i=ie(n),s=r?ie(r.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,s]);}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 n=JSON.parse(t[0]);return this.normalizeExtractionResult(n)}}catch(t){f.debug("Failed to parse entity extraction result",{error:String(t)});}return {entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,n=Array.isArray(t.entities)?t.entities:[],r=Array.isArray(t.relations)?t.relations:[],i=[],s=new Set,m=new Map;for(let c of n){let a=typeof c?.name=="string"?c.name.trim():"";if(!a)continue;let l=a.toLowerCase();if(s.has(l))continue;s.add(l),m.set(l,a);let u=typeof c?.type=="string"?c.type.trim():"",p=$e.has(u)?u:"keyword",b=c?.properties&&typeof c.properties=="object"&&!Array.isArray(c.properties)?c.properties:{};i.push({name:a,type:p,properties:b});}let o=[],d=new Set;for(let c of r){let a=typeof c?.source=="string"?c.source.trim():"",l=typeof c?.target=="string"?c.target.trim():"";if(!a||!l)continue;let u=m.get(a.toLowerCase()),p=m.get(l.toLowerCase());if(!u||!p||u===p)continue;let b=typeof c?.relation=="string"?c.relation.trim():"",L=Ue.has(b)?b:"related_to",I=`${u.toLowerCase()}|${p.toLowerCase()}|${L}`;d.has(I)||(d.add(I),o.push({source:u,target:p,relation:L}));}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 T("Memory system not initialized. Call initialize() first.");return this.searchEngine}getGraphStore(){if(!this.graphStore)throw new T("Memory system not initialized. Call initialize() first.");return this.graphStore}getArchiver(){if(!this.archiver)throw new T("Memory system not initialized. Call initialize() first.");return this.archiver}};async function We(g){let e=new Z(g);return await e.initialize(),e}async function er(g){let{Log:e}=await import('./chunks/log-E6JFAP3Z.cjs'),t=false;await e.init({logDir:g.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:g.print??false,dev:g.dev??t,level:g.level??("INFO")});}Object.defineProperty(exports,"GRAPH_ENTITY_TYPE_DEFINITIONS",{enumerable:true,get:function(){return types.GRAPH_ENTITY_TYPE_DEFINITIONS}});Object.defineProperty(exports,"GRAPH_RELATION_TYPE_DEFINITIONS",{enumerable:true,get:function(){return types.GRAPH_RELATION_TYPE_DEFINITIONS}});exports.GraphStore=H;exports.MEMORY_CATEGORIES=te;exports.MemoryArchiver=q;exports.MemoryDatabaseError=T;exports.MemoryDatabaseManager=Y;exports.MemoryEmbeddingError=B;exports.MemoryError=F;exports.MemoryErrorCode=Te;exports.MemoryFileError=O;exports.MemoryFileManager=N;exports.MemoryFormatter=D;exports.MemoryNotFoundError=W;exports.MemoryPermissionError=j;exports.MemorySearchError=J;exports.MemorySystem=Z;exports.MemoryValidationError=S;exports.addWord=Ve;exports.closeTokenizer=Ge;exports.createMemorySystem=We;exports.initLog=er;exports.initTokenizer=de;exports.isInitialized=Je;exports.loadCustomDict=we;exports.toFtsTokens=ie;exports.toFtsTokensForSearch=ce;exports.tokenize=Ie;exports.tokenizeForSearch=Ae;
146
+ ${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 l=`${s.name}::${s.type}`,u=m.get(l);if(u!==void 0)i.set(s.name,u);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 l=i.get(s.source),u=i.get(s.target);if(l&&u){let p=s.properties?JSON.stringify(s.properties):"{}";this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[l,u,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=crypto.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 l=s.toLowerCase();if(a.has(l))continue;a.add(l),c.set(l,s);let u=typeof d?.type=="string"?d.type.trim():"",p=$e.has(u)?u:"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():"",l=typeof d?.target=="string"?d.target.trim():"";if(!s||!l)continue;let u=c.get(s.toLowerCase()),p=c.get(l.toLowerCase());if(!u||!p||u===p)continue;let E=typeof d?.relation=="string"?d.relation.trim():"",v=We.has(E)?E:"related_to",A=`${u.toLowerCase()}|${p.toLowerCase()}|${v}`;if(m.has(A))continue;m.add(A);let $=d?.properties,S;if($&&typeof $=="object"&&!Array.isArray($))try{S=$,Object.keys(S).length===0&&(S=void 0);}catch{S=void 0;}o.push({source:u,target:p,relation:v,properties:S});}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 Ue(g){let e=new Z(g);return await e.initialize(),e}async function tr(g){let{Log:e}=await import('./chunks/log-RHKGN6UL.cjs'),t=false;await e.init({logDir:g.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:g.print??false,dev:g.dev??t,level:g.level??("INFO")});}Object.defineProperty(exports,"GRAPH_ENTITY_TYPE_DEFINITIONS",{enumerable:true,get:function(){return types.GRAPH_ENTITY_TYPE_DEFINITIONS}});Object.defineProperty(exports,"GRAPH_RELATION_TYPE_DEFINITIONS",{enumerable:true,get:function(){return types.GRAPH_RELATION_TYPE_DEFINITIONS}});exports.GraphStore=V;exports.MEMORY_CATEGORIES=te;exports.MemoryArchiver=H;exports.MemoryDatabaseError=R;exports.MemoryDatabaseManager=X;exports.MemoryEmbeddingError=Y;exports.MemoryError=x;exports.MemoryErrorCode=be;exports.MemoryFileError=D;exports.MemoryFileManager=M;exports.MemoryFormatter=L;exports.MemoryNotFoundError=j;exports.MemoryPermissionError=B;exports.MemorySearchError=G;exports.MemorySystem=Z;exports.MemoryValidationError=O;exports.addWord=Je;exports.closeTokenizer=Ke;exports.createMemorySystem=Ue;exports.initLog=tr;exports.initTokenizer=ae;exports.isInitialized=Ge;exports.loadCustomDict=_e;exports.toFtsTokens=ie;exports.toFtsTokensForSearch=de;exports.tokenize=Me;exports.tokenizeForSearch=Ne;
package/dist/index.d.cts CHANGED
@@ -77,7 +77,12 @@ interface IMemorySystem {
77
77
  tags?: string[];
78
78
  }): Promise<MemoryFact>;
79
79
  listAgentIds(): Promise<string[]>;
80
- queryForSummary(agentId: string, limit?: number): Promise<MemoryFact[]>;
80
+ queryForSummary(agentId: string, options?: {
81
+ limit?: number;
82
+ category?: string;
83
+ fromTime?: string;
84
+ toTime?: string;
85
+ }): Promise<MemoryFact[]>;
81
86
  archive(): Promise<void>;
82
87
  clear(): Promise<void>;
83
88
  close(): Promise<void>;
@@ -294,7 +299,12 @@ declare class MemorySystem implements IMemorySystem {
294
299
  tags?: string[];
295
300
  }): Promise<MemoryFact>;
296
301
  listAgentIds(): Promise<string[]>;
297
- queryForSummary(agentId: string, limit?: number): Promise<MemoryFact[]>;
302
+ queryForSummary(agentId: string, options?: {
303
+ limit?: number;
304
+ category?: string;
305
+ fromTime?: string;
306
+ toTime?: string;
307
+ }): Promise<MemoryFact[]>;
298
308
  archive(): Promise<void>;
299
309
  cleanupOrphanRecords(): Promise<void>;
300
310
  clear(): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -77,7 +77,12 @@ interface IMemorySystem {
77
77
  tags?: string[];
78
78
  }): Promise<MemoryFact>;
79
79
  listAgentIds(): Promise<string[]>;
80
- queryForSummary(agentId: string, limit?: number): Promise<MemoryFact[]>;
80
+ queryForSummary(agentId: string, options?: {
81
+ limit?: number;
82
+ category?: string;
83
+ fromTime?: string;
84
+ toTime?: string;
85
+ }): Promise<MemoryFact[]>;
81
86
  archive(): Promise<void>;
82
87
  clear(): Promise<void>;
83
88
  close(): Promise<void>;
@@ -294,7 +299,12 @@ declare class MemorySystem implements IMemorySystem {
294
299
  tags?: string[];
295
300
  }): Promise<MemoryFact>;
296
301
  listAgentIds(): Promise<string[]>;
297
- queryForSummary(agentId: string, limit?: number): Promise<MemoryFact[]>;
302
+ queryForSummary(agentId: string, options?: {
303
+ limit?: number;
304
+ category?: string;
305
+ fromTime?: string;
306
+ toTime?: string;
307
+ }): Promise<MemoryFact[]>;
298
308
  archive(): Promise<void>;
299
309
  cleanupOrphanRecords(): Promise<void>;
300
310
  clear(): Promise<void>;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import {b,a}from'./chunks/chunk-2WS5ZGKQ.mjs';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 {loadTextFile,Filesystem,formatLocalISO}from'@easbot/utils';import Se from'better-sqlite3';import {randomBytes,createHash}from'crypto';import w from'fs/promises';import R from'path';import {promises}from'fs';import {embed,embedMany,streamText}from'ai';var re=["user_preference","task_context","technical_fact","decision","relationship","reminder","error_pattern","workflow","exploration_finding","experience_summary","tool_usage","skill_creation","test","other"],x=class extends Error{constructor(t,n,r){super(t,{cause:r});this.code=n;this.cause=r;this.name="MemoryError";}},N=class extends x{constructor(e,t){super(e,"MEMORY_VALIDATION_ERROR",t),this.name="MemoryValidationError";}},j=class extends x{constructor(e){super(`Memory not found: ${e}`,"MEMORY_NOT_FOUND"),this.name="MemoryNotFoundError";}},B=class extends x{constructor(e){super(e,"MEMORY_PERMISSION_ERROR"),this.name="MemoryPermissionError";}},T=class extends x{constructor(e,t){super(e,"MEMORY_DATABASE_ERROR",t),this.name="MemoryDatabaseError";}},S=class extends x{constructor(e,t){super(e,"MEMORY_FILE_ERROR",t),this.name="MemoryFileError";}},G=class extends x{constructor(e,t){super(e,"MEMORY_SEARCH_ERROR",t),this.name="MemorySearchError";}},Y=class extends x{constructor(e,t){super(e,"MEMORY_EMBEDDING_ERROR",t),this.name="MemoryEmbeddingError";}},Re=(m=>(m.VALIDATION_ERROR="MEMORY_VALIDATION_ERROR",m.NOT_FOUND="MEMORY_NOT_FOUND",m.PERMISSION_ERROR="MEMORY_PERMISSION_ERROR",m.DATABASE_ERROR="MEMORY_DATABASE_ERROR",m.FILE_ERROR="MEMORY_FILE_ERROR",m.SEARCH_ERROR="MEMORY_SEARCH_ERROR",m.EMBEDDING_ERROR="MEMORY_EMBEDDING_ERROR",m))(Re||{});var M=b.create({service:"memory.tokenizer"}),F=false,we=loadTextFile("./assets/jieba_dict.txt",import.meta.url);async function ce(g){if(!F)try{M.debug("Initializing jieba tokenizer");let e=we();if(P.with_dict(e),M.debug("Built-in dictionary loaded"),g?.dictPath&&g.dictPath.length>0)for(let t of g.dictPath)await Ie(t);F=!0,M.debug("Jieba tokenizer initialized successfully");}catch(e){M.error("Failed to initialize jieba tokenizer",{error:String(e)}),M.warn("Using fallback tokenization (space-based)");}}async function Ie(g){if(!F)throw new Error("Tokenizer not initialized");try{let e=await Filesystem.readText(g);M.debug("Loading custom dictionary",{dictPath:g}),P.with_dict(e),M.debug("Custom dictionary loaded successfully",{dictPath:g});}catch(e){M.warn("Failed to load custom dictionary",{dictPath:g,error:String(e)});}}function Ae(g){if(!F)return g.split(/\s+/).filter(Boolean);try{return P.cut(g)}catch(e){return M.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Ne(g){if(!F)return g.split(/\s+/).filter(Boolean);try{return P.cut_for_search(g)}catch(e){return M.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Je(g,e,t){if(F)try{P.add_word(g,e,t),M.debug("Word added to dictionary",{word:g,freq:e,tag:t});}catch(n){M.warn("Failed to add word",{word:g,error:String(n)});}}function Ge(){return F}async function Ke(){F=false,M.debug("Tokenizer closed");}function se(g){if(!F)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ae(g).join(" ")}catch(e){return M.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}function me(g){if(!F)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ne(g).join(" ")}catch(e){return M.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}var X=class{constructor(e){a(this,"db",null);a(this,"storagePath");a(this,"initialized",false);a(this,"initPromise",null);this.storagePath=Filesystem.toUnixPath(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 T(`Database initialization failed: ${e.message}`,e)}}async openDatabaseAsync(){return new Promise((e,t)=>{setImmediate(()=>{try{let n=new Se(this.storagePath);n.pragma("journal_mode = WAL"),n.pragma("synchronous = NORMAL"),n.pragma("cache_size = -64000"),n.pragma("temp_store = MEMORY"),e(n);}catch(n){t(n);}});})}createTables(){if(!this.db)throw new T("Database not initialized");let e=this.db;e.exec(`
1
+ import {b,a}from'./chunks/chunk-2WS5ZGKQ.mjs';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 {loadTextFile,Filesystem,formatLocalISO}from'@easbot/utils';import Ie from'better-sqlite3';import {randomBytes,createHash}from'crypto';import N from'fs/promises';import T from'path';import {promises}from'fs';import {embed,embedMany,streamText}from'ai';var re=["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});a(this,"code",r);a(this,"cause",n);this.name="MemoryError";}},S=class extends k{constructor(e,t){super(e,"MEMORY_VALIDATION_ERROR",t),this.name="MemoryValidationError";}},B=class extends k{constructor(e){super(`Memory not found: ${e}`,"MEMORY_NOT_FOUND"),this.name="MemoryNotFoundError";}},Y=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";}},K=class extends k{constructor(e,t){super(e,"MEMORY_SEARCH_ERROR",t),this.name="MemorySearchError";}},X=class extends k{constructor(e,t){super(e,"MEMORY_EMBEDDING_ERROR",t),this.name="MemoryEmbeddingError";}},Re=(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))(Re||{});var _=b.create({service:"memory.tokenizer"}),x=false,_e=loadTextFile("./assets/jieba_dict.txt",import.meta.url);async function de(g){if(!x)try{_.debug("Initializing jieba tokenizer");let e=_e();if(P.with_dict(e),_.debug("Built-in dictionary loaded"),g?.dictPath&&g.dictPath.length>0)for(let t of g.dictPath)await Me(t);x=!0,_.debug("Jieba tokenizer initialized successfully");}catch(e){_.error("Failed to initialize jieba tokenizer",{error:String(e)}),_.warn("Using fallback tokenization (space-based)");}}async function Me(g){if(!x)throw new Error("Tokenizer not initialized");try{let e=await Filesystem.readText(g);_.debug("Loading custom dictionary",{dictPath:g}),P.with_dict(e),_.debug("Custom dictionary loaded successfully",{dictPath:g});}catch(e){_.warn("Failed to load custom dictionary",{dictPath:g,error:String(e)});}}function Ne(g){if(!x)return g.split(/\s+/).filter(Boolean);try{return P.cut(g)}catch(e){return _.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Ae(g){if(!x)return g.split(/\s+/).filter(Boolean);try{return P.cut_for_search(g)}catch(e){return _.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean)}}function Ge(g,e,t){if(x)try{P.add_word(g,e,t),_.debug("Word added to dictionary",{word:g,freq:e,tag:t});}catch(r){_.warn("Failed to add word",{word:g,error:String(r)});}}function Ke(){return x}async function Qe(){x=false,_.debug("Tokenizer closed");}function se(g){if(!x)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ne(g).join(" ")}catch(e){return _.warn("Tokenization failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}function ce(g){if(!x)return g.split(/\s+/).filter(Boolean).join(" ");try{return Ae(g).join(" ")}catch(e){return _.warn("Tokenization for search failed, using fallback",{error:String(e)}),g.split(/\s+/).filter(Boolean).join(" ")}}var q=class{constructor(e){a(this,"db",null);a(this,"storagePath");a(this,"initialized",false);a(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 Ie(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(`
2
2
  CREATE TABLE IF NOT EXISTS memory_facts (
3
3
  id TEXT PRIMARY KEY,
4
4
  agent_id TEXT NOT NULL,
@@ -61,31 +61,31 @@ import {b,a}from'./chunks/chunk-2WS5ZGKQ.mjs';import {GRAPH_ENTITY_TYPE_DEFINITI
61
61
  key TEXT PRIMARY KEY,
62
62
  value TEXT
63
63
  )
64
- `);}query(e,t){if(!this.db)throw new T("Database not initialized. Call initialize() first.");try{let n=this.db.prepare(e);return t?n.all(...t):n.all()}catch(n){throw new T(`Query failed: ${n.message}`,n)}}run(e,t){if(!this.db)throw new T("Database not initialized. Call initialize() first.");try{let n=this.db.prepare(e),r=t?n.run(...t):n.run();return {lastID:Number(r.lastInsertRowid),changes:r.changes}}catch(n){throw new T(`Write failed: ${n.message}`,n)}}transaction(e){if(!this.db)throw new T("Database not initialized. Call initialize() first.");return this.db.transaction(e)()}prepare(e){if(!this.db)throw new T("Database not initialized. Call initialize() first.");return this.db.prepare(e)}exec(e){if(!this.db)throw new T("Database not initialized. Call initialize() first.");this.db.exec(e);}getDb(){if(!this.db)throw new T("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 Le=["id","agentId","category","importance"],q="---",O=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),n=e.updatedAt?new Date(e.updatedAt):new Date,r={id:e.id,agentId:e.agentId,category:e.category,importance:e.importance,createdAt:formatLocalISO(t),updatedAt:formatLocalISO(n),source:e.source};e.sessionId&&(r.sessionId=e.sessionId),e.msgId&&(r.msgId=e.msgId),e.parentMsgId&&(r.parentMsgId=e.parentMsgId),e.tags&&e.tags.length>0&&(r.tags=e.tags),e.nodeIds&&e.nodeIds.length>0&&(r.nodeIds=e.nodeIds),e.filePath&&(r.filePath=e.filePath);let i=Object.entries(r).map(([s,m])=>Array.isArray(m)?`${s}: [${m.join(", ")}]`:`${s}: ${m}`);return [q,...i,q,"",e.content.trim(),""].join(`
64
+ `);}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 De=["id","agentId","category","importance"],H="---",D=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 [H,...i,H,"",e.content.trim(),""].join(`
65
65
  `)}static serializeFile(e){return e.map(t=>g.serialize(t)).join(`
66
- `)}static parse(e){let t=[],n=e.split(`
67
- `),r=0;for(;r<n.length;){if(n[r]?.trim()!==q){r++;continue}let i=r+1,s=-1;for(let u=i;u<n.length;u++)if(n[u]?.trim()===q){s=u;break}if(s===-1){r++;continue}let m=n.slice(i,s),o=g.parseFrontmatter(m);g.validateFrontmatter(o);let d=s+1,c=n.length;for(let u=d;u<n.length;u++)if(n[u]?.trim()===q){c=u;break}let a=n.slice(d,c).join(`
68
- `).trim(),l={id:String(o.id),agentId:String(o.agentId),category:o.category,importance:Number(o.importance),source:o.source??"session_self_write",content:a,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&&(l.sessionId=String(o.sessionId)),o.msgId&&(l.msgId=String(o.msgId)),o.parentMsgId&&(l.parentMsgId=String(o.parentMsgId)),o.filePath&&(l.filePath=String(o.filePath)),o.tags&&(l.tags=g.parseArrayField(o.tags)),o.nodeIds&&(l.nodeIds=g.parseArrayField(o.nodeIds).map(Number).filter(u=>!Number.isNaN(u))),t.push(l),r=c;}return t}static parseFrontmatter(e){let t={};for(let n of e){let r=n.indexOf(":");if(r===-1)continue;let i=n.slice(0,r).trim(),s=n.slice(r+1).trim();if(i)if(s.startsWith("[")&&s.endsWith("]")){let m=s.slice(1,-1).trim();t[i]=m?m.split(",").map(o=>o.trim()).filter(Boolean):[];}else t[i]=s;}return t}static validateFrontmatter(e){for(let r of Le)if(e[r]===void 0||e[r]==="")throw new N(`Missing required field in memory frontmatter: ${r}`);let t=e.category;if(!re.includes(t))throw new N(`Invalid category: "${t}". Valid values: ${re.join(", ")}`);let n=Number(e.importance);if(Number.isNaN(n)||n<1||n>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 n=t.slice(1,-1).trim();return n?n.split(",").map(r=>r.trim()).filter(Boolean):[]}return t?[t]:[]}return []}};var ue="MEMORY.md",pe="active",ve="archive",A=class g{static getMemoryMdPath(e){return R.join(e,ue)}static getActiveFilePath(e,t,n){let r=n??new Date,i=r.getFullYear(),s=String(r.getMonth()+1).padStart(2,"0"),m=String(r.getDate()).padStart(2,"0"),o=`${i}-${s}-${m}`;return R.join(e,pe,t,`${o}.md`)}static getArchiveFilePath(e,t,n,r){let i=new Date(n),s=`${i.getFullYear()}-${String(i.getMonth()+1).padStart(2,"0")}`;return R.join(e,ve,s,t,r)}static async readMemoryMd(e){let t=g.getMemoryMdPath(e);try{return await w.readFile(t,"utf-8")}catch(n){if(n.code==="ENOENT")return null;throw new S(`Failed to read MEMORY.md: ${n.message}`,n)}}static async write(e,t){let n=g.getActiveFilePath(e,t.category);Filesystem.toUnixPath(R.relative(e,n));if(R.basename(n)===ue)throw new B("Writing to MEMORY.md is not allowed. MEMORY.md is read-only.");try{await w.mkdir(R.dirname(n),{recursive:!0});let i=O.serialize(t),s="";try{s=await w.readFile(n,"utf-8");}catch{}let m=s.length>0&&!s.endsWith(`
66
+ `)}static parse(e){let t=[],r=e.split(`
67
+ `),n=0;for(;n<r.length;){if(r[n]?.trim()!==H){n++;continue}let i=n+1,a=-1;for(let u=i;u<r.length;u++)if(r[u]?.trim()===H){a=u;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 u=m;u<r.length;u++)if(r[u]?.trim()===H){d=u;break}let s=r.slice(m,d).join(`
68
+ `).trim(),l={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&&(l.sessionId=String(o.sessionId)),o.msgId&&(l.msgId=String(o.msgId)),o.parentMsgId&&(l.parentMsgId=String(o.parentMsgId)),o.filePath&&(l.filePath=String(o.filePath)),o.tags&&(l.tags=g.parseArrayField(o.tags)),o.nodeIds&&(l.nodeIds=g.parseArrayField(o.nodeIds).map(Number).filter(u=>!Number.isNaN(u))),t.push(l),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 De)if(e[n]===void 0||e[n]==="")throw new S(`Missing required field in memory frontmatter: ${n}`);let t=e.category;if(!re.includes(t))throw new S(`Invalid category: "${t}". Valid values: ${re.join(", ")}`);let r=Number(e.importance);if(Number.isNaN(r)||r<1||r>10)throw new S(`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 ge="MEMORY.md",le="active",ve="archive",M=class g{static getMemoryMdPath(e){return T.join(e,ge)}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 T.join(e,le,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 T.join(e,ve,a,t,n)}static async readMemoryMd(e){let t=g.getMemoryMdPath(e);try{return await N.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(T.basename(r)===ge)throw new Y("Writing to MEMORY.md is not allowed. MEMORY.md is read-only.");try{await N.mkdir(T.dirname(r),{recursive:!0});let n=D.serialize(t),i="";try{i=await N.readFile(r,"utf-8");}catch{}let a=i.length>0&&!i.endsWith(`
69
69
  `)?`
70
- `:"";return await w.writeFile(n,`${s}${m}${i}`,"utf-8"),Filesystem.normalize(n)}catch(i){throw i instanceof B?i:new S(`Failed to write memory to ${n}: ${i.message}`,i)}}static async read(e){try{let t=await w.readFile(e,"utf-8");return O.parse(t)}catch(t){if(t.code==="ENOENT")return [];throw new S(`Failed to read memory file ${e}: ${t.message}`,t)}}static async delete(e,t){try{let n=await g.read(e),r=n.filter(i=>i.id!==t);if(r.length===n.length)return;r.length===0?await w.unlink(e).catch(()=>{}):await w.writeFile(e,O.serializeFile(r),"utf-8");}catch(n){throw n instanceof S?n:new S(`Failed to delete memory ${t} from ${e}: ${n.message}`,n)}}static async update(e,t,n){try{let r=await g.read(e),i=r.findIndex(m=>m.id===t);if(i===-1)return;let s={...r[i],...n,updatedAt:new Date().toISOString()};r[i]=s,await w.writeFile(e,O.serializeFile(r),"utf-8");}catch(r){throw r instanceof S?r:new S(`Failed to update memory ${t} in ${e}: ${r.message}`,r)}}static async listActiveFiles(e){let t=R.join(e,pe),n=[];try{await g.scanDir(t,n);}catch(r){if(r.code==="ENOENT")return [];throw new S(`Failed to list active memory files: ${r.message}`,r)}return n}static async scanDir(e,t){let n=await w.readdir(e,{withFileTypes:true});for(let r of n){let i=R.join(e,r.name);r.isDirectory()?await g.scanDir(i,t):r.isFile()&&r.name.endsWith(".md")&&t.push(i);}}};var H=class{constructor(e,t){a(this,"db");a(this,"config");this.db=e,this.config=t;}async archive(){let t=(this.config.archiveDays??30)*864e5,n=Date.now(),r=[],i=await A.listActiveFiles(this.config.workspaceDir);for(let s of i){let m=await A.read(s);if(m.length===0)continue;let o=m[0]?.createdAt,d=o?new Date(o).getTime():n;if(n-d<=t)continue;let c=m[0]?.category;if(!c)continue;let a=R.basename(s),l=A.getArchiveFilePath(this.config.workspaceDir,c,d,a);await promises.mkdir(R.dirname(l),{recursive:true}),await promises.rename(s,l);let u=Filesystem.toUnixPath(R.relative(this.config.workspaceDir,l)),p=Filesystem.toUnixPath(R.relative(this.config.workspaceDir,s));this.db.prepare("UPDATE memory_facts SET file_path = ? WHERE file_path = ?").run(u,p),r.push({source:s,target:l,timestamp:n});}return {archivedCount:r.length,records:r}}};var Q=b.create({service:"memory.graph-store"}),V=class{constructor(e){a(this,"db");this.db=e;}async upsertNode(e,t,n){let r=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(n??{}),r,i.id),i.id;let s=this.db.prepare("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)").run(e,t,JSON.stringify(n??{}),r,r);return Number(s.lastInsertRowid)}async deleteNode(e){this.db.prepare("DELETE FROM nodes WHERE id = ?").run(e);}async upsertEdge(e,t,n,r){let i=this.db.prepare("INSERT INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)").run(e,t,n,JSON.stringify(r??{}),Date.now());return Number(i.lastInsertRowid)}async queryNodes(e={}){let t="SELECT id, name, type, properties, createdAt, updatedAt FROM nodes",n=[],r=[];if(e.ids&&e.ids.length>0){let s=e.ids.map(m=>typeof m=="string"?parseInt(m,10):m).filter(m=>!Number.isNaN(m));r.push(`id IN (${s.map(()=>"?").join(", ")})`),n.push(...s);}e.name&&(r.push("name LIKE ?"),n.push(`%${e.name}%`)),e.type&&(r.push("type = ?"),n.push(e.type)),r.length>0&&(t+=` WHERE ${r.join(" AND ")}`),t+=" ORDER BY id",e.limit&&(t+=" LIMIT ?",n.push(e.limit)),Q.debug("queryNodes",{sql:t,params:n,filter:e});let i=this.db.prepare(t).all(...n);return Q.debug("queryNodes result",{count:i.length}),i.map(s=>({id:s.id,name:s.name,type:s.type,properties:s.properties?JSON.parse(s.properties):void 0,createdAt:s.createdAt,updatedAt:s.updatedAt}))}async queryEdges(e={}){let t="SELECT id, source, target, relation, properties, createdAt FROM edges",n=[],r=[];if(e.ids&&e.ids.length>0&&(r.push(`id IN (${e.ids.map(()=>"?").join(", ")})`),n.push(...e.ids)),e.source!==void 0&&(r.push("source = ?"),n.push(e.source)),e.target!==void 0&&(r.push("target = ?"),n.push(e.target)),e.sourceOrTarget&&e.sourceOrTarget.length>0){let d=e.sourceOrTarget.map(c=>typeof c=="string"?parseInt(c,10):c).filter(c=>!Number.isNaN(c));r.push(`(source IN (${d.map(()=>"?").join(", ")}) OR target IN (${d.map(()=>"?").join(", ")}))`),n.push(...d,...d);}e.relation&&(r.push("relation = ?"),n.push(e.relation)),r.length>0&&(t+=` WHERE ${r.join(" AND ")}`),t+=" ORDER BY id",e.limit&&(t+=" LIMIT ?",n.push(e.limit)),Q.debug("queryEdges",{sql:t,params:n,filter:e});let i=this.db.prepare(t).all(...n);Q.debug("queryEdges result",{count:i.length});let s=[...new Set(i.map(d=>d.target))],m=s.length>0?await this.queryNodes({ids:s,limit:s.length}):[],o=new Map(m.map(d=>[d.id,d]));return i.map(d=>{let c={id:d.id,source:d.source,target:d.target,relation:d.relation,properties:d.properties?JSON.parse(d.properties):void 0,createdAt:d.createdAt},a=o.get(d.target);return a&&(c.targetNode=a),c})}async queryNeighbors(e,t=1,n){let r=new Set,i=[{id:e,level:0}],s=[],m=n?.maxEdgesPerNode??50;for(;i.length>0;){let o=i.shift();if(!o)break;if(r.has(o.id)||o.level>t)continue;r.add(o.id);let c=(await this.queryNodes({ids:[o.id],limit:1}))[0];if(!c)continue;let a=await this.queryEdges({sourceOrTarget:[o.id],limit:m});if(s.push({...c,edges:a}),o.level<t)for(let l of a){let u=l.source===o.id?l.target:l.source;r.has(u)||i.push({id:u,level:o.level+1});}}return s}};var $;(c=>{let g=null;function e(a){t()||(g={models:a.models,options:a.options??{}});}c.init=e;function t(){return g!==null}c.isInitialized=t;function n(){return g?{embedding:!!g.models.embeddingLlm,graph:!!g.models.graphLlm}:{embedding:false,graph:false}}c.capabilities=n;async function r(a){let u=m().models.embeddingLlm;if(!u)throw new Error("embeddingLlm model is not configured.");try{let p=await embed({model:u,value:a});return new Float32Array(p.embedding)}catch(p){let b=u.doEmbed;if(typeof b!="function")throw new Error("embeddingLlm model does not support embedding generation.",{cause:p});let I=(await b({values:[a]}))?.embeddings?.[0];if(!I||!Array.isArray(I))throw new Error("embeddingLlm model returned invalid embedding result.",{cause:p});return new Float32Array(I)}}c.embedText=r;async function i(a){let u=m().models.embeddingLlm;if(!u)throw new Error("embeddingLlm model is not configured.");try{return (await embedMany({model:u,values:a})).embeddings.map(b=>new Float32Array(b))}catch{return ((await u.doEmbed?.({values:a}))?.embeddings??[]).map(b=>new Float32Array(b))}}c.embedTexts=i;async function s(a,l){let u=m(),p=u.models.graphLlm;if(!p)throw new Error("llm model is not configured.");try{return (await streamText({model:p,prompt:a,maxOutputTokens:l?.maxOutputTokens??u.options.graph?.maxOutputTokens,temperature:l?.temperature??u.options.graph?.temperature})).text}catch{return (await p.doGenerate?.({prompt:[{role:"user",content:[{type:"text",text:a}]}],maxOutputTokens:l?.maxOutputTokens??u.options.graph?.maxOutputTokens}))?.content?.find(D=>D.type==="text")?.text??""}}c.generate=s;let m=()=>{if(!g)throw new Error("Llm is not initialized. Please call Llm.init() first.");return g};c.embed=r,c.embedMany=i;})($||($={}));var Z=class{constructor(e,t){a(this,"db");a(this,"config");a(this,"embeddingModel");this.db=e,this.config=t,this.embeddingModel=t.embeddingLlm,this.embeddingModel&&$.init({models:{embeddingLlm:this.embeddingModel,graphLlm:t.graphLlm}});}async search(e,t){if(!e.trim())return [];if(!t?.agentId)return [];let n=t.maxResults??this.config.search.maxResults,r=await this.hybridSearch(e,{...t,maxResults:n*2});return r.length===0?[]:r.slice(0,n)}async hybridSearch(e,t){let{maxResults:n=this.config.search.maxResults,minScore:r=this.config.search.minScore,vectorWeight:i=this.config.search.hybrid.vectorWeight,textWeight:s=this.config.search.hybrid.textWeight,enableEmbedding:m=true}=t??{},d=m&&!!this.embeddingModel?await this.embed(e):null,c=["mf.agent_id = ?"],a=[t?.agentId];t?.category&&(c.push("mf.category = ?"),a.push(t.category)),t?.minImportance!==void 0&&(c.push("mf.importance >= ?"),a.push(t.minImportance)),t?.source&&(c.push("mf.source = ?"),a.push(t.source)),t?.fromTime!==void 0&&(c.push("mf.created_at >= ?"),a.push(t.fromTime)),t?.toTime!==void 0&&(c.push("mf.created_at <= ?"),a.push(t.toTime));let l=c.join(" AND "),[u,p]=await Promise.all([d?this.vectorSearch(d,l,a,n,r,t?.candidateFactIds):Promise.resolve([]),this.ftsSearch(e,l,a,n,r)]),b=d?i:0,D=d?s:1;return this.mergeResults(u,p,b,D,l,a,r)}async vectorSearch(e,t,n,r,i,s){if(!this.embeddingModel)return [];try{let m;if(s&&s.length>0){let d=s.map(()=>"?").join(",");m=this.db.prepare(`
70
+ `:"";return await N.writeFile(r,`${i}${a}${n}`,"utf-8"),Filesystem.normalize(r)}catch(n){throw n instanceof Y?n:new O(`Failed to write memory to ${r}: ${n.message}`,n)}}static async read(e){try{let t=await N.readFile(e,"utf-8");return D.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 N.unlink(e).catch(()=>{}):await N.writeFile(e,D.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 N.writeFile(e,D.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=T.join(e,le),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 N.readdir(e,{withFileTypes:true});for(let n of r){let i=T.join(e,n.name);n.isDirectory()?await g.scanDir(i,t):n.isFile()&&n.name.endsWith(".md")&&t.push(i);}}};var V=class{constructor(e,t){a(this,"db");a(this,"config");this.db=e,this.config=t;}async archive(){let t=(this.config.archiveDays??30)*864e5,r=Date.now(),n=[],i=await M.listActiveFiles(this.config.workspaceDir);for(let a of i){let c=await M.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=T.basename(a),l=M.getArchiveFilePath(this.config.workspaceDir,d,m,s);await promises.mkdir(T.dirname(l),{recursive:true}),await promises.rename(a,l);let u=Filesystem.normalize(l),p=Filesystem.normalize(a);this.db.prepare("UPDATE memory_facts SET file_path = ? WHERE file_path = ?").run(u,p),n.push({source:a,target:l,timestamp:r});}return {archivedCount:n.length,records:n}}};var Q=b.create({service:"memory.graph-store"}),J=class{constructor(e){a(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)),Q.debug("queryNodes",{sql:t,params:r,filter:e});let i=this.db.prepare(t).all(...r);return Q.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)),Q.debug("queryEdges",{sql:t,params:r,filter:e});let i=this.db.prepare(t).all(...r);Q.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 l of s){let u=l.source===o.id?l.target:l.source;n.has(u)||i.push({id:u,level:o.level+1});}}return a}};var $;(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 u=c().models.embeddingLlm;if(!u)throw new Error("embeddingLlm model is not configured.");try{let p=await embed({model:u,value:s});return new Float32Array(p.embedding)}catch(p){let E=u.doEmbed;if(typeof E!="function")throw new Error("embeddingLlm model does not support embedding generation.",{cause:p});let A=(await E({values:[s]}))?.embeddings?.[0];if(!A||!Array.isArray(A))throw new Error("embeddingLlm model returned invalid embedding result.",{cause:p});return new Float32Array(A)}}d.embedText=n;async function i(s){let u=c().models.embeddingLlm;if(!u)throw new Error("embeddingLlm model is not configured.");try{return (await embedMany({model:u,values:s})).embeddings.map(E=>new Float32Array(E))}catch{return ((await u.doEmbed?.({values:s}))?.embeddings??[]).map(E=>new Float32Array(E))}}d.embedTexts=i;async function a(s,l){let u=c(),p=u.models.graphLlm;if(!p)throw new Error("llm model is not configured.");try{return (await streamText({model:p,prompt:s,maxOutputTokens:l?.maxOutputTokens??u.options.graph?.maxOutputTokens,temperature:l?.temperature??u.options.graph?.temperature})).text}catch{return (await p.doGenerate?.({prompt:[{role:"user",content:[{type:"text",text:s}]}],maxOutputTokens:l?.maxOutputTokens??u.options.graph?.maxOutputTokens}))?.content?.find(L=>L.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;})($||($={}));var Z=class{constructor(e,t){a(this,"db");a(this,"config");a(this,"embeddingModel");this.db=e,this.config=t,this.embeddingModel=t.embeddingLlm,this.embeddingModel&&$.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 l=d.join(" AND "),[u,p]=await Promise.all([m?this.vectorSearch(m,l,s,r,n,t?.candidateFactIds):Promise.resolve([]),this.ftsSearch(e,l,s,r,n)]),E=m?i:0,L=m?a:1;return this.mergeResults(u,p,E,L,l,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(`
71
71
  SELECT mf.id, mv.embedding
72
72
  FROM memory_facts mf
73
73
  JOIN memory_vectors mv ON mf.id = mv.fact_id
74
- WHERE ${t} AND mf.id IN (${d})
75
- `).all(...n,...s);}else m=this.db.prepare(`
74
+ WHERE ${t} AND mf.id IN (${m})
75
+ `).all(...r,...a);}else c=this.db.prepare(`
76
76
  SELECT mf.id, mv.embedding
77
77
  FROM memory_facts mf
78
78
  JOIN memory_vectors mv ON mf.id = mv.fact_id
79
79
  WHERE ${t}
80
80
  LIMIT ?
81
- `).all(...n,Math.max(r*100,1e3));let o=[];for(let d of m){let c=new Float32Array(d.embedding.buffer,d.embedding.byteOffset,d.embedding.length/4),a=this.cosineSimilarity(e,c);o.push({id:d.id,score:a});}return o.sort((d,c)=>c.score-d.score).slice(0,r)}catch(m){throw new G(`\u5411\u91CF\u641C\u7D22\u5931\u8D25: ${m instanceof Error?m.message:String(m)}`,m instanceof Error?m:void 0)}}async ftsSearch(e,t,n,r,i){let s=()=>[];try{let o=(me(e).trim()||e.trim()).split(/\s+/).filter(a=>a.length>0).map(a=>`"${a.replace(/"/g,'""')}"`).join(" "),d=this.db.prepare(`
81
+ `).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 K(`\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=(ce(e).trim()||e.trim()).split(/\s+/).filter(s=>s.length>0).map(s=>`"${s.replace(/"/g,'""')}"`).join(" "),m=this.db.prepare(`
82
82
  SELECT mf.id, bm25(memory_facts_fts) as score
83
83
  FROM memory_facts mf
84
84
  JOIN memory_facts_fts ON mf.id = memory_facts_fts.fact_id
85
85
  WHERE ${t} AND memory_facts_fts.content MATCH ?
86
86
  ORDER BY score DESC
87
87
  LIMIT ?
88
- `).all(...n,o,r);if(d.length===0)return s();let c=Math.max(...d.map(a=>Math.abs(a.score)),1);return d.map(a=>({id:a.id,score:1-Math.abs(a.score)/c})).filter(a=>a.score>=0)}catch{return s()}}async mergeResults(e,t,n,r,i,s,m){let o=n+r,d=n/o,c=r/o,a=new Map;for(let h of e)a.set(h.id,h.score*d);for(let h of t){let _=a.get(h.id)||0;a.set(h.id,_+h.score*c);}let l=Array.from(a.entries()).map(([h,_])=>({id:h,score:_})).sort((h,_)=>_.score-h.score).map(h=>h.id);if(l.length===0)return [];let u=l.map(()=>"?").join(","),p=this.db.prepare(`
88
+ `).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 w=s.get(h.id)||0;s.set(h.id,w+h.score*d);}let l=Array.from(s.entries()).map(([h,w])=>({id:h,score:w})).sort((h,w)=>w.score-h.score).map(h=>h.id);if(l.length===0)return [];let u=l.map(()=>"?").join(","),p=this.db.prepare(`
89
89
  SELECT
90
90
  mf.id as memoryId,
91
91
  mf.category,
@@ -98,21 +98,21 @@ import {b,a}from'./chunks/chunk-2WS5ZGKQ.mjs';import {GRAPH_ENTITY_TYPE_DEFINITI
98
98
  mf.node_ids
99
99
  FROM memory_facts mf
100
100
  WHERE mf.id IN (${u})
101
- `).all(...l),b=[],D=new Map;for(let h of p)if(h.node_ids)try{let _=JSON.parse(h.node_ids);D.set(h.memoryId,_),b.push(..._);}catch{}let I=Array.from(new Set(b)),oe=new Map,W=new Map;if(I.length>0){let h=I.map(()=>"?").join(", "),_=this.db.prepare(`SELECT id, name, type FROM nodes WHERE id IN (${h})`).all(...I);for(let y of _)oe.set(y.id,y);let J=this.db.prepare(`SELECT e.id, e.source, e.target, e.relation, e.properties, e.createdAt, n.name as targetName, n.type as targetType
101
+ `).all(...l),E=[],L=new Map;for(let h of p)if(h.node_ids)try{let w=JSON.parse(h.node_ids);L.set(h.memoryId,w),E.push(...w);}catch{}let A=Array.from(new Set(E)),W=new Map,I=new Map;if(A.length>0){let h=A.map(()=>"?").join(", "),w=this.db.prepare(`SELECT id, name, type FROM nodes WHERE id IN (${h})`).all(...A);for(let y of w)W.set(y.id,y);let G=this.db.prepare(`SELECT e.id, e.source, e.target, e.relation, e.properties, e.createdAt, n.name as targetName, n.type as targetType
102
102
  FROM edges e JOIN nodes n ON n.id = e.target
103
- WHERE e.source IN (${h})`).all(...I);for(let y of J){let U=W.get(y.source)??[];U.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}}),W.set(y.source,U);}let te=this.db.prepare(`SELECT e.id, e.source, e.target, e.relation, e.properties, e.createdAt, n.name as sourceName, n.type as sourceType
103
+ WHERE e.source IN (${h})`).all(...A);for(let y of G){let U=I.get(y.source)??[];U.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,U);}let te=this.db.prepare(`SELECT e.id, e.source, e.target, e.relation, e.properties, e.createdAt, n.name as sourceName, n.type as sourceType
104
104
  FROM edges e JOIN nodes n ON n.id = e.source
105
- WHERE e.target IN (${h})`).all(...I);for(let y of te){let U=W.get(y.target)??[];U.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}}),W.set(y.target,U);}}return p.map(h=>{let _=D.get(h.memoryId)??[],J=_.length>0?_.flatMap(ae=>{let de=oe.get(ae);return de?[{...de,edges:W.get(ae)}]:[]}):void 0,te=a.get(h.memoryId)??0,y=new Date(h.createdAt),U=(Date.now()-y.getTime())/864e5,Ee=Math.exp(-0.05*U),be=(h.importance-1)/9,Te=.4*te+.3*Ee+.3*be;return {memoryId:h.memoryId,category:h.category,importance:h.importance,agentId:h.agentId,snippet:h.snippet,score:Te,createdAt:h.createdAt,source:h.source,filePath:h.filePath,nodes:(J?.length??0)>0?J:void 0}}).filter(h=>h.score>=m).sort((h,_)=>_.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 $.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 n=0,r=0,i=0;for(let s=0;s<e.length;s++){let m=e[s],o=t[s];n+=m*o,r+=m*m,i+=o*o;}return n/(Math.sqrt(r)*Math.sqrt(i))}};var f=b.create({service:"memory.system"}),Ce=.7,ze=.3,$e=10;var Ue=new Set(GRAPH_ENTITY_TYPE_DEFINITIONS.map(g=>g.type)),We=new Set(GRAPH_RELATION_TYPE_DEFINITIONS.map(g=>g.type)),ee=class{constructor(e){a(this,"config");a(this,"db");a(this,"archiver",null);a(this,"searchEngine",null);a(this,"graphStore",null);a(this,"embeddingModel");a(this,"vectorDims");e.search?.hybrid;this.config={workspaceDir:e.workspaceDir,database:e.database,archiveDays:e.archiveDays??30,search:{maxResults:e.search?.maxResults??$e,minScore:e.search?.minScore??.3,hybrid:{enabled:e.search?.hybrid?.enabled??true,vectorWeight:e.search?.hybrid?.vectorWeight??Ce,textWeight:e.search?.hybrid?.textWeight??ze}},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&&$.init({models:{embeddingLlm:this.embeddingModel,graphLlm:this.config.graphLlm}});}async initialize(){await b.init({logDir:this.config.logDir??R.join(this.config.workspaceDir,"logs"),print:process.argv.includes("--print-logs"),dev:false,level:"INFO"}),await w.mkdir(R.dirname(this.config.database.path),{recursive:true}),await w.mkdir(R.join(this.config.workspaceDir,"active"),{recursive:true}),await w.mkdir(R.join(this.config.workspaceDir,"archive"),{recursive:true}),await this.db.initialize(),this.archiver=new H(this.db.getDb(),this.config),this.graphStore=new V(this.db.getDb()),this.searchEngine=new Z(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[n,r]of t)this.db.run("INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)",[n,r]);await ce({dictPath:this.config.tokenizer.dictPath}).catch(n=>{f.warn("Tokenizer initialization failed, using fallback",{error:String(n)});}),f.info("Memory system initialized",{workspaceDir:this.config.workspaceDir,dbPath:this.config.database.path});}async remember(e){if(!e.agentId?.trim())throw new N("agentId is required for remember operation");let t=new Date().toISOString(),n=O.generateId(),r={...e,id:n,source:"session_self_write",createdAt:t,updatedAt:t};A.write(this.config.workspaceDir,r).then(a=>{r.filePath=a,f.debug("Memory written to file",{id:n,filePath:a});}).catch(a=>{f.warn("Failed to write memory to file",{id:n,error:String(a)});});let i=[],s=this.config,m=this.extractEntities(r.content);if(i=this.storeEntitiesAndRelations(m.entities,m.relations).nodeIds,s.graphLlm){let a=r.content,l=r.agentId,u=r.id;f.debug("Scheduling background LLM extraction",{id:u,contentLength:a.length}),this.extractEntitiesWithLlm(a).then(p=>{f.debug("Background LLM extraction completed",{id:u,entities:p.entities.length,relations:p.relations.length}),this.mergeEntitiesAndRelations(u,l,p.entities,p.relations);}).catch(p=>{f.warn("Background graph extraction failed",{id:u,error:String(p)});});}r.nodeIds=i;let d=await this.embed(r.content),c=d?Buffer.from(d.buffer,d.byteOffset,d.byteLength):null;return this.db.transaction(()=>{this.db.run(`INSERT OR REPLACE INTO memory_facts
105
+ WHERE e.target IN (${h})`).all(...A);for(let y of te){let U=I.get(y.target)??[];U.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,U);}}return p.map(h=>{let w=L.get(h.memoryId)??[],G=w.length>0?w.flatMap(oe=>{let ae=W.get(oe);return ae?[{...ae,edges:I.get(oe)}]:[]}):void 0,te=s.get(h.memoryId)??0,y=new Date(h.createdAt),U=(Date.now()-y.getTime())/864e5,fe=Math.exp(-0.05*U),Ee=(h.importance-1)/9,be=.4*te+.3*fe+.3*Ee;return {memoryId:h.memoryId,category:h.category,importance:h.importance,agentId:h.agentId,snippet:h.snippet,score:be,createdAt:h.createdAt,source:h.source,filePath:h.filePath,nodes:(G?.length??0)>0?G:void 0}}).filter(h=>h.score>=c).sort((h,w)=>w.score-h.score)}async embed(e){if(!this.embeddingModel)throw new X("Embedding \u6A21\u578B\u672A\u914D\u7F6E\uFF0C\u65E0\u6CD5\u751F\u6210\u5411\u91CF");try{return await $.embedText(e)}catch(t){throw new X(`\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=b.create({service:"memory.system"}),Ce=.7,ze=.3,$e=10;var We=new Set(GRAPH_ENTITY_TYPE_DEFINITIONS.map(g=>g.type)),Ue=new Set(GRAPH_RELATION_TYPE_DEFINITIONS.map(g=>g.type)),ee=class{constructor(e){a(this,"config");a(this,"db");a(this,"archiver",null);a(this,"searchEngine",null);a(this,"graphStore",null);a(this,"embeddingModel");a(this,"vectorDims");e.search?.hybrid;this.config={workspaceDir:e.workspaceDir,database:e.database,archiveDays:e.archiveDays??30,search:{maxResults:e.search?.maxResults??$e,minScore:e.search?.minScore??.3,hybrid:{enabled:e.search?.hybrid?.enabled??true,vectorWeight:e.search?.hybrid?.vectorWeight??Ce,textWeight:e.search?.hybrid?.textWeight??ze}},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 q(e.database.path),this.embeddingModel&&$.init({models:{embeddingLlm:this.embeddingModel,graphLlm:this.config.graphLlm}});}async initialize(){await b.init({logDir:this.config.logDir??T.join(this.config.workspaceDir,"logs"),print:process.argv.includes("--print-logs"),dev:false,level:"INFO"}),await N.mkdir(T.dirname(this.config.database.path),{recursive:true}),await N.mkdir(T.join(this.config.workspaceDir,"active"),{recursive:true}),await N.mkdir(T.join(this.config.workspaceDir,"archive"),{recursive:true}),await this.db.initialize(),this.archiver=new V(this.db.getDb(),this.config),this.graphStore=new J(this.db.getDb()),this.searchEngine=new Z(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 de({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 S("agentId is required for remember operation");let t=new Date().toISOString(),r=D.generateId(),n=M.getActiveFilePath(this.config.workspaceDir,e.category),i={...e,id:r,source:"session_self_write",createdAt:t,updatedAt:t,filePath:Filesystem.normalize(n)};M.write(this.config.workspaceDir,i).then(l=>{f.debug("Memory written to file",{id:r,filePath:l});}).catch(l=>{f.warn("Failed to write memory to file",{id:r,error:String(l)});});let a=[],c=this.config,o=this.extractEntities(i.content);if(a=this.storeEntitiesAndRelations(o.entities,o.relations).nodeIds,c.graphLlm){let l=i.content,u=i.agentId,p=i.id;f.debug("Scheduling background LLM extraction",{id:p,contentLength:l.length}),this.extractEntitiesWithLlm(l).then(E=>{f.debug("Background LLM extraction completed",{id:p,entities:E.entities.length,relations:E.relations.length}),this.mergeEntitiesAndRelations(p,u,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
106
106
  (id, agent_id, session_id, msg_id, parent_msg_id, content, category, importance,
107
107
  source, tags, node_ids, file_path, created_at, updated_at)
108
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[r.id,r.agentId,r.sessionId??null,r.msgId??null,r.parentMsgId??null,r.content,r.category,r.importance,r.source,r.tags?JSON.stringify(r.tags):null,r.nodeIds?JSON.stringify(r.nodeIds):null,r.filePath?Filesystem.toUnixPath(r.filePath):null,r.createdAt,r.updatedAt]),c&&this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[r.id,c]),this.writeFts(r.id,r.agentId,r.content,r.tags);}),f.info("Memory stored",{id:r.id,category:r.category,agentId:r.agentId,nodeCount:i.length}),r}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 n=Math.min(Math.max(t?.maxDepth??2,1),3),r=await this.graphStore.queryNeighbors(e,n,{maxEdgesPerNode:t?.maxEdgesPerNode??20}),i=r.find(s=>s.id===e);return {node:i?{id:i.id,name:i.name,type:i.type}:void 0,nodes:r.map(s=>s),edges:r.flatMap(s=>s.edges??[])}}async forget(e,t){if(!e?.trim())throw new N("agentId is required for forget operation");let n=this.db.query("SELECT file_path, node_ids, content FROM memory_facts WHERE id = ? AND agent_id = ?",[t,e]);if(n.length===0)throw new j(t);let r=n[0]?.file_path,i=n[0]?.node_ids?JSON.parse(n[0].node_ids):[],s=n[0]?.content,m=s?createHash("sha256").update(s).digest("hex"):null,o=new Set;if(i.length>0){i.map(()=>"?").join(",");let a=this.db.query("SELECT node_ids FROM memory_facts WHERE id != ? AND agent_id = ? AND node_ids IS NOT NULL",[t,e]);for(let l of a)if(l.node_ids){let u=JSON.parse(l.node_ids);for(let p of u)o.add(p);}}let d=i.filter(c=>!o.has(c));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]),d.length>0){let c=d.map(()=>"?").join(",");this.db.run(`DELETE FROM nodes WHERE id IN (${c})`,d);}m&&this.db.run("DELETE FROM embedding_cache WHERE content_hash = ?",[m]);}),r){let c=R.isAbsolute(r)?r:R.join(this.config.workspaceDir,r);await A.delete(c,t).catch(a=>{f.warn("Failed to delete memory from file",{memoryId:t,filePath:r,error:String(a)});});}f.info("Memory deleted",{memoryId:t,agentId:e,orphanNodes:d.length});}async update(e,t,n){if(!e?.trim())throw new N("agentId is required for update operation");let r=this.db.query("SELECT * FROM memory_facts WHERE id = ? AND agent_id = ?",[t,e]);if(r.length===0)throw new j(t);let i=r[0],s=new Date().toISOString(),m=n.content??i.content,o=n.importance??i.importance,d=n.tags??(i.tags?JSON.parse(i.tags):void 0),c=n.content?await this.embed(m).then(l=>l?Buffer.from(l.buffer,l.byteOffset,l.byteLength):null):null;if(this.db.transaction(()=>{this.db.run(`UPDATE memory_facts SET content = ?, importance = ?, tags = ?, updated_at = ?
109
- WHERE id = ? AND agent_id = ?`,[m,o,d?JSON.stringify(d):null,s,t,e]),c&&this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[t,c]),this.writeFts(t,e,m,d);}),i.file_path){let l=R.isAbsolute(i.file_path)?i.file_path:R.join(this.config.workspaceDir,i.file_path);await A.update(l,t,n).catch(u=>{f.warn("Failed to update memory in file",{memoryId:t,error:String(u)});});}let a={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:m,category:i.category,importance:o,source:i.source,tags:d,nodeIds:i.node_ids?JSON.parse(i.node_ids):void 0,filePath:i.file_path??void 0,createdAt:String(i.created_at),updatedAt:s};return f.info("Memory updated",{memoryId:t,agentId:e}),a}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=10){return e?.trim()?this.db.query(`SELECT * FROM memory_facts
110
- WHERE agent_id = ?
108
+ 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 S("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 S("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 B(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 l of s)if(l.node_ids){let u=JSON.parse(l.node_ids);for(let p of u)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=T.isAbsolute(n)?n:T.join(this.config.workspaceDir,n);await M.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 S("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 B(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(l=>l?Buffer.from(l.buffer,l.byteOffset,l.byteLength):null):null;if(this.db.transaction(()=>{this.db.run(`UPDATE memory_facts SET content = ?, importance = ?, tags = ?, updated_at = ?
109
+ 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 l=T.isAbsolute(i.file_path)?i.file_path:T.join(this.config.workspaceDir,i.file_path);await M.update(l,t,r).catch(u=>{f.warn("Failed to update memory in file",{memoryId:t,error:String(u)});});}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
110
+ WHERE ${m}
111
111
  ORDER BY importance DESC, created_at DESC
112
- LIMIT ?`,[e,t]).map(r=>({id:r.id,agentId:r.agent_id,sessionId:r.session_id??void 0,msgId:r.msg_id??void 0,parentMsgId:r.parent_msg_id??void 0,content:r.content,category:r.category,importance:r.importance,source:r.source,tags:r.tags?JSON.parse(r.tags):void 0,nodeIds:r.node_ids?JSON.parse(r.node_ids):void 0,filePath:r.file_path??void 0,createdAt:String(r.created_at),updatedAt:String(r.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)"),n=this.db.run("DELETE FROM memory_vectors WHERE fact_id NOT IN (SELECT id FROM memory_facts)"),r=this.db.run("DELETE FROM embedding_cache WHERE content_hash NOT IN (SELECT content_hash FROM memory_facts)");return {orphanFts:t.changes,orphanVectors:n.changes,orphanCache:r.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 A.listActiveFiles(this.config.workspaceDir);for(let t of e)await w.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(),await b.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"),n=this.db.query("SELECT COUNT(*) as c FROM graph_edges"),r=this.db.query("SELECT key, value FROM meta"),i={};for(let s of r)i[s.key]=s.value;return {dbPath:this.config.database.path,workspaceDir:this.config.workspaceDir,factsCount:e[0]?.c??0,nodesCount:t[0]?.c??0,edgesCount:n[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 n=this.db.query("SELECT * FROM memory_facts ORDER BY category, created_at ASC",[]),r=new Map;for(let i of n){let s=i.category,m=new Date(i.created_at),d=`${`${m.getFullYear()}-${String(m.getMonth()+1).padStart(2,"0")}-${String(m.getDate()).padStart(2,"0")}`}.md`,c=`${s}/${d}`;if(!r.has(c)){let a=R.join(this.config.workspaceDir,"active",s,d);r.set(c,{path:a,facts:[]});}r.get(c).facts.push(i);}for(let[i,{path:s,facts:m}]of r)try{let o=R.dirname(s);await w.mkdir(o,{recursive:!0});let d=m.map(a=>{let l=this.rowToFact(a);return O.serialize(l)}).join(`
113
- `);if(await w.access(s).then(()=>!0).catch(()=>!1)){if((await w.readFile(s,"utf-8")).trim()===d.trim()){e.synced++;continue}e.updated++;}else e.created++;await w.writeFile(s,d,"utf-8"),e.synced++;}catch(o){let d=o instanceof Error?o.message:String(o);e.errors.push(`Failed to sync ${i}: ${d}`),f.warn("Memory file sync failed",{key:i,error:d});}return f.info("Memory sync completed",{synced:e.synced,created:e.created,updated:e.updated,errors:e.errors.length}),this.db.setMeta("lastSync",new Date().toISOString()),e}async hasMemoryFiles(){let e=[R.join(this.config.workspaceDir,"active"),R.join(this.config.workspaceDir,"archive")];for(let t of e)try{let n=await w.readdir(t,{withFileTypes:!0});for(let r of n){let i=R.join(t,r.name);if(r.isDirectory()){if((await w.readdir(i,{withFileTypes:!0})).length>0)return !0}else if(r.name.endsWith(".md"))return !0}}catch(n){if(n.code==="ENOENT")continue;throw n}return false}async clearFiles(){let e=[R.join(this.config.workspaceDir,"active"),R.join(this.config.workspaceDir,"archive")];for(let t of e)try{let n=await w.readdir(t,{withFileTypes:!0});for(let r of n){let i=R.join(t,r.name);r.isDirectory()?await w.rm(i,{recursive:!0,force:!0}):r.name.endsWith(".md")&&await w.unlink(i);}}catch(n){if(n.code!=="ENOENT")throw n}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=[],n=[],r=new Set,i=new Set,s=/([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(s)){let d=this.sanitizeEntityToken(o[1]??""),c=(o[2]??"related_to").trim(),a=this.sanitizeEntityToken(o[3]??"");if(!d||!a||d===a)continue;let l=d.toLowerCase();r.has(l)||(r.add(l),t.push({name:d,type:this.inferEntityType(d),properties:{source:"rule_extracted"}}));let u=a.toLowerCase();r.has(u)||(r.add(u),t.push({name:a,type:this.inferEntityType(a),properties:{source:"rule_extracted"}}));let p=`${l}|${u}|${c}`;i.has(p)||(i.add(p),n.push({source:d,target:a,relation:c}));}let m=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[];for(let o of m){let d=this.sanitizeEntityToken(o);if(!d)continue;let c=d.toLowerCase();r.has(c)||(r.add(c),t.push({name:d,type:this.inferEntityType(d),properties:{source:"keyword_extracted"}}));}return {entities:t,relations:n}}async extractEntitiesWithLlm(e){if(!this.config.graphLlm)return this.extractEntities(e);try{let n=this.buildEntityExtractionPrompt(e);f.debug("LLM extracting entities...",{contentLength:e.length});let r=await $.generate(n,{maxOutputTokens:2e3});f.debug("LLM extraction result",{resultLength:r.length,result:r.slice(0,200)});let i=this.parseEntityExtractionResult(r);return f.debug("Parsed entities",{entityCount:i.entities.length,relationCount:i.relations.length}),i}catch(n){return f.warn("LLM entity extraction failed, falling back to simple extraction",{error:String(n)}),this.extractEntities(e)}}buildEntityExtractionPrompt(e){let t=GRAPH_ENTITY_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
114
- `),n=GRAPH_RELATION_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
115
- `),r=e.slice(0,1e3);return `You are an information extraction engine for a general-purpose memory graph.
112
+ 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 M.listActiveFiles(this.config.workspaceDir);for(let t of e)await N.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(),await b.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`,l=`${o}/${s}`;if(!n.has(l)){let u=T.join(this.config.workspaceDir,"active",o,s);n.set(l,{path:u,facts:[]});}n.get(l).facts.push(c);}for(let[c,{path:o,facts:m}]of n)try{let d=T.dirname(o);await N.mkdir(d,{recursive:!0});let s=m.map(u=>{let p=this.rowToFact(u);return D.serialize(p)}).join(`
113
+ `);if(await N.access(o).then(()=>!0).catch(()=>!1)){if((await N.readFile(o,"utf-8")).trim()===s.trim()){e.synced++;continue}e.updated++;}else e.created++;await N.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=[T.join(this.config.workspaceDir,"active"),T.join(this.config.workspaceDir,"archive")];for(let t of e)try{let r=await N.readdir(t,{withFileTypes:!0});for(let n of r){let i=T.join(t,n.name);if(n.isDirectory()){if((await N.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=[T.join(this.config.workspaceDir,"active"),T.join(this.config.workspaceDir,"archive")];for(let t of e)try{let r=await N.readdir(t,{withFileTypes:!0});for(let n of r){let i=T.join(t,n.name);n.isDirectory()?await N.rm(i,{recursive:!0,force:!0}):n.name.endsWith(".md")&&await N.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 l=m.toLowerCase();n.has(l)||(n.add(l),t.push({name:m,type:this.inferEntityType(m),properties:{source:"rule_extracted"}}));let u=s.toLowerCase();n.has(u)||(n.add(u),t.push({name:s,type:this.inferEntityType(s),properties:{source:"rule_extracted"}}));let p=`${l}|${u}|${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 $.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(`
114
+ `),r=GRAPH_RELATION_TYPE_DEFINITIONS.map(i=>`- ${i.type}: ${i.rule}`).join(`
115
+ `),n=e.slice(0,1e3);return `You are an information extraction engine for a general-purpose memory graph.
116
116
 
117
117
  Extract entities and directed relations from the text.
118
118
 
@@ -120,7 +120,7 @@ Entity type taxonomy:
120
120
  ${t}
121
121
 
122
122
  Relation type taxonomy:
123
- ${n}
123
+ ${r}
124
124
 
125
125
  Extraction rules:
126
126
  - Output valid JSON only. Do not include markdown, prose, or code fences.
@@ -129,7 +129,8 @@ Extraction rules:
129
129
  - Include relation only if both source and target entities are present in the entities list.
130
130
  - Do not invent facts not grounded in the input text.
131
131
  - Keep relation direction meaningful (source -> target).
132
- - properties should contain short factual attributes only (plain JSON object).
132
+ - entity properties should contain short factual attributes only (plain JSON object).
133
+ - relation properties: Optional. Add properties only when the relation has meaningful attributes (e.g., confidence, weight, context). If no meaningful properties, use empty object {}.
133
134
 
134
135
  Return this exact JSON shape:
135
136
  {
@@ -137,9 +138,9 @@ Return this exact JSON shape:
137
138
  { "name": "string", "type": "one_of_entity_types", "properties": {} }
138
139
  ],
139
140
  "relations": [
140
- { "source": "entity_name", "target": "entity_name", "relation": "one_of_relation_types" }
141
+ { "source": "entity_name", "target": "entity_name", "relation": "one_of_relation_types", "properties": {} }
141
142
  ]
142
143
  }
143
144
 
144
145
  Input text:
145
- ${r}`}storeEntitiesAndRelations(e,t){if(e.length===0)return {nodeIds:[]};let n=new Map,r=new Date().toISOString(),i=e.map(()=>"?").join(","),s=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${i})`,e.map(o=>o.name)),m=new Map(s.map(o=>[`${o.name}::${o.type}`,o.id]));return this.db.transaction(()=>{for(let o of e){let d=`${o.name}::${o.type}`,c=m.get(d);if(c!==void 0)this.db.run("UPDATE nodes SET properties = ?, updatedAt = ? WHERE id = ?",[JSON.stringify(o.properties),r,c]),n.set(o.name,c);else {let a=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[o.name,o.type,JSON.stringify(o.properties),r,r]);a.lastID>0&&n.set(o.name,a.lastID);}}for(let o of t){let d=n.get(o.source),c=n.get(o.target);d&&c&&this.db.run("INSERT INTO edges (source, target, relation, createdAt) VALUES (?, ?, ?, ?)",[d,c,o.relation,r]);}}),{nodeIds:Array.from(n.values())}}mergeEntitiesAndRelations(e,t,n,r){if(n.length===0&&r.length===0)return;let i=new Map,s=new Date().toISOString(),m=n.map(()=>"?").join(","),o=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${m})`,n.map(c=>c.name)),d=new Map(o.map(c=>[`${c.name}::${c.type}`,c.id]));this.db.transaction(()=>{for(let a of n){let l=`${a.name}::${a.type}`,u=d.get(l);if(u!==void 0)i.set(a.name,u);else {let p=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[a.name,a.type,JSON.stringify(a.properties),s,s]);p.lastID>0&&i.set(a.name,p.lastID);}}for(let a of r){let l=i.get(a.source),u=i.get(a.target);l&&u&&this.db.run("INSERT INTO edges (source, target, relation, createdAt) VALUES (?, ?, ?, ?)",[l,u,a.relation,s]);}let c=Array.from(i.values());c.length>0&&this.db.run("UPDATE memory_facts SET node_ids = ? WHERE id = ?",[JSON.stringify(c),e]);});}async embed(e){if(!this.embeddingModel)return null;let t=createHash("sha256").update(e).digest("hex"),n=this.db.query("SELECT embedding FROM embedding_cache WHERE content_hash = ?",[t])[0];if(n)return new Float32Array(n.embedding.buffer,n.embedding.byteOffset,n.embedding.byteLength/4);try{let i=(await this.embeddingModel.doEmbed({values:[e]})).embeddings[0];if(!i||i.length===0)return null;let s=new Float32Array(i),m=Buffer.from(s.buffer,s.byteOffset,s.byteLength);return this.db.run("INSERT OR REPLACE INTO embedding_cache (content_hash, embedding) VALUES (?, ?)",[t,m]),this.vectorDims===void 0&&(this.vectorDims=i.length,this.db.run("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)",["vectorDims",String(i.length)])),s}catch(r){return f.warn("Embedding failed",{error:String(r)}),null}}async embedAndStore(e,t){let n=await this.embed(t);if(!n)return;let r=Buffer.from(n.buffer,n.byteOffset,n.byteLength);try{this.db.run("INSERT OR REPLACE INTO memory_vectors (fact_id, embedding) VALUES (?, ?)",[e,r]);}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(n){f.warn("Vector write failed",{factId:e,error:String(n)});}}writeFts(e,t,n,r){try{let i=se(n),s=r?se(r.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,s]);}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 n=JSON.parse(t[0]);return this.normalizeExtractionResult(n)}}catch(t){f.debug("Failed to parse entity extraction result",{error:String(t)});}return {entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,n=Array.isArray(t.entities)?t.entities:[],r=Array.isArray(t.relations)?t.relations:[],i=[],s=new Set,m=new Map;for(let c of n){let a=typeof c?.name=="string"?c.name.trim():"";if(!a)continue;let l=a.toLowerCase();if(s.has(l))continue;s.add(l),m.set(l,a);let u=typeof c?.type=="string"?c.type.trim():"",p=Ue.has(u)?u:"keyword",b=c?.properties&&typeof c.properties=="object"&&!Array.isArray(c.properties)?c.properties:{};i.push({name:a,type:p,properties:b});}let o=[],d=new Set;for(let c of r){let a=typeof c?.source=="string"?c.source.trim():"",l=typeof c?.target=="string"?c.target.trim():"";if(!a||!l)continue;let u=m.get(a.toLowerCase()),p=m.get(l.toLowerCase());if(!u||!p||u===p)continue;let b=typeof c?.relation=="string"?c.relation.trim():"",D=We.has(b)?b:"related_to",I=`${u.toLowerCase()}|${p.toLowerCase()}|${D}`;d.has(I)||(d.add(I),o.push({source:u,target:p,relation:D}));}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 T("Memory system not initialized. Call initialize() first.");return this.searchEngine}getGraphStore(){if(!this.graphStore)throw new T("Memory system not initialized. Call initialize() first.");return this.graphStore}getArchiver(){if(!this.archiver)throw new T("Memory system not initialized. Call initialize() first.");return this.archiver}};async function je(g){let e=new ee(g);return await e.initialize(),e}async function tr(g){let{Log:e}=await import('./chunks/log-P32ZYYG2.mjs'),t=false;await e.init({logDir:g.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:g.print??false,dev:g.dev??t,level:g.level??("INFO")});}export{V as GraphStore,re as MEMORY_CATEGORIES,H as MemoryArchiver,T as MemoryDatabaseError,X as MemoryDatabaseManager,Y as MemoryEmbeddingError,x as MemoryError,Re as MemoryErrorCode,S as MemoryFileError,A as MemoryFileManager,O as MemoryFormatter,j as MemoryNotFoundError,B as MemoryPermissionError,G as MemorySearchError,ee as MemorySystem,N as MemoryValidationError,Je as addWord,Ke as closeTokenizer,je as createMemorySystem,tr as initLog,ce as initTokenizer,Ge as isInitialized,Ie as loadCustomDict,se as toFtsTokens,me as toFtsTokensForSearch,Ae as tokenize,Ne as tokenizeForSearch};
146
+ ${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 l=`${s.name}::${s.type}`,u=m.get(l);if(u!==void 0)i.set(s.name,u);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 l=i.get(s.source),u=i.get(s.target);if(l&&u){let p=s.properties?JSON.stringify(s.properties):"{}";this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[l,u,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=se(r),a=n?se(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 l=s.toLowerCase();if(a.has(l))continue;a.add(l),c.set(l,s);let u=typeof d?.type=="string"?d.type.trim():"",p=We.has(u)?u:"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():"",l=typeof d?.target=="string"?d.target.trim():"";if(!s||!l)continue;let u=c.get(s.toLowerCase()),p=c.get(l.toLowerCase());if(!u||!p||u===p)continue;let E=typeof d?.relation=="string"?d.relation.trim():"",L=Ue.has(E)?E:"related_to",A=`${u.toLowerCase()}|${p.toLowerCase()}|${L}`;if(m.has(A))continue;m.add(A);let W=d?.properties,I;if(W&&typeof W=="object"&&!Array.isArray(W))try{I=W,Object.keys(I).length===0&&(I=void 0);}catch{I=void 0;}o.push({source:u,target:p,relation:L,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 je(g){let e=new ee(g);return await e.initialize(),e}async function rr(g){let{Log:e}=await import('./chunks/log-P32ZYYG2.mjs'),t=false;await e.init({logDir:g.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:g.print??false,dev:g.dev??t,level:g.level??("INFO")});}export{J as GraphStore,re as MEMORY_CATEGORIES,V as MemoryArchiver,R as MemoryDatabaseError,q as MemoryDatabaseManager,X as MemoryEmbeddingError,k as MemoryError,Re as MemoryErrorCode,O as MemoryFileError,M as MemoryFileManager,D as MemoryFormatter,B as MemoryNotFoundError,Y as MemoryPermissionError,K as MemorySearchError,ee as MemorySystem,S as MemoryValidationError,Ge as addWord,Qe as closeTokenizer,je as createMemorySystem,rr as initLog,de as initTokenizer,Ke as isInitialized,Me as loadCustomDict,se as toFtsTokens,ce as toFtsTokensForSearch,Ne as tokenize,Ae as tokenizeForSearch};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easbot/memory",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Memory management library for EASBOT ecosystem - 智能记忆管理库,支持混合搜索、中英文分词、增量索引",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -42,28 +42,27 @@
42
42
  "LICENSE"
43
43
  ],
44
44
  "dependencies": {
45
- "axios": "^1.15.2",
46
- "zod": "^4.3.6",
47
- "@ai-sdk/provider": "^3.0.8",
48
- "@ai-sdk/provider-utils": "^4.0.21",
49
- "@ai-sdk/openai-compatible": "2.0.37",
50
- "@ai-sdk/anthropic": "3.0.63",
51
- "ai": "^6.0.136",
45
+ "zod": "^4.4.3",
46
+ "@ai-sdk/provider": "^3.0.10",
47
+ "@ai-sdk/provider-utils": "^4.0.27",
48
+ "@ai-sdk/openai-compatible": "^2.0.47",
49
+ "@ai-sdk/anthropic": "^3.0.76",
50
+ "ai": "^6.0.176",
52
51
  "better-sqlite3": "^12.9.0",
53
52
  "jieba-wasm": "^2.4.0",
54
53
  "xdg-basedir": "^5.1.0",
55
- "@easbot/types": "0.2.1",
56
- "@easbot/utils": "0.2.1",
57
- "@easbot/local-model-sdk": "0.2.1",
58
- "@easbot/ollama-sdk": "0.2.1"
54
+ "@easbot/types": "0.2.2",
55
+ "@easbot/utils": "0.2.2",
56
+ "@easbot/local-model-sdk": "0.2.2",
57
+ "@easbot/ollama-sdk": "0.2.2"
59
58
  },
60
59
  "devDependencies": {
61
- "@types/node": "^22.17.0",
60
+ "@types/node": "^25.6.2",
62
61
  "@types/better-sqlite3": "^7.6.13",
63
62
  "tsup": "^8.5.1",
64
- "@biomejs/biome": "^2.4.8",
65
- "typescript": "^6.0.2",
66
- "vitest": "^4.1.1"
63
+ "@biomejs/biome": "^2.4.14",
64
+ "typescript": "^6.0.3",
65
+ "vitest": "^4.1.5"
67
66
  },
68
67
  "engines": {
69
68
  "node": ">=22.17.0"
@@ -1 +0,0 @@
1
- 'use strict';var chunkQAB5VLUW_cjs=require('./chunk-QAB5VLUW.cjs');Object.defineProperty(exports,"Log",{enumerable:true,get:function(){return chunkQAB5VLUW_cjs.c}});