toolnet-memory 0.2.14 → 0.2.16

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,7 @@
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
+ import"dotenv/config";import{existsSync as br,readFileSync as Sr}from"node:fs";import{homedir as Er}from"node:os";import{join as Cr}from"node:path";function xr(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 vr(){let r=process.env.TOOLNET_GLOBAL_ENV??Cr(Er(),".config","toolnet-memory",".env");if(!br(r))return;let e=Sr(r,"utf8");for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let s=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=xr(o.slice(n+1)))}}vr();function D(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function F(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function qe(){return{memory:{autoCapture:D(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:D(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:D(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:D(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:F(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:F(process.env.MEMORY_RERANK_TOP,10),finalContext:F(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:F(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:D(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:F(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var wr={critical:100,high:75,normal:50,temporary:20};function He(r){return wr[r]}function Ve(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"}import{createHash as Pr}from"node:crypto";import{existsSync as Me,mkdirSync as Ar,readFileSync as Rr,renameSync as Lr,writeFileSync as jr}from"node:fs";import{basename as Mr,dirname as Y,join as Q,parse as Je,resolve as K}from"node:path";var Qe=".toolnet",Tr="project.json";function Ir(r){return Pr("sha256").update(r).digest("hex").slice(0,16)}function Te(r){return Q(r,Qe,Tr)}function _r(r){return Me(Te(r))}function kr(r,e){let t=K(r),o=Je(t).root;for(;;){if(_r(t))return t;if(t===o||e&&t===K(e))break;let n=Y(t);if(n===t)break;t=n}return null}function Nr(r){let e=K(r),t=Je(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(s=>Me(Q(e,s))))return e;if(e===t)break;let n=Y(e);if(n===e)break;e=n}return K(r)}function Or(r){let e;try{e=JSON.parse(Rr(r,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${r}: ${n instanceof Error?n.message:String(n)}`)}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 o=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:Y(Y(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:o,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:o,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 We(r,e){let t=Q(r,Qe);Ar(t,{recursive:!0});let o=Te(r),n=`${o}.tmp-${process.pid}`;jr(n,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Lr(n,o)}function Ye(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 J=class{detect(e=process.cwd()){let t=K(e),o=Nr(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>Me(Q(o,d))),i=kr(t,s?o:void 0);if(i){let d=Te(i),f=Or(d);return f.rootPath!==i&&(f.rootPath=i,f.updatedAt=new Date().toISOString(),We(i,f)),Ye(f,i)}let a=new Date().toISOString(),c=Mr(o),l={version:1,id:Ir(o),name:c,remote:c,rootPath:o,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return We(o,l),Ye(l,o)}};import{randomUUID as zr}from"node:crypto";var Dr=[{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}],Z=class{scan(e){let t=[];for(let o of Dr){let n=new RegExp(o.regex.source,o.regex.flags);for(let s of e.matchAll(n))t.push({type:o.type,value:s[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var k=class{scanner=new Z;sanitize(e){let t=e,o=this.scanner.scan(e),n=new Set;for(let s of o)n.add(s.type),t=t.split(s.value).join(`[REDACTED:${s.type}]`);return{text:t,redacted:o.length,secretTypes:[...n]}}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[o,n]of Object.entries(e)){let s=o.toLowerCase();s.includes("password")||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")?t[o]="[REDACTED]":t[o]=this.sanitizeValue(n)}return t}return e}};var Fr=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Kr=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 Ze(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Kr.has(e)))}function Gr(r,e){let t=Ze(r),o=Ze(e);if(t.size===0||o.size===0)return 0;let n=0;for(let i of t)o.has(i)&&n++;let s=new Set([...t,...o]).size;return n/s}function Xe(r){return new Set(r.tags.filter(e=>!Fr.has(e.toLowerCase())))}var X=class{findSuperseded(e,t){if(e.type!=="rule"&&e.type!=="decision")return[];let o=typeof e.metadata?.topic=="string"?e.metadata.topic:void 0,n=Xe(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(o&&i&&o===i)return!0;let a=Xe(s);for(let c of n)if(a.has(c))return!0;return Gr(e.content,s.content)>=.6})}};var $r={critical:100,high:75,normal:50,temporary:20},Ur={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function et(r,e,t=new Date){let o;if(e==="temporary"&&(o=30),r==="activity"&&(o=Math.min(o??14,14)),r==="summary"&&(o=Math.min(o??30,30)),!!o)return new Date(t.getTime()+o*864e5).toISOString()}function Ie(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function Br(r){return!!r.metadata?.supersededBy}function _e(r,e=Date.now()){return!Ie(r,e)&&!Br(r)}function G(r,e=Date.now()){if(!_e(r,e))return 0;let t=$r[r.importance];if(r.importance==="critical")return t;let o=Ur[r.type]??180,s=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,i=Math.pow(.5,s/o);return t*i}var ee=class{memories=new Map;sanitizer=new k;conflicts=new X;remember(e){let t=new Date().toISOString(),o=this.sanitizer.sanitize(e.content.trim()).text,n=e.importance??Ve(e.type,o),s={id:zr(),projectId:e.projectId,type:e.type,content:o,importance:n,importanceScore:He(n),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??et(e.type,n,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 o of e)o?.id&&(this.memories.set(o.id,o),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,o)=>o.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>_e(t))}recent(e,t=10){return this.list(e).slice(0,t)}byType(e,t){return this.list(e).filter(o=>o.type===t)}search(e){let t=e.query.trim().toLowerCase(),o=e.limit??10,n=t.split(/\s+/).filter(Boolean);return this.list(e.projectId).filter(s=>{if(e.types&&!e.types.includes(s.type))return!1;let i=G(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=n.filter(d=>i.includes(d)).length,c=n.length===0?0:a/n.length,l=G(s)/500;return{memory:s,score:c+l,source:"memory"}}).filter(s=>t.length===0||s.score>0).sort((s,i)=>i.score-s.score).slice(0,o)}pruneExpired(e,t=Date.now()){let o=0;for(let[n,s]of this.memories)s.projectId===e&&Ie(s,t)&&(this.memories.delete(n),o++);return o}pruneSuperseded(e,t=30,o=Date.now()){let n=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;o-new Date(c).getTime()>=s&&(this.memories.delete(i),n++)}return n}clearProject(e){let t=0;for(let[o,n]of this.memories)n.projectId===e&&(this.memories.delete(o),t++);return t}};function N(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var te=class{score(e,t){let o=N(e),n=N([t.content,...t.tags??[],t.type].join(" "));if(o.length===0||n.length===0)return 0;let s=new Map;for(let a of n)s.set(a,(s.get(a)??0)+1);let i=0;for(let a of o){let c=s.get(a)??0;c!==0&&(i+=1+Math.log(1+c))}return i/o.length}};function tt(r,e=Date.now()){let t=r.updatedAt??r.createdAt,o=new Date(t).getTime();if(!Number.isFinite(o))return 0;let n=Math.max(0,e-o)/864e5;return Math.exp(-Math.LN2*n/30)}function rt(r){return G(r)/100}var qr={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function ot(r){return qr[r]??.4}var re=class{analyze(e){let t=e.toLowerCase(),o=[];return(t.includes("quy\u1EBFt \u0111\u1ECBnh")||t.includes("decision")||t.includes("\u0111\xE3 ch\u1ECDn"))&&o.push("decision"),(t.includes("todo")||t.includes("c\u1EA7n l\xE0m")||t.includes("ti\u1EBFp theo")||t.includes("ch\u01B0a xong"))&&o.push("todo"),(t.includes("quy t\u1EAFc")||t.includes("rule")||t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c"))&&o.push("rule"),(t.includes("t\xF3m t\u1EAFt")||t.includes("summary")||t.includes("\u0111\xE3 l\xE0m"))&&o.push("summary"),{query:e,preferredTypes:o}}};var oe=class{bm25=new te;analyzer=new re;search(e,t,o={}){let n=o.topK??8,s=o.minScore??.05,i=this.analyzer.analyze(e),a=[];for(let c of t){if(o.types?.length&&!o.types.includes(c.type))continue;let l=this.bm25.score(e,c),d=tt(c),f=rt(c),m=ot(c.type);i.preferredTypes.includes(c.type)&&(m=Math.min(1,m+.25));let u=l*.55+f*.2+d*.15+m*.1;l<=0||u<s||a.push({memory:c,score:u,scores:{keyword:l,recency:d,importance:f,type:m}})}return a.sort((c,l)=>l.score-c.score).slice(0,n)}};var ne=class{build(e,t=6e3){let o=[],n=0;for(let s of e){let i=s.memory,a=[`[${i.type.toUpperCase()}]`,i.content].join(" ");if(n+a.length>t)break;o.push(a),n+=a.length}return o.join(`
4
+ `)}};var se=class{constructor(e){this.memory=e}memory;searcher=new oe;contextBuilder=new ne;search(e,t,o={}){return this.searcher.search(t,this.memory.list(e),o)}context(e,t,o={}){let n=this.search(e,t,o);return this.contextBuilder.build(n)}};var nt=[{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 ie(r){let e=nt.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function ae(r){return nt.some(e=>e.id===r)}function p(r){return process.env[r]?.trim()||void 0}function h(...r){return r.find(e=>!!e?.trim())}function st(){if(p("GROQ_API_KEY"))return"groq";if(p("DEEPSEEK_API_KEY"))return"deepseek";if(p("NVIDIA_API_KEY")||p("NVIDIA_NIM_API_KEY"))return"nvidia";if(p("OPENROUTER_API_KEY"))return"openrouter";if(p("ALIBABA_API_KEY")||p("DASHSCOPE_API_KEY"))return"alibaba";if(p("GEMINI_API_KEY")||p("GOOGLE_API_KEY"))return"gemini";if(p("CLOUDFLARE_API_TOKEN")&&p("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(p("HF_TOKEN"))return"huggingface";if(p("OLLAMA_MODEL")||p("OLLAMA_BASE_URL"))return"ollama"}function Hr(){let r=p("TOOLNET_LLM_PROVIDER");return r&&ae(r)?r:st()??"openai-compatible"}function ke(r){let e=ie(r);switch(r){case"alibaba":return{provider:r,apiKey:h(p("ALIBABA_API_KEY"),p("DASHSCOPE_API_KEY")),baseUrl:h(p("ALIBABA_BASE_URL"),p("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:h(p("ALIBABA_MODEL"),p("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:p("OPENROUTER_API_KEY"),baseUrl:h(p("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:p("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:p("GROQ_API_KEY"),baseUrl:h(p("GROQ_BASE_URL"),e.defaultBaseUrl),model:p("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:p("DEEPSEEK_API_KEY"),baseUrl:h(p("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:h(p("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:h(p("NVIDIA_API_KEY"),p("NVIDIA_NIM_API_KEY")),baseUrl:h(p("NVIDIA_BASE_URL"),p("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:h(p("NVIDIA_MODEL"),p("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:h(p("GEMINI_API_KEY"),p("GOOGLE_API_KEY")),baseUrl:h(p("GEMINI_BASE_URL"),e.defaultBaseUrl),model:p("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:p("HF_TOKEN"),baseUrl:h(p("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:h(p("HF_LLM_MODEL"),p("HF_MODEL"))};case"ollama":return{provider:r,apiKey:p("OLLAMA_API_KEY"),baseUrl:h(p("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:p("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:p("CLOUDFLARE_ACCOUNT_ID"),apiKey:p("CLOUDFLARE_API_TOKEN"),baseUrl:p("CLOUDFLARE_AI_BASE_URL"),model:p("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:p("CUSTOM_AI_API_KEY"),baseUrl:p("CUSTOM_AI_BASE_URL"),model:p("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:h(p("OPENAI_API_KEY"),p("MODEL_API_KEY")),baseUrl:h(p("OPENAI_BASE_URL"),p("MODEL_BASE_URL")),model:h(p("OPENAI_MODEL"),p("MODEL_NAME"))}}}function Vr(){let r=p("TOOLNET_LLM_PROVIDER"),e=r&&ae(r)?r:Hr(),t=ie(e),o=ke(e);return{provider:e,apiKey:h(p("TOOLNET_LLM_API_KEY"),o.apiKey),baseUrl:h(p("TOOLNET_LLM_BASE_URL"),o.baseUrl,t.defaultBaseUrl),model:h(p("TOOLNET_LLM_MODEL"),o.model,t.defaultModel),accountId:h(p("TOOLNET_LLM_ACCOUNT_ID"),o.accountId)}}function Wr(){let r=p("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&ae(r)?r:p("HF_TOKEN")||p("HF_EMBEDDING_MODEL")?"huggingface":"local"}function Yr(){let r=Wr();if(r==="local")return{provider:"local",model:h(p("TOOLNET_EMBEDDING_MODEL"),p("LOCAL_EMBEDDING_MODEL"))};let e=ie(r),t,o,n,s;switch(r){case"huggingface":t=p("HF_TOKEN"),o=p("HF_INFERENCE_BASE_URL"),n=p("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=p("OPENAI_API_KEY"),o=p("OPENAI_BASE_URL"),n=p("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=p("CLOUDFLARE_API_TOKEN"),o=p("CLOUDFLARE_AI_BASE_URL"),n=p("CLOUDFLARE_EMBEDDING_MODEL"),s=p("CLOUDFLARE_ACCOUNT_ID");break;default:t=ke(r).apiKey,o=ke(r).baseUrl,n=p(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let i=h(p("TOOLNET_EMBEDDING_ACCOUNT_ID"),s),a=h(p("TOOLNET_EMBEDDING_BASE_URL"),o,e.defaultBaseUrl),c=r==="cloudflare"&&!a&&i?`https://api.cloudflare.com/client/v4/accounts/${i}/ai/v1`:a;return{provider:r,apiKey:h(p("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:c,model:h(p("TOOLNET_EMBEDDING_MODEL"),n),accountId:i}}function it(){let r=Vr(),e=Yr();return{llm:r,embedding:e,legacy:{llm:!p("TOOLNET_LLM_PROVIDER")&&!!st(),embedding:!p("TOOLNET_EMBEDDING_PROVIDER")&&!!(p("HF_TOKEN")||p("HF_EMBEDDING_MODEL"))}}}var ce=class{constructor(e){this.options=e}options;name="gemini";async embed(e){let t=this.options.model.replace(/^models\//,""),n=`${this.options.baseUrl?.replace(/\/+$/,"")||"https://generativelanguage.googleapis.com/v1beta"}/models/${encodeURIComponent(t)}:embedContent?key=${encodeURIComponent(this.options.apiKey)}`,s=await fetch(n,{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 o of e)t.push(await this.embed(o));return t}};import{createHash as Jr}from"node:crypto";var le=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),o=e.toLowerCase().split(/\s+/).filter(Boolean);for(let n of o){let i=Jr("sha256").update(n).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return Qr(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function Qr(r){let e=Math.sqrt(r.reduce((t,o)=>t+o*o,0));return e===0?r:r.map(t=>t/e)}var de=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(/\/+$/,""),o=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(!o.ok)throw new Error(`Embedding failed: ${o.status} ${await o.text()}`);let s=(await o.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}};var pe=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`,o=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(!o.ok)throw new Error(`HF embedding failed: ${o.status} ${await o.text()}`);let n=await o.json();if(!Array.isArray(n))throw new Error("HF embedding returned invalid response");return n.map(s=>Zr(s))}};function Zr(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,o=new Array(t).fill(0);for(let n of e)for(let s=0;s<t;s++)o[s]+=n[s]??0;for(let n=0;n<t;n++)o[n]/=e.length;return o}throw new Error("Unsupported embedding shape")}var Ne=class{constructor(e,t=new le){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 Xr(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function eo(){let r=it().embedding;if(r.provider==="local")return null;if(r.provider==="huggingface")return!r.apiKey||!r.model?null:new pe({token:r.apiKey,model:r.model});if(r.provider==="gemini")return!r.apiKey||!r.model?null:new ce({apiKey:r.apiKey,model:r.model,baseUrl:r.baseUrl});let e=r.baseUrl;return r.provider==="cloudflare"&&!e&&r.accountId&&(e=Xr(r.accountId)),e&&r.model?new de({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function at(){return new Ne(eo())}import*as C from"typescript";var O=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(o=>o.projectId===e&&(o.name===t||o.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 o of e)this.addSymbol(o);for(let o of t)this.addEdge(o)}clearProject(e){for(let[t,o]of this.symbols)o.projectId===e&&this.symbols.delete(t);for(let[t,o]of this.edges)o.projectId===e&&this.edges.delete(t)}};function me(r,e){let t=r.allSymbols(e),o=r.allEdges(e),n=i=>t.filter(a=>a.type===i).length,s=i=>o.filter(a=>a.type===i).length;return{files:n("file"),classes:n("class"),interfaces:n("interface"),functions:n("function"),methods:n("method"),properties:n("property"),routes:n("route"),symbols:t.length,edges:o.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 fe=class{constructor(e){this.graph=e}graph;callees(e,t,o=3){return this.walk(e,t,"out",o)}callers(e,t,o=3){return this.walk(e,t,"in",o)}walk(e,t,o,n){let s=[],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>=n)continue;let d=o==="out"?c.filter(f=>f.from===l.id):c.filter(f=>f.to===l.id);for(let f of d){let m=o==="out"?f.to:f.from;if(i.has(m))continue;i.add(m);let u=this.graph.getSymbol(m);if(!u)continue;let b=l.depth+1;s.push({symbol:u,depth:b}),a.push({id:m,depth:b})}}return s}};var ue=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(n=>n.type==="CALLS"&&n.to===t).map(n=>n.from).map(n=>this.graph.getSymbol(n)).filter(n=>!!n)}};var ge=class{constructor(e){this.graph=e}graph;analyze(e,t,o=4){let n=this.graph.allEdges(e),s=new Set([t]),i=[{id:t,depth:0}],a=[];for(;i.length;){let c=i.shift();if(c.depth>=o)continue;let l=n.filter(d=>d.to===c.id&&["CALLS","IMPORTS","INHERITS","IMPLEMENTS"].includes(d.type));for(let d of l){if(s.has(d.from))continue;s.add(d.from);let f=this.graph.getSymbol(d.from);if(!f)continue;let m=c.depth+1;a.push({symbol:f,depth:m,relation:d.type}),i.push({id:d.from,depth:m})}}return a}};function no(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 he=class{constructor(e){this.graph=e}graph;map(e,t){let o=this.graph.allSymbols(e),n=[];for(let s of t){let i=o.filter(l=>l.filePath===s.filePath),c=i.filter(l=>l.type!=="file").filter(l=>no(l,s));if(c.length===0){let l=i.find(d=>d.type==="file");l&&n.push({symbol:l,fileStatus:s.status,direct:!0});continue}for(let l of c)n.push({symbol:l,fileStatus:s.status,direct:!0})}return n}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var so={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function io(r){return r>=30?"CRITICAL":r>=16?"HIGH":r>=6?"MEDIUM":"LOW"}function ct(r){let e=r.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var ye=class{constructor(e){this.graph=e}graph;analyze(e,t,o=4){let n=this.graph.allEdges(e),s=new Map,i=0;for(let d of t){d.fileStatus==="deleted"?i+=8:d.fileStatus==="renamed"?i+=5:i+=2,d.symbol.type==="interface"&&(i+=5),d.symbol.type==="class"&&(i+=3);let f=new Set([d.symbol.id]),m=[{id:d.symbol.id,depth:0}];for(;m.length;){let u=m.shift();if(u.depth>=o)continue;let b=n.filter(S=>S.to===u.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(S.type));for(let S of b){if(f.has(S.from))continue;f.add(S.from);let A=this.graph.getSymbol(S.from);if(!A)continue;let R=u.depth+1,W=`${d.symbol.id}:${A.id}`;s.set(W,{symbol:A,relation:S.type,depth:R,sourceSymbolId:d.symbol.id});let T=so[S.type]??1;i+=Math.max(1,T-(R-1)),m.push({id:A.id,depth:R})}}}let a=[...s.values()].sort((d,f)=>d.depth-f.depth),c=[...new Set(a.map(d=>d.symbol.filePath))],l=c.filter(ct);return l.length===0&&l.push(...c.filter(d=>!ct(d)).slice(0,10)),{risk:io(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:l}}};import{execFile as ao}from"node:child_process";import{promisify as co}from"node:util";var Oe=co(ao);function lo(r){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let o of r.matchAll(t)){let n=Number(o[1]),s=Number(o[2]??1);e.push({startLine:n,endLine:Math.max(n,n+s-1)})}return e}function po(r){return r.startsWith("A")?"added":r.startsWith("D")?"deleted":r.startsWith("R")?"renamed":"modified"}async function lt(r){let e="";try{e=(await Oe("git",["diff","HEAD","--name-status","--no-renames"],{cwd:r,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let o of e.split(/\r?\n/).filter(Boolean)){let[n,...s]=o.split(" "),i=s.at(-1);if(!i)continue;let a="";try{a=(await Oe("git",["diff","HEAD","--unified=0","--",i],{cwd:r,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:po(n),ranges:lo(a)})}try{let o=await Oe("git",["ls-files","--others","--exclude-standard"],{cwd:r});for(let n of o.stdout.split(/\r?\n/).filter(Boolean))t.some(s=>s.filePath===n)||t.push({filePath:n,status:"added",ranges:[]})}catch{}return t}var be=class{constructor(e){this.graph=e;this.mapper=new he(e),this.blast=new ye(e)}graph;mapper;blast;async analyzeGitDiff(e,t,o={}){let n=await lt(t),s=this.mapper.map(e,n),i=this.blast.analyze(e,s,o.maxDepth??4);return{mode:"git_diff",changes:n,...i}}analyzeFile(e,t,o={}){let n=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,n,o.maxDepth??4)}}};var $=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 mo}from"node:crypto";import{readFile as fo}from"node:fs/promises";import{join as uo}from"node:path";function dt(r){return mo("sha256").update(r).digest("hex")}var Se=class{sanitizer=new k;async build(e,t,o,n={}){let s=n.maxLines??80,i=n.overlapLines??10,a=new Map;for(let l of o){let d=a.get(l.filePath)??[];d.push(l),a.set(l.filePath,d)}let c=[];for(let[l,d]of a){let f;try{f=await fo(uo(t,l),"utf8")}catch{continue}let m=f.split(/\r?\n/),u=d.filter(b=>b.type!=="file"&&typeof b.startLine=="number"&&typeof b.endLine=="number");if(u.length>0)for(let b of u)c.push(...this.chunkRange({projectId:e,filePath:l,lines:m,symbol:b,startLine:b.startLine,endLine:b.endLine,maxLines:s,overlapLines:i}));else c.push(...this.chunkRange({projectId:e,filePath:l,lines:m,startLine:1,endLine:Math.max(1,m.length),maxLines:s,overlapLines:i}))}return c}chunkRange(e){let{projectId:t,filePath:o,lines:n,symbol:s,maxLines:i}=e,a=Math.min(e.overlapLines,Math.max(0,i-1)),c=Math.max(1,e.startLine),l=Math.min(n.length,Math.max(c,e.endLine)),d=[],f=c,m=0;for(;f<=l;){let u=Math.min(l,f+i-1),b=n.slice(f-1,u).join(`
5
+ `).trim();if(b){let S=this.sanitizer.sanitize(b).text,A=dt(S),R=[t,o,s?.id??"file",String(m),A].join(":");d.push({id:dt(R).slice(0,32),projectId:t,filePath:o,symbolId:s?.id,symbolName:s?.qualifiedName??s?.name,symbolType:s?.type,startLine:f,endLine:u,content:S,contentHash:A})}if(u>=l)break;f=u-a+1,m++}return d}};var Ee=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 Ce=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 xe=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[o,n]of this.records)n.projectId===e&&(this.records.delete(o),t++);return t}exportProject(e){return[...this.records.values()].filter(t=>t.projectId===e)}importRecords(e){let t=0;for(let o of e)!o?.id||!o?.projectId||!Array.isArray(o.vector)||(this.records.set(o.id,o),t++);return t}search(e,t,o=10){let n=[];for(let s of this.records.values()){if(s.projectId!==e)continue;let i=go(t,s.vector);n.push({id:s.id,score:i,metadata:s.metadata})}return n.sort((s,i)=>i.score-s.score).slice(0,o)}size(){return this.records.size}};function go(r,e){if(r.length===0||e.length===0||r.length!==e.length)return 0;let t=0,o=0,n=0;for(let s=0;s<r.length;s++){let i=r[s]??0,a=e[s]??0;t+=i*a,o+=i*i,n+=a*a}return o===0||n===0?0:t/(Math.sqrt(o)*Math.sqrt(n))}function pt(r,e){let t=r.toLowerCase().replaceAll("\\","/"),o=e.toLowerCase(),n=/\b(test|tests|spec|fixture|mock)\b/.test(o);return(t.startsWith("tests/")||t.includes("/tests/")||t.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(t))&&!n?.35:t.includes("/generated/")||t.includes(".generated.")?.25:1}var ve=class{constructor(e){this.options=e}options;vectors=new xe;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:o,embeddings:n,graph:s,model:i}=this.options,a=new Ee(o),c=new Ce(o),l=await new Se().build(e,t,s.allSymbols(e));this.chunks.clear();for(let E of l)this.chunks.set(E.id,E);let d=await a.load(e),f=!d||d.chunks.length!==l.length||d.chunks.some(E=>!this.chunks.has(E.id));f&&await a.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:l});let m=await c.load(e),u=0;m&&m.model===i&&(u=this.vectors.importRecords(m.records));let b=new Set(l.map(E=>E.id)),S=0;for(let E of this.vectors.exportProject(e))b.has(E.id)||this.vectors.remove(E.id)&&S++;let A=l.filter(E=>{let I=this.vectors.get(E.id);return I?I.metadata?.contentHash!==E.contentHash:!0}),R=0,W=8,T=this.vectors.exportProject(e)[0]?.vector.length;for(let E=0;E<A.length;E+=W){let I=A.slice(E,E+W),hr=I.map(P=>[`file: ${P.filePath}`,P.symbolName?`symbol: ${P.symbolName}`:"",P.symbolType?`type: ${P.symbolType}`:"",P.content].filter(Boolean).join(`
6
+ `)),yr=await n.embedMany(hr);for(let P=0;P<I.length;P++){let j=I[P],_=yr[P];if(!(!j||!_||_.length===0)){if(T===void 0&&(T=_.length),_.length!==T){console.warn(`[code-semantic] skip dimension mismatch: ${_.length} != ${T}`);continue}this.vectors.upsert({id:j.id,projectId:e,vector:_,metadata:{contentHash:j.contentHash,filePath:j.filePath,symbolName:j.symbolName,symbolType:j.symbolType,startLine:j.startLine,endLine:j.endLine}}),R++}}}let je=this.vectors.exportProject(e),ze=R>0||S>0||!m||m.model!==i;return ze&&await c.save({version:1,projectId:e,model:i,dimensions:je[0]?.vector.length??T??0,updatedAt:new Date().toISOString(),records:je}),{chunks:l.length,vectorsLoaded:u,vectorsIndexed:R,vectorsRemoved:S,totalVectors:je.length,savedChunks:f,savedVectors:ze}}async search(e,t=8){let o=await this.options.embeddings.embed(e),n=this.vectors.search(this.options.projectId,o,Math.max(t*4,20)),s=new Set(N(e)),i=[];for(let a of n){let c=this.chunks.get(a.id);if(!c)continue;let l=new Set(N([c.filePath,c.symbolName??"",c.symbolType??"",c.content].join(" "))),d=0;for(let S of s)l.has(S)&&d++;let f=s.size===0?0:d/s.size,m=Math.max(0,a.score),u=pt(c.filePath,e),b=(m*.75+f*.25)*u;i.push({chunk:c,score:b,vectorScore:m,lexicalScore:f})}return i.sort((a,c)=>c.score-a.score).slice(0,t)}size(){return this.chunks.size}};import*as x from"typescript";import*as g from"typescript";var Yi=new Set([g.SyntaxKind.EqualsToken,g.SyntaxKind.PlusEqualsToken,g.SyntaxKind.MinusEqualsToken,g.SyntaxKind.AsteriskEqualsToken,g.SyntaxKind.SlashEqualsToken,g.SyntaxKind.PercentEqualsToken,g.SyntaxKind.QuestionQuestionEqualsToken,g.SyntaxKind.AmpersandAmpersandEqualsToken,g.SyntaxKind.BarBarEqualsToken]);function ho(r){return r.replaceAll("\\","/").toLowerCase()}var U=class{constructor(e){this.graph=e}graph;detect(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e),n=[];for(let i of t){if(i.type!=="route"&&i.type!=="file")continue;let a=this.classify(i,o);a&&n.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 n){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 o=ho(e.filePath),n=[];if(e.type==="route")return{kind:"route",score:100,reasons:["HTTP route"]};let s=null,i=0;if(o.startsWith("bin/"))s="cli",i=100,n.push("bin executable");else if(/(^|\/)(cli)\.[^.]+$/.test(o))s="cli",i=90,n.push("CLI entry file");else if(/(^|\/)(main|server)\.[^.]+$/.test(o))s="main",i=90,n.push("main/server file");else if(o.includes("/runtime/")&&/(^|\/)(bootstrap|index)\.[^.]+$/.test(o))s="runtime",i=75,n.push("runtime bootstrap");else if(/(^|\/)index\.[^.]+$/.test(o)){let c=t.filter(d=>d.to===e.id&&d.type!=="DEFINES").length,l=t.filter(d=>d.from===e.id&&d.type!=="DEFINES").length;(o.startsWith("packages/")||c===0||l>0)&&(s="package",i=o.startsWith("packages/")?70:55,n.push("package/public index"))}return s?(t.filter(c=>c.to===e.id&&c.type!=="DEFINES").length===0&&(i+=10,n.push("no incoming dependency")),{kind:s,score:i,reasons:n}):null}};var we=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),mt=new Set(["CALLS","CALL_REFERENCE"]),w=class{constructor(e){this.graph=e}graph;findSymbols(e,t){let o=t.trim().toLowerCase();return o?this.graph.allSymbols(e).filter(n=>n.name.toLowerCase().includes(o)||(n.qualifiedName?.toLowerCase().includes(o)??!1)||n.filePath.toLowerCase().includes(o)).sort((n,s)=>{let i=n.name.toLowerCase()===o,a=s.name.toLowerCase()===o;return i!==a?i?-1:1:n.filePath.localeCompare(s.filePath)}):[]}callers(e,t){return this.relatedIncoming(e,t,mt)}callees(e,t){return this.relatedOutgoing(e,t,mt)}dependents(e,t){return this.relatedIncoming(e,t,we)}dependencies(e,t){return this.relatedOutgoing(e,t,we)}neighborhood(e,t,o=1){let n=this.graph.getSymbol(t);return!n||n.projectId!==e?null:{center:n,incoming:this.walk(e,t,"incoming",o),outgoing:this.walk(e,t,"outgoing",o)}}shortestPath(e,t,o,n=12){let s=this.graph.getSymbol(t),i=this.graph.getSymbol(o);if(!s||!i||s.projectId!==e||i.projectId!==e)return{found:!1,distance:-1,symbols:[],edges:[]};if(t===o)return{found:!0,distance:0,symbols:[s],edges:[]};let a=this.graph.allEdges(e).filter(m=>we.has(m.type)),c=new Map;for(let m of a){let u=c.get(m.from)??[];u.push(m),c.set(m.from,u)}let l=[{id:t,depth:0}],d=new Set([t]),f=new Map;for(;l.length>0;){let m=l.shift();if(!(m.depth>=n)){for(let u of c.get(m.id)??[])if(!d.has(u.to)){if(d.add(u.to),f.set(u.to,{node:m.id,edge:u}),u.to===o)return this.buildPath(t,o,f);l.push({id:u.to,depth:m.depth+1})}}}return{found:!1,distance:-1,symbols:[],edges:[]}}buildPath(e,t,o){let n=[t],s=[],i=t;for(;i!==e;){let c=o.get(i);if(!c)return{found:!1,distance:-1,symbols:[],edges:[]};s.push(c.edge),i=c.node,n.push(i)}n.reverse(),s.reverse();let a=n.map(c=>this.graph.getSymbol(c)).filter(c=>!!c);return{found:!0,distance:s.length,symbols:a,edges:s}}walk(e,t,o,n){let s=this.graph.allEdges(e).filter(l=>we.has(l.type)),i=[{id:t,depth:0}],a=new Set([t]),c=[];for(;i.length>0;){let l=i.shift();if(!(l.depth>=n))for(let d of s){if(!(o==="incoming"?d.to===l.id:d.from===l.id))continue;let m=o==="incoming"?d.from:d.to;if(a.has(m))continue;let u=this.graph.getSymbol(m);u&&(a.add(m),c.push({symbol:u,depth:l.depth+1,via:d}),i.push({id:m,depth:l.depth+1}))}}return c}relatedIncoming(e,t,o){return[...new Set(this.graph.allEdges(e).filter(s=>s.to===t&&o.has(s.type)).map(s=>s.from))].map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}relatedOutgoing(e,t,o){return[...new Set(this.graph.allEdges(e).filter(s=>s.from===t&&o.has(s.type)).map(s=>s.to))].map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}};var ft=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function De(r){return r.replaceAll("\\","/").toLowerCase()}function yo(r){let e=De(r);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function bo(r){let e=De(r.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var B=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e),n=new Set(new U(this.graph).detect(e).map(i=>i.symbolId)),s=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||yo(i.filePath)||n.has(i.id)||bo(i)||o.filter(u=>u.to===i.id&&ft.has(u.type)).length>0)continue;let c=o.filter(u=>u.from===i.id&&ft.has(u.type)),l=["no incoming usage edge"],d=50;(i.type==="function"||i.type==="method")&&(d+=20,l.push("callable symbol")),i.type==="property"&&(d-=15),c.length===0&&(d+=10,l.push("no outgoing dependency")),De(i.filePath).includes("/internal/")&&(d+=10,l.push("internal implementation")),i.name.startsWith("_")&&(d+=5);let m=d>=75?"high":d>=55?"medium":"low";s.push({symbolId:i.id,name:i.name,qualifiedName:i.qualifiedName,type:i.type,filePath:i.filePath,startLine:i.startLine,confidence:m,score:d,reasons:l})}return s.sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath)||i.name.localeCompare(a.name))}};var So=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),z=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e).filter(i=>So.has(i.type)),n=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,d=0;for(let f of o){let m=n.get(f.from),u=n.get(f.to);!m||!u||m.filePath===u.filePath||(m.filePath===i&&(a.add(u.filePath),l++),u.filePath===i&&(c.add(m.filePath),d++))}return{filePath:i,dependencies:[...a].sort(),dependents:[...c].sort(),outgoingEdges:l,incomingEdges:d}})}};import{homedir as Uo}from"node:os";import{join as Bo}from"node:path";import{DeleteObjectCommand as Eo,GetObjectCommand as Co,HeadObjectCommand as xo,ListObjectsV2Command as vo,PutObjectCommand as wo,S3Client as Po}from"@aws-sdk/client-s3";import{getSignedUrl as Ao}from"@aws-sdk/s3-request-presigner";var Pe=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Po({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,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new wo({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await Ao(this.client,new Co({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.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 xo({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 Eo({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new vo({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};import{access as ut,mkdir as Ro,readFile as Lo,readdir as jo,rm as Mo,stat as gt,writeFile as To}from"node:fs/promises";import{dirname as Io,join as _o,relative as ht,resolve as ko}from"node:path";var q=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return ko(this.root,t)}async put(e,t){let o=this.path(e);await Ro(Io(o),{recursive:!0}),await To(o,t)}async get(e){try{return await Lo(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 ut(this.path(e)),!0}catch{return!1}}async delete(e){await Mo(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await ut(t)}catch{return o}let n=async i=>{let a=await jo(i,{withFileTypes:!0});for(let c of a){let l=_o(i,c.name);if(c.isDirectory()){await n(l);continue}let d=await gt(l);o.push({key:ht(this.root,l),size:d.size,updatedAt:d.mtime.toISOString()})}},s=await gt(t);return s.isDirectory()?await n(t):o.push({key:ht(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),o}};import{DeleteObjectCommand as No,GetObjectCommand as Oo,HeadObjectCommand as Do,ListObjectsV2Command as Fo,PutObjectCommand as Ko,S3Client as Go}from"@aws-sdk/client-s3";import{getSignedUrl as $o}from"@aws-sdk/s3-request-presigner";var H=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Go({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,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ko({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await $o(this.client,new Oo({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`${this.name} download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.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 Do({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 No({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new Fo({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};function Fe(r,e){return console.warn(e),new q(r)}function yt(r){let e=r.localRoot??Bo(Uo(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new H({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Fe(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 H({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Fe(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 Pe({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Fe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new q(e)}var Ae=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 o=JSON.parse(t);if(!Array.isArray(o))throw new Error("Invalid memory snapshot");return o}async save(e,t){let o=JSON.stringify(t,null,2);await this.storage.put(this.key(e),o,"application/json")}};function zo(r){return new Promise(e=>setTimeout(e,r))}async function bt(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=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(n,o*2**(i-1)),l=Math.floor(Math.random()*Math.max(1,c*.2));await zo(c+l)}throw s}var qo=new Set(["put","get","getText","delete","list"]);function St(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:qo.has(o)?(...s)=>bt(()=>Promise.resolve(n.apply(t,s)),e):n.bind(t)}})}function Et(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}function Ct(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 o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(o)return`${o[1]}memory/records/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),o)return`${o[1]}memory/vectors/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),o)return`${o[1]}code/graph/${o[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var Re=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=Et(n??o),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(),o=t,n=await this.provider.getText(e);if(n){let i;try{i=JSON.parse(n)}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"&&(o=i.createdAt)}let s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:t};await this.provider.put(e,JSON.stringify(s,null,2)+`
7
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Ct(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,o){return await this.ensureRegistered(),this.provider.put(this.key(e),t,o)}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 Xo}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as en}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as xt}from"zod";var vt={query:xt.string(),limit:xt.number().int().min(1).max(20).optional()};async function wt(r,e){return r.retrieval.search(r.project.id,e.query,{topK:e.limit??8}).map(o=>({id:o.memory.id,type:o.memory.type,content:o.memory.content,importance:o.memory.importance,score:o.score,tags:o.memory.tags}))}import{z as V}from"zod";var Pt={type:V.enum(["activity","decision","rule","todo","summary"]),content:V.string().min(1),tags:V.array(V.string()).optional(),importance:V.enum(["critical","high","normal","temporary"]).optional()};async function At(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)),t}import{z as Ho}from"zod";var Rt={id:Ho.string().min(1)};async function Lt(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)),{deleted:t}}import{z as Vo}from"zod";var jt={name:Vo.string().min(1)};async function Mt(r,e){return r.graph.findByName(r.project.id,e.name)}import{z as Wo}from"zod";function L(r,e){let t=r.graph.getSymbol(e);if(t&&t.projectId===r.project.id)return t;let o=new w(r.graph),n=o.findSymbols(r.project.id,e).find(s=>s.name===e||s.qualifiedName===e);return n||(o.findSymbols(r.project.id,e)[0]??null)}function v(r){return{id:r.id,name:r.name,qualifiedName:r.qualifiedName,type:r.type,filePath:r.filePath,startLine:r.startLine,endLine:r.endLine}}var Tt={symbolId:Wo.string().min(1)};async function It(r,e){let t=L(r,e.symbolId);if(!t)return{found:!1,query:e.symbolId,callers:[]};let n=new w(r.graph).callers(r.project.id,t.id);return{found:!0,symbol:v(t),count:n.length,callers:n.map(v)}}import{z as _t}from"zod";var kt={query:_t.string().min(1),limit:_t.number().int().min(1).max(50).optional()};async function Nt(r,e){let t=e.query.toLowerCase(),o=e.limit??20;return r.graph.allSymbols(r.project.id).filter(n=>n.name.toLowerCase().includes(t)||n.qualifiedName?.toLowerCase().includes(t)||n.filePath.toLowerCase().includes(t)).slice(0,o)}import{z as Ot}from"zod";var Dt={query:Ot.string().optional(),memoryLimit:Ot.number().int().min(1).max(20).optional()};async function Ft(r,e){let t=me(r.graph,r.project.id),o=r.memory.recent(r.project.id,5),n=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:o,relevant:n.map(s=>s.memory)}}import{z as Jo}from"zod";var Yo=["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"],M=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",o){let n=new Date().toISOString(),s=n.replace(/[:.]/g,"-"),i=this.projectPrefix(e),a=this.snapshotPrefix(e,s),c=[];for(let d of Yo){let f=`${i}/${d}`,m=await this.storage.get(f);m&&(await this.storage.put(`${a}/${d}`,m,"application/json"),c.push(d))}if(c.length===0)return null;let l={version:1,id:s,projectId:e,createdAt:n,reason:t,objects:c,metadata:o};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("/"),n=(await this.storage.list(t)).filter(i=>i.key.endsWith("/snapshot.json")),s=[];for(let i of n){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 o=this.snapshotPrefix(e,t),n=await this.storage.getText(`${o}/snapshot.json`);if(!n)throw new Error(`Snapshot not found: ${t}`);let s=JSON.parse(n);if(s.projectId!==e)throw new Error("Snapshot project mismatch");let i=this.projectPrefix(e),a=[];for(let c of s.objects){let l=await this.storage.get(`${o}/${c}`);l&&(await this.storage.put(`${i}/${c}`,l,"application/json"),a.push(c))}return{restored:a}}async remove(e,t){let o=this.snapshotPrefix(e,t),n=await this.storage.list(o);for(let s of n)await this.storage.delete(s.key);return n.length}async prune(e,t=10){let n=(await this.list(e)).slice(t),s=0;for(let i of n)await this.remove(e,i.id),s++;return s}};var Kt={reason:Jo.string().optional()};async function Gt(r,e){if(!r.storage)throw new Error("Storage unavailable");return new M(r.storage).create(r.project.id,e.reason??"manual-mcp")}async function $t(r){if(!r.storage)throw new Error("Storage unavailable");return new M(r.storage).list(r.project.id)}import{z as Qo}from"zod";var Ut={snapshotId:Qo.string().min(1)};async function Bt(r,e){if(!r.storage)throw new Error("Storage unavailable");let t=new M(r.storage);return await t.create(r.project.id,"before-rollback"),t.restore(r.project.id,e.snapshotId)}import{z as Ke}from"zod";var zt={symbolId:Ke.string().min(1),direction:Ke.enum(["callers","callees"]).optional(),depth:Ke.number().int().min(1).max(10).optional()};async function qt(r,e){let t=new fe(r.graph),o=e.direction??"callees",n=e.depth??3,s=o==="callers"?t.callers(r.project.id,e.symbolId,n):t.callees(r.project.id,e.symbolId,n);return{direction:o,depth:n,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 Ht}from"zod";var Vt={symbolId:Ht.string().min(1),depth:Ht.number().int().min(1).max(10).optional()};async function Wt(r,e){let t=r.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let n=new ge(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:n.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 Yt(r){return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:me(r.graph,r.project.id)}}import{z as Jt}from"zod";var Qt={filePath:Jt.string().min(1),direction:Jt.enum(["dependencies","dependents","both"]).optional()};async function Zt(r,e){let o=new z(r.graph).analyze(r.project.id).find(c=>c.filePath===e.filePath);if(!o)return{found:!1,filePath:e.filePath,dependencies:[],dependents:[]};let n=r.graph.allSymbols(r.project.id).filter(c=>c.type==="file"),s=new Map(n.map(c=>[c.filePath,c])),i=c=>({id:s.get(c)?.id??c,filePath:c}),a=e.direction??"both";return{found:!0,filePath:o.filePath,outgoingEdges:o.outgoingEdges,incomingEdges:o.incomingEdges,dependencies:a==="dependents"?[]:o.dependencies.map(i),dependents:a==="dependencies"?[]:o.dependents.map(i)}}import{z as Xt}from"zod";var er={query:Xt.string().min(1),limit:Xt.number().int().min(1).max(20).optional()};async function tr(r,e){return r.codeSemantic?{available:!0,results:(await r.codeSemantic.search(e.query,e.limit??8)).map(o=>({id:o.chunk.id,filePath:o.chunk.filePath,symbol:o.chunk.symbolName,symbolType:o.chunk.symbolType,startLine:o.chunk.startLine,endLine:o.chunk.endLine,score:o.score,vectorScore:o.vectorScore,lexicalScore:o.lexicalScore,content:o.chunk.content}))}:{available:!1,results:[]}}import{z as Ge}from"zod";var rr={mode:Ge.enum(["git_diff","file"]).optional(),filePath:Ge.string().optional(),depth:Ge.number().int().min(1).max(10).optional()};async function or(r,e){let t=new be(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 Zo}from"zod";var nr={symbol:Zo.string().min(1)};async function sr(r,e){let t=L(r,e.symbol);if(!t)return{found:!1,query:e.symbol,dependents:[]};let n=new w(r.graph).dependents(r.project.id,t.id);return{found:!0,symbol:v(t),count:n.length,dependents:n.map(v)}}import{z as $e}from"zod";var ir={from:$e.string().min(1),to:$e.string().min(1),maxDepth:$e.number().int().min(1).max(30).optional()};async function ar(r,e){let t=L(r,e.from),o=L(r,e.to);if(!t||!o)return{found:!1,fromFound:!!t,toFound:!!o,path:[],edges:[]};let s=new w(r.graph).shortestPath(r.project.id,t.id,o.id,e.maxDepth??12);return{found:s.found,distance:s.distance,from:v(t),to:v(o),path:s.symbols.map(v),edges:s.edges.map(i=>({id:i.id,type:i.type,from:i.from,to:i.to,metadata:i.metadata}))}}import{z as Ue}from"zod";var cr={symbol:Ue.string().min(1),depth:Ue.number().int().min(1).max(5).optional(),limit:Ue.number().int().min(1).max(200).optional()};async function lr(r,e){let t=L(r,e.symbol);if(!t)return{found:!1,query:e.symbol};let n=new w(r.graph).neighborhood(r.project.id,t.id,e.depth??1);if(!n)return{found:!1,query:e.symbol};let s=e.limit??50;return{found:!0,center:v(n.center),incomingCount:n.incoming.length,outgoingCount:n.outgoing.length,incoming:n.incoming.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:v(i.symbol)})),outgoing:n.outgoing.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:v(i.symbol)}))}}import{z as Be}from"zod";var pr={confidence:Be.enum(["high","medium","low","all"]).optional(),filePath:Be.string().min(1).optional(),limit:Be.number().int().min(1).max(500).optional()},dr={high:3,medium:2,low:1};async function mr(r,e){let o=new B(r.graph).analyze(r.project.id);if(e.confidence&&e.confidence!=="all"){let i=dr[e.confidence];o=o.filter(a=>dr[a.confidence]>=i)}e.filePath&&(o=o.filter(i=>i.filePath===e.filePath));let n=o.length,s=e.limit??100;return{total:n,high:o.filter(i=>i.confidence==="high").length,medium:o.filter(i=>i.confidence==="medium").length,low:o.filter(i=>i.confidence==="low").length,warning:"Dead-code results are candidates only. Verify before deleting code.",candidates:o.slice(0,s)}}function y(r){return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}function tn(r){let e=new Xo({name:"toolnet-memory",version:"0.1.0"});return e.tool("memory_search","Search relevant long-term memory for the current project.",vt,async t=>y(await wt(r,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",Pt,async t=>y(await At(r,t))),e.tool("memory_forget","Delete a memory by id.",Rt,async t=>y(await Lt(r,t))),e.tool("find_symbol","Find code symbols by exact name.",jt,async t=>y(await Mt(r,t))),e.tool("find_callers","Find functions or methods calling a symbol.",Tt,async t=>y(await It(r,t))),e.tool("code_search","Search indexed code symbols and files.",kt,async t=>y(await Nt(r,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",Dt,async t=>y(await Ft(r,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",zt,async t=>y(await qt(r,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",Vt,async t=>y(await Wt(r,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>y(await Yt(r))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",Qt,async t=>y(await Zt(r,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",er,async t=>y(await tr(r,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",Kt,async t=>y(await Gt(r,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>y(await $t(r))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",Ut,async t=>y(await Bt(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.",rr,async t=>y(await or(r,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",nr,async t=>y(await sr(r,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",ir,async t=>y(await ar(r,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",cr,async t=>y(await lr(r,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",pr,async t=>y(await mr(r,t))),e}async function fr(r){let e=tn(r),t=new en;await e.connect(t)}import{closeSync as rn,mkdirSync as on,openSync as nn,readFileSync as sn,unlinkSync as ur,writeFileSync as an}from"node:fs";import{tmpdir as cn}from"node:os";import{join as gr}from"node:path";function ln(r){try{return process.kill(r,0),!0}catch(e){return e?.code==="EPERM"}}var Le=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=gr(cn(),"toolnet-memory-locks");on(t,{recursive:!0});let o=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=gr(t,`${o}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=nn(this.path,"wx");an(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),rn(t),this.acquired=!0,process.once("exit",this.exitHandler);return}catch(t){if(t?.code!=="EEXIST")throw t;let o=!0;try{let n=JSON.parse(sn(this.path,"utf8"));Number.isInteger(n.pid)&&ln(n.pid)&&(o=!1)}catch{o=!0}if(!o)throw new Error("ToolNet Memory is already running for this project");try{ur(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{ur(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};async function dn(){let r=qe(),e=new J().detect(),t=yt({provider:r.storage.provider,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),o=St(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),n=new Re(o,e.id,e.name,e.remote??e.name),s=new Le(e.id);await s.acquire();let i=()=>{s.release().finally(()=>process.exit(0))};process.once("SIGINT",i),process.once("SIGTERM",i);let a=new ee,c=new Ae(n);a.importRecords(await c.load(e.id));let l=new se(a),d=new O,f=await new $(n).load(e.id);f&&d.import(f.symbols,f.edges);let m=new ue(d),u=new ve({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:n,embeddings:at(),graph:d});await u.initialize(),await fr({project:e,memory:a,retrieval:l,graph:d,references:m,codeSemantic:u,memoryStore:c,storage:n})}dn().catch(r=>{console.error(r),process.exit(1)});
@@ -0,0 +1,3 @@
1
+ import"dotenv/config";var f=[{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 u(e){let o=f.find(r=>r.id===e);if(!o)throw new Error(`Unsupported AI provider: ${e}`);return o}function E(e){return f.some(o=>o.id===e)}function n(e){return process.env[e]?.trim()||void 0}function a(...e){return e.find(o=>!!o?.trim())}function M(){if(n("GROQ_API_KEY"))return"groq";if(n("DEEPSEEK_API_KEY"))return"deepseek";if(n("NVIDIA_API_KEY")||n("NVIDIA_NIM_API_KEY"))return"nvidia";if(n("OPENROUTER_API_KEY"))return"openrouter";if(n("ALIBABA_API_KEY")||n("DASHSCOPE_API_KEY"))return"alibaba";if(n("GEMINI_API_KEY")||n("GOOGLE_API_KEY"))return"gemini";if(n("CLOUDFLARE_API_TOKEN")&&n("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(n("HF_TOKEN"))return"huggingface";if(n("OLLAMA_MODEL")||n("OLLAMA_BASE_URL"))return"ollama"}function w(){let e=n("TOOLNET_LLM_PROVIDER");return e&&E(e)?e:M()??"openai-compatible"}function b(e){let o=u(e);switch(e){case"alibaba":return{provider:e,apiKey:a(n("ALIBABA_API_KEY"),n("DASHSCOPE_API_KEY")),baseUrl:a(n("ALIBABA_BASE_URL"),n("DASHSCOPE_BASE_URL"),o.defaultBaseUrl),model:a(n("ALIBABA_MODEL"),n("DASHSCOPE_MODEL"))};case"openrouter":return{provider:e,apiKey:n("OPENROUTER_API_KEY"),baseUrl:a(n("OPENROUTER_BASE_URL"),o.defaultBaseUrl),model:n("OPENROUTER_MODEL")};case"groq":return{provider:e,apiKey:n("GROQ_API_KEY"),baseUrl:a(n("GROQ_BASE_URL"),o.defaultBaseUrl),model:n("GROQ_MODEL")};case"deepseek":return{provider:e,apiKey:n("DEEPSEEK_API_KEY"),baseUrl:a(n("DEEPSEEK_BASE_URL"),o.defaultBaseUrl),model:a(n("DEEPSEEK_MODEL"),o.defaultModel)};case"nvidia":return{provider:e,apiKey:a(n("NVIDIA_API_KEY"),n("NVIDIA_NIM_API_KEY")),baseUrl:a(n("NVIDIA_BASE_URL"),n("NVIDIA_NIM_BASE_URL"),o.defaultBaseUrl),model:a(n("NVIDIA_MODEL"),n("NVIDIA_NIM_MODEL"),o.defaultModel)};case"gemini":return{provider:e,apiKey:a(n("GEMINI_API_KEY"),n("GOOGLE_API_KEY")),baseUrl:a(n("GEMINI_BASE_URL"),o.defaultBaseUrl),model:n("GEMINI_MODEL")};case"huggingface":return{provider:e,apiKey:n("HF_TOKEN"),baseUrl:a(n("HF_INFERENCE_BASE_URL"),o.defaultBaseUrl),model:a(n("HF_LLM_MODEL"),n("HF_MODEL"))};case"ollama":return{provider:e,apiKey:n("OLLAMA_API_KEY"),baseUrl:a(n("OLLAMA_BASE_URL"),o.defaultBaseUrl),model:n("OLLAMA_MODEL")};case"cloudflare":return{provider:e,accountId:n("CLOUDFLARE_ACCOUNT_ID"),apiKey:n("CLOUDFLARE_API_TOKEN"),baseUrl:n("CLOUDFLARE_AI_BASE_URL"),model:n("CLOUDFLARE_MODEL")};case"custom":return{provider:e,apiKey:n("CUSTOM_AI_API_KEY"),baseUrl:n("CUSTOM_AI_BASE_URL"),model:n("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:a(n("OPENAI_API_KEY"),n("MODEL_API_KEY")),baseUrl:a(n("OPENAI_BASE_URL"),n("MODEL_BASE_URL")),model:a(n("OPENAI_MODEL"),n("MODEL_NAME"))}}}function k(){let e=n("TOOLNET_LLM_PROVIDER"),o=e&&E(e)?e:w(),r=u(o),t=b(o);return{provider:o,apiKey:a(n("TOOLNET_LLM_API_KEY"),t.apiKey),baseUrl:a(n("TOOLNET_LLM_BASE_URL"),t.baseUrl,r.defaultBaseUrl),model:a(n("TOOLNET_LLM_MODEL"),t.model,r.defaultModel),accountId:a(n("TOOLNET_LLM_ACCOUNT_ID"),t.accountId)}}function $(){let e=n("TOOLNET_EMBEDDING_PROVIDER");return e==="local"?"local":e&&E(e)?e:n("HF_TOKEN")||n("HF_EMBEDDING_MODEL")?"huggingface":"local"}function S(){let e=$();if(e==="local")return{provider:"local",model:a(n("TOOLNET_EMBEDDING_MODEL"),n("LOCAL_EMBEDDING_MODEL"))};let o=u(e),r,t,i,s;switch(e){case"huggingface":r=n("HF_TOKEN"),t=n("HF_INFERENCE_BASE_URL"),i=n("HF_EMBEDDING_MODEL");break;case"openai-compatible":r=n("OPENAI_API_KEY"),t=n("OPENAI_BASE_URL"),i=n("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":r=n("CLOUDFLARE_API_TOKEN"),t=n("CLOUDFLARE_AI_BASE_URL"),i=n("CLOUDFLARE_EMBEDDING_MODEL"),s=n("CLOUDFLARE_ACCOUNT_ID");break;default:r=b(e).apiKey,t=b(e).baseUrl,i=n(`${e.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let l=a(n("TOOLNET_EMBEDDING_ACCOUNT_ID"),s),d=a(n("TOOLNET_EMBEDDING_BASE_URL"),t,o.defaultBaseUrl),c=e==="cloudflare"&&!d&&l?`https://api.cloudflare.com/client/v4/accounts/${l}/ai/v1`:d;return{provider:e,apiKey:a(n("TOOLNET_EMBEDDING_API_KEY"),r),baseUrl:c,model:a(n("TOOLNET_EMBEDDING_MODEL"),i),accountId:l}}function p(){let e=k(),o=S();return{llm:e,embedding:o,legacy:{llm:!n("TOOLNET_LLM_PROVIDER")&&!!M(),embedding:!n("TOOLNET_EMBEDDING_PROVIDER")&&!!(n("HF_TOKEN")||n("HF_EMBEDDING_MODEL"))}}}function R(e=w()){let o=p().llm;if(e===o.provider)return{id:e,apiKey:o.apiKey,baseUrl:o.baseUrl,model:o.model,accountId:o.accountId};let r=b(e);return{id:e,apiKey:r.apiKey,baseUrl:r.baseUrl,model:r.model,accountId:r.accountId}}var P=class extends Error{status;constructor(o,r){super(o),this.name="AiHttpError",this.status=r}};async function g(e,o,r=3e4){let t=new AbortController,i=setTimeout(()=>t.abort(),r);i.unref?.();try{let s=await fetch(e,{...o,signal:t.signal}),l=await s.text();if(!s.ok){let d=l;try{let c=JSON.parse(l);d=c.error?.message??c.message??l}catch{}throw new P(d||`HTTP ${s.status}`,s.status)}return l.trim()?JSON.parse(l):{}}finally{clearTimeout(i)}}function A(e,o){return`${e.replace(/\/+$/,"")}/${o.replace(/^\/+/,"")}`}var y=class{constructor(o){this.config=o}config;id="cloudflare";model(){let o=this.config.model?.trim();if(!o)throw new Error("cloudflare: MODEL is not configured");return o}async generate(o){let r=this.config.accountId?.trim(),t=this.config.apiKey?.trim();if(!r)throw new Error("cloudflare: ACCOUNT ID is not configured");if(!t)throw new Error("cloudflare: API TOKEN is not configured");let i=this.model(),l=`${(this.config.baseUrl?.trim()||`https://api.cloudflare.com/client/v4/accounts/${r}/ai/run`).replace(/\/+$/,"")}/${i}`,d=await g(l,{method:"POST",headers:{authorization:`Bearer ${t}`,"content-type":"application/json",...this.config.headers},body:JSON.stringify({messages:o.messages,temperature:o.temperature,max_tokens:o.maxTokens})}),c=d.result?.response?.trim();if(!c)throw new Error(d.errors?.[0]?.message??"cloudflare: empty model response");return{text:c,provider:"cloudflare",model:i}}async healthCheck(){let o=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()-o}}catch(r){return{ok:!1,provider:"cloudflare",model:this.config.model,message:r instanceof Error?r.message:String(r),latencyMs:Date.now()-o}}}};var _=class{constructor(o){this.config=o}config;id="gemini";model(){let o=this.config.model?.trim();if(!o)throw new Error("gemini: MODEL is not configured");return o.replace(/^models\//,"")}async generate(o){let r=this.config.apiKey?.trim();if(!r)throw new Error("gemini: API KEY is not configured");let t=this.config.baseUrl?.trim()||"https://generativelanguage.googleapis.com/v1beta",i=this.model(),s=o.messages.filter(m=>m.role==="system"),l=o.messages.filter(m=>m.role!=="system").map(m=>({role:m.role==="assistant"?"model":"user",parts:[{text:m.content}]})),d=`${A(t,`models/${encodeURIComponent(i)}:generateContent`)}?key=${encodeURIComponent(r)}`,c=await g(d,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({...s.length?{systemInstruction:{parts:[{text:s.map(m=>m.content).join(`
2
+
3
+ `)}]}}:{},contents:l,generationConfig:{temperature:o.temperature,maxOutputTokens:o.maxTokens}})}),D=c.candidates?.[0]?.content?.parts?.map(m=>m.text??"").join("").trim();if(!D)throw new Error("gemini: empty model response");return{text:D,provider:"gemini",model:i,usage:c.usageMetadata?{inputTokens:c.usageMetadata.promptTokenCount,outputTokens:c.usageMetadata.candidatesTokenCount,totalTokens:c.usageMetadata.totalTokenCount}:void 0}}async healthCheck(){let o=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()-o}}catch(r){return{ok:!1,provider:"gemini",model:this.config.model,message:r instanceof Error?r.message:String(r),latencyMs:Date.now()-o}}}};var h=class{constructor(o){this.config=o;this.id=o.id}config;id;baseUrl(){let o=this.config.baseUrl?.trim();if(!o)throw new Error(`${this.id}: BASE URL is not configured`);return o}model(){let o=this.config.model?.trim();if(!o)throw new Error(`${this.id}: MODEL is not configured`);return o}headers(){let o={"content-type":"application/json",...this.config.headers};return this.config.apiKey&&(o.authorization=`Bearer ${this.config.apiKey}`),o}async generate(o){let r=this.model(),t=await g(A(this.baseUrl(),"chat/completions"),{method:"POST",headers:this.headers(),body:JSON.stringify({model:r,messages:o.messages,temperature:o.temperature,max_tokens:o.maxTokens})}),i=t.choices?.[0]?.message?.content?.trim();if(!i)throw new Error(`${this.id}: empty model response`);return{text:i,provider:this.id,model:r,usage:t.usage?{inputTokens:t.usage.prompt_tokens,outputTokens:t.usage.completion_tokens,totalTokens:t.usage.total_tokens}:void 0}}async healthCheck(){let o=Date.now();try{let r=await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8});return{ok:!0,provider:this.id,model:r.model,message:"Provider reachable",latencyMs:Date.now()-o}}catch(r){return{ok:!1,provider:this.id,model:this.config.model,message:r instanceof Error?r.message:String(r),latencyMs:Date.now()-o}}}};function N(e=R()){switch(u(e.id).transport){case"gemini":return new _(e);case"cloudflare":return new y(e);default:return new h(e)}}var v=class{constructor(o){this.options=o}options;name="gemini";async embed(o){let r=this.options.model.replace(/^models\//,""),i=`${this.options.baseUrl?.replace(/\/+$/,"")||"https://generativelanguage.googleapis.com/v1beta"}/models/${encodeURIComponent(r)}:embedContent?key=${encodeURIComponent(this.options.apiKey)}`,s=await fetch(i,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${r}`,content:{parts:[{text:o}]}})});if(!s.ok)throw new Error(`Gemini embedding failed: ${s.status} ${await s.text()}`);let d=(await s.json()).embedding?.values;if(!Array.isArray(d)||d.length===0)throw new Error("Gemini embedding returned invalid response");return d}async embedMany(o){let r=[];for(let t of o)r.push(await this.embed(t));return r}};import{createHash as x}from"node:crypto";var O=class{name="hash-fallback";dimensions=128;async embed(o){let r=new Array(this.dimensions).fill(0),t=o.toLowerCase().split(/\s+/).filter(Boolean);for(let i of t){let l=x("sha256").update(i).digest().readUInt32BE(0)%this.dimensions;r[l]+=1}return G(r)}async embedMany(o){return Promise.all(o.map(r=>this.embed(r)))}};function G(e){let o=Math.sqrt(e.reduce((r,t)=>r+t*t,0));return o===0?e:e.map(r=>r/o)}var I=class{constructor(o){this.options=o;this.dimensions=o.dimensions}options;name="openai-compatible";dimensions;async embed(o){let[r]=await this.embedMany([o]);return r}async embedMany(o){if(o.length===0)return[];let r=this.options.baseUrl.replace(/\/+$/,""),t=await fetch(`${r}/embeddings`,{method:"POST",headers:{"content-type":"application/json",...this.options.apiKey?{authorization:`Bearer ${this.options.apiKey}`}:{}},body:JSON.stringify({model:this.options.model,input:o})});if(!t.ok)throw new Error(`Embedding failed: ${t.status} ${await t.text()}`);let s=(await t.json()).data?.sort((l,d)=>(l.index??0)-(d.index??0)).map(l=>l.embedding);if(!s||s.length!==o.length||s.some(l=>!Array.isArray(l)))throw new Error("Embedding provider returned invalid response");return s}};var L=class{constructor(o){this.options=o}options;name="huggingface";dimensions=384;async embed(o){let[r]=await this.embedMany([o]);return r}async embedMany(o){if(o.length===0)return[];let r=`https://router.huggingface.co/hf-inference/models/${this.options.model}/pipeline/feature-extraction`,t=await fetch(r,{method:"POST",headers:{Authorization:`Bearer ${this.options.token}`,"Content-Type":"application/json"},body:JSON.stringify({inputs:o,options:{wait_for_model:!0}})});if(!t.ok)throw new Error(`HF embedding failed: ${t.status} ${await t.text()}`);let i=await t.json();if(!Array.isArray(i))throw new Error("HF embedding returned invalid response");return i.map(s=>F(s))}};function F(e){if(!Array.isArray(e))throw new Error("Invalid embedding");if(e.length>0&&typeof e[0]=="number")return e;if(e.length>0&&Array.isArray(e[0])){let o=e;if(o.length===0)return[];let r=o[0].length,t=new Array(r).fill(0);for(let i of o)for(let s=0;s<r;s++)t[s]+=i[s]??0;for(let i=0;i<r;i++)t[i]/=o.length;return t}throw new Error("Unsupported embedding shape")}var U=class{constructor(o,r=new O){this.primary=o;this.fallback=r}primary;fallback;name="resilient";async embed(o){if(this.primary)try{return await this.primary.embed(o)}catch(r){console.warn("[embedding] primary failed, fallback enabled:",r instanceof Error?r.message:r)}return this.fallback.embed(o)}async embedMany(o){if(this.primary)try{return await this.primary.embedMany(o)}catch(r){console.warn("[embedding] primary failed, fallback enabled:",r instanceof Error?r.message:r)}return this.fallback.embedMany(o)}};function H(e){return`https://api.cloudflare.com/client/v4/accounts/${e}/ai/v1`}function Y(){let e=p().embedding;if(e.provider==="local")return null;if(e.provider==="huggingface")return!e.apiKey||!e.model?null:new L({token:e.apiKey,model:e.model});if(e.provider==="gemini")return!e.apiKey||!e.model?null:new v({apiKey:e.apiKey,model:e.model,baseUrl:e.baseUrl});let o=e.baseUrl;return e.provider==="cloudflare"&&!o&&e.accountId&&(o=H(e.accountId)),o&&e.model?new I({apiKey:e.apiKey,baseUrl:o,model:e.model}):null}function T(){return new U(Y())}function K(e){return e?e.length<=8?"********":`${e.slice(0,4)}...${e.slice(-4)}`:"not configured"}function j(){console.log(""),console.log("ToolNet AI Providers"),console.log("===================="),console.log("");for(let e of f)console.log(`- ${e.label}`),console.log(` id : ${e.id}`),console.log(` protocol : ${e.transport}`),e.defaultBaseUrl&&console.log(` base URL : ${e.defaultBaseUrl}`),e.defaultModel&&console.log(` model : ${e.defaultModel}`),console.log("");console.log("- Local / Hash embedding"),console.log(" id : local"),console.log(" protocol : local"),console.log("")}function q(){let e=p();console.log(""),console.log("ToolNet Provider Status"),console.log("======================="),console.log(""),console.log("LLM"),console.log(` Provider : ${e.llm.provider}`),console.log(` Model : ${e.llm.model??"not configured"}`),console.log(` Base URL : ${e.llm.baseUrl??"default/provider native"}`),console.log(` API Key : ${K(e.llm.apiKey)}`),e.llm.accountId&&console.log(` Account : ${e.llm.accountId}`),console.log(` Legacy : ${e.legacy.llm?"yes":"no"}`),console.log(""),console.log("Embedding"),console.log(` Provider : ${e.embedding.provider}`),console.log(` Model : ${e.embedding.model??(e.embedding.provider==="local"?"local hash":"not configured")}`),console.log(` Base URL : ${e.embedding.baseUrl??(e.embedding.provider==="local"?"local":"default/provider native")}`),console.log(` API Key : ${e.embedding.provider==="local"?"not required":K(e.embedding.apiKey)}`),e.embedding.accountId&&console.log(` Account : ${e.embedding.accountId}`),console.log(` Legacy : ${e.legacy.embedding?"yes":"no"}`),console.log("")}async function C(){let e=p().llm;console.log(""),console.log("Testing LLM"),console.log("-----------"),console.log(`Provider : ${e.provider}`),console.log(`Model : ${e.model??"not configured"}`);try{let r=await N({id:e.provider,apiKey:e.apiKey,baseUrl:e.baseUrl,model:e.model,accountId:e.accountId}).healthCheck();return r.ok?(console.log("\u2713 Provider reachable"),r.latencyMs!==void 0&&console.log(`\u2713 Latency: ${r.latencyMs} ms`),console.log(""),!0):(console.log(`\u2717 ${r.message}`),!1)}catch(o){return console.log(`\u2717 ${o instanceof Error?o.message:String(o)}`),console.log(""),!1}}async function B(){let e=p().embedding;console.log(""),console.log("Testing Embedding"),console.log("-----------------"),console.log(`Provider : ${e.provider}`),console.log(`Model : ${e.model??(e.provider==="local"?"local hash":"not configured")}`);try{let r=await T().embed("ToolNet Memory provider health check");if(!Array.isArray(r)||r.length===0)throw new Error("Empty embedding vector");return console.log("\u2713 Embedding ready"),console.log(`\u2713 Dimensions: ${r.length}`),console.log(""),!0}catch(o){return console.log(`\u2717 ${o instanceof Error?o.message:String(o)}`),console.log(""),!1}}async function V(){let e=await C(),o=await B();return console.log(""),console.log("Provider Test Summary"),console.log("====================="),console.log(`LLM : ${e?"READY":"FAILED"}`),console.log(`Embedding : ${o?"READY":"FAILED"}`),console.log(""),e&&o}async function J(){let e=process.argv[2]??"status";if(e==="list"){j();return}if(e==="status"){q();return}if(e==="test"){let o=process.argv[3]??"all",r=!1;o==="llm"?r=await C():o==="embedding"?r=await B():r=await V(),process.exitCode=r?0:1;return}console.error(`Unknown provider command: ${e}`),console.error(""),console.error("Usage:"),console.error(" toolnet-memory provider:list"),console.error(" toolnet-memory provider:status"),console.error(" toolnet-memory provider:test"),console.error(" toolnet-memory provider:test llm"),console.error(" toolnet-memory provider:test embedding"),process.exitCode=1}J().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});