toolnet-memory 0.3.15 → 0.3.17

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.
Files changed (48) hide show
  1. package/.env.example +74 -0
  2. package/.release-target +1 -1
  3. package/README.md +316 -6
  4. package/bin/toolnet-memory +12 -0
  5. package/bundle/agy-hook.js +66 -66
  6. package/bundle/agy.js +56 -56
  7. package/bundle/api.js +15 -15
  8. package/bundle/audit.js +2 -0
  9. package/bundle/background-refresh.js +7 -7
  10. package/bundle/claude-hook.js +49 -49
  11. package/bundle/code-capabilities.js +2 -0
  12. package/bundle/codex-context.js +29 -29
  13. package/bundle/codex.js +71 -71
  14. package/bundle/context-runtime.js +39 -39
  15. package/bundle/context.js +15 -15
  16. package/bundle/copilot-hook.js +78 -78
  17. package/bundle/cursor-hook.js +78 -78
  18. package/bundle/docker-healthcheck.js +3 -0
  19. package/bundle/doctor.js +4 -4
  20. package/bundle/full-index.js +22 -21
  21. package/bundle/gc.js +5 -3
  22. package/bundle/graph-cli.js +1 -1
  23. package/bundle/graph-index.js +5 -4
  24. package/bundle/graph-ui.js +4 -3
  25. package/bundle/grok-hook.js +56 -56
  26. package/bundle/handoff-refresh.js +10 -10
  27. package/bundle/help-cli.js +4 -4
  28. package/bundle/impact.js +5 -4
  29. package/bundle/incremental.js +5 -5
  30. package/bundle/init.js +36 -35
  31. package/bundle/kiro-hook.js +85 -85
  32. package/bundle/learner.js +8 -6
  33. package/bundle/mcp.js +19 -17
  34. package/bundle/memory-agent.js +6 -6
  35. package/bundle/memory-query.js +7 -7
  36. package/bundle/opencode.js +77 -77
  37. package/bundle/project-manual.js +7 -7
  38. package/bundle/public/index.html +51 -2
  39. package/bundle/recovery-certify.js +9 -9
  40. package/bundle/runtime.js +16 -13
  41. package/bundle/semantic.js +6 -5
  42. package/bundle/service.js +11 -6
  43. package/bundle/snapshot.js +6 -4
  44. package/bundle/status-cli.js +4 -4
  45. package/bundle/toolnet-cli.js +46 -46
  46. package/bundle/work-continuity.js +7 -7
  47. package/package.json +38 -2
  48. package/release-manifest.json +143 -4
