toolnet-memory 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle/mcp.js CHANGED
@@ -1,7 +1,56 @@
1
- import"dotenv/config";import{existsSync as cr,readFileSync as lr}from"node:fs";import{homedir as pr}from"node:os";import{join as dr}from"node:path";function mr(o){let e=o.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
- `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function fr(){let o=process.env.TOOLNET_GLOBAL_ENV??dr(pr(),".config","toolnet-memory",".env");if(!cr(o))return;let e=lr(o,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let n=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)&&process.env[n]===void 0&&(process.env[n]=mr(r.slice(s+1)))}}fr();function _(o,e){return o===void 0?e:["1","true","yes","on"].includes(o.toLowerCase())}function O(o,e){if(!o)return e;let t=Number(o);return Number.isFinite(t)?t:e}function $e(){return{memory:{autoCapture:_(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:_(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:_(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:_(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:O(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:O(process.env.MEMORY_RERANK_TOP,10),finalContext:O(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:O(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:_(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:O(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var ur={critical:100,high:75,normal:50,temporary:20};function De(o){return ur[o]}function Ge(o,e){let t=e.toLowerCase();return t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c")||t.includes("must not")||t.includes("critical")?"critical":o==="rule"||o==="decision"?"high":o==="todo"?"normal":o==="activity"||o==="summary"?"temporary":"normal"}import{createHash as gr}from"node:crypto";import{existsSync as Ee,mkdirSync as hr,readFileSync as yr,renameSync as Sr,writeFileSync as br}from"node:fs";import{basename as xr,dirname as U,join as J,parse as Be,resolve as F}from"node:path";var qe=".toolnet",Cr="project.json";function wr(o){return gr("sha256").update(o).digest("hex").slice(0,16)}function Pe(o){return J(o,qe,Cr)}function vr(o){return Ee(Pe(o))}function Er(o,e){let t=F(o),r=Be(t).root;for(;;){if(vr(t))return t;if(t===r||e&&t===F(e))break;let s=U(t);if(s===t)break;t=s}return null}function Pr(o){let e=F(o),t=Be(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>Ee(J(e,n))))return e;if(e===t)break;let s=U(e);if(s===e)break;e=s}return F(o)}function jr(o){let e;try{e=JSON.parse(yr(o,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${o}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${o}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${o}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${o}`);let r=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:U(U(o)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function ze(o,e){let t=J(o,qe);hr(t,{recursive:!0});let r=Pe(o),s=`${r}.tmp-${process.pid}`;br(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Sr(s,r)}function Ke(o,e){return{id:o.id,name:o.name,remote:o.remote,rootPath:e,createdAt:o.createdAt,updatedAt:o.updatedAt,graphVersion:o.graphVersion,memoryVersion:o.memoryVersion,metadata:o.metadata}}var V=class{detect(e=process.cwd()){let t=F(e),r=Pr(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>Ee(J(r,p))),i=Er(t,n?r:void 0);if(i){let p=Pe(i),m=jr(p);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),ze(i,m)),Ke(m,i)}let a=new Date().toISOString(),c=xr(r),l={version:1,id:wr(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return ze(r,l),Ke(l,r)}};import{randomUUID as Ir}from"node:crypto";var kr=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],Y=class{scan(e){let t=[];for(let r of kr){let s=new RegExp(r.regex.source,r.regex.flags);for(let n of e.matchAll(s))t.push({type:r.type,value:n[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var L=class{scanner=new Y;sanitize(e){let t=e,r=this.scanner.scan(e),s=new Set;for(let n of r)s.add(n.type),t=t.split(n.value).join(`[REDACTED:${n.type}]`);return{text:t,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[r,s]of Object.entries(e)){let n=r.toLowerCase();n.includes("password")||n.includes("secret")||n.includes("token")||n.includes("cookie")||n.includes("authorization")?t[r]="[REDACTED]":t[r]=this.sanitizeValue(s)}return t}return e}};var Rr=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Tr=new Set(["d\xF9ng","s\u1EED","d\u1EE5ng","use","using","the","a","an","cho","v\xE0","l\xE0","c\u1EE7a","to","for","with","quy\u1EBFt","\u0111\u1ECBnh"]);function He(o){return new Set(o.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Tr.has(e)))}function Mr(o,e){let t=He(o),r=He(e);if(t.size===0||r.size===0)return 0;let s=0;for(let i of t)r.has(i)&&s++;let n=new Set([...t,...r]).size;return s/n}function We(o){return new Set(o.tags.filter(e=>!Rr.has(e.toLowerCase())))}var Q=class{findSuperseded(e,t){if(e.type!=="rule"&&e.type!=="decision")return[];let r=typeof e.metadata?.topic=="string"?e.metadata.topic:void 0,s=We(e);return t.filter(n=>{if(n.id===e.id||n.projectId!==e.projectId||n.type!==e.type||n.metadata?.supersededBy)return!1;let i=typeof n.metadata?.topic=="string"?n.metadata.topic:void 0;if(r&&i&&r===i)return!0;let a=We(n);for(let c of s)if(a.has(c))return!0;return Mr(e.content,n.content)>=.6})}};var Ar={critical:100,high:75,normal:50,temporary:20},Lr={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function Ue(o,e,t=new Date){let r;if(e==="temporary"&&(r=30),o==="activity"&&(r=Math.min(r??14,14)),o==="summary"&&(r=Math.min(r??30,30)),!!r)return new Date(t.getTime()+r*864e5).toISOString()}function je(o,e=Date.now()){return o.expiresAt?new Date(o.expiresAt).getTime()<=e:!1}function Nr(o){return!!o.metadata?.supersededBy}function ke(o,e=Date.now()){return!je(o,e)&&!Nr(o)}function $(o,e=Date.now()){if(!ke(o,e))return 0;let t=Ar[o.importance];if(o.importance==="critical")return t;let r=Lr[o.type]??180,n=Math.max(0,e-new Date(o.updatedAt).getTime())/864e5,i=Math.pow(.5,n/r);return t*i}var Z=class{memories=new Map;sanitizer=new L;conflicts=new Q;remember(e){let t=new Date().toISOString(),r=this.sanitizer.sanitize(e.content.trim()).text,s=e.importance??Ge(e.type,r),n={id:Ir(),projectId:e.projectId,type:e.type,content:r,importance:s,importanceScore:De(s),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??Ue(e.type,s,new Date(t)),metadata:this.sanitizer.sanitizeValue(e.metadata)},i=this.conflicts.findSuperseded(n,this.list(e.projectId));if(i.length){n.metadata={...n.metadata??{},supersedes:i.map(a=>a.id)};for(let a of i)a.updatedAt=t,a.metadata={...a.metadata??{},supersededBy:n.id,supersededAt:t},this.memories.set(a.id,a)}return this.memories.set(n.id,n),n}importRecords(e){let t=0;for(let r of e)r?.id&&(this.memories.set(r.id,r),t++);return t}exportProject(e){return this.listAll(e)}get(e){return this.memories.get(e)}delete(e){return this.memories.delete(e)}listAll(e){return[...this.memories.values()].filter(t=>t.projectId===e).sort((t,r)=>r.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>ke(t))}recent(e,t=10){return this.list(e).slice(0,t)}byType(e,t){return this.list(e).filter(r=>r.type===t)}search(e){let t=e.query.trim().toLowerCase(),r=e.limit??10,s=t.split(/\s+/).filter(Boolean);return this.list(e.projectId).filter(n=>{if(e.types&&!e.types.includes(n.type))return!1;let i=$(n);return!(e.minImportanceScore&&i<e.minImportanceScore||e.tags?.length&&!e.tags.some(c=>n.tags.includes(c)))}).map(n=>{let i=n.content.toLowerCase(),a=s.filter(p=>i.includes(p)).length,c=s.length===0?0:a/s.length,l=$(n)/500;return{memory:n,score:c+l,source:"memory"}}).filter(n=>t.length===0||n.score>0).sort((n,i)=>i.score-n.score).slice(0,r)}pruneExpired(e,t=Date.now()){let r=0;for(let[s,n]of this.memories)n.projectId===e&&je(n,t)&&(this.memories.delete(s),r++);return r}pruneSuperseded(e,t=30,r=Date.now()){let s=0,n=t*864e5;for(let[i,a]of this.memories){if(a.projectId!==e)continue;let c=a.metadata?.supersededAt;if(typeof c!="string")continue;r-new Date(c).getTime()>=n&&(this.memories.delete(i),s++)}return s}clearProject(e){let t=0;for(let[r,s]of this.memories)s.projectId===e&&(this.memories.delete(r),t++);return t}};function N(o){return o.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var X=class{score(e,t){let r=N(e),s=N([t.content,...t.tags??[],t.type].join(" "));if(r.length===0||s.length===0)return 0;let n=new Map;for(let a of s)n.set(a,(n.get(a)??0)+1);let i=0;for(let a of r){let c=n.get(a)??0;c!==0&&(i+=1+Math.log(1+c))}return i/r.length}};function Ve(o,e=Date.now()){let t=o.updatedAt??o.createdAt,r=new Date(t).getTime();if(!Number.isFinite(r))return 0;let s=Math.max(0,e-r)/864e5;return Math.exp(-Math.LN2*s/30)}function Je(o){return $(o)/100}var _r={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function Ye(o){return _r[o]??.4}var ee=class{analyze(e){let t=e.toLowerCase(),r=[];return(t.includes("quy\u1EBFt \u0111\u1ECBnh")||t.includes("decision")||t.includes("\u0111\xE3 ch\u1ECDn"))&&r.push("decision"),(t.includes("todo")||t.includes("c\u1EA7n l\xE0m")||t.includes("ti\u1EBFp theo")||t.includes("ch\u01B0a xong"))&&r.push("todo"),(t.includes("quy t\u1EAFc")||t.includes("rule")||t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c"))&&r.push("rule"),(t.includes("t\xF3m t\u1EAFt")||t.includes("summary")||t.includes("\u0111\xE3 l\xE0m"))&&r.push("summary"),{query:e,preferredTypes:r}}};var te=class{bm25=new X;analyzer=new ee;search(e,t,r={}){let s=r.topK??8,n=r.minScore??.05,i=this.analyzer.analyze(e),a=[];for(let c of t){if(r.types?.length&&!r.types.includes(c.type))continue;let l=this.bm25.score(e,c),p=Ve(c),m=Je(c),d=Ye(c.type);i.preferredTypes.includes(c.type)&&(d=Math.min(1,d+.25));let f=l*.55+m*.2+p*.15+d*.1;l<=0||f<n||a.push({memory:c,score:f,scores:{keyword:l,recency:p,importance:m,type:d}})}return a.sort((c,l)=>l.score-c.score).slice(0,s)}};var re=class{build(e,t=6e3){let r=[],s=0;for(let n of e){let i=n.memory,a=[`[${i.type.toUpperCase()}]`,i.content].join(" ");if(s+a.length>t)break;r.push(a),s+=a.length}return r.join(`
4
- `)}};var oe=class{constructor(e){this.memory=e}memory;searcher=new te;contextBuilder=new re;search(e,t,r={}){return this.searcher.search(t,this.memory.list(e),r)}context(e,t,r={}){let s=this.search(e,t,r);return this.contextBuilder.build(s)}};var se=class{constructor(e){this.options=e}options;name="huggingface";dimensions=384;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=`https://router.huggingface.co/hf-inference/models/${this.options.model}/pipeline/feature-extraction`,r=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.options.token}`,"Content-Type":"application/json"},body:JSON.stringify({inputs:e,options:{wait_for_model:!0}})});if(!r.ok)throw new Error(`HF embedding failed: ${r.status} ${await r.text()}`);let s=await r.json();if(!Array.isArray(s))throw new Error("HF embedding returned invalid response");return s.map(n=>Or(n))}};function Or(o){if(!Array.isArray(o))throw new Error("Invalid embedding");if(o.length>0&&typeof o[0]=="number")return o;if(o.length>0&&Array.isArray(o[0])){let e=o;if(e.length===0)return[];let t=e[0].length,r=new Array(t).fill(0);for(let s of e)for(let n=0;n<t;n++)r[n]+=s[n]??0;for(let s=0;s<t;s++)r[s]/=e.length;return r}throw new Error("Unsupported embedding shape")}import{createHash as Fr}from"node:crypto";var ne=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),r=e.toLowerCase().split(/\s+/).filter(Boolean);for(let s of r){let i=Fr("sha256").update(s).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return $r(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function $r(o){let e=Math.sqrt(o.reduce((t,r)=>t+r*r,0));return e===0?o:o.map(t=>t/e)}var Re=class{constructor(e,t=new ne){this.primary=e;this.fallback=t}primary;fallback;name="resilient";async embed(e){if(this.primary)try{return await this.primary.embed(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embed(e)}async embedMany(e){if(this.primary)try{return await this.primary.embedMany(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embedMany(e)}};function Qe(){let o=process.env.HF_TOKEN,e=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",t=o?new se({token:o,model:e}):null;return new Re(t)}import*as b from"typescript";var I=class{symbols=new Map;edges=new Map;addSymbol(e){this.symbols.set(e.id,e)}addEdge(e){this.edges.set(e.id,e)}getSymbol(e){return this.symbols.get(e)}findByName(e,t){return[...this.symbols.values()].filter(r=>r.projectId===e&&(r.name===t||r.qualifiedName===t))}allSymbols(e){return[...this.symbols.values()].filter(t=>t.projectId===e)}allEdges(e){return[...this.edges.values()].filter(t=>t.projectId===e)}import(e,t){for(let r of e)this.addSymbol(r);for(let r of t)this.addEdge(r)}clearProject(e){for(let[t,r]of this.symbols)r.projectId===e&&this.symbols.delete(t);for(let[t,r]of this.edges)r.projectId===e&&this.edges.delete(t)}};function ie(o,e){let t=o.allSymbols(e),r=o.allEdges(e),s=i=>t.filter(a=>a.type===i).length,n=i=>r.filter(a=>a.type===i).length;return{files:s("file"),classes:s("class"),interfaces:s("interface"),functions:s("function"),methods:s("method"),properties:s("property"),routes:s("route"),symbols:t.length,edges:r.length,calls:n("CALLS"),callReferences:n("CALL_REFERENCE"),imports:n("IMPORTS"),inherits:n("INHERITS"),implements:n("IMPLEMENTS"),usesType:n("USES_TYPE"),tests:n("TESTS"),routeEdges:n("ROUTE"),writes:n("WRITES")}}var ae=class{constructor(e){this.graph=e}graph;callees(e,t,r=3){return this.walk(e,t,"out",r)}callers(e,t,r=3){return this.walk(e,t,"in",r)}walk(e,t,r,s){let n=[],i=new Set([t]),a=[{id:t,depth:0}],c=this.graph.allEdges(e).filter(l=>l.type==="CALLS"||l.type==="CALL_REFERENCE");for(;a.length;){let l=a.shift();if(l.depth>=s)continue;let p=r==="out"?c.filter(m=>m.from===l.id):c.filter(m=>m.to===l.id);for(let m of p){let d=r==="out"?m.to:m.from;if(i.has(d))continue;i.add(d);let f=this.graph.getSymbol(d);if(!f)continue;let h=l.depth+1;n.push({symbol:f,depth:h}),a.push({id:d,depth:h})}}return n}};var ce=class{constructor(e){this.graph=e}graph;findSymbol(e,t){return this.graph.findByName(e,t)}findCallers(e,t){return this.graph.allEdges(e).filter(s=>s.type==="CALLS"&&s.to===t).map(s=>s.from).map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}};var le=class{constructor(e){this.graph=e}graph;analyze(e,t,r=4){let s=this.graph.allEdges(e),n=new Set([t]),i=[{id:t,depth:0}],a=[];for(;i.length;){let c=i.shift();if(c.depth>=r)continue;let l=s.filter(p=>p.to===c.id&&["CALLS","IMPORTS","INHERITS","IMPLEMENTS"].includes(p.type));for(let p of l){if(n.has(p.from))continue;n.add(p.from);let m=this.graph.getSymbol(p.from);if(!m)continue;let d=c.depth+1;a.push({symbol:m,depth:d,relation:p.type}),i.push({id:p.from,depth:d})}}return a}};function Kr(o,e){return e.ranges.length===0?!0:typeof o.startLine!="number"||typeof o.endLine!="number"?!1:e.ranges.some(t=>o.startLine<=t.endLine&&o.endLine>=t.startLine)}var pe=class{constructor(e){this.graph=e}graph;map(e,t){let r=this.graph.allSymbols(e),s=[];for(let n of t){let i=r.filter(l=>l.filePath===n.filePath),c=i.filter(l=>l.type!=="file").filter(l=>Kr(l,n));if(c.length===0){let l=i.find(p=>p.type==="file");l&&s.push({symbol:l,fileStatus:n.status,direct:!0});continue}for(let l of c)s.push({symbol:l,fileStatus:n.status,direct:!0})}return s}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var Br={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function qr(o){return o>=30?"CRITICAL":o>=16?"HIGH":o>=6?"MEDIUM":"LOW"}function Ze(o){let e=o.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var de=class{constructor(e){this.graph=e}graph;analyze(e,t,r=4){let s=this.graph.allEdges(e),n=new Map,i=0;for(let p of t){p.fileStatus==="deleted"?i+=8:p.fileStatus==="renamed"?i+=5:i+=2,p.symbol.type==="interface"&&(i+=5),p.symbol.type==="class"&&(i+=3);let m=new Set([p.symbol.id]),d=[{id:p.symbol.id,depth:0}];for(;d.length;){let f=d.shift();if(f.depth>=r)continue;let h=s.filter(y=>y.to===f.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(y.type));for(let y of h){if(m.has(y.from))continue;m.add(y.from);let E=this.graph.getSymbol(y.from);if(!E)continue;let P=f.depth+1,W=`${p.symbol.id}:${E.id}`;n.set(W,{symbol:E,relation:y.type,depth:P,sourceSymbolId:p.symbol.id});let T=Br[y.type]??1;i+=Math.max(1,T-(P-1)),d.push({id:E.id,depth:P})}}}let a=[...n.values()].sort((p,m)=>p.depth-m.depth),c=[...new Set(a.map(p=>p.symbol.filePath))],l=c.filter(Ze);return l.length===0&&l.push(...c.filter(p=>!Ze(p)).slice(0,10)),{risk:qr(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:l}}};import{execFile as Hr}from"node:child_process";import{promisify as Wr}from"node:util";var Te=Wr(Hr);function Ur(o){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let r of o.matchAll(t)){let s=Number(r[1]),n=Number(r[2]??1);e.push({startLine:s,endLine:Math.max(s,s+n-1)})}return e}function Vr(o){return o.startsWith("A")?"added":o.startsWith("D")?"deleted":o.startsWith("R")?"renamed":"modified"}async function Xe(o){let e="";try{e=(await Te("git",["diff","HEAD","--name-status","--no-renames"],{cwd:o,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let r of e.split(/\r?\n/).filter(Boolean)){let[s,...n]=r.split(" "),i=n.at(-1);if(!i)continue;let a="";try{a=(await Te("git",["diff","HEAD","--unified=0","--",i],{cwd:o,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:Vr(s),ranges:Ur(a)})}try{let r=await Te("git",["ls-files","--others","--exclude-standard"],{cwd:o});for(let s of r.stdout.split(/\r?\n/).filter(Boolean))t.some(n=>n.filePath===s)||t.push({filePath:s,status:"added",ranges:[]})}catch{}return t}var me=class{constructor(e){this.graph=e;this.mapper=new pe(e),this.blast=new de(e)}graph;mapper;blast;async analyzeGitDiff(e,t,r={}){let s=await Xe(t),n=this.mapper.map(e,s),i=this.blast.analyze(e,n,r.maxDepth??4);return{mode:"git_diff",changes:s,...i}}analyzeFile(e,t,r={}){let s=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,s,r.maxDepth??4)}}};var D=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};import{createHash as Jr}from"node:crypto";import{readFile as Yr}from"node:fs/promises";import{join as Qr}from"node:path";function et(o){return Jr("sha256").update(o).digest("hex")}var fe=class{sanitizer=new L;async build(e,t,r,s={}){let n=s.maxLines??80,i=s.overlapLines??10,a=new Map;for(let l of r){let p=a.get(l.filePath)??[];p.push(l),a.set(l.filePath,p)}let c=[];for(let[l,p]of a){let m;try{m=await Yr(Qr(t,l),"utf8")}catch{continue}let d=m.split(/\r?\n/),f=p.filter(h=>h.type!=="file"&&typeof h.startLine=="number"&&typeof h.endLine=="number");if(f.length>0)for(let h of f)c.push(...this.chunkRange({projectId:e,filePath:l,lines:d,symbol:h,startLine:h.startLine,endLine:h.endLine,maxLines:n,overlapLines:i}));else c.push(...this.chunkRange({projectId:e,filePath:l,lines:d,startLine:1,endLine:Math.max(1,d.length),maxLines:n,overlapLines:i}))}return c}chunkRange(e){let{projectId:t,filePath:r,lines:s,symbol:n,maxLines:i}=e,a=Math.min(e.overlapLines,Math.max(0,i-1)),c=Math.max(1,e.startLine),l=Math.min(s.length,Math.max(c,e.endLine)),p=[],m=c,d=0;for(;m<=l;){let f=Math.min(l,m+i-1),h=s.slice(m-1,f).join(`
5
- `).trim();if(h){let y=this.sanitizer.sanitize(h).text,E=et(y),P=[t,r,n?.id??"file",String(d),E].join(":");p.push({id:et(P).slice(0,32),projectId:t,filePath:r,symbolId:n?.id,symbolName:n?.qualifiedName??n?.name,symbolType:n?.type,startLine:m,endLine:f,content:y,contentHash:E})}if(f>=l)break;m=f-a+1,d++}return p}};var ue=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","chunks","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};var ge=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};var he=class{records=new Map;upsert(e){this.records.set(e.id,e)}get(e){return this.records.get(e)}has(e){return this.records.has(e)}remove(e){return this.records.delete(e)}clearProject(e){let t=0;for(let[r,s]of this.records)s.projectId===e&&(this.records.delete(r),t++);return t}exportProject(e){return[...this.records.values()].filter(t=>t.projectId===e)}importRecords(e){let t=0;for(let r of e)!r?.id||!r?.projectId||!Array.isArray(r.vector)||(this.records.set(r.id,r),t++);return t}search(e,t,r=10){let s=[];for(let n of this.records.values()){if(n.projectId!==e)continue;let i=Zr(t,n.vector);s.push({id:n.id,score:i,metadata:n.metadata})}return s.sort((n,i)=>i.score-n.score).slice(0,r)}size(){return this.records.size}};function Zr(o,e){if(o.length===0||e.length===0||o.length!==e.length)return 0;let t=0,r=0,s=0;for(let n=0;n<o.length;n++){let i=o[n]??0,a=e[n]??0;t+=i*a,r+=i*i,s+=a*a}return r===0||s===0?0:t/(Math.sqrt(r)*Math.sqrt(s))}function tt(o,e){let t=o.toLowerCase().replaceAll("\\","/"),r=e.toLowerCase(),s=/\b(test|tests|spec|fixture|mock)\b/.test(r);return(t.startsWith("tests/")||t.includes("/tests/")||t.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(t))&&!s?.35:t.includes("/generated/")||t.includes(".generated.")?.25:1}var ye=class{constructor(e){this.options=e}options;vectors=new he;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:r,embeddings:s,graph:n,model:i}=this.options,a=new ue(r),c=new ge(r),l=await new fe().build(e,t,n.allSymbols(e));this.chunks.clear();for(let S of l)this.chunks.set(S.id,S);let p=await a.load(e),m=!p||p.chunks.length!==l.length||p.chunks.some(S=>!this.chunks.has(S.id));m&&await a.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:l});let d=await c.load(e),f=0;d&&d.model===i&&(f=this.vectors.importRecords(d.records));let h=new Set(l.map(S=>S.id)),y=0;for(let S of this.vectors.exportProject(e))h.has(S.id)||this.vectors.remove(S.id)&&y++;let E=l.filter(S=>{let M=this.vectors.get(S.id);return M?M.metadata?.contentHash!==S.contentHash:!0}),P=0,W=8,T=this.vectors.exportProject(e)[0]?.vector.length;for(let S=0;S<E.length;S+=W){let M=E.slice(S,S+W),ir=M.map(v=>[`file: ${v.filePath}`,v.symbolName?`symbol: ${v.symbolName}`:"",v.symbolType?`type: ${v.symbolType}`:"",v.content].filter(Boolean).join(`
6
- `)),ar=await s.embedMany(ir);for(let v=0;v<M.length;v++){let k=M[v],A=ar[v];if(!(!k||!A||A.length===0)){if(T===void 0&&(T=A.length),A.length!==T){console.warn(`[code-semantic] skip dimension mismatch: ${A.length} != ${T}`);continue}this.vectors.upsert({id:k.id,projectId:e,vector:A,metadata:{contentHash:k.contentHash,filePath:k.filePath,symbolName:k.symbolName,symbolType:k.symbolType,startLine:k.startLine,endLine:k.endLine}}),P++}}}let ve=this.vectors.exportProject(e),Fe=P>0||y>0||!d||d.model!==i;return Fe&&await c.save({version:1,projectId:e,model:i,dimensions:ve[0]?.vector.length??T??0,updatedAt:new Date().toISOString(),records:ve}),{chunks:l.length,vectorsLoaded:f,vectorsIndexed:P,vectorsRemoved:y,totalVectors:ve.length,savedChunks:m,savedVectors:Fe}}async search(e,t=8){let r=await this.options.embeddings.embed(e),s=this.vectors.search(this.options.projectId,r,Math.max(t*4,20)),n=new Set(N(e)),i=[];for(let a of s){let c=this.chunks.get(a.id);if(!c)continue;let l=new Set(N([c.filePath,c.symbolName??"",c.symbolType??"",c.content].join(" "))),p=0;for(let y of n)l.has(y)&&p++;let m=n.size===0?0:p/n.size,d=Math.max(0,a.score),f=tt(c.filePath,e),h=(d*.75+m*.25)*f;i.push({chunk:c,score:h,vectorScore:d,lexicalScore:m})}return i.sort((a,c)=>c.score-a.score).slice(0,t)}size(){return this.chunks.size}};import*as x from"typescript";import*as u from"typescript";var vi=new Set([u.SyntaxKind.EqualsToken,u.SyntaxKind.PlusEqualsToken,u.SyntaxKind.MinusEqualsToken,u.SyntaxKind.AsteriskEqualsToken,u.SyntaxKind.SlashEqualsToken,u.SyntaxKind.PercentEqualsToken,u.SyntaxKind.QuestionQuestionEqualsToken,u.SyntaxKind.AmpersandAmpersandEqualsToken,u.SyntaxKind.BarBarEqualsToken]);function Xr(o){return o.replaceAll("\\","/").toLowerCase()}var G=class{constructor(e){this.graph=e}graph;detect(e){let t=this.graph.allSymbols(e),r=this.graph.allEdges(e),s=[];for(let i of t){if(i.type!=="route"&&i.type!=="file")continue;let a=this.classify(i,r);a&&s.push({symbolId:i.id,filePath:i.filePath,name:i.name,kind:a.kind,score:a.score,reasons:a.reasons})}let n=new Map;for(let i of s){let a=i.kind==="route"?i.symbolId:i.filePath,c=n.get(a);(!c||i.score>c.score)&&n.set(a,i)}return[...n.values()].sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath))}classify(e,t){let r=Xr(e.filePath),s=[];if(e.type==="route")return{kind:"route",score:100,reasons:["HTTP route"]};let n=null,i=0;if(r.startsWith("bin/"))n="cli",i=100,s.push("bin executable");else if(/(^|\/)(cli)\.[^.]+$/.test(r))n="cli",i=90,s.push("CLI entry file");else if(/(^|\/)(main|server)\.[^.]+$/.test(r))n="main",i=90,s.push("main/server file");else if(r.includes("/runtime/")&&/(^|\/)(bootstrap|index)\.[^.]+$/.test(r))n="runtime",i=75,s.push("runtime bootstrap");else if(/(^|\/)index\.[^.]+$/.test(r)){let c=t.filter(p=>p.to===e.id&&p.type!=="DEFINES").length,l=t.filter(p=>p.from===e.id&&p.type!=="DEFINES").length;(r.startsWith("packages/")||c===0||l>0)&&(n="package",i=r.startsWith("packages/")?70:55,s.push("package/public index"))}return n?(t.filter(c=>c.to===e.id&&c.type!=="DEFINES").length===0&&(i+=10,s.push("no incoming dependency")),{kind:n,score:i,reasons:s}):null}};var Se=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),rt=new Set(["CALLS","CALL_REFERENCE"]),w=class{constructor(e){this.graph=e}graph;findSymbols(e,t){let r=t.trim().toLowerCase();return r?this.graph.allSymbols(e).filter(s=>s.name.toLowerCase().includes(r)||(s.qualifiedName?.toLowerCase().includes(r)??!1)||s.filePath.toLowerCase().includes(r)).sort((s,n)=>{let i=s.name.toLowerCase()===r,a=n.name.toLowerCase()===r;return i!==a?i?-1:1:s.filePath.localeCompare(n.filePath)}):[]}callers(e,t){return this.relatedIncoming(e,t,rt)}callees(e,t){return this.relatedOutgoing(e,t,rt)}dependents(e,t){return this.relatedIncoming(e,t,Se)}dependencies(e,t){return this.relatedOutgoing(e,t,Se)}neighborhood(e,t,r=1){let s=this.graph.getSymbol(t);return!s||s.projectId!==e?null:{center:s,incoming:this.walk(e,t,"incoming",r),outgoing:this.walk(e,t,"outgoing",r)}}shortestPath(e,t,r,s=12){let n=this.graph.getSymbol(t),i=this.graph.getSymbol(r);if(!n||!i||n.projectId!==e||i.projectId!==e)return{found:!1,distance:-1,symbols:[],edges:[]};if(t===r)return{found:!0,distance:0,symbols:[n],edges:[]};let a=this.graph.allEdges(e).filter(d=>Se.has(d.type)),c=new Map;for(let d of a){let f=c.get(d.from)??[];f.push(d),c.set(d.from,f)}let l=[{id:t,depth:0}],p=new Set([t]),m=new Map;for(;l.length>0;){let d=l.shift();if(!(d.depth>=s)){for(let f of c.get(d.id)??[])if(!p.has(f.to)){if(p.add(f.to),m.set(f.to,{node:d.id,edge:f}),f.to===r)return this.buildPath(t,r,m);l.push({id:f.to,depth:d.depth+1})}}}return{found:!1,distance:-1,symbols:[],edges:[]}}buildPath(e,t,r){let s=[t],n=[],i=t;for(;i!==e;){let c=r.get(i);if(!c)return{found:!1,distance:-1,symbols:[],edges:[]};n.push(c.edge),i=c.node,s.push(i)}s.reverse(),n.reverse();let a=s.map(c=>this.graph.getSymbol(c)).filter(c=>!!c);return{found:!0,distance:n.length,symbols:a,edges:n}}walk(e,t,r,s){let n=this.graph.allEdges(e).filter(l=>Se.has(l.type)),i=[{id:t,depth:0}],a=new Set([t]),c=[];for(;i.length>0;){let l=i.shift();if(!(l.depth>=s))for(let p of n){if(!(r==="incoming"?p.to===l.id:p.from===l.id))continue;let d=r==="incoming"?p.from:p.to;if(a.has(d))continue;let f=this.graph.getSymbol(d);f&&(a.add(d),c.push({symbol:f,depth:l.depth+1,via:p}),i.push({id:d,depth:l.depth+1}))}}return c}relatedIncoming(e,t,r){return[...new Set(this.graph.allEdges(e).filter(n=>n.to===t&&r.has(n.type)).map(n=>n.from))].map(n=>this.graph.getSymbol(n)).filter(n=>!!n)}relatedOutgoing(e,t,r){return[...new Set(this.graph.allEdges(e).filter(n=>n.from===t&&r.has(n.type)).map(n=>n.to))].map(n=>this.graph.getSymbol(n)).filter(n=>!!n)}};var ot=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function Me(o){return o.replaceAll("\\","/").toLowerCase()}function eo(o){let e=Me(o);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function to(o){let e=Me(o.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var z=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),r=this.graph.allEdges(e),s=new Set(new G(this.graph).detect(e).map(i=>i.symbolId)),n=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||eo(i.filePath)||s.has(i.id)||to(i)||r.filter(f=>f.to===i.id&&ot.has(f.type)).length>0)continue;let c=r.filter(f=>f.from===i.id&&ot.has(f.type)),l=["no incoming usage edge"],p=50;(i.type==="function"||i.type==="method")&&(p+=20,l.push("callable symbol")),i.type==="property"&&(p-=15),c.length===0&&(p+=10,l.push("no outgoing dependency")),Me(i.filePath).includes("/internal/")&&(p+=10,l.push("internal implementation")),i.name.startsWith("_")&&(p+=5);let d=p>=75?"high":p>=55?"medium":"low";n.push({symbolId:i.id,name:i.name,qualifiedName:i.qualifiedName,type:i.type,filePath:i.filePath,startLine:i.startLine,confidence:d,score:p,reasons:l})}return n.sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath)||i.name.localeCompare(a.name))}};var ro=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),K=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),r=this.graph.allEdges(e).filter(i=>ro.has(i.type)),s=new Map(t.map(i=>[i.id,i]));return[...new Set(t.map(i=>i.filePath))].sort().map(i=>{let a=new Set,c=new Set,l=0,p=0;for(let m of r){let d=s.get(m.from),f=s.get(m.to);!d||!f||d.filePath===f.filePath||(d.filePath===i&&(a.add(f.filePath),l++),f.filePath===i&&(c.add(d.filePath),p++))}return{filePath:i,dependencies:[...a].sort(),dependents:[...c].sort(),outgoingEdges:l,incomingEdges:p}})}};import{homedir as jo}from"node:os";import{join as ko}from"node:path";import{DeleteObjectCommand as oo,GetObjectCommand as so,HeadObjectCommand as no,ListObjectsV2Command as io,PutObjectCommand as ao,S3Client as co}from"@aws-sdk/client-s3";import{getSignedUrl as lo}from"@aws-sdk/s3-request-presigner";var be=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new co({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,r="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new ao({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await lo(this.client,new so({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new no({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new oo({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new io({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of s.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};import{access as st,mkdir as po,readFile as mo,readdir as fo,rm as uo,stat as nt,writeFile as go}from"node:fs/promises";import{dirname as ho,join as yo,relative as it,resolve as So}from"node:path";var B=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return So(this.root,t)}async put(e,t){let r=this.path(e);await po(ho(r),{recursive:!0}),await go(r,t)}async get(e){try{return await mo(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await st(this.path(e)),!0}catch{return!1}}async delete(e){await uo(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await st(t)}catch{return r}let s=async i=>{let a=await fo(i,{withFileTypes:!0});for(let c of a){let l=yo(i,c.name);if(c.isDirectory()){await s(l);continue}let p=await nt(l);r.push({key:it(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},n=await nt(t);return n.isDirectory()?await s(t):r.push({key:it(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};import{DeleteObjectCommand as bo,GetObjectCommand as xo,HeadObjectCommand as Co,ListObjectsV2Command as wo,PutObjectCommand as vo,S3Client as Eo}from"@aws-sdk/client-s3";import{getSignedUrl as Po}from"@aws-sdk/s3-request-presigner";var q=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Eo({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,r="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new vo({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await Po(this.client,new xo({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Co({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new bo({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new wo({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of s.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};function Ae(o,e){return console.warn(e),new B(o)}function at(o){let e=o.localRoot??ko(jo(),".toolnet-memory","storage");if(o.provider==="r2"){let t=o.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new q({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ae(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(o.provider==="s3"){let t=o.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new q({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ae(e,"[storage] S3 credentials missing. Using local fallback.")}if(o.provider==="huggingface"){let t=o.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new be({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ae(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new B(e)}var xe=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let r=JSON.parse(t);if(!Array.isArray(r))throw new Error("Invalid memory snapshot");return r}async save(e,t){let r=JSON.stringify(t,null,2);await this.storage.put(this.key(e),r,"application/json")}};function Ro(o){return new Promise(e=>setTimeout(e,o))}async function ct(o,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,n;for(let i=1;i<=t;i++)try{return await o()}catch(a){if(n=a,i>=t)break;let c=Math.min(s,r*2**(i-1)),l=Math.floor(Math.random()*Math.max(1,c*.2));await Ro(c+l)}throw n}var To=new Set(["put","get","getText","delete","list"]);function lt(o,e={}){return new Proxy(o,{get(t,r){let s=Reflect.get(t,r,t);return typeof s!="function"?s:To.has(r)?(...n)=>ct(()=>Promise.resolve(s.apply(t,n)),e):s.bind(t)}})}function pt(o){let e=o.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function dt(o){let e=o.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var Ce=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=pt(s??r),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),r=t,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let n={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(n,null,2)+`
7
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=dt(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,r){return await this.ensureRegistered(),this.provider.put(this.key(e),t,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{McpServer as Fo}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as $o}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as mt}from"zod";var ft={query:mt.string(),limit:mt.number().int().min(1).max(20).optional()};async function ut(o,e){return o.retrieval.search(o.project.id,e.query,{topK:e.limit??8}).map(r=>({id:r.memory.id,type:r.memory.type,content:r.memory.content,importance:r.memory.importance,score:r.score,tags:r.memory.tags}))}import{z as H}from"zod";var gt={type:H.enum(["activity","decision","rule","todo","summary"]),content:H.string().min(1),tags:H.array(H.string()).optional(),importance:H.enum(["critical","high","normal","temporary"]).optional()};async function ht(o,e){let t=o.memory.remember({projectId:o.project.id,type:e.type,content:e.content,tags:e.tags,importance:e.importance,source:"mcp"});return o.memoryStore&&await o.memoryStore.save(o.project.id,o.memory.exportProject(o.project.id)),t}import{z as Mo}from"zod";var yt={id:Mo.string().min(1)};async function St(o,e){let t=o.memory.delete(e.id);return t&&o.memoryStore&&await o.memoryStore.save(o.project.id,o.memory.exportProject(o.project.id)),{deleted:t}}import{z as Ao}from"zod";var bt={name:Ao.string().min(1)};async function xt(o,e){return o.graph.findByName(o.project.id,e.name)}import{z as Lo}from"zod";function j(o,e){let t=o.graph.getSymbol(e);if(t&&t.projectId===o.project.id)return t;let r=new w(o.graph),s=r.findSymbols(o.project.id,e).find(n=>n.name===e||n.qualifiedName===e);return s||(r.findSymbols(o.project.id,e)[0]??null)}function C(o){return{id:o.id,name:o.name,qualifiedName:o.qualifiedName,type:o.type,filePath:o.filePath,startLine:o.startLine,endLine:o.endLine}}var Ct={symbolId:Lo.string().min(1)};async function wt(o,e){let t=j(o,e.symbolId);if(!t)return{found:!1,query:e.symbolId,callers:[]};let s=new w(o.graph).callers(o.project.id,t.id);return{found:!0,symbol:C(t),count:s.length,callers:s.map(C)}}import{z as vt}from"zod";var Et={query:vt.string().min(1),limit:vt.number().int().min(1).max(50).optional()};async function Pt(o,e){let t=e.query.toLowerCase(),r=e.limit??20;return o.graph.allSymbols(o.project.id).filter(s=>s.name.toLowerCase().includes(t)||s.qualifiedName?.toLowerCase().includes(t)||s.filePath.toLowerCase().includes(t)).slice(0,r)}import{z as jt}from"zod";var kt={query:jt.string().optional(),memoryLimit:jt.number().int().min(1).max(20).optional()};async function Rt(o,e){let t=ie(o.graph,o.project.id),r=o.memory.recent(o.project.id,5),s=e.query?o.retrieval.search(o.project.id,e.query,{topK:e.memoryLimit??5}):[];return{project:{id:o.project.id,name:o.project.name,rootPath:o.project.rootPath},architecture:t,recent:r,relevant:s.map(n=>n.memory)}}import{z as Io}from"zod";var No=["memories/current.json","vectors/current.json","graph/current.json","graph/manifest.json","graph/resolution/current.json","code/chunks/current.json","code/vectors/current.json","code/architecture/current.json","code/architecture/entry-points.json","code/architecture/hotspots.json","code/architecture/layers.json","code/architecture/clusters.json","code/analysis/current.json","code/analysis/dead-code.json","code/analysis/dependencies.json","code/visualization/graph.json"],R=class{constructor(e){this.storage=e}storage;projectPrefix(e){return`projects/${e}`}snapshotPrefix(e,t){return[this.projectPrefix(e),"snapshots",t].join("/")}async create(e,t="automatic",r){let s=new Date().toISOString(),n=s.replace(/[:.]/g,"-"),i=this.projectPrefix(e),a=this.snapshotPrefix(e,n),c=[];for(let p of No){let m=`${i}/${p}`,d=await this.storage.get(m);d&&(await this.storage.put(`${a}/${p}`,d,"application/json"),c.push(p))}if(c.length===0)return null;let l={version:1,id:n,projectId:e,createdAt:s,reason:t,objects:c,metadata:r};return await this.storage.put(`${a}/snapshot.json`,JSON.stringify(l,null,2),"application/json"),l}async list(e){let t=[this.projectPrefix(e),"snapshots"].join("/"),s=(await this.storage.list(t)).filter(i=>i.key.endsWith("/snapshot.json")),n=[];for(let i of s){let a=await this.storage.getText(i.key);if(a)try{n.push(JSON.parse(a))}catch{}}return n.sort((i,a)=>a.createdAt.localeCompare(i.createdAt))}async restore(e,t){let r=this.snapshotPrefix(e,t),s=await this.storage.getText(`${r}/snapshot.json`);if(!s)throw new Error(`Snapshot not found: ${t}`);let n=JSON.parse(s);if(n.projectId!==e)throw new Error("Snapshot project mismatch");let i=this.projectPrefix(e),a=[];for(let c of n.objects){let l=await this.storage.get(`${r}/${c}`);l&&(await this.storage.put(`${i}/${c}`,l,"application/json"),a.push(c))}return{restored:a}}async remove(e,t){let r=this.snapshotPrefix(e,t),s=await this.storage.list(r);for(let n of s)await this.storage.delete(n.key);return s.length}async prune(e,t=10){let s=(await this.list(e)).slice(t),n=0;for(let i of s)await this.remove(e,i.id),n++;return n}};var Tt={reason:Io.string().optional()};async function Mt(o,e){if(!o.storage)throw new Error("Storage unavailable");return new R(o.storage).create(o.project.id,e.reason??"manual-mcp")}async function At(o){if(!o.storage)throw new Error("Storage unavailable");return new R(o.storage).list(o.project.id)}import{z as _o}from"zod";var Lt={snapshotId:_o.string().min(1)};async function Nt(o,e){if(!o.storage)throw new Error("Storage unavailable");let t=new R(o.storage);return await t.create(o.project.id,"before-rollback"),t.restore(o.project.id,e.snapshotId)}import{z as Le}from"zod";var It={symbolId:Le.string().min(1),direction:Le.enum(["callers","callees"]).optional(),depth:Le.number().int().min(1).max(10).optional()};async function _t(o,e){let t=new ae(o.graph),r=e.direction??"callees",s=e.depth??3,n=r==="callers"?t.callers(o.project.id,e.symbolId,s):t.callees(o.project.id,e.symbolId,s);return{direction:r,depth:s,results:n.map(i=>({id:i.symbol.id,name:i.symbol.name,qualifiedName:i.symbol.qualifiedName,type:i.symbol.type,filePath:i.symbol.filePath,depth:i.depth}))}}import{z as Ot}from"zod";var Ft={symbolId:Ot.string().min(1),depth:Ot.number().int().min(1).max(10).optional()};async function $t(o,e){let t=o.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let s=new le(o.graph).analyze(o.project.id,t.id,e.depth??4);return{found:!0,target:{id:t.id,name:t.name,qualifiedName:t.qualifiedName,filePath:t.filePath,type:t.type},impacts:s.map(n=>({id:n.symbol.id,name:n.symbol.name,qualifiedName:n.symbol.qualifiedName,filePath:n.symbol.filePath,type:n.symbol.type,relation:n.relation,depth:n.depth}))}}async function Dt(o){return{project:{id:o.project.id,name:o.project.name,rootPath:o.project.rootPath},architecture:ie(o.graph,o.project.id)}}import{z as Gt}from"zod";var zt={filePath:Gt.string().min(1),direction:Gt.enum(["dependencies","dependents","both"]).optional()};async function Kt(o,e){let r=new K(o.graph).analyze(o.project.id).find(c=>c.filePath===e.filePath);if(!r)return{found:!1,filePath:e.filePath,dependencies:[],dependents:[]};let s=o.graph.allSymbols(o.project.id).filter(c=>c.type==="file"),n=new Map(s.map(c=>[c.filePath,c])),i=c=>({id:n.get(c)?.id??c,filePath:c}),a=e.direction??"both";return{found:!0,filePath:r.filePath,outgoingEdges:r.outgoingEdges,incomingEdges:r.incomingEdges,dependencies:a==="dependents"?[]:r.dependencies.map(i),dependents:a==="dependencies"?[]:r.dependents.map(i)}}import{z as Bt}from"zod";var qt={query:Bt.string().min(1),limit:Bt.number().int().min(1).max(20).optional()};async function Ht(o,e){return o.codeSemantic?{available:!0,results:(await o.codeSemantic.search(e.query,e.limit??8)).map(r=>({id:r.chunk.id,filePath:r.chunk.filePath,symbol:r.chunk.symbolName,symbolType:r.chunk.symbolType,startLine:r.chunk.startLine,endLine:r.chunk.endLine,score:r.score,vectorScore:r.vectorScore,lexicalScore:r.lexicalScore,content:r.chunk.content}))}:{available:!1,results:[]}}import{z as Ne}from"zod";var Wt={mode:Ne.enum(["git_diff","file"]).optional(),filePath:Ne.string().optional(),depth:Ne.number().int().min(1).max(10).optional()};async function Ut(o,e){let t=new me(o.graph);if((e.mode??(e.filePath?"file":"git_diff"))==="file"){if(!e.filePath)throw new Error("filePath is required when mode=file");return t.analyzeFile(o.project.id,e.filePath,{maxDepth:e.depth})}return t.analyzeGitDiff(o.project.id,o.project.rootPath,{maxDepth:e.depth})}import{z as Oo}from"zod";var Vt={symbol:Oo.string().min(1)};async function Jt(o,e){let t=j(o,e.symbol);if(!t)return{found:!1,query:e.symbol,dependents:[]};let s=new w(o.graph).dependents(o.project.id,t.id);return{found:!0,symbol:C(t),count:s.length,dependents:s.map(C)}}import{z as Ie}from"zod";var Yt={from:Ie.string().min(1),to:Ie.string().min(1),maxDepth:Ie.number().int().min(1).max(30).optional()};async function Qt(o,e){let t=j(o,e.from),r=j(o,e.to);if(!t||!r)return{found:!1,fromFound:!!t,toFound:!!r,path:[],edges:[]};let n=new w(o.graph).shortestPath(o.project.id,t.id,r.id,e.maxDepth??12);return{found:n.found,distance:n.distance,from:C(t),to:C(r),path:n.symbols.map(C),edges:n.edges.map(i=>({id:i.id,type:i.type,from:i.from,to:i.to,metadata:i.metadata}))}}import{z as _e}from"zod";var Zt={symbol:_e.string().min(1),depth:_e.number().int().min(1).max(5).optional(),limit:_e.number().int().min(1).max(200).optional()};async function Xt(o,e){let t=j(o,e.symbol);if(!t)return{found:!1,query:e.symbol};let s=new w(o.graph).neighborhood(o.project.id,t.id,e.depth??1);if(!s)return{found:!1,query:e.symbol};let n=e.limit??50;return{found:!0,center:C(s.center),incomingCount:s.incoming.length,outgoingCount:s.outgoing.length,incoming:s.incoming.slice(0,n).map(i=>({depth:i.depth,via:i.via?.type,symbol:C(i.symbol)})),outgoing:s.outgoing.slice(0,n).map(i=>({depth:i.depth,via:i.via?.type,symbol:C(i.symbol)}))}}import{z as Oe}from"zod";var tr={confidence:Oe.enum(["high","medium","low","all"]).optional(),filePath:Oe.string().min(1).optional(),limit:Oe.number().int().min(1).max(500).optional()},er={high:3,medium:2,low:1};async function rr(o,e){let r=new z(o.graph).analyze(o.project.id);if(e.confidence&&e.confidence!=="all"){let i=er[e.confidence];r=r.filter(a=>er[a.confidence]>=i)}e.filePath&&(r=r.filter(i=>i.filePath===e.filePath));let s=r.length,n=e.limit??100;return{total:s,high:r.filter(i=>i.confidence==="high").length,medium:r.filter(i=>i.confidence==="medium").length,low:r.filter(i=>i.confidence==="low").length,warning:"Dead-code results are candidates only. Verify before deleting code.",candidates:r.slice(0,n)}}function g(o){return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}function Do(o){let e=new Fo({name:"toolnet-memory",version:"0.1.0"});return e.tool("memory_search","Search relevant long-term memory for the current project.",ft,async t=>g(await ut(o,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",gt,async t=>g(await ht(o,t))),e.tool("memory_forget","Delete a memory by id.",yt,async t=>g(await St(o,t))),e.tool("find_symbol","Find code symbols by exact name.",bt,async t=>g(await xt(o,t))),e.tool("find_callers","Find functions or methods calling a symbol.",Ct,async t=>g(await wt(o,t))),e.tool("code_search","Search indexed code symbols and files.",Et,async t=>g(await Pt(o,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",kt,async t=>g(await Rt(o,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",It,async t=>g(await _t(o,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",Ft,async t=>g(await $t(o,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>g(await Dt(o))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",zt,async t=>g(await Kt(o,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",qt,async t=>g(await Ht(o,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",Tt,async t=>g(await Mt(o,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>g(await At(o))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",Lt,async t=>g(await Nt(o,t))),e.tool("impact_guard","Analyze blast radius before or after code changes. Maps changed files/lines to symbols, follows reverse dependencies, assigns risk and suggests verification targets.",Wt,async t=>g(await Ut(o,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",Vt,async t=>g(await Jt(o,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",Yt,async t=>g(await Qt(o,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",Zt,async t=>g(await Xt(o,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",tr,async t=>g(await rr(o,t))),e}async function or(o){let e=Do(o),t=new $o;await e.connect(t)}import{closeSync as Go,mkdirSync as zo,openSync as Ko,readFileSync as Bo,unlinkSync as sr,writeFileSync as qo}from"node:fs";import{tmpdir as Ho}from"node:os";import{join as nr}from"node:path";function Wo(o){try{return process.kill(o,0),!0}catch(e){return e?.code==="EPERM"}}var we=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=nr(Ho(),"toolnet-memory-locks");zo(t,{recursive:!0});let r=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=nr(t,`${r}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Ko(this.path,"wx");qo(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),Go(t),this.acquired=!0,process.once("exit",this.exitHandler);return}catch(t){if(t?.code!=="EEXIST")throw t;let r=!0;try{let s=JSON.parse(Bo(this.path,"utf8"));Number.isInteger(s.pid)&&Wo(s.pid)&&(r=!1)}catch{r=!0}if(!r)throw new Error("ToolNet Memory is already running for this project");try{sr(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{sr(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};async function Uo(){let o=$e(),e=new V().detect(),t=at({provider:o.storage.provider,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),r=lt(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),s=new Ce(r,e.id,e.name,e.remote??e.name),n=new we(e.id);await n.acquire();let i=()=>{n.release().finally(()=>process.exit(0))};process.once("SIGINT",i),process.once("SIGTERM",i);let a=new Z,c=new xe(s);a.importRecords(await c.load(e.id));let l=new oe(a),p=new I,m=await new D(s).load(e.id);m&&p.import(m.symbols,m.edges);let d=new ce(p),f=new ye({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:s,embeddings:Qe(),graph:p});await f.initialize(),await or({project:e,memory:a,retrieval:l,graph:p,references:d,codeSemantic:f,memoryStore:c,storage:s})}Uo().catch(o=>{console.error(o),process.exit(1)});
1
+ var hs=Object.defineProperty;var y=(r,e,t)=>()=>{if(t)throw t[0];try{return r&&(e=r(r=0)),e}catch(n){throw t=[n],n}};var be=(r,e)=>{for(var t in e)hs(r,t,{get:e[t],enumerable:!0})};var bs,ve,sr=y(()=>{"use strict";bs=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],ve=class{scan(e){let t=[];for(let n of bs){let o=new RegExp(n.regex.source,n.regex.flags);for(let s of e.matchAll(o))t.push({type:n.type,value:s[0]})}return t}hasSecrets(e){return this.scan(e).length>0}}});var _,Se=y(()=>{"use strict";sr();_=class{scanner=new ve;sanitize(e){let t=e,n=this.scanner.scan(e),o=new Set;for(let s of n)o.add(s.type),t=t.split(s.value).join(`[REDACTED:${s.type}]`);return{text:t,redacted:n.length,secretTypes:[...o]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[n,o]of Object.entries(e)){let s=n.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")?t[n]="[REDACTED]":t[n]=this.sanitizeValue(o)}return t}return e}}});function F(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var gt=y(()=>{"use strict"});import{existsSync as Mi,readFileSync as Pi}from"node:fs";import{homedir as Ai}from"node:os";import{join as Ei}from"node:path";function Ri(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function Ii(){let r=process.env.TOOLNET_GLOBAL_ENV??Ei(Ai(),".config","toolnet-memory",".env");if(!Mi(r))return;let e=Pi(r,"utf8");for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let o=n.indexOf("=");if(o<=0)continue;let s=n.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=Ri(n.slice(o+1)))}}var bn=y(()=>{"use strict";Ii()});var Sn={};be(Sn,{loadConfig:()=>vn});function Q(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function X(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function vn(){return{memory:{autoCapture:Q(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:Q(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:Q(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:Q(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:X(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:X(process.env.MEMORY_RERANK_TOP,10),finalContext:X(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:X(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:Q(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:X(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var Mt=y(()=>{"use strict";bn()});function N(r){let e=An.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function ee(r){return An.some(e=>e.id===r)}var An,Pt=y(()=>{"use strict";An=[{id:"openai-compatible",label:"OpenAI-compatible",requiresApiKey:!0,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"alibaba",label:"Alibaba / DashScope",requiresApiKey:!0,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"openrouter",label:"OpenRouter",defaultBaseUrl:"https://openrouter.ai/api/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"groq",label:"Groq",defaultBaseUrl:"https://api.groq.com/openai/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"deepseek",label:"DeepSeek",defaultBaseUrl:"https://api.deepseek.com",defaultModel:"deepseek-v4-flash",requiresApiKey:!0,transport:"openai-compatible"},{id:"nvidia",label:"NVIDIA NIM",defaultBaseUrl:"https://integrate.api.nvidia.com/v1",defaultModel:"deepseek-ai/deepseek-v4-pro",requiresApiKey:!0,transport:"openai-compatible"},{id:"gemini",label:"Gemini",defaultBaseUrl:"https://generativelanguage.googleapis.com/v1beta",requiresApiKey:!0,transport:"gemini"},{id:"huggingface",label:"Hugging Face",defaultBaseUrl:"https://router.huggingface.co/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"ollama",label:"Ollama / Local",defaultBaseUrl:"http://127.0.0.1:11434/v1",requiresApiKey:!1,transport:"openai-compatible"},{id:"custom",label:"Custom endpoint",requiresApiKey:!1,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"cloudflare",label:"Cloudflare Workers AI",requiresApiKey:!0,requiresAccountId:!0,transport:"cloudflare"}]});function d(r){return process.env[r]?.trim()||void 0}function k(...r){return r.find(e=>!!e?.trim())}function En(){if(d("GROQ_API_KEY"))return"groq";if(d("DEEPSEEK_API_KEY"))return"deepseek";if(d("NVIDIA_API_KEY")||d("NVIDIA_NIM_API_KEY"))return"nvidia";if(d("OPENROUTER_API_KEY"))return"openrouter";if(d("ALIBABA_API_KEY")||d("DASHSCOPE_API_KEY"))return"alibaba";if(d("GEMINI_API_KEY")||d("GOOGLE_API_KEY"))return"gemini";if(d("CLOUDFLARE_API_TOKEN")&&d("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(d("HF_TOKEN"))return"huggingface";if(d("OLLAMA_MODEL")||d("OLLAMA_BASE_URL"))return"ollama"}function Rn(){let r=d("TOOLNET_LLM_PROVIDER");return r&&ee(r)?r:En()??"openai-compatible"}function qe(r){let e=N(r);switch(r){case"alibaba":return{provider:r,apiKey:k(d("ALIBABA_API_KEY"),d("DASHSCOPE_API_KEY")),baseUrl:k(d("ALIBABA_BASE_URL"),d("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:k(d("ALIBABA_MODEL"),d("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:d("OPENROUTER_API_KEY"),baseUrl:k(d("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:d("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:d("GROQ_API_KEY"),baseUrl:k(d("GROQ_BASE_URL"),e.defaultBaseUrl),model:d("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:d("DEEPSEEK_API_KEY"),baseUrl:k(d("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:k(d("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:k(d("NVIDIA_API_KEY"),d("NVIDIA_NIM_API_KEY")),baseUrl:k(d("NVIDIA_BASE_URL"),d("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:k(d("NVIDIA_MODEL"),d("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:k(d("GEMINI_API_KEY"),d("GOOGLE_API_KEY")),baseUrl:k(d("GEMINI_BASE_URL"),e.defaultBaseUrl),model:d("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:d("HF_TOKEN"),baseUrl:k(d("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:k(d("HF_LLM_MODEL"),d("HF_MODEL"))};case"ollama":return{provider:r,apiKey:d("OLLAMA_API_KEY"),baseUrl:k(d("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:d("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:d("CLOUDFLARE_ACCOUNT_ID"),apiKey:d("CLOUDFLARE_API_TOKEN"),baseUrl:d("CLOUDFLARE_AI_BASE_URL"),model:d("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:d("CUSTOM_AI_API_KEY"),baseUrl:d("CUSTOM_AI_BASE_URL"),model:d("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:k(d("OPENAI_API_KEY"),d("MODEL_API_KEY")),baseUrl:k(d("OPENAI_BASE_URL"),d("MODEL_BASE_URL")),model:k(d("OPENAI_MODEL"),d("MODEL_NAME"))}}}function ta(){let r=d("TOOLNET_LLM_PROVIDER"),e=r&&ee(r)?r:Rn(),t=N(e),n=qe(e);return{provider:e,apiKey:k(d("TOOLNET_LLM_API_KEY"),n.apiKey),baseUrl:k(d("TOOLNET_LLM_BASE_URL"),n.baseUrl,t.defaultBaseUrl),model:k(d("TOOLNET_LLM_MODEL"),n.model,t.defaultModel),accountId:k(d("TOOLNET_LLM_ACCOUNT_ID"),n.accountId)}}function ra(){let r=d("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&ee(r)?r:d("HF_TOKEN")||d("HF_EMBEDDING_MODEL")?"huggingface":"local"}function na(){let r=ra();if(r==="local")return{provider:"local",model:k(d("TOOLNET_EMBEDDING_MODEL"),d("LOCAL_EMBEDDING_MODEL"))};let e=N(r),t,n,o,s;switch(r){case"huggingface":t=d("HF_TOKEN"),n=d("HF_INFERENCE_BASE_URL"),o=d("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=d("OPENAI_API_KEY"),n=d("OPENAI_BASE_URL"),o=d("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=d("CLOUDFLARE_API_TOKEN"),n=d("CLOUDFLARE_AI_BASE_URL"),o=d("CLOUDFLARE_EMBEDDING_MODEL"),s=d("CLOUDFLARE_ACCOUNT_ID");break;default:t=qe(r).apiKey,n=qe(r).baseUrl,o=d(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let i=k(d("TOOLNET_EMBEDDING_ACCOUNT_ID"),s),a=k(d("TOOLNET_EMBEDDING_BASE_URL"),n,e.defaultBaseUrl),c=r==="cloudflare"&&!a&&i?`https://api.cloudflare.com/client/v4/accounts/${i}/ai/v1`:a;return{provider:r,apiKey:k(d("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:c,model:k(d("TOOLNET_EMBEDDING_MODEL"),o),accountId:i}}function re(){let r=ta(),e=na();return{llm:r,embedding:e,legacy:{llm:!d("TOOLNET_LLM_PROVIDER")&&!!En(),embedding:!d("TOOLNET_EMBEDDING_PROVIDER")&&!!(d("HF_TOKEN")||d("HF_EMBEDDING_MODEL"))}}}function In(r=Rn()){let e=re().llm;if(r===e.provider)return{id:r,apiKey:e.apiKey,baseUrl:e.baseUrl,model:e.model,accountId:e.accountId};let t=qe(r);return{id:r,apiKey:t.apiKey,baseUrl:t.baseUrl,model:t.model,accountId:t.accountId}}function te(r,e){return d(`TOOLNET_LLM_FALLBACK_${r}_${e}`)}function Tn(){let r=[];for(let e of[1,2]){let t=te(e,"PROVIDER");if(!t||!ee(t))continue;let n=N(t);r.push({slot:e,config:{provider:t,apiKey:te(e,"API_KEY"),baseUrl:k(te(e,"BASE_URL"),n.defaultBaseUrl),model:k(te(e,"MODEL"),n.defaultModel),accountId:te(e,"ACCOUNT_ID")}})}return r}function jn(){let r=d("TOOLNET_LLM_FALLBACK_COOLDOWN_MS"),e=d("TOOLNET_LLM_MAX_RETRIES"),t=Number(r??6e4),n=Number(e??1);return{cooldownMs:Number.isFinite(t)&&t>=0?t:6e4,maxRetries:Number.isFinite(n)&&n>=0?Math.floor(n):1}}var Ve=y(()=>{"use strict";Pt()});var Io=y(()=>{"use strict"});import{DeleteObjectCommand as Qa,GetObjectCommand as Xa,HeadObjectCommand as Za,ListObjectsV2Command as ec,PutObjectCommand as tc,S3Client as rc}from"@aws-sdk/client-s3";import{getSignedUrl as nc}from"@aws-sdk/s3-request-presigner";var me,Tt=y(()=>{"use strict";me=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new rc({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new tc({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await nc(this.client,new Xa({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Za({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new Qa({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new ec({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let s of o.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}}});import{access as To,mkdir as oc,readFile as sc,readdir as ic,rm as ac,stat as jo,writeFile as cc}from"node:fs/promises";import{dirname as lc,join as uc,relative as _o,resolve as dc}from"node:path";var U,jt=y(()=>{"use strict";U=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return dc(this.root,t)}async put(e,t){let n=this.path(e);await oc(lc(n),{recursive:!0}),await cc(n,t)}async get(e){try{return await sc(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await To(this.path(e)),!0}catch{return!1}}async delete(e){await ac(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await To(t)}catch{return n}let o=async i=>{let a=await ic(i,{withFileTypes:!0});for(let c of a){let u=uc(i,c.name);if(c.isDirectory()){await o(u);continue}let l=await jo(u);n.push({key:_o(this.root,u),size:l.size,updatedAt:l.mtime.toISOString()})}},s=await jo(t);return s.isDirectory()?await o(t):n.push({key:_o(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),n}}});import{DeleteObjectCommand as mc,GetObjectCommand as pc,HeadObjectCommand as fc,ListObjectsV2Command as gc,PutObjectCommand as yc,S3Client as hc}from"@aws-sdk/client-s3";import{getSignedUrl as kc}from"@aws-sdk/s3-request-presigner";var W,_t=y(()=>{"use strict";W=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new hc({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new yc({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await kc(this.client,new pc({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`${this.name} download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new fc({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new mc({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new gc({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let s of o.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}}});import{homedir as bc}from"node:os";import{join as vc}from"node:path";function Ot(r,e){return console.warn(e),new U(r)}function Sc(r){let e=r.localRoot??vc(bc(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new W({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ot(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new W({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ot(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new me({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ot(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new U(e)}var Oo=y(()=>{"use strict";Tt();jt();_t()});var Nt,No=y(()=>{"use strict";Nt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let n=JSON.parse(t);if(!Array.isArray(n))throw new Error("Invalid memory snapshot");return n}async save(e,t){let n=JSON.stringify(t,null,2);await this.storage.put(this.key(e),n,"application/json")}}});var Lo=y(()=>{"use strict";jt()});var Do=y(()=>{"use strict";Tt()});var Ko=y(()=>{"use strict";_t()});var Lt,Fo=y(()=>{"use strict";Lt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return null;let n=JSON.parse(t);if(n.version!==1||n.projectId!==e||!Array.isArray(n.records))throw new Error("Invalid vector snapshot");return n}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var Dt,$o=y(()=>{"use strict";Dt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var Kt,Go=y(()=>{"use strict";Kt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","manifest.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var pe,Ft=y(()=>{"use strict";pe=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","chunks","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var fe,$t=y(()=>{"use strict";fe=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});function wc(r){return new Promise(e=>setTimeout(e,r))}async function zo(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,o=e.maxDelayMs??2e3,s;for(let i=1;i<=t;i++)try{return await r()}catch(a){if(s=a,i>=t)break;let c=Math.min(o,n*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await wc(c+u)}throw s}var Uo=y(()=>{"use strict"});function xc(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:Cc.has(n)?(...s)=>zo(()=>Promise.resolve(o.apply(t,s)),e):o.bind(t)}})}var Cc,Wo=y(()=>{"use strict";Uo();Cc=new Set(["put","get","getText","delete","list"])});function Gt(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}var zt=y(()=>{"use strict"});function Ut(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let o=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:e))}var Wt=y(()=>{"use strict"});var Bt,Bo=y(()=>{"use strict";zt();Wt();Bt=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=Gt(o??n),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),n=t,o=await this.provider.getText(e);if(o){let i;try{i=JSON.parse(o)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(n=i.createdAt)}let s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:t};await this.provider.put(e,JSON.stringify(s,null,2)+`
3
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Ut(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}}});var qo=y(()=>{"use strict";zt();Bo();Wt()});var qt,Vo=y(()=>{"use strict";qt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","resolution","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var Vt,Ho=y(()=>{"use strict";Vt=class{constructor(e){this.storage=e}storage;base(e){return["projects",e,"code","architecture"].join("/")}async load(e){let t=await this.storage.getText(`${this.base(e)}/current.json`);return t?JSON.parse(t):null}async save(e){let t=this.base(e.projectId),n=o=>JSON.stringify({version:e.version,projectId:e.projectId,updatedAt:e.updatedAt,data:o},null,2);await Promise.all([this.storage.put(`${t}/current.json`,JSON.stringify(e,null,2),"application/json"),this.storage.put(`${t}/entry-points.json`,n(e.entryPoints),"application/json"),this.storage.put(`${t}/hotspots.json`,n(e.hotspots),"application/json"),this.storage.put(`${t}/layers.json`,n(e.layers),"application/json"),this.storage.put(`${t}/clusters.json`,n(e.clusters),"application/json")])}}});var Ht,Jo=y(()=>{"use strict";Ht=class{constructor(e){this.storage=e}storage;base(e){return["projects",e,"code","analysis"].join("/")}async load(e){let t=await this.storage.getText(`${this.base(e)}/current.json`);return t?JSON.parse(t):null}async save(e){let t=this.base(e.projectId),n=o=>JSON.stringify({version:e.version,projectId:e.projectId,updatedAt:e.updatedAt,data:o},null,2);await Promise.all([this.storage.put(`${t}/current.json`,JSON.stringify(e,null,2),"application/json"),this.storage.put(`${t}/dead-code.json`,n(e.deadCode),"application/json"),this.storage.put(`${t}/dependencies.json`,n(e.dependencies),"application/json")])}}});var Jt,Yo=y(()=>{"use strict";Jt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","visualization","graph.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e,null,2),"application/json")}}});var Qo={};be(Qo,{HuggingFaceStorageProvider:()=>me,LocalStorageProvider:()=>U,MemoryStore:()=>Nt,PersistentArchitectureStore:()=>Vt,PersistentCodeAnalysisStore:()=>Ht,PersistentCodeChunkStore:()=>pe,PersistentCodeGraphStore:()=>Dt,PersistentCodeManifestStore:()=>Kt,PersistentCodeVectorStore:()=>fe,PersistentTypeResolutionStore:()=>qt,PersistentVectorStore:()=>Lt,PersistentVisualizationStore:()=>Jt,ProjectScopedStorageProvider:()=>Bt,S3StorageProvider:()=>W,createStorageProvider:()=>Sc,mapProjectStoragePath:()=>Ut,sanitizeProjectFolder:()=>Gt,withStorageRetry:()=>xc});var Xo=y(()=>{"use strict";Io();Oo();No();Lo();Do();Ko();Fo();$o();Go();Ft();$t();Wo();qo();Vo();Ho();Jo();Yo()});import{createHash as Mc}from"node:crypto";import{readFile as Pc}from"node:fs/promises";import{join as Ac}from"node:path";function Zo(r){return Mc("sha256").update(r).digest("hex")}var ot,es=y(()=>{"use strict";Se();ot=class{sanitizer=new _;async build(e,t,n,o={}){let s=o.maxLines??80,i=o.overlapLines??10,a=new Map;for(let u of n){let l=a.get(u.filePath)??[];l.push(u),a.set(u.filePath,l)}let c=[];for(let[u,l]of a){let m;try{m=await Pc(Ac(t,u),"utf8")}catch{continue}let f=m.split(/\r?\n/),p=l.filter(h=>h.type!=="file"&&typeof h.startLine=="number"&&typeof h.endLine=="number");if(p.length>0)for(let h of p)c.push(...this.chunkRange({projectId:e,filePath:u,lines:f,symbol:h,startLine:h.startLine,endLine:h.endLine,maxLines:s,overlapLines:i}));else c.push(...this.chunkRange({projectId:e,filePath:u,lines:f,startLine:1,endLine:Math.max(1,f.length),maxLines:s,overlapLines:i}))}return c}chunkRange(e){let{projectId:t,filePath:n,lines:o,symbol:s,maxLines:i}=e,a=Math.min(e.overlapLines,Math.max(0,i-1)),c=Math.max(1,e.startLine),u=Math.min(o.length,Math.max(c,e.endLine)),l=[],m=c,f=0;for(;m<=u;){let p=Math.min(u,m+i-1),h=o.slice(m-1,p).join(`
4
+ `).trim();if(h){let v=this.sanitizer.sanitize(h).text,M=Zo(v),A=[t,n,s?.id??"file",String(f),M].join(":");l.push({id:Zo(A).slice(0,32),projectId:t,filePath:n,symbolId:s?.id,symbolName:s?.qualifiedName??s?.name,symbolType:s?.type,startLine:m,endLine:p,content:v,contentHash:M})}if(p>=u)break;m=p-a+1,f++}return l}}});function Ec(r,e){if(r.length===0||e.length===0||r.length!==e.length)return 0;let t=0,n=0,o=0;for(let s=0;s<r.length;s++){let i=r[s]??0,a=e[s]??0;t+=i*a,n+=i*i,o+=a*a}return n===0||o===0?0:t/(Math.sqrt(n)*Math.sqrt(o))}var st,ts=y(()=>{"use strict";st=class{records=new Map;upsert(e){this.records.set(e.id,e)}get(e){return this.records.get(e)}has(e){return this.records.has(e)}remove(e){return this.records.delete(e)}clearProject(e){let t=0;for(let[n,o]of this.records)o.projectId===e&&(this.records.delete(n),t++);return t}exportProject(e){return[...this.records.values()].filter(t=>t.projectId===e)}importRecords(e){let t=0;for(let n of e)!n?.id||!n?.projectId||!Array.isArray(n.vector)||(this.records.set(n.id,n),t++);return t}search(e,t,n=10){let o=[];for(let s of this.records.values()){if(s.projectId!==e)continue;let i=Ec(t,s.vector);o.push({id:s.id,score:i,metadata:s.metadata})}return o.sort((s,i)=>i.score-s.score).slice(0,n)}size(){return this.records.size}}});function rs(r,e){let t=r.toLowerCase().replaceAll("\\","/"),n=e.toLowerCase(),o=/\b(test|tests|spec|fixture|mock)\b/.test(n);return(t.startsWith("tests/")||t.includes("/tests/")||t.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(t))&&!o?.35:t.includes("/generated/")||t.includes(".generated.")?.25:1}var ns=y(()=>{"use strict"});var os={};be(os,{SemanticCodeEngine:()=>Yt});var Yt,ss=y(()=>{"use strict";Ft();$t();es();ts();gt();ns();Yt=class{constructor(e){this.options=e}options;vectors=new st;chunks=new Map;async initialize(e){let{projectId:t,rootPath:n,storage:o,embeddings:s,graph:i,model:a}=this.options,c=new pe(o),u=new fe(o),l=await new ot().build(t,n,i.allSymbols(t));this.chunks.clear();for(let w of l)this.chunks.set(w.id,w);let m=await c.load(t),f=!m||m.chunks.length!==l.length||m.chunks.some(w=>!this.chunks.has(w.id));f&&await c.save({version:1,projectId:t,updatedAt:new Date().toISOString(),chunks:l});let p=await u.load(t),h=0;p&&p.model===a&&(h=this.vectors.importRecords(p.records));let v=new Set(l.map(w=>w.id)),M=0;for(let w of this.vectors.exportProject(t))v.has(w.id)||this.vectors.remove(w.id)&&M++;let A=l.filter(w=>{let D=this.vectors.get(w.id);return D?D.metadata?.contentHash!==w.contentHash:!0}),B=0,q=8,V=this.vectors.exportProject(t)[0]?.vector.length,ct=Math.ceil(A.length/q),tr=0;for(let w=0;w<A.length;w+=q){let D=A.slice(w,w+q),gs=D.map(P=>[`file: ${P.filePath}`,P.symbolName?`symbol: ${P.symbolName}`:"",P.symbolType?`type: ${P.symbolType}`:"",P.content].filter(Boolean).join(`
5
+ `)),ys=await s.embedMany(gs);for(let P=0;P<D.length;P++){let j=D[P],K=ys[P];if(!(!j||!K||K.length===0)){if(V===void 0&&(V=K.length),K.length!==V){console.warn(`[code-semantic] skip dimension mismatch: ${K.length} != ${V}`);continue}this.vectors.upsert({id:j.id,projectId:t,vector:K,metadata:{contentHash:j.contentHash,filePath:j.filePath,symbolName:j.symbolName,symbolType:j.symbolType,startLine:j.startLine,endLine:j.endLine}}),B++}}tr++,e?.({current:tr,total:ct,phase:"embedding"})}let lt=this.vectors.exportProject(t),rr=B>0||M>0||!p||p.model!==a;return rr&&(e?.({current:ct,total:ct,phase:"saving"}),await u.save({version:1,projectId:t,model:a,dimensions:lt[0]?.vector.length??V??0,updatedAt:new Date().toISOString(),records:lt})),{chunks:l.length,vectorsLoaded:h,vectorsIndexed:B,vectorsRemoved:M,totalVectors:lt.length,savedChunks:f,savedVectors:rr}}async search(e,t=8){let n=await this.options.embeddings.embed(e),o=this.vectors.search(this.options.projectId,n,Math.max(t*4,20)),s=new Set(F(e)),i=[];for(let a of o){let c=this.chunks.get(a.id);if(!c)continue;let u=new Set(F([c.filePath,c.symbolName??"",c.symbolType??"",c.content].join(" "))),l=0;for(let v of s)u.has(v)&&l++;let m=s.size===0?0:l/s.size,f=Math.max(0,a.score),p=rs(c.filePath,e),h=(f*.75+m*.25)*p;i.push({chunk:c,score:h,vectorScore:f,lexicalScore:m})}return i.sort((a,c)=>c.score-a.score).slice(0,t)}size(){return this.chunks.size}}});var is=y(()=>{"use strict"});var ge,Qt=y(()=>{"use strict";ge=class{constructor(e){this.options=e}options;name="gemini";async embed(e){let t=this.options.model.replace(/^models\//,""),o=`${this.options.baseUrl?.replace(/\/+$/,"")||"https://generativelanguage.googleapis.com/v1beta"}/models/${encodeURIComponent(t)}:embedContent?key=${encodeURIComponent(this.options.apiKey)}`,s=await fetch(o,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${t}`,content:{parts:[{text:e}]}})});if(!s.ok)throw new Error(`Gemini embedding failed: ${s.status} ${await s.text()}`);let a=(await s.json()).embedding?.values;if(!Array.isArray(a)||a.length===0)throw new Error("Gemini embedding returned invalid response");return a}async embedMany(e){let t=[];for(let n of e)t.push(await this.embed(n));return t}}});import{createHash as Rc}from"node:crypto";function Ic(r){let e=Math.sqrt(r.reduce((t,n)=>t+n*n,0));return e===0?r:r.map(t=>t/e)}var ye,Xt=y(()=>{"use strict";ye=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),n=e.toLowerCase().split(/\s+/).filter(Boolean);for(let o of n){let i=Rc("sha256").update(o).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return Ic(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}}});var he,Zt=y(()=>{"use strict";he=class{constructor(e){this.options=e;this.dimensions=e.dimensions}options;name="openai-compatible";dimensions;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=this.options.baseUrl.replace(/\/+$/,""),n=await fetch(`${t}/embeddings`,{method:"POST",headers:{"content-type":"application/json",...this.options.apiKey?{authorization:`Bearer ${this.options.apiKey}`}:{}},body:JSON.stringify({model:this.options.model,input:e})});if(!n.ok)throw new Error(`Embedding failed: ${n.status} ${await n.text()}`);let s=(await n.json()).data?.sort((i,a)=>(i.index??0)-(a.index??0)).map(i=>i.embedding);if(!s||s.length!==e.length||s.some(i=>!Array.isArray(i)))throw new Error("Embedding provider returned invalid response");return s}}});function Tc(r){if(!Array.isArray(r))throw new Error("Invalid embedding");if(r.length>0&&typeof r[0]=="number")return r;if(r.length>0&&Array.isArray(r[0])){let e=r;if(e.length===0)return[];let t=e[0].length,n=new Array(t).fill(0);for(let o of e)for(let s=0;s<t;s++)n[s]+=o[s]??0;for(let o=0;o<t;o++)n[o]/=e.length;return n}throw new Error("Unsupported embedding shape")}var ke,er=y(()=>{"use strict";ke=class{constructor(e){this.options=e}options;name="huggingface";dimensions=384;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=`https://router.huggingface.co/hf-inference/models/${this.options.model}/pipeline/feature-extraction`,n=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.options.token}`,"Content-Type":"application/json"},body:JSON.stringify({inputs:e,options:{wait_for_model:!0}})});if(!n.ok)throw new Error(`HF embedding failed: ${n.status} ${await n.text()}`);let o=await n.json();if(!Array.isArray(o))throw new Error("HF embedding returned invalid response");return o.map(s=>Tc(s))}}});function jc(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function _c(){let r=re().embedding;if(r.provider==="local")return null;if(r.provider==="huggingface")return!r.apiKey||!r.model?null:new ke({token:r.apiKey,model:r.model});if(r.provider==="gemini")return!r.apiKey||!r.model?null:new ge({apiKey:r.apiKey,model:r.model,baseUrl:r.baseUrl});let e=r.baseUrl;return r.provider==="cloudflare"&&!e&&r.accountId&&(e=jc(r.accountId)),e&&r.model?new he({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function Oc(){return new it(_c())}var it,as=y(()=>{"use strict";Ve();Qt();Xt();Zt();er();it=class{constructor(e,t=new ye){this.primary=e;this.fallback=t}primary;fallback;name="resilient";async embed(e){if(this.primary)try{return await this.primary.embed(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embed(e)}async embedMany(e){if(this.primary)try{return await this.primary.embedMany(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embedMany(e)}}});var cs={};be(cs,{GeminiEmbeddingProvider:()=>ge,HashEmbeddingProvider:()=>ye,HuggingFaceEmbeddingProvider:()=>ke,OpenAiCompatibleEmbeddingProvider:()=>he,ResilientEmbeddingProvider:()=>it,createEmbeddingProvider:()=>Oc});var ls=y(()=>{"use strict";is();as();er();Xt();Zt();Qt()});import"dotenv/config";import{randomUUID as _s}from"node:crypto";var ks={critical:100,high:75,normal:50,temporary:20};function nr(r){return ks[r]}function or(r,e){let t=e.toLowerCase();return t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c")||t.includes("must not")||t.includes("critical")?"critical":r==="rule"||r==="decision"?"high":r==="todo"?"normal":r==="activity"||r==="summary"?"temporary":"normal"}Se();var vs=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Ss=new Set(["d\xF9ng","s\u1EED","d\u1EE5ng","use","using","the","a","an","cho","v\xE0","l\xE0","c\u1EE7a","to","for","with","quy\u1EBFt","\u0111\u1ECBnh"]);function ir(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Ss.has(e)))}function ws(r,e){let t=ir(r),n=ir(e);if(t.size===0||n.size===0)return 0;let o=0;for(let i of t)n.has(i)&&o++;let s=new Set([...t,...n]).size;return o/s}function ar(r){return new Set(r.tags.filter(e=>!vs.has(e.toLowerCase())))}var we=class{findSuperseded(e,t){if(e.type!=="rule"&&e.type!=="decision")return[];let n=typeof e.metadata?.topic=="string"?e.metadata.topic:void 0,o=ar(e);return t.filter(s=>{if(s.id===e.id||s.projectId!==e.projectId||s.type!==e.type||s.metadata?.supersededBy)return!1;let i=typeof s.metadata?.topic=="string"?s.metadata.topic:void 0;if(n&&i&&n===i)return!0;let a=ar(s);for(let c of o)if(a.has(c))return!0;return ws(e.content,s.content)>=.6})}};var Cs=new Set(["code","decision","rule","todo","summary"]);function xs(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function cr(r){return r.tags.includes("class:permanent")?4:r.tags.includes("class:task")?3:r.tags.includes("class:session")?2:r.tags.includes("class:transient")?1:0}function Ms(r,e){let t=cr(e)-cr(r);if(t!==0)return t;let n=e.importanceScore-r.importanceScore;if(n!==0)return n;let o=e.updatedAt.localeCompare(r.updatedAt);if(o!==0)return o;let s=e.createdAt.localeCompare(r.createdAt);return s!==0?s:r.id.localeCompare(e.id)}function lr(r){let e=new Set,t=[];for(let n of r){let o=n.trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();e.has(s)||(e.add(s),t.push(o))}return t}function ur(r){let e=new Map;for(let o of r){if(!Cs.has(o.type)||o.metadata?.supersededBy)continue;let s=xs(o.content);if(!s)continue;let i=[o.projectId,o.type,s].join("\0"),a=e.get(i)??[];a.push(o),e.set(i,a)}let t=[],n=0;for(let o of e.values()){if(o.length<2)continue;let s=[...o].sort(Ms),i=s[0];if(!i)continue;let a=s.slice(1);t.push({canonicalId:i.id,duplicateIds:a.map(c=>c.id),mergedTags:lr(s.flatMap(c=>c.tags)),mergedSources:lr(s.map(c=>c.source))}),n+=a.length}return{groups:t,duplicates:n}}function ut(r){if(r.tags.includes("class:permanent"))return"permanent";if(r.tags.includes("class:task"))return"task";if(r.tags.includes("class:session"))return"session";if(r.tags.includes("class:transient"))return"transient"}function Ps(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function As(r){let e=ut(r);if(e==="permanent")return 730;if(e==="task")return 180;if(e==="session")return 45;if(e==="transient")return 7;switch(r.type){case"rule":return 730;case"decision":return 365;case"code":return 180;case"todo":return 120;case"summary":return 45;case"activity":return 14}}function Es(r){return ut(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function Rs(r){let e=r.normalize("NFKC").toLowerCase().trim();return e.length<8?!0:[/^ok(?:ay)?[.!]?$/u,/^done[.!]?$/u,/^thanks?[.!]?$/u,/^test(?:ing)?[.!]?$/u,/^npm notice\b/u,/^changed \d+ packages?/u,/^packages? are looking for funding/u].some(t=>t.test(e))}function dr(r,e=Date.now()){let t=50,n=[],o=ut(r);switch(o==="permanent"?(t+=25,n.push("permanent project knowledge")):o==="task"?(t+=15,n.push("active task knowledge")):o==="session"?(t+=2,n.push("session-scoped knowledge")):o==="transient"&&(t-=25,n.push("transient knowledge")),r.importance){case"critical":t+=25,n.push("critical importance");break;case"high":t+=15,n.push("high importance");break;case"normal":break;case"temporary":t-=15,n.push("temporary importance");break}(r.type==="rule"||r.type==="decision")&&(t+=10,n.push("durable knowledge type"));let s=r.content.trim().length;s<12?(t-=30,n.push("very short content")):s<30?(t-=10,n.push("limited context")):s<=1200?(t+=8,n.push("useful context density")):s>5e3&&(t-=15,n.push("excessively large memory")),Rs(r.content)&&(t-=35,n.push("matches transient/noise pattern"));let i=r.metadata?.consolidation;i&&typeof i=="object"&&Array.isArray(i.sources)&&i.sources.length>1&&(t+=10,n.push("confirmed across multiple sources"));let a=Ps(r,e)>=As(r);a&&(t-=15,n.push("stale for lifecycle class"));let c=Es(r);t=Math.max(0,Math.min(100,Math.round(t)));let u;t>=80?u="trusted":t>=55?u="useful":t>=30?u="weak":u="noise";let l=r.importance==="temporary"||r.type==="activity"||o==="transient";return{score:t,tier:u,stale:a,protected:c,pruneEligible:!c&&(u==="noise"&&l||a&&(u==="noise"||u==="weak")),reasons:n}}var Is={critical:100,high:75,normal:50,temporary:20},Ts={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function mr(r,e,t=new Date){let n;if(e==="temporary"&&(n=30),r==="activity"&&(n=Math.min(n??14,14)),r==="summary"&&(n=Math.min(n??30,30)),!!n)return new Date(t.getTime()+n*864e5).toISOString()}function dt(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function js(r){return!!r.metadata?.supersededBy}function mt(r,e=Date.now()){return!dt(r,e)&&!js(r)}function H(r,e=Date.now()){if(!mt(r,e))return 0;let t=Is[r.importance];if(r.importance==="critical")return t;let n=Ts[r.type]??180,s=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,i=Math.pow(.5,s/n);return t*i}var Ce=class{memories=new Map;sanitizer=new _;conflicts=new we;remember(e){let t=new Date().toISOString(),n=this.sanitizer.sanitize(e.content.trim()).text,o=e.importance??or(e.type,n),s={id:_s(),projectId:e.projectId,type:e.type,content:n,importance:o,importanceScore:nr(o),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??mr(e.type,o,new Date(t)),metadata:this.sanitizer.sanitizeValue(e.metadata)},i=this.conflicts.findSuperseded(s,this.list(e.projectId));if(i.length){s.metadata={...s.metadata??{},supersedes:i.map(a=>a.id)};for(let a of i)a.updatedAt=t,a.metadata={...a.metadata??{},supersededBy:s.id,supersededAt:t},this.memories.set(a.id,a)}return this.memories.set(s.id,s),s}importRecords(e){let t=0;for(let n of e)n?.id&&(this.memories.set(n.id,n),t++);return t}exportProject(e){return this.listAll(e)}get(e){return this.memories.get(e)}delete(e){return this.memories.delete(e)}listAll(e){return[...this.memories.values()].filter(t=>t.projectId===e).sort((t,n)=>n.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>mt(t))}recent(e,t=10){return this.list(e).slice(0,t)}byType(e,t){return this.list(e).filter(n=>n.type===t)}search(e){let t=e.query.trim().toLowerCase(),n=e.limit??10,o=t.split(/\s+/).filter(Boolean);return this.list(e.projectId).filter(s=>{if(e.types&&!e.types.includes(s.type))return!1;let i=H(s);return!(e.minImportanceScore&&i<e.minImportanceScore||e.tags?.length&&!e.tags.some(c=>s.tags.includes(c)))}).map(s=>{let i=s.content.toLowerCase(),a=o.filter(l=>i.includes(l)).length,c=o.length===0?0:a/o.length,u=H(s)/500;return{memory:s,score:c+u,source:"memory"}}).filter(s=>t.length===0||s.score>0).sort((s,i)=>i.score-s.score).slice(0,n)}consolidate(e,t=Date.now()){let n=ur(this.list(e)),o=[],s=0;for(let i of n.groups){let a=this.memories.get(i.canonicalId);if(a){a.tags=i.mergedTags,a.metadata={...a.metadata??{},consolidation:{version:1,consolidatedAt:new Date(t).toISOString(),mergedIds:i.duplicateIds,sources:i.mergedSources}},this.memories.set(a.id,a),o.push(a.id);for(let c of i.duplicateIds)this.memories.delete(c)&&(s+=1)}}return{groupsConsolidated:o.length,duplicatesRemoved:s,canonicalIds:o}}reviewLifecycle(e,t=Date.now()){let n={reviewed:0,trusted:0,useful:0,weak:0,noise:0,stale:0,protected:0,pruned:0};for(let o of this.list(e)){let s=dr(o,t);n.reviewed+=1,n[s.tier]+=1,s.stale&&(n.stale+=1),s.protected&&(n.protected+=1),o.metadata={...o.metadata??{},lifecycle:{version:1,reviewedAt:new Date(t).toISOString(),qualityScore:s.score,tier:s.tier,stale:s.stale,protected:s.protected,reasons:s.reasons}},this.memories.set(o.id,o),s.pruneEligible&&this.memories.delete(o.id)&&(n.pruned+=1)}return n}pruneExpired(e,t=Date.now()){let n=0;for(let[o,s]of this.memories)s.projectId===e&&dt(s,t)&&(this.memories.delete(o),n++);return n}pruneSuperseded(e,t=30,n=Date.now()){let o=0,s=t*864e5;for(let[i,a]of this.memories){if(a.projectId!==e)continue;let c=a.metadata?.supersededAt;if(typeof c!="string")continue;n-new Date(c).getTime()>=s&&(this.memories.delete(i),o++)}return o}clearProject(e){let t=0;for(let[n,o]of this.memories)o.projectId===e&&(this.memories.delete(n),t++);return t}};import{createHash as Os}from"node:crypto";import{existsSync as pt,mkdirSync as Ns,readFileSync as Ls,renameSync as Ds,writeFileSync as Ks}from"node:fs";import{basename as Fs,dirname as xe,join as Pe,parse as gr,resolve as J}from"node:path";var yr=".toolnet",$s="project.json";function Gs(r){return Os("sha256").update(r).digest("hex").slice(0,16)}function ft(r){return Pe(r,yr,$s)}function zs(r){return pt(ft(r))}function Us(r,e){let t=J(r),n=gr(t).root;for(;;){if(zs(t))return t;if(t===n||e&&t===J(e))break;let o=xe(t);if(o===t)break;t=o}return null}function Ws(r){let e=J(r),t=gr(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(s=>pt(Pe(e,s))))return e;if(e===t)break;let o=xe(e);if(o===e)break;e=o}return J(r)}function Bs(r){let e;try{e=JSON.parse(Ls(r,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${r}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:xe(xe(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:n,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:n,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function pr(r,e){let t=Pe(r,yr);Ns(t,{recursive:!0});let n=ft(r),o=`${n}.tmp-${process.pid}`;Ks(o,JSON.stringify(e,null,2)+`
6
+ `,{encoding:"utf8",mode:384}),Ds(o,n)}function fr(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var Me=class{detect(e=process.cwd()){let t=J(e),n=Ws(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>pt(Pe(n,l))),i=Us(t,s?n:void 0);if(i){let l=ft(i),m=Bs(l);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),pr(i,m)),fr(m,i)}let a=new Date().toISOString(),c=Fs(n),u={version:1,id:Gs(n),name:c,remote:c,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return pr(n,u),fr(u,n)}};gt();var Ae=class{score(e,t){let n=F(e),o=F([t.content,...t.tags??[],t.type].join(" "));if(n.length===0||o.length===0)return 0;let s=new Map;for(let a of o)s.set(a,(s.get(a)??0)+1);let i=0;for(let a of n){let c=s.get(a)??0;c!==0&&(i+=1+Math.log(1+c))}return i/n.length}};function hr(r,e=Date.now()){let t=r.updatedAt??r.createdAt,n=new Date(t).getTime();if(!Number.isFinite(n))return 0;let o=Math.max(0,e-n)/864e5;return Math.exp(-Math.LN2*o/30)}function kr(r){return H(r)/100}var qs={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function br(r){return qs[r]??.4}var Ee=class{analyze(e){let t=e.toLowerCase(),n=[];return(t.includes("quy\u1EBFt \u0111\u1ECBnh")||t.includes("decision")||t.includes("\u0111\xE3 ch\u1ECDn"))&&n.push("decision"),(t.includes("todo")||t.includes("c\u1EA7n l\xE0m")||t.includes("ti\u1EBFp theo")||t.includes("ch\u01B0a xong"))&&n.push("todo"),(t.includes("quy t\u1EAFc")||t.includes("rule")||t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c"))&&n.push("rule"),(t.includes("t\xF3m t\u1EAFt")||t.includes("summary")||t.includes("\u0111\xE3 l\xE0m"))&&n.push("summary"),{query:e,preferredTypes:n}}};var Re=class{bm25=new Ae;analyzer=new Ee;search(e,t,n={}){let o=n.topK??8,s=n.minScore??.05,i=this.analyzer.analyze(e),a=[];for(let c of t){if(n.types?.length&&!n.types.includes(c.type))continue;let u=this.bm25.score(e,c),l=hr(c),m=kr(c),f=br(c.type);i.preferredTypes.includes(c.type)&&(f=Math.min(1,f+.25));let p=u*.55+m*.2+l*.15+f*.1;u<=0||p<s||a.push({memory:c,score:p,scores:{keyword:u,recency:l,importance:m,type:f}})}return a.sort((c,u)=>u.score-c.score).slice(0,o)}};var Ie=class{build(e,t=6e3){let n=[],o=0;for(let s of e){let i=s.memory,a=[`[${i.type.toUpperCase()}]`,i.content].join(" ");if(o+a.length>t)break;n.push(a),o+=a.length}return n.join(`
7
+ `)}};var Te=class{constructor(e){this.memory=e}memory;searcher=new Re;contextBuilder=new Ie;search(e,t,n={}){return this.searcher.search(t,this.memory.list(e),n)}context(e,t,n={}){let o=this.search(e,t,n);return this.contextBuilder.build(o)}};var je=class{symbols=new Map;edges=new Map;addSymbol(e){this.symbols.set(e.id,e)}addEdge(e){this.edges.set(e.id,e)}getSymbol(e){return this.symbols.get(e)}findByName(e,t){return[...this.symbols.values()].filter(n=>n.projectId===e&&(n.name===t||n.qualifiedName===t))}allSymbols(e){return[...this.symbols.values()].filter(t=>t.projectId===e)}allEdges(e){return[...this.edges.values()].filter(t=>t.projectId===e)}import(e,t){for(let n of e)this.addSymbol(n);for(let n of t)this.addEdge(n)}clearProject(e){for(let[t,n]of this.symbols)n.projectId===e&&this.symbols.delete(t);for(let[t,n]of this.edges)n.projectId===e&&this.edges.delete(t)}};var _e=class{constructor(e){this.graph=e}graph;findSymbol(e,t){return this.graph.findByName(e,t)}findCallers(e,t){return this.graph.allEdges(e).filter(o=>o.type==="CALLS"&&o.to===t).map(o=>o.from).map(o=>this.graph.getSymbol(o)).filter(o=>!!o)}};import{McpServer as Va}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Ha}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as vr}from"zod";var Sr={query:vr.string(),limit:vr.number().int().min(1).max(20).optional()};async function wr(r,e){return r.retrieval.search(r.project.id,e.query,{topK:e.limit??8}).map(n=>({id:n.memory.id,type:n.memory.type,content:n.memory.content,importance:n.memory.importance,score:n.score,tags:n.memory.tags}))}import{z as Y}from"zod";import{createConnection as Js}from"node:net";import{homedir as Vs}from"node:os";import{join as Hs}from"node:path";function Cr(){return process.env.TOOLNET_SERVICE_SOCKET??Hs(Vs(),".toolnet","run","service.sock")}function xr(r,e={}){let t=e.socketPath??Cr(),n=e.timeoutMs??1e3;return new Promise((o,s)=>{let i=Js({path:t}),a="",c=!1,u=m=>{c||(c=!0,clearTimeout(l),i.destroy(),m())},l=setTimeout(()=>{u(()=>{s(new Error(`ToolNet service timeout after ${n}ms`))})},n);i.setEncoding("utf8"),i.once("connect",()=>{i.write(`${JSON.stringify(r)}
8
+ `)}),i.on("data",m=>{a+=m;let f=a.indexOf(`
9
+ `);if(f===-1)return;let p=a.slice(0,f).trim();u(()=>{try{o(JSON.parse(p))}catch(h){s(h instanceof Error?h:new Error(String(h)))}})}),i.once("error",m=>{u(()=>{s(m)})}),i.once("end",()=>{c||u(()=>{s(new Error("ToolNet service closed without response"))})})})}async function Ys(r,e={}){let t=await xr({type:"hydrate",project:r},e);if(!t.ok||t.type!=="hydrate")throw new Error(t.ok?"Invalid ToolNet service hydrate response":t.error);return t}async function Mr(r,e={}){try{return await Ys(r,e)}catch{return null}}async function Oe(r,e={}){try{let t=await xr({type:"invalidate",project:r},{timeoutMs:250,...e});return t.ok&&t.type==="invalidate"}catch{return!1}}var Pr={type:Y.enum(["activity","decision","rule","todo","summary"]),content:Y.string().min(1),tags:Y.array(Y.string()).optional(),importance:Y.enum(["critical","high","normal","temporary"]).optional()};async function Ar(r,e){let t=r.memory.remember({projectId:r.project.id,type:e.type,content:e.content,tags:e.tags,importance:e.importance,source:"mcp"});return r.memoryStore&&await r.memoryStore.save(r.project.id,r.memory.exportProject(r.project.id)),Oe(r.project),t}import{z as Qs}from"zod";var Er={id:Qs.string().min(1)};async function Rr(r,e){let t=r.memory.delete(e.id);return t&&r.memoryStore&&await r.memoryStore.save(r.project.id,r.memory.exportProject(r.project.id)),t&&Oe(r.project),{deleted:t}}import{z as Xs}from"zod";var Ir={name:Xs.string().min(1)};async function Tr(r,e){return r.graph.findByName(r.project.id,e.name)}import{z as Zs}from"zod";var Ne=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),jr=new Set(["CALLS","CALL_REFERENCE"]),x=class{constructor(e){this.graph=e}graph;findSymbols(e,t){let n=t.trim().toLowerCase();return n?this.graph.allSymbols(e).filter(o=>o.name.toLowerCase().includes(n)||(o.qualifiedName?.toLowerCase().includes(n)??!1)||o.filePath.toLowerCase().includes(n)).sort((o,s)=>{let i=o.name.toLowerCase()===n,a=s.name.toLowerCase()===n;return i!==a?i?-1:1:o.filePath.localeCompare(s.filePath)}):[]}callers(e,t){return this.relatedIncoming(e,t,jr)}callees(e,t){return this.relatedOutgoing(e,t,jr)}dependents(e,t){return this.relatedIncoming(e,t,Ne)}dependencies(e,t){return this.relatedOutgoing(e,t,Ne)}neighborhood(e,t,n=1){let o=this.graph.getSymbol(t);return!o||o.projectId!==e?null:{center:o,incoming:this.walk(e,t,"incoming",n),outgoing:this.walk(e,t,"outgoing",n)}}shortestPath(e,t,n,o=12){let s=this.graph.getSymbol(t),i=this.graph.getSymbol(n);if(!s||!i||s.projectId!==e||i.projectId!==e)return{found:!1,distance:-1,symbols:[],edges:[]};if(t===n)return{found:!0,distance:0,symbols:[s],edges:[]};let a=this.graph.allEdges(e).filter(f=>Ne.has(f.type)),c=new Map;for(let f of a){let p=c.get(f.from)??[];p.push(f),c.set(f.from,p)}let u=[{id:t,depth:0}],l=new Set([t]),m=new Map;for(;u.length>0;){let f=u.shift();if(!(f.depth>=o)){for(let p of c.get(f.id)??[])if(!l.has(p.to)){if(l.add(p.to),m.set(p.to,{node:f.id,edge:p}),p.to===n)return this.buildPath(t,n,m);u.push({id:p.to,depth:f.depth+1})}}}return{found:!1,distance:-1,symbols:[],edges:[]}}buildPath(e,t,n){let o=[t],s=[],i=t;for(;i!==e;){let c=n.get(i);if(!c)return{found:!1,distance:-1,symbols:[],edges:[]};s.push(c.edge),i=c.node,o.push(i)}o.reverse(),s.reverse();let a=o.map(c=>this.graph.getSymbol(c)).filter(c=>!!c);return{found:!0,distance:s.length,symbols:a,edges:s}}walk(e,t,n,o){let s=this.graph.allEdges(e).filter(u=>Ne.has(u.type)),i=[{id:t,depth:0}],a=new Set([t]),c=[];for(;i.length>0;){let u=i.shift();if(!(u.depth>=o))for(let l of s){if(!(n==="incoming"?l.to===u.id:l.from===u.id))continue;let f=n==="incoming"?l.from:l.to;if(a.has(f))continue;let p=this.graph.getSymbol(f);p&&(a.add(f),c.push({symbol:p,depth:u.depth+1,via:l}),i.push({id:f,depth:u.depth+1}))}}return c}relatedIncoming(e,t,n){return[...new Set(this.graph.allEdges(e).filter(s=>s.to===t&&n.has(s.type)).map(s=>s.from))].map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}relatedOutgoing(e,t,n){return[...new Set(this.graph.allEdges(e).filter(s=>s.from===t&&n.has(s.type)).map(s=>s.to))].map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}};function E(r,e){let t=r.graph.getSymbol(e);if(t&&t.projectId===r.project.id)return t;let n=new x(r.graph),o=n.findSymbols(r.project.id,e).find(s=>s.name===e||s.qualifiedName===e);return o||(n.findSymbols(r.project.id,e)[0]??null)}function C(r){return{id:r.id,name:r.name,qualifiedName:r.qualifiedName,type:r.type,filePath:r.filePath,startLine:r.startLine,endLine:r.endLine}}var _r={symbolId:Zs.string().min(1)};async function Or(r,e){let t=E(r,e.symbolId);if(!t)return{found:!1,query:e.symbolId,callers:[]};let o=new x(r.graph).callers(r.project.id,t.id);return{found:!0,symbol:C(t),count:o.length,callers:o.map(C)}}import{z as Nr}from"zod";var Lr={query:Nr.string().min(1),limit:Nr.number().int().min(1).max(50).optional()};async function Dr(r,e){let t=e.query.toLowerCase(),n=e.limit??20;return r.graph.allSymbols(r.project.id).filter(o=>o.name.toLowerCase().includes(t)||o.qualifiedName?.toLowerCase().includes(t)||o.filePath.toLowerCase().includes(t)).slice(0,n)}import{z as Kr}from"zod";function Le(r,e){let t=r.allSymbols(e),n=r.allEdges(e),o=i=>t.filter(a=>a.type===i).length,s=i=>n.filter(a=>a.type===i).length;return{files:o("file"),classes:o("class"),interfaces:o("interface"),functions:o("function"),methods:o("method"),properties:o("property"),routes:o("route"),symbols:t.length,edges:n.length,calls:s("CALLS"),callReferences:s("CALL_REFERENCE"),imports:s("IMPORTS"),inherits:s("INHERITS"),implements:s("IMPLEMENTS"),usesType:s("USES_TYPE"),tests:s("TESTS"),routeEdges:s("ROUTE"),writes:s("WRITES")}}var Fr={query:Kr.string().optional(),memoryLimit:Kr.number().int().min(1).max(20).optional()};async function $r(r,e){let t=Le(r.graph,r.project.id),n=r.memory.recent(r.project.id,5),o=e.query?r.retrieval.search(r.project.id,e.query,{topK:e.memoryLimit??5}):[];return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:t,recent:n,relevant:o.map(s=>s.memory)}}import{z as ti}from"zod";var ei=["memories/current.json","vectors/current.json","graph/current.json","graph/manifest.json","graph/resolution/current.json","code/chunks/current.json","code/vectors/current.json","code/architecture/current.json","code/architecture/entry-points.json","code/architecture/hotspots.json","code/architecture/layers.json","code/architecture/clusters.json","code/analysis/current.json","code/analysis/dead-code.json","code/analysis/dependencies.json","code/visualization/graph.json"],O=class{constructor(e){this.storage=e}storage;projectPrefix(e){return`projects/${e}`}snapshotPrefix(e,t){return[this.projectPrefix(e),"snapshots",t].join("/")}async create(e,t="automatic",n){let o=new Date().toISOString(),s=o.replace(/[:.]/g,"-"),i=this.projectPrefix(e),a=this.snapshotPrefix(e,s),c=[];for(let l of ei){let m=`${i}/${l}`,f=await this.storage.get(m);f&&(await this.storage.put(`${a}/${l}`,f,"application/json"),c.push(l))}if(c.length===0)return null;let u={version:1,id:s,projectId:e,createdAt:o,reason:t,objects:c,metadata:n};return await this.storage.put(`${a}/snapshot.json`,JSON.stringify(u,null,2),"application/json"),u}async list(e){let t=[this.projectPrefix(e),"snapshots"].join("/"),o=(await this.storage.list(t)).filter(i=>i.key.endsWith("/snapshot.json")),s=[];for(let i of o){let a=await this.storage.getText(i.key);if(a)try{s.push(JSON.parse(a))}catch{}}return s.sort((i,a)=>a.createdAt.localeCompare(i.createdAt))}async restore(e,t){let n=this.snapshotPrefix(e,t),o=await this.storage.getText(`${n}/snapshot.json`);if(!o)throw new Error(`Snapshot not found: ${t}`);let s=JSON.parse(o);if(s.projectId!==e)throw new Error("Snapshot project mismatch");let i=this.projectPrefix(e),a=[];for(let c of s.objects){let u=await this.storage.get(`${n}/${c}`);u&&(await this.storage.put(`${i}/${c}`,u,"application/json"),a.push(c))}return{restored:a}}async remove(e,t){let n=this.snapshotPrefix(e,t),o=await this.storage.list(n);for(let s of o)await this.storage.delete(s.key);return o.length}async prune(e,t=10){let o=(await this.list(e)).slice(t),s=0;for(let i of o)await this.remove(e,i.id),s++;return s}};var Gr={reason:ti.string().optional()};async function zr(r,e){if(!r.storage)throw new Error("Storage unavailable");return new O(r.storage).create(r.project.id,e.reason??"manual-mcp")}async function Ur(r){if(!r.storage)throw new Error("Storage unavailable");return new O(r.storage).list(r.project.id)}import{z as ri}from"zod";var Wr={snapshotId:ri.string().min(1)};async function Br(r,e){if(!r.storage)throw new Error("Storage unavailable");let t=new O(r.storage);return await t.create(r.project.id,"before-rollback"),t.restore(r.project.id,e.snapshotId)}import{z as yt}from"zod";var De=class{constructor(e){this.graph=e}graph;callees(e,t,n=3){return this.walk(e,t,"out",n)}callers(e,t,n=3){return this.walk(e,t,"in",n)}walk(e,t,n,o){let s=[],i=new Set([t]),a=[{id:t,depth:0}],c=this.graph.allEdges(e).filter(u=>u.type==="CALLS"||u.type==="CALL_REFERENCE");for(;a.length;){let u=a.shift();if(u.depth>=o)continue;let l=n==="out"?c.filter(m=>m.from===u.id):c.filter(m=>m.to===u.id);for(let m of l){let f=n==="out"?m.to:m.from;if(i.has(f))continue;i.add(f);let p=this.graph.getSymbol(f);if(!p)continue;let h=u.depth+1;s.push({symbol:p,depth:h}),a.push({id:f,depth:h})}}return s}};var qr={symbolId:yt.string().min(1),direction:yt.enum(["callers","callees"]).optional(),depth:yt.number().int().min(1).max(10).optional()};async function Vr(r,e){let t=new De(r.graph),n=e.direction??"callees",o=e.depth??3,s=n==="callers"?t.callers(r.project.id,e.symbolId,o):t.callees(r.project.id,e.symbolId,o);return{direction:n,depth:o,results:s.map(i=>({id:i.symbol.id,name:i.symbol.name,qualifiedName:i.symbol.qualifiedName,type:i.symbol.type,filePath:i.symbol.filePath,depth:i.depth}))}}import{z as Hr}from"zod";var Ke=class{constructor(e){this.graph=e}graph;analyze(e,t,n=4){let o=this.graph.allEdges(e),s=new Set([t]),i=[{id:t,depth:0}],a=[];for(;i.length;){let c=i.shift();if(c.depth>=n)continue;let u=o.filter(l=>l.to===c.id&&["CALLS","IMPORTS","INHERITS","IMPLEMENTS"].includes(l.type));for(let l of u){if(s.has(l.from))continue;s.add(l.from);let m=this.graph.getSymbol(l.from);if(!m)continue;let f=c.depth+1;a.push({symbol:m,depth:f,relation:l.type}),i.push({id:l.from,depth:f})}}return a}};var Jr={symbolId:Hr.string().min(1),depth:Hr.number().int().min(1).max(10).optional()};async function Yr(r,e){let t=r.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let o=new Ke(r.graph).analyze(r.project.id,t.id,e.depth??4);return{found:!0,target:{id:t.id,name:t.name,qualifiedName:t.qualifiedName,filePath:t.filePath,type:t.type},impacts:o.map(s=>({id:s.symbol.id,name:s.symbol.name,qualifiedName:s.symbol.qualifiedName,filePath:s.symbol.filePath,type:s.symbol.type,relation:s.relation,depth:s.depth}))}}async function Qr(r){return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:Le(r.graph,r.project.id)}}import{z as Xr}from"zod";var ni=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),Fe=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),n=this.graph.allEdges(e).filter(i=>ni.has(i.type)),o=new Map(t.map(i=>[i.id,i]));return[...new Set(t.map(i=>i.filePath))].sort().map(i=>{let a=new Set,c=new Set,u=0,l=0;for(let m of n){let f=o.get(m.from),p=o.get(m.to);!f||!p||f.filePath===p.filePath||(f.filePath===i&&(a.add(p.filePath),u++),p.filePath===i&&(c.add(f.filePath),l++))}return{filePath:i,dependencies:[...a].sort(),dependents:[...c].sort(),outgoingEdges:u,incomingEdges:l}})}};var Zr={filePath:Xr.string().min(1),direction:Xr.enum(["dependencies","dependents","both"]).optional()};async function en(r,e){let n=new Fe(r.graph).analyze(r.project.id).find(c=>c.filePath===e.filePath);if(!n)return{found:!1,filePath:e.filePath,dependencies:[],dependents:[]};let o=r.graph.allSymbols(r.project.id).filter(c=>c.type==="file"),s=new Map(o.map(c=>[c.filePath,c])),i=c=>({id:s.get(c)?.id??c,filePath:c}),a=e.direction??"both";return{found:!0,filePath:n.filePath,outgoingEdges:n.outgoingEdges,incomingEdges:n.incomingEdges,dependencies:a==="dependents"?[]:n.dependencies.map(i),dependents:a==="dependencies"?[]:n.dependents.map(i)}}import{z as tn}from"zod";var rn={query:tn.string().min(1),limit:tn.number().int().min(1).max(20).optional()};async function nn(r,e){return r.codeSemantic?{available:!0,results:(await r.codeSemantic.search(e.query,e.limit??8)).map(n=>({id:n.chunk.id,filePath:n.chunk.filePath,symbol:n.chunk.symbolName,symbolType:n.chunk.symbolType,startLine:n.chunk.startLine,endLine:n.chunk.endLine,score:n.score,vectorScore:n.vectorScore,lexicalScore:n.lexicalScore,content:n.chunk.content}))}:{available:!1,results:[]}}import{z as kt}from"zod";import{execFile as oi}from"node:child_process";import{promisify as si}from"node:util";var ht=si(oi);function ii(r){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let n of r.matchAll(t)){let o=Number(n[1]),s=Number(n[2]??1);e.push({startLine:o,endLine:Math.max(o,o+s-1)})}return e}function ai(r){return r.startsWith("A")?"added":r.startsWith("D")?"deleted":r.startsWith("R")?"renamed":"modified"}async function on(r){let e="";try{e=(await ht("git",["diff","HEAD","--name-status","--no-renames"],{cwd:r,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let n of e.split(/\r?\n/).filter(Boolean)){let[o,...s]=n.split(" "),i=s.at(-1);if(!i)continue;let a="";try{a=(await ht("git",["diff","HEAD","--unified=0","--",i],{cwd:r,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:ai(o),ranges:ii(a)})}try{let n=await ht("git",["ls-files","--others","--exclude-standard"],{cwd:r});for(let o of n.stdout.split(/\r?\n/).filter(Boolean))t.some(s=>s.filePath===o)||t.push({filePath:o,status:"added",ranges:[]})}catch{}return t}function ci(r,e){return e.ranges.length===0?!0:typeof r.startLine!="number"||typeof r.endLine!="number"?!1:e.ranges.some(t=>r.startLine<=t.endLine&&r.endLine>=t.startLine)}var $e=class{constructor(e){this.graph=e}graph;map(e,t){let n=this.graph.allSymbols(e),o=[];for(let s of t){let i=n.filter(u=>u.filePath===s.filePath),c=i.filter(u=>u.type!=="file").filter(u=>ci(u,s));if(c.length===0){let u=i.find(l=>l.type==="file");u&&o.push({symbol:u,fileStatus:s.status,direct:!0});continue}for(let u of c)o.push({symbol:u,fileStatus:s.status,direct:!0})}return o}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var li={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function ui(r){return r>=30?"CRITICAL":r>=16?"HIGH":r>=6?"MEDIUM":"LOW"}function sn(r){let e=r.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var Ge=class{constructor(e){this.graph=e}graph;analyze(e,t,n=4){let o=this.graph.allEdges(e),s=new Map,i=0;for(let l of t){l.fileStatus==="deleted"?i+=8:l.fileStatus==="renamed"?i+=5:i+=2,l.symbol.type==="interface"&&(i+=5),l.symbol.type==="class"&&(i+=3);let m=new Set([l.symbol.id]),f=[{id:l.symbol.id,depth:0}];for(;f.length;){let p=f.shift();if(p.depth>=n)continue;let h=o.filter(v=>v.to===p.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(v.type));for(let v of h){if(m.has(v.from))continue;m.add(v.from);let M=this.graph.getSymbol(v.from);if(!M)continue;let A=p.depth+1,B=`${l.symbol.id}:${M.id}`;s.set(B,{symbol:M,relation:v.type,depth:A,sourceSymbolId:l.symbol.id});let q=li[v.type]??1;i+=Math.max(1,q-(A-1)),f.push({id:M.id,depth:A})}}}let a=[...s.values()].sort((l,m)=>l.depth-m.depth),c=[...new Set(a.map(l=>l.symbol.filePath))],u=c.filter(sn);return u.length===0&&u.push(...c.filter(l=>!sn(l)).slice(0,10)),{risk:ui(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:u}}};var ze=class{constructor(e){this.graph=e;this.mapper=new $e(e),this.blast=new Ge(e)}graph;mapper;blast;async analyzeGitDiff(e,t,n={}){let o=await on(t),s=this.mapper.map(e,o),i=this.blast.analyze(e,s,n.maxDepth??4);return{mode:"git_diff",changes:o,...i}}analyzeFile(e,t,n={}){let o=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,o,n.maxDepth??4)}}};var an={mode:kt.enum(["git_diff","file"]).optional(),filePath:kt.string().optional(),depth:kt.number().int().min(1).max(10).optional()};async function cn(r,e){let t=new ze(r.graph);if((e.mode??(e.filePath?"file":"git_diff"))==="file"){if(!e.filePath)throw new Error("filePath is required when mode=file");return t.analyzeFile(r.project.id,e.filePath,{maxDepth:e.depth})}return t.analyzeGitDiff(r.project.id,r.project.rootPath,{maxDepth:e.depth})}import{z as di}from"zod";var ln={symbol:di.string().min(1)};async function un(r,e){let t=E(r,e.symbol);if(!t)return{found:!1,query:e.symbol,dependents:[]};let o=new x(r.graph).dependents(r.project.id,t.id);return{found:!0,symbol:C(t),count:o.length,dependents:o.map(C)}}import{z as bt}from"zod";var dn={from:bt.string().min(1),to:bt.string().min(1),maxDepth:bt.number().int().min(1).max(30).optional()};async function mn(r,e){let t=E(r,e.from),n=E(r,e.to);if(!t||!n)return{found:!1,fromFound:!!t,toFound:!!n,path:[],edges:[]};let s=new x(r.graph).shortestPath(r.project.id,t.id,n.id,e.maxDepth??12);return{found:s.found,distance:s.distance,from:C(t),to:C(n),path:s.symbols.map(C),edges:s.edges.map(i=>({id:i.id,type:i.type,from:i.from,to:i.to,metadata:i.metadata}))}}import{z as vt}from"zod";var pn={symbol:vt.string().min(1),depth:vt.number().int().min(1).max(5).optional(),limit:vt.number().int().min(1).max(200).optional()};async function fn(r,e){let t=E(r,e.symbol);if(!t)return{found:!1,query:e.symbol};let o=new x(r.graph).neighborhood(r.project.id,t.id,e.depth??1);if(!o)return{found:!1,query:e.symbol};let s=e.limit??50;return{found:!0,center:C(o.center),incomingCount:o.incoming.length,outgoingCount:o.outgoing.length,incoming:o.incoming.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:C(i.symbol)})),outgoing:o.outgoing.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:C(i.symbol)}))}}import{z as wt}from"zod";function mi(r){return r.replaceAll("\\","/").toLowerCase()}var Ue=class{constructor(e){this.graph=e}graph;detect(e){let t=this.graph.allSymbols(e),n=this.graph.allEdges(e),o=[];for(let i of t){if(i.type!=="route"&&i.type!=="file")continue;let a=this.classify(i,n);a&&o.push({symbolId:i.id,filePath:i.filePath,name:i.name,kind:a.kind,score:a.score,reasons:a.reasons})}let s=new Map;for(let i of o){let a=i.kind==="route"?i.symbolId:i.filePath,c=s.get(a);(!c||i.score>c.score)&&s.set(a,i)}return[...s.values()].sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath))}classify(e,t){let n=mi(e.filePath),o=[];if(e.type==="route")return{kind:"route",score:100,reasons:["HTTP route"]};let s=null,i=0;if(n.startsWith("bin/"))s="cli",i=100,o.push("bin executable");else if(/(^|\/)(cli)\.[^.]+$/.test(n))s="cli",i=90,o.push("CLI entry file");else if(/(^|\/)(main|server)\.[^.]+$/.test(n))s="main",i=90,o.push("main/server file");else if(n.includes("/runtime/")&&/(^|\/)(bootstrap|index)\.[^.]+$/.test(n))s="runtime",i=75,o.push("runtime bootstrap");else if(/(^|\/)index\.[^.]+$/.test(n)){let c=t.filter(l=>l.to===e.id&&l.type!=="DEFINES").length,u=t.filter(l=>l.from===e.id&&l.type!=="DEFINES").length;(n.startsWith("packages/")||c===0||u>0)&&(s="package",i=n.startsWith("packages/")?70:55,o.push("package/public index"))}return s?(t.filter(c=>c.to===e.id&&c.type!=="DEFINES").length===0&&(i+=10,o.push("no incoming dependency")),{kind:s,score:i,reasons:o}):null}};var gn=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function St(r){return r.replaceAll("\\","/").toLowerCase()}function pi(r){let e=St(r);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function fi(r){let e=St(r.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var We=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),n=this.graph.allEdges(e),o=new Set(new Ue(this.graph).detect(e).map(i=>i.symbolId)),s=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||pi(i.filePath)||o.has(i.id)||fi(i)||n.filter(p=>p.to===i.id&&gn.has(p.type)).length>0)continue;let c=n.filter(p=>p.from===i.id&&gn.has(p.type)),u=["no incoming usage edge"],l=50;(i.type==="function"||i.type==="method")&&(l+=20,u.push("callable symbol")),i.type==="property"&&(l-=15),c.length===0&&(l+=10,u.push("no outgoing dependency")),St(i.filePath).includes("/internal/")&&(l+=10,u.push("internal implementation")),i.name.startsWith("_")&&(l+=5);let f=l>=75?"high":l>=55?"medium":"low";s.push({symbolId:i.id,name:i.name,qualifiedName:i.qualifiedName,type:i.type,filePath:i.filePath,startLine:i.startLine,confidence:f,score:l,reasons:u})}return s.sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath)||i.name.localeCompare(a.name))}};var hn={confidence:wt.enum(["high","medium","low","all"]).optional(),filePath:wt.string().min(1).optional(),limit:wt.number().int().min(1).max(500).optional()},yn={high:3,medium:2,low:1};async function kn(r,e){let n=new We(r.graph).analyze(r.project.id);if(e.confidence&&e.confidence!=="all"){let i=yn[e.confidence];n=n.filter(a=>yn[a.confidence]>=i)}e.filePath&&(n=n.filter(i=>i.filePath===e.filePath));let o=n.length,s=e.limit??100;return{total:o,high:n.filter(i=>i.confidence==="high").length,medium:n.filter(i=>i.confidence==="medium").length,low:n.filter(i=>i.confidence==="low").length,warning:"Dead-code results are candidates only. Verify before deleting code.",candidates:n.slice(0,s)}}import{z as $n}from"zod";import{existsSync as Li,readFileSync as Di}from"node:fs";import{join as Ki}from"node:path";import{existsSync as gi,mkdirSync as md,readFileSync as yi,renameSync as pd,writeFileSync as fd}from"node:fs";import{dirname as yd,join as hi}from"node:path";function ki(r){return hi(r.rootPath,".toolnet","work","current.json")}function Ct(r){let e=ki(r);if(!gi(e))return null;try{let t=JSON.parse(yi(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as bi,mkdirSync as bd,readFileSync as vi,renameSync as vd,writeFileSync as Sd}from"node:fs";import{dirname as Cd,join as Si}from"node:path";function wi(r){return Si(r.rootPath,".toolnet","context","session-origin.json")}function xt(r){let e=wi(r);if(!bi(e))return null;try{let t=JSON.parse(vi(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function Ci(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function Be(r){let e=Ci(r),t=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),n=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return t&&n?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}import{existsSync as Ti,mkdirSync as lm,readFileSync as ji}from"node:fs";import{join as wn}from"node:path";Se();Mt();var Qd=new _;function _i(r){return wn(r.rootPath,".toolnet","memory","checkpoints")}function Oi(r){return wn(_i(r),"latest.json")}function Ni(r){let e=Oi(r);if(!Ti(e))return null;try{let t=JSON.parse(ji(e,"utf8"));return t.schema!=="toolnet.memory.checkpoint.v1"||t.project.id!==r.id?null:t}catch{return null}}function Cn(r){return Ni(r)}var Fi={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,request:95,activity:90,phase:75,file:65,next_action:55,blocker:45},next_action:{next_action:100,todo:80,task:65,blocker:60,file:40},last_file:{file:100,task:65,next_action:40},blocker:{blocker:100,task:60,next_action:50,file:35},decision:{decision:100,rule:85,architecture:80,task:45,file:30},completed:{completed:100,progress:70,task:30},status:{progress:100,task:85,phase:75,blocker:65,next_action:60},summary:{task:100,request:98,activity:96,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,rule:54,architecture:53,fix:52,progress:50,test:45,goal:35}},$i={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function Gi(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function g(r,e){let t=e.value.replace(/\s+/g," ").trim();t&&r.push({...e,value:t,score:0})}function zi(r){let e=Ki(r.rootPath,".toolnet","work","handoff-latest.json");if(!Li(e))return null;try{let n=JSON.parse(Di(e,"utf8")).continuity;return n?.schema!=="toolnet.handoff.v2"||n.project.id!==r.id?null:n}catch{return null}}function Ui(r){let e=Cn(r);if(!e)return[];let t=[];e.request&&g(t,{kind:"request",value:e.request,source:"checkpoint"}),e.activity&&g(t,{kind:"activity",value:e.activity,source:"checkpoint"}),e.current.phase&&g(t,{kind:"phase",value:e.current.phase.title,source:"checkpoint"}),e.current.task&&g(t,{kind:"task",value:e.current.task.title,source:"checkpoint"});let n=e.files.active.at(-1);n&&g(t,{kind:"file",value:n,source:"checkpoint"});for(let o of e.nextActions)g(t,{kind:"next_action",value:o,source:"checkpoint"});for(let o of e.blockers)g(t,{kind:"blocker",value:o,source:"checkpoint"});for(let o of e.completed.tasks)g(t,{kind:"completed",value:o,source:"checkpoint"});for(let o of e.remaining.tasks)g(t,{kind:"todo",value:o,source:"checkpoint"});for(let o of e.durableFacts)g(t,{kind:o.kind,value:o.content,source:"checkpoint"});return t}function Wi(r){let e=zi(r);if(!e)return[];let t=[];g(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.request&&g(t,{kind:"request",value:e.request,source:"handoff"}),e.activity&&g(t,{kind:"activity",value:e.activity,source:"handoff"}),e.goal&&g(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&g(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&g(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&g(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&g(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let n of e.blockers)g(t,{kind:"blocker",value:n,source:"handoff"});for(let n of e.decisions)g(t,{kind:"decision",value:n,source:"handoff"});for(let n of e.completed.tasks)g(t,{kind:"completed",value:n,source:"handoff"});for(let n of e.remaining.todos)g(t,{kind:"todo",value:n,source:"handoff"});return g(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),g(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function Bi(r){let e=xt(r);if(!e)return[];let t=[];return g(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&g(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&g(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&g(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&g(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&g(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&g(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function qi(r){let e=Ct(r);if(!e)return[];let t=[];e.currentRequest&&g(t,{kind:"request",value:e.currentRequest,source:"work-state"}),e.currentActivity&&g(t,{kind:"activity",value:e.currentActivity,source:"work-state"}),e.goal&&g(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&g(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&g(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let n=e.activeFiles?.at(-1)??e.filesTouched.at(-1);n&&g(t,{kind:"file",value:n,source:"work-state"});for(let o of e.nextActions.slice(0,5))g(t,{kind:"next_action",value:o,source:"work-state"});for(let o of e.blockers.slice(-5))g(t,{kind:"blocker",value:o,source:"work-state"});for(let o of e.decisions.slice(-5))g(t,{kind:"decision",value:o,source:"work-state"});for(let o of e.tasks.filter(s=>s.status==="completed").slice(-8))g(t,{kind:"completed",value:o.title,source:"work-state"});for(let o of e.tasks.filter(s=>s.status!=="completed"&&s.status!=="cancelled").slice(0,8))g(t,{kind:"todo",value:o.title,source:"work-state"});for(let o of e.tests.slice(-5))g(t,{kind:"test",value:o,source:"work-state"});return g(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),t}function Vi(r,e){let t=Fi[r];return e.map((n,o)=>({...n,score:(t[n.kind]??10)+$i[n.source]+Math.max(0,5-o*.01)}))}function Hi(r){let e=new Map;for(let t of r){let n=`${t.kind}:${Gi(t.value)}`,o=e.get(n);(!o||t.score>o.score)&&e.set(n,t)}return[...e.values()]}function $(r,e,t={}){let n=Be(e),o=[...Ui(r),...Wi(r),...Bi(r),...qi(r)],s=Hi(Vi(n,o)).sort((l,m)=>m.score-l.score),i=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),c=[],u=0;for(let l of s){if(c.length>=i)break;let m=l.kind.length+l.value.length+l.source.length+16;c.length>0&&u+m>a||(c.push(l),u+=m)}return{intent:n,facts:c,context:{project:{id:r.id,name:r.name},intent:n,selectedFacts:c.map(l=>({kind:l.kind,value:l.value,source:l.source}))},stats:{candidates:o.length,selected:c.length,chars:u}}}var xn={previous_agent:"Agent tr\u01B0\u1EDBc",request:"Y\xEAu c\u1EA7u hi\u1EC7n t\u1EA1i",activity:"\u0110ang l\xE0m",goal:"M\u1EE5c ti\xEAu",phase:"Phase",task:"Task hi\u1EC7n t\u1EA1i",file:"File hi\u1EC7n t\u1EA1i",todo:"TODO",next_action:"Ti\u1EBFp theo",blocker:"Blocker",decision:"Quy\u1EBFt \u0111\u1ECBnh",rule:"Quy t\u1EAFc",architecture:"Ki\u1EBFn tr\xFAc",fix:"\u0110\xE3 s\u1EEDa",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},Mn=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],Ji={previous_agent:["previous_agent"],current_task:["request","activity","task","file","next_action"],next_action:["next_action","task","file","todo"],last_file:["file","task","next_action"],blocker:["blocker"],decision:["decision"],completed:["completed"],status:["progress","task","next_action","blocker"],summary:Mn};function Yi(r){let e=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)}function Qi(r){let e=r.filter(n=>n.source==="handoff");if(e.length===0)return r;let t=r.filter(n=>n.source==="checkpoint"&&["rule","architecture","fix"].includes(n.kind));return[...e,...t]}function Xi(r){let e=new Set,t=[];for(let n of r){let o=`${n.kind}:${n.value.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}`;e.has(o)||(e.add(o),t.push(n))}return t}function Pn(r){switch(r){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function Zi(r,e){let t=[];for(let n of e){let o=r.filter(s=>s.kind===n).slice(0,Pn(n));for(let s of o)t.push(`${xn[n]}: ${s.value}`)}return t.join(`
10
+ `)}function ea(r,e){let t=Ji[e]??Mn,n=[];for(let o of t){let s=r.filter(i=>i.kind===o).slice(0,Pn(o));for(let i of s)n.push(`${xn[o]}: ${i.value}`)}return n.join(`
11
+ `)}function Z(r,e){let t=$(r,e,{maxFacts:32,maxChars:6400}),n=Xi(Qi(t.facts)),o=Yi(e)?Zi(n,["todo","task","next_action","file"]):ea(n,String(t.intent));return o?{intent:String(t.intent),answer:o,source:n[0]?.source??"none"}:{intent:String(t.intent),answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}Ve();var ne=class extends Error{status;constructor(e,t){super(e),this.name="AiHttpError",this.status=t}};async function G(r,e,t=3e4){let n=new AbortController,o=setTimeout(()=>n.abort(),t);o.unref?.();try{let s=await fetch(r,{...e,signal:n.signal}),i=await s.text();if(!s.ok){let a=i;try{let c=JSON.parse(i);a=c.error?.message??c.message??i}catch{}throw new ne(a||`HTTP ${s.status}`,s.status)}return i.trim()?JSON.parse(i):{}}finally{clearTimeout(o)}}function He(r,e){return`${r.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`}Ve();Pt();var Je=class{constructor(e){this.config=e}config;id="cloudflare";model(){let e=this.config.model?.trim();if(!e)throw new Error("cloudflare: MODEL is not configured");return e}async generate(e){let t=this.config.accountId?.trim(),n=this.config.apiKey?.trim();if(!t)throw new Error("cloudflare: ACCOUNT ID is not configured");if(!n)throw new Error("cloudflare: API TOKEN is not configured");let o=this.model(),i=`${(this.config.baseUrl?.trim()||`https://api.cloudflare.com/client/v4/accounts/${t}/ai/run`).replace(/\/+$/,"")}/${o}`,a=await G(i,{method:"POST",headers:{authorization:`Bearer ${n}`,"content-type":"application/json",...this.config.headers},body:JSON.stringify({messages:e.messages,temperature:e.temperature,max_tokens:e.maxTokens})}),c=a.result?.response?.trim();if(!c)throw new Error(a.errors?.[0]?.message??"cloudflare: empty model response");return{text:c,provider:"cloudflare",model:o}}async healthCheck(){let e=Date.now();try{return{ok:!0,provider:"cloudflare",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:"cloudflare",model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}};var Ye=class{constructor(e){this.config=e}config;id="gemini";model(){let e=this.config.model?.trim();if(!e)throw new Error("gemini: MODEL is not configured");return e.replace(/^models\//,"")}async generate(e){let t=this.config.apiKey?.trim();if(!t)throw new Error("gemini: API KEY is not configured");let n=this.config.baseUrl?.trim()||"https://generativelanguage.googleapis.com/v1beta",o=this.model(),s=e.messages.filter(l=>l.role==="system"),i=e.messages.filter(l=>l.role!=="system").map(l=>({role:l.role==="assistant"?"model":"user",parts:[{text:l.content}]})),a=`${He(n,`models/${encodeURIComponent(o)}:generateContent`)}?key=${encodeURIComponent(t)}`,c=await G(a,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({...s.length?{systemInstruction:{parts:[{text:s.map(l=>l.content).join(`
12
+
13
+ `)}]}}:{},contents:i,generationConfig:{temperature:e.temperature,maxOutputTokens:e.maxTokens}})}),u=c.candidates?.[0]?.content?.parts?.map(l=>l.text??"").join("").trim();if(!u)throw new Error("gemini: empty model response");return{text:u,provider:"gemini",model:o,usage:c.usageMetadata?{inputTokens:c.usageMetadata.promptTokenCount,outputTokens:c.usageMetadata.candidatesTokenCount,totalTokens:c.usageMetadata.totalTokenCount}:void 0}}async healthCheck(){let e=Date.now();try{return{ok:!0,provider:"gemini",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:"gemini",model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}};var Qe=class{constructor(e){this.config=e;this.id=e.id}config;id;baseUrl(){let e=this.config.baseUrl?.trim();if(!e)throw new Error(`${this.id}: BASE URL is not configured`);return e}model(){let e=this.config.model?.trim();if(!e)throw new Error(`${this.id}: MODEL is not configured`);return e}headers(){let e={"content-type":"application/json",...this.config.headers};return this.config.apiKey&&(e.authorization=`Bearer ${this.config.apiKey}`),e}async generate(e){let t=this.model(),n=await G(He(this.baseUrl(),"chat/completions"),{method:"POST",headers:this.headers(),body:JSON.stringify({model:t,messages:e.messages,temperature:e.temperature,max_tokens:e.maxTokens,...this.id==="alibaba"?{enable_thinking:!1}:{}})}),o=n.choices?.[0]?.message?.content?.trim();if(!o)throw new Error(`${this.id}: empty model response`);return{text:o,provider:this.id,model:t,usage:n.usage?{inputTokens:n.usage.prompt_tokens,outputTokens:n.usage.completion_tokens,totalTokens:n.usage.total_tokens}:void 0}}async healthCheck(){let e=Date.now();try{let t=await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8});return{ok:!0,provider:this.id,model:t.model,message:"Provider reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:this.id,model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}};function _n(r=In()){switch(N(r.id).transport){case"gemini":return new Ye(r);case"cloudflare":return new Je(r);default:return new Qe(r)}}function oa(r){return new Promise(e=>{setTimeout(e,r)})}function sa(r){if(r instanceof ne){let t=r.status;return t===void 0||t===408||t===409||t===425||t===429?!0:t>=500}if(!(r instanceof Error))return!0;let e=r.message.toLowerCase();return e.includes("401")||e.includes("403")||e.includes("400")||e.includes("invalid api key")||e.includes("unauthorized")||e.includes("forbidden")?!1:e.includes("timeout")||e.includes("timed out")||e.includes("abort")||e.includes("network")||e.includes("fetch failed")||e.includes("econnreset")||e.includes("econnrefused")||e.includes("429")||e.includes("rate limit")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("504")}var Xe=class{id;config;providers;states=new Map;cooldownMs;maxRetries;constructor(e,t=[],n={}){this.id=e.config.id,this.config=e.config,this.cooldownMs=n.cooldownMs??6e4,this.maxRetries=Math.max(0,n.maxRetries??1),this.providers=[e,...t].map(o=>({provider:_n(o.config),label:o.label}))}key(e){let t=this.providers[e];return`${e}:${t.provider.id}:${t.provider.config.model??""}`}state(e){let t=this.key(e),n=this.states.get(t);return n||(n={failures:0,cooldownUntil:0},this.states.set(t,n)),n}available(e){return this.state(e).cooldownUntil<=Date.now()}success(e){let t=this.state(e);t.failures=0,t.cooldownUntil=0,t.lastError=void 0}fail(e,t){let n=this.state(e);n.failures+=1,n.lastError=t instanceof Error?t.message:String(t),n.cooldownUntil=Date.now()+this.cooldownMs}async generate(e){let t=[];for(let n=0;n<this.providers.length;n+=1){if(!this.available(n)){t.push(`${this.providers[n].label}: cooldown`);continue}let o=this.providers[n];for(let s=0;s<=this.maxRetries;s+=1)try{let i=await o.provider.generate(e);return this.success(n),i}catch(i){let a=i instanceof Error?i.message:String(i),c=sa(i);if(t.push(`${o.label}: ${a}`),!c)throw i;if(s<this.maxRetries){await oa(Math.min(250*2**s,2e3));continue}this.fail(n,i)}}throw new Error(`All ToolNet LLM providers failed: ${t.join(" | ")}`)}async healthCheck(){let e=Date.now();try{let t=await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8});return{ok:!0,provider:t.provider,model:t.model,message:"Fallback chain reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:this.id,model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}status(){return this.providers.map((e,t)=>{let n=this.state(t);return{position:t,provider:e.provider.id,model:e.provider.config.model,cooldown:n.cooldownUntil>Date.now(),cooldownUntil:n.cooldownUntil||void 0,failures:n.failures,lastError:n.lastError}})}};function On(){let r=re(),e=Tn();return new Xe({label:`Primary (${r.llm.provider})`,config:{id:r.llm.provider,apiKey:r.llm.apiKey,baseUrl:r.llm.baseUrl,model:r.llm.model,accountId:r.llm.accountId}},e.map(t=>({label:`Fallback ${t.slot} (${t.config.provider})`,config:{id:t.config.provider,apiKey:t.config.apiKey,baseUrl:t.config.baseUrl,model:t.config.model,accountId:t.config.accountId}})),jn())}var At=class{constructor(e=On()){this.provider=e}provider;get activeProvider(){return this.provider}setProvider(e){this.provider=e}generate(e){return this.provider.generate(e)}};function Nn(){return new At(On())}function ia(r,e){let t=JSON.stringify(r,null,2);return t.length<=e?t:t.slice(0,e)+`
14
+ [truncated]`}function aa(r,e){let t=Z(r,e),n=$(r,e,{maxFacts:12,maxChars:3200});return ia({project:n.context.project,intent:n.intent,directAnswer:t.answer,selectedMemory:n.context.selectedFacts,retrievalStats:n.stats},4200)}async function Ln(r,e,t={}){let n=Z(r,e),o=aa(r,e),s=t.router??Nn();try{let i=await s.generate({temperature:.1,maxTokens:450,messages:[{role:"system",content:`
15
+ You are ToolNet Memory Agent.
16
+
17
+ You are NOT the coding agent.
18
+
19
+ Your job is to help another coding AI continue work from previous sessions.
20
+
21
+ Rules:
22
+
23
+ 1. Answer only from the supplied ToolNet project memory.
24
+ 2. Never invent completed work, files, blockers, decisions, or test results.
25
+ 3. Prefer the latest session/work state over old information.
26
+ 4. Be concise.
27
+ 5. Do not dump raw JSON or full memory files.
28
+ 6. Tell the coding agent exactly:
29
+ - what the previous agent was doing,
30
+ - what is already completed,
31
+ - what remains unfinished,
32
+ - what file was last touched,
33
+ - what should be done next,
34
+ when those facts are available.
35
+ 7. If information is missing, say it is not recorded.
36
+ 8. Do not explain ToolNet internals unless asked.
37
+ 9. Do not repeat irrelevant history.
38
+ 10. Respond in the same language as the question.
39
+
40
+ Think of yourself as the project's memory coworker talking directly to another AI.
41
+ `.trim()},{role:"user",content:`
42
+ Question from coding agent:
43
+
44
+ ${e}
45
+
46
+ ToolNet selected memory:
47
+
48
+ ${o}
49
+
50
+ Answer the coding agent directly.
51
+ `.trim()}]}),a=i.text.trim();return a?{answer:a,provider:i.provider,model:i.model,usedAi:!0}:{answer:n.answer,usedAi:!1}}catch{return{answer:n.answer,usedAi:!1}}}import{existsSync as ca,mkdirSync as la,readFileSync as ua,renameSync as da,rmSync as ma,writeFileSync as pa}from"node:fs";import{join as Dn}from"node:path";var fa=720*60*1e3;function Kn(r){return Dn(r.rootPath,".toolnet","context","memory-agent-conversation.json")}function oe(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function ga(r){let e=oe(r);return[/\btiếp tục\b/u,/\btiếp tục task\b/u,/\blúc nãy\b/u,/\btrước đó\b/u,/\btask trước\b/u,/\bprevious (?:task|session|work)\b/u,/\bcontinue\b/u,/\bresume\b/u,/\bcurrent task\b/u,/\bđang làm gì\b/u].some(t=>t.test(e))}function ya(r){if(ga(r))return!1;let e=oe(r),t=e.split(/\s+/u).filter(Boolean);return[/^(?:tại sao|vì sao|sao vậy)\b/u,/^(?:why|why so|why that)\b/u,/^(?:còn|thế|vậy|rồi sao|sau đó)\b/u,/^(?:what about|and what|then what)\b/u,/^(?:cái đó|việc đó|nó|phần đó)\b/u].some(n=>n.test(e))?!0:t.length<=5&&/\b(?:nó|đó|vậy|thế|that|it|this)\b/u.test(e)}function ha(r,e,t){let n=Kn(r);if(!ca(n))return null;try{let o=JSON.parse(ua(n,"utf8"));if(o.schema!=="toolnet.memory-conversation.v1"||o.version!==1||o.projectId!==r.id||!Array.isArray(o.focus))return null;let s=Date.parse(o.updatedAt);return!Number.isFinite(s)||e-s>t?null:o}catch{return null}}function ka(r,e=8){let t=new Set,n=[];for(let o of r){let s=o.value.replace(/\s+/gu," ").trim();if(!s)continue;let i=[o.kind,oe(s)].join(":");if(!t.has(i)&&(t.add(i),n.push({...o,value:s}),n.length>=e))break}return n}function ba(r,e){let t=Kn(r),n=Dn(r.rootPath,".toolnet","context");la(n,{recursive:!0,mode:448});let o=`${t}.${process.pid}.tmp`;try{pa(o,JSON.stringify(e,null,2)+`
52
+ `,{encoding:"utf8",mode:384}),da(o,t)}finally{ma(o,{force:!0})}}function va(r){return r.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
53
+ `)}function Sa(r,e){return r.priorFocus.find(t=>t.kind===e)?.value}function Et(r){if(!r.usedPriorFocus||r.currentIntent!=="summary"||r.priorFocus.length===0)return null;let e=oe(r.originalQuestion),t=/^(?:tại sao|vì sao|sao vậy|why|why so|why that)\b/u.test(e),n=/^(?:rồi sao|sau đó|tiếp thì sao|thế tiếp theo|then what|what next)\b/u.test(e),o=t?["decision","blocker","next_action","task","file"]:n?["next_action","todo","task","blocker","file","decision"]:["task","next_action","file","decision","blocker"],s={task:"Task li\xEAn quan",next_action:"Vi\u1EC7c ti\u1EBFp theo",file:"File li\xEAn quan",decision:"Quy\u1EBFt \u0111\u1ECBnh li\xEAn quan",blocker:"Blocker",todo:"TODO"},i=[];for(let a of o){let c=Sa(r,a);if(c&&(i.push(`${s[a]??a}: ${c}.`),t&&i.length>=2||!t&&i.length>=3))break}return i.length===0?null:{answer:i.join(" "),intent:"summary",source:"conversation-focus"}}function wa(r){let e=oe(r);return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(e)}function Fn(r,e,t={}){let n=t.now??Date.now(),o=t.maxAgeMs??fa,s=ha(r,n,o),i=!!(s&&s.focus.length>0&&ya(e)&&!wa(e)),a=i&&s?[e.trim(),"","Previous ToolNet Memory conversation focus:",va(s),"","Use the compact focus only to resolve the current follow-up question.","Do not reconstruct or request raw session transcripts."].join(`
54
+ `):e.trim(),c=Be(e),l=$(r,a,{maxFacts:8,maxChars:1800}).facts.map(f=>({kind:f.kind,value:f.value,source:f.source})),m=ka(i&&s?[...l,...s.focus]:l);return ba(r,{schema:"toolnet.memory-conversation.v1",version:1,projectId:r.id,updatedAt:new Date(n).toISOString(),lastIntent:c,focus:m}),{question:a,originalQuestion:e,usedPriorFocus:i,previousIntent:s?.lastIntent,currentIntent:c,priorFocus:s?.focus??[],focusCount:m.length}}var Gn={question:$n.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:$n.enum(["ai","local"]).optional().describe("ai uses ToolNet Memory Agent with configured LLM fallback chain. local returns deterministic local memory only.")};async function zn(r,e){let t=Fn(r.project,e.question);if(e.mode==="local"){let o=Et(t);if(o)return{answer:o.answer,mode:"local",usedAi:!1,source:o.source,intent:o.intent};let s=Z(r.project,t.originalQuestion);return{answer:s.answer,mode:"local",usedAi:!1,source:s.source,intent:s.intent}}let n=await Ln(r.project,t.question);if(!n.usedAi){let o=Et(t);if(o)return{answer:o.answer,mode:"ai",usedAi:!1,provider:n.provider,model:n.model}}return{answer:n.answer,mode:"ai",usedAi:n.usedAi,provider:n.provider,model:n.model}}import{z as Jn}from"zod";import{chmodSync as ip,existsSync as Un,mkdirSync as ap,readFileSync as Wn,renameSync as cp,writeFileSync as lp}from"node:fs";import{dirname as dp,join as se}from"node:path";var Bn="toolnet.context-offload.v1",Ca="toolnet.context-offload-asset.v1";function qn(r){return se(r,".toolnet","offload")}function Vn(r){return se(qn(r),"assets")}function xa(r){return se(qn(r),"graph.json")}function Rt(){return{schema:Bn,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function Ma(r){let e=xa(r);if(!Un(e))return Rt();try{let t=JSON.parse(Wn(e,"utf8"));return t.schema!==Bn||t.version!==1||!Array.isArray(t.nodes)?Rt():t}catch{return Rt()}}function Pa(r,e){let t=e.trim().toLowerCase();if(!/^[a-f0-9]{8,64}$/u.test(t))throw new Error("Invalid context offload asset reference.");if(t.length===64&&Un(se(Vn(r),`${t}.json`)))return t;let n=Ma(r).nodes.map(o=>o.id).filter(o=>o.startsWith(t));if(n.length===0)throw new Error(`Context offload asset not found: ${e}`);if(n.length>1)throw new Error(`Ambiguous context offload asset reference: ${e}`);return n[0]}function Hn(r,e,t=6e3){let n=Pa(r,e),o=Wn(se(Vn(r),`${n}.json`),"utf8"),s=JSON.parse(o);if(s.schema!==Ca||s.version!==1||s.assetId!==n)throw new Error(`Invalid context offload asset: ${e}`);let i=Math.max(200,Math.min(2e4,Math.floor(t)));return{assetId:n,kind:s.event.type,bytes:Buffer.byteLength(o,"utf8"),truncated:o.length>i,content:o.length>i?`${o.slice(0,i)}
55
+ [truncated]`:o}}var Yn={assetId:Jn.string().regex(/^[a-f0-9]{8,64}$/iu).describe("Asset reference from the ToolNet Context Offload Graph."),maxChars:Jn.number().int().min(200).max(2e4).optional().describe("Maximum asset characters to return. Defaults to 6000.")};async function Qn(r,e){return Hn(r.project.rootPath,e.assetId,e.maxChars??6e3)}import{z as eo}from"zod";import{chmodSync as hp,existsSync as Aa,mkdirSync as kp,readFileSync as Ea,readdirSync as Ra,renameSync as bp,statSync as Ia,writeFileSync as vp}from"node:fs";import{join as Xn}from"node:path";var Ta="toolnet.skill-memory.v1";function ja(r,e=Number.MAX_SAFE_INTEGER){let t=new Set,n=[];for(let o of r){let s=o.replace(/\s+/gu," ").trim();if(!s)continue;let i=s.normalize("NFKC").toLowerCase();if(!t.has(i)&&(t.add(i),n.push(s),n.length>=e))break}return n}function _a(r){return Xn(r.rootPath,".toolnet","memory","skills")}function Oa(r,e){if(!r||typeof r!="object")return!1;let t=r;return t.schema===Ta&&t.version===1&&t.projectId===e&&typeof t.id=="string"&&typeof t.task=="string"&&Array.isArray(t.steps)&&Array.isArray(t.verification)&&Array.isArray(t.files)}function Na(r){let e=_a(r);if(!Aa(e))return[];if(!Ia(e).isDirectory())return[];let t=[];for(let n of Ra(e)){if(!n.endsWith(".json"))continue;let o=Xn(e,n);try{let s=JSON.parse(Ea(o,"utf8"));Oa(s,r.id)&&t.push(s)}catch{}}return t.sort((n,o)=>{let s=o.createdAt.localeCompare(n.createdAt);return s!==0?s:n.id.localeCompare(o.id)})}function La(r){return ja(r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_./-]+/gu).filter(e=>e.length>=2),32)}function Da(r,e){let t=e.normalize("NFKC").toLowerCase().trim();if(!t)return 0;if(r.id.toLowerCase()===t||r.fingerprint.toLowerCase()===t)return 1e3;let n=[r.title,r.task,r.summary,...r.steps,...r.verification,...r.files].join(`
56
+ `).normalize("NFKC").toLowerCase(),o=0;r.task.normalize("NFKC").toLowerCase().includes(t)&&(o+=40),r.title.normalize("NFKC").toLowerCase().includes(t)&&(o+=30);for(let s of La(t))n.includes(s)&&(o+=5),r.task.normalize("NFKC").toLowerCase().includes(s)&&(o+=4),r.files.some(i=>i.toLowerCase().includes(s))&&(o+=3);return o}function Zn(r,e,t=5){let n=Math.max(1,Math.min(10,Math.floor(t)));return Na(r).map(o=>({...o,score:Da(o,e)})).filter(o=>o.score>0).sort((o,s)=>s.score!==o.score?s.score-o.score:s.createdAt.localeCompare(o.createdAt)).slice(0,n)}var to={query:eo.string().min(2).max(500).describe("Task, problem, file, command or workflow to match against successful reusable Skill Memory SOPs."),limit:eo.number().int().min(1).max(10).optional().describe("Maximum matching reusable SOPs to return. Default 5.")};async function ro(r,e){let t=Zn(r.project,e.query,e.limit??5);return{schema:"toolnet.skill-memory-search.v1",query:e.query,count:t.length,matches:t}}import{z as go}from"zod";var no="wiki/state.v1.json";function Ka(r){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:r.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function Fa(r,e){let t=JSON.parse(r);if(t.schema!=="toolnet.wiki.v1"||t.version!==1||t.projectId!==e.id||!Array.isArray(t.pages)||!Array.isArray(t.revisions))throw new Error("Invalid ToolNet Wiki state");return t}var R=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(no);if(!e){let t=Ka(this.project);return await this.save(t),t}return Fa(e,this.project)}async save(e){await this.storage.put(no,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as io}from"node:crypto";var S=class extends Error{constructor(t,n){super(t);this.statusCode=n}statusCode};function ie(r){let e=new Set,t=[];for(let n of r){let o=n.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();e.has(s)||(e.add(s),t.push(o))}return t}function ae(r){let e=r.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!e)throw new S("Invalid Wiki slug",400);return e}function oo(r){let e=[];for(let t of r.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let n=t[1]?.trim();n&&e.push(ae(n))}return ie(e)}function $a(r){return r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function so(r){return{id:`revision-${io()}`,pageId:r.id,slug:r.slug,revision:r.revision,title:r.title,...r.summary?{summary:r.summary}:{},content:r.content,tags:[...r.tags],links:[...r.links],createdAt:r.updatedAt}}function L(r){return structuredClone(r)}var I=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(e){let t,n=this.queue.then(async()=>{let o=await this.ensureState();t=e(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=n.then(()=>{},()=>{}),await n,t}async summary(){let e=await this.ensureState(),t=new Set(e.pages.flatMap(n=>n.links));return{schema:"toolnet.wiki-summary.v1",projectId:e.projectId,pages:e.pages.length,revisions:e.revisions.length,tags:ie(e.pages.flatMap(n=>n.tags)).sort((n,o)=>n.localeCompare(o)),links:e.pages.reduce((n,o)=>n+o.links.length,0),orphanPages:e.pages.filter(n=>n.links.length===0&&!t.has(n.slug)).length,automatedPages:e.pages.filter(n=>n.tags.some(o=>o.startsWith("toolnet-auto-"))).length,updatedAt:e.updatedAt}}async listPages(){let e=await this.ensureState();return L([...e.pages].sort((t,n)=>t.title.localeCompare(n.title)))}async getPage(e){let t=await this.ensureState(),n=ae(e),o=t.pages.find(s=>s.slug===n||s.id===e);if(!o)throw new S(`Wiki page not found: ${e}`,404);return L(o)}async createPage(e){return this.mutate(t=>{let n=e.title.trim(),o=e.content.trim();if(!n)throw new S("Wiki title is required",400);let s=ae(e.slug??n);if(t.pages.some(c=>c.slug===s))throw new S(`Wiki page already exists: ${s}`,409);let i=new Date().toISOString(),a={id:`wiki-${io()}`,slug:s,title:n,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:o,tags:ie(e.tags??[]),links:oo(o),revision:1,createdAt:i,updatedAt:i};return t.pages.push(a),t.revisions.push(so(a)),L(a)})}async updatePage(e,t){return this.mutate(n=>{let o=ae(e),s=n.pages.find(i=>i.slug===o||i.id===e);if(!s)throw new S(`Wiki page not found: ${e}`,404);if(t.title!==void 0){let i=t.title.trim();if(!i)throw new S("Wiki title is required",400);s.title=i}if(t.summary!==void 0){let i=t.summary.trim();i?s.summary=i:delete s.summary}return t.content!==void 0&&(s.content=t.content.trim(),s.links=oo(s.content)),t.tags!==void 0&&(s.tags=ie(t.tags)),s.revision+=1,s.updatedAt=new Date().toISOString(),n.revisions.push(so(s)),L(s)})}async history(e){let t=await this.getPage(e),n=await this.ensureState();return L(n.revisions.filter(o=>o.pageId===t.id).sort((o,s)=>s.revision-o.revision))}async backlinks(e){let t=await this.getPage(e),n=await this.ensureState();return L(n.pages.filter(o=>o.links.includes(t.slug)).sort((o,s)=>o.title.localeCompare(s.title)))}async search(e,t=10){let n=await this.ensureState(),o=ie($a(e));if(o.length===0)return[];let s=Math.max(1,Math.min(20,Math.floor(t))),i=[];for(let a of n.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),l=a.summary?.toLowerCase()??"",m=a.content.toLowerCase(),f=a.tags.map(h=>h.toLowerCase()),p=0;for(let h of o)u===h&&(p+=12),c===h&&(p+=10),c.includes(h)&&(p+=6),u.includes(h)&&(p+=5),f.some(v=>v===h)?p+=5:f.some(v=>v.includes(h))&&(p+=3),l.includes(h)&&(p+=2),m.includes(h)&&(p+=1);p>0&&i.push({page:L(a),score:p})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,s)}};import{createHash as Ga,randomUUID as ao}from"node:crypto";var co="wiki/governance.v1.json",po="toolnet.knowledge-governance.v1",lo=500,ce={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function za(r,e=0,t=1){return Math.max(e,Math.min(t,r))}function It(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function uo(r){return Ga("sha256").update(r.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function Ua(r){let e=[r.title,r.summary??"",r.content.slice(0,2e3),...r.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(e)}function Wa(r){let e=r.sourceType==="skill"?.96:r.sourceType==="memory"?.94:.88,t=r.tags.map(n=>n.toLowerCase());return(t.includes("permanent")||t.includes("task"))&&(e+=.03),r.content.length>=200&&(e+=.02),r.content.length<80&&(e-=.05),r.title.length<4&&(e-=.05),za(e)}function mo(r){let e=new Date().toISOString();return{schema:po,version:1,projectId:r,policy:{...ce},reviews:[],audit:[],createdAt:e,updatedAt:e}}function fo(r){let e=r.autoApproveThreshold??ce.autoApproveThreshold,t=r.criticalApproveThreshold??ce.criticalApproveThreshold,n=r.staleAfterDays??ce.staleAfterDays;if(!Number.isFinite(e)||e<.5||e>1)throw new S("Invalid autoApproveThreshold",400);if(!Number.isFinite(t)||t<.5||t>1)throw new S("Invalid criticalApproveThreshold",400);if(!Number.isInteger(n)||n<1||n>3650)throw new S("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:t,staleAfterDays:n}}var le=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(co);if(!e){let t=mo(this.project.id);return await this.save(t),t}try{let t=JSON.parse(e);if(t.schema!==po||t.version!==1||t.projectId!==this.project.id||!Array.isArray(t.reviews)||!Array.isArray(t.audit))throw new Error("invalid");return{...t,policy:fo(t.policy??ce)}}catch{let t=mo(this.project.id);return await this.save(t),t}}async save(e){await this.storage.put(co,JSON.stringify(e,null,2),"application/json")}},ue=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(e,t,n,o={}){e.audit.push({id:ao(),action:t,principal:n,...o.reviewId?{reviewId:o.reviewId}:{},...o.sourceKey?{sourceKey:o.sourceKey}:{},timestamp:new Date().toISOString(),...o.metadata?{metadata:o.metadata}:{}}),e.audit.length>lo&&(e.audit=e.audit.slice(-lo))}async mutate(e){let t,n=this.queue.then(async()=>{let o=await this.ensureState();t=await e(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=n.then(()=>{},()=>{}),await n,t}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(e,t){return this.mutate(n=>(n.policy=fo({...n.policy,...e}),this.audit(n,"policy:update",t,{metadata:{...n.policy}}),{...n.policy}))}async summary(){let e=await this.ensureState(),t=n=>e.reviews.filter(o=>o.status===n).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:e.projectId,pending:t("pending"),approved:t("approved"),rejected:t("rejected"),superseded:t("superseded"),criticalPending:e.reviews.filter(n=>n.status==="pending"&&n.risk==="critical").length,conflictPending:e.reviews.filter(n=>n.status==="pending"&&n.risk==="conflict").length,auditEvents:e.audit.length,policy:{...e.policy},updatedAt:e.updatedAt}}async listReviews(e){let t=await this.ensureState();return structuredClone(t.reviews.filter(n=>!e||n.status===e).sort((n,o)=>o.updatedAt.localeCompare(n.updatedAt)))}async auditLog(e=100){let t=await this.ensureState(),n=Math.max(1,Math.min(500,Math.floor(e)));return structuredClone(t.audit.slice(-n).reverse())}async assess(e,t){let n=await this.ensureState(),o=Wa(e),s=It(e.title),i=t.filter(l=>l.slug!==e.slug&&It(l.title)===s&&uo(l.content)!==uo(e.content)).map(l=>l.slug),a=Ua(e),c=[];o<n.policy.autoApproveThreshold&&c.push(`confidence:${o.toFixed(2)}`),a&&o<n.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:u,requiresReview:i.length>0||o<n.policy.autoApproveThreshold||a&&o<n.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(e,t){let n=await this.assess(e,t);return this.mutate(o=>{let s=o.reviews.find(c=>c.sourceKey===e.sourceKey&&c.digest===e.digest);if(s?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:n,review:structuredClone(s)};if(s?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:n,review:structuredClone(s)};if(!n.requiresReview)return this.audit(o,"knowledge:auto-approved","system",{sourceKey:e.sourceKey,metadata:{confidence:n.confidence,risk:n.risk}}),{allowed:!0,mode:"auto-approved",assessment:n};if(s?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:n,review:structuredClone(s)};let i=new Date().toISOString(),a={id:ao(),sourceKey:e.sourceKey,sourceType:e.sourceType,slug:e.slug,marker:e.marker,digest:e.digest,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...new Set([...e.tags,e.marker])],confidence:n.confidence,risk:n.risk,reasons:[...n.reasons],conflicts:[...n.conflicts],status:"pending",createdAt:i,updatedAt:i};return o.reviews.push(a),this.audit(o,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:n,review:structuredClone(a)}})}async markApplied(e,t){await this.mutate(n=>{let o=n.reviews.find(s=>s.sourceKey===e&&s.digest===t&&s.status==="approved");o&&(o.appliedAt=new Date().toISOString(),o.updatedAt=o.appliedAt,this.audit(n,"knowledge:applied",o.reviewedBy??"system",{reviewId:o.id,sourceKey:e}))})}async decide(e,t,n){return this.mutate(async o=>{let s=o.reviews.find(u=>u.id===e);if(!s)throw new S(`Governance review not found: ${e}`,404);if(s.status!=="pending")throw new S("Governance review is already resolved",409);let i=new Date().toISOString();if(s.reviewedAt=i,s.reviewedBy=t.principal,s.updatedAt=i,t.note?.trim()&&(s.reviewNote=t.note.trim()),t.action==="reject")return s.status="rejected",this.audit(o,"knowledge:rejected",t.principal,{reviewId:e,sourceKey:s.sourceKey}),structuredClone(s);if(t.action==="supersede")return s.status="superseded",t.targetReviewId&&(s.supersededBy=t.targetReviewId),this.audit(o,"knowledge:superseded",t.principal,{reviewId:e,sourceKey:s.sourceKey,metadata:{targetReviewId:t.targetReviewId}}),structuredClone(s);if(t.action==="merge"){if(!t.targetReviewId)throw new S("targetReviewId is required for merge",400);let u=o.reviews.find(l=>l.id===t.targetReviewId);if(!u)throw new S("Merge target review not found",404);return s.status="superseded",s.mergedInto=u.id,this.audit(o,"knowledge:merged",t.principal,{reviewId:e,sourceKey:s.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(s)}s.status="approved";let c=(await n.listPages()).find(u=>u.slug===s.slug);if(c&&!c.tags.includes(s.marker))throw new S(`Wiki page '${s.slug}' is manually managed`,409);return c?await n.updatePage(s.slug,{title:s.title,summary:s.summary??"",content:s.content,tags:s.tags}):await n.createPage({slug:s.slug,title:s.title,...s.summary?{summary:s.summary}:{},content:s.content,tags:s.tags}),s.appliedAt=i,this.audit(o,"knowledge:approved",t.principal,{reviewId:e,sourceKey:s.sourceKey}),structuredClone(s)})}async quality(e){let t=await this.ensureState(),n=await e.listPages(),o=Date.now(),s=t.policy.staleAfterDays*864e5,i=n.map(l=>{let m=o-Date.parse(l.updatedAt);return{slug:l.slug,title:l.title,updatedAt:l.updatedAt,ageDays:Math.max(0,Math.floor(m/864e5)),stale:Number.isFinite(m)&&m>s}}).filter(l=>l.stale).map(({stale:l,...m})=>m),a=new Map;for(let l of n){let m=It(l.title),f=a.get(m)??[];f.push(l),a.set(m,f)}let c=[...a.entries()].filter(([,l])=>l.length>1).map(([l,m])=>({title:l,pages:m.map(f=>f.slug)})),u=t.reviews.filter(l=>l.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:n.length,automatedPages:n.filter(l=>l.tags.some(m=>m.startsWith("toolnet-auto-"))).length,manualPages:n.filter(l=>!l.tags.some(m=>m.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(l=>l.confidence<t.policy.autoApproveThreshold).length,conflicts:u.filter(l=>l.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var yo={query:go.string().min(2).max(500).describe("Knowledge topic or project concept to search in ToolNet Wiki."),limit:go.number().int().min(1).max(10).optional().describe("Maximum Wiki matches. Default 5.")};async function ho(r,e){let t=r.storage;if(!t)throw new Error("Wiki storage unavailable");let n=new I(new R(t,r.project));await n.initialize();let o=await n.search(e.query,e.limit??5);return{schema:"toolnet.wiki-search.v1",query:e.query,count:o.length,results:o.map(({page:s,score:i})=>({id:s.id,slug:s.slug,title:s.title,summary:s.summary,tags:s.tags,links:s.links,revision:s.revision,updatedAt:s.updatedAt,score:i}))}}import{z as Ba}from"zod";var ko={page:Ba.string().min(1).max(200).describe("Wiki page slug or page id.")};async function bo(r,e){let t=r.storage;if(!t)throw new Error("Wiki storage unavailable");let n=new I(new R(t,r.project));await n.initialize();let o=await n.getPage(e.page),s=await n.backlinks(o.slug);return{schema:"toolnet.wiki-read.v1",page:o,backlinks:s.map(i=>({slug:i.slug,title:i.title}))}}import{z as qa}from"zod";var vo={includePending:qa.boolean().optional().describe("Include compact pending-review metadata. Default false.")};async function So(r,e){let t=r.storage;if(!t)throw new Error("Knowledge Governance storage unavailable");let n=new ue(new le(t,r.project));await n.initialize();let o=new I(new R(t,r.project));await o.initialize();let s=await n.summary(),i=await n.quality(o),a=e.includePending?(await n.listReviews("pending")).slice(0,10).map(c=>({id:c.id,sourceType:c.sourceType,title:c.title,confidence:c.confidence,risk:c.risk,reasons:c.reasons})):void 0;return{schema:"toolnet.knowledge-governance-status.v1",summary:s,quality:{stalePages:i.stalePages.length,duplicateTitles:i.duplicateTitles.length,pendingReviews:i.pendingReviews,conflicts:i.conflicts},...a?{pending:a}:{}}}var wo={};function Co(r){let e=r.project.id;return{project:{id:e,name:r.project.name,remote:r.project.remote??r.project.name,rootPath:r.project.rootPath},runtime:r.runtime?{phase:r.runtime.phase,dependencies:{memory:{...r.runtime.dependencies.memory},graph:{...r.runtime.dependencies.graph},semantic:{...r.runtime.dependencies.semantic}},metrics:{...r.runtime.metrics},errors:[...r.runtime.errors],dataSource:r.runtime.dataSource,lastUpdatedAt:r.runtime.lastUpdatedAt}:null,storage:r.storage?.name??null,data:{memories:r.memory.exportProject(e).length,graphSymbols:r.graph.allSymbols(e).length,graphEdges:r.graph.allEdges(e).length,semanticAvailable:r.codeSemantic!==void 0}}}function b(r){return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}var Ja=["# ToolNet Memory \u2014 Persistent Project Continuity","","ToolNet Memory provides persistent work continuity across coding agents and sessions.","","CONTINUITY RULES:","","1. When the user asks to continue, resume, finish, pick up, or return to previous work,"," call memory_agent_ask BEFORE reconstructing previous work from git, files, or session history.","",'2. Use memory_agent_ask with mode="local" for direct continuity facts such as:'," - current task"," - completed work"," - current/last file"," - TODOs"," - blockers"," - next action","",'3. Use mode="ai" only when the continuity question is ambiguous or requires synthesis.',"","4. NEVER reconstruct previous work by reading or searching raw agent/session history, including:"," - .toolnet/sessions/**"," - state.json"," - events.jsonl"," - raw transcripts"," - ~/.gemini/antigravity-cli/brain/**"," - another coding agent's internal session history","","5. Do not search the filesystem for the implementation or JSON schema of memory_agent_ask."," Invoke the MCP tool directly.","","6. After ToolNet resolves continuity, inspect the current repository only to verify current truth."," Current repository evidence overrides stale memory.","","7. Do not ask the user to repeat project context already available through ToolNet Memory.","","8. Do not call memory_agent_ask for unrelated coding questions when current context is sufficient.","","9. Large tool/file payloads may be stored outside prompt context."," If the compact graph references a needed asset, call context_offload_read.","","10. Never bulk-load offloaded assets. Read only the minimum asset required."].join("\\n");function Ya(r){let e=new Va({name:"toolnet-memory",version:"0.1.0"},{instructions:Ja});return e.tool("memory_search","Search relevant long-term memory for the current project.",Sr,async t=>b(await wr(r,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",Pr,async t=>b(await Ar(r,t))),e.tool("memory_forget","Delete a memory by id.",Er,async t=>b(await Rr(r,t))),e.tool("find_symbol","Find code symbols by exact name.",Ir,async t=>b(await Tr(r,t))),e.tool("find_callers","Find functions or methods calling a symbol.",_r,async t=>b(await Or(r,t))),e.tool("code_search","Search indexed code symbols and files.",Lr,async t=>b(await Dr(r,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",Fr,async t=>b(await $r(r,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",qr,async t=>b(await Vr(r,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",Jr,async t=>b(await Yr(r,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>b(await Qr(r))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",Zr,async t=>b(await en(r,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",rn,async t=>b(await nn(r,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",Gr,async t=>b(await zr(r,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>b(await Ur(r))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",Wr,async t=>b(await Br(r,t))),e.tool("impact_guard","Analyze blast radius before or after code changes. Maps changed files/lines to symbols, follows reverse dependencies, assigns risk and suggests verification targets.",an,async t=>b(await cn(r,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",ln,async t=>b(await un(r,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",dn,async t=>b(await mn(r,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",pn,async t=>b(await fn(r,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",hn,async t=>b(await kn(r,t))),e.tool("memory_agent_ask",["Ask ToolNet Memory Agent about previous project work.","CALL THIS TOOL before guessing when the user asks to continue/resume previous work,","mentions a previous agent/session, asks what was unfinished, what file was last touched,","which TODOs are complete, blockers, decisions, or what should happen next.","Use mode=local for direct state facts and mode=ai for composite or ambiguous continuity questions.","Do not use it for unrelated coding questions when current repository context is already sufficient.","Returns concise selected memory instead of raw transcripts or full memory dumps.","Short conversational follow-ups are supported using compact ToolNet Memory focus; raw transcripts are never replayed."].join(" "),Gn,async t=>b(await zn(r,t))),e.tool("context_offload_read",["Read one external ToolNet tool/file asset referenced by the compact context graph.","Use only when needed for the current task.","Never bulk-load all offloaded assets."].join(" "),Yn,async t=>b(await Qn(r,t))),e.tool("skill_memory_search",["Search successful ToolNet project work promoted into reusable Skill Memory SOPs.","Call this before repeating a task that may have been solved successfully before.","Returns compact procedure steps, files and verification evidence.","Raw transcripts are never returned."].join(" "),to,async t=>b(await ro(r,t))),e.tool("wiki_search",["Search the ToolNet project Wiki for durable project knowledge.","Use Wiki before rereading broad project history when a maintained knowledge page may exist.","Returns compact metadata; call wiki_read only for the page needed."].join(" "),yo,async t=>b(await ho(r,t))),e.tool("wiki_read",["Read one ToolNet Wiki page by slug or id.","Returns the maintained page plus compact backlinks.","Do not bulk-read unrelated Wiki pages."].join(" "),ko,async t=>b(await bo(r,t))),e.tool("toolnet_status",["Inspect ToolNet MCP runtime health.","Returns dependency readiness, degraded state, retry counts,","startup timing, hydration timing, storage source and project data counts."].join(" "),wo,async()=>b(Co(r))),e.tool("knowledge_governance_status",["Inspect ToolNet Knowledge Governance health.","Returns review counts, confidence, conflicts, stale knowledge, and optional compact pending reviews.","Use this before trusting or changing important durable project knowledge."].join(" "),vo,async t=>b(await So(r,t))),e}async function xo(r){let e=Ya(r),t=new Ha;await e.connect(t)}function Mo(){return new Date().toISOString()}function T(r){r.lastUpdatedAt=Mo()}function Ze(r=Date.now()){return{phase:"starting",dependencies:{memory:{state:"idle",attempts:0},graph:{state:"idle",attempts:0},semantic:{state:"idle",attempts:0}},metrics:{processStartedAtMs:r,hydrationRuns:0,retryCount:0},errors:[],dataSource:"none",lastUpdatedAt:Mo()}}function Po(r,e=Date.now()){r.metrics.mcpConnectedAtMs=e,r.metrics.startupMs=e-r.metrics.processStartedAtMs,r.phase="hydrating",T(r)}function Ao(r,e=Date.now()){r.phase="hydrating",r.metrics.hydrationStartedAtMs=e,r.metrics.hydrationRuns+=1,T(r)}function et(r,e){r.dependencies[e].state!=="ready"&&(r.dependencies[e].state="loading",r.dependencies[e].lastError=void 0,T(r))}function tt(r,e){r.dependencies[e].attempts+=1,T(r)}function rt(r){r.metrics.retryCount+=1,T(r)}function z(r,e,t=Date.now()){let n=r.dependencies[e];n.state="ready",n.lastError=void 0,n.readyAfterMs=t-r.metrics.processStartedAtMs,T(r)}function de(r,e,t){let n=r.dependencies[e];n.state="failed",n.lastError=t instanceof Error?t.message:String(t),T(r)}function Eo(r,e=Date.now()){r.metrics.hydrationFinishedAtMs=e,r.metrics.hydrationStartedAtMs!==void 0&&(r.metrics.hydrationMs=e-r.metrics.hydrationStartedAtMs),r.errors=Object.entries(r.dependencies).filter(([,n])=>n.state==="failed").map(([n,o])=>`${n}: ${o.lastError??"unknown error"}`);let t=Object.values(r.dependencies).every(n=>n.state==="ready");r.phase=t?"ready":"degraded",T(r)}function Ro(r,e){r.phase="failed",r.errors=[e instanceof Error?e.message:String(e)],T(r)}async function nt(r,e){let t=Math.max(1,Math.floor(e.attempts)),n;for(let o=1;o<=t;o+=1){e.onAttempt?.(o);try{return await r()}catch(s){if(n=s,o>=t)break;e.onRetry?.(o,s),e.delayMs>0&&await new Promise(i=>{setTimeout(i,e.delayMs)})}}throw n instanceof Error?n:new Error(String(n??"operation failed"))}function us(r,e){let t=Number(r);return!Number.isFinite(t)||t<1?e:Math.floor(t)}function Nc(r,e){let t=Number(r);return!Number.isFinite(t)||t<0?e:Math.floor(t)}function Lc(r){let e=r.runtime;return e?{memory:e.dependencies.memory.state==="ready"?"ready":"failed",graph:e.dependencies.graph.state==="ready"?"ready":"failed",semantic:e.dependencies.semantic.state==="ready"?"ready":"failed",errors:[...e.errors]}:{memory:"failed",graph:"failed",semantic:"failed",errors:["runtime unavailable"]}}async function ds(r){let e=r.runtime??Ze(Date.now());r.runtime=e,Ao(e);let t=us(process.env.TOOLNET_MCP_HYDRATION_RETRIES,3),n=Nc(process.env.TOOLNET_MCP_HYDRATION_RETRY_DELAY_MS,500);if(e.dependencies.memory.state!=="ready"||e.dependencies.graph.state!=="ready"){let o=await Mr(r.project,{timeoutMs:us(process.env.TOOLNET_SERVICE_REQUEST_TIMEOUT_MS,1e3)});o&&(e.dataSource="daemon",e.dependencies.memory.state!=="ready"&&(r.memory.importRecords(o.memory),z(e,"memory")),e.dependencies.graph.state!=="ready"&&(o.graph&&r.graph.import(o.graph.symbols,o.graph.edges),z(e,"graph")))}try{let[{loadConfig:o},s]=await Promise.all([Promise.resolve().then(()=>(Mt(),Sn)),Promise.resolve().then(()=>(Xo(),Qo))]),i=o(),a=s.createStorageProvider({provider:i.storage.provider,r2:i.storage.r2,s3:i.storage.s3,huggingface:i.storage.huggingface,localRoot:i.storage.localRoot}),c=s.withStorageRetry(a,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),u=new s.ProjectScopedStorageProvider(c,r.project.id,r.project.name,r.project.remote??r.project.name),l=new s.MemoryStore(u);r.storage=u,r.memoryStore=l;let m=e.dependencies.memory.state==="ready"?Promise.resolve():(async()=>{e.dataSource="embedded",et(e,"memory");try{let p=await nt(()=>l.load(r.project.id),{attempts:t,delayMs:n,onAttempt:()=>{tt(e,"memory")},onRetry:()=>{rt(e)}});r.memory.importRecords(p),z(e,"memory")}catch(p){de(e,"memory",p)}})(),f=e.dependencies.graph.state==="ready"?Promise.resolve():(async()=>{e.dataSource="embedded",et(e,"graph");try{let p=await nt(()=>new s.PersistentCodeGraphStore(u).load(r.project.id),{attempts:t,delayMs:n,onAttempt:()=>{tt(e,"graph")},onRetry:()=>{rt(e)}});p&&r.graph.import(p.symbols,p.edges),z(e,"graph")}catch(p){de(e,"graph",p)}})();if(await Promise.all([m,f]),e.dependencies.semantic.state!=="ready"){et(e,"semantic");try{let[{SemanticCodeEngine:p},{createEmbeddingProvider:h}]=await Promise.all([Promise.resolve().then(()=>(ss(),os)),Promise.resolve().then(()=>(ls(),cs))]),v=new p({projectId:r.project.id,rootPath:r.project.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:u,embeddings:h(),graph:r.graph});await nt(()=>v.initialize(),{attempts:t,delayMs:n,onAttempt:()=>{tt(e,"semantic")},onRetry:()=>{rt(e)}}),r.codeSemantic=v,z(e,"semantic")}catch(p){de(e,"semantic",p)}}}catch(o){for(let s of["memory","graph","semantic"])e.dependencies[s].state!=="ready"&&de(e,s,o)}return Eo(e),Lc(r)}import{closeSync as Dc,mkdirSync as Kc,openSync as Fc,readFileSync as $c,unlinkSync as ms,writeFileSync as Gc}from"node:fs";import{tmpdir as zc}from"node:os";import{join as ps}from"node:path";function Uc(r){try{return process.kill(r,0),!0}catch(e){return e?.code==="EPERM"}}var at=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=ps(zc(),"toolnet-memory-locks");Kc(t,{recursive:!0});let n=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=ps(t,`${n}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Fc(this.path,"wx");Gc(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),Dc(t),this.acquired=!0,process.once("exit",this.exitHandler);return}catch(t){if(t?.code!=="EEXIST")throw t;let n=!0;try{let o=JSON.parse($c(this.path,"utf8"));Number.isInteger(o.pid)&&Uc(o.pid)&&(n=!1)}catch{n=!0}if(!n)throw new Error("ToolNet Memory is already running for this project");try{ms(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{ms(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};function fs(){let r=Number(process.env.TOOLNET_MCP_DEGRADED_RETRY_MS??3e4);return Number.isFinite(r)&&r>=1e3?Math.floor(r):3e4}async function Wc(){let r=Date.now(),e=new Me().detect(),t=new at(e.id);await t.acquire();let n=()=>{t.release().finally(()=>process.exit(0))};process.once("SIGINT",n),process.once("SIGTERM",n);let o=new Ce,s=new Te(o),i=new je,a=new _e(i),c=Ze(r),u={project:e,memory:o,retrieval:s,graph:i,references:a,runtime:c};await xo(u),Po(c);let l=async()=>{try{await ds(u),c.phase==="degraded"&&setTimeout(()=>{l()},fs()).unref()}catch(m){Ro(c,m),setTimeout(()=>{c.phase="degraded",l()},fs()).unref()}};l()}Wc().catch(r=>{console.error(r),process.exit(1)});