toolnet-memory 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import"dotenv/config";import{existsSync as ae,readFileSync as ce}from"node:fs";import{homedir as de}from"node:os";import{join as pe}from"node:path";function me(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 le(){let o=process.env.TOOLNET_GLOBAL_ENV??pe(de(),".config","toolnet-memory",".env");if(!ae(o))return;let e=ce(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 i=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=me(r.slice(s+1)))}}le();function C(o,e){return o===void 0?e:["1","true","yes","on"].includes(o.toLowerCase())}function R(o,e){if(!o)return e;let t=Number(o);return Number.isFinite(t)?t:e}function K(){return{memory:{autoCapture:C(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:C(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:C(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:C(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:R(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:R(process.env.MEMORY_RERANK_TOP,10),finalContext:R(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:R(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:R(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ge}from"node:crypto";import{existsSync as F,mkdirSync as ue,readFileSync as fe,renameSync as ye,writeFileSync as he}from"node:fs";import{basename as Se,dirname as E,join as T,parse as J,resolve as k}from"node:path";var H=".toolnet",ve="project.json";function xe(o){return ge("sha256").update(o).digest("hex").slice(0,16)}function L(o){return T(o,H,ve)}function je(o){return F(L(o))}function be(o,e){let t=k(o),r=J(t).root;for(;;){if(je(t))return t;if(t===r||e&&t===k(e))break;let s=E(t);if(s===t)break;t=s}return null}function we(o){let e=k(o),t=J(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(i=>F(T(e,i))))return e;if(e===t)break;let s=E(e);if(s===e)break;e=s}return k(o)}function Pe(o){let e;try{e=JSON.parse(fe(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:E(E(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 V(o,e){let t=T(o,H);ue(t,{recursive:!0});let r=L(o),s=`${r}.tmp-${process.pid}`;he(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),ye(s,r)}function G(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 A=class{detect(e=process.cwd()){let t=k(e),r=we(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>F(T(r,p))),n=be(t,i?r:void 0);if(n){let p=L(n),l=Pe(p);return l.rootPath!==n&&(l.rootPath=n,l.updatedAt=new Date().toISOString(),V(n,l)),G(l,n)}let m=new Date().toISOString(),d=Se(r),c={version:1,id:xe(r),name:d,remote:d,rootPath:r,createdAt:m,updatedAt:m,graphVersion:0,memoryVersion:0};return V(r,c),G(c,r)}};import{homedir as ze}from"node:os";import{join as Be}from"node:path";import{DeleteObjectCommand as Re,GetObjectCommand as ke,HeadObjectCommand as Me,ListObjectsV2Command as Ce,PutObjectCommand as Ee,S3Client as Ae}from"@aws-sdk/client-s3";import{getSignedUrl as Te}from"@aws-sdk/s3-request-presigner";var I=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ae({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 Ee({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await Te(this.client,new ke({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 Me({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 Re({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new Ce({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let i of s.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};import{access as U,mkdir as Ie,readFile as Oe,readdir as $e,rm as Ne,stat as W,writeFile as _e}from"node:fs/promises";import{dirname as De,join as Fe,relative as Y,resolve as Le}from"node:path";var M=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Le(this.root,t)}async put(e,t){let r=this.path(e);await Ie(De(r),{recursive:!0}),await _e(r,t)}async get(e){try{return await Oe(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 U(this.path(e)),!0}catch{return!1}}async delete(e){await Ne(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await U(t)}catch{return r}let s=async n=>{let m=await $e(n,{withFileTypes:!0});for(let d of m){let c=Fe(n,d.name);if(d.isDirectory()){await s(c);continue}let p=await W(c);r.push({key:Y(this.root,c),size:p.size,updatedAt:p.mtime.toISOString()})}},i=await W(t);return i.isDirectory()?await s(t):r.push({key:Y(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),r}};function Z(o){let e=o.localRoot??Be(ze(),".toolnet-memory","storage");if(o.provider==="huggingface"){let t=o.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new I({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new M(e))}return new M(e)}var O=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};var $=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","manifest.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function X(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 Q(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 N=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=X(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 n;try{n=JSON.parse(s)}catch(m){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${m instanceof Error?m.message:String(m)}`)}if(typeof n.id=="string"&&n.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${n.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof n.createdAt=="string"&&(r=n.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Q(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{join as qe}from"node:path";import{readdir as Je}from"node:fs/promises";import{extname as He,join as Ue,relative as We}from"node:path";import{basename as Ke}from"node:path";var Ve=new Set([".env",".env.local",".env.production",".env.development","id_rsa","id_ed25519","credentials","credentials.json","service-account.json"]),Ge=new Set([".pem",".key",".p12",".pfx"]);function q(o){let e=Ke(o).toLowerCase();if(Ve.has(e))return!0;for(let t of Ge)if(e.endsWith(t))return!0;return!1}var Ye=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".mts",".cts"]),Ze=new Set(["node_modules",".git","dist","build","coverage",".next",".cache",".toolnet-memory"]);async function ee(o){let e=[];async function t(r){let s=await Je(r,{withFileTypes:!0});for(let i of s){if(Ze.has(i.name))continue;let n=Ue(r,i.name);if(i.isDirectory()){await t(n);continue}Ye.has(He(i.name))&&(q(n)||e.push(We(o,n)))}}return await t(o),e.sort()}import{createHash as Xe}from"node:crypto";import{readFile as Qe}from"node:fs/promises";async function te(o){let e=await Qe(o);return Xe("sha256").update(e).digest("hex")}async function re(o,e){let t=await ee(e),r={};for(let s of t)r[s]={path:s,hash:await te(qe(e,s))};return{version:1,projectId:o,updatedAt:new Date().toISOString(),files:r}}function oe(o,e){let t=o?.files??{},r=e.files,s=[],i=[],n=[],m=[];for(let[d,c]of Object.entries(r)){let p=t[d];p?p.hash!==c.hash?i.push(d):m.push(d):s.push(d)}for(let d of Object.keys(t))r[d]||n.push(d);return{added:s.sort(),modified:i.sort(),deleted:n.sort(),unchanged:m.sort()}}import{readFile as et}from"node:fs/promises";import{join as tt}from"node:path";import{createHash as rt}from"node:crypto";import h from"typescript";function se(o,e){return rt("sha256").update(`${o}:${e}`).digest("hex").slice(0,24)}function z(o,e){return o.getLineAndCharacterOfPosition(e.getStart(o)).line+1}async function ne(o,e,t){let r=tt(e,t),s=await et(r,"utf8"),i=h.createSourceFile(t,s,h.ScriptTarget.Latest,!0,t.endsWith(".tsx")||t.endsWith(".jsx")?h.ScriptKind.TSX:h.ScriptKind.TS),n=[],m=[],d=[],c=[],p={id:se(o,`file:${t}`),projectId:o,name:t,qualifiedName:t,type:"file",filePath:t,startLine:1,endLine:i.getLineAndCharacterOfPosition(i.end).line+1};n.push(p);let l=[],v=[];function f(a,S,y,u){let j=se(o,`${t}:${y}:${u??S}:${a.pos}`);return n.push({id:j,projectId:o,name:S,qualifiedName:u??S,type:y,filePath:t,startLine:z(i,a),endLine:i.getLineAndCharacterOfPosition(a.end).line+1}),j}function w(a){if(!h.isStringLiteral(a.moduleSpecifier))return;let S=[],y=a.importClause;if(y?.name&&S.push({localName:y.name.text,importedName:"default",kind:"default"}),y?.namedBindings&&h.isNamedImports(y.namedBindings))for(let u of y.namedBindings.elements)S.push({localName:u.name.text,importedName:u.propertyName?.text??u.name.text,kind:"named"});y?.namedBindings&&h.isNamespaceImport(y.namedBindings)&&S.push({localName:y.namedBindings.name.text,importedName:"*",kind:"namespace"}),m.push({source:a.moduleSpecifier.text,bindings:S})}function x(a,S){for(let y of a.heritageClauses??[])for(let u of y.types){let j=u.expression.getText(i).split(".").at(-1)??"";j&&c.push({fromId:S,targetName:j,type:y.token===h.SyntaxKind.ExtendsKeyword?"INHERITS":"IMPLEMENTS"})}}function g(a){let S=!1,y=!1;if(h.isImportDeclaration(a)&&w(a),h.isInterfaceDeclaration(a)&&f(a,a.name.text,"interface",a.name.text),h.isClassDeclaration(a)&&a.name){let u=f(a,a.name.text,"class",a.name.text);x(a,u),v.push({id:u,name:a.name.text}),y=!0}if(h.isFunctionDeclaration(a)&&a.name){let u=f(a,a.name.text,"function",a.name.text);l.push(u),S=!0}if(h.isMethodDeclaration(a)&&a.name){let u=a.name.getText(i),j=v.at(-1)?.name,ie=f(a,u,"method",j?`${j}.${u}`:u);l.push(ie),S=!0}if(h.isCallExpression(a)&&(h.isIdentifier(a.expression)&&d.push({callerId:l.at(-1),calleeName:a.expression.text,line:z(i,a)}),h.isPropertyAccessExpression(a.expression))){let u=a.expression;d.push({callerId:l.at(-1),qualifier:u.expression.getText(i),calleeName:u.name.text,line:z(i,a)})}h.forEachChild(a,g),S&&l.pop(),y&&v.pop()}return g(i),{filePath:t,symbols:n,imports:m,calls:d,heritage:c}}import{createHash as ot}from"node:crypto";import{dirname as st,extname as nt,normalize as it,posix as at}from"node:path";var P=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 ct(o,e,t,r){return ot("sha256").update(`${o}:${e}:${t}:${r}`).digest("hex").slice(0,24)}function b(o){return it(o).replaceAll("\\","/")}function B(o,e,t){if(!e.startsWith("."))return;let r=b(at.join(st(o),e)),s=nt(r),i;if(s===".js"){let n=r.slice(0,-3);i=[`${n}.ts`,`${n}.tsx`,`${n}.js`,`${n}.jsx`]}else if(s===".mjs"){let n=r.slice(0,-4);i=[`${n}.mts`,`${n}.ts`,`${n}.mjs`]}else if(s===".cjs"){let n=r.slice(0,-4);i=[`${n}.cts`,`${n}.ts`,`${n}.cjs`]}else s?i=[r]:i=[`${r}.ts`,`${r}.tsx`,`${r}.mts`,`${r}.cts`,`${r}.js`,`${r}.jsx`,`${r}.mjs`,`${r}.cjs`,`${r}/index.ts`,`${r}/index.tsx`,`${r}/index.js`,`${r}/index.jsx`];return i.find(n=>t.has(b(n)))}var _=class{build(e,t){let r=new P,s=new Map;for(let n of t)for(let m of n.symbols)r.addSymbol(m),m.type==="file"&&s.set(b(n.filePath),m);let i=new Set(s.keys());for(let n of t){let m=b(n.filePath),d=s.get(m);if(d){for(let c of n.symbols)c.id!==d.id&&r.addEdge(this.edge(e,d.id,"DEFINES",c.id));for(let c of n.imports){let p=B(m,c.source,i);if(!p)continue;let l=s.get(p);l&&r.addEdge(this.edge(e,d.id,"IMPORTS",l.id,{source:c.source}))}for(let c of n.heritage){let p=r.findByName(e,c.targetName).filter(l=>l.type==="class"||l.type==="interface");for(let l of p)r.addEdge(this.edge(e,c.fromId,c.type,l.id))}for(let c of n.calls){if(!c.callerId)continue;let p=this.resolveCallTargets(e,n,c.calleeName,c.qualifier,t,r,i);for(let l of p)l.id!==c.callerId&&r.addEdge(this.edge(e,c.callerId,"CALLS",l.id,{line:c.line,qualifier:c.qualifier}))}}}return r}resolveCallTargets(e,t,r,s,i,n,m){let d=b(t.filePath),c=n.findByName(e,r).filter(p=>b(p.filePath)===d);if(!s&&c.length)return c;if(s)for(let p of t.imports){if(!p.bindings.find(f=>f.kind==="namespace"&&f.localName===s))continue;let v=B(d,p.source,m);if(v)return n.findByName(e,r).filter(f=>b(f.filePath)===v)}for(let p of t.imports){let l=p.bindings.find(x=>x.localName===r);if(!l)continue;let v=B(d,p.source,m);if(!v)continue;let f=l.importedName==="default"?r:l.importedName,w=n.findByName(e,f).filter(x=>b(x.filePath)===v);if(w.length)return w}return n.findByName(e,r).filter(p=>p.type==="function"||p.type==="method")}edge(e,t,r,s,i){return{id:ct(e,t,r,s),projectId:e,from:t,to:s,type:r,metadata:i}}};var D=class{constructor(e){this.storage=e}storage;async index(e,t){let r=new $(this.storage),s=new O(this.storage),i=await r.load(e),n=await s.load(e),m=await re(e,t),d=oe(i,m),c=[...d.added,...d.modified];if(i&&n&&c.length===0&&d.deleted.length===0)return{firstRun:!1,scanned:Object.keys(m.files).length,parsed:0,added:0,modified:0,deleted:0,unchanged:d.unchanged.length,symbols:n.symbols.length,edges:n.edges.length,saved:!1};let p=n?.symbols.filter(g=>d.unchanged.includes(g.filePath))??[],l=[];for(let g of c)l.push(await ne(e,t,g));let v=new _().build(e,l),f=new P;for(let g of p)f.addSymbol(g);for(let g of v.allSymbols(e))f.addSymbol(g);let w=new Set(f.allSymbols(e).map(g=>g.id));for(let g of n?.edges??[])w.has(g.from)&&w.has(g.to)&&!c.includes(n.symbols.find(a=>a.id===g.from)?.filePath??"")&&!c.includes(n.symbols.find(a=>a.id===g.to)?.filePath??"")&&f.addEdge(g);for(let g of v.allEdges(e))f.addEdge(g);let x={version:1,projectId:e,updatedAt:new Date().toISOString(),files:Object.keys(m.files).length,symbols:f.allSymbols(e),edges:f.allEdges(e)};return await s.save(x),await r.save(m),{firstRun:i===null,scanned:Object.keys(m.files).length,parsed:c.length,added:d.added.length,modified:d.modified.length,deleted:d.deleted.length,unchanged:d.unchanged.length,symbols:x.symbols.length,edges:x.edges.length,saved:!0}}};async function dt(){let o=K(),e=new A().detect(),t=Z({provider:o.storage.provider,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),r=new N(t,e.id,e.name,e.remote??e.name),s=await new D(r).index(e.id,e.rootPath);console.log({ok:!0,storage:r.name,...s})}dt().catch(o=>{console.error(o),process.exit(1)});
1
+ import"dotenv/config";import{existsSync as ae,readFileSync as ce}from"node:fs";import{homedir as de}from"node:os";import{join as pe}from"node:path";function me(s){let e=s.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 le(){let s=process.env.TOOLNET_GLOBAL_ENV??pe(de(),".config","toolnet-memory",".env");if(!ae(s))return;let e=ce(s,"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 o=r.indexOf("=");if(o<=0)continue;let i=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=me(r.slice(o+1)))}}le();function C(s,e){return s===void 0?e:["1","true","yes","on"].includes(s.toLowerCase())}function R(s,e){if(!s)return e;let t=Number(s);return Number.isFinite(t)?t:e}function K(){return{memory:{autoCapture:C(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:C(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:C(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:C(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:R(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:R(process.env.MEMORY_RERANK_TOP,10),finalContext:R(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:R(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:R(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ge}from"node:crypto";import{existsSync as F,mkdirSync as ue,readFileSync as fe,renameSync as ye,writeFileSync as he}from"node:fs";import{basename as Se,dirname as E,join as T,parse as J,resolve as k}from"node:path";var H=".toolnet",ve="project.json";function xe(s){return ge("sha256").update(s).digest("hex").slice(0,16)}function L(s){return T(s,H,ve)}function je(s){return F(L(s))}function be(s,e){let t=k(s),r=J(t).root;for(;;){if(je(t))return t;if(t===r||e&&t===k(e))break;let o=E(t);if(o===t)break;t=o}return null}function we(s){let e=k(s),t=J(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(i=>F(T(e,i))))return e;if(e===t)break;let o=E(e);if(o===e)break;e=o}return k(s)}function Pe(s){let e;try{e=JSON.parse(fe(s,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${s}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${s}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${s}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${s}`);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:E(E(s)),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 V(s,e){let t=T(s,H);ue(t,{recursive:!0});let r=L(s),o=`${r}.tmp-${process.pid}`;he(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ye(o,r)}function G(s,e){return{id:s.id,name:s.name,remote:s.remote,rootPath:e,createdAt:s.createdAt,updatedAt:s.updatedAt,graphVersion:s.graphVersion,memoryVersion:s.memoryVersion,metadata:s.metadata}}var A=class{detect(e=process.cwd()){let t=k(e),r=we(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>F(T(r,m))),n=be(t,i?r:void 0);if(n){let m=L(n),g=Pe(m);return g.rootPath!==n&&(g.rootPath=n,g.updatedAt=new Date().toISOString(),V(n,g)),G(g,n)}let l=new Date().toISOString(),d=Se(r),c={version:1,id:xe(r),name:d,remote:d,rootPath:r,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return V(r,c),G(c,r)}};import{homedir as ze}from"node:os";import{join as Be}from"node:path";import{DeleteObjectCommand as Re,GetObjectCommand as ke,HeadObjectCommand as Me,ListObjectsV2Command as Ce,PutObjectCommand as Ee,S3Client as Ae}from"@aws-sdk/client-s3";import{getSignedUrl as Te}from"@aws-sdk/s3-request-presigner";var I=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ae({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 o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ee({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await Te(this.client,new ke({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 Me({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 Re({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new Ce({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};import{access as U,mkdir as Ie,readFile as Oe,readdir as $e,rm as Ne,stat as W,writeFile as _e}from"node:fs/promises";import{dirname as De,join as Fe,relative as Y,resolve as Le}from"node:path";var M=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Le(this.root,t)}async put(e,t){let r=this.path(e);await Ie(De(r),{recursive:!0}),await _e(r,t)}async get(e){try{return await Oe(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 U(this.path(e)),!0}catch{return!1}}async delete(e){await Ne(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await U(t)}catch{return r}let o=async n=>{let l=await $e(n,{withFileTypes:!0});for(let d of l){let c=Fe(n,d.name);if(d.isDirectory()){await o(c);continue}let m=await W(c);r.push({key:Y(this.root,c),size:m.size,updatedAt:m.mtime.toISOString()})}},i=await W(t);return i.isDirectory()?await o(t):r.push({key:Y(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),r}};function Z(s){let e=s.localRoot??Be(ze(),".toolnet-memory","storage");if(s.provider==="huggingface"){let t=s.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new I({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new M(e))}return new M(e)}var O=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};var $=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","manifest.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function X(s){let e=s.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 Q(s){let e=s.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 o=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:e))}var N=class{constructor(e,t,r,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=X(o??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,o=await this.provider.getText(e);if(o){let n;try{n=JSON.parse(o)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}if(typeof n.id=="string"&&n.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${n.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof n.createdAt=="string"&&(r=n.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Q(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{join as qe}from"node:path";import{readdir as Je}from"node:fs/promises";import{extname as He,join as Ue,relative as We}from"node:path";import{basename as Ke}from"node:path";var Ve=new Set([".env",".env.local",".env.production",".env.development","id_rsa","id_ed25519","credentials","credentials.json","service-account.json"]),Ge=new Set([".pem",".key",".p12",".pfx"]);function q(s){let e=Ke(s).toLowerCase();if(Ve.has(e))return!0;for(let t of Ge)if(e.endsWith(t))return!0;return!1}var Ye=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".mts",".cts"]),Ze=new Set(["node_modules",".git","dist","build","coverage",".next",".cache",".toolnet-memory"]);async function ee(s){let e=[];async function t(r){let o=await Je(r,{withFileTypes:!0});for(let i of o){if(Ze.has(i.name))continue;let n=Ue(r,i.name);if(i.isDirectory()){await t(n);continue}Ye.has(He(i.name))&&(q(n)||e.push(We(s,n)))}}return await t(s),e.sort()}import{createHash as Xe}from"node:crypto";import{readFile as Qe}from"node:fs/promises";async function te(s){let e=await Qe(s);return Xe("sha256").update(e).digest("hex")}async function re(s,e){let t=await ee(e),r={};for(let o of t)r[o]={path:o,hash:await te(qe(e,o))};return{version:1,projectId:s,updatedAt:new Date().toISOString(),files:r}}function se(s,e){let t=s?.files??{},r=e.files,o=[],i=[],n=[],l=[];for(let[d,c]of Object.entries(r)){let m=t[d];m?m.hash!==c.hash?i.push(d):l.push(d):o.push(d)}for(let d of Object.keys(t))r[d]||n.push(d);return{added:o.sort(),modified:i.sort(),deleted:n.sort(),unchanged:l.sort()}}import{readFile as et}from"node:fs/promises";import{join as tt}from"node:path";import{createHash as rt}from"node:crypto";import*as p from"typescript";function oe(s,e){return rt("sha256").update(`${s}:${e}`).digest("hex").slice(0,24)}function z(s,e){return s.getLineAndCharacterOfPosition(e.getStart(s)).line+1}async function ne(s,e,t){let r=tt(e,t),o=await et(r,"utf8"),i=p.createSourceFile(t,o,p.ScriptTarget.Latest,!0,t.endsWith(".tsx")||t.endsWith(".jsx")?p.ScriptKind.TSX:p.ScriptKind.TS),n=[],l=[],d=[],c=[],m={id:oe(s,`file:${t}`),projectId:s,name:t,qualifiedName:t,type:"file",filePath:t,startLine:1,endLine:i.getLineAndCharacterOfPosition(i.end).line+1};n.push(m);let g=[],v=[];function y(a,S,h,f){let j=oe(s,`${t}:${h}:${f??S}:${a.pos}`);return n.push({id:j,projectId:s,name:S,qualifiedName:f??S,type:h,filePath:t,startLine:z(i,a),endLine:i.getLineAndCharacterOfPosition(a.end).line+1}),j}function w(a){if(!p.isStringLiteral(a.moduleSpecifier))return;let S=[],h=a.importClause;if(h?.name&&S.push({localName:h.name.text,importedName:"default",kind:"default"}),h?.namedBindings&&p.isNamedImports(h.namedBindings))for(let f of h.namedBindings.elements)S.push({localName:f.name.text,importedName:f.propertyName?.text??f.name.text,kind:"named"});h?.namedBindings&&p.isNamespaceImport(h.namedBindings)&&S.push({localName:h.namedBindings.name.text,importedName:"*",kind:"namespace"}),l.push({source:a.moduleSpecifier.text,bindings:S})}function x(a,S){for(let h of a.heritageClauses??[])for(let f of h.types){let j=f.expression.getText(i).split(".").at(-1)??"";j&&c.push({fromId:S,targetName:j,type:h.token===p.SyntaxKind.ExtendsKeyword?"INHERITS":"IMPLEMENTS"})}}function u(a){let S=!1,h=!1;if(p.isImportDeclaration(a)&&w(a),p.isInterfaceDeclaration(a)&&y(a,a.name.text,"interface",a.name.text),p.isClassDeclaration(a)&&a.name){let f=y(a,a.name.text,"class",a.name.text);x(a,f),v.push({id:f,name:a.name.text}),h=!0}if(p.isFunctionDeclaration(a)&&a.name){let f=y(a,a.name.text,"function",a.name.text);g.push(f),S=!0}if(p.isMethodDeclaration(a)&&a.name){let f=a.name.getText(i),j=v.at(-1)?.name,ie=y(a,f,"method",j?`${j}.${f}`:f);g.push(ie),S=!0}if(p.isCallExpression(a)&&(p.isIdentifier(a.expression)&&d.push({callerId:g.at(-1),calleeName:a.expression.text,line:z(i,a)}),p.isPropertyAccessExpression(a.expression))){let f=a.expression;d.push({callerId:g.at(-1),qualifier:f.expression.getText(i),calleeName:f.name.text,line:z(i,a)})}p.forEachChild(a,u),S&&g.pop(),h&&v.pop()}return u(i),{filePath:t,symbols:n,imports:l,calls:d,heritage:c}}import{createHash as st}from"node:crypto";import{dirname as ot,extname as nt,normalize as it,posix as at}from"node:path";var P=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 ct(s,e,t,r){return st("sha256").update(`${s}:${e}:${t}:${r}`).digest("hex").slice(0,24)}function b(s){return it(s).replaceAll("\\","/")}function B(s,e,t){if(!e.startsWith("."))return;let r=b(at.join(ot(s),e)),o=nt(r),i;if(o===".js"){let n=r.slice(0,-3);i=[`${n}.ts`,`${n}.tsx`,`${n}.js`,`${n}.jsx`]}else if(o===".mjs"){let n=r.slice(0,-4);i=[`${n}.mts`,`${n}.ts`,`${n}.mjs`]}else if(o===".cjs"){let n=r.slice(0,-4);i=[`${n}.cts`,`${n}.ts`,`${n}.cjs`]}else o?i=[r]:i=[`${r}.ts`,`${r}.tsx`,`${r}.mts`,`${r}.cts`,`${r}.js`,`${r}.jsx`,`${r}.mjs`,`${r}.cjs`,`${r}/index.ts`,`${r}/index.tsx`,`${r}/index.js`,`${r}/index.jsx`];return i.find(n=>t.has(b(n)))}var _=class{build(e,t){let r=new P,o=new Map;for(let n of t)for(let l of n.symbols)r.addSymbol(l),l.type==="file"&&o.set(b(n.filePath),l);let i=new Set(o.keys());for(let n of t){let l=b(n.filePath),d=o.get(l);if(d){for(let c of n.symbols)c.id!==d.id&&r.addEdge(this.edge(e,d.id,"DEFINES",c.id));for(let c of n.imports){let m=B(l,c.source,i);if(!m)continue;let g=o.get(m);g&&r.addEdge(this.edge(e,d.id,"IMPORTS",g.id,{source:c.source}))}for(let c of n.heritage){let m=r.findByName(e,c.targetName).filter(g=>g.type==="class"||g.type==="interface");for(let g of m)r.addEdge(this.edge(e,c.fromId,c.type,g.id))}for(let c of n.calls){if(!c.callerId)continue;let m=this.resolveCallTargets(e,n,c.calleeName,c.qualifier,t,r,i);for(let g of m)g.id!==c.callerId&&r.addEdge(this.edge(e,c.callerId,"CALLS",g.id,{line:c.line,qualifier:c.qualifier}))}}}return r}resolveCallTargets(e,t,r,o,i,n,l){let d=b(t.filePath),c=n.findByName(e,r).filter(m=>b(m.filePath)===d);if(!o&&c.length)return c;if(o)for(let m of t.imports){if(!m.bindings.find(y=>y.kind==="namespace"&&y.localName===o))continue;let v=B(d,m.source,l);if(v)return n.findByName(e,r).filter(y=>b(y.filePath)===v)}for(let m of t.imports){let g=m.bindings.find(x=>x.localName===r);if(!g)continue;let v=B(d,m.source,l);if(!v)continue;let y=g.importedName==="default"?r:g.importedName,w=n.findByName(e,y).filter(x=>b(x.filePath)===v);if(w.length)return w}return n.findByName(e,r).filter(m=>m.type==="function"||m.type==="method")}edge(e,t,r,o,i){return{id:ct(e,t,r,o),projectId:e,from:t,to:o,type:r,metadata:i}}};var D=class{constructor(e){this.storage=e}storage;async index(e,t){let r=new $(this.storage),o=new O(this.storage),i=await r.load(e),n=await o.load(e),l=await re(e,t),d=se(i,l),c=[...d.added,...d.modified];if(i&&n&&c.length===0&&d.deleted.length===0)return{firstRun:!1,scanned:Object.keys(l.files).length,parsed:0,added:0,modified:0,deleted:0,unchanged:d.unchanged.length,symbols:n.symbols.length,edges:n.edges.length,saved:!1};let m=n?.symbols.filter(u=>d.unchanged.includes(u.filePath))??[],g=[];for(let u of c)g.push(await ne(e,t,u));let v=new _().build(e,g),y=new P;for(let u of m)y.addSymbol(u);for(let u of v.allSymbols(e))y.addSymbol(u);let w=new Set(y.allSymbols(e).map(u=>u.id));for(let u of n?.edges??[])w.has(u.from)&&w.has(u.to)&&!c.includes(n.symbols.find(a=>a.id===u.from)?.filePath??"")&&!c.includes(n.symbols.find(a=>a.id===u.to)?.filePath??"")&&y.addEdge(u);for(let u of v.allEdges(e))y.addEdge(u);let x={version:1,projectId:e,updatedAt:new Date().toISOString(),files:Object.keys(l.files).length,symbols:y.allSymbols(e),edges:y.allEdges(e)};return await o.save(x),await r.save(l),{firstRun:i===null,scanned:Object.keys(l.files).length,parsed:c.length,added:d.added.length,modified:d.modified.length,deleted:d.deleted.length,unchanged:d.unchanged.length,symbols:x.symbols.length,edges:x.edges.length,saved:!0}}};async function dt(){let s=K(),e=new A().detect(),t=Z({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),r=new N(t,e.id,e.name,e.remote??e.name),o=await new D(r).index(e.id,e.rootPath);console.log({ok:!0,storage:r.name,...o})}dt().catch(s=>{console.error(s),process.exit(1)});
package/bundle/mcp.js CHANGED
@@ -1,7 +1,7 @@
1
- import"dotenv/config";import{existsSync as sr,readFileSync as nr}from"node:fs";import{homedir as ir}from"node:os";import{join as ar}from"node:path";function cr(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 lr(){let o=process.env.TOOLNET_GLOBAL_ENV??ar(ir(),".config","toolnet-memory",".env");if(!sr(o))return;let e=nr(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]=cr(r.slice(s+1)))}}lr();function q(o,e){return o===void 0?e:["1","true","yes","on"].includes(o.toLowerCase())}function A(o,e){if(!o)return e;let t=Number(o);return Number.isFinite(t)?t:e}function Ie(){return{memory:{autoCapture:q(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:q(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:q(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:q(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:A(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:A(process.env.MEMORY_RERANK_TOP,10),finalContext:A(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:A(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:A(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var pr={critical:100,high:75,normal:50,temporary:20};function Oe(o){return pr[o]}function _e(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 dr}from"node:crypto";import{existsSync as Ce,mkdirSync as mr,readFileSync as fr,renameSync as ur,writeFileSync as gr}from"node:fs";import{basename as hr,dirname as K,join as W,parse as De,resolve as I}from"node:path";var Ge=".toolnet",yr="project.json";function Sr(o){return dr("sha256").update(o).digest("hex").slice(0,16)}function we(o){return W(o,Ge,yr)}function br(o){return Ce(we(o))}function xr(o,e){let t=I(o),r=De(t).root;for(;;){if(br(t))return t;if(t===r||e&&t===I(e))break;let s=K(t);if(s===t)break;t=s}return null}function Cr(o){let e=I(o),t=De(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>Ce(W(e,n))))return e;if(e===t)break;let s=K(e);if(s===e)break;e=s}return I(o)}function wr(o){let e;try{e=JSON.parse(fr(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:K(K(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 Fe(o,e){let t=W(o,Ge);mr(t,{recursive:!0});let r=we(o),s=`${r}.tmp-${process.pid}`;gr(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),ur(s,r)}function $e(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 H=class{detect(e=process.cwd()){let t=I(e),r=Cr(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>Ce(W(r,p))),i=xr(t,n?r:void 0);if(i){let p=we(i),m=wr(p);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),Fe(i,m)),$e(m,i)}let a=new Date().toISOString(),c=hr(r),l={version:1,id:Sr(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return Fe(r,l),$e(l,r)}};import{randomUUID as kr}from"node:crypto";var vr=[{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}],V=class{scan(e){let t=[];for(let r of vr){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 k=class{scanner=new V;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 Er=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Pr=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(o){return new Set(o.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Pr.has(e)))}function jr(o,e){let t=ze(o),r=ze(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 Be(o){return new Set(o.tags.filter(e=>!Er.has(e.toLowerCase())))}var U=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=Be(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=Be(n);for(let c of s)if(a.has(c))return!0;return jr(e.content,n.content)>=.6})}};var Rr={critical:100,high:75,normal:50,temporary:20},Tr={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function qe(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 ve(o,e=Date.now()){return o.expiresAt?new Date(o.expiresAt).getTime()<=e:!1}function Mr(o){return!!o.metadata?.supersededBy}function Ee(o,e=Date.now()){return!ve(o,e)&&!Mr(o)}function O(o,e=Date.now()){if(!Ee(o,e))return 0;let t=Rr[o.importance];if(o.importance==="critical")return t;let r=Tr[o.type]??180,n=Math.max(0,e-new Date(o.updatedAt).getTime())/864e5,i=Math.pow(.5,n/r);return t*i}var J=class{memories=new Map;sanitizer=new k;conflicts=new U;remember(e){let t=new Date().toISOString(),r=this.sanitizer.sanitize(e.content.trim()).text,s=e.importance??_e(e.type,r),n={id:kr(),projectId:e.projectId,type:e.type,content:r,importance:s,importanceScore:Oe(s),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??qe(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=>Ee(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=O(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=O(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&&ve(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 L(o){return o.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var Y=class{score(e,t){let r=L(e),s=L([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 Ke(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 He(o){return O(o)/100}var Lr={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function We(o){return Lr[o]??.4}var Q=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 Z=class{bm25=new Y;analyzer=new Q;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=Ke(c),m=He(c),d=We(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 X=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 ee=class{constructor(e){this.memory=e}memory;searcher=new Z;contextBuilder=new X;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 te=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=>Nr(n))}};function Nr(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 Ar}from"node:crypto";var re=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=Ar("sha256").update(s).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return Ir(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function Ir(o){let e=Math.sqrt(o.reduce((t,r)=>t+r*r,0));return e===0?o:o.map(t=>t/e)}var Pe=class{constructor(e,t=new re){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 Ve(){let o=process.env.HF_TOKEN,e=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",t=o?new te({token:o,model:e}):null;return new Pe(t)}import Hs from"typescript";var N=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 oe(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 se=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 g=l.depth+1;n.push({symbol:f,depth:g}),a.push({id:d,depth:g})}}return n}};var ne=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 ie=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 $r(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 ae=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=>$r(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 Dr={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function Gr(o){return o>=30?"CRITICAL":o>=16?"HIGH":o>=6?"MEDIUM":"LOW"}function Ue(o){let e=o.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var ce=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 g=s.filter(h=>h.to===f.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(h.type));for(let h of g){if(m.has(h.from))continue;m.add(h.from);let C=this.graph.getSymbol(h.from);if(!C)continue;let w=f.depth+1,B=`${p.symbol.id}:${C.id}`;n.set(B,{symbol:C,relation:h.type,depth:w,sourceSymbolId:p.symbol.id});let R=Dr[h.type]??1;i+=Math.max(1,R-(w-1)),d.push({id:C.id,depth:w})}}}let a=[...n.values()].sort((p,m)=>p.depth-m.depth),c=[...new Set(a.map(p=>p.symbol.filePath))],l=c.filter(Ue);return l.length===0&&l.push(...c.filter(p=>!Ue(p)).slice(0,10)),{risk:Gr(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:l}}};import{execFile as zr}from"node:child_process";import{promisify as Br}from"node:util";var je=Br(zr);function qr(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 Kr(o){return o.startsWith("A")?"added":o.startsWith("D")?"deleted":o.startsWith("R")?"renamed":"modified"}async function Je(o){let e="";try{e=(await je("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 je("git",["diff","HEAD","--unified=0","--",i],{cwd:o,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:Kr(s),ranges:qr(a)})}try{let r=await je("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 le=class{constructor(e){this.graph=e;this.mapper=new ae(e),this.blast=new ce(e)}graph;mapper;blast;async analyzeGitDiff(e,t,r={}){let s=await Je(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 _=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 Hr}from"node:crypto";import{readFile as Wr}from"node:fs/promises";import{join as Vr}from"node:path";function Ye(o){return Hr("sha256").update(o).digest("hex")}var pe=class{sanitizer=new k;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 Wr(Vr(t,l),"utf8")}catch{continue}let d=m.split(/\r?\n/),f=p.filter(g=>g.type!=="file"&&typeof g.startLine=="number"&&typeof g.endLine=="number");if(f.length>0)for(let g of f)c.push(...this.chunkRange({projectId:e,filePath:l,lines:d,symbol:g,startLine:g.startLine,endLine:g.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),g=s.slice(m-1,f).join(`
5
- `).trim();if(g){let h=this.sanitizer.sanitize(g).text,C=Ye(h),w=[t,r,n?.id??"file",String(d),C].join(":");p.push({id:Ye(w).slice(0,32),projectId:t,filePath:r,symbolId:n?.id,symbolName:n?.qualifiedName??n?.name,symbolType:n?.type,startLine:m,endLine:f,content:h,contentHash:C})}if(f>=l)break;m=f-a+1,d++}return p}};var de=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 me=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 fe=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=Ur(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 Ur(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 Qe(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 ue=class{constructor(e){this.options=e}options;vectors=new fe;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:r,embeddings:s,graph:n,model:i}=this.options,a=new de(r),c=new me(r),l=await new pe().build(e,t,n.allSymbols(e));this.chunks.clear();for(let y of l)this.chunks.set(y.id,y);let p=await a.load(e),m=!p||p.chunks.length!==l.length||p.chunks.some(y=>!this.chunks.has(y.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 g=new Set(l.map(y=>y.id)),h=0;for(let y of this.vectors.exportProject(e))g.has(y.id)||this.vectors.remove(y.id)&&h++;let C=l.filter(y=>{let T=this.vectors.get(y.id);return T?T.metadata?.contentHash!==y.contentHash:!0}),w=0,B=8,R=this.vectors.exportProject(e)[0]?.vector.length;for(let y=0;y<C.length;y+=B){let T=C.slice(y,y+B),rr=T.map(x=>[`file: ${x.filePath}`,x.symbolName?`symbol: ${x.symbolName}`:"",x.symbolType?`type: ${x.symbolType}`:"",x.content].filter(Boolean).join(`
6
- `)),or=await s.embedMany(rr);for(let x=0;x<T.length;x++){let P=T[x],M=or[x];if(!(!P||!M||M.length===0)){if(R===void 0&&(R=M.length),M.length!==R){console.warn(`[code-semantic] skip dimension mismatch: ${M.length} != ${R}`);continue}this.vectors.upsert({id:P.id,projectId:e,vector:M,metadata:{contentHash:P.contentHash,filePath:P.filePath,symbolName:P.symbolName,symbolType:P.symbolType,startLine:P.startLine,endLine:P.endLine}}),w++}}}let xe=this.vectors.exportProject(e),Ae=w>0||h>0||!d||d.model!==i;return Ae&&await c.save({version:1,projectId:e,model:i,dimensions:xe[0]?.vector.length??R??0,updatedAt:new Date().toISOString(),records:xe}),{chunks:l.length,vectorsLoaded:f,vectorsIndexed:w,vectorsRemoved:h,totalVectors:xe.length,savedChunks:m,savedVectors:Ae}}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(L(e)),i=[];for(let a of s){let c=this.chunks.get(a.id);if(!c)continue;let l=new Set(L([c.filePath,c.symbolName??"",c.symbolType??"",c.content].join(" "))),p=0;for(let h of n)l.has(h)&&p++;let m=n.size===0?0:p/n.size,d=Math.max(0,a.score),f=Qe(c.filePath,e),g=(d*.75+m*.25)*f;i.push({chunk:c,score:g,vectorScore:d,lexicalScore:m})}return i.sort((a,c)=>c.score-a.score).slice(0,t)}size(){return this.chunks.size}};import di from"typescript";import v from"typescript";var yi=new Set([v.SyntaxKind.EqualsToken,v.SyntaxKind.PlusEqualsToken,v.SyntaxKind.MinusEqualsToken,v.SyntaxKind.AsteriskEqualsToken,v.SyntaxKind.SlashEqualsToken,v.SyntaxKind.PercentEqualsToken,v.SyntaxKind.QuestionQuestionEqualsToken,v.SyntaxKind.AmpersandAmpersandEqualsToken,v.SyntaxKind.BarBarEqualsToken]);function Jr(o){return o.replaceAll("\\","/").toLowerCase()}var F=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=Jr(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 ge=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),Ze=new Set(["CALLS","CALL_REFERENCE"]),b=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,Ze)}callees(e,t){return this.relatedOutgoing(e,t,Ze)}dependents(e,t){return this.relatedIncoming(e,t,ge)}dependencies(e,t){return this.relatedOutgoing(e,t,ge)}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=>ge.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=>ge.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 Xe=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function Re(o){return o.replaceAll("\\","/").toLowerCase()}function Yr(o){let e=Re(o);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function Qr(o){let e=Re(o.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var $=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),r=this.graph.allEdges(e),s=new Set(new F(this.graph).detect(e).map(i=>i.symbolId)),n=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||Yr(i.filePath)||s.has(i.id)||Qr(i)||r.filter(f=>f.to===i.id&&Xe.has(f.type)).length>0)continue;let c=r.filter(f=>f.from===i.id&&Xe.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")),Re(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 Zr=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),D=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),r=this.graph.allEdges(e).filter(i=>Zr.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 go}from"node:os";import{join as ho}from"node:path";import{DeleteObjectCommand as Xr,GetObjectCommand as eo,HeadObjectCommand as to,ListObjectsV2Command as ro,PutObjectCommand as oo,S3Client as so}from"@aws-sdk/client-s3";import{getSignedUrl as no}from"@aws-sdk/s3-request-presigner";var he=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new so({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 oo({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await no(this.client,new eo({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 to({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 Xr({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new ro({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 et,mkdir as io,readFile as ao,readdir as co,rm as lo,stat as tt,writeFile as po}from"node:fs/promises";import{dirname as mo,join as fo,relative as rt,resolve as uo}from"node:path";var G=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return uo(this.root,t)}async put(e,t){let r=this.path(e);await io(mo(r),{recursive:!0}),await po(r,t)}async get(e){try{return await ao(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 et(this.path(e)),!0}catch{return!1}}async delete(e){await lo(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await et(t)}catch{return r}let s=async i=>{let a=await co(i,{withFileTypes:!0});for(let c of a){let l=fo(i,c.name);if(c.isDirectory()){await s(l);continue}let p=await tt(l);r.push({key:rt(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},n=await tt(t);return n.isDirectory()?await s(t):r.push({key:rt(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};function ot(o){let e=o.localRoot??ho(go(),".toolnet-memory","storage");if(o.provider==="huggingface"){let t=o.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new he({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new G(e))}return new G(e)}var ye=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 yo(o){return new Promise(e=>setTimeout(e,o))}async function st(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 yo(c+l)}throw n}var So=new Set(["put","get","getText","delete","list"]);function nt(o,e={}){return new Proxy(o,{get(t,r){let s=Reflect.get(t,r,t);return typeof s!="function"?s:So.has(r)?(...n)=>st(()=>Promise.resolve(s.apply(t,n)),e):s.bind(t)}})}function it(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 at(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 Se=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=it(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=at(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 jo}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Ro}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as ct}from"zod";var lt={query:ct.string(),limit:ct.number().int().min(1).max(20).optional()};async function pt(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}from"zod";var dt={type:z.enum(["activity","decision","rule","todo","summary"]),content:z.string().min(1),tags:z.array(z.string()).optional(),importance:z.enum(["critical","high","normal","temporary"]).optional()};async function mt(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 bo}from"zod";var ft={id:bo.string().min(1)};async function ut(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 xo}from"zod";var gt={name:xo.string().min(1)};async function ht(o,e){return o.graph.findByName(o.project.id,e.name)}import{z as Co}from"zod";function E(o,e){let t=o.graph.getSymbol(e);if(t&&t.projectId===o.project.id)return t;let r=new b(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 S(o){return{id:o.id,name:o.name,qualifiedName:o.qualifiedName,type:o.type,filePath:o.filePath,startLine:o.startLine,endLine:o.endLine}}var yt={symbolId:Co.string().min(1)};async function St(o,e){let t=E(o,e.symbolId);if(!t)return{found:!1,query:e.symbolId,callers:[]};let s=new b(o.graph).callers(o.project.id,t.id);return{found:!0,symbol:S(t),count:s.length,callers:s.map(S)}}import{z as bt}from"zod";var xt={query:bt.string().min(1),limit:bt.number().int().min(1).max(50).optional()};async function Ct(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 wt}from"zod";var vt={query:wt.string().optional(),memoryLimit:wt.number().int().min(1).max(20).optional()};async function Et(o,e){let t=oe(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 vo}from"zod";var wo=["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"],j=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 wo){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 Pt={reason:vo.string().optional()};async function jt(o,e){if(!o.storage)throw new Error("Storage unavailable");return new j(o.storage).create(o.project.id,e.reason??"manual-mcp")}async function Rt(o){if(!o.storage)throw new Error("Storage unavailable");return new j(o.storage).list(o.project.id)}import{z as Eo}from"zod";var Tt={snapshotId:Eo.string().min(1)};async function Mt(o,e){if(!o.storage)throw new Error("Storage unavailable");let t=new j(o.storage);return await t.create(o.project.id,"before-rollback"),t.restore(o.project.id,e.snapshotId)}import{z as Te}from"zod";var kt={symbolId:Te.string().min(1),direction:Te.enum(["callers","callees"]).optional(),depth:Te.number().int().min(1).max(10).optional()};async function Lt(o,e){let t=new se(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 Nt}from"zod";var At={symbolId:Nt.string().min(1),depth:Nt.number().int().min(1).max(10).optional()};async function It(o,e){let t=o.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let s=new ie(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 Ot(o){return{project:{id:o.project.id,name:o.project.name,rootPath:o.project.rootPath},architecture:oe(o.graph,o.project.id)}}import{z as _t}from"zod";var Ft={filePath:_t.string().min(1),direction:_t.enum(["dependencies","dependents","both"]).optional()};async function $t(o,e){let r=new D(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 Dt}from"zod";var Gt={query:Dt.string().min(1),limit:Dt.number().int().min(1).max(20).optional()};async function zt(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 Me}from"zod";var Bt={mode:Me.enum(["git_diff","file"]).optional(),filePath:Me.string().optional(),depth:Me.number().int().min(1).max(10).optional()};async function qt(o,e){let t=new le(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 Po}from"zod";var Kt={symbol:Po.string().min(1)};async function Ht(o,e){let t=E(o,e.symbol);if(!t)return{found:!1,query:e.symbol,dependents:[]};let s=new b(o.graph).dependents(o.project.id,t.id);return{found:!0,symbol:S(t),count:s.length,dependents:s.map(S)}}import{z as ke}from"zod";var Wt={from:ke.string().min(1),to:ke.string().min(1),maxDepth:ke.number().int().min(1).max(30).optional()};async function Vt(o,e){let t=E(o,e.from),r=E(o,e.to);if(!t||!r)return{found:!1,fromFound:!!t,toFound:!!r,path:[],edges:[]};let n=new b(o.graph).shortestPath(o.project.id,t.id,r.id,e.maxDepth??12);return{found:n.found,distance:n.distance,from:S(t),to:S(r),path:n.symbols.map(S),edges:n.edges.map(i=>({id:i.id,type:i.type,from:i.from,to:i.to,metadata:i.metadata}))}}import{z as Le}from"zod";var Ut={symbol:Le.string().min(1),depth:Le.number().int().min(1).max(5).optional(),limit:Le.number().int().min(1).max(200).optional()};async function Jt(o,e){let t=E(o,e.symbol);if(!t)return{found:!1,query:e.symbol};let s=new b(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:S(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:S(i.symbol)})),outgoing:s.outgoing.slice(0,n).map(i=>({depth:i.depth,via:i.via?.type,symbol:S(i.symbol)}))}}import{z as Ne}from"zod";var Qt={confidence:Ne.enum(["high","medium","low","all"]).optional(),filePath:Ne.string().min(1).optional(),limit:Ne.number().int().min(1).max(500).optional()},Yt={high:3,medium:2,low:1};async function Zt(o,e){let r=new $(o.graph).analyze(o.project.id);if(e.confidence&&e.confidence!=="all"){let i=Yt[e.confidence];r=r.filter(a=>Yt[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 u(o){return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}function To(o){let e=new jo({name:"toolnet-memory",version:"0.1.0"});return e.tool("memory_search","Search relevant long-term memory for the current project.",lt,async t=>u(await pt(o,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",dt,async t=>u(await mt(o,t))),e.tool("memory_forget","Delete a memory by id.",ft,async t=>u(await ut(o,t))),e.tool("find_symbol","Find code symbols by exact name.",gt,async t=>u(await ht(o,t))),e.tool("find_callers","Find functions or methods calling a symbol.",yt,async t=>u(await St(o,t))),e.tool("code_search","Search indexed code symbols and files.",xt,async t=>u(await Ct(o,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",vt,async t=>u(await Et(o,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",kt,async t=>u(await Lt(o,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",At,async t=>u(await It(o,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>u(await Ot(o))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",Ft,async t=>u(await $t(o,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",Gt,async t=>u(await zt(o,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",Pt,async t=>u(await jt(o,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>u(await Rt(o))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",Tt,async t=>u(await Mt(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.",Bt,async t=>u(await qt(o,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",Kt,async t=>u(await Ht(o,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",Wt,async t=>u(await Vt(o,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",Ut,async t=>u(await Jt(o,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",Qt,async t=>u(await Zt(o,t))),e}async function Xt(o){let e=To(o),t=new Ro;await e.connect(t)}import{closeSync as Mo,mkdirSync as ko,openSync as Lo,readFileSync as No,unlinkSync as er,writeFileSync as Ao}from"node:fs";import{tmpdir as Io}from"node:os";import{join as tr}from"node:path";function Oo(o){try{return process.kill(o,0),!0}catch(e){return e?.code==="EPERM"}}var be=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=tr(Io(),"toolnet-memory-locks");ko(t,{recursive:!0});let r=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=tr(t,`${r}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Lo(this.path,"wx");Ao(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),Mo(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(No(this.path,"utf8"));Number.isInteger(s.pid)&&Oo(s.pid)&&(r=!1)}catch{r=!0}if(!r)throw new Error("ToolNet Memory is already running for this project");try{er(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{er(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};async function _o(){let o=Ie(),e=new H().detect(),t=ot({provider:o.storage.provider,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),r=nt(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),s=new Se(r,e.id,e.name,e.remote??e.name),n=new be(e.id);await n.acquire();let i=()=>{n.release().finally(()=>process.exit(0))};process.once("SIGINT",i),process.once("SIGTERM",i);let a=new J,c=new ye(s);a.importRecords(await c.load(e.id));let l=new ee(a),p=new N,m=await new _(s).load(e.id);m&&p.import(m.symbols,m.edges);let d=new ne(p),f=new ue({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:s,embeddings:Ve(),graph:p});await f.initialize(),await Xt({project:e,memory:a,retrieval:l,graph:p,references:d,codeSemantic:f,memoryStore:c,storage:s})}_o().catch(o=>{console.error(o),process.exit(1)});
1
+ import"dotenv/config";import{existsSync as ir,readFileSync as ar}from"node:fs";import{homedir as cr}from"node:os";import{join as lr}from"node:path";function pr(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 dr(){let o=process.env.TOOLNET_GLOBAL_ENV??lr(cr(),".config","toolnet-memory",".env");if(!ir(o))return;let e=ar(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]=pr(r.slice(s+1)))}}dr();function H(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:H(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:H(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:H(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:H(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",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 mr={critical:100,high:75,normal:50,temporary:20};function Fe(o){return mr[o]}function $e(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 fr}from"node:crypto";import{existsSync as ve,mkdirSync as ur,readFileSync as gr,renameSync as hr,writeFileSync as yr}from"node:fs";import{basename as Sr,dirname as W,join as U,parse as ze,resolve as _}from"node:path";var Be=".toolnet",br="project.json";function xr(o){return fr("sha256").update(o).digest("hex").slice(0,16)}function Ee(o){return U(o,Be,br)}function Cr(o){return ve(Ee(o))}function wr(o,e){let t=_(o),r=ze(t).root;for(;;){if(Cr(t))return t;if(t===r||e&&t===_(e))break;let s=W(t);if(s===t)break;t=s}return null}function vr(o){let e=_(o),t=ze(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>ve(U(e,n))))return e;if(e===t)break;let s=W(e);if(s===e)break;e=s}return _(o)}function Er(o){let e;try{e=JSON.parse(gr(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:W(W(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 De(o,e){let t=U(o,Be);ur(t,{recursive:!0});let r=Ee(o),s=`${r}.tmp-${process.pid}`;yr(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),hr(s,r)}function Ge(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=_(e),r=vr(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>ve(U(r,p))),i=wr(t,n?r:void 0);if(i){let p=Ee(i),m=Er(p);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),De(i,m)),Ge(m,i)}let a=new Date().toISOString(),c=Sr(r),l={version:1,id:xr(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return De(r,l),Ge(l,r)}};import{randomUUID as Nr}from"node:crypto";var Pr=[{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}],J=class{scan(e){let t=[];for(let r of Pr){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 N=class{scanner=new J;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 jr=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Rr=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 qe(o){return new Set(o.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Rr.has(e)))}function Tr(o,e){let t=qe(o),r=qe(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 Ke(o){return new Set(o.tags.filter(e=>!jr.has(e.toLowerCase())))}var Y=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=Ke(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=Ke(n);for(let c of s)if(a.has(c))return!0;return Tr(e.content,n.content)>=.6})}};var Mr={critical:100,high:75,normal:50,temporary:20},kr={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function He(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 Pe(o,e=Date.now()){return o.expiresAt?new Date(o.expiresAt).getTime()<=e:!1}function Lr(o){return!!o.metadata?.supersededBy}function je(o,e=Date.now()){return!Pe(o,e)&&!Lr(o)}function F(o,e=Date.now()){if(!je(o,e))return 0;let t=Mr[o.importance];if(o.importance==="critical")return t;let r=kr[o.type]??180,n=Math.max(0,e-new Date(o.updatedAt).getTime())/864e5,i=Math.pow(.5,n/r);return t*i}var Q=class{memories=new Map;sanitizer=new N;conflicts=new Y;remember(e){let t=new Date().toISOString(),r=this.sanitizer.sanitize(e.content.trim()).text,s=e.importance??$e(e.type,r),n={id:Nr(),projectId:e.projectId,type:e.type,content:r,importance:s,importanceScore:Fe(s),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??He(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=>je(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=F(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=F(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&&Pe(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 A(o){return o.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var Z=class{score(e,t){let r=A(e),s=A([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 We(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 Ve(o){return F(o)/100}var Ar={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function Ue(o){return Ar[o]??.4}var X=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 ee=class{bm25=new Z;analyzer=new X;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=We(c),m=Ve(c),d=Ue(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 te=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 re=class{constructor(e){this.memory=e}memory;searcher=new ee;contextBuilder=new te;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 oe=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=>Ir(n))}};function Ir(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 Or}from"node:crypto";var se=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=Or("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 se){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 Je(){let o=process.env.HF_TOKEN,e=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",t=o?new oe({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 ne(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 ie=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 ae=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 ce=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 Gr(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 le=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=>Gr(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 zr={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function Br(o){return o>=30?"CRITICAL":o>=16?"HIGH":o>=6?"MEDIUM":"LOW"}function Ye(o){let e=o.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var pe=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,K=`${p.symbol.id}:${E.id}`;n.set(K,{symbol:E,relation:y.type,depth:P,sourceSymbolId:p.symbol.id});let M=zr[y.type]??1;i+=Math.max(1,M-(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(Ye);return l.length===0&&l.push(...c.filter(p=>!Ye(p)).slice(0,10)),{risk:Br(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:l}}};import{execFile as qr}from"node:child_process";import{promisify as Kr}from"node:util";var Te=Kr(qr);function Hr(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 Wr(o){return o.startsWith("A")?"added":o.startsWith("D")?"deleted":o.startsWith("R")?"renamed":"modified"}async function Qe(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:Wr(s),ranges:Hr(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 de=class{constructor(e){this.graph=e;this.mapper=new le(e),this.blast=new pe(e)}graph;mapper;blast;async analyzeGitDiff(e,t,r={}){let s=await Qe(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 $=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 Vr}from"node:crypto";import{readFile as Ur}from"node:fs/promises";import{join as Jr}from"node:path";function Ze(o){return Vr("sha256").update(o).digest("hex")}var me=class{sanitizer=new N;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 Ur(Jr(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=Ze(y),P=[t,r,n?.id??"file",String(d),E].join(":");p.push({id:Ze(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 fe=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 ue=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 ge=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=Yr(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 Yr(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 Xe(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 he=class{constructor(e){this.options=e}options;vectors=new ge;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:r,embeddings:s,graph:n,model:i}=this.options,a=new fe(r),c=new ue(r),l=await new me().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 k=this.vectors.get(S.id);return k?k.metadata?.contentHash!==S.contentHash:!0}),P=0,K=8,M=this.vectors.exportProject(e)[0]?.vector.length;for(let S=0;S<E.length;S+=K){let k=E.slice(S,S+K),sr=k.map(v=>[`file: ${v.filePath}`,v.symbolName?`symbol: ${v.symbolName}`:"",v.symbolType?`type: ${v.symbolType}`:"",v.content].filter(Boolean).join(`
6
+ `)),nr=await s.embedMany(sr);for(let v=0;v<k.length;v++){let R=k[v],L=nr[v];if(!(!R||!L||L.length===0)){if(M===void 0&&(M=L.length),L.length!==M){console.warn(`[code-semantic] skip dimension mismatch: ${L.length} != ${M}`);continue}this.vectors.upsert({id:R.id,projectId:e,vector:L,metadata:{contentHash:R.contentHash,filePath:R.filePath,symbolName:R.symbolName,symbolType:R.symbolType,startLine:R.startLine,endLine:R.endLine}}),P++}}}let we=this.vectors.exportProject(e),Oe=P>0||y>0||!d||d.model!==i;return Oe&&await c.save({version:1,projectId:e,model:i,dimensions:we[0]?.vector.length??M??0,updatedAt:new Date().toISOString(),records:we}),{chunks:l.length,vectorsLoaded:f,vectorsIndexed:P,vectorsRemoved:y,totalVectors:we.length,savedChunks:m,savedVectors:Oe}}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(A(e)),i=[];for(let a of s){let c=this.chunks.get(a.id);if(!c)continue;let l=new Set(A([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=Xe(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 ui=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 Qr(o){return o.replaceAll("\\","/").toLowerCase()}var D=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=Qr(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 ye=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),et=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,et)}callees(e,t){return this.relatedOutgoing(e,t,et)}dependents(e,t){return this.relatedIncoming(e,t,ye)}dependencies(e,t){return this.relatedOutgoing(e,t,ye)}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=>ye.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=>ye.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 tt=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function Me(o){return o.replaceAll("\\","/").toLowerCase()}function Zr(o){let e=Me(o);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function Xr(o){let e=Me(o.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var G=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),r=this.graph.allEdges(e),s=new Set(new D(this.graph).detect(e).map(i=>i.symbolId)),n=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||Zr(i.filePath)||s.has(i.id)||Xr(i)||r.filter(f=>f.to===i.id&&tt.has(f.type)).length>0)continue;let c=r.filter(f=>f.from===i.id&&tt.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 eo=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),r=this.graph.allEdges(e).filter(i=>eo.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 yo}from"node:os";import{join as So}from"node:path";import{DeleteObjectCommand as to,GetObjectCommand as ro,HeadObjectCommand as oo,ListObjectsV2Command as so,PutObjectCommand as no,S3Client as io}from"@aws-sdk/client-s3";import{getSignedUrl as ao}from"@aws-sdk/s3-request-presigner";var Se=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new io({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 no({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await ao(this.client,new ro({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 oo({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 to({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new so({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 rt,mkdir as co,readFile as lo,readdir as po,rm as mo,stat as ot,writeFile as fo}from"node:fs/promises";import{dirname as uo,join as go,relative as st,resolve as ho}from"node:path";var B=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return ho(this.root,t)}async put(e,t){let r=this.path(e);await co(uo(r),{recursive:!0}),await fo(r,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 rt(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),r=[];try{await rt(t)}catch{return r}let s=async i=>{let a=await po(i,{withFileTypes:!0});for(let c of a){let l=go(i,c.name);if(c.isDirectory()){await s(l);continue}let p=await ot(l);r.push({key:st(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},n=await ot(t);return n.isDirectory()?await s(t):r.push({key:st(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};function nt(o){let e=o.localRoot??So(yo(),".toolnet-memory","storage");if(o.provider==="huggingface"){let t=o.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new Se({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new B(e))}return new B(e)}var be=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 bo(o){return new Promise(e=>setTimeout(e,o))}async function it(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 bo(c+l)}throw n}var xo=new Set(["put","get","getText","delete","list"]);function at(o,e={}){return new Proxy(o,{get(t,r){let s=Reflect.get(t,r,t);return typeof s!="function"?s:xo.has(r)?(...n)=>it(()=>Promise.resolve(s.apply(t,n)),e):s.bind(t)}})}function ct(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 lt(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 xe=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=ct(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=lt(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 To}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Mo}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as pt}from"zod";var dt={query:pt.string(),limit:pt.number().int().min(1).max(20).optional()};async function mt(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 q}from"zod";var ft={type:q.enum(["activity","decision","rule","todo","summary"]),content:q.string().min(1),tags:q.array(q.string()).optional(),importance:q.enum(["critical","high","normal","temporary"]).optional()};async function ut(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 Co}from"zod";var gt={id:Co.string().min(1)};async function ht(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 wo}from"zod";var yt={name:wo.string().min(1)};async function St(o,e){return o.graph.findByName(o.project.id,e.name)}import{z as vo}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 bt={symbolId:vo.string().min(1)};async function xt(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 Ct}from"zod";var wt={query:Ct.string().min(1),limit:Ct.number().int().min(1).max(50).optional()};async function vt(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 Et}from"zod";var Pt={query:Et.string().optional(),memoryLimit:Et.number().int().min(1).max(20).optional()};async function jt(o,e){let t=ne(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 Po}from"zod";var Eo=["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"],T=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 Eo){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 Rt={reason:Po.string().optional()};async function Tt(o,e){if(!o.storage)throw new Error("Storage unavailable");return new T(o.storage).create(o.project.id,e.reason??"manual-mcp")}async function Mt(o){if(!o.storage)throw new Error("Storage unavailable");return new T(o.storage).list(o.project.id)}import{z as jo}from"zod";var kt={snapshotId:jo.string().min(1)};async function Lt(o,e){if(!o.storage)throw new Error("Storage unavailable");let t=new T(o.storage);return await t.create(o.project.id,"before-rollback"),t.restore(o.project.id,e.snapshotId)}import{z as ke}from"zod";var Nt={symbolId:ke.string().min(1),direction:ke.enum(["callers","callees"]).optional(),depth:ke.number().int().min(1).max(10).optional()};async function At(o,e){let t=new ie(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 It}from"zod";var Ot={symbolId:It.string().min(1),depth:It.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 ce(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 Ft(o){return{project:{id:o.project.id,name:o.project.name,rootPath:o.project.rootPath},architecture:ne(o.graph,o.project.id)}}import{z as $t}from"zod";var Dt={filePath:$t.string().min(1),direction:$t.enum(["dependencies","dependents","both"]).optional()};async function Gt(o,e){let r=new z(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 zt}from"zod";var Bt={query:zt.string().min(1),limit:zt.number().int().min(1).max(20).optional()};async function qt(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 Le}from"zod";var Kt={mode:Le.enum(["git_diff","file"]).optional(),filePath:Le.string().optional(),depth:Le.number().int().min(1).max(10).optional()};async function Ht(o,e){let t=new de(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 Ro}from"zod";var Wt={symbol:Ro.string().min(1)};async function Vt(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 Ne}from"zod";var Ut={from:Ne.string().min(1),to:Ne.string().min(1),maxDepth:Ne.number().int().min(1).max(30).optional()};async function Jt(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 Ae}from"zod";var Yt={symbol:Ae.string().min(1),depth:Ae.number().int().min(1).max(5).optional(),limit:Ae.number().int().min(1).max(200).optional()};async function Qt(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 Ie}from"zod";var Xt={confidence:Ie.enum(["high","medium","low","all"]).optional(),filePath:Ie.string().min(1).optional(),limit:Ie.number().int().min(1).max(500).optional()},Zt={high:3,medium:2,low:1};async function er(o,e){let r=new G(o.graph).analyze(o.project.id);if(e.confidence&&e.confidence!=="all"){let i=Zt[e.confidence];r=r.filter(a=>Zt[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 ko(o){let e=new To({name:"toolnet-memory",version:"0.1.0"});return e.tool("memory_search","Search relevant long-term memory for the current project.",dt,async t=>g(await mt(o,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",ft,async t=>g(await ut(o,t))),e.tool("memory_forget","Delete a memory by id.",gt,async t=>g(await ht(o,t))),e.tool("find_symbol","Find code symbols by exact name.",yt,async t=>g(await St(o,t))),e.tool("find_callers","Find functions or methods calling a symbol.",bt,async t=>g(await xt(o,t))),e.tool("code_search","Search indexed code symbols and files.",wt,async t=>g(await vt(o,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",Pt,async t=>g(await jt(o,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",Nt,async t=>g(await At(o,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",Ot,async t=>g(await _t(o,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>g(await Ft(o))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",Dt,async t=>g(await Gt(o,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",Bt,async t=>g(await qt(o,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",Rt,async t=>g(await Tt(o,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>g(await Mt(o))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",kt,async t=>g(await Lt(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.",Kt,async t=>g(await Ht(o,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",Wt,async t=>g(await Vt(o,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",Ut,async t=>g(await Jt(o,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",Yt,async t=>g(await Qt(o,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",Xt,async t=>g(await er(o,t))),e}async function tr(o){let e=ko(o),t=new Mo;await e.connect(t)}import{closeSync as Lo,mkdirSync as No,openSync as Ao,readFileSync as Io,unlinkSync as rr,writeFileSync as Oo}from"node:fs";import{tmpdir as _o}from"node:os";import{join as or}from"node:path";function Fo(o){try{return process.kill(o,0),!0}catch(e){return e?.code==="EPERM"}}var Ce=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=or(_o(),"toolnet-memory-locks");No(t,{recursive:!0});let r=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=or(t,`${r}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Ao(this.path,"wx");Oo(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),Lo(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(Io(this.path,"utf8"));Number.isInteger(s.pid)&&Fo(s.pid)&&(r=!1)}catch{r=!0}if(!r)throw new Error("ToolNet Memory is already running for this project");try{rr(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{rr(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};async function $o(){let o=_e(),e=new V().detect(),t=nt({provider:o.storage.provider,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),r=at(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),s=new xe(r,e.id,e.name,e.remote??e.name),n=new Ce(e.id);await n.acquire();let i=()=>{n.release().finally(()=>process.exit(0))};process.once("SIGINT",i),process.once("SIGTERM",i);let a=new Q,c=new be(s);a.importRecords(await c.load(e.id));let l=new re(a),p=new I,m=await new $(s).load(e.id);m&&p.import(m.symbols,m.edges);let d=new ae(p),f=new he({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:s,embeddings:Je(),graph:p});await f.initialize(),await tr({project:e,memory:a,retrieval:l,graph:p,references:d,codeSemantic:f,memoryStore:c,storage:s})}$o().catch(o=>{console.error(o),process.exit(1)});