@@ -1,4 +1,4 @@
1
- import{existsSync as $e,readFileSync as Le}from"node:fs";import{homedir as Ge}from"node:os";import{join as We}from"node:path";function ze(t){let e=t.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 Ue(){let t=process.env.TOOLNET_GLOBAL_ENV??We(Ge(),".config","toolnet-memory",".env");if(!$e(t))return;let e=Le(t,"utf8");for(let r of e.split(/\r?\n/)){let o=r.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let i=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=ze(o.slice(n+1)))}}Ue();function k(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function x(t,e){if(!t)return e;let r=Number(t);return Number.isFinite(r)?r:e}function z(){return{memory:{autoCapture:k(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:k(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:k(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:k(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:x(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:x(process.env.MEMORY_RERANK_TOP,10),finalContext:x(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:x(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:k(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:x(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Ve}from"node:crypto";import{existsSync as O,mkdirSync as Je,readFileSync as Be,renameSync as Ye,writeFileSync as Ze}from"node:fs";import{basename as qe,dirname as A,join as S,parse as Y,resolve as m}from"node:path";var Z=".toolnet",Qe="project.json";function Xe(t){return Ve("sha256").update(t).digest("hex").slice(0,16)}function M(t){return S(t,Z,Qe)}function et(t){return O(M(t))}function U(t,e){let r=m(t),o=Y(r).root;for(;;){if(et(r))return r;if(r===o||e&&r===m(e))break;let n=A(r);if(n===r)break;r=n}return null}function V(t){let e=m(t),r=Y(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(i=>O(S(e,i))))return e;if(e===r)break;let n=A(e);if(n===e)break;e=n}return m(t)}function J(t){let e;try{e=JSON.parse(Be(t,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${t}: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let r=e;if(typeof r.id!="string"||!r.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof r.name!="string"||!r.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let o=new Date().toISOString();return{version:1,id:r.id,name:r.name,remote:typeof r.remote=="string"&&r.remote.trim()?r.remote:r.name,rootPath:typeof r.rootPath=="string"?r.rootPath:A(A(t)),createdAt:typeof r.createdAt=="string"?r.createdAt:o,updatedAt:typeof r.updatedAt=="string"?r.updatedAt:o,graphVersion:typeof r.graphVersion=="number"?r.graphVersion:0,memoryVersion:typeof r.memoryVersion=="number"?r.memoryVersion:0,metadata:r.metadata&&typeof r.metadata=="object"?r.metadata:void 0}}function B(t,e){let r=S(t,Z);Je(r,{recursive:!0});let o=M(t),n=`${o}.tmp-${process.pid}`;Ze(n,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Ye(n,o)}function F(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var I=class{findExisting(e=process.cwd()){let r=m(e),o=V(r),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>O(S(o,l))),s=U(r,i?o:void 0);if(!s)return null;let c=J(M(s));return F(c,s)}requireExisting(e=process.cwd()){let r=this.findExisting(e);if(!r)throw new Error("PROJECT_NOT_INITIALIZED");return r}detect(e=process.cwd()){let r=m(e),o=V(r),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>O(S(o,d))),s=U(r,i?o:void 0);if(s){let d=M(s),a=J(d);return a.rootPath!==s&&(a.rootPath=s,a.updatedAt=new Date().toISOString(),B(s,a)),F(a,s)}let c=new Date().toISOString(),l=qe(o),u={version:1,id:Xe(o),name:l,remote:l,rootPath:o,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return B(o,u),F(u,o)}};var tt=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_-]{20,}\b/g,confidence:"exact"},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g,confidence:"exact"},{type:"aws_access_key",regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,confidence:"exact"},{type:"github_token",regex:/\b(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{40,255})\b/g,confidence:"exact"},{type:"stripe_secret_key",regex:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,confidence:"exact"},{type:"google_api_key",regex:/\bAIza[A-Za-z0-9_-]{30,}\b/g,confidence:"exact"},{type:"slack_token",regex:/\bxox[baprs]-[A-Za-z0-9-]{16,}\b/g,confidence:"exact"},{type:"npm_token",regex:/\bnpm_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._~+/=-]{16,}\b/gi,confidence:"high"},{type:"jwt",regex:/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,confidence:"exact"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,confidence:"exact"},{type:"password_assignment",regex:/\b(?:password|passwd|pwd)\s*[:=]\s*["']?[^"' \t\r\n]{6,}["']?/gi,confidence:"high"},{type:"secret_assignment",regex:/\b(?:secret|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)\s*[:=]\s*["']?[^"' \t\r\n]{8,}["']?/gi,confidence:"high"},{type:"cookie",regex:/\b(?:cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi,confidence:"high"},{type:"url_credentials",regex:/\bhttps?:\/\/[^:/@\s]+:[^/@\s]{4,}@[^/\s]+/gi,confidence:"high"}],rt=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function q(t){return t.normalize("NFKC").trim().toLowerCase()}function ot(t){if(t.length===0)return 0;let e=new Map;for(let o of t)e.set(o,(e.get(o)??0)+1);let r=0;for(let o of e.values()){let n=o/t.length;r-=n*Math.log2(n)}return r}function nt(t){return/^[a-f0-9]{32}$/iu.test(t)||/^[a-f0-9]{40}$/iu.test(t)||/^[a-f0-9]{64}$/iu.test(t)}function it(t,e,r){let o=t.slice(Math.max(0,e-48),e),n=t.slice(r,Math.min(t.length,r+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${o} ${n}`)}function st(t,e){return t.start<e.end&&e.start<t.end}function Q(t){return t.sort((e,r)=>e.start!==r.start?e.start-r.start:r.end-r.start-(e.end-e.start))}var R=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let r of e.allowValues??[]){let o=q(r);o&&this.allowValues.add(o)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let r=[];for(let i of tt){let s=new RegExp(i.regex.source,i.regex.flags);for(let c of e.matchAll(s))c.index===void 0||!c[0]||this.allowed(c[0])||r.push({type:i.type,value:c[0],start:c.index,end:c.index+c[0].length,confidence:i.confidence})}this.enableEntropyHeuristic&&r.push(...this.entropyMatches(e));let o=Q(r),n=[];for(let i of o)n.some(s=>st(s,i))||n.push(i);return Q(n)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let r=q(e);return rt.has(r)?!0:this.allowValues.has(r)}entropyMatches(e){let r=[],o=/[A-Za-z0-9_+/=-]{32,160}/g;for(let n of e.matchAll(o)){if(n.index===void 0||!n[0])continue;let i=n[0];this.allowed(i)||nt(i)||!/[A-Za-z]/u.test(i)||!/[0-9]/u.test(i)||it(e,n.index,n.index+i.length)&&(ot(i)<3.7||r.push({type:"high_entropy_secret",value:i,start:n.index,end:n.index+i.length,confidence:"heuristic"}))}return r}};var E=class{scanner;constructor(e={}){this.scanner=new R(e)}sanitize(e){let r=this.scanner.scan(e);if(r.length===0)return{text:e,redacted:0,secretTypes:[]};let o=e,n=[...r].sort((s,c)=>c.start-s.start),i=new Set;for(let s of n)i.add(s.type),o=o.slice(0,s.start)+`[REDACTED:${s.type}]`+o.slice(s.end);return{text:o,redacted:r.length,secretTypes:[...i].sort()}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(r=>this.sanitizeValue(r));if(e&&typeof e=="object"){let r={};for(let[o,n]of Object.entries(e)){let i=o.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(i.includes("password")||i.includes("passwd")||i==="pwd"||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")||i.includes("apikey")||i.includes("accesskey")||i.includes("privatekey")||i.includes("clientsecret")||i.includes("credential")){r[o]="[REDACTED]";continue}r[o]=this.sanitizeValue(n)}return r}return e}};var Ur=new E;import{homedir as It}from"node:os";import{join as Rt}from"node:path";import{DeleteObjectCommand as at,GetObjectCommand as ut,HeadObjectCommand as lt,ListObjectsV2Command as dt,PutObjectCommand as pt,S3Client as gt}from"@aws-sdk/client-s3";import{getSignedUrl as ft}from"@aws-sdk/s3-request-presigner";var T=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new gt({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,r,o="application/octet-stream"){let n=typeof r=="string"?Buffer.from(r,"utf8"):r;await this.client.send(new pt({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let r=await ft(this.client,new ut({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(r,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await this.client.send(new lt({Bucket:this.bucket,Key:e})),!0}catch(r){if(typeof r=="object"&&r!==null&&"$metadata"in r&&r.$metadata?.httpStatusCode===404)return!1;throw r}}async delete(e){await this.client.send(new at({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],o;do{let n=await this.client.send(new dt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let i of n.Contents??[])i.Key&&r.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return r}};import{access as X,mkdir as mt,readFile as yt,readdir as ht,rm as kt,stat as ee,writeFile as xt}from"node:fs/promises";import{dirname as St,join as Ct,relative as te,resolve as bt}from"node:path";var C=class{constructor(e){this.root=e}root;name="local";path(e){let r=e.replace(/^\/+/,"");return bt(this.root,r)}async put(e,r){let o=this.path(e);await mt(St(o),{recursive:!0}),await xt(o,r)}async get(e){try{return await yt(this.path(e))}catch(r){if(typeof r=="object"&&r!==null&&"code"in r&&r.code==="ENOENT")return null;throw r}}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await X(this.path(e)),!0}catch{return!1}}async delete(e){await kt(this.path(e),{force:!0})}async list(e=""){let r=this.path(e),o=[];try{await X(r)}catch{return o}let n=async s=>{let c=await ht(s,{withFileTypes:!0});for(let l of c){let u=Ct(s,l.name);if(l.isDirectory()){await n(u);continue}let d=await ee(u);o.push({key:te(this.root,u),size:d.size,updatedAt:d.mtime.toISOString()})}},i=await ee(r);return i.isDirectory()?await n(r):o.push({key:te(this.root,r),size:i.size,updatedAt:i.mtime.toISOString()}),o}};import{DeleteObjectCommand as vt,GetObjectCommand as wt,HeadObjectCommand as Pt,ListObjectsV2Command as jt,PutObjectCommand as Ot,S3Client as At}from"@aws-sdk/client-s3";import{getSignedUrl as Mt}from"@aws-sdk/s3-request-presigner";var b=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new At({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,r,o="application/octet-stream"){let n=typeof r=="string"?Buffer.from(r,"utf8"):r;await this.client.send(new Ot({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let r=await Mt(this.client,new wt({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(r,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`${this.name} download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await this.client.send(new Pt({Bucket:this.bucket,Key:e})),!0}catch(r){if(typeof r=="object"&&r!==null&&"$metadata"in r&&r.$metadata?.httpStatusCode===404)return!1;throw r}}async delete(e){await this.client.send(new vt({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],o;do{let n=await this.client.send(new jt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let i of n.Contents??[])i.Key&&r.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return r}};function H(t,e){return console.warn(e),new C(t)}function re(t){let e=t.localRoot??Rt(It(),".toolnet-memory","storage");if(t.provider==="r2"){let r=t.r2;return r?.accountId&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new b({name:"r2",endpoint:`https://${r.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:r.bucket,forcePathStyle:!0,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):H(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let r=t.s3;return r?.bucket&&r.accessKeyId&&r.secretAccessKey?new b({name:"s3",endpoint:r.endpoint,region:r.region??"us-east-1",bucket:r.bucket,forcePathStyle:r.forcePathStyle??!1,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):H(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let r=t.huggingface;return r?.namespace&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new T({namespace:r.namespace,bucket:r.bucket,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):H(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new C(e)}function Et(t){return new Promise(e=>setTimeout(e,t))}async function oe(t,e={}){let r=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,i;for(let s=1;s<=r;s++)try{return await t()}catch(c){if(i=c,s>=r)break;let l=Math.min(n,o*2**(s-1)),u=Math.floor(Math.random()*Math.max(1,l*.2));await Et(l+u)}throw i}var Tt=new Set(["put","get","getText","delete","list"]);function ne(t,e={}){return new Proxy(t,{get(r,o){let n=Reflect.get(r,o,r);return typeof n!="function"?n:Tt.has(o)?(...i)=>oe(()=>Promise.resolve(n.apply(r,i)),e):n.bind(r)}})}function ie(t){let e=t.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(t){let e=t.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 r=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(o)return`${o[1]}memory/records/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),o)return`${o[1]}memory/vectors/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),o)return`${o[1]}code/graph/${o[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var D=class{constructor(e,r,o,n){this.provider=e;this.name=e.name,this.projectId=r,this.projectName=o,this.folder=ie(n??o),this.sourcePrefix=`projects/${r}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,r=new Date().toISOString(),o=r,n=await this.provider.getText(e);if(n){let s;try{s=JSON.parse(n)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof s.id=="string"&&s.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${s.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof s.createdAt=="string"&&(o=s.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:r};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,r,o){return await this.ensureRegistered(),this.provider.put(this.key(e),r,o)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{existsSync as de,readFileSync as Ht,readdirSync as ae}from"node:fs";import{join as v}from"node:path";var Mn=new Int32Array(new SharedArrayBuffer(4));import{closeSync as Dn,existsSync as Dt,fsyncSync as _n,mkdirSync as Nn,openSync as Fn,readFileSync as _t,renameSync as Hn,writeFileSync as Kn}from"node:fs";import{dirname as Ln,join as Nt}from"node:path";function Ft(t){return Nt(t.rootPath,".toolnet","work","current.json")}function ce(t){let e=Ft(t);if(!Dt(e))return null;try{let r=JSON.parse(_t(e,"utf8"));return r.version!==1||r.projectId!==t.id?null:r}catch{return null}}function pe(t){if(!de(t))return null;try{return JSON.parse(Ht(t,"utf8"))}catch{return null}}function ue(t,e){if(!de(t))return[];let r=[];for(let o of ae(t,{withFileTypes:!0})){if(!o.isDirectory())continue;let n=v(t,o.name);for(let i of ae(n,{withFileTypes:!0})){if(!i.isDirectory())continue;let s=pe(v(n,i.name,"state.json"));s&&s.version===1&&s.projectId===e.id&&r.push(s)}}return r}function Kt(t){let e=v(t.rootPath,".toolnet","runtime","sources"),r=v(t.rootPath,".toolnet","sessions"),o=ue(e,t),n=ue(r,t),i=new Map;for(let s of n)i.set(`${s.agent}:${s.nativeSessionId}`,s);for(let s of o)i.set(`${s.agent}:${s.nativeSessionId}`,s);return Array.from(i.values())}function le(t){return t.filter(e=>!!e).sort().at(-1)}function $t(t){let e=pe(v(t.rootPath,".toolnet","runtime","opencode-status.json"));return!e||e.projectRoot&&e.projectRoot!==t.rootPath?null:e}function ge(t){let e=Kt(t),o=[...e].sort((a,p)=>(a.lastLocalEventAt??a.updatedAt).localeCompare(p.lastLocalEventAt??p.updatedAt)).at(-1),n=Array.from(new Set(e.map(a=>a.agent))).sort(),i=e.reduce((a,p)=>a+Math.max(0,p.lastSequence-p.lastRemoteSequence),0),s=$t(t),c=s?.state==="capture-failed",l=s?.state==="sync-failed",u;c?u="degraded":i>0||l?u="pending":e.length>0?u="healthy":u="unknown";let d=ce(t);return{ok:u!=="degraded",agents:n,sessions:e.length,latestAgent:o?.agent,latestSessionId:o?.nativeSessionId,lastCaptureAt:le(e.map(a=>a.lastLocalEventAt??a.updatedAt)),lastFlushAt:le(e.map(a=>a.lastRemoteAt)),pendingWal:i,currentTask:d?.currentTask?.title,currentFile:d?.activeFiles?.at(-1)??d?.filesTouched.at(-1),syncHealth:u,opencode:s?{state:s.state,reason:s.reason,timestamp:s.timestamp,error:s.error}:void 0}}import{existsSync as Te}from"node:fs";import{homedir as ur}from"node:os";import{join as lr}from"node:path";import{spawnSync as dr}from"node:child_process";import{homedir as Lt}from"node:os";import{join as w}from"node:path";function fe(t={}){return w(t.home??Lt(),".gemini")}function Gt(t={}){return w(fe(t),"antigravity-cli")}function me(t={}){return w(fe(t),"config")}function Wt(t={}){return w(me(t),"mcp_config.json")}function zt(t={}){let e=t.cwd??process.cwd();return w(e,".agents","mcp_config.json")}function ye(t={}){return[Gt(t),Wt(t),me(t),zt(t)]}import{homedir as Ut}from"node:os";import{join as he}from"node:path";function ke(t={}){let e=process.env.OPENCODE_CONFIG_DIR?.trim();if(e)return e;let r=t.xdgConfigHome??process.env.XDG_CONFIG_HOME?.trim();return r?he(r,"opencode"):he(t.home??Ut(),".config","opencode")}import{homedir as Vt}from"node:os";import{join as Jt}from"node:path";function xe(t={}){return Jt(t.home??Vt(),".claude")}import{homedir as Bt}from"node:os";import{join as P}from"node:path";function K(t={}){return t.kiroHome??process.env.KIRO_HOME??P(t.home??Bt(),".kiro")}function Yt(t={}){return P(K(t),"settings")}function $(t={}){return P(Yt(t),"mcp.json")}function Zt(t={}){return P(K(t),"hooks")}function Se(t={}){return P(Zt(t),"toolnet-memory.json")}function Ce(t={}){return[K(t),$(t)]}import{homedir as qt}from"node:os";import{join as be}from"node:path";function ve(t={}){return be(t.home??qt(),".toolnetcli")}function Qt(t={}){return be(ve(t),"config.json")}function we(t={}){let e=ve(t),r=Qt(t);return[e,r]}import{homedir as Xt}from"node:os";import{join as L}from"node:path";function Pe(t={}){if(t.kiloHome)return t.kiloHome;if(process.env.KILO_HOME)return process.env.KILO_HOME;let e=t.xdgConfigHome??process.env.XDG_CONFIG_HOME;return e?L(e,"kilo"):L(t.home??Xt(),".config","kilo")}function er(t={}){return L(Pe(t),"kilo.jsonc")}function je(t={}){let e=Pe(t),r=er(t);return[e,r]}import{homedir as tr}from"node:os";import{join as Oe,resolve as fi}from"node:path";function Ae(t={}){return t.cursorHome??Oe(t.home??tr(),".cursor")}function rr(t={}){return t.cursorConfigDir??process.env.CURSOR_CONFIG_DIR??(t.xdgConfigHome??process.env.XDG_CONFIG_HOME?Oe(t.xdgConfigHome??process.env.XDG_CONFIG_HOME,"cursor"):void 0)??Ae(t)}function Me(t={}){return Array.from(new Set([Ae(t),rr(t)]))}import{homedir as or}from"node:os";import{join as nr,resolve as ki}from"node:path";function ir(t={}){return t.copilotHome??process.env.COPILOT_HOME??nr(t.home??or(),".copilot")}function Ie(t={}){return[ir(t)]}import{homedir as sr}from"node:os";import{join as cr,resolve as bi}from"node:path";function ar(t={}){return t.grokHome??process.env.GROK_HOME??cr(t.home??sr(),".grok")}function Re(t={}){return[ar(t)]}function pr(t){return dr("sh",["-lc",`command -v ${JSON.stringify(t)} >/dev/null 2>&1`],{stdio:"ignore"}).status===0}function g(t){let e=t.commandExists(t.command),r=t.configPaths.filter(i=>Te(i)),o=r.length>0,n=[];e&&n.push(`command:${t.command}`);for(let i of r)n.push(`config:${i}`);return{agent:t.agent,detected:e||o,commandDetected:e,configDetected:o,evidence:n}}function Ee(t){let e=t.commands.filter(s=>t.commandExists(s)),r=t.configPaths.filter(s=>Te(s)),o=e.length>0,n=r.length>0,i=[...e.map(s=>`command:${s}`),...r.map(s=>`config:${s}`)];return{agent:t.agent,detected:o||n,commandDetected:o,configDetected:n,evidence:i}}function De(t={}){let e=t.home??ur(),r=t.commandExists??pr,o=t.codexHome??process.env.CODEX_HOME??lr(e,".codex");return[g({agent:"agy",command:"agy",commandExists:r,configPaths:ye({home:e})}),g({agent:"opencode",command:"opencode",commandExists:r,configPaths:[ke({home:e,xdgConfigHome:t.xdgConfigHome})]}),g({agent:"claude",command:"claude",commandExists:r,configPaths:[xe({home:e})]}),g({agent:"kiro",command:"kiro-cli",commandExists:r,configPaths:Ce({home:e,kiroHome:t.kiroHome})}),Ee({agent:"cursor",commands:["agent","cursor-agent"],commandExists:r,configPaths:Me({home:e,cursorHome:t.cursorHome,cursorConfigDir:t.cursorConfigDir,xdgConfigHome:t.xdgConfigHome})}),g({agent:"copilot",command:"copilot",commandExists:r,configPaths:Ie({home:e,copilotHome:t.copilotHome})}),g({agent:"grok",command:"grok",commandExists:r,configPaths:Re({home:e,grokHome:t.grokHome})}),g({agent:"toolnet-cli",command:"toolnet",commandExists:r,configPaths:we({home:e})}),Ee({agent:"kilo",commands:["kilo","kilo-code"],commandExists:r,configPaths:je({home:e,kiloHome:t.kiloHome})}),g({agent:"codex",command:"codex",commandExists:r,configPaths:[o]})]}import{existsSync as G,readFileSync as gr}from"node:fs";var fr="ToolNet Memory - ",mr=["SessionStart","UserPromptSubmit","PreToolUse","PostToolUse","Stop"];function y(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function _e(t){if(!G(t))return{};let e;try{e=JSON.parse(gr(t,"utf8"))}catch(r){return{error:r instanceof Error?r.message:String(r)}}return y(e)?{value:e}:{error:"root must be a JSON object"}}function yr(t){if(!t||!y(t.mcpServers))return!1;let e=t.mcpServers["toolnet-memory"];return y(e)?typeof e.command=="string"&&e.command.trim().length>0&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp"&&e.disabled!==!0:!1}function hr(t){if(!(!y(t)||!y(t.action)))return typeof t.action.command=="string"?t.action.command:void 0}function kr(t){if(!t||t.version!=="v1"||!Array.isArray(t.hooks))return[];let e=new Set;for(let r of t.hooks){if(!y(r)||typeof r.name!="string"||!r.name.startsWith(fr))continue;let o=hr(r);!o||!o.includes("session:kiro-hook")||r.enabled!==!1&&typeof r.trigger=="string"&&e.add(r.trigger)}return[...e]}function Ne(t={}){let e=t.configFile??$(),r=t.hooksFile??Se(),o=_e(e),n=_e(r),i=!o.error&&yr(o.value),s=n.error?[]:kr(n.value),c=mr.every(p=>s.includes(p)),l=[];o.error&&l.push(`MCP config: ${o.error}`),n.error&&l.push(`Hooks config: ${n.error}`);let u=i&&c,d=G(e)||G(r),a=l.length>0?"invalid":u?"ready":d?"partial":"not-installed";return{installed:u,state:a,mcp:{configured:i,configFile:e,error:o.error},hooks:{configured:c,hooksFile:r,triggers:s,error:n.error},errors:l}}var xr={spinner:["\xB7","\u2722","\u2733","\u2736","\u273B","\u273D"],barFilled:"\u2588",barEmpty:"\u2591",phaseDone:"\u25C6",phaseActive:"\u25C7",rail:"\u2502",branch:"\u251C",corner:"\u2514",dash:"\u2014"},Sr={spinner:[".","*","+","x","*","+"],barFilled:"#",barEmpty:"-",phaseDone:"[OK]",phaseActive:"[>>]",rail:"|",branch:"|",corner:"\\",dash:"-"};function Cr(){if(process.env.TOOLNET_ASCII==="1")return!1;if(process.env.TOOLNET_UNICODE==="1")return!0;if(process.platform==="win32"){let t=process.env.TERM_PROGRAM,e=process.env.WT_SESSION,r=process.env.VSCODE_PID,o=process.env.ConEmuPID;return!!(e||r||o||t==="vscode")}return process.env.TERM!=="linux"}var W;function Fe(){return W||(W=Cr()?xr:Sr),W}var h={reset:"\x1B[0m",green:"\x1B[32m",cyan:"\x1B[36m",red:"\x1B[31m",yellow:"\x1B[33m",amber:"\x1B[38;5;214m",white:"\x1B[97m",dim:"\x1B[2m",bold:"\x1B[1m"};function br(t){return t.noColor||process.env.NO_COLOR?!1:t.tty??process.stdout.isTTY??!1}function j(t,e,r){return br(r)?`${e}${t}${h.reset}`:t}function _(t,e){return j(t,h.dim,e)}function vr(t,e){return j(t,h.bold,e)}function wr(t,e){return j(t,h.cyan,e)}function Pr(t,e){return j(t,h.red,e)}function jr(t,e){return j(t,h.white,e)}function He(t,e,r){let o=Fe(),n=e?` ${_(`v${e}`,r)}`:"";return`${wr(o.phaseDone,r)} ${t}${n}`}function N(t,e){return vr(t,e)}function f(t,e,r,o){let n=" ".repeat(Math.max(0,r-t.length));return` ${_(t,o)}${n} ${jr(e,o)}`}function Ke(t){return Pr("\u2717",t)}function Or(t){return{tty:t.tty,noColor:t.noColor}}async function Ar(t){let e=Or(t);console.log(""),console.log(He("ToolNet Status",void 0,e)),console.log("");try{let r=new I().detect(),o=z();console.log(N("PROJECT",e)),console.log(f("Name",r.name,8,e));let n=ne(re({provider:o.storage.provider,r2:o.storage.r2,s3:o.storage.s3,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),{attempts:3}),i=new D(n,r.id,r.name,r.remote??r.name),s="unknown",c="unknown";try{s=await i.exists(`${r.id}/memory.json`)?"ready":"not initialized"}catch{s="error"}try{c=await i.exists(`${r.id}/code-graph.json`)?"ready":"not built"}catch{c="error"}console.log(f("Memory",s,8,e)),console.log(f("Index",c,8,e)),console.log("");let l=De(),u=l.filter(a=>a.detected).map(a=>a.agent);if(u.length>0){if(console.log(N("INTEGRATIONS",e)),console.log(f("Detected",u.join(", "),8,e)),l.find(p=>p.agent==="kiro")?.detected){let p=Ne();console.log(f("Kiro",p.installed?"ready":p.state,8,e))}console.log("")}let d=ge(r);if(d.agents.length>0){console.log(N("SERVICE",e));let a=d.syncHealth==="healthy"?"running":d.syncHealth==="degraded"?"degraded":"stopped";console.log(f("Daemon",a,8,e)),console.log("")}}catch(r){console.log(Ke(e)+" Failed to get status"),console.log(""),console.log(_(` ${r instanceof Error?r.message:String(r)}`,e)),console.log(""),process.exitCode=1}}async function Mr(){let t=process.argv.slice(2),e={tty:process.stdout.isTTY,noColor:process.env.NO_COLOR!==void 0||t.includes("--no-color")};await Ar(e)}Mr().catch(t=>{console.error(""),console.error(t instanceof Error?t.message:String(t)),console.error(""),process.exitCode=1});
1
+ import{existsSync as yt,readFileSync as ht}from"node:fs";import{homedir as xt}from"node:os";import{join as kt}from"node:path";function St(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 Ct(){let r=process.env.TOOLNET_GLOBAL_ENV??kt(xt(),".config","toolnet-memory",".env");if(!yt(r))return;let e=ht(r,"utf8");for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let o=n.indexOf("=");if(o<=0)continue;let i=n.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=St(n.slice(o+1)))}}Ct();function b(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function w(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function se(){return{memory:{autoCapture:b(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:b(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:b(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:b(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:w(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:w(process.env.MEMORY_RERANK_TOP,10),finalContext:w(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:w(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:b(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:w(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Rt}from"node:crypto";import{existsSync as K,mkdirSync as At,readFileSync as jt,renameSync as It,writeFileSync as Mt}from"node:fs";import{basename as Tt,dirname as F,join as P,parse as me,resolve as y}from"node:path";import{createHash as ue}from"node:crypto";import{spawnSync as bt}from"node:child_process";var E="git-remote-v1",wt=new Set(["github.com","gitlab.com","bitbucket.org"]);function de(r,e){let t=e.replaceAll("\\","/").replace(/^\/+/u,"").replace(/\/+$/u,"").replace(/\.git$/iu,"").replace(/\/+/gu,"/");return!t||t==="."||t===".."||t.split("/").some(n=>!n||n==="."||n==="..")?null:(wt.has(r)&&(t=t.toLowerCase()),t)}function Et(r){let e;try{e=new URL(r)}catch{return null}if(!["https:","http:","ssh:","git:"].includes(e.protocol))return null;let t=e.hostname.trim().toLowerCase();if(!t)return null;let n=e.protocol==="https:"&&e.port==="443"||e.protocol==="http:"&&e.port==="80"||e.protocol==="ssh:"&&e.port==="22",o=e.port&&!n?`${t}:${e.port}`:t,i=de(t,e.pathname);return i?`${o}/${i}`:null}function Pt(r){let e=r.match(/^(?:[^@\s/:]+@)?([^:/\s]+):(.+)$/u);if(!e)return null;let t=e[1]?.trim().toLowerCase();if(!t||t.length===1)return null;let n=de(t,e[2]??"");return n?`${t}/${n}`:null}function ce(r){let e=r.trim();return e?e.includes("://")?Et(e):Pt(e):null}function vt(r){return ue("sha256").update(`${E}:${r}`).digest("hex")}function le(r){return ue("sha256").update(`toolnet-project:${E}:${r}`).digest("hex").slice(0,16)}function Ot(r){return r.split("/").filter(Boolean).at(-1)?.trim()||null}function W(r,e){let t=bt("git",["-C",r,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function ae(r,e){let t=Ot(r);return t?{scheme:E,canonicalRemote:r,fingerprint:vt(r),repositoryName:t,source:e}:null}function pe(r){let e=W(r,["remote","get-url","origin"]);if(e){let o=ce(e);if(o)return ae(o,"origin")}let t=W(r,["remote"]);if(!t)return null;let n=new Set;for(let o of t.split(/\r?\n/u).map(i=>i.trim()).filter(Boolean)){let i=W(r,["remote","get-url",o]);if(!i)continue;let s=ce(i);s&&n.add(s)}return n.size!==1?null:ae([...n][0],"unique-remote")}var ge=".toolnet",_t="project.json";function Nt(r){return Rt("sha256").update(r).digest("hex").slice(0,16)}function k(r){return P(r,ge,_t)}function ye(r){return K(k(r))}function fe(r,e){let t=y(r),n=me(t).root;for(;;){if(ye(t))return t;if(t===n||e&&t===y(e))break;let o=F(t);if(o===t)break;t=o}return null}function Y(r){let e=y(r),t=me(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>K(P(e,i))))return e;if(e===t)break;let o=F(e);if(o===e)break;e=o}return y(r)}function N(r){let e;try{e=JSON.parse(jt(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 n=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:F(F(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:n,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:n,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 D(r,e){let t=P(r,ge);At(t,{recursive:!0});let n=k(r),o=`${n}.tmp-${process.pid}`;Mt(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),It(o,n)}function g(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}}function B(r){return{version:1,scheme:E,canonicalRemote:r.canonicalRemote,fingerprint:r.fingerprint,repositoryName:r.repositoryName}}function Dt(r){let e=r.metadata?.toolnetIdentity;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return typeof t.fingerprint=="string"?t.fingerprint:null}var L=class{adopt(e,t){let n=Y(y(e));if(!t.id.trim())throw new Error("PROJECT_ADOPTION_INVALID_ID");if(!t.name.trim())throw new Error("PROJECT_ADOPTION_INVALID_NAME");if(!t.remote.trim())throw new Error("PROJECT_ADOPTION_INVALID_REMOTE");if(ye(n)){let c=N(k(n));if(c.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${c.id}`,`requested=${t.id}`].join(" "));return g(c,n)}let o=new Date().toISOString(),i={...t.metadata};t.gitIdentity&&(i.toolnetIdentity=B(t.gitIdentity));let s={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:n,createdAt:t.createdAt??o,updatedAt:o,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(i).length?i:void 0};return D(n,s),g(s,n)}recordGitIdentity(e,t,n={}){let o=this.requireExisting(e),i=k(o.rootPath),s=N(i),c=Dt(s);if(c&&c!==t.fingerprint&&!n.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${c}`,`current=${t.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let u=s.metadata?.toolnetIdentity;return u&&typeof u=="object"&&!Array.isArray(u)&&u.fingerprint===t.fingerprint||(s.metadata={...s.metadata,toolnetIdentity:B(t)},s.updatedAt=new Date().toISOString(),D(o.rootPath,s)),g(s,o.rootPath)}findExisting(e=process.cwd()){let t=y(e),n=Y(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(u=>K(P(n,u))),s=fe(t,i?n:void 0);if(!s)return null;let c=N(k(s));return g(c,s)}requireExisting(e=process.cwd()){let t=this.findExisting(e);if(!t)throw new Error("PROJECT_NOT_INITIALIZED");return t}detect(e=process.cwd()){let t=y(e),n=Y(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>K(P(n,d))),s=fe(t,i?n:void 0);if(s){let d=k(s),p=N(d);return p.rootPath!==s&&(p.rootPath=s,p.updatedAt=new Date().toISOString(),D(s,p)),g(p,s)}let c=new Date().toISOString(),u=Tt(n),a=pe(n),f={version:1,id:a?le(a.canonicalRemote):Nt(n),name:u,remote:a?.repositoryName??u,rootPath:n,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0,metadata:a?{toolnetIdentity:B(a)}:void 0};return D(n,f),g(f,n)}};var Kt=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_-]{20,}\b/g,confidence:"exact"},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g,confidence:"exact"},{type:"aws_access_key",regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,confidence:"exact"},{type:"github_token",regex:/\b(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{40,255})\b/g,confidence:"exact"},{type:"stripe_secret_key",regex:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,confidence:"exact"},{type:"google_api_key",regex:/\bAIza[A-Za-z0-9_-]{30,}\b/g,confidence:"exact"},{type:"slack_token",regex:/\bxox[baprs]-[A-Za-z0-9-]{16,}\b/g,confidence:"exact"},{type:"npm_token",regex:/\bnpm_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._~+/=-]{16,}\b/gi,confidence:"high"},{type:"jwt",regex:/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,confidence:"exact"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,confidence:"exact"},{type:"password_assignment",regex:/\b(?:password|passwd|pwd)\s*[:=]\s*["']?[^"' \t\r\n]{6,}["']?/gi,confidence:"high"},{type:"secret_assignment",regex:/\b(?:secret|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)\s*[:=]\s*["']?[^"' \t\r\n]{8,}["']?/gi,confidence:"high"},{type:"cookie",regex:/\b(?:cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi,confidence:"high"},{type:"url_credentials",regex:/\bhttps?:\/\/[^:/@\s]+:[^/@\s]{4,}@[^/\s]+/gi,confidence:"high"}],Ft=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function he(r){return r.normalize("NFKC").trim().toLowerCase()}function Lt(r){if(r.length===0)return 0;let e=new Map;for(let n of r)e.set(n,(e.get(n)??0)+1);let t=0;for(let n of e.values()){let o=n/r.length;t-=o*Math.log2(o)}return t}function $t(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function Ht(r,e,t){let n=r.slice(Math.max(0,e-48),e),o=r.slice(t,Math.min(r.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${n} ${o}`)}function Gt(r,e){return r.start<e.end&&e.start<r.end}function xe(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var $=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=he(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let i of Kt){let s=new RegExp(i.regex.source,i.regex.flags);for(let c of e.matchAll(s))c.index===void 0||!c[0]||this.allowed(c[0])||t.push({type:i.type,value:c[0],start:c.index,end:c.index+c[0].length,confidence:i.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let n=xe(t),o=[];for(let i of n)o.some(s=>Gt(s,i))||o.push(i);return xe(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=he(e);return Ft.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],n=/[A-Za-z0-9_+/=-]{32,160}/g;for(let o of e.matchAll(n)){if(o.index===void 0||!o[0])continue;let i=o[0];this.allowed(i)||$t(i)||!/[A-Za-z]/u.test(i)||!/[0-9]/u.test(i)||Ht(e,o.index,o.index+i.length)&&(Lt(i)<3.7||t.push({type:"high_entropy_secret",value:i,start:o.index,end:o.index+i.length,confidence:"heuristic"}))}return t}};var H=class{scanner;constructor(e={}){this.scanner=new $(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let n=e,o=[...t].sort((s,c)=>c.start-s.start),i=new Set;for(let s of o)i.add(s.type),n=n.slice(0,s.start)+`[REDACTED:${s.type}]`+n.slice(s.end);return{text:n,redacted:t.length,secretTypes:[...i].sort()}}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[n,o]of Object.entries(e)){let i=n.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(i.includes("password")||i.includes("passwd")||i==="pwd"||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")||i.includes("apikey")||i.includes("accesskey")||i.includes("privatekey")||i.includes("clientsecret")||i.includes("credential")){t[n]="[REDACTED]";continue}t[n]=this.sanitizeValue(o)}return t}return e}};var $n=new H;import{homedir as Sr}from"node:os";import{join as Cr}from"node:path";import{DeleteObjectCommand as Vt,GetObjectCommand as zt,HeadObjectCommand as Wt,ListObjectsV2Command as Yt,PutObjectCommand as Bt,S3Client as Jt}from"@aws-sdk/client-s3";import{getSignedUrl as qt}from"@aws-sdk/s3-request-presigner";var G=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Jt({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,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Bt({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await qt(this.client,new zt({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.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 Wt({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 Vt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new Yt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}};import{access as ke,mkdir as Zt,readFile as Qt,readdir as Xt,rm as er,stat as Se,writeFile as tr}from"node:fs/promises";import{dirname as rr,join as nr,relative as Ce,resolve as or}from"node:path";var v=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return or(this.root,t)}async put(e,t){let n=this.path(e);await Zt(rr(n),{recursive:!0}),await tr(n,t)}async get(e){try{return await Qt(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 ke(this.path(e)),!0}catch{return!1}}async delete(e){await er(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await ke(t)}catch{return n}let o=async s=>{let c=await Xt(s,{withFileTypes:!0});for(let u of c){let a=nr(s,u.name);if(u.isDirectory()){await o(a);continue}let f=await Se(a);n.push({key:Ce(this.root,a),size:f.size,updatedAt:f.mtime.toISOString()})}},i=await Se(t);return i.isDirectory()?await o(t):n.push({key:Ce(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),n}};import{DeleteObjectCommand as ir,GetObjectCommand as sr,HeadObjectCommand as cr,ListObjectsV2Command as ar,PutObjectCommand as ur,S3Client as dr}from"@aws-sdk/client-s3";import{getSignedUrl as lr}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 dr({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,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new ur({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await lr(this.client,new sr({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`${this.name} download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.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 cr({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 ir({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new ar({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}};import{createCipheriv as pr,createDecipheriv as fr,createHash as mr,randomBytes as gr,timingSafeEqual as yr}from"node:crypto";import{readFileSync as hr}from"node:fs";var h=Buffer.from("TNMEME01","ascii"),we=1,R=8,A=12,J=16,Ee=h.length+1+R+A+J,xr="toolnet-memory:remote-encryption:v1:",Pe="aes-256-gcm",q=32,l=class extends Error{constructor(t,n){super(n);this.code=t;this.name="RemoteEncryptionError"}code};function kr(r){return r?["1","true","yes","on","enabled"].includes(r.trim().toLowerCase()):!1}function Z(r=process.env){return kr(r.TOOLNET_REMOTE_ENCRYPTION)}function be(r){let e=r.trim();if(!e)throw new l("REMOTE_ENCRYPTION_KEY_EMPTY","Remote encryption key is empty.");let t;if(e.startsWith("hex:")){let n=e.slice(4);if(!/^[0-9a-f]{64}$/iu.test(n))throw new l("REMOTE_ENCRYPTION_KEY_INVALID","hex: remote encryption key must contain exactly 64 hexadecimal characters.");t=Buffer.from(n,"hex")}else if(/^[0-9a-f]{64}$/iu.test(e))t=Buffer.from(e,"hex");else{let n=e.startsWith("base64:")?e.slice(7):e;if(!/^[A-Za-z0-9+/_-]+={0,2}$/u.test(n))throw new l("REMOTE_ENCRYPTION_KEY_INVALID","Remote encryption key must be 32 raw bytes encoded as hexadecimal or base64.");t=Buffer.from(n,n.includes("-")||n.includes("_")?"base64url":"base64")}if(t.length!==q)throw new l("REMOTE_ENCRYPTION_KEY_INVALID_LENGTH",`Remote encryption key must decode to exactly ${q} bytes.`);return t}function ve(r=process.env){let e=r.TOOLNET_REMOTE_ENCRYPTION_KEY?.trim(),t=r.TOOLNET_REMOTE_ENCRYPTION_KEY_FILE?.trim();if(e&&t)throw new l("REMOTE_ENCRYPTION_KEY_AMBIGUOUS","Configure either TOOLNET_REMOTE_ENCRYPTION_KEY or TOOLNET_REMOTE_ENCRYPTION_KEY_FILE, not both.");if(e)return be(e);if(t){let n;try{n=hr(t,"utf8")}catch(o){throw new l("REMOTE_ENCRYPTION_KEY_FILE_READ_FAILED",[`Unable to read remote encryption key file: ${t}.`,o instanceof Error?o.message:String(o)].join(" "))}return be(n)}}function Oe(r){return mr("sha256").update(r).digest().subarray(0,R)}function Re(r){return Buffer.from(`${xr}${r}`,"utf8")}function Q(r){return r.byteLength<h.length?!1:Buffer.from(r).subarray(0,h.length).equals(h)}function Ae(r,e,t){if(t.byteLength!==q)throw new l("REMOTE_ENCRYPTION_KEY_INVALID_LENGTH","AES-256-GCM requires a 32-byte key.");let n=typeof e=="string"?Buffer.from(e,"utf8"):Buffer.from(e),o=gr(A),i=pr(Pe,t,o);i.setAAD(Re(r));let s=Buffer.concat([i.update(n),i.final()]),c=i.getAuthTag(),u=Buffer.alloc(Ee),a=0;return h.copy(u,a),a+=h.length,u.writeUInt8(we,a),a+=1,Oe(t).copy(u,a),a+=R,o.copy(u,a),a+=A,c.copy(u,a),Buffer.concat([u,s])}function je(r,e,t){let n=Buffer.from(e);if(!Q(n))throw new l("REMOTE_ENCRYPTION_ENVELOPE_REQUIRED","Payload is not a ToolNet encrypted remote object.");if(n.length<Ee)throw new l("REMOTE_ENCRYPTION_ENVELOPE_TRUNCATED","Encrypted remote payload is truncated.");let o=h.length,i=n.readUInt8(o);if(o+=1,i!==we)throw new l("REMOTE_ENCRYPTION_VERSION_UNSUPPORTED",`Unsupported remote encryption envelope version: ${i}.`);let s=n.subarray(o,o+R);o+=R;let c=Oe(t);if(!yr(s,c))throw new l("REMOTE_ENCRYPTION_KEY_MISMATCH","Configured remote encryption key does not match this encrypted object.");let u=n.subarray(o,o+A);o+=A;let a=n.subarray(o,o+J);o+=J;let f=n.subarray(o),d=fr(Pe,t,u);d.setAAD(Re(r)),d.setAuthTag(a);try{return Buffer.concat([d.update(f),d.final()])}catch{throw new l("REMOTE_ENCRYPTION_AUTH_FAILED","Encrypted remote object failed AES-GCM authentication.")}}var X=class{constructor(e,t){this.inner=e;this.options=t;if(this.name=e.name,t.enabled&&!t.key)throw new l("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote client-side encryption is enabled but no encryption key is configured.")}inner;options;name;async put(e,t,n){if(!this.options.enabled){await this.inner.put(e,t,n);return}let o=this.options.key;if(!o)throw new l("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote encryption key is unavailable.");let i=Ae(e,t,o);await this.inner.put(e,i,"application/octet-stream")}async get(e){let t=await this.inner.get(e);if(!t)return null;if(!Q(t))return t;if(!this.options.enabled)throw new l("REMOTE_ENCRYPTION_REQUIRED",["Remote object is client-side encrypted.","Enable TOOLNET_REMOTE_ENCRYPTION and configure the matching key."].join(" "));let n=this.options.key;if(!n)throw new l("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote object is encrypted but no decryption key is configured.");return je(e,t,n)}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){return this.inner.exists(e)}async delete(e){await this.inner.delete(e)}async list(e=""){return this.inner.list(e)}};function Ie(r,e=process.env){if(r.name==="local")return Z(e)&&console.warn("[storage] Remote encryption requested but active storage provider is local; local data remains unchanged."),r;let t=Z(e),n=t?ve(e):void 0;return new X(r,{enabled:t,key:n})}function j(r){return Ie(r)}function ee(r,e){return console.warn(e),j(new v(r))}function Me(r){let e=r.localRoot??Cr(Sr(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?j(new O({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):ee(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?j(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})):ee(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?j(new G({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):ee(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return j(new v(e))}function br(r){return new Promise(e=>setTimeout(e,r))}async function Te(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,o=e.maxDelayMs??2e3,i;for(let s=1;s<=t;s++)try{return await r()}catch(c){if(i=c,s>=t)break;let u=Math.min(o,n*2**(s-1)),a=Math.floor(Math.random()*Math.max(1,u*.2));await br(u+a)}throw i}var wr=new Set(["put","get","getText","delete","list"]);function _e(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:wr.has(n)?(...i)=>Te(()=>Promise.resolve(o.apply(t,i)),e):o.bind(t)}})}function Ne(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 De(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 n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[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 U=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=Ne(o??n),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(),n=t,o=await this.provider.getText(e);if(o){let s;try{s=JSON.parse(o)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof s.id=="string"&&s.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${s.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof s.createdAt=="string"&&(n=s.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,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=De(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,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}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{existsSync as He,readFileSync as Rr,readdirSync as Fe}from"node:fs";import{join as I}from"node:path";var _i=new Int32Array(new SharedArrayBuffer(4));import{closeSync as Li,existsSync as Er,fsyncSync as $i,mkdirSync as Hi,openSync as Gi,readFileSync as Pr,renameSync as Ui,writeFileSync as Vi}from"node:fs";import{dirname as Wi,join as vr}from"node:path";function Or(r){return vr(r.rootPath,".toolnet","work","current.json")}function Ke(r){let e=Or(r);if(!Er(e))return null;try{let t=JSON.parse(Pr(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function Ge(r){if(!He(r))return null;try{return JSON.parse(Rr(r,"utf8"))}catch{return null}}function Le(r,e){if(!He(r))return[];let t=[];for(let n of Fe(r,{withFileTypes:!0})){if(!n.isDirectory())continue;let o=I(r,n.name);for(let i of Fe(o,{withFileTypes:!0})){if(!i.isDirectory())continue;let s=Ge(I(o,i.name,"state.json"));s&&s.version===1&&s.projectId===e.id&&t.push(s)}}return t}function Ar(r){let e=I(r.rootPath,".toolnet","runtime","sources"),t=I(r.rootPath,".toolnet","sessions"),n=Le(e,r),o=Le(t,r),i=new Map;for(let s of o)i.set(`${s.agent}:${s.nativeSessionId}`,s);for(let s of n)i.set(`${s.agent}:${s.nativeSessionId}`,s);return Array.from(i.values())}function $e(r){return r.filter(e=>!!e).sort().at(-1)}function jr(r){let e=Ge(I(r.rootPath,".toolnet","runtime","opencode-status.json"));return!e||e.projectRoot&&e.projectRoot!==r.rootPath?null:e}function Ue(r){let e=Ar(r),n=[...e].sort((d,p)=>(d.lastLocalEventAt??d.updatedAt).localeCompare(p.lastLocalEventAt??p.updatedAt)).at(-1),o=Array.from(new Set(e.map(d=>d.agent))).sort(),i=e.reduce((d,p)=>d+Math.max(0,p.lastSequence-p.lastRemoteSequence),0),s=jr(r),c=s?.state==="capture-failed",u=s?.state==="sync-failed",a;c?a="degraded":i>0||u?a="pending":e.length>0?a="healthy":a="unknown";let f=Ke(r);return{ok:a!=="degraded",agents:o,sessions:e.length,latestAgent:n?.agent,latestSessionId:n?.nativeSessionId,lastCaptureAt:$e(e.map(d=>d.lastLocalEventAt??d.updatedAt)),lastFlushAt:$e(e.map(d=>d.lastRemoteAt)),pendingWal:i,currentTask:f?.currentTask?.title,currentFile:f?.activeFiles?.at(-1)??f?.filesTouched.at(-1),syncHealth:a,opencode:s?{state:s.state,reason:s.reason,timestamp:s.timestamp,error:s.error}:void 0}}import{existsSync as ut}from"node:fs";import{homedir as Xr}from"node:os";import{join as en}from"node:path";import{spawnSync as tn}from"node:child_process";import{homedir as Ir}from"node:os";import{join as M}from"node:path";function Ve(r={}){return M(r.home??Ir(),".gemini")}function Mr(r={}){return M(Ve(r),"antigravity-cli")}function ze(r={}){return M(Ve(r),"config")}function Tr(r={}){return M(ze(r),"mcp_config.json")}function _r(r={}){let e=r.cwd??process.cwd();return M(e,".agents","mcp_config.json")}function We(r={}){return[Mr(r),Tr(r),ze(r),_r(r)]}import{homedir as Nr}from"node:os";import{join as Ye}from"node:path";function Be(r={}){let e=process.env.OPENCODE_CONFIG_DIR?.trim();if(e)return e;let t=r.xdgConfigHome??process.env.XDG_CONFIG_HOME?.trim();return t?Ye(t,"opencode"):Ye(r.home??Nr(),".config","opencode")}import{homedir as Dr}from"node:os";import{join as Kr}from"node:path";function Je(r={}){return Kr(r.home??Dr(),".claude")}import{homedir as Fr}from"node:os";import{join as T}from"node:path";function te(r={}){return r.kiroHome??process.env.KIRO_HOME??T(r.home??Fr(),".kiro")}function Lr(r={}){return T(te(r),"settings")}function re(r={}){return T(Lr(r),"mcp.json")}function $r(r={}){return T(te(r),"hooks")}function qe(r={}){return T($r(r),"toolnet-memory.json")}function Ze(r={}){return[te(r),re(r)]}import{homedir as Hr}from"node:os";import{join as Qe}from"node:path";function Xe(r={}){return Qe(r.home??Hr(),".toolnetcli")}function Gr(r={}){return Qe(Xe(r),"config.json")}function et(r={}){let e=Xe(r),t=Gr(r);return[e,t]}import{homedir as Ur}from"node:os";import{join as ne}from"node:path";function tt(r={}){if(r.kiloHome)return r.kiloHome;if(process.env.KILO_HOME)return process.env.KILO_HOME;let e=r.xdgConfigHome??process.env.XDG_CONFIG_HOME;return e?ne(e,"kilo"):ne(r.home??Ur(),".config","kilo")}function Vr(r={}){return ne(tt(r),"kilo.jsonc")}function rt(r={}){let e=tt(r),t=Vr(r);return[e,t]}import{homedir as zr}from"node:os";import{join as nt,resolve as ks}from"node:path";function ot(r={}){return r.cursorHome??nt(r.home??zr(),".cursor")}function Wr(r={}){return r.cursorConfigDir??process.env.CURSOR_CONFIG_DIR??(r.xdgConfigHome??process.env.XDG_CONFIG_HOME?nt(r.xdgConfigHome??process.env.XDG_CONFIG_HOME,"cursor"):void 0)??ot(r)}function it(r={}){return Array.from(new Set([ot(r),Wr(r)]))}import{homedir as Yr}from"node:os";import{join as Br,resolve as ws}from"node:path";function Jr(r={}){return r.copilotHome??process.env.COPILOT_HOME??Br(r.home??Yr(),".copilot")}function st(r={}){return[Jr(r)]}import{homedir as qr}from"node:os";import{join as Zr,resolve as Os}from"node:path";function Qr(r={}){return r.grokHome??process.env.GROK_HOME??Zr(r.home??qr(),".grok")}function ct(r={}){return[Qr(r)]}function rn(r){return tn("sh",["-lc",`command -v ${JSON.stringify(r)} >/dev/null 2>&1`],{stdio:"ignore"}).status===0}function m(r){let e=r.commandExists(r.command),t=r.configPaths.filter(i=>ut(i)),n=t.length>0,o=[];e&&o.push(`command:${r.command}`);for(let i of t)o.push(`config:${i}`);return{agent:r.agent,detected:e||n,commandDetected:e,configDetected:n,evidence:o}}function at(r){let e=r.commands.filter(s=>r.commandExists(s)),t=r.configPaths.filter(s=>ut(s)),n=e.length>0,o=t.length>0,i=[...e.map(s=>`command:${s}`),...t.map(s=>`config:${s}`)];return{agent:r.agent,detected:n||o,commandDetected:n,configDetected:o,evidence:i}}function dt(r={}){let e=r.home??Xr(),t=r.commandExists??rn,n=r.codexHome??process.env.CODEX_HOME??en(e,".codex");return[m({agent:"agy",command:"agy",commandExists:t,configPaths:We({home:e})}),m({agent:"opencode",command:"opencode",commandExists:t,configPaths:[Be({home:e,xdgConfigHome:r.xdgConfigHome})]}),m({agent:"claude",command:"claude",commandExists:t,configPaths:[Je({home:e})]}),m({agent:"kiro",command:"kiro-cli",commandExists:t,configPaths:Ze({home:e,kiroHome:r.kiroHome})}),at({agent:"cursor",commands:["agent","cursor-agent"],commandExists:t,configPaths:it({home:e,cursorHome:r.cursorHome,cursorConfigDir:r.cursorConfigDir,xdgConfigHome:r.xdgConfigHome})}),m({agent:"copilot",command:"copilot",commandExists:t,configPaths:st({home:e,copilotHome:r.copilotHome})}),m({agent:"grok",command:"grok",commandExists:t,configPaths:ct({home:e,grokHome:r.grokHome})}),m({agent:"toolnet-cli",command:"toolnet",commandExists:t,configPaths:et({home:e})}),at({agent:"kilo",commands:["kilo","kilo-code"],commandExists:t,configPaths:rt({home:e,kiloHome:r.kiloHome})}),m({agent:"codex",command:"codex",commandExists:t,configPaths:[n]})]}import{existsSync as oe,readFileSync as nn}from"node:fs";var on="ToolNet Memory - ",sn=["SessionStart","UserPromptSubmit","PreToolUse","PostToolUse","Stop"];function S(r){return typeof r=="object"&&r!==null&&!Array.isArray(r)}function lt(r){if(!oe(r))return{};let e;try{e=JSON.parse(nn(r,"utf8"))}catch(t){return{error:t instanceof Error?t.message:String(t)}}return S(e)?{value:e}:{error:"root must be a JSON object"}}function cn(r){if(!r||!S(r.mcpServers))return!1;let e=r.mcpServers["toolnet-memory"];return S(e)?typeof e.command=="string"&&e.command.trim().length>0&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp"&&e.disabled!==!0:!1}function an(r){if(!(!S(r)||!S(r.action)))return typeof r.action.command=="string"?r.action.command:void 0}function un(r){if(!r||r.version!=="v1"||!Array.isArray(r.hooks))return[];let e=new Set;for(let t of r.hooks){if(!S(t)||typeof t.name!="string"||!t.name.startsWith(on))continue;let n=an(t);!n||!n.includes("session:kiro-hook")||t.enabled!==!1&&typeof t.trigger=="string"&&e.add(t.trigger)}return[...e]}function pt(r={}){let e=r.configFile??re(),t=r.hooksFile??qe(),n=lt(e),o=lt(t),i=!n.error&&cn(n.value),s=o.error?[]:un(o.value),c=sn.every(p=>s.includes(p)),u=[];n.error&&u.push(`MCP config: ${n.error}`),o.error&&u.push(`Hooks config: ${o.error}`);let a=i&&c,f=oe(e)||oe(t),d=u.length>0?"invalid":a?"ready":f?"partial":"not-installed";return{installed:a,state:d,mcp:{configured:i,configFile:e,error:n.error},hooks:{configured:c,hooksFile:t,triggers:s,error:o.error},errors:u}}var dn={spinner:["\xB7","\u2722","\u2733","\u2736","\u273B","\u273D"],barFilled:"\u2588",barEmpty:"\u2591",phaseDone:"\u25C6",phaseActive:"\u25C7",rail:"\u2502",branch:"\u251C",corner:"\u2514",dash:"\u2014"},ln={spinner:[".","*","+","x","*","+"],barFilled:"#",barEmpty:"-",phaseDone:"[OK]",phaseActive:"[>>]",rail:"|",branch:"|",corner:"\\",dash:"-"};function pn(){if(process.env.TOOLNET_ASCII==="1")return!1;if(process.env.TOOLNET_UNICODE==="1")return!0;if(process.platform==="win32"){let r=process.env.TERM_PROGRAM,e=process.env.WT_SESSION,t=process.env.VSCODE_PID,n=process.env.ConEmuPID;return!!(e||t||n||r==="vscode")}return process.env.TERM!=="linux"}var ie;function ft(){return ie||(ie=pn()?dn:ln),ie}var C={reset:"\x1B[0m",green:"\x1B[32m",cyan:"\x1B[36m",red:"\x1B[31m",yellow:"\x1B[33m",amber:"\x1B[38;5;214m",white:"\x1B[97m",dim:"\x1B[2m",bold:"\x1B[1m"};function fn(r){return r.noColor||process.env.NO_COLOR?!1:r.tty??process.stdout.isTTY??!1}function _(r,e,t){return fn(t)?`${e}${r}${C.reset}`:r}function V(r,e){return _(r,C.dim,e)}function mn(r,e){return _(r,C.bold,e)}function gn(r,e){return _(r,C.cyan,e)}function yn(r,e){return _(r,C.red,e)}function hn(r,e){return _(r,C.white,e)}function mt(r,e,t){let n=ft(),o=e?` ${V(`v${e}`,t)}`:"";return`${gn(n.phaseDone,t)} ${r}${o}`}function z(r,e){return mn(r,e)}function x(r,e,t,n){let o=" ".repeat(Math.max(0,t-r.length));return` ${V(r,n)}${o} ${hn(e,n)}`}function gt(r){return yn("\u2717",r)}function xn(r){return{tty:r.tty,noColor:r.noColor}}async function kn(r){let e=xn(r);console.log(""),console.log(mt("ToolNet Status",void 0,e)),console.log("");try{let t=new L().detect(),n=se();console.log(z("PROJECT",e)),console.log(x("Name",t.name,8,e));let o=_e(Me({provider:n.storage.provider,r2:n.storage.r2,s3:n.storage.s3,huggingface:n.storage.huggingface,localRoot:n.storage.localRoot}),{attempts:3}),i=new U(o,t.id,t.name,t.remote??t.name),s="unknown",c="unknown";try{s=await i.exists(`${t.id}/memory.json`)?"ready":"not initialized"}catch{s="error"}try{c=await i.exists(`${t.id}/code-graph.json`)?"ready":"not built"}catch{c="error"}console.log(x("Memory",s,8,e)),console.log(x("Index",c,8,e)),console.log("");let u=dt(),a=u.filter(d=>d.detected).map(d=>d.agent);if(a.length>0){if(console.log(z("INTEGRATIONS",e)),console.log(x("Detected",a.join(", "),8,e)),u.find(p=>p.agent==="kiro")?.detected){let p=pt();console.log(x("Kiro",p.installed?"ready":p.state,8,e))}console.log("")}let f=Ue(t);if(f.agents.length>0){console.log(z("SERVICE",e));let d=f.syncHealth==="healthy"?"running":f.syncHealth==="degraded"?"degraded":"stopped";console.log(x("Daemon",d,8,e)),console.log("")}}catch(t){console.log(gt(e)+" Failed to get status"),console.log(""),console.log(V(` ${t instanceof Error?t.message:String(t)}`,e)),console.log(""),process.exitCode=1}}async function Sn(){let r=process.argv.slice(2),e={tty:process.stdout.isTTY,noColor:process.env.NO_COLOR!==void 0||r.includes("--no-color")};await kn(e)}Sn().catch(r=>{console.error(""),console.error(r instanceof Error?r.message:String(r)),console.error(""),process.exitCode=1});