toolnet-memory 0.3.15 → 0.3.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.env.example +74 -0
  2. package/.release-target +1 -1
  3. package/README.md +316 -6
  4. package/bin/toolnet-memory +12 -0
  5. package/bundle/agy-hook.js +66 -66
  6. package/bundle/agy.js +56 -56
  7. package/bundle/api.js +15 -15
  8. package/bundle/audit.js +2 -0
  9. package/bundle/background-refresh.js +7 -7
  10. package/bundle/claude-hook.js +49 -49
  11. package/bundle/code-capabilities.js +2 -0
  12. package/bundle/codex-context.js +29 -29
  13. package/bundle/codex.js +71 -71
  14. package/bundle/context-runtime.js +39 -39
  15. package/bundle/context.js +15 -15
  16. package/bundle/copilot-hook.js +78 -78
  17. package/bundle/cursor-hook.js +78 -78
  18. package/bundle/docker-healthcheck.js +3 -0
  19. package/bundle/doctor.js +4 -4
  20. package/bundle/full-index.js +22 -21
  21. package/bundle/gc.js +5 -3
  22. package/bundle/graph-cli.js +1 -1
  23. package/bundle/graph-index.js +5 -4
  24. package/bundle/graph-ui.js +4 -3
  25. package/bundle/grok-hook.js +56 -56
  26. package/bundle/handoff-refresh.js +10 -10
  27. package/bundle/help-cli.js +4 -4
  28. package/bundle/impact.js +5 -4
  29. package/bundle/incremental.js +5 -5
  30. package/bundle/init.js +36 -35
  31. package/bundle/kiro-hook.js +85 -85
  32. package/bundle/learner.js +8 -6
  33. package/bundle/mcp.js +19 -17
  34. package/bundle/memory-agent.js +6 -6
  35. package/bundle/memory-query.js +7 -7
  36. package/bundle/opencode.js +77 -77
  37. package/bundle/project-manual.js +7 -7
  38. package/bundle/public/index.html +51 -2
  39. package/bundle/recovery-certify.js +9 -9
  40. package/bundle/runtime.js +16 -13
  41. package/bundle/semantic.js +6 -5
  42. package/bundle/service.js +11 -6
  43. package/bundle/snapshot.js +6 -4
  44. package/bundle/status-cli.js +4 -4
  45. package/bundle/toolnet-cli.js +46 -46
  46. package/bundle/work-continuity.js +7 -7
  47. package/package.json +38 -2
  48. package/release-manifest.json +143 -4
