@easbot/note 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +24 -22
package/dist/index.cjs
CHANGED
|
@@ -123,4 +123,4 @@ ${b}`}u.embed=s,u.embedMany=i;})(exports.Llm||(exports.Llm={}));var Z=chunkF2MSB
|
|
|
123
123
|
|
|
124
124
|
`);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(`
|
|
125
125
|
|
|
126
|
-
`);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){Z.debug("Failed to parse entity extraction result",{error:String(t)});}return {entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,r=Array.isArray(t.entities)?t.entities:[],n=Array.isArray(t.relations)?t.relations:[],o=[],s=new Set,i=new Map;for(let d of r){let l=typeof d?.name=="string"?d.name.trim():"";if(!l)continue;let g=l.toLowerCase();if(s.has(g))continue;s.add(g),i.set(g,l);let u=typeof d?.type=="string"?d.type.trim():"",m=ke.has(u)?u:"keyword",h=d?.properties&&typeof d.properties=="object"&&!Array.isArray(d.properties)?d.properties:{};o.push({name:l,type:m,properties:h});}let c=[],a=new Set;for(let d of n){let l=typeof d?.source=="string"?d.source.trim():"",g=typeof d?.target=="string"?d.target.trim():"";if(!l||!g)continue;let u=i.get(l.toLowerCase()),m=i.get(g.toLowerCase());if(!u||!m||u===m)continue;let h=typeof d?.relation=="string"?d.relation.trim():"",f=De.has(h)?h:"related_to",y=`${u.toLowerCase()}|${m.toLowerCase()}|${f}`;a.has(y)||(a.add(y),c.push({source:u,target:m,relation:f}));}return {entities:o,relations:c}}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 d of e.matchAll(i)){let l=this.sanitizeEntityToken(d[1]??""),g=(d[2]??"related_to").trim(),u=this.sanitizeEntityToken(d[3]??"");if(!l||!u||l===u)continue;let m=l.toLowerCase(),h=u.toLowerCase();n.has(m)||(n.add(m),s.set(m,l),t.push({name:l,type:this.inferEntityType(l),properties:{source:"rule_extracted"}})),n.has(h)||(n.add(h),s.set(h,u),t.push({name:u,type:this.inferEntityType(u),properties:{source:"rule_extracted"}}));let f=`${m}|${h}|${g}`;o.has(f)||(o.add(f),r.push({source:l,target:u,relation:g}));}let c=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[],a=e.split(/\n\s*\n/);for(let d of c){let l=this.sanitizeEntityToken(d);if(!l)continue;let g=l.toLowerCase();n.has(g)||(n.add(g),s.set(g,l),t.push({name:l,type:this.inferEntityType(l),properties:{source:"keyword_extracted"}}));}for(let d of a){if(d.trim().length<20)continue;let l=[];for(let g of d.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{2,80}/gu)??[]){let u=this.sanitizeEntityToken(g);if(!u)continue;let m=u.toLowerCase();n.has(m)&&!l.some(h=>h.key===m)&&l.push({key:m,name:u});}for(let g=0;g<l.length;g++)for(let u=g+1;u<l.length;u++){let m=l[g],h=l[u];if(m.key===h.key)continue;let f="related_to",y=this.inferEntityType(m.name),b=this.inferEntityType(h.name);y==="document"&&b==="object"?f="defines":y==="object"&&b==="document"?f="referenced_in":y==="process"&&b==="object"?f="uses":y==="object"&&b==="process"?f="used_by":y==="concept"&&(f="relates_to");let S=`${m.key}|${h.key}|${f}`;o.has(S)||(o.add(S),r.push({source:m.name,target:h.name,relation:f}));}}return {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){if(t.length===0&&r.length===0)return;let n=new Map,o=new Date().toISOString(),s=t.map(()=>"?").join(","),i=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${s})`,t.map(c=>c.name));for(let c of i)n.set(c.name,c.id);this.db.transaction(()=>{for(let c of t)if(n.get(c.name)===void 0){let d=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[c.name,c.type,JSON.stringify(c.properties),o,o]);d.lastID>0&&n.set(c.name,d.lastID);}for(let c of r){let a=n.get(c.source),d=n.get(c.target);if(a&&d){let l=this.db.query("SELECT id FROM nodes WHERE id = ?",[a]),g=this.db.query("SELECT id FROM nodes WHERE id = ?",[d]);l.length>0&&g.length>0&&this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[a,d,c.relation,"{}",o]);}}});}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 d=n.get(a.name);d&&c.push(d);}r.set(s,c);}});}};chunkF2MSBWJN_cjs.c.create({service:"note-search"});var Y=class{constructor(e,t){chunkF2MSBWJN_cjs.a(this,"db");chunkF2MSBWJN_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),[d,l]=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(d,l,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),d=this.cosineSimilarity(e,a);s.push({chunkId:c.chunkId,score:d});}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=ie(e),i=this.db.query("SELECT chunkId, rank FROM chunks_fts WHERE chunks_fts MATCH ? ORDER BY rank LIMIT ?",[s,t]);if(i.length===0)return o();let c=i.map(a=>({chunkId:a.chunkId,score:1/(1+a.rank)}));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 g of e){let u=`${g.chunk.id}`,m=g.score*i;a.set(u,{...g,score:m,source:"hybrid"});}for(let g of t){let u=`${g.chunk.id}`,m=a.get(u);if(m)m.score+=g.score*c;else {let h=g.score*c;a.set(u,{...g,score:h,source:"hybrid"});}}return Array.from(a.values()).map(g=>{let u=g.score,m=new Date(g.document.updatedAt),h=(Date.now()-m.getTime())/864e5,f=Math.exp(-0.01*h),y=.6*u+.4*f;return {...g,score:y}}).sort((g,u)=>u.score-g.score)}async rerank(e,t,r){if(!this.config.rerankLlm)return t.slice(0,r);try{let n=t.map(a=>{let d=a.nodes&&a.nodes.length>0?a.nodes.map(l=>{let g=(l.edges??[]).map(u=>{let m=u.source===l.id?"\u2192":"\u2190",h=u.targetNode?`${u.targetNode.type}:${u.targetNode.name}`:`id=${u.target}`;return `${m} [${u.relation}] ${h}`}).join(" | ");return `node: id=${l.id} name=${l.name} type=${l.type}${g?` edges: ${g}`:""}`}).join(" | "):"";return `<doc filePath="${a.document.path}" lineStart="${a.chunk.startLine}" lineEnd="${a.chunk.endLine}"><snippet>${a.snippet}</snippet>${d?`<nodes>${d}</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,d)=>{let l=s.get(d)??a.score,g=i*a.score+(1-i)*l;return {...a,originalScore:a.score,score:g,source:"reranked"}});return c.sort((a,d)=>d.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])),d=Array.from(new Set(c.map(p=>p.documentId))),l=d.length>0?this.db.query("SELECT * FROM documents WHERE id IN ("+d.map(()=>"?").join(", ")+")",d):[],g=new Map(l.map(p=>[p.id,p])),u=new Map,m=[];for(let p of c){let I=[];try{let T=p.nodeIds?JSON.parse(p.nodeIds):[];I=Array.isArray(T)?T.filter(M=>typeof M=="number"):[];}catch{I=[];}u.set(p.id,I),m.push(...I);}let h=Array.from(new Set(m)),f=h.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+h.map(()=>"?").join(", ")+")",h):[],y=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}])),b=s&&h.length>0?this.db.query("SELECT * FROM edges WHERE source IN ("+h.map(()=>"?").join(", ")+") OR target IN ("+h.map(()=>"?").join(", ")+") ORDER BY id LIMIT ?",[...h,...h,h.length*i]):[],S=[...new Set([...h,...b.map(p=>p.target)])],$=S.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+S.map(()=>"?").join(", ")+")",S):[],O=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}])),k=new Map;for(let p of b){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},T=O.get(p.target);T&&(I.targetNode=T);let M=k.get(I.source)??[];M.length<i&&(M.push(I),k.set(I.source,M));let P=k.get(I.target)??[];P.length<i&&(P.push(I),k.set(I.target,P));}for(let p of e){let I=a.get(p.chunkId);if(!I)continue;let T=g.get(I.documentId);if(!T)continue;let M=u.get(I.id)??[],P=M.map(w=>y.get(w)).filter(w=>w!==void 0),q=s&&M.length>0?Array.from(new Map(M.flatMap(w=>k.get(w)??[]).map(w=>[w.id,w])).values()):[],B=new Map;for(let w of q){let re=B.get(w.source)??[];re.push(w),B.set(w.source,re);}let te=P.length>0?P.map(w=>({...w,edges:s?B.get(w.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:M,path:T.path,createdAt:I.createdAt},document:{id:T.id,path:T.path,title:T.title,contentHash:T.contentHash,summary:T.summary,lastModified:T.lastModified,createdAt:T.createdAt,updatedAt:T.updatedAt},nodes:te.length>0?te:void 0,score:p.score,snippet:I.content.slice(0,200),source:t});}return n}};var Q=class{constructor(e){chunkF2MSBWJN_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 d=[...new Set([e,...a])],l=await this.queryNodes({ids:d,limit:d.length}),g=new Map(l.map(u=>[u.id,u]));for(let u of c){let m=g.get(u.target);m&&(u.targetNode=m);}return {nodes:l,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}),d=Array.from(new Set(c.map(g=>g.target))),l=Array.from(new Set(a.map(g=>g.source)));n.set(i.id,{callers:l,callees:d});for(let g of [...l,...d])s.has(g)||o.push({id:g,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 d=a.join(",");if(o.has(d))continue;if(o.add(d),a.length>1){let g=this.db.query("SELECT id, name FROM nodes WHERE id = ?",[c]);if(g.length>0&&g[0]?.name===t){let u=a.map(()=>"?").join(","),m=this.db.query(`SELECT * FROM nodes WHERE id IN (${u})`,a),h=new Map(m.map(y=>[y.id,y])),f=[];for(let y of a){let b=h.get(y);b&&f.push({id:b.id,name:b.name,type:b.type,properties:b.properties?JSON.parse(b.properties):void 0,createdAt:b.createdAt,updatedAt:b.updatedAt});}n.push(f);continue}}let l=this.db.query("SELECT source, target FROM edges WHERE source = ? OR target = ?",[c,c]);for(let g of l){let u=g.source===c?g.target:g.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]),d=this.db.query("SELECT * FROM edges WHERE id = ?",[c.lastID])[0];return {id:d.id,source:d.source,target:d.target,relation:d.relation,properties:d.properties?JSON.parse(d.properties):void 0,createdAt:d.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 d=t==="ancestor"?a.target:a.source;o.has(d)||(o.add(d),s.add(d),n.push(d));}}return s.size===0?[]:this.queryNodes({ids:Array.from(s),limit:s.size})}};var V=chunkF2MSBWJN_cjs.c.create({service:"note-scanner"}),Ce=["node_modules/**",".git/**","dist/**","build/**","__pycache__/**","*.min.md"],W=class{constructor(e){chunkF2MSBWJN_cjs.a(this,"workspaceDir");chunkF2MSBWJN_cjs.a(this,"extraPaths");chunkF2MSBWJN_cjs.a(this,"sources");chunkF2MSBWJN_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=___namespace.default.join(this.workspaceDir,s);r.push({source:s,dir:i});}for(let s of this.extraPaths){let i=___namespace.default.isAbsolute(s)?s:___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 z__default.default.access(e);}catch{return V.debug("Directory not found, skipping",{dir:e}),r}let n=async o=>{try{let s=await z__default.default.readdir(o,{withFileTypes:!0});for(let i of s){let c=___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){V.warn("Failed to scan directory",{dir:o,error:String(s)});}};return await n(e),r}async scanFile(e,t="upload"){try{let r=await z__default.default.stat(e);if(!r.isFile())return null;let n=await z__default.default.readFile(e,"utf-8"),o=crypto.createHash("sha256").update(n).digest("hex"),s=___namespace.default.isAbsolute(e)?utils.Filesystem.toUnixPath(___namespace.default.relative(this.workspaceDir,e)):e;return {absolutePath:e,relativePath:s||___namespace.default.basename(e),source:t,contentHash:o,lastModified:r.mtimeMs,size:r.size}}catch(r){return V.error("Failed to scan file",{filePath:e,error:String(r)}),null}}async getFileInfo(e,t){try{let r=await z__default.default.readFile(e,"utf-8"),n=await z__default.default.stat(e),o=crypto.createHash("sha256").update(r).digest("hex"),s=utils.Filesystem.toUnixPath(___namespace.default.relative(this.workspaceDir,e));return {absolutePath:e,relativePath:s,source:t,contentHash:o,lastModified:n.mtimeMs,size:n.size}}catch(r){return V.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=chunkF2MSBWJN_cjs.c.create({service:"note"}),J=class{constructor(e){chunkF2MSBWJN_cjs.a(this,"config");chunkF2MSBWJN_cjs.a(this,"db");chunkF2MSBWJN_cjs.a(this,"pipeline");chunkF2MSBWJN_cjs.a(this,"searchEngine");chunkF2MSBWJN_cjs.a(this,"graphInterface");chunkF2MSBWJN_cjs.a(this,"fileScanner");chunkF2MSBWJN_cjs.a(this,"initialized",false);chunkF2MSBWJN_cjs.a(this,"dirty",false);chunkF2MSBWJN_cjs.a(this,"syncTimer");chunkF2MSBWJN_cjs.a(this,"syncConfig");chunkF2MSBWJN_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 G(this.config.database.path),this.pipeline=new X(this.db,this.config),this.searchEngine=new Y(this.db,this.config),this.graphInterface=new Q(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 chunkF2MSBWJN_cjs.c.init({logDir:this.config.logDir||___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());}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.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||___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.toUnixPath(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=>utils.Filesystem.toUnixPath(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(d){let l=d instanceof Error?d.message:String(d);r.errors.push({filePath:a,error:`Failed to delete document: ${l}`}),A.error("Failed to delete document",{path:a,error:l});}for(let a=0;a<n.length;a++){let d=n[a],l=utils.Filesystem.toUnixPath(d.relativePath);e?.(a+1,n.length,d);try{let g=i.get(l);if(g===void 0){let u=await this.pipeline.process(d.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:l});}else if(g!==d.contentHash){let u=await this.pipeline.process(d.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:l});}else r.filesSkipped++;}catch(g){let u=g instanceof Error?g.message:String(g);r.errors.push({filePath:l,error:u}),A.error("Failed to process document",{path:l,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 Ue(E){let e=new J(E);return await e.initialize(),e}async function ar(E){let{Log:e}=await import('./chunks/log-LGRFSTIM.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=J;exports.addWord=nt;exports.closeTokenizer=it;exports.createNoteKnowledge=Ue;exports.initLog=ar;exports.initTokenizer=rt;exports.isInitialized=st;exports.loadCustomDict=ye;exports.toFtsTokens=se;exports.toFtsTokensForSearch=ie;exports.tokenize=be;exports.tokenizeForSearch=Ie;
|
|
126
|
+
`);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){Z.debug("Failed to parse entity extraction result",{error:String(t)});}return {entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,r=Array.isArray(t.entities)?t.entities:[],n=Array.isArray(t.relations)?t.relations:[],o=[],s=new Set,i=new Map;for(let d of r){let l=typeof d?.name=="string"?d.name.trim():"";if(!l)continue;let g=l.toLowerCase();if(s.has(g))continue;s.add(g),i.set(g,l);let u=typeof d?.type=="string"?d.type.trim():"",m=ke.has(u)?u:"keyword",h=d?.properties&&typeof d.properties=="object"&&!Array.isArray(d.properties)?d.properties:{};o.push({name:l,type:m,properties:h});}let c=[],a=new Set;for(let d of n){let l=typeof d?.source=="string"?d.source.trim():"",g=typeof d?.target=="string"?d.target.trim():"";if(!l||!g)continue;let u=i.get(l.toLowerCase()),m=i.get(g.toLowerCase());if(!u||!m||u===m)continue;let h=typeof d?.relation=="string"?d.relation.trim():"",f=De.has(h)?h:"related_to",y=`${u.toLowerCase()}|${m.toLowerCase()}|${f}`;a.has(y)||(a.add(y),c.push({source:u,target:m,relation:f}));}return {entities:o,relations:c}}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 d of e.matchAll(i)){let l=this.sanitizeEntityToken(d[1]??""),g=(d[2]??"related_to").trim(),u=this.sanitizeEntityToken(d[3]??"");if(!l||!u||l===u)continue;let m=l.toLowerCase(),h=u.toLowerCase();n.has(m)||(n.add(m),s.set(m,l),t.push({name:l,type:this.inferEntityType(l),properties:{source:"rule_extracted"}})),n.has(h)||(n.add(h),s.set(h,u),t.push({name:u,type:this.inferEntityType(u),properties:{source:"rule_extracted"}}));let f=`${m}|${h}|${g}`;o.has(f)||(o.add(f),r.push({source:l,target:u,relation:g}));}let c=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[],a=e.split(/\n\s*\n/);for(let d of c){let l=this.sanitizeEntityToken(d);if(!l)continue;let g=l.toLowerCase();n.has(g)||(n.add(g),s.set(g,l),t.push({name:l,type:this.inferEntityType(l),properties:{source:"keyword_extracted"}}));}for(let d of a){if(d.trim().length<20)continue;let l=[];for(let g of d.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{2,80}/gu)??[]){let u=this.sanitizeEntityToken(g);if(!u)continue;let m=u.toLowerCase();n.has(m)&&!l.some(h=>h.key===m)&&l.push({key:m,name:u});}for(let g=0;g<l.length;g++)for(let u=g+1;u<l.length;u++){let m=l[g],h=l[u];if(m.key===h.key)continue;let f="related_to",y=this.inferEntityType(m.name),b=this.inferEntityType(h.name);y==="document"&&b==="object"?f="defines":y==="object"&&b==="document"?f="referenced_in":y==="process"&&b==="object"?f="uses":y==="object"&&b==="process"?f="used_by":y==="concept"&&(f="relates_to");let S=`${m.key}|${h.key}|${f}`;o.has(S)||(o.add(S),r.push({source:m.name,target:h.name,relation:f}));}}return {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){if(t.length===0&&r.length===0)return;let n=new Map,o=new Date().toISOString(),s=t.map(()=>"?").join(","),i=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${s})`,t.map(c=>c.name));for(let c of i)n.set(c.name,c.id);this.db.transaction(()=>{for(let c of t)if(n.get(c.name)===void 0){let d=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[c.name,c.type,JSON.stringify(c.properties),o,o]);d.lastID>0&&n.set(c.name,d.lastID);}for(let c of r){let a=n.get(c.source),d=n.get(c.target);if(a&&d){let l=this.db.query("SELECT id FROM nodes WHERE id = ?",[a]),g=this.db.query("SELECT id FROM nodes WHERE id = ?",[d]);l.length>0&&g.length>0&&this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[a,d,c.relation,"{}",o]);}}});}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 d=n.get(a.name);d&&c.push(d);}r.set(s,c);}});}};chunkF2MSBWJN_cjs.c.create({service:"note-search"});var Y=class{constructor(e,t){chunkF2MSBWJN_cjs.a(this,"db");chunkF2MSBWJN_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),[d,l]=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(d,l,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),d=this.cosineSimilarity(e,a);s.push({chunkId:c.chunkId,score:d});}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=ie(e),i=this.db.query("SELECT chunkId, rank FROM chunks_fts WHERE chunks_fts MATCH ? ORDER BY rank LIMIT ?",[s,t]);if(i.length===0)return o();let c=i.map(a=>({chunkId:a.chunkId,score:1/(1+a.rank)}));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 g of e){let u=`${g.chunk.id}`,m=g.score*i;a.set(u,{...g,score:m,source:"hybrid"});}for(let g of t){let u=`${g.chunk.id}`,m=a.get(u);if(m)m.score+=g.score*c;else {let h=g.score*c;a.set(u,{...g,score:h,source:"hybrid"});}}return Array.from(a.values()).map(g=>{let u=g.score,m=new Date(g.document.updatedAt),h=(Date.now()-m.getTime())/864e5,f=Math.exp(-0.01*h),y=.6*u+.4*f;return {...g,score:y}}).sort((g,u)=>u.score-g.score)}async rerank(e,t,r){if(!this.config.rerankLlm)return t.slice(0,r);try{let n=t.map(a=>{let d=a.nodes&&a.nodes.length>0?a.nodes.map(l=>{let g=(l.edges??[]).map(u=>{let m=u.source===l.id?"\u2192":"\u2190",h=u.targetNode?`${u.targetNode.type}:${u.targetNode.name}`:`id=${u.target}`;return `${m} [${u.relation}] ${h}`}).join(" | ");return `node: id=${l.id} name=${l.name} type=${l.type}${g?` edges: ${g}`:""}`}).join(" | "):"";return `<doc filePath="${a.document.path}" lineStart="${a.chunk.startLine}" lineEnd="${a.chunk.endLine}"><snippet>${a.snippet}</snippet>${d?`<nodes>${d}</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,d)=>{let l=s.get(d)??a.score,g=i*a.score+(1-i)*l;return {...a,originalScore:a.score,score:g,source:"reranked"}});return c.sort((a,d)=>d.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])),d=Array.from(new Set(c.map(p=>p.documentId))),l=d.length>0?this.db.query("SELECT * FROM documents WHERE id IN ("+d.map(()=>"?").join(", ")+")",d):[],g=new Map(l.map(p=>[p.id,p])),u=new Map,m=[];for(let p of c){let I=[];try{let T=p.nodeIds?JSON.parse(p.nodeIds):[];I=Array.isArray(T)?T.filter(M=>typeof M=="number"):[];}catch{I=[];}u.set(p.id,I),m.push(...I);}let h=Array.from(new Set(m)),f=h.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+h.map(()=>"?").join(", ")+")",h):[],y=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}])),b=s&&h.length>0?this.db.query("SELECT * FROM edges WHERE source IN ("+h.map(()=>"?").join(", ")+") OR target IN ("+h.map(()=>"?").join(", ")+") ORDER BY id LIMIT ?",[...h,...h,h.length*i]):[],S=[...new Set([...h,...b.map(p=>p.target)])],$=S.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+S.map(()=>"?").join(", ")+")",S):[],O=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}])),k=new Map;for(let p of b){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},T=O.get(p.target);T&&(I.targetNode=T);let M=k.get(I.source)??[];M.length<i&&(M.push(I),k.set(I.source,M));let P=k.get(I.target)??[];P.length<i&&(P.push(I),k.set(I.target,P));}for(let p of e){let I=a.get(p.chunkId);if(!I)continue;let T=g.get(I.documentId);if(!T)continue;let M=u.get(I.id)??[],P=M.map(w=>y.get(w)).filter(w=>w!==void 0),q=s&&M.length>0?Array.from(new Map(M.flatMap(w=>k.get(w)??[]).map(w=>[w.id,w])).values()):[],B=new Map;for(let w of q){let re=B.get(w.source)??[];re.push(w),B.set(w.source,re);}let te=P.length>0?P.map(w=>({...w,edges:s?B.get(w.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:M,path:T.path,createdAt:I.createdAt},document:{id:T.id,path:T.path,title:T.title,contentHash:T.contentHash,summary:T.summary,lastModified:T.lastModified,createdAt:T.createdAt,updatedAt:T.updatedAt},nodes:te.length>0?te:void 0,score:p.score,snippet:I.content.slice(0,200),source:t});}return n}};var Q=class{constructor(e){chunkF2MSBWJN_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 d=[...new Set([e,...a])],l=await this.queryNodes({ids:d,limit:d.length}),g=new Map(l.map(u=>[u.id,u]));for(let u of c){let m=g.get(u.target);m&&(u.targetNode=m);}return {nodes:l,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}),d=Array.from(new Set(c.map(g=>g.target))),l=Array.from(new Set(a.map(g=>g.source)));n.set(i.id,{callers:l,callees:d});for(let g of [...l,...d])s.has(g)||o.push({id:g,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 d=a.join(",");if(o.has(d))continue;if(o.add(d),a.length>1){let g=this.db.query("SELECT id, name FROM nodes WHERE id = ?",[c]);if(g.length>0&&g[0]?.name===t){let u=a.map(()=>"?").join(","),m=this.db.query(`SELECT * FROM nodes WHERE id IN (${u})`,a),h=new Map(m.map(y=>[y.id,y])),f=[];for(let y of a){let b=h.get(y);b&&f.push({id:b.id,name:b.name,type:b.type,properties:b.properties?JSON.parse(b.properties):void 0,createdAt:b.createdAt,updatedAt:b.updatedAt});}n.push(f);continue}}let l=this.db.query("SELECT source, target FROM edges WHERE source = ? OR target = ?",[c,c]);for(let g of l){let u=g.source===c?g.target:g.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]),d=this.db.query("SELECT * FROM edges WHERE id = ?",[c.lastID])[0];return {id:d.id,source:d.source,target:d.target,relation:d.relation,properties:d.properties?JSON.parse(d.properties):void 0,createdAt:d.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 d=t==="ancestor"?a.target:a.source;o.has(d)||(o.add(d),s.add(d),n.push(d));}}return s.size===0?[]:this.queryNodes({ids:Array.from(s),limit:s.size})}};var V=chunkF2MSBWJN_cjs.c.create({service:"note-scanner"}),Ce=["node_modules/**",".git/**","dist/**","build/**","__pycache__/**","*.min.md"],W=class{constructor(e){chunkF2MSBWJN_cjs.a(this,"workspaceDir");chunkF2MSBWJN_cjs.a(this,"extraPaths");chunkF2MSBWJN_cjs.a(this,"sources");chunkF2MSBWJN_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=___namespace.default.join(this.workspaceDir,s);r.push({source:s,dir:i});}for(let s of this.extraPaths){let i=___namespace.default.isAbsolute(s)?s:___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 z__default.default.access(e);}catch{return V.debug("Directory not found, skipping",{dir:e}),r}let n=async o=>{try{let s=await z__default.default.readdir(o,{withFileTypes:!0});for(let i of s){let c=___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){V.warn("Failed to scan directory",{dir:o,error:String(s)});}};return await n(e),r}async scanFile(e,t="upload"){try{let r=await z__default.default.stat(e);if(!r.isFile())return null;let n=await z__default.default.readFile(e,"utf-8"),o=crypto.createHash("sha256").update(n).digest("hex"),s=___namespace.default.isAbsolute(e)?utils.Filesystem.toUnixPath(___namespace.default.relative(this.workspaceDir,e)):e;return {absolutePath:e,relativePath:s||___namespace.default.basename(e),source:t,contentHash:o,lastModified:r.mtimeMs,size:r.size}}catch(r){return V.error("Failed to scan file",{filePath:e,error:String(r)}),null}}async getFileInfo(e,t){try{let r=await z__default.default.readFile(e,"utf-8"),n=await z__default.default.stat(e),o=crypto.createHash("sha256").update(r).digest("hex"),s=utils.Filesystem.toUnixPath(___namespace.default.relative(this.workspaceDir,e));return {absolutePath:e,relativePath:s,source:t,contentHash:o,lastModified:n.mtimeMs,size:n.size}}catch(r){return V.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=chunkF2MSBWJN_cjs.c.create({service:"note"}),J=class{constructor(e){chunkF2MSBWJN_cjs.a(this,"config");chunkF2MSBWJN_cjs.a(this,"db");chunkF2MSBWJN_cjs.a(this,"pipeline");chunkF2MSBWJN_cjs.a(this,"searchEngine");chunkF2MSBWJN_cjs.a(this,"graphInterface");chunkF2MSBWJN_cjs.a(this,"fileScanner");chunkF2MSBWJN_cjs.a(this,"initialized",false);chunkF2MSBWJN_cjs.a(this,"dirty",false);chunkF2MSBWJN_cjs.a(this,"syncTimer");chunkF2MSBWJN_cjs.a(this,"syncConfig");chunkF2MSBWJN_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 G(this.config.database.path),this.pipeline=new X(this.db,this.config),this.searchEngine=new Y(this.db,this.config),this.graphInterface=new Q(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 chunkF2MSBWJN_cjs.c.init({logDir:this.config.logDir||___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());}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||___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.toUnixPath(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=>utils.Filesystem.toUnixPath(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(d){let l=d instanceof Error?d.message:String(d);r.errors.push({filePath:a,error:`Failed to delete document: ${l}`}),A.error("Failed to delete document",{path:a,error:l});}for(let a=0;a<n.length;a++){let d=n[a],l=utils.Filesystem.toUnixPath(d.relativePath);e?.(a+1,n.length,d);try{let g=i.get(l);if(g===void 0){let u=await this.pipeline.process(d.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:l});}else if(g!==d.contentHash){let u=await this.pipeline.process(d.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:l});}else r.filesSkipped++;}catch(g){let u=g instanceof Error?g.message:String(g);r.errors.push({filePath:l,error:u}),A.error("Failed to process document",{path:l,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 Ue(E){let e=new J(E);return await e.initialize(),e}async function ar(E){let{Log:e}=await import('./chunks/log-LGRFSTIM.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=J;exports.addWord=nt;exports.closeTokenizer=it;exports.createNoteKnowledge=Ue;exports.initLog=ar;exports.initTokenizer=rt;exports.isInitialized=st;exports.loadCustomDict=ye;exports.toFtsTokens=se;exports.toFtsTokensForSearch=ie;exports.tokenize=be;exports.tokenizeForSearch=Ie;
|
package/dist/index.mjs
CHANGED
|
@@ -123,4 +123,4 @@ ${b}`}u.embed=s,u.embedMany=i;})(L||(L={}));var ee=b.create({service:"note-inges
|
|
|
123
123
|
|
|
124
124
|
`);if(!this.config.graphLlm)return this.extractEntitiesByRules(t);try{let r=await L.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(`
|
|
125
125
|
|
|
126
|
-
`);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){ee.debug("Failed to parse entity extraction result",{error:String(t)});}return {entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,r=Array.isArray(t.entities)?t.entities:[],n=Array.isArray(t.relations)?t.relations:[],o=[],s=new Set,i=new Map;for(let d of r){let l=typeof d?.name=="string"?d.name.trim():"";if(!l)continue;let g=l.toLowerCase();if(s.has(g))continue;s.add(g),i.set(g,l);let u=typeof d?.type=="string"?d.type.trim():"",m=De.has(u)?u:"keyword",h=d?.properties&&typeof d.properties=="object"&&!Array.isArray(d.properties)?d.properties:{};o.push({name:l,type:m,properties:h});}let c=[],a=new Set;for(let d of n){let l=typeof d?.source=="string"?d.source.trim():"",g=typeof d?.target=="string"?d.target.trim():"";if(!l||!g)continue;let u=i.get(l.toLowerCase()),m=i.get(g.toLowerCase());if(!u||!m||u===m)continue;let h=typeof d?.relation=="string"?d.relation.trim():"",f=Oe.has(h)?h:"related_to",y=`${u.toLowerCase()}|${m.toLowerCase()}|${f}`;a.has(y)||(a.add(y),c.push({source:u,target:m,relation:f}));}return {entities:o,relations:c}}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 d of e.matchAll(i)){let l=this.sanitizeEntityToken(d[1]??""),g=(d[2]??"related_to").trim(),u=this.sanitizeEntityToken(d[3]??"");if(!l||!u||l===u)continue;let m=l.toLowerCase(),h=u.toLowerCase();n.has(m)||(n.add(m),s.set(m,l),t.push({name:l,type:this.inferEntityType(l),properties:{source:"rule_extracted"}})),n.has(h)||(n.add(h),s.set(h,u),t.push({name:u,type:this.inferEntityType(u),properties:{source:"rule_extracted"}}));let f=`${m}|${h}|${g}`;o.has(f)||(o.add(f),r.push({source:l,target:u,relation:g}));}let c=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[],a=e.split(/\n\s*\n/);for(let d of c){let l=this.sanitizeEntityToken(d);if(!l)continue;let g=l.toLowerCase();n.has(g)||(n.add(g),s.set(g,l),t.push({name:l,type:this.inferEntityType(l),properties:{source:"keyword_extracted"}}));}for(let d of a){if(d.trim().length<20)continue;let l=[];for(let g of d.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{2,80}/gu)??[]){let u=this.sanitizeEntityToken(g);if(!u)continue;let m=u.toLowerCase();n.has(m)&&!l.some(h=>h.key===m)&&l.push({key:m,name:u});}for(let g=0;g<l.length;g++)for(let u=g+1;u<l.length;u++){let m=l[g],h=l[u];if(m.key===h.key)continue;let f="related_to",y=this.inferEntityType(m.name),b=this.inferEntityType(h.name);y==="document"&&b==="object"?f="defines":y==="object"&&b==="document"?f="referenced_in":y==="process"&&b==="object"?f="uses":y==="object"&&b==="process"?f="used_by":y==="concept"&&(f="relates_to");let S=`${m.key}|${h.key}|${f}`;o.has(S)||(o.add(S),r.push({source:m.name,target:h.name,relation:f}));}}return {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){if(t.length===0&&r.length===0)return;let n=new Map,o=new Date().toISOString(),s=t.map(()=>"?").join(","),i=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${s})`,t.map(c=>c.name));for(let c of i)n.set(c.name,c.id);this.db.transaction(()=>{for(let c of t)if(n.get(c.name)===void 0){let d=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[c.name,c.type,JSON.stringify(c.properties),o,o]);d.lastID>0&&n.set(c.name,d.lastID);}for(let c of r){let a=n.get(c.source),d=n.get(c.target);if(a&&d){let l=this.db.query("SELECT id FROM nodes WHERE id = ?",[a]),g=this.db.query("SELECT id FROM nodes WHERE id = ?",[d]);l.length>0&&g.length>0&&this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[a,d,c.relation,"{}",o]);}}});}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 d=n.get(a.name);d&&c.push(d);}r.set(s,c);}});}};b.create({service:"note-search"});var Q=class{constructor(e,t){a(this,"db");a(this,"config");this.db=e,this.config={...DEFAULT_NOTE_CHUNK_CONFIG,...t,embeddingLlm:t.embeddingLlm},t.embeddingLlm&&L.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),[d,l]=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(d,l,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),d=this.cosineSimilarity(e,a);s.push({chunkId:c.chunkId,score:d});}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=oe(e),i=this.db.query("SELECT chunkId, rank FROM chunks_fts WHERE chunks_fts MATCH ? ORDER BY rank LIMIT ?",[s,t]);if(i.length===0)return o();let c=i.map(a=>({chunkId:a.chunkId,score:1/(1+a.rank)}));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 g of e){let u=`${g.chunk.id}`,m=g.score*i;a.set(u,{...g,score:m,source:"hybrid"});}for(let g of t){let u=`${g.chunk.id}`,m=a.get(u);if(m)m.score+=g.score*c;else {let h=g.score*c;a.set(u,{...g,score:h,source:"hybrid"});}}return Array.from(a.values()).map(g=>{let u=g.score,m=new Date(g.document.updatedAt),h=(Date.now()-m.getTime())/864e5,f=Math.exp(-0.01*h),y=.6*u+.4*f;return {...g,score:y}}).sort((g,u)=>u.score-g.score)}async rerank(e,t,r){if(!this.config.rerankLlm)return t.slice(0,r);try{let n=t.map(a=>{let d=a.nodes&&a.nodes.length>0?a.nodes.map(l=>{let g=(l.edges??[]).map(u=>{let m=u.source===l.id?"\u2192":"\u2190",h=u.targetNode?`${u.targetNode.type}:${u.targetNode.name}`:`id=${u.target}`;return `${m} [${u.relation}] ${h}`}).join(" | ");return `node: id=${l.id} name=${l.name} type=${l.type}${g?` edges: ${g}`:""}`}).join(" | "):"";return `<doc filePath="${a.document.path}" lineStart="${a.chunk.startLine}" lineEnd="${a.chunk.endLine}"><snippet>${a.snippet}</snippet>${d?`<nodes>${d}</nodes>`:""}</doc>`}),o=await L.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,d)=>{let l=s.get(d)??a.score,g=i*a.score+(1-i)*l;return {...a,originalScore:a.score,score:g,source:"reranked"}});return c.sort((a,d)=>d.score-a.score),c.slice(0,r)}catch{return t.slice(0,r)}}async embed(e){try{return await L.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])),d=Array.from(new Set(c.map(p=>p.documentId))),l=d.length>0?this.db.query("SELECT * FROM documents WHERE id IN ("+d.map(()=>"?").join(", ")+")",d):[],g=new Map(l.map(p=>[p.id,p])),u=new Map,m=[];for(let p of c){let I=[];try{let T=p.nodeIds?JSON.parse(p.nodeIds):[];I=Array.isArray(T)?T.filter(C=>typeof C=="number"):[];}catch{I=[];}u.set(p.id,I),m.push(...I);}let h=Array.from(new Set(m)),f=h.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+h.map(()=>"?").join(", ")+")",h):[],y=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}])),b=s&&h.length>0?this.db.query("SELECT * FROM edges WHERE source IN ("+h.map(()=>"?").join(", ")+") OR target IN ("+h.map(()=>"?").join(", ")+") ORDER BY id LIMIT ?",[...h,...h,h.length*i]):[],S=[...new Set([...h,...b.map(p=>p.target)])],q=S.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+S.map(()=>"?").join(", ")+")",S):[],O=new Map(q.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}])),k=new Map;for(let p of b){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},T=O.get(p.target);T&&(I.targetNode=T);let C=k.get(I.source)??[];C.length<i&&(C.push(I),k.set(I.source,C));let x=k.get(I.target)??[];x.length<i&&(x.push(I),k.set(I.target,x));}for(let p of e){let I=a.get(p.chunkId);if(!I)continue;let T=g.get(I.documentId);if(!T)continue;let C=u.get(I.id)??[],x=C.map(w=>y.get(w)).filter(w=>w!==void 0),K=s&&C.length>0?Array.from(new Map(C.flatMap(w=>k.get(w)??[]).map(w=>[w.id,w])).values()):[],W=new Map;for(let w of K){let ne=W.get(w.source)??[];ne.push(w),W.set(w.source,ne);}let re=x.length>0?x.map(w=>({...w,edges:s?W.get(w.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:C,path:T.path,createdAt:I.createdAt},document:{id:T.id,path:T.path,title:T.title,contentHash:T.contentHash,summary:T.summary,lastModified:T.lastModified,createdAt:T.createdAt,updatedAt:T.updatedAt},nodes:re.length>0?re:void 0,score:p.score,snippet:I.content.slice(0,200),source:t});}return n}};var V=class{constructor(e){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 d=[...new Set([e,...a])],l=await this.queryNodes({ids:d,limit:d.length}),g=new Map(l.map(u=>[u.id,u]));for(let u of c){let m=g.get(u.target);m&&(u.targetNode=m);}return {nodes:l,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}),d=Array.from(new Set(c.map(g=>g.target))),l=Array.from(new Set(a.map(g=>g.source)));n.set(i.id,{callers:l,callees:d});for(let g of [...l,...d])s.has(g)||o.push({id:g,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 d=a.join(",");if(o.has(d))continue;if(o.add(d),a.length>1){let g=this.db.query("SELECT id, name FROM nodes WHERE id = ?",[c]);if(g.length>0&&g[0]?.name===t){let u=a.map(()=>"?").join(","),m=this.db.query(`SELECT * FROM nodes WHERE id IN (${u})`,a),h=new Map(m.map(y=>[y.id,y])),f=[];for(let y of a){let b=h.get(y);b&&f.push({id:b.id,name:b.name,type:b.type,properties:b.properties?JSON.parse(b.properties):void 0,createdAt:b.createdAt,updatedAt:b.updatedAt});}n.push(f);continue}}let l=this.db.query("SELECT source, target FROM edges WHERE source = ? OR target = ?",[c,c]);for(let g of l){let u=g.source===c?g.target:g.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]),d=this.db.query("SELECT * FROM edges WHERE id = ?",[c.lastID])[0];return {id:d.id,source:d.source,target:d.target,relation:d.relation,properties:d.properties?JSON.parse(d.properties):void 0,createdAt:d.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 d=t==="ancestor"?a.target:a.source;o.has(d)||(o.add(d),s.add(d),n.push(d));}}return s.size===0?[]:this.queryNodes({ids:Array.from(s),limit:s.size})}};var J=b.create({service:"note-scanner"}),Me=["node_modules/**",".git/**","dist/**","build/**","__pycache__/**","*.min.md"],$=class{constructor(e){a(this,"workspaceDir");a(this,"extraPaths");a(this,"sources");a(this,"ignorePatterns");this.workspaceDir=e.workspaceDir,this.extraPaths=e.extraPaths??[],this.sources=new Set(e.sources??["docs"]),this.ignorePatterns=[...Me,...e.ignorePatterns??[]];}async scanAll(e){let t=[],r=[];for(let s of this.sources){let i=U__default.join(this.workspaceDir,s);r.push({source:s,dir:i});}for(let s of this.extraPaths){let i=U__default.isAbsolute(s)?s:U__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 B.access(e);}catch{return J.debug("Directory not found, skipping",{dir:e}),r}let n=async o=>{try{let s=await B.readdir(o,{withFileTypes:!0});for(let i of s){let c=U__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){J.warn("Failed to scan directory",{dir:o,error:String(s)});}};return await n(e),r}async scanFile(e,t="upload"){try{let r=await B.stat(e);if(!r.isFile())return null;let n=await B.readFile(e,"utf-8"),o=createHash("sha256").update(n).digest("hex"),s=U__default.isAbsolute(e)?Filesystem.toUnixPath(U__default.relative(this.workspaceDir,e)):e;return {absolutePath:e,relativePath:s||U__default.basename(e),source:t,contentHash:o,lastModified:r.mtimeMs,size:r.size}}catch(r){return J.error("Failed to scan file",{filePath:e,error:String(r)}),null}}async getFileInfo(e,t){try{let r=await B.readFile(e,"utf-8"),n=await B.stat(e),o=createHash("sha256").update(r).digest("hex"),s=Filesystem.toUnixPath(U__default.relative(this.workspaceDir,e));return {absolutePath:e,relativePath:s,source:t,contentHash:o,lastModified:n.mtimeMs,size:n.size}}catch(r){return J.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=b.create({service:"note"}),Z=class{constructor(e){a(this,"config");a(this,"db");a(this,"pipeline");a(this,"searchEngine");a(this,"graphInterface");a(this,"fileScanner");a(this,"initialized",false);a(this,"dirty",false);a(this,"syncTimer");a(this,"syncConfig");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||getDefaultDatabasePath(xdgData,"note.db");this.config={workspaceDir:t,database:{path:n,walMode:e.database?.walMode??true},vectorDims:e.vectorDims??768,...DEFAULT_NOTE_CHUNK_CONFIG,extraPaths:e.extraPaths,sources:e.sources,search:{...DEFAULT_SEARCH_CONFIG,...e.search},indexer:{...DEFAULT_INDEXER_CONFIG,...e.indexer},sync:{...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 Y(this.db,this.config),this.searchEngine=new Q(this.db,this.config),this.graphInterface=new V(this.db),this.fileScanner=new $({workspaceDir:this.config.workspaceDir,extraPaths:this.config.extraPaths,sources:this.config.sources,ignorePatterns:this.config?.indexer?.ignorePatterns});}async initialize(){if(this.initialized)return;await b.init({logDir:this.config.logDir||U__default.join(this.config.workspaceDir,"logs"),print:process.argv.includes("--print-logs"),dev:false,level:"INFO"}),L.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());}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.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||U__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=Filesystem.toUnixPath(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=>Filesystem.toUnixPath(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(d){let l=d instanceof Error?d.message:String(d);r.errors.push({filePath:a,error:`Failed to delete document: ${l}`}),A.error("Failed to delete document",{path:a,error:l});}for(let a=0;a<n.length;a++){let d=n[a],l=Filesystem.toUnixPath(d.relativePath);e?.(a+1,n.length,d);try{let g=i.get(l);if(g===void 0){let u=await this.pipeline.process(d.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:l});}else if(g!==d.contentHash){let u=await this.pipeline.process(d.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:l});}else r.filesSkipped++;}catch(g){let u=g instanceof Error?g.message:String(g);r.errors.push({filePath:l,error:u}),A.error("Failed to process document",{path:l,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 Z(E);return await e.initialize(),e}async function cr(E){let{Log:e}=await import('./chunks/log-EPJXYODF.mjs'),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")});}export{$ as FileScanner,R as KnowledgeBaseError,z as KnowledgeBaseErrorCode,L as Llm,Z as NoteKnowledge,st as addWord,ot as closeTokenizer,He as createNoteKnowledge,cr as initLog,nt as initTokenizer,it as isInitialized,be as loadCustomDict,ie as toFtsTokens,oe as toFtsTokensForSearch,Ie as tokenize,Ne as tokenizeForSearch};
|
|
126
|
+
`);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){ee.debug("Failed to parse entity extraction result",{error:String(t)});}return {entities:[],relations:[]}}normalizeExtractionResult(e){let t=e,r=Array.isArray(t.entities)?t.entities:[],n=Array.isArray(t.relations)?t.relations:[],o=[],s=new Set,i=new Map;for(let d of r){let l=typeof d?.name=="string"?d.name.trim():"";if(!l)continue;let g=l.toLowerCase();if(s.has(g))continue;s.add(g),i.set(g,l);let u=typeof d?.type=="string"?d.type.trim():"",m=De.has(u)?u:"keyword",h=d?.properties&&typeof d.properties=="object"&&!Array.isArray(d.properties)?d.properties:{};o.push({name:l,type:m,properties:h});}let c=[],a=new Set;for(let d of n){let l=typeof d?.source=="string"?d.source.trim():"",g=typeof d?.target=="string"?d.target.trim():"";if(!l||!g)continue;let u=i.get(l.toLowerCase()),m=i.get(g.toLowerCase());if(!u||!m||u===m)continue;let h=typeof d?.relation=="string"?d.relation.trim():"",f=Oe.has(h)?h:"related_to",y=`${u.toLowerCase()}|${m.toLowerCase()}|${f}`;a.has(y)||(a.add(y),c.push({source:u,target:m,relation:f}));}return {entities:o,relations:c}}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 d of e.matchAll(i)){let l=this.sanitizeEntityToken(d[1]??""),g=(d[2]??"related_to").trim(),u=this.sanitizeEntityToken(d[3]??"");if(!l||!u||l===u)continue;let m=l.toLowerCase(),h=u.toLowerCase();n.has(m)||(n.add(m),s.set(m,l),t.push({name:l,type:this.inferEntityType(l),properties:{source:"rule_extracted"}})),n.has(h)||(n.add(h),s.set(h,u),t.push({name:u,type:this.inferEntityType(u),properties:{source:"rule_extracted"}}));let f=`${m}|${h}|${g}`;o.has(f)||(o.add(f),r.push({source:l,target:u,relation:g}));}let c=e.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{1,80}/gu)??[],a=e.split(/\n\s*\n/);for(let d of c){let l=this.sanitizeEntityToken(d);if(!l)continue;let g=l.toLowerCase();n.has(g)||(n.add(g),s.set(g,l),t.push({name:l,type:this.inferEntityType(l),properties:{source:"keyword_extracted"}}));}for(let d of a){if(d.trim().length<20)continue;let l=[];for(let g of d.match(/[\p{L}\p{N}][\p{L}\p{N}_.-]{2,80}/gu)??[]){let u=this.sanitizeEntityToken(g);if(!u)continue;let m=u.toLowerCase();n.has(m)&&!l.some(h=>h.key===m)&&l.push({key:m,name:u});}for(let g=0;g<l.length;g++)for(let u=g+1;u<l.length;u++){let m=l[g],h=l[u];if(m.key===h.key)continue;let f="related_to",y=this.inferEntityType(m.name),b=this.inferEntityType(h.name);y==="document"&&b==="object"?f="defines":y==="object"&&b==="document"?f="referenced_in":y==="process"&&b==="object"?f="uses":y==="object"&&b==="process"?f="used_by":y==="concept"&&(f="relates_to");let S=`${m.key}|${h.key}|${f}`;o.has(S)||(o.add(S),r.push({source:m.name,target:h.name,relation:f}));}}return {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){if(t.length===0&&r.length===0)return;let n=new Map,o=new Date().toISOString(),s=t.map(()=>"?").join(","),i=this.db.query(`SELECT id, name, type FROM nodes WHERE name IN (${s})`,t.map(c=>c.name));for(let c of i)n.set(c.name,c.id);this.db.transaction(()=>{for(let c of t)if(n.get(c.name)===void 0){let d=this.db.run("INSERT INTO nodes (name, type, properties, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",[c.name,c.type,JSON.stringify(c.properties),o,o]);d.lastID>0&&n.set(c.name,d.lastID);}for(let c of r){let a=n.get(c.source),d=n.get(c.target);if(a&&d){let l=this.db.query("SELECT id FROM nodes WHERE id = ?",[a]),g=this.db.query("SELECT id FROM nodes WHERE id = ?",[d]);l.length>0&&g.length>0&&this.db.run("INSERT OR REPLACE INTO edges (source, target, relation, properties, createdAt) VALUES (?, ?, ?, ?, ?)",[a,d,c.relation,"{}",o]);}}});}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 d=n.get(a.name);d&&c.push(d);}r.set(s,c);}});}};b.create({service:"note-search"});var Q=class{constructor(e,t){a(this,"db");a(this,"config");this.db=e,this.config={...DEFAULT_NOTE_CHUNK_CONFIG,...t,embeddingLlm:t.embeddingLlm},t.embeddingLlm&&L.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),[d,l]=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(d,l,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),d=this.cosineSimilarity(e,a);s.push({chunkId:c.chunkId,score:d});}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=oe(e),i=this.db.query("SELECT chunkId, rank FROM chunks_fts WHERE chunks_fts MATCH ? ORDER BY rank LIMIT ?",[s,t]);if(i.length===0)return o();let c=i.map(a=>({chunkId:a.chunkId,score:1/(1+a.rank)}));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 g of e){let u=`${g.chunk.id}`,m=g.score*i;a.set(u,{...g,score:m,source:"hybrid"});}for(let g of t){let u=`${g.chunk.id}`,m=a.get(u);if(m)m.score+=g.score*c;else {let h=g.score*c;a.set(u,{...g,score:h,source:"hybrid"});}}return Array.from(a.values()).map(g=>{let u=g.score,m=new Date(g.document.updatedAt),h=(Date.now()-m.getTime())/864e5,f=Math.exp(-0.01*h),y=.6*u+.4*f;return {...g,score:y}}).sort((g,u)=>u.score-g.score)}async rerank(e,t,r){if(!this.config.rerankLlm)return t.slice(0,r);try{let n=t.map(a=>{let d=a.nodes&&a.nodes.length>0?a.nodes.map(l=>{let g=(l.edges??[]).map(u=>{let m=u.source===l.id?"\u2192":"\u2190",h=u.targetNode?`${u.targetNode.type}:${u.targetNode.name}`:`id=${u.target}`;return `${m} [${u.relation}] ${h}`}).join(" | ");return `node: id=${l.id} name=${l.name} type=${l.type}${g?` edges: ${g}`:""}`}).join(" | "):"";return `<doc filePath="${a.document.path}" lineStart="${a.chunk.startLine}" lineEnd="${a.chunk.endLine}"><snippet>${a.snippet}</snippet>${d?`<nodes>${d}</nodes>`:""}</doc>`}),o=await L.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,d)=>{let l=s.get(d)??a.score,g=i*a.score+(1-i)*l;return {...a,originalScore:a.score,score:g,source:"reranked"}});return c.sort((a,d)=>d.score-a.score),c.slice(0,r)}catch{return t.slice(0,r)}}async embed(e){try{return await L.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])),d=Array.from(new Set(c.map(p=>p.documentId))),l=d.length>0?this.db.query("SELECT * FROM documents WHERE id IN ("+d.map(()=>"?").join(", ")+")",d):[],g=new Map(l.map(p=>[p.id,p])),u=new Map,m=[];for(let p of c){let I=[];try{let T=p.nodeIds?JSON.parse(p.nodeIds):[];I=Array.isArray(T)?T.filter(C=>typeof C=="number"):[];}catch{I=[];}u.set(p.id,I),m.push(...I);}let h=Array.from(new Set(m)),f=h.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+h.map(()=>"?").join(", ")+")",h):[],y=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}])),b=s&&h.length>0?this.db.query("SELECT * FROM edges WHERE source IN ("+h.map(()=>"?").join(", ")+") OR target IN ("+h.map(()=>"?").join(", ")+") ORDER BY id LIMIT ?",[...h,...h,h.length*i]):[],S=[...new Set([...h,...b.map(p=>p.target)])],q=S.length>0?this.db.query("SELECT * FROM nodes WHERE id IN ("+S.map(()=>"?").join(", ")+")",S):[],O=new Map(q.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}])),k=new Map;for(let p of b){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},T=O.get(p.target);T&&(I.targetNode=T);let C=k.get(I.source)??[];C.length<i&&(C.push(I),k.set(I.source,C));let x=k.get(I.target)??[];x.length<i&&(x.push(I),k.set(I.target,x));}for(let p of e){let I=a.get(p.chunkId);if(!I)continue;let T=g.get(I.documentId);if(!T)continue;let C=u.get(I.id)??[],x=C.map(w=>y.get(w)).filter(w=>w!==void 0),K=s&&C.length>0?Array.from(new Map(C.flatMap(w=>k.get(w)??[]).map(w=>[w.id,w])).values()):[],W=new Map;for(let w of K){let ne=W.get(w.source)??[];ne.push(w),W.set(w.source,ne);}let re=x.length>0?x.map(w=>({...w,edges:s?W.get(w.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:C,path:T.path,createdAt:I.createdAt},document:{id:T.id,path:T.path,title:T.title,contentHash:T.contentHash,summary:T.summary,lastModified:T.lastModified,createdAt:T.createdAt,updatedAt:T.updatedAt},nodes:re.length>0?re:void 0,score:p.score,snippet:I.content.slice(0,200),source:t});}return n}};var V=class{constructor(e){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 d=[...new Set([e,...a])],l=await this.queryNodes({ids:d,limit:d.length}),g=new Map(l.map(u=>[u.id,u]));for(let u of c){let m=g.get(u.target);m&&(u.targetNode=m);}return {nodes:l,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}),d=Array.from(new Set(c.map(g=>g.target))),l=Array.from(new Set(a.map(g=>g.source)));n.set(i.id,{callers:l,callees:d});for(let g of [...l,...d])s.has(g)||o.push({id:g,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 d=a.join(",");if(o.has(d))continue;if(o.add(d),a.length>1){let g=this.db.query("SELECT id, name FROM nodes WHERE id = ?",[c]);if(g.length>0&&g[0]?.name===t){let u=a.map(()=>"?").join(","),m=this.db.query(`SELECT * FROM nodes WHERE id IN (${u})`,a),h=new Map(m.map(y=>[y.id,y])),f=[];for(let y of a){let b=h.get(y);b&&f.push({id:b.id,name:b.name,type:b.type,properties:b.properties?JSON.parse(b.properties):void 0,createdAt:b.createdAt,updatedAt:b.updatedAt});}n.push(f);continue}}let l=this.db.query("SELECT source, target FROM edges WHERE source = ? OR target = ?",[c,c]);for(let g of l){let u=g.source===c?g.target:g.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]),d=this.db.query("SELECT * FROM edges WHERE id = ?",[c.lastID])[0];return {id:d.id,source:d.source,target:d.target,relation:d.relation,properties:d.properties?JSON.parse(d.properties):void 0,createdAt:d.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 d=t==="ancestor"?a.target:a.source;o.has(d)||(o.add(d),s.add(d),n.push(d));}}return s.size===0?[]:this.queryNodes({ids:Array.from(s),limit:s.size})}};var J=b.create({service:"note-scanner"}),Me=["node_modules/**",".git/**","dist/**","build/**","__pycache__/**","*.min.md"],$=class{constructor(e){a(this,"workspaceDir");a(this,"extraPaths");a(this,"sources");a(this,"ignorePatterns");this.workspaceDir=e.workspaceDir,this.extraPaths=e.extraPaths??[],this.sources=new Set(e.sources??["docs"]),this.ignorePatterns=[...Me,...e.ignorePatterns??[]];}async scanAll(e){let t=[],r=[];for(let s of this.sources){let i=U__default.join(this.workspaceDir,s);r.push({source:s,dir:i});}for(let s of this.extraPaths){let i=U__default.isAbsolute(s)?s:U__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 B.access(e);}catch{return J.debug("Directory not found, skipping",{dir:e}),r}let n=async o=>{try{let s=await B.readdir(o,{withFileTypes:!0});for(let i of s){let c=U__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){J.warn("Failed to scan directory",{dir:o,error:String(s)});}};return await n(e),r}async scanFile(e,t="upload"){try{let r=await B.stat(e);if(!r.isFile())return null;let n=await B.readFile(e,"utf-8"),o=createHash("sha256").update(n).digest("hex"),s=U__default.isAbsolute(e)?Filesystem.toUnixPath(U__default.relative(this.workspaceDir,e)):e;return {absolutePath:e,relativePath:s||U__default.basename(e),source:t,contentHash:o,lastModified:r.mtimeMs,size:r.size}}catch(r){return J.error("Failed to scan file",{filePath:e,error:String(r)}),null}}async getFileInfo(e,t){try{let r=await B.readFile(e,"utf-8"),n=await B.stat(e),o=createHash("sha256").update(r).digest("hex"),s=Filesystem.toUnixPath(U__default.relative(this.workspaceDir,e));return {absolutePath:e,relativePath:s,source:t,contentHash:o,lastModified:n.mtimeMs,size:n.size}}catch(r){return J.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=b.create({service:"note"}),Z=class{constructor(e){a(this,"config");a(this,"db");a(this,"pipeline");a(this,"searchEngine");a(this,"graphInterface");a(this,"fileScanner");a(this,"initialized",false);a(this,"dirty",false);a(this,"syncTimer");a(this,"syncConfig");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||getDefaultDatabasePath(xdgData,"note.db");this.config={workspaceDir:t,database:{path:n,walMode:e.database?.walMode??true},vectorDims:e.vectorDims??768,...DEFAULT_NOTE_CHUNK_CONFIG,extraPaths:e.extraPaths,sources:e.sources,search:{...DEFAULT_SEARCH_CONFIG,...e.search},indexer:{...DEFAULT_INDEXER_CONFIG,...e.indexer},sync:{...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 Y(this.db,this.config),this.searchEngine=new Q(this.db,this.config),this.graphInterface=new V(this.db),this.fileScanner=new $({workspaceDir:this.config.workspaceDir,extraPaths:this.config.extraPaths,sources:this.config.sources,ignorePatterns:this.config?.indexer?.ignorePatterns});}async initialize(){if(this.initialized)return;await b.init({logDir:this.config.logDir||U__default.join(this.config.workspaceDir,"logs"),print:process.argv.includes("--print-logs"),dev:false,level:"INFO"}),L.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());}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||U__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=Filesystem.toUnixPath(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=>Filesystem.toUnixPath(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(d){let l=d instanceof Error?d.message:String(d);r.errors.push({filePath:a,error:`Failed to delete document: ${l}`}),A.error("Failed to delete document",{path:a,error:l});}for(let a=0;a<n.length;a++){let d=n[a],l=Filesystem.toUnixPath(d.relativePath);e?.(a+1,n.length,d);try{let g=i.get(l);if(g===void 0){let u=await this.pipeline.process(d.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:l});}else if(g!==d.contentHash){let u=await this.pipeline.process(d.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:l});}else r.filesSkipped++;}catch(g){let u=g instanceof Error?g.message:String(g);r.errors.push({filePath:l,error:u}),A.error("Failed to process document",{path:l,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 Z(E);return await e.initialize(),e}async function cr(E){let{Log:e}=await import('./chunks/log-EPJXYODF.mjs'),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")});}export{$ as FileScanner,R as KnowledgeBaseError,z as KnowledgeBaseErrorCode,L as Llm,Z as NoteKnowledge,st as addWord,ot as closeTokenizer,He as createNoteKnowledge,cr as initLog,nt as initTokenizer,it as isInitialized,be as loadCustomDict,ie as toFtsTokens,oe as toFtsTokensForSearch,Ie as tokenize,Ne as tokenizeForSearch};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easbot/note",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Note Knowledge Base - 非结构化记忆和文档知识库管理系统,支持混合搜索(向量+FTS+图)和 LLM 驱动的知识摄取",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -14,6 +14,23 @@
|
|
|
14
14
|
},
|
|
15
15
|
"./package.json": "./package.json"
|
|
16
16
|
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "tsup --watch --env.NODE_ENV development",
|
|
19
|
+
"build": "tsup --env.NODE_ENV production",
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"test:run": "vitest run",
|
|
22
|
+
"lint": "biome check .",
|
|
23
|
+
"lint:fix": "biome check --write .",
|
|
24
|
+
"lint:report": "biome check --reporter=summary .",
|
|
25
|
+
"format": "biome format .",
|
|
26
|
+
"format:fix": "biome format --write .",
|
|
27
|
+
"type-check": "tsc --noEmit",
|
|
28
|
+
"clean": "npx rimraf dist node_modules",
|
|
29
|
+
"prepare": "echo norun",
|
|
30
|
+
"prepublishOnly": "pnpm build",
|
|
31
|
+
"publish:npm": "bash scripts/publish.sh",
|
|
32
|
+
"publish:npm:win": "powershell -ExecutionPolicy Bypass -File scripts/publish.ps1"
|
|
33
|
+
},
|
|
17
34
|
"keywords": [
|
|
18
35
|
"easbot",
|
|
19
36
|
"knowledge-base",
|
|
@@ -50,14 +67,14 @@
|
|
|
50
67
|
"@ai-sdk/provider-utils": "^4.0.21",
|
|
51
68
|
"@ai-sdk/openai-compatible": "2.0.37",
|
|
52
69
|
"@ai-sdk/anthropic": "3.0.63",
|
|
70
|
+
"@easbot/local-model-sdk": "workspace:*",
|
|
71
|
+
"@easbot/ollama-sdk": "workspace:*",
|
|
72
|
+
"@easbot/types": "workspace:*",
|
|
73
|
+
"@easbot/utils": "workspace:*",
|
|
53
74
|
"ai": "^6.0.136",
|
|
54
75
|
"better-sqlite3": "^12.9.0",
|
|
55
76
|
"jieba-wasm": "^2.4.0",
|
|
56
|
-
"xdg-basedir": "^5.1.0"
|
|
57
|
-
"@easbot/local-model-sdk": "0.1.14",
|
|
58
|
-
"@easbot/ollama-sdk": "0.1.14",
|
|
59
|
-
"@easbot/types": "0.1.14",
|
|
60
|
-
"@easbot/utils": "0.1.14"
|
|
77
|
+
"xdg-basedir": "^5.1.0"
|
|
61
78
|
},
|
|
62
79
|
"devDependencies": {
|
|
63
80
|
"@biomejs/biome": "^2.4.8",
|
|
@@ -74,20 +91,5 @@
|
|
|
74
91
|
},
|
|
75
92
|
"publishConfig": {
|
|
76
93
|
"access": "public"
|
|
77
|
-
},
|
|
78
|
-
"scripts": {
|
|
79
|
-
"dev": "tsup --watch --env.NODE_ENV development",
|
|
80
|
-
"build": "tsup --env.NODE_ENV production",
|
|
81
|
-
"test": "vitest",
|
|
82
|
-
"test:run": "vitest run",
|
|
83
|
-
"lint": "biome check .",
|
|
84
|
-
"lint:fix": "biome check --write .",
|
|
85
|
-
"lint:report": "biome check --reporter=summary .",
|
|
86
|
-
"format": "biome format .",
|
|
87
|
-
"format:fix": "biome format --write .",
|
|
88
|
-
"type-check": "tsc --noEmit",
|
|
89
|
-
"clean": "npx rimraf dist node_modules",
|
|
90
|
-
"publish:npm": "bash scripts/publish.sh",
|
|
91
|
-
"publish:npm:win": "powershell -ExecutionPolicy Bypass -File scripts/publish.ps1"
|
|
92
94
|
}
|
|
93
|
-
}
|
|
95
|
+
}
|