toolnet-memory 0.3.16 → 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.
- package/.env.example +74 -0
- package/.release-target +1 -1
- package/README.md +165 -7
- package/bin/toolnet-memory +12 -0
- package/bundle/agy-hook.js +59 -59
- package/bundle/agy.js +58 -58
- package/bundle/api.js +15 -15
- package/bundle/audit.js +2 -0
- package/bundle/background-refresh.js +7 -7
- package/bundle/code-capabilities.js +2 -0
- package/bundle/codex.js +63 -63
- package/bundle/context-runtime.js +41 -41
- package/bundle/context.js +15 -15
- package/bundle/copilot-hook.js +73 -73
- package/bundle/cursor-hook.js +73 -73
- package/bundle/docker-healthcheck.js +3 -0
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +20 -19
- package/bundle/gc.js +5 -3
- package/bundle/graph-cli.js +1 -1
- package/bundle/graph-index.js +5 -4
- package/bundle/graph-ui.js +4 -3
- package/bundle/grok-hook.js +52 -52
- package/bundle/handoff-refresh.js +2 -2
- package/bundle/help-cli.js +4 -4
- package/bundle/impact.js +5 -4
- package/bundle/incremental.js +5 -5
- package/bundle/init.js +35 -35
- package/bundle/kiro-hook.js +74 -74
- package/bundle/learner.js +8 -6
- package/bundle/mcp.js +19 -17
- package/bundle/memory-agent.js +4 -4
- package/bundle/memory-query.js +3 -3
- package/bundle/opencode.js +73 -73
- package/bundle/project-manual.js +7 -7
- package/bundle/public/index.html +51 -2
- package/bundle/runtime.js +16 -13
- package/bundle/semantic.js +6 -5
- package/bundle/service.js +11 -6
- package/bundle/snapshot.js +6 -4
- package/bundle/status-cli.js +4 -4
- package/bundle/toolnet-cli.js +49 -49
- package/bundle/work-continuity.js +7 -7
- package/package.json +26 -2
- package/release-manifest.json +94 -5
|
@@ -8,5 +8,5 @@ import*as f from"fs";import*as u from"path";import{existsSync as _,mkdirSync as
|
|
|
8
8
|
|
|
9
9
|
[Current work truncated for fast handoff]`:t,o=K(n);return["# ToolNet Fast Handoff","",`Project: ${n.name}`,"",...o?[o,""]:[],i,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
|
|
10
10
|
`)}function z(n){let e=me(n);if(e===null)return{updated:!1,reason:"missing-current",chars:0};if(!e.trim())return{updated:!1,reason:"empty-current",chars:0};let t=ge(n,e);return $(n)?.text.trim()===t.trim()?{updated:!1,reason:"unchanged",chars:t.length}:(F(n,t),{updated:!0,reason:"updated",chars:t.length})}import{existsSync as ye,readFileSync as he}from"node:fs";import{homedir as xe}from"node:os";import{join as Se}from"node:path";function be(n){let e=n.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
|
|
11
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function ve(){let n=process.env.TOOLNET_GLOBAL_ENV??Se(xe(),".config","toolnet-memory",".env");if(!ye(n))return;let e=he(n,"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 i=r.indexOf("=");if(i<=0)continue;let o=r.slice(0,i).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=be(r.slice(i+1)))}}ve();import{createHash as Ee}from"node:crypto";import{existsSync as b,mkdirSync as Te,readFileSync as Ie,renameSync as _e,writeFileSync as Oe}from"node:fs";import{basename as je,dirname as v,join as h,parse as U,resolve as l}from"node:path";import{createHash as H}from"node:crypto";import{spawnSync as we}from"node:child_process";var y="git-remote-v1",Me=new Set(["github.com","gitlab.com","bitbucket.org"]);function B(n,e){let t=e.replaceAll("\\","/").replace(/^\/+/u,"").replace(/\/+$/u,"").replace(/\.git$/iu,"").replace(/\/+/gu,"/");return!t||t==="."||t===".."||t.split("/").some(r=>!r||r==="."||r==="..")?null:(Me.has(n)&&(t=t.toLowerCase()),t)}function
|
|
12
|
-
`,{encoding:"utf8",mode:384}),_e(i,r)}function d(n,e){return{id:n.id,name:n.name,remote:n.remote,rootPath:e,createdAt:n.createdAt,updatedAt:n.updatedAt,graphVersion:n.graphVersion,memoryVersion:n.memoryVersion,metadata:n.metadata}}function T(n){return{version:1,scheme:y,canonicalRemote:n.canonicalRemote,fingerprint:n.fingerprint,repositoryName:n.repositoryName}}function De(n){let e=n.metadata?.toolnetIdentity;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return typeof t.fingerprint=="string"?t.fingerprint:null}var w=class{adopt(e,t){let r=E(l(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(Z(r)){let a=x(p(r));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return d(a,r)}let i=new Date().toISOString(),o={...t.metadata};t.gitIdentity&&(o.toolnetIdentity=T(t.gitIdentity));let s={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:r,createdAt:t.createdAt??i,updatedAt:i,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(o).length?o:void 0};return S(r,s),d(s,r)}recordGitIdentity(e,t,r={}){let i=this.requireExisting(e),o=p(i.rootPath),s=x(o),a=De(s);if(a&&a!==t.fingerprint&&!r.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${a}`,`current=${t.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let c=s.metadata?.toolnetIdentity;return c&&typeof c=="object"&&!Array.isArray(c)&&c.fingerprint===t.fingerprint||(s.metadata={...s.metadata,toolnetIdentity:T(t)},s.updatedAt=new Date().toISOString(),S(i.rootPath,s)),d(s,i.rootPath)}findExisting(e=process.cwd()){let t=l(e),r=E(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>b(h(r,c))),s=J(t,o?r:void 0);if(!s)return null;let a=x(p(s));return d(a,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=l(e),r=E(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(
|
|
11
|
+
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function ve(){let n=process.env.TOOLNET_GLOBAL_ENV??Se(xe(),".config","toolnet-memory",".env");if(!ye(n))return;let e=he(n,"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 i=r.indexOf("=");if(i<=0)continue;let o=r.slice(0,i).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=be(r.slice(i+1)))}}ve();import{createHash as Ee}from"node:crypto";import{existsSync as b,mkdirSync as Te,readFileSync as Ie,renameSync as _e,writeFileSync as Oe}from"node:fs";import{basename as je,dirname as v,join as h,parse as U,resolve as l}from"node:path";import{createHash as H}from"node:crypto";import{spawnSync as we}from"node:child_process";var y="git-remote-v1",Me=new Set(["github.com","gitlab.com","bitbucket.org"]);function B(n,e){let t=e.replaceAll("\\","/").replace(/^\/+/u,"").replace(/\/+$/u,"").replace(/\.git$/iu,"").replace(/\/+/gu,"/");return!t||t==="."||t===".."||t.split("/").some(r=>!r||r==="."||r==="..")?null:(Me.has(n)&&(t=t.toLowerCase()),t)}function Ae(n){let e;try{e=new URL(n)}catch{return null}if(!["https:","http:","ssh:","git:"].includes(e.protocol))return null;let t=e.hostname.trim().toLowerCase();if(!t)return null;let r=e.protocol==="https:"&&e.port==="443"||e.protocol==="http:"&&e.port==="80"||e.protocol==="ssh:"&&e.port==="22",i=e.port&&!r?`${t}:${e.port}`:t,o=B(t,e.pathname);return o?`${i}/${o}`:null}function ke(n){let e=n.match(/^(?:[^@\s/:]+@)?([^:/\s]+):(.+)$/u);if(!e)return null;let t=e[1]?.trim().toLowerCase();if(!t||t.length===1)return null;let r=B(t,e[2]??"");return r?`${t}/${r}`:null}function V(n){let e=n.trim();return e?e.includes("://")?Ae(e):ke(e):null}function Re(n){return H("sha256").update(`${y}:${n}`).digest("hex")}function Y(n){return H("sha256").update(`toolnet-project:${y}:${n}`).digest("hex").slice(0,16)}function Ce(n){return n.split("/").filter(Boolean).at(-1)?.trim()||null}function C(n,e){let t=we("git",["-C",n,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function G(n,e){let t=Ce(n);return t?{scheme:y,canonicalRemote:n,fingerprint:Re(n),repositoryName:t,source:e}:null}function W(n){let e=C(n,["remote","get-url","origin"]);if(e){let i=V(e);if(i)return G(i,"origin")}let t=C(n,["remote"]);if(!t)return null;let r=new Set;for(let i of t.split(/\r?\n/u).map(o=>o.trim()).filter(Boolean)){let o=C(n,["remote","get-url",i]);if(!o)continue;let s=V(o);s&&r.add(s)}return r.size!==1?null:G([...r][0],"unique-remote")}var q=".toolnet",Pe="project.json";function Ne(n){return Ee("sha256").update(n).digest("hex").slice(0,16)}function p(n){return h(n,q,Pe)}function Z(n){return b(p(n))}function J(n,e){let t=l(n),r=U(t).root;for(;;){if(Z(t))return t;if(t===r||e&&t===l(e))break;let i=v(t);if(i===t)break;t=i}return null}function E(n){let e=l(n),t=U(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>b(h(e,o))))return e;if(e===t)break;let i=v(e);if(i===e)break;e=i}return l(n)}function x(n){let e;try{e=JSON.parse(Ie(n,"utf8"))}catch(i){throw new Error(`Invalid ToolNet project manifest: ${n}: ${i instanceof Error?i.message:String(i)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${n}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${n}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${n}`);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:v(v(n)),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 S(n,e){let t=h(n,q);Te(t,{recursive:!0});let r=p(n),i=`${r}.tmp-${process.pid}`;Oe(i,JSON.stringify(e,null,2)+`
|
|
12
|
+
`,{encoding:"utf8",mode:384}),_e(i,r)}function d(n,e){return{id:n.id,name:n.name,remote:n.remote,rootPath:e,createdAt:n.createdAt,updatedAt:n.updatedAt,graphVersion:n.graphVersion,memoryVersion:n.memoryVersion,metadata:n.metadata}}function T(n){return{version:1,scheme:y,canonicalRemote:n.canonicalRemote,fingerprint:n.fingerprint,repositoryName:n.repositoryName}}function De(n){let e=n.metadata?.toolnetIdentity;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return typeof t.fingerprint=="string"?t.fingerprint:null}var w=class{adopt(e,t){let r=E(l(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(Z(r)){let a=x(p(r));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return d(a,r)}let i=new Date().toISOString(),o={...t.metadata};t.gitIdentity&&(o.toolnetIdentity=T(t.gitIdentity));let s={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:r,createdAt:t.createdAt??i,updatedAt:i,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(o).length?o:void 0};return S(r,s),d(s,r)}recordGitIdentity(e,t,r={}){let i=this.requireExisting(e),o=p(i.rootPath),s=x(o),a=De(s);if(a&&a!==t.fingerprint&&!r.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${a}`,`current=${t.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let c=s.metadata?.toolnetIdentity;return c&&typeof c=="object"&&!Array.isArray(c)&&c.fingerprint===t.fingerprint||(s.metadata={...s.metadata,toolnetIdentity:T(t)},s.updatedAt=new Date().toISOString(),S(i.rootPath,s)),d(s,i.rootPath)}findExisting(e=process.cwd()){let t=l(e),r=E(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>b(h(r,c))),s=J(t,o?r:void 0);if(!s)return null;let a=x(p(s));return d(a,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=l(e),r=E(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(k=>b(h(r,k))),s=J(t,o?r:void 0);if(s){let k=p(s),g=x(k);return g.rootPath!==s&&(g.rootPath=s,g.updatedAt=new Date().toISOString(),S(s,g)),d(g,s)}let a=new Date().toISOString(),c=je(r),m=W(r),I={version:1,id:m?Y(m.canonicalRemote):Ne(r),name:c,remote:m?.repositoryName??c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:m?{toolnetIdentity:T(m)}:void 0};return S(r,I),d(I,r)}};var Fe=[{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"}],$e=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function Q(n){return n.normalize("NFKC").trim().toLowerCase()}function Le(n){if(n.length===0)return 0;let e=new Map;for(let r of n)e.set(r,(e.get(r)??0)+1);let t=0;for(let r of e.values()){let i=r/n.length;t-=i*Math.log2(i)}return t}function Ke(n){return/^[a-f0-9]{32}$/iu.test(n)||/^[a-f0-9]{40}$/iu.test(n)||/^[a-f0-9]{64}$/iu.test(n)}function ze(n,e,t){let r=n.slice(Math.max(0,e-48),e),i=n.slice(t,Math.min(n.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${i}`)}function Ve(n,e){return n.start<e.end&&e.start<n.end}function X(n){return n.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var M=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let r=Q(t);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let o of Fe){let s=new RegExp(o.regex.source,o.regex.flags);for(let a of e.matchAll(s))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:o.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:o.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let r=X(t),i=[];for(let o of r)i.some(s=>Ve(s,o))||i.push(o);return X(i)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=Q(e);return $e.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let i of e.matchAll(r)){if(i.index===void 0||!i[0])continue;let o=i[0];this.allowed(o)||Ke(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||ze(e,i.index,i.index+o.length)&&(Le(o)<3.7||t.push({type:"high_entropy_secret",value:o,start:i.index,end:i.index+o.length,confidence:"heuristic"}))}return t}};var A=class{scanner;constructor(e={}){this.scanner=new M(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let r=e,i=[...t].sort((s,a)=>a.start-s.start),o=new Set;for(let s of i)o.add(s.type),r=r.slice(0,s.start)+`[REDACTED:${s.type}]`+r.slice(s.end);return{text:r,redacted:t.length,secretTypes:[...o].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[r,i]of Object.entries(e)){let o=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")){t[r]="[REDACTED]";continue}t[r]=this.sanitizeValue(i)}return t}return e}};var Gt=new A;function Ge(){let n=process.cwd(),e=L(n);if(!e){console.error("Not in a ToolNet project."),process.exitCode=1;return}let t=new w().detect(e);if(!t){console.error("Unable to detect ToolNet project."),process.exitCode=1;return}let r=z(t);console.log(JSON.stringify({project:t.name,...r},null,2))}Ge();
|
package/bundle/help-cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readFileSync as A}from"node:fs";import{dirname as G,resolve as w}from"node:path";import{fileURLToPath as D}from"node:url";var I={spinner:["\xB7","\u2722","\u2733","\u2736","\u273B","\u273D"],barFilled:"\u2588",barEmpty:"\u2591",phaseDone:"\u25C6",phaseActive:"\u25C7",rail:"\u2502",branch:"\u251C",corner:"\u2514",dash:"\u2014"},R={spinner:[".","*","+","x","*","+"],barFilled:"#",barEmpty:"-",phaseDone:"[OK]",phaseActive:"[>>]",rail:"|",branch:"|",corner:"\\",dash:"-"};function U(){if(process.env.TOOLNET_ASCII==="1")return!1;if(process.env.TOOLNET_UNICODE==="1")return!0;if(process.platform==="win32"){let o=process.env.TERM_PROGRAM,e=process.env.WT_SESSION,n=process.env.VSCODE_PID,t=process.env.ConEmuPID;return!!(e||n||t||o==="vscode")}return process.env.TERM!=="linux"}var h;function k(){return h||(h=U()?I:R),h}var m={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 T(o){return o.noColor||process.env.NO_COLOR?!1:o.tty??process.stdout.isTTY??!1}function f(o,e,n){return T(n)?`${e}${o}${m.reset}`:o}function N(o,e){return f(o,m.dim,e)}function M(o,e){return f(o,m.bold,e)}function b(o,e){return f(o,m.cyan,e)}function g(o,e,n){let t=k(),i=e?` ${N(`v${e}`,n)}`:"";return`${b(t.phaseDone,n)} ${o}${i}`}function a(o,e){return M(o,e)}function l(o,e,n,t){let i=" ".repeat(Math.max(0,n-o.length));return` ${b(o,t)}${i} ${e}`}var u=[{name:"init",description:"Initialize current project",usage:"toolnet-memory init [path] [--adopt-remote NAME] [--no-remote-identity] [--rebind-git-identity]",category:"core",examples:["toolnet-memory init","toolnet-memory init /path/to/project","toolnet-memory init --adopt-remote my-project"]},{name:"doctor",description:"Check system health",category:"core"},{name:"ask",description:"Ask project memory",usage:"toolnet-memory ask <question>",category:"memory"},{name:"context",description:"Show current project context",category:"memory",aliases:["context:print"]},{name:"work",description:"Show current work state",category:"memory",aliases:["work:status"]},{name:"index",description:"Build code intelligence",category:"code",pipeline:["Scanning files","Parsing code","Type Resolution","Rich Graph","Local Code Search \u2014 SQLite FTS5/BM25","Architecture Intelligence","Graph Analysis","3D Visualization Dataset"]},{name:"semantic",description:"Local code search \u2014 SQLite FTS5/BM25 (legacy command name)",usage:"toolnet-memory semantic <query>",category:"code"},{name:"impact",description:"Analyze change impact",usage:"toolnet-memory impact <file>",category:"code"},{name:"graph",description:"Open code graph UI",category:"code"},{name:"graph:ui",description:"Open code graph UI",category:"code",hidden:!0},{name:"status",description:"Show ToolNet status",category:"system"},{name:"gc",description:"Plan or apply safe retention cleanup",usage:"toolnet-memory gc [--dry-run|--apply] [--remote] [--keep-snapshots N] [--snapshot-days N] [--runtime-days N] [--stale-lock-minutes N] [--project PATH] [--json]",category:"system",examples:["toolnet-memory gc","toolnet-memory gc --remote --dry-run","toolnet-memory gc --apply","toolnet-memory gc --remote --apply --keep-snapshots 10"]},{name:"update",description:"Update ToolNet Memory",category:"system"},{name:"context:print",description:"Print fast project context",category:"context",hidden:!0},{name:"context:sync",description:"Show context hash/size",category:"context"},{name:"context:refresh",description:"Rebuild deep startup brief cache",category:"context"},{name:"brief",description:"Show full project brief",category:"context"},{name:"brief:json",description:"Show brief as JSON",category:"context"},{name:"profile:show",description:"Show .toolnet/profile.md",category:"context"},{name:"profile:sync",description:"Sync profile to agent files",category:"context"},{name:"work:status",description:"Show current work state",category:"work",hidden:!0},{name:"work:json",description:"Show work state as JSON",category:"work"},{name:"work:reconcile",description:"Reconcile work continuity",category:"work"},{name:"handoff:latest",description:"Show latest session handoff",category:"work"},{name:"handoff:refresh",description:"Refresh handoff data",category:"work"},{name:"index:graph",description:"Build graph index only",category:"code"},{name:"incremental",description:"Incremental code indexing",category:"code"},{name:"config",description:"Manage configuration",usage:"toolnet-memory config <get|set|list|open>",category:"system"},{name:"integrate:detect",description:"Detect agent integrations",category:"integration"},{name:"integrate:auto",description:"Auto-enable integrations with safe project scope policy",usage:"toolnet-memory integrate:auto [--all] [--scope global|project|both] [--project <path>] [--json]",category:"integration",examples:["toolnet-memory integrate:auto","toolnet-memory integrate:auto --project /path/to/toolnet-project","toolnet-memory integrate:auto --scope global","toolnet-memory integrate:auto --scope both --project /path/to/project"]},{name:"integrate:agy",description:"Install Agy hooks",category:"integration"},{name:"integrate:codex",description:"Install Codex integration",category:"integration"},{name:"integrate:opencode",description:"Install OpenCode plugin",category:"integration"},{name:"integrate:claude",description:"Install Claude Code integration",category:"integration"},{name:"integrate:kiro",description:"Install Kiro CLI integration",usage:"toolnet-memory integrate:kiro [--status] [--json]",category:"integration"},{name:"integrate:cursor",description:"Install Cursor CLI integration",usage:"toolnet-memory integrate:cursor [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:cursor --scope global","toolnet-memory integrate:cursor --scope project --project /path/to/project","toolnet-memory integrate:cursor --scope both --project /path/to/project"]},{name:"integrate:copilot",description:"Install GitHub Copilot CLI integration",usage:"toolnet-memory integrate:copilot [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:copilot --scope global","toolnet-memory integrate:copilot --scope project --project /path/to/project","toolnet-memory integrate:copilot --scope both --project /path/to/project"]},{name:"integrate:grok",description:"Install Grok Build integration",usage:"toolnet-memory integrate:grok [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:grok --scope global","toolnet-memory integrate:grok --scope project --project /path/to/project","toolnet-memory integrate:grok --scope both --project /path/to/project"]},{name:"integrate:toolnet-cli",description:"Install ToolNet CLI MCP integration",usage:"toolnet-memory integrate:toolnet-cli [--status] [--json] [--force]",category:"integration",examples:["toolnet-memory integrate:toolnet-cli","toolnet-memory integrate:toolnet-cli --status"]},{name:"integrate:kilo",description:"Install Kilo CLI MCP integration",usage:"toolnet-memory integrate:kilo [--status] [--json] [--force]",category:"integration",examples:["toolnet-memory integrate:kilo","toolnet-memory integrate:kilo --status"]},{name:"integrate:all",description:"Auto-enable all detected integrations",usage:"toolnet-memory integrate:all [--json]",category:"integration"},{name:"integrate:status",description:"Show unified Cursor/Copilot/Grok scoped integration status",usage:"toolnet-memory integrate:status [--scope global|project|both] [--project <path>] [--agent cursor|copilot|grok] [--json]",category:"integration",examples:["toolnet-memory integrate:status --scope global","toolnet-memory integrate:status --scope both --project /path/to/project","toolnet-memory integrate:status --scope both --project /path/to/project --agent cursor"]},{name:"session:agy-sync",description:"Sync Agy session",category:"session"},{name:"session:agy-recover",description:"Recover Agy sessions",category:"session"},{name:"session:agy-hook",description:"Agy session hook",category:"session",hidden:!0},{name:"session:codex-sync",description:"Sync Codex session",category:"session"},{name:"session:codex-recover",description:"Recover Codex sessions",category:"session"},{name:"session:codex-notify",description:"Codex notification hook",category:"session",hidden:!0},{name:"session:codex-context",description:"Codex context hook",category:"session",hidden:!0},{name:"session:opencode-sync",description:"Sync OpenCode session",category:"session"},{name:"session:opencode-recover",description:"Recover OpenCode sessions",category:"session"},{name:"session:claude-hook",description:"Claude session hook",category:"session",hidden:!0},{name:"session:kiro-hook",description:"Kiro lifecycle hook",category:"session",hidden:!0},{name:"session:cursor-hook",description:"Cursor lifecycle hook",category:"session",hidden:!0},{name:"session:copilot-hook",description:"Copilot lifecycle hook",category:"session",hidden:!0},{name:"session:grok-hook",description:"Grok lifecycle hook",category:"session",hidden:!0},{name:"memory:review",description:"Review memory entries",category:"session"},{name:"memory:reconcile",description:"Reconcile memory state",category:"session"},{name:"guard:check",description:"Check project rules",category:"guard"},{name:"guard:explain",description:"Show rules and evidence",category:"guard"},{name:"guard:json",description:"Output guard result as JSON",category:"guard",hidden:!0},{name:"project:manual-init",description:"Initialize project manual",category:"project"},{name:"project:manual-show",description:"Show project manual",category:"project"},{name:"project:manual-sync",description:"Sync project manual",category:"project"},{name:"snapshot:list",description:"List snapshots",category:"snapshot"},{name:"snapshot:create",description:"Create snapshot",category:"snapshot"},{name:"snapshot:restore",description:"Restore snapshot",category:"snapshot"},{name:"recover",description:"Recover latest snapshot",category:"snapshot"},{name:"service",description:"Run daemon in foreground",category:"service"},{name:"service:install",description:"Install/start daemon",category:"service"},{name:"service:start",description:"Start daemon",category:"service"},{name:"service:stop",description:"Stop daemon",category:"service"},{name:"service:restart",description:"Restart daemon",category:"service"},{name:"service:status",description:"Show daemon status",category:"service"},{name:"service:remove",description:"Remove daemon",category:"service"},{name:"mcp",description:"Run MCP server",category:"advanced"},{name:"api",description:"Run API server",category:"advanced"},{name:"run",description:"Run ToolNet runtime",category:"advanced",hidden:!0},{name:"production:certify",description:"Verify production runtime",category:"advanced"},{name:"certify:continuity",description:"Certify work continuity",category:"advanced"}];function x(o){return{tty:o.tty,noColor:o.noColor}}function O(o){let e=[],n=o.version??"0.0.0",t=x(o);e.push(""),e.push(g("ToolNet Memory",n,t)),e.push(" Persistent memory & code intelligence for AI coding agents"),e.push(""),e.push(a("USAGE",t)),e.push(" toolnet-memory <command> [options]"),e.push("");let i=[{key:"core",title:"GET STARTED"},{key:"memory",title:"MEMORY"},{key:"code",title:"CODE"},{key:"system",title:"SYSTEM"}];for(let{key:s,title:d}of i){let c=u.filter(r=>r.category===s&&!r.hidden);if(c.length===0)continue;e.push(a(d,t));let y=Math.max(...c.map(r=>r.name.length));for(let r of c)e.push(l(r.name,r.description,y,t));e.push("")}return e.push(a("MORE",t)),e.push(l("help --all","Show all advanced commands",15,t)),e.push(l("help <command>","Show command details",15,t)),e.push(""),e.join(`
|
|
2
|
-
`)}function
|
|
3
|
-
`)}function
|
|
4
|
-
`)}function v(o){return u.flatMap(t=>[t.name,...t.aliases??[]]).filter(t=>t===o?!1:!!(t.startsWith(o)||o.length>=3&&t.includes(o))).slice(0,3)}function
|
|
1
|
+
import{readFileSync as G}from"node:fs";import{dirname as M,resolve as w}from"node:path";import{fileURLToPath as L}from"node:url";var T={spinner:["\xB7","\u2722","\u2733","\u2736","\u273B","\u273D"],barFilled:"\u2588",barEmpty:"\u2591",phaseDone:"\u25C6",phaseActive:"\u25C7",rail:"\u2502",branch:"\u251C",corner:"\u2514",dash:"\u2014"},R={spinner:[".","*","+","x","*","+"],barFilled:"#",barEmpty:"-",phaseDone:"[OK]",phaseActive:"[>>]",rail:"|",branch:"|",corner:"\\",dash:"-"};function I(){if(process.env.TOOLNET_ASCII==="1")return!1;if(process.env.TOOLNET_UNICODE==="1")return!0;if(process.platform==="win32"){let o=process.env.TERM_PROGRAM,e=process.env.WT_SESSION,n=process.env.VSCODE_PID,t=process.env.ConEmuPID;return!!(e||n||t||o==="vscode")}return process.env.TERM!=="linux"}var h;function k(){return h||(h=I()?T:R),h}var m={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 N(o){return o.noColor||process.env.NO_COLOR?!1:o.tty??process.stdout.isTTY??!1}function f(o,e,n){return N(n)?`${e}${o}${m.reset}`:o}function U(o,e){return f(o,m.dim,e)}function A(o,e){return f(o,m.bold,e)}function O(o,e){return f(o,m.cyan,e)}function g(o,e,n){let t=k(),i=e?` ${U(`v${e}`,n)}`:"";return`${O(t.phaseDone,n)} ${o}${i}`}function a(o,e){return A(o,e)}function l(o,e,n,t){let i=" ".repeat(Math.max(0,n-o.length));return` ${O(o,t)}${i} ${e}`}var u=[{name:"init",description:"Initialize current project",usage:"toolnet-memory init [path] [--adopt-remote NAME] [--no-remote-identity] [--rebind-git-identity]",category:"core",examples:["toolnet-memory init","toolnet-memory init /path/to/project","toolnet-memory init --adopt-remote my-project"]},{name:"doctor",description:"Check system health",category:"core"},{name:"ask",description:"Ask project memory",usage:"toolnet-memory ask <question>",category:"memory"},{name:"context",description:"Show current project context",category:"memory",aliases:["context:print"]},{name:"work",description:"Show current work state",category:"memory",aliases:["work:status"]},{name:"index",description:"Build code intelligence",category:"code",pipeline:["Scanning files","Parsing code","Type Resolution","Rich Graph","Local Code Search \u2014 SQLite FTS5/BM25","Architecture Intelligence","Graph Analysis","3D Visualization Dataset"]},{name:"semantic",description:"Local code search \u2014 SQLite FTS5/BM25 (legacy command name)",usage:"toolnet-memory semantic <query>",category:"code"},{name:"impact",description:"Analyze change impact",usage:"toolnet-memory impact <file>",category:"code"},{name:"graph",description:"Open localhost-first code graph UI with optional bearer authentication",usage:"toolnet-memory graph",category:"code",examples:["toolnet-memory graph","TOOLNET_GRAPH_HOST=0.0.0.0 TOOLNET_GRAPH_TOKEN=<random-token> toolnet-memory graph"]},{name:"graph:ui",description:"Open code graph UI",category:"code",hidden:!0},{name:"status",description:"Show ToolNet status",category:"system"},{name:"gc",description:"Plan or apply safe retention cleanup",usage:"toolnet-memory gc [--dry-run|--apply] [--remote] [--keep-snapshots N] [--snapshot-days N] [--runtime-days N] [--stale-lock-minutes N] [--project PATH] [--json]",category:"system",examples:["toolnet-memory gc","toolnet-memory gc --remote --dry-run","toolnet-memory gc --apply","toolnet-memory gc --remote --apply --keep-snapshots 10"]},{name:"update",description:"Update ToolNet Memory",category:"system"},{name:"context:print",description:"Print fast project context",category:"context",hidden:!0},{name:"context:sync",description:"Show context hash/size",category:"context"},{name:"context:refresh",description:"Rebuild deep startup brief cache",category:"context"},{name:"brief",description:"Show full project brief",category:"context"},{name:"brief:json",description:"Show brief as JSON",category:"context"},{name:"profile:show",description:"Show .toolnet/profile.md",category:"context"},{name:"profile:sync",description:"Sync profile to agent files",category:"context"},{name:"work:status",description:"Show current work state",category:"work",hidden:!0},{name:"work:json",description:"Show work state as JSON",category:"work"},{name:"work:reconcile",description:"Reconcile work continuity",category:"work"},{name:"handoff:latest",description:"Show latest session handoff",category:"work"},{name:"handoff:refresh",description:"Refresh handoff data",category:"work"},{name:"index:graph",description:"Build graph index only",category:"code"},{name:"incremental",description:"Incremental code indexing",category:"code"},{name:"config",description:"Manage configuration",usage:"toolnet-memory config <get|set|list|open>",category:"system"},{name:"integrate:detect",description:"Detect agent integrations",category:"integration"},{name:"integrate:auto",description:"Auto-enable integrations with safe project scope policy",usage:"toolnet-memory integrate:auto [--all] [--scope global|project|both] [--project <path>] [--json]",category:"integration",examples:["toolnet-memory integrate:auto","toolnet-memory integrate:auto --project /path/to/toolnet-project","toolnet-memory integrate:auto --scope global","toolnet-memory integrate:auto --scope both --project /path/to/project"]},{name:"integrate:agy",description:"Install Agy hooks",category:"integration"},{name:"integrate:codex",description:"Install Codex integration",category:"integration"},{name:"integrate:opencode",description:"Install OpenCode plugin",category:"integration"},{name:"integrate:claude",description:"Install Claude Code integration",category:"integration"},{name:"integrate:kiro",description:"Install Kiro CLI integration",usage:"toolnet-memory integrate:kiro [--status] [--json]",category:"integration"},{name:"integrate:cursor",description:"Install Cursor CLI integration",usage:"toolnet-memory integrate:cursor [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:cursor --scope global","toolnet-memory integrate:cursor --scope project --project /path/to/project","toolnet-memory integrate:cursor --scope both --project /path/to/project"]},{name:"integrate:copilot",description:"Install GitHub Copilot CLI integration",usage:"toolnet-memory integrate:copilot [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:copilot --scope global","toolnet-memory integrate:copilot --scope project --project /path/to/project","toolnet-memory integrate:copilot --scope both --project /path/to/project"]},{name:"integrate:grok",description:"Install Grok Build integration",usage:"toolnet-memory integrate:grok [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:grok --scope global","toolnet-memory integrate:grok --scope project --project /path/to/project","toolnet-memory integrate:grok --scope both --project /path/to/project"]},{name:"integrate:toolnet-cli",description:"Install ToolNet CLI MCP integration",usage:"toolnet-memory integrate:toolnet-cli [--status] [--json] [--force]",category:"integration",examples:["toolnet-memory integrate:toolnet-cli","toolnet-memory integrate:toolnet-cli --status"]},{name:"integrate:kilo",description:"Install Kilo CLI MCP integration",usage:"toolnet-memory integrate:kilo [--status] [--json] [--force]",category:"integration",examples:["toolnet-memory integrate:kilo","toolnet-memory integrate:kilo --status"]},{name:"integrate:all",description:"Auto-enable all detected integrations",usage:"toolnet-memory integrate:all [--json]",category:"integration"},{name:"integrate:status",description:"Show unified Cursor/Copilot/Grok scoped integration status",usage:"toolnet-memory integrate:status [--scope global|project|both] [--project <path>] [--agent cursor|copilot|grok] [--json]",category:"integration",examples:["toolnet-memory integrate:status --scope global","toolnet-memory integrate:status --scope both --project /path/to/project","toolnet-memory integrate:status --scope both --project /path/to/project --agent cursor"]},{name:"session:agy-sync",description:"Sync Agy session",category:"session"},{name:"session:agy-recover",description:"Recover Agy sessions",category:"session"},{name:"session:agy-hook",description:"Agy session hook",category:"session",hidden:!0},{name:"session:codex-sync",description:"Sync Codex session",category:"session"},{name:"session:codex-recover",description:"Recover Codex sessions",category:"session"},{name:"session:codex-notify",description:"Codex notification hook",category:"session",hidden:!0},{name:"session:codex-context",description:"Codex context hook",category:"session",hidden:!0},{name:"session:opencode-sync",description:"Sync OpenCode session",category:"session"},{name:"session:opencode-recover",description:"Recover OpenCode sessions",category:"session"},{name:"session:claude-hook",description:"Claude session hook",category:"session",hidden:!0},{name:"session:kiro-hook",description:"Kiro lifecycle hook",category:"session",hidden:!0},{name:"session:cursor-hook",description:"Cursor lifecycle hook",category:"session",hidden:!0},{name:"session:copilot-hook",description:"Copilot lifecycle hook",category:"session",hidden:!0},{name:"session:grok-hook",description:"Grok lifecycle hook",category:"session",hidden:!0},{name:"memory:review",description:"Review memory entries",category:"session"},{name:"memory:reconcile",description:"Reconcile memory state",category:"session"},{name:"guard:check",description:"Check project rules",category:"guard"},{name:"guard:explain",description:"Show rules and evidence",category:"guard"},{name:"guard:json",description:"Output guard result as JSON",category:"guard",hidden:!0},{name:"project:manual-init",description:"Initialize project manual",category:"project"},{name:"project:manual-show",description:"Show project manual",category:"project"},{name:"project:manual-sync",description:"Sync project manual",category:"project"},{name:"snapshot:list",description:"List snapshots",category:"snapshot"},{name:"snapshot:create",description:"Create snapshot",category:"snapshot"},{name:"snapshot:restore",description:"Restore snapshot",category:"snapshot"},{name:"recover",description:"Recover latest snapshot",category:"snapshot"},{name:"service",description:"Run daemon in foreground",category:"service"},{name:"service:install",description:"Install/start daemon",category:"service"},{name:"service:start",description:"Start daemon",category:"service"},{name:"service:stop",description:"Stop daemon",category:"service"},{name:"service:restart",description:"Restart daemon",category:"service"},{name:"service:status",description:"Show daemon status",category:"service"},{name:"service:remove",description:"Remove daemon",category:"service"},{name:"mcp",description:"Run MCP server",category:"advanced"},{name:"api",description:"Run API server",category:"advanced"},{name:"run",description:"Run ToolNet runtime",category:"advanced",hidden:!0},{name:"production:certify",description:"Verify production runtime",category:"advanced"},{name:"certify:continuity",description:"Certify work continuity",category:"advanced"}];function x(o){return{tty:o.tty,noColor:o.noColor}}function b(o){let e=[],n=o.version??"0.0.0",t=x(o);e.push(""),e.push(g("ToolNet Memory",n,t)),e.push(" Persistent memory & code intelligence for AI coding agents"),e.push(""),e.push(a("USAGE",t)),e.push(" toolnet-memory <command> [options]"),e.push("");let i=[{key:"core",title:"GET STARTED"},{key:"memory",title:"MEMORY"},{key:"code",title:"CODE"},{key:"system",title:"SYSTEM"}];for(let{key:s,title:d}of i){let c=u.filter(r=>r.category===s&&!r.hidden);if(c.length===0)continue;e.push(a(d,t));let y=Math.max(...c.map(r=>r.name.length));for(let r of c)e.push(l(r.name,r.description,y,t));e.push("")}return e.push(a("MORE",t)),e.push(l("help --all","Show all advanced commands",15,t)),e.push(l("help <command>","Show command details",15,t)),e.push(""),e.join(`
|
|
2
|
+
`)}function S(o){let e=[],n=o.version??"0.0.0",t=x(o);e.push(""),e.push(g("ToolNet Memory",n,t)),e.push(" Persistent memory & code intelligence for AI coding agents"),e.push(""),e.push(a("USAGE",t)),e.push(" toolnet-memory <command> [options]"),e.push("");let i=[{key:"core",title:"PROJECT SETUP"},{key:"memory",title:"MEMORY"},{key:"code",title:"CODE INTELLIGENCE"},{key:"system",title:"SYSTEM"},{key:"context",title:"CONTEXT & MEMORY"},{key:"work",title:"WORK CONTINUITY"},{key:"integration",title:"AGENT INTEGRATIONS"},{key:"session",title:"SESSIONS"},{key:"guard",title:"GUARD"},{key:"project",title:"PROJECT MANUAL"},{key:"snapshot",title:"SNAPSHOTS & RECOVERY"},{key:"service",title:"BACKGROUND SERVICE"},{key:"advanced",title:"DEVELOPER / PRODUCTION"}];for(let{key:s,title:d}of i){let c=u.filter(r=>r.category===s&&!r.hidden);if(c.length===0)continue;e.push(a(d,t));let y=Math.max(...c.map(r=>r.name.length));for(let r of c)e.push(l(r.name,r.description,y,t));e.push("")}return e.join(`
|
|
3
|
+
`)}function j(o,e){let n=u.find(s=>s.name===o||s.aliases?.includes(o));if(!n)return null;let t=[],i=x(e);if(t.push(""),t.push(g(n.name,void 0,i)),t.push(""),t.push(n.description),t.push(""),n.usage&&(t.push(a("USAGE",i)),t.push(` ${n.usage}`),t.push("")),n.aliases&&n.aliases.length>0){t.push(a("ALIASES",i));for(let s of n.aliases)t.push(` ${s}`);t.push("")}if(n.pipeline&&n.pipeline.length>0){t.push(a("PIPELINE",i));for(let s of n.pipeline)t.push(` ${s}`);t.push("")}if(n.examples&&n.examples.length>0){t.push(a("EXAMPLES",i));for(let s of n.examples)t.push(` ${s}`);t.push("")}return t.join(`
|
|
4
|
+
`)}function v(o){return u.flatMap(t=>[t.name,...t.aliases??[]]).filter(t=>t===o?!1:!!(t.startsWith(o)||o.length>=3&&t.includes(o))).slice(0,3)}function P(){let o=M(L(import.meta.url)),e=[w(o,"../package.json"),w(o,"../../package.json")];for(let n of e)try{let t=JSON.parse(G(n,"utf8"));if(t.version)return t.version}catch{}return process.env.npm_package_version??"unknown"}var p=process.argv.slice(2),C={version:P(),tty:!!process.stdout.isTTY};function E(o){let e=v(o);if(console.error(""),console.error(`\u2715 Unknown command: ${o}`),e.length>0){console.error(""),console.error(" Did you mean:");for(let n of e)console.error(` ${n}`)}console.error(""),console.error(" Run `toolnet-memory help` to see available commands."),console.error("")}if(p[0]==="--unknown")E(p[1]??""),process.exitCode=1;else if(p[0]==="--all")console.log(S(C));else if(p[0]){let o=j(p[0],C);o?console.log(o):(E(p[0]),process.exitCode=1)}else console.log(b(C));
|
package/bundle/impact.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import"dotenv/config";import{existsSync as
|
|
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
|
|
3
|
-
`,{encoding:"utf8",mode:384}),Fe(s,r)}function S(n,e){return{id:n.id,name:n.name,remote:n.remote,rootPath:e,createdAt:n.createdAt,updatedAt:n.updatedAt,graphVersion:n.graphVersion,memoryVersion:n.memoryVersion,metadata:n.metadata}}function U(n){return{version:1,scheme:w,canonicalRemote:n.canonicalRemote,fingerprint:n.fingerprint,repositoryName:n.repositoryName}}function ze(n){let e=n.metadata?.toolnetIdentity;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return typeof t.fingerprint=="string"?t.fingerprint:null}var _=class{adopt(e,t){let r=W(b(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(oe(r)){let a=I(x(r));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return S(a,r)}let s=new Date().toISOString(),o={...t.metadata};t.gitIdentity&&(o.toolnetIdentity=U(t.gitIdentity));let i={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:r,createdAt:t.createdAt??s,updatedAt:s,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(o).length?o:void 0};return j(r,i),S(i,r)}recordGitIdentity(e,t,r={}){let s=this.requireExisting(e),o=x(s.rootPath),i=I(o),a=ze(i);if(a&&a!==t.fingerprint&&!r.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${a}`,`current=${t.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let c=i.metadata?.toolnetIdentity;return c&&typeof c=="object"&&!Array.isArray(c)&&c.fingerprint===t.fingerprint||(i.metadata={...i.metadata,toolnetIdentity:U(t)},i.updatedAt=new Date().toISOString(),j(s.rootPath,i)),S(i,s.rootPath)}findExisting(e=process.cwd()){let t=b(e),r=W(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>L(v(r,c))),i=re(t,o?r:void 0);if(!i)return null;let a=I(x(i));return S(a,i)}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=b(e),r=W(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(g=>L(v(r,g))),i=re(t,o?r:void 0);if(i){let g=x(i),f=I(g);return f.rootPath!==i&&(f.rootPath=i,f.updatedAt=new Date().toISOString(),j(i,f)),S(f,i)}let a=new Date().toISOString(),c=$e(r),l=te(r),p={version:1,id:l?ee(l.canonicalRemote):Ke(r),name:c,remote:l?.repositoryName??c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:l?{toolnetIdentity:U(l)}:void 0};return j(r,p),S(p,r)}};var Be=[{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"}],He=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function ie(n){return n.normalize("NFKC").trim().toLowerCase()}function We(n){if(n.length===0)return 0;let e=new Map;for(let r of n)e.set(r,(e.get(r)??0)+1);let t=0;for(let r of e.values()){let s=r/n.length;t-=s*Math.log2(s)}return t}function Ue(n){return/^[a-f0-9]{32}$/iu.test(n)||/^[a-f0-9]{40}$/iu.test(n)||/^[a-f0-9]{64}$/iu.test(n)}function Ve(n,e,t){let r=n.slice(Math.max(0,e-48),e),s=n.slice(t,Math.min(n.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${s}`)}function Ye(n,e){return n.start<e.end&&e.start<n.end}function ae(n){return n.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var O=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let r=ie(t);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let o of Be){let i=new RegExp(o.regex.source,o.regex.flags);for(let a of e.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:o.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:o.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let r=ae(t),s=[];for(let o of r)s.some(i=>Ye(i,o))||s.push(o);return ae(s)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=ie(e);return He.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let s of e.matchAll(r)){if(s.index===void 0||!s[0])continue;let o=s[0];this.allowed(o)||Ue(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||Ve(e,s.index,s.index+o.length)&&(We(o)<3.7||t.push({type:"high_entropy_secret",value:o,start:s.index,end:s.index+o.length,confidence:"heuristic"}))}return t}};var R=class{scanner;constructor(e={}){this.scanner=new O(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let r=e,s=[...t].sort((i,a)=>a.start-i.start),o=new Set;for(let i of s)o.add(i.type),r=r.slice(0,i.start)+`[REDACTED:${i.type}]`+r.slice(i.end);return{text:r,redacted:t.length,secretTypes:[...o].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[r,s]of Object.entries(e)){let o=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")){t[r]="[REDACTED]";continue}t[r]=this.sanitizeValue(s)}return t}return e}};var Xt=new R;import{homedir as yt}from"node:os";import{join as St}from"node:path";import{DeleteObjectCommand as qe,GetObjectCommand as Je,HeadObjectCommand as Qe,ListObjectsV2Command as Ze,PutObjectCommand as Xe,S3Client as et}from"@aws-sdk/client-s3";import{getSignedUrl as tt}from"@aws-sdk/s3-request-presigner";var F=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new et({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,r="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Xe({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await tt(this.client,new Je({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 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 qe({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new Ze({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};import{access as ce,mkdir as rt,readFile as nt,readdir as st,rm as ot,stat as le,writeFile as it}from"node:fs/promises";import{dirname as at,join as ct,relative as de,resolve as lt}from"node:path";var k=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return lt(this.root,t)}async put(e,t){let r=this.path(e);await rt(at(r),{recursive:!0}),await it(r,t)}async get(e){try{return await nt(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 ce(this.path(e)),!0}catch{return!1}}async delete(e){await ot(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await ce(t)}catch{return r}let s=async i=>{let a=await st(i,{withFileTypes:!0});for(let c of a){let l=ct(i,c.name);if(c.isDirectory()){await s(l);continue}let p=await le(l);r.push({key:de(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await le(t);return o.isDirectory()?await s(t):r.push({key:de(this.root,t),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as dt,GetObjectCommand as pt,HeadObjectCommand as ut,ListObjectsV2Command as mt,PutObjectCommand as ft,S3Client as gt}from"@aws-sdk/client-s3";import{getSignedUrl as ht}from"@aws-sdk/s3-request-presigner";var P=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new gt({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,r="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new ft({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await ht(this.client,new pt({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 ut({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 dt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new mt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};function V(n,e){return console.warn(e),new k(n)}function pe(n){let e=n.localRoot??St(yt(),".toolnet-memory","storage");if(n.provider==="r2"){let t=n.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new P({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(n.provider==="s3"){let t=n.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new P({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] S3 credentials missing. Using local fallback.")}if(n.provider==="huggingface"){let t=n.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new F({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new k(e)}var A=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function bt(n){return new Promise(e=>setTimeout(e,n))}async function ue(n,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=t;i++)try{return await n()}catch(a){if(o=a,i>=t)break;let c=Math.min(s,r*2**(i-1)),l=Math.floor(Math.random()*Math.max(1,c*.2));await bt(c+l)}throw o}var xt=new Set(["put","get","getText","delete","list"]);function me(n,e={}){return new Proxy(n,{get(t,r){let s=Reflect.get(t,r,t);return typeof s!="function"?s:xt.has(r)?(...o)=>ue(()=>Promise.resolve(s.apply(t,o)),e):s.bind(t)}})}function fe(n){let e=n.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 ge(n){let e=n.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var D=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=fe(s??r),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),r=t,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(o,null,2)+`
|
|
4
|
-
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=
|
|
1
|
+
import"dotenv/config";import{existsSync as Ye,readFileSync as Ve}from"node:fs";import{homedir as qe}from"node:os";import{join as Je}from"node:path";function Qe(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 Ze(){let r=process.env.TOOLNET_GLOBAL_ENV??Je(qe(),".config","toolnet-memory",".env");if(!Ye(r))return;let e=Ve(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 s=n.indexOf("=");if(s<=0)continue;let o=n.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=Qe(n.slice(s+1)))}}Ze();function R(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function v(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function ce(){return{memory:{autoCapture:R(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:R(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:R(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:R(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:v(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:v(process.env.MEMORY_RERANK_TOP,10),finalContext:v(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:v(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:R(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:v(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ot}from"node:crypto";import{existsSync as G,mkdirSync as it,readFileSync as at,renameSync as ct,writeFileSync as lt}from"node:fs";import{basename as dt,dirname as K,join as k,parse as he,resolve as E}from"node:path";import{createHash as pe}from"node:crypto";import{spawnSync as Xe}from"node:child_process";var P="git-remote-v1",et=new Set(["github.com","gitlab.com","bitbucket.org"]);function ue(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:(et.has(r)&&(t=t.toLowerCase()),t)}function tt(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",s=e.port&&!n?`${t}:${e.port}`:t,o=ue(t,e.pathname);return o?`${s}/${o}`:null}function rt(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=ue(t,e[2]??"");return n?`${t}/${n}`:null}function le(r){let e=r.trim();return e?e.includes("://")?tt(e):rt(e):null}function nt(r){return pe("sha256").update(`${P}:${r}`).digest("hex")}function fe(r){return pe("sha256").update(`toolnet-project:${P}:${r}`).digest("hex").slice(0,16)}function st(r){return r.split("/").filter(Boolean).at(-1)?.trim()||null}function Z(r,e){let t=Xe("git",["-C",r,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function de(r,e){let t=st(r);return t?{scheme:P,canonicalRemote:r,fingerprint:nt(r),repositoryName:t,source:e}:null}function me(r){let e=Z(r,["remote","get-url","origin"]);if(e){let s=le(e);if(s)return de(s,"origin")}let t=Z(r,["remote"]);if(!t)return null;let n=new Set;for(let s of t.split(/\r?\n/u).map(o=>o.trim()).filter(Boolean)){let o=Z(r,["remote","get-url",s]);if(!o)continue;let i=le(o);i&&n.add(i)}return n.size!==1?null:de([...n][0],"unique-remote")}var ye=".toolnet",pt="project.json";function ut(r){return ot("sha256").update(r).digest("hex").slice(0,16)}function w(r){return k(r,ye,pt)}function Se(r){return G(w(r))}function ge(r,e){let t=E(r),n=he(t).root;for(;;){if(Se(t))return t;if(t===n||e&&t===E(e))break;let s=K(t);if(s===t)break;t=s}return null}function X(r){let e=E(r),t=he(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(o=>G(k(e,o))))return e;if(e===t)break;let s=K(e);if(s===e)break;e=s}return E(r)}function D(r){let e;try{e=JSON.parse(at(r,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${r}: ${s instanceof Error?s.message:String(s)}`)}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:K(K(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 $(r,e){let t=k(r,ye);it(t,{recursive:!0});let n=w(r),s=`${n}.tmp-${process.pid}`;lt(s,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),ct(s,n)}function x(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 ee(r){return{version:1,scheme:P,canonicalRemote:r.canonicalRemote,fingerprint:r.fingerprint,repositoryName:r.repositoryName}}function ft(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 B=class{adopt(e,t){let n=X(E(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(Se(n)){let a=D(w(n));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return x(a,n)}let s=new Date().toISOString(),o={...t.metadata};t.gitIdentity&&(o.toolnetIdentity=ee(t.gitIdentity));let i={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:n,createdAt:t.createdAt??s,updatedAt:s,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(o).length?o:void 0};return $(n,i),x(i,n)}recordGitIdentity(e,t,n={}){let s=this.requireExisting(e),o=w(s.rootPath),i=D(o),a=ft(i);if(a&&a!==t.fingerprint&&!n.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${a}`,`current=${t.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let l=i.metadata?.toolnetIdentity;return l&&typeof l=="object"&&!Array.isArray(l)&&l.fingerprint===t.fingerprint||(i.metadata={...i.metadata,toolnetIdentity:ee(t)},i.updatedAt=new Date().toISOString(),$(s.rootPath,i)),x(i,s.rootPath)}findExisting(e=process.cwd()){let t=E(e),n=X(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>G(k(n,l))),i=ge(t,o?n:void 0);if(!i)return null;let a=D(w(i));return x(a,i)}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=E(e),n=X(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(g=>G(k(n,g))),i=ge(t,o?n:void 0);if(i){let g=w(i),h=D(g);return h.rootPath!==i&&(h.rootPath=i,h.updatedAt=new Date().toISOString(),$(i,h)),x(h,i)}let a=new Date().toISOString(),l=dt(n),c=me(n),p={version:1,id:c?fe(c.canonicalRemote):ut(n),name:l,remote:c?.repositoryName??l,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:c?{toolnetIdentity:ee(c)}:void 0};return $(n,p),x(p,n)}};var mt=[{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"}],gt=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function be(r){return r.normalize("NFKC").trim().toLowerCase()}function ht(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 s=n/r.length;t-=s*Math.log2(s)}return t}function yt(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function St(r,e,t){let n=r.slice(Math.max(0,e-48),e),s=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} ${s}`)}function bt(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 z=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=be(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let o of mt){let i=new RegExp(o.regex.source,o.regex.flags);for(let a of e.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:o.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:o.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let n=xe(t),s=[];for(let o of n)s.some(i=>bt(i,o))||s.push(o);return xe(s)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=be(e);return gt.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],n=/[A-Za-z0-9_+/=-]{32,160}/g;for(let s of e.matchAll(n)){if(s.index===void 0||!s[0])continue;let o=s[0];this.allowed(o)||yt(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||St(e,s.index,s.index+o.length)&&(ht(o)<3.7||t.push({type:"high_entropy_secret",value:o,start:s.index,end:s.index+o.length,confidence:"heuristic"}))}return t}};var T=class{scanner;constructor(e={}){this.scanner=new z(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let n=e,s=[...t].sort((i,a)=>a.start-i.start),o=new Set;for(let i of s)o.add(i.type),n=n.slice(0,i.start)+`[REDACTED:${i.type}]`+n.slice(i.end);return{text:n,redacted:t.length,secretTypes:[...o].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,s]of Object.entries(e)){let o=n.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")){t[n]="[REDACTED]";continue}t[n]=this.sanitizeValue(s)}return t}return e}};var Dr=new T;import{homedir as Jt}from"node:os";import{join as Qt}from"node:path";import{DeleteObjectCommand as xt,GetObjectCommand as Et,HeadObjectCommand as Ct,ListObjectsV2Command as wt,PutObjectCommand as Rt,S3Client as vt}from"@aws-sdk/client-s3";import{getSignedUrl as Pt}from"@aws-sdk/s3-request-presigner";var U=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new vt({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 s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Rt({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let t=await Pt(this.client,new Et({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 Ct({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 xt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let s=await this.client.send(new wt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let o of s.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return t}};import{access as Ee,mkdir as kt,readFile as Tt,readdir as At,rm as Mt,stat as Ce,writeFile as It}from"node:fs/promises";import{dirname as Nt,join as Lt,relative as we,resolve as _t}from"node:path";var A=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return _t(this.root,t)}async put(e,t){let n=this.path(e);await kt(Nt(n),{recursive:!0}),await It(n,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 Ee(this.path(e)),!0}catch{return!1}}async delete(e){await Mt(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await Ee(t)}catch{return n}let s=async i=>{let a=await At(i,{withFileTypes:!0});for(let l of a){let c=Lt(i,l.name);if(l.isDirectory()){await s(c);continue}let p=await Ce(c);n.push({key:we(this.root,c),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await Ce(t);return o.isDirectory()?await s(t):n.push({key:we(this.root,t),size:o.size,updatedAt:o.mtime.toISOString()}),n}};import{DeleteObjectCommand as Ot,GetObjectCommand as jt,HeadObjectCommand as Ft,ListObjectsV2Command as Dt,PutObjectCommand as $t,S3Client as Gt}from"@aws-sdk/client-s3";import{getSignedUrl as Kt}from"@aws-sdk/s3-request-presigner";var M=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Gt({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 s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new $t({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let t=await Kt(this.client,new jt({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 Ft({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 Ot({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let s=await this.client.send(new Dt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let o of s.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return t}};import{createCipheriv as Bt,createDecipheriv as zt,createHash as Ut,randomBytes as Ht,timingSafeEqual as Wt}from"node:crypto";import{readFileSync as Yt}from"node:fs";var C=Buffer.from("TNMEME01","ascii"),ve=1,I=8,N=12,te=16,Pe=C.length+1+I+N+te,Vt="toolnet-memory:remote-encryption:v1:",ke="aes-256-gcm",re=32,u=class extends Error{constructor(t,n){super(n);this.code=t;this.name="RemoteEncryptionError"}code};function qt(r){return r?["1","true","yes","on","enabled"].includes(r.trim().toLowerCase()):!1}function ne(r=process.env){return qt(r.TOOLNET_REMOTE_ENCRYPTION)}function Re(r){let e=r.trim();if(!e)throw new u("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 u("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 u("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!==re)throw new u("REMOTE_ENCRYPTION_KEY_INVALID_LENGTH",`Remote encryption key must decode to exactly ${re} bytes.`);return t}function Te(r=process.env){let e=r.TOOLNET_REMOTE_ENCRYPTION_KEY?.trim(),t=r.TOOLNET_REMOTE_ENCRYPTION_KEY_FILE?.trim();if(e&&t)throw new u("REMOTE_ENCRYPTION_KEY_AMBIGUOUS","Configure either TOOLNET_REMOTE_ENCRYPTION_KEY or TOOLNET_REMOTE_ENCRYPTION_KEY_FILE, not both.");if(e)return Re(e);if(t){let n;try{n=Yt(t,"utf8")}catch(s){throw new u("REMOTE_ENCRYPTION_KEY_FILE_READ_FAILED",[`Unable to read remote encryption key file: ${t}.`,s instanceof Error?s.message:String(s)].join(" "))}return Re(n)}}function Ae(r){return Ut("sha256").update(r).digest().subarray(0,I)}function Me(r){return Buffer.from(`${Vt}${r}`,"utf8")}function se(r){return r.byteLength<C.length?!1:Buffer.from(r).subarray(0,C.length).equals(C)}function Ie(r,e,t){if(t.byteLength!==re)throw new u("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),s=Ht(N),o=Bt(ke,t,s);o.setAAD(Me(r));let i=Buffer.concat([o.update(n),o.final()]),a=o.getAuthTag(),l=Buffer.alloc(Pe),c=0;return C.copy(l,c),c+=C.length,l.writeUInt8(ve,c),c+=1,Ae(t).copy(l,c),c+=I,s.copy(l,c),c+=N,a.copy(l,c),Buffer.concat([l,i])}function Ne(r,e,t){let n=Buffer.from(e);if(!se(n))throw new u("REMOTE_ENCRYPTION_ENVELOPE_REQUIRED","Payload is not a ToolNet encrypted remote object.");if(n.length<Pe)throw new u("REMOTE_ENCRYPTION_ENVELOPE_TRUNCATED","Encrypted remote payload is truncated.");let s=C.length,o=n.readUInt8(s);if(s+=1,o!==ve)throw new u("REMOTE_ENCRYPTION_VERSION_UNSUPPORTED",`Unsupported remote encryption envelope version: ${o}.`);let i=n.subarray(s,s+I);s+=I;let a=Ae(t);if(!Wt(i,a))throw new u("REMOTE_ENCRYPTION_KEY_MISMATCH","Configured remote encryption key does not match this encrypted object.");let l=n.subarray(s,s+N);s+=N;let c=n.subarray(s,s+te);s+=te;let p=n.subarray(s),g=zt(ke,t,l);g.setAAD(Me(r)),g.setAuthTag(c);try{return Buffer.concat([g.update(p),g.final()])}catch{throw new u("REMOTE_ENCRYPTION_AUTH_FAILED","Encrypted remote object failed AES-GCM authentication.")}}var oe=class{constructor(e,t){this.inner=e;this.options=t;if(this.name=e.name,t.enabled&&!t.key)throw new u("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 s=this.options.key;if(!s)throw new u("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote encryption key is unavailable.");let o=Ie(e,t,s);await this.inner.put(e,o,"application/octet-stream")}async get(e){let t=await this.inner.get(e);if(!t)return null;if(!se(t))return t;if(!this.options.enabled)throw new u("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 u("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote object is encrypted but no decryption key is configured.");return Ne(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 Le(r,e=process.env){if(r.name==="local")return ne(e)&&console.warn("[storage] Remote encryption requested but active storage provider is local; local data remains unchanged."),r;let t=ne(e),n=t?Te(e):void 0;return new oe(r,{enabled:t,key:n})}function L(r){return Le(r)}function ie(r,e){return console.warn(e),L(new A(r))}function _e(r){let e=r.localRoot??Qt(Jt(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?L(new M({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):ie(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?L(new M({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):ie(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?L(new U({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):ie(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return L(new A(e))}var _=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function Zt(r){return new Promise(e=>setTimeout(e,r))}async function Oe(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=t;i++)try{return await r()}catch(a){if(o=a,i>=t)break;let l=Math.min(s,n*2**(i-1)),c=Math.floor(Math.random()*Math.max(1,l*.2));await Zt(l+c)}throw o}var Xt=new Set(["put","get","getText","delete","list"]);function je(r,e={}){return new Proxy(r,{get(t,n){let s=Reflect.get(t,n,t);return typeof s!="function"?s:Xt.has(n)?(...o)=>Oe(()=>Promise.resolve(s.apply(t,o)),e):s.bind(t)}})}function Fe(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 s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var H=class{constructor(e,t,n,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=Fe(s??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,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(n=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:t};await this.provider.put(e,JSON.stringify(o,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))}};var js=2*1024*1024;var O=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(n=>n.projectId===e&&(n.name===t||n.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 n of e)this.addSymbol(n);for(let n of t)this.addEdge(n)}clearProject(e){for(let[t,n]of this.symbols)n.projectId===e&&this.symbols.delete(t);for(let[t,n]of this.edges)n.projectId===e&&this.edges.delete(t)}};var S={supported:!0,structural:!0,lexicalSearch:!0,engine:"typescript-compiler-api",lexicalEngine:"file-chunk-fts5-bm25"},j={supported:!1,structural:!1,lexicalSearch:!0,engine:"unsupported",lexicalEngine:"file-chunk-fts5-bm25"},W=[{language:"typescript",extensions:[".ts"],...S},{language:"tsx",extensions:[".tsx"],...S},{language:"javascript",extensions:[".js"],...S},{language:"jsx",extensions:[".jsx"],...S},{language:"mts",extensions:[".mts"],...S},{language:"cts",extensions:[".cts"],...S},{language:"mjs",extensions:[".mjs"],...S},{language:"cjs",extensions:[".cjs"],...S},{language:"python",extensions:[".py"],...j,lspServer:"pyright-langserver"},{language:"go",extensions:[".go"],...j,lspServer:"gopls"},{language:"rust",extensions:[".rs"],...j,lspServer:"rust-analyzer"},{language:"c",extensions:[".c",".h"],...j,lspServer:"clangd"},{language:"cpp",extensions:[".cc",".cpp",".cxx",".hpp",".hh"],...j,lspServer:"clangd"}];import*as f from"typescript";function nr(r,e){return e.ranges.length===0?!0:typeof r.startLine!="number"||typeof r.endLine!="number"?!1:e.ranges.some(t=>r.startLine<=t.endLine&&r.endLine>=t.startLine)}var Y=class{constructor(e){this.graph=e}graph;map(e,t){let n=this.graph.allSymbols(e),s=[];for(let o of t){let i=n.filter(c=>c.filePath===o.filePath),l=i.filter(c=>c.type!=="file").filter(c=>nr(c,o));if(l.length===0){let c=i.find(p=>p.type==="file");c&&s.push({symbol:c,fileStatus:o.status,direct:!0});continue}for(let c of l)s.push({symbol:c,fileStatus:o.status,direct:!0})}return s}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var sr={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function or(r){return r>=30?"CRITICAL":r>=16?"HIGH":r>=6?"MEDIUM":"LOW"}function Ge(r){let e=r.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var V=class{constructor(e){this.graph=e}graph;analyze(e,t,n=4){let s=this.graph.allEdges(e),o=new Map,i=0;for(let p of t){p.fileStatus==="deleted"?i+=8:p.fileStatus==="renamed"?i+=5:i+=2,p.symbol.type==="interface"&&(i+=5),p.symbol.type==="class"&&(i+=3);let g=new Set([p.symbol.id]),h=[{id:p.symbol.id,depth:0}];for(;h.length;){let J=h.shift();if(J.depth>=n)continue;let Ue=s.filter(y=>y.to===J.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(y.type));for(let y of Ue){if(g.has(y.from))continue;g.add(y.from);let F=this.graph.getSymbol(y.from);if(!F)continue;let Q=J.depth+1,He=`${p.symbol.id}:${F.id}`;o.set(He,{symbol:F,relation:y.type,depth:Q,sourceSymbolId:p.symbol.id});let We=sr[y.type]??1;i+=Math.max(1,We-(Q-1)),h.push({id:F.id,depth:Q})}}}let a=[...o.values()].sort((p,g)=>p.depth-g.depth),l=[...new Set(a.map(p=>p.symbol.filePath))],c=l.filter(Ge);return c.length===0&&c.push(...l.filter(p=>!Ge(p)).slice(0,10)),{risk:or(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:l,suggestedTests:c}}};import{execFile as ir}from"node:child_process";import{promisify as ar}from"node:util";var ae=ar(ir);function cr(r){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let n of r.matchAll(t)){let s=Number(n[1]),o=Number(n[2]??1);e.push({startLine:s,endLine:Math.max(s,s+o-1)})}return e}function lr(r){return r.startsWith("A")?"added":r.startsWith("D")?"deleted":r.startsWith("R")?"renamed":"modified"}async function Ke(r){let e="";try{e=(await ae("git",["diff","HEAD","--name-status","--no-renames"],{cwd:r,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let n of e.split(/\r?\n/).filter(Boolean)){let[s,...o]=n.split(" "),i=o.at(-1);if(!i)continue;let a="";try{a=(await ae("git",["diff","HEAD","--unified=0","--",i],{cwd:r,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:lr(s),ranges:cr(a)})}try{let n=await ae("git",["ls-files","--others","--exclude-standard"],{cwd:r});for(let s of n.stdout.split(/\r?\n/).filter(Boolean))t.some(o=>o.filePath===s)||t.push({filePath:s,status:"added",ranges:[]})}catch{}return t}var q=class{constructor(e){this.graph=e;this.mapper=new Y(e),this.blast=new V(e)}graph;mapper;blast;async analyzeGitDiff(e,t,n={}){let s=await Ke(t),o=this.mapper.map(e,s),i=this.blast.analyze(e,o,n.maxDepth??4);return{mode:"git_diff",changes:s,...i}}analyzeFile(e,t,n={}){let s=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,s,n.maxDepth??4)}}};import*as b from"typescript";import{DatabaseSync as ti}from"node:sqlite";import*as m from"typescript";import*as d from"typescript";var Ai=new Set([d.SyntaxKind.EqualsToken,d.SyntaxKind.PlusEqualsToken,d.SyntaxKind.MinusEqualsToken,d.SyntaxKind.AsteriskEqualsToken,d.SyntaxKind.SlashEqualsToken,d.SyntaxKind.PercentEqualsToken,d.SyntaxKind.QuestionQuestionEqualsToken,d.SyntaxKind.AmpersandAmpersandEqualsToken,d.SyntaxKind.BarBarEqualsToken]);import{spawnSync as ur}from"node:child_process";var fr=[{language:"python",command:"pyright-langserver"},{language:"go",command:"gopls"},{language:"rust",command:"rust-analyzer"},{language:"c",command:"clangd"},{language:"cpp",command:"clangd"}];function mr(r){return r.split(/\r?\n/u).map(t=>t.trim()).find(Boolean)||void 0}function gr(r,e){let t=ur(e,["--version"],{encoding:"utf8",timeout:2e3,windowsHide:!0}),n=!t.error&&t.status===0,s=[t.stdout??"",t.stderr??""].join(`
|
|
5
|
+
`);return{language:r,command:e,installed:n,...n?{version:mr(s)}:{},mode:"external-optional",activeInStructuralGraph:!1}}function Be(){return fr.map(r=>gr(r.language,r.command))}var hr=process.argv.includes("--json"),ze=Be(),yr={structuralParser:{engine:"typescript-compiler-api",languages:W.filter(r=>r.structural).map(r=>r.language)},lexicalSearch:{engine:"sqlite-fts5-bm25",languages:W.filter(r=>r.lexicalSearch).map(r=>r.language)},lspFoundation:{mode:"detection-only",automaticDownload:!1,structuralGraphIntegration:!1,servers:ze}};if(hr)console.log(JSON.stringify(yr,null,2));else{console.log("ToolNet Code Intelligence Capabilities"),console.log(""),console.log("Structural parser: TypeScript Compiler API");for(let r of W)console.log([r.language.padEnd(12),r.structural?"structural=yes":"structural=no",r.lexicalSearch?"lexical=yes":"lexical=no",r.lspServer?`lsp=${r.lspServer}`:""].filter(Boolean).join(" "));console.log(""),console.log("LSP detection:");for(let r of ze)console.log([r.language.padEnd(12),r.command.padEnd(22),r.installed?"available":"not-installed"].join(" "))}async function Sr(){let r=ce(),e=new B().detect(),t=je(_e({provider:r.storage.provider,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),{attempts:3}),n=new H(t,e.id,e.name,e.remote??e.name),s=await new _(n).load(e.id);if(!s)throw new Error("Code graph missing");let o=new O;o.import(s.symbols,s.edges);let i=new q(o),a=process.argv[2],l=a?i.analyzeFile(e.id,a):await i.analyzeGitDiff(e.id,e.rootPath);console.log({risk:l.risk,riskScore:l.riskScore,changedSymbols:l.changedSymbols.map(c=>({symbol:c.symbol.qualifiedName,file:c.symbol.filePath,type:c.symbol.type})),impactedFiles:l.impactedFiles,suggestedTests:l.suggestedTests,impactedCount:l.impacted.length})}Sr().catch(r=>{console.error(r),process.exit(1)});
|