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.
Files changed (45) hide show
  1. package/.env.example +74 -0
  2. package/.release-target +1 -1
  3. package/README.md +157 -7
  4. package/bin/toolnet-memory +12 -0
  5. package/bundle/agy-hook.js +59 -59
  6. package/bundle/agy.js +58 -58
  7. package/bundle/api.js +15 -15
  8. package/bundle/audit.js +2 -0
  9. package/bundle/background-refresh.js +7 -7
  10. package/bundle/code-capabilities.js +2 -0
  11. package/bundle/codex.js +63 -63
  12. package/bundle/context-runtime.js +41 -41
  13. package/bundle/context.js +15 -15
  14. package/bundle/copilot-hook.js +73 -73
  15. package/bundle/cursor-hook.js +73 -73
  16. package/bundle/docker-healthcheck.js +3 -0
  17. package/bundle/doctor.js +4 -4
  18. package/bundle/full-index.js +20 -19
  19. package/bundle/gc.js +5 -3
  20. package/bundle/graph-cli.js +1 -1
  21. package/bundle/graph-index.js +5 -4
  22. package/bundle/graph-ui.js +4 -3
  23. package/bundle/grok-hook.js +52 -52
  24. package/bundle/handoff-refresh.js +2 -2
  25. package/bundle/help-cli.js +4 -4
  26. package/bundle/impact.js +5 -4
  27. package/bundle/incremental.js +5 -5
  28. package/bundle/init.js +35 -35
  29. package/bundle/kiro-hook.js +74 -74
  30. package/bundle/learner.js +8 -6
  31. package/bundle/mcp.js +19 -17
  32. package/bundle/memory-agent.js +4 -4
  33. package/bundle/memory-query.js +3 -3
  34. package/bundle/opencode.js +73 -73
  35. package/bundle/project-manual.js +7 -7
  36. package/bundle/public/index.html +1089 -2306
  37. package/bundle/runtime.js +16 -13
  38. package/bundle/semantic.js +6 -5
  39. package/bundle/service.js +11 -6
  40. package/bundle/snapshot.js +6 -4
  41. package/bundle/status-cli.js +4 -4
  42. package/bundle/toolnet-cli.js +49 -49
  43. package/bundle/work-continuity.js +7 -7
  44. package/package.json +26 -2
  45. package/release-manifest.json +57 -1