package/bundle/learner.js CHANGED
@@ -1,9 +1,11 @@
1
- import{existsSync as De,readFileSync as ze}from"node:fs";import{homedir as He}from"node:os";import{join as Ve}from"node:path";function Le(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 Be(){let r=process.env.TOOLNET_GLOBAL_ENV??Ve(He(),".config","toolnet-memory",".env");if(!De(r))return;let e=ze(r,"utf8");for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let s=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=Le(o.slice(n+1)))}}Be();function S(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 Y(){return{memory:{autoCapture:S(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:S(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:S(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:S(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:S(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)}}}var Je={critical:100,high:75,normal:50,temporary:20};function W(r){return Je[r]}function Z(r,e){let t=e.toLowerCase();return t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c")||t.includes("must not")||t.includes("critical")?"critical":r==="rule"||r==="decision"?"high":r==="todo"?"normal":r==="activity"||r==="summary"?"temporary":"normal"}import{createHash as Fe}from"node:crypto";import{existsSync as j,mkdirSync as Ue,readFileSync as Ye,renameSync as We,writeFileSync as Ze}from"node:fs";import{basename as Ge,dirname as M,join as w,parse as ee,resolve as y}from"node:path";var te=".toolnet",qe="project.json";function Qe(r){return Fe("sha256").update(r).digest("hex").slice(0,16)}function k(r){return w(r,te,qe)}function Xe(r){return j(k(r))}function G(r,e){let t=y(r),o=ee(t).root;for(;;){if(Xe(t))return t;if(t===o||e&&t===y(e))break;let n=M(t);if(n===t)break;t=n}return null}function q(r){let e=y(r),t=ee(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(s=>j(w(e,s))))return e;if(e===t)break;let n=M(e);if(n===e)break;e=n}return y(r)}function Q(r){let e;try{e=JSON.parse(Ye(r,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${r}: ${n instanceof Error?n.message:String(n)}`)}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 o=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:M(M(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:o,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:o,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 X(r,e){let t=w(r,te);Ue(t,{recursive:!0});let o=k(r),n=`${o}.tmp-${process.pid}`;Ze(n,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),We(n,o)}function D(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var R=class{findExisting(e=process.cwd()){let t=y(e),o=q(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>j(w(o,c))),i=G(t,s?o:void 0);if(!i)return null;let a=Q(k(i));return D(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),o=q(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>j(w(o,l))),i=G(t,s?o:void 0);if(i){let l=k(i),m=Q(l);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),X(i,m)),D(m,i)}let a=new Date().toISOString(),c=Ge(o),u={version:1,id:Qe(o),name:c,remote:c,rootPath:o,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return X(o,u),D(u,o)}};import{randomUUID as kt}from"node:crypto";var et=[{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"}],tt=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function re(r){return r.normalize("NFKC").trim().toLowerCase()}function rt(r){if(r.length===0)return 0;let e=new Map;for(let o of r)e.set(o,(e.get(o)??0)+1);let t=0;for(let o of e.values()){let n=o/r.length;t-=n*Math.log2(n)}return t}function ot(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function nt(r,e,t){let o=r.slice(Math.max(0,e-48),e),n=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(`${o} ${n}`)}function st(r,e){return r.start<e.end&&e.start<r.end}function oe(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var A=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let o=re(t);o&&this.allowValues.add(o)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let s of et){let i=new RegExp(s.regex.source,s.regex.flags);for(let a of e.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:s.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:s.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let o=oe(t),n=[];for(let s of o)n.some(i=>st(i,s))||n.push(s);return oe(n)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=re(e);return tt.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],o=/[A-Za-z0-9_+/=-]{32,160}/g;for(let n of e.matchAll(o)){if(n.index===void 0||!n[0])continue;let s=n[0];this.allowed(s)||ot(s)||!/[A-Za-z]/u.test(s)||!/[0-9]/u.test(s)||nt(e,n.index,n.index+s.length)&&(rt(s)<3.7||t.push({type:"high_entropy_secret",value:s,start:n.index,end:n.index+s.length,confidence:"heuristic"}))}return t}};var I=class{scanner;constructor(e={}){this.scanner=new A(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let o=e,n=[...t].sort((i,a)=>a.start-i.start),s=new Set;for(let i of n)s.add(i.type),o=o.slice(0,i.start)+`[REDACTED:${i.type}]`+o.slice(i.end);return{text:o,redacted:t.length,secretTypes:[...s].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[o,n]of Object.entries(e)){let s=o.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")){t[o]="[REDACTED]";continue}t[o]=this.sanitizeValue(n)}return t}return e}};var ne=new I;function se(r){return ne.sanitize(r).text}function z(r){return ne.sanitizeValue(r)}var it=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),at=new Set(["d\xF9ng","s\u1EED","d\u1EE5ng","use","using","the","a","an","cho","v\xE0","l\xE0","c\u1EE7a","to","for","with","quy\u1EBFt","\u0111\u1ECBnh"]);function ie(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!at.has(e)))}function ct(r,e){let t=ie(r),o=ie(e);if(t.size===0||o.size===0)return 0;let n=0;for(let i of t)o.has(i)&&(n+=1);let s=new Set([...t,...o]).size;return s===0?0:n/s}function ae(r){return new Set(r.tags.filter(e=>!it.has(e.toLowerCase())))}function H(r){let e=r.metadata?.evidence;if(!e||typeof e!="object")return{userExplicit:!1,sourceVerified:!1,testVerified:!1,crossSessionConfirmations:0,assistantDerived:!1};let t=e,o=Number(t.crossSessionConfirmations);return{userExplicit:t.userExplicit===!0,sourceVerified:t.sourceVerified===!0,testVerified:t.testVerified===!0,crossSessionConfirmations:Number.isFinite(o)?Math.max(0,o):0,assistantDerived:t.assistantDerived===!0}}function ut(r){let e=H(r);return e.userExplicit||e.sourceVerified||e.testVerified||e.crossSessionConfirmations>0}function dt(r){let e=Number(r.metadata?.confidence);return!Number.isFinite(e)||e<0?0:e>1?1:e}function pt(r){return r.importance==="critical"?20:r.importance==="high"?12:r.importance==="normal"?5:0}function ce(r){let e=H(r),t=pt(r);return e.userExplicit&&(t+=100),e.sourceVerified&&(t+=60),e.testVerified&&(t+=60),t+=Math.min(5,e.crossSessionConfirmations)*12,t+=dt(r)*10,r.metadata?.knowledgeClass==="permanent"&&(t+=10),e.assistantDerived&&(t-=15),Math.round(t*1e3)/1e3}function ue(r){let e=r.metadata?.topic;if(typeof e!="string")return;let t=e.normalize("NFKC").trim().toLowerCase();if(t)return t}function lt(r,e){let t=ae(r),o=ae(e);for(let n of t)if(o.has(n))return!0;return!1}function mt(r,e){if(e.id===r.id||e.projectId!==r.projectId||e.type!==r.type||e.metadata?.supersededBy)return!1;let t=ue(r),o=ue(e);return t&&o&&t===o||lt(r,e)?!0:ct(r.content,e.content)>=.6}function de(r){return r.type!=="rule"?!1:H(r).userExplicit}function ft(r,e){return!de(r)||!de(e)?!1:r.createdAt>=e.createdAt}var P=class{resolve(e,t){if(e.type!=="rule"&&e.type!=="decision")return{superseded:[],conflicts:[]};let o=[],n=[],s=ce(e);for(let i of t){if(!mt(e,i))continue;let a=ce(i);if(s>a){o.push(i);continue}if(s<a){n.push(i);continue}if(ft(e,i)){o.push(i);continue}if(!ut(i)&&e.createdAt>=i.createdAt){o.push(i);continue}n.push(i)}return{superseded:o,conflicts:n}}findSuperseded(e,t){return this.resolve(e,t).superseded}};var gt=new Set(["code","decision","rule","todo","summary"]);function yt(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function pe(r){return r.tags.includes("class:permanent")?4:r.tags.includes("class:task")?3:r.tags.includes("class:session")?2:r.tags.includes("class:transient")?1:0}function ht(r,e){let t=pe(e)-pe(r);if(t!==0)return t;let o=e.importanceScore-r.importanceScore;if(o!==0)return o;let n=e.updatedAt.localeCompare(r.updatedAt);if(n!==0)return n;let s=e.createdAt.localeCompare(r.createdAt);return s!==0?s:r.id.localeCompare(e.id)}function le(r){let e=new Set,t=[];for(let o of r){let n=o.trim();if(!n)continue;let s=n.normalize("NFKC").toLowerCase();e.has(s)||(e.add(s),t.push(n))}return t}function me(r){let e=new Map;for(let n of r){if(!gt.has(n.type)||n.metadata?.supersededBy)continue;let s=yt(n.content);if(!s)continue;let i=[n.projectId,n.type,s].join("\0"),a=e.get(i)??[];a.push(n),e.set(i,a)}let t=[],o=0;for(let n of e.values()){if(n.length<2)continue;let s=[...n].sort(ht),i=s[0];if(!i)continue;let a=s.slice(1);t.push({canonicalId:i.id,duplicateIds:a.map(c=>c.id),mergedTags:le(s.flatMap(c=>c.tags)),mergedSources:le(s.map(c=>c.source))}),o+=a.length}return{groups:t,duplicates:o}}function V(r){if(r.tags.includes("class:permanent"))return"permanent";if(r.tags.includes("class:task"))return"task";if(r.tags.includes("class:session"))return"session";if(r.tags.includes("class:transient"))return"transient"}function St(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function vt(r){let e=V(r);if(e==="permanent")return 730;if(e==="task")return 180;if(e==="session")return 45;if(e==="transient")return 7;switch(r.type){case"rule":return 730;case"decision":return 365;case"code":return 180;case"todo":return 120;case"summary":return 45;case"activity":return 14}}function wt(r){return V(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function bt(r){let e=r.normalize("NFKC").toLowerCase().trim();return e.length<8?!0:[/^ok(?:ay)?[.!]?$/u,/^done[.!]?$/u,/^thanks?[.!]?$/u,/^test(?:ing)?[.!]?$/u,/^npm notice\b/u,/^changed \d+ packages?/u,/^packages? are looking for funding/u].some(t=>t.test(e))}function fe(r,e=Date.now()){let t=50,o=[],n=V(r);switch(n==="permanent"?(t+=25,o.push("permanent project knowledge")):n==="task"?(t+=15,o.push("active task knowledge")):n==="session"?(t+=2,o.push("session-scoped knowledge")):n==="transient"&&(t-=25,o.push("transient knowledge")),r.importance){case"critical":t+=25,o.push("critical importance");break;case"high":t+=15,o.push("high importance");break;case"normal":break;case"temporary":t-=15,o.push("temporary importance");break}(r.type==="rule"||r.type==="decision")&&(t+=10,o.push("durable knowledge type"));let s=r.content.trim().length;s<12?(t-=30,o.push("very short content")):s<30?(t-=10,o.push("limited context")):s<=1200?(t+=8,o.push("useful context density")):s>5e3&&(t-=15,o.push("excessively large memory")),bt(r.content)&&(t-=35,o.push("matches transient/noise pattern"));let i=r.metadata?.consolidation;i&&typeof i=="object"&&Array.isArray(i.sources)&&i.sources.length>1&&(t+=10,o.push("confirmed across multiple sources"));let a=St(r,e)>=vt(r);a&&(t-=15,o.push("stale for lifecycle class"));let c=wt(r);t=Math.max(0,Math.min(100,Math.round(t)));let u;t>=80?u="trusted":t>=55?u="useful":t>=30?u="weak":u="noise";let l=r.importance==="temporary"||r.type==="activity"||n==="transient";return{score:t,tier:u,stale:a,protected:c,pruneEligible:!c&&(u==="noise"&&l||a&&(u==="noise"||u==="weak")),reasons:o}}var xt={critical:100,high:75,normal:50,temporary:20},jt={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function ge(r,e,t=new Date){let o;if(e==="temporary"&&(o=30),r==="activity"&&(o=Math.min(o??14,14)),r==="summary"&&(o=Math.min(o??30,30)),!!o)return new Date(t.getTime()+o*864e5).toISOString()}function L(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function Mt(r){return!!r.metadata?.supersededBy}function B(r,e=Date.now()){return!L(r,e)&&!Mt(r)}function J(r,e=Date.now()){if(!B(r,e))return 0;let t=xt[r.importance];if(r.importance==="critical")return t;let o=jt[r.type]??180,s=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,i=Math.pow(.5,s/o);return t*i}var C=class{memories=new Map;conflicts=new P;remember(e){let t=new Date().toISOString(),o=se(e.content.trim()),n=e.importance??Z(e.type,o),s={id:kt(),projectId:e.projectId,type:e.type,content:o,importance:n,importanceScore:W(n),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??ge(e.type,n,new Date(t)),metadata:z(e.metadata)},i=this.conflicts.resolve(s,this.list(e.projectId));if(i.superseded.length>0){s.metadata={...s.metadata??{},supersedes:i.superseded.map(a=>a.id)};for(let a of i.superseded)a.updatedAt=t,a.metadata={...a.metadata??{},supersededBy:s.id,supersededAt:t},this.memories.set(a.id,a)}if(i.conflicts.length>0){let a=i.conflicts.map(c=>c.id);s.metadata={...s.metadata??{},conflictsWith:a};for(let c of i.conflicts){let u=Array.isArray(c.metadata?.conflictsWith)?c.metadata?.conflictsWith:[],l=new Set(u.filter(m=>typeof m=="string"));l.add(s.id),c.updatedAt=t,c.metadata={...c.metadata??{},conflictsWith:[...l]},this.memories.set(c.id,c)}}return this.memories.set(s.id,s),s}importRecords(e){let t=0;for(let o of e){if(!o?.id)continue;let n=z(o);this.memories.set(n.id,n),t++}return t}exportProject(e){return this.listAll(e)}get(e){return this.memories.get(e)}delete(e){return this.memories.delete(e)}listAll(e){return[...this.memories.values()].filter(t=>t.projectId===e).sort((t,o)=>o.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>B(t))}recent(e,t=10){return this.list(e).slice(0,t)}byType(e,t){return this.list(e).filter(o=>o.type===t)}search(e){let t=e.query.trim().toLowerCase(),o=e.limit??10,n=t.split(/\s+/).filter(Boolean);return this.list(e.projectId).filter(s=>{if(e.types&&!e.types.includes(s.type))return!1;let i=J(s);return!(e.minImportanceScore&&i<e.minImportanceScore||e.tags?.length&&!e.tags.some(c=>s.tags.includes(c)))}).map(s=>{let i=s.content.toLowerCase(),a=n.filter(l=>i.includes(l)).length,c=n.length===0?0:a/n.length,u=J(s)/500;return{memory:s,score:c+u,source:"memory"}}).filter(s=>t.length===0||s.score>0).sort((s,i)=>i.score-s.score).slice(0,o)}consolidate(e,t=Date.now()){let o=me(this.list(e)),n=[],s=0;for(let i of o.groups){let a=this.memories.get(i.canonicalId);if(a){a.tags=i.mergedTags,a.metadata={...a.metadata??{},consolidation:{version:1,consolidatedAt:new Date(t).toISOString(),mergedIds:i.duplicateIds,sources:i.mergedSources}},this.memories.set(a.id,a),n.push(a.id);for(let c of i.duplicateIds)this.memories.delete(c)&&(s+=1)}}return{groupsConsolidated:n.length,duplicatesRemoved:s,canonicalIds:n}}reviewLifecycle(e,t=Date.now()){let o={reviewed:0,trusted:0,useful:0,weak:0,noise:0,stale:0,protected:0,pruned:0};for(let n of this.list(e)){let s=fe(n,t);o.reviewed+=1,o[s.tier]+=1,s.stale&&(o.stale+=1),s.protected&&(o.protected+=1),n.metadata={...n.metadata??{},lifecycle:{version:1,reviewedAt:new Date(t).toISOString(),qualityScore:s.score,tier:s.tier,stale:s.stale,protected:s.protected,reasons:s.reasons}},this.memories.set(n.id,n),s.pruneEligible&&this.memories.delete(n.id)&&(o.pruned+=1)}return o}pruneExpired(e,t=Date.now()){let o=0;for(let[n,s]of this.memories)s.projectId===e&&L(s,t)&&(this.memories.delete(n),o++);return o}pruneSuperseded(e,t=30,o=Date.now()){let n=0,s=t*864e5;for(let[i,a]of this.memories){if(a.projectId!==e)continue;let c=a.metadata?.supersededAt;if(typeof c!="string")continue;o-new Date(c).getTime()>=s&&(this.memories.delete(i),n++)}return n}clearProject(e){let t=0;for(let[o,n]of this.memories)n.projectId===e&&(this.memories.delete(o),t++);return t}};import{homedir as Wt}from"node:os";import{join as Zt}from"node:path";import{DeleteObjectCommand as Rt,GetObjectCommand as At,HeadObjectCommand as It,ListObjectsV2Command as Pt,PutObjectCommand as Ct,S3Client as Ot}from"@aws-sdk/client-s3";import{getSignedUrl as Tt}from"@aws-sdk/s3-request-presigner";var O=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ot({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,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ct({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await Tt(this.client,new At({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new It({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 Rt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new Pt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};import{access as ye,mkdir as Et,readFile as _t,readdir as Nt,rm as Kt,stat as he,writeFile as $t}from"node:fs/promises";import{dirname as Dt,join as zt,relative as Se,resolve as Ht}from"node:path";var b=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Ht(this.root,t)}async put(e,t){let o=this.path(e);await Et(Dt(o),{recursive:!0}),await $t(o,t)}async get(e){try{return await _t(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 ye(this.path(e)),!0}catch{return!1}}async delete(e){await Kt(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await ye(t)}catch{return o}let n=async i=>{let a=await Nt(i,{withFileTypes:!0});for(let c of a){let u=zt(i,c.name);if(c.isDirectory()){await n(u);continue}let l=await he(u);o.push({key:Se(this.root,u),size:l.size,updatedAt:l.mtime.toISOString()})}},s=await he(t);return s.isDirectory()?await n(t):o.push({key:Se(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),o}};import{DeleteObjectCommand as Vt,GetObjectCommand as Lt,HeadObjectCommand as Bt,ListObjectsV2Command as Jt,PutObjectCommand as Ft,S3Client as Ut}from"@aws-sdk/client-s3";import{getSignedUrl as Yt}from"@aws-sdk/s3-request-presigner";var x=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Ut({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ft({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await Yt(this.client,new Lt({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`${this.name} download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Bt({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new Vt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new Jt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};function F(r,e){return console.warn(e),new b(r)}function ve(r){let e=r.localRoot??Zt(Wt(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new x({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):F(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new x({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):F(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new O({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):F(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new b(e)}var T=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let o=JSON.parse(t);if(!Array.isArray(o))throw new Error("Invalid memory snapshot");return o}async save(e,t){let o=JSON.stringify(t,null,2);await this.storage.put(this.key(e),o,"application/json")}};function Gt(r){return new Promise(e=>setTimeout(e,r))}async function we(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,s;for(let i=1;i<=t;i++)try{return await r()}catch(a){if(s=a,i>=t)break;let c=Math.min(n,o*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await Gt(c+u)}throw s}var qt=new Set(["put","get","getText","delete","list"]);function be(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:qt.has(o)?(...s)=>we(()=>Promise.resolve(n.apply(t,s)),e):n.bind(t)}})}function xe(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 je(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 o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(o)return`${o[1]}memory/records/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),o)return`${o[1]}memory/vectors/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),o)return`${o[1]}code/graph/${o[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var E=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=xe(n??o),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(),o=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"&&(o=i.createdAt)}let s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:t};await this.provider.put(e,JSON.stringify(s,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=je(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,o){return await this.ensureRegistered(),this.provider.put(this.key(e),t,o)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{closeSync as Qt,mkdirSync as Xt,openSync as er,readFileSync as tr,unlinkSync as Me,writeFileSync as rr}from"node:fs";import{tmpdir as or}from"node:os";import{join as ke}from"node:path";function nr(r){try{return process.kill(r,0),!0}catch(e){return e?.code==="EPERM"}}var _=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=ke(or(),"toolnet-memory-locks");Xt(t,{recursive:!0});let o=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=ke(t,`${o}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=er(this.path,"wx");rr(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),Qt(t),this.acquired=!0,process.once("exit",this.exitHandler);return}catch(t){if(t?.code!=="EEXIST")throw t;let o=!0;try{let n=JSON.parse(tr(this.path,"utf8"));Number.isInteger(n.pid)&&nr(n.pid)&&(o=!1)}catch{o=!0}if(!o)throw new Error("ToolNet Memory is already running for this project");try{Me(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{Me(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};import{createHash as pr}from"node:crypto";import{hostname as lr}from"node:os";import{createHash as sr,randomUUID as ir}from"node:crypto";function g(r,e){let t=r.trim();if(!t)throw new Error(`${e} is required`);return t}function N(r,e){return encodeURIComponent(g(r,e))}function ar(r){let e=JSON.stringify(r);if(e===void 0)throw new Error("Multi-host operation payload must be JSON serializable");return e}function Ae(r){return sr("sha256").update(r).digest("hex")}function Ie(r){return Ae(ar(r))}function Pe(r){return Number.isFinite(Date.parse(r))}function cr(r){return Ae(JSON.stringify({version:r.version,operationId:r.operationId,projectId:r.projectId,scope:r.scope,hostId:r.hostId,occurredAt:r.occurredAt,payloadSha256:r.payloadSha256,payload:r.payload}))}function Ce(r){let e=g(r.projectId,"projectId"),t=g(r.scope,"scope"),o=g(r.hostId,"hostId"),n=g(r.operationId??ir(),"operationId"),s=r.occurredAt??new Date().toISOString();if(!Pe(s))throw new Error(`Invalid operation timestamp: ${s}`);return{version:1,operationId:n,projectId:e,scope:t,hostId:o,occurredAt:s,payloadSha256:Ie(r.payload),payload:r.payload}}function Oe(r,e){let t=["projects",N(r,"projectId"),"operations"];return e?`${[...t,N(e,"scope")].join("/")}/`:`${t.join("/")}/`}function ur(r){return[Oe(r.projectId,r.scope).replace(/\/$/,""),N(r.hostId,"hostId"),`${N(r.operationId,"operationId")}-${r.payloadSha256}.json`].join("/")}async function Te(r,e){let t=ur(e);return await r.put(t,`${JSON.stringify(e,null,2)}
5
- `,"application/json"),t}function dr(r){let e;try{e=JSON.parse(r)}catch{return null}return e.version!==1||typeof e.operationId!="string"||typeof e.projectId!="string"||typeof e.scope!="string"||typeof e.hostId!="string"||typeof e.occurredAt!="string"||!Pe(e.occurredAt)||typeof e.payloadSha256!="string"||Ie(e.payload)!==e.payloadSha256?null:e}function Re(r,e){let t=r.occurredAt.localeCompare(e.occurredAt);if(t!==0)return t;let o=r.hostId.localeCompare(e.hostId);if(o!==0)return o;let n=r.operationId.localeCompare(e.operationId);return n!==0?n:r.payloadSha256.localeCompare(e.payloadSha256)}async function Ee(r,e,t){let o=g(e,"projectId"),n=g(t,"scope"),s=Oe(o,n),i=await r.list(s),a=[],c=[];for(let p of i){let d=await r.getText(p.key);if(!d){a.push(p.key);continue}let f=dr(d);if(!f){a.push(p.key);continue}if(f.projectId!==o){a.push(p.key);continue}if(f.scope!==n){a.push(p.key);continue}c.push(f)}let u=new Map;for(let p of c){let d=u.get(p.operationId);if(!d){u.set(p.operationId,[p]);continue}d.push(p)}let l=[],m=[];for(let[p,d]of u){if(new Set(d.map($e=>cr($e))).size>1){m.push({operationId:p,variants:[...d].sort(Re)});continue}let h=d[0];h&&l.push(h)}return l.sort(Re),m.sort((p,d)=>p.operationId.localeCompare(d.operationId)),a.sort(),{operations:l,conflicts:m,invalidKeys:a}}function mr(r){let t=(r??process.env.TOOLNET_HOST_ID??lr()).trim();return t||`pid-${process.pid}`}function fr(r){let e=t=>{if(t===null||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>e(n));let o=t;return Object.fromEntries(Object.keys(o).sort().map(n=>[n,e(o[n])]))};return JSON.stringify(e(r))}function K(r){return pr("sha256").update(fr(r)).digest("hex")}function gr(r,e){let t=K(r).slice(0,12),o=K(e);return["memory",t,o].join("-")}function yr(r,e){let t=r.updatedAt.localeCompare(e.updatedAt);if(t!==0)return t;let o=r.createdAt.localeCompare(e.createdAt);return o!==0?o:K(r).localeCompare(K(e))}function hr(r,e){return yr(r,e)>=0?r:e}function U(r,e){let t=new Map;for(let o of r)t.set(o.id,o);for(let o of e){if(o.payload.kind!=="upsert")continue;let n=o.payload.memory,s=t.get(n.id);if(!s){t.set(n.id,n);continue}t.set(n.id,hr(s,n))}return[...t.values()].sort((o,n)=>o.id.localeCompare(n.id))}var $=class{constructor(e,t={}){this.storage=e;this.legacy=new T(e),this.hostId=mr(t.hostId)}storage;legacy;hostId;diagnostics={operationCount:0,conflicts:0,invalidKeys:0};getDiagnostics(){return{...this.diagnostics}}async operations(e){let t=await Ee(this.storage,e,"memory");return this.diagnostics={operationCount:t.operations.length,conflicts:t.conflicts.length,invalidKeys:t.invalidKeys.length},t.operations}async load(e){let t=await this.legacy.load(e),o=await this.operations(e);return U(t,o)}async appendMemory(e,t){let o=Ce({projectId:e,scope:"memory",hostId:this.hostId,operationId:gr(this.hostId,t),occurredAt:t.updatedAt,payload:{kind:"upsert",memory:t}});await Te(this.storage,o)}async refreshProjection(e){let t=await this.legacy.load(e),o=await this.operations(e),n=U(t,o);return await this.legacy.save(e,n),n}async save(e,t){let o=[...t].sort((i,a)=>i.id.localeCompare(a.id));for(let i of o)await this.appendMemory(e,i);let n=await this.operations(e),s=U(t,n);await this.legacy.save(e,s)}};function _e(r){let e=r.metadata?.learningFingerprint;return typeof e=="string"?e:void 0}function Ne(r){return!r||typeof r!="object"?{}:r}function Sr(r){let e=r.metadata?.confirmingSessionKeys,t=new Set;if(Array.isArray(e))for(let n of e)typeof n=="string"&&t.add(n);let o=r.metadata?.sessionKey;return typeof o=="string"&&t.add(o),t}function vr(r,e){let t=Sr(r),o=t.size;t.add(e.sessionKey);let n=Ne(r.metadata?.evidence),s=Ne(e.evidence),i=t.size,a=n.userExplicit===!0||s.userExplicit===!0,c=n.sourceVerified===!0||s.sourceVerified===!0,u=n.testVerified===!0||s.testVerified===!0,l=n.assistantDerived===!0&&s.assistantDerived===!0,m=Number(n.crossSessionConfirmations??0);return o!==i||m!==i||n.userExplicit!==a||n.sourceVerified!==c||n.testVerified!==u||n.assistantDerived!==l?(r.metadata={...r.metadata??{},evidence:{userExplicit:a,sourceVerified:c,testVerified:u,crossSessionConfirmations:i,assistantDerived:l},confirmingSessionKeys:[...t].sort()},!0):!1}async function wr(r,e){let t=`projects/${r.id}/memory/learned/`,o=await e.list(t),n=[];for(let s of o.filter(i=>i.key.includes("/batches/")&&i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(s.key);if(i)try{let a=JSON.parse(i);if(a.version!==1||!Array.isArray(a.candidates))continue;n.push(a)}catch{}}return n}async function Ke(r,e){let t=await wr(r,e),o=new $(e),n=await o.load(r.id),s=new C;s.importRecords(n);let i=new Set(n.map(p=>_e(p)).filter(p=>!!p)),a=new Map(n.flatMap(p=>{let d=_e(p);return d?[[d,p]]:[]})),c=0,u=0,l=0,m=0;for(let p of t)for(let d of p.candidates){if(c+=1,i.has(d.fingerprint)){l+=1;let h=a.get(d.fingerprint);m+=h&&vr(h,d)?1:0;continue}let f=s.remember({projectId:r.id,type:d.type,content:d.content,importance:d.importance,tags:d.tags,source:"session-memory-learner",metadata:{learningFingerprint:d.fingerprint,learningKind:d.kind,confidence:d.confidence,provenance:d.provenance,sourceCreatedAt:d.createdAt,sessionKey:d.sessionKey,agent:d.agent,nativeSessionId:d.nativeSessionId}});i.add(d.fingerprint),a.set(d.fingerprint,f),u+=1}return(u>0||m>0)&&await o.save(r.id,s.exportProject(r.id)),{batches:t.length,candidates:c,added:u,duplicates:l,memories:s.exportProject(r.id).length}}function br(r,e){let t=r.indexOf(e);return t>=0?r[t+1]:void 0}async function xr(){let[r="help",...e]=process.argv.slice(2);if(r!=="reconcile"){console.log(`Session Memory Learner
1
+ import{existsSync as Ht,readFileSync as Vt}from"node:fs";import{homedir as zt}from"node:os";import{join as Ut}from"node:path";function Bt(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 Yt(){let r=process.env.TOOLNET_GLOBAL_ENV??Ut(zt(),".config","toolnet-memory",".env");if(!Ht(r))return;let e=Vt(r,"utf8");for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let o=n.indexOf("=");if(o<=0)continue;let i=n.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=Bt(n.slice(o+1)))}}Yt();function M(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function I(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function we(){return{memory:{autoCapture:M(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:M(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:M(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:M(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:I(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:I(process.env.MEMORY_RERANK_TOP,10),finalContext:I(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:I(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:M(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:I(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var Ft={critical:100,high:75,normal:50,temporary:20};function ve(r){return Ft[r]}function be(r,e){let t=e.toLowerCase();return t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c")||t.includes("must not")||t.includes("critical")?"critical":r==="rule"||r==="decision"?"high":r==="todo"?"normal":r==="activity"||r==="summary"?"temporary":"normal"}import{createHash as Xt}from"node:crypto";import{existsSync as L,mkdirSync as er,readFileSync as tr,renameSync as rr,writeFileSync as nr}from"node:fs";import{basename as or,dirname as $,join as P,parse as ke,resolve as S}from"node:path";import{createHash as Re}from"node:crypto";import{spawnSync as Jt}from"node:child_process";var A="git-remote-v1",Gt=new Set(["github.com","gitlab.com","bitbucket.org"]);function Me(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:(Gt.has(r)&&(t=t.toLowerCase()),t)}function qt(r){let e;try{e=new URL(r)}catch{return null}if(!["https:","http:","ssh:","git:"].includes(e.protocol))return null;let t=e.hostname.trim().toLowerCase();if(!t)return null;let n=e.protocol==="https:"&&e.port==="443"||e.protocol==="http:"&&e.port==="80"||e.protocol==="ssh:"&&e.port==="22",o=e.port&&!n?`${t}:${e.port}`:t,i=Me(t,e.pathname);return i?`${o}/${i}`:null}function Wt(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=Me(t,e[2]??"");return n?`${t}/${n}`:null}function xe(r){let e=r.trim();return e?e.includes("://")?qt(e):Wt(e):null}function Zt(r){return Re("sha256").update(`${A}:${r}`).digest("hex")}function Ie(r){return Re("sha256").update(`toolnet-project:${A}:${r}`).digest("hex").slice(0,16)}function Qt(r){return r.split("/").filter(Boolean).at(-1)?.trim()||null}function ee(r,e){let t=Jt("git",["-C",r,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function Ee(r,e){let t=Qt(r);return t?{scheme:A,canonicalRemote:r,fingerprint:Zt(r),repositoryName:t,source:e}:null}function Ae(r){let e=ee(r,["remote","get-url","origin"]);if(e){let o=xe(e);if(o)return Ee(o,"origin")}let t=ee(r,["remote"]);if(!t)return null;let n=new Set;for(let o of t.split(/\r?\n/u).map(i=>i.trim()).filter(Boolean)){let i=ee(r,["remote","get-url",o]);if(!i)continue;let s=xe(i);s&&n.add(s)}return n.size!==1?null:Ee([...n][0],"unique-remote")}var je=".toolnet",ir="project.json";function sr(r){return Xt("sha256").update(r).digest("hex").slice(0,16)}function R(r){return P(r,je,ir)}function Te(r){return L(R(r))}function Pe(r,e){let t=S(r),n=ke(t).root;for(;;){if(Te(t))return t;if(t===n||e&&t===S(e))break;let o=$(t);if(o===t)break;t=o}return null}function te(r){let e=S(r),t=ke(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>L(P(e,i))))return e;if(e===t)break;let o=$(e);if(o===e)break;e=o}return S(r)}function K(r){let e;try{e=JSON.parse(tr(r,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${r}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:$($(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:n,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:n,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function D(r,e){let t=P(r,je);er(t,{recursive:!0});let n=R(r),o=`${n}.tmp-${process.pid}`;nr(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),rr(o,n)}function h(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 re(r){return{version:1,scheme:A,canonicalRemote:r.canonicalRemote,fingerprint:r.fingerprint,repositoryName:r.repositoryName}}function ar(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 H=class{adopt(e,t){let n=te(S(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(Te(n)){let a=K(R(n));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return h(a,n)}let o=new Date().toISOString(),i={...t.metadata};t.gitIdentity&&(i.toolnetIdentity=re(t.gitIdentity));let s={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:n,createdAt:t.createdAt??o,updatedAt:o,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(i).length?i:void 0};return D(n,s),h(s,n)}recordGitIdentity(e,t,n={}){let o=this.requireExisting(e),i=R(o.rootPath),s=K(i),a=ar(s);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 c=s.metadata?.toolnetIdentity;return c&&typeof c=="object"&&!Array.isArray(c)&&c.fingerprint===t.fingerprint||(s.metadata={...s.metadata,toolnetIdentity:re(t)},s.updatedAt=new Date().toISOString(),D(o.rootPath,s)),h(s,o.rootPath)}findExisting(e=process.cwd()){let t=S(e),n=te(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>L(P(n,c))),s=Pe(t,i?n:void 0);if(!s)return null;let a=K(R(s));return h(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=S(e),n=te(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>L(P(n,f))),s=Pe(t,i?n:void 0);if(s){let f=R(s),l=K(f);return l.rootPath!==s&&(l.rootPath=s,l.updatedAt=new Date().toISOString(),D(s,l)),h(l,s)}let a=new Date().toISOString(),c=or(n),d=Ae(n),p={version:1,id:d?Ie(d.canonicalRemote):sr(n),name:c,remote:d?.repositoryName??c,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:d?{toolnetIdentity:re(d)}:void 0};return D(n,p),h(p,n)}};import{randomUUID as Hr}from"node:crypto";var cr=[{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"}],dr=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function Oe(r){return r.normalize("NFKC").trim().toLowerCase()}function ur(r){if(r.length===0)return 0;let e=new Map;for(let n of r)e.set(n,(e.get(n)??0)+1);let t=0;for(let n of e.values()){let o=n/r.length;t-=o*Math.log2(o)}return t}function pr(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function lr(r,e,t){let n=r.slice(Math.max(0,e-48),e),o=r.slice(t,Math.min(r.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${n} ${o}`)}function mr(r,e){return r.start<e.end&&e.start<r.end}function Ce(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var V=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=Oe(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let i of cr){let s=new RegExp(i.regex.source,i.regex.flags);for(let a of e.matchAll(s))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:i.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:i.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let n=Ce(t),o=[];for(let i of n)o.some(s=>mr(s,i))||o.push(i);return Ce(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=Oe(e);return dr.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],n=/[A-Za-z0-9_+/=-]{32,160}/g;for(let o of e.matchAll(n)){if(o.index===void 0||!o[0])continue;let i=o[0];this.allowed(i)||pr(i)||!/[A-Za-z]/u.test(i)||!/[0-9]/u.test(i)||lr(e,o.index,o.index+i.length)&&(ur(i)<3.7||t.push({type:"high_entropy_secret",value:i,start:o.index,end:o.index+i.length,confidence:"heuristic"}))}return t}};var z=class{scanner;constructor(e={}){this.scanner=new V(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let n=e,o=[...t].sort((s,a)=>a.start-s.start),i=new Set;for(let s of o)i.add(s.type),n=n.slice(0,s.start)+`[REDACTED:${s.type}]`+n.slice(s.end);return{text:n,redacted:t.length,secretTypes:[...i].sort()}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[n,o]of Object.entries(e)){let i=n.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(i.includes("password")||i.includes("passwd")||i==="pwd"||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")||i.includes("apikey")||i.includes("accesskey")||i.includes("privatekey")||i.includes("clientsecret")||i.includes("credential")){t[n]="[REDACTED]";continue}t[n]=this.sanitizeValue(o)}return t}return e}};var _e=new z;function Ne(r){return _e.sanitize(r).text}function w(r){return _e.sanitizeValue(r)}var fr=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","next_action","next-action","opencode","agy","codex","claude","kiro","cursor","copilot","grok","toolnet","kilo"]),gr=new Set(["d\xF9ng","s\u1EED","d\u1EE5ng","cho","v\xE0","l\xE0","c\u1EE7a","v\u1EDBi","m\u1ED9t","c\xE1c","use","using","the","a","an","to","for","with","and","of","quy\u1EBFt","\u0111\u1ECBnh"]),yr=new Set(["todo","task","next","step","action","need","needs","needed","remaining","fix","fixed","fixing","resolve","resolved","implemented","complete","completed","done","pass","passed","passing","tests","test","c\u1EA7n","l\xE0m","s\u1EEDa","\u0111\xE3","x\u1EED","l\xFD","ho\xE0n","t\u1EA5t","th\xE0nh","ti\u1EBFp","theo","b\u01B0\u1EDBc"]),hr=new Set(["rule","decision","todo","next_action","fix","context","architecture"]);function y(r){return r.normalize("NFKC").trim().toLowerCase()}function Be(r,e){for(let t of e){let n=r.metadata?.[t];if(typeof n!="string")continue;let o=y(n);if(o)return o}}function Ye(r,e){for(let t of r.tags){let n=y(t);for(let o of e){if(!n.startsWith(o))continue;let i=n.slice(o.length).trim();if(i)return i}}}function U(r){if(typeof r!="string")return;let e=y(r).replaceAll("-","_");if(e==="nextaction")return"next_action";if(hr.has(e))return e}function v(r){let e=U(r.metadata?.conflictKind);if(e)return e;let t=U(r.metadata?.learningKind);if(t)return t;let n=U(r.metadata?.lifecycleKind);if(n)return n;for(let o of r.tags){let i=y(o);if(!i.startsWith("kind:"))continue;let s=U(i.slice(5));if(s)return s}return r.tags.some(o=>y(o)==="next_action")?"next_action":r.type==="rule"?"rule":r.type==="decision"?"decision":r.type==="todo"?"todo":"other"}function Sr(r){let e=r.metadata?.lifecycleState;return typeof e=="string"&&["active","conflicting","superseded","resolved","completed","stale"].includes(e)?e:r.metadata?.supersededBy?"superseded":"active"}function oe(r){return new Set(y(r).replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/u).filter(e=>e.length>2&&!gr.has(e)))}function Ke(r){return new Set([...oe(r)].filter(e=>!yr.has(e)))}function Fe(r,e){if(r.size===0||e.size===0)return 0;let t=0;for(let o of r)e.has(o)&&(t+=1);let n=new Set([...r,...e]).size;return n===0?0:t/n}function wr(r,e){return Fe(oe(r),oe(e))}function vr(r,e){return Fe(Ke(r),Ke(e))}function De(r){return new Set(r.tags.map(y).filter(e=>!(fr.has(e)||e.startsWith("class:")||e.startsWith("kind:")||e.startsWith("level:"))))}function br(r,e){let t=De(r),n=De(e);for(let o of t)if(n.has(o))return!0;return!1}function Le(r){return Be(r,["topic","topicKey"])??Ye(r,["topic:"])}function $e(r){return Be(r,["entity","entityKey","subject","taskId","taskKey"])??Ye(r,["entity:","subject:","task:"])}function He(r){let e=r.metadata?.provenance;if(!e||typeof e!="object"||Array.isArray(e))return new Set;let t=e.sourcePaths;return Array.isArray(t)?new Set(t.filter(n=>typeof n=="string").map(y).filter(Boolean)):new Set}function xr(r,e){let t=He(r);if(t.size===0)return!1;let n=He(e);for(let o of t)if(n.has(o))return!0;return!1}function k(r){let e=r.metadata?.evidence;if(!e||typeof e!="object"||Array.isArray(e))return{userExplicit:!1,sourceVerified:!1,testVerified:!1,crossSessionConfirmations:0,assistantDerived:!1};let t=e,n=Number(t.crossSessionConfirmations);return{userExplicit:t.userExplicit===!0,sourceVerified:t.sourceVerified===!0,testVerified:t.testVerified===!0,crossSessionConfirmations:Number.isFinite(n)?Math.max(0,n):0,assistantDerived:t.assistantDerived===!0}}function Er(r){let e=k(r);return e.userExplicit||e.sourceVerified||e.testVerified||e.crossSessionConfirmations>0}function Rr(r){let e=Number(r.metadata?.confidence);return Number.isFinite(e)?Math.max(0,Math.min(1,e)):0}function Mr(r){return r.importance==="critical"?20:r.importance==="high"?12:r.importance==="normal"?5:0}function Ve(r){let e=k(r),t=Mr(r);return e.userExplicit&&(t+=100),e.sourceVerified&&(t+=60),e.testVerified&&(t+=60),t+=Math.min(5,e.crossSessionConfirmations)*12,t+=Rr(r)*10,r.metadata?.knowledgeClass==="permanent"&&(t+=10),e.assistantDerived&&(t-=15),Math.round(t*1e3)/1e3}function Ir(r,e){if(r==="other"||e==="other")return!1;if(r===e)return!0;let t=new Set(["todo","next_action"]);return!!(t.has(r)&&t.has(e)||r==="fix"&&t.has(e)||e==="fix"&&t.has(r)||r==="fix"&&e==="context"||e==="fix"&&r==="context")}function Ar(r,e){if(r==="fix"&&e==="context"||e==="fix"&&r==="context")return .65;let t=new Set(["todo","next_action","fix"]);return t.has(r)&&t.has(e)?.38:r==="rule"||r==="decision"?.6:.5}function Pr(r,e){if(e.id===r.id||e.projectId!==r.projectId)return!1;let t=Sr(e);if(["superseded","resolved","completed","stale"].includes(t))return!1;let n=v(r),o=v(e);if(!Ir(n,o))return!1;let i=Le(r),s=Le(e);if(i&&s&&i===s)return!0;let a=$e(r),c=$e(e);if(a&&c&&a===c||br(r,e))return!0;let d=Ar(n,o),p=vr(r.content,e.content);return!!(p>=d||wr(r.content,e.content)>=d||xr(r,e)&&p>=Math.max(.3,d-.2))}function ze(r){return v(r)==="rule"&&k(r).userExplicit}function kr(r,e){return!ze(r)||!ze(e)?!1:r.createdAt>=e.createdAt}function Ue(r){let e=k(r);return e.userExplicit||e.sourceVerified||e.testVerified}function B(r){return r==="todo"||r==="next_action"}function ne(r,e){return r.createdAt>=e.createdAt}var Y=class{resolve(e,t){let n=v(e),o={kind:n,superseded:[],conflicts:[],completed:[],resolved:[]};if(n==="other")return o;let i=Ve(e);for(let s of t){if(!Pr(e,s))continue;let a=v(s),c=Ve(s);if(n==="fix"&&B(a)){if(Ue(e)){o.completed.push(s);continue}o.conflicts.push(s);continue}if(n==="fix"&&a==="context"){if(Ue(e)&&i>=c){o.resolved.push(s);continue}o.conflicts.push(s);continue}if(B(n)&&a==="fix"){if(k(e).userExplicit||i>c){o.superseded.push(s);continue}o.conflicts.push(s);continue}if(B(n)&&B(a)){if(i>c||i===c&&ne(e,s)){o.superseded.push(s);continue}o.conflicts.push(s);continue}if(i>c){o.superseded.push(s);continue}if(i<c){o.conflicts.push(s);continue}if(kr(e,s)){o.superseded.push(s);continue}if(["context","fix","architecture","decision"].includes(n)&&ne(e,s)){o.superseded.push(s);continue}if(!Er(s)&&ne(e,s)){o.superseded.push(s);continue}o.conflicts.push(s)}return o}findSuperseded(e,t){return this.resolve(e,t).superseded}};var jr=new Set(["code","decision","rule","todo","summary"]);function Tr(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function Je(r){return r.tags.includes("class:permanent")?4:r.tags.includes("class:task")?3:r.tags.includes("class:session")?2:r.tags.includes("class:transient")?1:0}function Or(r,e){let t=Je(e)-Je(r);if(t!==0)return t;let n=e.importanceScore-r.importanceScore;if(n!==0)return n;let o=e.updatedAt.localeCompare(r.updatedAt);if(o!==0)return o;let i=e.createdAt.localeCompare(r.createdAt);return i!==0?i:r.id.localeCompare(e.id)}function Ge(r){let e=new Set,t=[];for(let n of r){let o=n.trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();e.has(i)||(e.add(i),t.push(o))}return t}function qe(r){let e=new Map;for(let o of r){if(!jr.has(o.type)||o.metadata?.supersededBy)continue;let i=Tr(o.content);if(!i)continue;let s=[o.projectId,o.type,i].join("\0"),a=e.get(s)??[];a.push(o),e.set(s,a)}let t=[],n=0;for(let o of e.values()){if(o.length<2)continue;let i=[...o].sort(Or),s=i[0];if(!s)continue;let a=i.slice(1);t.push({canonicalId:s.id,duplicateIds:a.map(c=>c.id),mergedTags:Ge(i.flatMap(c=>c.tags)),mergedSources:Ge(i.map(c=>c.source))}),n+=a.length}return{groups:t,duplicates:n}}function ie(r){if(r.tags.includes("class:permanent"))return"permanent";if(r.tags.includes("class:task"))return"task";if(r.tags.includes("class:session"))return"session";if(r.tags.includes("class:transient"))return"transient"}function Cr(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function _r(r){let e=ie(r);if(e==="permanent")return 730;if(e==="task")return 180;if(e==="session")return 45;if(e==="transient")return 7;switch(r.type){case"rule":return 730;case"decision":return 365;case"code":return 180;case"todo":return 120;case"summary":return 45;case"activity":return 14}}function Nr(r){return ie(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function Kr(r){let e=r.normalize("NFKC").toLowerCase().trim();return e.length<8?!0:[/^ok(?:ay)?[.!]?$/u,/^done[.!]?$/u,/^thanks?[.!]?$/u,/^test(?:ing)?[.!]?$/u,/^npm notice\b/u,/^changed \d+ packages?/u,/^packages? are looking for funding/u].some(t=>t.test(e))}function We(r,e=Date.now()){let t=50,n=[],o=ie(r);switch(o==="permanent"?(t+=25,n.push("permanent project knowledge")):o==="task"?(t+=15,n.push("active task knowledge")):o==="session"?(t+=2,n.push("session-scoped knowledge")):o==="transient"&&(t-=25,n.push("transient knowledge")),r.importance){case"critical":t+=25,n.push("critical importance");break;case"high":t+=15,n.push("high importance");break;case"normal":break;case"temporary":t-=15,n.push("temporary importance");break}(r.type==="rule"||r.type==="decision")&&(t+=10,n.push("durable knowledge type"));let i=r.content.trim().length;i<12?(t-=30,n.push("very short content")):i<30?(t-=10,n.push("limited context")):i<=1200?(t+=8,n.push("useful context density")):i>5e3&&(t-=15,n.push("excessively large memory")),Kr(r.content)&&(t-=35,n.push("matches transient/noise pattern"));let s=r.metadata?.consolidation;s&&typeof s=="object"&&Array.isArray(s.sources)&&s.sources.length>1&&(t+=10,n.push("confirmed across multiple sources"));let a=Cr(r,e)>=_r(r);a&&(t-=15,n.push("stale for lifecycle class"));let c=Nr(r);t=Math.max(0,Math.min(100,Math.round(t)));let d;t>=80?d="trusted":t>=55?d="useful":t>=30?d="weak":d="noise";let p=r.importance==="temporary"||r.type==="activity"||o==="transient";return{score:t,tier:d,stale:a,protected:c,pruneEligible:!c&&(d==="noise"&&p||a&&(d==="noise"||d==="weak")),reasons:n}}var Dr={critical:100,high:75,normal:50,temporary:20},Lr={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function Ze(r,e,t=new Date){let n;if(e==="temporary"&&(n=30),r==="activity"&&(n=Math.min(n??14,14)),r==="summary"&&(n=Math.min(n??30,30)),!!n)return new Date(t.getTime()+n*864e5).toISOString()}function se(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function $r(r){return!!r.metadata?.supersededBy||r.metadata?.lifecycleState==="superseded"}function ae(r,e=Date.now()){if(se(r,e)||$r(r))return!1;let t=r.metadata?.lifecycleState;return!(t==="completed"||t==="resolved"||t==="conflicting"||t==="stale")}function ce(r,e=Date.now()){if(!ae(r,e))return 0;let t=Dr[r.importance];if(r.importance==="critical")return t;let n=Lr[r.type]??180,i=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,s=Math.pow(.5,i/n);return t*s}var F=class{memories=new Map;conflicts=new Y;remember(e){let n=(e.createdAt&&Number.isFinite(Date.parse(e.createdAt))?new Date(e.createdAt).toISOString():void 0)??new Date().toISOString(),o=Ne(e.content.trim()),i=e.importance??be(e.type,o),s={id:Hr(),projectId:e.projectId,type:e.type,content:o,importance:i,importanceScore:ve(i),tags:e.tags??[],source:e.source??"agent",createdAt:n,updatedAt:n,expiresAt:e.expiresAt??Ze(e.type,i,new Date(n)),metadata:w(e.metadata)};s.metadata={...s.metadata??{},lifecycleState:"active"},s.metadata={...s.metadata,conflictKind:v(s)};let a=this.conflicts.resolve(s,this.list(e.projectId));if(a.superseded.length>0){s.metadata={...s.metadata??{},supersedes:a.superseded.map(c=>c.id)};for(let c of a.superseded)c.updatedAt=n,c.metadata={...c.metadata??{},supersededBy:s.id,supersededAt:n,lifecycleState:"superseded"},this.memories.set(c.id,c)}if(a.completed.length>0){s.metadata={...s.metadata??{},completes:a.completed.map(c=>c.id)};for(let c of a.completed)c.updatedAt=n,c.metadata={...c.metadata??{},lifecycleState:"completed",completedBy:s.id,completedAt:n},this.memories.set(c.id,c)}if(a.resolved.length>0){s.metadata={...s.metadata??{},resolves:a.resolved.map(c=>c.id)};for(let c of a.resolved)c.updatedAt=n,c.metadata={...c.metadata??{},lifecycleState:"resolved",resolvedBy:s.id,resolvedAt:n},this.memories.set(c.id,c)}if(a.conflicts.length>0){let c=a.conflicts.map(d=>d.id);s.metadata={...s.metadata??{},conflictsWith:c,lifecycleState:"conflicting"};for(let d of a.conflicts){let p=Array.isArray(d.metadata?.conflictsWith)?d.metadata?.conflictsWith:[],f=new Set(p.filter(l=>typeof l=="string"));f.add(s.id),d.updatedAt=n,d.metadata={...d.metadata??{},conflictsWith:[...f]},this.memories.set(d.id,d)}}return this.memories.set(s.id,s),s}importRecords(e){let t=0;for(let n of e){if(!n?.id)continue;let o=w(n);this.memories.set(o.id,o),t++}return t}exportProject(e){return this.listAll(e)}get(e){return this.memories.get(e)}delete(e){return this.memories.delete(e)}listAll(e){return[...this.memories.values()].filter(t=>t.projectId===e).sort((t,n)=>n.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>ae(t))}recent(e,t=10){return this.list(e).slice(0,t)}byType(e,t){return this.list(e).filter(n=>n.type===t)}search(e){let t=e.query.trim().toLowerCase(),n=e.limit??10,o=t.split(/\s+/).filter(Boolean);return this.list(e.projectId).filter(i=>{if(e.types&&!e.types.includes(i.type))return!1;let s=ce(i);return!(e.minImportanceScore&&s<e.minImportanceScore||e.tags?.length&&!e.tags.some(c=>i.tags.includes(c)))}).map(i=>{let s=i.content.toLowerCase(),a=o.filter(p=>s.includes(p)).length,c=o.length===0?0:a/o.length,d=ce(i)/500;return{memory:i,score:c+d,source:"memory"}}).filter(i=>t.length===0||i.score>0).sort((i,s)=>s.score-i.score).slice(0,n)}consolidate(e,t=Date.now()){let n=qe(this.list(e)),o=[],i=0;for(let s of n.groups){let a=this.memories.get(s.canonicalId);if(a){a.tags=s.mergedTags,a.metadata={...a.metadata??{},consolidation:{version:1,consolidatedAt:new Date(t).toISOString(),mergedIds:s.duplicateIds,sources:s.mergedSources}},this.memories.set(a.id,a),o.push(a.id);for(let c of s.duplicateIds)this.memories.delete(c)&&(i+=1)}}return{groupsConsolidated:o.length,duplicatesRemoved:i,canonicalIds:o}}reviewLifecycle(e,t=Date.now()){let n={reviewed:0,trusted:0,useful:0,weak:0,noise:0,stale:0,protected:0,pruned:0};for(let o of this.list(e)){let i=We(o,t);n.reviewed+=1,n[i.tier]+=1,i.stale&&(n.stale+=1),i.protected&&(n.protected+=1),o.metadata={...o.metadata??{},lifecycle:{version:1,reviewedAt:new Date(t).toISOString(),qualityScore:i.score,tier:i.tier,stale:i.stale,protected:i.protected,reasons:i.reasons}},this.memories.set(o.id,o),i.pruneEligible&&this.memories.delete(o.id)&&(n.pruned+=1)}return n}pruneExpired(e,t=Date.now()){let n=0;for(let[o,i]of this.memories)i.projectId===e&&se(i,t)&&(this.memories.delete(o),n++);return n}pruneSuperseded(e,t=30,n=Date.now()){let o=0,i=t*864e5;for(let[s,a]of this.memories){if(a.projectId!==e)continue;let c=a.metadata?.supersededAt;if(typeof c!="string")continue;n-new Date(c).getTime()>=i&&(this.memories.delete(s),o++)}return o}clearProject(e){let t=0;for(let[n,o]of this.memories)o.projectId===e&&(this.memories.delete(n),t++);return t}};import{homedir as Sn}from"node:os";import{join as wn}from"node:path";import{DeleteObjectCommand as Vr,GetObjectCommand as zr,HeadObjectCommand as Ur,ListObjectsV2Command as Br,PutObjectCommand as Yr,S3Client as Fr}from"@aws-sdk/client-s3";import{getSignedUrl as Jr}from"@aws-sdk/s3-request-presigner";var J=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Fr({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Yr({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Jr(this.client,new zr({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 Ur({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 Vr({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new Br({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}};import{access as Qe,mkdir as Gr,readFile as qr,readdir as Wr,rm as Zr,stat as Xe,writeFile as Qr}from"node:fs/promises";import{dirname as Xr,join as en,relative as et,resolve as tn}from"node:path";var j=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return tn(this.root,t)}async put(e,t){let n=this.path(e);await Gr(Xr(n),{recursive:!0}),await Qr(n,t)}async get(e){try{return await qr(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 Qe(this.path(e)),!0}catch{return!1}}async delete(e){await Zr(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await Qe(t)}catch{return n}let o=async s=>{let a=await Wr(s,{withFileTypes:!0});for(let c of a){let d=en(s,c.name);if(c.isDirectory()){await o(d);continue}let p=await Xe(d);n.push({key:et(this.root,d),size:p.size,updatedAt:p.mtime.toISOString()})}},i=await Xe(t);return i.isDirectory()?await o(t):n.push({key:et(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),n}};import{DeleteObjectCommand as rn,GetObjectCommand as nn,HeadObjectCommand as on,ListObjectsV2Command as sn,PutObjectCommand as an,S3Client as cn}from"@aws-sdk/client-s3";import{getSignedUrl as dn}from"@aws-sdk/s3-request-presigner";var T=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new cn({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new an({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await dn(this.client,new nn({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 on({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 rn({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new sn({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let i of o.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}};import{createCipheriv as un,createDecipheriv as pn,createHash as ln,randomBytes as mn,timingSafeEqual as fn}from"node:crypto";import{readFileSync as gn}from"node:fs";var b=Buffer.from("TNMEME01","ascii"),rt=1,O=8,C=12,de=16,nt=b.length+1+O+C+de,yn="toolnet-memory:remote-encryption:v1:",ot="aes-256-gcm",ue=32,g=class extends Error{constructor(t,n){super(n);this.code=t;this.name="RemoteEncryptionError"}code};function hn(r){return r?["1","true","yes","on","enabled"].includes(r.trim().toLowerCase()):!1}function pe(r=process.env){return hn(r.TOOLNET_REMOTE_ENCRYPTION)}function tt(r){let e=r.trim();if(!e)throw new g("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 g("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 g("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!==ue)throw new g("REMOTE_ENCRYPTION_KEY_INVALID_LENGTH",`Remote encryption key must decode to exactly ${ue} bytes.`);return t}function it(r=process.env){let e=r.TOOLNET_REMOTE_ENCRYPTION_KEY?.trim(),t=r.TOOLNET_REMOTE_ENCRYPTION_KEY_FILE?.trim();if(e&&t)throw new g("REMOTE_ENCRYPTION_KEY_AMBIGUOUS","Configure either TOOLNET_REMOTE_ENCRYPTION_KEY or TOOLNET_REMOTE_ENCRYPTION_KEY_FILE, not both.");if(e)return tt(e);if(t){let n;try{n=gn(t,"utf8")}catch(o){throw new g("REMOTE_ENCRYPTION_KEY_FILE_READ_FAILED",[`Unable to read remote encryption key file: ${t}.`,o instanceof Error?o.message:String(o)].join(" "))}return tt(n)}}function st(r){return ln("sha256").update(r).digest().subarray(0,O)}function at(r){return Buffer.from(`${yn}${r}`,"utf8")}function le(r){return r.byteLength<b.length?!1:Buffer.from(r).subarray(0,b.length).equals(b)}function ct(r,e,t){if(t.byteLength!==ue)throw new g("REMOTE_ENCRYPTION_KEY_INVALID_LENGTH","AES-256-GCM requires a 32-byte key.");let n=typeof e=="string"?Buffer.from(e,"utf8"):Buffer.from(e),o=mn(C),i=un(ot,t,o);i.setAAD(at(r));let s=Buffer.concat([i.update(n),i.final()]),a=i.getAuthTag(),c=Buffer.alloc(nt),d=0;return b.copy(c,d),d+=b.length,c.writeUInt8(rt,d),d+=1,st(t).copy(c,d),d+=O,o.copy(c,d),d+=C,a.copy(c,d),Buffer.concat([c,s])}function dt(r,e,t){let n=Buffer.from(e);if(!le(n))throw new g("REMOTE_ENCRYPTION_ENVELOPE_REQUIRED","Payload is not a ToolNet encrypted remote object.");if(n.length<nt)throw new g("REMOTE_ENCRYPTION_ENVELOPE_TRUNCATED","Encrypted remote payload is truncated.");let o=b.length,i=n.readUInt8(o);if(o+=1,i!==rt)throw new g("REMOTE_ENCRYPTION_VERSION_UNSUPPORTED",`Unsupported remote encryption envelope version: ${i}.`);let s=n.subarray(o,o+O);o+=O;let a=st(t);if(!fn(s,a))throw new g("REMOTE_ENCRYPTION_KEY_MISMATCH","Configured remote encryption key does not match this encrypted object.");let c=n.subarray(o,o+C);o+=C;let d=n.subarray(o,o+de);o+=de;let p=n.subarray(o),f=pn(ot,t,c);f.setAAD(at(r)),f.setAuthTag(d);try{return Buffer.concat([f.update(p),f.final()])}catch{throw new g("REMOTE_ENCRYPTION_AUTH_FAILED","Encrypted remote object failed AES-GCM authentication.")}}var me=class{constructor(e,t){this.inner=e;this.options=t;if(this.name=e.name,t.enabled&&!t.key)throw new g("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote client-side encryption is enabled but no encryption key is configured.")}inner;options;name;async put(e,t,n){if(!this.options.enabled){await this.inner.put(e,t,n);return}let o=this.options.key;if(!o)throw new g("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote encryption key is unavailable.");let i=ct(e,t,o);await this.inner.put(e,i,"application/octet-stream")}async get(e){let t=await this.inner.get(e);if(!t)return null;if(!le(t))return t;if(!this.options.enabled)throw new g("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 g("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote object is encrypted but no decryption key is configured.");return dt(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 ut(r,e=process.env){if(r.name==="local")return pe(e)&&console.warn("[storage] Remote encryption requested but active storage provider is local; local data remains unchanged."),r;let t=pe(e),n=t?it(e):void 0;return new me(r,{enabled:t,key:n})}function _(r){return ut(r)}function fe(r,e){return console.warn(e),_(new j(r))}function pt(r){let e=r.localRoot??wn(Sn(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?_(new T({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):fe(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?_(new T({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):fe(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?_(new J({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):fe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return _(new j(e))}var G=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let n=JSON.parse(t);if(!Array.isArray(n))throw new Error("Invalid memory snapshot");return n}async save(e,t){let n=JSON.stringify(t,null,2);await this.storage.put(this.key(e),n,"application/json")}};function vn(r){return new Promise(e=>setTimeout(e,r))}async function lt(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,o=e.maxDelayMs??2e3,i;for(let s=1;s<=t;s++)try{return await r()}catch(a){if(i=a,s>=t)break;let c=Math.min(o,n*2**(s-1)),d=Math.floor(Math.random()*Math.max(1,c*.2));await vn(c+d)}throw i}var bn=new Set(["put","get","getText","delete","list"]);function mt(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:bn.has(n)?(...i)=>lt(()=>Promise.resolve(o.apply(t,i)),e):o.bind(t)}})}function ft(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 gt(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let o=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:e))}var q=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=ft(o??n),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),n=t,o=await this.provider.getText(e);if(o){let s;try{s=JSON.parse(o)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof s.id=="string"&&s.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${s.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof s.createdAt=="string"&&(n=s.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=gt(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{closeSync as xn,mkdirSync as En,openSync as Rn,readFileSync as Mn,unlinkSync as yt,writeFileSync as In}from"node:fs";import{tmpdir as An}from"node:os";import{join as ht}from"node:path";function Pn(r){try{return process.kill(r,0),!0}catch(e){return e?.code==="EPERM"}}var W=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=ht(An(),"toolnet-memory-locks");En(t,{recursive:!0});let n=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=ht(t,`${n}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Rn(this.path,"wx");In(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),xn(t),this.acquired=!0,process.once("exit",this.exitHandler);return}catch(t){if(t?.code!=="EEXIST")throw t;let n=!0;try{let o=JSON.parse(Mn(this.path,"utf8"));Number.isInteger(o.pid)&&Pn(o.pid)&&(n=!1)}catch{n=!0}if(!n)throw new Error("ToolNet Memory is already running for this project");try{yt(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{yt(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};import{createHash as Nn}from"node:crypto";import{hostname as Kn}from"node:os";import{createHash as kn,randomUUID as jn}from"node:crypto";function x(r,e){let t=r.trim();if(!t)throw new Error(`${e} is required`);return t}function Z(r,e){return encodeURIComponent(x(r,e))}function Tn(r){let e=JSON.stringify(r);if(e===void 0)throw new Error("Multi-host operation payload must be JSON serializable");return e}function wt(r){return kn("sha256").update(r).digest("hex")}function vt(r){return wt(Tn(r))}function bt(r){return Number.isFinite(Date.parse(r))}function On(r){return wt(JSON.stringify({version:r.version,operationId:r.operationId,projectId:r.projectId,scope:r.scope,hostId:r.hostId,occurredAt:r.occurredAt,payloadSha256:r.payloadSha256,payload:r.payload}))}function xt(r){let e=x(r.projectId,"projectId"),t=x(r.scope,"scope"),n=x(r.hostId,"hostId"),o=x(r.operationId??jn(),"operationId"),i=r.occurredAt??new Date().toISOString();if(!bt(i))throw new Error(`Invalid operation timestamp: ${i}`);return{version:1,operationId:o,projectId:e,scope:t,hostId:n,occurredAt:i,payloadSha256:vt(r.payload),payload:r.payload}}function Et(r,e){let t=["projects",Z(r,"projectId"),"operations"];return e?`${[...t,Z(e,"scope")].join("/")}/`:`${t.join("/")}/`}function Cn(r){return[Et(r.projectId,r.scope).replace(/\/$/,""),Z(r.hostId,"hostId"),`${Z(r.operationId,"operationId")}-${r.payloadSha256}.json`].join("/")}async function Rt(r,e){let t=Cn(e);return await r.put(t,`${JSON.stringify(e,null,2)}
5
+ `,"application/json"),t}function _n(r){let e;try{e=JSON.parse(r)}catch{return null}return e.version!==1||typeof e.operationId!="string"||typeof e.projectId!="string"||typeof e.scope!="string"||typeof e.hostId!="string"||typeof e.occurredAt!="string"||!bt(e.occurredAt)||typeof e.payloadSha256!="string"||vt(e.payload)!==e.payloadSha256?null:e}function St(r,e){let t=r.occurredAt.localeCompare(e.occurredAt);if(t!==0)return t;let n=r.hostId.localeCompare(e.hostId);if(n!==0)return n;let o=r.operationId.localeCompare(e.operationId);return o!==0?o:r.payloadSha256.localeCompare(e.payloadSha256)}async function Mt(r,e,t){let n=x(e,"projectId"),o=x(t,"scope"),i=Et(n,o),s=await r.list(i),a=[],c=[];for(let l of s){let m=await r.getText(l.key);if(!m){a.push(l.key);continue}let u=_n(m);if(!u){a.push(l.key);continue}if(u.projectId!==n){a.push(l.key);continue}if(u.scope!==o){a.push(l.key);continue}c.push(u)}let d=new Map;for(let l of c){let m=d.get(l.operationId);if(!m){d.set(l.operationId,[l]);continue}m.push(l)}let p=[],f=[];for(let[l,m]of d){if(new Set(m.map(N=>On(N))).size>1){f.push({operationId:l,variants:[...m].sort(St)});continue}let E=m[0];E&&p.push(E)}return p.sort(St),f.sort((l,m)=>l.operationId.localeCompare(m.operationId)),a.sort(),{operations:p,conflicts:f,invalidKeys:a}}function Dn(r){let t=(r??process.env.TOOLNET_HOST_ID??Kn()).trim();return t||`pid-${process.pid}`}function Ln(r){let e=t=>{if(t===null||typeof t!="object")return t;if(Array.isArray(t))return t.map(o=>e(o));let n=t;return Object.fromEntries(Object.keys(n).sort().map(o=>[o,e(n[o])]))};return JSON.stringify(e(r))}function Q(r){return Nn("sha256").update(Ln(r)).digest("hex")}function $n(r,e){let t=Q(r).slice(0,12),n=Q(e);return["memory",t,n].join("-")}function Hn(r,e){let t=r.updatedAt.localeCompare(e.updatedAt);if(t!==0)return t;let n=r.createdAt.localeCompare(e.createdAt);return n!==0?n:Q(r).localeCompare(Q(e))}function Vn(r,e){return Hn(r,e)>=0?r:e}function ge(r,e){let t=new Map;for(let n of r)t.set(n.id,n);for(let n of e){if(n.payload.kind!=="upsert")continue;let o=n.payload.memory,i=t.get(o.id);if(!i){t.set(o.id,o);continue}t.set(o.id,Vn(i,o))}return[...t.values()].sort((n,o)=>n.id.localeCompare(o.id))}var X=class{constructor(e,t={}){this.storage=e;this.legacy=new G(e),this.hostId=Dn(t.hostId)}storage;legacy;hostId;diagnostics={operationCount:0,conflicts:0,invalidKeys:0};getDiagnostics(){return{...this.diagnostics}}async operations(e){let t=await Mt(this.storage,e,"memory");return this.diagnostics={operationCount:t.operations.length,conflicts:t.conflicts.length,invalidKeys:t.invalidKeys.length},t.operations}async load(e){let t=await this.legacy.load(e),n=await this.operations(e);return ge(t,n)}async appendMemory(e,t){let n=xt({projectId:e,scope:"memory",hostId:this.hostId,operationId:$n(this.hostId,t),occurredAt:t.updatedAt,payload:{kind:"upsert",memory:t}});await Rt(this.storage,n)}async refreshProjection(e){let t=await this.legacy.load(e),n=await this.operations(e),o=ge(t,n);return await this.legacy.save(e,o),o}async save(e,t){let n=[...t].sort((s,a)=>s.id.localeCompare(a.id));for(let s of n)await this.appendMemory(e,s);let o=await this.operations(e),i=ge(t,o);await this.legacy.save(e,i)}};import{appendFileSync as zn,closeSync as Un,existsSync as It,mkdirSync as At,openSync as Bn,readFileSync as Pt,statSync as Yn,unlinkSync as kt,writeFileSync as Fn}from"node:fs";import{createHash as Jn,randomUUID as jt}from"node:crypto";import{dirname as Tt,join as Se}from"node:path";var ye="0".repeat(64),Gn=3e4,qn=100,Wn=20;function Zn(r){return new Promise(e=>{setTimeout(e,r)})}function Qn(r){return Se(r.rootPath,".toolnet","audit")}function Ot(r){return Se(Qn(r),"events.jsonl")}function Ct(r){return Se(r.rootPath,".toolnet","runtime","locks","audit.lock")}function he(r){if(Array.isArray(r))return r.map(he);if(!r||typeof r!="object")return r;let e=r;return Object.fromEntries(Object.keys(e).sort().map(t=>[t,he(e[t])]))}function Xn(r){return JSON.stringify(he(r))}function _t(r){return Jn("sha256").update(Xn(r),"utf8").digest("hex")}function eo(){let r=process.env.TOOLNET_AGENT_ID?.trim()||process.env.TOOLNET_AGENT?.trim();return r?{kind:"agent",id:r}:{kind:"system",id:`pid:${process.pid}`}}function Nt(r){let e=Ot(r);if(!It(e))return[];let t=Pt(e,"utf8"),n=[];for(let o of t.split(/\r?\n/u)){let i=o.trim();i&&n.push(JSON.parse(i))}return n}function to(r){try{return Date.now()-Yn(r).mtimeMs>Gn}catch{return!0}}async function ro(r){let e=Ct(r);At(Tt(e),{recursive:!0,mode:448});for(let t=0;t<qn;t+=1){let n=jt();try{let o=Bn(e,"wx",384);try{Fn(o,JSON.stringify({token:n,pid:process.pid,createdAt:new Date().toISOString()})+`
6
+ `)}finally{Un(o)}return n}catch(o){if(o.code!=="EEXIST")throw o;if(to(e)){try{kt(e)}catch{}continue}await Zn(Wn)}}throw new Error("AUDIT_LOCK_TIMEOUT")}function no(r,e){let t=Ct(r);if(It(t))try{if(JSON.parse(Pt(t,"utf8")).token!==e)return;kt(t)}catch{}}function oo(r){return Nt(r).at(-1)}async function io(r,e){let t=await ro(r);try{let n=oo(r);if(n){let p=so(r);if(!p.valid)throw new Error(["AUDIT_LOG_INTEGRITY_FAILED",p.error??""].filter(Boolean).join(" "))}let o=e.details?w(e.details):void 0,i=e.target?w(e.target):void 0,s=w(e.actor??eo()),a={version:1,sequence:(n?.sequence??0)+1,id:jt(),at:e.at??new Date().toISOString(),projectId:r.id,action:e.action,outcome:e.outcome,actor:s,...i?{target:i}:{},...o?{details:o}:{},previousHash:n?.hash??ye},c={...a,hash:_t(a)},d=Ot(r);return At(Tt(d),{recursive:!0,mode:448}),zn(d,JSON.stringify(c)+`
7
+ `,{encoding:"utf8",mode:384}),c}finally{no(r,t)}}async function Kt(r,e){try{return await io(r,e),!0}catch(t){return console.warn(`[audit] ${t instanceof Error?t.message:String(t)}`),!1}}function so(r){let e;try{e=Nt(r)}catch(o){return{valid:!1,records:0,lastHash:ye,firstInvalidLine:1,error:o instanceof Error?o.message:String(o)}}let t=ye,n=1;for(let o=0;o<e.length;o+=1){let i=e[o];if(i.sequence!==n)return{valid:!1,records:e.length,lastHash:t,firstInvalidLine:o+1,error:"AUDIT_SEQUENCE_INVALID"};if(i.previousHash!==t)return{valid:!1,records:e.length,lastHash:t,firstInvalidLine:o+1,error:"AUDIT_PREVIOUS_HASH_INVALID"};let{hash:s,...a}=i,c=_t(a);if(s!==c)return{valid:!1,records:e.length,lastHash:t,firstInvalidLine:o+1,error:"AUDIT_HASH_INVALID"};t=s,n+=1}return{valid:!0,records:e.length,lastHash:t}}function Dt(r){let e=r.metadata?.learningFingerprint;return typeof e=="string"?e:void 0}function Lt(r){return!r||typeof r!="object"?{}:r}function ao(r){let e=r.metadata?.confirmingSessionKeys,t=new Set;if(Array.isArray(e))for(let o of e)typeof o=="string"&&t.add(o);let n=r.metadata?.sessionKey;return typeof n=="string"&&t.add(n),t}function co(r,e){let t=ao(r),n=t.size;t.add(e.sessionKey);let o=Lt(r.metadata?.evidence),i=Lt(e.evidence),s=t.size,a=o.userExplicit===!0||i.userExplicit===!0,c=o.sourceVerified===!0||i.sourceVerified===!0,d=o.testVerified===!0||i.testVerified===!0,p=o.assistantDerived===!0&&i.assistantDerived===!0,f=Number(o.crossSessionConfirmations??0);return n!==s||f!==s||o.userExplicit!==a||o.sourceVerified!==c||o.testVerified!==d||o.assistantDerived!==p?(r.metadata={...r.metadata??{},evidence:{userExplicit:a,sourceVerified:c,testVerified:d,crossSessionConfirmations:s,assistantDerived:p},confirmingSessionKeys:[...t].sort()},!0):!1}async function uo(r,e){let t=`projects/${r.id}/memory/learned/`,n=await e.list(t),o=[];for(let i of n.filter(s=>s.key.includes("/batches/")&&s.key.endsWith(".json")).sort((s,a)=>s.key.localeCompare(a.key))){let s=await e.getText(i.key);if(s)try{let a=JSON.parse(s);if(a.version!==1||!Array.isArray(a.candidates))continue;o.push(a)}catch{}}return o}async function $t(r,e){let t=await uo(r,e),n=new X(e),o=await n.load(r.id),i=new F;i.importRecords(o);let s=new Set(o.map(m=>Dt(m)).filter(m=>!!m)),a=new Map(o.flatMap(m=>{let u=Dt(m);return u?[[u,m]]:[]})),c=0,d=0,p=0,f=0,l=[];for(let m of t)for(let u of m.candidates){if(c+=1,s.has(u.fingerprint)){p+=1;let N=a.get(u.fingerprint);f+=N&&co(N,u)?1:0;continue}let E=i.remember({projectId:r.id,type:u.type,content:u.content,importance:u.importance,tags:u.tags,source:"session-memory-learner",createdAt:u.createdAt,metadata:{learningFingerprint:u.fingerprint,learningKind:u.kind,conflictKind:u.kind,lifecycleState:"active",confidence:u.confidence,evidence:u.evidence,provenance:u.provenance,sourceCreatedAt:u.createdAt,sessionKey:u.sessionKey,agent:u.agent,nativeSessionId:u.nativeSessionId}});s.add(u.fingerprint),a.set(u.fingerprint,E),l.push({id:E.id,type:E.type,kind:u.kind,agent:u.agent}),d+=1}if(d>0||f>0){await n.save(r.id,i.exportProject(r.id));for(let m of l)await Kt(r,{action:"memory.save",outcome:"success",actor:{kind:"agent",id:m.agent},details:{memoryId:m.id,type:m.type,learningKind:m.kind,source:"session-memory-learner"}})}return{batches:t.length,candidates:c,added:d,duplicates:p,memories:i.exportProject(r.id).length}}function po(r,e){let t=r.indexOf(e);return t>=0?r[t+1]:void 0}async function lo(){let[r="help",...e]=process.argv.slice(2);if(r!=="reconcile"){console.log(`Session Memory Learner
6
8
 
7
9
  Commands:
8
10
  reconcile [--project PATH]
9
- `);return}let t=br(e,"--project")??process.cwd(),o=new R().detect(t),n=Y(),s=be(ve({provider:n.storage.provider,huggingface:n.storage.huggingface,localRoot:n.storage.localRoot}),{attempts:3}),i=new E(s,o.id,o.name,o.remote??o.name),a=new _(o.id);await a.acquire();try{let c=await Ke(o,i);console.log(JSON.stringify({project:o.name,...c},null,2))}finally{await a.release()}}xr().catch(r=>{console.error(r instanceof Error?r.message:r),process.exit(1)});
11
+ `);return}let t=po(e,"--project")??process.cwd(),n=new H().detect(t),o=we(),i=mt(pt({provider:o.storage.provider,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),{attempts:3}),s=new q(i,n.id,n.name,n.remote??n.name),a=new W(n.id);await a.acquire();try{let c=await $t(n,s);console.log(JSON.stringify({project:n.name,...c},null,2))}finally{await a.release()}}lo().catch(r=>{console.error(r instanceof Error?r.message:r),process.exit(1)});