toolnet-memory 0.2.15 → 0.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import"dotenv/config";import{existsSync as Le,readFileSync as Re}from"node:fs";import{homedir as Te}from"node:os";import{join as Ie}from"node:path";function _e(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 ke(){let s=process.env.TOOLNET_GLOBAL_ENV??Ie(Te(),".config","toolnet-memory",".env");if(!Le(s))return;let e=Re(s,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let i=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=_e(r.slice(o+1)))}}ke();function I(s,e){return s===void 0?e:["1","true","yes","on"].includes(s.toLowerCase())}function _(s,e){if(!s)return e;let t=Number(s);return Number.isFinite(t)?t:e}function ce(){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:_(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:_(process.env.MEMORY_RERANK_TOP,10),finalContext:_(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:_(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:_(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Ne}from"node:crypto";import{existsSync as ee,mkdirSync as Me,readFileSync as Oe,renameSync as je,writeFileSync as De}from"node:fs";import{basename as Fe,dirname as D,join as K,parse as pe,resolve as k}from"node:path";var me=".toolnet",Ke="project.json";function Ge(s){return Ne("sha256").update(s).digest("hex").slice(0,16)}function te(s){return K(s,me,Ke)}function $e(s){return ee(te(s))}function Be(s,e){let t=k(s),r=pe(t).root;for(;;){if($e(t))return t;if(t===r||e&&t===k(e))break;let o=D(t);if(o===t)break;t=o}return null}function Ue(s){let e=k(s),t=pe(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(i=>ee(K(e,i))))return e;if(e===t)break;let o=D(e);if(o===e)break;e=o}return k(s)}function ze(s){let e;try{e=JSON.parse(Oe(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:D(D(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 le(s,e){let t=K(s,me);Me(t,{recursive:!0});let r=te(s),o=`${r}.tmp-${process.pid}`;De(o,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),je(o,r)}function de(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 F=class{detect(e=process.cwd()){let t=k(e),r=Ue(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>ee(K(r,p))),a=Be(t,i?r:void 0);if(a){let p=te(a),f=ze(p);return f.rootPath!==a&&(f.rootPath=a,f.updatedAt=new Date().toISOString(),le(a,f)),de(f,a)}let c=new Date().toISOString(),d=Fe(r),l={version:1,id:Ge(r),name:d,remote:d,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return le(r,l),de(l,r)}};var He=[{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}],G=class{scan(e){let t=[];for(let r of He){let o=new RegExp(r.regex.source,r.regex.flags);for(let i of e.matchAll(o))t.push({type:r.type,value:i[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var N=class{scanner=new G;sanitize(e){let t=e,r=this.scanner.scan(e),o=new Set;for(let i of r)o.add(i.type),t=t.split(i.value).join(`[REDACTED:${i.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 i=r.toLowerCase();i.includes("password")||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")?t[r]="[REDACTED]":t[r]=this.sanitizeValue(o)}return t}return e}};import{homedir as ft}from"node:os";import{join as gt}from"node:path";import{DeleteObjectCommand as Ve,GetObjectCommand as We,HeadObjectCommand as Ye,ListObjectsV2Command as qe,PutObjectCommand as Je,S3Client as Qe}from"@aws-sdk/client-s3";import{getSignedUrl as Ze}from"@aws-sdk/s3-request-presigner";var $=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Qe({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 Je({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await Ze(this.client,new We({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 Ye({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 Ve({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new qe({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};import{access as ue,mkdir as Xe,readFile as et,readdir as tt,rm as rt,stat as fe,writeFile as st}from"node:fs/promises";import{dirname as ot,join as nt,relative as ge,resolve as it}from"node:path";var M=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return it(this.root,t)}async put(e,t){let r=this.path(e);await Xe(ot(r),{recursive:!0}),await st(r,t)}async get(e){try{return await et(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 ue(this.path(e)),!0}catch{return!1}}async delete(e){await rt(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await ue(t)}catch{return r}let o=async a=>{let c=await tt(a,{withFileTypes:!0});for(let d of c){let l=nt(a,d.name);if(d.isDirectory()){await o(l);continue}let p=await fe(l);r.push({key:ge(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},i=await fe(t);return i.isDirectory()?await o(t):r.push({key:ge(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),r}};import{DeleteObjectCommand as at,GetObjectCommand as ct,HeadObjectCommand as lt,ListObjectsV2Command as dt,PutObjectCommand as pt,S3Client as mt}from"@aws-sdk/client-s3";import{getSignedUrl as ut}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,r="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new pt({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await ut(this.client,new ct({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 lt({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 at({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new dt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};function re(s,e){return console.warn(e),new M(s)}function he(s){let e=s.localRoot??gt(ft(),".toolnet-memory","storage");if(s.provider==="r2"){let t=s.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}):re(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 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}):re(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 $({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):re(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 B=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 U=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 ye(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 Se(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=ye(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 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"&&(r=a.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=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,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 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(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 bt}from"node:child_process";import{promisify as Et}from"node:util";var Us=Et(bt);import{createHash as Ct}from"node:crypto";import{readFile as vt}from"node:fs/promises";import{join as xt}from"node:path";function be(s){return Ct("sha256").update(s).digest("hex")}var H=class{sanitizer=new N;async build(e,t,r,o={}){let i=o.maxLines??80,a=o.overlapLines??10,c=new Map;for(let l of r){let p=c.get(l.filePath)??[];p.push(l),c.set(l.filePath,p)}let d=[];for(let[l,p]of c){let f;try{f=await vt(xt(t,l),"utf8")}catch{continue}let y=f.split(/\r?\n/),E=p.filter(S=>S.type!=="file"&&typeof S.startLine=="number"&&typeof S.endLine=="number");if(E.length>0)for(let S of E)d.push(...this.chunkRange({projectId:e,filePath:l,lines:y,symbol:S,startLine:S.startLine,endLine:S.endLine,maxLines:i,overlapLines:a}));else d.push(...this.chunkRange({projectId:e,filePath:l,lines:y,startLine:1,endLine:Math.max(1,y.length),maxLines:i,overlapLines:a}))}return d}chunkRange(e){let{projectId:t,filePath:r,lines:o,symbol:i,maxLines:a}=e,c=Math.min(e.overlapLines,Math.max(0,a-1)),d=Math.max(1,e.startLine),l=Math.min(o.length,Math.max(d,e.endLine)),p=[],f=d,y=0;for(;f<=l;){let E=Math.min(l,f+a-1),S=o.slice(f-1,E).join(`
5
- `).trim();if(S){let v=this.sanitizer.sanitize(S).text,L=be(v),R=[t,r,i?.id??"file",String(y),L].join(":");p.push({id:be(R).slice(0,32),projectId:t,filePath:r,symbolId:i?.id,symbolName:i?.qualifiedName??i?.name,symbolType:i?.type,startLine:f,endLine:E,content:v,contentHash:L})}if(E>=l)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[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 i of this.records.values()){if(i.projectId!==e)continue;let a=wt(t,i.vector);o.push({id:i.id,score:a,metadata:i.metadata})}return o.sort((i,a)=>a.score-i.score).slice(0,r)}size(){return this.records.size}};function wt(s,e){if(s.length===0||e.length===0||s.length!==e.length)return 0;let t=0,r=0,o=0;for(let i=0;i<s.length;i++){let a=s[i]??0,c=e[i]??0;t+=a*c,r+=a*a,o+=c*c}return r===0||o===0?0:t/(Math.sqrt(r)*Math.sqrt(o))}function se(s){return s.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}function Ee(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 V;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:r,embeddings:o,graph:i,model:a}=this.options,c=new B(r),d=new U(r),l=await new H().build(e,t,i.allSymbols(e));this.chunks.clear();for(let g of l)this.chunks.set(g.id,g);let p=await c.load(e),f=!p||p.chunks.length!==l.length||p.chunks.some(g=>!this.chunks.has(g.id));f&&await c.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:l});let y=await d.load(e),E=0;y&&y.model===a&&(E=this.vectors.importRecords(y.records));let S=new Set(l.map(g=>g.id)),v=0;for(let g of this.vectors.exportProject(e))S.has(g.id)||this.vectors.remove(g.id)&&v++;let L=l.filter(g=>{let w=this.vectors.get(g.id);return w?w.metadata?.contentHash!==g.contentHash:!0}),R=0,ie=8,T=this.vectors.exportProject(e)[0]?.vector.length;for(let g=0;g<L.length;g+=ie){let w=L.slice(g,g+ie),Pe=w.map(C=>[`file: ${C.filePath}`,C.symbolName?`symbol: ${C.symbolName}`:"",C.symbolType?`type: ${C.symbolType}`:"",C.content].filter(Boolean).join(`
6
- `)),Ae=await o.embedMany(Pe);for(let C=0;C<w.length;C++){let x=w[C],P=Ae[C];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 X=this.vectors.exportProject(e),ae=R>0||v>0||!y||y.model!==a;return ae&&await d.save({version:1,projectId:e,model:a,dimensions:X[0]?.vector.length??T??0,updatedAt:new Date().toISOString(),records:X}),{chunks:l.length,vectorsLoaded:E,vectorsIndexed:R,vectorsRemoved:v,totalVectors:X.length,savedChunks:f,savedVectors:ae}}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)),i=new Set(se(e)),a=[];for(let c of o){let d=this.chunks.get(c.id);if(!d)continue;let l=new Set(se([d.filePath,d.symbolName??"",d.symbolType??"",d.content].join(" "))),p=0;for(let v of i)l.has(v)&&p++;let f=i.size===0?0:p/i.size,y=Math.max(0,c.score),E=Ee(d.filePath,e),S=(y*.75+f*.25)*E;a.push({chunk:d,score:S,vectorScore:y,lexicalScore:f})}return a.sort((c,d)=>d.score-c.score).slice(0,t)}size(){return this.chunks.size}};import*as b from"typescript";import*as m from"typescript";var Jo=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(s){let e=Ce.find(t=>t.id===s);if(!e)throw new Error(`Unsupported AI provider: ${s}`);return e}function q(s){return Ce.some(e=>e.id===s)}function n(s){return process.env[s]?.trim()||void 0}function u(...s){return s.find(e=>!!e?.trim())}function ve(){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 At(){let s=n("TOOLNET_LLM_PROVIDER");return s&&q(s)?s:ve()??"openai-compatible"}function oe(s){let e=Y(s);switch(s){case"alibaba":return{provider:s,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:s,apiKey:n("OPENROUTER_API_KEY"),baseUrl:u(n("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:n("OPENROUTER_MODEL")};case"groq":return{provider:s,apiKey:n("GROQ_API_KEY"),baseUrl:u(n("GROQ_BASE_URL"),e.defaultBaseUrl),model:n("GROQ_MODEL")};case"deepseek":return{provider:s,apiKey:n("DEEPSEEK_API_KEY"),baseUrl:u(n("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:u(n("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:s,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:s,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:s,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:s,apiKey:n("OLLAMA_API_KEY"),baseUrl:u(n("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:n("OLLAMA_MODEL")};case"cloudflare":return{provider:s,accountId:n("CLOUDFLARE_ACCOUNT_ID"),apiKey:n("CLOUDFLARE_API_TOKEN"),baseUrl:n("CLOUDFLARE_AI_BASE_URL"),model:n("CLOUDFLARE_MODEL")};case"custom":return{provider:s,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 Lt(){let s=n("TOOLNET_LLM_PROVIDER"),e=s&&q(s)?s:At(),t=Y(e),r=oe(e);return{provider:e,apiKey:u(n("TOOLNET_LLM_API_KEY"),r.apiKey),baseUrl:u(n("TOOLNET_LLM_BASE_URL"),r.baseUrl,t.defaultBaseUrl),model:u(n("TOOLNET_LLM_MODEL"),r.model,t.defaultModel),accountId:u(n("TOOLNET_LLM_ACCOUNT_ID"),r.accountId)}}function Rt(){let s=n("TOOLNET_EMBEDDING_PROVIDER");return s==="local"?"local":s&&q(s)?s:n("HF_TOKEN")||n("HF_EMBEDDING_MODEL")?"huggingface":"local"}function Tt(){let s=Rt();if(s==="local")return{provider:"local",model:u(n("TOOLNET_EMBEDDING_MODEL"),n("LOCAL_EMBEDDING_MODEL"))};let e=Y(s),t,r,o,i;switch(s){case"huggingface":t=n("HF_TOKEN"),r=n("HF_INFERENCE_BASE_URL"),o=n("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=n("OPENAI_API_KEY"),r=n("OPENAI_BASE_URL"),o=n("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=n("CLOUDFLARE_API_TOKEN"),r=n("CLOUDFLARE_AI_BASE_URL"),o=n("CLOUDFLARE_EMBEDDING_MODEL"),i=n("CLOUDFLARE_ACCOUNT_ID");break;default:t=oe(s).apiKey,r=oe(s).baseUrl,o=n(`${s.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}return{provider:s,apiKey:u(n("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:u(n("TOOLNET_EMBEDDING_BASE_URL"),r,e.defaultBaseUrl),model:u(n("TOOLNET_EMBEDDING_MODEL"),o),accountId:u(n("TOOLNET_EMBEDDING_ACCOUNT_ID"),i)}}function xe(){let s=Lt(),e=Tt();return{llm:s,embedding:e,legacy:{llm:!n("TOOLNET_LLM_PROVIDER")&&!!ve(),embedding:!n("TOOLNET_EMBEDDING_PROVIDER")&&!!(n("HF_TOKEN")||n("HF_EMBEDDING_MODEL"))}}}var J=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(i=>It(i))}};function It(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 i=0;i<t;i++)r[i]+=o[i]??0;for(let o=0;o<t;o++)r[o]/=e.length;return r}throw new Error("Unsupported embedding shape")}import{createHash as _t}from"node:crypto";var Q=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 a=_t("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(s){let e=Math.sqrt(s.reduce((t,r)=>t+r*r,0));return e===0?s:s.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(/\/+$/,""),r=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(!r.ok)throw new Error(`Embedding failed: ${r.status} ${await r.text()}`);let i=(await r.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 ne=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(){let s=xe().embedding;return s.provider==="local"?null:s.provider==="huggingface"?!s.apiKey||!s.model?null:new J({token:s.apiKey,model:s.model}):s.baseUrl&&s.model?new Z({apiKey:s.apiKey,baseUrl:s.baseUrl,model:s.model}):null}function we(){return new ne(Nt())}async function Mt(){let s=ce(),e=new F().detect(),t=he({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 A,i=await new j(r).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:r,embeddings:we(),graph:o}),c=await a.initialize(),d=process.argv.slice(2).join(" ")||"memory storage hugging face",l=await a.search(d,5);console.log({ok:!0,query:d,...c,results:l.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)}))})}Mt().catch(s=>{console.error(s),process.exit(1)});
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)});
package/bundle/setup.js CHANGED
@@ -1,7 +1,7 @@
1
- import m from"node:fs";import j from"node:os";import R from"node:path";import ze from"node:readline/promises";import{stdin as f,stdout as I}from"node:process";import{HeadBucketCommand as Ze,S3Client as Qe}from"@aws-sdk/client-s3";var W=[{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 A(e){let t=W.find(o=>o.id===e);if(!t)throw new Error(`Unsupported AI provider: ${e}`);return t}function N(e){return W.some(t=>t.id===e)}function i(e){return process.env[e]?.trim()||void 0}function g(...e){return e.find(t=>!!t?.trim())}function X(){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 z(){let e=i("TOOLNET_LLM_PROVIDER");return e&&N(e)?e:X()??"openai-compatible"}function h(e){let t=A(e);switch(e){case"alibaba":return{provider:e,apiKey:g(i("ALIBABA_API_KEY"),i("DASHSCOPE_API_KEY")),baseUrl:g(i("ALIBABA_BASE_URL"),i("DASHSCOPE_BASE_URL"),t.defaultBaseUrl),model:g(i("ALIBABA_MODEL"),i("DASHSCOPE_MODEL"))};case"openrouter":return{provider:e,apiKey:i("OPENROUTER_API_KEY"),baseUrl:g(i("OPENROUTER_BASE_URL"),t.defaultBaseUrl),model:i("OPENROUTER_MODEL")};case"groq":return{provider:e,apiKey:i("GROQ_API_KEY"),baseUrl:g(i("GROQ_BASE_URL"),t.defaultBaseUrl),model:i("GROQ_MODEL")};case"deepseek":return{provider:e,apiKey:i("DEEPSEEK_API_KEY"),baseUrl:g(i("DEEPSEEK_BASE_URL"),t.defaultBaseUrl),model:g(i("DEEPSEEK_MODEL"),t.defaultModel)};case"nvidia":return{provider:e,apiKey:g(i("NVIDIA_API_KEY"),i("NVIDIA_NIM_API_KEY")),baseUrl:g(i("NVIDIA_BASE_URL"),i("NVIDIA_NIM_BASE_URL"),t.defaultBaseUrl),model:g(i("NVIDIA_MODEL"),i("NVIDIA_NIM_MODEL"),t.defaultModel)};case"gemini":return{provider:e,apiKey:g(i("GEMINI_API_KEY"),i("GOOGLE_API_KEY")),baseUrl:g(i("GEMINI_BASE_URL"),t.defaultBaseUrl),model:i("GEMINI_MODEL")};case"huggingface":return{provider:e,apiKey:i("HF_TOKEN"),baseUrl:g(i("HF_INFERENCE_BASE_URL"),t.defaultBaseUrl),model:g(i("HF_LLM_MODEL"),i("HF_MODEL"))};case"ollama":return{provider:e,apiKey:i("OLLAMA_API_KEY"),baseUrl:g(i("OLLAMA_BASE_URL"),t.defaultBaseUrl),model:i("OLLAMA_MODEL")};case"cloudflare":return{provider:e,accountId:i("CLOUDFLARE_ACCOUNT_ID"),apiKey:i("CLOUDFLARE_API_TOKEN"),baseUrl:i("CLOUDFLARE_AI_BASE_URL"),model:i("CLOUDFLARE_MODEL")};case"custom":return{provider:e,apiKey:i("CUSTOM_AI_API_KEY"),baseUrl:i("CUSTOM_AI_BASE_URL"),model:i("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:g(i("OPENAI_API_KEY"),i("MODEL_API_KEY")),baseUrl:g(i("OPENAI_BASE_URL"),i("MODEL_BASE_URL")),model:g(i("OPENAI_MODEL"),i("MODEL_NAME"))}}}function Te(){let e=i("TOOLNET_LLM_PROVIDER"),t=e&&N(e)?e:z(),o=A(t),n=h(t);return{provider:t,apiKey:g(i("TOOLNET_LLM_API_KEY"),n.apiKey),baseUrl:g(i("TOOLNET_LLM_BASE_URL"),n.baseUrl,o.defaultBaseUrl),model:g(i("TOOLNET_LLM_MODEL"),n.model,o.defaultModel),accountId:g(i("TOOLNET_LLM_ACCOUNT_ID"),n.accountId)}}function Ae(){let e=i("TOOLNET_EMBEDDING_PROVIDER");return e==="local"?"local":e&&N(e)?e:i("HF_TOKEN")||i("HF_EMBEDDING_MODEL")?"huggingface":"local"}function Se(){let e=Ae();if(e==="local")return{provider:"local",model:g(i("TOOLNET_EMBEDDING_MODEL"),i("LOCAL_EMBEDDING_MODEL"))};let t=A(e),o,n,r,s;switch(e){case"huggingface":o=i("HF_TOKEN"),n=i("HF_INFERENCE_BASE_URL"),r=i("HF_EMBEDDING_MODEL");break;case"openai-compatible":o=i("OPENAI_API_KEY"),n=i("OPENAI_BASE_URL"),r=i("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":o=i("CLOUDFLARE_API_TOKEN"),n=i("CLOUDFLARE_AI_BASE_URL"),r=i("CLOUDFLARE_EMBEDDING_MODEL"),s=i("CLOUDFLARE_ACCOUNT_ID");break;default:o=h(e).apiKey,n=h(e).baseUrl,r=i(`${e.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}return{provider:e,apiKey:g(i("TOOLNET_EMBEDDING_API_KEY"),o),baseUrl:g(i("TOOLNET_EMBEDDING_BASE_URL"),n,t.defaultBaseUrl),model:g(i("TOOLNET_EMBEDDING_MODEL"),r),accountId:g(i("TOOLNET_EMBEDDING_ACCOUNT_ID"),s)}}function Ce(){let e=Te(),t=Se();return{llm:e,embedding:t,legacy:{llm:!i("TOOLNET_LLM_PROVIDER")&&!!X(),embedding:!i("TOOLNET_EMBEDDING_PROVIDER")&&!!(i("HF_TOKEN")||i("HF_EMBEDDING_MODEL"))}}}function Z(e=z()){let t=Ce().llm;if(e===t.provider)return{id:e,apiKey:t.apiKey,baseUrl:t.baseUrl,model:t.model,accountId:t.accountId};let o=h(e);return{id:e,apiKey:o.apiKey,baseUrl:o.baseUrl,model:o.model,accountId:o.accountId}}var w=class extends Error{status;constructor(t,o){super(t),this.name="AiHttpError",this.status=o}};async function S(e,t,o=3e4){let n=new AbortController,r=setTimeout(()=>n.abort(),o);r.unref?.();try{let s=await fetch(e,{...t,signal:n.signal}),a=await s.text();if(!s.ok){let l=a;try{let c=JSON.parse(a);l=c.error?.message??c.message??a}catch{}throw new w(l||`HTTP ${s.status}`,s.status)}return a.trim()?JSON.parse(a):{}}finally{clearTimeout(r)}}function D(e,t){return`${e.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`}var P=class{constructor(t){this.config=t}config;id="cloudflare";model(){let t=this.config.model?.trim();if(!t)throw new Error("cloudflare: MODEL is not configured");return t}async generate(t){let o=this.config.accountId?.trim(),n=this.config.apiKey?.trim();if(!o)throw new Error("cloudflare: ACCOUNT ID is not configured");if(!n)throw new Error("cloudflare: API TOKEN is not configured");let r=this.model(),a=`${(this.config.baseUrl?.trim()||`https://api.cloudflare.com/client/v4/accounts/${o}/ai/run`).replace(/\/+$/,"")}/${r}`,l=await S(a,{method:"POST",headers:{authorization:`Bearer ${n}`,"content-type":"application/json",...this.config.headers},body:JSON.stringify({messages:t.messages,temperature:t.temperature,max_tokens:t.maxTokens})}),c=l.result?.response?.trim();if(!c)throw new Error(l.errors?.[0]?.message??"cloudflare: empty model response");return{text:c,provider:"cloudflare",model:r}}async healthCheck(){let t=Date.now();try{return{ok:!0,provider:"cloudflare",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-t}}catch(o){return{ok:!1,provider:"cloudflare",model:this.config.model,message:o instanceof Error?o.message:String(o),latencyMs:Date.now()-t}}}};var U=class{constructor(t){this.config=t}config;id="gemini";model(){let t=this.config.model?.trim();if(!t)throw new Error("gemini: MODEL is not configured");return t.replace(/^models\//,"")}async generate(t){let o=this.config.apiKey?.trim();if(!o)throw new Error("gemini: API KEY is not configured");let n=this.config.baseUrl?.trim()||"https://generativelanguage.googleapis.com/v1beta",r=this.model(),s=t.messages.filter(E=>E.role==="system"),a=t.messages.filter(E=>E.role!=="system").map(E=>({role:E.role==="assistant"?"model":"user",parts:[{text:E.content}]})),l=`${D(n,`models/${encodeURIComponent(r)}:generateContent`)}?key=${encodeURIComponent(o)}`,c=await S(l,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({...s.length?{systemInstruction:{parts:[{text:s.map(E=>E.content).join(`
1
+ import p from"node:fs";import Z from"node:os";import h from"node:path";import Eo from"node:readline/promises";import{stdin as A,stdout as D}from"node:process";import{HeadBucketCommand as go,S3Client as _o}from"@aws-sdk/client-s3";var ie=[{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 C(e){let o=ie.find(t=>t.id===e);if(!o)throw new Error(`Unsupported AI provider: ${e}`);return o}function b(e){return ie.some(o=>o.id===e)}function c(e){return process.env[e]?.trim()||void 0}function L(...e){return e.find(o=>!!o?.trim())}function se(){if(c("GROQ_API_KEY"))return"groq";if(c("DEEPSEEK_API_KEY"))return"deepseek";if(c("NVIDIA_API_KEY")||c("NVIDIA_NIM_API_KEY"))return"nvidia";if(c("OPENROUTER_API_KEY"))return"openrouter";if(c("ALIBABA_API_KEY")||c("DASHSCOPE_API_KEY"))return"alibaba";if(c("GEMINI_API_KEY")||c("GOOGLE_API_KEY"))return"gemini";if(c("CLOUDFLARE_API_TOKEN")&&c("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(c("HF_TOKEN"))return"huggingface";if(c("OLLAMA_MODEL")||c("OLLAMA_BASE_URL"))return"ollama"}function ce(){let e=c("TOOLNET_LLM_PROVIDER");return e&&b(e)?e:se()??"openai-compatible"}function K(e){let o=C(e);switch(e){case"alibaba":return{provider:e,apiKey:L(c("ALIBABA_API_KEY"),c("DASHSCOPE_API_KEY")),baseUrl:L(c("ALIBABA_BASE_URL"),c("DASHSCOPE_BASE_URL"),o.defaultBaseUrl),model:L(c("ALIBABA_MODEL"),c("DASHSCOPE_MODEL"))};case"openrouter":return{provider:e,apiKey:c("OPENROUTER_API_KEY"),baseUrl:L(c("OPENROUTER_BASE_URL"),o.defaultBaseUrl),model:c("OPENROUTER_MODEL")};case"groq":return{provider:e,apiKey:c("GROQ_API_KEY"),baseUrl:L(c("GROQ_BASE_URL"),o.defaultBaseUrl),model:c("GROQ_MODEL")};case"deepseek":return{provider:e,apiKey:c("DEEPSEEK_API_KEY"),baseUrl:L(c("DEEPSEEK_BASE_URL"),o.defaultBaseUrl),model:L(c("DEEPSEEK_MODEL"),o.defaultModel)};case"nvidia":return{provider:e,apiKey:L(c("NVIDIA_API_KEY"),c("NVIDIA_NIM_API_KEY")),baseUrl:L(c("NVIDIA_BASE_URL"),c("NVIDIA_NIM_BASE_URL"),o.defaultBaseUrl),model:L(c("NVIDIA_MODEL"),c("NVIDIA_NIM_MODEL"),o.defaultModel)};case"gemini":return{provider:e,apiKey:L(c("GEMINI_API_KEY"),c("GOOGLE_API_KEY")),baseUrl:L(c("GEMINI_BASE_URL"),o.defaultBaseUrl),model:c("GEMINI_MODEL")};case"huggingface":return{provider:e,apiKey:c("HF_TOKEN"),baseUrl:L(c("HF_INFERENCE_BASE_URL"),o.defaultBaseUrl),model:L(c("HF_LLM_MODEL"),c("HF_MODEL"))};case"ollama":return{provider:e,apiKey:c("OLLAMA_API_KEY"),baseUrl:L(c("OLLAMA_BASE_URL"),o.defaultBaseUrl),model:c("OLLAMA_MODEL")};case"cloudflare":return{provider:e,accountId:c("CLOUDFLARE_ACCOUNT_ID"),apiKey:c("CLOUDFLARE_API_TOKEN"),baseUrl:c("CLOUDFLARE_AI_BASE_URL"),model:c("CLOUDFLARE_MODEL")};case"custom":return{provider:e,apiKey:c("CUSTOM_AI_API_KEY"),baseUrl:c("CUSTOM_AI_BASE_URL"),model:c("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:L(c("OPENAI_API_KEY"),c("MODEL_API_KEY")),baseUrl:L(c("OPENAI_BASE_URL"),c("MODEL_BASE_URL")),model:L(c("OPENAI_MODEL"),c("MODEL_NAME"))}}}function be(){let e=c("TOOLNET_LLM_PROVIDER"),o=e&&b(e)?e:ce(),t=C(o),n=K(o);return{provider:o,apiKey:L(c("TOOLNET_LLM_API_KEY"),n.apiKey),baseUrl:L(c("TOOLNET_LLM_BASE_URL"),n.baseUrl,t.defaultBaseUrl),model:L(c("TOOLNET_LLM_MODEL"),n.model,t.defaultModel),accountId:L(c("TOOLNET_LLM_ACCOUNT_ID"),n.accountId)}}function Ke(){let e=c("TOOLNET_EMBEDDING_PROVIDER");return e==="local"?"local":e&&b(e)?e:c("HF_TOKEN")||c("HF_EMBEDDING_MODEL")?"huggingface":"local"}function Ue(){let e=Ke();if(e==="local")return{provider:"local",model:L(c("TOOLNET_EMBEDDING_MODEL"),c("LOCAL_EMBEDDING_MODEL"))};let o=C(e),t,n,r,i;switch(e){case"huggingface":t=c("HF_TOKEN"),n=c("HF_INFERENCE_BASE_URL"),r=c("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=c("OPENAI_API_KEY"),n=c("OPENAI_BASE_URL"),r=c("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=c("CLOUDFLARE_API_TOKEN"),n=c("CLOUDFLARE_AI_BASE_URL"),r=c("CLOUDFLARE_EMBEDDING_MODEL"),i=c("CLOUDFLARE_ACCOUNT_ID");break;default:t=K(e).apiKey,n=K(e).baseUrl,r=c(`${e.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let s=L(c("TOOLNET_EMBEDDING_ACCOUNT_ID"),i),l=L(c("TOOLNET_EMBEDDING_BASE_URL"),n,o.defaultBaseUrl),a=e==="cloudflare"&&!l&&s?`https://api.cloudflare.com/client/v4/accounts/${s}/ai/v1`:l;return{provider:e,apiKey:L(c("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:a,model:L(c("TOOLNET_EMBEDDING_MODEL"),r),accountId:s}}function Be(){let e=be(),o=Ue();return{llm:e,embedding:o,legacy:{llm:!c("TOOLNET_LLM_PROVIDER")&&!!se(),embedding:!c("TOOLNET_EMBEDDING_PROVIDER")&&!!(c("HF_TOKEN")||c("HF_EMBEDDING_MODEL"))}}}function ae(e=ce()){let o=Be().llm;if(e===o.provider)return{id:e,apiKey:o.apiKey,baseUrl:o.baseUrl,model:o.model,accountId:o.accountId};let t=K(e);return{id:e,apiKey:t.apiKey,baseUrl:t.baseUrl,model:t.model,accountId:t.accountId}}var H=class extends Error{status;constructor(o,t){super(o),this.name="AiHttpError",this.status=t}};async function R(e,o,t=3e4){let n=new AbortController,r=setTimeout(()=>n.abort(),t);r.unref?.();try{let i=await fetch(e,{...o,signal:n.signal}),s=await i.text();if(!i.ok){let l=s;try{let a=JSON.parse(s);l=a.error?.message??a.message??s}catch{}throw new H(l||`HTTP ${i.status}`,i.status)}return s.trim()?JSON.parse(s):{}}finally{clearTimeout(r)}}function U(e,o){return`${e.replace(/\/+$/,"")}/${o.replace(/^\/+/,"")}`}var B=class{constructor(o){this.config=o}config;id="cloudflare";model(){let o=this.config.model?.trim();if(!o)throw new Error("cloudflare: MODEL is not configured");return o}async generate(o){let t=this.config.accountId?.trim(),n=this.config.apiKey?.trim();if(!t)throw new Error("cloudflare: ACCOUNT ID is not configured");if(!n)throw new Error("cloudflare: API TOKEN is not configured");let r=this.model(),s=`${(this.config.baseUrl?.trim()||`https://api.cloudflare.com/client/v4/accounts/${t}/ai/run`).replace(/\/+$/,"")}/${r}`,l=await R(s,{method:"POST",headers:{authorization:`Bearer ${n}`,"content-type":"application/json",...this.config.headers},body:JSON.stringify({messages:o.messages,temperature:o.temperature,max_tokens:o.maxTokens})}),a=l.result?.response?.trim();if(!a)throw new Error(l.errors?.[0]?.message??"cloudflare: empty model response");return{text:a,provider:"cloudflare",model:r}}async healthCheck(){let o=Date.now();try{return{ok:!0,provider:"cloudflare",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-o}}catch(t){return{ok:!1,provider:"cloudflare",model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-o}}}};var w=class{constructor(o){this.config=o}config;id="gemini";model(){let o=this.config.model?.trim();if(!o)throw new Error("gemini: MODEL is not configured");return o.replace(/^models\//,"")}async generate(o){let t=this.config.apiKey?.trim();if(!t)throw new Error("gemini: API KEY is not configured");let n=this.config.baseUrl?.trim()||"https://generativelanguage.googleapis.com/v1beta",r=this.model(),i=o.messages.filter(d=>d.role==="system"),s=o.messages.filter(d=>d.role!=="system").map(d=>({role:d.role==="assistant"?"model":"user",parts:[{text:d.content}]})),l=`${U(n,`models/${encodeURIComponent(r)}:generateContent`)}?key=${encodeURIComponent(t)}`,a=await R(l,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({...i.length?{systemInstruction:{parts:[{text:i.map(d=>d.content).join(`
2
2
 
3
- `)}]}}:{},contents:a,generationConfig:{temperature:t.temperature,maxOutputTokens:t.maxTokens}})}),d=c.candidates?.[0]?.content?.parts?.map(E=>E.text??"").join("").trim();if(!d)throw new Error("gemini: empty model response");return{text:d,provider:"gemini",model:r,usage:c.usageMetadata?{inputTokens:c.usageMetadata.promptTokenCount,outputTokens:c.usageMetadata.candidatesTokenCount,totalTokens:c.usageMetadata.totalTokenCount}:void 0}}async healthCheck(){let t=Date.now();try{return{ok:!0,provider:"gemini",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-t}}catch(o){return{ok:!1,provider:"gemini",model:this.config.model,message:o instanceof Error?o.message:String(o),latencyMs:Date.now()-t}}}};var K=class{constructor(t){this.config=t;this.id=t.id}config;id;baseUrl(){let t=this.config.baseUrl?.trim();if(!t)throw new Error(`${this.id}: BASE URL is not configured`);return t}model(){let t=this.config.model?.trim();if(!t)throw new Error(`${this.id}: MODEL is not configured`);return t}headers(){let t={"content-type":"application/json",...this.config.headers};return this.config.apiKey&&(t.authorization=`Bearer ${this.config.apiKey}`),t}async generate(t){let o=this.model(),n=await S(D(this.baseUrl(),"chat/completions"),{method:"POST",headers:this.headers(),body:JSON.stringify({model:o,messages:t.messages,temperature:t.temperature,max_tokens:t.maxTokens})}),r=n.choices?.[0]?.message?.content?.trim();if(!r)throw new Error(`${this.id}: empty model response`);return{text:r,provider:this.id,model:o,usage:n.usage?{inputTokens:n.usage.prompt_tokens,outputTokens:n.usage.completion_tokens,totalTokens:n.usage.total_tokens}:void 0}}async healthCheck(){let t=Date.now();try{let o=await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8});return{ok:!0,provider:this.id,model:o.model,message:"Provider reachable",latencyMs:Date.now()-t}}catch(o){return{ok:!1,provider:this.id,model:this.config.model,message:o instanceof Error?o.message:String(o),latencyMs:Date.now()-t}}}};function Q(e=Z()){switch(A(e.id).transport){case"gemini":return new U(e);case"cloudflare":return new P(e);default:return new K(e)}}import{existsSync as $}from"node:fs";import{homedir as F}from"node:os";import{join as v}from"node:path";import{spawnSync as Ge}from"node:child_process";import{existsSync as ye,mkdirSync as Ie,readFileSync as Re,writeFileSync as Me}from"node:fs";import{homedir as Le}from"node:os";import{dirname as Ne,join as he}from"node:path";function De(e){return`'${e.replace(/'/g,"'\\''")}'`}function ee(e={}){let t=e.hooksFile??he(Le(),".gemini","config","hooks.json");Ie(Ne(t),{recursive:!0});let o={};if(ye(t))try{o=JSON.parse(Re(t,"utf8"))}catch(s){throw new Error(`Invalid existing Agy hooks.json: ${s instanceof Error?s.message:String(s)}`)}let n=e.binary??"toolnet-memory",r=`${De(n)} session:agy-hook`;return o["toolnet-memory"]={enabled:!0,PreInvocation:[{type:"command",command:`${r} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${r} post`,timeout:15}],Stop:[{type:"command",command:`${r} stop`,timeout:30}]},Me(t,JSON.stringify(o,null,2)+`
4
- `,{encoding:"utf8",mode:384}),t}import{existsSync as Pe,mkdirSync as oe,readFileSync as Ue,writeFileSync as ne}from"node:fs";import{homedir as B}from"node:os";import{join as b}from"node:path";var te="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",k="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function Ke(){let e=b(B(),".config","opencode","AGENTS.md");oe(b(B(),".config","opencode"),{recursive:!0});let t=`${te}
3
+ `)}]}}:{},contents:s,generationConfig:{temperature:o.temperature,maxOutputTokens:o.maxTokens}})}),E=a.candidates?.[0]?.content?.parts?.map(d=>d.text??"").join("").trim();if(!E)throw new Error("gemini: empty model response");return{text:E,provider:"gemini",model:r,usage:a.usageMetadata?{inputTokens:a.usageMetadata.promptTokenCount,outputTokens:a.usageMetadata.candidatesTokenCount,totalTokens:a.usageMetadata.totalTokenCount}:void 0}}async healthCheck(){let o=Date.now();try{return{ok:!0,provider:"gemini",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-o}}catch(t){return{ok:!1,provider:"gemini",model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-o}}}};var Y=class{constructor(o){this.config=o;this.id=o.id}config;id;baseUrl(){let o=this.config.baseUrl?.trim();if(!o)throw new Error(`${this.id}: BASE URL is not configured`);return o}model(){let o=this.config.model?.trim();if(!o)throw new Error(`${this.id}: MODEL is not configured`);return o}headers(){let o={"content-type":"application/json",...this.config.headers};return this.config.apiKey&&(o.authorization=`Bearer ${this.config.apiKey}`),o}async generate(o){let t=this.model(),n=await R(U(this.baseUrl(),"chat/completions"),{method:"POST",headers:this.headers(),body:JSON.stringify({model:t,messages:o.messages,temperature:o.temperature,max_tokens:o.maxTokens})}),r=n.choices?.[0]?.message?.content?.trim();if(!r)throw new Error(`${this.id}: empty model response`);return{text:r,provider:this.id,model:t,usage:n.usage?{inputTokens:n.usage.prompt_tokens,outputTokens:n.usage.completion_tokens,totalTokens:n.usage.total_tokens}:void 0}}async healthCheck(){let o=Date.now();try{let t=await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8});return{ok:!0,provider:this.id,model:t.model,message:"Provider reachable",latencyMs:Date.now()-o}}catch(t){return{ok:!1,provider:this.id,model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-o}}}};function le(e=ae()){switch(C(e.id).transport){case"gemini":return new w(e);case"cloudflare":return new B(e);default:return new Y(e)}}import{existsSync as W}from"node:fs";import{homedir as v}from"node:os";import{join as J}from"node:path";import{spawnSync as no}from"node:child_process";import{existsSync as we,mkdirSync as Ye,readFileSync as $e,writeFileSync as ke}from"node:fs";import{homedir as Fe}from"node:os";import{dirname as xe,join as Ge}from"node:path";function He(e){return`'${e.replace(/'/g,"'\\''")}'`}function Ee(e={}){let o=e.hooksFile??Ge(Fe(),".gemini","config","hooks.json");Ye(xe(o),{recursive:!0});let t={};if(we(o))try{t=JSON.parse($e(o,"utf8"))}catch(i){throw new Error(`Invalid existing Agy hooks.json: ${i instanceof Error?i.message:String(i)}`)}let n=e.binary??"toolnet-memory",r=`${He(n)} session:agy-hook`;return t["toolnet-memory"]={enabled:!0,PreInvocation:[{type:"command",command:`${r} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${r} post`,timeout:15}],Stop:[{type:"command",command:`${r} stop`,timeout:30}]},ke(o,JSON.stringify(t,null,2)+`
4
+ `,{encoding:"utf8",mode:384}),o}import{existsSync as qe,mkdirSync as _e,readFileSync as Ve,writeFileSync as de}from"node:fs";import{homedir as V}from"node:os";import{join as $}from"node:path";var ge="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",q="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function je(){let e=$(V(),".config","opencode","AGENTS.md");_e($(V(),".config","opencode"),{recursive:!0});let o=`${ge}
5
5
  ## ToolNet Memory
6
6
 
7
7
  ToolNet Memory is available for projects that already contain a valid \`.toolnet/project.json\`.
@@ -16,10 +16,10 @@ Rules:
16
16
  6. Raw transcripts must not be injected into prompts.
17
17
  7. Current repository evidence has priority over stale memory when they conflict.
18
18
 
19
- ${k}`,o=Pe(e)?Ue(e,"utf8"):"",n=o.indexOf(te),r=o.indexOf(k);return n>=0&&r>=n?o=o.slice(0,n)+t+o.slice(r+k.length):(o=o.trimEnd(),o&&(o+=`
19
+ ${q}`,t=qe(e)?Ve(e,"utf8"):"",n=t.indexOf(ge),r=t.indexOf(q);return n>=0&&r>=n?t=t.slice(0,n)+o+t.slice(r+q.length):(t=t.trimEnd(),t&&(t+=`
20
20
 
21
- `),o+=t),ne(e,o.trimEnd()+`
22
- `,{encoding:"utf8",mode:384}),e}function re(e={}){let t=e.directory??b(B(),".config","opencode","plugins");oe(t,{recursive:!0}),Ke();let o=b(t,"toolnet-memory.js"),n=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=`
21
+ `),t+=o),de(e,t.trimEnd()+`
22
+ `,{encoding:"utf8",mode:384}),e}function Oe(e={}){let o=e.directory??$(V(),".config","opencode","plugins");_e(o,{recursive:!0}),je();let t=$(o,"toolnet-memory.js"),n=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=`
23
23
  // Generated by ToolNet Memory.
24
24
  // OpenCode integration:
25
25
  // - project gated
@@ -647,17 +647,17 @@ export const ToolNetMemoryPlugin =
647
647
  },
648
648
  }
649
649
  }
650
- `;return ne(o,r.trimStart(),{encoding:"utf8",mode:384}),o}import{existsSync as be,mkdirSync as ie,readFileSync as Ye,writeFileSync as se}from"node:fs";import{homedir as ae}from"node:os";import{dirname as ce,join as x}from"node:path";function we(e){let t=[],o=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,n;for(;n=o.exec(e);){let r=n[1]??n[2]??"";try{t.push(n[1]!==void 0?JSON.parse(`"${r}"`):r)}catch{t.push(r)}}return t}function le(e={}){let t=e.configFile??x(process.env.CODEX_HOME??x(ae(),".codex"),"config.toml"),o=e.previousFile??x(ae(),".config","toolnet-memory","codex-notify-previous.json");ie(ce(t),{recursive:!0}),ie(ce(o),{recursive:!0});let n=be(t)?Ye(t,"utf8"):"",r=e.binary??"toolnet-memory",s=`notify = [${JSON.stringify(r)}, "session:codex-notify"]`,a=n.split(`
651
- `),l=a.findIndex(u=>/^\s*\[/.test(u));l<0&&(l=a.length);let c=-1,d=-1;for(let u=0;u<l;u+=1)if(/^\s*notify\s*=/.test(a[u])){if(c=u,d=u,a[u].includes("[")&&!a[u].includes("]"))for(;d+1<l&&(d+=1,!a[d].includes("]")););break}let E=[];if(c>=0){let u=a.slice(c,d+1).join(`
652
- `);E=we(u),a.splice(c,d-c+1,s)}else l=a.findIndex(u=>/^\s*\[/.test(u)),l<0&&(l=a.length),a.splice(l,0,s);let y=E.length>=2&&E[E.length-1]==="session:codex-notify";return E.length>0&&!y&&se(o,JSON.stringify(E,null,2)+`
653
- `,{encoding:"utf8",mode:384}),n=a.join(`
650
+ `;return de(t,r.trimStart(),{encoding:"utf8",mode:384}),t}import{existsSync as We,mkdirSync as Le,readFileSync as ve,writeFileSync as fe}from"node:fs";import{homedir as ue}from"node:os";import{dirname as me,join as j}from"node:path";function Je(e){let o=[],t=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,n;for(;n=t.exec(e);){let r=n[1]??n[2]??"";try{o.push(n[1]!==void 0?JSON.parse(`"${r}"`):r)}catch{o.push(r)}}return o}function Te(e={}){let o=e.configFile??j(process.env.CODEX_HOME??j(ue(),".codex"),"config.toml"),t=e.previousFile??j(ue(),".config","toolnet-memory","codex-notify-previous.json");Le(me(o),{recursive:!0}),Le(me(t),{recursive:!0});let n=We(o)?ve(o,"utf8"):"",r=e.binary??"toolnet-memory",i=`notify = [${JSON.stringify(r)}, "session:codex-notify"]`,s=n.split(`
651
+ `),l=s.findIndex(O=>/^\s*\[/.test(O));l<0&&(l=s.length);let a=-1,E=-1;for(let O=0;O<l;O+=1)if(/^\s*notify\s*=/.test(s[O])){if(a=O,E=O,s[O].includes("[")&&!s[O].includes("]"))for(;E+1<l&&(E+=1,!s[E].includes("]")););break}let d=[];if(a>=0){let O=s.slice(a,E+1).join(`
652
+ `);d=Je(O),s.splice(a,E-a+1,i)}else l=s.findIndex(O=>/^\s*\[/.test(O)),l<0&&(l=s.length),s.splice(l,0,i);let m=d.length>=2&&d[d.length-1]==="session:codex-notify";return d.length>0&&!m&&fe(t,JSON.stringify(d,null,2)+`
653
+ `,{encoding:"utf8",mode:384}),n=s.join(`
654
654
  `),n.endsWith(`
655
655
  `)||(n+=`
656
- `),se(t,n,{encoding:"utf8",mode:384}),{configFile:t,previousFile:o,preservedPrevious:E.length>0&&!y}}import{existsSync as ke,mkdirSync as Be,readFileSync as xe,writeFileSync as $e}from"node:fs";import{homedir as Fe}from"node:os";import{dirname as ve,join as de}from"node:path";function He(e){return`'${e.replace(/'/g,"'\\''")}'`}function ge(e={}){let t=e.hooksFile??de(process.env.CODEX_HOME??de(Fe(),".codex"),"hooks.json");Be(ve(t),{recursive:!0});let o={};if(ke(t))try{o=JSON.parse(xe(t,"utf8"))}catch(l){throw new Error(`Invalid existing Codex hooks.json: ${l instanceof Error?l.message:String(l)}`)}let n=o.hooks&&typeof o.hooks=="object"&&!Array.isArray(o.hooks)?o.hooks:{};o.hooks=n;let s=(Array.isArray(n.SessionStart)?n.SessionStart:[]).filter(l=>{try{return!JSON.stringify(l).includes("session:codex-context")}catch{return!0}}),a=e.binary??"toolnet-memory";return s.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${He(a)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),n.SessionStart=s,$e(t,JSON.stringify(o,null,2)+`
657
- `,{encoding:"utf8",mode:384}),t}function H(e){return Ge("sh",["-lc",`command -v ${JSON.stringify(e)} >/dev/null 2>&1`],{stdio:"ignore"}).status===0}function qe(){return H("agy")||$(v(F(),".gemini"))}function je(){return H("opencode")||$(v(F(),".config","opencode"))}function Ve(){return H("codex")||$(process.env.CODEX_HOME??v(F(),".codex"))}function G(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=[];if(!(e.force===!0||qe()))o.push({agent:"agy",detected:!1,installed:!1,targets:[]});else try{let r=ee({binary:t});o.push({agent:"agy",detected:!0,installed:!0,targets:[r]})}catch(r){o.push({agent:"agy",detected:!0,installed:!1,targets:[],error:r instanceof Error?r.message:String(r)})}if(!(e.force===!0||je()))o.push({agent:"opencode",detected:!1,installed:!1,targets:[]});else try{let r=re({binary:t});o.push({agent:"opencode",detected:!0,installed:!0,targets:[r]})}catch(r){o.push({agent:"opencode",detected:!0,installed:!1,targets:[],error:r instanceof Error?r.message:String(r)})}if(!(e.force===!0||Ve()))o.push({agent:"codex",detected:!1,installed:!1,targets:[]});else try{let r=le({binary:t}),s=ge({binary:t}),a=[r.configFile,s];r.preservedPrevious&&a.push(r.previousFile),o.push({agent:"codex",detected:!0,installed:!0,targets:a})}catch(r){o.push({agent:"codex",detected:!0,installed:!1,targets:[],error:r instanceof Error?r.message:String(r)})}return o}function Je(e){console.log(""),console.log("ToolNet Memory AI Integrations"),console.log("=============================="),console.log("");for(let t of e){let o=t.agent==="agy"?"Agy / Antigravity":t.agent==="opencode"?"OpenCode":"Codex";if(!t.detected){console.log(`- ${o}: not detected`);continue}if(t.installed){console.log(`\u2713 ${o}: automatic memory enabled`);continue}console.log(`\u2717 ${o}: integration failed`),t.error&&console.log(` ${t.error}`)}console.log("")}async function We(){let e=process.argv.slice(2),t=e.includes("--all"),o=e.includes("--json"),n=G({force:t});if(o){console.log(JSON.stringify(n,null,2));return}Je(n)}var Xe=process.argv[1]&&(process.argv[1].endsWith("auto-integrate.js")||process.argv[1].endsWith("auto-integrate.ts"));Xe&&We().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});var q=R.join(j.homedir(),".config","toolnet-memory"),_=R.join(q,".env"),et=new Set(["MEMORY_STORAGE_PROVIDER","R2_ACCOUNT_ID","R2_BUCKET","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","S3_ENDPOINT","S3_REGION","S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY","S3_FORCE_PATH_STYLE","HF_NAMESPACE","HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY","HF_URL","HF_TOKEN","HF_EMBEDDING_MODEL","TOOLNET_LLM_PROVIDER","TOOLNET_LLM_API_KEY","TOOLNET_LLM_BASE_URL","TOOLNET_LLM_MODEL","TOOLNET_LLM_ACCOUNT_ID","TOOLNET_EMBEDDING_PROVIDER","TOOLNET_EMBEDDING_API_KEY","TOOLNET_EMBEDDING_BASE_URL","TOOLNET_EMBEDDING_MODEL","TOOLNET_EMBEDDING_ACCOUNT_ID","MEMORY_LOCAL_STORAGE_PATH","MEMORY_LOCAL_CACHE_MB","MEMORY_AUTO_CAPTURE","MEMORY_AUTO_RETRIEVE","MEMORY_AUTO_SUMMARIZE","MEMORY_AUTO_SYNC","MEMORY_MAX_CANDIDATES","MEMORY_RERANK_TOP","MEMORY_FINAL_CONTEXT","MEMORY_TOKEN_BUDGET","TOOLNET_SESSION_LEARNING","TOOLNET_WORK_CONTINUITY","TOOLNET_SEMANTIC_CONTINUITY","TOOLNET_SMART_HANDOFF"]);function tt(e){let t=new Map;for(let o of e.split(/\r?\n/)){let n=o.trim();if(!n||n.startsWith("#"))continue;let r=n.indexOf("=");if(r===-1)continue;let s=n.slice(0,r).trim(),a=n.slice(r+1).trim();s&&t.set(s,a)}return t}function T(e){let t=e.get("MEMORY_STORAGE_PROVIDER")?.trim();return t==="r2"||t==="s3"||t==="local"||t==="huggingface"?t:e.get("R2_ACCOUNT_ID")&&e.get("R2_BUCKET")?"r2":e.get("S3_BUCKET")?"s3":e.get("HF_BUCKET")&&e.get("HF_S3_ACCESS_KEY_ID")?"huggingface":e.get("MEMORY_LOCAL_STORAGE_PATH")?"local":"r2"}function M(e){switch(e){case"r2":return"Cloudflare R2";case"s3":return"S3 / S3-compatible";case"huggingface":return"Hugging Face S3";case"local":return"Local";default:return e}}function Ee(e){switch(e){case"r2":return["R2_ACCOUNT_ID","R2_BUCKET","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY"];case"s3":return["S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY"];case"huggingface":return["HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY"];case"local":return[];default:return[]}}function ue(e){let t=T(e);return t==="local"?!0:Ee(t).every(o=>!!e.get(o)?.trim())}function V(e){return e?e.length<=8?"configured":`${e.slice(0,4)}\u2022\u2022\u2022\u2022${e.slice(-3)}`:"not configured"}function ot(e){let o=["# ==========================================================","# TOOLNET MEMORY","# Generated by: toolnet-memory setup","# Do not commit this file.","# ==========================================================","",`MEMORY_STORAGE_PROVIDER=${T(e)}`,"","# ----------------------------------------------------------","# Cloudflare R2","# ----------------------------------------------------------",`R2_ACCOUNT_ID=${e.get("R2_ACCOUNT_ID")??""}`,`R2_BUCKET=${e.get("R2_BUCKET")??"toolnet-memory"}`,`R2_ACCESS_KEY_ID=${e.get("R2_ACCESS_KEY_ID")??""}`,`R2_SECRET_ACCESS_KEY=${e.get("R2_SECRET_ACCESS_KEY")??""}`,"","# ----------------------------------------------------------","# Generic S3 / S3-compatible","# ----------------------------------------------------------",`S3_ENDPOINT=${e.get("S3_ENDPOINT")??""}`,`S3_REGION=${e.get("S3_REGION")??"us-east-1"}`,`S3_BUCKET=${e.get("S3_BUCKET")??"toolnet-memory"}`,`S3_ACCESS_KEY_ID=${e.get("S3_ACCESS_KEY_ID")??""}`,`S3_SECRET_ACCESS_KEY=${e.get("S3_SECRET_ACCESS_KEY")??""}`,`S3_FORCE_PATH_STYLE=${e.get("S3_FORCE_PATH_STYLE")??"false"}`,"","# ----------------------------------------------------------","# Hugging Face S3","# ----------------------------------------------------------",`HF_NAMESPACE=${e.get("HF_NAMESPACE")??""}`,`HF_BUCKET=${e.get("HF_BUCKET")??"toolnet-memory"}`,`HF_S3_ACCESS_KEY_ID=${e.get("HF_S3_ACCESS_KEY_ID")??""}`,`HF_S3_SECRET_ACCESS_KEY=${e.get("HF_S3_SECRET_ACCESS_KEY")??""}`,`HF_URL=${e.get("HF_URL")??""}`,"","# ----------------------------------------------------------","# AI / LLM - canonical ToolNet configuration","# ----------------------------------------------------------",`TOOLNET_LLM_PROVIDER=${e.get("TOOLNET_LLM_PROVIDER")??""}`,`TOOLNET_LLM_API_KEY=${e.get("TOOLNET_LLM_API_KEY")??""}`,`TOOLNET_LLM_BASE_URL=${e.get("TOOLNET_LLM_BASE_URL")??""}`,`TOOLNET_LLM_MODEL=${e.get("TOOLNET_LLM_MODEL")??""}`,`TOOLNET_LLM_ACCOUNT_ID=${e.get("TOOLNET_LLM_ACCOUNT_ID")??""}`,"","# ----------------------------------------------------------","# Embedding - canonical ToolNet configuration","# ----------------------------------------------------------",`TOOLNET_EMBEDDING_PROVIDER=${e.get("TOOLNET_EMBEDDING_PROVIDER")??""}`,`TOOLNET_EMBEDDING_API_KEY=${e.get("TOOLNET_EMBEDDING_API_KEY")??""}`,`TOOLNET_EMBEDDING_BASE_URL=${e.get("TOOLNET_EMBEDDING_BASE_URL")??""}`,`TOOLNET_EMBEDDING_MODEL=${e.get("TOOLNET_EMBEDDING_MODEL")??""}`,`TOOLNET_EMBEDDING_ACCOUNT_ID=${e.get("TOOLNET_EMBEDDING_ACCOUNT_ID")??""}`,"","# ----------------------------------------------------------","# Embedding - legacy/current compatibility","# ----------------------------------------------------------",`HF_TOKEN=${e.get("HF_TOKEN")??""}`,`HF_EMBEDDING_MODEL=${e.get("HF_EMBEDDING_MODEL")??"sentence-transformers/all-MiniLM-L6-v2"}`,"","# ----------------------------------------------------------","# Local storage/cache","# ----------------------------------------------------------",`MEMORY_LOCAL_STORAGE_PATH=${e.get("MEMORY_LOCAL_STORAGE_PATH")??""}`,`MEMORY_LOCAL_CACHE_MB=${e.get("MEMORY_LOCAL_CACHE_MB")??"200"}`,"","# ----------------------------------------------------------","# Automation","# ----------------------------------------------------------",`MEMORY_AUTO_CAPTURE=${e.get("MEMORY_AUTO_CAPTURE")??"true"}`,`MEMORY_AUTO_RETRIEVE=${e.get("MEMORY_AUTO_RETRIEVE")??"true"}`,`MEMORY_AUTO_SUMMARIZE=${e.get("MEMORY_AUTO_SUMMARIZE")??"true"}`,`MEMORY_AUTO_SYNC=${e.get("MEMORY_AUTO_SYNC")??"true"}`,"","# ----------------------------------------------------------","# Retrieval","# ----------------------------------------------------------",`MEMORY_MAX_CANDIDATES=${e.get("MEMORY_MAX_CANDIDATES")??"50"}`,`MEMORY_RERANK_TOP=${e.get("MEMORY_RERANK_TOP")??"10"}`,`MEMORY_FINAL_CONTEXT=${e.get("MEMORY_FINAL_CONTEXT")??"5"}`,`MEMORY_TOKEN_BUDGET=${e.get("MEMORY_TOKEN_BUDGET")??"2000"}`,"","# ----------------------------------------------------------","# Automatic Session Memory","# ----------------------------------------------------------",`TOOLNET_SESSION_LEARNING=${e.get("TOOLNET_SESSION_LEARNING")??"1"}`,`TOOLNET_WORK_CONTINUITY=${e.get("TOOLNET_WORK_CONTINUITY")??"1"}`,`TOOLNET_SEMANTIC_CONTINUITY=${e.get("TOOLNET_SEMANTIC_CONTINUITY")??"1"}`,`TOOLNET_SMART_HANDOFF=${e.get("TOOLNET_SMART_HANDOFF")??"1"}`],n=[...e.entries()].filter(([r])=>!et.has(r));if(n.length>0){o.push("","# ----------------------------------------------------------","# Preserved settings","# ----------------------------------------------------------");for(let[r,s]of n)o.push(`${r}=${s}`)}return`${o.join(`
656
+ `),fe(o,n,{encoding:"utf8",mode:384}),{configFile:o,previousFile:t,preservedPrevious:d.length>0&&!m}}import{existsSync as Xe,mkdirSync as ze,readFileSync as Qe,writeFileSync as Ze}from"node:fs";import{homedir as eo}from"node:os";import{dirname as oo,join as Ae}from"node:path";function to(e){return`'${e.replace(/'/g,"'\\''")}'`}function pe(e={}){let o=e.hooksFile??Ae(process.env.CODEX_HOME??Ae(eo(),".codex"),"hooks.json");ze(oo(o),{recursive:!0});let t={};if(Xe(o))try{t=JSON.parse(Qe(o,"utf8"))}catch(l){throw new Error(`Invalid existing Codex hooks.json: ${l instanceof Error?l.message:String(l)}`)}let n=t.hooks&&typeof t.hooks=="object"&&!Array.isArray(t.hooks)?t.hooks:{};t.hooks=n;let i=(Array.isArray(n.SessionStart)?n.SessionStart:[]).filter(l=>{try{return!JSON.stringify(l).includes("session:codex-context")}catch{return!0}}),s=e.binary??"toolnet-memory";return i.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${to(s)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),n.SessionStart=i,Ze(o,JSON.stringify(t,null,2)+`
657
+ `,{encoding:"utf8",mode:384}),o}function X(e){return no("sh",["-lc",`command -v ${JSON.stringify(e)} >/dev/null 2>&1`],{stdio:"ignore"}).status===0}function ro(){return X("agy")||W(J(v(),".gemini"))}function io(){return X("opencode")||W(J(v(),".config","opencode"))}function so(){return X("codex")||W(process.env.CODEX_HOME??J(v(),".codex"))}function z(e={}){let o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=[];if(!(e.force===!0||ro()))t.push({agent:"agy",detected:!1,installed:!1,targets:[]});else try{let r=Ee({binary:o});t.push({agent:"agy",detected:!0,installed:!0,targets:[r]})}catch(r){t.push({agent:"agy",detected:!0,installed:!1,targets:[],error:r instanceof Error?r.message:String(r)})}if(!(e.force===!0||io()))t.push({agent:"opencode",detected:!1,installed:!1,targets:[]});else try{let r=Oe({binary:o});t.push({agent:"opencode",detected:!0,installed:!0,targets:[r]})}catch(r){t.push({agent:"opencode",detected:!0,installed:!1,targets:[],error:r instanceof Error?r.message:String(r)})}if(!(e.force===!0||so()))t.push({agent:"codex",detected:!1,installed:!1,targets:[]});else try{let r=Te({binary:o}),i=pe({binary:o}),s=[r.configFile,i];r.preservedPrevious&&s.push(r.previousFile),t.push({agent:"codex",detected:!0,installed:!0,targets:s})}catch(r){t.push({agent:"codex",detected:!0,installed:!1,targets:[],error:r instanceof Error?r.message:String(r)})}return t}function co(e){console.log(""),console.log("ToolNet Memory AI Integrations"),console.log("=============================="),console.log("");for(let o of e){let t=o.agent==="agy"?"Agy / Antigravity":o.agent==="opencode"?"OpenCode":"Codex";if(!o.detected){console.log(`- ${t}: not detected`);continue}if(o.installed){console.log(`\u2713 ${t}: automatic memory enabled`);continue}console.log(`\u2717 ${t}: integration failed`),o.error&&console.log(` ${o.error}`)}console.log("")}async function ao(){let e=process.argv.slice(2),o=e.includes("--all"),t=e.includes("--json"),n=z({force:o});if(t){console.log(JSON.stringify(n,null,2));return}co(n)}var lo=process.argv[1]&&(process.argv[1].endsWith("auto-integrate.js")||process.argv[1].endsWith("auto-integrate.ts"));lo&&ao().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});var Q=h.join(Z.homedir(),".config","toolnet-memory"),u=h.join(Q,".env"),Oo=new Set(["MEMORY_STORAGE_PROVIDER","R2_ACCOUNT_ID","R2_BUCKET","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY","S3_ENDPOINT","S3_REGION","S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY","S3_FORCE_PATH_STYLE","HF_NAMESPACE","HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY","HF_URL","HF_TOKEN","HF_EMBEDDING_MODEL","TOOLNET_LLM_PROVIDER","TOOLNET_LLM_API_KEY","TOOLNET_LLM_BASE_URL","TOOLNET_LLM_MODEL","TOOLNET_LLM_FALLBACK_1_PROVIDER","TOOLNET_LLM_FALLBACK_1_API_KEY","TOOLNET_LLM_FALLBACK_1_BASE_URL","TOOLNET_LLM_FALLBACK_1_MODEL","TOOLNET_LLM_FALLBACK_1_ACCOUNT_ID","TOOLNET_LLM_FALLBACK_2_PROVIDER","TOOLNET_LLM_FALLBACK_2_API_KEY","TOOLNET_LLM_FALLBACK_2_BASE_URL","TOOLNET_LLM_FALLBACK_2_MODEL","TOOLNET_LLM_FALLBACK_2_ACCOUNT_ID","TOOLNET_LLM_FALLBACK_COOLDOWN_MS","TOOLNET_LLM_MAX_RETRIES","TOOLNET_LLM_ACCOUNT_ID","TOOLNET_EMBEDDING_PROVIDER","TOOLNET_EMBEDDING_API_KEY","TOOLNET_EMBEDDING_BASE_URL","TOOLNET_EMBEDDING_MODEL","TOOLNET_EMBEDDING_ACCOUNT_ID","MEMORY_LOCAL_STORAGE_PATH","MEMORY_LOCAL_CACHE_MB","MEMORY_AUTO_CAPTURE","MEMORY_AUTO_RETRIEVE","MEMORY_AUTO_SUMMARIZE","MEMORY_AUTO_SYNC","MEMORY_MAX_CANDIDATES","MEMORY_RERANK_TOP","MEMORY_FINAL_CONTEXT","MEMORY_TOKEN_BUDGET","TOOLNET_SESSION_LEARNING","TOOLNET_WORK_CONTINUITY","TOOLNET_SEMANTIC_CONTINUITY","TOOLNET_SMART_HANDOFF"]);function Lo(e){let o=new Map;for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;let r=n.indexOf("=");if(r===-1)continue;let i=n.slice(0,r).trim(),s=n.slice(r+1).trim();i&&o.set(i,s)}return o}function N(e){let o=e.get("MEMORY_STORAGE_PROVIDER")?.trim();return o==="r2"||o==="s3"||o==="local"||o==="huggingface"?o:e.get("R2_ACCOUNT_ID")&&e.get("R2_BUCKET")?"r2":e.get("S3_BUCKET")?"s3":e.get("HF_BUCKET")&&e.get("HF_S3_ACCESS_KEY_ID")?"huggingface":e.get("MEMORY_LOCAL_STORAGE_PATH")?"local":"r2"}function P(e){switch(e){case"r2":return"Cloudflare R2";case"s3":return"S3 / S3-compatible";case"huggingface":return"Hugging Face S3";case"local":return"Local";default:return e}}function Se(e){switch(e){case"r2":return["R2_ACCOUNT_ID","R2_BUCKET","R2_ACCESS_KEY_ID","R2_SECRET_ACCESS_KEY"];case"s3":return["S3_BUCKET","S3_ACCESS_KEY_ID","S3_SECRET_ACCESS_KEY"];case"huggingface":return["HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY"];case"local":return[];default:return[]}}function Ce(e){let o=N(e);return o==="local"?!0:Se(o).every(t=>!!e.get(t)?.trim())}function ee(e){return e?e.length<=8?"configured":`${e.slice(0,4)}\u2022\u2022\u2022\u2022${e.slice(-3)}`:"not configured"}function fo(e){let t=["# ==========================================================","# TOOLNET MEMORY","# Generated by: toolnet-memory setup","# Do not commit this file.","# ==========================================================","",`MEMORY_STORAGE_PROVIDER=${N(e)}`,"","# ----------------------------------------------------------","# Cloudflare R2","# ----------------------------------------------------------",`R2_ACCOUNT_ID=${e.get("R2_ACCOUNT_ID")??""}`,`R2_BUCKET=${e.get("R2_BUCKET")??"toolnet-memory"}`,`R2_ACCESS_KEY_ID=${e.get("R2_ACCESS_KEY_ID")??""}`,`R2_SECRET_ACCESS_KEY=${e.get("R2_SECRET_ACCESS_KEY")??""}`,"","# ----------------------------------------------------------","# Generic S3 / S3-compatible","# ----------------------------------------------------------",`S3_ENDPOINT=${e.get("S3_ENDPOINT")??""}`,`S3_REGION=${e.get("S3_REGION")??"us-east-1"}`,`S3_BUCKET=${e.get("S3_BUCKET")??"toolnet-memory"}`,`S3_ACCESS_KEY_ID=${e.get("S3_ACCESS_KEY_ID")??""}`,`S3_SECRET_ACCESS_KEY=${e.get("S3_SECRET_ACCESS_KEY")??""}`,`S3_FORCE_PATH_STYLE=${e.get("S3_FORCE_PATH_STYLE")??"false"}`,"","# ----------------------------------------------------------","# Hugging Face S3","# ----------------------------------------------------------",`HF_NAMESPACE=${e.get("HF_NAMESPACE")??""}`,`HF_BUCKET=${e.get("HF_BUCKET")??"toolnet-memory"}`,`HF_S3_ACCESS_KEY_ID=${e.get("HF_S3_ACCESS_KEY_ID")??""}`,`HF_S3_SECRET_ACCESS_KEY=${e.get("HF_S3_SECRET_ACCESS_KEY")??""}`,`HF_URL=${e.get("HF_URL")??""}`,"","# ----------------------------------------------------------","# AI / LLM - canonical ToolNet configuration","# ----------------------------------------------------------",`TOOLNET_LLM_PROVIDER=${e.get("TOOLNET_LLM_PROVIDER")??""}`,`TOOLNET_LLM_API_KEY=${e.get("TOOLNET_LLM_API_KEY")??""}`,`TOOLNET_LLM_BASE_URL=${e.get("TOOLNET_LLM_BASE_URL")??""}`,`TOOLNET_LLM_MODEL=${e.get("TOOLNET_LLM_MODEL")??""}`,`TOOLNET_LLM_ACCOUNT_ID=${e.get("TOOLNET_LLM_ACCOUNT_ID")??""}`,"","# ----------------------------------------------------------","# LLM fallback chain","# ----------------------------------------------------------",`TOOLNET_LLM_FALLBACK_1_PROVIDER=${e.get("TOOLNET_LLM_FALLBACK_1_PROVIDER")??""}`,`TOOLNET_LLM_FALLBACK_1_API_KEY=${e.get("TOOLNET_LLM_FALLBACK_1_API_KEY")??""}`,`TOOLNET_LLM_FALLBACK_1_BASE_URL=${e.get("TOOLNET_LLM_FALLBACK_1_BASE_URL")??""}`,`TOOLNET_LLM_FALLBACK_1_MODEL=${e.get("TOOLNET_LLM_FALLBACK_1_MODEL")??""}`,`TOOLNET_LLM_FALLBACK_1_ACCOUNT_ID=${e.get("TOOLNET_LLM_FALLBACK_1_ACCOUNT_ID")??""}`,`TOOLNET_LLM_FALLBACK_2_PROVIDER=${e.get("TOOLNET_LLM_FALLBACK_2_PROVIDER")??""}`,`TOOLNET_LLM_FALLBACK_2_API_KEY=${e.get("TOOLNET_LLM_FALLBACK_2_API_KEY")??""}`,`TOOLNET_LLM_FALLBACK_2_BASE_URL=${e.get("TOOLNET_LLM_FALLBACK_2_BASE_URL")??""}`,`TOOLNET_LLM_FALLBACK_2_MODEL=${e.get("TOOLNET_LLM_FALLBACK_2_MODEL")??""}`,`TOOLNET_LLM_FALLBACK_2_ACCOUNT_ID=${e.get("TOOLNET_LLM_FALLBACK_2_ACCOUNT_ID")??""}`,`TOOLNET_LLM_FALLBACK_COOLDOWN_MS=${e.get("TOOLNET_LLM_FALLBACK_COOLDOWN_MS")??"60000"}`,`TOOLNET_LLM_MAX_RETRIES=${e.get("TOOLNET_LLM_MAX_RETRIES")??"1"}`,"","# ----------------------------------------------------------","# Embedding - canonical ToolNet configuration","# ----------------------------------------------------------",`TOOLNET_EMBEDDING_PROVIDER=${e.get("TOOLNET_EMBEDDING_PROVIDER")??""}`,`TOOLNET_EMBEDDING_API_KEY=${e.get("TOOLNET_EMBEDDING_API_KEY")??""}`,`TOOLNET_EMBEDDING_BASE_URL=${e.get("TOOLNET_EMBEDDING_BASE_URL")??""}`,`TOOLNET_EMBEDDING_MODEL=${e.get("TOOLNET_EMBEDDING_MODEL")??""}`,`TOOLNET_EMBEDDING_ACCOUNT_ID=${e.get("TOOLNET_EMBEDDING_ACCOUNT_ID")??""}`,"","# ----------------------------------------------------------","# Embedding - legacy/current compatibility","# ----------------------------------------------------------",`HF_TOKEN=${e.get("HF_TOKEN")??""}`,`HF_EMBEDDING_MODEL=${e.get("HF_EMBEDDING_MODEL")??"sentence-transformers/all-MiniLM-L6-v2"}`,"","# ----------------------------------------------------------","# Local storage/cache","# ----------------------------------------------------------",`MEMORY_LOCAL_STORAGE_PATH=${e.get("MEMORY_LOCAL_STORAGE_PATH")??""}`,`MEMORY_LOCAL_CACHE_MB=${e.get("MEMORY_LOCAL_CACHE_MB")??"200"}`,"","# ----------------------------------------------------------","# Automation","# ----------------------------------------------------------",`MEMORY_AUTO_CAPTURE=${e.get("MEMORY_AUTO_CAPTURE")??"true"}`,`MEMORY_AUTO_RETRIEVE=${e.get("MEMORY_AUTO_RETRIEVE")??"true"}`,`MEMORY_AUTO_SUMMARIZE=${e.get("MEMORY_AUTO_SUMMARIZE")??"true"}`,`MEMORY_AUTO_SYNC=${e.get("MEMORY_AUTO_SYNC")??"true"}`,"","# ----------------------------------------------------------","# Retrieval","# ----------------------------------------------------------",`MEMORY_MAX_CANDIDATES=${e.get("MEMORY_MAX_CANDIDATES")??"50"}`,`MEMORY_RERANK_TOP=${e.get("MEMORY_RERANK_TOP")??"10"}`,`MEMORY_FINAL_CONTEXT=${e.get("MEMORY_FINAL_CONTEXT")??"5"}`,`MEMORY_TOKEN_BUDGET=${e.get("MEMORY_TOKEN_BUDGET")??"2000"}`,"","# ----------------------------------------------------------","# Automatic Session Memory","# ----------------------------------------------------------",`TOOLNET_SESSION_LEARNING=${e.get("TOOLNET_SESSION_LEARNING")??"1"}`,`TOOLNET_WORK_CONTINUITY=${e.get("TOOLNET_WORK_CONTINUITY")??"1"}`,`TOOLNET_SEMANTIC_CONTINUITY=${e.get("TOOLNET_SEMANTIC_CONTINUITY")??"1"}`,`TOOLNET_SMART_HANDOFF=${e.get("TOOLNET_SMART_HANDOFF")??"1"}`],n=[...e.entries()].filter(([r])=>!Oo.has(r));if(n.length>0){t.push("","# ----------------------------------------------------------","# Preserved settings","# ----------------------------------------------------------");for(let[r,i]of n)t.push(`${r}=${i}`)}return`${t.join(`
658
658
  `)}
659
- `}function O(e){m.mkdirSync(q,{recursive:!0,mode:448});let t=`${_}.tmp-${process.pid}`;m.writeFileSync(t,ot(e),{encoding:"utf8",mode:384}),m.renameSync(t,_),m.chmodSync(q,448),m.chmodSync(_,384)}function p(e,t,o,n){let r=o.trim();if(r){e.set(t,r);return}!e.get(t)&&n!==void 0&&e.set(t,n)}async function Y(e,t){return f.isTTY?(e.pause(),I.write(t),new Promise(o=>{let n="",r=!1,s=()=>{r||(r=!0,f.off("data",a),f.setRawMode?.(!1),f.pause(),I.write(`
660
- `),e.resume(),o(n))},a=l=>{for(let c of l.toString("utf8")){if(c==="\r"||c===`
661
- `){s();return}if(c===""&&(f.off("data",a),f.setRawMode?.(!1),I.write(`
662
- `),process.exit(130)),c==="\x7F"){n=n.slice(0,-1);continue}n+=c}};f.resume(),f.setRawMode?.(!0),f.on("data",a)})):""}function L(e){return e.trim().replace(/\/+$/,"")}function _e(e){return`https://${e}.r2.cloudflarestorage.com`}async function J(e){let t=new AbortController,o=setTimeout(()=>t.abort(),15e3);o.unref?.();let n=new Qe({region:e.region,endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}});try{return await n.send(new Ze({Bucket:e.bucket}),{abortSignal:t.signal}),{ok:!0,message:`Bucket "${e.bucket}" reachable`}}catch(r){return{ok:!1,message:r instanceof Error?r.message:String(r)}}finally{clearTimeout(o),n.destroy()}}async function nt(e){let t=e.get("R2_ACCOUNT_ID")?.trim()??"",o=e.get("R2_BUCKET")?.trim()??"",n=e.get("R2_ACCESS_KEY_ID")?.trim()??"",r=e.get("R2_SECRET_ACCESS_KEY")?.trim()??"";return!t||!o||!n||!r?{ok:!1,message:"R2 configuration is incomplete"}:J({endpoint:_e(t),region:"auto",bucket:o,accessKeyId:n,secretAccessKey:r})}async function rt(e){let t=L(e.get("S3_ENDPOINT")??""),o=e.get("S3_REGION")?.trim()||"us-east-1",n=e.get("S3_BUCKET")?.trim()??"",r=e.get("S3_ACCESS_KEY_ID")?.trim()??"",s=e.get("S3_SECRET_ACCESS_KEY")?.trim()??"";return!n||!r||!s?{ok:!1,message:"S3 configuration is incomplete"}:J({endpoint:t||void 0,region:o,bucket:n,accessKeyId:r,secretAccessKey:s,forcePathStyle:e.get("S3_FORCE_PATH_STYLE")==="true"})}async function it(e){let t=L(e.get("HF_URL")??""),o=e.get("HF_BUCKET")?.trim()??"",n=e.get("HF_S3_ACCESS_KEY_ID")?.trim()??"",r=e.get("HF_S3_SECRET_ACCESS_KEY")?.trim()??"";return t?!o||!n||!r?{ok:!1,message:"Hugging Face S3 configuration is incomplete"}:J({endpoint:t,region:"us-east-1",bucket:o,accessKeyId:n,secretAccessKey:r,forcePathStyle:!0}):{ok:!1,message:"HF_URL / S3 endpoint is required for connection test"}}async function st(e){let t=e.get("MEMORY_LOCAL_STORAGE_PATH")?.trim()||R.join(j.homedir(),".local","share","toolnet-memory"),o=R.join(t,`.toolnet-test-${process.pid}-${Date.now()}`);try{return m.mkdirSync(t,{recursive:!0,mode:448}),m.writeFileSync(o,`toolnet-memory
663
- `,{encoding:"utf8",mode:384}),m.unlinkSync(o),{ok:!0,message:`Writable: ${t}`}}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}}async function at(e,t){switch(e){case"r2":return nt(t);case"s3":return rt(t);case"huggingface":return it(t);case"local":return st(t)}}async function ct(e,t){console.log(""),console.log(`Testing ${M(e)}...`);let o=await at(e,t);return o.ok?console.log(`\u2713 ${o.message}`):(console.log("\u2717 Connection test failed"),console.log(` ${o.message}`)),console.log(""),o}function lt(){console.log(""),console.log("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.log("\u2551 TOOLNET MEMORY SETUP \u2551"),console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),console.log("")}function dt(e){let t=T(e);console.log("Current configuration"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(`Storage : ${M(t)} ${ue(e)?"\u2713":"\u26A0 incomplete"}`);let o=e.get("TOOLNET_LLM_PROVIDER"),n=e.get("TOOLNET_LLM_MODEL"),r=e.get("TOOLNET_EMBEDDING_PROVIDER");console.log(`LLM : ${o?`${fe(o)}${n?` / ${n}`:""}`:"not configured"}`),console.log(`Embedding: ${r||"legacy/default"}`),console.log("")}async function gt(e){console.log("Setup"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" 1. Storage"),console.log(" 2. AI Model"),console.log(" 3. Finish & Save"),console.log(" 0. Exit without saving"),console.log("");let t=(await e.question("Choose [1-3]: ")).trim();return t==="1"?"storage":t==="2"?"ai":t==="0"?"exit":"finish"}async function Et(e,t){console.log(""),console.log("Storage"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(` 1. Cloudflare R2${t==="r2"?" \u2713 current":""}`),console.log(` 2. S3 / S3-compatible${t==="s3"?" \u2713 current":""}`),console.log(` 3. Hugging Face S3${t==="huggingface"?" \u2713 current":""}`),console.log(` 4. Local${t==="local"?" \u2713 current":""}`),console.log(""),console.log(" 0. Back"),console.log("");let o=(await e.question("Choose storage: ")).trim();return o==="0"?"back":o==="2"?"s3":o==="3"?"huggingface":o==="4"?"local":"r2"}async function ut(e,t){console.log(""),console.log("Cloudflare R2"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let o=await e.question(t.get("R2_ACCOUNT_ID")?`ACCOUNT ID [${t.get("R2_ACCOUNT_ID")}]: `:"ACCOUNT ID: "),n=await e.question(t.get("R2_ACCESS_KEY_ID")?`ACCESS KEY ID [${V(t.get("R2_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),r=await e.question(`BUCKET [${t.get("R2_BUCKET")||"toolnet-memory"}]: `);p(t,"R2_ACCOUNT_ID",o),p(t,"R2_ACCESS_KEY_ID",n),p(t,"R2_BUCKET",r,"toolnet-memory");let s=t.get("R2_ACCOUNT_ID")?.trim();s&&console.log(`URL: ${_e(s)}`);let a=await Y(e,t.get("R2_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");a.trim()&&t.set("R2_SECRET_ACCESS_KEY",a.trim())}async function _t(e,t){console.log(""),console.log("S3 / S3-compatible"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let o=await e.question(t.get("S3_ENDPOINT")?`URL / ENDPOINT [${t.get("S3_ENDPOINT")}]: `:"URL / ENDPOINT [blank = AWS S3]: "),n=await e.question(`REGION [${t.get("S3_REGION")||"us-east-1"}]: `),r=await e.question(t.get("S3_ACCESS_KEY_ID")?`ACCESS KEY ID [${V(t.get("S3_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),s=await e.question(`BUCKET [${t.get("S3_BUCKET")||"toolnet-memory"}]: `),a=t.get("S3_FORCE_PATH_STYLE")==="true",l=await e.question(`FORCE PATH STYLE [${a?"Y":"N"}] (y/n): `);if(o.trim()&&t.set("S3_ENDPOINT",L(o)),p(t,"S3_REGION",n,"us-east-1"),p(t,"S3_ACCESS_KEY_ID",r),p(t,"S3_BUCKET",s,"toolnet-memory"),l.trim()){let d=l.trim().toLowerCase();t.set("S3_FORCE_PATH_STYLE",d==="y"||d==="yes"?"true":"false")}else t.has("S3_FORCE_PATH_STYLE")||t.set("S3_FORCE_PATH_STYLE","false");let c=await Y(e,t.get("S3_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");c.trim()&&t.set("S3_SECRET_ACCESS_KEY",c.trim())}async function ft(e,t){console.log(""),console.log("Hugging Face S3"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let o=await e.question(t.get("HF_NAMESPACE")?`NAMESPACE [${t.get("HF_NAMESPACE")}]: `:"NAMESPACE [optional]: "),n=await e.question(t.get("HF_S3_ACCESS_KEY_ID")?`ACCESS KEY ID [${V(t.get("HF_S3_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),r=await e.question(`BUCKET [${t.get("HF_BUCKET")||"toolnet-memory"}]: `),s=await e.question(t.get("HF_URL")?`URL [${t.get("HF_URL")}]: `:"URL / S3 ENDPOINT: ");p(t,"HF_NAMESPACE",o),p(t,"HF_S3_ACCESS_KEY_ID",n),p(t,"HF_BUCKET",r,"toolnet-memory"),s.trim()&&t.set("HF_URL",L(s));let a=await Y(e,t.get("HF_S3_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");a.trim()&&t.set("HF_S3_SECRET_ACCESS_KEY",a.trim())}async function mt(e,t){console.log(""),console.log("Local Storage"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let o=t.get("MEMORY_LOCAL_STORAGE_PATH")??R.join(j.homedir(),".local","share","toolnet-memory"),n=await e.question(`LOCAL PATH [${o}]: `);p(t,"MEMORY_LOCAL_STORAGE_PATH",n,o)}async function pt(e,t){let o=new Map(t);for(;;){let n=await Et(e,T(t));if(n==="back")return;let r=new Map(t);t.set("MEMORY_STORAGE_PROVIDER",n),n==="r2"?await ut(e,t):n==="s3"?await _t(e,t):n==="huggingface"?await ft(e,t):await mt(e,t);let s=Ee(n).filter(c=>!t.get(c)?.trim());if(s.length){console.log(""),console.log("\u26A0 Missing required fields:");for(let d of s)console.log(` - ${d}`);console.log(""),console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let c=(await e.question("Choose [1]: ")).trim()||"1";if(c==="2"){O(t),console.log(""),console.log("\u26A0 Saved with incomplete configuration"),console.log("");return}if(c==="3"){t.clear();for(let[d,E]of r)t.set(d,E);continue}if(c==="4"){t.clear();for(let[d,E]of o)t.set(d,E);console.log(""),console.log("Storage changes cancelled."),console.log("");return}continue}if((await ct(n,t)).ok){O(t),console.log(`\u2713 ${M(n)} configuration saved`),console.log(` ${_}`),console.log("");return}console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let l=(await e.question("Choose [1]: ")).trim()||"1";if(l==="2"){O(t),console.log(""),console.log("\u26A0 Saved even though connection test failed"),console.log("");return}if(l==="3"){t.clear();for(let[c,d]of r)t.set(c,d);continue}if(l==="4"){t.clear();for(let[c,d]of o)t.set(c,d);console.log(""),console.log("Storage changes cancelled."),console.log("");return}}}var C=[{id:"openai-compatible",label:"OpenAI-compatible",apiKeyRequired:!0,baseUrlRequired:!0},{id:"alibaba",label:"Alibaba / DashScope",baseUrl:"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",suggestedModel:"qwen3.6-flash",apiKeyRequired:!0},{id:"openrouter",label:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",apiKeyRequired:!0},{id:"groq",label:"Groq",baseUrl:"https://api.groq.com/openai/v1",apiKeyRequired:!0},{id:"deepseek",label:"DeepSeek",baseUrl:"https://api.deepseek.com",suggestedModel:"deepseek-v4-flash",apiKeyRequired:!0},{id:"nvidia",label:"NVIDIA NIM",baseUrl:"https://integrate.api.nvidia.com/v1",suggestedModel:"deepseek-ai/deepseek-v4-pro",apiKeyRequired:!0},{id:"gemini",label:"Gemini",baseUrl:"https://generativelanguage.googleapis.com/v1beta",suggestedModel:"gemini-3.6-flash",apiKeyRequired:!0},{id:"huggingface",label:"Hugging Face",baseUrl:"https://router.huggingface.co/v1",apiKeyRequired:!0},{id:"ollama",label:"Ollama / Local",baseUrl:"http://127.0.0.1:11434/v1",apiKeyRequired:!1},{id:"custom",label:"Custom endpoint",apiKeyRequired:!1,baseUrlRequired:!0},{id:"cloudflare",label:"Cloudflare Workers AI",suggestedModel:"@cf/meta/llama-3.1-8b-instruct",apiKeyRequired:!0,accountIdRequired:!0}];function Ot(e){return C.find(t=>t.id===e)}function fe(e){return Ot(e)?.label??e??"not configured"}function me(e){let t=e.get("TOOLNET_LLM_PROVIDER")?.trim();return C.some(o=>o.id===t)?t:void 0}async function pe(e,t){console.log(""),console.log("AI Model"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),C.forEach((r,s)=>{console.log(` ${s+1}. ${r.label}${t===r.id?" \u2713 current":""}`)}),console.log(""),console.log(" 0. Back"),console.log("");let o=(await e.question("Choose provider: ")).trim();if(o==="0")return"back";let n=Number(o)-1;return Number.isInteger(n)&&n>=0&&n<C.length?C[n].id:(console.log(""),console.log("\u26A0 Invalid provider selection"),pe(e,t))}function Tt(e,t){return!(!e.get("TOOLNET_LLM_MODEL")?.trim()||t.apiKeyRequired&&!e.get("TOOLNET_LLM_API_KEY")?.trim()||t.accountIdRequired&&!e.get("TOOLNET_LLM_ACCOUNT_ID")?.trim()||t.baseUrlRequired&&!e.get("TOOLNET_LLM_BASE_URL")?.trim())}function At(e){e.delete("TOOLNET_LLM_API_KEY"),e.delete("TOOLNET_LLM_BASE_URL"),e.delete("TOOLNET_LLM_MODEL"),e.delete("TOOLNET_LLM_ACCOUNT_ID")}async function St(e,t,o){console.log(""),console.log(o.label),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let n=t.get("TOOLNET_LLM_PROVIDER");if(n&&n!==o.id&&At(t),t.set("TOOLNET_LLM_PROVIDER",o.id),o.accountIdRequired){let c=t.get("TOOLNET_LLM_ACCOUNT_ID"),d=await e.question(c?`ACCOUNT ID [${c}]: `:"ACCOUNT ID: ");p(t,"TOOLNET_LLM_ACCOUNT_ID",d)}else t.delete("TOOLNET_LLM_ACCOUNT_ID");if(o.apiKeyRequired||o.id==="custom"){let c=t.get("TOOLNET_LLM_API_KEY"),d=await Y(e,c?"API KEY [configured, Enter = keep]: ":o.apiKeyRequired?"API KEY: ":"API KEY [optional]: ");d.trim()&&t.set("TOOLNET_LLM_API_KEY",d.trim())}else t.delete("TOOLNET_LLM_API_KEY");if(o.id!=="cloudflare"){let d=t.get("TOOLNET_LLM_BASE_URL")||o.baseUrl||"",y=(await e.question(d?`BASE URL [${d}]: `:o.baseUrlRequired?"BASE URL: ":"BASE URL [optional]: ")).trim()||d;y?t.set("TOOLNET_LLM_BASE_URL",L(y)):t.delete("TOOLNET_LLM_BASE_URL")}else t.delete("TOOLNET_LLM_BASE_URL");let s=t.get("TOOLNET_LLM_MODEL")||o.suggestedModel||"",l=(await e.question(s?`MODEL [${s}]: `:"MODEL: ")).trim()||s;l&&t.set("TOOLNET_LLM_MODEL",l)}function Ct(e){let t=me(e);if(!t)throw new Error("AI provider is not configured");return{id:t,apiKey:e.get("TOOLNET_LLM_API_KEY")?.trim()||void 0,baseUrl:e.get("TOOLNET_LLM_BASE_URL")?.trim()||void 0,model:e.get("TOOLNET_LLM_MODEL")?.trim()||void 0,accountId:e.get("TOOLNET_LLM_ACCOUNT_ID")?.trim()||void 0}}async function yt(e){let t=Ct(e);console.log(""),console.log(`Testing ${fe(t.id)}...`);try{let n=await Q(t).healthCheck();return n.ok?(console.log(`\u2713 Provider reachable${n.latencyMs?` (${n.latencyMs} ms)`:""}`),console.log(`\u2713 Model: ${n.model??t.model??"configured"}`),console.log(""),{ok:!0,message:n.message}):(console.log("\u2717 AI provider test failed"),console.log(` ${n.message}`),console.log(""),{ok:!1,message:n.message})}catch(o){let n=o instanceof Error?o.message:String(o);return console.log("\u2717 AI provider test failed"),console.log(` ${n}`),console.log(""),{ok:!1,message:n}}}async function It(e,t){let o=new Map(t);for(;;){let n=await pe(e,me(t));if(n==="back")return;let r=C.find(l=>l.id===n);if(!r)continue;if(await St(e,t,r),!Tt(t,r)){console.log(""),console.log("\u26A0 AI configuration is incomplete."),console.log(""),console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let l=(await e.question("Choose [1]: ")).trim()||"1";if(l==="2"){O(t),console.log(""),console.log("\u26A0 AI configuration saved without validation"),console.log(` ${_}`),console.log("");return}if(l==="3")continue;if(l==="4"){t.clear();for(let[c,d]of o)t.set(c,d);console.log(""),console.log("AI changes cancelled."),console.log("");return}continue}if((await yt(t)).ok){O(t),console.log(`\u2713 ${r.label} configuration saved`),console.log(` ${_}`),console.log("");return}console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let a=(await e.question("Choose [1]: ")).trim()||"1";if(a==="2"){O(t),console.log(""),console.log("\u26A0 AI configuration saved even though provider test failed"),console.log(` ${_}`),console.log("");return}if(a!=="3"&&a==="4"){t.clear();for(let[l,c]of o)t.set(l,c);console.log(""),console.log("AI changes cancelled."),console.log("");return}}}function Rt(){try{let t=G().filter(o=>o.installed);if(t.length===0)return;console.log(""),console.log("Automatic AI memory");for(let o of t){let n=o.agent==="agy"?"Agy / Antigravity":o.agent==="opencode"?"OpenCode":o.agent==="codex"?"Codex":o.agent;console.log(` \u2713 ${n}`)}}catch{}}function Oe(e){e.has("MEMORY_STORAGE_PROVIDER")||e.set("MEMORY_STORAGE_PROVIDER",T(e)),e.has("MEMORY_LOCAL_CACHE_MB")||e.set("MEMORY_LOCAL_CACHE_MB","200"),e.has("MEMORY_AUTO_CAPTURE")||e.set("MEMORY_AUTO_CAPTURE","true"),e.has("MEMORY_AUTO_RETRIEVE")||e.set("MEMORY_AUTO_RETRIEVE","true"),e.has("MEMORY_AUTO_SUMMARIZE")||e.set("MEMORY_AUTO_SUMMARIZE","true"),e.has("MEMORY_AUTO_SYNC")||e.set("MEMORY_AUTO_SYNC","true"),e.has("MEMORY_MAX_CANDIDATES")||e.set("MEMORY_MAX_CANDIDATES","50"),e.has("MEMORY_RERANK_TOP")||e.set("MEMORY_RERANK_TOP","10"),e.has("MEMORY_FINAL_CONTEXT")||e.set("MEMORY_FINAL_CONTEXT","5"),e.has("MEMORY_TOKEN_BUDGET")||e.set("MEMORY_TOKEN_BUDGET","2000"),e.has("TOOLNET_SESSION_LEARNING")||e.set("TOOLNET_SESSION_LEARNING","1"),e.has("TOOLNET_WORK_CONTINUITY")||e.set("TOOLNET_WORK_CONTINUITY","1"),e.has("TOOLNET_SEMANTIC_CONTINUITY")||e.set("TOOLNET_SEMANTIC_CONTINUITY","1"),e.has("TOOLNET_SMART_HANDOFF")||e.set("TOOLNET_SMART_HANDOFF","1")}async function Mt(e,t){Oe(e),t||O(e),console.log("TOOLNET MEMORY SETUP"),console.log(""),console.log("Interactive terminal not detected."),console.log(`Config: ${_}`),console.log(`Storage: ${M(T(e))}`),console.log(""),console.log("Run from an interactive terminal to configure providers:"),console.log(" toolnet-memory setup")}async function Lt(){let e=m.existsSync(_),t=e?tt(m.readFileSync(_,"utf8")):new Map,o=new Map(t);if(Oe(o),!f.isTTY||!I.isTTY){await Mt(o,e);return}let n=ze.createInterface({input:f,output:I}),r=!1;try{for(;;){lt(),dt(o);let s=await gt(n);if(s==="storage"){let a=JSON.stringify([...o.entries()]);await pt(n,o),r=r||a!==JSON.stringify([...o.entries()]);continue}if(s==="ai"){let a=JSON.stringify([...o.entries()]);await It(n,o),r=r||a!==JSON.stringify([...o.entries()]);continue}if(s==="exit"){if(!r){console.log(""),console.log("No changes made.");return}console.log("");let a=(await n.question("Discard unsaved changes? (y/N): ")).trim().toLowerCase();if(a==="y"||a==="yes"){console.log(""),console.log("Changes discarded.");return}continue}O(o),console.log(""),console.log("\u2713 Configuration saved"),console.log(` ${_}`),console.log(""),console.log(`\u2713 Permissions: ${m.statSync(_).mode.toString(8).slice(-3)}`),console.log(`\u2713 Storage: ${M(T(o))}`),ue(o)||console.log("\u26A0 Storage configuration is incomplete."),Rt(),console.log(""),console.log("Next:"),console.log(" toolnet-memory doctor"),console.log("");return}}finally{n.close()}}Lt().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1)});
659
+ `}function f(e){p.mkdirSync(Q,{recursive:!0,mode:448});let o=`${u}.tmp-${process.pid}`;p.writeFileSync(o,fo(e),{encoding:"utf8",mode:384}),p.renameSync(o,u),p.chmodSync(Q,448),p.chmodSync(u,384)}function T(e,o,t,n){let r=t.trim();if(r){e.set(o,r);return}!e.get(o)&&n!==void 0&&e.set(o,n)}async function y(e,o){return A.isTTY?(e.pause(),D.write(o),new Promise(t=>{let n="",r=!1,i=()=>{r||(r=!0,A.off("data",s),A.setRawMode?.(!1),A.pause(),D.write(`
660
+ `),e.resume(),t(n))},s=l=>{for(let a of l.toString("utf8")){if(a==="\r"||a===`
661
+ `){i();return}if(a===""&&(A.off("data",s),A.setRawMode?.(!1),D.write(`
662
+ `),process.exit(130)),a==="\x7F"){n=n.slice(0,-1);continue}n+=a}};A.resume(),A.setRawMode?.(!0),A.on("data",s)})):""}function S(e){return e.trim().replace(/\/+$/,"")}function Re(e){return`https://${e}.r2.cloudflarestorage.com`}async function oe(e){let o=new AbortController,t=setTimeout(()=>o.abort(),15e3);t.unref?.();let n=new _o({region:e.region,endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}});try{return await n.send(new go({Bucket:e.bucket}),{abortSignal:o.signal}),{ok:!0,message:`Bucket "${e.bucket}" reachable`}}catch(r){return{ok:!1,message:r instanceof Error?r.message:String(r)}}finally{clearTimeout(t),n.destroy()}}async function uo(e){let o=e.get("R2_ACCOUNT_ID")?.trim()??"",t=e.get("R2_BUCKET")?.trim()??"",n=e.get("R2_ACCESS_KEY_ID")?.trim()??"",r=e.get("R2_SECRET_ACCESS_KEY")?.trim()??"";return!o||!t||!n||!r?{ok:!1,message:"R2 configuration is incomplete"}:oe({endpoint:Re(o),region:"auto",bucket:t,accessKeyId:n,secretAccessKey:r})}async function mo(e){let o=S(e.get("S3_ENDPOINT")??""),t=e.get("S3_REGION")?.trim()||"us-east-1",n=e.get("S3_BUCKET")?.trim()??"",r=e.get("S3_ACCESS_KEY_ID")?.trim()??"",i=e.get("S3_SECRET_ACCESS_KEY")?.trim()??"";return!n||!r||!i?{ok:!1,message:"S3 configuration is incomplete"}:oe({endpoint:o||void 0,region:t,bucket:n,accessKeyId:r,secretAccessKey:i,forcePathStyle:e.get("S3_FORCE_PATH_STYLE")==="true"})}async function To(e){let o=S(e.get("HF_URL")??""),t=e.get("HF_BUCKET")?.trim()??"",n=e.get("HF_S3_ACCESS_KEY_ID")?.trim()??"",r=e.get("HF_S3_SECRET_ACCESS_KEY")?.trim()??"";return o?!t||!n||!r?{ok:!1,message:"Hugging Face S3 configuration is incomplete"}:oe({endpoint:o,region:"us-east-1",bucket:t,accessKeyId:n,secretAccessKey:r,forcePathStyle:!0}):{ok:!1,message:"HF_URL / S3 endpoint is required for connection test"}}async function Ao(e){let o=e.get("MEMORY_LOCAL_STORAGE_PATH")?.trim()||h.join(Z.homedir(),".local","share","toolnet-memory"),t=h.join(o,`.toolnet-test-${process.pid}-${Date.now()}`);try{return p.mkdirSync(o,{recursive:!0,mode:448}),p.writeFileSync(t,`toolnet-memory
663
+ `,{encoding:"utf8",mode:384}),p.unlinkSync(t),{ok:!0,message:`Writable: ${o}`}}catch(n){return{ok:!1,message:n instanceof Error?n.message:String(n)}}}async function po(e,o){switch(e){case"r2":return uo(o);case"s3":return mo(o);case"huggingface":return To(o);case"local":return Ao(o)}}async function Mo(e,o){console.log(""),console.log(`Testing ${P(e)}...`);let t=await po(e,o);return t.ok?console.log(`\u2713 ${t.message}`):(console.log("\u2717 Connection test failed"),console.log(` ${t.message}`)),console.log(""),t}function Io(){console.log(""),console.log("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.log("\u2551 TOOLNET MEMORY SETUP \u2551"),console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),console.log("")}function No(e){let o=N(e);console.log("Current configuration"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(`Storage : ${P(o)} ${Ce(e)?"\u2713":"\u26A0 incomplete"}`);let t=e.get("TOOLNET_LLM_PROVIDER"),n=e.get("TOOLNET_LLM_MODEL"),r=e.get("TOOLNET_EMBEDDING_PROVIDER");console.log(`LLM : ${t?`${M(t)}${n?` / ${n}`:""}`:"not configured"}`),console.log(`Embedding: ${r||"legacy/default"}`),console.log("")}async function So(e){console.log("Setup"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" 1. Storage"),console.log(" 2. AI Model"),console.log(" 3. Finish & Save"),console.log(" 0. Exit without saving"),console.log("");let o=(await e.question("Choose [1-3]: ")).trim();return o==="1"?"storage":o==="2"?"ai":o==="0"?"exit":"finish"}async function Co(e,o){console.log(""),console.log("Storage"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(` 1. Cloudflare R2${o==="r2"?" \u2713 current":""}`),console.log(` 2. S3 / S3-compatible${o==="s3"?" \u2713 current":""}`),console.log(` 3. Hugging Face S3${o==="huggingface"?" \u2713 current":""}`),console.log(` 4. Local${o==="local"?" \u2713 current":""}`),console.log(""),console.log(" 0. Back"),console.log("");let t=(await e.question("Choose storage: ")).trim();return t==="0"?"back":t==="2"?"s3":t==="3"?"huggingface":t==="4"?"local":"r2"}async function Ro(e,o){console.log(""),console.log("Cloudflare R2"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=await e.question(o.get("R2_ACCOUNT_ID")?`ACCOUNT ID [${o.get("R2_ACCOUNT_ID")}]: `:"ACCOUNT ID: "),n=await e.question(o.get("R2_ACCESS_KEY_ID")?`ACCESS KEY ID [${ee(o.get("R2_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),r=await e.question(`BUCKET [${o.get("R2_BUCKET")||"toolnet-memory"}]: `);T(o,"R2_ACCOUNT_ID",t),T(o,"R2_ACCESS_KEY_ID",n),T(o,"R2_BUCKET",r,"toolnet-memory");let i=o.get("R2_ACCOUNT_ID")?.trim();i&&console.log(`URL: ${Re(i)}`);let s=await y(e,o.get("R2_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");s.trim()&&o.set("R2_SECRET_ACCESS_KEY",s.trim())}async function yo(e,o){console.log(""),console.log("S3 / S3-compatible"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=await e.question(o.get("S3_ENDPOINT")?`URL / ENDPOINT [${o.get("S3_ENDPOINT")}]: `:"URL / ENDPOINT [blank = AWS S3]: "),n=await e.question(`REGION [${o.get("S3_REGION")||"us-east-1"}]: `),r=await e.question(o.get("S3_ACCESS_KEY_ID")?`ACCESS KEY ID [${ee(o.get("S3_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),i=await e.question(`BUCKET [${o.get("S3_BUCKET")||"toolnet-memory"}]: `),s=o.get("S3_FORCE_PATH_STYLE")==="true",l=await e.question(`FORCE PATH STYLE [${s?"Y":"N"}] (y/n): `);if(t.trim()&&o.set("S3_ENDPOINT",S(t)),T(o,"S3_REGION",n,"us-east-1"),T(o,"S3_ACCESS_KEY_ID",r),T(o,"S3_BUCKET",i,"toolnet-memory"),l.trim()){let E=l.trim().toLowerCase();o.set("S3_FORCE_PATH_STYLE",E==="y"||E==="yes"?"true":"false")}else o.has("S3_FORCE_PATH_STYLE")||o.set("S3_FORCE_PATH_STYLE","false");let a=await y(e,o.get("S3_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");a.trim()&&o.set("S3_SECRET_ACCESS_KEY",a.trim())}async function Do(e,o){console.log(""),console.log("Hugging Face S3"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=await e.question(o.get("HF_NAMESPACE")?`NAMESPACE [${o.get("HF_NAMESPACE")}]: `:"NAMESPACE [optional]: "),n=await e.question(o.get("HF_S3_ACCESS_KEY_ID")?`ACCESS KEY ID [${ee(o.get("HF_S3_ACCESS_KEY_ID"))}]: `:"ACCESS KEY ID: "),r=await e.question(`BUCKET [${o.get("HF_BUCKET")||"toolnet-memory"}]: `),i=await e.question(o.get("HF_URL")?`URL [${o.get("HF_URL")}]: `:"URL / S3 ENDPOINT: ");T(o,"HF_NAMESPACE",t),T(o,"HF_S3_ACCESS_KEY_ID",n),T(o,"HF_BUCKET",r,"toolnet-memory"),i.trim()&&o.set("HF_URL",S(i));let s=await y(e,o.get("HF_S3_SECRET_ACCESS_KEY")?"SECRET ACCESS KEY [configured, Enter = keep]: ":"SECRET ACCESS KEY: ");s.trim()&&o.set("HF_S3_SECRET_ACCESS_KEY",s.trim())}async function ho(e,o){console.log(""),console.log("Local Storage"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=o.get("MEMORY_LOCAL_STORAGE_PATH")??h.join(Z.homedir(),".local","share","toolnet-memory"),n=await e.question(`LOCAL PATH [${t}]: `);T(o,"MEMORY_LOCAL_STORAGE_PATH",n,t)}async function Po(e,o){let t=new Map(o);for(;;){let n=await Co(e,N(o));if(n==="back")return;let r=new Map(o);o.set("MEMORY_STORAGE_PROVIDER",n),n==="r2"?await Ro(e,o):n==="s3"?await yo(e,o):n==="huggingface"?await Do(e,o):await ho(e,o);let i=Se(n).filter(a=>!o.get(a)?.trim());if(i.length){console.log(""),console.log("\u26A0 Missing required fields:");for(let E of i)console.log(` - ${E}`);console.log(""),console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let a=(await e.question("Choose [1]: ")).trim()||"1";if(a==="2"){f(o),console.log(""),console.log("\u26A0 Saved with incomplete configuration"),console.log("");return}if(a==="3"){o.clear();for(let[E,d]of r)o.set(E,d);continue}if(a==="4"){o.clear();for(let[E,d]of t)o.set(E,d);console.log(""),console.log("Storage changes cancelled."),console.log("");return}continue}if((await Mo(n,o)).ok){f(o),console.log(`\u2713 ${P(n)} configuration saved`),console.log(` ${u}`),console.log("");return}console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let l=(await e.question("Choose [1]: ")).trim()||"1";if(l==="2"){f(o),console.log(""),console.log("\u26A0 Saved even though connection test failed"),console.log("");return}if(l==="3"){o.clear();for(let[a,E]of r)o.set(a,E);continue}if(l==="4"){o.clear();for(let[a,E]of t)o.set(a,E);console.log(""),console.log("Storage changes cancelled."),console.log("");return}}}var I=[{id:"openai-compatible",label:"OpenAI-compatible",apiKeyRequired:!0,baseUrlRequired:!0},{id:"alibaba",label:"Alibaba / DashScope",baseUrl:"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",suggestedModel:"qwen3.6-flash",apiKeyRequired:!0},{id:"openrouter",label:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",apiKeyRequired:!0},{id:"groq",label:"Groq",baseUrl:"https://api.groq.com/openai/v1",apiKeyRequired:!0},{id:"deepseek",label:"DeepSeek",baseUrl:"https://api.deepseek.com",suggestedModel:"deepseek-v4-flash",apiKeyRequired:!0},{id:"nvidia",label:"NVIDIA NIM",baseUrl:"https://integrate.api.nvidia.com/v1",suggestedModel:"deepseek-ai/deepseek-v4-pro",apiKeyRequired:!0},{id:"gemini",label:"Gemini",baseUrl:"https://generativelanguage.googleapis.com/v1beta",suggestedModel:"gemini-3.6-flash",apiKeyRequired:!0},{id:"huggingface",label:"Hugging Face",baseUrl:"https://router.huggingface.co/v1",apiKeyRequired:!0},{id:"ollama",label:"Ollama / Local",baseUrl:"http://127.0.0.1:11434/v1",apiKeyRequired:!1},{id:"custom",label:"Custom endpoint",apiKeyRequired:!1,baseUrlRequired:!0},{id:"cloudflare",label:"Cloudflare Workers AI",suggestedModel:"@cf/meta/llama-3.1-8b-instruct",apiKeyRequired:!0,accountIdRequired:!0}];function bo(e){return I.find(o=>o.id===e)}function M(e){return bo(e)?.label??e??"not configured"}function ye(e){let o=e.get("TOOLNET_LLM_PROVIDER")?.trim();return I.some(t=>t.id===o)?o:void 0}async function te(e,o){console.log(""),console.log("AI Model"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),I.forEach((r,i)=>{console.log(` ${i+1}. ${r.label}${o===r.id?" \u2713 current":""}`)}),console.log(""),console.log(" 0. Back"),console.log("");let t=(await e.question("Choose provider: ")).trim();if(t==="0")return"back";let n=Number(t)-1;return Number.isInteger(n)&&n>=0&&n<I.length?I[n].id:(console.log(""),console.log("\u26A0 Invalid provider selection"),te(e,o))}function Ko(e,o){return!(!e.get("TOOLNET_LLM_MODEL")?.trim()||o.apiKeyRequired&&!e.get("TOOLNET_LLM_API_KEY")?.trim()||o.accountIdRequired&&!e.get("TOOLNET_LLM_ACCOUNT_ID")?.trim()||o.baseUrlRequired&&!e.get("TOOLNET_LLM_BASE_URL")?.trim())}function Uo(e){e.delete("TOOLNET_LLM_API_KEY"),e.delete("TOOLNET_LLM_BASE_URL"),e.delete("TOOLNET_LLM_MODEL"),e.delete("TOOLNET_LLM_ACCOUNT_ID")}async function Bo(e,o,t){console.log(""),console.log(t.label),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let n=o.get("TOOLNET_LLM_PROVIDER");if(n&&n!==t.id&&Uo(o),o.set("TOOLNET_LLM_PROVIDER",t.id),t.accountIdRequired){let a=o.get("TOOLNET_LLM_ACCOUNT_ID"),E=await e.question(a?`ACCOUNT ID [${a}]: `:"ACCOUNT ID: ");T(o,"TOOLNET_LLM_ACCOUNT_ID",E)}else o.delete("TOOLNET_LLM_ACCOUNT_ID");if(t.apiKeyRequired||t.id==="custom"){let a=o.get("TOOLNET_LLM_API_KEY"),E=await y(e,a?"API KEY [configured, Enter = keep]: ":t.apiKeyRequired?"API KEY: ":"API KEY [optional]: ");E.trim()&&o.set("TOOLNET_LLM_API_KEY",E.trim())}else o.delete("TOOLNET_LLM_API_KEY");if(t.id!=="cloudflare"){let E=o.get("TOOLNET_LLM_BASE_URL")||t.baseUrl||"",m=(await e.question(E?`BASE URL [${E}]: `:t.baseUrlRequired?"BASE URL: ":"BASE URL [optional]: ")).trim()||E;m?o.set("TOOLNET_LLM_BASE_URL",S(m)):o.delete("TOOLNET_LLM_BASE_URL")}else o.delete("TOOLNET_LLM_BASE_URL");let i=o.get("TOOLNET_LLM_MODEL")||t.suggestedModel||"",l=(await e.question(i?`MODEL [${i}]: `:"MODEL: ")).trim()||i;l&&o.set("TOOLNET_LLM_MODEL",l)}function wo(e){let o=ye(e);if(!o)throw new Error("AI provider is not configured");return{id:o,apiKey:e.get("TOOLNET_LLM_API_KEY")?.trim()||void 0,baseUrl:e.get("TOOLNET_LLM_BASE_URL")?.trim()||void 0,model:e.get("TOOLNET_LLM_MODEL")?.trim()||void 0,accountId:e.get("TOOLNET_LLM_ACCOUNT_ID")?.trim()||void 0}}async function Yo(e){let o=wo(e);console.log(""),console.log(`Testing ${M(o.id)}...`);try{let n=await le(o).healthCheck();return n.ok?(console.log(`\u2713 Provider reachable${n.latencyMs?` (${n.latencyMs} ms)`:""}`),console.log(`\u2713 Model: ${n.model??o.model??"configured"}`),console.log(""),{ok:!0,message:n.message}):(console.log("\u2717 AI provider test failed"),console.log(` ${n.message}`),console.log(""),{ok:!1,message:n.message})}catch(t){let n=t instanceof Error?t.message:String(t);return console.log("\u2717 AI provider test failed"),console.log(` ${n}`),console.log(""),{ok:!1,message:n}}}var F=[{id:"local",label:"Local / Hash",apiKeyRequired:!1},{id:"huggingface",label:"Hugging Face",suggestedModel:"sentence-transformers/all-MiniLM-L6-v2",apiKeyRequired:!0},{id:"openai-compatible",label:"OpenAI-compatible",apiKeyRequired:!0,baseUrlRequired:!0},{id:"alibaba",label:"Alibaba / DashScope",baseUrl:"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",suggestedModel:"text-embedding-v4",apiKeyRequired:!0},{id:"openrouter",label:"OpenRouter",baseUrl:"https://openrouter.ai/api/v1",apiKeyRequired:!0},{id:"nvidia",label:"NVIDIA NIM",baseUrl:"https://integrate.api.nvidia.com/v1",apiKeyRequired:!0},{id:"ollama",label:"Ollama / Local",baseUrl:"http://127.0.0.1:11434/v1",apiKeyRequired:!1},{id:"gemini",label:"Gemini",baseUrl:"https://generativelanguage.googleapis.com/v1beta",suggestedModel:"gemini-embedding-001",apiKeyRequired:!0},{id:"cloudflare",label:"Cloudflare Workers AI",suggestedModel:"@cf/baai/bge-base-en-v1.5",apiKeyRequired:!0,accountIdRequired:!0},{id:"custom",label:"Custom OpenAI-compatible endpoint",apiKeyRequired:!1,baseUrlRequired:!0}];function ne(e){return F.find(o=>o.id===e)?.label??e??"not configured"}async function De(e,o){console.log(""),console.log("Embedding Model"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),F.forEach((r,i)=>{console.log(` ${i+1}. ${r.label}${o===r.id?" \u2713 current":""}`)}),console.log(""),console.log(" 0. Back"),console.log("");let t=(await e.question("Choose embedding provider: ")).trim();if(t==="0")return"back";let n=Number(t)-1;return Number.isInteger(n)&&n>=0&&n<F.length?F[n]:(console.log(""),console.log("\u26A0 Invalid selection"),De(e,o))}function Me(e){e.delete("TOOLNET_EMBEDDING_API_KEY"),e.delete("TOOLNET_EMBEDDING_BASE_URL"),e.delete("TOOLNET_EMBEDDING_MODEL"),e.delete("TOOLNET_EMBEDDING_ACCOUNT_ID")}async function $o(e,o,t){let n=o.get("TOOLNET_EMBEDDING_PROVIDER");if(n&&n!==t.id&&Me(o),o.set("TOOLNET_EMBEDDING_PROVIDER",t.id),console.log(""),console.log(t.label),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),t.id==="local"){Me(o),console.log("\u2713 Local embedding selected"),console.log(" No API key required.");return}if(t.accountIdRequired){let a=o.get("TOOLNET_EMBEDDING_ACCOUNT_ID"),E=await e.question(a?`ACCOUNT ID [${a}]: `:"ACCOUNT ID: ");T(o,"TOOLNET_EMBEDDING_ACCOUNT_ID",E)}else o.delete("TOOLNET_EMBEDDING_ACCOUNT_ID");if(t.apiKeyRequired||t.id==="custom"){let a=o.get("TOOLNET_EMBEDDING_API_KEY"),E=await y(e,a?"API KEY [configured, Enter = keep]: ":t.apiKeyRequired?"API KEY: ":"API KEY [optional]: ");E.trim()&&o.set("TOOLNET_EMBEDDING_API_KEY",E.trim())}else o.delete("TOOLNET_EMBEDDING_API_KEY");if(t.id==="cloudflare"){let a=o.get("TOOLNET_EMBEDDING_ACCOUNT_ID")?.trim();if(a){let E=`https://api.cloudflare.com/client/v4/accounts/${a}/ai/v1`;o.set("TOOLNET_EMBEDDING_BASE_URL",E),console.log(`BASE URL: ${E}`)}}else{let E=o.get("TOOLNET_EMBEDDING_BASE_URL")||t.baseUrl||"",m=(await e.question(E?`BASE URL [${E}]: `:t.baseUrlRequired?"BASE URL: ":"BASE URL [optional]: ")).trim()||E;m&&o.set("TOOLNET_EMBEDDING_BASE_URL",S(m))}let i=o.get("TOOLNET_EMBEDDING_MODEL")||t.suggestedModel||"",l=(await e.question(i?`MODEL [${i}]: `:"MODEL: ")).trim()||i;l&&o.set("TOOLNET_EMBEDDING_MODEL",l)}function ko(e,o){return o.id==="local"?!0:o.apiKeyRequired&&!e.get("TOOLNET_EMBEDDING_API_KEY")?.trim()||o.accountIdRequired&&!e.get("TOOLNET_EMBEDDING_ACCOUNT_ID")?.trim()||o.baseUrlRequired&&!e.get("TOOLNET_EMBEDDING_BASE_URL")?.trim()?!1:!!e.get("TOOLNET_EMBEDDING_MODEL")?.trim()}async function he(e){let o=e.get("TOOLNET_EMBEDDING_PROVIDER")?.trim();if(console.log(""),console.log(`Testing embedding: ${ne(o)}...`),o==="local")return console.log("\u2713 Local embedding ready"),console.log(""),!0;let t=e.get("TOOLNET_EMBEDDING_API_KEY")?.trim(),n=e.get("TOOLNET_EMBEDDING_MODEL")?.trim(),r=e.get("TOOLNET_EMBEDDING_BASE_URL")?.trim();try{if(!n)throw new Error("Embedding model is missing");if(o==="huggingface"){if(!t)throw new Error("API key is missing");let i=await fetch(`https://router.huggingface.co/hf-inference/models/${n}/pipeline/feature-extraction`,{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({inputs:["toolnet memory test"]})});if(!i.ok)throw new Error(`HTTP ${i.status}: ${await i.text()}`)}else if(o==="gemini"){if(!t)throw new Error("API key is missing");let i=n.replace(/^models\//,"");r=r||"https://generativelanguage.googleapis.com/v1beta";let s=await fetch(`${r.replace(/\/+$/,"")}/models/${encodeURIComponent(i)}:embedContent?key=${encodeURIComponent(t)}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${i}`,content:{parts:[{text:"toolnet memory test"}]}})});if(!s.ok)throw new Error(`HTTP ${s.status}: ${await s.text()}`)}else{if(!r)throw new Error("BASE URL is missing");let i=await fetch(`${r.replace(/\/+$/,"")}/embeddings`,{method:"POST",headers:{"content-type":"application/json",...t?{authorization:`Bearer ${t}`}:{}},body:JSON.stringify({model:n,input:["toolnet memory test"]})});if(!i.ok)throw new Error(`HTTP ${i.status}: ${await i.text()}`);let s=await i.json();if(!Array.isArray(s.data)||!Array.isArray(s.data[0]?.embedding))throw new Error("Invalid embedding response")}return console.log("\u2713 Embedding provider reachable"),console.log(`\u2713 Model: ${n}`),console.log(""),!0}catch(i){return console.log("\u2717 Embedding test failed"),console.log(` ${i instanceof Error?i.message:String(i)}`),console.log(""),!1}}async function Fo(e,o){let t=new Map(o);for(;;){let n=await De(e,o.get("TOOLNET_EMBEDDING_PROVIDER"));if(n==="back")return;if(await $o(e,o,n),!ko(o,n)){console.log(""),console.log("\u26A0 Embedding configuration is incomplete."),console.log(""),console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let s=(await e.question("Choose [1]: ")).trim()||"1";if(s==="2"){f(o);return}if(s==="3")continue;if(s==="4"){o.clear();for(let[l,a]of t)o.set(l,a);return}continue}if(await he(o)){f(o),console.log(`\u2713 ${n.label} embedding configuration saved`),console.log(` ${u}`),console.log("");return}console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let i=(await e.question("Choose [1]: ")).trim()||"1";if(i==="2"){f(o);return}if(i!=="3"&&i==="4"){o.clear();for(let[s,l]of t)o.set(s,l);return}}}async function xo(e,o){let t=o.get("TOOLNET_LLM_PROVIDER")?.trim();if(!t){console.log(""),console.log("\u26A0 Configure LLM first."),console.log("");return}if(t==="deepseek"||t==="groq"){console.log(""),console.log(`\u26A0 ${M(t)} is configured as LLM-only.`),console.log("Choose Embedding separately."),console.log("");return}o.set("TOOLNET_EMBEDDING_PROVIDER",t);let n=o.get("TOOLNET_LLM_API_KEY"),r=o.get("TOOLNET_LLM_BASE_URL"),i=o.get("TOOLNET_LLM_ACCOUNT_ID");n&&o.set("TOOLNET_EMBEDDING_API_KEY",n),r&&o.set("TOOLNET_EMBEDDING_BASE_URL",r),i&&o.set("TOOLNET_EMBEDDING_ACCOUNT_ID",i);let s="";t==="alibaba"?s="text-embedding-v4":t==="gemini"?s="gemini-embedding-001":t==="cloudflare"?s="@cf/baai/bge-base-en-v1.5":t==="huggingface"&&(s="sentence-transformers/all-MiniLM-L6-v2");let a=(await e.question(s?`EMBEDDING MODEL [${s}]: `:"EMBEDDING MODEL: ")).trim()||s;if(!a){console.log(""),console.log("\u26A0 Embedding model is required."),console.log("");return}if(o.set("TOOLNET_EMBEDDING_MODEL",a),!await he(o)){let d=(await e.question("Save anyway? (y/N): ")).trim().toLowerCase();if(d!=="y"&&d!=="yes")return}f(o),console.log(""),console.log("\u2713 LLM credentials reused for Embedding"),console.log(`\u2713 Embedding model: ${a}`),console.log("")}function x(e){return`TOOLNET_LLM_FALLBACK_${e}`}function G(e,o){let t=x(o);for(let n of["PROVIDER","API_KEY","BASE_URL","MODEL","ACCOUNT_ID"])e.delete(`${t}_${n}`)}function Ie(e,o){let t=x(o),n=e.get(`${t}_PROVIDER`);if(!n)return"not configured";let r=e.get(`${t}_MODEL`);return`${M(n)}${r?` / ${r}`:""}`}async function Ne(e,o,t){console.log(""),console.log(`Fallback ${t}`),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let n=await te(e,void 0);if(n==="back")return;let r=o.get("TOOLNET_LLM_PROVIDER");if(n===r){console.log(""),console.log("\u26A0 Fallback cannot be the same provider as Primary."),console.log("");return}let i=t===1?2:1,s=o.get(`${x(i)}_PROVIDER`);if(n===s){console.log(""),console.log("\u26A0 This provider is already used by the other fallback."),console.log("");return}let l=I.find(O=>O.id===n);if(!l)return;let a=x(t);if(G(o,t),o.set(`${a}_PROVIDER`,n),l.accountIdRequired){let O=await e.question("ACCOUNT ID: ");O.trim()&&o.set(`${a}_ACCOUNT_ID`,O.trim())}if(l.apiKeyRequired||n==="custom"){let O=await y(e,l.apiKeyRequired?"API KEY: ":"API KEY [optional]: ");O.trim()&&o.set(`${a}_API_KEY`,O.trim())}if(n==="cloudflare"){let O=o.get(`${a}_ACCOUNT_ID`);O&&o.set(`${a}_BASE_URL`,`https://api.cloudflare.com/client/v4/accounts/${O}/ai`)}else{let O=l.baseUrl??"",re=(await e.question(O?`BASE URL [${O}]: `:l.baseUrlRequired?"BASE URL: ":"BASE URL [optional]: ")).trim()||O;re&&o.set(`${a}_BASE_URL`,S(re))}let E=l.suggestedModel??"",m=(await e.question(E?`MODEL [${E}]: `:"MODEL: ")).trim()||E;if(!m){console.log(""),console.log("\u26A0 MODEL is required."),console.log(""),G(o,t);return}o.set(`${a}_MODEL`,m),f(o),console.log(""),console.log(`\u2713 Fallback ${t} saved`),console.log(` ${M(n)} / ${m}`),console.log("")}async function Go(e,o){let t=o.get("TOOLNET_LLM_FALLBACK_COOLDOWN_MS")||"60000",n=o.get("TOOLNET_LLM_MAX_RETRIES")||"1";console.log(""),console.log("Fallback Policy"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let r=await e.question(`COOLDOWN MS [${t}]: `);if(r.trim()){let s=Number(r.trim());Number.isFinite(s)&&s>=0?o.set("TOOLNET_LLM_FALLBACK_COOLDOWN_MS",String(Math.floor(s))):console.log("\u26A0 Invalid cooldown; keeping previous value.")}let i=await e.question(`MAX RETRIES [${n}]: `);if(i.trim()){let s=Number(i.trim());Number.isFinite(s)&&s>=0&&s<=5?o.set("TOOLNET_LLM_MAX_RETRIES",String(Math.floor(s))):console.log("\u26A0 MAX RETRIES must be between 0 and 5.")}f(o),console.log(""),console.log("\u2713 Fallback policy saved"),console.log("")}async function Ho(e,o){for(;;){console.log(""),console.log("LLM Fallback"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(` Primary : ${o.get("TOOLNET_LLM_PROVIDER")?`${M(o.get("TOOLNET_LLM_PROVIDER"))} / ${o.get("TOOLNET_LLM_MODEL")||"model not configured"}`:"not configured"}`),console.log(` Fallback 1 : ${Ie(o,1)}`),console.log(` Fallback 2 : ${Ie(o,2)}`),console.log(` Cooldown : ${o.get("TOOLNET_LLM_FALLBACK_COOLDOWN_MS")||"60000"} ms`),console.log(` Retries : ${o.get("TOOLNET_LLM_MAX_RETRIES")||"1"}`),console.log(""),console.log(" 1. Configure Fallback 1"),console.log(" 2. Configure Fallback 2"),console.log(" 3. Remove Fallback 1"),console.log(" 4. Remove Fallback 2"),console.log(" 5. Retry / cooldown settings"),console.log(" 0. Back"),console.log("");let t=(await e.question("Choose: ")).trim();if(t==="0")return;if(t==="1"){await Ne(e,o,1);continue}if(t==="2"){await Ne(e,o,2);continue}if(t==="3"){G(o,1),f(o),console.log(""),console.log("\u2713 Fallback 1 removed"),console.log("");continue}if(t==="4"){G(o,2),f(o),console.log(""),console.log("\u2713 Fallback 2 removed"),console.log("");continue}if(t==="5"){await Go(e,o);continue}console.log(""),console.log("\u26A0 Invalid selection")}}async function qo(e,o){for(;;){console.log(""),console.log("AI Model"),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let t=o.get("TOOLNET_LLM_PROVIDER"),n=o.get("TOOLNET_EMBEDDING_PROVIDER");console.log(` LLM : ${t?`${M(t)} / ${o.get("TOOLNET_LLM_MODEL")||"model not configured"}`:"not configured"}`),console.log(` Embedding : ${n?`${ne(n)} / ${o.get("TOOLNET_EMBEDDING_MODEL")||(n==="local"?"local hash":"model not configured")}`:"legacy/default"}`),console.log(""),console.log(" 1. Configure LLM"),console.log(" 2. Configure Embedding"),console.log(" 3. Use LLM provider credentials for Embedding"),console.log(" 4. Configure LLM Fallbacks"),console.log(" 0. Back"),console.log("");let r=(await e.question("Choose: ")).trim();if(r==="0")return;if(r==="1"){await Vo(e,o);continue}if(r==="2"){await Fo(e,o);continue}if(r==="3"){await xo(e,o);continue}if(r==="4"){await Ho(e,o);continue}console.log(""),console.log("\u26A0 Invalid selection")}}async function Vo(e,o){let t=new Map(o);for(;;){let n=await te(e,ye(o));if(n==="back")return;let r=I.find(l=>l.id===n);if(!r)continue;if(await Bo(e,o,r),!Ko(o,r)){console.log(""),console.log("\u26A0 AI configuration is incomplete."),console.log(""),console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let l=(await e.question("Choose [1]: ")).trim()||"1";if(l==="2"){f(o),console.log(""),console.log("\u26A0 AI configuration saved without validation"),console.log(` ${u}`),console.log("");return}if(l==="3")continue;if(l==="4"){o.clear();for(let[a,E]of t)o.set(a,E);console.log(""),console.log("AI changes cancelled."),console.log("");return}continue}if((await Yo(o)).ok){f(o),console.log(`\u2713 ${r.label} configuration saved`),console.log(` ${u}`),console.log("");return}console.log(" 1. Retry"),console.log(" 2. Save anyway"),console.log(" 3. Choose another provider"),console.log(" 4. Cancel"),console.log("");let s=(await e.question("Choose [1]: ")).trim()||"1";if(s==="2"){f(o),console.log(""),console.log("\u26A0 AI configuration saved even though provider test failed"),console.log(` ${u}`),console.log("");return}if(s!=="3"&&s==="4"){o.clear();for(let[l,a]of t)o.set(l,a);console.log(""),console.log("AI changes cancelled."),console.log("");return}}}function jo(){try{let o=z().filter(t=>t.installed);if(o.length===0)return;console.log(""),console.log("Automatic AI memory");for(let t of o){let n=t.agent==="agy"?"Agy / Antigravity":t.agent==="opencode"?"OpenCode":t.agent==="codex"?"Codex":t.agent;console.log(` \u2713 ${n}`)}}catch{}}function g(e,...o){for(let t of o){let n=e.get(t)?.trim();if(n)return n}}function _(e,o,t){t&&!e.get(o)?.trim()&&e.set(o,t)}function Wo(e){let o=!1,t=JSON.stringify([...e.entries()]);if(!e.get("TOOLNET_LLM_PROVIDER")?.trim()){let i;g(e,"GROQ_API_KEY")?i="groq":g(e,"DEEPSEEK_API_KEY")?i="deepseek":g(e,"NVIDIA_API_KEY","NVIDIA_NIM_API_KEY")?i="nvidia":g(e,"OPENROUTER_API_KEY")?i="openrouter":g(e,"ALIBABA_API_KEY","DASHSCOPE_API_KEY")?i="alibaba":g(e,"GEMINI_API_KEY","GOOGLE_API_KEY")?i="gemini":g(e,"CLOUDFLARE_API_TOKEN")&&g(e,"CLOUDFLARE_ACCOUNT_ID")?i="cloudflare":g(e,"HF_TOKEN")?i="huggingface":g(e,"OLLAMA_MODEL","OLLAMA_BASE_URL")?i="ollama":g(e,"OPENAI_API_KEY","MODEL_API_KEY")&&(i="openai-compatible"),i&&e.set("TOOLNET_LLM_PROVIDER",i)}switch(e.get("TOOLNET_LLM_PROVIDER")?.trim()){case"groq":_(e,"TOOLNET_LLM_API_KEY",g(e,"GROQ_API_KEY")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"GROQ_BASE_URL")||"https://api.groq.com/openai/v1"),_(e,"TOOLNET_LLM_MODEL",g(e,"GROQ_MODEL"));break;case"deepseek":_(e,"TOOLNET_LLM_API_KEY",g(e,"DEEPSEEK_API_KEY")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"DEEPSEEK_BASE_URL")||"https://api.deepseek.com"),_(e,"TOOLNET_LLM_MODEL",g(e,"DEEPSEEK_MODEL")||"deepseek-v4-flash");break;case"nvidia":_(e,"TOOLNET_LLM_API_KEY",g(e,"NVIDIA_API_KEY","NVIDIA_NIM_API_KEY")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"NVIDIA_BASE_URL","NVIDIA_NIM_BASE_URL")||"https://integrate.api.nvidia.com/v1"),_(e,"TOOLNET_LLM_MODEL",g(e,"NVIDIA_MODEL","NVIDIA_NIM_MODEL"));break;case"openrouter":_(e,"TOOLNET_LLM_API_KEY",g(e,"OPENROUTER_API_KEY")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"OPENROUTER_BASE_URL")||"https://openrouter.ai/api/v1"),_(e,"TOOLNET_LLM_MODEL",g(e,"OPENROUTER_MODEL"));break;case"alibaba":_(e,"TOOLNET_LLM_API_KEY",g(e,"ALIBABA_API_KEY","DASHSCOPE_API_KEY")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"ALIBABA_BASE_URL","DASHSCOPE_BASE_URL")),_(e,"TOOLNET_LLM_MODEL",g(e,"ALIBABA_MODEL","DASHSCOPE_MODEL"));break;case"gemini":_(e,"TOOLNET_LLM_API_KEY",g(e,"GEMINI_API_KEY","GOOGLE_API_KEY")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"GEMINI_BASE_URL")||"https://generativelanguage.googleapis.com/v1beta"),_(e,"TOOLNET_LLM_MODEL",g(e,"GEMINI_MODEL"));break;case"huggingface":_(e,"TOOLNET_LLM_API_KEY",g(e,"HF_TOKEN")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"HF_INFERENCE_BASE_URL")||"https://router.huggingface.co/v1"),_(e,"TOOLNET_LLM_MODEL",g(e,"HF_LLM_MODEL","HF_MODEL"));break;case"ollama":_(e,"TOOLNET_LLM_API_KEY",g(e,"OLLAMA_API_KEY")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"OLLAMA_BASE_URL")||"http://127.0.0.1:11434/v1"),_(e,"TOOLNET_LLM_MODEL",g(e,"OLLAMA_MODEL"));break;case"cloudflare":_(e,"TOOLNET_LLM_API_KEY",g(e,"CLOUDFLARE_API_TOKEN")),_(e,"TOOLNET_LLM_ACCOUNT_ID",g(e,"CLOUDFLARE_ACCOUNT_ID")),_(e,"TOOLNET_LLM_MODEL",g(e,"CLOUDFLARE_MODEL"));break;case"openai-compatible":_(e,"TOOLNET_LLM_API_KEY",g(e,"OPENAI_API_KEY","MODEL_API_KEY")),_(e,"TOOLNET_LLM_BASE_URL",g(e,"OPENAI_BASE_URL","MODEL_BASE_URL")),_(e,"TOOLNET_LLM_MODEL",g(e,"OPENAI_MODEL","MODEL_NAME"));break}!e.get("TOOLNET_EMBEDDING_PROVIDER")?.trim()&&g(e,"HF_TOKEN")&&(e.set("TOOLNET_EMBEDDING_PROVIDER","huggingface"),_(e,"TOOLNET_EMBEDDING_API_KEY",g(e,"HF_TOKEN")),_(e,"TOOLNET_EMBEDDING_MODEL",g(e,"HF_EMBEDDING_MODEL")||"sentence-transformers/all-MiniLM-L6-v2"));let r=JSON.stringify([...e.entries()]);return o=t!==r,o}function k(e,o="not configured"){return e?.trim()||o}function vo(e){let o=P(N(e)),t=e.get("TOOLNET_LLM_PROVIDER"),n=e.get("TOOLNET_LLM_MODEL"),r=e.get("TOOLNET_EMBEDDING_PROVIDER"),i=e.get("TOOLNET_EMBEDDING_MODEL"),s=e.get("TOOLNET_LLM_FALLBACK_1_PROVIDER"),l=e.get("TOOLNET_LLM_FALLBACK_2_PROVIDER");console.log(""),console.log("TOOLNET MEMORY READY"),console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),console.log(`Storage : ${o}`),console.log(`LLM : ${t?`${M(t)} / ${k(n)}`:"not configured"}`),console.log(`Fallback 1 : ${s?`${M(s)} / ${k(e.get("TOOLNET_LLM_FALLBACK_1_MODEL"))}`:"none"}`),console.log(`Fallback 2 : ${l?`${M(l)} / ${k(e.get("TOOLNET_LLM_FALLBACK_2_MODEL"))}`:"none"}`),console.log(`Embedding : ${r?`${r==="local"?"Local / Hash":ne(r)} / ${k(i,r==="local"?"local hash":"not configured")}`:"legacy/default"}`),console.log(""),console.log(`Config : ${u}`),console.log(`Permissions: ${p.statSync(u).mode.toString(8).slice(-3)}`),console.log(""),console.log("Secrets : hidden"),console.log("Config mode: canonical TOOLNET_*"),console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550")}function Pe(e){Wo(e),e.has("TOOLNET_LLM_FALLBACK_COOLDOWN_MS")||e.set("TOOLNET_LLM_FALLBACK_COOLDOWN_MS","60000"),e.has("TOOLNET_LLM_MAX_RETRIES")||e.set("TOOLNET_LLM_MAX_RETRIES","1"),e.has("MEMORY_STORAGE_PROVIDER")||e.set("MEMORY_STORAGE_PROVIDER",N(e)),e.has("MEMORY_LOCAL_CACHE_MB")||e.set("MEMORY_LOCAL_CACHE_MB","200"),e.has("MEMORY_AUTO_CAPTURE")||e.set("MEMORY_AUTO_CAPTURE","true"),e.has("MEMORY_AUTO_RETRIEVE")||e.set("MEMORY_AUTO_RETRIEVE","true"),e.has("MEMORY_AUTO_SUMMARIZE")||e.set("MEMORY_AUTO_SUMMARIZE","true"),e.has("MEMORY_AUTO_SYNC")||e.set("MEMORY_AUTO_SYNC","true"),e.has("MEMORY_MAX_CANDIDATES")||e.set("MEMORY_MAX_CANDIDATES","50"),e.has("MEMORY_RERANK_TOP")||e.set("MEMORY_RERANK_TOP","10"),e.has("MEMORY_FINAL_CONTEXT")||e.set("MEMORY_FINAL_CONTEXT","5"),e.has("MEMORY_TOKEN_BUDGET")||e.set("MEMORY_TOKEN_BUDGET","2000"),e.has("TOOLNET_SESSION_LEARNING")||e.set("TOOLNET_SESSION_LEARNING","1"),e.has("TOOLNET_WORK_CONTINUITY")||e.set("TOOLNET_WORK_CONTINUITY","1"),e.has("TOOLNET_SEMANTIC_CONTINUITY")||e.set("TOOLNET_SEMANTIC_CONTINUITY","1"),e.has("TOOLNET_SMART_HANDOFF")||e.set("TOOLNET_SMART_HANDOFF","1")}async function Jo(e,o){Pe(e),o||f(e),console.log("TOOLNET MEMORY SETUP"),console.log(""),console.log("Interactive terminal not detected."),console.log(`Config: ${u}`),console.log(`Storage: ${P(N(e))}`),console.log(""),console.log("Run from an interactive terminal to configure providers:"),console.log(" toolnet-memory setup")}async function Xo(){let e=p.existsSync(u),o=e?Lo(p.readFileSync(u,"utf8")):new Map,t=new Map(o);if(Pe(t),!A.isTTY||!D.isTTY){await Jo(t,e);return}let n=Eo.createInterface({input:A,output:D}),r=!1;try{for(;;){Io(),No(t);let i=await So(n);if(i==="storage"){let s=JSON.stringify([...t.entries()]);await Po(n,t),r=r||s!==JSON.stringify([...t.entries()]);continue}if(i==="ai"){let s=JSON.stringify([...t.entries()]);await qo(n,t),r=r||s!==JSON.stringify([...t.entries()]);continue}if(i==="exit"){if(!r){console.log(""),console.log("No changes made.");return}console.log("");let s=(await n.question("Discard unsaved changes? (y/N): ")).trim().toLowerCase();if(s==="y"||s==="yes"){console.log(""),console.log("Changes discarded.");return}continue}f(t),Ce(t)||(console.log(""),console.log("\u26A0 Storage configuration is incomplete.")),jo(),vo(t),console.log(""),console.log("Validate:"),console.log(" toolnet-memory provider:status"),console.log(" toolnet-memory provider:test"),console.log(" toolnet-memory doctor"),console.log("");return}}finally{n.close()}}Xo().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolnet-memory",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "description": "Persistent project memory, work continuity, and code intelligence for AI coding agents.",
5
5
  "type": "module",
6
6
  "license": "MIT",