toolnet-memory 0.3.15 → 0.3.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +74 -0
- package/.release-target +1 -1
- package/README.md +316 -6
- package/bin/toolnet-memory +12 -0
- package/bundle/agy-hook.js +66 -66
- package/bundle/agy.js +56 -56
- package/bundle/api.js +15 -15
- package/bundle/audit.js +2 -0
- package/bundle/background-refresh.js +7 -7
- package/bundle/claude-hook.js +49 -49
- package/bundle/code-capabilities.js +2 -0
- package/bundle/codex-context.js +29 -29
- package/bundle/codex.js +71 -71
- package/bundle/context-runtime.js +39 -39
- package/bundle/context.js +15 -15
- package/bundle/copilot-hook.js +78 -78
- package/bundle/cursor-hook.js +78 -78
- package/bundle/docker-healthcheck.js +3 -0
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +22 -21
- 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 +56 -56
- package/bundle/handoff-refresh.js +10 -10
- package/bundle/help-cli.js +4 -4
- package/bundle/impact.js +5 -4
- package/bundle/incremental.js +5 -5
- package/bundle/init.js +36 -35
- package/bundle/kiro-hook.js +85 -85
- package/bundle/learner.js +8 -6
- package/bundle/mcp.js +19 -17
- package/bundle/memory-agent.js +6 -6
- package/bundle/memory-query.js +7 -7
- package/bundle/opencode.js +77 -77
- package/bundle/project-manual.js +7 -7
- package/bundle/public/index.html +51 -2
- package/bundle/recovery-certify.js +9 -9
- 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 +46 -46
- package/bundle/work-continuity.js +7 -7
- package/package.json +38 -2
- package/release-manifest.json +143 -4
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as f from"fs";import*as u from"path";import{existsSync as _,mkdirSync as te,readFileSync as O,renameSync as ne,writeFileSync as re}from"node:fs";import{dirname as oe,join as j}from"node:path";import{createHash as ee}from"node:crypto";function R(n){return ee("sha256").update(n).digest("hex")}function P(n){return j(n.rootPath,".toolnet","context","handoff.md")}function N(n){return j(n.rootPath,".toolnet","context","handoff.json")}function D(n,e){te(oe(n),{recursive:!0});let t=`${n}.tmp-${process.pid}-${Date.now()}`;re(t,e.endsWith(`
|
|
2
2
|
`)?e:`${e}
|
|
3
|
-
`,{encoding:"utf8",mode:384}),
|
|
4
|
-
`)}function
|
|
5
|
-
`).trim();if(!t)return null;let r={version:1,projectId:n.id,projectName:n.name,text:t,digest:
|
|
6
|
-
`)}function
|
|
7
|
-
`).trim(),r=2400,
|
|
3
|
+
`,{encoding:"utf8",mode:384}),ne(t,n)}function ie(n,e){D(n,`${JSON.stringify(e,null,2)}
|
|
4
|
+
`)}function F(n,e){let t=e.replace(/\r\n/g,`
|
|
5
|
+
`).trim();if(!t)return null;let r={version:1,projectId:n.id,projectName:n.name,text:t,digest:R(t),generatedAt:new Date().toISOString()};return D(P(n),t),ie(N(n),r),r}function $(n){let e=P(n);if(!_(e))return null;try{let t=O(e,"utf8").trim();if(!t)return null;let r=new Date(0).toISOString(),i=N(n);if(_(i))try{let o=JSON.parse(O(i,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:n.id,projectName:n.name,text:t,digest:R(t),generatedAt:r}}catch{return null}}function L(n){let e=u.resolve(n),t=u.parse(e).root;for(;e!==t;){let r=u.join(e,".toolnet");if(f.existsSync(r)&&f.statSync(r).isDirectory())return e;e=u.dirname(e)}return null}import{existsSync as le,readFileSync as fe}from"node:fs";import{join as pe}from"node:path";import{existsSync as se,mkdirSync as pt,readFileSync as ae,renameSync as mt,writeFileSync as gt}from"node:fs";import{dirname as ht,join as ce}from"node:path";function ue(n){return ce(n.rootPath,".toolnet","context","session-origin.json")}function de(n){let e=ue(n);if(!se(e))return null;try{let t=JSON.parse(ae(e,"utf8"));return t.version!==1||t.projectId!==n.id?null:t}catch{return null}}function K(n){let e=de(n);if(!e)return null;let t=["Previous session:",`- Agent: ${e.agent}`,`- Session: ${e.nativeSessionId}`];return e.currentRequest&&t.push(`- Current request: ${e.currentRequest}`),e.currentActivity&&t.push(`- Current activity: ${e.currentActivity}`),e.currentPhase&&t.push(`- Current phase: ${e.currentPhase}`),e.currentTask&&t.push(`- Current task: ${e.currentTask}`),e.lastTouchedFile&&t.push(`- Last touched file: ${e.lastTouchedFile}`),e.latestBlocker&&t.push(`- Blocker: ${e.latestBlocker}`),e.latestNextAction&&t.push(`- Next action: ${e.latestNextAction}`),e.latestDecision&&t.push(`- Important decision: ${e.latestDecision}`),t.join(`
|
|
6
|
+
`)}function me(n){let e=pe(n.rootPath,".toolnet","current.md");if(!le(e))return null;try{return fe(e,"utf8").trim()}catch{return null}}function ge(n,e){let t=e.replace(/\r\n/g,`
|
|
7
|
+
`).trim(),r=2400,i=t.length>r?`${t.slice(0,r)}
|
|
8
8
|
|
|
9
|
-
[Current work truncated for fast handoff]`:t,o=
|
|
10
|
-
`)}function
|
|
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
|
|
12
|
-
`,{encoding:"utf8",mode:384}),
|
|
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
|
+
`)}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 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 M,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 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 T(o,e){return f(o,m.dim,e)}function G(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?` ${T(`v${e}`,n)}`:"";return`${b(t.phaseDone,n)} ${o}${i}`}function a(o,e){return G(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]",category:"core"},{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","Semantic Code Index","Architecture Intelligence","Graph Analysis","3D Visualization Dataset"]},{name:"semantic",description:"Semantic code search",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
|
|
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}),Ce(n,r)}function G(s,e){return{id:s.id,name:s.name,remote:s.remote,rootPath:e,createdAt:s.createdAt,updatedAt:s.updatedAt,graphVersion:s.graphVersion,memoryVersion:s.memoryVersion,metadata:s.metadata}}var A=class{findExisting(e=process.cwd()){let t=y(e),r=U(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>R(x(r,d))),i=W(t,o?r:void 0);if(!i)return null;let a=H(M(i));return G(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=y(e),r=U(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>R(x(r,p))),i=W(t,o?r:void 0);if(i){let p=M(i),m=H(p);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),V(i,m)),G(m,i)}let a=new Date().toISOString(),d=we(r),l={version:1,id:ke(r),name:d,remote:d,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return V(r,l),G(l,r)}};var Re=[{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"}],Te=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function q(s){return s.normalize("NFKC").trim().toLowerCase()}function Me(s){if(s.length===0)return 0;let e=new Map;for(let r of s)e.set(r,(e.get(r)??0)+1);let t=0;for(let r of e.values()){let n=r/s.length;t-=n*Math.log2(n)}return t}function Ae(s){return/^[a-f0-9]{32}$/iu.test(s)||/^[a-f0-9]{40}$/iu.test(s)||/^[a-f0-9]{64}$/iu.test(s)}function je(s,e,t){let r=s.slice(Math.max(0,e-48),e),n=s.slice(t,Math.min(s.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${n}`)}function Ie(s,e){return s.start<e.end&&e.start<s.end}function Z(s){return s.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var j=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 Re){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=Z(t),n=[];for(let o of r)n.some(i=>Ie(i,o))||n.push(o);return Z(n)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=q(e);return Te.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let n of e.matchAll(r)){if(n.index===void 0||!n[0])continue;let o=n[0];this.allowed(o)||Ae(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||je(e,n.index,n.index+o.length)&&(Me(o)<3.7||t.push({type:"high_entropy_secret",value:o,start:n.index,end:n.index+o.length,confidence:"heuristic"}))}return t}};var C=class{scanner;constructor(e={}){this.scanner=new j(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let r=e,n=[...t].sort((i,a)=>a.start-i.start),o=new Set;for(let i of n)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,n]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(n)}return t}return e}};var Lt=new C;import{homedir as tt}from"node:os";import{join as rt}from"node:path";import{DeleteObjectCommand as Le,GetObjectCommand as Ne,HeadObjectCommand as Oe,ListObjectsV2Command as _e,PutObjectCommand as Fe,S3Client as De}from"@aws-sdk/client-s3";import{getSignedUrl as $e}from"@aws-sdk/s3-request-presigner";var I=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new De({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 n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Fe({Bucket:this.bucket,Key:e,Body:n,ContentType:r}))}async get(e){let t=await $e(this.client,new Ne({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 Oe({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 Le({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let n=await this.client.send(new _e({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of n.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=n.IsTruncated?n.NextContinuationToken:void 0}while(r);return t}};import{access as Q,mkdir as Ge,readFile as ze,readdir as Ke,rm as Be,stat as X,writeFile as We}from"node:fs/promises";import{dirname as Ue,join as He,relative as ee,resolve as Ve}from"node:path";var E=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Ve(this.root,t)}async put(e,t){let r=this.path(e);await Ge(Ue(r),{recursive:!0}),await We(r,t)}async get(e){try{return await ze(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 Q(this.path(e)),!0}catch{return!1}}async delete(e){await Be(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await Q(t)}catch{return r}let n=async i=>{let a=await Ke(i,{withFileTypes:!0});for(let d of a){let l=He(i,d.name);if(d.isDirectory()){await n(l);continue}let p=await X(l);r.push({key:ee(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await X(t);return o.isDirectory()?await n(t):r.push({key:ee(this.root,t),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Ye,GetObjectCommand as Je,HeadObjectCommand as qe,ListObjectsV2Command as Ze,PutObjectCommand as Qe,S3Client as Xe}from"@aws-sdk/client-s3";import{getSignedUrl as et}from"@aws-sdk/s3-request-presigner";var w=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Xe({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 n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Qe({Bucket:this.bucket,Key:e,Body:n,ContentType:r}))}async get(e){let t=await et(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(`${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 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 Ye({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let n=await this.client.send(new Ze({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of n.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=n.IsTruncated?n.NextContinuationToken:void 0}while(r);return t}};function z(s,e){return console.warn(e),new E(s)}function te(s){let e=s.localRoot??rt(tt(),".toolnet-memory","storage");if(s.provider==="r2"){let t=s.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new w({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):z(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(s.provider==="s3"){let t=s.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new w({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):z(e,"[storage] S3 credentials missing. Using local fallback.")}if(s.provider==="huggingface"){let t=s.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new I({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):z(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new E(e)}var v=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 st(s){return new Promise(e=>setTimeout(e,s))}async function re(s,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,n=e.maxDelayMs??2e3,o;for(let i=1;i<=t;i++)try{return await s()}catch(a){if(o=a,i>=t)break;let d=Math.min(n,r*2**(i-1)),l=Math.floor(Math.random()*Math.max(1,d*.2));await st(d+l)}throw o}var nt=new Set(["put","get","getText","delete","list"]);function se(s,e={}){return new Proxy(s,{get(t,r){let n=Reflect.get(t,r,t);return typeof n!="function"?n:nt.has(r)?(...o)=>re(()=>Promise.resolve(n.apply(t,o)),e):n.bind(t)}})}function ne(s){let e=s.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function oe(s){let e=s.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var L=class{constructor(e,t,r,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=ne(n??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,n=await this.provider.getText(e);if(n){let i;try{i=JSON.parse(n)}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)});
|