package/bundle/api.js CHANGED
@@ -1,15 +1,15 @@
1
- import"dotenv/config";import{existsSync as cn,readFileSync as un}from"node:fs";import{homedir as ln}from"node:os";import{join as dn}from"node:path";function mn(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 pn(){let r=process.env.TOOLNET_GLOBAL_ENV??dn(ln(),".config","toolnet-memory",".env");if(!cn(r))return;let e=un(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]=mn(n.slice(o+1)))}}pn();function _(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function N(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function Se(){return{memory:{autoCapture:_(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:_(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:_(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:_(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:N(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:N(process.env.MEMORY_RERANK_TOP,10),finalContext:N(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:N(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:_(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:N(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var fn={critical:100,high:75,normal:50,temporary:20};function We(r){return fn[r]}function ze(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 bn}from"node:crypto";import{existsSync as ee,mkdirSync as Sn,readFileSync as xn,renameSync as Mn,writeFileSync as An}from"node:fs";import{basename as Cn,dirname as te,join as $,parse as Ye,resolve as C}from"node:path";import{createHash as qe}from"node:crypto";import{spawnSync as gn}from"node:child_process";var K="git-remote-v1",yn=new Set(["github.com","gitlab.com","bitbucket.org"]);function Be(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:(yn.has(r)&&(t=t.toLowerCase()),t)}function hn(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=Be(t,e.pathname);return i?`${o}/${i}`:null}function kn(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=Be(t,e[2]??"");return n?`${t}/${n}`:null}function Ge(r){let e=r.trim();return e?e.includes("://")?hn(e):kn(e):null}function vn(r){return qe("sha256").update(`${K}:${r}`).digest("hex")}function Ue(r){return qe("sha256").update(`toolnet-project:${K}:${r}`).digest("hex").slice(0,16)}function wn(r){return r.split("/").filter(Boolean).at(-1)?.trim()||null}function xe(r,e){let t=gn("git",["-C",r,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function Ve(r,e){let t=wn(r);return t?{scheme:K,canonicalRemote:r,fingerprint:vn(r),repositoryName:t,source:e}:null}function Je(r){let e=xe(r,["remote","get-url","origin"]);if(e){let o=Ge(e);if(o)return Ve(o,"origin")}let t=xe(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=xe(r,["remote","get-url",o]);if(!i)continue;let s=Ge(i);s&&n.add(s)}return n.size!==1?null:Ve([...n][0],"unique-remote")}var Xe=".toolnet",Pn="project.json";function In(r){return bn("sha256").update(r).digest("hex").slice(0,16)}function R(r){return $(r,Xe,Pn)}function Ze(r){return ee(R(r))}function Qe(r,e){let t=C(r),n=Ye(t).root;for(;;){if(Ze(t))return t;if(t===n||e&&t===C(e))break;let o=te(t);if(o===t)break;t=o}return null}function Me(r){let e=C(r),t=Ye(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>ee($(e,i))))return e;if(e===t)break;let o=te(e);if(o===e)break;e=o}return C(r)}function X(r){let e;try{e=JSON.parse(xn(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:te(te(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 Z(r,e){let t=$(r,Xe);Sn(t,{recursive:!0});let n=R(r),o=`${n}.tmp-${process.pid}`;An(o,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Mn(o,n)}function A(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 Ae(r){return{version:1,scheme:K,canonicalRemote:r.canonicalRemote,fingerprint:r.fingerprint,repositoryName:r.repositoryName}}function Tn(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 re=class{adopt(e,t){let n=Me(C(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(Ze(n)){let a=X(R(n));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return A(a,n)}let o=new Date().toISOString(),i={...t.metadata};t.gitIdentity&&(i.toolnetIdentity=Ae(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 Z(n,s),A(s,n)}recordGitIdentity(e,t,n={}){let o=this.requireExisting(e),i=R(o.rootPath),s=X(i),a=Tn(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:Ae(t)},s.updatedAt=new Date().toISOString(),Z(o.rootPath,s)),A(s,o.rootPath)}findExisting(e=process.cwd()){let t=C(e),n=Me(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>ee($(n,c))),s=Qe(t,i?n:void 0);if(!s)return null;let a=X(R(s));return A(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=C(e),n=Me(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>ee($(n,p))),s=Qe(t,i?n:void 0);if(s){let p=R(s),g=X(p);return g.rootPath!==s&&(g.rootPath=s,g.updatedAt=new Date().toISOString(),Z(s,g)),A(g,s)}let a=new Date().toISOString(),c=Cn(n),u=Je(n),l={version:1,id:u?Ue(u.canonicalRemote):In(n),name:c,remote:u?.repositoryName??c,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:u?{toolnetIdentity:Ae(u)}:void 0};return Z(n,l),A(l,n)}};import{randomUUID as co}from"node:crypto";var Rn=[{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"}],jn=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function et(r){return r.normalize("NFKC").trim().toLowerCase()}function En(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 On(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function _n(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 Nn(r,e){return r.start<e.end&&e.start<r.end}function tt(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var ne=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=et(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let i of Rn){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=tt(t),o=[];for(let i of n)o.some(s=>Nn(s,i))||o.push(i);return tt(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=et(e);return jn.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)||On(i)||!/[A-Za-z]/u.test(i)||!/[0-9]/u.test(i)||_n(e,o.index,o.index+i.length)&&(En(i)<3.7||t.push({type:"high_entropy_secret",value:i,start:o.index,end:o.index+i.length,confidence:"heuristic"}))}return t}};var j=class{scanner;constructor(e={}){this.scanner=new ne(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 rt=new j;function nt(r){return rt.sanitize(r).text}function oe(r){return rt.sanitizeValue(r)}var Kn=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"]),$n=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"]),Fn=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"]),Ln=new Set(["rule","decision","todo","next_action","fix","context","architecture"]);function b(r){return r.normalize("NFKC").trim().toLowerCase()}function mt(r,e){for(let t of e){let n=r.metadata?.[t];if(typeof n!="string")continue;let o=b(n);if(o)return o}}function pt(r,e){for(let t of r.tags){let n=b(t);for(let o of e){if(!n.startsWith(o))continue;let i=n.slice(o.length).trim();if(i)return i}}}function ie(r){if(typeof r!="string")return;let e=b(r).replaceAll("-","_");if(e==="nextaction")return"next_action";if(Ln.has(e))return e}function P(r){let e=ie(r.metadata?.conflictKind);if(e)return e;let t=ie(r.metadata?.learningKind);if(t)return t;let n=ie(r.metadata?.lifecycleKind);if(n)return n;for(let o of r.tags){let i=b(o);if(!i.startsWith("kind:"))continue;let s=ie(i.slice(5));if(s)return s}return r.tags.some(o=>b(o)==="next_action")?"next_action":r.type==="rule"?"rule":r.type==="decision"?"decision":r.type==="todo"?"todo":"other"}function Hn(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 Pe(r){return new Set(b(r).replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/u).filter(e=>e.length>2&&!$n.has(e)))}function ot(r){return new Set([...Pe(r)].filter(e=>!Fn.has(e)))}function ft(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 Dn(r,e){return ft(Pe(r),Pe(e))}function Wn(r,e){return ft(ot(r),ot(e))}function it(r){return new Set(r.tags.map(b).filter(e=>!(Kn.has(e)||e.startsWith("class:")||e.startsWith("kind:")||e.startsWith("level:"))))}function zn(r,e){let t=it(r),n=it(e);for(let o of t)if(n.has(o))return!0;return!1}function st(r){return mt(r,["topic","topicKey"])??pt(r,["topic:"])}function at(r){return mt(r,["entity","entityKey","subject","taskId","taskKey"])??pt(r,["entity:","subject:","task:"])}function ct(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(b).filter(Boolean)):new Set}function Gn(r,e){let t=ct(r);if(t.size===0)return!1;let n=ct(e);for(let o of t)if(n.has(o))return!0;return!1}function F(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 Vn(r){let e=F(r);return e.userExplicit||e.sourceVerified||e.testVerified||e.crossSessionConfirmations>0}function qn(r){let e=Number(r.metadata?.confidence);return Number.isFinite(e)?Math.max(0,Math.min(1,e)):0}function Bn(r){return r.importance==="critical"?20:r.importance==="high"?12:r.importance==="normal"?5:0}function ut(r){let e=F(r),t=Bn(r);return e.userExplicit&&(t+=100),e.sourceVerified&&(t+=60),e.testVerified&&(t+=60),t+=Math.min(5,e.crossSessionConfirmations)*12,t+=qn(r)*10,r.metadata?.knowledgeClass==="permanent"&&(t+=10),e.assistantDerived&&(t-=15),Math.round(t*1e3)/1e3}function Un(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 Jn(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 Qn(r,e){if(e.id===r.id||e.projectId!==r.projectId)return!1;let t=Hn(e);if(["superseded","resolved","completed","stale"].includes(t))return!1;let n=P(r),o=P(e);if(!Un(n,o))return!1;let i=st(r),s=st(e);if(i&&s&&i===s)return!0;let a=at(r),c=at(e);if(a&&c&&a===c||zn(r,e))return!0;let u=Jn(n,o),l=Wn(r.content,e.content);return!!(l>=u||Dn(r.content,e.content)>=u||Gn(r,e)&&l>=Math.max(.3,u-.2))}function lt(r){return P(r)==="rule"&&F(r).userExplicit}function Yn(r,e){return!lt(r)||!lt(e)?!1:r.createdAt>=e.createdAt}function dt(r){let e=F(r);return e.userExplicit||e.sourceVerified||e.testVerified}function se(r){return r==="todo"||r==="next_action"}function Ce(r,e){return r.createdAt>=e.createdAt}var ae=class{resolve(e,t){let n=P(e),o={kind:n,superseded:[],conflicts:[],completed:[],resolved:[]};if(n==="other")return o;let i=ut(e);for(let s of t){if(!Qn(e,s))continue;let a=P(s),c=ut(s);if(n==="fix"&&se(a)){if(dt(e)){o.completed.push(s);continue}o.conflicts.push(s);continue}if(n==="fix"&&a==="context"){if(dt(e)&&i>=c){o.resolved.push(s);continue}o.conflicts.push(s);continue}if(se(n)&&a==="fix"){if(F(e).userExplicit||i>c){o.superseded.push(s);continue}o.conflicts.push(s);continue}if(se(n)&&se(a)){if(i>c||i===c&&Ce(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(Yn(e,s)){o.superseded.push(s);continue}if(["context","fix","architecture","decision"].includes(n)&&Ce(e,s)){o.superseded.push(s);continue}if(!Vn(s)&&Ce(e,s)){o.superseded.push(s);continue}o.conflicts.push(s)}return o}findSuperseded(e,t){return this.resolve(e,t).superseded}};var Xn=new Set(["code","decision","rule","todo","summary"]);function Zn(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function gt(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 eo(r,e){let t=gt(e)-gt(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 yt(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 ht(r){let e=new Map;for(let o of r){if(!Xn.has(o.type)||o.metadata?.supersededBy)continue;let i=Zn(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(eo),s=i[0];if(!s)continue;let a=i.slice(1);t.push({canonicalId:s.id,duplicateIds:a.map(c=>c.id),mergedTags:yt(i.flatMap(c=>c.tags)),mergedSources:yt(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 to(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function ro(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 no(r){return Ie(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function oo(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 kt(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")),oo(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=to(r,e)>=ro(r);a&&(t-=15,n.push("stale for lifecycle class"));let c=no(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"||o==="transient";return{score:t,tier:u,stale:a,protected:c,pruneEligible:!c&&(u==="noise"&&l||a&&(u==="noise"||u==="weak")),reasons:n}}var io={critical:100,high:75,normal:50,temporary:20},so={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function vt(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 Te(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function ao(r){return!!r.metadata?.supersededBy||r.metadata?.lifecycleState==="superseded"}function Re(r,e=Date.now()){if(Te(r,e)||ao(r))return!1;let t=r.metadata?.lifecycleState;return!(t==="completed"||t==="resolved"||t==="conflicting"||t==="stale")}function L(r,e=Date.now()){if(!Re(r,e))return 0;let t=io[r.importance];if(r.importance==="critical")return t;let n=so[r.type]??180,i=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,s=Math.pow(.5,i/n);return t*s}var ce=class{memories=new Map;conflicts=new ae;remember(e){let n=(e.createdAt&&Number.isFinite(Date.parse(e.createdAt))?new Date(e.createdAt).toISOString():void 0)??new Date().toISOString(),o=nt(e.content.trim()),i=e.importance??ze(e.type,o),s={id:co(),projectId:e.projectId,type:e.type,content:o,importance:i,importanceScore:We(i),tags:e.tags??[],source:e.source??"agent",createdAt:n,updatedAt:n,expiresAt:e.expiresAt??vt(e.type,i,new Date(n)),metadata:oe(e.metadata)};s.metadata={...s.metadata??{},lifecycleState:"active"},s.metadata={...s.metadata,conflictKind:P(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(u=>u.id);s.metadata={...s.metadata??{},conflictsWith:c,lifecycleState:"conflicting"};for(let u of a.conflicts){let l=Array.isArray(u.metadata?.conflictsWith)?u.metadata?.conflictsWith:[],p=new Set(l.filter(g=>typeof g=="string"));p.add(s.id),u.updatedAt=n,u.metadata={...u.metadata??{},conflictsWith:[...p]},this.memories.set(u.id,u)}}return this.memories.set(s.id,s),s}importRecords(e){let t=0;for(let n of e){if(!n?.id)continue;let o=oe(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=>Re(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=L(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,u=L(i)/500;return{memory:i,score:c+u,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=ht(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=kt(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&&Te(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}};function je(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var ue=class{score(e,t){let n=je(e),o=je([t.content,...t.tags??[],t.type].join(" "));if(n.length===0||o.length===0)return 0;let i=new Map;for(let a of o)i.set(a,(i.get(a)??0)+1);let s=0;for(let a of n){let c=i.get(a)??0;c!==0&&(s+=1+Math.log(1+c))}return s/n.length}};function wt(r,e=Date.now()){let t=r.updatedAt??r.createdAt,n=new Date(t).getTime();if(!Number.isFinite(n))return 0;let o=Math.max(0,e-n)/864e5;return Math.exp(-Math.LN2*o/30)}function bt(r){return L(r)/100}var uo={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function St(r){return uo[r]??.4}var le=class{analyze(e){let t=e.toLowerCase(),n=[];return(t.includes("quy\u1EBFt \u0111\u1ECBnh")||t.includes("decision")||t.includes("\u0111\xE3 ch\u1ECDn"))&&n.push("decision"),(t.includes("todo")||t.includes("c\u1EA7n l\xE0m")||t.includes("ti\u1EBFp theo")||t.includes("ch\u01B0a xong"))&&n.push("todo"),(t.includes("quy t\u1EAFc")||t.includes("rule")||t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c"))&&n.push("rule"),(t.includes("t\xF3m t\u1EAFt")||t.includes("summary")||t.includes("\u0111\xE3 l\xE0m"))&&n.push("summary"),{query:e,preferredTypes:n}}};var de=class{bm25=new ue;analyzer=new le;search(e,t,n={}){let o=n.topK??8,i=n.minScore??.05,s=this.analyzer.analyze(e),a=[];for(let c of t){if(n.types?.length&&!n.types.includes(c.type))continue;let u=this.bm25.score(e,c),l=wt(c),p=bt(c),g=St(c.type);s.preferredTypes.includes(c.type)&&(g=Math.min(1,g+.25));let y=u*.55+p*.2+l*.15+g*.1;u<=0||y<i||a.push({memory:c,score:y,scores:{keyword:u,recency:l,importance:p,type:g}})}return a.sort((c,u)=>u.score-c.score).slice(0,o)}};var me=class{build(e,t=6e3){let n=[],o=0;for(let i of e){let s=i.memory,a=[`[${s.type.toUpperCase()}]`,s.content].join(" ");if(o+a.length>t)break;n.push(a),o+=a.length}return n.join(`
4
- `)}};var pe=class{constructor(e){this.memory=e}memory;searcher=new de;contextBuilder=new me;search(e,t,n={}){return this.searcher.search(t,this.memory.list(e),n)}context(e,t,n={}){let o=this.search(e,t,n);return this.contextBuilder.build(o)}};import{homedir as Oo}from"node:os";import{join as _o}from"node:path";import{DeleteObjectCommand as lo,GetObjectCommand as mo,HeadObjectCommand as po,ListObjectsV2Command as fo,PutObjectCommand as go,S3Client as yo}from"@aws-sdk/client-s3";import{getSignedUrl as ho}from"@aws-sdk/s3-request-presigner";var fe=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new yo({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 go({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await ho(this.client,new mo({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 po({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 lo({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new fo({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 xt,mkdir as ko,readFile as vo,readdir as wo,rm as bo,stat as Mt,writeFile as So}from"node:fs/promises";import{dirname as xo,join as Mo,relative as At,resolve as Ao}from"node:path";var H=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Ao(this.root,t)}async put(e,t){let n=this.path(e);await ko(xo(n),{recursive:!0}),await So(n,t)}async get(e){try{return await vo(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 xt(this.path(e)),!0}catch{return!1}}async delete(e){await bo(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await xt(t)}catch{return n}let o=async s=>{let a=await wo(s,{withFileTypes:!0});for(let c of a){let u=Mo(s,c.name);if(c.isDirectory()){await o(u);continue}let l=await Mt(u);n.push({key:At(this.root,u),size:l.size,updatedAt:l.mtime.toISOString()})}},i=await Mt(t);return i.isDirectory()?await o(t):n.push({key:At(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),n}};import{DeleteObjectCommand as Co,GetObjectCommand as Po,HeadObjectCommand as Io,ListObjectsV2Command as To,PutObjectCommand as Ro,S3Client as jo}from"@aws-sdk/client-s3";import{getSignedUrl as Eo}from"@aws-sdk/s3-request-presigner";var D=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new jo({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 Ro({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Eo(this.client,new Po({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 Io({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 Co({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new To({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 Ee(r,e){return console.warn(e),new H(r)}function Ct(r){let e=r.localRoot??_o(Oo(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new D({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ee(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 D({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ee(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 fe({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Ee(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new H(e)}var ge=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 No(r){return new Promise(e=>setTimeout(e,r))}async function Pt(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)),u=Math.floor(Math.random()*Math.max(1,c*.2));await No(c+u)}throw i}var Ko=new Set(["put","get","getText","delete","list"]);function It(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:Ko.has(n)?(...i)=>Pt(()=>Promise.resolve(o.apply(t,i)),e):o.bind(t)}})}function Tt(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 Rt(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 ye=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=Tt(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)+`
5
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Rt(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};var S=["hub:read","teams:write","agents:write","acl:manage","loadouts:write","observability:read","wiki:read","wiki:write","governance:read","governance:write"];var jt="hub/state.v1.json";function $o(r,e){let t=new Date().toISOString();return{schema:"toolnet.memory-hub.v1",version:1,ownerPrincipal:e,project:{id:r.id,name:r.name,remote:r.remote??r.name},teams:[],agents:[],acl:[{principal:e,role:"owner",scopes:[...S],createdAt:t,updatedAt:t}],loadouts:[],observability:{requests:0,mutations:0,errors:0,events:[]},createdAt:t,updatedAt:t}}function Fo(r,e){let t=JSON.parse(r);if(t.schema!=="toolnet.memory-hub.v1"||t.version!==1||!t.project||t.project.id!==e.id||!Array.isArray(t.teams)||!Array.isArray(t.agents)||!Array.isArray(t.acl)||!Array.isArray(t.loadouts)||!t.observability||!Array.isArray(t.observability.events))throw new Error("Invalid ToolNet Memory Hub state");return t}var he=class{constructor(e,t,n){this.storage=e;this.project=t;this.ownerPrincipal=n}storage;project;ownerPrincipal;async load(){let e=await this.storage.getText(jt);if(!e){let t=$o(this.project,this.ownerPrincipal);return await this.save(t),t}return Fo(e,this.project)}async save(e){await this.storage.put(jt,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as Oe}from"node:crypto";var Et=["memory_search","memory_agent_ask","skill_memory_search","context_offload_read","wiki_search","wiki_read","knowledge_governance_status"],h=class extends Error{constructor(t,n){super(t);this.statusCode=n}statusCode};function Lo(r){return r==="owner"||r==="admin"?[...S]:["hub:read"]}function _e(r){return[...new Set(r.map(e=>e.trim()).filter(Boolean))]}function Ho(r){return structuredClone(r)}var ke=class{constructor(e,t=100){this.store=e;this.maxEvents=t}store;maxEvents;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(e){let t,n=this.queue.then(async()=>{let o=await this.ensureState();t=e(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=n.then(()=>{},()=>{}),await n,t}grantFor(e,t){return e.acl.find(n=>n.principal===t)}async authorize(e,t){let n=await this.ensureState(),o=this.grantFor(n,e);return!!(o&&(o.role==="owner"||o.role==="admin"||o.scopes.includes(t)))}async requireScope(e,t){if(!await this.authorize(e,t))throw new h(`Principal '${e}' lacks '${t}'`,403)}event(e,t,n,o){return{id:Oe(),kind:e,action:t,principal:n,ok:o,timestamp:new Date().toISOString()}}pushEvent(e,t){e.observability.events.push(t),e.observability.events.length>this.maxEvents&&(e.observability.events=e.observability.events.slice(-this.maxEvents)),e.observability.lastActivityAt=t.timestamp}mutation(e,t,n){e.observability.mutations+=1,this.pushEvent(e,this.event("mutation",t,n,!0))}async summary(e){await this.requireScope(e,"hub:read");let t=await this.ensureState();return{schema:t.schema,project:{...t.project},teams:t.teams.length,agents:t.agents.length,aclGrants:t.acl.length,loadouts:t.loadouts.length,updatedAt:t.updatedAt}}async listTeams(e){return await this.requireScope(e,"hub:read"),structuredClone((await this.ensureState()).teams)}async createTeam(e,t){return await this.requireScope(e,"teams:write"),this.mutate(n=>{let o=new Date().toISOString(),i=t.id?.trim()||`team-${Oe().slice(0,8)}`;if(n.teams.some(a=>a.id===i))throw new h(`Team already exists: ${i}`,409);let s={id:i,name:t.name.trim(),...t.description?.trim()?{description:t.description.trim()}:{},createdAt:o,updatedAt:o};return n.teams.push(s),this.mutation(n,`team:create:${i}`,e),structuredClone(s)})}async listAgents(e){return await this.requireScope(e,"hub:read"),structuredClone((await this.ensureState()).agents)}async createAgent(e,t){return await this.requireScope(e,"agents:write"),this.mutate(n=>{let o=new Date().toISOString(),i=t.id?.trim()||`agent-${Oe().slice(0,8)}`;if(n.agents.some(c=>c.id===i))throw new h(`Agent already exists: ${i}`,409);let s=_e(t.teamIds??[]);for(let c of s)if(!n.teams.some(u=>u.id===c))throw new h(`Team not found: ${c}`,404);let a={id:i,name:t.name.trim(),...t.kind?.trim()?{kind:t.kind.trim()}:{},teamIds:s,...t.metadata?{metadata:structuredClone(t.metadata)}:{},createdAt:o,updatedAt:o};return n.agents.push(a),n.loadouts.push({agentId:i,tools:[...Et],memoryMode:"local",skillMemory:!0,contextOffload:!0,maxContextChars:6400,updatedAt:o}),this.mutation(n,`agent:create:${i}`,e),structuredClone(a)})}async listAcl(e){return await this.requireScope(e,"acl:manage"),structuredClone((await this.ensureState()).acl)}async grantAcl(e,t){return await this.requireScope(e,"acl:manage"),this.mutate(n=>{let o=new Date().toISOString(),i=_e(t.scopes??Lo(t.role));for(let c of i)if(!S.includes(c))throw new h(`Unknown Memory Hub scope: ${c}`,400);let s=n.acl.find(c=>c.principal===t.principal);if(s)return s.role=t.role,s.scopes=[...i],s.updatedAt=o,this.mutation(n,`acl:update:${t.principal}`,e),structuredClone(s);let a={principal:t.principal,role:t.role,scopes:[...i],createdAt:o,updatedAt:o};return n.acl.push(a),this.mutation(n,`acl:grant:${t.principal}`,e),structuredClone(a)})}async revokeAcl(e,t){await this.requireScope(e,"acl:manage"),await this.mutate(n=>{if(t===n.ownerPrincipal)throw new h("Memory Hub owner ACL cannot be revoked",409);let o=n.acl.length;if(n.acl=n.acl.filter(i=>i.principal!==t),n.acl.length===o)throw new h(`ACL principal not found: ${t}`,404);this.mutation(n,`acl:revoke:${t}`,e)})}async listLoadouts(e){return await this.requireScope(e,"hub:read"),structuredClone((await this.ensureState()).loadouts)}async getLoadout(e,t){await this.requireScope(e,"hub:read");let n=(await this.ensureState()).loadouts.find(o=>o.agentId===t);if(!n)throw new h(`Agent loadout not found: ${t}`,404);return structuredClone(n)}async setLoadout(e,t){return await this.requireScope(e,"loadouts:write"),this.mutate(n=>{if(!n.agents.some(s=>s.id===t.agentId))throw new h(`Agent not found: ${t.agentId}`,404);let o=new Date().toISOString(),i=n.loadouts.find(s=>s.agentId===t.agentId);return i||(i={agentId:t.agentId,tools:[...Et],memoryMode:"local",skillMemory:!0,contextOffload:!0,maxContextChars:6400,updatedAt:o},n.loadouts.push(i)),t.tools&&(i.tools=_e(t.tools)),t.memoryMode&&(i.memoryMode=t.memoryMode),t.skillMemory!==void 0&&(i.skillMemory=t.skillMemory),t.contextOffload!==void 0&&(i.contextOffload=t.contextOffload),t.maxContextChars!==void 0&&(i.maxContextChars=t.maxContextChars),i.updatedAt=o,this.mutation(n,`loadout:set:${t.agentId}`,e),structuredClone(i)})}async observability(e){return await this.requireScope(e,"observability:read"),structuredClone((await this.ensureState()).observability)}async recordRequest(e){await this.mutate(t=>{let n=e.statusCode<400;t.observability.requests+=1,n||(t.observability.errors+=1);let o={...this.event("request",`${e.method} ${e.path}`,e.principal,n),statusCode:e.statusCode,durationMs:Math.max(0,Math.floor(e.durationMs))};this.pushEvent(t,o)})}async snapshot(){return Ho(await this.ensureState())}};var Ot="wiki/state.v1.json";function Do(r){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:r.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function Wo(r,e){let t=JSON.parse(r);if(t.schema!=="toolnet.wiki.v1"||t.version!==1||t.projectId!==e.id||!Array.isArray(t.pages)||!Array.isArray(t.revisions))throw new Error("Invalid ToolNet Wiki state");return t}var W=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(Ot);if(!e){let t=Do(this.project);return await this.save(t),t}return Wo(e,this.project)}async save(e){await this.storage.put(Ot,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as Kt}from"node:crypto";var f=class extends Error{constructor(t,n){super(t);this.statusCode=n}statusCode};function z(r){let e=new Set,t=[];for(let n of r){let o=n.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();e.has(i)||(e.add(i),t.push(o))}return t}function G(r){let e=r.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!e)throw new f("Invalid Wiki slug",400);return e}function _t(r){let e=[];for(let t of r.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let n=t[1]?.trim();n&&e.push(G(n))}return z(e)}function zo(r){return r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function Nt(r){return{id:`revision-${Kt()}`,pageId:r.id,slug:r.slug,revision:r.revision,title:r.title,...r.summary?{summary:r.summary}:{},content:r.content,tags:[...r.tags],links:[...r.links],createdAt:r.updatedAt}}function I(r){return structuredClone(r)}var V=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(e){let t,n=this.queue.then(async()=>{let o=await this.ensureState();t=e(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=n.then(()=>{},()=>{}),await n,t}async summary(){let e=await this.ensureState(),t=new Set(e.pages.flatMap(n=>n.links));return{schema:"toolnet.wiki-summary.v1",projectId:e.projectId,pages:e.pages.length,revisions:e.revisions.length,tags:z(e.pages.flatMap(n=>n.tags)).sort((n,o)=>n.localeCompare(o)),links:e.pages.reduce((n,o)=>n+o.links.length,0),orphanPages:e.pages.filter(n=>n.links.length===0&&!t.has(n.slug)).length,automatedPages:e.pages.filter(n=>n.tags.some(o=>o.startsWith("toolnet-auto-"))).length,updatedAt:e.updatedAt}}async listPages(){let e=await this.ensureState();return I([...e.pages].sort((t,n)=>t.title.localeCompare(n.title)))}async getPage(e){let t=await this.ensureState(),n=G(e),o=t.pages.find(i=>i.slug===n||i.id===e);if(!o)throw new f(`Wiki page not found: ${e}`,404);return I(o)}async createPage(e){return this.mutate(t=>{let n=e.title.trim(),o=e.content.trim();if(!n)throw new f("Wiki title is required",400);let i=G(e.slug??n);if(t.pages.some(c=>c.slug===i))throw new f(`Wiki page already exists: ${i}`,409);let s=new Date().toISOString(),a={id:`wiki-${Kt()}`,slug:i,title:n,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:o,tags:z(e.tags??[]),links:_t(o),revision:1,createdAt:s,updatedAt:s};return t.pages.push(a),t.revisions.push(Nt(a)),I(a)})}async updatePage(e,t){return this.mutate(n=>{let o=G(e),i=n.pages.find(s=>s.slug===o||s.id===e);if(!i)throw new f(`Wiki page not found: ${e}`,404);if(t.title!==void 0){let s=t.title.trim();if(!s)throw new f("Wiki title is required",400);i.title=s}if(t.summary!==void 0){let s=t.summary.trim();s?i.summary=s:delete i.summary}return t.content!==void 0&&(i.content=t.content.trim(),i.links=_t(i.content)),t.tags!==void 0&&(i.tags=z(t.tags)),i.revision+=1,i.updatedAt=new Date().toISOString(),n.revisions.push(Nt(i)),I(i)})}async history(e){let t=await this.getPage(e),n=await this.ensureState();return I(n.revisions.filter(o=>o.pageId===t.id).sort((o,i)=>i.revision-o.revision))}async backlinks(e){let t=await this.getPage(e),n=await this.ensureState();return I(n.pages.filter(o=>o.links.includes(t.slug)).sort((o,i)=>o.title.localeCompare(i.title)))}async search(e,t=10){let n=await this.ensureState(),o=z(zo(e));if(o.length===0)return[];let i=Math.max(1,Math.min(20,Math.floor(t))),s=[];for(let a of n.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),l=a.summary?.toLowerCase()??"",p=a.content.toLowerCase(),g=a.tags.map(v=>v.toLowerCase()),y=0;for(let v of o)u===v&&(y+=12),c===v&&(y+=10),c.includes(v)&&(y+=6),u.includes(v)&&(y+=5),g.some(be=>be===v)?y+=5:g.some(be=>be.includes(v))&&(y+=3),l.includes(v)&&(y+=2),p.includes(v)&&(y+=1);y>0&&s.push({page:I(a),score:y})}return s.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,i)}};import{createHash as Go,randomUUID as $t}from"node:crypto";var Ft="wiki/governance.v1.json",Wt="toolnet.knowledge-governance.v1",Lt=500,q={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function Vo(r,e=0,t=1){return Math.max(e,Math.min(t,r))}function Ne(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function Ht(r){return Go("sha256").update(r.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function qo(r){let e=[r.title,r.summary??"",r.content.slice(0,2e3),...r.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(e)}function Bo(r){let e=r.sourceType==="skill"?.96:r.sourceType==="memory"?.94:.88,t=r.tags.map(n=>n.toLowerCase());return(t.includes("permanent")||t.includes("task"))&&(e+=.03),r.content.length>=200&&(e+=.02),r.content.length<80&&(e-=.05),r.title.length<4&&(e-=.05),Vo(e)}function Dt(r){let e=new Date().toISOString();return{schema:Wt,version:1,projectId:r,policy:{...q},reviews:[],audit:[],createdAt:e,updatedAt:e}}function zt(r){let e=r.autoApproveThreshold??q.autoApproveThreshold,t=r.criticalApproveThreshold??q.criticalApproveThreshold,n=r.staleAfterDays??q.staleAfterDays;if(!Number.isFinite(e)||e<.5||e>1)throw new f("Invalid autoApproveThreshold",400);if(!Number.isFinite(t)||t<.5||t>1)throw new f("Invalid criticalApproveThreshold",400);if(!Number.isInteger(n)||n<1||n>3650)throw new f("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:t,staleAfterDays:n}}var B=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(Ft);if(!e){let t=Dt(this.project.id);return await this.save(t),t}try{let t=JSON.parse(e);if(t.schema!==Wt||t.version!==1||t.projectId!==this.project.id||!Array.isArray(t.reviews)||!Array.isArray(t.audit))throw new Error("invalid");return{...t,policy:zt(t.policy??q)}}catch{let t=Dt(this.project.id);return await this.save(t),t}}async save(e){await this.storage.put(Ft,JSON.stringify(e,null,2),"application/json")}},U=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(e,t,n,o={}){e.audit.push({id:$t(),action:t,principal:n,...o.reviewId?{reviewId:o.reviewId}:{},...o.sourceKey?{sourceKey:o.sourceKey}:{},timestamp:new Date().toISOString(),...o.metadata?{metadata:o.metadata}:{}}),e.audit.length>Lt&&(e.audit=e.audit.slice(-Lt))}async mutate(e){let t,n=this.queue.then(async()=>{let o=await this.ensureState();t=await e(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=n.then(()=>{},()=>{}),await n,t}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(e,t){return this.mutate(n=>(n.policy=zt({...n.policy,...e}),this.audit(n,"policy:update",t,{metadata:{...n.policy}}),{...n.policy}))}async summary(){let e=await this.ensureState(),t=n=>e.reviews.filter(o=>o.status===n).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:e.projectId,pending:t("pending"),approved:t("approved"),rejected:t("rejected"),superseded:t("superseded"),criticalPending:e.reviews.filter(n=>n.status==="pending"&&n.risk==="critical").length,conflictPending:e.reviews.filter(n=>n.status==="pending"&&n.risk==="conflict").length,auditEvents:e.audit.length,policy:{...e.policy},updatedAt:e.updatedAt}}async listReviews(e){let t=await this.ensureState();return structuredClone(t.reviews.filter(n=>!e||n.status===e).sort((n,o)=>o.updatedAt.localeCompare(n.updatedAt)))}async auditLog(e=100){let t=await this.ensureState(),n=Math.max(1,Math.min(500,Math.floor(e)));return structuredClone(t.audit.slice(-n).reverse())}async assess(e,t){let n=await this.ensureState(),o=Bo(e),i=Ne(e.title),s=t.filter(l=>l.slug!==e.slug&&Ne(l.title)===i&&Ht(l.content)!==Ht(e.content)).map(l=>l.slug),a=qo(e),c=[];o<n.policy.autoApproveThreshold&&c.push(`confidence:${o.toFixed(2)}`),a&&o<n.policy.criticalApproveThreshold&&c.push("critical-knowledge"),s.length>0&&c.push("conflicting-knowledge");let u=s.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:u,requiresReview:s.length>0||o<n.policy.autoApproveThreshold||a&&o<n.policy.criticalApproveThreshold,reasons:c,conflicts:s}}async gate(e,t){let n=await this.assess(e,t);return this.mutate(o=>{let i=o.reviews.find(c=>c.sourceKey===e.sourceKey&&c.digest===e.digest);if(i?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:n,review:structuredClone(i)};if(i?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:n,review:structuredClone(i)};if(!n.requiresReview)return this.audit(o,"knowledge:auto-approved","system",{sourceKey:e.sourceKey,metadata:{confidence:n.confidence,risk:n.risk}}),{allowed:!0,mode:"auto-approved",assessment:n};if(i?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:n,review:structuredClone(i)};let s=new Date().toISOString(),a={id:$t(),sourceKey:e.sourceKey,sourceType:e.sourceType,slug:e.slug,marker:e.marker,digest:e.digest,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...new Set([...e.tags,e.marker])],confidence:n.confidence,risk:n.risk,reasons:[...n.reasons],conflicts:[...n.conflicts],status:"pending",createdAt:s,updatedAt:s};return o.reviews.push(a),this.audit(o,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:n,review:structuredClone(a)}})}async markApplied(e,t){await this.mutate(n=>{let o=n.reviews.find(i=>i.sourceKey===e&&i.digest===t&&i.status==="approved");o&&(o.appliedAt=new Date().toISOString(),o.updatedAt=o.appliedAt,this.audit(n,"knowledge:applied",o.reviewedBy??"system",{reviewId:o.id,sourceKey:e}))})}async decide(e,t,n){return this.mutate(async o=>{let i=o.reviews.find(u=>u.id===e);if(!i)throw new f(`Governance review not found: ${e}`,404);if(i.status!=="pending")throw new f("Governance review is already resolved",409);let s=new Date().toISOString();if(i.reviewedAt=s,i.reviewedBy=t.principal,i.updatedAt=s,t.note?.trim()&&(i.reviewNote=t.note.trim()),t.action==="reject")return i.status="rejected",this.audit(o,"knowledge:rejected",t.principal,{reviewId:e,sourceKey:i.sourceKey}),structuredClone(i);if(t.action==="supersede")return i.status="superseded",t.targetReviewId&&(i.supersededBy=t.targetReviewId),this.audit(o,"knowledge:superseded",t.principal,{reviewId:e,sourceKey:i.sourceKey,metadata:{targetReviewId:t.targetReviewId}}),structuredClone(i);if(t.action==="merge"){if(!t.targetReviewId)throw new f("targetReviewId is required for merge",400);let u=o.reviews.find(l=>l.id===t.targetReviewId);if(!u)throw new f("Merge target review not found",404);return i.status="superseded",i.mergedInto=u.id,this.audit(o,"knowledge:merged",t.principal,{reviewId:e,sourceKey:i.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(i)}i.status="approved";let c=(await n.listPages()).find(u=>u.slug===i.slug);if(c&&!c.tags.includes(i.marker))throw new f(`Wiki page '${i.slug}' is manually managed`,409);return c?await n.updatePage(i.slug,{title:i.title,summary:i.summary??"",content:i.content,tags:i.tags}):await n.createPage({slug:i.slug,title:i.title,...i.summary?{summary:i.summary}:{},content:i.content,tags:i.tags}),i.appliedAt=s,this.audit(o,"knowledge:approved",t.principal,{reviewId:e,sourceKey:i.sourceKey}),structuredClone(i)})}async quality(e){let t=await this.ensureState(),n=await e.listPages(),o=Date.now(),i=t.policy.staleAfterDays*864e5,s=n.map(l=>{let p=o-Date.parse(l.updatedAt);return{slug:l.slug,title:l.title,updatedAt:l.updatedAt,ageDays:Math.max(0,Math.floor(p/864e5)),stale:Number.isFinite(p)&&p>i}}).filter(l=>l.stale).map(({stale:l,...p})=>p),a=new Map;for(let l of n){let p=Ne(l.title),g=a.get(p)??[];g.push(l),a.set(p,g)}let c=[...a.entries()].filter(([,l])=>l.length>1).map(([l,p])=>({title:l,pages:p.map(g=>g.slug)})),u=t.reviews.filter(l=>l.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:n.length,automatedPages:n.filter(l=>l.tags.some(p=>p.startsWith("toolnet-auto-"))).length,manualPages:n.filter(l=>!l.tags.some(p=>p.startsWith("toolnet-auto-"))).length,stalePages:s,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(l=>l.confidence<t.policy.autoApproveThreshold).length,conflicts:u.filter(l=>l.risk==="conflict").length,generatedAt:new Date().toISOString()}}};import{timingSafeEqual as gs}from"node:crypto";import{createServer as ys}from"node:http";function Gt(r){return{ok:!0,service:"toolnet-memory",schema:"toolnet.api-health.v1",project:{id:r.id,name:r.name,remote:r.remote??r.name}}}function Vt(r){return{schema:"toolnet.api-project.v1",project:{id:r.id,name:r.name,remote:r.remote??r.name,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,createdAt:r.createdAt,updatedAt:r.updatedAt}}}import{z as Fe}from"zod";import{existsSync as ui,readFileSync as li}from"node:fs";import{join as di}from"node:path";var du=new Int32Array(new SharedArrayBuffer(4));import{closeSync as yu,existsSync as Uo,fsyncSync as hu,mkdirSync as ku,openSync as vu,readFileSync as Jo,renameSync as wu,writeFileSync as bu}from"node:fs";import{dirname as xu,join as Qo}from"node:path";function Yo(r){return Qo(r.rootPath,".toolnet","work","current.json")}function Ke(r){let e=Yo(r);if(!Uo(e))return null;try{let t=JSON.parse(Jo(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as Xo,mkdirSync as Pu,readFileSync as Zo,renameSync as Iu,writeFileSync as Tu}from"node:fs";import{dirname as ju,join as ei}from"node:path";function ti(r){return ei(r.rootPath,".toolnet","context","session-origin.json")}function $e(r){let e=ti(r);if(!Xo(e))return null;try{let t=JSON.parse(Zo(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function ri(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function ve(r){let e=ri(r),t=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),n=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return t&&n?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}import{existsSync as oi,mkdirSync as hl,readFileSync as ii}from"node:fs";import{join as qt}from"node:path";var nl=new j;function si(r){return qt(r.rootPath,".toolnet","memory","checkpoints")}function ai(r){return qt(si(r),"latest.json")}function ci(r){let e=ai(r);if(!oi(e))return null;try{let t=JSON.parse(ii(e,"utf8"));return t.schema!=="toolnet.memory.checkpoint.v1"||t.project.id!==r.id?null:t}catch{return null}}function Bt(r){return ci(r)}var mi={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,request:95,activity:90,phase:75,file:65,next_action:55,blocker:45},next_action:{next_action:100,todo:80,task:65,blocker:60,file:40},last_file:{file:100,task:65,next_action:40},blocker:{blocker:100,task:60,next_action:50,file:35},decision:{decision:100,rule:85,architecture:80,task:45,file:30},completed:{completed:100,progress:70,task:30},status:{progress:100,task:85,phase:75,blocker:65,next_action:60},summary:{task:100,request:98,activity:96,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,rule:54,architecture:53,fix:52,progress:50,test:45,goal:35}},pi={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function fi(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function d(r,e){let t=e.value.replace(/\s+/g," ").trim();t&&r.push({...e,value:t,score:0})}function gi(r){let e=di(r.rootPath,".toolnet","work","handoff-latest.json");if(!ui(e))return null;try{let n=JSON.parse(li(e,"utf8")).continuity;return n?.schema!=="toolnet.handoff.v2"||n.project.id!==r.id?null:n}catch{return null}}function yi(r){let e=Bt(r);if(!e)return[];let t=[];e.request&&d(t,{kind:"request",value:e.request,source:"checkpoint"}),e.activity&&d(t,{kind:"activity",value:e.activity,source:"checkpoint"}),e.current.phase&&d(t,{kind:"phase",value:e.current.phase.title,source:"checkpoint"}),e.current.task&&d(t,{kind:"task",value:e.current.task.title,source:"checkpoint"});let n=e.files.active.at(-1);n&&d(t,{kind:"file",value:n,source:"checkpoint"});for(let o of e.nextActions)d(t,{kind:"next_action",value:o,source:"checkpoint"});for(let o of e.blockers)d(t,{kind:"blocker",value:o,source:"checkpoint"});for(let o of e.completed.tasks)d(t,{kind:"completed",value:o,source:"checkpoint"});for(let o of e.remaining.tasks)d(t,{kind:"todo",value:o,source:"checkpoint"});for(let o of e.durableFacts)d(t,{kind:o.kind,value:o.content,source:"checkpoint"});return t}function hi(r){let e=gi(r);if(!e)return[];let t=[];d(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.request&&d(t,{kind:"request",value:e.request,source:"handoff"}),e.activity&&d(t,{kind:"activity",value:e.activity,source:"handoff"}),e.goal&&d(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&d(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&d(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&d(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&d(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let n of e.blockers)d(t,{kind:"blocker",value:n,source:"handoff"});for(let n of e.decisions)d(t,{kind:"decision",value:n,source:"handoff"});for(let n of e.completed.tasks)d(t,{kind:"completed",value:n,source:"handoff"});for(let n of e.remaining.todos)d(t,{kind:"todo",value:n,source:"handoff"});return d(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),d(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function ki(r){let e=$e(r);if(!e)return[];let t=[];return d(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&d(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&d(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&d(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&d(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&d(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&d(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function vi(r){let e=Ke(r);if(!e)return[];let t=[];e.currentRequest&&d(t,{kind:"request",value:e.currentRequest,source:"work-state"}),e.currentActivity&&d(t,{kind:"activity",value:e.currentActivity,source:"work-state"}),e.goal&&d(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&d(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&d(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let n=e.activeFiles?.at(-1)??e.filesTouched.at(-1);n&&d(t,{kind:"file",value:n,source:"work-state"});for(let o of e.nextActions.slice(0,5))d(t,{kind:"next_action",value:o,source:"work-state"});for(let o of e.blockers.slice(-5))d(t,{kind:"blocker",value:o,source:"work-state"});for(let o of e.decisions.slice(-5))d(t,{kind:"decision",value:o,source:"work-state"});for(let o of e.tasks.filter(i=>i.status==="completed").slice(-8))d(t,{kind:"completed",value:o.title,source:"work-state"});for(let o of e.tasks.filter(i=>i.status!=="completed"&&i.status!=="cancelled").slice(0,8))d(t,{kind:"todo",value:o.title,source:"work-state"});for(let o of e.tests.slice(-5))d(t,{kind:"test",value:o,source:"work-state"});return d(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),t}function wi(r,e){let t=mi[r];return e.map((n,o)=>({...n,score:(t[n.kind]??10)+pi[n.source]+Math.max(0,5-o*.01)}))}function bi(r){let e=new Map;for(let t of r){let n=`${t.kind}:${fi(t.value)}`,o=e.get(n);(!o||t.score>o.score)&&e.set(n,t)}return[...e.values()]}function we(r,e,t={}){let n=ve(e),o=[...yi(r),...hi(r),...ki(r),...vi(r)],i=bi(wi(n,o)).sort((l,p)=>p.score-l.score),s=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),c=[],u=0;for(let l of i){if(c.length>=s)break;let p=l.kind.length+l.value.length+l.source.length+16;c.length>0&&u+p>a||(c.push(l),u+=p)}return{intent:n,facts:c,context:{project:{id:r.id,name:r.name},intent:n,selectedFacts:c.map(l=>({kind:l.kind,value:l.value,source:l.source}))},stats:{candidates:o.length,selected:c.length,chars:u}}}var Ut={previous_agent:"Agent tr\u01B0\u1EDBc",request:"Y\xEAu c\u1EA7u hi\u1EC7n t\u1EA1i",activity:"\u0110ang l\xE0m",goal:"M\u1EE5c ti\xEAu",phase:"Phase",task:"Task hi\u1EC7n t\u1EA1i",file:"File hi\u1EC7n t\u1EA1i",todo:"TODO",next_action:"Ti\u1EBFp theo",blocker:"Blocker",decision:"Quy\u1EBFt \u0111\u1ECBnh",rule:"Quy t\u1EAFc",architecture:"Ki\u1EBFn tr\xFAc",fix:"\u0110\xE3 s\u1EEDa",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},Jt=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],Si={previous_agent:["previous_agent"],current_task:["request","activity","task","file","next_action"],next_action:["next_action","task","file","todo"],last_file:["file","task","next_action"],blocker:["blocker"],decision:["decision"],completed:["completed"],status:["progress","task","next_action","blocker"],summary:Jt};function xi(r){let e=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)}function Mi(r){let e=r.filter(n=>n.source==="handoff");if(e.length===0)return r;let t=r.filter(n=>n.source==="checkpoint"&&["rule","architecture","fix"].includes(n.kind));return[...e,...t]}function Ai(r){let e=new Set,t=[];for(let n of r){let o=`${n.kind}:${n.value.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}`;e.has(o)||(e.add(o),t.push(n))}return t}function Qt(r){switch(r){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function Ci(r,e){let t=[];for(let n of e){let o=r.filter(i=>i.kind===n).slice(0,Qt(n));for(let i of o)t.push(`${Ut[n]}: ${i.value}`)}return t.join(`
6
- `)}function Pi(r,e){let t=Si[e]??Jt,n=[];for(let o of t){let i=r.filter(s=>s.kind===o).slice(0,Qt(o));for(let s of i)n.push(`${Ut[o]}: ${s.value}`)}return n.join(`
7
- `)}function Yt(r,e){let t=we(r,e,{maxFacts:32,maxChars:6400}),n=Ai(Mi(t.facts)),o=xi(e)?Ci(n,["todo","task","next_action","file"]):Pi(n,String(t.intent));return o?{intent:String(t.intent),answer:o,source:n[0]?.source??"none"}:{intent:String(t.intent),answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}import{existsSync as Ii,mkdirSync as Ti,readFileSync as Ri,renameSync as ji,rmSync as Ei,writeFileSync as Oi}from"node:fs";import{join as Xt}from"node:path";var _i=720*60*1e3;function Zt(r){return Xt(r.rootPath,".toolnet","context","memory-agent-conversation.json")}function J(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function Ni(r){let e=J(r);return[/\btiếp tục\b/u,/\btiếp tục task\b/u,/\blúc nãy\b/u,/\btrước đó\b/u,/\btask trước\b/u,/\bprevious (?:task|session|work)\b/u,/\bcontinue\b/u,/\bresume\b/u,/\bcurrent task\b/u,/\bđang làm gì\b/u].some(t=>t.test(e))}function Ki(r){if(Ni(r))return!1;let e=J(r),t=e.split(/\s+/u).filter(Boolean);return[/^(?:tại sao|vì sao|sao vậy)\b/u,/^(?:why|why so|why that)\b/u,/^(?:còn|thế|vậy|rồi sao|sau đó)\b/u,/^(?:what about|and what|then what)\b/u,/^(?:cái đó|việc đó|nó|phần đó)\b/u].some(n=>n.test(e))?!0:t.length<=5&&/\b(?:nó|đó|vậy|thế|that|it|this)\b/u.test(e)}function $i(r,e,t){let n=Zt(r);if(!Ii(n))return null;try{let o=JSON.parse(Ri(n,"utf8"));if(o.schema!=="toolnet.memory-conversation.v1"||o.version!==1||o.projectId!==r.id||!Array.isArray(o.focus))return null;let i=Date.parse(o.updatedAt);return!Number.isFinite(i)||e-i>t?null:o}catch{return null}}function Fi(r,e=8){let t=new Set,n=[];for(let o of r){let i=o.value.replace(/\s+/gu," ").trim();if(!i)continue;let s=[o.kind,J(i)].join(":");if(!t.has(s)&&(t.add(s),n.push({...o,value:i}),n.length>=e))break}return n}function Li(r,e){let t=Zt(r),n=Xt(r.rootPath,".toolnet","context");Ti(n,{recursive:!0,mode:448});let o=`${t}.${process.pid}.tmp`;try{Oi(o,JSON.stringify(e,null,2)+`
8
- `,{encoding:"utf8",mode:384}),ji(o,t)}finally{Ei(o,{force:!0})}}function Hi(r){return r.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
9
- `)}function Di(r,e){return r.priorFocus.find(t=>t.kind===e)?.value}function er(r){if(!r.usedPriorFocus||r.currentIntent!=="summary"||r.priorFocus.length===0)return null;let e=J(r.originalQuestion),t=/^(?:tại sao|vì sao|sao vậy|why|why so|why that)\b/u.test(e),n=/^(?:rồi sao|sau đó|tiếp thì sao|thế tiếp theo|then what|what next)\b/u.test(e),o=t?["decision","blocker","next_action","task","file"]:n?["next_action","todo","task","blocker","file","decision"]:["task","next_action","file","decision","blocker"],i={task:"Task li\xEAn quan",next_action:"Vi\u1EC7c ti\u1EBFp theo",file:"File li\xEAn quan",decision:"Quy\u1EBFt \u0111\u1ECBnh li\xEAn quan",blocker:"Blocker",todo:"TODO"},s=[];for(let a of o){let c=Di(r,a);if(c&&(s.push(`${i[a]??a}: ${c}.`),t&&s.length>=2||!t&&s.length>=3))break}return s.length===0?null:{answer:s.join(" "),intent:"summary",source:"conversation-focus"}}function Wi(r){let e=J(r);return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(e)}function tr(r,e,t={}){let n=t.now??Date.now(),o=t.maxAgeMs??_i,i=$i(r,n,o),s=!!(i&&i.focus.length>0&&Ki(e)&&!Wi(e)),a=s&&i?[e.trim(),"","Previous ToolNet Memory conversation focus:",Hi(i),"","Use the compact focus only to resolve the current follow-up question.","Do not reconstruct or request raw session transcripts."].join(`
10
- `):e.trim(),c=ve(e),l=we(r,a,{maxFacts:8,maxChars:1800}).facts.map(g=>({kind:g.kind,value:g.value,source:g.source})),p=Fi(s&&i?[...l,...i.focus]:l);return Li(r,{schema:"toolnet.memory-conversation.v1",version:1,projectId:r.id,updatedAt:new Date(n).toISOString(),lastIntent:c,focus:p}),{question:a,originalQuestion:e,usedPriorFocus:s,previousIntent:i?.lastIntent,currentIntent:c,priorFocus:i?.focus??[],focusCount:p.length}}import{existsSync as zi,readFileSync as Gi}from"node:fs";import{join as Vi}from"node:path";function x(r){return!!r?.trim()}function rr(r){let e=[],t=[],n=100;x(r.goal)||x(r.request)||(e.push("goal_or_request"),n-=20),x(r.activity)||x(r.current.task?.title)||x(r.current.phase?.title)||(e.push("current_work"),n-=25),x(r.nextAction)||x(r.remaining.todos[0])||(e.push("next_action"),n-=25),r.tests.status!=="unknown"||r.tests.recent.length>0||(r.tests.checks?.length??0)>0||(r.evidence?.commands.length??0)>0||(r.evidence?.references.length??0)>0||(e.push("evidence"),n-=20),x(r.files.current)||r.files.recent.length>0||(r.files.active?.length??0)>0||(r.files.modified?.length??0)>0||(r.files.created?.length??0)>0||(e.push("files"),n-=10),r.tests.status==="failing"&&t.push("tests_failing"),r.blockers.length>0&&t.push("active_blockers"),n=Math.max(0,Math.min(100,n));let u=e.includes("current_work")||e.includes("next_action"),l;return n>=80&&!u?l="high":n>=50?l="medium":l="low",{confidence:l,score:n,missingContext:e,warnings:t}}var nr={compact:{completed:3,evidence:3,files:5,blockers:2,maxChars:1800},normal:{completed:10,evidence:10,files:15,blockers:5,maxChars:4200},benchmark:{completed:30,evidence:30,files:40,blockers:10,maxChars:1e4}};function E(r){let e=new Set,t=[];for(let n of r){let o=n?.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();e.has(i)||(e.add(i),t.push(o))}return t}function O(r){return r.length>0?r.map(e=>`- ${e}`).join(`
11
- `):"- none"}function qi(r,e){return r.length<=e?r:[r.slice(0,e).trimEnd(),"","[Structured handoff truncated]"].join(`
12
- `)}function or(r,e){if(e)return e;let t=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/\bbenchmark\b/u.test(t)||/\bdeep handoff\b/u.test(t)||/\bfull handoff\b/u.test(t)||/\btakeover\b/u.test(t)||/\btake over\b/u.test(t)||/tiếp quản/u.test(t)||/bằng chứng đầy đủ/u.test(t)||/evidence.*(?:file|test|command)/u.test(t)?"benchmark":/\bcompact\b/u.test(t)||/\bbrief\b/u.test(t)||/ngắn gọn/u.test(t)||/tóm tắt ngắn/u.test(t)?"compact":"normal"}function Bi(r,e="normal"){let t=nr[e],n=E([`Source agent: ${r.source.agent}`,`Captured: ${r.capturedAt}`,r.goal?`Goal: ${r.goal}`:void 0,r.request?`Request: ${r.request}`:void 0,r.activity?`Activity: ${r.activity}`:void 0,r.current.phase?`Phase: ${r.current.phase.title} [${r.current.phase.status}]`:void 0,r.current.task?`Task: ${r.current.task.title} [${r.current.task.status}]`:void 0,r.current.file?`Current file: ${r.current.file}`:void 0,`Progress: ${JSON.stringify(r.progress)}`]),o=E([...r.completed.phases.map(u=>`Phase: ${u}`),...r.completed.tasks.map(u=>`Task: ${u}`)]).slice(0,t.completed),i=E([`Tests status: ${r.tests.status}`,...r.tests.recent.map(u=>`Test: ${u}`),...(r.tests.checks??[]).map(u=>`Check [${u.status}] ${u.kind}: ${u.command}`),...(r.evidence?.commands??[]).map(u=>`Command: ${u}`),...(r.evidence?.references??[]).map(u=>`Reference: ${u}`),...r.decisions.map(u=>`Decision: ${u}`),...r.attention.map(u=>`Attention: ${u}`)]).slice(0,t.evidence),s=E([r.files.current,...(r.files.active??[]).map(u=>`Active: ${u}`),...(r.files.modified??[]).map(u=>`Modified: ${u}`),...(r.files.created??[]).map(u=>`Created: ${u}`),...(r.files.deleted??[]).map(u=>`Deleted: ${u}`),...r.files.recent.map(u=>`Recent: ${u}`)]).slice(0,t.files),a=E(r.blockers).slice(0,t.blockers),c=E([r.nextAction,r.nextAction?void 0:r.remaining.todos[0]]).slice(0,1);return{currentState:n,completed:o,evidence:i,filesTouched:s,blockers:a,nextAction:c}}function Ui(r,e,t){return[`HANDOFF_DETAIL: ${e}`,`CONTINUITY_CONFIDENCE: ${t.confidence}`,`QUALITY_SCORE: ${t.score}`,`MISSING_CONTEXT: ${t.missingContext.length>0?t.missingContext.join(", "):"none"}`,`QUALITY_WARNINGS: ${t.warnings.length>0?t.warnings.join(", "):"none"}`,"","CURRENT_STATE",O(r.currentState),"","COMPLETED",O(r.completed),"","EVIDENCE",O(r.evidence),"","FILES_TOUCHED",O(r.filesTouched),"","BLOCKERS",O(r.blockers),"","NEXT_ACTION",O(r.nextAction)].join(`
13
- `)}function ir(r,e="normal"){let t=Vi(r.rootPath,".toolnet","work","handoff-latest.json");if(!zi(t))return null;try{let o=JSON.parse(Gi(t,"utf8")).continuity;if(!o||o.schema!=="toolnet.handoff.v2"||o.version!==2)return null;let i=Bi(o,e),s=rr(o),a=qi(Ui(i,e,s),nr[e].maxChars);return{detail:e,data:i,quality:s,text:a}}catch{return null}}function Ji(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}var Qi=[/\bhandoff\b/u,/\bcontinuity\b/u,/\bcontinue\b/u,/\bresume\b/u,/\btakeover\b/u,/\btake over\b/u,/tiếp tục/u,/tiếp quản/u,/bàn giao/u,/dừng ở đâu/u,/đang làm gì/u],Yi=[/\bcurrent state\b/u,/\bcurrent task\b/u,/\bevidence\b/u,/\breport locations?\b/u,/\bfiles?\b/u,/\burls?\b/u,/\bassets?\b/u,/\btests?\b/u,/\bcommands?\b/u,/\bblockers?\b/u,/\bnext actions?\b/u,/trạng thái hiện tại/u,/task hiện tại/u,/bằng chứng/u,/vị trí báo cáo/u,/file/u,/url/u,/blocker/u,/việc tiếp theo/u,/bước tiếp theo/u],Xi=[/\bsummarize\b/u,/\bsummary\b/u,/\bfull state\b/u,/\bfull context\b/u,/tóm tắt/u,/đầy đủ/u,/toàn bộ trạng thái/u];function Zi(r){let e=0;for(let t of Yi)t.test(r)&&(e+=1);return e}function sr(r,e){let t=Ji(r);if(/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(t)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(t)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(t))return!1;if(e==="summary"||e==="status")return!0;if(!t)return!1;let o=Qi.some(a=>a.test(t)),i=Xi.some(a=>a.test(t)),s=Zi(t);return!!(o&&s>=1||i&&s>=2||s>=4)}var Bl={question:Fe.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:Fe.enum(["local"]).optional().describe("Returns deterministic local memory only. No external AI is used."),detail:Fe.enum(["compact","normal","benchmark"]).optional().describe("Handoff detail level. compact=minimal, normal=standard, benchmark=deep evidence/files/tests for agent takeover.")};function ar(r,e,t,n,o){if(!sr(e,t))return{answer:n};let i=or(e,o),s=ir(r.project,i);return s?{answer:s.text,handoff:s.data,detail:s.detail,confidence:s.quality.confidence,missingContext:s.quality.missingContext,quality:s.quality}:{answer:n}}async function cr(r,e){let t=tr(r.project,e.question),n=er(t);if(n)return{...ar(r,t.originalQuestion,String(n.intent),n.answer,e.detail),mode:"local",usedAi:!1,source:n.source,intent:n.intent};let o=Yt(r.project,t.originalQuestion),i=ar(r,t.originalQuestion,String(o.intent),o.answer,e.detail);return"handoff"in i?{...i,mode:"local",usedAi:!1,source:o.source,intent:o.intent,routing:"deterministic-handoff"}:{...i,mode:"local",usedAi:!1,source:o.source,intent:o.intent}}import{z as gr}from"zod";import{chmodSync as Ql,existsSync as ur,mkdirSync as Yl,readFileSync as lr,renameSync as Xl,writeFileSync as Zl}from"node:fs";import{dirname as td,join as Q}from"node:path";var dr="toolnet.context-offload.v1",es="toolnet.context-offload-asset.v1";function mr(r){return Q(r,".toolnet","offload")}function pr(r){return Q(mr(r),"assets")}function ts(r){return Q(mr(r),"graph.json")}function Le(){return{schema:dr,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function rs(r){let e=ts(r);if(!ur(e))return Le();try{let t=JSON.parse(lr(e,"utf8"));return t.schema!==dr||t.version!==1||!Array.isArray(t.nodes)?Le():t}catch{return Le()}}function ns(r,e){let t=e.trim().toLowerCase();if(!/^[a-f0-9]{8,64}$/u.test(t))throw new Error("Invalid context offload asset reference.");if(t.length===64&&ur(Q(pr(r),`${t}.json`)))return t;let n=rs(r).nodes.map(o=>o.id).filter(o=>o.startsWith(t));if(n.length===0)throw new Error(`Context offload asset not found: ${e}`);if(n.length>1)throw new Error(`Ambiguous context offload asset reference: ${e}`);return n[0]}function fr(r,e,t=6e3){let n=ns(r,e),o=lr(Q(pr(r),`${n}.json`),"utf8"),i=JSON.parse(o);if(i.schema!==es||i.version!==1||i.assetId!==n)throw new Error(`Invalid context offload asset: ${e}`);let s=Math.max(200,Math.min(2e4,Math.floor(t)));return{assetId:n,kind:i.event.type,bytes:Buffer.byteLength(o,"utf8"),truncated:o.length>s,content:o.length>s?`${o.slice(0,s)}
14
- [truncated]`:o}}var id={assetId:gr.string().regex(/^[a-f0-9]{8,64}$/iu).describe("Asset reference from the ToolNet Context Offload Graph."),maxChars:gr.number().int().min(200).max(2e4).optional().describe("Maximum asset characters to return. Defaults to 6000.")};async function yr(r,e){return fr(r.project.rootPath,e.assetId,e.maxChars??6e3)}async function hr(r,e){return{schema:"toolnet.api-memory-ask.v1",result:await cr({project:r},e)}}async function kr(r,e){return{schema:"toolnet.api-context-offload.v1",result:await yr({project:r},e)}}import{z as vr}from"zod";var dd={query:vr.string(),limit:vr.number().int().min(1).max(20).optional()};async function wr(r,e){return r.retrieval.search(r.project.id,e.query,{topK:e.limit??8}).map(n=>({id:n.memory.id,type:n.memory.type,content:n.memory.content,importance:n.memory.importance,score:n.score,tags:n.memory.tags}))}import{z as xr}from"zod";import{chmodSync as fd,existsSync as os,mkdirSync as gd,readFileSync as is,readdirSync as ss,renameSync as yd,statSync as as,writeFileSync as hd}from"node:fs";import{join as br}from"node:path";var cs="toolnet.skill-memory.v1";function us(r,e=Number.MAX_SAFE_INTEGER){let t=new Set,n=[];for(let o of r){let i=o.replace(/\s+/gu," ").trim();if(!i)continue;let s=i.normalize("NFKC").toLowerCase();if(!t.has(s)&&(t.add(s),n.push(i),n.length>=e))break}return n}function ls(r){return br(r.rootPath,".toolnet","memory","skills")}function ds(r,e){if(!r||typeof r!="object")return!1;let t=r;return t.schema===cs&&t.version===1&&t.projectId===e&&typeof t.id=="string"&&typeof t.task=="string"&&Array.isArray(t.steps)&&Array.isArray(t.verification)&&Array.isArray(t.files)}function ms(r){let e=ls(r);if(!os(e))return[];if(!as(e).isDirectory())return[];let t=[];for(let n of ss(e)){if(!n.endsWith(".json"))continue;let o=br(e,n);try{let i=JSON.parse(is(o,"utf8"));ds(i,r.id)&&t.push(i)}catch{}}return t.sort((n,o)=>{let i=o.createdAt.localeCompare(n.createdAt);return i!==0?i:n.id.localeCompare(o.id)})}function ps(r){return us(r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_./-]+/gu).filter(e=>e.length>=2),32)}function fs(r,e){let t=e.normalize("NFKC").toLowerCase().trim();if(!t)return 0;if(r.id.toLowerCase()===t||r.fingerprint.toLowerCase()===t)return 1e3;let n=[r.title,r.task,r.summary,...r.steps,...r.verification,...r.files].join(`
15
- `).normalize("NFKC").toLowerCase(),o=0;r.task.normalize("NFKC").toLowerCase().includes(t)&&(o+=40),r.title.normalize("NFKC").toLowerCase().includes(t)&&(o+=30);for(let i of ps(t))n.includes(i)&&(o+=5),r.task.normalize("NFKC").toLowerCase().includes(i)&&(o+=4),r.files.some(s=>s.toLowerCase().includes(i))&&(o+=3);return o}function Sr(r,e,t=5){let n=Math.max(1,Math.min(10,Math.floor(t)));return ms(r).map(o=>({...o,score:fs(o,e)})).filter(o=>o.score>0).sort((o,i)=>i.score!==o.score?i.score-o.score:i.createdAt.localeCompare(o.createdAt)).slice(0,n)}var Sd={query:xr.string().min(2).max(500).describe("Task, problem, file, command or workflow to match against successful reusable Skill Memory SOPs."),limit:xr.number().int().min(1).max(10).optional().describe("Maximum matching reusable SOPs to return. Default 5.")};async function Mr(r,e){let t=Sr(r.project,e.query,e.limit??5);return{schema:"toolnet.skill-memory-search.v1",query:e.query,count:t.length,matches:t}}async function Ar(r,e,t){return{schema:"toolnet.api-memory-search.v1",results:await wr({project:r,retrieval:e},t)}}async function Cr(r,e){return{schema:"toolnet.api-skill-search.v1",result:await Mr({project:r},e)}}function Y(r){if(!r||typeof r!="object"||Array.isArray(r))throw new Error("Invalid Memory Hub request");return r}function w(r,e,t=1,n=200){if(typeof r!="string"||r.trim().length<t||r.trim().length>n)throw new Error(`Invalid ${e}`);return r.trim()}function Pr(r,e,t=500){if(r!==void 0)return w(r,e,1,t)}function He(r,e,t=64){if(r!==void 0){if(!Array.isArray(r)||r.length>t||r.some(n=>typeof n!="string"||!n.trim()))throw new Error(`Invalid ${e}`);return r.map(n=>n.trim())}}async function Ir(r,e){return{schema:"toolnet.api-hub-summary.v1",hub:await r.summary(e)}}async function Tr(r,e){return{schema:"toolnet.api-hub-teams.v1",teams:await r.listTeams(e)}}async function Rr(r,e,t){let n=Y(t),o={...n.id!==void 0?{id:w(n.id,"team id",2,100)}:{},name:w(n.name,"team name",2,100),...n.description!==void 0?{description:Pr(n.description,"team description",500)}:{}};return{schema:"toolnet.api-hub-team.v1",team:await r.createTeam(e,o)}}async function jr(r,e){return{schema:"toolnet.api-hub-agents.v1",agents:await r.listAgents(e)}}async function Er(r,e,t){let n=Y(t),o={...n.id!==void 0?{id:w(n.id,"agent id",2,100)}:{},name:w(n.name,"agent name",2,100),...n.kind!==void 0?{kind:Pr(n.kind,"agent kind",100)}:{},...n.teamIds!==void 0?{teamIds:He(n.teamIds,"teamIds",64)}:{},...n.metadata&&typeof n.metadata=="object"&&!Array.isArray(n.metadata)?{metadata:n.metadata}:{}};return{schema:"toolnet.api-hub-agent.v1",agent:await r.createAgent(e,o)}}async function Or(r,e){return{schema:"toolnet.api-hub-acl.v1",grants:await r.listAcl(e)}}async function _r(r,e,t){let n=Y(t),o=w(n.role,"role",4,20);if(!["owner","admin","member","viewer"].includes(o))throw new Error("Invalid role");let i=He(n.scopes,"scopes",S.length);if(i?.some(a=>!S.includes(a)))throw new Error("Invalid Memory Hub scope");let s={principal:w(n.principal,"principal",1,120),role:o,...i?{scopes:i}:{}};return{schema:"toolnet.api-hub-acl-grant.v1",grant:await r.grantAcl(e,s)}}async function Nr(r,e,t){let n=Y(t),o=w(n.principal,"principal",1,120);return await r.revokeAcl(e,o),{schema:"toolnet.api-hub-acl-revoke.v1",principal:o,revoked:!0}}async function Kr(r,e){return{schema:"toolnet.api-hub-loadouts.v1",loadouts:await r.listLoadouts(e)}}async function $r(r,e,t){let n=Y(t),o=n.maxContextChars;if(o!==void 0&&(!Number.isInteger(o)||o<500||o>5e4))throw new Error("Invalid maxContextChars");let i=n.memoryMode;if(i!==void 0&&i!=="local"&&i!=="ai")throw new Error("Invalid memoryMode");if(n.skillMemory!==void 0&&typeof n.skillMemory!="boolean")throw new Error("Invalid skillMemory");if(n.contextOffload!==void 0&&typeof n.contextOffload!="boolean")throw new Error("Invalid contextOffload");let s={agentId:w(n.agentId,"agentId",2,100),...n.tools!==void 0?{tools:He(n.tools,"tools",64)}:{},...i?{memoryMode:i}:{},...n.skillMemory!==void 0?{skillMemory:n.skillMemory}:{},...n.contextOffload!==void 0?{contextOffload:n.contextOffload}:{},...o!==void 0?{maxContextChars:o}:{}};return{schema:"toolnet.api-hub-loadout.v1",loadout:await r.setLoadout(e,s)}}async function Fr(r,e){return{schema:"toolnet.api-hub-observability.v1",observability:await r.observability(e)}}async function M(r,e,t){if(!await r.authorize(e,t))throw new f(`Principal '${e}' lacks '${t}'`,403)}function Lr(r){if(!r||typeof r!="object"||Array.isArray(r))throw new f("Invalid Wiki request",400);return r}function De(r,e,t){if(typeof r!="string"||!r.trim()||r.length>t)throw new f(`Invalid ${e}`,400);return r.trim()}function Hr(r,e,t){if(r!==void 0){if(typeof r!="string"||r.length>t)throw new f(`Invalid ${e}`,400);return r}}function Dr(r){if(r!==void 0){if(!Array.isArray(r)||r.length>50||r.some(e=>typeof e!="string"||e.length>100))throw new f("Invalid Wiki tags",400);return r}}async function Wr(r,e,t){return await M(e,t,"wiki:read"),{schema:"toolnet.api-wiki-summary.v1",wiki:await r.summary()}}async function zr(r,e,t){return await M(e,t,"wiki:read"),{schema:"toolnet.api-wiki-pages.v1",pages:await r.listPages()}}async function Gr(r,e,t,n){await M(e,t,"wiki:write");let o=Lr(n),i={...o.slug!==void 0?{slug:De(o.slug,"Wiki slug",120)}:{},title:De(o.title,"Wiki title",200),...o.summary!==void 0?{summary:Hr(o.summary,"Wiki summary",1e3)}:{},content:typeof o.content=="string"?o.content:"",...o.tags!==void 0?{tags:Dr(o.tags)}:{}};return{schema:"toolnet.api-wiki-page.v1",page:await r.createPage(i)}}async function Vr(r,e,t,n){return await M(e,t,"wiki:read"),{schema:"toolnet.api-wiki-page.v1",page:await r.getPage(n)}}async function qr(r,e,t,n,o){await M(e,t,"wiki:write");let i=Lr(o),s={...i.title!==void 0?{title:De(i.title,"Wiki title",200)}:{},...i.summary!==void 0?{summary:Hr(i.summary,"Wiki summary",1e3)}:{},...i.content!==void 0?{content:typeof i.content=="string"?i.content:(()=>{throw new f("Invalid Wiki content",400)})()}:{},...i.tags!==void 0?{tags:Dr(i.tags)}:{}};return{schema:"toolnet.api-wiki-page.v1",page:await r.updatePage(n,s)}}async function Br(r,e,t,n,o){return await M(e,t,"wiki:read"),{schema:"toolnet.api-wiki-search.v1",query:n,results:await r.search(n,o)}}async function Ur(r,e,t,n){return await M(e,t,"wiki:read"),{schema:"toolnet.api-wiki-history.v1",revisions:await r.history(n)}}async function Jr(r,e,t,n){return await M(e,t,"wiki:read"),{schema:"toolnet.api-wiki-backlinks.v1",pages:await r.backlinks(n)}}async function T(r,e,t){if(!await r.authorize(e,t))throw new f(`Principal '${e}' lacks '${t}'`,403)}function Qr(r){if(!r||typeof r!="object"||Array.isArray(r))throw new f("Invalid governance request",400);return r}async function Yr(r,e,t){return await T(e,t,"governance:read"),{schema:"toolnet.api-governance-summary.v1",governance:await r.summary()}}async function Xr(r,e,t,n){if(await T(e,t,"governance:read"),n&&!new Set(["pending","approved","rejected","superseded"]).has(n))throw new f("Invalid review status",400);return{schema:"toolnet.api-governance-reviews.v1",reviews:await r.listReviews(n)}}async function Zr(r,e,t,n,o,i){await T(t,n,"governance:write");let s=Qr(i),a=s.action;if(a!=="approve"&&a!=="reject"&&a!=="supersede"&&a!=="merge")throw new f("Invalid governance action",400);if(s.note!==void 0&&typeof s.note!="string")throw new f("Invalid review note",400);if(s.targetReviewId!==void 0&&typeof s.targetReviewId!="string")throw new f("Invalid targetReviewId",400);return{schema:"toolnet.api-governance-review.v1",review:await r.decide(o,{action:a,principal:n,...typeof s.note=="string"?{note:s.note}:{},...typeof s.targetReviewId=="string"?{targetReviewId:s.targetReviewId}:{}},e)}}async function en(r,e,t,n){return await T(t,n,"governance:read"),{schema:"toolnet.api-knowledge-quality.v1",quality:await r.quality(e)}}async function tn(r,e,t){return await T(e,t,"governance:read"),{schema:"toolnet.api-governance-policy.v1",policy:await r.policy()}}async function rn(r,e,t,n){await T(e,t,"governance:write");let o=Qr(n),i={};if(o.autoApproveThreshold!==void 0){if(typeof o.autoApproveThreshold!="number")throw new f("Invalid autoApproveThreshold",400);i.autoApproveThreshold=o.autoApproveThreshold}if(o.criticalApproveThreshold!==void 0){if(typeof o.criticalApproveThreshold!="number")throw new f("Invalid criticalApproveThreshold",400);i.criticalApproveThreshold=o.criticalApproveThreshold}if(o.staleAfterDays!==void 0){if(typeof o.staleAfterDays!="number")throw new f("Invalid staleAfterDays",400);i.staleAfterDays=o.staleAfterDays}return{schema:"toolnet.api-governance-policy.v1",policy:await r.setPolicy(i,t)}}async function nn(r,e,t,n){return await T(e,t,"governance:read"),{schema:"toolnet.api-governance-audit.v1",events:await r.auditLog(n)}}function hs(r){let e=r.headers["x-toolnet-principal"];return(Array.isArray(e)?e[0]:e)?.trim()||"anonymous"}function ks(r,e){if(!e)return!0;let t=r.headers.authorization;if(!t?.startsWith("Bearer "))return!1;let n=Buffer.from(t.slice(7)),o=Buffer.from(e);return n.length===o.length&&gs(n,o)}function m(r,e,t){r.statusCode=e,r.setHeader("content-type","application/json; charset=utf-8"),r.setHeader("cache-control","no-store"),r.end(JSON.stringify(t))}async function k(r){let e=[],t=0;for await(let n of r){let o=Buffer.isBuffer(n)?n:Buffer.from(n);if(t+=o.length,t>16384)throw new Error("Request body too large");e.push(o)}return e.length===0?{}:JSON.parse(Buffer.concat(e).toString("utf8"))}function vs(r){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;return typeof e.question!="string"||e.question.length<2||e.question.length>4e3||e.mode!==void 0&&e.mode!=="local"?null:{question:e.question,...e.mode?{mode:e.mode}:{}}}function ws(r){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;return typeof e.query!="string"||e.limit!==void 0&&(!Number.isInteger(e.limit)||e.limit<1||e.limit>20)?null:{query:e.query,...e.limit!==void 0?{limit:e.limit}:{}}}function bs(r){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;return typeof e.query!="string"||e.query.length<2||e.query.length>500||e.limit!==void 0&&(!Number.isInteger(e.limit)||e.limit<1||e.limit>10)?null:{query:e.query,...e.limit!==void 0?{limit:e.limit}:{}}}function Ss(r){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;return typeof e.assetId!="string"||!/^[a-f0-9]{8,64}$/iu.test(e.assetId)||e.maxChars!==void 0&&(!Number.isInteger(e.maxChars)||e.maxChars<200||e.maxChars>2e4)?null:{assetId:e.assetId,...e.maxChars!==void 0?{maxChars:e.maxChars}:{}}}function on(r){return ys(async(e,t)=>{try{let n=new URL(e.url??"/",`http://${e.headers.host??"localhost"}`),o=hs(e),i=Date.now();if(t.once("finish",()=>{r.hub&&r.hub.recordRequest({method:e.method??"GET",path:n.pathname,principal:o,statusCode:t.statusCode,durationMs:Date.now()-i}).catch(()=>{})}),n.pathname.startsWith("/v1/")&&!ks(e,r.token)){m(t,401,{error:"Unauthorized"});return}if(e.method==="GET"&&n.pathname==="/v1/health"){m(t,200,Gt(r.project));return}if(e.method==="GET"&&n.pathname==="/v1/project"){m(t,200,Vt(r.project));return}if(e.method==="POST"&&n.pathname==="/v1/memory/ask"){let l=vs(await k(e));if(!l){m(t,400,{error:"Invalid memory ask request"});return}m(t,200,await hr(r.project,l));return}if(e.method==="POST"&&n.pathname==="/v1/memory/search"){let l=ws(await k(e));if(!l){m(t,400,{error:"Invalid memory search request"});return}m(t,200,await Ar(r.project,r.retrieval,l));return}if(e.method==="POST"&&n.pathname==="/v1/skills/search"){let l=bs(await k(e));if(!l){m(t,400,{error:"Invalid skill search request"});return}m(t,200,await Cr(r.project,l));return}if(e.method==="POST"&&n.pathname==="/v1/offload/read"){let l=Ss(await k(e));if(!l){m(t,400,{error:"Invalid context offload request"});return}m(t,200,await kr(r.project,l));return}if(n.pathname.startsWith("/v1/hub")&&!r.hub){m(t,503,{error:"Memory Hub unavailable"});return}if(e.method==="GET"&&n.pathname==="/v1/hub"){m(t,200,await Ir(r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/hub/teams"){m(t,200,await Tr(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/teams"){m(t,201,await Rr(r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/agents"){m(t,200,await jr(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/agents"){m(t,201,await Er(r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/acl"){m(t,200,await Or(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/acl/grant"){m(t,200,await _r(r.hub,o,await k(e)));return}if(e.method==="POST"&&n.pathname==="/v1/hub/acl/revoke"){m(t,200,await Nr(r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/loadouts"){m(t,200,await Kr(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/loadouts"){m(t,200,await $r(r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/observability"){m(t,200,await Fr(r.hub,o));return}if(n.pathname.startsWith("/v1/wiki")&&(!r.wiki||!r.hub)){m(t,503,{error:"Wiki unavailable"});return}if(e.method==="GET"&&n.pathname==="/v1/wiki"){m(t,200,await Wr(r.wiki,r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/wiki/pages"){m(t,200,await zr(r.wiki,r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/wiki/pages"){m(t,201,await Gr(r.wiki,r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/wiki/search"){let l=n.searchParams.get("q")??"",p=Number(n.searchParams.get("limit")??10),g=Number.isInteger(p)?Math.max(1,Math.min(20,p)):10;m(t,200,await Br(r.wiki,r.hub,o,l,g));return}let s=/^\/v1\/wiki\/pages\/([^/]+)\/history$/u.exec(n.pathname);if(e.method==="GET"&&s){m(t,200,await Ur(r.wiki,r.hub,o,decodeURIComponent(s[1])));return}let a=/^\/v1\/wiki\/pages\/([^/]+)\/backlinks$/u.exec(n.pathname);if(e.method==="GET"&&a){m(t,200,await Jr(r.wiki,r.hub,o,decodeURIComponent(a[1])));return}let c=/^\/v1\/wiki\/pages\/([^/]+)$/u.exec(n.pathname);if(e.method==="GET"&&c){m(t,200,await Vr(r.wiki,r.hub,o,decodeURIComponent(c[1])));return}if(e.method==="PUT"&&c){m(t,200,await qr(r.wiki,r.hub,o,decodeURIComponent(c[1]),await k(e)));return}if(n.pathname.startsWith("/v1/governance")&&(!r.governance||!r.wiki||!r.hub)){m(t,503,{error:"Knowledge Governance unavailable"});return}if(e.method==="GET"&&n.pathname==="/v1/governance"){m(t,200,await Yr(r.governance,r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/governance/reviews"){m(t,200,await Xr(r.governance,r.hub,o,n.searchParams.get("status")??void 0));return}let u=/^\/v1\/governance\/reviews\/([^/]+)$/u.exec(n.pathname);if(e.method==="POST"&&u){m(t,200,await Zr(r.governance,r.wiki,r.hub,o,decodeURIComponent(u[1]),await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/governance/quality"){m(t,200,await en(r.governance,r.wiki,r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/governance/policy"){m(t,200,await tn(r.governance,r.hub,o));return}if(e.method==="PUT"&&n.pathname==="/v1/governance/policy"){m(t,200,await rn(r.governance,r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/governance/audit"){let l=Number(n.searchParams.get("limit")??100),p=Number.isInteger(l)?Math.max(1,Math.min(500,l)):100;m(t,200,await nn(r.governance,r.hub,o,p));return}m(t,404,{error:"Not found"})}catch(n){if(n instanceof h||n instanceof f){m(t,n.statusCode,{error:n.message});return}if(n instanceof Error&&n.message.startsWith("Invalid ")){m(t,400,{error:n.message});return}m(t,500,{error:n instanceof Error?n.message:String(n)})}})}var sn=process.env.TOOLNET_API_HOST??"127.0.0.1",an=Number(process.env.TOOLNET_API_PORT??9750);async function xs(){let r=Se(),e=new re().detect(),t=Ct({provider:r.storage.provider,r2:r.storage.r2,s3:r.storage.s3,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),n=It(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),o=new ye(n,e.id,e.name,e.remote??e.name),i=new he(o,e,process.env.TOOLNET_HUB_OWNER?.trim()||"owner"),s=new ke(i,Number(process.env.TOOLNET_HUB_MAX_EVENTS??100));await s.initialize();let a=new W(o,e),c=new V(a);await c.initialize();let u=new U(new B(o,e));await u.initialize();let l=new ce,p=new ge(o);l.importRecords(await p.load(e.id));let g=new pe(l);on({project:e,retrieval:g,token:process.env.TOOLNET_API_TOKEN?.trim()||void 0,hub:s,wiki:c,governance:u}).listen(an,sn,()=>{console.log("ToolNet Memory API"),console.log(`Project: ${e.name}`),console.log(`Listening: http://${sn}:${an}`)})}xs().catch(r=>{console.error(r),process.exit(1)});
1
+ import"dotenv/config";import{existsSync as In,readFileSync as En}from"node:fs";import{homedir as Tn}from"node:os";import{join as Rn}from"node:path";function jn(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 On(){let r=process.env.TOOLNET_GLOBAL_ENV??Rn(Tn(),".config","toolnet-memory",".env");if(!In(r))return;let e=En(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]=jn(n.slice(o+1)))}}On();function K(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function $(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function Pe(){return{memory:{autoCapture:K(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:K(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:K(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:K(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:$(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:$(process.env.MEMORY_RERANK_TOP,10),finalContext:$(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:$(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:K(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:$(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var _n={critical:100,high:75,normal:50,temporary:20};function Xe(r){return _n[r]}function Ze(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 Dn}from"node:crypto";import{existsSync as ie,mkdirSync as Wn,readFileSync as zn,renameSync as Gn,writeFileSync as Vn}from"node:fs";import{basename as qn,dirname as se,join as L,parse as at,resolve as P}from"node:path";import{createHash as rt}from"node:crypto";import{spawnSync as Nn}from"node:child_process";var F="git-remote-v1",Kn=new Set(["github.com","gitlab.com","bitbucket.org"]);function nt(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:(Kn.has(r)&&(t=t.toLowerCase()),t)}function $n(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=nt(t,e.pathname);return i?`${o}/${i}`:null}function Fn(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=nt(t,e[2]??"");return n?`${t}/${n}`:null}function et(r){let e=r.trim();return e?e.includes("://")?$n(e):Fn(e):null}function Ln(r){return rt("sha256").update(`${F}:${r}`).digest("hex")}function ot(r){return rt("sha256").update(`toolnet-project:${F}:${r}`).digest("hex").slice(0,16)}function Hn(r){return r.split("/").filter(Boolean).at(-1)?.trim()||null}function Ie(r,e){let t=Nn("git",["-C",r,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function tt(r,e){let t=Hn(r);return t?{scheme:F,canonicalRemote:r,fingerprint:Ln(r),repositoryName:t,source:e}:null}function it(r){let e=Ie(r,["remote","get-url","origin"]);if(e){let o=et(e);if(o)return tt(o,"origin")}let t=Ie(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=Ie(r,["remote","get-url",o]);if(!i)continue;let s=et(i);s&&n.add(s)}return n.size!==1?null:tt([...n][0],"unique-remote")}var ct=".toolnet",Bn="project.json";function Un(r){return Dn("sha256").update(r).digest("hex").slice(0,16)}function j(r){return L(r,ct,Bn)}function ut(r){return ie(j(r))}function st(r,e){let t=P(r),n=at(t).root;for(;;){if(ut(t))return t;if(t===n||e&&t===P(e))break;let o=se(t);if(o===t)break;t=o}return null}function Ee(r){let e=P(r),t=at(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>ie(L(e,i))))return e;if(e===t)break;let o=se(e);if(o===e)break;e=o}return P(r)}function ne(r){let e;try{e=JSON.parse(zn(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:se(se(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 oe(r,e){let t=L(r,ct);Wn(t,{recursive:!0});let n=j(r),o=`${n}.tmp-${process.pid}`;Vn(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Gn(o,n)}function C(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 Te(r){return{version:1,scheme:F,canonicalRemote:r.canonicalRemote,fingerprint:r.fingerprint,repositoryName:r.repositoryName}}function Yn(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 ae=class{adopt(e,t){let n=Ee(P(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(ut(n)){let a=ne(j(n));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return C(a,n)}let o=new Date().toISOString(),i={...t.metadata};t.gitIdentity&&(i.toolnetIdentity=Te(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 oe(n,s),C(s,n)}recordGitIdentity(e,t,n={}){let o=this.requireExisting(e),i=j(o.rootPath),s=ne(i),a=Yn(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:Te(t)},s.updatedAt=new Date().toISOString(),oe(o.rootPath,s)),C(s,o.rootPath)}findExisting(e=process.cwd()){let t=P(e),n=Ee(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>ie(L(n,c))),s=st(t,i?n:void 0);if(!s)return null;let a=ne(j(s));return C(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=P(e),n=Ee(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>ie(L(n,d))),s=st(t,i?n:void 0);if(s){let d=j(s),g=ne(d);return g.rootPath!==s&&(g.rootPath=s,g.updatedAt=new Date().toISOString(),oe(s,g)),C(g,s)}let a=new Date().toISOString(),c=qn(n),u=it(n),l={version:1,id:u?ot(u.canonicalRemote):Un(n),name:c,remote:u?.repositoryName??c,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:u?{toolnetIdentity:Te(u)}:void 0};return oe(n,l),C(l,n)}};import{randomUUID as Eo}from"node:crypto";var Jn=[{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"}],Qn=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function lt(r){return r.normalize("NFKC").trim().toLowerCase()}function Xn(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 Zn(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function eo(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 to(r,e){return r.start<e.end&&e.start<r.end}function dt(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var ce=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=lt(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let i of Jn){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=dt(t),o=[];for(let i of n)o.some(s=>to(s,i))||o.push(i);return dt(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=lt(e);return Qn.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)||Zn(i)||!/[A-Za-z]/u.test(i)||!/[0-9]/u.test(i)||eo(e,o.index,o.index+i.length)&&(Xn(i)<3.7||t.push({type:"high_entropy_secret",value:i,start:o.index,end:o.index+i.length,confidence:"heuristic"}))}return t}};var O=class{scanner;constructor(e={}){this.scanner=new ce(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 mt=new O;function pt(r){return mt.sanitize(r).text}function ue(r){return mt.sanitizeValue(r)}var ro=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"]),no=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"]),oo=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"]),io=new Set(["rule","decision","todo","next_action","fix","context","architecture"]);function S(r){return r.normalize("NFKC").trim().toLowerCase()}function St(r,e){for(let t of e){let n=r.metadata?.[t];if(typeof n!="string")continue;let o=S(n);if(o)return o}}function xt(r,e){for(let t of r.tags){let n=S(t);for(let o of e){if(!n.startsWith(o))continue;let i=n.slice(o.length).trim();if(i)return i}}}function le(r){if(typeof r!="string")return;let e=S(r).replaceAll("-","_");if(e==="nextaction")return"next_action";if(io.has(e))return e}function I(r){let e=le(r.metadata?.conflictKind);if(e)return e;let t=le(r.metadata?.learningKind);if(t)return t;let n=le(r.metadata?.lifecycleKind);if(n)return n;for(let o of r.tags){let i=S(o);if(!i.startsWith("kind:"))continue;let s=le(i.slice(5));if(s)return s}return r.tags.some(o=>S(o)==="next_action")?"next_action":r.type==="rule"?"rule":r.type==="decision"?"decision":r.type==="todo"?"todo":"other"}function so(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 je(r){return new Set(S(r).replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/u).filter(e=>e.length>2&&!no.has(e)))}function ft(r){return new Set([...je(r)].filter(e=>!oo.has(e)))}function Mt(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 ao(r,e){return Mt(je(r),je(e))}function co(r,e){return Mt(ft(r),ft(e))}function gt(r){return new Set(r.tags.map(S).filter(e=>!(ro.has(e)||e.startsWith("class:")||e.startsWith("kind:")||e.startsWith("level:"))))}function uo(r,e){let t=gt(r),n=gt(e);for(let o of t)if(n.has(o))return!0;return!1}function yt(r){return St(r,["topic","topicKey"])??xt(r,["topic:"])}function ht(r){return St(r,["entity","entityKey","subject","taskId","taskKey"])??xt(r,["entity:","subject:","task:"])}function kt(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(S).filter(Boolean)):new Set}function lo(r,e){let t=kt(r);if(t.size===0)return!1;let n=kt(e);for(let o of t)if(n.has(o))return!0;return!1}function H(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 mo(r){let e=H(r);return e.userExplicit||e.sourceVerified||e.testVerified||e.crossSessionConfirmations>0}function po(r){let e=Number(r.metadata?.confidence);return Number.isFinite(e)?Math.max(0,Math.min(1,e)):0}function fo(r){return r.importance==="critical"?20:r.importance==="high"?12:r.importance==="normal"?5:0}function vt(r){let e=H(r),t=fo(r);return e.userExplicit&&(t+=100),e.sourceVerified&&(t+=60),e.testVerified&&(t+=60),t+=Math.min(5,e.crossSessionConfirmations)*12,t+=po(r)*10,r.metadata?.knowledgeClass==="permanent"&&(t+=10),e.assistantDerived&&(t-=15),Math.round(t*1e3)/1e3}function go(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 yo(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 ho(r,e){if(e.id===r.id||e.projectId!==r.projectId)return!1;let t=so(e);if(["superseded","resolved","completed","stale"].includes(t))return!1;let n=I(r),o=I(e);if(!go(n,o))return!1;let i=yt(r),s=yt(e);if(i&&s&&i===s)return!0;let a=ht(r),c=ht(e);if(a&&c&&a===c||uo(r,e))return!0;let u=yo(n,o),l=co(r.content,e.content);return!!(l>=u||ao(r.content,e.content)>=u||lo(r,e)&&l>=Math.max(.3,u-.2))}function wt(r){return I(r)==="rule"&&H(r).userExplicit}function ko(r,e){return!wt(r)||!wt(e)?!1:r.createdAt>=e.createdAt}function bt(r){let e=H(r);return e.userExplicit||e.sourceVerified||e.testVerified}function de(r){return r==="todo"||r==="next_action"}function Re(r,e){return r.createdAt>=e.createdAt}var me=class{resolve(e,t){let n=I(e),o={kind:n,superseded:[],conflicts:[],completed:[],resolved:[]};if(n==="other")return o;let i=vt(e);for(let s of t){if(!ho(e,s))continue;let a=I(s),c=vt(s);if(n==="fix"&&de(a)){if(bt(e)){o.completed.push(s);continue}o.conflicts.push(s);continue}if(n==="fix"&&a==="context"){if(bt(e)&&i>=c){o.resolved.push(s);continue}o.conflicts.push(s);continue}if(de(n)&&a==="fix"){if(H(e).userExplicit||i>c){o.superseded.push(s);continue}o.conflicts.push(s);continue}if(de(n)&&de(a)){if(i>c||i===c&&Re(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(ko(e,s)){o.superseded.push(s);continue}if(["context","fix","architecture","decision"].includes(n)&&Re(e,s)){o.superseded.push(s);continue}if(!mo(s)&&Re(e,s)){o.superseded.push(s);continue}o.conflicts.push(s)}return o}findSuperseded(e,t){return this.resolve(e,t).superseded}};var vo=new Set(["code","decision","rule","todo","summary"]);function wo(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function At(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 bo(r,e){let t=At(e)-At(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 Ct(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 Pt(r){let e=new Map;for(let o of r){if(!vo.has(o.type)||o.metadata?.supersededBy)continue;let i=wo(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(bo),s=i[0];if(!s)continue;let a=i.slice(1);t.push({canonicalId:s.id,duplicateIds:a.map(c=>c.id),mergedTags:Ct(i.flatMap(c=>c.tags)),mergedSources:Ct(i.map(c=>c.source))}),n+=a.length}return{groups:t,duplicates:n}}function Oe(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 So(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function xo(r){let e=Oe(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 Mo(r){return Oe(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function Ao(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 It(r,e=Date.now()){let t=50,n=[],o=Oe(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")),Ao(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=So(r,e)>=xo(r);a&&(t-=15,n.push("stale for lifecycle class"));let c=Mo(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"||o==="transient";return{score:t,tier:u,stale:a,protected:c,pruneEligible:!c&&(u==="noise"&&l||a&&(u==="noise"||u==="weak")),reasons:n}}var Co={critical:100,high:75,normal:50,temporary:20},Po={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function Et(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 _e(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function Io(r){return!!r.metadata?.supersededBy||r.metadata?.lifecycleState==="superseded"}function Ne(r,e=Date.now()){if(_e(r,e)||Io(r))return!1;let t=r.metadata?.lifecycleState;return!(t==="completed"||t==="resolved"||t==="conflicting"||t==="stale")}function D(r,e=Date.now()){if(!Ne(r,e))return 0;let t=Co[r.importance];if(r.importance==="critical")return t;let n=Po[r.type]??180,i=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,s=Math.pow(.5,i/n);return t*s}var pe=class{memories=new Map;conflicts=new me;remember(e){let n=(e.createdAt&&Number.isFinite(Date.parse(e.createdAt))?new Date(e.createdAt).toISOString():void 0)??new Date().toISOString(),o=pt(e.content.trim()),i=e.importance??Ze(e.type,o),s={id:Eo(),projectId:e.projectId,type:e.type,content:o,importance:i,importanceScore:Xe(i),tags:e.tags??[],source:e.source??"agent",createdAt:n,updatedAt:n,expiresAt:e.expiresAt??Et(e.type,i,new Date(n)),metadata:ue(e.metadata)};s.metadata={...s.metadata??{},lifecycleState:"active"},s.metadata={...s.metadata,conflictKind:I(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(u=>u.id);s.metadata={...s.metadata??{},conflictsWith:c,lifecycleState:"conflicting"};for(let u of a.conflicts){let l=Array.isArray(u.metadata?.conflictsWith)?u.metadata?.conflictsWith:[],d=new Set(l.filter(g=>typeof g=="string"));d.add(s.id),u.updatedAt=n,u.metadata={...u.metadata??{},conflictsWith:[...d]},this.memories.set(u.id,u)}}return this.memories.set(s.id,s),s}importRecords(e){let t=0;for(let n of e){if(!n?.id)continue;let o=ue(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=>Ne(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=D(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,u=D(i)/500;return{memory:i,score:c+u,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=Pt(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=It(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&&_e(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}};function Ke(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var fe=class{score(e,t){let n=Ke(e),o=Ke([t.content,...t.tags??[],t.type].join(" "));if(n.length===0||o.length===0)return 0;let i=new Map;for(let a of o)i.set(a,(i.get(a)??0)+1);let s=0;for(let a of n){let c=i.get(a)??0;c!==0&&(s+=1+Math.log(1+c))}return s/n.length}};function Tt(r,e=Date.now()){let t=r.updatedAt??r.createdAt,n=new Date(t).getTime();if(!Number.isFinite(n))return 0;let o=Math.max(0,e-n)/864e5;return Math.exp(-Math.LN2*o/30)}function Rt(r){return D(r)/100}var To={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function jt(r){return To[r]??.4}var ge=class{analyze(e){let t=e.toLowerCase(),n=[];return(t.includes("quy\u1EBFt \u0111\u1ECBnh")||t.includes("decision")||t.includes("\u0111\xE3 ch\u1ECDn"))&&n.push("decision"),(t.includes("todo")||t.includes("c\u1EA7n l\xE0m")||t.includes("ti\u1EBFp theo")||t.includes("ch\u01B0a xong"))&&n.push("todo"),(t.includes("quy t\u1EAFc")||t.includes("rule")||t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c"))&&n.push("rule"),(t.includes("t\xF3m t\u1EAFt")||t.includes("summary")||t.includes("\u0111\xE3 l\xE0m"))&&n.push("summary"),{query:e,preferredTypes:n}}};var ye=class{bm25=new fe;analyzer=new ge;search(e,t,n={}){let o=n.topK??8,i=n.minScore??.05,s=this.analyzer.analyze(e),a=[];for(let c of t){if(n.types?.length&&!n.types.includes(c.type))continue;let u=this.bm25.score(e,c),l=Tt(c),d=Rt(c),g=jt(c.type);s.preferredTypes.includes(c.type)&&(g=Math.min(1,g+.25));let h=u*.55+d*.2+l*.15+g*.1;u<=0||h<i||a.push({memory:c,score:h,scores:{keyword:u,recency:l,importance:d,type:g}})}return a.sort((c,u)=>u.score-c.score).slice(0,o)}};var he=class{build(e,t=6e3){let n=[],o=0;for(let i of e){let s=i.memory,a=[`[${s.type.toUpperCase()}]`,s.content].join(" ");if(o+a.length>t)break;n.push(a),o+=a.length}return n.join(`
4
+ `)}};var ke=class{constructor(e){this.memory=e}memory;searcher=new ye;contextBuilder=new he;search(e,t,n={}){return this.searcher.search(t,this.memory.list(e),n)}context(e,t,n={}){let o=this.search(e,t,n);return this.contextBuilder.build(o)}};import{homedir as ai}from"node:os";import{join as ci}from"node:path";import{DeleteObjectCommand as Ro,GetObjectCommand as jo,HeadObjectCommand as Oo,ListObjectsV2Command as _o,PutObjectCommand as No,S3Client as Ko}from"@aws-sdk/client-s3";import{getSignedUrl as $o}from"@aws-sdk/s3-request-presigner";var ve=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ko({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 No({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await $o(this.client,new jo({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 Oo({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 Ro({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new _o({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 Ot,mkdir as Fo,readFile as Lo,readdir as Ho,rm as Do,stat as _t,writeFile as Wo}from"node:fs/promises";import{dirname as zo,join as Go,relative as Nt,resolve as Vo}from"node:path";var W=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Vo(this.root,t)}async put(e,t){let n=this.path(e);await Fo(zo(n),{recursive:!0}),await Wo(n,t)}async get(e){try{return await Lo(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 Ot(this.path(e)),!0}catch{return!1}}async delete(e){await Do(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await Ot(t)}catch{return n}let o=async s=>{let a=await Ho(s,{withFileTypes:!0});for(let c of a){let u=Go(s,c.name);if(c.isDirectory()){await o(u);continue}let l=await _t(u);n.push({key:Nt(this.root,u),size:l.size,updatedAt:l.mtime.toISOString()})}},i=await _t(t);return i.isDirectory()?await o(t):n.push({key:Nt(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),n}};import{DeleteObjectCommand as qo,GetObjectCommand as Bo,HeadObjectCommand as Uo,ListObjectsV2Command as Yo,PutObjectCommand as Jo,S3Client as Qo}from"@aws-sdk/client-s3";import{getSignedUrl as Xo}from"@aws-sdk/s3-request-presigner";var z=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Qo({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 Jo({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Xo(this.client,new Bo({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 Uo({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 qo({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new Yo({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 Zo,createDecipheriv as ei,createHash as ti,randomBytes as ri,timingSafeEqual as ni}from"node:crypto";import{readFileSync as oi}from"node:fs";var E=Buffer.from("TNMEME01","ascii"),$t=1,G=8,V=12,$e=16,Ft=E.length+1+G+V+$e,ii="toolnet-memory:remote-encryption:v1:",Lt="aes-256-gcm",Fe=32,y=class extends Error{constructor(t,n){super(n);this.code=t;this.name="RemoteEncryptionError"}code};function si(r){return r?["1","true","yes","on","enabled"].includes(r.trim().toLowerCase()):!1}function Le(r=process.env){return si(r.TOOLNET_REMOTE_ENCRYPTION)}function Kt(r){let e=r.trim();if(!e)throw new y("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 y("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 y("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!==Fe)throw new y("REMOTE_ENCRYPTION_KEY_INVALID_LENGTH",`Remote encryption key must decode to exactly ${Fe} bytes.`);return t}function Ht(r=process.env){let e=r.TOOLNET_REMOTE_ENCRYPTION_KEY?.trim(),t=r.TOOLNET_REMOTE_ENCRYPTION_KEY_FILE?.trim();if(e&&t)throw new y("REMOTE_ENCRYPTION_KEY_AMBIGUOUS","Configure either TOOLNET_REMOTE_ENCRYPTION_KEY or TOOLNET_REMOTE_ENCRYPTION_KEY_FILE, not both.");if(e)return Kt(e);if(t){let n;try{n=oi(t,"utf8")}catch(o){throw new y("REMOTE_ENCRYPTION_KEY_FILE_READ_FAILED",[`Unable to read remote encryption key file: ${t}.`,o instanceof Error?o.message:String(o)].join(" "))}return Kt(n)}}function Dt(r){return ti("sha256").update(r).digest().subarray(0,G)}function Wt(r){return Buffer.from(`${ii}${r}`,"utf8")}function He(r){return r.byteLength<E.length?!1:Buffer.from(r).subarray(0,E.length).equals(E)}function zt(r,e,t){if(t.byteLength!==Fe)throw new y("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=ri(V),i=Zo(Lt,t,o);i.setAAD(Wt(r));let s=Buffer.concat([i.update(n),i.final()]),a=i.getAuthTag(),c=Buffer.alloc(Ft),u=0;return E.copy(c,u),u+=E.length,c.writeUInt8($t,u),u+=1,Dt(t).copy(c,u),u+=G,o.copy(c,u),u+=V,a.copy(c,u),Buffer.concat([c,s])}function Gt(r,e,t){let n=Buffer.from(e);if(!He(n))throw new y("REMOTE_ENCRYPTION_ENVELOPE_REQUIRED","Payload is not a ToolNet encrypted remote object.");if(n.length<Ft)throw new y("REMOTE_ENCRYPTION_ENVELOPE_TRUNCATED","Encrypted remote payload is truncated.");let o=E.length,i=n.readUInt8(o);if(o+=1,i!==$t)throw new y("REMOTE_ENCRYPTION_VERSION_UNSUPPORTED",`Unsupported remote encryption envelope version: ${i}.`);let s=n.subarray(o,o+G);o+=G;let a=Dt(t);if(!ni(s,a))throw new y("REMOTE_ENCRYPTION_KEY_MISMATCH","Configured remote encryption key does not match this encrypted object.");let c=n.subarray(o,o+V);o+=V;let u=n.subarray(o,o+$e);o+=$e;let l=n.subarray(o),d=ei(Lt,t,c);d.setAAD(Wt(r)),d.setAuthTag(u);try{return Buffer.concat([d.update(l),d.final()])}catch{throw new y("REMOTE_ENCRYPTION_AUTH_FAILED","Encrypted remote object failed AES-GCM authentication.")}}var De=class{constructor(e,t){this.inner=e;this.options=t;if(this.name=e.name,t.enabled&&!t.key)throw new y("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 y("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote encryption key is unavailable.");let i=zt(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(!He(t))return t;if(!this.options.enabled)throw new y("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 y("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote object is encrypted but no decryption key is configured.");return Gt(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 Vt(r,e=process.env){if(r.name==="local")return Le(e)&&console.warn("[storage] Remote encryption requested but active storage provider is local; local data remains unchanged."),r;let t=Le(e),n=t?Ht(e):void 0;return new De(r,{enabled:t,key:n})}function q(r){return Vt(r)}function We(r,e){return console.warn(e),q(new W(r))}function qt(r){let e=r.localRoot??ci(ai(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?q(new z({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):We(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?q(new z({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):We(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?q(new ve({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey})):We(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return q(new W(e))}var we=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 ui(r){return new Promise(e=>setTimeout(e,r))}async function Bt(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)),u=Math.floor(Math.random()*Math.max(1,c*.2));await ui(c+u)}throw i}var li=new Set(["put","get","getText","delete","list"]);function Ut(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:li.has(n)?(...i)=>Bt(()=>Promise.resolve(o.apply(t,i)),e):o.bind(t)}})}function Yt(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 Jt(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 be=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=Yt(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)+`
5
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Jt(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};var x=["hub:read","teams:write","agents:write","acl:manage","loadouts:write","observability:read","wiki:read","wiki:write","governance:read","governance:write"];var Qt="hub/state.v1.json";function di(r,e){let t=new Date().toISOString();return{schema:"toolnet.memory-hub.v1",version:1,ownerPrincipal:e,project:{id:r.id,name:r.name,remote:r.remote??r.name},teams:[],agents:[],acl:[{principal:e,role:"owner",scopes:[...x],createdAt:t,updatedAt:t}],loadouts:[],observability:{requests:0,mutations:0,errors:0,events:[]},createdAt:t,updatedAt:t}}function mi(r,e){let t=JSON.parse(r);if(t.schema!=="toolnet.memory-hub.v1"||t.version!==1||!t.project||t.project.id!==e.id||!Array.isArray(t.teams)||!Array.isArray(t.agents)||!Array.isArray(t.acl)||!Array.isArray(t.loadouts)||!t.observability||!Array.isArray(t.observability.events))throw new Error("Invalid ToolNet Memory Hub state");return t}var Se=class{constructor(e,t,n){this.storage=e;this.project=t;this.ownerPrincipal=n}storage;project;ownerPrincipal;async load(){let e=await this.storage.getText(Qt);if(!e){let t=di(this.project,this.ownerPrincipal);return await this.save(t),t}return mi(e,this.project)}async save(e){await this.storage.put(Qt,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as ze}from"node:crypto";var Xt=["memory_search","memory_agent_ask","skill_memory_search","context_offload_read","wiki_search","wiki_read","knowledge_governance_status"],k=class extends Error{constructor(t,n){super(t);this.statusCode=n}statusCode};function pi(r){return r==="owner"||r==="admin"?[...x]:["hub:read"]}function Ge(r){return[...new Set(r.map(e=>e.trim()).filter(Boolean))]}function fi(r){return structuredClone(r)}var xe=class{constructor(e,t=100){this.store=e;this.maxEvents=t}store;maxEvents;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(e){let t,n=this.queue.then(async()=>{let o=await this.ensureState();t=e(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=n.then(()=>{},()=>{}),await n,t}grantFor(e,t){return e.acl.find(n=>n.principal===t)}async authorize(e,t){let n=await this.ensureState(),o=this.grantFor(n,e);return!!(o&&(o.role==="owner"||o.role==="admin"||o.scopes.includes(t)))}async requireScope(e,t){if(!await this.authorize(e,t))throw new k(`Principal '${e}' lacks '${t}'`,403)}event(e,t,n,o){return{id:ze(),kind:e,action:t,principal:n,ok:o,timestamp:new Date().toISOString()}}pushEvent(e,t){e.observability.events.push(t),e.observability.events.length>this.maxEvents&&(e.observability.events=e.observability.events.slice(-this.maxEvents)),e.observability.lastActivityAt=t.timestamp}mutation(e,t,n){e.observability.mutations+=1,this.pushEvent(e,this.event("mutation",t,n,!0))}async summary(e){await this.requireScope(e,"hub:read");let t=await this.ensureState();return{schema:t.schema,project:{...t.project},teams:t.teams.length,agents:t.agents.length,aclGrants:t.acl.length,loadouts:t.loadouts.length,updatedAt:t.updatedAt}}async listTeams(e){return await this.requireScope(e,"hub:read"),structuredClone((await this.ensureState()).teams)}async createTeam(e,t){return await this.requireScope(e,"teams:write"),this.mutate(n=>{let o=new Date().toISOString(),i=t.id?.trim()||`team-${ze().slice(0,8)}`;if(n.teams.some(a=>a.id===i))throw new k(`Team already exists: ${i}`,409);let s={id:i,name:t.name.trim(),...t.description?.trim()?{description:t.description.trim()}:{},createdAt:o,updatedAt:o};return n.teams.push(s),this.mutation(n,`team:create:${i}`,e),structuredClone(s)})}async listAgents(e){return await this.requireScope(e,"hub:read"),structuredClone((await this.ensureState()).agents)}async createAgent(e,t){return await this.requireScope(e,"agents:write"),this.mutate(n=>{let o=new Date().toISOString(),i=t.id?.trim()||`agent-${ze().slice(0,8)}`;if(n.agents.some(c=>c.id===i))throw new k(`Agent already exists: ${i}`,409);let s=Ge(t.teamIds??[]);for(let c of s)if(!n.teams.some(u=>u.id===c))throw new k(`Team not found: ${c}`,404);let a={id:i,name:t.name.trim(),...t.kind?.trim()?{kind:t.kind.trim()}:{},teamIds:s,...t.metadata?{metadata:structuredClone(t.metadata)}:{},createdAt:o,updatedAt:o};return n.agents.push(a),n.loadouts.push({agentId:i,tools:[...Xt],memoryMode:"local",skillMemory:!0,contextOffload:!0,maxContextChars:6400,updatedAt:o}),this.mutation(n,`agent:create:${i}`,e),structuredClone(a)})}async listAcl(e){return await this.requireScope(e,"acl:manage"),structuredClone((await this.ensureState()).acl)}async grantAcl(e,t){return await this.requireScope(e,"acl:manage"),this.mutate(n=>{let o=new Date().toISOString(),i=Ge(t.scopes??pi(t.role));for(let c of i)if(!x.includes(c))throw new k(`Unknown Memory Hub scope: ${c}`,400);let s=n.acl.find(c=>c.principal===t.principal);if(s)return s.role=t.role,s.scopes=[...i],s.updatedAt=o,this.mutation(n,`acl:update:${t.principal}`,e),structuredClone(s);let a={principal:t.principal,role:t.role,scopes:[...i],createdAt:o,updatedAt:o};return n.acl.push(a),this.mutation(n,`acl:grant:${t.principal}`,e),structuredClone(a)})}async revokeAcl(e,t){await this.requireScope(e,"acl:manage"),await this.mutate(n=>{if(t===n.ownerPrincipal)throw new k("Memory Hub owner ACL cannot be revoked",409);let o=n.acl.length;if(n.acl=n.acl.filter(i=>i.principal!==t),n.acl.length===o)throw new k(`ACL principal not found: ${t}`,404);this.mutation(n,`acl:revoke:${t}`,e)})}async listLoadouts(e){return await this.requireScope(e,"hub:read"),structuredClone((await this.ensureState()).loadouts)}async getLoadout(e,t){await this.requireScope(e,"hub:read");let n=(await this.ensureState()).loadouts.find(o=>o.agentId===t);if(!n)throw new k(`Agent loadout not found: ${t}`,404);return structuredClone(n)}async setLoadout(e,t){return await this.requireScope(e,"loadouts:write"),this.mutate(n=>{if(!n.agents.some(s=>s.id===t.agentId))throw new k(`Agent not found: ${t.agentId}`,404);let o=new Date().toISOString(),i=n.loadouts.find(s=>s.agentId===t.agentId);return i||(i={agentId:t.agentId,tools:[...Xt],memoryMode:"local",skillMemory:!0,contextOffload:!0,maxContextChars:6400,updatedAt:o},n.loadouts.push(i)),t.tools&&(i.tools=Ge(t.tools)),t.memoryMode&&(i.memoryMode=t.memoryMode),t.skillMemory!==void 0&&(i.skillMemory=t.skillMemory),t.contextOffload!==void 0&&(i.contextOffload=t.contextOffload),t.maxContextChars!==void 0&&(i.maxContextChars=t.maxContextChars),i.updatedAt=o,this.mutation(n,`loadout:set:${t.agentId}`,e),structuredClone(i)})}async observability(e){return await this.requireScope(e,"observability:read"),structuredClone((await this.ensureState()).observability)}async recordRequest(e){await this.mutate(t=>{let n=e.statusCode<400;t.observability.requests+=1,n||(t.observability.errors+=1);let o={...this.event("request",`${e.method} ${e.path}`,e.principal,n),statusCode:e.statusCode,durationMs:Math.max(0,Math.floor(e.durationMs))};this.pushEvent(t,o)})}async snapshot(){return fi(await this.ensureState())}};var Zt="wiki/state.v1.json";function gi(r){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:r.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function yi(r,e){let t=JSON.parse(r);if(t.schema!=="toolnet.wiki.v1"||t.version!==1||t.projectId!==e.id||!Array.isArray(t.pages)||!Array.isArray(t.revisions))throw new Error("Invalid ToolNet Wiki state");return t}var B=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(Zt);if(!e){let t=gi(this.project);return await this.save(t),t}return yi(e,this.project)}async save(e){await this.storage.put(Zt,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as rr}from"node:crypto";var f=class extends Error{constructor(t,n){super(t);this.statusCode=n}statusCode};function U(r){let e=new Set,t=[];for(let n of r){let o=n.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();e.has(i)||(e.add(i),t.push(o))}return t}function Y(r){let e=r.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!e)throw new f("Invalid Wiki slug",400);return e}function er(r){let e=[];for(let t of r.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let n=t[1]?.trim();n&&e.push(Y(n))}return U(e)}function hi(r){return r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function tr(r){return{id:`revision-${rr()}`,pageId:r.id,slug:r.slug,revision:r.revision,title:r.title,...r.summary?{summary:r.summary}:{},content:r.content,tags:[...r.tags],links:[...r.links],createdAt:r.updatedAt}}function T(r){return structuredClone(r)}var J=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(e){let t,n=this.queue.then(async()=>{let o=await this.ensureState();t=e(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=n.then(()=>{},()=>{}),await n,t}async summary(){let e=await this.ensureState(),t=new Set(e.pages.flatMap(n=>n.links));return{schema:"toolnet.wiki-summary.v1",projectId:e.projectId,pages:e.pages.length,revisions:e.revisions.length,tags:U(e.pages.flatMap(n=>n.tags)).sort((n,o)=>n.localeCompare(o)),links:e.pages.reduce((n,o)=>n+o.links.length,0),orphanPages:e.pages.filter(n=>n.links.length===0&&!t.has(n.slug)).length,automatedPages:e.pages.filter(n=>n.tags.some(o=>o.startsWith("toolnet-auto-"))).length,updatedAt:e.updatedAt}}async listPages(){let e=await this.ensureState();return T([...e.pages].sort((t,n)=>t.title.localeCompare(n.title)))}async getPage(e){let t=await this.ensureState(),n=Y(e),o=t.pages.find(i=>i.slug===n||i.id===e);if(!o)throw new f(`Wiki page not found: ${e}`,404);return T(o)}async createPage(e){return this.mutate(t=>{let n=e.title.trim(),o=e.content.trim();if(!n)throw new f("Wiki title is required",400);let i=Y(e.slug??n);if(t.pages.some(c=>c.slug===i))throw new f(`Wiki page already exists: ${i}`,409);let s=new Date().toISOString(),a={id:`wiki-${rr()}`,slug:i,title:n,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:o,tags:U(e.tags??[]),links:er(o),revision:1,createdAt:s,updatedAt:s};return t.pages.push(a),t.revisions.push(tr(a)),T(a)})}async updatePage(e,t){return this.mutate(n=>{let o=Y(e),i=n.pages.find(s=>s.slug===o||s.id===e);if(!i)throw new f(`Wiki page not found: ${e}`,404);if(t.title!==void 0){let s=t.title.trim();if(!s)throw new f("Wiki title is required",400);i.title=s}if(t.summary!==void 0){let s=t.summary.trim();s?i.summary=s:delete i.summary}return t.content!==void 0&&(i.content=t.content.trim(),i.links=er(i.content)),t.tags!==void 0&&(i.tags=U(t.tags)),i.revision+=1,i.updatedAt=new Date().toISOString(),n.revisions.push(tr(i)),T(i)})}async history(e){let t=await this.getPage(e),n=await this.ensureState();return T(n.revisions.filter(o=>o.pageId===t.id).sort((o,i)=>i.revision-o.revision))}async backlinks(e){let t=await this.getPage(e),n=await this.ensureState();return T(n.pages.filter(o=>o.links.includes(t.slug)).sort((o,i)=>o.title.localeCompare(i.title)))}async search(e,t=10){let n=await this.ensureState(),o=U(hi(e));if(o.length===0)return[];let i=Math.max(1,Math.min(20,Math.floor(t))),s=[];for(let a of n.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),l=a.summary?.toLowerCase()??"",d=a.content.toLowerCase(),g=a.tags.map(w=>w.toLowerCase()),h=0;for(let w of o)u===w&&(h+=12),c===w&&(h+=10),c.includes(w)&&(h+=6),u.includes(w)&&(h+=5),g.some(Ce=>Ce===w)?h+=5:g.some(Ce=>Ce.includes(w))&&(h+=3),l.includes(w)&&(h+=2),d.includes(w)&&(h+=1);h>0&&s.push({page:T(a),score:h})}return s.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,i)}};import{createHash as ki,randomUUID as nr}from"node:crypto";var or="wiki/governance.v1.json",cr="toolnet.knowledge-governance.v1",ir=500,Q={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function vi(r,e=0,t=1){return Math.max(e,Math.min(t,r))}function Ve(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function sr(r){return ki("sha256").update(r.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function wi(r){let e=[r.title,r.summary??"",r.content.slice(0,2e3),...r.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(e)}function bi(r){let e=r.sourceType==="skill"?.96:r.sourceType==="memory"?.94:.88,t=r.tags.map(n=>n.toLowerCase());return(t.includes("permanent")||t.includes("task"))&&(e+=.03),r.content.length>=200&&(e+=.02),r.content.length<80&&(e-=.05),r.title.length<4&&(e-=.05),vi(e)}function ar(r){let e=new Date().toISOString();return{schema:cr,version:1,projectId:r,policy:{...Q},reviews:[],audit:[],createdAt:e,updatedAt:e}}function ur(r){let e=r.autoApproveThreshold??Q.autoApproveThreshold,t=r.criticalApproveThreshold??Q.criticalApproveThreshold,n=r.staleAfterDays??Q.staleAfterDays;if(!Number.isFinite(e)||e<.5||e>1)throw new f("Invalid autoApproveThreshold",400);if(!Number.isFinite(t)||t<.5||t>1)throw new f("Invalid criticalApproveThreshold",400);if(!Number.isInteger(n)||n<1||n>3650)throw new f("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:t,staleAfterDays:n}}var X=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(or);if(!e){let t=ar(this.project.id);return await this.save(t),t}try{let t=JSON.parse(e);if(t.schema!==cr||t.version!==1||t.projectId!==this.project.id||!Array.isArray(t.reviews)||!Array.isArray(t.audit))throw new Error("invalid");return{...t,policy:ur(t.policy??Q)}}catch{let t=ar(this.project.id);return await this.save(t),t}}async save(e){await this.storage.put(or,JSON.stringify(e,null,2),"application/json")}},Z=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(e,t,n,o={}){e.audit.push({id:nr(),action:t,principal:n,...o.reviewId?{reviewId:o.reviewId}:{},...o.sourceKey?{sourceKey:o.sourceKey}:{},timestamp:new Date().toISOString(),...o.metadata?{metadata:o.metadata}:{}}),e.audit.length>ir&&(e.audit=e.audit.slice(-ir))}async mutate(e){let t,n=this.queue.then(async()=>{let o=await this.ensureState();t=await e(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=n.then(()=>{},()=>{}),await n,t}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(e,t){return this.mutate(n=>(n.policy=ur({...n.policy,...e}),this.audit(n,"policy:update",t,{metadata:{...n.policy}}),{...n.policy}))}async summary(){let e=await this.ensureState(),t=n=>e.reviews.filter(o=>o.status===n).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:e.projectId,pending:t("pending"),approved:t("approved"),rejected:t("rejected"),superseded:t("superseded"),criticalPending:e.reviews.filter(n=>n.status==="pending"&&n.risk==="critical").length,conflictPending:e.reviews.filter(n=>n.status==="pending"&&n.risk==="conflict").length,auditEvents:e.audit.length,policy:{...e.policy},updatedAt:e.updatedAt}}async listReviews(e){let t=await this.ensureState();return structuredClone(t.reviews.filter(n=>!e||n.status===e).sort((n,o)=>o.updatedAt.localeCompare(n.updatedAt)))}async auditLog(e=100){let t=await this.ensureState(),n=Math.max(1,Math.min(500,Math.floor(e)));return structuredClone(t.audit.slice(-n).reverse())}async assess(e,t){let n=await this.ensureState(),o=bi(e),i=Ve(e.title),s=t.filter(l=>l.slug!==e.slug&&Ve(l.title)===i&&sr(l.content)!==sr(e.content)).map(l=>l.slug),a=wi(e),c=[];o<n.policy.autoApproveThreshold&&c.push(`confidence:${o.toFixed(2)}`),a&&o<n.policy.criticalApproveThreshold&&c.push("critical-knowledge"),s.length>0&&c.push("conflicting-knowledge");let u=s.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:u,requiresReview:s.length>0||o<n.policy.autoApproveThreshold||a&&o<n.policy.criticalApproveThreshold,reasons:c,conflicts:s}}async gate(e,t){let n=await this.assess(e,t);return this.mutate(o=>{let i=o.reviews.find(c=>c.sourceKey===e.sourceKey&&c.digest===e.digest);if(i?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:n,review:structuredClone(i)};if(i?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:n,review:structuredClone(i)};if(!n.requiresReview)return this.audit(o,"knowledge:auto-approved","system",{sourceKey:e.sourceKey,metadata:{confidence:n.confidence,risk:n.risk}}),{allowed:!0,mode:"auto-approved",assessment:n};if(i?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:n,review:structuredClone(i)};let s=new Date().toISOString(),a={id:nr(),sourceKey:e.sourceKey,sourceType:e.sourceType,slug:e.slug,marker:e.marker,digest:e.digest,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...new Set([...e.tags,e.marker])],confidence:n.confidence,risk:n.risk,reasons:[...n.reasons],conflicts:[...n.conflicts],status:"pending",createdAt:s,updatedAt:s};return o.reviews.push(a),this.audit(o,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:n,review:structuredClone(a)}})}async markApplied(e,t){await this.mutate(n=>{let o=n.reviews.find(i=>i.sourceKey===e&&i.digest===t&&i.status==="approved");o&&(o.appliedAt=new Date().toISOString(),o.updatedAt=o.appliedAt,this.audit(n,"knowledge:applied",o.reviewedBy??"system",{reviewId:o.id,sourceKey:e}))})}async decide(e,t,n){return this.mutate(async o=>{let i=o.reviews.find(u=>u.id===e);if(!i)throw new f(`Governance review not found: ${e}`,404);if(i.status!=="pending")throw new f("Governance review is already resolved",409);let s=new Date().toISOString();if(i.reviewedAt=s,i.reviewedBy=t.principal,i.updatedAt=s,t.note?.trim()&&(i.reviewNote=t.note.trim()),t.action==="reject")return i.status="rejected",this.audit(o,"knowledge:rejected",t.principal,{reviewId:e,sourceKey:i.sourceKey}),structuredClone(i);if(t.action==="supersede")return i.status="superseded",t.targetReviewId&&(i.supersededBy=t.targetReviewId),this.audit(o,"knowledge:superseded",t.principal,{reviewId:e,sourceKey:i.sourceKey,metadata:{targetReviewId:t.targetReviewId}}),structuredClone(i);if(t.action==="merge"){if(!t.targetReviewId)throw new f("targetReviewId is required for merge",400);let u=o.reviews.find(l=>l.id===t.targetReviewId);if(!u)throw new f("Merge target review not found",404);return i.status="superseded",i.mergedInto=u.id,this.audit(o,"knowledge:merged",t.principal,{reviewId:e,sourceKey:i.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(i)}i.status="approved";let c=(await n.listPages()).find(u=>u.slug===i.slug);if(c&&!c.tags.includes(i.marker))throw new f(`Wiki page '${i.slug}' is manually managed`,409);return c?await n.updatePage(i.slug,{title:i.title,summary:i.summary??"",content:i.content,tags:i.tags}):await n.createPage({slug:i.slug,title:i.title,...i.summary?{summary:i.summary}:{},content:i.content,tags:i.tags}),i.appliedAt=s,this.audit(o,"knowledge:approved",t.principal,{reviewId:e,sourceKey:i.sourceKey}),structuredClone(i)})}async quality(e){let t=await this.ensureState(),n=await e.listPages(),o=Date.now(),i=t.policy.staleAfterDays*864e5,s=n.map(l=>{let d=o-Date.parse(l.updatedAt);return{slug:l.slug,title:l.title,updatedAt:l.updatedAt,ageDays:Math.max(0,Math.floor(d/864e5)),stale:Number.isFinite(d)&&d>i}}).filter(l=>l.stale).map(({stale:l,...d})=>d),a=new Map;for(let l of n){let d=Ve(l.title),g=a.get(d)??[];g.push(l),a.set(d,g)}let c=[...a.entries()].filter(([,l])=>l.length>1).map(([l,d])=>({title:l,pages:d.map(g=>g.slug)})),u=t.reviews.filter(l=>l.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:n.length,automatedPages:n.filter(l=>l.tags.some(d=>d.startsWith("toolnet-auto-"))).length,manualPages:n.filter(l=>!l.tags.some(d=>d.startsWith("toolnet-auto-"))).length,stalePages:s,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(l=>l.confidence<t.policy.autoApproveThreshold).length,conflicts:u.filter(l=>l.risk==="conflict").length,generatedAt:new Date().toISOString()}}};import{timingSafeEqual as zs}from"node:crypto";import{createServer as Gs}from"node:http";function lr(r){return{ok:!0,service:"toolnet-memory",schema:"toolnet.api-health.v1",project:{id:r.id,name:r.name,remote:r.remote??r.name}}}function dr(r){return{schema:"toolnet.api-project.v1",project:{id:r.id,name:r.name,remote:r.remote??r.name,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,createdAt:r.createdAt,updatedAt:r.updatedAt}}}import{z as Ue}from"zod";import{existsSync as $i,readFileSync as Fi}from"node:fs";import{join as Li}from"node:path";var qu=new Int32Array(new SharedArrayBuffer(4));import{closeSync as Qu,existsSync as Si,fsyncSync as Xu,mkdirSync as Zu,openSync as el,readFileSync as xi,renameSync as tl,writeFileSync as rl}from"node:fs";import{dirname as ol,join as Mi}from"node:path";function Ai(r){return Mi(r.rootPath,".toolnet","work","current.json")}function qe(r){let e=Ai(r);if(!Si(e))return null;try{let t=JSON.parse(xi(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as Ci,mkdirSync as cl,readFileSync as Pi,renameSync as ul,writeFileSync as ll}from"node:fs";import{dirname as ml,join as Ii}from"node:path";function Ei(r){return Ii(r.rootPath,".toolnet","context","session-origin.json")}function Be(r){let e=Ei(r);if(!Ci(e))return null;try{let t=JSON.parse(Pi(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function Ti(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function Me(r){let e=Ti(r),t=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),n=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return t&&n?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}import{existsSync as ji,mkdirSync as Xl,readFileSync as Oi}from"node:fs";import{join as mr}from"node:path";var Fl=new O;function _i(r){return mr(r.rootPath,".toolnet","memory","checkpoints")}function Ni(r){return mr(_i(r),"latest.json")}function Ki(r){let e=Ni(r);if(!ji(e))return null;try{let t=JSON.parse(Oi(e,"utf8"));return t.schema!=="toolnet.memory.checkpoint.v1"||t.project.id!==r.id?null:t}catch{return null}}function pr(r){return Ki(r)}var Hi={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,request:95,activity:90,phase:75,file:65,next_action:55,blocker:45},next_action:{next_action:100,todo:80,task:65,blocker:60,file:40},last_file:{file:100,task:65,next_action:40},blocker:{blocker:100,task:60,next_action:50,file:35},decision:{decision:100,rule:85,architecture:80,task:45,file:30},completed:{completed:100,progress:70,task:30},status:{progress:100,task:85,phase:75,blocker:65,next_action:60},summary:{task:100,request:98,activity:96,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,rule:54,architecture:53,fix:52,progress:50,test:45,goal:35}},Di={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function Wi(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function m(r,e){let t=e.value.replace(/\s+/g," ").trim();t&&r.push({...e,value:t,score:0})}function zi(r){let e=Li(r.rootPath,".toolnet","work","handoff-latest.json");if(!$i(e))return null;try{let n=JSON.parse(Fi(e,"utf8")).continuity;return n?.schema!=="toolnet.handoff.v2"||n.project.id!==r.id?null:n}catch{return null}}function Gi(r){let e=pr(r);if(!e)return[];let t=[];e.request&&m(t,{kind:"request",value:e.request,source:"checkpoint"}),e.activity&&m(t,{kind:"activity",value:e.activity,source:"checkpoint"}),e.current.phase&&m(t,{kind:"phase",value:e.current.phase.title,source:"checkpoint"}),e.current.task&&m(t,{kind:"task",value:e.current.task.title,source:"checkpoint"});let n=e.files.active.at(-1);n&&m(t,{kind:"file",value:n,source:"checkpoint"});for(let o of e.nextActions)m(t,{kind:"next_action",value:o,source:"checkpoint"});for(let o of e.blockers)m(t,{kind:"blocker",value:o,source:"checkpoint"});for(let o of e.completed.tasks)m(t,{kind:"completed",value:o,source:"checkpoint"});for(let o of e.remaining.tasks)m(t,{kind:"todo",value:o,source:"checkpoint"});for(let o of e.durableFacts)m(t,{kind:o.kind,value:o.content,source:"checkpoint"});return t}function Vi(r){let e=zi(r);if(!e)return[];let t=[];m(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.request&&m(t,{kind:"request",value:e.request,source:"handoff"}),e.activity&&m(t,{kind:"activity",value:e.activity,source:"handoff"}),e.goal&&m(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&m(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&m(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&m(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&m(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let n of e.blockers)m(t,{kind:"blocker",value:n,source:"handoff"});for(let n of e.decisions)m(t,{kind:"decision",value:n,source:"handoff"});for(let n of e.completed.tasks)m(t,{kind:"completed",value:n,source:"handoff"});for(let n of e.remaining.todos)m(t,{kind:"todo",value:n,source:"handoff"});return m(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),m(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function qi(r){let e=Be(r);if(!e)return[];let t=[];return m(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&m(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&m(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&m(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&m(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&m(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&m(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function Bi(r){let e=qe(r);if(!e)return[];let t=[];e.currentRequest&&m(t,{kind:"request",value:e.currentRequest,source:"work-state"}),e.currentActivity&&m(t,{kind:"activity",value:e.currentActivity,source:"work-state"}),e.goal&&m(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&m(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&m(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let n=e.activeFiles?.at(-1)??e.filesTouched.at(-1);n&&m(t,{kind:"file",value:n,source:"work-state"});for(let o of e.nextActions.slice(0,5))m(t,{kind:"next_action",value:o,source:"work-state"});for(let o of e.blockers.slice(-5))m(t,{kind:"blocker",value:o,source:"work-state"});for(let o of e.decisions.slice(-5))m(t,{kind:"decision",value:o,source:"work-state"});for(let o of e.tasks.filter(i=>i.status==="completed").slice(-8))m(t,{kind:"completed",value:o.title,source:"work-state"});for(let o of e.tasks.filter(i=>i.status!=="completed"&&i.status!=="cancelled").slice(0,8))m(t,{kind:"todo",value:o.title,source:"work-state"});for(let o of e.tests.slice(-5))m(t,{kind:"test",value:o,source:"work-state"});return m(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),t}function Ui(r,e){let t=Hi[r];return e.map((n,o)=>({...n,score:(t[n.kind]??10)+Di[n.source]+Math.max(0,5-o*.01)}))}function Yi(r){let e=new Map;for(let t of r){let n=`${t.kind}:${Wi(t.value)}`,o=e.get(n);(!o||t.score>o.score)&&e.set(n,t)}return[...e.values()]}function Ae(r,e,t={}){let n=Me(e),o=[...Gi(r),...Vi(r),...qi(r),...Bi(r)],i=Yi(Ui(n,o)).sort((l,d)=>d.score-l.score),s=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),c=[],u=0;for(let l of i){if(c.length>=s)break;let d=l.kind.length+l.value.length+l.source.length+16;c.length>0&&u+d>a||(c.push(l),u+=d)}return{intent:n,facts:c,context:{project:{id:r.id,name:r.name},intent:n,selectedFacts:c.map(l=>({kind:l.kind,value:l.value,source:l.source}))},stats:{candidates:o.length,selected:c.length,chars:u}}}var fr={previous_agent:"Agent tr\u01B0\u1EDBc",request:"Y\xEAu c\u1EA7u hi\u1EC7n t\u1EA1i",activity:"\u0110ang l\xE0m",goal:"M\u1EE5c ti\xEAu",phase:"Phase",task:"Task hi\u1EC7n t\u1EA1i",file:"File hi\u1EC7n t\u1EA1i",todo:"TODO",next_action:"Ti\u1EBFp theo",blocker:"Blocker",decision:"Quy\u1EBFt \u0111\u1ECBnh",rule:"Quy t\u1EAFc",architecture:"Ki\u1EBFn tr\xFAc",fix:"\u0110\xE3 s\u1EEDa",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},gr=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],Ji={previous_agent:["previous_agent"],current_task:["request","activity","task","file","next_action"],next_action:["next_action","task","file","todo"],last_file:["file","task","next_action"],blocker:["blocker"],decision:["decision"],completed:["completed"],status:["progress","task","next_action","blocker"],summary:gr};function Qi(r){let e=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)}function Xi(r){let e=r.filter(n=>n.source==="handoff");if(e.length===0)return r;let t=r.filter(n=>n.source==="checkpoint"&&["rule","architecture","fix"].includes(n.kind));return[...e,...t]}function Zi(r){let e=new Set,t=[];for(let n of r){let o=`${n.kind}:${n.value.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}`;e.has(o)||(e.add(o),t.push(n))}return t}function yr(r){switch(r){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function es(r,e){let t=[];for(let n of e){let o=r.filter(i=>i.kind===n).slice(0,yr(n));for(let i of o)t.push(`${fr[n]}: ${i.value}`)}return t.join(`
6
+ `)}function ts(r,e){let t=Ji[e]??gr,n=[];for(let o of t){let i=r.filter(s=>s.kind===o).slice(0,yr(o));for(let s of i)n.push(`${fr[o]}: ${s.value}`)}return n.join(`
7
+ `)}function hr(r,e){let t=Ae(r,e,{maxFacts:32,maxChars:6400}),n=Zi(Xi(t.facts)),o=Qi(e)?es(n,["todo","task","next_action","file"]):ts(n,String(t.intent));return o?{intent:String(t.intent),answer:o,source:n[0]?.source??"none"}:{intent:String(t.intent),answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}import{existsSync as rs,mkdirSync as ns,readFileSync as os,renameSync as is,rmSync as ss,writeFileSync as as}from"node:fs";import{join as kr}from"node:path";var cs=720*60*1e3;function vr(r){return kr(r.rootPath,".toolnet","context","memory-agent-conversation.json")}function ee(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function us(r){let e=ee(r);return[/\btiếp tục\b/u,/\btiếp tục task\b/u,/\blúc nãy\b/u,/\btrước đó\b/u,/\btask trước\b/u,/\bprevious (?:task|session|work)\b/u,/\bcontinue\b/u,/\bresume\b/u,/\bcurrent task\b/u,/\bđang làm gì\b/u].some(t=>t.test(e))}function ls(r){if(us(r))return!1;let e=ee(r),t=e.split(/\s+/u).filter(Boolean);return[/^(?:tại sao|vì sao|sao vậy)\b/u,/^(?:why|why so|why that)\b/u,/^(?:còn|thế|vậy|rồi sao|sau đó)\b/u,/^(?:what about|and what|then what)\b/u,/^(?:cái đó|việc đó|nó|phần đó)\b/u].some(n=>n.test(e))?!0:t.length<=5&&/\b(?:nó|đó|vậy|thế|that|it|this)\b/u.test(e)}function ds(r,e,t){let n=vr(r);if(!rs(n))return null;try{let o=JSON.parse(os(n,"utf8"));if(o.schema!=="toolnet.memory-conversation.v1"||o.version!==1||o.projectId!==r.id||!Array.isArray(o.focus))return null;let i=Date.parse(o.updatedAt);return!Number.isFinite(i)||e-i>t?null:o}catch{return null}}function ms(r,e=8){let t=new Set,n=[];for(let o of r){let i=o.value.replace(/\s+/gu," ").trim();if(!i)continue;let s=[o.kind,ee(i)].join(":");if(!t.has(s)&&(t.add(s),n.push({...o,value:i}),n.length>=e))break}return n}function ps(r,e){let t=vr(r),n=kr(r.rootPath,".toolnet","context");ns(n,{recursive:!0,mode:448});let o=`${t}.${process.pid}.tmp`;try{as(o,JSON.stringify(e,null,2)+`
8
+ `,{encoding:"utf8",mode:384}),is(o,t)}finally{ss(o,{force:!0})}}function fs(r){return r.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
9
+ `)}function gs(r,e){return r.priorFocus.find(t=>t.kind===e)?.value}function wr(r){if(!r.usedPriorFocus||r.currentIntent!=="summary"||r.priorFocus.length===0)return null;let e=ee(r.originalQuestion),t=/^(?:tại sao|vì sao|sao vậy|why|why so|why that)\b/u.test(e),n=/^(?:rồi sao|sau đó|tiếp thì sao|thế tiếp theo|then what|what next)\b/u.test(e),o=t?["decision","blocker","next_action","task","file"]:n?["next_action","todo","task","blocker","file","decision"]:["task","next_action","file","decision","blocker"],i={task:"Task li\xEAn quan",next_action:"Vi\u1EC7c ti\u1EBFp theo",file:"File li\xEAn quan",decision:"Quy\u1EBFt \u0111\u1ECBnh li\xEAn quan",blocker:"Blocker",todo:"TODO"},s=[];for(let a of o){let c=gs(r,a);if(c&&(s.push(`${i[a]??a}: ${c}.`),t&&s.length>=2||!t&&s.length>=3))break}return s.length===0?null:{answer:s.join(" "),intent:"summary",source:"conversation-focus"}}function ys(r){let e=ee(r);return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(e)}function br(r,e,t={}){let n=t.now??Date.now(),o=t.maxAgeMs??cs,i=ds(r,n,o),s=!!(i&&i.focus.length>0&&ls(e)&&!ys(e)),a=s&&i?[e.trim(),"","Previous ToolNet Memory conversation focus:",fs(i),"","Use the compact focus only to resolve the current follow-up question.","Do not reconstruct or request raw session transcripts."].join(`
10
+ `):e.trim(),c=Me(e),l=Ae(r,a,{maxFacts:8,maxChars:1800}).facts.map(g=>({kind:g.kind,value:g.value,source:g.source})),d=ms(s&&i?[...l,...i.focus]:l);return ps(r,{schema:"toolnet.memory-conversation.v1",version:1,projectId:r.id,updatedAt:new Date(n).toISOString(),lastIntent:c,focus:d}),{question:a,originalQuestion:e,usedPriorFocus:s,previousIntent:i?.lastIntent,currentIntent:c,priorFocus:i?.focus??[],focusCount:d.length}}import{existsSync as hs,readFileSync as ks}from"node:fs";import{join as vs}from"node:path";function M(r){return!!r?.trim()}function Sr(r){let e=[],t=[],n=100;M(r.goal)||M(r.request)||(e.push("goal_or_request"),n-=20),M(r.activity)||M(r.current.task?.title)||M(r.current.phase?.title)||(e.push("current_work"),n-=25),M(r.nextAction)||M(r.remaining.todos[0])||(e.push("next_action"),n-=25),r.tests.status!=="unknown"||r.tests.recent.length>0||(r.tests.checks?.length??0)>0||(r.evidence?.commands.length??0)>0||(r.evidence?.references.length??0)>0||(e.push("evidence"),n-=20),M(r.files.current)||r.files.recent.length>0||(r.files.active?.length??0)>0||(r.files.modified?.length??0)>0||(r.files.created?.length??0)>0||(e.push("files"),n-=10),r.tests.status==="failing"&&t.push("tests_failing"),r.blockers.length>0&&t.push("active_blockers"),n=Math.max(0,Math.min(100,n));let u=e.includes("current_work")||e.includes("next_action"),l;return n>=80&&!u?l="high":n>=50?l="medium":l="low",{confidence:l,score:n,missingContext:e,warnings:t}}var xr={compact:{completed:3,evidence:3,files:5,blockers:2,maxChars:1800},normal:{completed:10,evidence:10,files:15,blockers:5,maxChars:4200},benchmark:{completed:30,evidence:30,files:40,blockers:10,maxChars:1e4}};function _(r){let e=new Set,t=[];for(let n of r){let o=n?.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();e.has(i)||(e.add(i),t.push(o))}return t}function N(r){return r.length>0?r.map(e=>`- ${e}`).join(`
11
+ `):"- none"}function ws(r,e){return r.length<=e?r:[r.slice(0,e).trimEnd(),"","[Structured handoff truncated]"].join(`
12
+ `)}function Mr(r,e){if(e)return e;let t=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/\bbenchmark\b/u.test(t)||/\bdeep handoff\b/u.test(t)||/\bfull handoff\b/u.test(t)||/\btakeover\b/u.test(t)||/\btake over\b/u.test(t)||/tiếp quản/u.test(t)||/bằng chứng đầy đủ/u.test(t)||/evidence.*(?:file|test|command)/u.test(t)?"benchmark":/\bcompact\b/u.test(t)||/\bbrief\b/u.test(t)||/ngắn gọn/u.test(t)||/tóm tắt ngắn/u.test(t)?"compact":"normal"}function bs(r,e="normal"){let t=xr[e],n=_([`Source agent: ${r.source.agent}`,`Captured: ${r.capturedAt}`,r.goal?`Goal: ${r.goal}`:void 0,r.request?`Request: ${r.request}`:void 0,r.activity?`Activity: ${r.activity}`:void 0,r.current.phase?`Phase: ${r.current.phase.title} [${r.current.phase.status}]`:void 0,r.current.task?`Task: ${r.current.task.title} [${r.current.task.status}]`:void 0,r.current.file?`Current file: ${r.current.file}`:void 0,`Progress: ${JSON.stringify(r.progress)}`]),o=_([...r.completed.phases.map(u=>`Phase: ${u}`),...r.completed.tasks.map(u=>`Task: ${u}`)]).slice(0,t.completed),i=_([`Tests status: ${r.tests.status}`,...r.tests.recent.map(u=>`Test: ${u}`),...(r.tests.checks??[]).map(u=>`Check [${u.status}] ${u.kind}: ${u.command}`),...(r.evidence?.commands??[]).map(u=>`Command: ${u}`),...(r.evidence?.references??[]).map(u=>`Reference: ${u}`),...r.decisions.map(u=>`Decision: ${u}`),...r.attention.map(u=>`Attention: ${u}`)]).slice(0,t.evidence),s=_([r.files.current,...(r.files.active??[]).map(u=>`Active: ${u}`),...(r.files.modified??[]).map(u=>`Modified: ${u}`),...(r.files.created??[]).map(u=>`Created: ${u}`),...(r.files.deleted??[]).map(u=>`Deleted: ${u}`),...r.files.recent.map(u=>`Recent: ${u}`)]).slice(0,t.files),a=_(r.blockers).slice(0,t.blockers),c=_([r.nextAction,r.nextAction?void 0:r.remaining.todos[0]]).slice(0,1);return{currentState:n,completed:o,evidence:i,filesTouched:s,blockers:a,nextAction:c}}function Ss(r,e,t){return[`HANDOFF_DETAIL: ${e}`,`CONTINUITY_CONFIDENCE: ${t.confidence}`,`QUALITY_SCORE: ${t.score}`,`MISSING_CONTEXT: ${t.missingContext.length>0?t.missingContext.join(", "):"none"}`,`QUALITY_WARNINGS: ${t.warnings.length>0?t.warnings.join(", "):"none"}`,"","CURRENT_STATE",N(r.currentState),"","COMPLETED",N(r.completed),"","EVIDENCE",N(r.evidence),"","FILES_TOUCHED",N(r.filesTouched),"","BLOCKERS",N(r.blockers),"","NEXT_ACTION",N(r.nextAction)].join(`
13
+ `)}function Ar(r,e="normal"){let t=vs(r.rootPath,".toolnet","work","handoff-latest.json");if(!hs(t))return null;try{let o=JSON.parse(ks(t,"utf8")).continuity;if(!o||o.schema!=="toolnet.handoff.v2"||o.version!==2)return null;let i=bs(o,e),s=Sr(o),a=ws(Ss(i,e,s),xr[e].maxChars);return{detail:e,data:i,quality:s,text:a}}catch{return null}}function xs(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}var Ms=[/\bhandoff\b/u,/\bcontinuity\b/u,/\bcontinue\b/u,/\bresume\b/u,/\btakeover\b/u,/\btake over\b/u,/tiếp tục/u,/tiếp quản/u,/bàn giao/u,/dừng ở đâu/u,/đang làm gì/u],As=[/\bcurrent state\b/u,/\bcurrent task\b/u,/\bevidence\b/u,/\breport locations?\b/u,/\bfiles?\b/u,/\burls?\b/u,/\bassets?\b/u,/\btests?\b/u,/\bcommands?\b/u,/\bblockers?\b/u,/\bnext actions?\b/u,/trạng thái hiện tại/u,/task hiện tại/u,/bằng chứng/u,/vị trí báo cáo/u,/file/u,/url/u,/blocker/u,/việc tiếp theo/u,/bước tiếp theo/u],Cs=[/\bsummarize\b/u,/\bsummary\b/u,/\bfull state\b/u,/\bfull context\b/u,/tóm tắt/u,/đầy đủ/u,/toàn bộ trạng thái/u];function Ps(r){let e=0;for(let t of As)t.test(r)&&(e+=1);return e}function Cr(r,e){let t=xs(r);if(/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(t)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(t)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(t))return!1;if(e==="summary"||e==="status")return!0;if(!t)return!1;let o=Ms.some(a=>a.test(t)),i=Cs.some(a=>a.test(t)),s=Ps(t);return!!(o&&s>=1||i&&s>=2||s>=4)}var Id={question:Ue.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:Ue.enum(["local"]).optional().describe("Returns deterministic local memory only. No external AI is used."),detail:Ue.enum(["compact","normal","benchmark"]).optional().describe("Handoff detail level. compact=minimal, normal=standard, benchmark=deep evidence/files/tests for agent takeover.")};function Pr(r,e,t,n,o){if(!Cr(e,t))return{answer:n};let i=Mr(e,o),s=Ar(r.project,i);return s?{answer:s.text,handoff:s.data,detail:s.detail,confidence:s.quality.confidence,missingContext:s.quality.missingContext,quality:s.quality}:{answer:n}}async function Ir(r,e){let t=br(r.project,e.question),n=wr(t);if(n)return{...Pr(r,t.originalQuestion,String(n.intent),n.answer,e.detail),mode:"local",usedAi:!1,source:n.source,intent:n.intent};let o=hr(r.project,t.originalQuestion),i=Pr(r,t.originalQuestion,String(o.intent),o.answer,e.detail);return"handoff"in i?{...i,mode:"local",usedAi:!1,source:o.source,intent:o.intent,routing:"deterministic-handoff"}:{...i,mode:"local",usedAi:!1,source:o.source,intent:o.intent}}import{z as Nr}from"zod";import{chmodSync as Rd,existsSync as Er,mkdirSync as jd,readFileSync as Tr,renameSync as Od,writeFileSync as _d}from"node:fs";import{dirname as Kd,join as te}from"node:path";var Rr="toolnet.context-offload.v1",Is="toolnet.context-offload-asset.v1";function jr(r){return te(r,".toolnet","offload")}function Or(r){return te(jr(r),"assets")}function Es(r){return te(jr(r),"graph.json")}function Ye(){return{schema:Rr,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function Ts(r){let e=Es(r);if(!Er(e))return Ye();try{let t=JSON.parse(Tr(e,"utf8"));return t.schema!==Rr||t.version!==1||!Array.isArray(t.nodes)?Ye():t}catch{return Ye()}}function Rs(r,e){let t=e.trim().toLowerCase();if(!/^[a-f0-9]{8,64}$/u.test(t))throw new Error("Invalid context offload asset reference.");if(t.length===64&&Er(te(Or(r),`${t}.json`)))return t;let n=Ts(r).nodes.map(o=>o.id).filter(o=>o.startsWith(t));if(n.length===0)throw new Error(`Context offload asset not found: ${e}`);if(n.length>1)throw new Error(`Ambiguous context offload asset reference: ${e}`);return n[0]}function _r(r,e,t=6e3){let n=Rs(r,e),o=Tr(te(Or(r),`${n}.json`),"utf8"),i=JSON.parse(o);if(i.schema!==Is||i.version!==1||i.assetId!==n)throw new Error(`Invalid context offload asset: ${e}`);let s=Math.max(200,Math.min(2e4,Math.floor(t)));return{assetId:n,kind:i.event.type,bytes:Buffer.byteLength(o,"utf8"),truncated:o.length>s,content:o.length>s?`${o.slice(0,s)}
14
+ [truncated]`:o}}var Hd={assetId:Nr.string().regex(/^[a-f0-9]{8,64}$/iu).describe("Asset reference from the ToolNet Context Offload Graph."),maxChars:Nr.number().int().min(200).max(2e4).optional().describe("Maximum asset characters to return. Defaults to 6000.")};async function Kr(r,e){return _r(r.project.rootPath,e.assetId,e.maxChars??6e3)}async function $r(r,e){return{schema:"toolnet.api-memory-ask.v1",result:await Ir({project:r},e)}}async function Fr(r,e){return{schema:"toolnet.api-context-offload.v1",result:await Kr({project:r},e)}}import{z as Lr}from"zod";var qd={query:Lr.string(),limit:Lr.number().int().min(1).max(20).optional()};async function Hr(r,e){return r.retrieval.search(r.project.id,e.query,{topK:e.limit??8}).map(n=>({id:n.memory.id,type:n.memory.type,content:n.memory.content,importance:n.memory.importance,score:n.score,tags:n.memory.tags}))}import{z as zr}from"zod";import{chmodSync as Yd,existsSync as js,mkdirSync as Jd,readFileSync as Os,readdirSync as _s,renameSync as Qd,statSync as Ns,writeFileSync as Xd}from"node:fs";import{join as Dr}from"node:path";var Ks="toolnet.skill-memory.v1";function $s(r,e=Number.MAX_SAFE_INTEGER){let t=new Set,n=[];for(let o of r){let i=o.replace(/\s+/gu," ").trim();if(!i)continue;let s=i.normalize("NFKC").toLowerCase();if(!t.has(s)&&(t.add(s),n.push(i),n.length>=e))break}return n}function Fs(r){return Dr(r.rootPath,".toolnet","memory","skills")}function Ls(r,e){if(!r||typeof r!="object")return!1;let t=r;return t.schema===Ks&&t.version===1&&t.projectId===e&&typeof t.id=="string"&&typeof t.task=="string"&&Array.isArray(t.steps)&&Array.isArray(t.verification)&&Array.isArray(t.files)}function Hs(r){let e=Fs(r);if(!js(e))return[];if(!Ns(e).isDirectory())return[];let t=[];for(let n of _s(e)){if(!n.endsWith(".json"))continue;let o=Dr(e,n);try{let i=JSON.parse(Os(o,"utf8"));Ls(i,r.id)&&t.push(i)}catch{}}return t.sort((n,o)=>{let i=o.createdAt.localeCompare(n.createdAt);return i!==0?i:n.id.localeCompare(o.id)})}function Ds(r){return $s(r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_./-]+/gu).filter(e=>e.length>=2),32)}function Ws(r,e){let t=e.normalize("NFKC").toLowerCase().trim();if(!t)return 0;if(r.id.toLowerCase()===t||r.fingerprint.toLowerCase()===t)return 1e3;let n=[r.title,r.task,r.summary,...r.steps,...r.verification,...r.files].join(`
15
+ `).normalize("NFKC").toLowerCase(),o=0;r.task.normalize("NFKC").toLowerCase().includes(t)&&(o+=40),r.title.normalize("NFKC").toLowerCase().includes(t)&&(o+=30);for(let i of Ds(t))n.includes(i)&&(o+=5),r.task.normalize("NFKC").toLowerCase().includes(i)&&(o+=4),r.files.some(s=>s.toLowerCase().includes(i))&&(o+=3);return o}function Wr(r,e,t=5){let n=Math.max(1,Math.min(10,Math.floor(t)));return Hs(r).map(o=>({...o,score:Ws(o,e)})).filter(o=>o.score>0).sort((o,i)=>i.score!==o.score?i.score-o.score:i.createdAt.localeCompare(o.createdAt)).slice(0,n)}var nm={query:zr.string().min(2).max(500).describe("Task, problem, file, command or workflow to match against successful reusable Skill Memory SOPs."),limit:zr.number().int().min(1).max(10).optional().describe("Maximum matching reusable SOPs to return. Default 5.")};async function Gr(r,e){let t=Wr(r.project,e.query,e.limit??5);return{schema:"toolnet.skill-memory-search.v1",query:e.query,count:t.length,matches:t}}async function Vr(r,e,t){return{schema:"toolnet.api-memory-search.v1",results:await Hr({project:r,retrieval:e},t)}}async function qr(r,e){return{schema:"toolnet.api-skill-search.v1",result:await Gr({project:r},e)}}function re(r){if(!r||typeof r!="object"||Array.isArray(r))throw new Error("Invalid Memory Hub request");return r}function b(r,e,t=1,n=200){if(typeof r!="string"||r.trim().length<t||r.trim().length>n)throw new Error(`Invalid ${e}`);return r.trim()}function Br(r,e,t=500){if(r!==void 0)return b(r,e,1,t)}function Je(r,e,t=64){if(r!==void 0){if(!Array.isArray(r)||r.length>t||r.some(n=>typeof n!="string"||!n.trim()))throw new Error(`Invalid ${e}`);return r.map(n=>n.trim())}}async function Ur(r,e){return{schema:"toolnet.api-hub-summary.v1",hub:await r.summary(e)}}async function Yr(r,e){return{schema:"toolnet.api-hub-teams.v1",teams:await r.listTeams(e)}}async function Jr(r,e,t){let n=re(t),o={...n.id!==void 0?{id:b(n.id,"team id",2,100)}:{},name:b(n.name,"team name",2,100),...n.description!==void 0?{description:Br(n.description,"team description",500)}:{}};return{schema:"toolnet.api-hub-team.v1",team:await r.createTeam(e,o)}}async function Qr(r,e){return{schema:"toolnet.api-hub-agents.v1",agents:await r.listAgents(e)}}async function Xr(r,e,t){let n=re(t),o={...n.id!==void 0?{id:b(n.id,"agent id",2,100)}:{},name:b(n.name,"agent name",2,100),...n.kind!==void 0?{kind:Br(n.kind,"agent kind",100)}:{},...n.teamIds!==void 0?{teamIds:Je(n.teamIds,"teamIds",64)}:{},...n.metadata&&typeof n.metadata=="object"&&!Array.isArray(n.metadata)?{metadata:n.metadata}:{}};return{schema:"toolnet.api-hub-agent.v1",agent:await r.createAgent(e,o)}}async function Zr(r,e){return{schema:"toolnet.api-hub-acl.v1",grants:await r.listAcl(e)}}async function en(r,e,t){let n=re(t),o=b(n.role,"role",4,20);if(!["owner","admin","member","viewer"].includes(o))throw new Error("Invalid role");let i=Je(n.scopes,"scopes",x.length);if(i?.some(a=>!x.includes(a)))throw new Error("Invalid Memory Hub scope");let s={principal:b(n.principal,"principal",1,120),role:o,...i?{scopes:i}:{}};return{schema:"toolnet.api-hub-acl-grant.v1",grant:await r.grantAcl(e,s)}}async function tn(r,e,t){let n=re(t),o=b(n.principal,"principal",1,120);return await r.revokeAcl(e,o),{schema:"toolnet.api-hub-acl-revoke.v1",principal:o,revoked:!0}}async function rn(r,e){return{schema:"toolnet.api-hub-loadouts.v1",loadouts:await r.listLoadouts(e)}}async function nn(r,e,t){let n=re(t),o=n.maxContextChars;if(o!==void 0&&(!Number.isInteger(o)||o<500||o>5e4))throw new Error("Invalid maxContextChars");let i=n.memoryMode;if(i!==void 0&&i!=="local"&&i!=="ai")throw new Error("Invalid memoryMode");if(n.skillMemory!==void 0&&typeof n.skillMemory!="boolean")throw new Error("Invalid skillMemory");if(n.contextOffload!==void 0&&typeof n.contextOffload!="boolean")throw new Error("Invalid contextOffload");let s={agentId:b(n.agentId,"agentId",2,100),...n.tools!==void 0?{tools:Je(n.tools,"tools",64)}:{},...i?{memoryMode:i}:{},...n.skillMemory!==void 0?{skillMemory:n.skillMemory}:{},...n.contextOffload!==void 0?{contextOffload:n.contextOffload}:{},...o!==void 0?{maxContextChars:o}:{}};return{schema:"toolnet.api-hub-loadout.v1",loadout:await r.setLoadout(e,s)}}async function on(r,e){return{schema:"toolnet.api-hub-observability.v1",observability:await r.observability(e)}}async function A(r,e,t){if(!await r.authorize(e,t))throw new f(`Principal '${e}' lacks '${t}'`,403)}function sn(r){if(!r||typeof r!="object"||Array.isArray(r))throw new f("Invalid Wiki request",400);return r}function Qe(r,e,t){if(typeof r!="string"||!r.trim()||r.length>t)throw new f(`Invalid ${e}`,400);return r.trim()}function an(r,e,t){if(r!==void 0){if(typeof r!="string"||r.length>t)throw new f(`Invalid ${e}`,400);return r}}function cn(r){if(r!==void 0){if(!Array.isArray(r)||r.length>50||r.some(e=>typeof e!="string"||e.length>100))throw new f("Invalid Wiki tags",400);return r}}async function un(r,e,t){return await A(e,t,"wiki:read"),{schema:"toolnet.api-wiki-summary.v1",wiki:await r.summary()}}async function ln(r,e,t){return await A(e,t,"wiki:read"),{schema:"toolnet.api-wiki-pages.v1",pages:await r.listPages()}}async function dn(r,e,t,n){await A(e,t,"wiki:write");let o=sn(n),i={...o.slug!==void 0?{slug:Qe(o.slug,"Wiki slug",120)}:{},title:Qe(o.title,"Wiki title",200),...o.summary!==void 0?{summary:an(o.summary,"Wiki summary",1e3)}:{},content:typeof o.content=="string"?o.content:"",...o.tags!==void 0?{tags:cn(o.tags)}:{}};return{schema:"toolnet.api-wiki-page.v1",page:await r.createPage(i)}}async function mn(r,e,t,n){return await A(e,t,"wiki:read"),{schema:"toolnet.api-wiki-page.v1",page:await r.getPage(n)}}async function pn(r,e,t,n,o){await A(e,t,"wiki:write");let i=sn(o),s={...i.title!==void 0?{title:Qe(i.title,"Wiki title",200)}:{},...i.summary!==void 0?{summary:an(i.summary,"Wiki summary",1e3)}:{},...i.content!==void 0?{content:typeof i.content=="string"?i.content:(()=>{throw new f("Invalid Wiki content",400)})()}:{},...i.tags!==void 0?{tags:cn(i.tags)}:{}};return{schema:"toolnet.api-wiki-page.v1",page:await r.updatePage(n,s)}}async function fn(r,e,t,n,o){return await A(e,t,"wiki:read"),{schema:"toolnet.api-wiki-search.v1",query:n,results:await r.search(n,o)}}async function gn(r,e,t,n){return await A(e,t,"wiki:read"),{schema:"toolnet.api-wiki-history.v1",revisions:await r.history(n)}}async function yn(r,e,t,n){return await A(e,t,"wiki:read"),{schema:"toolnet.api-wiki-backlinks.v1",pages:await r.backlinks(n)}}async function R(r,e,t){if(!await r.authorize(e,t))throw new f(`Principal '${e}' lacks '${t}'`,403)}function hn(r){if(!r||typeof r!="object"||Array.isArray(r))throw new f("Invalid governance request",400);return r}async function kn(r,e,t){return await R(e,t,"governance:read"),{schema:"toolnet.api-governance-summary.v1",governance:await r.summary()}}async function vn(r,e,t,n){if(await R(e,t,"governance:read"),n&&!new Set(["pending","approved","rejected","superseded"]).has(n))throw new f("Invalid review status",400);return{schema:"toolnet.api-governance-reviews.v1",reviews:await r.listReviews(n)}}async function wn(r,e,t,n,o,i){await R(t,n,"governance:write");let s=hn(i),a=s.action;if(a!=="approve"&&a!=="reject"&&a!=="supersede"&&a!=="merge")throw new f("Invalid governance action",400);if(s.note!==void 0&&typeof s.note!="string")throw new f("Invalid review note",400);if(s.targetReviewId!==void 0&&typeof s.targetReviewId!="string")throw new f("Invalid targetReviewId",400);return{schema:"toolnet.api-governance-review.v1",review:await r.decide(o,{action:a,principal:n,...typeof s.note=="string"?{note:s.note}:{},...typeof s.targetReviewId=="string"?{targetReviewId:s.targetReviewId}:{}},e)}}async function bn(r,e,t,n){return await R(t,n,"governance:read"),{schema:"toolnet.api-knowledge-quality.v1",quality:await r.quality(e)}}async function Sn(r,e,t){return await R(e,t,"governance:read"),{schema:"toolnet.api-governance-policy.v1",policy:await r.policy()}}async function xn(r,e,t,n){await R(e,t,"governance:write");let o=hn(n),i={};if(o.autoApproveThreshold!==void 0){if(typeof o.autoApproveThreshold!="number")throw new f("Invalid autoApproveThreshold",400);i.autoApproveThreshold=o.autoApproveThreshold}if(o.criticalApproveThreshold!==void 0){if(typeof o.criticalApproveThreshold!="number")throw new f("Invalid criticalApproveThreshold",400);i.criticalApproveThreshold=o.criticalApproveThreshold}if(o.staleAfterDays!==void 0){if(typeof o.staleAfterDays!="number")throw new f("Invalid staleAfterDays",400);i.staleAfterDays=o.staleAfterDays}return{schema:"toolnet.api-governance-policy.v1",policy:await r.setPolicy(i,t)}}async function Mn(r,e,t,n){return await R(e,t,"governance:read"),{schema:"toolnet.api-governance-audit.v1",events:await r.auditLog(n)}}function Vs(r){let e=r.headers["x-toolnet-principal"];return(Array.isArray(e)?e[0]:e)?.trim()||"anonymous"}function qs(r,e){if(!e)return!0;let t=r.headers.authorization;if(!t?.startsWith("Bearer "))return!1;let n=Buffer.from(t.slice(7)),o=Buffer.from(e);return n.length===o.length&&zs(n,o)}function p(r,e,t){r.statusCode=e,r.setHeader("content-type","application/json; charset=utf-8"),r.setHeader("cache-control","no-store"),r.end(JSON.stringify(t))}async function v(r){let e=[],t=0;for await(let n of r){let o=Buffer.isBuffer(n)?n:Buffer.from(n);if(t+=o.length,t>16384)throw new Error("Request body too large");e.push(o)}return e.length===0?{}:JSON.parse(Buffer.concat(e).toString("utf8"))}function Bs(r){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;return typeof e.question!="string"||e.question.length<2||e.question.length>4e3||e.mode!==void 0&&e.mode!=="local"?null:{question:e.question,...e.mode?{mode:e.mode}:{}}}function Us(r){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;return typeof e.query!="string"||e.limit!==void 0&&(!Number.isInteger(e.limit)||e.limit<1||e.limit>20)?null:{query:e.query,...e.limit!==void 0?{limit:e.limit}:{}}}function Ys(r){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;return typeof e.query!="string"||e.query.length<2||e.query.length>500||e.limit!==void 0&&(!Number.isInteger(e.limit)||e.limit<1||e.limit>10)?null:{query:e.query,...e.limit!==void 0?{limit:e.limit}:{}}}function Js(r){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;return typeof e.assetId!="string"||!/^[a-f0-9]{8,64}$/iu.test(e.assetId)||e.maxChars!==void 0&&(!Number.isInteger(e.maxChars)||e.maxChars<200||e.maxChars>2e4)?null:{assetId:e.assetId,...e.maxChars!==void 0?{maxChars:e.maxChars}:{}}}function An(r){return Gs(async(e,t)=>{try{let n=new URL(e.url??"/",`http://${e.headers.host??"localhost"}`),o=Vs(e),i=Date.now();if(t.once("finish",()=>{r.hub&&r.hub.recordRequest({method:e.method??"GET",path:n.pathname,principal:o,statusCode:t.statusCode,durationMs:Date.now()-i}).catch(()=>{})}),n.pathname.startsWith("/v1/")&&!qs(e,r.token)){p(t,401,{error:"Unauthorized"});return}if(e.method==="GET"&&n.pathname==="/v1/health"){p(t,200,lr(r.project));return}if(e.method==="GET"&&n.pathname==="/v1/project"){p(t,200,dr(r.project));return}if(e.method==="POST"&&n.pathname==="/v1/memory/ask"){let l=Bs(await v(e));if(!l){p(t,400,{error:"Invalid memory ask request"});return}p(t,200,await $r(r.project,l));return}if(e.method==="POST"&&n.pathname==="/v1/memory/search"){let l=Us(await v(e));if(!l){p(t,400,{error:"Invalid memory search request"});return}p(t,200,await Vr(r.project,r.retrieval,l));return}if(e.method==="POST"&&n.pathname==="/v1/skills/search"){let l=Ys(await v(e));if(!l){p(t,400,{error:"Invalid skill search request"});return}p(t,200,await qr(r.project,l));return}if(e.method==="POST"&&n.pathname==="/v1/offload/read"){let l=Js(await v(e));if(!l){p(t,400,{error:"Invalid context offload request"});return}p(t,200,await Fr(r.project,l));return}if(n.pathname.startsWith("/v1/hub")&&!r.hub){p(t,503,{error:"Memory Hub unavailable"});return}if(e.method==="GET"&&n.pathname==="/v1/hub"){p(t,200,await Ur(r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/hub/teams"){p(t,200,await Yr(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/teams"){p(t,201,await Jr(r.hub,o,await v(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/agents"){p(t,200,await Qr(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/agents"){p(t,201,await Xr(r.hub,o,await v(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/acl"){p(t,200,await Zr(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/acl/grant"){p(t,200,await en(r.hub,o,await v(e)));return}if(e.method==="POST"&&n.pathname==="/v1/hub/acl/revoke"){p(t,200,await tn(r.hub,o,await v(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/loadouts"){p(t,200,await rn(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/loadouts"){p(t,200,await nn(r.hub,o,await v(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/observability"){p(t,200,await on(r.hub,o));return}if(n.pathname.startsWith("/v1/wiki")&&(!r.wiki||!r.hub)){p(t,503,{error:"Wiki unavailable"});return}if(e.method==="GET"&&n.pathname==="/v1/wiki"){p(t,200,await un(r.wiki,r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/wiki/pages"){p(t,200,await ln(r.wiki,r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/wiki/pages"){p(t,201,await dn(r.wiki,r.hub,o,await v(e)));return}if(e.method==="GET"&&n.pathname==="/v1/wiki/search"){let l=n.searchParams.get("q")??"",d=Number(n.searchParams.get("limit")??10),g=Number.isInteger(d)?Math.max(1,Math.min(20,d)):10;p(t,200,await fn(r.wiki,r.hub,o,l,g));return}let s=/^\/v1\/wiki\/pages\/([^/]+)\/history$/u.exec(n.pathname);if(e.method==="GET"&&s){p(t,200,await gn(r.wiki,r.hub,o,decodeURIComponent(s[1])));return}let a=/^\/v1\/wiki\/pages\/([^/]+)\/backlinks$/u.exec(n.pathname);if(e.method==="GET"&&a){p(t,200,await yn(r.wiki,r.hub,o,decodeURIComponent(a[1])));return}let c=/^\/v1\/wiki\/pages\/([^/]+)$/u.exec(n.pathname);if(e.method==="GET"&&c){p(t,200,await mn(r.wiki,r.hub,o,decodeURIComponent(c[1])));return}if(e.method==="PUT"&&c){p(t,200,await pn(r.wiki,r.hub,o,decodeURIComponent(c[1]),await v(e)));return}if(n.pathname.startsWith("/v1/governance")&&(!r.governance||!r.wiki||!r.hub)){p(t,503,{error:"Knowledge Governance unavailable"});return}if(e.method==="GET"&&n.pathname==="/v1/governance"){p(t,200,await kn(r.governance,r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/governance/reviews"){p(t,200,await vn(r.governance,r.hub,o,n.searchParams.get("status")??void 0));return}let u=/^\/v1\/governance\/reviews\/([^/]+)$/u.exec(n.pathname);if(e.method==="POST"&&u){p(t,200,await wn(r.governance,r.wiki,r.hub,o,decodeURIComponent(u[1]),await v(e)));return}if(e.method==="GET"&&n.pathname==="/v1/governance/quality"){p(t,200,await bn(r.governance,r.wiki,r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/governance/policy"){p(t,200,await Sn(r.governance,r.hub,o));return}if(e.method==="PUT"&&n.pathname==="/v1/governance/policy"){p(t,200,await xn(r.governance,r.hub,o,await v(e)));return}if(e.method==="GET"&&n.pathname==="/v1/governance/audit"){let l=Number(n.searchParams.get("limit")??100),d=Number.isInteger(l)?Math.max(1,Math.min(500,l)):100;p(t,200,await Mn(r.governance,r.hub,o,d));return}p(t,404,{error:"Not found"})}catch(n){if(n instanceof k||n instanceof f){p(t,n.statusCode,{error:n.message});return}if(n instanceof Error&&n.message.startsWith("Invalid ")){p(t,400,{error:n.message});return}p(t,500,{error:n instanceof Error?n.message:String(n)})}})}var Cn=process.env.TOOLNET_API_HOST??"127.0.0.1",Pn=Number(process.env.TOOLNET_API_PORT??9750);async function Qs(){let r=Pe(),e=new ae().detect(),t=qt({provider:r.storage.provider,r2:r.storage.r2,s3:r.storage.s3,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),n=Ut(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),o=new be(n,e.id,e.name,e.remote??e.name),i=new Se(o,e,process.env.TOOLNET_HUB_OWNER?.trim()||"owner"),s=new xe(i,Number(process.env.TOOLNET_HUB_MAX_EVENTS??100));await s.initialize();let a=new B(o,e),c=new J(a);await c.initialize();let u=new Z(new X(o,e));await u.initialize();let l=new pe,d=new we(o);l.importRecords(await d.load(e.id));let g=new ke(l);An({project:e,retrieval:g,token:process.env.TOOLNET_API_TOKEN?.trim()||void 0,hub:s,wiki:c,governance:u}).listen(Pn,Cn,()=>{console.log("ToolNet Memory API"),console.log(`Project: ${e.name}`),console.log(`Listening: http://${Cn}:${Pn}`)})}Qs().catch(r=>{console.error(r),process.exit(1)});