@easbot/note 0.2.4 → 0.2.6

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 chunkHGWZVGLR_cjs=require('./chunk-HGWZVGLR.cjs');Object.defineProperty(exports,"Log",{enumerable:true,get:function(){return chunkHGWZVGLR_cjs.c}});
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var chunkU3YLMQXK_cjs=require('./chunks/chunk-U3YLMQXK.cjs'),ue=require('better-sqlite3'),utils=require('@easbot/utils'),types=require('@easbot/types'),U=require('fs/promises'),B=require('path'),crypto=require('crypto'),v=require('jieba-wasm'),ai=require('ai'),xdgBasedir=require('xdg-basedir');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 ue__default=/*#__PURE__*/_interopDefault(ue);var U__default=/*#__PURE__*/_interopDefault(U);var B__namespace=/*#__PURE__*/_interopNamespace(B);var v__namespace=/*#__PURE__*/_interopNamespace(v);var H=(d=>(d.DATABASE_INIT_FAILED="DATABASE_INIT_FAILED",d.DATABASE_NOT_INITIALIZED="DATABASE_NOT_INITIALIZED",d.DATABASE_QUERY_FAILED="DATABASE_QUERY_FAILED",d.DOCUMENT_PARSE_FAILED="DOCUMENT_PARSE_FAILED",d.EMBEDDING_FAILED="EMBEDDING_FAILED",d.ENTITY_EXTRACTION_FAILED="ENTITY_EXTRACTION_FAILED",d.SEARCH_FAILED="SEARCH_FAILED",d.NODE_NOT_FOUND="NODE_NOT_FOUND",d.EDGE_NOT_FOUND="EDGE_NOT_FOUND",d.INVALID_CONFIG="INVALID_CONFIG",d.MODEL_INJECTION_FAILED="MODEL_INJECTION_FAILED",d))(H||{}),R=class extends Error{constructor(t,r,n){super(t,{cause:n});chunkU3YLMQXK_cjs.a(this,"code",r);chunkU3YLMQXK_cjs.a(this,"cause",n);this.name="KnowledgeBaseError";}toString(){return `${this.name}: ${this.message} (${this.code})`}};var X=class{constructor(e){chunkU3YLMQXK_cjs.a(this,"db",null);chunkU3YLMQXK_cjs.a(this,"storagePath");chunkU3YLMQXK_cjs.a(this,"initialized",false);chunkU3YLMQXK_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();}catch(e){throw new R(`Database initialization failed: ${e.message}`,"DATABASE_INIT_FAILED",e)}}async openDatabaseAsync(){return new Promise((e,t)=>{setImmediate(()=>{try{let r=new ue__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);}});})}ensureInitialized(){if(!this.initialized||!this.db)throw new R("Database not initialized. Call initialize() first.","DATABASE_NOT_INITIALIZED")}createTables(){if(!this.db)throw new R("Database not initialized. Call initialize() first.","DATABASE_NOT_INITIALIZED");let e=this.db;e.exec(`
1
+ 'use strict';var chunkHGWZVGLR_cjs=require('./chunks/chunk-HGWZVGLR.cjs'),ue=require('better-sqlite3'),utils=require('@easbot/utils'),types=require('@easbot/types'),U=require('fs/promises'),B=require('path'),crypto=require('crypto'),v=require('jieba-wasm'),ai=require('ai'),xdgBasedir=require('xdg-basedir');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 ue__default=/*#__PURE__*/_interopDefault(ue);var U__default=/*#__PURE__*/_interopDefault(U);var B__namespace=/*#__PURE__*/_interopNamespace(B);var v__namespace=/*#__PURE__*/_interopNamespace(v);var H=(d=>(d.DATABASE_INIT_FAILED="DATABASE_INIT_FAILED",d.DATABASE_NOT_INITIALIZED="DATABASE_NOT_INITIALIZED",d.DATABASE_QUERY_FAILED="DATABASE_QUERY_FAILED",d.DOCUMENT_PARSE_FAILED="DOCUMENT_PARSE_FAILED",d.EMBEDDING_FAILED="EMBEDDING_FAILED",d.ENTITY_EXTRACTION_FAILED="ENTITY_EXTRACTION_FAILED",d.SEARCH_FAILED="SEARCH_FAILED",d.NODE_NOT_FOUND="NODE_NOT_FOUND",d.EDGE_NOT_FOUND="EDGE_NOT_FOUND",d.INVALID_CONFIG="INVALID_CONFIG",d.MODEL_INJECTION_FAILED="MODEL_INJECTION_FAILED",d))(H||{}),R=class extends Error{constructor(t,r,n){super(t,{cause:n});chunkHGWZVGLR_cjs.a(this,"code",r);chunkHGWZVGLR_cjs.a(this,"cause",n);this.name="KnowledgeBaseError";}toString(){return `${this.name}: ${this.message} (${this.code})`}};var X=class{constructor(e){chunkHGWZVGLR_cjs.a(this,"db",null);chunkHGWZVGLR_cjs.a(this,"storagePath");chunkHGWZVGLR_cjs.a(this,"initialized",false);chunkHGWZVGLR_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();}catch(e){throw new R(`Database initialization failed: ${e.message}`,"DATABASE_INIT_FAILED",e)}}async openDatabaseAsync(){return new Promise((e,t)=>{setImmediate(()=>{try{let r=new ue__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);}});})}ensureInitialized(){if(!this.initialized||!this.db)throw new R("Database not initialized. Call initialize() first.","DATABASE_NOT_INITIALIZED")}createTables(){if(!this.db)throw new R("Database not initialized. Call initialize() first.","DATABASE_NOT_INITIALIZED");let e=this.db;e.exec(`
2
2
  CREATE TABLE IF NOT EXISTS nodes (
3
3
  id INTEGER PRIMARY KEY AUTOINCREMENT,
4
4
  name TEXT NOT NULL,
@@ -81,7 +81,7 @@
81
81
  `),e.pragma("foreign_keys = ON");}query(e,t){if(!this.db)throw new Error("Database not initialized");try{let r=this.db.prepare(e);return t?r.all(...t):r.all()}catch(r){throw new R(`Query failed: ${r.message}`,"DATABASE_QUERY_FAILED",r)}}run(e,t){if(!this.db)throw new Error("Database not initialized");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(`Execution failed: ${r.message}`,"DATABASE_QUERY_FAILED",r)}}transaction(e){if(!this.db)throw new Error("Database not initialized");return this.db.transaction(e)()}async close(){this.db&&(this.db.close(),this.db=null);}getPath(){return this.storagePath}getDb(){if(!this.db)throw new Error("Database not initialized");return this.db}async getDocumentsCount(){return (await this.query("SELECT COUNT(*) as count FROM documents"))[0]?.count??0}async getChunksCount(){return (await this.query("SELECT COUNT(*) as count FROM chunks"))[0]?.count??0}async getNodesCount(){return (await this.query("SELECT COUNT(*) as count FROM nodes"))[0]?.count??0}async getEdgesCount(){return (await this.query("SELECT COUNT(*) as count FROM edges"))[0]?.count??0}async isVectorSearchAvailable(){try{return ((await this.query("SELECT COUNT(*) as count FROM vectors"))[0]?.count??0)>0}catch{return false}}async healthCheck(){try{return this.db?(await this.query("SELECT 1"),!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);}getAllDocumentPaths(){if(!this.db)throw new Error("Database not initialized");return this.db.prepare("SELECT path FROM documents").all().map(t=>t.path)}getDocumentIdByPath(e){if(!this.db)throw new Error("Database not initialized");return this.db.prepare("SELECT id FROM documents WHERE path = ?").get(e)?.id??null}getChunkIdsByDocumentId(e){if(!this.db)throw new Error("Database not initialized");return this.db.prepare("SELECT id FROM chunks WHERE documentId = ?").all(e).map(r=>r.id)}cleanupDocumentData(e){if(!this.db)throw new Error("Database not initialized");this.transaction(()=>{let t=this.db.prepare("SELECT id, nodeIds, contentHash FROM chunks WHERE documentId = ?").all(e);if(t.length===0){this.run("DELETE FROM documents WHERE id = ?",[e]);return}let r=t.map(s=>s.id),n=t.map(s=>s.contentHash),o=new Set;for(let s of t)if(s.nodeIds)try{let i=JSON.parse(s.nodeIds);for(let c of i)o.add(c);}catch{}if(r.length>0){let s=r.map(()=>"?").join(",");try{this.run(`DELETE FROM chunks_fts WHERE chunkId IN (${s})`,r);}catch{for(let i of r)try{this.run("DELETE FROM chunks_fts WHERE chunkId = ?",[i]);}catch{}}}if(o.size>0){let s=Array.from(o),i=this.db.prepare(`
82
82
  SELECT nodeIds FROM chunks
83
83
  WHERE documentId != ?
84
- `).all(e),c=new Set;for(let a of i)if(a.nodeIds)try{let l=JSON.parse(a.nodeIds);for(let d of l)c.add(d);}catch{}for(let a of s)c.has(a)||this.run("DELETE FROM nodes WHERE id = ?",[a]);}if(n.length>0)for(let s of n){let i=this.db.prepare("SELECT COUNT(*) as count FROM chunks WHERE contentHash = ? AND documentId != ?").get(s,e);(!i||i.count===0)&&this.run("DELETE FROM embedding_cache WHERE contentHash = ?",[s]);}this.run("DELETE FROM chunks WHERE documentId = ?",[e]),this.run("DELETE FROM documents WHERE id = ?",[e]);});}deleteDocumentByPath(e){let t=this.getDocumentIdByPath(e);return t===null?false:(this.cleanupDocumentData(t),true)}};var P=class{async parse(e){try{let t=await U.readFile(e,"utf-8"),r=B.extname(e).toLowerCase(),n=this.parseMarkdown(t);return {content:n.content,metadata:n.metadata}}catch(t){throw new R(`\u6587\u6863\u89E3\u6790\u5931\u8D25: ${t.message}`,"DOCUMENT_PARSE_FAILED",t)}}parseMarkdown(e){let{frontmatter:t,content:r}=utils.Markdown.extractFrontmatter(e),n={};t.title!==void 0&&(n.title=String(t.title)),t.author!==void 0&&(n.author=String(t.author)),t.date!==void 0&&(n.date=String(t.date));for(let[s,i]of Object.entries(t))["title","author","date"].includes(s)||(n[s]=i);return {content:utils.Markdown.format(r),metadata:n}}static computeHash(e){return crypto.createHash("sha256").update(e,"utf-8").digest("hex")}};var M=chunkU3YLMQXK_cjs.c.create({service:"note.tokenizer"}),x=false,fe=utils.loadTextFile("./assets/jieba_dict.txt",chunkU3YLMQXK_cjs.b);async function it(E){if(!x)try{M.info("Initializing jieba tokenizer");let e=fe();if(v__namespace.with_dict(e),M.info("Built-in dictionary loaded"),E?.dictPath&&E.dictPath.length>0)for(let t of E.dictPath)await ye(t);x=!0,M.info("Jieba tokenizer initialized");}catch(e){throw M.error("Failed to initialize jieba tokenizer",{error:String(e)}),e}}async function ye(E){if(!x)throw new Error("Tokenizer not initialized");try{let e=await utils.Filesystem.readText(E);v__namespace.with_dict(e),M.info("Custom dictionary loaded",{dictPath:E});}catch(e){M.warn("Failed to load custom dictionary",{dictPath:E,error:String(e)});}}function be(E){if(!x)return E.split(/\s+/).filter(Boolean);try{return v__namespace.cut(E)}catch(e){return M.warn("Tokenization failed, using fallback",{error:String(e)}),E.split(/\s+/).filter(Boolean)}}function Ie(E){if(!x)return E.split(/\s+/).filter(Boolean);try{return v__namespace.cut_for_search(E)}catch(e){return M.warn("Tokenization for search failed, using fallback",{error:String(e)}),E.split(/\s+/).filter(Boolean)}}function ot(E,e,t){if(x)try{v__namespace.add_word(E,e,t);}catch(r){M.warn("Failed to add word",{word:E,error:String(r)});}}function at(){return x}async function ct(){x=false,M.info("Tokenizer closed");}function ne(E){return be(E).join(" ")}function se(E){return Ie(E).join(" ")}exports.Llm=void 0;(u=>{let E=chunkU3YLMQXK_cjs.c.create({service:"note-llm"}),e=null,t=()=>{if(!e)throw new Error("Llm is not initialized. Please call Llm.init() first.");return e};function r(h){n()||(e={models:h.models,options:{graph:h.options?.graph,rerankTopN:h.options?.rerankTopN}},E.debug("Llm initialized"));}u.init=r;function n(){return e!==null}u.isInitialized=n;function o(){return e?{embedding:!!e.models.embeddingLlm,graphLlm:!!e.models.graphLlm,rerankLlm:!!e.models.rerankLlm}:{embedding:false,graphLlm:false,rerankLlm:false}}u.capabilities=o;async function s(h){let f=t().models.embeddingLlm;if(!f)throw new Error("embeddingLlm model is not configured.");let b=await ai.embed({model:f,value:h});return new Float32Array(b.embedding)}u.embedText=s;async function i(h){let f=t().models.embeddingLlm;if(!f)throw new Error("embeddingLlm model is not configured.");return (await ai.embedMany({model:f,values:h})).embeddings.map(N=>new Float32Array(N))}u.embedTexts=i;async function c(h,g){let f=t(),b=f.models.graphLlm;if(!b)return "";let N=l(h);return (await ai.streamText({model:b,prompt:N,maxOutputTokens:g?.maxOutputTokens??f.options.graph?.maxOutputTokens,temperature:g?.temperature??f.options.graph?.temperature})).text}u.generateGraph=c;async function a(h,g,f){let b=t();return b.models.rerankLlm?(await ai.rerank({model:b.models.rerankLlm,query:h,documents:g,topN:f??b.options.rerankTopN??g.length})).ranking.map(T=>({index:T.originalIndex,score:T.score??0})):[]}u.rerank=a;function l(h){let g=types.GRAPH_ENTITY_TYPE_DEFINITIONS.map(T=>`- ${T.type}: ${T.rule}`).join(`
84
+ `).all(e),c=new Set;for(let a of i)if(a.nodeIds)try{let l=JSON.parse(a.nodeIds);for(let d of l)c.add(d);}catch{}for(let a of s)c.has(a)||this.run("DELETE FROM nodes WHERE id = ?",[a]);}if(n.length>0)for(let s of n){let i=this.db.prepare("SELECT COUNT(*) as count FROM chunks WHERE contentHash = ? AND documentId != ?").get(s,e);(!i||i.count===0)&&this.run("DELETE FROM embedding_cache WHERE contentHash = ?",[s]);}this.run("DELETE FROM chunks WHERE documentId = ?",[e]),this.run("DELETE FROM documents WHERE id = ?",[e]);});}deleteDocumentByPath(e){let t=this.getDocumentIdByPath(e);return t===null?false:(this.cleanupDocumentData(t),true)}};var P=class{async parse(e){try{let t=await U.readFile(e,"utf-8"),r=B.extname(e).toLowerCase(),n=this.parseMarkdown(t);return {content:n.content,metadata:n.metadata}}catch(t){throw new R(`\u6587\u6863\u89E3\u6790\u5931\u8D25: ${t.message}`,"DOCUMENT_PARSE_FAILED",t)}}parseMarkdown(e){let{frontmatter:t,content:r}=utils.Markdown.extractFrontmatter(e),n={};t.title!==void 0&&(n.title=String(t.title)),t.author!==void 0&&(n.author=String(t.author)),t.date!==void 0&&(n.date=String(t.date));for(let[s,i]of Object.entries(t))["title","author","date"].includes(s)||(n[s]=i);return {content:utils.Markdown.format(r),metadata:n}}static computeHash(e){return crypto.createHash("sha256").update(e,"utf-8").digest("hex")}};var M=chunkHGWZVGLR_cjs.c.create({service:"note.tokenizer"}),x=false,fe=utils.loadTextFile("./assets/jieba_dict.txt",chunkHGWZVGLR_cjs.b);async function it(E){if(!x)try{M.info("Initializing jieba tokenizer");let e=fe();if(v__namespace.with_dict(e),M.info("Built-in dictionary loaded"),E?.dictPath&&E.dictPath.length>0)for(let t of E.dictPath)await ye(t);x=!0,M.info("Jieba tokenizer initialized");}catch(e){throw M.error("Failed to initialize jieba tokenizer",{error:String(e)}),e}}async function ye(E){if(!x)throw new Error("Tokenizer not initialized");try{let e=await utils.Filesystem.readText(E);v__namespace.with_dict(e),M.info("Custom dictionary loaded",{dictPath:E});}catch(e){M.warn("Failed to load custom dictionary",{dictPath:E,error:String(e)});}}function be(E){if(!x)return E.split(/\s+/).filter(Boolean);try{return v__namespace.cut(E)}catch(e){return M.warn("Tokenization failed, using fallback",{error:String(e)}),E.split(/\s+/).filter(Boolean)}}function Ie(E){if(!x)return E.split(/\s+/).filter(Boolean);try{return v__namespace.cut_for_search(E)}catch(e){return M.warn("Tokenization for search failed, using fallback",{error:String(e)}),E.split(/\s+/).filter(Boolean)}}function ot(E,e,t){if(x)try{v__namespace.add_word(E,e,t);}catch(r){M.warn("Failed to add word",{word:E,error:String(r)});}}function at(){return x}async function ct(){x=false,M.info("Tokenizer closed");}function ne(E){return be(E).join(" ")}function se(E){return Ie(E).join(" ")}exports.Llm=void 0;(u=>{let E=chunkHGWZVGLR_cjs.c.create({service:"note-llm"}),e=null,t=()=>{if(!e)throw new Error("Llm is not initialized. Please call Llm.init() first.");return e};function r(h){n()||(e={models:h.models,options:{graph:h.options?.graph,rerankTopN:h.options?.rerankTopN}},E.debug("Llm initialized"));}u.init=r;function n(){return e!==null}u.isInitialized=n;function o(){return e?{embedding:!!e.models.embeddingLlm,graphLlm:!!e.models.graphLlm,rerankLlm:!!e.models.rerankLlm}:{embedding:false,graphLlm:false,rerankLlm:false}}u.capabilities=o;async function s(h){let f=t().models.embeddingLlm;if(!f)throw new Error("embeddingLlm model is not configured.");let b=await ai.embed({model:f,value:h});return new Float32Array(b.embedding)}u.embedText=s;async function i(h){let f=t().models.embeddingLlm;if(!f)throw new Error("embeddingLlm model is not configured.");return (await ai.embedMany({model:f,values:h})).embeddings.map(N=>new Float32Array(N))}u.embedTexts=i;async function c(h,g){let f=t(),b=f.models.graphLlm;if(!b)return "";let N=l(h);return (await ai.streamText({model:b,prompt:N,maxOutputTokens:g?.maxOutputTokens??f.options.graph?.maxOutputTokens,temperature:g?.temperature??f.options.graph?.temperature})).text}u.generateGraph=c;async function a(h,g,f){let b=t();return b.models.rerankLlm?(await ai.rerank({model:b.models.rerankLlm,query:h,documents:g,topN:f??b.options.rerankTopN??g.length})).ranking.map(T=>({index:T.originalIndex,score:T.score??0})):[]}u.rerank=a;function l(h){let g=types.GRAPH_ENTITY_TYPE_DEFINITIONS.map(T=>`- ${T.type}: ${T.rule}`).join(`
85
85
  `),f=types.GRAPH_RELATION_TYPE_DEFINITIONS.map(T=>`- ${T.type}: ${T.rule}`).join(`
86
86
  `),N=h.slice(0,5).join(`
87
87
 
@@ -117,7 +117,7 @@ Return this exact JSON shape:
117
117
  }
118
118
 
119
119
  Input text:
120
- ${N}`}u.embed=s,u.embedMany=i;})(exports.Llm||(exports.Llm={}));var Y=chunkU3YLMQXK_cjs.c.create({service:"note-ingestion"}),ke=new Set(types.GRAPH_ENTITY_TYPE_DEFINITIONS.map(E=>E.type)),De=new Set(types.GRAPH_RELATION_TYPE_DEFINITIONS.map(E=>E.type)),Q=class{constructor(e,t){chunkU3YLMQXK_cjs.a(this,"db");chunkU3YLMQXK_cjs.a(this,"config");chunkU3YLMQXK_cjs.a(this,"parser");this.db=e,this.config={...types.DEFAULT_NOTE_CHUNK_CONFIG,...t,embeddingLlm:t.embeddingLlm},this.parser=new P,t.embeddingLlm&&exports.Llm.init({models:{embeddingLlm:t.embeddingLlm,graphLlm:t.graphLlm,rerankLlm:t.rerankLlm}});}async process(e){let t=utils.Filesystem.normalize(e),{content:r,metadata:n}=await this.parser.parse(e),o=P.computeHash(r),s=this.db.query("SELECT id, contentHash FROM documents WHERE path = ?",[t]);if(s.length>0&&s[0]?.contentHash===o){let g=this.db.query("SELECT id FROM chunks WHERE documentId = ?",[s[0].id]).flatMap(N=>{let T=this.db.query("SELECT nodeIds FROM chunks WHERE id = ?",[N.id]);return T[0]?.nodeIds?JSON.parse(T[0].nodeIds):[]}),f=new Set(g).size,b=this.db.query(`SELECT id FROM edges WHERE source IN (${Array.from({length:f},()=>"?").join(",")})`,[...new Set(g)]).length;return {documentId:s[0].id,chunksCreated:0,vectorsCreated:0,entitiesExtracted:f,relationsExtracted:b}}let i=this.chunk(r),c=await this.embedWithCache(i),a=new Map,l,d,m="",u=this.extractEntitiesSync(i);if(l=u.entities.length,d=u.relations.length,this.mapChunksToNodes(i,u.entities,a),this.storeEntities(u.entities,u.relations),this.config.graphLlm){let h=t;this.extractEntities(i).then(g=>{m=g.summary,this.mergeEntitiesAndRelations(h,g.entities,g.relations,g.summary),Y.debug("LLM entity extraction completed in background",{path:h,entities:g.entities.length,relations:g.relations.length,summary:g.summary});}).catch(g=>{Y.warn("Background graph extraction failed",{path:h,error:String(g)});});}return this.db.transaction(()=>{s.length>0&&this.db.cleanupDocumentData(s[0].id);let g=this.db.run(`INSERT INTO documents (path, title, contentHash, summary, metadata, lastModified, createdAt, updatedAt)
120
+ ${N}`}u.embed=s,u.embedMany=i;})(exports.Llm||(exports.Llm={}));var Y=chunkHGWZVGLR_cjs.c.create({service:"note-ingestion"}),ke=new Set(types.GRAPH_ENTITY_TYPE_DEFINITIONS.map(E=>E.type)),De=new Set(types.GRAPH_RELATION_TYPE_DEFINITIONS.map(E=>E.type)),Q=class{constructor(e,t){chunkHGWZVGLR_cjs.a(this,"db");chunkHGWZVGLR_cjs.a(this,"config");chunkHGWZVGLR_cjs.a(this,"parser");this.db=e,this.config={...types.DEFAULT_NOTE_CHUNK_CONFIG,...t,embeddingLlm:t.embeddingLlm},this.parser=new P,t.embeddingLlm&&exports.Llm.init({models:{embeddingLlm:t.embeddingLlm,graphLlm:t.graphLlm,rerankLlm:t.rerankLlm}});}async process(e){let t=utils.Filesystem.normalize(e),{content:r,metadata:n}=await this.parser.parse(e),o=P.computeHash(r),s=this.db.query("SELECT id, contentHash FROM documents WHERE path = ?",[t]);if(s.length>0&&s[0]?.contentHash===o){let g=this.db.query("SELECT id FROM chunks WHERE documentId = ?",[s[0].id]).flatMap(N=>{let T=this.db.query("SELECT nodeIds FROM chunks WHERE id = ?",[N.id]);return T[0]?.nodeIds?JSON.parse(T[0].nodeIds):[]}),f=new Set(g).size,b=this.db.query(`SELECT id FROM edges WHERE source IN (${Array.from({length:f},()=>"?").join(",")})`,[...new Set(g)]).length;return {documentId:s[0].id,chunksCreated:0,vectorsCreated:0,entitiesExtracted:f,relationsExtracted:b}}let i=this.chunk(r),c=await this.embedWithCache(i),a=new Map,l,d,m="",u=this.extractEntitiesSync(i);if(l=u.entities.length,d=u.relations.length,this.mapChunksToNodes(i,u.entities,a),this.storeEntities(u.entities,u.relations),this.config.graphLlm){let h=t;this.extractEntities(i).then(g=>{m=g.summary,this.mergeEntitiesAndRelations(h,g.entities,g.relations,g.summary),Y.debug("LLM entity extraction completed in background",{path:h,entities:g.entities.length,relations:g.relations.length,summary:g.summary});}).catch(g=>{Y.warn("Background graph extraction failed",{path:h,error:String(g)});});}return this.db.transaction(()=>{s.length>0&&this.db.cleanupDocumentData(s[0].id);let g=this.db.run(`INSERT INTO documents (path, title, contentHash, summary, metadata, lastModified, createdAt, updatedAt)
121
121
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,[t,n.title||B__namespace.basename(e)||"Untitled",o,typeof m=="string"&&m.length>0?m:typeof u.summary=="string"?u.summary:"",JSON.stringify(n||{}),new Date().toISOString(),new Date().toISOString(),new Date().toISOString()]).lastID,f=0,b=0;r.split(`
122
122
  `);let T=0,_=0,$=[];for(let L=0;L<i.length;L++){let p=i[L],I=p.split(`
123
123
  `).length-1;$.push({startLine:_,endLine:_+I,startChar:T,endChar:T+p.length});let S=this.config.chunkOverlap;T=T+Math.max(1,p.length-S);let w=Math.floor(S/20);_=_+Math.max(1,I-w);}for(let L=0;L<i.length;L++){let p=i[L],I=P.computeHash(p),S=a.get(L)||[],w=$[L],q=this.db.run(`INSERT INTO chunks (documentId, startLine, endLine, startChar, endChar, content, contentHash, nodeIds, createdAt)
@@ -125,4 +125,4 @@ ${N}`}u.embed=s,u.embedMany=i;})(exports.Llm||(exports.Llm={}));var Y=chunkU3YLM
125
125
 
