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