toolnet-memory 0.2.20 → 0.2.21

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 Re,readFileSync as Te}from"node:fs";import{homedir as _e}from"node:os";import{join as Ie}from"node:path";function ke(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 Ne(){let r=process.env.TOOLNET_GLOBAL_ENV??Ie(_e(),".config","toolnet-memory",".env");if(!Re(r))return;let e=Te(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 i=s.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=ke(s.slice(o+1)))}}Ne();function _(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function I(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function le(){return{memory:{autoCapture:_(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:_(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:_(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:_(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:I(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:I(process.env.MEMORY_RERANK_TOP,10),finalContext:I(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:I(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:_(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:I(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Me}from"node:crypto";import{existsSync as te,mkdirSync as Oe,readFileSync as je,renameSync as De,writeFileSync as Fe}from"node:fs";import{basename as Ke,dirname as D,join as K,parse as me,resolve as k}from"node:path";var ue=".toolnet",$e="project.json";function Ge(r){return Me("sha256").update(r).digest("hex").slice(0,16)}function re(r){return K(r,ue,$e)}function Ue(r){return te(re(r))}function Be(r,e){let t=k(r),s=me(t).root;for(;;){if(Ue(t))return t;if(t===s||e&&t===k(e))break;let o=D(t);if(o===t)break;t=o}return null}function ze(r){let e=k(r),t=me(e).root,s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(s.some(i=>te(K(e,i))))return e;if(e===t)break;let o=D(e);if(o===e)break;e=o}return k(r)}function He(r){let e;try{e=JSON.parse(je(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 de(r,e){let t=K(r,ue);Oe(t,{recursive:!0});let s=re(r),o=`${s}.tmp-${process.pid}`;Fe(o,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),De(o,s)}function pe(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=k(e),s=ze(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>te(K(s,p))),a=Be(t,i?s:void 0);if(a){let p=re(a),f=He(p);return f.rootPath!==a&&(f.rootPath=a,f.updatedAt=new Date().toISOString(),de(a,f)),pe(f,a)}let c=new Date().toISOString(),l=Ke(s),d={version:1,id:Ge(s),name:l,remote:l,rootPath:s,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return de(s,d),pe(d,s)}};var Ve=[{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 Ve){let o=new RegExp(s.regex.source,s.regex.flags);for(let i of e.matchAll(o))t.push({type:s.type,value:i[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var N=class{scanner=new $;sanitize(e){let t=e,s=this.scanner.scan(e),o=new Set;for(let i of s)o.add(i.type),t=t.split(i.value).join(`[REDACTED:${i.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 i=s.toLowerCase();i.includes("password")||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")?t[s]="[REDACTED]":t[s]=this.sanitizeValue(o)}return t}return e}};import{homedir as gt}from"node:os";import{join as ht}from"node:path";import{DeleteObjectCommand as We,GetObjectCommand as Ye,HeadObjectCommand as qe,ListObjectsV2Command as Je,PutObjectCommand as Qe,S3Client as Ze}from"@aws-sdk/client-s3";import{getSignedUrl as Xe}from"@aws-sdk/s3-request-presigner";var G=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,s="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Qe({Bucket:this.bucket,Key:e,Body:o,ContentType:s}))}async get(e){let t=await Xe(this.client,new Ye({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 qe({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 We({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],s;do{let o=await this.client.send(new Je({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:s}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});s=o.IsTruncated?o.NextContinuationToken:void 0}while(s);return t}};import{access as fe,mkdir as et,readFile as tt,readdir as rt,rm as st,stat as ge,writeFile as ot}from"node:fs/promises";import{dirname as nt,join as it,relative as he,resolve as at}from"node:path";var M=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return at(this.root,t)}async put(e,t){let s=this.path(e);await et(nt(s),{recursive:!0}),await ot(s,t)}async get(e){try{return await tt(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 fe(this.path(e)),!0}catch{return!1}}async delete(e){await st(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),s=[];try{await fe(t)}catch{return s}let o=async a=>{let c=await rt(a,{withFileTypes:!0});for(let l of c){let d=it(a,l.name);if(l.isDirectory()){await o(d);continue}let p=await ge(d);s.push({key:he(this.root,d),size:p.size,updatedAt:p.mtime.toISOString()})}},i=await ge(t);return i.isDirectory()?await o(t):s.push({key:he(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),s}};import{DeleteObjectCommand as ct,GetObjectCommand as lt,HeadObjectCommand as dt,ListObjectsV2Command as pt,PutObjectCommand as mt,S3Client as ut}from"@aws-sdk/client-s3";import{getSignedUrl as ft}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 ut({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 mt({Bucket:this.bucket,Key:e,Body:o,ContentType:s}))}async get(e){let t=await ft(this.client,new lt({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 dt({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 ct({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],s;do{let o=await this.client.send(new pt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:s}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});s=o.IsTruncated?o.NextContinuationToken:void 0}while(s);return t}};function se(r,e){return console.warn(e),new M(r)}function ye(r){let e=r.localRoot??ht(gt(),".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}):se(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}):se(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}):se(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new M(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 be(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 Se(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=be(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 i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:s,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=Se(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 A=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 Et}from"node:child_process";import{promisify as vt}from"node:util";var Hs=vt(Et);import{createHash as Ct}from"node:crypto";import{readFile as xt}from"node:fs/promises";import{join as wt}from"node:path";function Ee(r){return Ct("sha256").update(r).digest("hex")}var H=class{sanitizer=new N;async build(e,t,s,o={}){let i=o.maxLines??80,a=o.overlapLines??10,c=new Map;for(let d of s){let p=c.get(d.filePath)??[];p.push(d),c.set(d.filePath,p)}let l=[];for(let[d,p]of c){let f;try{f=await xt(wt(t,d),"utf8")}catch{continue}let y=f.split(/\r?\n/),E=p.filter(b=>b.type!=="file"&&typeof b.startLine=="number"&&typeof b.endLine=="number");if(E.length>0)for(let b of E)l.push(...this.chunkRange({projectId:e,filePath:d,lines:y,symbol:b,startLine:b.startLine,endLine:b.endLine,maxLines:i,overlapLines:a}));else l.push(...this.chunkRange({projectId:e,filePath:d,lines:y,startLine:1,endLine:Math.max(1,y.length),maxLines:i,overlapLines:a}))}return l}chunkRange(e){let{projectId:t,filePath:s,lines:o,symbol:i,maxLines:a}=e,c=Math.min(e.overlapLines,Math.max(0,a-1)),l=Math.max(1,e.startLine),d=Math.min(o.length,Math.max(l,e.endLine)),p=[],f=l,y=0;for(;f<=d;){let E=Math.min(d,f+a-1),b=o.slice(f-1,E).join(`
5
- `).trim();if(b){let C=this.sanitizer.sanitize(b).text,L=Ee(C),R=[t,s,i?.id??"file",String(y),L].join(":");p.push({id:Ee(R).slice(0,32),projectId:t,filePath:s,symbolId:i?.id,symbolName:i?.qualifiedName??i?.name,symbolType:i?.type,startLine:f,endLine:E,content:C,contentHash:L})}if(E>=d)break;f=E-c+1,y++}return p}};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 i of this.records.values()){if(i.projectId!==e)continue;let a=Pt(t,i.vector);o.push({id:i.id,score:a,metadata:i.metadata})}return o.sort((i,a)=>a.score-i.score).slice(0,s)}size(){return this.records.size}};function Pt(r,e){if(r.length===0||e.length===0||r.length!==e.length)return 0;let t=0,s=0,o=0;for(let i=0;i<r.length;i++){let a=r[i]??0,c=e[i]??0;t+=a*c,s+=a*a,o+=c*c}return s===0||o===0?0:t/(Math.sqrt(s)*Math.sqrt(o))}function oe(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}function ve(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(){let{projectId:e,rootPath:t,storage:s,embeddings:o,graph:i,model:a}=this.options,c=new U(s),l=new B(s),d=await new H().build(e,t,i.allSymbols(e));this.chunks.clear();for(let g of d)this.chunks.set(g.id,g);let p=await c.load(e),f=!p||p.chunks.length!==d.length||p.chunks.some(g=>!this.chunks.has(g.id));f&&await c.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:d});let y=await l.load(e),E=0;y&&y.model===a&&(E=this.vectors.importRecords(y.records));let b=new Set(d.map(g=>g.id)),C=0;for(let g of this.vectors.exportProject(e))b.has(g.id)||this.vectors.remove(g.id)&&C++;let L=d.filter(g=>{let w=this.vectors.get(g.id);return w?w.metadata?.contentHash!==g.contentHash:!0}),R=0,ae=8,T=this.vectors.exportProject(e)[0]?.vector.length;for(let g=0;g<L.length;g+=ae){let w=L.slice(g,g+ae),Ae=w.map(v=>[`file: ${v.filePath}`,v.symbolName?`symbol: ${v.symbolName}`:"",v.symbolType?`type: ${v.symbolType}`:"",v.content].filter(Boolean).join(`
6
- `)),Le=await o.embedMany(Ae);for(let v=0;v<w.length;v++){let x=w[v],P=Le[v];if(!(!x||!P||P.length===0)){if(T===void 0&&(T=P.length),P.length!==T){console.warn(`[code-semantic] skip dimension mismatch: ${P.length} != ${T}`);continue}this.vectors.upsert({id:x.id,projectId:e,vector:P,metadata:{contentHash:x.contentHash,filePath:x.filePath,symbolName:x.symbolName,symbolType:x.symbolType,startLine:x.startLine,endLine:x.endLine}}),R++}}}let ee=this.vectors.exportProject(e),ce=R>0||C>0||!y||y.model!==a;return ce&&await l.save({version:1,projectId:e,model:a,dimensions:ee[0]?.vector.length??T??0,updatedAt:new Date().toISOString(),records:ee}),{chunks:d.length,vectorsLoaded:E,vectorsIndexed:R,vectorsRemoved:C,totalVectors:ee.length,savedChunks:f,savedVectors:ce}}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)),i=new Set(oe(e)),a=[];for(let c of o){let l=this.chunks.get(c.id);if(!l)continue;let d=new Set(oe([l.filePath,l.symbolName??"",l.symbolType??"",l.content].join(" "))),p=0;for(let C of i)d.has(C)&&p++;let f=i.size===0?0:p/i.size,y=Math.max(0,c.score),E=ve(l.filePath,e),b=(y*.75+f*.25)*E;a.push({chunk:l,score:b,vectorScore:y,lexicalScore:f})}return a.sort((c,l)=>l.score-c.score).slice(0,t)}size(){return this.chunks.size}};import*as S from"typescript";import*as m from"typescript";var Zo=new Set([m.SyntaxKind.EqualsToken,m.SyntaxKind.PlusEqualsToken,m.SyntaxKind.MinusEqualsToken,m.SyntaxKind.AsteriskEqualsToken,m.SyntaxKind.SlashEqualsToken,m.SyntaxKind.PercentEqualsToken,m.SyntaxKind.QuestionQuestionEqualsToken,m.SyntaxKind.AmpersandAmpersandEqualsToken,m.SyntaxKind.BarBarEqualsToken]);var Ce=[{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=Ce.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function q(r){return Ce.some(e=>e.id===r)}function n(r){return process.env[r]?.trim()||void 0}function u(...r){return r.find(e=>!!e?.trim())}function xe(){if(n("GROQ_API_KEY"))return"groq";if(n("DEEPSEEK_API_KEY"))return"deepseek";if(n("NVIDIA_API_KEY")||n("NVIDIA_NIM_API_KEY"))return"nvidia";if(n("OPENROUTER_API_KEY"))return"openrouter";if(n("ALIBABA_API_KEY")||n("DASHSCOPE_API_KEY"))return"alibaba";if(n("GEMINI_API_KEY")||n("GOOGLE_API_KEY"))return"gemini";if(n("CLOUDFLARE_API_TOKEN")&&n("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(n("HF_TOKEN"))return"huggingface";if(n("OLLAMA_MODEL")||n("OLLAMA_BASE_URL"))return"ollama"}function Lt(){let r=n("TOOLNET_LLM_PROVIDER");return r&&q(r)?r:xe()??"openai-compatible"}function ne(r){let e=Y(r);switch(r){case"alibaba":return{provider:r,apiKey:u(n("ALIBABA_API_KEY"),n("DASHSCOPE_API_KEY")),baseUrl:u(n("ALIBABA_BASE_URL"),n("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:u(n("ALIBABA_MODEL"),n("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:n("OPENROUTER_API_KEY"),baseUrl:u(n("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:n("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:n("GROQ_API_KEY"),baseUrl:u(n("GROQ_BASE_URL"),e.defaultBaseUrl),model:n("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:n("DEEPSEEK_API_KEY"),baseUrl:u(n("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:u(n("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:u(n("NVIDIA_API_KEY"),n("NVIDIA_NIM_API_KEY")),baseUrl:u(n("NVIDIA_BASE_URL"),n("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:u(n("NVIDIA_MODEL"),n("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:u(n("GEMINI_API_KEY"),n("GOOGLE_API_KEY")),baseUrl:u(n("GEMINI_BASE_URL"),e.defaultBaseUrl),model:n("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:n("HF_TOKEN"),baseUrl:u(n("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:u(n("HF_LLM_MODEL"),n("HF_MODEL"))};case"ollama":return{provider:r,apiKey:n("OLLAMA_API_KEY"),baseUrl:u(n("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:n("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:n("CLOUDFLARE_ACCOUNT_ID"),apiKey:n("CLOUDFLARE_API_TOKEN"),baseUrl:n("CLOUDFLARE_AI_BASE_URL"),model:n("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:n("CUSTOM_AI_API_KEY"),baseUrl:n("CUSTOM_AI_BASE_URL"),model:n("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:u(n("OPENAI_API_KEY"),n("MODEL_API_KEY")),baseUrl:u(n("OPENAI_BASE_URL"),n("MODEL_BASE_URL")),model:u(n("OPENAI_MODEL"),n("MODEL_NAME"))}}}function Rt(){let r=n("TOOLNET_LLM_PROVIDER"),e=r&&q(r)?r:Lt(),t=Y(e),s=ne(e);return{provider:e,apiKey:u(n("TOOLNET_LLM_API_KEY"),s.apiKey),baseUrl:u(n("TOOLNET_LLM_BASE_URL"),s.baseUrl,t.defaultBaseUrl),model:u(n("TOOLNET_LLM_MODEL"),s.model,t.defaultModel),accountId:u(n("TOOLNET_LLM_ACCOUNT_ID"),s.accountId)}}function Tt(){let r=n("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&q(r)?r:n("HF_TOKEN")||n("HF_EMBEDDING_MODEL")?"huggingface":"local"}function _t(){let r=Tt();if(r==="local")return{provider:"local",model:u(n("TOOLNET_EMBEDDING_MODEL"),n("LOCAL_EMBEDDING_MODEL"))};let e=Y(r),t,s,o,i;switch(r){case"huggingface":t=n("HF_TOKEN"),s=n("HF_INFERENCE_BASE_URL"),o=n("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=n("OPENAI_API_KEY"),s=n("OPENAI_BASE_URL"),o=n("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=n("CLOUDFLARE_API_TOKEN"),s=n("CLOUDFLARE_AI_BASE_URL"),o=n("CLOUDFLARE_EMBEDDING_MODEL"),i=n("CLOUDFLARE_ACCOUNT_ID");break;default:t=ne(r).apiKey,s=ne(r).baseUrl,o=n(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let a=u(n("TOOLNET_EMBEDDING_ACCOUNT_ID"),i),c=u(n("TOOLNET_EMBEDDING_BASE_URL"),s,e.defaultBaseUrl),l=r==="cloudflare"&&!c&&a?`https://api.cloudflare.com/client/v4/accounts/${a}/ai/v1`:c;return{provider:r,apiKey:u(n("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:l,model:u(n("TOOLNET_EMBEDDING_MODEL"),o),accountId:a}}function we(){let r=Rt(),e=_t();return{llm:r,embedding:e,legacy:{llm:!n("TOOLNET_LLM_PROVIDER")&&!!xe(),embedding:!n("TOOLNET_EMBEDDING_PROVIDER")&&!!(n("HF_TOKEN")||n("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)}`,i=await fetch(o,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${t}`,content:{parts:[{text:e}]}})});if(!i.ok)throw new Error(`Gemini embedding failed: ${i.status} ${await i.text()}`);let c=(await i.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 It}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=It("sha256").update(o).digest().readUInt32BE(0)%this.dimensions;t[a]+=1}return kt(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function kt(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 i=(await s.json()).data?.sort((a,c)=>(a.index??0)-(c.index??0)).map(a=>a.embedding);if(!i||i.length!==e.length||i.some(a=>!Array.isArray(a)))throw new Error("Embedding provider returned invalid response");return i}};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(i=>Nt(i))}};function Nt(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 i=0;i<t;i++)s[i]+=o[i]??0;for(let o=0;o<t;o++)s[o]/=e.length;return s}throw new Error("Unsupported embedding shape")}var ie=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 Mt(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function Ot(){let r=we().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=Mt(r.accountId)),e&&r.model?new Z({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function Pe(){return new ie(Ot())}async function jt(){let r=le(),e=new F().detect(),t=ye({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 A,i=await new j(s).load(e.id);if(!i)throw new Error("Code graph missing. Run npm run code:index:test first.");o.import(i.symbols,i.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:Pe(),graph:o}),c=await a.initialize(),l=process.argv.slice(2).join(" ")||"memory storage hugging face",d=await a.search(l,5);console.log({ok:!0,query:l,...c,results:d.map(p=>({score:Number(p.score.toFixed(4)),file:p.chunk.filePath,symbol:p.chunk.symbolName,lines:`${p.chunk.startLine}-${p.chunk.endLine}`,preview:p.chunk.content.replace(/\s+/g," ").slice(0,140)}))})}jt().catch(r=>{console.error(r),process.exit(1)});
1
+ import"dotenv/config";import{existsSync as Re,readFileSync as ke}from"node:fs";import{homedir as Ie}from"node:os";import{join as Te}from"node:path";function _e(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 Me(){let r=process.env.TOOLNET_GLOBAL_ENV??Te(Ie(),".config","toolnet-memory",".env");if(!Re(r))return;let e=ke(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 i=s.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=_e(s.slice(o+1)))}}Me();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 le(){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 Ne}from"node:crypto";import{existsSync as te,mkdirSync as Oe,readFileSync as je,renameSync as De,writeFileSync as Fe}from"node:fs";import{basename as Ke,dirname as D,join as K,parse as ue,resolve as _}from"node:path";var me=".toolnet",$e="project.json";function Ge(r){return Ne("sha256").update(r).digest("hex").slice(0,16)}function re(r){return K(r,me,$e)}function Ue(r){return te(re(r))}function Be(r,e){let t=_(r),s=ue(t).root;for(;;){if(Ue(t))return t;if(t===s||e&&t===_(e))break;let o=D(t);if(o===t)break;t=o}return null}function ze(r){let e=_(r),t=ue(e).root,s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(s.some(i=>te(K(e,i))))return e;if(e===t)break;let o=D(e);if(o===e)break;e=o}return _(r)}function He(r){let e;try{e=JSON.parse(je(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 de(r,e){let t=K(r,me);Oe(t,{recursive:!0});let s=re(r),o=`${s}.tmp-${process.pid}`;Fe(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),De(o,s)}function pe(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=ze(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>te(K(s,p))),a=Be(t,i?s:void 0);if(a){let p=re(a),f=He(p);return f.rootPath!==a&&(f.rootPath=a,f.updatedAt=new Date().toISOString(),de(a,f)),pe(f,a)}let c=new Date().toISOString(),l=Ke(s),d={version:1,id:Ge(s),name:l,remote:l,rootPath:s,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return de(s,d),pe(d,s)}};var Ve=[{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 Ve){let o=new RegExp(s.regex.source,s.regex.flags);for(let i of e.matchAll(o))t.push({type:s.type,value:i[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 i of s)o.add(i.type),t=t.split(i.value).join(`[REDACTED:${i.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 i=s.toLowerCase();i.includes("password")||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")?t[s]="[REDACTED]":t[s]=this.sanitizeValue(o)}return t}return e}};import{homedir as gt}from"node:os";import{join as ht}from"node:path";import{DeleteObjectCommand as We,GetObjectCommand as Ye,HeadObjectCommand as qe,ListObjectsV2Command as Je,PutObjectCommand as Qe,S3Client as Ze}from"@aws-sdk/client-s3";import{getSignedUrl as Xe}from"@aws-sdk/s3-request-presigner";var G=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,s="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Qe({Bucket:this.bucket,Key:e,Body:o,ContentType:s}))}async get(e){let t=await Xe(this.client,new Ye({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 qe({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 We({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],s;do{let o=await this.client.send(new Je({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:s}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});s=o.IsTruncated?o.NextContinuationToken:void 0}while(s);return t}};import{access as fe,mkdir as et,readFile as tt,readdir as rt,rm as st,stat as ge,writeFile as ot}from"node:fs/promises";import{dirname as nt,join as it,relative as he,resolve as at}from"node:path";var N=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return at(this.root,t)}async put(e,t){let s=this.path(e);await et(nt(s),{recursive:!0}),await ot(s,t)}async get(e){try{return await tt(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 fe(this.path(e)),!0}catch{return!1}}async delete(e){await st(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),s=[];try{await fe(t)}catch{return s}let o=async a=>{let c=await rt(a,{withFileTypes:!0});for(let l of c){let d=it(a,l.name);if(l.isDirectory()){await o(d);continue}let p=await ge(d);s.push({key:he(this.root,d),size:p.size,updatedAt:p.mtime.toISOString()})}},i=await ge(t);return i.isDirectory()?await o(t):s.push({key:he(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),s}};import{DeleteObjectCommand as ct,GetObjectCommand as lt,HeadObjectCommand as dt,ListObjectsV2Command as pt,PutObjectCommand as ut,S3Client as mt}from"@aws-sdk/client-s3";import{getSignedUrl as ft}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 mt({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 ut({Bucket:this.bucket,Key:e,Body:o,ContentType:s}))}async get(e){let t=await ft(this.client,new lt({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 dt({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 ct({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],s;do{let o=await this.client.send(new pt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:s}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});s=o.IsTruncated?o.NextContinuationToken:void 0}while(s);return t}};function se(r,e){return console.warn(e),new N(r)}function ye(r){let e=r.localRoot??ht(gt(),".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}):se(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}):se(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}):se(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 be(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 Se(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=be(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 i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:s,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=Se(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 A=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 Et}from"node:child_process";import{promisify as Ct}from"node:util";var Qs=Ct(Et);import{createHash as vt}from"node:crypto";import{readFile as xt}from"node:fs/promises";import{join as wt}from"node:path";function Ee(r){return vt("sha256").update(r).digest("hex")}var H=class{sanitizer=new M;async build(e,t,s,o={}){let i=o.maxLines??80,a=o.overlapLines??10,c=new Map;for(let d of s){let p=c.get(d.filePath)??[];p.push(d),c.set(d.filePath,p)}let l=[];for(let[d,p]of c){let f;try{f=await xt(wt(t,d),"utf8")}catch{continue}let y=f.split(/\r?\n/),E=p.filter(b=>b.type!=="file"&&typeof b.startLine=="number"&&typeof b.endLine=="number");if(E.length>0)for(let b of E)l.push(...this.chunkRange({projectId:e,filePath:d,lines:y,symbol:b,startLine:b.startLine,endLine:b.endLine,maxLines:i,overlapLines:a}));else l.push(...this.chunkRange({projectId:e,filePath:d,lines:y,startLine:1,endLine:Math.max(1,y.length),maxLines:i,overlapLines:a}))}return l}chunkRange(e){let{projectId:t,filePath:s,lines:o,symbol:i,maxLines:a}=e,c=Math.min(e.overlapLines,Math.max(0,a-1)),l=Math.max(1,e.startLine),d=Math.min(o.length,Math.max(l,e.endLine)),p=[],f=l,y=0;for(;f<=d;){let E=Math.min(d,f+a-1),b=o.slice(f-1,E).join(`
5
+ `).trim();if(b){let v=this.sanitizer.sanitize(b).text,L=Ee(v),R=[t,s,i?.id??"file",String(y),L].join(":");p.push({id:Ee(R).slice(0,32),projectId:t,filePath:s,symbolId:i?.id,symbolName:i?.qualifiedName??i?.name,symbolType:i?.type,startLine:f,endLine:E,content:v,contentHash:L})}if(E>=d)break;f=E-c+1,y++}return p}};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 i of this.records.values()){if(i.projectId!==e)continue;let a=Pt(t,i.vector);o.push({id:i.id,score:a,metadata:i.metadata})}return o.sort((i,a)=>a.score-i.score).slice(0,s)}size(){return this.records.size}};function Pt(r,e){if(r.length===0||e.length===0||r.length!==e.length)return 0;let t=0,s=0,o=0;for(let i=0;i<r.length;i++){let a=r[i]??0,c=e[i]??0;t+=a*c,s+=a*a,o+=c*c}return s===0||o===0?0:t/(Math.sqrt(s)*Math.sqrt(o))}function oe(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}function Ce(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(){let{projectId:e,rootPath:t,storage:s,embeddings:o,graph:i,model:a}=this.options,c=new U(s),l=new B(s),d=await new H().build(e,t,i.allSymbols(e));this.chunks.clear();for(let g of d)this.chunks.set(g.id,g);let p=await c.load(e),f=!p||p.chunks.length!==d.length||p.chunks.some(g=>!this.chunks.has(g.id));f&&await c.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:d});let y=await l.load(e),E=0;y&&y.model===a&&(E=this.vectors.importRecords(y.records));let b=new Set(d.map(g=>g.id)),v=0;for(let g of this.vectors.exportProject(e))b.has(g.id)||this.vectors.remove(g.id)&&v++;let L=d.filter(g=>{let w=this.vectors.get(g.id);return w?w.metadata?.contentHash!==g.contentHash:!0}),R=0,ae=8,k=this.vectors.exportProject(e)[0]?.vector.length;for(let g=0;g<L.length;g+=ae){let w=L.slice(g,g+ae),Ae=w.map(C=>[`file: ${C.filePath}`,C.symbolName?`symbol: ${C.symbolName}`:"",C.symbolType?`type: ${C.symbolType}`:"",C.content].filter(Boolean).join(`
6
+ `)),Le=await o.embedMany(Ae);for(let C=0;C<w.length;C++){let x=w[C],P=Le[C];if(!(!x||!P||P.length===0)){if(k===void 0&&(k=P.length),P.length!==k){console.warn(`[code-semantic] skip dimension mismatch: ${P.length} != ${k}`);continue}this.vectors.upsert({id:x.id,projectId:e,vector:P,metadata:{contentHash:x.contentHash,filePath:x.filePath,symbolName:x.symbolName,symbolType:x.symbolType,startLine:x.startLine,endLine:x.endLine}}),R++}}}let ee=this.vectors.exportProject(e),ce=R>0||v>0||!y||y.model!==a;return ce&&await l.save({version:1,projectId:e,model:a,dimensions:ee[0]?.vector.length??k??0,updatedAt:new Date().toISOString(),records:ee}),{chunks:d.length,vectorsLoaded:E,vectorsIndexed:R,vectorsRemoved:v,totalVectors:ee.length,savedChunks:f,savedVectors:ce}}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)),i=new Set(oe(e)),a=[];for(let c of o){let l=this.chunks.get(c.id);if(!l)continue;let d=new Set(oe([l.filePath,l.symbolName??"",l.symbolType??"",l.content].join(" "))),p=0;for(let v of i)d.has(v)&&p++;let f=i.size===0?0:p/i.size,y=Math.max(0,c.score),E=Ce(l.filePath,e),b=(y*.75+f*.25)*E;a.push({chunk:l,score:b,vectorScore:y,lexicalScore:f})}return a.sort((c,l)=>l.score-c.score).slice(0,t)}size(){return this.chunks.size}};import*as S from"typescript";import*as u from"typescript";var on=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]);var ve=[{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=ve.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function q(r){return ve.some(e=>e.id===r)}function n(r){return process.env[r]?.trim()||void 0}function m(...r){return r.find(e=>!!e?.trim())}function xe(){if(n("GROQ_API_KEY"))return"groq";if(n("DEEPSEEK_API_KEY"))return"deepseek";if(n("NVIDIA_API_KEY")||n("NVIDIA_NIM_API_KEY"))return"nvidia";if(n("OPENROUTER_API_KEY"))return"openrouter";if(n("ALIBABA_API_KEY")||n("DASHSCOPE_API_KEY"))return"alibaba";if(n("GEMINI_API_KEY")||n("GOOGLE_API_KEY"))return"gemini";if(n("CLOUDFLARE_API_TOKEN")&&n("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(n("HF_TOKEN"))return"huggingface";if(n("OLLAMA_MODEL")||n("OLLAMA_BASE_URL"))return"ollama"}function Lt(){let r=n("TOOLNET_LLM_PROVIDER");return r&&q(r)?r:xe()??"openai-compatible"}function ne(r){let e=Y(r);switch(r){case"alibaba":return{provider:r,apiKey:m(n("ALIBABA_API_KEY"),n("DASHSCOPE_API_KEY")),baseUrl:m(n("ALIBABA_BASE_URL"),n("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:m(n("ALIBABA_MODEL"),n("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:n("OPENROUTER_API_KEY"),baseUrl:m(n("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:n("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:n("GROQ_API_KEY"),baseUrl:m(n("GROQ_BASE_URL"),e.defaultBaseUrl),model:n("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:n("DEEPSEEK_API_KEY"),baseUrl:m(n("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:m(n("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:m(n("NVIDIA_API_KEY"),n("NVIDIA_NIM_API_KEY")),baseUrl:m(n("NVIDIA_BASE_URL"),n("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:m(n("NVIDIA_MODEL"),n("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:m(n("GEMINI_API_KEY"),n("GOOGLE_API_KEY")),baseUrl:m(n("GEMINI_BASE_URL"),e.defaultBaseUrl),model:n("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:n("HF_TOKEN"),baseUrl:m(n("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:m(n("HF_LLM_MODEL"),n("HF_MODEL"))};case"ollama":return{provider:r,apiKey:n("OLLAMA_API_KEY"),baseUrl:m(n("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:n("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:n("CLOUDFLARE_ACCOUNT_ID"),apiKey:n("CLOUDFLARE_API_TOKEN"),baseUrl:n("CLOUDFLARE_AI_BASE_URL"),model:n("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:n("CUSTOM_AI_API_KEY"),baseUrl:n("CUSTOM_AI_BASE_URL"),model:n("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:m(n("OPENAI_API_KEY"),n("MODEL_API_KEY")),baseUrl:m(n("OPENAI_BASE_URL"),n("MODEL_BASE_URL")),model:m(n("OPENAI_MODEL"),n("MODEL_NAME"))}}}function Rt(){let r=n("TOOLNET_LLM_PROVIDER"),e=r&&q(r)?r:Lt(),t=Y(e),s=ne(e);return{provider:e,apiKey:m(n("TOOLNET_LLM_API_KEY"),s.apiKey),baseUrl:m(n("TOOLNET_LLM_BASE_URL"),s.baseUrl,t.defaultBaseUrl),model:m(n("TOOLNET_LLM_MODEL"),s.model,t.defaultModel),accountId:m(n("TOOLNET_LLM_ACCOUNT_ID"),s.accountId)}}function kt(){let r=n("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&q(r)?r:n("HF_TOKEN")||n("HF_EMBEDDING_MODEL")?"huggingface":"local"}function It(){let r=kt();if(r==="local")return{provider:"local",model:m(n("TOOLNET_EMBEDDING_MODEL"),n("LOCAL_EMBEDDING_MODEL"))};let e=Y(r),t,s,o,i;switch(r){case"huggingface":t=n("HF_TOKEN"),s=n("HF_INFERENCE_BASE_URL"),o=n("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=n("OPENAI_API_KEY"),s=n("OPENAI_BASE_URL"),o=n("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=n("CLOUDFLARE_API_TOKEN"),s=n("CLOUDFLARE_AI_BASE_URL"),o=n("CLOUDFLARE_EMBEDDING_MODEL"),i=n("CLOUDFLARE_ACCOUNT_ID");break;default:t=ne(r).apiKey,s=ne(r).baseUrl,o=n(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let a=m(n("TOOLNET_EMBEDDING_ACCOUNT_ID"),i),c=m(n("TOOLNET_EMBEDDING_BASE_URL"),s,e.defaultBaseUrl),l=r==="cloudflare"&&!c&&a?`https://api.cloudflare.com/client/v4/accounts/${a}/ai/v1`:c;return{provider:r,apiKey:m(n("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:l,model:m(n("TOOLNET_EMBEDDING_MODEL"),o),accountId:a}}function we(){let r=Rt(),e=It();return{llm:r,embedding:e,legacy:{llm:!n("TOOLNET_LLM_PROVIDER")&&!!xe(),embedding:!n("TOOLNET_EMBEDDING_PROVIDER")&&!!(n("HF_TOKEN")||n("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)}`,i=await fetch(o,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${t}`,content:{parts:[{text:e}]}})});if(!i.ok)throw new Error(`Gemini embedding failed: ${i.status} ${await i.text()}`);let c=(await i.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 Tt}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=Tt("sha256").update(o).digest().readUInt32BE(0)%this.dimensions;t[a]+=1}return _t(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function _t(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 i=(await s.json()).data?.sort((a,c)=>(a.index??0)-(c.index??0)).map(a=>a.embedding);if(!i||i.length!==e.length||i.some(a=>!Array.isArray(a)))throw new Error("Embedding provider returned invalid response");return i}};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(i=>Mt(i))}};function Mt(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 i=0;i<t;i++)s[i]+=o[i]??0;for(let o=0;o<t;o++)s[o]/=e.length;return s}throw new Error("Unsupported embedding shape")}var ie=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 Nt(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function Ot(){let r=we().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=Nt(r.accountId)),e&&r.model?new Z({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function Pe(){return new ie(Ot())}async function jt(){let r=le(),e=new F().detect(),t=ye({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 A,i=await new j(s).load(e.id);if(!i)throw new Error("Code graph missing. Run npm run code:index:test first.");o.import(i.symbols,i.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:Pe(),graph:o}),c=await a.initialize(),l=process.argv.slice(2).join(" ")||"memory storage hugging face",d=await a.search(l,5);console.log({ok:!0,query:l,...c,results:d.map(p=>({score:Number(p.score.toFixed(4)),file:p.chunk.filePath,symbol:p.chunk.symbolName,lines:`${p.chunk.startLine}-${p.chunk.endLine}`,preview:p.chunk.content.replace(/\s+/g," ").slice(0,140)}))})}jt().catch(r=>{console.error(r),process.exit(1)});