126
126
  `);if(!this.config.graphLlm)return this.extractEntitiesByRules(t);try{let r=await exports.Llm.generateGraph(e,{maxOutputTokens:2e3}),n=this.parseEntityExtractionResult(r);return n.entities.length===0&&n.relations.length===0?this.extractEntitiesByRules(t):n}catch(r){if(r instanceof Error)return this.extractEntitiesByRules(t);throw new R(`\u5B9E\u4F53\u63D0\u53D6\u5931\u8D25: ${String(r)}`,"ENTITY_EXTRACTION_FAILED")}}extractEntitiesSync(e){let t=e.slice(0,5).join(`
127
127
 
128
- `);return this.extractEntitiesByRules(t)}parseEntityExtractionResult(e){try{let t=e.match(/\{[\s\S]*\}/);if(t){let r=JSON.parse(t[0]);return this.normalizeExtractionResult(r)}}catch(t){Y.debug("Failed to parse entity extraction result",{error:String(t)});}return {summary:"",entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,r=typeof t.summary=="string"?t.summary.trim():"",n=Array.isArray(t.entities)?t.entities:[],o=Array.isArray(t.relations)?t.relations:[],s=[],i=new Set,c=new Map;for(let d of n){let m=typeof d?.name=="string"?d.name.trim():"";if(!m)continue;let u=m.toLowerCase();if(i.has(u))continue;i.add(u),c.set(u,m);let h=typeof d?.type=="string"?d.type.trim():"",g=ke.has(h)?h:"keyword",f=d?.properties&&typeof d.properties=="object"&&!Array.isArray(d.properties)?d.properties:{};s.push({name:m,type:g,properties:f});}let a=[],l=new Set;for(let d of o){let m=typeof d?.source=="string"?d.source.trim():"",u=typeof d?.target=="string"?d.target.trim():"";if(!m||!u)continue;let h=c.get(m.toLowerCase()),g=c.get(u.toLowerCase());if(!h||!g||h===g)continue;let f=typeof d?.relation=="string"?d.relation.trim():"",b=De.has(f)?f:"related_to",N=`${h.toLowerCase()}|${g.toLowerCase()}|${b}`;l.has(N)||(l.add(N),a.push({source:h,target:g,relation:b}));}return {summary:r,entities:s,relations:a}}extractEntitiesByRules(e){let t=[],r=[],n=new Set,o=new Set,s=new Map,i=/([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 l of e.matchAll(i)){let d=this.sanitizeEntityToken(l[1]??""),m=(l[2]??"related_to").trim(),u=this.sanitizeEntityToken(l[3]??"");if(!d||!u||d===u)continue;let h=d.toLowerCase(),g=u.toLowerCase();n.has(h)||(n.add(h),s.set(h,d),t.push({name:d,type:this.inferEntityType(d),properties:{source:"rule_extracted"}})),n.has(g)||(n.add(g),s.set(g,u),t.push({name:u,type:this.inferEntityType(u),properties:{source:"rule_extracted"}}));let f=`${h}|${g}|${m}`;o.has(f)||(o.add(f),r.push({source:d,target:u,relation:m}));}let c=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[],a=e.split(/\n\s*\n/);for(let l of c){let d=this.sanitizeEntityToken(l);if(!d)continue;let m=d.toLowerCase();n.has(m)||(n.add(m),s.set(m,d),t.push({name:d,type:this.inferEntityType(d),properties:{source:"keyword_extracted"}}));}for(let l of a){if(l.trim().length<20)continue;let d=[];for(let m of l.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{2,80}/gu)??[]){let u=this.sanitizeEntityToken(m);if(!u)continue;let h=u.toLowerCase();n.has(h)&&!d.some(g=>g.key===h)&&d.push({key:h,name:u});}for(let m=0;m<d.length;m++)for(let u=m+1;u<d.length;u++){let h=d[m],g=d[u];if(h.key===g.key)continue;let f="related_to",b=this.inferEntityType(h.name),N=this.inferEntityType(g.name);b==="document"&&N==="object"?f="defines":b==="object"&&N==="document"?f="referenced_in":b==="process"&&N==="object"?f="uses":b==="object"&&N==="process"?f="used_by":b==="concept"&&(f="relates_to");let T=`${h.key}|${g.key}|${f}`;o.has(T)||(o.add(T),r.push({source:h.name,target:g.name,relation:f}));}}return {summary:"",entities:t,relations:r}}sanitizeEntityToken(e){return e.trim().replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu,"").replace(/\s+/g," ").slice(0,120)}inferEntityType(e){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)?"object":"keyword"}storeEntities(e,t){if(e.length===0)return;let r=new Map,n=new Date().toISOString();for(let o of e){let s=this.db.query("SELECT id FROM nodes WHERE name = ? AND type = ?",[o.name,o.type]);s.length>0&&s[0]&&r.set(o.name,s[0].id);}this.db.transaction(()=>{for(let o of e){if(r.has(o.name))continue;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 s=r.get(o.source),i=r.get(o.target);if(s&&i){let c=this.db.query("SELECT id FROM nodes WHERE id = ?",[s]),a=this.db.query("SELECT id FROM nodes WHERE id = ?",[i]);c.length>0&&a.length>0&&this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[s,i,o.relation,"{}",n]);}}});}mergeEntitiesAndRelations(e,t,r,n){if(t.length===0&&r.length===0&&(!n||n.trim().length===0))return;let o=new Map,s=new Date().toISOString();if(t.length>0){let i=t.map(()=>"?").join(","),c=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${i})`,t.map(a=>a.name));for(let a of c)o.set(a.name,a.id);}this.db.transaction(()=>{for(let i of t)if(o.get(i.name)===void 0){let a=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[i.name,i.type,JSON.stringify(i.properties),s,s]);a.lastID>0&&o.set(i.name,a.lastID);}for(let i of r){let c=o.get(i.source),a=o.get(i.target);if(c&&a){let l=this.db.query("SELECT id FROM nodes WHERE id = ?",[c]),d=this.db.query("SELECT id FROM nodes WHERE id = ?",[a]);l.length>0&&d.length>0&&this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[c,a,i.relation,"{}",s]);}}n&&n.trim().length>0&&(this.db.run("UPDATE documents SET summary = ?, updatedAt = ? WHERE path = ?",[n,s,e]),Y.debug("Updated document summary",{path:e,summaryLength:n.length}));});}float32ToBuffer(e){return Buffer.from(e.buffer,e.byteOffset,e.byteLength)}ensureVectorDims(e){this.db.query("SELECT value FROM meta WHERE key = ?",["vectorDims"]).length===0&&this.db.run("INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)",["vectorDims",String(e)]);}mapChunksToNodes(e,t,r){let n=new Map,o=new Date().toISOString();this.db.transaction(()=>{for(let s of t){let i=this.db.query("SELECT id FROM nodes WHERE name = ? AND type = ?",[s.name,s.type]);if(i.length>0&&i[0])n.set(s.name,i[0].id);else {let c=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[s.name,s.type,JSON.stringify(s.properties),o,o]);c.lastID>0&&n.set(s.name,c.lastID);}}for(let s=0;s<e.length;s++){let i=e[s],c=[];for(let a of t)if(i.includes(a.name)){let l=n.get(a.name);l&&c.push(l);}r.set(s,c);}});}};chunkU3YLMQXK_cjs.c.create({service:"note-search"});var V=class{constructor(e,t){chunkU3YLMQXK_cjs.a(this,"db");chunkU3YLMQXK_cjs.a(this,"config");this.db=e,this.config={...types.DEFAULT_NOTE_CHUNK_CONFIG,...t,embeddingLlm:t.embeddingLlm},t.embeddingLlm&&exports.Llm.init({models:{embeddingLlm:t.embeddingLlm,graphLlm:t.graphLlm,rerankLlm:t.rerankLlm}});}async search(e,t){if(!e.trim())return [];let r=t?.maxResults||3,n=t?.minScore??this.config.search.minScore,o=await this.hybridSearch(e,{...t,maxResults:r*2});return o.length===0?[]:this.config.rerankLlm?(await this.rerank(e,o,r)).filter(i=>i.score>=n):o.filter(s=>s.score>=n).slice(0,r)}async hybridSearch(e,t){let{maxResults:r=this.config.search.maxResults,minScore:n=this.config.search.minScore,vectorWeight:o=this.config.search.hybrid.vectorWeight,textWeight:s=this.config.search.hybrid.textWeight,enableEmbedding:i=true,enableFts:c=true}=t??{},a=i?await this.embed(e):new Float32Array(0),[l,d]=await Promise.all([i&&this.config.embeddingLlm?this.vectorSearch(a,r,n,t):Promise.resolve([]),c===false?Promise.resolve([]):this.ftsSearch(e,r,n,t)]);return this.mergeResults(l,d,o,s,n)}async vectorSearch(e,t,r,n){if(!this.config.embeddingLlm)return [];try{let o;if(n?.candidateChunkIds&&n.candidateChunkIds.length>0){let c=n.candidateChunkIds.map(()=>"?").join(",");o=this.db.query(`SELECT chunkId, embedding FROM vectors WHERE chunkId IN (${c})`,n.candidateChunkIds);}else o=this.db.query("SELECT chunkId, embedding FROM vectors LIMIT ?",[Math.max(t*100,1e3)]);let s=[];for(let c of o){let a=new Float32Array(c.embedding.buffer,c.embedding.byteOffset,c.embedding.length/4),l=this.cosineSimilarity(e,a);s.push({chunkId:c.chunkId,score:l});}s.sort((c,a)=>a.score-c.score);let i=s.slice(0,t);return this.buildSearchResults(i,"vector",n)}catch(o){throw new R(`\u5411\u91CF\u641C\u7D22\u5931\u8D25: ${o.message}`,"SEARCH_FAILED",o)}}async ftsSearch(e,t,r,n){let o=async()=>[];try{let s=se(e),i=this.db.query("SELECT chunkId, bm25(chunks_fts) as score FROM chunks_fts WHERE content MATCH ? ORDER BY score DESC LIMIT ?",[s,t]);if(i.length===0)return o();let c=i.map(a=>({chunkId:a.chunkId,score:-a.score}));return this.buildSearchResults(c,"fts",n)}catch{return o()}}mergeResults(e,t,r,n,o){let s=r+n,i=r/s,c=n/s,a=new Map;for(let m of e){let u=`${m.chunk.id}`,h=m.score*i;a.set(u,{...m,score:h,source:"hybrid"});}for(let m of t){let u=`${m.chunk.id}`,h=a.get(u);if(h)h.score+=m.score*c;else {let g=m.score*c;a.set(u,{...m,score:g,source:"hybrid"});}}return Array.from(a.values()).map(m=>{let u=m.score,h=new Date(m.document.updatedAt),g=(Date.now()-h.getTime())/864e5,f=Math.exp(-0.01*g),b=.6*u+.4*f;return {...m,score:b}}).sort((m,u)=>u.score-m.score)}async rerank(e,t,r){if(!this.config.rerankLlm)return t.slice(0,r);try{let n=t.map(a=>{let l=a.nodes&&a.nodes.length>0?a.nodes.map(d=>{let m=(d.edges??[]).map(u=>{let h=u.source===d.id?"\u2192":"\u2190",g=u.targetNode?`${u.targetNode.type}:${u.targetNode.name}`:`id=${u.target}`;return `${h} [${u.relation}] ${g}`}).join(" | ");return `node: id=${d.id} name=${d.name} type=${d.type}${m?` edges: ${m}`:""}`}).join(" | "):"";return `<doc filePath="${a.document.path}" lineStart="${a.chunk.startLine}" lineEnd="${a.chunk.endLine}"><snippet>${a.snippet}</snippet>${l?`<nodes>${l}</nodes>`:""}</doc>`}),o=await exports.Llm.rerank(e,n,t.length);if(o.length===0)return t.slice(0,r);let s=new Map;for(let a of o)a.index>=0&&a.index<t.length&&s.set(a.index,a.score);let i=.5,c=t.map((a,l)=>{let d=s.get(l)??a.score,m=i*a.score+(1-i)*d;return {...a,originalScore:a.score,score:m,source:"reranked"}});return c.sort((a,l)=>l.score-a.score),c.slice(0,r)}catch{return t.slice(0,r)}}async embed(e){try{return await exports.Llm.embed(e)}catch{return new Float32Array(this.config.vectorDims)}}cosineSimilarity(e,t){let r=0,n=0,o=0;for(let s=0;s<e.length;s++){let i=e[s],c=t[s];r+=i*c,n+=i*i,o+=c*c;}return n===0||o===0?0:r/(Math.sqrt(n)*Math.sqrt(o))}async buildSearchResults(e,t,r){let n=[],o=e.map(p=>p.chunkId);if(o.length===0)return n;let s=r?.includeEdges??true,i=Math.max(1,r?.edgesLimit??100),c=this.db.query("SELECT * FROM chunks WHERE id IN ("+o.map(()=>"?").join(", ")+")",o),a=new Map(c.map(p=>[p.id,p])),l=Array.from(new Set(c.map(p=>p.documentId))),d=l.length>0?this.db.query("SELECT * FROM documents WHERE id IN ("+l.map(()=>"?").join(", ")+")",l):[],m=new Map(d.map(p=>[p.id,p])),u=new Map,h=[];for(let p of c){let I=[];try{let S=p.nodeIds?JSON.parse(p.nodeIds):[];I=Array.isArray(S)?S.filter(w=>typeof w=="number"):[];}catch{I=[];}u.set(p.id,I),h.push(...I);}let g=Array.from(new Set(h)),f=g.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+g.map(()=>"?").join(", ")+")",g):[],b=new Map(f.map(p=>[p.id,{id:p.id,name:p.name,type:p.type,properties:p.properties?JSON.parse(p.properties):void 0,createdAt:p.createdAt,updatedAt:p.updatedAt}])),N=s&&g.length>0?this.db.query("SELECT * FROM edges WHERE source IN ("+g.map(()=>"?").join(", ")+") OR target IN ("+g.map(()=>"?").join(", ")+") ORDER BY id LIMIT ?",[...g,...g,g.length*i]):[],T=[...new Set([...g,...N.map(p=>p.target)])],_=T.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+T.map(()=>"?").join(", ")+")",T):[],$=new Map(_.map(p=>[p.id,{id:p.id,name:p.name,type:p.type,properties:p.properties?JSON.parse(p.properties):void 0,createdAt:p.createdAt,updatedAt:p.updatedAt}])),L=new Map;for(let p of N){let I={id:p.id,source:p.source,target:p.target,relation:p.relation,properties:p.properties?JSON.parse(p.properties):void 0,createdAt:p.createdAt},S=$.get(p.target);S&&(I.targetNode=S);let w=L.get(I.source)??[];w.length<i&&(w.push(I),L.set(I.source,w));let F=L.get(I.target)??[];F.length<i&&(F.push(I),L.set(I.target,F));}for(let p of e){let I=a.get(p.chunkId);if(!I)continue;let S=m.get(I.documentId);if(!S)continue;let w=u.get(I.id)??[],F=w.map(k=>b.get(k)).filter(k=>k!==void 0),q=s&&w.length>0?Array.from(new Map(w.flatMap(k=>L.get(k)??[]).map(k=>[k.id,k])).values()):[],z=new Map;for(let k of q){let te=z.get(k.source)??[];te.push(k),z.set(k.source,te);}let K=F.length>0?F.map(k=>({...k,edges:s?z.get(k.id)??[]:void 0})):[];n.push({chunk:{id:I.id,documentId:I.documentId,startLine:I.startLine,endLine:I.endLine,startChar:I.startChar,endChar:I.endChar,content:I.content,contentHash:I.contentHash,nodeIds:w,path:S.path,createdAt:I.createdAt},document:{id:S.id,path:S.path,title:S.title,contentHash:S.contentHash,summary:S.summary,lastModified:S.lastModified,createdAt:S.createdAt,updatedAt:S.updatedAt},nodes:K.length>0?K:void 0,score:p.score,snippet:I.content.slice(0,200),source:t});}return n}};var J=class{constructor(e){chunkU3YLMQXK_cjs.a(this,"db");this.db=e;}async queryNodes(e,t){try{if(typeof e=="string")return this.db.query(e,t).map(c=>this.mapNode(c));let r=[],n=[];e.ids&&e.ids.length>0&&(r.push(`id IN (${e.ids.map(()=>"?").join(",")})`),n.push(...e.ids)),e.name&&(r.push("name LIKE ?"),n.push(`%${e.name}%`)),e.type&&(r.push("type = ?"),n.push(e.type));let o="SELECT * FROM nodes";return r.length>0&&(o+=` WHERE ${r.join(" AND ")}`),o+=" ORDER BY id",e.limit&&e.limit>0&&(o+=" LIMIT ?",n.push(e.limit)),this.db.query(o,n).map(i=>this.mapNode(i))}catch(r){throw new R(`\u67E5\u8BE2\u8282\u70B9\u5931\u8D25: ${r.message}`,"SEARCH_FAILED",r)}}async queryEdges(e,t){try{if(typeof e=="string")return this.db.query(e,t).map(c=>this.mapEdge(c));let r=[],n=[];e.ids&&e.ids.length>0&&(r.push(`id IN (${e.ids.map(()=>"?").join(",")})`),n.push(...e.ids)),typeof e.source=="number"&&(r.push("source = ?"),n.push(e.source)),typeof e.target=="number"&&(r.push("target = ?"),n.push(e.target)),e.sourceOrTarget&&e.sourceOrTarget.length>0&&(r.push(`(source IN (${e.sourceOrTarget.map(()=>"?").join(", ")}) OR target IN (${e.sourceOrTarget.map(()=>"?").join(", ")}))`),n.push(...e.sourceOrTarget,...e.sourceOrTarget)),e.relation&&(r.push("relation = ?"),n.push(e.relation));let o="SELECT * FROM edges";return r.length>0&&(o+=` WHERE ${r.join(" AND ")}`),o+=" ORDER BY id",e.limit&&e.limit>0&&(o+=" LIMIT ?",n.push(e.limit)),this.db.query(o,n).map(i=>this.mapEdge(i))}catch(r){throw new R(`\u67E5\u8BE2\u8FB9\u5931\u8D25: ${r.message}`,"SEARCH_FAILED",r)}}async queryNeighbors(e,t){let r=t?.direction??"both",n=t?.relationTypes,o=t?.limit&&t.limit>0?t.limit:100,s=[],i=[];r==="incoming"?(s.push("target = ?"),i.push(e)):r==="outgoing"?(s.push("source = ?"),i.push(e)):(s.push("(source = ? OR target = ?)"),i.push(e,e)),n&&n.length>0&&(s.push(`relation IN (${n.map(()=>"?").join(",")})`),i.push(...n));let c=await this.queryEdges(`SELECT * FROM edges WHERE ${s.join(" AND ")} ORDER BY id LIMIT ?`,[...i,o]),a=Array.from(new Set(c.map(u=>u.source===e?u.target:u.source)));if(a.length===0)return {nodes:await this.queryNodes({ids:[e],limit:1}),edges:c};let l=[...new Set([e,...a])],d=await this.queryNodes({ids:l,limit:l.length}),m=new Map(d.map(u=>[u.id,u]));for(let u of c){let h=m.get(u.target);h&&(u.targetNode=h);}return {nodes:d,edges:c}}async queryCallGraph(e,t=2){let r=Math.max(1,t),n=new Map,o=[{id:e,level:0}],s=new Set;for(;o.length>0;){let i=o.shift();if(s.has(i.id)||i.level>r)continue;s.add(i.id);let c=await this.queryEdges({source:i.id,relation:"CALLS",limit:100}),a=await this.queryEdges({target:i.id,relation:"CALLS",limit:100}),l=Array.from(new Set(c.map(m=>m.target))),d=Array.from(new Set(a.map(m=>m.source)));n.set(i.id,{callers:d,callees:l});for(let m of [...d,...l])s.has(m)||o.push({id:m,level:i.level+1});}return n}async queryInheritance(e){let t=["EXTENDS","INHERITS_FROM","IMPLEMENTS"],r=await this.collectInheritance(e,"ancestor",t),n=await this.collectInheritance(e,"descendant",t);return {ancestors:r,descendants:n}}async findPath(e,t,r=3){let n=[],o=new Set,s=this.db.query("SELECT * FROM nodes WHERE name = ?",[e]);if(s.length===0)return [];let i=s.map(c=>({nodeId:c.id,path:[c.id]}));for(;i.length>0;){let{nodeId:c,path:a}=i.shift();if(a.length>r)continue;let l=a.join(",");if(o.has(l))continue;if(o.add(l),a.length>1){let m=this.db.query("SELECT id, name FROM nodes WHERE id = ?",[c]);if(m.length>0&&m[0]?.name===t){let u=a.map(()=>"?").join(","),h=this.db.query(`SELECT * FROM nodes WHERE id IN (${u})`,a),g=new Map(h.map(b=>[b.id,b])),f=[];for(let b of a){let N=g.get(b);N&&f.push({id:N.id,name:N.name,type:N.type,properties:N.properties?JSON.parse(N.properties):void 0,createdAt:N.createdAt,updatedAt:N.updatedAt});}n.push(f);continue}}let d=this.db.query("SELECT source, target FROM edges WHERE source = ? OR target = ?",[c,c]);for(let m of d){let u=m.source===c?m.target:m.source;a.includes(u)||i.push({nodeId:u,path:[...a,u]});}}return n}async searchNodesByName(e){return this.queryNodes("SELECT * FROM nodes WHERE name LIKE ?",[e])}async searchNodesByType(e){return this.queryNodes("SELECT * FROM nodes WHERE type = ?",[e])}async searchRelations(e){return this.queryEdges("SELECT * FROM edges WHERE relation = ?",[e])}async createNode(e,t,r){let n=new Date().toISOString(),o=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[e,t,r?JSON.stringify(r):null,n,n]),i=this.db.query("SELECT * FROM nodes WHERE id = ?",[o.lastID])[0];return {id:i.id,name:i.name,type:i.type,properties:i.properties?JSON.parse(i.properties):void 0,createdAt:i.createdAt,updatedAt:i.updatedAt}}async updateNode(e,t){let r=new Date().toISOString();this.db.run("UPDATE nodes SET properties = ?, updatedAt = ? WHERE id = ?",[JSON.stringify(t),r,e]);let n=this.db.query("SELECT * FROM nodes WHERE id = ?",[e]);if(n.length===0)throw new R(`\u8282\u70B9\u4E0D\u5B58\u5728: ${e}`,"NODE_NOT_FOUND");let o=n[0];return {id:o.id,name:o.name,type:o.type,properties:o.properties?JSON.parse(o.properties):void 0,createdAt:o.createdAt,updatedAt:o.updatedAt}}async deleteNode(e){this.db.run("DELETE FROM nodes WHERE id = ?",[e]);}async createEdge(e,t,r,n){let o=this.db.query("SELECT id FROM nodes WHERE id = ?",[e]),s=this.db.query("SELECT id FROM nodes WHERE id = ?",[t]);if(o.length===0||s.length===0)throw new R("\u8282\u70B9\u4E0D\u5B58\u5728","NODE_NOT_FOUND");let i=new Date().toISOString(),c=this.db.run("INSERT INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[e,t,r,n?JSON.stringify(n):null,i]),l=this.db.query("SELECT * FROM edges WHERE id = ?",[c.lastID])[0];return {id:l.id,source:l.source,target:l.target,relation:l.relation,properties:l.properties?JSON.parse(l.properties):void 0,createdAt:l.createdAt}}async deleteEdge(e){this.db.run("DELETE FROM edges WHERE id = ?",[e]);}mapNode(e){return {id:e.id,name:e.name,type:e.type,properties:e.properties?JSON.parse(e.properties):void 0,createdAt:e.createdAt,updatedAt:e.updatedAt}}mapEdge(e){return {id:e.id,source:e.source,target:e.target,relation:e.relation,properties:e.properties?JSON.parse(e.properties):void 0,createdAt:e.createdAt}}async collectInheritance(e,t,r){let n=[e],o=new Set([e]),s=new Set;for(;n.length>0;){let i=n.shift(),c=t==="ancestor"?await this.queryEdges(`SELECT * FROM edges WHERE source = ? AND relation IN (${r.map(()=>"?").join(",")})`,[i,...r]):await this.queryEdges(`SELECT * FROM edges WHERE target = ? AND relation IN (${r.map(()=>"?").join(",")})`,[i,...r]);for(let a of c){let l=t==="ancestor"?a.target:a.source;o.has(l)||(o.add(l),s.add(l),n.push(l));}}return s.size===0?[]:this.queryNodes({ids:Array.from(s),limit:s.size})}};var Z=chunkU3YLMQXK_cjs.c.create({service:"note-scanner"}),Ce=["node_modules/**",".git/**","dist/**","build/**","__pycache__/**","*.min.md"],W=class{constructor(e){chunkU3YLMQXK_cjs.a(this,"workspaceDir");chunkU3YLMQXK_cjs.a(this,"extraPaths");chunkU3YLMQXK_cjs.a(this,"sources");chunkU3YLMQXK_cjs.a(this,"ignorePatterns");this.workspaceDir=e.workspaceDir,this.extraPaths=e.extraPaths??[],this.sources=new Set(e.sources??["docs"]),this.ignorePatterns=[...Ce,...e.ignorePatterns??[]];}async scanAll(e){let t=[],r=[];for(let s of this.sources){let i=B__namespace.default.join(this.workspaceDir,s);r.push({source:s,dir:i});}for(let s of this.extraPaths){let i=B__namespace.default.isAbsolute(s)?s:B__namespace.default.join(this.workspaceDir,s);r.push({source:"local",dir:i});}let n=0,o=r.length;for(let s of r){let i=await this.scanDirectory(s.dir,s.source);t.push(...i),n++,e?.(n,o,i[0]||{absolutePath:s.dir,relativePath:s.dir,source:s.source,contentHash:"",lastModified:0,size:0});}return t}async scanDirectory(e,t){let r=[];try{await U__default.default.access(e);}catch{return Z.debug("Directory not found, skipping",{dir:e}),r}let n=async o=>{try{let s=await U__default.default.readdir(o,{withFileTypes:!0});for(let i of s){let c=B__namespace.default.join(o,i.name);if(!this.shouldIgnore(i.name)){if(i.isDirectory())await n(c);else if(i.isFile()&&this.isMarkdownFile(i.name)){let a=await this.getFileInfo(c,t);a&&r.push(a);}}}}catch(s){Z.warn("Failed to scan directory",{dir:o,error:String(s)});}};return await n(e),r}async scanFile(e,t="upload"){try{let r=await U__default.default.stat(e);if(!r.isFile())return null;let n=await U__default.default.readFile(e,"utf-8"),o=crypto.createHash("sha256").update(n).digest("hex"),s=utils.Filesystem.normalize(e);return {absolutePath:e,relativePath:s||B__namespace.default.basename(e),source:t,contentHash:o,lastModified:r.mtimeMs,size:r.size}}catch(r){return Z.error("Failed to scan file",{filePath:e,error:String(r)}),null}}async getFileInfo(e,t){try{let r=await U__default.default.readFile(e,"utf-8"),n=await U__default.default.stat(e),o=crypto.createHash("sha256").update(r).digest("hex"),s=utils.Filesystem.normalize(e);return {absolutePath:e,relativePath:s,source:t,contentHash:o,lastModified:n.mtimeMs,size:n.size}}catch(r){return Z.error("Failed to get file info",{filePath:e,error:String(r)}),null}}shouldIgnore(e){if(e.startsWith("."))return true;for(let t of this.ignorePatterns)if(new RegExp("^"+t.replace(/\*\*/g,".*").replace(/\*/g,"[^/]*")+"$").test(e))return true;return false}isMarkdownFile(e){return e.endsWith(".md")||e.endsWith(".markdown")}};var A=chunkU3YLMQXK_cjs.c.create({service:"note"}),ee=class{constructor(e){chunkU3YLMQXK_cjs.a(this,"config");chunkU3YLMQXK_cjs.a(this,"db");chunkU3YLMQXK_cjs.a(this,"pipeline");chunkU3YLMQXK_cjs.a(this,"searchEngine");chunkU3YLMQXK_cjs.a(this,"graphInterface");chunkU3YLMQXK_cjs.a(this,"fileScanner");chunkU3YLMQXK_cjs.a(this,"initialized",false);chunkU3YLMQXK_cjs.a(this,"dirty",false);chunkU3YLMQXK_cjs.a(this,"syncTimer");chunkU3YLMQXK_cjs.a(this,"syncConfig");chunkU3YLMQXK_cjs.a(this,"syncingInProgress",false);let t=e.workspaceDir||process.cwd(),r=e.embeddingLlm;if(!r)throw new Error("embeddingLlm is required");let n=e.database?.path||types.getDefaultDatabasePath(xdgBasedir.xdgData,"note.db");this.config={workspaceDir:t,database:{path:n,walMode:e.database?.walMode??true},vectorDims:e.vectorDims??768,...types.DEFAULT_NOTE_CHUNK_CONFIG,extraPaths:e.extraPaths,sources:e.sources,search:{...types.DEFAULT_SEARCH_CONFIG,...e.search},indexer:{...types.DEFAULT_INDEXER_CONFIG,...e.indexer},sync:{...types.DEFAULT_SYNC_CONFIG,...e.sync},logDir:e.logDir,embeddingLlm:r,graphLlm:e.graphLlm,rerankLlm:e.rerankLlm},this.syncConfig=this.config.sync,this.db=new X(this.config.database.path),this.pipeline=new Q(this.db,this.config),this.searchEngine=new V(this.db,this.config),this.graphInterface=new J(this.db),this.fileScanner=new W({workspaceDir:this.config.workspaceDir,extraPaths:this.config.extraPaths,sources:this.config.sources,ignorePatterns:this.config?.indexer?.ignorePatterns});}async initialize(){if(this.initialized)return;await chunkU3YLMQXK_cjs.c.init({logDir:this.config.logDir||B__namespace.default.join(this.config.workspaceDir,"logs"),print:process.argv.includes("--print-logs"),dev:false,level:"INFO"}),exports.Llm.init({models:{embeddingLlm:this.config.embeddingLlm,graphLlm:this.config.graphLlm,rerankLlm:this.config.rerankLlm},options:{graph:{maxOutputTokens:2e3,temperature:.1}}}),await this.db.initialize();let e=[["version","1.0.0"],["chunkSize",String(this.config.chunkSize)],["chunkOverlap",String(this.config.chunkOverlap)],["createdAt",new Date().toISOString()]];for(let[t,r]of e)this.db.run("INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)",[t,r]);this.initialized=true,this.syncConfig.onBoot&&(this.syncAll().catch(t=>A.warn("onBoot sync failed",{error:String(t)})),this.startSyncTimer()),A.debug("NoteKnowledge initialized",{workspaceDir:this.config.workspaceDir,dbPath:this.config.database.path,embeddingEnabled:!!this.config.embeddingLlm,graphLlmEnabled:!!this.config.graphLlm,rerankLlmEnabled:!!this.config.rerankLlm,chunkSize:this.config.chunkSize,chunkOverlap:this.config.chunkOverlap,sources:this.config.sources,syncOnBoot:this.syncConfig.onBoot,syncIntervalMs:this.syncConfig.intervalMs,hybridSearch:this.config.search?.hybrid?.enabled,vectorWeight:this.config.search?.hybrid?.vectorWeight,textWeight:this.config.search?.hybrid?.textWeight});}startSyncTimer(){this.syncTimer&&clearInterval(this.syncTimer),this.syncConfig.intervalMs>0&&(this.syncTimer=setInterval(async()=>{try{await this.syncAll();}catch(e){A.error("Interval sync failed",{error:String(e)});}},this.syncConfig.intervalMs));}ensureSynced(){this.dirty&&!this.syncingInProgress&&this.syncConfig.onSearch&&this.syncAll().catch(e=>{A.warn("Background sync failed",{error:String(e)});});}stopSyncTimer(){this.syncTimer&&(clearInterval(this.syncTimer),this.syncTimer=void 0);}async syncAll(){if(this.syncingInProgress){A.debug("Sync already in progress, skipping...");return}this.syncingInProgress=true,A.debug("Starting sync...");try{let e=await this.sync((t,r,n)=>{A.debug("Syncing file",{current:t,total:r,path:n.relativePath||B__namespace.default.basename(n.absolutePath)});});this.dirty=!1,A.debug("Sync completed",{totalFiles:e.filesAdded+e.filesUpdated+e.filesSkipped,added:e.filesAdded,updated:e.filesUpdated,deleted:e.filesDeleted,skipped:e.filesSkipped,errors:e.errors.length});}finally{this.syncingInProgress=false;}}async ingestDocument(e){return await this.ensureInitialized(),this.pipeline.process(e)}async ingestDocuments(e,t){await this.ensureInitialized();let r=[];for(let n=0;n<e.length;n++){let o=await this.pipeline.process(e[n]);r.push(o),t?.((n+1)/e.length);}return r}async scanAndIngest(e){for(await this.ensureInitialized();this.syncingInProgress;)await new Promise(n=>setTimeout(n,100));let t=await this.fileScanner.scanAll(e);if(t.length===0)return [];let r=t.map(n=>n.absolutePath);return this.ingestDocuments(r,n=>{e?.(Math.round(n*t.length),t.length,t[0]||{absolutePath:"ingesting...",relativePath:"ingesting...",source:"docs",contentHash:"",lastModified:0,size:0});})}async ingestUploadedFile(e){await this.ensureInitialized();let t=await this.fileScanner.scanFile(e,"upload");if(!t)throw new Error(`\u65E0\u6CD5\u626B\u63CF\u6587\u4EF6: ${e}`);return this.pipeline.process(t.absolutePath)}async removeDocument(e){await this.ensureInitialized();let t=utils.Filesystem.normalize(e);try{this.db.deleteDocumentByPath(t)&&A.debug("Removed document",{path:t});}catch(r){throw A.error("Failed to remove document",{path:t,error:String(r)}),r}}markDirty(){this.dirty=true,A.debug("Marked as dirty, will sync before next search");}async sync(e){if(await this.ensureInitialized(),this.syncingInProgress)return A.debug("Sync already in progress, skipping..."),{success:true,filesAdded:0,filesUpdated:0,filesDeleted:0,filesSkipped:0,chunksCreated:0,vectorsCreated:0,entitiesExtracted:0,relationsExtracted:0,errors:[],duration:0};this.syncingInProgress=true;try{let t=Date.now(),r={success:!0,filesAdded:0,filesUpdated:0,filesDeleted:0,filesSkipped:0,chunksCreated:0,vectorsCreated:0,entitiesExtracted:0,relationsExtracted:0,errors:[],duration:0},n=await this.fileScanner.scanAll(e),o=new Set(n.map(a=>a.relativePath)),s=this.db.query("SELECT path, contentHash FROM documents"),i=new Map;for(let a of s)i.set(a.path,a.contentHash);for(let[a]of i)if(!o.has(a))try{this.db.deleteDocumentByPath(a)&&(r.filesDeleted++,A.debug("Deleted document from index",{path:a}));}catch(l){let d=l instanceof Error?l.message:String(l);r.errors.push({filePath:a,error:`Failed to delete document: ${d}`}),A.error("Failed to delete document",{path:a,error:d});}for(let a=0;a<n.length;a++){let l=n[a],d=l.relativePath;e?.(a+1,n.length,l);try{let m=i.get(d);if(m===void 0){let u=await this.pipeline.process(l.absolutePath);r.filesAdded++,r.chunksCreated+=u.chunksCreated,r.vectorsCreated+=u.vectorsCreated,r.entitiesExtracted+=u.entitiesExtracted||0,r.relationsExtracted+=u.relationsExtracted||0,A.debug("Added new document",{path:d});}else if(m!==l.contentHash){let u=await this.pipeline.process(l.absolutePath);r.filesUpdated++,r.chunksCreated+=u.chunksCreated,r.vectorsCreated+=u.vectorsCreated,r.entitiesExtracted+=u.entitiesExtracted||0,r.relationsExtracted+=u.relationsExtracted||0,A.debug("Updated document",{path:d});}else r.filesSkipped++;}catch(m){let u=m instanceof Error?m.message:String(m);r.errors.push({filePath:d,error:u}),A.error("Failed to process document",{path:d,error:u});}}r.duration=Date.now()-t,r.success=r.errors.length===0;let c={timestamp:new Date().toISOString(),success:r.success,filesAdded:r.filesAdded,filesUpdated:r.filesUpdated,filesDeleted:r.filesDeleted,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,vectorsCreated:r.vectorsCreated,entitiesExtracted:r.entitiesExtracted,relationsExtracted:r.relationsExtracted,errorCount:r.errors.length,duration:r.duration};return this.db.setMeta("lastSync",c.timestamp),this.db.setMeta("lastSyncResult",JSON.stringify(c)),A.info("Sync completed",{added:r.filesAdded,updated:r.filesUpdated,deleted:r.filesDeleted,skipped:r.filesSkipped,errors:r.errors.length,duration:r.duration}),r}finally{this.syncingInProgress=false;}}async search(e,t){return await this.ensureInitialized(),this.ensureSynced(),this.searchEngine.search(e,t)}async queryNodes(e,t){return await this.ensureInitialized(),typeof e=="string"?this.graphInterface.queryNodes(e,t):this.graphInterface.queryNodes(e)}async queryEdges(e,t){return await this.ensureInitialized(),typeof e=="string"?this.graphInterface.queryEdges(e,t):this.graphInterface.queryEdges(e)}async findPath(e,t,r){return await this.ensureInitialized(),this.graphInterface.findPath(e,t,r)}async queryNeighbors(e,t){return await this.ensureInitialized(),this.graphInterface.queryNeighbors(e,t)}async queryCallGraph(e,t){return await this.ensureInitialized(),this.graphInterface.queryCallGraph(e,t)}async queryInheritance(e){return await this.ensureInitialized(),this.graphInterface.queryInheritance(e)}async createNode(e,t,r){return await this.ensureInitialized(),this.graphInterface.createNode(e,t,r)}async updateNode(e,t){return await this.ensureInitialized(),this.graphInterface.updateNode(e,t)}async deleteNode(e){return await this.ensureInitialized(),this.graphInterface.deleteNode(e)}async createEdge(e,t,r,n){return await this.ensureInitialized(),this.graphInterface.createEdge(e,t,r,n)}async deleteEdge(e){return await this.ensureInitialized(),this.graphInterface.deleteEdge(e)}getStatus(){let e=this.db.getPath(),t=0,r=0,n=0,o=0;try{t=this.db.getDb().prepare("SELECT COUNT(*) as count FROM documents").get()?.count||0,r=this.db.getDb().prepare("SELECT COUNT(*) as count FROM chunks").get()?.count||0,n=this.db.getDb().prepare("SELECT COUNT(*) as count FROM nodes").get()?.count||0,o=this.db.getDb().prepare("SELECT COUNT(*) as count FROM edges").get()?.count||0;}catch{}return {dbPath:e,workspaceDir:this.config.workspaceDir,documentsCount:t,chunksCount:r,nodesCount:n,edgesCount:o,embeddingLlmAvailable:!!this.config.embeddingLlm,graphLlmAvailable:!!this.config.graphLlm,rerankLlmAvailable:!!this.config.rerankLlm,healthy:this.initialized,meta:this.getMetaMap()}}getMetaMap(){let e={};try{let t=this.db.query("SELECT key, value FROM meta");for(let r of t)e[r.key]=r.value;}catch{}return e}async healthCheck(){try{return this.db.query("SELECT 1"),!0}catch{return false}}async clear(){this.db.transaction(()=>{this.db.run("DELETE FROM chunks"),this.db.run("DELETE FROM documents"),this.db.run("DELETE FROM vectors"),this.db.run("DELETE FROM nodes"),this.db.run("DELETE FROM edges"),this.db.run("DELETE FROM embedding_cache"),this.db.run("DELETE FROM sqlite_sequence WHERE name IN ('chunks', 'documents', 'nodes', 'edges')");});try{this.db.run("INSERT INTO chunks_fts(chunks_fts) VALUES('delete-all')");}catch(e){A.warn("Failed to clear FTS index",{error:String(e)});}A.info("Note knowledge base cleared");}async ensureInitialized(){this.initialized||await this.initialize();}async close(){this.initialized&&(this.stopSyncTimer(),await this.db.close(),this.initialized=false,A.info("NoteKnowledge closed"));}};async function He(E){let e=new ee(E);return await e.initialize(),e}async function ur(E){let{Log:e}=await import('./chunks/log-WNH7UHDM.cjs'),t=false;await e.init({logDir:E.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:E.print??false,dev:E.dev??t,level:E.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.FileScanner=W;exports.KnowledgeBaseError=R;exports.KnowledgeBaseErrorCode=H;exports.NoteKnowledge=ee;exports.addWord=ot;exports.closeTokenizer=ct;exports.createNoteKnowledge=He;exports.initLog=ur;exports.initTokenizer=it;exports.isInitialized=at;exports.loadCustomDict=ye;exports.toFtsTokens=ne;exports.toFtsTokensForSearch=se;exports.tokenize=be;exports.tokenizeForSearch=Ie;
128
+ `);return this.extractEntitiesByRules(t)}parseEntityExtractionResult(e){try{let t=e.match(/\{[\s\S]*\}/);if(t){let r=JSON.parse(t[0]);return this.normalizeExtractionResult(r)}}catch(t){Y.debug("Failed to parse entity extraction result",{error:String(t)});}return {summary:"",entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,r=typeof t.summary=="string"?t.summary.trim():"",n=Array.isArray(t.entities)?t.entities:[],o=Array.isArray(t.relations)?t.relations:[],s=[],i=new Set,c=new Map;for(let d of n){let m=typeof d?.name=="string"?d.name.trim():"";if(!m)continue;let u=m.toLowerCase();if(i.has(u))continue;i.add(u),c.set(u,m);let h=typeof d?.type=="string"?d.type.trim():"",g=ke.has(h)?h:"keyword",f=d?.properties&&typeof d.properties=="object"&&!Array.isArray(d.properties)?d.properties:{};s.push({name:m,type:g,properties:f});}let a=[],l=new Set;for(let d of o){let m=typeof d?.source=="string"?d.source.trim():"",u=typeof d?.target=="string"?d.target.trim():"";if(!m||!u)continue;let h=c.get(m.toLowerCase()),g=c.get(u.toLowerCase());if(!h||!g||h===g)continue;let f=typeof d?.relation=="string"?d.relation.trim():"",b=De.has(f)?f:"related_to",N=`${h.toLowerCase()}|${g.toLowerCase()}|${b}`;l.has(N)||(l.add(N),a.push({source:h,target:g,relation:b}));}return {summary:r,entities:s,relations:a}}extractEntitiesByRules(e){let t=[],r=[],n=new Set,o=new Set,s=new Map,i=/([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 l of e.matchAll(i)){let d=this.sanitizeEntityToken(l[1]??""),m=(l[2]??"related_to").trim(),u=this.sanitizeEntityToken(l[3]??"");if(!d||!u||d===u)continue;let h=d.toLowerCase(),g=u.toLowerCase();n.has(h)||(n.add(h),s.set(h,d),t.push({name:d,type:this.inferEntityType(d),properties:{source:"rule_extracted"}})),n.has(g)||(n.add(g),s.set(g,u),t.push({name:u,type:this.inferEntityType(u),properties:{source:"rule_extracted"}}));let f=`${h}|${g}|${m}`;o.has(f)||(o.add(f),r.push({source:d,target:u,relation:m}));}let c=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[],a=e.split(/\n\s*\n/);for(let l of c){let d=this.sanitizeEntityToken(l);if(!d)continue;let m=d.toLowerCase();n.has(m)||(n.add(m),s.set(m,d),t.push({name:d,type:this.inferEntityType(d),properties:{source:"keyword_extracted"}}));}for(let l of a){if(l.trim().length<20)continue;let d=[];for(let m of l.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{2,80}/gu)??[]){let u=this.sanitizeEntityToken(m);if(!u)continue;let h=u.toLowerCase();n.has(h)&&!d.some(g=>g.key===h)&&d.push({key:h,name:u});}for(let m=0;m<d.length;m++)for(let u=m+1;u<d.length;u++){let h=d[m],g=d[u];if(h.key===g.key)continue;let f="related_to",b=this.inferEntityType(h.name),N=this.inferEntityType(g.name);b==="document"&&N==="object"?f="defines":b==="object"&&N==="document"?f="referenced_in":b==="process"&&N==="object"?f="uses":b==="object"&&N==="process"?f="used_by":b==="concept"&&(f="relates_to");let T=`${h.key}|${g.key}|${f}`;o.has(T)||(o.add(T),r.push({source:h.name,target:g.name,relation:f}));}}return {summary:"",entities:t,relations:r}}sanitizeEntityToken(e){return e.trim().replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu,"").replace(/\s+/g," ").slice(0,120)}inferEntityType(e){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)?"object":"keyword"}storeEntities(e,t){if(e.length===0)return;let r=new Map,n=new Date().toISOString();for(let o of e){let s=this.db.query("SELECT id FROM nodes WHERE name = ? AND type = ?",[o.name,o.type]);s.length>0&&s[0]&&r.set(o.name,s[0].id);}this.db.transaction(()=>{for(let o of e){if(r.has(o.name))continue;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 s=r.get(o.source),i=r.get(o.target);if(s&&i){let c=this.db.query("SELECT id FROM nodes WHERE id = ?",[s]),a=this.db.query("SELECT id FROM nodes WHERE id = ?",[i]);c.length>0&&a.length>0&&this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[s,i,o.relation,"{}",n]);}}});}mergeEntitiesAndRelations(e,t,r,n){if(t.length===0&&r.length===0&&(!n||n.trim().length===0))return;let o=new Map,s=new Date().toISOString();if(t.length>0){let i=t.map(()=>"?").join(","),c=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${i})`,t.map(a=>a.name));for(let a of c)o.set(a.name,a.id);}this.db.transaction(()=>{for(let i of t)if(o.get(i.name)===void 0){let a=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[i.name,i.type,JSON.stringify(i.properties),s,s]);a.lastID>0&&o.set(i.name,a.lastID);}for(let i of r){let c=o.get(i.source),a=o.get(i.target);if(c&&a){let l=this.db.query("SELECT id FROM nodes WHERE id = ?",[c]),d=this.db.query("SELECT id FROM nodes WHERE id = ?",[a]);l.length>0&&d.length>0&&this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[c,a,i.relation,"{}",s]);}}n&&n.trim().length>0&&(this.db.run("UPDATE documents SET summary = ?, updatedAt = ? WHERE path = ?",[n,s,e]),Y.debug("Updated document summary",{path:e,summaryLength:n.length}));});}float32ToBuffer(e){return Buffer.from(e.buffer,e.byteOffset,e.byteLength)}ensureVectorDims(e){this.db.query("SELECT value FROM meta WHERE key = ?",["vectorDims"]).length===0&&this.db.run("INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)",["vectorDims",String(e)]);}mapChunksToNodes(e,t,r){let n=new Map,o=new Date().toISOString();this.db.transaction(()=>{for(let s of t){let i=this.db.query("SELECT id FROM nodes WHERE name = ? AND type = ?",[s.name,s.type]);if(i.length>0&&i[0])n.set(s.name,i[0].id);else {let c=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[s.name,s.type,JSON.stringify(s.properties),o,o]);c.lastID>0&&n.set(s.name,c.lastID);}}for(let s=0;s<e.length;s++){let i=e[s],c=[];for(let a of t)if(i.includes(a.name)){let l=n.get(a.name);l&&c.push(l);}r.set(s,c);}});}};chunkHGWZVGLR_cjs.c.create({service:"note-search"});var V=class{constructor(e,t){chunkHGWZVGLR_cjs.a(this,"db");chunkHGWZVGLR_cjs.a(this,"config");this.db=e,this.config={...types.DEFAULT_NOTE_CHUNK_CONFIG,...t,embeddingLlm:t.embeddingLlm},t.embeddingLlm&&exports.Llm.init({models:{embeddingLlm:t.embeddingLlm,graphLlm:t.graphLlm,rerankLlm:t.rerankLlm}});}async search(e,t){if(!e.trim())return [];let r=t?.maxResults||3,n=t?.minScore??this.config.search.minScore,o=await this.hybridSearch(e,{...t,maxResults:r*2});return o.length===0?[]:this.config.rerankLlm?(await this.rerank(e,o,r)).filter(i=>i.score>=n):o.filter(s=>s.score>=n).slice(0,r)}async hybridSearch(e,t){let{maxResults:r=this.config.search.maxResults,minScore:n=this.config.search.minScore,vectorWeight:o=this.config.search.hybrid.vectorWeight,textWeight:s=this.config.search.hybrid.textWeight,enableEmbedding:i=true,enableFts:c=true}=t??{},a=i?await this.embed(e):new Float32Array(0),[l,d]=await Promise.all([i&&this.config.embeddingLlm?this.vectorSearch(a,r,n,t):Promise.resolve([]),c===false?Promise.resolve([]):this.ftsSearch(e,r,n,t)]);return this.mergeResults(l,d,o,s,n)}async vectorSearch(e,t,r,n){if(!this.config.embeddingLlm)return [];try{let o;if(n?.candidateChunkIds&&n.candidateChunkIds.length>0){let c=n.candidateChunkIds.map(()=>"?").join(",");o=this.db.query(`SELECT chunkId, embedding FROM vectors WHERE chunkId IN (${c})`,n.candidateChunkIds);}else o=this.db.query("SELECT chunkId, embedding FROM vectors LIMIT ?",[Math.max(t*100,1e3)]);let s=[];for(let c of o){let a=new Float32Array(c.embedding.buffer,c.embedding.byteOffset,c.embedding.length/4),l=this.cosineSimilarity(e,a);s.push({chunkId:c.chunkId,score:l});}s.sort((c,a)=>a.score-c.score);let i=s.slice(0,t);return this.buildSearchResults(i,"vector",n)}catch(o){throw new R(`\u5411\u91CF\u641C\u7D22\u5931\u8D25: ${o.message}`,"SEARCH_FAILED",o)}}async ftsSearch(e,t,r,n){let o=async()=>[];try{let s=se(e),i=this.db.query("SELECT chunkId, bm25(chunks_fts) as score FROM chunks_fts WHERE content MATCH ? ORDER BY score DESC LIMIT ?",[s,t]);if(i.length===0)return o();let c=i.map(a=>({chunkId:a.chunkId,score:-a.score}));return this.buildSearchResults(c,"fts",n)}catch{return o()}}mergeResults(e,t,r,n,o){let s=r+n,i=r/s,c=n/s,a=new Map;for(let m of e){let u=`${m.chunk.id}`,h=m.score*i;a.set(u,{...m,score:h,source:"hybrid"});}for(let m of t){let u=`${m.chunk.id}`,h=a.get(u);if(h)h.score+=m.score*c;else {let g=m.score*c;a.set(u,{...m,score:g,source:"hybrid"});}}return Array.from(a.values()).map(m=>{let u=m.score,h=new Date(m.document.updatedAt),g=(Date.now()-h.getTime())/864e5,f=Math.exp(-0.01*g),b=.6*u+.4*f;return {...m,score:b}}).sort((m,u)=>u.score-m.score)}async rerank(e,t,r){if(!this.config.rerankLlm)return t.slice(0,r);try{let n=t.map(a=>{let l=a.nodes&&a.nodes.length>0?a.nodes.map(d=>{let m=(d.edges??[]).map(u=>{let h=u.source===d.id?"\u2192":"\u2190",g=u.targetNode?`${u.targetNode.type}:${u.targetNode.name}`:`id=${u.target}`;return `${h} [${u.relation}] ${g}`}).join(" | ");return `node: id=${d.id} name=${d.name} type=${d.type}${m?` edges: ${m}`:""}`}).join(" | "):"";return `<doc filePath="${a.document.path}" lineStart="${a.chunk.startLine}" lineEnd="${a.chunk.endLine}"><snippet>${a.snippet}</snippet>${l?`<nodes>${l}</nodes>`:""}</doc>`}),o=await exports.Llm.rerank(e,n,t.length);if(o.length===0)return t.slice(0,r);let s=new Map;for(let a of o)a.index>=0&&a.index<t.length&&s.set(a.index,a.score);let i=.5,c=t.map((a,l)=>{let d=s.get(l)??a.score,m=i*a.score+(1-i)*d;return {...a,originalScore:a.score,score:m,source:"reranked"}});return c.sort((a,l)=>l.score-a.score),c.slice(0,r)}catch{return t.slice(0,r)}}async embed(e){try{return await exports.Llm.embed(e)}catch{return new Float32Array(this.config.vectorDims)}}cosineSimilarity(e,t){let r=0,n=0,o=0;for(let s=0;s<e.length;s++){let i=e[s],c=t[s];r+=i*c,n+=i*i,o+=c*c;}return n===0||o===0?0:r/(Math.sqrt(n)*Math.sqrt(o))}async buildSearchResults(e,t,r){let n=[],o=e.map(p=>p.chunkId);if(o.length===0)return n;let s=r?.includeEdges??true,i=Math.max(1,r?.edgesLimit??100),c=this.db.query("SELECT * FROM chunks WHERE id IN ("+o.map(()=>"?").join(", ")+")",o),a=new Map(c.map(p=>[p.id,p])),l=Array.from(new Set(c.map(p=>p.documentId))),d=l.length>0?this.db.query("SELECT * FROM documents WHERE id IN ("+l.map(()=>"?").join(", ")+")",l):[],m=new Map(d.map(p=>[p.id,p])),u=new Map,h=[];for(let p of c){let I=[];try{let S=p.nodeIds?JSON.parse(p.nodeIds):[];I=Array.isArray(S)?S.filter(w=>typeof w=="number"):[];}catch{I=[];}u.set(p.id,I),h.push(...I);}let g=Array.from(new Set(h)),f=g.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+g.map(()=>"?").join(", ")+")",g):[],b=new Map(f.map(p=>[p.id,{id:p.id,name:p.name,type:p.type,properties:p.properties?JSON.parse(p.properties):void 0,createdAt:p.createdAt,updatedAt:p.updatedAt}])),N=s&&g.length>0?this.db.query("SELECT * FROM edges WHERE source IN ("+g.map(()=>"?").join(", ")+") OR target IN ("+g.map(()=>"?").join(", ")+") ORDER BY id LIMIT ?",[...g,...g,g.length*i]):[],T=[...new Set([...g,...N.map(p=>p.target)])],_=T.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+T.map(()=>"?").join(", ")+")",T):[],$=new Map(_.map(p=>[p.id,{id:p.id,name:p.name,type:p.type,properties:p.properties?JSON.parse(p.properties):void 0,createdAt:p.createdAt,updatedAt:p.updatedAt}])),L=new Map;for(let p of N){let I={id:p.id,source:p.source,target:p.target,relation:p.relation,properties:p.properties?JSON.parse(p.properties):void 0,createdAt:p.createdAt},S=$.get(p.target);S&&(I.targetNode=S);let w=L.get(I.source)??[];w.length<i&&(w.push(I),L.set(I.source,w));let F=L.get(I.target)??[];F.length<i&&(F.push(I),L.set(I.target,F));}for(let p of e){let I=a.get(p.chunkId);if(!I)continue;let S=m.get(I.documentId);if(!S)continue;let w=u.get(I.id)??[],F=w.map(k=>b.get(k)).filter(k=>k!==void 0),q=s&&w.length>0?Array.from(new Map(w.flatMap(k=>L.get(k)??[]).map(k=>[k.id,k])).values()):[],z=new Map;for(let k of q){let te=z.get(k.source)??[];te.push(k),z.set(k.source,te);}let K=F.length>0?F.map(k=>({...k,edges:s?z.get(k.id)??[]:void 0})):[];n.push({chunk:{id:I.id,documentId:I.documentId,startLine:I.startLine,endLine:I.endLine,startChar:I.startChar,endChar:I.endChar,content:I.content,contentHash:I.contentHash,nodeIds:w,path:S.path,createdAt:I.createdAt},document:{id:S.id,path:S.path,title:S.title,contentHash:S.contentHash,summary:S.summary,lastModified:S.lastModified,createdAt:S.createdAt,updatedAt:S.updatedAt},nodes:K.length>0?K:void 0,score:p.score,snippet:I.content.slice(0,200),source:t});}return n}};var J=class{constructor(e){chunkHGWZVGLR_cjs.a(this,"db");this.db=e;}async queryNodes(e,t){try{if(typeof e=="string")return this.db.query(e,t).map(c=>this.mapNode(c));let r=[],n=[];e.ids&&e.ids.length>0&&(r.push(`id IN (${e.ids.map(()=>"?").join(",")})`),n.push(...e.ids)),e.name&&(r.push("name LIKE ?"),n.push(`%${e.name}%`)),e.type&&(r.push("type = ?"),n.push(e.type));let o="SELECT * FROM nodes";return r.length>0&&(o+=` WHERE ${r.join(" AND ")}`),o+=" ORDER BY id",e.limit&&e.limit>0&&(o+=" LIMIT ?",n.push(e.limit)),this.db.query(o,n).map(i=>this.mapNode(i))}catch(r){throw new R(`\u67E5\u8BE2\u8282\u70B9\u5931\u8D25: ${r.message}`,"SEARCH_FAILED",r)}}async queryEdges(e,t){try{if(typeof e=="string")return this.db.query(e,t).map(c=>this.mapEdge(c));let r=[],n=[];e.ids&&e.ids.length>0&&(r.push(`id IN (${e.ids.map(()=>"?").join(",")})`),n.push(...e.ids)),typeof e.source=="number"&&(r.push("source = ?"),n.push(e.source)),typeof e.target=="number"&&(r.push("target = ?"),n.push(e.target)),e.sourceOrTarget&&e.sourceOrTarget.length>0&&(r.push(`(source IN (${e.sourceOrTarget.map(()=>"?").join(", ")}) OR target IN (${e.sourceOrTarget.map(()=>"?").join(", ")}))`),n.push(...e.sourceOrTarget,...e.sourceOrTarget)),e.relation&&(r.push("relation = ?"),n.push(e.relation));let o="SELECT * FROM edges";return r.length>0&&(o+=` WHERE ${r.join(" AND ")}`),o+=" ORDER BY id",e.limit&&e.limit>0&&(o+=" LIMIT ?",n.push(e.limit)),this.db.query(o,n).map(i=>this.mapEdge(i))}catch(r){throw new R(`\u67E5\u8BE2\u8FB9\u5931\u8D25: ${r.message}`,"SEARCH_FAILED",r)}}async queryNeighbors(e,t){let r=t?.direction??"both",n=t?.relationTypes,o=t?.limit&&t.limit>0?t.limit:100,s=[],i=[];r==="incoming"?(s.push("target = ?"),i.push(e)):r==="outgoing"?(s.push("source = ?"),i.push(e)):(s.push("(source = ? OR target = ?)"),i.push(e,e)),n&&n.length>0&&(s.push(`relation IN (${n.map(()=>"?").join(",")})`),i.push(...n));let c=await this.queryEdges(`SELECT * FROM edges WHERE ${s.join(" AND ")} ORDER BY id LIMIT ?`,[...i,o]),a=Array.from(new Set(c.map(u=>u.source===e?u.target:u.source)));if(a.length===0)return {nodes:await this.queryNodes({ids:[e],limit:1}),edges:c};let l=[...new Set([e,...a])],d=await this.queryNodes({ids:l,limit:l.length}),m=new Map(d.map(u=>[u.id,u]));for(let u of c){let h=m.get(u.target);h&&(u.targetNode=h);}return {nodes:d,edges:c}}async queryCallGraph(e,t=2){let r=Math.max(1,t),n=new Map,o=[{id:e,level:0}],s=new Set;for(;o.length>0;){let i=o.shift();if(s.has(i.id)||i.level>r)continue;s.add(i.id);let c=await this.queryEdges({source:i.id,relation:"CALLS",limit:100}),a=await this.queryEdges({target:i.id,relation:"CALLS",limit:100}),l=Array.from(new Set(c.map(m=>m.target))),d=Array.from(new Set(a.map(m=>m.source)));n.set(i.id,{callers:d,callees:l});for(let m of [...d,...l])s.has(m)||o.push({id:m,level:i.level+1});}return n}async queryInheritance(e){let t=["EXTENDS","INHERITS_FROM","IMPLEMENTS"],r=await this.collectInheritance(e,"ancestor",t),n=await this.collectInheritance(e,"descendant",t);return {ancestors:r,descendants:n}}async findPath(e,t,r=3){let n=[],o=new Set,s=this.db.query("SELECT * FROM nodes WHERE name = ?",[e]);if(s.length===0)return [];let i=s.map(c=>({nodeId:c.id,path:[c.id]}));for(;i.length>0;){let{nodeId:c,path:a}=i.shift();if(a.length>r)continue;let l=a.join(",");if(o.has(l))continue;if(o.add(l),a.length>1){let m=this.db.query("SELECT id, name FROM nodes WHERE id = ?",[c]);if(m.length>0&&m[0]?.name===t){let u=a.map(()=>"?").join(","),h=this.db.query(`SELECT * FROM nodes WHERE id IN (${u})`,a),g=new Map(h.map(b=>[b.id,b])),f=[];for(let b of a){let N=g.get(b);N&&f.push({id:N.id,name:N.name,type:N.type,properties:N.properties?JSON.parse(N.properties):void 0,createdAt:N.createdAt,updatedAt:N.updatedAt});}n.push(f);continue}}let d=this.db.query("SELECT source, target FROM edges WHERE source = ? OR target = ?",[c,c]);for(let m of d){let u=m.source===c?m.target:m.source;a.includes(u)||i.push({nodeId:u,path:[...a,u]});}}return n}async searchNodesByName(e){return this.queryNodes("SELECT * FROM nodes WHERE name LIKE ?",[e])}async searchNodesByType(e){return this.queryNodes("SELECT * FROM nodes WHERE type = ?",[e])}async searchRelations(e){return this.queryEdges("SELECT * FROM edges WHERE relation = ?",[e])}async createNode(e,t,r){let n=new Date().toISOString(),o=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[e,t,r?JSON.stringify(r):null,n,n]),i=this.db.query("SELECT * FROM nodes WHERE id = ?",[o.lastID])[0];return {id:i.id,name:i.name,type:i.type,properties:i.properties?JSON.parse(i.properties):void 0,createdAt:i.createdAt,updatedAt:i.updatedAt}}async updateNode(e,t){let r=new Date().toISOString();this.db.run("UPDATE nodes SET properties = ?, updatedAt = ? WHERE id = ?",[JSON.stringify(t),r,e]);let n=this.db.query("SELECT * FROM nodes WHERE id = ?",[e]);if(n.length===0)throw new R(`\u8282\u70B9\u4E0D\u5B58\u5728: ${e}`,"NODE_NOT_FOUND");let o=n[0];return {id:o.id,name:o.name,type:o.type,properties:o.properties?JSON.parse(o.properties):void 0,createdAt:o.createdAt,updatedAt:o.updatedAt}}async deleteNode(e){this.db.run("DELETE FROM nodes WHERE id = ?",[e]);}async createEdge(e,t,r,n){let o=this.db.query("SELECT id FROM nodes WHERE id = ?",[e]),s=this.db.query("SELECT id FROM nodes WHERE id = ?",[t]);if(o.length===0||s.length===0)throw new R("\u8282\u70B9\u4E0D\u5B58\u5728","NODE_NOT_FOUND");let i=new Date().toISOString(),c=this.db.run("INSERT INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[e,t,r,n?JSON.stringify(n):null,i]),l=this.db.query("SELECT * FROM edges WHERE id = ?",[c.lastID])[0];return {id:l.id,source:l.source,target:l.target,relation:l.relation,properties:l.properties?JSON.parse(l.properties):void 0,createdAt:l.createdAt}}async deleteEdge(e){this.db.run("DELETE FROM edges WHERE id = ?",[e]);}mapNode(e){return {id:e.id,name:e.name,type:e.type,properties:e.properties?JSON.parse(e.properties):void 0,createdAt:e.createdAt,updatedAt:e.updatedAt}}mapEdge(e){return {id:e.id,source:e.source,target:e.target,relation:e.relation,properties:e.properties?JSON.parse(e.properties):void 0,createdAt:e.createdAt}}async collectInheritance(e,t,r){let n=[e],o=new Set([e]),s=new Set;for(;n.length>0;){let i=n.shift(),c=t==="ancestor"?await this.queryEdges(`SELECT * FROM edges WHERE source = ? AND relation IN (${r.map(()=>"?").join(",")})`,[i,...r]):await this.queryEdges(`SELECT * FROM edges WHERE target = ? AND relation IN (${r.map(()=>"?").join(",")})`,[i,...r]);for(let a of c){let l=t==="ancestor"?a.target:a.source;o.has(l)||(o.add(l),s.add(l),n.push(l));}}return s.size===0?[]:this.queryNodes({ids:Array.from(s),limit:s.size})}};var Z=chunkHGWZVGLR_cjs.c.create({service:"note-scanner"}),Ce=["node_modules/**",".git/**","dist/**","build/**","__pycache__/**","*.min.md"],W=class{constructor(e){chunkHGWZVGLR_cjs.a(this,"workspaceDir");chunkHGWZVGLR_cjs.a(this,"extraPaths");chunkHGWZVGLR_cjs.a(this,"sources");chunkHGWZVGLR_cjs.a(this,"ignorePatterns");this.workspaceDir=e.workspaceDir,this.extraPaths=e.extraPaths??[],this.sources=new Set(e.sources??["docs"]),this.ignorePatterns=[...Ce,...e.ignorePatterns??[]];}async scanAll(e){let t=[],r=[];for(let s of this.sources){let i=B__namespace.default.join(this.workspaceDir,s);r.push({source:s,dir:i});}for(let s of this.extraPaths){let i=B__namespace.default.isAbsolute(s)?s:B__namespace.default.join(this.workspaceDir,s);r.push({source:"local",dir:i});}let n=0,o=r.length;for(let s of r){let i=await this.scanDirectory(s.dir,s.source);t.push(...i),n++,e?.(n,o,i[0]||{absolutePath:s.dir,relativePath:s.dir,source:s.source,contentHash:"",lastModified:0,size:0});}return t}async scanDirectory(e,t){let r=[];try{await U__default.default.access(e);}catch{return Z.debug("Directory not found, skipping",{dir:e}),r}let n=async o=>{try{let s=await U__default.default.readdir(o,{withFileTypes:!0});for(let i of s){let c=B__namespace.default.join(o,i.name);if(!this.shouldIgnore(i.name)){if(i.isDirectory())await n(c);else if(i.isFile()&&this.isMarkdownFile(i.name)){let a=await this.getFileInfo(c,t);a&&r.push(a);}}}}catch(s){Z.warn("Failed to scan directory",{dir:o,error:String(s)});}};return await n(e),r}async scanFile(e,t="upload"){try{let r=await U__default.default.stat(e);if(!r.isFile())return null;let n=await U__default.default.readFile(e,"utf-8"),o=crypto.createHash("sha256").update(n).digest("hex"),s=utils.Filesystem.normalize(e);return {absolutePath:e,relativePath:s||B__namespace.default.basename(e),source:t,contentHash:o,lastModified:r.mtimeMs,size:r.size}}catch(r){return Z.error("Failed to scan file",{filePath:e,error:String(r)}),null}}async getFileInfo(e,t){try{let r=await U__default.default.readFile(e,"utf-8"),n=await U__default.default.stat(e),o=crypto.createHash("sha256").update(r).digest("hex"),s=utils.Filesystem.normalize(e);return {absolutePath:e,relativePath:s,source:t,contentHash:o,lastModified:n.mtimeMs,size:n.size}}catch(r){return Z.error("Failed to get file info",{filePath:e,error:String(r)}),null}}shouldIgnore(e){if(e.startsWith("."))return true;for(let t of this.ignorePatterns)if(new RegExp("^"+t.replace(/\*\*/g,".*").replace(/\*/g,"[^/]*")+"$").test(e))return true;return false}isMarkdownFile(e){return e.endsWith(".md")||e.endsWith(".markdown")}};var A=chunkHGWZVGLR_cjs.c.create({service:"note"}),ee=class{constructor(e){chunkHGWZVGLR_cjs.a(this,"config");chunkHGWZVGLR_cjs.a(this,"db");chunkHGWZVGLR_cjs.a(this,"pipeline");chunkHGWZVGLR_cjs.a(this,"searchEngine");chunkHGWZVGLR_cjs.a(this,"graphInterface");chunkHGWZVGLR_cjs.a(this,"fileScanner");chunkHGWZVGLR_cjs.a(this,"initialized",false);chunkHGWZVGLR_cjs.a(this,"dirty",false);chunkHGWZVGLR_cjs.a(this,"syncTimer");chunkHGWZVGLR_cjs.a(this,"syncConfig");chunkHGWZVGLR_cjs.a(this,"syncingInProgress",false);let t=e.workspaceDir||process.cwd(),r=e.embeddingLlm;if(!r)throw new Error("embeddingLlm is required");let n=e.database?.path||types.getDefaultDatabasePath(xdgBasedir.xdgData,"note.db");this.config={workspaceDir:t,database:{path:n,walMode:e.database?.walMode??true},vectorDims:e.vectorDims??768,...types.DEFAULT_NOTE_CHUNK_CONFIG,extraPaths:e.extraPaths,sources:e.sources,search:{...types.DEFAULT_SEARCH_CONFIG,...e.search},indexer:{...types.DEFAULT_INDEXER_CONFIG,...e.indexer},sync:{...types.DEFAULT_SYNC_CONFIG,...e.sync},logDir:e.logDir,embeddingLlm:r,graphLlm:e.graphLlm,rerankLlm:e.rerankLlm},this.syncConfig=this.config.sync,this.db=new X(this.config.database.path),this.pipeline=new Q(this.db,this.config),this.searchEngine=new V(this.db,this.config),this.graphInterface=new J(this.db),this.fileScanner=new W({workspaceDir:this.config.workspaceDir,extraPaths:this.config.extraPaths,sources:this.config.sources,ignorePatterns:this.config?.indexer?.ignorePatterns});}async initialize(){if(this.initialized)return;await chunkHGWZVGLR_cjs.c.init({logDir:this.config.logDir||B__namespace.default.join(this.config.workspaceDir,"logs"),print:process.argv.includes("--print-logs"),dev:false,level:"INFO"}),exports.Llm.init({models:{embeddingLlm:this.config.embeddingLlm,graphLlm:this.config.graphLlm,rerankLlm:this.config.rerankLlm},options:{graph:{maxOutputTokens:2e3,temperature:.1}}}),await this.db.initialize();let e=[["version","1.0.0"],["chunkSize",String(this.config.chunkSize)],["chunkOverlap",String(this.config.chunkOverlap)],["createdAt",new Date().toISOString()]];for(let[t,r]of e)this.db.run("INSERT OR IGNORE INTO meta (key, value) VALUES (?, ?)",[t,r]);this.initialized=true,this.syncConfig.onBoot&&(this.syncAll().catch(t=>A.warn("onBoot sync failed",{error:String(t)})),this.startSyncTimer()),A.debug("NoteKnowledge initialized",{workspaceDir:this.config.workspaceDir,dbPath:this.config.database.path,embeddingEnabled:!!this.config.embeddingLlm,graphLlmEnabled:!!this.config.graphLlm,rerankLlmEnabled:!!this.config.rerankLlm,chunkSize:this.config.chunkSize,chunkOverlap:this.config.chunkOverlap,sources:this.config.sources,syncOnBoot:this.syncConfig.onBoot,syncIntervalMs:this.syncConfig.intervalMs,hybridSearch:this.config.search?.hybrid?.enabled,vectorWeight:this.config.search?.hybrid?.vectorWeight,textWeight:this.config.search?.hybrid?.textWeight});}startSyncTimer(){this.syncTimer&&clearInterval(this.syncTimer),this.syncConfig.intervalMs>0&&(this.syncTimer=setInterval(async()=>{try{await this.syncAll();}catch(e){A.error("Interval sync failed",{error:String(e)});}},this.syncConfig.intervalMs));}ensureSynced(){this.dirty&&!this.syncingInProgress&&this.syncConfig.onSearch&&this.syncAll().catch(e=>{A.warn("Background sync failed",{error:String(e)});});}stopSyncTimer(){this.syncTimer&&(clearInterval(this.syncTimer),this.syncTimer=void 0);}async syncAll(){if(this.syncingInProgress){A.debug("Sync already in progress, skipping...");return}this.syncingInProgress=true,A.debug("Starting sync...");try{let e=await this.sync((t,r,n)=>{A.debug("Syncing file",{current:t,total:r,path:n.relativePath||B__namespace.default.basename(n.absolutePath)});});this.dirty=!1,A.debug("Sync completed",{totalFiles:e.filesAdded+e.filesUpdated+e.filesSkipped,added:e.filesAdded,updated:e.filesUpdated,deleted:e.filesDeleted,skipped:e.filesSkipped,errors:e.errors.length});}finally{this.syncingInProgress=false;}}async ingestDocument(e){return await this.ensureInitialized(),this.pipeline.process(e)}async ingestDocuments(e,t){await this.ensureInitialized();let r=[];for(let n=0;n<e.length;n++){let o=await this.pipeline.process(e[n]);r.push(o),t?.((n+1)/e.length);}return r}async scanAndIngest(e){for(await this.ensureInitialized();this.syncingInProgress;)await new Promise(n=>setTimeout(n,100));let t=await this.fileScanner.scanAll(e);if(t.length===0)return [];let r=t.map(n=>n.absolutePath);return this.ingestDocuments(r,n=>{e?.(Math.round(n*t.length),t.length,t[0]||{absolutePath:"ingesting...",relativePath:"ingesting...",source:"docs",contentHash:"",lastModified:0,size:0});})}async ingestUploadedFile(e){await this.ensureInitialized();let t=await this.fileScanner.scanFile(e,"upload");if(!t)throw new Error(`\u65E0\u6CD5\u626B\u63CF\u6587\u4EF6: ${e}`);return this.pipeline.process(t.absolutePath)}async removeDocument(e){await this.ensureInitialized();let t=utils.Filesystem.normalize(e);try{this.db.deleteDocumentByPath(t)&&A.debug("Removed document",{path:t});}catch(r){throw A.error("Failed to remove document",{path:t,error:String(r)}),r}}markDirty(){this.dirty=true,A.debug("Marked as dirty, will sync before next search");}async sync(e){if(await this.ensureInitialized(),this.syncingInProgress)return A.debug("Sync already in progress, skipping..."),{success:true,filesAdded:0,filesUpdated:0,filesDeleted:0,filesSkipped:0,chunksCreated:0,vectorsCreated:0,entitiesExtracted:0,relationsExtracted:0,errors:[],duration:0};this.syncingInProgress=true;try{let t=Date.now(),r={success:!0,filesAdded:0,filesUpdated:0,filesDeleted:0,filesSkipped:0,chunksCreated:0,vectorsCreated:0,entitiesExtracted:0,relationsExtracted:0,errors:[],duration:0},n=await this.fileScanner.scanAll(e),o=new Set(n.map(a=>a.relativePath)),s=this.db.query("SELECT path, contentHash FROM documents"),i=new Map;for(let a of s)i.set(a.path,a.contentHash);for(let[a]of i)if(!o.has(a))try{this.db.deleteDocumentByPath(a)&&(r.filesDeleted++,A.debug("Deleted document from index",{path:a}));}catch(l){let d=l instanceof Error?l.message:String(l);r.errors.push({filePath:a,error:`Failed to delete document: ${d}`}),A.error("Failed to delete document",{path:a,error:d});}for(let a=0;a<n.length;a++){let l=n[a],d=l.relativePath;e?.(a+1,n.length,l);try{let m=i.get(d);if(m===void 0){let u=await this.pipeline.process(l.absolutePath);r.filesAdded++,r.chunksCreated+=u.chunksCreated,r.vectorsCreated+=u.vectorsCreated,r.entitiesExtracted+=u.entitiesExtracted||0,r.relationsExtracted+=u.relationsExtracted||0,A.debug("Added new document",{path:d});}else if(m!==l.contentHash){let u=await this.pipeline.process(l.absolutePath);r.filesUpdated++,r.chunksCreated+=u.chunksCreated,r.vectorsCreated+=u.vectorsCreated,r.entitiesExtracted+=u.entitiesExtracted||0,r.relationsExtracted+=u.relationsExtracted||0,A.debug("Updated document",{path:d});}else r.filesSkipped++;}catch(m){let u=m instanceof Error?m.message:String(m);r.errors.push({filePath:d,error:u}),A.error("Failed to process document",{path:d,error:u});}}r.duration=Date.now()-t,r.success=r.errors.length===0;let c={timestamp:new Date().toISOString(),success:r.success,filesAdded:r.filesAdded,filesUpdated:r.filesUpdated,filesDeleted:r.filesDeleted,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,vectorsCreated:r.vectorsCreated,entitiesExtracted:r.entitiesExtracted,relationsExtracted:r.relationsExtracted,errorCount:r.errors.length,duration:r.duration};return this.db.setMeta("lastSync",c.timestamp),this.db.setMeta("lastSyncResult",JSON.stringify(c)),A.info("Sync completed",{added:r.filesAdded,updated:r.filesUpdated,deleted:r.filesDeleted,skipped:r.filesSkipped,errors:r.errors.length,duration:r.duration}),r}finally{this.syncingInProgress=false;}}async search(e,t){return await this.ensureInitialized(),this.ensureSynced(),this.searchEngine.search(e,t)}async queryNodes(e,t){return await this.ensureInitialized(),typeof e=="string"?this.graphInterface.queryNodes(e,t):this.graphInterface.queryNodes(e)}async queryEdges(e,t){return await this.ensureInitialized(),typeof e=="string"?this.graphInterface.queryEdges(e,t):this.graphInterface.queryEdges(e)}async findPath(e,t,r){return await this.ensureInitialized(),this.graphInterface.findPath(e,t,r)}async queryNeighbors(e,t){return await this.ensureInitialized(),this.graphInterface.queryNeighbors(e,t)}async queryCallGraph(e,t){return await this.ensureInitialized(),this.graphInterface.queryCallGraph(e,t)}async queryInheritance(e){return await this.ensureInitialized(),this.graphInterface.queryInheritance(e)}async createNode(e,t,r){return await this.ensureInitialized(),this.graphInterface.createNode(e,t,r)}async updateNode(e,t){return await this.ensureInitialized(),this.graphInterface.updateNode(e,t)}async deleteNode(e){return await this.ensureInitialized(),this.graphInterface.deleteNode(e)}async createEdge(e,t,r,n){return await this.ensureInitialized(),this.graphInterface.createEdge(e,t,r,n)}async deleteEdge(e){return await this.ensureInitialized(),this.graphInterface.deleteEdge(e)}getStatus(){let e=this.db.getPath(),t=0,r=0,n=0,o=0;try{t=this.db.getDb().prepare("SELECT COUNT(*) as count FROM documents").get()?.count||0,r=this.db.getDb().prepare("SELECT COUNT(*) as count FROM chunks").get()?.count||0,n=this.db.getDb().prepare("SELECT COUNT(*) as count FROM nodes").get()?.count||0,o=this.db.getDb().prepare("SELECT COUNT(*) as count FROM edges").get()?.count||0;}catch{}return {dbPath:e,workspaceDir:this.config.workspaceDir,documentsCount:t,chunksCount:r,nodesCount:n,edgesCount:o,embeddingLlmAvailable:!!this.config.embeddingLlm,graphLlmAvailable:!!this.config.graphLlm,rerankLlmAvailable:!!this.config.rerankLlm,healthy:this.initialized,meta:this.getMetaMap()}}getMetaMap(){let e={};try{let t=this.db.query("SELECT key, value FROM meta");for(let r of t)e[r.key]=r.value;}catch{}return e}async healthCheck(){try{return this.db.query("SELECT 1"),!0}catch{return false}}async clear(){this.db.transaction(()=>{this.db.run("DELETE FROM chunks"),this.db.run("DELETE FROM documents"),this.db.run("DELETE FROM vectors"),this.db.run("DELETE FROM nodes"),this.db.run("DELETE FROM edges"),this.db.run("DELETE FROM embedding_cache"),this.db.run("DELETE FROM sqlite_sequence WHERE name IN ('chunks', 'documents', 'nodes', 'edges')");});try{this.db.run("INSERT INTO chunks_fts(chunks_fts) VALUES('delete-all')");}catch(e){A.warn("Failed to clear FTS index",{error:String(e)});}A.info("Note knowledge base cleared");}async ensureInitialized(){this.initialized||await this.initialize();}async close(){this.initialized&&(this.stopSyncTimer(),await this.db.close(),this.initialized=false,A.info("NoteKnowledge closed"));}};async function He(E){let e=new ee(E);return await e.initialize(),e}async function ur(E){let{Log:e}=await import('./chunks/log-YAYNRHCI.cjs'),t=false;await e.init({logDir:E.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:E.print??false,dev:E.dev??t,level:E.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.FileScanner=W;exports.KnowledgeBaseError=R;exports.KnowledgeBaseErrorCode=H;exports.NoteKnowledge=ee;exports.addWord=ot;exports.closeTokenizer=ct;exports.createNoteKnowledge=He;exports.initLog=ur;exports.initTokenizer=it;exports.isInitialized=at;exports.loadCustomDict=ye;exports.toFtsTokens=ne;exports.toFtsTokensForSearch=se;exports.tokenize=be;exports.tokenizeForSearch=Ie;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easbot/note",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Note Knowledge Base - 非结构化记忆和文档知识库管理系统,支持混合搜索(向量+FTS+图)和 LLM 驱动的知识摄取",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -54,10 +54,10 @@
54
54
  "better-sqlite3": "^12.9.0",
55
55
  "jieba-wasm": "^2.4.0",
56
56
  "xdg-basedir": "^5.1.0",
57
- "@easbot/local-model-sdk": "0.2.4",
58
- "@easbot/ollama-sdk": "0.2.4",
59
- "@easbot/types": "0.2.4",
60
- "@easbot/utils": "0.2.4"
57
+ "@easbot/local-model-sdk": "0.2.6",
58
+ "@easbot/ollama-sdk": "0.2.6",
59
+ "@easbot/types": "0.2.6",
60
+ "@easbot/utils": "0.2.6"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@biomejs/biome": "^2.4.14",
@@ -1 +0,0 @@
1
- 'use strict';var chunkU3YLMQXK_cjs=require('./chunk-U3YLMQXK.cjs');Object.defineProperty(exports,"Log",{enumerable:true,get:function(){return chunkU3YLMQXK_cjs.c}});