toolnet-memory 0.3.14 → 0.3.16
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 +0 -1
- package/.release-target +1 -1
- package/README.md +182 -6
- package/bin/toolnet-memory +5 -0
- package/bundle/agy-hook.js +71 -71
- package/bundle/agy.js +65 -65
- package/bundle/api.js +15 -15
- package/bundle/auto-integrate.js +28 -28
- package/bundle/background-refresh.js +7 -7
- package/bundle/claude-hook.js +51 -50
- package/bundle/codex-context.js +29 -28
- package/bundle/codex.js +77 -77
- package/bundle/context-runtime.js +44 -43
- package/bundle/context.js +15 -15
- package/bundle/continuity-certify.js +13 -13
- package/bundle/copilot-hook.js +88 -86
- package/bundle/copilot.js +4 -4
- package/bundle/cursor-hook.js +88 -86
- package/bundle/cursor.js +4 -4
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +21 -21
- package/bundle/gc.js +3 -0
- package/bundle/graph-index.js +4 -4
- package/bundle/graph-ui.js +3 -3
- package/bundle/grok-hook.js +64 -63
- package/bundle/grok.js +5 -5
- package/bundle/handoff-refresh.js +10 -10
- package/bundle/help-cli.js +3 -3
- package/bundle/impact.js +4 -4
- package/bundle/incremental.js +5 -4
- package/bundle/init.js +38 -37
- package/bundle/integration-status.js +4 -4
- package/bundle/kiro-hook.js +93 -92
- package/bundle/learner.js +6 -6
- package/bundle/mcp.js +17 -17
- package/bundle/memory-agent.js +7 -7
- package/bundle/memory-query.js +7 -7
- package/bundle/opencode.js +84 -84
- package/bundle/project-manual.js +7 -7
- package/bundle/recovery-certify.js +15 -15
- package/bundle/runtime.js +13 -12
- package/bundle/semantic.js +5 -5
- package/bundle/snapshot.js +4 -4
- package/bundle/status-cli.js +4 -4
- package/bundle/toolnet-cli.js +60 -60
- package/bundle/work-continuity.js +7 -7
- package/package.json +21 -3
- package/release-manifest.json +104 -3
package/bundle/learner.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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}),ze(n,o)}function G(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var b=class{detect(e=process.cwd()){let t=v(e),o=Ye(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>K(x(o,l))),i=Ue(t,s?o:void 0);if(i){let l=$(i),m=We(l);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),W(i,m)),G(m,i)}let a=new Date().toISOString(),c=Ve(o),u={version:1,id:Je(o),name:c,remote:c,rootPath:o,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return W(o,u),G(u,o)}};import{randomUUID as gt}from"node:crypto";var Ge=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],k=class{scan(e){let t=[];for(let o of Ge){let n=new RegExp(o.regex.source,o.regex.flags);for(let s of e.matchAll(n))t.push({type:o.type,value:s[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var R=class{scanner=new k;sanitize(e){let t=e,o=this.scanner.scan(e),n=new Set;for(let s of o)n.add(s.type),t=t.split(s.value).join(`[REDACTED:${s.type}]`);return{text:t,redacted:o.length,secretTypes:[...n]}}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,"");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]":t[o]=this.sanitizeValue(n)}return t}return e}};var qe=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Qe=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 Z(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Qe.has(e)))}function Ze(r,e){let t=Z(r),o=Z(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 X(r){return new Set(r.tags.filter(e=>!qe.has(e.toLowerCase())))}function D(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 Xe(r){let e=D(r);return e.userExplicit||e.sourceVerified||e.testVerified||e.crossSessionConfirmations>0}function et(r){let e=Number(r.metadata?.confidence);return!Number.isFinite(e)||e<0?0:e>1?1:e}function tt(r){return r.importance==="critical"?20:r.importance==="high"?12:r.importance==="normal"?5:0}function ee(r){let e=D(r),t=tt(r);return e.userExplicit&&(t+=100),e.sourceVerified&&(t+=60),e.testVerified&&(t+=60),t+=Math.min(5,e.crossSessionConfirmations)*12,t+=et(r)*10,r.metadata?.knowledgeClass==="permanent"&&(t+=10),e.assistantDerived&&(t-=15),Math.round(t*1e3)/1e3}function te(r){let e=r.metadata?.topic;if(typeof e!="string")return;let t=e.normalize("NFKC").trim().toLowerCase();if(t)return t}function rt(r,e){let t=X(r),o=X(e);for(let n of t)if(o.has(n))return!0;return!1}function ot(r,e){if(e.id===r.id||e.projectId!==r.projectId||e.type!==r.type||e.metadata?.supersededBy)return!1;let t=te(r),o=te(e);return t&&o&&t===o||rt(r,e)?!0:Ze(r.content,e.content)>=.6}function re(r){return r.type!=="rule"?!1:D(r).userExplicit}function nt(r,e){return!re(r)||!re(e)?!1:r.createdAt>=e.createdAt}var I=class{resolve(e,t){if(e.type!=="rule"&&e.type!=="decision")return{superseded:[],conflicts:[]};let o=[],n=[],s=ee(e);for(let i of t){if(!ot(e,i))continue;let a=ee(i);if(s>a){o.push(i);continue}if(s<a){n.push(i);continue}if(nt(e,i)){o.push(i);continue}if(!Xe(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 st=new Set(["code","decision","rule","todo","summary"]);function it(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 at(r,e){let t=oe(e)-oe(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 ne(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 se(r){let e=new Map;for(let n of r){if(!st.has(n.type)||n.metadata?.supersededBy)continue;let s=it(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(at),i=s[0];if(!i)continue;let a=s.slice(1);t.push({canonicalId:i.id,duplicateIds:a.map(c=>c.id),mergedTags:ne(s.flatMap(c=>c.tags)),mergedSources:ne(s.map(c=>c.source))}),o+=a.length}return{groups:t,duplicates:o}}function H(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 ct(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function ut(r){let e=H(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 dt(r){return H(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function pt(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 ie(r,e=Date.now()){let t=50,o=[],n=H(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")),pt(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=ct(r,e)>=ut(r);a&&(t-=15,o.push("stale for lifecycle class"));let c=dt(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 lt={critical:100,high:75,normal:50,temporary:20},mt={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function ae(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 z(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function ft(r){return!!r.metadata?.supersededBy}function L(r,e=Date.now()){return!z(r,e)&&!ft(r)}function V(r,e=Date.now()){if(!L(r,e))return 0;let t=lt[r.importance];if(r.importance==="critical")return t;let o=mt[r.type]??180,s=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,i=Math.pow(.5,s/o);return t*i}var P=class{memories=new Map;sanitizer=new R;conflicts=new I;remember(e){let t=new Date().toISOString(),o=this.sanitizer.sanitize(e.content.trim()).text,n=e.importance??Y(e.type,o),s={id:gt(),projectId:e.projectId,type:e.type,content:o,importance:n,importanceScore:U(n),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??ae(e.type,n,new Date(t)),metadata:this.sanitizer.sanitizeValue(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)o?.id&&(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,o)=>o.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>L(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=V(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=V(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=se(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=ie(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&&z(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 Dt}from"node:os";import{join as Ht}from"node:path";import{DeleteObjectCommand as yt,GetObjectCommand as ht,HeadObjectCommand as St,ListObjectsV2Command as vt,PutObjectCommand as wt,S3Client as jt}from"@aws-sdk/client-s3";import{getSignedUrl as Mt}from"@aws-sdk/s3-request-presigner";var A=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new jt({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new wt({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await Mt(this.client,new ht({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 St({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 yt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new vt({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 ce,mkdir as bt,readFile as xt,readdir as kt,rm as Rt,stat as ue,writeFile as It}from"node:fs/promises";import{dirname as Pt,join as At,relative as de,resolve as Ct}from"node:path";var w=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Ct(this.root,t)}async put(e,t){let o=this.path(e);await bt(Pt(o),{recursive:!0}),await It(o,t)}async get(e){try{return await xt(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await ce(this.path(e)),!0}catch{return!1}}async delete(e){await Rt(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await ce(t)}catch{return o}let n=async i=>{let a=await kt(i,{withFileTypes:!0});for(let c of a){let u=At(i,c.name);if(c.isDirectory()){await n(u);continue}let l=await ue(u);o.push({key:de(this.root,u),size:l.size,updatedAt:l.mtime.toISOString()})}},s=await ue(t);return s.isDirectory()?await n(t):o.push({key:de(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),o}};import{DeleteObjectCommand as Ot,GetObjectCommand as Tt,HeadObjectCommand as Et,ListObjectsV2Command as _t,PutObjectCommand as Nt,S3Client as Kt}from"@aws-sdk/client-s3";import{getSignedUrl as $t}from"@aws-sdk/s3-request-presigner";var j=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Kt({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 Nt({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await $t(this.client,new Tt({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 Et({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new Ot({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new _t({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 B(r,e){return console.warn(e),new w(r)}function pe(r){let e=r.localRoot??Ht(Dt(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new j({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):B(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 j({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):B(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 A({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):B(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new w(e)}var C=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 zt(r){return new Promise(e=>setTimeout(e,r))}async function le(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 zt(c+u)}throw s}var Lt=new Set(["put","get","getText","delete","list"]);function me(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:Lt.has(o)?(...s)=>le(()=>Promise.resolve(n.apply(t,s)),e):n.bind(t)}})}function fe(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function ge(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 O=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=fe(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=
|
|
5
|
-
`,"application/json"),t}function
|
|
1
|
+
import{existsSync as st,readFileSync as at}from"node:fs";import{homedir as ct}from"node:os";import{join as dt}from"node:path";function ut(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 pt(){let r=process.env.TOOLNET_GLOBAL_ENV??dt(ct(),".config","toolnet-memory",".env");if(!st(r))return;let e=at(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]=ut(n.slice(o+1)))}}pt();function x(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function M(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function ie(){return{memory:{autoCapture:x(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:x(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:x(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:x(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:M(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:M(process.env.MEMORY_RERANK_TOP,10),finalContext:M(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:M(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:x(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:M(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var lt={critical:100,high:75,normal:50,temporary:20};function se(r){return lt[r]}function ae(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 vt}from"node:crypto";import{existsSync as E,mkdirSync as wt,readFileSync as bt,renameSync as xt,writeFileSync as Mt}from"node:fs";import{basename as jt,dirname as T,join as k,parse as ge,resolve as h}from"node:path";import{createHash as ue}from"node:crypto";import{spawnSync as mt}from"node:child_process";var j="git-remote-v1",ft=new Set(["github.com","gitlab.com","bitbucket.org"]);function pe(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:(ft.has(r)&&(t=t.toLowerCase()),t)}function gt(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=pe(t,e.pathname);return i?`${o}/${i}`:null}function yt(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=pe(t,e[2]??"");return n?`${t}/${n}`:null}function ce(r){let e=r.trim();return e?e.includes("://")?gt(e):yt(e):null}function ht(r){return ue("sha256").update(`${j}:${r}`).digest("hex")}function le(r){return ue("sha256").update(`toolnet-project:${j}:${r}`).digest("hex").slice(0,16)}function St(r){return r.split("/").filter(Boolean).at(-1)?.trim()||null}function U(r,e){let t=mt("git",["-C",r,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function de(r,e){let t=St(r);return t?{scheme:j,canonicalRemote:r,fingerprint:ht(r),repositoryName:t,source:e}:null}function me(r){let e=U(r,["remote","get-url","origin"]);if(e){let o=ce(e);if(o)return de(o,"origin")}let t=U(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=U(r,["remote","get-url",o]);if(!i)continue;let s=ce(i);s&&n.add(s)}return n.size!==1?null:de([...n][0],"unique-remote")}var ye=".toolnet",kt="project.json";function Rt(r){return vt("sha256").update(r).digest("hex").slice(0,16)}function w(r){return k(r,ye,kt)}function he(r){return E(w(r))}function fe(r,e){let t=h(r),n=ge(t).root;for(;;){if(he(t))return t;if(t===n||e&&t===h(e))break;let o=T(t);if(o===t)break;t=o}return null}function Y(r){let e=h(r),t=ge(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>E(k(e,i))))return e;if(e===t)break;let o=T(e);if(o===e)break;e=o}return h(r)}function P(r){let e;try{e=JSON.parse(bt(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:T(T(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 C(r,e){let t=k(r,ye);wt(t,{recursive:!0});let n=w(r),o=`${n}.tmp-${process.pid}`;Mt(o,JSON.stringify(e,null,2)+`
|
|
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=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,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 Or,mkdirSync as _r,openSync as Nr,readFileSync as Kr,unlinkSync as Ge,writeFileSync as Dr}from"node:fs";import{tmpdir as $r}from"node:os";import{join as Ue}from"node:path";function zr(r){try{return process.kill(r,0),!0}catch(e){return e?.code==="EPERM"}}var F=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=Ue($r(),"toolnet-memory-locks");_r(t,{recursive:!0});let n=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=Ue(t,`${n}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Nr(this.path,"wx");Dr(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),Or(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(Kr(this.path,"utf8"));Number.isInteger(o.pid)&&zr(o.pid)&&(n=!1)}catch{n=!0}if(!n)throw new Error("ToolNet Memory is already running for this project");try{Ge(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{Ge(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};import{createHash as Gr}from"node:crypto";import{hostname as Ur}from"node:os";import{createHash as Lr,randomUUID as Hr}from"node:crypto";function v(r,e){let t=r.trim();if(!t)throw new Error(`${e} is required`);return t}function B(r,e){return encodeURIComponent(v(r,e))}function Vr(r){let e=JSON.stringify(r);if(e===void 0)throw new Error("Multi-host operation payload must be JSON serializable");return e}function qe(r){return Lr("sha256").update(r).digest("hex")}function We(r){return qe(Vr(r))}function Ze(r){return Number.isFinite(Date.parse(r))}function Fr(r){return qe(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 Qe(r){let e=v(r.projectId,"projectId"),t=v(r.scope,"scope"),n=v(r.hostId,"hostId"),o=v(r.operationId??Hr(),"operationId"),i=r.occurredAt??new Date().toISOString();if(!Ze(i))throw new Error(`Invalid operation timestamp: ${i}`);return{version:1,operationId:o,projectId:e,scope:t,hostId:n,occurredAt:i,payloadSha256:We(r.payload),payload:r.payload}}function Xe(r,e){let t=["projects",B(r,"projectId"),"operations"];return e?`${[...t,B(e,"scope")].join("/")}/`:`${t.join("/")}/`}function Br(r){return[Xe(r.projectId,r.scope).replace(/\/$/,""),B(r.hostId,"hostId"),`${B(r.operationId,"operationId")}-${r.payloadSha256}.json`].join("/")}async function et(r,e){let t=Br(e);return await r.put(t,`${JSON.stringify(e,null,2)}
|
|
5
|
+
`,"application/json"),t}function Jr(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"||!Ze(e.occurredAt)||typeof e.payloadSha256!="string"||We(e.payload)!==e.payloadSha256?null:e}function Ye(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 tt(r,e,t){let n=v(e,"projectId"),o=v(t,"scope"),i=Xe(n,o),s=await r.list(i),a=[],c=[];for(let p of s){let u=await r.getText(p.key);if(!u){a.push(p.key);continue}let g=Jr(u);if(!g){a.push(p.key);continue}if(g.projectId!==n){a.push(p.key);continue}if(g.scope!==o){a.push(p.key);continue}c.push(g)}let d=new Map;for(let p of c){let u=d.get(p.operationId);if(!u){d.set(p.operationId,[p]);continue}u.push(p)}let l=[],m=[];for(let[p,u]of d){if(new Set(u.map(it=>Fr(it))).size>1){m.push({operationId:p,variants:[...u].sort(Ye)});continue}let b=u[0];b&&l.push(b)}return l.sort(Ye),m.sort((p,u)=>p.operationId.localeCompare(u.operationId)),a.sort(),{operations:l,conflicts:m,invalidKeys:a}}function Yr(r){let t=(r??process.env.TOOLNET_HOST_ID??Ur()).trim();return t||`pid-${process.pid}`}function qr(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 J(r){return Gr("sha256").update(qr(r)).digest("hex")}function Wr(r,e){let t=J(r).slice(0,12),n=J(e);return["memory",t,n].join("-")}function Zr(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:J(r).localeCompare(J(e))}function Qr(r,e){return Zr(r,e)>=0?r:e}function oe(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,Qr(i,o))}return[...t.values()].sort((n,o)=>n.id.localeCompare(o.id))}var G=class{constructor(e,t={}){this.storage=e;this.legacy=new H(e),this.hostId=Yr(t.hostId)}storage;legacy;hostId;diagnostics={operationCount:0,conflicts:0,invalidKeys:0};getDiagnostics(){return{...this.diagnostics}}async operations(e){let t=await tt(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 oe(t,n)}async appendMemory(e,t){let n=Qe({projectId:e,scope:"memory",hostId:this.hostId,operationId:Wr(this.hostId,t),occurredAt:t.updatedAt,payload:{kind:"upsert",memory:t}});await et(this.storage,n)}async refreshProjection(e){let t=await this.legacy.load(e),n=await this.operations(e),o=oe(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=oe(t,o);await this.legacy.save(e,i)}};function rt(r){let e=r.metadata?.learningFingerprint;return typeof e=="string"?e:void 0}function nt(r){return!r||typeof r!="object"?{}:r}function Xr(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 en(r,e){let t=Xr(r),n=t.size;t.add(e.sessionKey);let o=nt(r.metadata?.evidence),i=nt(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,l=o.assistantDerived===!0&&i.assistantDerived===!0,m=Number(o.crossSessionConfirmations??0);return n!==s||m!==s||o.userExplicit!==a||o.sourceVerified!==c||o.testVerified!==d||o.assistantDerived!==l?(r.metadata={...r.metadata??{},evidence:{userExplicit:a,sourceVerified:c,testVerified:d,crossSessionConfirmations:s,assistantDerived:l},confirmingSessionKeys:[...t].sort()},!0):!1}async function tn(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 ot(r,e){let t=await tn(r,e),n=new G(e),o=await n.load(r.id),i=new z;i.importRecords(o);let s=new Set(o.map(p=>rt(p)).filter(p=>!!p)),a=new Map(o.flatMap(p=>{let u=rt(p);return u?[[u,p]]:[]})),c=0,d=0,l=0,m=0;for(let p of t)for(let u of p.candidates){if(c+=1,s.has(u.fingerprint)){l+=1;let b=a.get(u.fingerprint);m+=b&&en(b,u)?1:0;continue}let g=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,g),d+=1}return(d>0||m>0)&&await n.save(r.id,i.exportProject(r.id)),{batches:t.length,candidates:c,added:d,duplicates:l,memories:i.exportProject(r.id).length}}function rn(r,e){let t=r.indexOf(e);return t>=0?r[t+1]:void 0}async function nn(){let[r="help",...e]=process.argv.slice(2);if(r!=="reconcile"){console.log(`Session Memory Learner
|
|
6
6
|
|
|
7
7
|
Commands:
|
|
8
8
|
reconcile [--project PATH]
|
|
9
|
-
`);return}let t=
|
|
9
|
+
`);return}let t=rn(e,"--project")??process.cwd(),n=new O().detect(t),o=ie(),i=Fe(He({provider:o.storage.provider,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),{attempts:3}),s=new V(i,n.id,n.name,n.remote??n.name),a=new F(n.id);await a.acquire();try{let c=await ot(n,s);console.log(JSON.stringify({project:n.name,...c},null,2))}finally{await a.release()}}nn().catch(r=>{console.error(r instanceof Error?r.message:r),process.exit(1)});
|