toolnet-memory 0.3.16 → 0.3.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +74 -0
- package/.release-target +1 -1
- package/README.md +157 -7
- package/bin/toolnet-memory +12 -0
- package/bundle/agy-hook.js +59 -59
- package/bundle/agy.js +58 -58
- package/bundle/api.js +15 -15
- package/bundle/audit.js +2 -0
- package/bundle/background-refresh.js +7 -7
- package/bundle/code-capabilities.js +2 -0
- package/bundle/codex.js +63 -63
- package/bundle/context-runtime.js +41 -41
- package/bundle/context.js +15 -15
- package/bundle/copilot-hook.js +73 -73
- package/bundle/cursor-hook.js +73 -73
- package/bundle/docker-healthcheck.js +3 -0
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +20 -19
- package/bundle/gc.js +5 -3
- package/bundle/graph-cli.js +1 -1
- package/bundle/graph-index.js +5 -4
- package/bundle/graph-ui.js +4 -3
- package/bundle/grok-hook.js +52 -52
- package/bundle/handoff-refresh.js +2 -2
- package/bundle/help-cli.js +4 -4
- package/bundle/impact.js +5 -4
- package/bundle/incremental.js +5 -5
- package/bundle/init.js +35 -35
- package/bundle/kiro-hook.js +74 -74
- package/bundle/learner.js +8 -6
- package/bundle/mcp.js +19 -17
- package/bundle/memory-agent.js +4 -4
- package/bundle/memory-query.js +3 -3
- package/bundle/opencode.js +73 -73
- package/bundle/project-manual.js +7 -7
- package/bundle/public/index.html +1089 -2306
- package/bundle/runtime.js +16 -13
- package/bundle/semantic.js +6 -5
- package/bundle/service.js +11 -6
- package/bundle/snapshot.js +6 -4
- package/bundle/status-cli.js +4 -4
- package/bundle/toolnet-cli.js +49 -49
- package/bundle/work-continuity.js +7 -7
- package/package.json +26 -2
- package/release-manifest.json +57 -1
package/bundle/learner.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import{existsSync as
|
|
2
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function
|
|
3
|
-
`,{encoding:"utf8",mode:384}),xt(o,n)}function y(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 q(r){return{version:1,scheme:j,canonicalRemote:r.canonicalRemote,fingerprint:r.fingerprint,repositoryName:r.repositoryName}}function It(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 O=class{adopt(e,t){let n=Y(h(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(he(n)){let a=P(w(n));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return y(a,n)}let o=new Date().toISOString(),i={...t.metadata};t.gitIdentity&&(i.toolnetIdentity=q(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 C(n,s),y(s,n)}recordGitIdentity(e,t,n={}){let o=this.requireExisting(e),i=w(o.rootPath),s=P(i),a=It(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:q(t)},s.updatedAt=new Date().toISOString(),C(o.rootPath,s)),y(s,o.rootPath)}findExisting(e=process.cwd()){let t=h(e),n=Y(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>E(k(n,c))),s=fe(t,i?n:void 0);if(!s)return null;let a=P(w(s));return y(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=h(e),n=Y(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>E(k(n,m))),s=fe(t,i?n:void 0);if(s){let m=w(s),p=P(m);return p.rootPath!==s&&(p.rootPath=s,p.updatedAt=new Date().toISOString(),C(s,p)),y(p,s)}let a=new Date().toISOString(),c=jt(n),d=me(n),l={version:1,id:d?le(d.canonicalRemote):Rt(n),name:c,remote:d?.repositoryName??c,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:d?{toolnetIdentity:q(d)}:void 0};return C(n,l),y(l,n)}};import{randomUUID as sr}from"node:crypto";var At=[{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"}],Pt=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function Se(r){return r.normalize("NFKC").trim().toLowerCase()}function Ct(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 Et(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function Tt(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 Ot(r,e){return r.start<e.end&&e.start<r.end}function ve(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var _=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=Se(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let i of At){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=ve(t),o=[];for(let i of n)o.some(s=>Ot(s,i))||o.push(i);return ve(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=Se(e);return Pt.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)||Et(i)||!/[A-Za-z]/u.test(i)||!/[0-9]/u.test(i)||Tt(e,o.index,o.index+i.length)&&(Ct(i)<3.7||t.push({type:"high_entropy_secret",value:i,start:o.index,end:o.index+i.length,confidence:"heuristic"}))}return t}};var N=class{scanner;constructor(e={}){this.scanner=new _(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let n=e,o=[...t].sort((s,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 we=new N;function be(r){return we.sanitize(r).text}function W(r){return we.sanitizeValue(r)}var _t=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"]),Nt=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"]),Kt=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"]),Dt=new Set(["rule","decision","todo","next_action","fix","context","architecture"]);function f(r){return r.normalize("NFKC").trim().toLowerCase()}function Ce(r,e){for(let t of e){let n=r.metadata?.[t];if(typeof n!="string")continue;let o=f(n);if(o)return o}}function Ee(r,e){for(let t of r.tags){let n=f(t);for(let o of e){if(!n.startsWith(o))continue;let i=n.slice(o.length).trim();if(i)return i}}}function K(r){if(typeof r!="string")return;let e=f(r).replaceAll("-","_");if(e==="nextaction")return"next_action";if(Dt.has(e))return e}function S(r){let e=K(r.metadata?.conflictKind);if(e)return e;let t=K(r.metadata?.learningKind);if(t)return t;let n=K(r.metadata?.lifecycleKind);if(n)return n;for(let o of r.tags){let i=f(o);if(!i.startsWith("kind:"))continue;let s=K(i.slice(5));if(s)return s}return r.tags.some(o=>f(o)==="next_action")?"next_action":r.type==="rule"?"rule":r.type==="decision"?"decision":r.type==="todo"?"todo":"other"}function $t(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 Q(r){return new Set(f(r).replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/u).filter(e=>e.length>2&&!Nt.has(e)))}function xe(r){return new Set([...Q(r)].filter(e=>!Kt.has(e)))}function Te(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 zt(r,e){return Te(Q(r),Q(e))}function Lt(r,e){return Te(xe(r),xe(e))}function Me(r){return new Set(r.tags.map(f).filter(e=>!(_t.has(e)||e.startsWith("class:")||e.startsWith("kind:")||e.startsWith("level:"))))}function Ht(r,e){let t=Me(r),n=Me(e);for(let o of t)if(n.has(o))return!0;return!1}function je(r){return Ce(r,["topic","topicKey"])??Ee(r,["topic:"])}function ke(r){return Ce(r,["entity","entityKey","subject","taskId","taskKey"])??Ee(r,["entity:","subject:","task:"])}function Re(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(f).filter(Boolean)):new Set}function Vt(r,e){let t=Re(r);if(t.size===0)return!1;let n=Re(e);for(let o of t)if(n.has(o))return!0;return!1}function R(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 Ft(r){let e=R(r);return e.userExplicit||e.sourceVerified||e.testVerified||e.crossSessionConfirmations>0}function Bt(r){let e=Number(r.metadata?.confidence);return Number.isFinite(e)?Math.max(0,Math.min(1,e)):0}function Jt(r){return r.importance==="critical"?20:r.importance==="high"?12:r.importance==="normal"?5:0}function Ie(r){let e=R(r),t=Jt(r);return e.userExplicit&&(t+=100),e.sourceVerified&&(t+=60),e.testVerified&&(t+=60),t+=Math.min(5,e.crossSessionConfirmations)*12,t+=Bt(r)*10,r.metadata?.knowledgeClass==="permanent"&&(t+=10),e.assistantDerived&&(t-=15),Math.round(t*1e3)/1e3}function Gt(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 Ut(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 Yt(r,e){if(e.id===r.id||e.projectId!==r.projectId)return!1;let t=$t(e);if(["superseded","resolved","completed","stale"].includes(t))return!1;let n=S(r),o=S(e);if(!Gt(n,o))return!1;let i=je(r),s=je(e);if(i&&s&&i===s)return!0;let a=ke(r),c=ke(e);if(a&&c&&a===c||Ht(r,e))return!0;let d=Ut(n,o),l=Lt(r.content,e.content);return!!(l>=d||zt(r.content,e.content)>=d||Vt(r,e)&&l>=Math.max(.3,d-.2))}function Ae(r){return S(r)==="rule"&&R(r).userExplicit}function qt(r,e){return!Ae(r)||!Ae(e)?!1:r.createdAt>=e.createdAt}function Pe(r){let e=R(r);return e.userExplicit||e.sourceVerified||e.testVerified}function D(r){return r==="todo"||r==="next_action"}function Z(r,e){return r.createdAt>=e.createdAt}var $=class{resolve(e,t){let n=S(e),o={kind:n,superseded:[],conflicts:[],completed:[],resolved:[]};if(n==="other")return o;let i=Ie(e);for(let s of t){if(!Yt(e,s))continue;let a=S(s),c=Ie(s);if(n==="fix"&&D(a)){if(Pe(e)){o.completed.push(s);continue}o.conflicts.push(s);continue}if(n==="fix"&&a==="context"){if(Pe(e)&&i>=c){o.resolved.push(s);continue}o.conflicts.push(s);continue}if(D(n)&&a==="fix"){if(R(e).userExplicit||i>c){o.superseded.push(s);continue}o.conflicts.push(s);continue}if(D(n)&&D(a)){if(i>c||i===c&&Z(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(qt(e,s)){o.superseded.push(s);continue}if(["context","fix","architecture","decision"].includes(n)&&Z(e,s)){o.superseded.push(s);continue}if(!Ft(s)&&Z(e,s)){o.superseded.push(s);continue}o.conflicts.push(s)}return o}findSuperseded(e,t){return this.resolve(e,t).superseded}};var Wt=new Set(["code","decision","rule","todo","summary"]);function Zt(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function Oe(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 Qt(r,e){let t=Oe(e)-Oe(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 _e(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 Ne(r){let e=new Map;for(let o of r){if(!Wt.has(o.type)||o.metadata?.supersededBy)continue;let i=Zt(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(Qt),s=i[0];if(!s)continue;let a=i.slice(1);t.push({canonicalId:s.id,duplicateIds:a.map(c=>c.id),mergedTags:_e(i.flatMap(c=>c.tags)),mergedSources:_e(i.map(c=>c.source))}),n+=a.length}return{groups:t,duplicates:n}}function X(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 Xt(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function er(r){let e=X(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 tr(r){return X(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function rr(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 Ke(r,e=Date.now()){let t=50,n=[],o=X(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")),rr(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=Xt(r,e)>=er(r);a&&(t-=15,n.push("stale for lifecycle class"));let c=tr(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 l=r.importance==="temporary"||r.type==="activity"||o==="transient";return{score:t,tier:d,stale:a,protected:c,pruneEligible:!c&&(d==="noise"&&l||a&&(d==="noise"||d==="weak")),reasons:n}}var nr={critical:100,high:75,normal:50,temporary:20},or={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function De(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 ee(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function ir(r){return!!r.metadata?.supersededBy||r.metadata?.lifecycleState==="superseded"}function te(r,e=Date.now()){if(ee(r,e)||ir(r))return!1;let t=r.metadata?.lifecycleState;return!(t==="completed"||t==="resolved"||t==="conflicting"||t==="stale")}function re(r,e=Date.now()){if(!te(r,e))return 0;let t=nr[r.importance];if(r.importance==="critical")return t;let n=or[r.type]??180,i=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,s=Math.pow(.5,i/n);return t*s}var z=class{memories=new Map;conflicts=new $;remember(e){let n=(e.createdAt&&Number.isFinite(Date.parse(e.createdAt))?new Date(e.createdAt).toISOString():void 0)??new Date().toISOString(),o=be(e.content.trim()),i=e.importance??ae(e.type,o),s={id:sr(),projectId:e.projectId,type:e.type,content:o,importance:i,importanceScore:se(i),tags:e.tags??[],source:e.source??"agent",createdAt:n,updatedAt:n,expiresAt:e.expiresAt??De(e.type,i,new Date(n)),metadata:W(e.metadata)};s.metadata={...s.metadata??{},lifecycleState:"active"},s.metadata={...s.metadata,conflictKind:S(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 l=Array.isArray(d.metadata?.conflictsWith)?d.metadata?.conflictsWith:[],m=new Set(l.filter(p=>typeof p=="string"));m.add(s.id),d.updatedAt=n,d.metadata={...d.metadata??{},conflictsWith:[...m]},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=>te(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=re(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(l=>s.includes(l)).length,c=o.length===0?0:a/o.length,d=re(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=Ne(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=Ke(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&&ee(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 Pr}from"node:os";import{join as Cr}from"node:path";import{DeleteObjectCommand as ar,GetObjectCommand as cr,HeadObjectCommand as dr,ListObjectsV2Command as ur,PutObjectCommand as pr,S3Client as lr}from"@aws-sdk/client-s3";import{getSignedUrl as mr}from"@aws-sdk/s3-request-presigner";var L=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new lr({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 pr({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await mr(this.client,new cr({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 dr({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 ar({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new ur({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 $e,mkdir as fr,readFile as gr,readdir as yr,rm as hr,stat as ze,writeFile as Sr}from"node:fs/promises";import{dirname as vr,join as wr,relative as Le,resolve as br}from"node:path";var I=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return br(this.root,t)}async put(e,t){let n=this.path(e);await fr(vr(n),{recursive:!0}),await Sr(n,t)}async get(e){try{return await gr(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 $e(this.path(e)),!0}catch{return!1}}async delete(e){await hr(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await $e(t)}catch{return n}let o=async s=>{let a=await yr(s,{withFileTypes:!0});for(let c of a){let d=wr(s,c.name);if(c.isDirectory()){await o(d);continue}let l=await ze(d);n.push({key:Le(this.root,d),size:l.size,updatedAt:l.mtime.toISOString()})}},i=await ze(t);return i.isDirectory()?await o(t):n.push({key:Le(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),n}};import{DeleteObjectCommand as xr,GetObjectCommand as Mr,HeadObjectCommand as jr,ListObjectsV2Command as kr,PutObjectCommand as Rr,S3Client as Ir}from"@aws-sdk/client-s3";import{getSignedUrl as Ar}from"@aws-sdk/s3-request-presigner";var A=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Ir({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 Rr({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Ar(this.client,new Mr({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 jr({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 xr({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new kr({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}};function ne(r,e){return console.warn(e),new I(r)}function He(r){let e=r.localRoot??Cr(Pr(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new A({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):ne(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 A({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):ne(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 L({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):ne(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new I(e)}var H=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 Er(r){return new Promise(e=>setTimeout(e,r))}async function Ve(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 Er(c+d)}throw i}var Tr=new Set(["put","get","getText","delete","list"]);function Fe(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:Tr.has(n)?(...i)=>Ve(()=>Promise.resolve(o.apply(t,i)),e):o.bind(t)}})}function Be(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function 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 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 V=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=Be(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=
|
|
5
|
-
`,"application/json"),t}function
|
|
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=
|
|
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)});
|