toolnet-memory 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import"dotenv/config";import{existsSync as Se,readFileSync as be}from"node:fs";import{homedir as xe}from"node:os";import{join as Ee}from"node:path";function Ce(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 we(){let s=process.env.TOOLNET_GLOBAL_ENV??Ee(xe(),".config","toolnet-memory",".env");if(!Se(s))return;let e=be(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 n=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)&&process.env[n]===void 0&&(process.env[n]=Ce(r.slice(o+1)))}}we();function R(s,e){return s===void 0?e:["1","true","yes","on"].includes(s.toLowerCase())}function j(s,e){if(!s)return e;let t=Number(s);return Number.isFinite(t)?t:e}function re(){return{memory:{autoCapture:R(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:R(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:R(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:R(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:j(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:j(process.env.MEMORY_RERANK_TOP,10),finalContext:j(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:j(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:R(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:j(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ve}from"node:crypto";import{existsSync as q,mkdirSync as Pe,readFileSync as ke,renameSync as Te,writeFileSync as Re}from"node:fs";import{basename as je,dirname as O,join as F,parse as ne,resolve as A}from"node:path";var ie=".toolnet",Ae="project.json";function Le(s){return ve("sha256").update(s).digest("hex").slice(0,16)}function J(s){return F(s,ie,Ae)}function Ne(s){return q(J(s))}function Me(s,e){let t=A(s),r=ne(t).root;for(;;){if(Ne(t))return t;if(t===r||e&&t===A(e))break;let o=O(t);if(o===t)break;t=o}return null}function Ie(s){let e=A(s),t=ne(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>q(F(e,n))))return e;if(e===t)break;let o=O(e);if(o===e)break;e=o}return A(s)}function Oe(s){let e;try{e=JSON.parse(ke(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:O(O(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 se(s,e){let t=F(s,ie);Pe(t,{recursive:!0});let r=J(s),o=`${r}.tmp-${process.pid}`;Re(o,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Te(o,r)}function oe(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 _=class{detect(e=process.cwd()){let t=A(e),r=Ie(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>q(F(r,d))),i=Me(t,n?r:void 0);if(i){let d=J(i),m=Oe(d);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),se(i,m)),oe(m,i)}let c=new Date().toISOString(),l=je(r),a={version:1,id:Le(r),name:l,remote:l,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return se(r,a),oe(a,r)}};var _e=[{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}],$=class{scan(e){let t=[];for(let r of _e){let o=new RegExp(r.regex.source,r.regex.flags);for(let n of e.matchAll(o))t.push({type:r.type,value:n[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var L=class{scanner=new $;sanitize(e){let t=e,r=this.scanner.scan(e),o=new Set;for(let n of r)o.add(n.type),t=t.split(n.value).join(`[REDACTED:${n.type}]`);return{text:t,redacted:r.length,secretTypes:[...o]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[r,o]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(o)}return t}return e}};import{homedir as nt}from"node:os";import{join as it}from"node:path";import{DeleteObjectCommand as Fe,GetObjectCommand as $e,HeadObjectCommand as De,ListObjectsV2Command as Ge,PutObjectCommand as Ke,S3Client as ze}from"@aws-sdk/client-s3";import{getSignedUrl as Be}from"@aws-sdk/s3-request-presigner";var D=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new ze({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 Ke({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await Be(this.client,new $e({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 De({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 Fe({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new Ge({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};import{access as ae,mkdir as He,readFile as We,readdir as Ue,rm as Ve,stat as ce,writeFile as Ye}from"node:fs/promises";import{dirname as qe,join as Je,relative as le,resolve as Qe}from"node:path";var N=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Qe(this.root,t)}async put(e,t){let r=this.path(e);await He(qe(r),{recursive:!0}),await Ye(r,t)}async get(e){try{return await We(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 ae(this.path(e)),!0}catch{return!1}}async delete(e){await Ve(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await ae(t)}catch{return r}let o=async i=>{let c=await Ue(i,{withFileTypes:!0});for(let l of c){let a=Je(i,l.name);if(l.isDirectory()){await o(a);continue}let d=await ce(a);r.push({key:le(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},n=await ce(t);return n.isDirectory()?await o(t):r.push({key:le(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};import{DeleteObjectCommand as Ze,GetObjectCommand as Xe,HeadObjectCommand as et,ListObjectsV2Command as tt,PutObjectCommand as rt,S3Client as st}from"@aws-sdk/client-s3";import{getSignedUrl as ot}from"@aws-sdk/s3-request-presigner";var M=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new st({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,r="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new rt({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await ot(this.client,new Xe({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new et({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 Ze({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new tt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};function Q(s,e){return console.warn(e),new N(s)}function de(s){let e=s.localRoot??it(nt(),".toolnet-memory","storage");if(s.provider==="r2"){let t=s.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new M({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Q(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(s.provider==="s3"){let t=s.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new M({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Q(e,"[storage] S3 credentials missing. Using local fallback.")}if(s.provider==="huggingface"){let t=s.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new D({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Q(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new N(e)}var I=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 G=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 K=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function pe(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 me(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 z=class{constructor(e,t,r,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=pe(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 i;try{i=JSON.parse(o)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}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)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=me(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*as u from"typescript";var v=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)}};import{execFile as dt}from"node:child_process";import{promisify as pt}from"node:util";var js=pt(dt);import{createHash as mt}from"node:crypto";import{readFile as ft}from"node:fs/promises";import{join as ut}from"node:path";function fe(s){return mt("sha256").update(s).digest("hex")}var B=class{sanitizer=new L;async build(e,t,r,o={}){let n=o.maxLines??80,i=o.overlapLines??10,c=new Map;for(let a of r){let d=c.get(a.filePath)??[];d.push(a),c.set(a.filePath,d)}let l=[];for(let[a,d]of c){let m;try{m=await ft(ut(t,a),"utf8")}catch{continue}let g=m.split(/\r?\n/),S=d.filter(h=>h.type!=="file"&&typeof h.startLine=="number"&&typeof h.endLine=="number");if(S.length>0)for(let h of S)l.push(...this.chunkRange({projectId:e,filePath:a,lines:g,symbol:h,startLine:h.startLine,endLine:h.endLine,maxLines:n,overlapLines:i}));else l.push(...this.chunkRange({projectId:e,filePath:a,lines:g,startLine:1,endLine:Math.max(1,g.length),maxLines:n,overlapLines:i}))}return l}chunkRange(e){let{projectId:t,filePath:r,lines:o,symbol:n,maxLines:i}=e,c=Math.min(e.overlapLines,Math.max(0,i-1)),l=Math.max(1,e.startLine),a=Math.min(o.length,Math.max(l,e.endLine)),d=[],m=l,g=0;for(;m<=a;){let S=Math.min(a,m+i-1),h=o.slice(m-1,S).join(`
5
- `).trim();if(h){let x=this.sanitizer.sanitize(h).text,P=fe(x),k=[t,r,n?.id??"file",String(g),P].join(":");d.push({id:fe(k).slice(0,32),projectId:t,filePath:r,symbolId:n?.id,symbolName:n?.qualifiedName??n?.name,symbolType:n?.type,startLine:m,endLine:S,content:x,contentHash:P})}if(S>=a)break;m=S-c+1,g++}return d}};var H=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,o]of this.records)o.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 o=[];for(let n of this.records.values()){if(n.projectId!==e)continue;let i=gt(t,n.vector);o.push({id:n.id,score:i,metadata:n.metadata})}return o.sort((n,i)=>i.score-n.score).slice(0,r)}size(){return this.records.size}};function gt(s,e){if(s.length===0||e.length===0||s.length!==e.length)return 0;let t=0,r=0,o=0;for(let n=0;n<s.length;n++){let i=s[n]??0,c=e[n]??0;t+=i*c,r+=i*i,o+=c*c}return r===0||o===0?0:t/(Math.sqrt(r)*Math.sqrt(o))}function Z(s){return s.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}function ue(s,e){let t=s.toLowerCase().replaceAll("\\","/"),r=e.toLowerCase(),o=/\b(test|tests|spec|fixture|mock)\b/.test(r);return(t.startsWith("tests/")||t.includes("/tests/")||t.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(t))&&!o?.35:t.includes("/generated/")||t.includes(".generated.")?.25:1}var W=class{constructor(e){this.options=e}options;vectors=new H;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:r,embeddings:o,graph:n,model:i}=this.options,c=new G(r),l=new K(r),a=await new B().build(e,t,n.allSymbols(e));this.chunks.clear();for(let f of a)this.chunks.set(f.id,f);let d=await c.load(e),m=!d||d.chunks.length!==a.length||d.chunks.some(f=>!this.chunks.has(f.id));m&&await c.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:a});let g=await l.load(e),S=0;g&&g.model===i&&(S=this.vectors.importRecords(g.records));let h=new Set(a.map(f=>f.id)),x=0;for(let f of this.vectors.exportProject(e))h.has(f.id)||this.vectors.remove(f.id)&&x++;let P=a.filter(f=>{let C=this.vectors.get(f.id);return C?C.metadata?.contentHash!==f.contentHash:!0}),k=0,ee=8,T=this.vectors.exportProject(e)[0]?.vector.length;for(let f=0;f<P.length;f+=ee){let C=P.slice(f,f+ee),he=C.map(b=>[`file: ${b.filePath}`,b.symbolName?`symbol: ${b.symbolName}`:"",b.symbolType?`type: ${b.symbolType}`:"",b.content].filter(Boolean).join(`
6
- `)),ye=await o.embedMany(he);for(let b=0;b<C.length;b++){let E=C[b],w=ye[b];if(!(!E||!w||w.length===0)){if(T===void 0&&(T=w.length),w.length!==T){console.warn(`[code-semantic] skip dimension mismatch: ${w.length} != ${T}`);continue}this.vectors.upsert({id:E.id,projectId:e,vector:w,metadata:{contentHash:E.contentHash,filePath:E.filePath,symbolName:E.symbolName,symbolType:E.symbolType,startLine:E.startLine,endLine:E.endLine}}),k++}}}let Y=this.vectors.exportProject(e),te=k>0||x>0||!g||g.model!==i;return te&&await l.save({version:1,projectId:e,model:i,dimensions:Y[0]?.vector.length??T??0,updatedAt:new Date().toISOString(),records:Y}),{chunks:a.length,vectorsLoaded:S,vectorsIndexed:k,vectorsRemoved:x,totalVectors:Y.length,savedChunks:m,savedVectors:te}}async search(e,t=8){let r=await this.options.embeddings.embed(e),o=this.vectors.search(this.options.projectId,r,Math.max(t*4,20)),n=new Set(Z(e)),i=[];for(let c of o){let l=this.chunks.get(c.id);if(!l)continue;let a=new Set(Z([l.filePath,l.symbolName??"",l.symbolType??"",l.content].join(" "))),d=0;for(let x of n)a.has(x)&&d++;let m=n.size===0?0:d/n.size,g=Math.max(0,c.score),S=ue(l.filePath,e),h=(g*.75+m*.25)*S;i.push({chunk:l,score:h,vectorScore:g,lexicalScore:m})}return i.sort((c,l)=>l.score-c.score).slice(0,t)}size(){return this.chunks.size}};import*as y from"typescript";import*as p from"typescript";var _o=new Set([p.SyntaxKind.EqualsToken,p.SyntaxKind.PlusEqualsToken,p.SyntaxKind.MinusEqualsToken,p.SyntaxKind.AsteriskEqualsToken,p.SyntaxKind.SlashEqualsToken,p.SyntaxKind.PercentEqualsToken,p.SyntaxKind.QuestionQuestionEqualsToken,p.SyntaxKind.AmpersandAmpersandEqualsToken,p.SyntaxKind.BarBarEqualsToken]);var U=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 o=await r.json();if(!Array.isArray(o))throw new Error("HF embedding returned invalid response");return o.map(n=>yt(n))}};function yt(s){if(!Array.isArray(s))throw new Error("Invalid embedding");if(s.length>0&&typeof s[0]=="number")return s;if(s.length>0&&Array.isArray(s[0])){let e=s;if(e.length===0)return[];let t=e[0].length,r=new Array(t).fill(0);for(let o of e)for(let n=0;n<t;n++)r[n]+=o[n]??0;for(let o=0;o<t;o++)r[o]/=e.length;return r}throw new Error("Unsupported embedding shape")}import{createHash as St}from"node:crypto";var V=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 o of r){let i=St("sha256").update(o).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return bt(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function bt(s){let e=Math.sqrt(s.reduce((t,r)=>t+r*r,0));return e===0?s:s.map(t=>t/e)}var X=class{constructor(e,t=new V){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 ge(){let s=process.env.HF_TOKEN,e=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",t=s?new U({token:s,model:e}):null;return new X(t)}async function xt(){let s=re(),e=new _().detect(),t=de({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),r=new z(t,e.id,e.name,e.remote??e.name),o=new v,n=await new I(r).load(e.id);if(!n)throw new Error("Code graph missing. Run npm run code:index:test first.");o.import(n.symbols,n.edges);let i=new W({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:r,embeddings:ge(),graph:o}),c=await i.initialize(),l=process.argv.slice(2).join(" ")||"memory storage hugging face",a=await i.search(l,5);console.log({ok:!0,query:l,...c,results:a.map(d=>({score:Number(d.score.toFixed(4)),file:d.chunk.filePath,symbol:d.chunk.symbolName,lines:`${d.chunk.startLine}-${d.chunk.endLine}`,preview:d.chunk.content.replace(/\s+/g," ").slice(0,140)}))})}xt().catch(s=>{console.error(s),process.exit(1)});
1
+ import"dotenv/config";import{existsSync as Te,readFileSync as _e}from"node:fs";import{homedir as Me}from"node:os";import{join as Ne}from"node:path";function Oe(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function je(){let r=process.env.TOOLNET_GLOBAL_ENV??Ne(Me(),".config","toolnet-memory",".env");if(!Te(r))return;let e=_e(r,"utf8");for(let t of e.split(/\r?\n/)){let s=t.trim();if(!s||s.startsWith("#"))continue;s.startsWith("export ")&&(s=s.slice(7));let o=s.indexOf("=");if(o<=0)continue;let n=s.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)&&process.env[n]===void 0&&(process.env[n]=Oe(s.slice(o+1)))}}je();function I(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function T(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function ue(){return{memory:{autoCapture:I(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:I(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:I(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:I(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:T(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:T(process.env.MEMORY_RERANK_TOP,10),finalContext:T(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:T(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:I(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:T(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as De}from"node:crypto";import{existsSync as oe,mkdirSync as Fe,readFileSync as Ke,renameSync as $e,writeFileSync as Ge}from"node:fs";import{basename as Ue,dirname as D,join as K,parse as ge,resolve as _}from"node:path";var he=".toolnet",Be="project.json";function ze(r){return De("sha256").update(r).digest("hex").slice(0,16)}function ne(r){return K(r,he,Be)}function He(r){return oe(ne(r))}function Ve(r,e){let t=_(r),s=ge(t).root;for(;;){if(He(t))return t;if(t===s||e&&t===_(e))break;let o=D(t);if(o===t)break;t=o}return null}function We(r){let e=_(r),t=ge(e).root,s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(s.some(n=>oe(K(e,n))))return e;if(e===t)break;let o=D(e);if(o===e)break;e=o}return _(r)}function Ye(r){let e;try{e=JSON.parse(Ke(r,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${r}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let s=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:D(D(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:s,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:s,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 me(r,e){let t=K(r,he);Fe(t,{recursive:!0});let s=ne(r),o=`${s}.tmp-${process.pid}`;Ge(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),$e(o,s)}function fe(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var F=class{detect(e=process.cwd()){let t=_(e),s=We(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>oe(K(s,l))),a=Ve(t,n?s:void 0);if(a){let l=ne(a),f=Ye(l);return f.rootPath!==a&&(f.rootPath=a,f.updatedAt=new Date().toISOString(),me(a,f)),fe(f,a)}let c=new Date().toISOString(),d=Ue(s),m={version:1,id:ze(s),name:d,remote:d,rootPath:s,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return me(s,m),fe(m,s)}};var qe=[{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}],$=class{scan(e){let t=[];for(let s of qe){let o=new RegExp(s.regex.source,s.regex.flags);for(let n of e.matchAll(o))t.push({type:s.type,value:n[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var M=class{scanner=new $;sanitize(e){let t=e,s=this.scanner.scan(e),o=new Set;for(let n of s)o.add(n.type),t=t.split(n.value).join(`[REDACTED:${n.type}]`);return{text:t,redacted:s.length,secretTypes:[...o]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[s,o]of Object.entries(e)){let n=s.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");n.includes("password")||n.includes("passwd")||n==="pwd"||n.includes("secret")||n.includes("token")||n.includes("cookie")||n.includes("authorization")||n.includes("apikey")||n.includes("accesskey")||n.includes("privatekey")||n.includes("clientsecret")||n.includes("credential")?t[s]="[REDACTED]":t[s]=this.sanitizeValue(o)}return t}return e}};import{homedir as bt}from"node:os";import{join as St}from"node:path";import{DeleteObjectCommand as Je,GetObjectCommand as Qe,HeadObjectCommand as Ze,ListObjectsV2Command as Xe,PutObjectCommand as et,S3Client as tt}from"@aws-sdk/client-s3";import{getSignedUrl as rt}from"@aws-sdk/s3-request-presigner";var G=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new tt({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,s="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new et({Bucket:this.bucket,Key:e,Body:o,ContentType:s}))}async get(e){let t=await rt(this.client,new Qe({Bucket:this.bucket,Key:e}),{expiresIn:60}),s=await fetch(t,{redirect:"follow"});if(s.status===404)return null;if(!s.ok)throw new Error(`HF download failed: ${s.status} ${s.statusText}`);return new Uint8Array(await s.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 Ze({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 Je({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],s;do{let o=await this.client.send(new Xe({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:s}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});s=o.IsTruncated?o.NextContinuationToken:void 0}while(s);return t}};import{access as ye,mkdir as st,readFile as ot,readdir as nt,rm as it,stat as be,writeFile as at}from"node:fs/promises";import{dirname as ct,join as lt,relative as Se,resolve as dt}from"node:path";var N=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return dt(this.root,t)}async put(e,t){let s=this.path(e);await st(ct(s),{recursive:!0}),await at(s,t)}async get(e){try{return await ot(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 ye(this.path(e)),!0}catch{return!1}}async delete(e){await it(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),s=[];try{await ye(t)}catch{return s}let o=async a=>{let c=await nt(a,{withFileTypes:!0});for(let d of c){let m=lt(a,d.name);if(d.isDirectory()){await o(m);continue}let l=await be(m);s.push({key:Se(this.root,m),size:l.size,updatedAt:l.mtime.toISOString()})}},n=await be(t);return n.isDirectory()?await o(t):s.push({key:Se(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),s}};import{DeleteObjectCommand as pt,GetObjectCommand as ut,HeadObjectCommand as mt,ListObjectsV2Command as ft,PutObjectCommand as gt,S3Client as ht}from"@aws-sdk/client-s3";import{getSignedUrl as yt}from"@aws-sdk/s3-request-presigner";var O=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new ht({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,s="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new gt({Bucket:this.bucket,Key:e,Body:o,ContentType:s}))}async get(e){let t=await yt(this.client,new ut({Bucket:this.bucket,Key:e}),{expiresIn:60}),s=await fetch(t,{redirect:"follow"});if(s.status===404)return null;if(!s.ok)throw new Error(`${this.name} download failed: ${s.status} ${s.statusText}`);return new Uint8Array(await s.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 mt({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 pt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],s;do{let o=await this.client.send(new ft({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:s}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});s=o.IsTruncated?o.NextContinuationToken:void 0}while(s);return t}};function ie(r,e){return console.warn(e),new N(r)}function Ee(r){let e=r.localRoot??St(bt(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new O({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):ie(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new O({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):ie(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new G({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):ie(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new N(e)}var j=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 U=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 B=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function Ce(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function ve(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let s=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(s)return`${s[1]}memory/records/${s[2]}`;if(s=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),s)return`${s[1]}memory/vectors/${s[2]}`;if(s=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),s)return`${s[1]}code/graph/${s[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 z=class{constructor(e,t,s,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=s,this.folder=Ce(o??s),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(),s=t,o=await this.provider.getText(e);if(o){let a;try{a=JSON.parse(o)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof a.id=="string"&&a.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${a.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof a.createdAt=="string"&&(s=a.createdAt)}let n={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:s,updatedAt:t};await this.provider.put(e,JSON.stringify(n,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=ve(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,s){return await this.ensureRegistered(),this.provider.put(this.key(e),t,s)}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*as h from"typescript";var L=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(s=>s.projectId===e&&(s.name===t||s.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 s of e)this.addSymbol(s);for(let s of t)this.addEdge(s)}clearProject(e){for(let[t,s]of this.symbols)s.projectId===e&&this.symbols.delete(t);for(let[t,s]of this.edges)s.projectId===e&&this.edges.delete(t)}};import{execFile as xt}from"node:child_process";import{promisify as wt}from"node:util";var eo=wt(xt);import{createHash as Pt}from"node:crypto";import{readFile as At}from"node:fs/promises";import{join as Lt}from"node:path";function xe(r){return Pt("sha256").update(r).digest("hex")}var H=class{sanitizer=new M;async build(e,t,s,o={}){let n=o.maxLines??80,a=o.overlapLines??10,c=new Map;for(let m of s){let l=c.get(m.filePath)??[];l.push(m),c.set(m.filePath,l)}let d=[];for(let[m,l]of c){let f;try{f=await At(Lt(t,m),"utf8")}catch{continue}let E=f.split(/\r?\n/),y=l.filter(b=>b.type!=="file"&&typeof b.startLine=="number"&&typeof b.endLine=="number");if(y.length>0)for(let b of y)d.push(...this.chunkRange({projectId:e,filePath:m,lines:E,symbol:b,startLine:b.startLine,endLine:b.endLine,maxLines:n,overlapLines:a}));else d.push(...this.chunkRange({projectId:e,filePath:m,lines:E,startLine:1,endLine:Math.max(1,E.length),maxLines:n,overlapLines:a}))}return d}chunkRange(e){let{projectId:t,filePath:s,lines:o,symbol:n,maxLines:a}=e,c=Math.min(e.overlapLines,Math.max(0,a-1)),d=Math.max(1,e.startLine),m=Math.min(o.length,Math.max(d,e.endLine)),l=[],f=d,E=0;for(;f<=m;){let y=Math.min(m,f+a-1),b=o.slice(f-1,y).join(`
5
+ `).trim();if(b){let x=this.sanitizer.sanitize(b).text,w=xe(x),R=[t,s,n?.id??"file",String(E),w].join(":");l.push({id:xe(R).slice(0,32),projectId:t,filePath:s,symbolId:n?.id,symbolName:n?.qualifiedName??n?.name,symbolType:n?.type,startLine:f,endLine:y,content:x,contentHash:w})}if(y>=m)break;f=y-c+1,E++}return l}};var V=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[s,o]of this.records)o.projectId===e&&(this.records.delete(s),t++);return t}exportProject(e){return[...this.records.values()].filter(t=>t.projectId===e)}importRecords(e){let t=0;for(let s of e)!s?.id||!s?.projectId||!Array.isArray(s.vector)||(this.records.set(s.id,s),t++);return t}search(e,t,s=10){let o=[];for(let n of this.records.values()){if(n.projectId!==e)continue;let a=Rt(t,n.vector);o.push({id:n.id,score:a,metadata:n.metadata})}return o.sort((n,a)=>a.score-n.score).slice(0,s)}size(){return this.records.size}};function Rt(r,e){if(r.length===0||e.length===0||r.length!==e.length)return 0;let t=0,s=0,o=0;for(let n=0;n<r.length;n++){let a=r[n]??0,c=e[n]??0;t+=a*c,s+=a*a,o+=c*c}return s===0||o===0?0:t/(Math.sqrt(s)*Math.sqrt(o))}function ae(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}function we(r,e){let t=r.toLowerCase().replaceAll("\\","/"),s=e.toLowerCase(),o=/\b(test|tests|spec|fixture|mock)\b/.test(s);return(t.startsWith("tests/")||t.includes("/tests/")||t.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(t))&&!o?.35:t.includes("/generated/")||t.includes(".generated.")?.25:1}var W=class{constructor(e){this.options=e}options;vectors=new V;chunks=new Map;async initialize(e){let{projectId:t,rootPath:s,storage:o,embeddings:n,graph:a,model:c}=this.options,d=new U(o),m=new B(o),l=await new H().build(t,s,a.allSymbols(t));this.chunks.clear();for(let g of l)this.chunks.set(g.id,g);let f=await d.load(t),E=!f||f.chunks.length!==l.length||f.chunks.some(g=>!this.chunks.has(g.id));E&&await d.save({version:1,projectId:t,updatedAt:new Date().toISOString(),chunks:l});let y=await m.load(t),b=0;y&&y.model===c&&(b=this.vectors.importRecords(y.records));let x=new Set(l.map(g=>g.id)),w=0;for(let g of this.vectors.exportProject(t))x.has(g.id)||this.vectors.remove(g.id)&&w++;let R=l.filter(g=>{let P=this.vectors.get(g.id);return P?P.metadata?.contentHash!==g.contentHash:!0}),ee=0,te=8,k=this.vectors.exportProject(t)[0]?.vector.length,re=Math.ceil(R.length/te),de=0;for(let g=0;g<R.length;g+=te){let P=R.slice(g,g+te),ke=P.map(C=>[`file: ${C.filePath}`,C.symbolName?`symbol: ${C.symbolName}`:"",C.symbolType?`type: ${C.symbolType}`:"",C.content].filter(Boolean).join(`
6
+ `)),Ie=await n.embedMany(ke);for(let C=0;C<P.length;C++){let v=P[C],A=Ie[C];if(!(!v||!A||A.length===0)){if(k===void 0&&(k=A.length),A.length!==k){console.warn(`[code-semantic] skip dimension mismatch: ${A.length} != ${k}`);continue}this.vectors.upsert({id:v.id,projectId:t,vector:A,metadata:{contentHash:v.contentHash,filePath:v.filePath,symbolName:v.symbolName,symbolType:v.symbolType,startLine:v.startLine,endLine:v.endLine}}),ee++}}de++,e?.({current:de,total:re,phase:"embedding"})}let se=this.vectors.exportProject(t),pe=ee>0||w>0||!y||y.model!==c;return pe&&(e?.({current:re,total:re,phase:"saving"}),await m.save({version:1,projectId:t,model:c,dimensions:se[0]?.vector.length??k??0,updatedAt:new Date().toISOString(),records:se})),{chunks:l.length,vectorsLoaded:b,vectorsIndexed:ee,vectorsRemoved:w,totalVectors:se.length,savedChunks:E,savedVectors:pe}}async search(e,t=8){let s=await this.options.embeddings.embed(e),o=this.vectors.search(this.options.projectId,s,Math.max(t*4,20)),n=new Set(ae(e)),a=[];for(let c of o){let d=this.chunks.get(c.id);if(!d)continue;let m=new Set(ae([d.filePath,d.symbolName??"",d.symbolType??"",d.content].join(" "))),l=0;for(let x of n)m.has(x)&&l++;let f=n.size===0?0:l/n.size,E=Math.max(0,c.score),y=we(d.filePath,e),b=(E*.75+f*.25)*y;a.push({chunk:d,score:b,vectorScore:E,lexicalScore:f})}return a.sort((c,d)=>d.score-c.score).slice(0,t)}size(){return this.chunks.size}};import*as S from"typescript";import*as p from"typescript";var cn=new Set([p.SyntaxKind.EqualsToken,p.SyntaxKind.PlusEqualsToken,p.SyntaxKind.MinusEqualsToken,p.SyntaxKind.AsteriskEqualsToken,p.SyntaxKind.SlashEqualsToken,p.SyntaxKind.PercentEqualsToken,p.SyntaxKind.QuestionQuestionEqualsToken,p.SyntaxKind.AmpersandAmpersandEqualsToken,p.SyntaxKind.BarBarEqualsToken]);var Pe=[{id:"openai-compatible",label:"OpenAI-compatible",requiresApiKey:!0,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"alibaba",label:"Alibaba / DashScope",requiresApiKey:!0,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"openrouter",label:"OpenRouter",defaultBaseUrl:"https://openrouter.ai/api/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"groq",label:"Groq",defaultBaseUrl:"https://api.groq.com/openai/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"deepseek",label:"DeepSeek",defaultBaseUrl:"https://api.deepseek.com",defaultModel:"deepseek-v4-flash",requiresApiKey:!0,transport:"openai-compatible"},{id:"nvidia",label:"NVIDIA NIM",defaultBaseUrl:"https://integrate.api.nvidia.com/v1",defaultModel:"deepseek-ai/deepseek-v4-pro",requiresApiKey:!0,transport:"openai-compatible"},{id:"gemini",label:"Gemini",defaultBaseUrl:"https://generativelanguage.googleapis.com/v1beta",requiresApiKey:!0,transport:"gemini"},{id:"huggingface",label:"Hugging Face",defaultBaseUrl:"https://router.huggingface.co/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"ollama",label:"Ollama / Local",defaultBaseUrl:"http://127.0.0.1:11434/v1",requiresApiKey:!1,transport:"openai-compatible"},{id:"custom",label:"Custom endpoint",requiresApiKey:!1,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"cloudflare",label:"Cloudflare Workers AI",requiresApiKey:!0,requiresAccountId:!0,transport:"cloudflare"}];function Y(r){let e=Pe.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function q(r){return Pe.some(e=>e.id===r)}function i(r){return process.env[r]?.trim()||void 0}function u(...r){return r.find(e=>!!e?.trim())}function Ae(){if(i("GROQ_API_KEY"))return"groq";if(i("DEEPSEEK_API_KEY"))return"deepseek";if(i("NVIDIA_API_KEY")||i("NVIDIA_NIM_API_KEY"))return"nvidia";if(i("OPENROUTER_API_KEY"))return"openrouter";if(i("ALIBABA_API_KEY")||i("DASHSCOPE_API_KEY"))return"alibaba";if(i("GEMINI_API_KEY")||i("GOOGLE_API_KEY"))return"gemini";if(i("CLOUDFLARE_API_TOKEN")&&i("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(i("HF_TOKEN"))return"huggingface";if(i("OLLAMA_MODEL")||i("OLLAMA_BASE_URL"))return"ollama"}function It(){let r=i("TOOLNET_LLM_PROVIDER");return r&&q(r)?r:Ae()??"openai-compatible"}function ce(r){let e=Y(r);switch(r){case"alibaba":return{provider:r,apiKey:u(i("ALIBABA_API_KEY"),i("DASHSCOPE_API_KEY")),baseUrl:u(i("ALIBABA_BASE_URL"),i("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:u(i("ALIBABA_MODEL"),i("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:i("OPENROUTER_API_KEY"),baseUrl:u(i("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:i("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:i("GROQ_API_KEY"),baseUrl:u(i("GROQ_BASE_URL"),e.defaultBaseUrl),model:i("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:i("DEEPSEEK_API_KEY"),baseUrl:u(i("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:u(i("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:u(i("NVIDIA_API_KEY"),i("NVIDIA_NIM_API_KEY")),baseUrl:u(i("NVIDIA_BASE_URL"),i("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:u(i("NVIDIA_MODEL"),i("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:u(i("GEMINI_API_KEY"),i("GOOGLE_API_KEY")),baseUrl:u(i("GEMINI_BASE_URL"),e.defaultBaseUrl),model:i("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:i("HF_TOKEN"),baseUrl:u(i("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:u(i("HF_LLM_MODEL"),i("HF_MODEL"))};case"ollama":return{provider:r,apiKey:i("OLLAMA_API_KEY"),baseUrl:u(i("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:i("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:i("CLOUDFLARE_ACCOUNT_ID"),apiKey:i("CLOUDFLARE_API_TOKEN"),baseUrl:i("CLOUDFLARE_AI_BASE_URL"),model:i("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:i("CUSTOM_AI_API_KEY"),baseUrl:i("CUSTOM_AI_BASE_URL"),model:i("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:u(i("OPENAI_API_KEY"),i("MODEL_API_KEY")),baseUrl:u(i("OPENAI_BASE_URL"),i("MODEL_BASE_URL")),model:u(i("OPENAI_MODEL"),i("MODEL_NAME"))}}}function Tt(){let r=i("TOOLNET_LLM_PROVIDER"),e=r&&q(r)?r:It(),t=Y(e),s=ce(e);return{provider:e,apiKey:u(i("TOOLNET_LLM_API_KEY"),s.apiKey),baseUrl:u(i("TOOLNET_LLM_BASE_URL"),s.baseUrl,t.defaultBaseUrl),model:u(i("TOOLNET_LLM_MODEL"),s.model,t.defaultModel),accountId:u(i("TOOLNET_LLM_ACCOUNT_ID"),s.accountId)}}function _t(){let r=i("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&q(r)?r:i("HF_TOKEN")||i("HF_EMBEDDING_MODEL")?"huggingface":"local"}function Mt(){let r=_t();if(r==="local")return{provider:"local",model:u(i("TOOLNET_EMBEDDING_MODEL"),i("LOCAL_EMBEDDING_MODEL"))};let e=Y(r),t,s,o,n;switch(r){case"huggingface":t=i("HF_TOKEN"),s=i("HF_INFERENCE_BASE_URL"),o=i("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=i("OPENAI_API_KEY"),s=i("OPENAI_BASE_URL"),o=i("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=i("CLOUDFLARE_API_TOKEN"),s=i("CLOUDFLARE_AI_BASE_URL"),o=i("CLOUDFLARE_EMBEDDING_MODEL"),n=i("CLOUDFLARE_ACCOUNT_ID");break;default:t=ce(r).apiKey,s=ce(r).baseUrl,o=i(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let a=u(i("TOOLNET_EMBEDDING_ACCOUNT_ID"),n),c=u(i("TOOLNET_EMBEDDING_BASE_URL"),s,e.defaultBaseUrl),d=r==="cloudflare"&&!c&&a?`https://api.cloudflare.com/client/v4/accounts/${a}/ai/v1`:c;return{provider:r,apiKey:u(i("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:d,model:u(i("TOOLNET_EMBEDDING_MODEL"),o),accountId:a}}function Le(){let r=Tt(),e=Mt();return{llm:r,embedding:e,legacy:{llm:!i("TOOLNET_LLM_PROVIDER")&&!!Ae(),embedding:!i("TOOLNET_EMBEDDING_PROVIDER")&&!!(i("HF_TOKEN")||i("HF_EMBEDDING_MODEL"))}}}var J=class{constructor(e){this.options=e}options;name="gemini";async embed(e){let t=this.options.model.replace(/^models\//,""),o=`${this.options.baseUrl?.replace(/\/+$/,"")||"https://generativelanguage.googleapis.com/v1beta"}/models/${encodeURIComponent(t)}:embedContent?key=${encodeURIComponent(this.options.apiKey)}`,n=await fetch(o,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${t}`,content:{parts:[{text:e}]}})});if(!n.ok)throw new Error(`Gemini embedding failed: ${n.status} ${await n.text()}`);let c=(await n.json()).embedding?.values;if(!Array.isArray(c)||c.length===0)throw new Error("Gemini embedding returned invalid response");return c}async embedMany(e){let t=[];for(let s of e)t.push(await this.embed(s));return t}};import{createHash as Nt}from"node:crypto";var Q=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),s=e.toLowerCase().split(/\s+/).filter(Boolean);for(let o of s){let a=Nt("sha256").update(o).digest().readUInt32BE(0)%this.dimensions;t[a]+=1}return Ot(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function Ot(r){let e=Math.sqrt(r.reduce((t,s)=>t+s*s,0));return e===0?r:r.map(t=>t/e)}var Z=class{constructor(e){this.options=e;this.dimensions=e.dimensions}options;name="openai-compatible";dimensions;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=this.options.baseUrl.replace(/\/+$/,""),s=await fetch(`${t}/embeddings`,{method:"POST",headers:{"content-type":"application/json",...this.options.apiKey?{authorization:`Bearer ${this.options.apiKey}`}:{}},body:JSON.stringify({model:this.options.model,input:e})});if(!s.ok)throw new Error(`Embedding failed: ${s.status} ${await s.text()}`);let n=(await s.json()).data?.sort((a,c)=>(a.index??0)-(c.index??0)).map(a=>a.embedding);if(!n||n.length!==e.length||n.some(a=>!Array.isArray(a)))throw new Error("Embedding provider returned invalid response");return n}};var X=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`,s=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(!s.ok)throw new Error(`HF embedding failed: ${s.status} ${await s.text()}`);let o=await s.json();if(!Array.isArray(o))throw new Error("HF embedding returned invalid response");return o.map(n=>jt(n))}};function jt(r){if(!Array.isArray(r))throw new Error("Invalid embedding");if(r.length>0&&typeof r[0]=="number")return r;if(r.length>0&&Array.isArray(r[0])){let e=r;if(e.length===0)return[];let t=e[0].length,s=new Array(t).fill(0);for(let o of e)for(let n=0;n<t;n++)s[n]+=o[n]??0;for(let o=0;o<t;o++)s[o]/=e.length;return s}throw new Error("Unsupported embedding shape")}var le=class{constructor(e,t=new Q){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 Dt(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function Ft(){let r=Le().embedding;if(r.provider==="local")return null;if(r.provider==="huggingface")return!r.apiKey||!r.model?null:new X({token:r.apiKey,model:r.model});if(r.provider==="gemini")return!r.apiKey||!r.model?null:new J({apiKey:r.apiKey,model:r.model,baseUrl:r.baseUrl});let e=r.baseUrl;return r.provider==="cloudflare"&&!e&&r.accountId&&(e=Dt(r.accountId)),e&&r.model?new Z({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function Re(){return new le(Ft())}async function Kt(){let r=ue(),e=new F().detect(),t=Ee({provider:r.storage.provider,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),s=new z(t,e.id,e.name,e.remote??e.name),o=new L,n=await new j(s).load(e.id);if(!n)throw new Error("Code graph missing. Run npm run code:index:test first.");o.import(n.symbols,n.edges);let a=new W({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:s,embeddings:Re(),graph:o}),c=await a.initialize(),d=process.argv.slice(2).join(" ")||"memory storage hugging face",m=await a.search(d,5);console.log({ok:!0,query:d,...c,results:m.map(l=>({score:Number(l.score.toFixed(4)),file:l.chunk.filePath,symbol:l.chunk.symbolName,lines:`${l.chunk.startLine}-${l.chunk.endLine}`,preview:l.chunk.content.replace(/\s+/g," ").slice(0,140)}))})}Kt().catch(r=>{console.error(r),process.exit(1)});
@@ -0,0 +1,3 @@
1
+ import{existsSync as E}from"node:fs";import{dirname as M,join as O}from"node:path";import{fileURLToPath as k}from"node:url";import{spawnSync as C}from"node:child_process";import{createConnection as T}from"node:net";import{homedir as y}from"node:os";import{join as N}from"node:path";function v(){return process.env.TOOLNET_SERVICE_SOCKET??N(y(),".toolnet","run","service.sock")}function P(e,t={}){let o=t.socketPath??v(),f=t.timeoutMs??1e3;return new Promise((h,c)=>{let n=T({path:o}),a="",u=!1,l=i=>{u||(u=!0,clearTimeout(S),n.destroy(),i())},S=setTimeout(()=>{l(()=>{c(new Error(`ToolNet service timeout after ${f}ms`))})},f);n.setEncoding("utf8"),n.once("connect",()=>{n.write(`${JSON.stringify(e)}
2
+ `)}),n.on("data",i=>{a+=i;let m=a.indexOf(`
3
+ `);if(m===-1)return;let w=a.slice(0,m).trim();l(()=>{try{h(JSON.parse(w))}catch(p){c(p instanceof Error?p:new Error(String(p)))}})}),n.once("error",i=>{l(()=>{c(i)})}),n.once("end",()=>{u||l(()=>{c(new Error("ToolNet service closed without response"))})})})}async function d(e={}){let t=await P({type:"ping"},e);if(!t.ok||t.type!=="ping")throw new Error(t.ok?"Invalid ToolNet service ping response":t.error);return t}var s=process.env.TOOLNET_PM2_NAME??"toolnet-memory-service";function r(e,t=!1){let o=C("pm2",e,{encoding:"utf8",stdio:t?"pipe":"inherit"});if(o.error)throw o.error;return o}function x(){if(r(["--version"],!0).status!==0)throw new Error("PM2 is not installed. Install it with: npm install -g pm2")}function R(){let e=M(k(import.meta.url)),t=O(e,"service.js");if(!E(t))throw new Error(`Production service bundle missing: ${t}`);return t}function $(){return r(["describe",s],!0).status===0}async function g(e){try{let t=await d({timeoutMs:500});if(e){console.log(JSON.stringify({running:!0,...t.stats},null,2));return}console.log(""),console.log("\u25C7 ToolNet Memory Service"),console.log(""),console.log("\u25C6 Daemon"),console.log("\u2502"),console.log("\u251C \u25C6 Status \u2014 running"),console.log(`\u251C \u25C6 PID \u2014 ${t.stats.pid}`),console.log(`\u251C \u25C6 Cache entries \u2014 ${t.stats.cacheEntries}`),console.log(`\u251C \u25C6 Cache hits \u2014 ${t.stats.cacheHits}`),console.log(`\u251C \u25C6 Cache misses \u2014 ${t.stats.cacheMisses}`),console.log("\u2502"),console.log("\u2514 \u25C6 Service healthy"),console.log("")}catch{if(e){console.log(JSON.stringify({running:!1},null,2));return}console.log(""),console.log("\u25C7 ToolNet Memory Service"),console.log(""),console.log("\u25C6 Daemon"),console.log("\u2502"),console.log("\u2514 \u25C7 Status \u2014 stopped"),console.log("")}}async function b(){let e=process.argv[2]??"status",t=process.argv.includes("--json");if(e==="status"){await g(t);return}if(x(),e==="install"){if($()){if(r(["restart",s,"--update-env"],!0).status!==0)throw new Error("PM2 restart failed")}else if(r(["start",R(),"--name",s,"--interpreter",process.execPath,"--time"],!0).status!==0)throw new Error("PM2 install failed");r(["save"],!0),await g(!1);return}if(e==="start"){if(r(["start",s],!0).status!==0)throw new Error("Service is not installed. Run toolnet-memory service:install");return}if(e==="stop"){if(r(["stop",s],!0).status!==0)throw new Error("PM2 stop failed");return}if(e==="restart"){if(r(["restart",s,"--update-env"],!0).status!==0)throw new Error("PM2 restart failed");return}if(e==="remove"){if(r(["delete",s],!0).status!==0)throw new Error("PM2 delete failed");r(["save"],!0);return}throw new Error(`Unknown service command: ${e}`)}b().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
@@ -0,0 +1,6 @@
1
+ import{chmodSync as je,existsSync as M,mkdirSync as Pe,unlinkSync as D}from"node:fs";import{createConnection as we,createServer as xe}from"node:net";import{dirname as ke,resolve as Te}from"node:path";import{pathToFileURL as be}from"node:url";import{existsSync as B,readFileSync as H}from"node:fs";import{homedir as J}from"node:os";import{join as V}from"node:path";function L(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 z(){let o=process.env.TOOLNET_GLOBAL_ENV??V(J(),".config","toolnet-memory",".env");if(!B(o))return;let e=H(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]=L(r.slice(s+1)))}}z();function m(o,e){return o===void 0?e:["1","true","yes","on"].includes(o.toLowerCase())}function y(o,e){if(!o)return e;let t=Number(o);return Number.isFinite(t)?t:e}function C(){return{memory:{autoCapture:m(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:m(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:m(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:m(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:y(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:y(process.env.MEMORY_RERANK_TOP,10),finalContext:y(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:y(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:m(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:y(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{homedir as me}from"node:os";import{join as ye}from"node:path";import{DeleteObjectCommand as F,GetObjectCommand as Y,HeadObjectCommand as G,ListObjectsV2Command as W,PutObjectCommand as q,S3Client as Q}from"@aws-sdk/client-s3";import{getSignedUrl as Z}from"@aws-sdk/s3-request-presigner";var v=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Q({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 q({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await Z(this.client,new Y({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 G({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 F({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new W({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 O,mkdir as X,readFile as ee,readdir as te,rm as re,stat as E,writeFile as oe}from"node:fs/promises";import{dirname as se,join as ne,relative as A,resolve as ie}from"node:path";var f=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return ie(this.root,t)}async put(e,t){let r=this.path(e);await X(se(r),{recursive:!0}),await oe(r,t)}async get(e){try{return await ee(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 O(this.path(e)),!0}catch{return!1}}async delete(e){await re(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await O(t)}catch{return r}let s=async i=>{let c=await te(i,{withFileTypes:!0});for(let g of c){let l=ne(i,g.name);if(g.isDirectory()){await s(l);continue}let a=await E(l);r.push({key:A(this.root,l),size:a.size,updatedAt:a.mtime.toISOString()})}},n=await E(t);return n.isDirectory()?await s(t):r.push({key:A(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};import{DeleteObjectCommand as ae,GetObjectCommand as ce,HeadObjectCommand as pe,ListObjectsV2Command as ue,PutObjectCommand as le,S3Client as de}from"@aws-sdk/client-s3";import{getSignedUrl as ge}from"@aws-sdk/s3-request-presigner";var h=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new de({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,r="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new le({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await ge(this.client,new ce({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new pe({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 ae({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new ue({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of s.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};function T(o,e){return console.warn(e),new f(o)}function R(o){let e=o.localRoot??ye(me(),".toolnet-memory","storage");if(o.provider==="r2"){let t=o.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new h({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(o.provider==="s3"){let t=o.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new h({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] S3 credentials missing. Using local fallback.")}if(o.provider==="huggingface"){let t=o.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new v({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new f(e)}var j=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")}};var P=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")}};function fe(o){return new Promise(e=>setTimeout(e,o))}async function N(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(c){if(n=c,i>=t)break;let g=Math.min(s,r*2**(i-1)),l=Math.floor(Math.random()*Math.max(1,g*.2));await fe(g+l)}throw n}var he=new Set(["put","get","getText","delete","list"]);function I(o,e={}){return new Proxy(o,{get(t,r){let s=Reflect.get(t,r,t);return typeof s!="function"?s:he.has(r)?(...n)=>N(()=>Promise.resolve(s.apply(t,n)),e):s.bind(t)}})}function _(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 K(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 w=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=_(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(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}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)+`
3
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=K(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{homedir as Se}from"node:os";import{join as ve}from"node:path";function $(){return process.env.TOOLNET_SERVICE_SOCKET??ve(Se(),".toolnet","run","service.sock")}function b(o){return o instanceof Error?o.message:String(o)}function Ce(o){return`${o.id}:${o.remote??o.name}`}async function Oe(o){let e=C(),t=R({provider:e.storage.provider,r2:e.storage.r2,s3:e.storage.s3,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),r=I(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),s=new w(r,o.id,o.name,o.remote??o.name),[n,i]=await Promise.all([new j(s).load(o.id),new P(s).load(o.id)]);return{memory:n,graph:i}}function Ee(o,e=200){return new Promise(t=>{let r=we({path:o}),s=!1,n=c=>{s||(s=!0,clearTimeout(i),r.destroy(),t(c))},i=setTimeout(()=>{n(!1)},e);r.once("connect",()=>{n(!0)}),r.once("error",()=>{n(!1)})})}async function Ae(o={}){let e=o.socketPath??$(),t=Math.max(1e3,o.cacheTtlMs??Number(process.env.TOOLNET_SERVICE_CACHE_TTL_MS??3e4)),r=o.loader??Oe,s=new Map,n=new Date().toISOString(),i={requests:0,cacheHits:0,cacheMisses:0},c=()=>({pid:process.pid,startedAt:n,requests:i.requests,cacheHits:i.cacheHits,cacheMisses:i.cacheMisses,cacheEntries:s.size}),g=async a=>{if(i.requests+=1,a.type==="ping")return{ok:!0,type:"ping",stats:c()};let p=Ce(a.project);if(a.type==="invalidate")return{ok:!0,type:"invalidate",removed:s.delete(p)};let d=s.get(p);if(d&&d.expiresAt>Date.now())return i.cacheHits+=1,{ok:!0,type:"hydrate",cacheHit:!0,loadedAt:d.loadedAt,memory:d.data.memory,graph:d.data.graph};i.cacheMisses+=1;try{let u=await r(a.project),S=new Date().toISOString();return s.set(p,{expiresAt:Date.now()+t,loadedAt:S,data:u}),{ok:!0,type:"hydrate",cacheHit:!1,loadedAt:S,memory:u.memory,graph:u.graph}}catch(u){return{ok:!1,error:b(u)}}};if(Pe(ke(e),{recursive:!0,mode:448}),M(e)){if(await Ee(e))throw new Error(`ToolNet service already running at ${e}`);D(e)}let l=xe(a=>{a.setEncoding("utf8");let p="";a.on("data",d=>{p+=d;let u=p.indexOf(`
4
+ `);if(u===-1)return;let S=p.slice(0,u).trim();p=p.slice(u+1),(async()=>{try{let x=JSON.parse(S),k=await g(x);a.end(`${JSON.stringify(k)}
5
+ `)}catch(x){let k={ok:!1,error:b(x)};a.end(`${JSON.stringify(k)}
6
+ `)}})()})});return await new Promise((a,p)=>{let d=u=>{p(u)};l.once("error",d),l.listen(e,()=>{l.off("error",d),a()})}),je(e,384),{socketPath:e,stats:c,close:async()=>{await new Promise(a=>{l.close(()=>{a()})}),M(e)&&D(e)}}}async function Re(){let o=await Ae();console.log(`[toolnet-memory] service ready: ${o.socketPath}`);let e=()=>{o.close().finally(()=>process.exit(0))};process.once("SIGINT",e),process.once("SIGTERM",e)}var U=process.argv[1];U&&import.meta.url===be(Te(U)).href&&Re().catch(o=>{console.error(`[toolnet-memory] service failed: ${b(o)}`),process.exit(1)});export{Oe as loadProjectForService,Ae as startToolNetService};