toolnet-memory 0.3.15 → 0.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle/api.js CHANGED
@@ -1,15 +1,15 @@
1
- import"dotenv/config";import{existsSync as Hr,readFileSync as Lr}from"node:fs";import{homedir as Dr}from"node:os";import{join as Wr}from"node:path";function zr(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 Vr(){let r=process.env.TOOLNET_GLOBAL_ENV??Wr(Dr(),".config","toolnet-memory",".env");if(!Hr(r))return;let e=Lr(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]=zr(n.slice(o+1)))}}Vr();function R(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function j(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function pe(){return{memory:{autoCapture:R(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:R(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:R(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:R(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:j(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:j(process.env.MEMORY_RERANK_TOP,10),finalContext:j(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:j(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:R(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:j(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var Gr={critical:100,high:75,normal:50,temporary:20};function Re(r){return Gr[r]}function je(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 qr}from"node:crypto";import{existsSync as q,mkdirSync as Br,readFileSync as Ur,renameSync as Jr,writeFileSync as Qr}from"node:fs";import{basename as Yr,dirname as B,join as E,parse as Ke,resolve as C}from"node:path";var $e=".toolnet",Zr="project.json";function Xr(r){return qr("sha256").update(r).digest("hex").slice(0,16)}function U(r){return E(r,$e,Zr)}function en(r){return q(U(r))}function Ee(r,e){let t=C(r),n=Ke(t).root;for(;;){if(en(t))return t;if(t===n||e&&t===C(e))break;let o=B(t);if(o===t)break;t=o}return null}function Oe(r){let e=C(r),t=Ke(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>q(E(e,i))))return e;if(e===t)break;let o=B(e);if(o===e)break;e=o}return C(r)}function _e(r){let e;try{e=JSON.parse(Ur(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:B(B(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 Ne(r,e){let t=E(r,$e);Br(t,{recursive:!0});let n=U(r),o=`${n}.tmp-${process.pid}`;Qr(o,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Jr(o,n)}function fe(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var J=class{findExisting(e=process.cwd()){let t=C(e),n=Oe(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>q(E(n,c))),s=Ee(t,i?n:void 0);if(!s)return null;let a=_e(U(s));return fe(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=Oe(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(u=>q(E(n,u))),s=Ee(t,i?n:void 0);if(s){let u=U(s),p=_e(u);return p.rootPath!==s&&(p.rootPath=s,p.updatedAt=new Date().toISOString(),Ne(s,p)),fe(p,s)}let a=new Date().toISOString(),c=Yr(n),l={version:1,id:Xr(n),name:c,remote:c,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return Ne(n,l),fe(l,n)}};import{randomUUID as Pn}from"node:crypto";var tn=[{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"}],rn=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function Fe(r){return r.normalize("NFKC").trim().toLowerCase()}function nn(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 sn(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 an(r,e){return r.start<e.end&&e.start<r.end}function He(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var Q=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=Fe(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let i of tn){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=He(t),o=[];for(let i of n)o.some(s=>an(s,i))||o.push(i);return He(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=Fe(e);return rn.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)||sn(e,o.index,o.index+i.length)&&(nn(i)<3.7||t.push({type:"high_entropy_secret",value:i,start:o.index,end:o.index+i.length,confidence:"heuristic"}))}return t}};var P=class{scanner;constructor(e={}){this.scanner=new Q(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 Le=new P;function De(r){return Le.sanitize(r).text}function Y(r){return Le.sanitizeValue(r)}var cn=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),un=new Set(["d\xF9ng","s\u1EED","d\u1EE5ng","use","using","the","a","an","cho","v\xE0","l\xE0","c\u1EE7a","to","for","with","quy\u1EBFt","\u0111\u1ECBnh"]);function We(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!un.has(e)))}function ln(r,e){let t=We(r),n=We(e);if(t.size===0||n.size===0)return 0;let o=0;for(let s of t)n.has(s)&&(o+=1);let i=new Set([...t,...n]).size;return i===0?0:o/i}function ze(r){return new Set(r.tags.filter(e=>!cn.has(e.toLowerCase())))}function ge(r){let e=r.metadata?.evidence;if(!e||typeof e!="object")return{userExplicit:!1,sourceVerified:!1,testVerified:!1,crossSessionConfirmations:0,assistantDerived:!1};let t=e,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 dn(r){let e=ge(r);return e.userExplicit||e.sourceVerified||e.testVerified||e.crossSessionConfirmations>0}function mn(r){let e=Number(r.metadata?.confidence);return!Number.isFinite(e)||e<0?0:e>1?1:e}function pn(r){return r.importance==="critical"?20:r.importance==="high"?12:r.importance==="normal"?5:0}function Ve(r){let e=ge(r),t=pn(r);return e.userExplicit&&(t+=100),e.sourceVerified&&(t+=60),e.testVerified&&(t+=60),t+=Math.min(5,e.crossSessionConfirmations)*12,t+=mn(r)*10,r.metadata?.knowledgeClass==="permanent"&&(t+=10),e.assistantDerived&&(t-=15),Math.round(t*1e3)/1e3}function Ge(r){let e=r.metadata?.topic;if(typeof e!="string")return;let t=e.normalize("NFKC").trim().toLowerCase();if(t)return t}function fn(r,e){let t=ze(r),n=ze(e);for(let o of t)if(n.has(o))return!0;return!1}function gn(r,e){if(e.id===r.id||e.projectId!==r.projectId||e.type!==r.type||e.metadata?.supersededBy)return!1;let t=Ge(r),n=Ge(e);return t&&n&&t===n||fn(r,e)?!0:ln(r.content,e.content)>=.6}function qe(r){return r.type!=="rule"?!1:ge(r).userExplicit}function yn(r,e){return!qe(r)||!qe(e)?!1:r.createdAt>=e.createdAt}var Z=class{resolve(e,t){if(e.type!=="rule"&&e.type!=="decision")return{superseded:[],conflicts:[]};let n=[],o=[],i=Ve(e);for(let s of t){if(!gn(e,s))continue;let a=Ve(s);if(i>a){n.push(s);continue}if(i<a){o.push(s);continue}if(yn(e,s)){n.push(s);continue}if(!dn(s)&&e.createdAt>=s.createdAt){n.push(s);continue}o.push(s)}return{superseded:n,conflicts:o}}findSuperseded(e,t){return this.resolve(e,t).superseded}};var hn=new Set(["code","decision","rule","todo","summary"]);function kn(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function Be(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 vn(r,e){let t=Be(e)-Be(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 Ue(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 Je(r){let e=new Map;for(let o of r){if(!hn.has(o.type)||o.metadata?.supersededBy)continue;let i=kn(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(vn),s=i[0];if(!s)continue;let a=i.slice(1);t.push({canonicalId:s.id,duplicateIds:a.map(c=>c.id),mergedTags:Ue(i.flatMap(c=>c.tags)),mergedSources:Ue(i.map(c=>c.source))}),n+=a.length}return{groups:t,duplicates:n}}function ye(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 wn(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function bn(r){let e=ye(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 Sn(r){return ye(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function xn(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 Qe(r,e=Date.now()){let t=50,n=[],o=ye(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")),xn(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=wn(r,e)>=bn(r);a&&(t-=15,n.push("stale for lifecycle class"));let c=Sn(r);t=Math.max(0,Math.min(100,Math.round(t)));let l;t>=80?l="trusted":t>=55?l="useful":t>=30?l="weak":l="noise";let u=r.importance==="temporary"||r.type==="activity"||o==="transient";return{score:t,tier:l,stale:a,protected:c,pruneEligible:!c&&(l==="noise"&&u||a&&(l==="noise"||l==="weak")),reasons:n}}var Mn={critical:100,high:75,normal:50,temporary:20},An={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function Ye(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 he(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function Cn(r){return!!r.metadata?.supersededBy}function ke(r,e=Date.now()){return!he(r,e)&&!Cn(r)}function O(r,e=Date.now()){if(!ke(r,e))return 0;let t=Mn[r.importance];if(r.importance==="critical")return t;let n=An[r.type]??180,i=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,s=Math.pow(.5,i/n);return t*s}var X=class{memories=new Map;conflicts=new Z;remember(e){let t=new Date().toISOString(),n=De(e.content.trim()),o=e.importance??je(e.type,n),i={id:Pn(),projectId:e.projectId,type:e.type,content:n,importance:o,importanceScore:Re(o),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??Ye(e.type,o,new Date(t)),metadata:Y(e.metadata)},s=this.conflicts.resolve(i,this.list(e.projectId));if(s.superseded.length>0){i.metadata={...i.metadata??{},supersedes:s.superseded.map(a=>a.id)};for(let a of s.superseded)a.updatedAt=t,a.metadata={...a.metadata??{},supersededBy:i.id,supersededAt:t},this.memories.set(a.id,a)}if(s.conflicts.length>0){let a=s.conflicts.map(c=>c.id);i.metadata={...i.metadata??{},conflictsWith:a};for(let c of s.conflicts){let l=Array.isArray(c.metadata?.conflictsWith)?c.metadata?.conflictsWith:[],u=new Set(l.filter(p=>typeof p=="string"));u.add(i.id),c.updatedAt=t,c.metadata={...c.metadata??{},conflictsWith:[...u]},this.memories.set(c.id,c)}}return this.memories.set(i.id,i),i}importRecords(e){let t=0;for(let n of e){if(!n?.id)continue;let o=Y(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=>ke(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=O(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(u=>s.includes(u)).length,c=o.length===0?0:a/o.length,l=O(i)/500;return{memory:i,score:c+l,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=Je(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=Qe(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&&he(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 ve(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var ee=class{score(e,t){let n=ve(e),o=ve([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 Ze(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 Xe(r){return O(r)/100}var In={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function et(r){return In[r]??.4}var te=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 re=class{bm25=new ee;analyzer=new te;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 l=this.bm25.score(e,c),u=Ze(c),p=Xe(c),g=et(c.type);s.preferredTypes.includes(c.type)&&(g=Math.min(1,g+.25));let y=l*.55+p*.2+u*.15+g*.1;l<=0||y<i||a.push({memory:c,score:y,scores:{keyword:l,recency:u,importance:p,type:g}})}return a.sort((c,l)=>l.score-c.score).slice(0,o)}};var ne=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 oe=class{constructor(e){this.memory=e}memory;searcher=new re;contextBuilder=new ne;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 Yn}from"node:os";import{join as Zn}from"node:path";import{DeleteObjectCommand as Tn,GetObjectCommand as Rn,HeadObjectCommand as jn,ListObjectsV2Command as En,PutObjectCommand as On,S3Client as _n}from"@aws-sdk/client-s3";import{getSignedUrl as Nn}from"@aws-sdk/s3-request-presigner";var ie=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new _n({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 On({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Nn(this.client,new Rn({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 jn({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 Tn({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new En({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 tt,mkdir as Kn,readFile as $n,readdir as Fn,rm as Hn,stat as rt,writeFile as Ln}from"node:fs/promises";import{dirname as Dn,join as Wn,relative as nt,resolve as zn}from"node:path";var _=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return zn(this.root,t)}async put(e,t){let n=this.path(e);await Kn(Dn(n),{recursive:!0}),await Ln(n,t)}async get(e){try{return await $n(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 tt(this.path(e)),!0}catch{return!1}}async delete(e){await Hn(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await tt(t)}catch{return n}let o=async s=>{let a=await Fn(s,{withFileTypes:!0});for(let c of a){let l=Wn(s,c.name);if(c.isDirectory()){await o(l);continue}let u=await rt(l);n.push({key:nt(this.root,l),size:u.size,updatedAt:u.mtime.toISOString()})}},i=await rt(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 Vn,GetObjectCommand as Gn,HeadObjectCommand as qn,ListObjectsV2Command as Bn,PutObjectCommand as Un,S3Client as Jn}from"@aws-sdk/client-s3";import{getSignedUrl as Qn}from"@aws-sdk/s3-request-presigner";var N=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Jn({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 Un({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Qn(this.client,new Gn({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 qn({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 Vn({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new Bn({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 we(r,e){return console.warn(e),new _(r)}function ot(r){let e=r.localRoot??Zn(Yn(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new N({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?new N({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?new ie({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):we(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new _(e)}var se=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 Xn(r){return new Promise(e=>setTimeout(e,r))}async function it(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)),l=Math.floor(Math.random()*Math.max(1,c*.2));await Xn(c+l)}throw i}var eo=new Set(["put","get","getText","delete","list"]);function st(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:eo.has(n)?(...i)=>it(()=>Promise.resolve(o.apply(t,i)),e):o.bind(t)}})}function at(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 ct(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 ae=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=at(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=ct(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 b=["hub:read","teams:write","agents:write","acl:manage","loadouts:write","observability:read","wiki:read","wiki:write","governance:read","governance:write"];var ut="hub/state.v1.json";function to(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:[...b],createdAt:t,updatedAt:t}],loadouts:[],observability:{requests:0,mutations:0,errors:0,events:[]},createdAt:t,updatedAt:t}}function ro(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 ce=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(ut);if(!e){let t=to(this.project,this.ownerPrincipal);return await this.save(t),t}return ro(e,this.project)}async save(e){await this.storage.put(ut,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as be}from"node:crypto";var lt=["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 no(r){return r==="owner"||r==="admin"?[...b]:["hub:read"]}function Se(r){return[...new Set(r.map(e=>e.trim()).filter(Boolean))]}function oo(r){return structuredClone(r)}var ue=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:be(),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-${be().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-${be().slice(0,8)}`;if(n.agents.some(c=>c.id===i))throw new h(`Agent already exists: ${i}`,409);let s=Se(t.teamIds??[]);for(let c of s)if(!n.teams.some(l=>l.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:[...lt],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=Se(t.scopes??no(t.role));for(let c of i)if(!b.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:[...lt],memoryMode:"local",skillMemory:!0,contextOffload:!0,maxContextChars:6400,updatedAt:o},n.loadouts.push(i)),t.tools&&(i.tools=Se(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 oo(await this.ensureState())}};var dt="wiki/state.v1.json";function io(r){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:r.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function so(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 K=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(dt);if(!e){let t=io(this.project);return await this.save(t),t}return so(e,this.project)}async save(e){await this.storage.put(dt,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as ft}from"node:crypto";var f=class extends Error{constructor(t,n){super(t);this.statusCode=n}statusCode};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 F(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 mt(r){let e=[];for(let t of r.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let n=t[1]?.trim();n&&e.push(F(n))}return $(e)}function ao(r){return r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function pt(r){return{id:`revision-${ft()}`,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 M(r){return structuredClone(r)}var H=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:$(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 M([...e.pages].sort((t,n)=>t.title.localeCompare(n.title)))}async getPage(e){let t=await this.ensureState(),n=F(e),o=t.pages.find(i=>i.slug===n||i.id===e);if(!o)throw new f(`Wiki page not found: ${e}`,404);return M(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=F(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-${ft()}`,slug:i,title:n,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:o,tags:$(e.tags??[]),links:mt(o),revision:1,createdAt:s,updatedAt:s};return t.pages.push(a),t.revisions.push(pt(a)),M(a)})}async updatePage(e,t){return this.mutate(n=>{let o=F(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=mt(i.content)),t.tags!==void 0&&(i.tags=$(t.tags)),i.revision+=1,i.updatedAt=new Date().toISOString(),n.revisions.push(pt(i)),M(i)})}async history(e){let t=await this.getPage(e),n=await this.ensureState();return M(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 M(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=$(ao(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(),l=a.slug.toLowerCase(),u=a.summary?.toLowerCase()??"",p=a.content.toLowerCase(),g=a.tags.map(v=>v.toLowerCase()),y=0;for(let v of o)l===v&&(y+=12),c===v&&(y+=10),c.includes(v)&&(y+=6),l.includes(v)&&(y+=5),g.some(me=>me===v)?y+=5:g.some(me=>me.includes(v))&&(y+=3),u.includes(v)&&(y+=2),p.includes(v)&&(y+=1);y>0&&s.push({page:M(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 co,randomUUID as gt}from"node:crypto";var yt="wiki/governance.v1.json",wt="toolnet.knowledge-governance.v1",ht=500,L={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function uo(r,e=0,t=1){return Math.max(e,Math.min(t,r))}function xe(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function kt(r){return co("sha256").update(r.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function lo(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 mo(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),uo(e)}function vt(r){let e=new Date().toISOString();return{schema:wt,version:1,projectId:r,policy:{...L},reviews:[],audit:[],createdAt:e,updatedAt:e}}function bt(r){let e=r.autoApproveThreshold??L.autoApproveThreshold,t=r.criticalApproveThreshold??L.criticalApproveThreshold,n=r.staleAfterDays??L.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 D=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(yt);if(!e){let t=vt(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:bt(t.policy??L)}}catch{let t=vt(this.project.id);return await this.save(t),t}}async save(e){await this.storage.put(yt,JSON.stringify(e,null,2),"application/json")}},W=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:gt(),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>ht&&(e.audit=e.audit.slice(-ht))}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=bt({...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=mo(e),i=xe(e.title),s=t.filter(u=>u.slug!==e.slug&&xe(u.title)===i&&kt(u.content)!==kt(e.content)).map(u=>u.slug),a=lo(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 l=s.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:l,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:gt(),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(l=>l.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 l=o.reviews.find(u=>u.id===t.targetReviewId);if(!l)throw new f("Merge target review not found",404);return i.status="superseded",i.mergedInto=l.id,this.audit(o,"knowledge:merged",t.principal,{reviewId:e,sourceKey:i.sourceKey,metadata:{targetReviewId:l.id}}),structuredClone(i)}i.status="approved";let c=(await n.listPages()).find(l=>l.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(u=>{let p=o-Date.parse(u.updatedAt);return{slug:u.slug,title:u.title,updatedAt:u.updatedAt,ageDays:Math.max(0,Math.floor(p/864e5)),stale:Number.isFinite(p)&&p>i}}).filter(u=>u.stale).map(({stale:u,...p})=>p),a=new Map;for(let u of n){let p=xe(u.title),g=a.get(p)??[];g.push(u),a.set(p,g)}let c=[...a.entries()].filter(([,u])=>u.length>1).map(([u,p])=>({title:u,pages:p.map(g=>g.slug)})),l=t.reviews.filter(u=>u.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:n.length,automatedPages:n.filter(u=>u.tags.some(p=>p.startsWith("toolnet-auto-"))).length,manualPages:n.filter(u=>!u.tags.some(p=>p.startsWith("toolnet-auto-"))).length,stalePages:s,duplicateTitles:c,pendingReviews:l.length,lowConfidenceReviews:l.filter(u=>u.confidence<t.policy.autoApproveThreshold).length,conflicts:l.filter(u=>u.risk==="conflict").length,generatedAt:new Date().toISOString()}}};import{timingSafeEqual as _i}from"node:crypto";import{createServer as Ni}from"node:http";function St(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 xt(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 Ce}from"zod";import{existsSync as Io,readFileSync as To}from"node:fs";import{join as Ro}from"node:path";var xc=new Int32Array(new SharedArrayBuffer(4));import{closeSync as Ic,existsSync as po,fsyncSync as Tc,mkdirSync as Rc,openSync as jc,readFileSync as fo,renameSync as Ec,writeFileSync as Oc}from"node:fs";import{dirname as Nc,join as go}from"node:path";function yo(r){return go(r.rootPath,".toolnet","work","current.json")}function Me(r){let e=yo(r);if(!po(e))return null;try{let t=JSON.parse(fo(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as ho,mkdirSync as Hc,readFileSync as ko,renameSync as Lc,writeFileSync as Dc}from"node:fs";import{dirname as zc,join as vo}from"node:path";function wo(r){return vo(r.rootPath,".toolnet","context","session-origin.json")}function Ae(r){let e=wo(r);if(!ho(e))return null;try{let t=JSON.parse(ko(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function bo(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function le(r){let e=bo(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 xo,mkdirSync as Tu,readFileSync as Mo}from"node:fs";import{join as Mt}from"node:path";var gu=new P;function Ao(r){return Mt(r.rootPath,".toolnet","memory","checkpoints")}function Co(r){return Mt(Ao(r),"latest.json")}function Po(r){let e=Co(r);if(!xo(e))return null;try{let t=JSON.parse(Mo(e,"utf8"));return t.schema!=="toolnet.memory.checkpoint.v1"||t.project.id!==r.id?null:t}catch{return null}}function At(r){return Po(r)}var jo={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}},Eo={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function Oo(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 _o(r){let e=Ro(r.rootPath,".toolnet","work","handoff-latest.json");if(!Io(e))return null;try{let n=JSON.parse(To(e,"utf8")).continuity;return n?.schema!=="toolnet.handoff.v2"||n.project.id!==r.id?null:n}catch{return null}}function No(r){let e=At(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 Ko(r){let e=_o(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 $o(r){let e=Ae(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 Fo(r){let e=Me(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 Ho(r,e){let t=jo[r];return e.map((n,o)=>({...n,score:(t[n.kind]??10)+Eo[n.source]+Math.max(0,5-o*.01)}))}function Lo(r){let e=new Map;for(let t of r){let n=`${t.kind}:${Oo(t.value)}`,o=e.get(n);(!o||t.score>o.score)&&e.set(n,t)}return[...e.values()]}function de(r,e,t={}){let n=le(e),o=[...No(r),...Ko(r),...$o(r),...Fo(r)],i=Lo(Ho(n,o)).sort((u,p)=>p.score-u.score),s=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),c=[],l=0;for(let u of i){if(c.length>=s)break;let p=u.kind.length+u.value.length+u.source.length+16;c.length>0&&l+p>a||(c.push(u),l+=p)}return{intent:n,facts:c,context:{project:{id:r.id,name:r.name},intent:n,selectedFacts:c.map(u=>({kind:u.kind,value:u.value,source:u.source}))},stats:{candidates:o.length,selected:c.length,chars:l}}}var Ct={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"},Pt=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],Do={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:Pt};function Wo(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 zo(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 Vo(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 It(r){switch(r){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function Go(r,e){let t=[];for(let n of e){let o=r.filter(i=>i.kind===n).slice(0,It(n));for(let i of o)t.push(`${Ct[n]}: ${i.value}`)}return t.join(`
6
- `)}function qo(r,e){let t=Do[e]??Pt,n=[];for(let o of t){let i=r.filter(s=>s.kind===o).slice(0,It(o));for(let s of i)n.push(`${Ct[o]}: ${s.value}`)}return n.join(`
7
- `)}function Tt(r,e){let t=de(r,e,{maxFacts:32,maxChars:6400}),n=Vo(zo(t.facts)),o=Wo(e)?Go(n,["todo","task","next_action","file"]):qo(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 Bo,mkdirSync as Uo,readFileSync as Jo,renameSync as Qo,rmSync as Yo,writeFileSync as Zo}from"node:fs";import{join as Rt}from"node:path";var Xo=720*60*1e3;function jt(r){return Rt(r.rootPath,".toolnet","context","memory-agent-conversation.json")}function z(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function ei(r){let e=z(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 ti(r){if(ei(r))return!1;let e=z(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 ri(r,e,t){let n=jt(r);if(!Bo(n))return null;try{let o=JSON.parse(Jo(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 ni(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,z(i)].join(":");if(!t.has(s)&&(t.add(s),n.push({...o,value:i}),n.length>=e))break}return n}function oi(r,e){let t=jt(r),n=Rt(r.rootPath,".toolnet","context");Uo(n,{recursive:!0,mode:448});let o=`${t}.${process.pid}.tmp`;try{Zo(o,JSON.stringify(e,null,2)+`
8
- `,{encoding:"utf8",mode:384}),Qo(o,t)}finally{Yo(o,{force:!0})}}function ii(r){return r.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
9
- `)}function si(r,e){return r.priorFocus.find(t=>t.kind===e)?.value}function Et(r){if(!r.usedPriorFocus||r.currentIntent!=="summary"||r.priorFocus.length===0)return null;let e=z(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=si(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 ai(r){let e=z(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 Ot(r,e,t={}){let n=t.now??Date.now(),o=t.maxAgeMs??Xo,i=ri(r,n,o),s=!!(i&&i.focus.length>0&&ti(e)&&!ai(e)),a=s&&i?[e.trim(),"","Previous ToolNet Memory conversation focus:",ii(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=le(e),u=de(r,a,{maxFacts:8,maxChars:1800}).facts.map(g=>({kind:g.kind,value:g.value,source:g.source})),p=ni(s&&i?[...u,...i.focus]:u);return oi(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 ci,readFileSync as ui}from"node:fs";import{join as li}from"node:path";function S(r){return!!r?.trim()}function _t(r){let e=[],t=[],n=100;S(r.goal)||S(r.request)||(e.push("goal_or_request"),n-=20),S(r.activity)||S(r.current.task?.title)||S(r.current.phase?.title)||(e.push("current_work"),n-=25),S(r.nextAction)||S(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),S(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 l=e.includes("current_work")||e.includes("next_action"),u;return n>=80&&!l?u="high":n>=50?u="medium":u="low",{confidence:u,score:n,missingContext:e,warnings:t}}var Nt={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 I(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 T(r){return r.length>0?r.map(e=>`- ${e}`).join(`
11
- `):"- none"}function di(r,e){return r.length<=e?r:[r.slice(0,e).trimEnd(),"","[Structured handoff truncated]"].join(`
12
- `)}function Kt(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 mi(r,e="normal"){let t=Nt[e],n=I([`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=I([...r.completed.phases.map(l=>`Phase: ${l}`),...r.completed.tasks.map(l=>`Task: ${l}`)]).slice(0,t.completed),i=I([`Tests status: ${r.tests.status}`,...r.tests.recent.map(l=>`Test: ${l}`),...(r.tests.checks??[]).map(l=>`Check [${l.status}] ${l.kind}: ${l.command}`),...(r.evidence?.commands??[]).map(l=>`Command: ${l}`),...(r.evidence?.references??[]).map(l=>`Reference: ${l}`),...r.decisions.map(l=>`Decision: ${l}`),...r.attention.map(l=>`Attention: ${l}`)]).slice(0,t.evidence),s=I([r.files.current,...(r.files.active??[]).map(l=>`Active: ${l}`),...(r.files.modified??[]).map(l=>`Modified: ${l}`),...(r.files.created??[]).map(l=>`Created: ${l}`),...(r.files.deleted??[]).map(l=>`Deleted: ${l}`),...r.files.recent.map(l=>`Recent: ${l}`)]).slice(0,t.files),a=I(r.blockers).slice(0,t.blockers),c=I([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 pi(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",T(r.currentState),"","COMPLETED",T(r.completed),"","EVIDENCE",T(r.evidence),"","FILES_TOUCHED",T(r.filesTouched),"","BLOCKERS",T(r.blockers),"","NEXT_ACTION",T(r.nextAction)].join(`
13
- `)}function $t(r,e="normal"){let t=li(r.rootPath,".toolnet","work","handoff-latest.json");if(!ci(t))return null;try{let o=JSON.parse(ui(t,"utf8")).continuity;if(!o||o.schema!=="toolnet.handoff.v2"||o.version!==2)return null;let i=mi(o,e),s=_t(o),a=di(pi(i,e,s),Nt[e].maxChars);return{detail:e,data:i,quality:s,text:a}}catch{return null}}function fi(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}var gi=[/\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],hi=[/\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 ki(r){let e=0;for(let t of yi)t.test(r)&&(e+=1);return e}function Ft(r,e){let t=fi(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=gi.some(a=>a.test(t)),i=hi.some(a=>a.test(t)),s=ki(t);return!!(o&&s>=1||i&&s>=2||s>=4)}var il={question:Ce.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:Ce.enum(["local"]).optional().describe("Returns deterministic local memory only. No external AI is used."),detail:Ce.enum(["compact","normal","benchmark"]).optional().describe("Handoff detail level. compact=minimal, normal=standard, benchmark=deep evidence/files/tests for agent takeover.")};function Ht(r,e,t,n,o){if(!Ft(e,t))return{answer:n};let i=Kt(e,o),s=$t(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 Lt(r,e){let t=Ot(r.project,e.question),n=Et(t);if(n)return{...Ht(r,t.originalQuestion,String(n.intent),n.answer,e.detail),mode:"local",usedAi:!1,source:n.source,intent:n.intent};let o=Tt(r.project,t.originalQuestion),i=Ht(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 Bt}from"zod";import{chmodSync as cl,existsSync as Dt,mkdirSync as ul,readFileSync as Wt,renameSync as ll,writeFileSync as dl}from"node:fs";import{dirname as pl,join as V}from"node:path";var zt="toolnet.context-offload.v1",vi="toolnet.context-offload-asset.v1";function Vt(r){return V(r,".toolnet","offload")}function Gt(r){return V(Vt(r),"assets")}function wi(r){return V(Vt(r),"graph.json")}function Pe(){return{schema:zt,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function bi(r){let e=wi(r);if(!Dt(e))return Pe();try{let t=JSON.parse(Wt(e,"utf8"));return t.schema!==zt||t.version!==1||!Array.isArray(t.nodes)?Pe():t}catch{return Pe()}}function Si(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&&Dt(V(Gt(r),`${t}.json`)))return t;let n=bi(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 qt(r,e,t=6e3){let n=Si(r,e),o=Wt(V(Gt(r),`${n}.json`),"utf8"),i=JSON.parse(o);if(i.schema!==vi||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 hl={assetId:Bt.string().regex(/^[a-f0-9]{8,64}$/iu).describe("Asset reference from the ToolNet Context Offload Graph."),maxChars:Bt.number().int().min(200).max(2e4).optional().describe("Maximum asset characters to return. Defaults to 6000.")};async function Ut(r,e){return qt(r.project.rootPath,e.assetId,e.maxChars??6e3)}async function Jt(r,e){return{schema:"toolnet.api-memory-ask.v1",result:await Lt({project:r},e)}}async function Qt(r,e){return{schema:"toolnet.api-context-offload.v1",result:await Ut({project:r},e)}}import{z as Yt}from"zod";var xl={query:Yt.string(),limit:Yt.number().int().min(1).max(20).optional()};async function Zt(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 tr}from"zod";import{chmodSync as Cl,existsSync as xi,mkdirSync as Pl,readFileSync as Mi,readdirSync as Ai,renameSync as Il,statSync as Ci,writeFileSync as Tl}from"node:fs";import{join as Xt}from"node:path";var Pi="toolnet.skill-memory.v1";function Ii(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 Ti(r){return Xt(r.rootPath,".toolnet","memory","skills")}function Ri(r,e){if(!r||typeof r!="object")return!1;let t=r;return t.schema===Pi&&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 ji(r){let e=Ti(r);if(!xi(e))return[];if(!Ci(e).isDirectory())return[];let t=[];for(let n of Ai(e)){if(!n.endsWith(".json"))continue;let o=Xt(e,n);try{let i=JSON.parse(Mi(o,"utf8"));Ri(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 Ei(r){return Ii(r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_./-]+/gu).filter(e=>e.length>=2),32)}function Oi(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 Ei(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 er(r,e,t=5){let n=Math.max(1,Math.min(10,Math.floor(t)));return ji(r).map(o=>({...o,score:Oi(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 _l={query:tr.string().min(2).max(500).describe("Task, problem, file, command or workflow to match against successful reusable Skill Memory SOPs."),limit:tr.number().int().min(1).max(10).optional().describe("Maximum matching reusable SOPs to return. Default 5.")};async function rr(r,e){let t=er(r.project,e.query,e.limit??5);return{schema:"toolnet.skill-memory-search.v1",query:e.query,count:t.length,matches:t}}async function nr(r,e,t){return{schema:"toolnet.api-memory-search.v1",results:await Zt({project:r,retrieval:e},t)}}async function or(r,e){return{schema:"toolnet.api-skill-search.v1",result:await rr({project:r},e)}}function G(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 ir(r,e,t=500){if(r!==void 0)return w(r,e,1,t)}function Ie(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 sr(r,e){return{schema:"toolnet.api-hub-summary.v1",hub:await r.summary(e)}}async function ar(r,e){return{schema:"toolnet.api-hub-teams.v1",teams:await r.listTeams(e)}}async function cr(r,e,t){let n=G(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:ir(n.description,"team description",500)}:{}};return{schema:"toolnet.api-hub-team.v1",team:await r.createTeam(e,o)}}async function ur(r,e){return{schema:"toolnet.api-hub-agents.v1",agents:await r.listAgents(e)}}async function lr(r,e,t){let n=G(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:ir(n.kind,"agent kind",100)}:{},...n.teamIds!==void 0?{teamIds:Ie(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 dr(r,e){return{schema:"toolnet.api-hub-acl.v1",grants:await r.listAcl(e)}}async function mr(r,e,t){let n=G(t),o=w(n.role,"role",4,20);if(!["owner","admin","member","viewer"].includes(o))throw new Error("Invalid role");let i=Ie(n.scopes,"scopes",b.length);if(i?.some(a=>!b.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 pr(r,e,t){let n=G(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 fr(r,e){return{schema:"toolnet.api-hub-loadouts.v1",loadouts:await r.listLoadouts(e)}}async function gr(r,e,t){let n=G(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:Ie(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 yr(r,e){return{schema:"toolnet.api-hub-observability.v1",observability:await r.observability(e)}}async function x(r,e,t){if(!await r.authorize(e,t))throw new f(`Principal '${e}' lacks '${t}'`,403)}function hr(r){if(!r||typeof r!="object"||Array.isArray(r))throw new f("Invalid Wiki request",400);return r}function Te(r,e,t){if(typeof r!="string"||!r.trim()||r.length>t)throw new f(`Invalid ${e}`,400);return r.trim()}function kr(r,e,t){if(r!==void 0){if(typeof r!="string"||r.length>t)throw new f(`Invalid ${e}`,400);return r}}function vr(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 x(e,t,"wiki:read"),{schema:"toolnet.api-wiki-summary.v1",wiki:await r.summary()}}async function br(r,e,t){return await x(e,t,"wiki:read"),{schema:"toolnet.api-wiki-pages.v1",pages:await r.listPages()}}async function Sr(r,e,t,n){await x(e,t,"wiki:write");let o=hr(n),i={...o.slug!==void 0?{slug:Te(o.slug,"Wiki slug",120)}:{},title:Te(o.title,"Wiki title",200),...o.summary!==void 0?{summary:kr(o.summary,"Wiki summary",1e3)}:{},content:typeof o.content=="string"?o.content:"",...o.tags!==void 0?{tags:vr(o.tags)}:{}};return{schema:"toolnet.api-wiki-page.v1",page:await r.createPage(i)}}async function xr(r,e,t,n){return await x(e,t,"wiki:read"),{schema:"toolnet.api-wiki-page.v1",page:await r.getPage(n)}}async function Mr(r,e,t,n,o){await x(e,t,"wiki:write");let i=hr(o),s={...i.title!==void 0?{title:Te(i.title,"Wiki title",200)}:{},...i.summary!==void 0?{summary:kr(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:vr(i.tags)}:{}};return{schema:"toolnet.api-wiki-page.v1",page:await r.updatePage(n,s)}}async function Ar(r,e,t,n,o){return await x(e,t,"wiki:read"),{schema:"toolnet.api-wiki-search.v1",query:n,results:await r.search(n,o)}}async function Cr(r,e,t,n){return await x(e,t,"wiki:read"),{schema:"toolnet.api-wiki-history.v1",revisions:await r.history(n)}}async function Pr(r,e,t,n){return await x(e,t,"wiki:read"),{schema:"toolnet.api-wiki-backlinks.v1",pages:await r.backlinks(n)}}async function A(r,e,t){if(!await r.authorize(e,t))throw new f(`Principal '${e}' lacks '${t}'`,403)}function Ir(r){if(!r||typeof r!="object"||Array.isArray(r))throw new f("Invalid governance request",400);return r}async function Tr(r,e,t){return await A(e,t,"governance:read"),{schema:"toolnet.api-governance-summary.v1",governance:await r.summary()}}async function Rr(r,e,t,n){if(await A(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 jr(r,e,t,n,o,i){await A(t,n,"governance:write");let s=Ir(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 Er(r,e,t,n){return await A(t,n,"governance:read"),{schema:"toolnet.api-knowledge-quality.v1",quality:await r.quality(e)}}async function Or(r,e,t){return await A(e,t,"governance:read"),{schema:"toolnet.api-governance-policy.v1",policy:await r.policy()}}async function _r(r,e,t,n){await A(e,t,"governance:write");let o=Ir(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 Nr(r,e,t,n){return await A(e,t,"governance:read"),{schema:"toolnet.api-governance-audit.v1",events:await r.auditLog(n)}}function Ki(r){let e=r.headers["x-toolnet-principal"];return(Array.isArray(e)?e[0]:e)?.trim()||"anonymous"}function $i(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&&_i(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 Fi(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 Hi(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 Li(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 Di(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 Kr(r){return Ni(async(e,t)=>{try{let n=new URL(e.url??"/",`http://${e.headers.host??"localhost"}`),o=Ki(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/")&&!$i(e,r.token)){m(t,401,{error:"Unauthorized"});return}if(e.method==="GET"&&n.pathname==="/v1/health"){m(t,200,St(r.project));return}if(e.method==="GET"&&n.pathname==="/v1/project"){m(t,200,xt(r.project));return}if(e.method==="POST"&&n.pathname==="/v1/memory/ask"){let u=Fi(await k(e));if(!u){m(t,400,{error:"Invalid memory ask request"});return}m(t,200,await Jt(r.project,u));return}if(e.method==="POST"&&n.pathname==="/v1/memory/search"){let u=Hi(await k(e));if(!u){m(t,400,{error:"Invalid memory search request"});return}m(t,200,await nr(r.project,r.retrieval,u));return}if(e.method==="POST"&&n.pathname==="/v1/skills/search"){let u=Li(await k(e));if(!u){m(t,400,{error:"Invalid skill search request"});return}m(t,200,await or(r.project,u));return}if(e.method==="POST"&&n.pathname==="/v1/offload/read"){let u=Di(await k(e));if(!u){m(t,400,{error:"Invalid context offload request"});return}m(t,200,await Qt(r.project,u));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 sr(r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/hub/teams"){m(t,200,await ar(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/teams"){m(t,201,await cr(r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/agents"){m(t,200,await ur(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/agents"){m(t,201,await lr(r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/acl"){m(t,200,await dr(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/acl/grant"){m(t,200,await mr(r.hub,o,await k(e)));return}if(e.method==="POST"&&n.pathname==="/v1/hub/acl/revoke"){m(t,200,await pr(r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/loadouts"){m(t,200,await fr(r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/hub/loadouts"){m(t,200,await gr(r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/hub/observability"){m(t,200,await yr(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 br(r.wiki,r.hub,o));return}if(e.method==="POST"&&n.pathname==="/v1/wiki/pages"){m(t,201,await Sr(r.wiki,r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/wiki/search"){let u=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 Ar(r.wiki,r.hub,o,u,g));return}let s=/^\/v1\/wiki\/pages\/([^/]+)\/history$/u.exec(n.pathname);if(e.method==="GET"&&s){m(t,200,await Cr(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 Pr(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 xr(r.wiki,r.hub,o,decodeURIComponent(c[1])));return}if(e.method==="PUT"&&c){m(t,200,await Mr(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 Tr(r.governance,r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/governance/reviews"){m(t,200,await Rr(r.governance,r.hub,o,n.searchParams.get("status")??void 0));return}let l=/^\/v1\/governance\/reviews\/([^/]+)$/u.exec(n.pathname);if(e.method==="POST"&&l){m(t,200,await jr(r.governance,r.wiki,r.hub,o,decodeURIComponent(l[1]),await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/governance/quality"){m(t,200,await Er(r.governance,r.wiki,r.hub,o));return}if(e.method==="GET"&&n.pathname==="/v1/governance/policy"){m(t,200,await Or(r.governance,r.hub,o));return}if(e.method==="PUT"&&n.pathname==="/v1/governance/policy"){m(t,200,await _r(r.governance,r.hub,o,await k(e)));return}if(e.method==="GET"&&n.pathname==="/v1/governance/audit"){let u=Number(n.searchParams.get("limit")??100),p=Number.isInteger(u)?Math.max(1,Math.min(500,u)):100;m(t,200,await Nr(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 $r=process.env.TOOLNET_API_HOST??"127.0.0.1",Fr=Number(process.env.TOOLNET_API_PORT??9750);async function Wi(){let r=pe(),e=new J().detect(),t=ot({provider:r.storage.provider,r2:r.storage.r2,s3:r.storage.s3,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),n=st(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),o=new ae(n,e.id,e.name,e.remote??e.name),i=new ce(o,e,process.env.TOOLNET_HUB_OWNER?.trim()||"owner"),s=new ue(i,Number(process.env.TOOLNET_HUB_MAX_EVENTS??100));await s.initialize();let a=new K(o,e),c=new H(a);await c.initialize();let l=new W(new D(o,e));await l.initialize();let u=new X,p=new se(o);u.importRecords(await p.load(e.id));let g=new oe(u);Kr({project:e,retrieval:g,token:process.env.TOOLNET_API_TOKEN?.trim()||void 0,hub:s,wiki:c,governance:l}).listen(Fr,$r,()=>{console.log("ToolNet Memory API"),console.log(`Project: ${e.name}`),console.log(`Listening: http://${$r}:${Fr}`)})}Wi().catch(r=>{console.error(r),process.exit(1)});
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)});