toolnet-memory 0.3.14 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +0 -1
- package/.release-target +1 -1
- package/README.md +25 -1
- package/bin/toolnet-memory +5 -0
- package/bundle/agy-hook.js +67 -67
- package/bundle/agy.js +61 -61
- package/bundle/api.js +15 -15
- package/bundle/auto-integrate.js +28 -28
- package/bundle/background-refresh.js +7 -7
- package/bundle/claude-hook.js +51 -50
- package/bundle/codex-context.js +25 -24
- package/bundle/codex.js +71 -71
- package/bundle/context-runtime.js +45 -44
- package/bundle/context.js +15 -15
- package/bundle/continuity-certify.js +13 -13
- package/bundle/copilot-hook.js +87 -85
- package/bundle/copilot.js +4 -4
- package/bundle/cursor-hook.js +87 -85
- package/bundle/cursor.js +4 -4
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +20 -20
- package/bundle/gc.js +3 -0
- package/bundle/graph-index.js +4 -4
- package/bundle/graph-ui.js +3 -3
- package/bundle/grok-hook.js +60 -59
- package/bundle/grok.js +5 -5
- package/bundle/handoff-refresh.js +10 -10
- package/bundle/help-cli.js +4 -4
- package/bundle/impact.js +4 -4
- package/bundle/incremental.js +5 -4
- package/bundle/init.js +37 -37
- package/bundle/integration-status.js +4 -4
- package/bundle/kiro-hook.js +82 -81
- package/bundle/learner.js +6 -6
- package/bundle/mcp.js +17 -17
- package/bundle/memory-agent.js +7 -7
- package/bundle/memory-query.js +7 -7
- package/bundle/opencode.js +80 -80
- package/bundle/project-manual.js +7 -7
- package/bundle/recovery-certify.js +15 -15
- package/bundle/runtime.js +13 -12
- package/bundle/semantic.js +5 -5
- package/bundle/snapshot.js +4 -4
- package/bundle/status-cli.js +4 -4
- package/bundle/toolnet-cli.js +60 -60
- package/bundle/work-continuity.js +7 -7
- package/package.json +9 -3
- package/release-manifest.json +54 -3
package/bundle/toolnet-cli.js
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import{existsSync as
|
|
2
|
-
`,{encoding:"utf8",mode:384}),
|
|
3
|
-
`,{encoding:"utf8",mode:384}),
|
|
4
|
-
`,"application/json")}async scan(t){let n=`${t.remotePrefix}/events/`,r=await this.storage.list(n),
|
|
5
|
-
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||
|
|
1
|
+
import{existsSync as rs,mkdirSync as os,readFileSync as ss,renameSync as is,rmSync as as,writeFileSync as cs}from"node:fs";import{dirname as us}from"node:path";import{homedir as ns}from"node:os";import{join as Sn}from"node:path";function kn(e={}){return Sn(e.home??ns(),".toolnetcli")}function Ke(e={}){let t=e.cwd??process.cwd();return Sn(t,".toolnet","mcp.json")}function At(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ls(e){if(!rs(e))return{};let t=ss(e,"utf8").trim();if(!t)return{};let n;try{n=JSON.parse(t)}catch{throw new Error(`Invalid existing ToolNet CLI MCP config at ${e}: parse error. Not overwriting.`)}if(!At(n))throw new Error(`Invalid existing ToolNet CLI MCP config at ${e}: root must be a JSON object. Not overwriting.`);return n}function ds(e,t){os(us(e),{recursive:!0,mode:448});let n=`${e}.tmp-${process.pid}-${Date.now()}`;try{cs(n,`${JSON.stringify(t,null,2)}
|
|
2
|
+
`,{encoding:"utf8",mode:384}),is(n,e)}finally{as(n,{force:!0})}}function vn(e={}){let t=e.binary??"toolnet-memory",n=e.configFile??Ke({cwd:e.cwd}),r=ls(n),o="toolnet-memory";if(At(r.mcpServers)&&r.mcpServers[o]!=null&&!e.force)return{installed:!0,changed:!1,configFile:n};let i=At(r.mcpServers)?{...r.mcpServers}:{};return i[o]={command:t,args:["mcp"]},r.mcpServers=i,ds(n,r),{installed:!0,changed:!0,configFile:n}}function wn(e={}){let t=e.binary??"toolnet-memory",n=vn({binary:t,configFile:e.configFile,force:e.force,cwd:e.cwd});return{installed:n.installed,changed:n.changed,mcp:{...n,configured:n.installed},files:[n.configFile]}}import{existsSync as mn}from"node:fs";import{spawnSync as fl}from"node:child_process";var ps={mcp:!0,continuityRead:!0,nativeCapture:!1,lifecycleHooks:!1,sharedJournalWrite:!1,level:"mcp-only"},Mt={mcp:!0,continuityRead:!0,nativeCapture:!0,lifecycleHooks:!1,sharedJournalWrite:!0,level:"native-capture"},X={mcp:!0,continuityRead:!0,nativeCapture:!0,lifecycleHooks:!0,sharedJournalWrite:!0,level:"native-capture"},fs={mcp:!0,continuityRead:!0,nativeCapture:!0,lifecycleHooks:!0,sharedJournalWrite:!0,level:"native-capture"};function K(e,t,n){return{agent:e,...t,refreshMode:n}}var cd={agy:K("agy",X,"native-lifecycle"),opencode:K("opencode",fs,"persistent-plugin"),codex:K("codex",X,"native-lifecycle"),claude:K("claude",X,"native-lifecycle"),kiro:K("kiro",X,"native-lifecycle"),cursor:K("cursor",X,"native-lifecycle"),copilot:K("copilot",X,"native-lifecycle"),grok:K("grok",X,"native-lifecycle"),"toolnet-cli":K("toolnet-cli",Mt,"native-session"),kilo:K("kilo",ps,"mcp-only")};import{existsSync as ol,readFileSync as sl}from"node:fs";import{homedir as il}from"node:os";import{join as dn}from"node:path";var ms=[{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"}],gs=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function bn(e){return e.normalize("NFKC").trim().toLowerCase()}function ys(e){if(e.length===0)return 0;let t=new Map;for(let r of e)t.set(r,(t.get(r)??0)+1);let n=0;for(let r of t.values()){let o=r/e.length;n-=o*Math.log2(o)}return n}function hs(e){return/^[a-f0-9]{32}$/iu.test(e)||/^[a-f0-9]{40}$/iu.test(e)||/^[a-f0-9]{64}$/iu.test(e)}function Ss(e,t,n){let r=e.slice(Math.max(0,t-48),t),o=e.slice(n,Math.min(e.length,n+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${o}`)}function ks(e,t){return e.start<t.end&&t.start<e.end}function xn(e){return e.sort((t,n)=>t.start!==n.start?t.start-n.start:n.end-n.start-(t.end-t.start))}var Le=class{allowValues=new Set;enableEntropyHeuristic;constructor(t={}){for(let n of t.allowValues??[]){let r=bn(n);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=t.enableEntropyHeuristic??!0}scan(t){let n=[];for(let s of ms){let i=new RegExp(s.regex.source,s.regex.flags);for(let a of t.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||n.push({type:s.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:s.confidence})}this.enableEntropyHeuristic&&n.push(...this.entropyMatches(t));let r=xn(n),o=[];for(let s of r)o.some(i=>ks(i,s))||o.push(s);return xn(o)}hasSecrets(t){return this.scan(t).length>0}allowed(t){let n=bn(t);return gs.has(n)?!0:this.allowValues.has(n)}entropyMatches(t){let n=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let o of t.matchAll(r)){if(o.index===void 0||!o[0])continue;let s=o[0];this.allowed(s)||hs(s)||!/[A-Za-z]/u.test(s)||!/[0-9]/u.test(s)||Ss(t,o.index,o.index+s.length)&&(ys(s)<3.7||n.push({type:"high_entropy_secret",value:s,start:o.index,end:o.index+s.length,confidence:"heuristic"}))}return n}};var J=class{scanner;constructor(t={}){this.scanner=new Le(t)}sanitize(t){let n=this.scanner.scan(t);if(n.length===0)return{text:t,redacted:0,secretTypes:[]};let r=t,o=[...n].sort((i,a)=>a.start-i.start),s=new Set;for(let i of o)s.add(i.type),r=r.slice(0,i.start)+`[REDACTED:${i.type}]`+r.slice(i.end);return{text:r,redacted:n.length,secretTypes:[...s].sort()}}sanitizeValue(t){if(typeof t=="string")return this.sanitize(t).text;if(Array.isArray(t))return t.map(n=>this.sanitizeValue(n));if(t&&typeof t=="object"){let n={};for(let[r,o]of Object.entries(t)){let s=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")){n[r]="[REDACTED]";continue}n[r]=this.sanitizeValue(o)}return n}return t}};import{join as js}from"node:path";import{createHash as vs}from"node:crypto";import{dirname as ws}from"node:path";import{mkdirSync as bs,readFileSync as xs,renameSync as Cs,writeFileSync as Is}from"node:fs";function w(e){return vs("sha256").update(e).digest("hex")}function Pt(e){if(Array.isArray(e))return e.map(Pt);if(e&&typeof e=="object"){let t=e,n={};for(let r of Object.keys(t).sort())n[r]=Pt(t[r]);return n}return e}function $e(e){return JSON.stringify(Pt(e))}function Fe(e){try{return JSON.parse(xs(e,"utf8"))}catch{return null}}function O(e,t){bs(ws(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;Is(n,JSON.stringify(t,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),Cs(n,e)}function Cn(e,t){let n=e.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),o=w(n).slice(0,12);if(!r||r==="."||r==="..")return`${t}--${o}`;let s=r.slice(0,100);return s===n&&n.length<=100?s:`${s.slice(0,85)}--${o}`}function In(e,t,n){let r=t.trim(),o=n.trim();if(!r)throw new Error("Session agent is required");if(!o)throw new Error("Native session ID is required");let s=Cn(r.toLowerCase(),"agent"),i=Cn(o,"session");return{projectId:e.id,projectName:e.name,projectRoot:e.rootPath,agent:r,nativeSessionId:o,sessionKey:`${r}:${o}`,remotePrefix:["projects",e.id,"runtime","sources",s,i].join("/"),localDirectory:js(e.rootPath,".toolnet","runtime","sources",s,i)}}function jn(e){return String(e).padStart(12,"0")}var We=class{constructor(t,n=100,r=512*1024){this.storage=t;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(t){let n=await this.storage.getText(t);return n?JSON.parse(n):null}async putJson(t,n){await this.storage.put(t,JSON.stringify(n,null,2)+`
|
|
4
|
+
`,"application/json")}async scan(t){let n=`${t.remotePrefix}/events/`,r=await this.storage.list(n),o=[],s=0;for(let i of r){let a=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!a)continue;let c=Number(a[1]),u=Number(a[2]);!Number.isFinite(c)||!Number.isFinite(u)||(o.push({key:i.key,start:c,end:u}),s=Math.max(s,u))}return o.sort((i,a)=>i.start-a.start),{chunks:o,maxSequence:s}}split(t){let n=[],r=[],o=0;for(let s of t){let i=Buffer.byteLength(JSON.stringify(s)+`
|
|
5
|
+
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||o+i>this.maxChunkBytes)&&(n.push(r),r=[],o=0),r.push(s),o+=i}return r.length>0&&n.push(r),n}async loadManifest(t){return this.getJson(`${t.remotePrefix}/session.json`)}async loadCursor(t){return this.getJson(`${t.remotePrefix}/cursor.json`)}async recover(t){let n=await this.scan(t);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(t,n,r,o={}){let s=await this.loadManifest(t),i=await this.scan(t),a=n.filter(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(a)){let S=g[0],v=g[g.length-1],x=g.map(E=>JSON.stringify(E)).join(`
|
|
6
6
|
`)+`
|
|
7
|
-
`,
|
|
8
|
-
`,null,"utf8"),
|
|
9
|
-
`,null,"utf8"),
|
|
7
|
+
`,T=w(x).slice(0,16),M=[t.remotePrefix,"events",`${jn(S.sequence)}-${jn(v.sequence)}-${T}.jsonl`].join("/");await this.storage.exists(M)||await this.storage.put(M,x,"application/x-ndjson"),c+=g.length}let u=await this.scan(t),d=n[n.length-1],l=s?.status??"active";d?.type==="session_end"||d?.type==="session_idle"?l="idle":d?.type==="error"?l="error":n.length>0&&(l="active");let p=new Date().toISOString(),f=n[0],m={version:1,projectId:t.projectId,projectName:t.projectName,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,status:l,createdAt:s?.createdAt??f?.timestamp??p,updatedAt:d?.timestamp??p,firstEventAt:s?.firstEventAt??f?.timestamp,lastEventAt:d?.timestamp??s?.lastEventAt,eventCount:u.maxSequence,chunkCount:u.chunks.length,metadata:{...s?.metadata,...o.metadata}};(o.title??s?.title)&&(m.title=o.title??s?.title);let h={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:u.maxSequence,lastRemoteSequence:u.maxSequence,sourceCursors:r,updatedAt:p};return await this.putJson(`${t.remotePrefix}/cursor.json`,h),await this.putJson(`${t.remotePrefix}/session.json`,m),{uploadedEvents:c,lastRemoteSequence:u.maxSequence,eventCount:m.eventCount,chunkCount:m.chunkCount,status:l}}};import{closeSync as ye,existsSync as Je,fsyncSync as Lt,mkdirSync as Vs,openSync as he,readFileSync as Dn,readSync as Js,rmSync as $n,statSync as _t,truncateSync as Bs,writeSync as Hs}from"node:fs";import{join as Kt}from"node:path";var As=new Set(["thinking","reasoning","reasoningcontent","chainofthought","cot","analysistext","internalreasoning","modelthinking"]),Ms=new Set(["reasoning","thinking","chain_of_thought","chain-of-thought","internal_reasoning","internal-reasoning"]);function Ps(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,"")}function Ts(e){for(let t of["type","kind"]){let n=e[t];if(typeof n=="string"){let r=n.toLowerCase();if(Ms.has(r))return n}}return null}function Tt(e,t=0){if(t>12)return"[ToolNet nested value omitted]";if(Array.isArray(e))return e.map(s=>Tt(s,t+1));if(!e||typeof e!="object")return e;let n=e,r=Ts(n);if(r)return{type:r,omitted:"[private reasoning omitted]"};let o={};for(let[s,i]of Object.entries(n))As.has(Ps(s))||(o[s]=Tt(i,t+1));return o}function Es(e){if(!e)return new Date().toISOString();let t=new Date(e);return Number.isNaN(t.getTime())?new Date().toISOString():t.toISOString()}function Z(e){return e?.trim()||void 0}function An(e,t={}){let n={...e.provenance??{}},r=Z(e.source)??Z(t.source)??Z(n.source);return{...e,timestamp:Es(e.timestamp),source:r,turnId:Z(e.turnId)??Z(t.turnId),cwd:Z(e.cwd)??Z(t.cwd),data:Tt(e.data??{}),provenance:n}}var Os=new J;function fe(e){return Os.sanitizeValue(e)}import{randomUUID as Et}from"node:crypto";import{closeSync as oe,existsSync as se,fsyncSync as me,mkdirSync as Ot,openSync as ge,readFileSync as Nt,readdirSync as Ns,renameSync as Rs,rmSync as De,statSync as _s,writeSync as ze}from"node:fs";import{join as B}from"node:path";var Ks=12e4,Ls=80,$s="reconcile-required";function Fs(e){e<=0||Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}function ie(e){return B(e,".toolnet","journal")}function Tn(e){return B(ie(e),"events.jsonl")}function qe(e){return B(ie(e),$s)}function Ws(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t?.code!=="ESRCH"}}function En(e){if(!se(e))return null;try{let t=JSON.parse(Nt(e,"utf8"));return t.version!==1||typeof t.token!="string"||typeof t.pid!="number"||typeof t.acquiredAt!="string"?null:{version:1,token:t.token,pid:t.pid,acquiredAt:t.acquiredAt}}catch{return null}}function Ds(e){if(!se(e))return!1;let t=0;try{t=Date.now()-_s(e).mtimeMs}catch{return!1}if(t<=Ks)return!1;let n=En(e);return n?!Ws(n.pid):!0}function zs(e){if(!Ds(e))return!1;try{return De(e,{force:!0}),!0}catch{return!1}}function On(e){for(let t=0;t<Ls;t+=1){let n=Et();try{let r=ge(e,"wx",384),o={version:1,token:n,pid:process.pid,acquiredAt:new Date().toISOString()};try{return ze(r,`${JSON.stringify(o)}
|
|
8
|
+
`,null,"utf8"),me(r),{fd:r,token:n}}catch(s){throw oe(r),De(e,{force:!0}),s}}catch(r){if(r?.code!=="EEXIST")throw r;if(zs(e))continue;Fs(25)}}throw new Error(`Shared project journal is locked: ${e}`)}function Nn(e,t){oe(t.fd),En(e)?.token===t.token&&De(e,{force:!0})}function Mn(e){if(!se(e))return[];let t="";try{t=Nt(e,"utf8")}catch{return[]}let n=[];for(let r of t.split(/\r?\n/)){let o=r.trim();if(o)try{let s=JSON.parse(o);if(s.version!==1||typeof s.id!="string"||s.id.length===0||typeof s.projectId!="string"||s.projectId.length===0)continue;n.push(s)}catch{}}return n}function Rn(e){if(!se(e))return[];let t=[];for(let n of Ns(e,{withFileTypes:!0})){let r=B(e,n.name);if(n.isDirectory()){t.push(...Rn(r));continue}n.isFile()&&n.name==="events.jsonl"&&t.push(r)}return t.sort()}function Ve(e){let t=null;try{t=ge(e,"r"),me(t)}catch{}finally{if(t===null)return;oe(t)}}function Pn(e){let t=qe(e);if(!se(t))return null;try{return Nt(t,"utf8").trim()||null}catch{return null}}function Rt(e){let t=ie(e);Ot(t,{recursive:!0,mode:448});let n=qe(e),r=[Et(),new Date().toISOString()].join("|"),o=ge(n,"w",384);try{ze(o,`${r}
|
|
9
|
+
`,null,"utf8"),me(o)}finally{oe(o)}Ve(t)}function qs(e,t,n){let r=B(e,`.events.jsonl.tmp-${process.pid}-${Et()}`),o=ge(r,"w",384);try{let s=n.length===0?"":`${n.map(i=>JSON.stringify(i)).join(`
|
|
10
10
|
`)}
|
|
11
|
-
`;
|
|
11
|
+
`;s&&ze(o,s,null,"utf8"),me(o)}finally{oe(o)}Rs(r,t),Ve(e)}function _n(e){let t=ie(e),n=Tn(e),r=B(e,".toolnet","runtime","sources"),o=Pn(e),s=Rn(r),i=[],a=new Set;for(let l of Mn(n))a.has(l.id)||(a.add(l.id),i.push(l));let c=i.length,u=[];for(let l of s)for(let p of Mn(l))a.has(p.id)||(a.add(p.id),u.push(p));u.sort((l,p)=>{let f=l.timestamp.localeCompare(p.timestamp);return f!==0?f:l.id.localeCompare(p.id)}),i.push(...u),qs(t,n,i);let d=Pn(e);return o&&d===o&&(De(qe(e),{force:!0}),Ve(t)),{filesScanned:s.length,existingEvents:c,recoveredEvents:u.length,totalEvents:i.length}}function Kn(e){let t=ie(e);Ot(t,{recursive:!0,mode:448});let n=B(t,"journal.lock"),r=On(n);try{return _n(e)}finally{Nn(n,r)}}function Ln(e,t){if(t.length===0)return;let n=ie(e);Ot(n,{recursive:!0,mode:448});let r=Tn(e),o=B(n,"journal.lock"),s=On(o);try{if(se(qe(e))){_n(e);return}let i=`${t.map(c=>JSON.stringify(c)).join(`
|
|
12
12
|
`)}
|
|
13
|
-
`,a=
|
|
14
|
-
`),
|
|
13
|
+
`,a=ge(r,"a",384);try{ze(a,i,null,"utf8"),me(a)}finally{oe(a)}Ve(n)}finally{Nn(o,s)}}var Gs=12e4,Us=80,Fn=2e3;function Ys(e){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}function zn(e,t){let n=Buffer.isBuffer(t)?t:Buffer.from(t,"utf8"),r=0;for(;r<n.length;){let o=Hs(e,n,r,n.length-r);if(o<=0)throw new Error("Unable to write session WAL");r+=o}}function $t(e){let t=e.trim();if(!t)return null;try{let n=JSON.parse(t);return n.version!==1||typeof n.id!="string"||!n.id||typeof n.sequence!="number"||!Number.isFinite(n.sequence)||typeof n.projectId!="string"||!n.projectId||typeof n.timestamp!="string"?null:n}catch{return null}}function Xs(e){if(!Je(e))return[];let t="";try{t=Dn(e,"utf8")}catch{return[]}let n=[];for(let r of t.split(/\r?\n/)){let o=$t(r);o&&n.push(o)}return n}function Wn(e){return e.type==="session_end"||e.type==="session_idle"?"idle":e.type==="error"?"error":"active"}function Zs(e){if(!Je(e))return!1;let t;try{t=Dn(e)}catch{return!1}if(t.length===0||t[t.length-1]===10)return!1;let n=t.lastIndexOf(10),r=n>=0?n+1:0,o=t.subarray(r).toString("utf8").trim();if($t(o)){let i=he(e,"a");try{zn(i,`
|
|
14
|
+
`),Lt(i)}finally{ye(i)}return!0}Bs(e,r);let s=he(e,"a");try{Lt(s)}finally{ye(s)}return!0}function Qs(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(e[n]!==t[n])return!1;return!0}var Be=class{constructor(t,n={}){this.identity=t;this.eventContext=n;Vs(t.localDirectory,{recursive:!0}),this.eventsFile=Kt(t.localDirectory,"events.jsonl"),this.stateFile=Kt(t.localDirectory,"state.json"),this.lockFile=Kt(t.localDirectory,"journal.lock")}identity;eventContext;eventsFile;stateFile;lockFile;initialState(){let t=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:t,updatedAt:t,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return Fe(this.stateFile)??this.initialState()}recoverStateUnsafe(){Zs(this.eventsFile);let t=this.loadStateUnsafe(),n=Xs(this.eventsFile);if(n.length===0)return t;let r=n[0];for(let l of n)l.sequence<=r.sequence||(r=l);let o=n.slice(-Fn).map(l=>l.id),s=Je(this.eventsFile)?_t(this.eventsFile).size:0,i=Math.max(t.lastSequence,r.sequence),a=Math.min(t.remoteByteOffset,s),c=r.sequence>t.lastSequence;if(!(c||a!==t.remoteByteOffset||!Qs(t.recentEventIds,o)||t.lastLocalEventAt!==r.timestamp))return t;let d={...t,status:Wn(r),updatedAt:r.timestamp,lastLocalEventAt:r.timestamp,lastSequence:i,remoteByteOffset:a,recentEventIds:o};if(this.saveStateUnsafe(d),!c)return d;try{Rt(this.identity.projectRoot)}catch{return d}try{Kn(this.identity.projectRoot)}catch{}return d}loadState(){return this.withLock(()=>this.recoverStateUnsafe())}saveStateUnsafe(t){O(this.stateFile,t)}acquireLock(){for(let t=0;t<Us;t+=1)try{return he(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-_t(this.lockFile).mtimeMs>Gs){$n(this.lockFile,{force:!0});continue}}catch{}Ys(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(t){let n=this.acquireLock();try{return t()}finally{ye(n),$n(this.lockFile,{force:!0})}}append(t){return t.length===0?[]:this.withLock(()=>{let n=this.recoverStateUnsafe(),r=new Set(n.recentEventIds),o=n.lastSequence,s=[];for(let l of t){let p=An(l,this.eventContext),f=p.timestamp??new Date().toISOString(),m=p.data??{},h=p.provenance?.rawDigest??w($e(m)),g=fe(m),S=p.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,p.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,o+1,p.type,f,h].join("|"),v=w(S).slice(0,32);if(r.has(v))continue;o+=1;let x={version:1,id:v,sequence:o,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,sessionId:this.identity.nativeSessionId,type:p.type,timestamp:f,source:p.source??p.provenance?.source??this.identity.agent,data:g,provenance:{...p.provenance,rawDigest:h}};p.role!==void 0&&(x.role=p.role),p.turnId!==void 0&&(x.turnId=p.turnId),p.cwd!==void 0&&(x.cwd=p.cwd),p.sourceEventId!==void 0&&(x.sourceEventId=p.sourceEventId),p.sourceSequence!==void 0&&(x.sourceSequence=p.sourceSequence),s.push(x),r.add(v)}if(s.length===0)return[];let i=s.map(l=>JSON.stringify(l)).join(`
|
|
15
15
|
`)+`
|
|
16
|
-
`,a=
|
|
17
|
-
`)}function
|
|
18
|
-
`),a=Math.max(
|
|
19
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function
|
|
20
|
-
`).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let d=u.toLowerCase().replace(/\s+/g," ");if(r.has(d))continue;r.add(d);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(u)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(u)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(l="file");let p=
|
|
16
|
+
`,a=he(this.eventsFile,"a",384);try{zn(a,i),Lt(a)}finally{ye(a)}try{Ln(this.identity.projectRoot,s)}catch{try{Rt(this.identity.projectRoot)}catch{}}let c=s[s.length-1],u=Wn(c),d=Array.from(r).slice(-Fn);return this.saveStateUnsafe({...n,status:u,updatedAt:c.timestamp,lastLocalEventAt:c.timestamp,lastSequence:c.sequence,recentEventIds:d}),s})}readPending(){return this.withLock(()=>{let t=this.recoverStateUnsafe();if(!Je(this.eventsFile))return{events:[],startOffset:t.remoteByteOffset,endOffset:t.remoteByteOffset};let n=_t(this.eventsFile).size,r=Math.min(t.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let o=n-r,s=Buffer.alloc(o),i=he(this.eventsFile,"r");try{Js(i,s,0,o,r)}finally{ye(i)}let a=[];for(let c of s.toString("utf8").split(/\r?\n/)){let u=$t(c);u&&a.push(u)}return{events:a,startOffset:r,endOffset:n}})}markRemote(t,n){this.withLock(()=>{let r=this.recoverStateUnsafe(),o=new Date().toISOString();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,t),remoteByteOffset:Math.max(r.remoteByteOffset,n),lastRemoteAt:o,updatedAt:o})})}setSourceCursor(t,n){this.withLock(()=>{let r=this.recoverStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[t]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as ec,existsSync as tc,openSync as nc,readSync as rc,statSync as oc}from"node:fs";var ei=new Set(["rule","blocker","architecture","deploy"]),ti=new Set(["fix","todo","context","next_action"]);function Ft(e){return e<0?0:e>1?1:e}function qn(e,t){let n=Number.parseFloat(e??"");return Number.isFinite(n)?n:t}function ni(e){return e==="off"?"off":e==="balanced"?"balanced":e==="aggressive"?"aggressive":"conservative"}function Wt(){return{mode:ni(process.env.TOOLNET_MEMORY_PROMOTION),minScore:Ft(qn(process.env.TOOLNET_PROMOTE_MIN_SCORE,.65)),minConfidence:Ft(qn(process.env.TOOLNET_PROMOTE_MIN_CONFIDENCE,.78))}}function ri(e){switch(e){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function oi(e){let t=Ft(ri(e.importance)*.75+e.confidence*.25);return Math.round(t*1e6)/1e6}function si(e){return e.evidence?e.evidence:{userExplicit:!1,sourceVerified:!1,testVerified:!1,crossSessionConfirmations:0,assistantDerived:!1}}function ii(e,t=Wt()){if(e.importance==="temporary"||e.confidence<t.minConfidence)return"transient";let n=si(e);return e.kind==="rule"&&n.userExplicit?"permanent":e.kind==="rule"?"session":e.kind==="architecture"&&(n.userExplicit||n.sourceVerified||n.testVerified||n.crossSessionConfirmations>=2)?"permanent":e.kind==="architecture"?"session":e.kind==="decision"||e.kind==="todo"||e.kind==="fix"?"task":"session"}function ai(e,t=Wt()){if(t.mode==="off")return Number.POSITIVE_INFINITY;let n=0;t.mode==="balanced"&&(n=.1),t.mode==="aggressive"&&(n=.15);let r=Math.max(t.mode==="aggressive"?.5:.55,t.minScore-n);return ei.has(e)&&(r=Math.max(.5,r-.1)),ti.has(e)&&(r=Math.max(.5,r-.05)),r}function Dt(e,t=Wt()){let n=ii(e,t),r=oi(e),o=ai(e.kind,t);return n==="transient"?{knowledgeClass:n,score:r,threshold:o,persist:!1}:t.mode==="off"?{knowledgeClass:n,score:r,threshold:o,persist:!1}:{knowledgeClass:n,score:r,threshold:o,persist:r>=o}}function Vn(e,t){let n=t.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":e==="rule"||e==="decision"?"high":e==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var Gn=[/không được/iu,/tuyệt đối/iu,/bắt buộc/iu,/đừng\s+/iu,/must not/iu,/do not/iu,/don't/iu,/\bnever\b/iu],ci=[/từ giờ/iu,/về sau/iu,/mỗi lần/iu,/luôn luôn/iu,/\bluôn\b/iu,/quy tắc/iu,/workflow/iu,/\balways\b/iu,/\brequired\b/iu,/\bmust\b/iu,/from now on/iu],ui=[/\bchốt\b/iu,/quyết định/iu,/sẽ dùng/iu,/chọn .+ thay/iu,/đổi sang/iu,/chuyển sang/iu,/\bdecided\b/iu,/\bchosen\b/iu,/we will use/iu,/use .+ instead/iu,/switch(?:ed)? to/iu],li=[/\btodo\b/iu,/cần làm/iu,/cần thêm/iu,/cần sửa/iu,/cần kiểm tra/iu,/tiếp theo/iu,/bước tiếp theo/iu,/còn phải/iu,/còn cần/iu,/next step/iu,/\bneed to\b/iu,/\bremaining\b/iu,/follow[- ]?up/iu],di=[/đã sửa/iu,/đã fix/iu,/đã khắc phục/iu,/đã xử lý/iu,/hoàn tất/iu,/hoàn thành/iu,/\bfixed\b/iu,/\bresolved\b/iu,/\bimplemented\b/iu,/\bcompleted\b/iu,/\bpasses?\b/iu],Jn=[/kiến trúc/iu,/pipeline/iu,/adapter/iu,/schema/iu,/runtime/iu,/namespace/iu,/storage/iu,/lưu trữ/iu,/workflow/iu,/session core/iu,/memory engine/iu,/retrieval/iu],pi=[/\bdùng\b/iu,/\btách\b/iu,/\bthay\b/iu,/\bchuyển\b/iu,/\blưu\b/iu,/\bmap\b/iu,/\buse\b/iu,/\bsplit\b/iu,/\bstore\b/iu,/\breplace\b/iu,/\bmove\b/iu],fi=[/đường dẫn/iu,/\bpath\b/iu,/\bport\b/iu,/\bendpoint\b/iu,/\bdomain\b/iu,/\bbucket\b/iu,/\brepository\b/iu,/\brepo\b/iu,/\bbranch\b/iu,/\/[A-Za-z0-9._/-]{4,}/u],mi=[/\blà\b/iu,/\bở\b/iu,/\bdùng\b/iu,/\bnằm\b/iu,/\bis\b/iu,/\buse\b/iu,/located/iu,/runs on/iu],Bn=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),gi=new Set(["payload","data","content","message","messages","parts","summary"]);function N(e,t){return t.some(n=>n.test(e))}function Un(e){return e.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function yi(e){return Un(e).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function hi(e){return!(e.length<12||e.length>1e3||(e.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(e))}function zt(e,t,n,r=0){if(!(r>6)&&!(typeof e=="string"&&t&&!Bn.has(t))){if(typeof e=="string"){n.push(e);return}if(Array.isArray(e)){for(let o of e.slice(0,50))zt(o,t,n,r+1);return}if(!(!e||typeof e!="object"))for(let[o,s]of Object.entries(e))(Bn.has(o)||gi.has(o))&&zt(s,o,n,r+1)}}function Si(e){let t=[];zt(e.data,void 0,t);let n=[],r=new Set;for(let o of t)for(let s of o.split(/\n+|(?<=[.!?])\s+/u)){let i=Un(s);if(hi(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function Hn(e){return(e.role??(typeof e.data.role=="string"?e.data.role:"")).toLowerCase()}function ki(e,t,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=t==="user"||n.type==="user_prompt",o=t==="assistant"||n.type==="assistant_message";return r&&N(e,Gn)?{kind:"rule",confidence:.98}:r&&N(e,ci)?{kind:"rule",confidence:.92}:N(e,ui)?{kind:N(e,Jn)?"architecture":"decision",confidence:r?.93:.86}:r&&N(e,li)?{kind:"todo",confidence:.87}:N(e,Jn)&&N(e,pi)?{kind:"architecture",confidence:r?.88:.82}:o&&N(e,di)?{kind:"fix",confidence:.8}:r&&N(e,fi)&&N(e,mi)?{kind:"context",confidence:.79}:null}function vi(e,t,n){let r=t==="user"||n.type==="user_prompt",o=t==="assistant"||n.type==="assistant_message",s=!!n.provenance.sourcePath&&(e==="architecture"||e==="context"||e==="fix"),i=e==="fix"&&/(?:test|tests|pass|passed|passing)/iu.test(JSON.stringify(n.data));return{userExplicit:r,sourceVerified:s,testVerified:i,crossSessionConfirmations:1,assistantDerived:o}}function wi(e){switch(e){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function bi(e,t,n){return e==="rule"&&N(n,Gn)?"critical":e==="architecture"||e==="decision"||e==="rule"?"high":e==="fix"||e==="context"?"normal":Vn(t,n)}function Yn(e,t){let n=[],r=new Set,o=new Map;for(let s of t){let i=typeof s.data.messageId=="string"?s.data.messageId:void 0,a=Hn(s);i&&a&&o.set(i,a)}for(let s of t){let i=Hn(s),a=typeof s.data.messageId=="string"?s.data.messageId:void 0;!i&&a&&(i=o.get(a)??"");for(let c of Si(s)){let u=ki(c,i,s);if(!u||u.confidence<.75)continue;let d=wi(u.kind),l=yi(c),p=w([e.projectId,u.kind,l].join("|"));if(r.has(p))continue;r.add(p);let f=s.provenance.sourcePath?[s.provenance.sourcePath]:[],m=s.sourceEventId?[s.sourceEventId]:[];n.push({version:1,fingerprint:p,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,kind:u.kind,type:d,content:c,confidence:u.confidence,importance:bi(u.kind,d,c),evidence:vi(u.kind,i,s),tags:[d],provenance:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventIds:[s.id],sourceEventIds:m,sourcePaths:f,firstSequence:s.sequence,lastSequence:s.sequence},createdAt:s.timestamp})}}return n}import{createHash as xi}from"node:crypto";var Ci=["project-knowledge","implementation","continuation","session-context"],Ii={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function qt(e){return xi("sha256").update(e).digest("hex")}function He(e,t){return`${e}:${qt(t).slice(0,24)}`}function ji(e){try{return qt(JSON.stringify(e))}catch{return qt(String(e))}}function Q(e){let t=new Set,n=[];for(let r of e){let o=r?.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function Zn(e,t=420){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:`${n.slice(0,Math.max(0,t-1)).trimEnd()}\u2026`}function Ai(e){return e==="rule"||e==="architecture"?"project-knowledge":e==="decision"||e==="fix"?"implementation":e==="todo"?"continuation":"session-context"}function Xn(e){return e.length===0?0:e.reduce((t,n)=>t+n,0)/e.length}function Mi(e){return e.slice().sort((t,n)=>n.importanceScore-t.importanceScore||n.confidence-t.confidence||t.id.localeCompare(n.id)).slice(0,5).map(t=>Zn(t.content)).join(" | ")}function Pi(e){return e.slice().sort((t,n)=>n.importanceScore-t.importanceScore||n.confidence-t.confidence||t.id.localeCompare(n.id)).slice(0,6).map(t=>Zn(t.content)).join(`
|
|
17
|
+
`)}function Qn(e,t){let n=e.slice().sort((p,f)=>p.sequence-f.sequence||p.timestamp.localeCompare(f.timestamp)||p.id.localeCompare(f.id)),r=n.map(p=>({id:He("raw",[p.projectId,p.agent,p.nativeSessionId,p.id,String(p.sequence)].join("|")),level:"raw",eventId:p.id,sourceEventId:p.sourceEventId,sequence:p.sequence,type:p.type,role:p.role,timestamp:p.timestamp,sourcePath:p.provenance.sourcePath,payloadDigest:ji(p.data)})),o=new Map,s=new Map;n.forEach((p,f)=>{let m=r[f];m&&(o.set(p.id,m.id),p.sourceEventId&&s.set(p.sourceEventId,m.id))});let i=t.map(p=>{let f=Q([...p.provenance.eventIds.map(m=>o.get(m)),...p.provenance.sourceEventIds.map(m=>s.get(m))]);return{id:He("fact",p.fingerprint),level:"fact",fingerprint:p.fingerprint,kind:p.kind,type:p.type,content:p.content,knowledgeClass:p.knowledgeClass,importanceScore:p.importanceScore,confidence:p.confidence,tags:Q([...p.tags,"level:fact",`class:${p.knowledgeClass}`,`kind:${p.kind}`]),rawIds:f,sourcePaths:Q(p.provenance.sourcePaths)}}),a=new Map;for(let p of i){let f=Ai(p.kind),m=a.get(f)??[];m.push(p),a.set(f,m)}let c=[];for(let p of Ci){let f=a.get(p);if(!f?.length)continue;let m=f.slice().sort((g,S)=>S.importanceScore-g.importanceScore||S.confidence-g.confidence||g.id.localeCompare(S.id)),h=m.map(g=>g.id);c.push({id:He("scene",`${p}|${h.join("|")}`),level:"scene",kind:p,title:Ii[p],summary:Mi(m),factIds:h,importanceScore:Math.max(...m.map(g=>g.importanceScore)),confidence:Xn(m.map(g=>g.confidence)),tags:Q(["level:scene",`scene:${p}`,...m.flatMap(g=>g.tags)]),sourcePaths:Q(m.flatMap(g=>g.sourcePaths))})}let u=new Map(i.map(p=>[p.id,p])),d=[];for(let p of c){let m=p.factIds.map(S=>u.get(S)).filter(S=>!!S).filter(S=>(S.knowledgeClass==="permanent"||S.knowledgeClass==="task")&&S.importanceScore>=.55);if(m.length===0)continue;let h=m.some(S=>S.knowledgeClass==="permanent")?"permanent":"task",g=Pi(m);d.push({id:He("knowledge",`${p.id}|${h}|${m.map(S=>S.id).join("|")}`),level:"knowledge",knowledgeClass:h,title:p.title,content:g,sceneIds:[p.id],factIds:m.map(S=>S.id),importanceScore:Math.max(...m.map(S=>S.importanceScore)),confidence:Xn(m.map(S=>S.confidence)),tags:Q(["level:knowledge",`class:${h}`,`scene:${p.kind}`,...m.flatMap(S=>S.tags)]),sourcePaths:Q(m.flatMap(S=>S.sourcePaths))})}let l=[];for(let p of i)for(let f of p.rawIds)l.push({from:f,to:p.id,type:"supports"});for(let p of c)for(let f of p.factIds)l.push({from:f,to:p.id,type:"belongs_to"});for(let p of d)for(let f of p.sceneIds)l.push({from:f,to:p.id,type:"promotes_to"});return{schema:"toolnet.memory-hierarchy.v1",version:1,raw:r,facts:i,scenes:c,knowledge:d,links:l,stats:{raw:r.length,facts:i.length,scenes:c.length,knowledge:d.length,links:l.length}}}function Ti(e){return e?Math.ceil(e.length/3.5):0}function er(e,t){if(!e)return"";if(Ti(e)<=t)return e;let r=Math.floor(t*3.5),o=e.slice(0,r),s=o.lastIndexOf("."),i=o.lastIndexOf(`
|
|
18
|
+
`),a=Math.max(s,i);return a>r*.7?o.slice(0,a+1):o}import{existsSync as Ei,readFileSync as Oi}from"node:fs";import{homedir as Ni}from"node:os";import{join as Ri}from"node:path";function _i(e){let t=e.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?(t=t.slice(1,-1),t.replace(/\\n/g,`
|
|
19
|
+
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function Ki(){let e=process.env.TOOLNET_GLOBAL_ENV??Ri(Ni(),".config","toolnet-memory",".env");if(!Ei(e))return;let t=Oi(e,"utf8");for(let n of t.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let s=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=_i(r.slice(o+1)))}}Ki();function Se(e,t){return e===void 0?t:["1","true","yes","on"].includes(e.toLowerCase())}function ke(e,t){if(!e)return t;let n=Number(e);return Number.isFinite(n)?n:t}function Ge(){return{memory:{autoCapture:Se(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:Se(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:Se(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:Se(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:ke(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:ke(process.env.MEMORY_RERANK_TOP,10),finalContext:ke(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:ke(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:Se(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:ke(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}function ve(){let e=Ge(),t=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||t==="archive"||t==="full",r=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",o=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),s=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),a=n,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||t==="full";return{sessionSave:t,rawTranscript:n,memoryPromotion:r,promoteMinScore:o,sessionSummaryMaxTokens:s,durableMemoryMaxItemsPerSession:i,archiveLocal:a,archiveRemote:c}}function tr(e){return(e||ve()).durableMemoryMaxItemsPerSession}function nr(e){return(e||ve()).sessionSummaryMaxTokens}var rr=new J;function or(e){let t=e.trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{let r=JSON.parse(t);return JSON.stringify(rr.sanitizeValue(r))}catch{}let n=rr.sanitize(e).text;return n=n.replace(/("(?:api[_-]?key|token|secret|password|cookie|authorization)"\s*:\s*)"[^"]*"/gi,'$1"[REDACTED]"').replace(/('(?:api[_-]?key|token|secret|password|cookie|authorization)'\s*:\s*)'[^']*'/gi,"$1'[REDACTED]'").replace(/\b(api[_-]?key|token|secret|password|cookie|authorization)\b\s*[:=]\s*[^\s,;]+/gi,"$1=[REDACTED]").replace(/\bbearer\s+[A-Za-z0-9._~+/=-]+/gi,"Bearer [REDACTED]"),n}function Li(e,t){let n=e.toLowerCase(),r=.5,o=["nh\u1EDB","remember","quy t\u1EAFc","rule","t\u1EEB gi\u1EDD","from now","kh\xF4ng \u0111\u01B0\u1EE3c","must not","lu\xF4n lu\xF4n","always","never","critical","important","blocker","deploy","production","architecture"];for(let i of o)n.includes(i)&&(r+=.15);t==="rule"||t==="architecture"||t==="blocker"?r+=.2:t==="decision"||t==="deploy"?r+=.15:(t==="fix"||t==="next_action")&&(r+=.1),e.length<20?r-=.3:e.length>500&&(r-=.1);let s=[/npm (notice|warn|ERR)/i,/\d+ packages? in \d+/i,/found \d+ vulnerabilities/i,/up to date/i,/added \d+ packages/i,/^(ok|done|success|error|warning)$/i];for(let i of s)i.test(e)&&(r-=.4);return Math.max(0,Math.min(1,r))}function $i(e,t){let n=[],r=new Set;for(let i of e){let a=i.split(`
|
|
20
|
+
`).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let d=u.toLowerCase().replace(/\s+/g," ");if(r.has(d))continue;r.add(d);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(u)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(u)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(l="file");let p=Li(u,l);if(p<.3)continue;let f=or(u);n.push({category:l,text:f,importance:p,sourceSessionId:t})}}let o=ve(),s=tr(o);return n.sort((i,a)=>a.importance-i.importance).slice(0,s)}function Fi(e){let t=ve(),n=nr(t),s=e.join(`
|
|
21
21
|
|
|
22
22
|
`).split(`
|
|
23
|
-
`).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).map(i=>
|
|
24
|
-
`);return
|
|
25
|
-
|
|
26
|
-
`).filter(f=>f.trim())).map(f=>typeof f=="string"?f:JSON.stringify(f)).filter(f=>f.trim()),
|
|
27
|
-
`)}function
|
|
28
|
-
`;Ui(He(Di(e),`${c}.json`),d)?s+=1:o+=1,i.push(c),n=Yi(n,{id:c,kind:a.type,bytes:Buffer.byteLength(d,"utf8"),createdAt:a.timestamp,sourceRefs:[Gi(a)],files:Hi(a)})}return r>0&&Ji(e,n),{eligible:r,written:s,deduped:o,graphNodes:n.nodes.length,assetIds:i}}import{createHash as sa}from"node:crypto";import{existsSync as oa,readdirSync as ia,readFileSync as aa}from"node:fs";import{basename as ca,join as Ir}from"node:path";import{randomUUID as dr}from"node:crypto";var C=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function ke(e){let t=new Set,n=[];for(let r of e){let s=r.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();t.has(o)||(t.add(o),n.push(s))}return n}function ee(e){let t=e.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!t)throw new C("Invalid Wiki slug",400);return t}function ur(e){let t=[];for(let n of e.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&t.push(ee(r))}return ke(t)}function Xi(e){return e.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(t=>t.trim()).filter(t=>t.length>=2)}function lr(e){return{id:`revision-${dr()}`,pageId:e.id,slug:e.slug,revision:e.revision,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...e.tags],links:[...e.links],createdAt:e.updatedAt}}function Z(e){return structuredClone(e)}var Ge=class{constructor(t){this.store=t}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(t){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=t(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let t=await this.ensureState(),n=new Set(t.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:t.projectId,pages:t.pages.length,revisions:t.revisions.length,tags:ke(t.pages.flatMap(r=>r.tags)).sort((r,s)=>r.localeCompare(s)),links:t.pages.reduce((r,s)=>r+s.links.length,0),orphanPages:t.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:t.pages.filter(r=>r.tags.some(s=>s.startsWith("toolnet-auto-"))).length,updatedAt:t.updatedAt}}async listPages(){let t=await this.ensureState();return Z([...t.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(t){let n=await this.ensureState(),r=ee(t),s=n.pages.find(o=>o.slug===r||o.id===t);if(!s)throw new C(`Wiki page not found: ${t}`,404);return Z(s)}async createPage(t){return this.mutate(n=>{let r=t.title.trim(),s=t.content.trim();if(!r)throw new C("Wiki title is required",400);let o=ee(t.slug??r);if(n.pages.some(c=>c.slug===o))throw new C(`Wiki page already exists: ${o}`,409);let i=new Date().toISOString(),a={id:`wiki-${dr()}`,slug:o,title:r,...t.summary?.trim()?{summary:t.summary.trim()}:{},content:s,tags:ke(t.tags??[]),links:ur(s),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(lr(a)),Z(a)})}async updatePage(t,n){return this.mutate(r=>{let s=ee(t),o=r.pages.find(i=>i.slug===s||i.id===t);if(!o)throw new C(`Wiki page not found: ${t}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new C("Wiki title is required",400);o.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?o.summary=i:delete o.summary}return n.content!==void 0&&(o.content=n.content.trim(),o.links=ur(o.content)),n.tags!==void 0&&(o.tags=ke(n.tags)),o.revision+=1,o.updatedAt=new Date().toISOString(),r.revisions.push(lr(o)),Z(o)})}async history(t){let n=await this.getPage(t),r=await this.ensureState();return Z(r.revisions.filter(s=>s.pageId===n.id).sort((s,o)=>o.revision-s.revision))}async backlinks(t){let n=await this.getPage(t),r=await this.ensureState();return Z(r.pages.filter(s=>s.links.includes(n.slug)).sort((s,o)=>s.title.localeCompare(o.title)))}async search(t,n=10){let r=await this.ensureState(),s=ke(Xi(t));if(s.length===0)return[];let o=Math.max(1,Math.min(20,Math.floor(n))),i=[];for(let a of r.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),d=a.summary?.toLowerCase()??"",l=a.content.toLowerCase(),p=a.tags.map(g=>g.toLowerCase()),f=0;for(let g of s)u===g&&(f+=12),c===g&&(f+=10),c.includes(g)&&(f+=6),u.includes(g)&&(f+=5),p.some(S=>S===g)?f+=5:p.some(S=>S.includes(g))&&(f+=3),d.includes(g)&&(f+=2),l.includes(g)&&(f+=1);f>0&&i.push({page:Z(a),score:f})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,o)}};var pr="wiki/state.v1.json";function Qi(e){let t=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:e.id,pages:[],revisions:[],createdAt:t,updatedAt:t}}function Zi(e,t){let n=JSON.parse(e);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==t.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var Ue=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(pr);if(!t){let n=Qi(this.project);return await this.save(n),n}return Zi(t,this.project)}async save(t){await this.storage.put(pr,JSON.stringify(t,null,2),"application/json")}};import{createHash as ea,randomUUID as fr}from"node:crypto";var mr="wiki/governance.v1.json",Sr="toolnet.knowledge-governance.v1",gr=500,ve={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function ta(e,t=0,n=1){return Math.max(t,Math.min(n,e))}function qt(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function yr(e){return ea("sha256").update(e.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function na(e){let t=[e.title,e.summary??"",e.content.slice(0,2e3),...e.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(t)}function ra(e){let t=e.sourceType==="skill"?.96:e.sourceType==="memory"?.94:.88,n=e.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(t+=.03),e.content.length>=200&&(t+=.02),e.content.length<80&&(t-=.05),e.title.length<4&&(t-=.05),ta(t)}function hr(e){let t=new Date().toISOString();return{schema:Sr,version:1,projectId:e,policy:{...ve},reviews:[],audit:[],createdAt:t,updatedAt:t}}function kr(e){let t=e.autoApproveThreshold??ve.autoApproveThreshold,n=e.criticalApproveThreshold??ve.criticalApproveThreshold,r=e.staleAfterDays??ve.staleAfterDays;if(!Number.isFinite(t)||t<.5||t>1)throw new C("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new C("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new C("Invalid staleAfterDays",400);return{autoApproveThreshold:t,criticalApproveThreshold:n,staleAfterDays:r}}var Ye=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(mr);if(!t){let n=hr(this.project.id);return await this.save(n),n}try{let n=JSON.parse(t);if(n.schema!==Sr||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:kr(n.policy??ve)}}catch{let n=hr(this.project.id);return await this.save(n),n}}async save(t){await this.storage.put(mr,JSON.stringify(t,null,2),"application/json")}},Xe=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(t,n,r,s={}){t.audit.push({id:fr(),action:n,principal:r,...s.reviewId?{reviewId:s.reviewId}:{},...s.sourceKey?{sourceKey:s.sourceKey}:{},timestamp:new Date().toISOString(),...s.metadata?{metadata:s.metadata}:{}}),t.audit.length>gr&&(t.audit=t.audit.slice(-gr))}async mutate(t){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=await t(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(t,n){return this.mutate(r=>(r.policy=kr({...r.policy,...t}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let t=await this.ensureState(),n=r=>t.reviews.filter(s=>s.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:t.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:t.audit.length,policy:{...t.policy},updatedAt:t.updatedAt}}async listReviews(t){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!t||r.status===t).sort((r,s)=>s.updatedAt.localeCompare(r.updatedAt)))}async auditLog(t=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(t)));return structuredClone(n.audit.slice(-r).reverse())}async assess(t,n){let r=await this.ensureState(),s=ra(t),o=qt(t.title),i=n.filter(d=>d.slug!==t.slug&&qt(d.title)===o&&yr(d.content)!==yr(t.content)).map(d=>d.slug),a=na(t),c=[];s<r.policy.autoApproveThreshold&&c.push(`confidence:${s.toFixed(2)}`),a&&s<r.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:s,risk:u,requiresReview:i.length>0||s<r.policy.autoApproveThreshold||a&&s<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(t,n){let r=await this.assess(t,n);return this.mutate(s=>{let o=s.reviews.find(c=>c.sourceKey===t.sourceKey&&c.digest===t.digest);if(o?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(o)};if(o?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(o)};if(!r.requiresReview)return this.audit(s,"knowledge:auto-approved","system",{sourceKey:t.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(o?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(o)};let i=new Date().toISOString(),a={id:fr(),sourceKey:t.sourceKey,sourceType:t.sourceType,slug:t.slug,marker:t.marker,digest:t.digest,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...new Set([...t.tags,t.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};return s.reviews.push(a),this.audit(s,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(a)}})}async markApplied(t,n){await this.mutate(r=>{let s=r.reviews.find(o=>o.sourceKey===t&&o.digest===n&&o.status==="approved");s&&(s.appliedAt=new Date().toISOString(),s.updatedAt=s.appliedAt,this.audit(r,"knowledge:applied",s.reviewedBy??"system",{reviewId:s.id,sourceKey:t}))})}async decide(t,n,r){return this.mutate(async s=>{let o=s.reviews.find(u=>u.id===t);if(!o)throw new C(`Governance review not found: ${t}`,404);if(o.status!=="pending")throw new C("Governance review is already resolved",409);let i=new Date().toISOString();if(o.reviewedAt=i,o.reviewedBy=n.principal,o.updatedAt=i,n.note?.trim()&&(o.reviewNote=n.note.trim()),n.action==="reject")return o.status="rejected",this.audit(s,"knowledge:rejected",n.principal,{reviewId:t,sourceKey:o.sourceKey}),structuredClone(o);if(n.action==="supersede")return o.status="superseded",n.targetReviewId&&(o.supersededBy=n.targetReviewId),this.audit(s,"knowledge:superseded",n.principal,{reviewId:t,sourceKey:o.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(o);if(n.action==="merge"){if(!n.targetReviewId)throw new C("targetReviewId is required for merge",400);let u=s.reviews.find(d=>d.id===n.targetReviewId);if(!u)throw new C("Merge target review not found",404);return o.status="superseded",o.mergedInto=u.id,this.audit(s,"knowledge:merged",n.principal,{reviewId:t,sourceKey:o.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(o)}o.status="approved";let c=(await r.listPages()).find(u=>u.slug===o.slug);if(c&&!c.tags.includes(o.marker))throw new C(`Wiki page '${o.slug}' is manually managed`,409);return c?await r.updatePage(o.slug,{title:o.title,summary:o.summary??"",content:o.content,tags:o.tags}):await r.createPage({slug:o.slug,title:o.title,...o.summary?{summary:o.summary}:{},content:o.content,tags:o.tags}),o.appliedAt=i,this.audit(s,"knowledge:approved",n.principal,{reviewId:t,sourceKey:o.sourceKey}),structuredClone(o)})}async quality(t){let n=await this.ensureState(),r=await t.listPages(),s=Date.now(),o=n.policy.staleAfterDays*864e5,i=r.map(d=>{let l=s-Date.parse(d.updatedAt);return{slug:d.slug,title:d.title,updatedAt:d.updatedAt,ageDays:Math.max(0,Math.floor(l/864e5)),stale:Number.isFinite(l)&&l>o}}).filter(d=>d.stale).map(({stale:d,...l})=>l),a=new Map;for(let d of r){let l=qt(d.title),p=a.get(l)??[];p.push(d),a.set(l,p)}let c=[...a.entries()].filter(([,d])=>d.length>1).map(([d,l])=>({title:d,pages:l.map(p=>p.slug)})),u=n.reviews.filter(d=>d.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(d=>d.tags.some(l=>l.startsWith("toolnet-auto-"))).length,manualPages:r.filter(d=>!d.tags.some(l=>l.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(d=>d.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(d=>d.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var jr="wiki/automation.v1.json",Ar="toolnet.wiki-automation.v1",Vt=8e3,vr=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function be(e){return sa("sha256").update(JSON.stringify(e)).digest("hex")}function we(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function wr(e){return Array.isArray(e)?e:[]}function Mr(e){return typeof e!="string"?void 0:e.replace(/\s+/gu," ").trim()||void 0}function Bt(e){return Array.isArray(e)?e.map(Mr).filter(t=>!!t):[]}function K(e,t){for(let n of t){let r=Mr(e[n]);if(r)return r}}function xe(e){let t=new Set,n=[];for(let r of e){let s=r.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();t.has(o)||(t.add(o),n.push(s))}return n}function Qe(e,t=0,n=""){if(t>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(vr.has(r))return[];if(typeof e=="string"){let i=e.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(e))return e.flatMap(i=>Qe(i,t+1,n));let s=we(e);if(!s)return[];let o=[];for(let[i,a]of Object.entries(s)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();vr.has(c)||o.push(...Qe(a,t+1,i))}return o}function br(e){let n=xe(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(s=>Qe(e[s],0,s)));return(n.length>0?n:xe(Qe(e))).join(`
|
|
29
|
-
|
|
30
|
-
`).slice(0,
|
|
31
|
-
${u}`),l&&
|
|
32
|
-
${l}`),p.length>0&&
|
|
33
|
-
${p.map((
|
|
34
|
-
`)}`),f.length>0&&
|
|
35
|
-
${f.map(
|
|
36
|
-
`)}`),
|
|
37
|
-
${
|
|
38
|
-
`)}`);let
|
|
39
|
-
|
|
40
|
-
`).slice(0,
|
|
41
|
-
`).slice(0,
|
|
42
|
-
`,{encoding:"utf8",mode:384}),
|
|
43
|
-
`,c=
|
|
44
|
-
`,"application/json"),u}};function
|
|
23
|
+
`).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).map(i=>or(i)).join(`
|
|
24
|
+
`);return er(s,n)}function sr(e,t){let r=(Array.isArray(e)?e:e.split(`
|
|
25
|
+
|
|
26
|
+
`).filter(f=>f.trim())).map(f=>typeof f=="string"?f:JSON.stringify(f)).filter(f=>f.trim()),o=$i(r,t),s=o.filter(f=>f.category==="decision").map(f=>f.text),i=o.filter(f=>f.category==="rule").map(f=>f.text),a=o.filter(f=>f.category==="file").map(f=>f.text),c=o.filter(f=>f.category==="fix").map(f=>f.text),u=o.filter(f=>f.category==="blocker").map(f=>f.text),d=o.filter(f=>f.category==="next_action").map(f=>f.text),l=o.filter(f=>f.category==="deploy").map(f=>f.text);return{summary:Fi(r),decisions:s,projectRules:i,filesChanged:a,bugsFixed:c,commands:l,blockers:u,nextActions:d,durableFacts:o}}function H(e){let t=new Set,n=[];for(let r of e){let o=r?.replace(/\s+/g," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function Wi(e){let t=new Map;for(let n of e){if(!n||!n.id||!Number.isFinite(n.sequence))continue;let r=n.sourceEventId?`${n.agent}:${n.sourceEventId}`:n.id,o=t.get(r);(!o||n.sequence>o.sequence)&&t.set(r,n)}return[...t.values()].sort((n,r)=>n.sequence-r.sequence||n.timestamp.localeCompare(r.timestamp))}function Di(e){let t=e.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}_./:-]+/gu)??[],n=new Set;for(let r of t)if(!(r.length<2||/^\d+$/u.test(r))&&(n.add(r),n.size>=40))break;return[...n]}function zi(e){let t=Dt(e);return{...e,knowledgeClass:t.knowledgeClass,importanceScore:t.score,retrievalTerms:Di(e.content),tags:H([...e.tags,"level:fact",`class:${t.knowledgeClass}`,`kind:${e.kind}`])}}function qi(e){return e.map(t=>{try{return JSON.stringify({type:t.type,role:t.role,data:t.data,provenance:{sourcePath:t.provenance.sourcePath,files:t.provenance.files}})}catch{return""}}).filter(Boolean)}function Vi(e,t,n){let r=sr(qi(t),e.nativeSessionId),o=n.filter(u=>u.kind==="todo").map(u=>u.content),s=n.flatMap(u=>u.provenance.sourcePaths),i=n.filter(u=>u.kind==="architecture").map(u=>u.content),a=H([...o,...r.nextActions]),c=H([...r.nextActions,...o]);return{summary:r.summary,state:{task:c[0]??a[0],decisions:H(r.decisions),files:H([...r.filesChanged,...s]),todos:a,completed:H(r.bugsFixed),blockers:H(r.blockers),nextActions:c,architecture:H(i)}}}function Ue(e,t){let n=Wi(t),r=Yn(e,n).map(zi),o=r.filter(d=>Dt(d).persist).sort((d,l)=>l.importanceScore-d.importanceScore),{summary:s,state:i}=Vi(e,n,o),a=o.map(d=>({fingerprint:d.fingerprint,kind:d.kind,knowledgeClass:d.knowledgeClass,importanceScore:d.importanceScore,content:d.content,terms:d.retrievalTerms})),c=Qn(n,o),u=d=>r.filter(l=>l.knowledgeClass===d).length;return{version:2,normalizedEvents:n,summary:s,state:i,candidates:o,retrievalIndex:a,hierarchy:c,stats:{inputEvents:t.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:o.length,permanent:u("permanent"),task:u("task"),session:u("session"),transient:u("transient")}}}import{createHash as Ji}from"node:crypto";import{chmodSync as ir,existsSync as Bi,mkdirSync as Hi,readFileSync as Gi,renameSync as Ui,writeFileSync as ar}from"node:fs";import{dirname as cr,join as Ye}from"node:path";var Bt="toolnet.context-offload.v1",Yi="toolnet.context-offload-asset.v1",Xi=256,Zi=new Set(["tool_call","tool_result","file_read","file_write","file_edit","command","test","artifact"]);function ur(e){return Ye(e,".toolnet","offload")}function Qi(e){return Ye(ur(e),"assets")}function lr(e){return Ye(ur(e),"graph.json")}function dr(e){Hi(e,{recursive:!0,mode:448});try{ir(e,448)}catch{}}function ea(e,t){dr(cr(e));let n=`${e}.${process.pid}.${Date.now()}.tmp`;ar(n,t,{encoding:"utf8",mode:384}),Ui(n,e);try{ir(e,384)}catch{}}function Jt(e){return Array.isArray(e)?e.map(Jt):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,Jt(n)])):e}function ta(e){return Ji("sha256").update(JSON.stringify(Jt(e)),"utf8").digest("hex")}function Vt(){return{schema:Bt,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function na(e){let t=lr(e);if(!Bi(t))return Vt();try{let n=JSON.parse(Gi(t,"utf8"));return n.schema!==Bt||n.version!==1||!Array.isArray(n.nodes)?Vt():n}catch{return Vt()}}function ra(e,t){ea(lr(e),JSON.stringify(t,null,2)+`
|
|
27
|
+
`)}function oa(e,t=260){if(typeof e!="string")return null;let n=e.replace(/\s+/gu," ").trim();return n?n.slice(0,t):null}function sa(e){let t=[...e.provenance.files??[],e.provenance.sourcePath],n=[];for(let r of t){let o=oa(r);if(!(!o||n.includes(o))&&(n.push(o),n.length===3))break}return n}function ia(e){return`${e.agent}:${e.sourceEventId??e.id}`.replace(/\s+/gu," ").trim().slice(0,120)}function aa(e,t){dr(cr(e));try{return ar(e,t,{encoding:"utf8",flag:"wx",mode:384}),!0}catch(n){if(n.code==="EEXIST")return!1;throw n}}function ca(e,t){let n=e.nodes.find(o=>o.id===t.id),r=n?{...n,kind:t.kind,bytes:t.bytes,sourceRefs:Array.from(new Set([...n.sourceRefs,...t.sourceRefs])).slice(-8),files:Array.from(new Set([...n.files,...t.files])).slice(0,6)}:t;return{schema:Bt,version:1,updatedAt:new Date().toISOString(),nodes:[...e.nodes.filter(o=>o.id!==t.id),r].slice(-Xi)}}function pr(e,t){let n=na(e),r=0,o=0,s=0,i=[];for(let a of t){if(!Zi.has(a.type))continue;r+=1;let c=ta({type:a.type,data:a.data}),u={schema:Yi,version:1,assetId:c,event:{type:a.type,agent:a.agent,nativeSessionId:a.nativeSessionId,timestamp:a.timestamp,sourceEventId:a.sourceEventId,provenance:a.provenance,data:a.data}},d=JSON.stringify(u,null,2)+`
|
|
28
|
+
`;aa(Ye(Qi(e),`${c}.json`),d)?o+=1:s+=1,i.push(c),n=ca(n,{id:c,kind:a.type,bytes:Buffer.byteLength(d,"utf8"),createdAt:a.timestamp,sourceRefs:[ia(a)],files:sa(a)})}return r>0&&ra(e,n),{eligible:r,written:o,deduped:s,graphNodes:n.nodes.length,assetIds:i}}import{createHash as ya}from"node:crypto";import{existsSync as ha,readdirSync as Sa,readFileSync as ka}from"node:fs";import{basename as va,join as Pr}from"node:path";import{randomUUID as gr}from"node:crypto";var I=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function we(e){let t=new Set,n=[];for(let r of e){let o=r.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function te(e){let t=e.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!t)throw new I("Invalid Wiki slug",400);return t}function fr(e){let t=[];for(let n of e.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&t.push(te(r))}return we(t)}function ua(e){return e.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(t=>t.trim()).filter(t=>t.length>=2)}function mr(e){return{id:`revision-${gr()}`,pageId:e.id,slug:e.slug,revision:e.revision,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...e.tags],links:[...e.links],createdAt:e.updatedAt}}function ee(e){return structuredClone(e)}var Xe=class{constructor(t){this.store=t}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(t){let n,r=this.queue.then(async()=>{let o=await this.ensureState();n=t(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let t=await this.ensureState(),n=new Set(t.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:t.projectId,pages:t.pages.length,revisions:t.revisions.length,tags:we(t.pages.flatMap(r=>r.tags)).sort((r,o)=>r.localeCompare(o)),links:t.pages.reduce((r,o)=>r+o.links.length,0),orphanPages:t.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:t.pages.filter(r=>r.tags.some(o=>o.startsWith("toolnet-auto-"))).length,updatedAt:t.updatedAt}}async listPages(){let t=await this.ensureState();return ee([...t.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(t){let n=await this.ensureState(),r=te(t),o=n.pages.find(s=>s.slug===r||s.id===t);if(!o)throw new I(`Wiki page not found: ${t}`,404);return ee(o)}async createPage(t){return this.mutate(n=>{let r=t.title.trim(),o=t.content.trim();if(!r)throw new I("Wiki title is required",400);let s=te(t.slug??r);if(n.pages.some(c=>c.slug===s))throw new I(`Wiki page already exists: ${s}`,409);let i=new Date().toISOString(),a={id:`wiki-${gr()}`,slug:s,title:r,...t.summary?.trim()?{summary:t.summary.trim()}:{},content:o,tags:we(t.tags??[]),links:fr(o),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(mr(a)),ee(a)})}async updatePage(t,n){return this.mutate(r=>{let o=te(t),s=r.pages.find(i=>i.slug===o||i.id===t);if(!s)throw new I(`Wiki page not found: ${t}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new I("Wiki title is required",400);s.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?s.summary=i:delete s.summary}return n.content!==void 0&&(s.content=n.content.trim(),s.links=fr(s.content)),n.tags!==void 0&&(s.tags=we(n.tags)),s.revision+=1,s.updatedAt=new Date().toISOString(),r.revisions.push(mr(s)),ee(s)})}async history(t){let n=await this.getPage(t),r=await this.ensureState();return ee(r.revisions.filter(o=>o.pageId===n.id).sort((o,s)=>s.revision-o.revision))}async backlinks(t){let n=await this.getPage(t),r=await this.ensureState();return ee(r.pages.filter(o=>o.links.includes(n.slug)).sort((o,s)=>o.title.localeCompare(s.title)))}async search(t,n=10){let r=await this.ensureState(),o=we(ua(t));if(o.length===0)return[];let s=Math.max(1,Math.min(20,Math.floor(n))),i=[];for(let a of r.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),d=a.summary?.toLowerCase()??"",l=a.content.toLowerCase(),p=a.tags.map(m=>m.toLowerCase()),f=0;for(let m of o)u===m&&(f+=12),c===m&&(f+=10),c.includes(m)&&(f+=6),u.includes(m)&&(f+=5),p.some(h=>h===m)?f+=5:p.some(h=>h.includes(m))&&(f+=3),d.includes(m)&&(f+=2),l.includes(m)&&(f+=1);f>0&&i.push({page:ee(a),score:f})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,s)}};var yr="wiki/state.v1.json";function la(e){let t=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:e.id,pages:[],revisions:[],createdAt:t,updatedAt:t}}function da(e,t){let n=JSON.parse(e);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==t.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var Ze=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(yr);if(!t){let n=la(this.project);return await this.save(n),n}return da(t,this.project)}async save(t){await this.storage.put(yr,JSON.stringify(t,null,2),"application/json")}};import{createHash as pa,randomUUID as hr}from"node:crypto";var Sr="wiki/governance.v1.json",br="toolnet.knowledge-governance.v1",kr=500,be={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function fa(e,t=0,n=1){return Math.max(t,Math.min(n,e))}function Ht(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function vr(e){return pa("sha256").update(e.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function ma(e){let t=[e.title,e.summary??"",e.content.slice(0,2e3),...e.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(t)}function ga(e){let t=e.sourceType==="skill"?.96:e.sourceType==="memory"?.94:.88,n=e.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(t+=.03),e.content.length>=200&&(t+=.02),e.content.length<80&&(t-=.05),e.title.length<4&&(t-=.05),fa(t)}function wr(e){let t=new Date().toISOString();return{schema:br,version:1,projectId:e,policy:{...be},reviews:[],audit:[],createdAt:t,updatedAt:t}}function xr(e){let t=e.autoApproveThreshold??be.autoApproveThreshold,n=e.criticalApproveThreshold??be.criticalApproveThreshold,r=e.staleAfterDays??be.staleAfterDays;if(!Number.isFinite(t)||t<.5||t>1)throw new I("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new I("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new I("Invalid staleAfterDays",400);return{autoApproveThreshold:t,criticalApproveThreshold:n,staleAfterDays:r}}var Qe=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(Sr);if(!t){let n=wr(this.project.id);return await this.save(n),n}try{let n=JSON.parse(t);if(n.schema!==br||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:xr(n.policy??be)}}catch{let n=wr(this.project.id);return await this.save(n),n}}async save(t){await this.storage.put(Sr,JSON.stringify(t,null,2),"application/json")}},et=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(t,n,r,o={}){t.audit.push({id:hr(),action:n,principal:r,...o.reviewId?{reviewId:o.reviewId}:{},...o.sourceKey?{sourceKey:o.sourceKey}:{},timestamp:new Date().toISOString(),...o.metadata?{metadata:o.metadata}:{}}),t.audit.length>kr&&(t.audit=t.audit.slice(-kr))}async mutate(t){let n,r=this.queue.then(async()=>{let o=await this.ensureState();n=await t(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(t,n){return this.mutate(r=>(r.policy=xr({...r.policy,...t}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let t=await this.ensureState(),n=r=>t.reviews.filter(o=>o.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:t.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:t.audit.length,policy:{...t.policy},updatedAt:t.updatedAt}}async listReviews(t){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!t||r.status===t).sort((r,o)=>o.updatedAt.localeCompare(r.updatedAt)))}async auditLog(t=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(t)));return structuredClone(n.audit.slice(-r).reverse())}async assess(t,n){let r=await this.ensureState(),o=ga(t),s=Ht(t.title),i=n.filter(d=>d.slug!==t.slug&&Ht(d.title)===s&&vr(d.content)!==vr(t.content)).map(d=>d.slug),a=ma(t),c=[];o<r.policy.autoApproveThreshold&&c.push(`confidence:${o.toFixed(2)}`),a&&o<r.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:u,requiresReview:i.length>0||o<r.policy.autoApproveThreshold||a&&o<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(t,n){let r=await this.assess(t,n);return this.mutate(o=>{let s=o.reviews.find(c=>c.sourceKey===t.sourceKey&&c.digest===t.digest);if(s?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(s)};if(s?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(s)};if(!r.requiresReview)return this.audit(o,"knowledge:auto-approved","system",{sourceKey:t.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(s?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(s)};let i=new Date().toISOString(),a={id:hr(),sourceKey:t.sourceKey,sourceType:t.sourceType,slug:t.slug,marker:t.marker,digest:t.digest,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...new Set([...t.tags,t.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};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:r,review:structuredClone(a)}})}async markApplied(t,n){await this.mutate(r=>{let o=r.reviews.find(s=>s.sourceKey===t&&s.digest===n&&s.status==="approved");o&&(o.appliedAt=new Date().toISOString(),o.updatedAt=o.appliedAt,this.audit(r,"knowledge:applied",o.reviewedBy??"system",{reviewId:o.id,sourceKey:t}))})}async decide(t,n,r){return this.mutate(async o=>{let s=o.reviews.find(u=>u.id===t);if(!s)throw new I(`Governance review not found: ${t}`,404);if(s.status!=="pending")throw new I("Governance review is already resolved",409);let i=new Date().toISOString();if(s.reviewedAt=i,s.reviewedBy=n.principal,s.updatedAt=i,n.note?.trim()&&(s.reviewNote=n.note.trim()),n.action==="reject")return s.status="rejected",this.audit(o,"knowledge:rejected",n.principal,{reviewId:t,sourceKey:s.sourceKey}),structuredClone(s);if(n.action==="supersede")return s.status="superseded",n.targetReviewId&&(s.supersededBy=n.targetReviewId),this.audit(o,"knowledge:superseded",n.principal,{reviewId:t,sourceKey:s.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(s);if(n.action==="merge"){if(!n.targetReviewId)throw new I("targetReviewId is required for merge",400);let u=o.reviews.find(d=>d.id===n.targetReviewId);if(!u)throw new I("Merge target review not found",404);return s.status="superseded",s.mergedInto=u.id,this.audit(o,"knowledge:merged",n.principal,{reviewId:t,sourceKey:s.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(s)}s.status="approved";let c=(await r.listPages()).find(u=>u.slug===s.slug);if(c&&!c.tags.includes(s.marker))throw new I(`Wiki page '${s.slug}' is manually managed`,409);return c?await r.updatePage(s.slug,{title:s.title,summary:s.summary??"",content:s.content,tags:s.tags}):await r.createPage({slug:s.slug,title:s.title,...s.summary?{summary:s.summary}:{},content:s.content,tags:s.tags}),s.appliedAt=i,this.audit(o,"knowledge:approved",n.principal,{reviewId:t,sourceKey:s.sourceKey}),structuredClone(s)})}async quality(t){let n=await this.ensureState(),r=await t.listPages(),o=Date.now(),s=n.policy.staleAfterDays*864e5,i=r.map(d=>{let l=o-Date.parse(d.updatedAt);return{slug:d.slug,title:d.title,updatedAt:d.updatedAt,ageDays:Math.max(0,Math.floor(l/864e5)),stale:Number.isFinite(l)&&l>s}}).filter(d=>d.stale).map(({stale:d,...l})=>l),a=new Map;for(let d of r){let l=Ht(d.title),p=a.get(l)??[];p.push(d),a.set(l,p)}let c=[...a.entries()].filter(([,d])=>d.length>1).map(([d,l])=>({title:d,pages:l.map(p=>p.slug)})),u=n.reviews.filter(d=>d.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(d=>d.tags.some(l=>l.startsWith("toolnet-auto-"))).length,manualPages:r.filter(d=>!d.tags.some(l=>l.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(d=>d.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(d=>d.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var Tr="wiki/automation.v1.json",Er="toolnet.wiki-automation.v1",Yt=8e3,Cr=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function Ce(e){return ya("sha256").update(JSON.stringify(e)).digest("hex")}function xe(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function Ir(e){return Array.isArray(e)?e:[]}function Or(e){return typeof e!="string"?void 0:e.replace(/\s+/gu," ").trim()||void 0}function Gt(e){return Array.isArray(e)?e.map(Or).filter(t=>!!t):[]}function L(e,t){for(let n of t){let r=Or(e[n]);if(r)return r}}function Ie(e){let t=new Set,n=[];for(let r of e){let o=r.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function tt(e,t=0,n=""){if(t>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(Cr.has(r))return[];if(typeof e=="string"){let i=e.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(e))return e.flatMap(i=>tt(i,t+1,n));let o=xe(e);if(!o)return[];let s=[];for(let[i,a]of Object.entries(o)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();Cr.has(c)||s.push(...tt(a,t+1,i))}return s}function jr(e){let n=Ie(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(o=>tt(e[o],0,o)));return(n.length>0?n:Ie(tt(e))).join(`
|
|
29
|
+
|
|
30
|
+
`).slice(0,Yt)}function Ar(e,t){return L(e,["id","key","fingerprint","knowledgeId","sceneId"])??t}function Mr(e,t){return L(e,["title","name","topic","label","task","kind","type"])??t}function wa(e){return(L(e,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function ba(e){return(L(e,["kind","sceneKind","type"])??"").toLowerCase()}function xa(e){let t=xe(e);if(!t)return[];let n=[],r=Ir(t.knowledge);for(let[s,i]of r.entries()){let a=xe(i);if(!a)continue;let c=wa(a);if(c==="session"||c==="transient")continue;let u=jr(a);if(u.length<20)continue;let d=Ar(a,Ce(a).slice(0,16)),l=Mr(a,`Durable Memory ${s+1}`);n.push({sourceKey:`memory:${d}`,sourceType:"memory",title:l,summary:L(a,["summary","description"]),content:u,tags:Ie(["toolnet","auto","memory",...c?[c]:[]])})}let o=Ir(t.scenes);for(let[s,i]of o.entries()){let a=xe(i);if(!a)continue;let c=ba(a);if(c==="session-context")continue;let u=jr(a);if(u.length<20)continue;let d=Ar(a,Ce(a).slice(0,16)),l=Mr(a,`Knowledge Scene ${s+1}`);n.push({sourceKey:`scene:${d}`,sourceType:"scene",title:l,summary:L(a,["summary","description"]),content:u,tags:Ie(["toolnet","auto","scene",...c?[c]:[]])})}return n}function Ca(e){return Pr(e,".toolnet","memory","skills")}function Ia(e){let t=Ca(e);if(!ha(t))return{candidates:[],failed:0};let n=[],r=0,o=Sa(t).filter(s=>s.endsWith(".json")).sort();for(let s of o)try{let i=JSON.parse(ka(Pr(t,s),"utf8")),a=xe(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let c=L(a,["id","fingerprint"])??va(s,".json"),u=L(a,["task"])??"",d=L(a,["title"])||u||`Reusable Skill ${c.slice(0,8)}`,l=L(a,["summary"])??void 0,p=Gt(a.steps),f=Gt(a.verification),m=Gt(a.files),h=[];u&&h.push(`## Task
|
|
31
|
+
${u}`),l&&h.push(`## Summary
|
|
32
|
+
${l}`),p.length>0&&h.push(`## Procedure
|
|
33
|
+
${p.map((S,v)=>`${v+1}. ${S}`).join(`
|
|
34
|
+
`)}`),f.length>0&&h.push(`## Verification
|
|
35
|
+
${f.map(S=>`- ${S}`).join(`
|
|
36
|
+
`)}`),m.length>0&&h.push(`## Relevant Files
|
|
37
|
+
${m.map(S=>`- \`${S}\``).join(`
|
|
38
|
+
`)}`);let g=h.join(`
|
|
39
|
+
|
|
40
|
+
`).slice(0,Yt);if(g.length<20)continue;n.push({sourceKey:`skill:${c}`,sourceType:"skill",title:d,summary:l,content:g,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function Ut(e){let t=new Date().toISOString();return{schema:Er,version:1,projectId:e,entries:[],createdAt:t,updatedAt:t}}async function ja(e,t){let n=await e.getText(Tr);if(!n)return Ut(t);try{let r=JSON.parse(n);return r.schema!==Er||r.version!==1||r.projectId!==t||!Array.isArray(r.entries)?Ut(t):r}catch{return Ut(t)}}async function Aa(e,t){await e.put(Tr,JSON.stringify(t,null,2),"application/json")}function Ma(e){return`toolnet-auto-${Ce(e).slice(0,12)}`}function Pa(e){let t=te(e.title).slice(0,72),n=Ce(e.sourceKey).slice(0,10);return te(`auto-${e.sourceType}-${t}-${n}`)}function Ta(e){return[`> Auto-generated by ToolNet Knowledge Automation from ${e.sourceType==="skill"?"reusable Skill Memory":e.sourceType==="scene"?"semantic memory scene":"durable memory"}.`,"",e.content].join(`
|
|
41
|
+
`).slice(0,Yt)}function Ea(e){return Ce({sourceType:e.sourceType,title:e.title,summary:e.summary,content:e.content,tags:e.tags})}function Oa(e,t){return e.tags.includes(t)}async function Nr(e){let t=xa(e.hierarchy),n=Ia(e.project.rootPath),r=new Map;for(let f of[...t,...n.candidates])r.set(f.sourceKey,f);let o=[...r.values()].sort((f,m)=>f.sourceKey.localeCompare(m.sourceKey)),s={schema:"toolnet.wiki-automation-result.v1",scanned:t.length+n.candidates.length,eligible:o.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new Xe(new Ze(e.storage,e.project));await i.initialize();let a=new et(new Qe(e.storage,e.project));await a.initialize();let c=await ja(e.storage,e.project.id),u=await i.listPages(),d=new Map(u.map(f=>[f.slug,f])),l=new Map(c.entries.map(f=>[f.sourceKey,f]));for(let f of o)try{let m=Ma(f.sourceKey),h=Ea(f),g=l.get(f.sourceKey),S=g?.slug??Pa(f),v=d.get(S);if(v&&!Oa(v,m)){s.skipped+=1;continue}let x=Ie([...f.tags,m]),T=Ta(f),M=await a.gate({sourceKey:f.sourceKey,sourceType:f.sourceType,slug:S,marker:m,digest:h,title:f.title,...f.summary?{summary:f.summary}:{},content:T,tags:x},[...d.values()]);if(!M.allowed){M.mode==="pending-review"?s.reviewPending+=1:s.skipped+=1;continue}M.mode==="auto-approved"?s.autoApproved+=1:M.mode==="review-approved"&&(s.reviewApproved+=1),v?g?.digest!==h?(v=await i.updatePage(S,{title:f.title,summary:f.summary??"",content:T,tags:x}),d.set(v.slug,v),s.updated+=1,s.pages.push({sourceKey:f.sourceKey,sourceType:f.sourceType,slug:v.slug,action:"updated"})):(s.unchanged+=1,s.pages.push({sourceKey:f.sourceKey,sourceType:f.sourceType,slug:S,action:"unchanged"})):(v=await i.createPage({slug:S,title:f.title,summary:f.summary,content:T,tags:x}),d.set(v.slug,v),s.created+=1,s.pages.push({sourceKey:f.sourceKey,sourceType:f.sourceType,slug:v.slug,action:"created"}));let E=new Date().toISOString(),C={sourceKey:f.sourceKey,sourceType:f.sourceType,slug:S,digest:h,marker:m,updatedAt:E},b=c.entries.findIndex(D=>D.sourceKey===f.sourceKey);b>=0?c.entries[b]=C:c.entries.push(C),l.set(f.sourceKey,C),await a.markApplied(f.sourceKey,h)}catch(m){if(m instanceof I&&m.statusCode===409){s.skipped+=1;continue}s.failed+=1}let p=new Date().toISOString();return c.updatedAt=p,c.lastRunAt=p,c.entries.sort((f,m)=>f.sourceKey.localeCompare(m.sourceKey)),await Aa(e.storage,c),s}import{createHash as Na}from"node:crypto";import{chmodSync as _r,existsSync as Ra,mkdirSync as _a,readFileSync as Tp,readdirSync as Ep,renameSync as Ka,statSync as Op,writeFileSync as La}from"node:fs";import{join as Kr}from"node:path";var $a="toolnet.skill-memory.v1",Rr=5,Fa=16,Wa=24,Da=32;function za(e){return Na("sha256").update(e).digest("hex")}function Ae(e,t=Number.MAX_SAFE_INTEGER){let n=new Set,r=[];for(let o of e){let s=o.replace(/\s+/gu," ").trim();if(!s)continue;let i=s.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(s),r.length>=t))break}return r}function Xt(e,t=360){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:n.slice(0,Math.max(0,t-1)).trimEnd()+"\u2026"}function qa(e){return e.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/giu,"Bearer [REDACTED]").replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu,"[REDACTED]").replace(/\b(api[_-]?key|token|password|passwd|secret)\b(\s*[:=]\s*)(["']?)[^\s"'`]+/giu,"$1$2[REDACTED]")}function q(e,t=360){return e&&Xt(qa(e),t)||void 0}function Me(e,t){for(let n of t){let r=e[n];if(typeof r=="string"&&r.trim())return r}}function Lr(e,t){for(let n of t){let r=e[n];if(typeof r=="number"&&Number.isFinite(r))return r;if(typeof r=="string"&&r.trim()&&Number.isFinite(Number(r)))return Number(r)}}function $r(e,t){for(let n of t){let r=e[n];if(typeof r=="boolean")return r;if(typeof r=="string"){let o=r.trim().toLowerCase();if(["true","yes","pass","passed","success","succeeded","ok"].includes(o))return!0;if(["false","no","fail","failed","error"].includes(o))return!1}}}function Fr(e){let t=e.data??{};if($r(t,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=Lr(t,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let o=Me(t,["status","result","outcome"]);return!!(o&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(o))}function je(e){let t=e.data??{};if(Fr(e))return!1;if($r(t,["passed","pass","success","succeeded","ok"])===!0||Lr(t,["exitCode","exit_code","code","statusCode"])===0)return!0;let o=Me(t,["status","result","outcome"]);return o&&/\b(pass(?:ed)?|success(?:ful)?|succeeded|ok|green|complete(?:d)?)\b/iu.test(o)?!0:e.type==="commit"||e.type==="deploy"}function Wr(e){let t=e.data??{},n=Me(t,["path","file","filePath","filename","target"]);if(n)return q(n,260);let r=e.provenance?.files;return q(r?.[0],260)}function Zt(e){return q(Me(e.data??{},["command","cmd","script"]),420)}function ae(e){return q(Me(e.data??{},["name","test","suite","title","message","text","result","status"]),300)}function Va(e){let t=[];for(let n of[...e].sort((r,o)=>r.sequence-o.sequence))if(je(n)){if(n.type==="test"){let r=ae(n)??Zt(n)??"Tests passed";t.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=ae(n);t.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=ae(n);t.push(r?`Deploy: ${r}`:"Deployment completed")}}return Ae(t,10)}function Ja(e,t){let n=[];for(let r of[...e].sort((o,s)=>o.sequence-s.sequence))switch(r.type){case"file_write":case"file_edit":{let o=Wr(r);o&&n.push(`Update ${o}`);break}case"command":{if(Fr(r))break;let o=Zt(r);o&&n.push(`Run: ${o}`);break}case"test":{if(!je(r))break;let o=ae(r)??Zt(r)??"project tests";n.push(`Verify: ${o}`);break}case"commit":{if(!je(r))break;let o=ae(r);n.push(o?`Commit: ${o}`:"Commit verified changes");break}case"deploy":{if(!je(r))break;let o=ae(r);n.push(o?`Deploy: ${o}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of t.files.slice(0,8)){let o=q(r,260);o&&n.push(`Update ${o}`)}return Ae(n,Fa)}function Ba(e,t){let n=[...t.files];for(let r of e){let o=Wr(r);o&&n.push(o);for(let s of r.provenance?.files??[]){let i=q(s,260);i&&n.push(i)}}return Ae(n,Wa)}function Ha(e){return Ae(e.filter(t=>["file_write","file_edit","command","test","commit","deploy"].includes(t.type)).map(t=>t.id),Da)}function Ga(e){return e.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function Dr(e,t,n){if(t.length===0)return[];let r=Va(t),o=Ae(n.completed.map(m=>q(m,280)??""),Rr);if(!(o.length>0||t.some(m=>["test","commit","deploy"].includes(m.type)&&je(m))))return[];let i=q(n.task,280)??q(n.nextActions[0],280),a=o.length>0?o:i?[i]:[];if(a.length===0)return[];let c=Ja(t,n);if(c.length===0)return[];let u=Ba(t,n),d=Ha(t),l=Math.min(...t.map(m=>m.sequence)),p=Math.max(...t.map(m=>m.sequence)),f=Ga(t);return a.slice(0,Rr).map(m=>{let h=[`Reusable procedure learned from successful task: ${m}.`,u.length>0?`Files: ${u.slice(0,6).join(", ")}.`:"",r.length>0?`Verification: ${r.slice(0,4).join("; ")}.`:""].filter(Boolean),g=JSON.stringify({projectId:e.projectId,task:m,steps:c,verification:r,files:u}),S=za(g);return{schema:$a,version:1,id:`skill-${S.slice(0,24)}`,fingerprint:S,projectId:e.projectId,title:Xt(`SOP: ${m}`,180),task:m,summary:Xt(h.join(" "),900),steps:c,verification:r,files:u,source:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:l,lastSequence:p,eventIds:d},createdAt:f}})}function Ua(e){return Kr(e.rootPath,".toolnet","memory","skills")}function Ya(e){let t=Ua(e);return _a(t,{recursive:!0,mode:448}),_r(t,448),t}function zr(e,t){if(t.length===0)return{written:0,deduped:0,files:[]};let n=Ya(e),r=0,o=0,s=[];for(let i of t){if(i.projectId!==e.id)throw new Error(`Skill project mismatch: ${i.projectId} != ${e.id}`);let a=Kr(n,`${i.id}.json`);if(s.push(a),Ra(a)){o+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;La(c,JSON.stringify(i,null,2)+`
|
|
42
|
+
`,{encoding:"utf8",mode:384}),Ka(c,a),_r(a,384),r+=1}return{written:r,deduped:o,files:s}}function qr(e){return String(e).padStart(12,"0")}function Xa(e){return`projects/${e.projectId}/memory/learned`}var nt=class{constructor(t){this.storage=t}storage;async write(t,n,r){if(r.length===0||n.length===0)return null;let o=Math.min(...n.map(l=>l.sequence)),s=Math.max(...n.map(l=>l.sequence)),i={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,createdAt:new Date().toISOString(),firstSequence:o,lastSequence:s,candidateCount:r.length,candidates:r},a=JSON.stringify(i,null,2)+`
|
|
43
|
+
`,c=w(r.map(l=>l.fingerprint).sort().join("|")).slice(0,16),u=w(t.sessionKey).slice(0,12),d=[Xa(t),"batches",`${qr(o)}-${qr(s)}-${u}-${c}.json`].join("/");return await this.storage.exists(d)||await this.storage.put(d,a,"application/json"),d}};import{createHash as Za}from"node:crypto";function Vr(e){return String(e).padStart(12,"0")}function Jr(e){return Za("sha256").update(e).digest("hex")}function Qa(e){return`projects/${e.projectId}/memory/hierarchy`}var rt=class{constructor(t){this.storage=t}storage;async write(t,n,r){if(n.length===0||r.facts.length===0)return null;let o=Math.min(...n.map(d=>d.sequence)),s=Math.max(...n.map(d=>d.sequence)),i={schema:"toolnet.memory-hierarchy-batch.v1",version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,createdAt:new Date().toISOString(),firstSequence:o,lastSequence:s,hierarchy:r},a=Jr([...r.facts.map(d=>d.id),...r.knowledge.map(d=>d.id)].sort().join("|")).slice(0,16),c=Jr(t.sessionKey).slice(0,12),u=[Qa(t),"batches",`${Vr(o)}-${Vr(s)}-${c}-${a}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,`${JSON.stringify(i,null,2)}
|
|
44
|
+
`,"application/json"),u}};function sc(e,t){if(!tc(e))return{events:[],nextOffset:t};let n=oc(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let o=n-r,s=Buffer.alloc(o),i=nc(e,"r");try{rc(i,s,0,o,r)}finally{ec(i)}let a=s.toString("utf8"),c=a.lastIndexOf(`
|
|
45
45
|
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
46
|
-
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var
|
|
47
|
-
`))))}function
|
|
48
|
-
`).toLowerCase();return/\b(error|failed|failure|failing)\b/u.test(n)&&!/\b0\s+failed\b/u.test(n)?"failed":/\b(success|successful|completed|passed|green)\b/u.test(n)||/\b\d+\s+passed\b/u.test(n)?"passed":/\b(running|started|in[_ -]?progress)\b/u.test(n)?"running":"unknown"}function
|
|
49
|
-
`,a=
|
|
50
|
-
`)).slice(0,24),c=
|
|
51
|
-
`,"application/json"),
|
|
46
|
+
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var ot=class{constructor(t){this.options=t;this.journal=new nt(t.storage),this.hierarchyJournal=new rt(t.storage)}options;journal;hierarchyJournal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,o=sc(this.options.wal.eventsFile,r);if(o.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:o.nextOffset};let s=Ue(this.options.identity,o.events),i=s.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,o.events,i));let c=!1;s.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,o.events,s.hierarchy));let u=Dr(this.options.identity,o.events,s.state),d=zr(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",s.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",s.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",s.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",s.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",s.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",s.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",s.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",s.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",s.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",s.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",s.hierarchy.stats.knowledge),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.journal_written",c?1:0),this.options.wal.setSourceCursor("memory.skill.assets",u.length),this.options.wal.setSourceCursor("memory.skill.written",d.written),this.options.wal.setSourceCursor("memory.skill.deduped",d.deduped);try{let l=pr(this.options.project.rootPath,o.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",l.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",l.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",l.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",l.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let l=await Nr({project:this.options.project,storage:this.options.storage,hierarchy:s.hierarchy});this.options.wal.setSourceCursor("memory.wiki_automation.scanned",l.scanned),this.options.wal.setSourceCursor("memory.wiki_automation.eligible",l.eligible),this.options.wal.setSourceCursor("memory.wiki_automation.created",l.created),this.options.wal.setSourceCursor("memory.wiki_automation.updated",l.updated),this.options.wal.setSourceCursor("memory.wiki_automation.unchanged",l.unchanged),this.options.wal.setSourceCursor("memory.wiki_automation.skipped",l.skipped),this.options.wal.setSourceCursor("memory.wiki_automation.failed",l.failed),this.options.wal.setSourceCursor("memory.wiki_automation.review_pending",l.reviewPending),this.options.wal.setSourceCursor("memory.wiki_automation.auto_approved",l.autoApproved),this.options.wal.setSourceCursor("memory.wiki_automation.review_approved",l.reviewApproved)}catch{this.options.wal.setSourceCursor("memory.wiki_automation.failed",1)}return this.options.wal.setSourceCursor("memory.learner.offset",o.nextOffset),{scannedEvents:o.events.length,candidates:i.length,journalWritten:a,nextOffset:o.nextOffset}}};import{closeSync as bc,existsSync as xc,openSync as Cc,readSync as Ic,statSync as jc}from"node:fs";function Br(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function Te(e){return e.toLowerCase().replace(/[^a-z0-9]/gu,"")}function Pe(e,t,n=0){if(n>8)return;if(Array.isArray(e)){for(let o of e.slice(0,50))Pe(o,t,n+1);return}let r=Br(e);if(r)for(let[o,s]of Object.entries(r))t(o,s,r),Pe(s,t,n+1)}function ce(e,t){let n=[];return Pe(e,(r,o)=>{t.has(Te(r))&&typeof o=="string"&&o.trim()&&n.push(o.trim())}),n}function ic(e){let t=e.trim();if(!t.startsWith("{"))return null;try{return Br(JSON.parse(t))}catch{return null}}function ac(e){let t=e.data;for(let r of["tool","toolName","tool_name"]){let o=t[r];if(typeof o=="string"&&o.trim())return o.trim().toLowerCase()}let n="";return Pe(t,(r,o,s)=>{if(n)return;let i=Te(r);if(["tool","toolname"].includes(i)&&typeof o=="string"){n=o.trim().toLowerCase();return}if(i!=="name"||typeof o!="string")return;let a=typeof s.type=="string"?s.type.toLowerCase():"";(a.includes("tool")||a.includes("function")||a.includes("command"))&&(n=o.trim().toLowerCase())}),n}function cc(e){let t=ce(e.data,new Set(["command","cmd","script"])),n=ce(e.data,new Set(["arguments","args"]));for(let r of n){let o=ic(r);if(o)for(let s of ce(o,new Set(["command","cmd","script"])))t.push(s)}return Array.from(new Set(t.map(r=>r.trim()).filter(Boolean)))}function uc(e){let t=ce(e.data,new Set(["filepath","file_path","filename","file","path","target"].map(Te)));return Array.from(new Set(t.map(n=>n.trim()).filter(n=>n.length>0&&n.length<1e3&&!n.includes(`
|
|
47
|
+
`))))}function lc(e,t){return e.type==="file_edit"||e.type==="file_write"?"modified":/\b(delete|remove|unlink)\b/iu.test(t)?"deleted":/\b(create|add[_-]?file|new[_-]?file)\b/iu.test(t)?"created":/\b(edit|write|patch|apply[_-]?patch|replace|update[_-]?file)\b/iu.test(t)?"modified":null}function dc(e){let t=ce(e.data,new Set(["patch","diff","arguments","input"].map(Te))),n=[];for(let r of t){let o=[{regex:/^\*\*\* Update File:\s*(.+)$/gimu,action:"modified"},{regex:/^\*\*\* Add File:\s*(.+)$/gimu,action:"created"},{regex:/^\*\*\* Delete File:\s*(.+)$/gimu,action:"deleted"}];for(let s of o)for(let i of r.matchAll(s.regex)){let a=i[1]?.trim();a&&n.push({kind:"file",text:a,fileAction:s.action,confidence:.99})}}return n}function pc(e){let t=e.toLowerCase();return/\b(typecheck|type-check)\b/u.test(t)||/\btsc\b[\s\S]*--noemit\b/u.test(t)?"typecheck":/\b(eslint|lint)\b/u.test(t)?"lint":/\b(vitest|jest|pytest)\b/u.test(t)||/\bgo\s+test\b/u.test(t)||/\bcargo\s+test\b/u.test(t)||/\b(npm|pnpm|yarn)\s+(run\s+)?test\b/u.test(t)?"test":/\b(npm|pnpm|yarn)\s+(run\s+)?build\b/u.test(t)||/\bcargo\s+build\b/u.test(t)||/\bgo\s+build\b/u.test(t)||/\btsc\b/u.test(t)?"build":null}function fc(e){let t=null;return Pe(e,(n,r)=>{if(t===null&&["exitcode","code"].includes(Te(n))){if(typeof r=="number"&&Number.isFinite(r)){t=r;return}if(typeof r=="string"){let o=Number(r);Number.isFinite(o)&&(t=o)}}}),t}function mc(e){return ce(e,new Set(["status","state","result","output","outputsummary","message","text"]))}function gc(e){let t=fc(e.data);if(t!==null)return t===0?"passed":"failed";let n=mc(e.data).join(`
|
|
48
|
+
`).toLowerCase();return/\b(error|failed|failure|failing)\b/u.test(n)&&!/\b0\s+failed\b/u.test(n)?"failed":/\b(success|successful|completed|passed|green)\b/u.test(n)||/\b\d+\s+passed\b/u.test(n)?"passed":/\b(running|started|in[_ -]?progress)\b/u.test(n)?"running":"unknown"}function yc(e){let t=[],n=new Set;for(let r of e){let o=[r.kind,r.fileAction??"",r.checkKind??"",r.checkStatus??"",r.text].join("|");n.has(o)||(n.add(o),t.push(r))}return t}function Hr(e){let t=[],n=ac(e),r=lc(e,n);if(r)for(let o of uc(e))t.push({kind:"file",text:o,fileAction:r,confidence:e.type==="file_edit"||e.type==="file_write"?1:.96});t.push(...dc(e));for(let o of cc(e)){t.push({kind:"command",text:o,confidence:.98});let s=pc(o);s&&t.push({kind:"test",text:o,checkKind:s,checkStatus:gc(e),confidence:.98})}return yc(t)}var hc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function re(e){return e.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ur(e){return re(e).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function ne(e,t,n=0){if(!(n>6)){if(typeof e=="string"){t.push(e);return}if(Array.isArray(e)){for(let r of e.slice(0,50))ne(r,t,n+1);return}if(!(!e||typeof e!="object"))for(let[r,o]of Object.entries(e))(hc.has(r)||["data","payload","parts","messages"].includes(r))&&ne(o,t,n+1)}}function st(e){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(e)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(e)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(e)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(e)?"in_progress":"pending"}function Gr(e){let t=re(e);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(t)}function j(e,t,n,r,o={}){let s=re(r),i=o.key??Ur(s);return{version:1,id:w([e.projectId,n,i,t.id,s,o.status??"",o.fileAction??"",o.checkKind??"",o.checkStatus??"",o.order??""].join("|")).slice(0,32),projectId:e.projectId,kind:n,key:i,text:s,status:o.status,fileAction:o.fileAction,checkKind:o.checkKind,checkStatus:o.checkStatus,order:o.order,confidence:o.confidence??.85,occurredAt:t.timestamp,sequence:t.sequence,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventId:t.id,sourceEventId:t.sourceEventId}}function Sc(e,t,n){let r=re(n);if(r.length<5||r.length>1200)return[];let o=[],s=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&o.push(j(e,t,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&o.push(j(e,t,"plan",a[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,u;for(;!s&&(u=c.exec(r));){let p=Number(u[1]),f=re(u[2]??""),m=f&&!Gr(f)?`Phase ${p} - ${f}`:`Phase ${p}`;o.push(j(e,t,"phase",m,{key:`phase:${p}`,order:p,status:st(r),confidence:.93}))}let d=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);d?.[2]&&o.push(j(e,t,"task",d[2],{status:d[1].trim()?"completed":st(d[2]),confidence:.96}));let l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let p=l[1]?Number(l[1]):void 0,f=re(l[2]),m=Gr(f);o.push(j(e,t,"task",m&&p!==void 0?`TODO ${p}`:f,{key:p!==void 0?`task:${p}`:Ur(f),order:p,status:st(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let p=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");p&&o.push(j(e,t,"next_action",p,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&o.push(j(e,t,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&o.push(j(e,t,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&o.push(j(e,t,"decision",r,{confidence:.9})),r.length<=300&&/^(?:đang\s+(?:sửa|cập nhật|triển khai|xử lý|làm|refactor|fix)|(?:i(?:'m| am)\s+)?(?:working on|implementing|fixing|refactoring|updating|editing)\b)/iu.test(r)&&o.push(j(e,t,"activity",r,{confidence:.86})),o}function it(e,t){if(t.length===0)return[];let n=[],r=new Set;function o(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of t){if(i.type==="user_prompt"||i.role==="user"){let c=[];ne(i.data,c);let u=c.map(d=>re(d)).find(d=>d.length>=8&&d.length<=1200&&!/^\[?toolnet\b/iu.test(d));u&&o(j(e,i,"request",u,{confidence:.96}))}for(let c of Hr(i))o(j(e,i,c.kind,c.text,{fileAction:c.fileAction,checkKind:c.checkKind,checkStatus:c.checkStatus,status:c.kind==="test"?c.checkStatus==="passed"?"completed":c.checkStatus==="failed"?"blocked":c.checkStatus==="running"?"in_progress":"pending":void 0,confidence:c.confidence}));if(i.type==="decision"){let c=[];ne(i.data,c);for(let u of c)o(j(e,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];ne(i.data,c);for(let u of c)o(j(e,i,"task",u,{status:st(u),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let u=i.data[c];typeof u=="string"&&u&&o(j(e,i,"file",u,{fileAction:"modified",confidence:1}))}if(i.type==="test"){let c=[];ne(i.data,c);for(let u of c)o(j(e,i,"test",u,{confidence:1}))}let a=[];ne(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let d of Sc(e,i,u))o(d)}let s=t[t.length-1];return o(j(e,s,"session",`${e.agent}:${e.nativeSessionId}`,{key:e.sessionKey,confidence:1})),n}function Yr(e){return String(e).padStart(12,"0")}var at=class{constructor(t){this.storage=t}storage;async write(t,n){if(n.length===0)return null;let r=Math.min(...n.map(d=>d.sequence)),o=Math.max(...n.map(d=>d.sequence)),s={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,createdAt:n.map(d=>d.occurredAt).sort().at(-1)??new Date().toISOString(),firstSequence:r,lastSequence:o,observations:n},i=JSON.stringify(s,null,2)+`
|
|
49
|
+
`,a=w(n.map(d=>JSON.stringify(d)).sort().join(`
|
|
50
|
+
`)).slice(0,24),c=w(t.sessionKey).slice(0,12),u=[`projects/${t.projectId}`,"work","observations",`${Yr(r)}-${Yr(o)}-${c}-${a}.json`].join("/");return await this.storage.put(u,i,"application/json"),u}};import{join as Xr}from"node:path";import{mkdirSync as kc}from"node:fs";function Qr(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(e,t=20){let n=[],r=new Set;for(let o of e.slice().reverse()){let s=Qr(o);if(!(!s||r.has(s))&&(r.add(s),n.push(o),n.length>=t))break}return n.reverse()}function vc(e,t=20){let n=new Map;for(let r of e){let o=`${r.kind}|${Qr(r.command)}`;n.delete(o),n.set(o,r)}return Array.from(n.values()).slice(-t)}function wc(e){return e.kind==="phase"?/^Phase\s+\d+$/iu.test(e.text):e.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(e.text):!1}function Zr(e,t){let n=t.status??e?.status??"pending",r=n;e&&(e.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(e.status==="in_progress"||e.status==="blocked")&&(r=e.status));let o=e&&wc(t)?e.title:t.text;return{id:e?.id??w(t.key).slice(0,24),title:o,status:r,order:t.order??e?.order,confidence:Math.max(t.confidence,e?.confidence??0),updatedAt:t.occurredAt,updatedBy:{agent:t.agent,nativeSessionId:t.nativeSessionId,eventId:t.eventId}}}async function eo(e,t){let n=`projects/${e.id}/work/observations/`,r=await t.list(n),o=[];for(let s of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await t.getText(s.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&o.push(a)}catch{}}return o}async function Ee(e,t){let r=(await eo(e,t)).flatMap(y=>y.observations).sort((y,k)=>{let P=y.occurredAt.localeCompare(k.occurredAt);if(P!==0)return P;let V=y.sequence-k.sequence;return V!==0?V:y.id.localeCompare(k.id)}),o=new Map,s=new Map,i,a,c,u,d,l=[],p=[],f=[],m=[],h=[],g=new Map,S=[],v=[],x=[],T=[],M=[],E=[];for(let y of r)switch(y.kind){case"request":i=y.text;break;case"activity":a=y.text;break;case"goal":c=y.text;break;case"plan":u=y.text;break;case"phase":o.set(y.key,Zr(o.get(y.key),y));break;case"task":s.set(y.key,Zr(s.get(y.key),y));break;case"decision":l.push(y.text);break;case"blocker":p.push(y.text);break;case"warning":f.push(y.text);break;case"next_action":m.push(y.text);break;case"file":{h.push(y.text);let k=y.fileAction??"active";g.delete(y.text),g.set(y.text,k),k==="modified"?S.push(y.text):k==="created"?v.push(y.text):k==="deleted"&&x.push(y.text);break}case"command":T.push(y.text);break;case"test":M.push(y.text),y.checkKind&&E.push({kind:y.checkKind,command:y.text,status:y.checkStatus??"unknown",updatedAt:y.occurredAt,agent:y.agent,nativeSessionId:y.nativeSessionId});break;case"session":d={agent:y.agent,nativeSessionId:y.nativeSessionId,sessionKey:y.sessionKey,updatedAt:y.occurredAt};break}let C=Array.from(o.values()).sort((y,k)=>(y.order??Number.MAX_SAFE_INTEGER)-(k.order??Number.MAX_SAFE_INTEGER)),b=Array.from(s.values()).sort((y,k)=>(y.order??Number.MAX_SAFE_INTEGER)-(k.order??Number.MAX_SAFE_INTEGER)),D=C.find(y=>y.status==="in_progress")??C.find(y=>y.status==="blocked")??C.find(y=>y.status==="pending"),z=b.find(y=>y.status==="in_progress")??b.find(y=>y.status==="blocked")??b.find(y=>y.status==="pending"),It=$([...m,...z?[z.title]:[],...!z&&D?[D.title]:[],...b.filter(y=>y.status==="pending").slice(0,5).map(y=>y.title)],8),jt=$([...p,...C.filter(y=>y.status==="blocked").map(y=>y.title),...b.filter(y=>y.status==="blocked").map(y=>y.title)],20),pe={version:1,projectId:e.id,projectName:e.name,currentRequest:i,currentActivity:a,goal:c,plan:u,phases:C,tasks:b,decisions:$(l,20),blockers:jt,warnings:$(f,20),nextActions:It,filesTouched:$(h,30),activeFiles:Array.from(g.entries()).filter(([,y])=>y!=="deleted").map(([y])=>y).slice(-5),modifiedFiles:$(S,30),createdFiles:$(v,30),deletedFiles:$(x,30),commands:$(T,20),tests:$(M,20),checks:vc(E,20),currentPhase:D,currentTask:z,progress:{phasesTotal:C.length,phasesCompleted:C.filter(y=>y.status==="completed").length,tasksTotal:b.length,tasksCompleted:b.filter(y=>y.status==="completed").length,blocked:C.filter(y=>y.status==="blocked").length+b.filter(y=>y.status==="blocked").length},lastSession:d,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},_e=Xr(e.rootPath,".toolnet","work");return kc(_e,{recursive:!0}),O(Xr(_e,"current.json"),pe),await t.put(`projects/${e.id}/work/current.json`,JSON.stringify(pe,null,2)+`
|
|
51
|
+
`,"application/json"),pe}async function to(e,t){if((await eo(e,t)).length>0)return Ee(e,t);let r=await t.getText(`projects/${e.id}/work/current.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}function Ac(e,t){if(!xc(e))return{events:[],nextOffset:t};let n=jc(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let o=n-r,s=Buffer.alloc(o),i=Cc(e,"r");try{Ic(i,s,0,o,r)}finally{bc(i)}let a=s.toString("utf8"),c=a.lastIndexOf(`
|
|
52
52
|
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
53
|
-
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var
|
|
54
|
-
`,"application/json"),c}};import{mkdirSync as
|
|
55
|
-
`,"application/json"),f}function
|
|
53
|
+
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var ct=class{constructor(t){this.options=t;this.journal=new at(t.storage)}options;journal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["work.continuity.offset"]??0),r=Ac(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let o=it(this.options.identity,r.events),s=!1,i=!1;return o.length>0&&(s=!!await this.journal.write(this.options.identity,o),s&&(await Ee(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:o.length,journalWritten:s,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as Kc,existsSync as Lc,openSync as $c,readSync as Fc,statSync as Wc}from"node:fs";var Mc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function ue(e){return e.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Qt(e,t,n=0){if(!(n>6)){if(typeof e=="string"){t.push(e);return}if(Array.isArray(e)){for(let r of e.slice(0,50))Qt(r,t,n+1);return}if(!(!e||typeof e!="object"))for(let[r,o]of Object.entries(e))(Mc.has(r)||["data","payload","parts","messages"].includes(r))&&Qt(o,t,n+1)}}function R(e,t,n,r,o,s=.95){let i=ue(r);return{version:1,id:w([e.projectId,n,o.type,o.key??"",i.toLowerCase(),t.id].join("|")).slice(0,32),projectId:e.projectId,kind:n,value:i,scope:o.type,scopeKey:o.key,scopeOrder:o.order,confidence:s,evidence:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventId:t.id,sourceEventId:t.sourceEventId,sequence:t.sequence,occurredAt:t.timestamp}}}function F(e,t){let n=e.toLowerCase();for(let r of t){let o=r.toLowerCase();if(n.startsWith(`${o}:`)||n.startsWith(`${o} -`)||n.startsWith(`${o} \u2014`))return ue(e.slice(r.length+1))}return null}function Pc(e){let t=e.trimStart();return t.startsWith("- ")||t.startsWith("* ")||/^\d+[.)]\s+/u.test(t)}function Tc(e){return ue(e.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function no(e,t){let n=[],r=new Set;function o(s){!s.value||s.value.length<3||r.has(s.id)||(r.add(s.id),n.push(s))}for(let s of t){let i=[];Qt(s.data,i);for(let a of i){let c={type:"project"},u=null;for(let d of a.split(/\r?\n/u)){let l=ue(d);if(!l){u=null;continue}let p=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(p){let b=Number(p[1]);c={type:"phase",key:`phase:${b}`,order:b,title:ue(p[2]??"")},u=null;continue}let f=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let b=Number(f[1]);c={type:"task",key:`task:${b}`,order:b,title:ue(f[2]??"")},u=null;continue}let m=F(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(m){o(R(e,s,"mission",m,{type:"project"},.99)),u=null;continue}let h=F(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){o(R(e,s,c.type==="phase"?"phase_objective":"objective",h,c,.98)),u=null;continue}let g=F(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){o(R(e,s,c.type==="phase"?"phase_why":"why",g,c,.98)),u=null;continue}let S=F(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(S){o(R(e,s,"desired_outcome",S,{type:"project"},.98)),u=null;continue}let v=F(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(v){o(R(e,s,"plan_rationale",v,{type:"project"},.98)),u=null;continue}let x=F(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(x){o(R(e,s,"phase_deliverable",x,c,.97)),u=null;continue}let T=F(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(T){o(R(e,s,"acceptance_criterion",T,c,.98)),u="acceptance_criterion";continue}let M=F(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(M){o(R(e,s,"dependency",M,c,.97)),u="dependency";continue}let E=F(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(E){o(R(e,s,"open_question",E,c,.95)),u="open_question";continue}let C=F(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(C){o(R(e,s,"constraint",C,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){u="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){u="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){u="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){u="constraint";continue}if(u&&Pc(d)){o(R(e,s,u,Tc(d),c,.96));continue}u=null}}}return n}function ro(e){return String(e).padStart(12,"0")}var ut=class{constructor(t){this.storage=t}storage;async write(t,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.evidence.sequence)),o=Math.max(...n.map(u=>u.evidence.sequence)),s={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:r,lastSequence:o,createdAt:new Date().toISOString(),observations:n},i=w(n.map(u=>u.id).sort().join("|")).slice(0,16),a=w(t.sessionKey).slice(0,12),c=[`projects/${t.projectId}`,"work","semantic","observations",`${ro(r)}-${ro(o)}-${a}-${i}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,JSON.stringify(s,null,2)+`
|
|
54
|
+
`,"application/json"),c}};import{mkdirSync as Ec}from"node:fs";import{join as oo}from"node:path";function Oc(e){return{value:e.value,confidence:e.confidence,evidence:e.evidence}}function Nc(e,t){if(!t)return!0;let n=e.evidence.occurredAt.localeCompare(t.evidence.occurredAt);return n!==0?n>0:e.evidence.sessionKey===t.evidence.sessionKey?e.evidence.sequence>=t.evidence.sequence:e.confidence>=t.confidence}function G(e,t){return Nc(t,e)?t:e}function U(e,t=30){let n=new Set,r=[];for(let o of e){let s=o.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!s||n.has(s)||(n.add(s),r.push(o))}return r.slice(-t)}async function Rc(e,t){let n=`projects/${e.id}/work/semantic/observations/`,r=await t.list(n),o=[];for(let s of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await t.getText(s.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&o.push(a)}catch{}}return o}function _c(e){return{key:e.scopeKey??`phase:${e.scopeOrder??0}`,order:e.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function so(e,t){let r=(await Rc(e,t)).flatMap(h=>h.observations).sort((h,g)=>{let S=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return S!==0?S:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),o,s,i,a,c,u=new Map,d=[],l=[],p=[];for(let h of r){let g=Oc(h);if(h.scope==="phase"&&h.scopeKey){let S=u.get(h.scopeKey)??_c(h);switch(h.kind){case"phase_objective":S.objective=G(S.objective,g);break;case"phase_why":S.why=G(S.why,g);break;case"phase_deliverable":S.deliverable=G(S.deliverable,g);break;case"acceptance_criterion":S.acceptanceCriteria.push(g);break;case"dependency":S.dependencies.push(g);break;case"open_question":S.openQuestions.push(g);break;case"constraint":S.constraints.push(g);break;case"note":S.notes.push(g);break}u.set(S.key,S);continue}switch(h.kind){case"mission":o=G(o,g);break;case"objective":s=G(s,g);break;case"why":i=G(i,g);break;case"desired_outcome":a=G(a,g);break;case"plan_rationale":c=G(c,g);break;case"open_question":d.push(g);break;case"constraint":l.push(g);break;case"note":p.push(g);break}}for(let h of u.values())h.acceptanceCriteria=U(h.acceptanceCriteria,20),h.dependencies=U(h.dependencies,15),h.openQuestions=U(h.openQuestions,15),h.constraints=U(h.constraints,15),h.notes=U(h.notes,20);let f={version:1,projectId:e.id,projectName:e.name,mission:o,activeObjective:s,why:i,desiredOutcome:a,planRationale:c,phases:Array.from(u.values()).sort((h,g)=>h.order-g.order),openQuestions:U(d,20),constraints:U(l,20),notes:U(p,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},m=oo(e.rootPath,".toolnet","work");return Ec(m,{recursive:!0}),O(oo(m,"semantic-current.json"),f),await t.put(`projects/${e.id}/work/semantic/current.json`,JSON.stringify(f,null,2)+`
|
|
55
|
+
`,"application/json"),f}function Dc(e,t){if(!Lc(e))return{events:[],nextOffset:t};let n=Wc(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let o=Buffer.alloc(n-r),s=$c(e,"r");try{Fc(s,o,0,o.length,r)}finally{Kc(s)}let i=o.toString("utf8"),a=i.lastIndexOf(`
|
|
56
56
|
`);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
|
|
57
|
-
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var
|
|
57
|
+
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var lt=class{constructor(t){this.options=t;this.journal=new ut(t.storage)}options;journal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["work.semantic.offset"]??0),r=Dc(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let o=no(this.options.identity,r.events),s=!1,i=!1;return o.length>0&&(s=!!await this.journal.write(this.options.identity,o),s&&(await so(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:o.length,journalWritten:s,reconciled:i,nextOffset:r.nextOffset}}};import{existsSync as Ru,mkdirSync as _u}from"node:fs";import{join as tn}from"node:path";import{existsSync as co,mkdirSync as zc,readFileSync as qc,statSync as io,writeFileSync as Vc}from"node:fs";import{dirname as Jc,join as Bc}from"node:path";var ao=64*1024,Hc=`# ToolNet Project Operating Manual
|
|
58
58
|
|
|
59
59
|
This file contains persistent instructions for AI agents working on this project.
|
|
60
60
|
|
|
@@ -97,18 +97,18 @@ Things an AI agent should always remember.
|
|
|
97
97
|
<!--
|
|
98
98
|
- [advisory] Prefer small focused files.
|
|
99
99
|
-->
|
|
100
|
-
`;function
|
|
101
|
-
`,{encoding:"utf8"}),
|
|
102
|
-
`,{encoding:"utf8"}),
|
|
103
|
-
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function
|
|
104
|
-
`,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(
|
|
105
|
-
`,"application/json"),
|
|
106
|
-
`)}function
|
|
100
|
+
`;function uo(e){return Bc(e.rootPath,".toolnet","PROJECT.md")}function Gc(e){return e.normalize("NFKC").replace(/\s+/g," ").trim()}function Uc(e){let t=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,o;for(;o=r.exec(e);){let s=o[1].toLowerCase(),i=Gc(o[2]);if(!i)continue;let a=`${s}:${i.toLowerCase()}`;n.has(a)||(n.add(a),t.push({id:w(a).slice(0,24),mode:s,text:i,source:"manual"}))}return t}function Yc(e){let t=uo(e);return co(t)||(zc(Jc(t),{recursive:!0}),Vc(t,Hc,{encoding:"utf8",mode:384})),t}function lo(e,t=!1){let n=t?Yc(e):uo(e);if(!co(n))return null;if(io(n).size>ao)throw new Error(`PROJECT.md exceeds ${ao} bytes`);let o=qc(n,"utf8");return{path:n,content:o,digest:w(o),rules:Uc(o),bytes:Buffer.byteLength(o,"utf8"),updatedAt:new Date(io(n).mtimeMs).toISOString()}}import{randomUUID as Xc}from"node:crypto";import{closeSync as Zc,existsSync as po,fsyncSync as Qc,mkdirSync as eu,openSync as tu,readFileSync as nu,statSync as ru,unlinkSync as fo,writeFileSync as ou}from"node:fs";import{dirname as su,join as iu}from"node:path";var au=new Int32Array(new SharedArrayBuffer(4));function cu(e){e<=0||Atomics.wait(au,0,0,e)}function uu(e){return iu(e.rootPath,".toolnet","work",".current.lock")}function lu(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t?.code!=="ESRCH"}}function mo(e){if(!po(e))return null;try{let t=JSON.parse(nu(e,"utf8"));return t.version!==1||typeof t.token!="string"||typeof t.pid!="number"||typeof t.acquiredAt!="string"?null:{version:1,token:t.token,pid:t.pid,acquiredAt:t.acquiredAt}}catch{return null}}function du(e){try{return Date.now()-ru(e).mtimeMs}catch{return 0}}function pu(e,t){if(!po(e)||du(e)<t)return!1;let n=mo(e);return n?!lu(n.pid):!0}function fu(e,t){if(!pu(e,t))return!1;try{return fo(e),!0}catch{return!1}}function mu(e,t){let n={version:1,token:t,pid:process.pid,acquiredAt:new Date().toISOString()},r=tu(e,"wx",384);try{ou(r,`${JSON.stringify(n,null,2)}
|
|
101
|
+
`,{encoding:"utf8"}),Qc(r)}finally{Zc(r)}}function gu(e,t){if(mo(e)?.token===t)try{fo(e)}catch{}}function yu(e,t={}){let n=Math.max(100,t.timeoutMs??5e3),r=Math.max(5,t.retryMs??20),o=Math.max(n*2,t.staleMs??3e4),s=uu(e);eu(su(s),{recursive:!0});let i=Xc(),a=Date.now()+n;for(;;)try{mu(s,i);let c=!1;return()=>{c||(c=!0,gu(s,i))}}catch(c){if(c?.code!=="EEXIST")throw c;if(fu(s,o))continue;if(Date.now()>=a)throw new Error(`Timed out acquiring project work lock: ${s}`);cu(r)}}function go(e,t,n={}){let r=yu(e,n);try{return t()}finally{r()}}import{closeSync as hu,existsSync as Su,fsyncSync as ku,mkdirSync as vu,openSync as wu,readFileSync as bu,renameSync as xu,writeFileSync as Cu}from"node:fs";import{dirname as Iu,join as ju}from"node:path";function Au(e,t){vu(Iu(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`,r=wu(n,"w",384);try{Cu(r,`${JSON.stringify(t,null,2)}
|
|
102
|
+
`,{encoding:"utf8"}),ku(r)}finally{hu(r)}xu(n,e)}function wo(e){return ju(e.rootPath,".toolnet","work","current.json")}function en(e){let t=wo(e);if(!Su(t))return null;try{let n=JSON.parse(bu(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function dt(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function _(e,t,n){let r=[],o=new Set;for(let s of[...e,...t].reverse()){let i=dt(s);if(!(!i||o.has(i))&&(o.add(i),r.push(s),r.length>=n))break}return r.reverse()}function Mu(e,t,n=20){let r=new Map;for(let o of[...e,...t]){let s=`${o.kind}|${dt(o.command)}`;r.delete(s),r.set(s,o)}return Array.from(r.values()).slice(-n)}function Pu(e){return e.kind==="phase"?/^Phase\s+\d+$/iu.test(e.text):e.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(e.text):!1}function yo(e,t){let n=t.status??e?.status??"pending",r=n;e?.status==="completed"&&n!=="completed"&&(r="completed"),e&&n==="pending"&&(e.status==="in_progress"||e.status==="blocked")&&(r=e.status);let o=e&&Pu(t)?e.title:t.text;return{id:e?.id??t.id,title:o,status:r,order:t.order??e?.order,confidence:Math.max(e?.confidence??0,t.confidence),updatedAt:t.occurredAt,updatedBy:{agent:t.agent,nativeSessionId:t.nativeSessionId,eventId:t.eventId}}}function ho(e){let t=new Map;for(let n of e){let r=n.order!==void 0?`order:${n.order}`:dt(n.title);t.set(r,n)}return t}function So(e){return e.order!==void 0?`order:${e.order}`:dt(e.key||e.text)}function ko(e){return Array.from(e).sort((t,n)=>{let r=t.order??Number.MAX_SAFE_INTEGER,o=n.order??Number.MAX_SAFE_INTEGER;return r!==o?r-o:t.updatedAt.localeCompare(n.updatedAt)})}function vo(e){return e.find(t=>t.status==="in_progress")??e.find(t=>t.status==="blocked")??e.find(t=>t.status==="pending")}function Tu(e,t){let n=en(e),r=ho(n?.phases??[]),o=ho(n?.tasks??[]),s=n?.currentRequest,i=n?.currentActivity,a=n?.goal,c=n?.plan,u=n?.lastSession,d=[],l=[],p=[],f=[],m=[],h=[...n?.activeFiles??[]],g=[],S=[],v=[],x=[],T=[],M=[],E=[...t].sort((k,P)=>{let V=k.occurredAt.localeCompare(P.occurredAt);return V!==0?V:k.sequence-P.sequence});for(let k of E)switch(k.kind){case"request":s=k.text;break;case"activity":i=k.text;break;case"goal":a=k.text;break;case"plan":c=k.text;break;case"phase":{let P=So(k);r.set(P,yo(r.get(P),k));break}case"task":{let P=So(k);o.set(P,yo(o.get(P),k));break}case"decision":d.push(k.text);break;case"blocker":l.push(k.text);break;case"warning":p.push(k.text);break;case"next_action":f.push(k.text);break;case"file":{m.push(k.text);let P=k.fileAction??"active",V=h.indexOf(k.text);V>=0&&h.splice(V,1),P!=="deleted"&&h.push(k.text),P==="modified"?g.push(k.text):P==="created"?S.push(k.text):P==="deleted"&&v.push(k.text);break}case"command":x.push(k.text);break;case"test":T.push(k.text),k.checkKind&&M.push({kind:k.checkKind,command:k.text,status:k.checkStatus??"unknown",updatedAt:k.occurredAt,agent:k.agent,nativeSessionId:k.nativeSessionId});break;case"session":u={agent:k.agent,nativeSessionId:k.nativeSessionId,sessionKey:k.sessionKey,updatedAt:k.occurredAt};break}let C=ko(r.values()),b=ko(o.values()),D=vo(C),z=vo(b),It=_(n?.nextActions??[],[...f,...z?[z.title]:[],...!z&&D?[D.title]:[],...b.filter(k=>k.status==="pending").slice(0,5).map(k=>k.title)],8),jt=_(n?.blockers??[],[...l,...C.filter(k=>k.status==="blocked").map(k=>k.title),...b.filter(k=>k.status==="blocked").map(k=>k.title)],20),pe=E.length>0?E[E.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),_e={version:1,projectId:e.id,projectName:e.name,currentRequest:s,currentActivity:i,goal:a,plan:c,phases:C,tasks:b,decisions:_(n?.decisions??[],d,20),blockers:jt,warnings:_(n?.warnings??[],p,20),nextActions:It,filesTouched:_(n?.filesTouched??[],m,30),activeFiles:_([],h,5),modifiedFiles:_(n?.modifiedFiles??[],g,30),createdFiles:_(n?.createdFiles??[],S,30),deletedFiles:_(n?.deletedFiles??[],v,30),commands:_(n?.commands??[],x,20),tests:_(n?.tests??[],T,20),checks:Mu(n?.checks??[],M,20),currentPhase:D,currentTask:z,progress:{phasesTotal:C.length,phasesCompleted:C.filter(k=>k.status==="completed").length,tasksTotal:b.length,tasksCompleted:b.filter(k=>k.status==="completed").length,blocked:C.filter(k=>k.status==="blocked").length+b.filter(k=>k.status==="blocked").length},lastSession:u,updatedAt:pe},y=fe(_e);return Au(wo(e),y),y}function bo(e,t){return go(e,()=>Tu(e,t))}function A(e,t){let n=new Set,r=[];for(let o of e){let s=o.replace(/\s+/g," ").trim();if(!s)continue;let i=s.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(s),r.length>=t))break}return r}function xo(e){if(e)return{id:e.id,title:e.title,status:e.status}}function Eu(e,t=[]){let n=t.slice(-10);if(n.some(o=>o.status==="failed"))return"failing";if(n.some(o=>o.status==="passed"))return"passing";let r=e.slice(-10).join(`
|
|
103
|
+
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function Ou(e){return w(JSON.stringify(e))}function Nu(e){let t=[];for(let n of e){if(!n)continue;let r=n.match(/https?:\/\/[^\s<>"'`)\]}]+/giu)??[];for(let o of r){let s=o.replace(/[.,;:!?]+$/gu,"").trim();s&&t.push(s)}}return A(t,30)}function Co(e){let{project:t,identity:n,state:r}=e,o=r.activeFiles?.at(-1)??r.filesTouched.at(-1),s=r.phases.filter(v=>v.status==="completed").map(v=>v.title),i=r.tasks.filter(v=>v.status==="completed").map(v=>v.title),a=r.phases.filter(v=>v.status!=="completed"&&v.status!=="cancelled").map(v=>v.title),c=r.tasks.filter(v=>v.status!=="completed"&&v.status!=="cancelled").map(v=>v.title),u=new Set(r.tasks.filter(v=>v.status==="completed").map(v=>v.title.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),d=A(r.nextActions.filter(v=>!u.has(v.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),10),l=A([...c,...d],15),p=A(r.tests.slice().reverse(),10),f=A([...(r.activeFiles??[]).slice().reverse(),...r.filesTouched.slice().reverse()],20),m={schema:"toolnet.handoff.v2",version:2,project:{id:t.id,name:t.name},source:{agent:n.agent,nativeSessionId:n.nativeSessionId,sessionKey:n.sessionKey,sequence:e.sequence,reason:e.reason},capturedAt:e.capturedAt??new Date().toISOString(),goal:r.goal,request:r.currentRequest,activity:r.currentActivity,current:{phase:xo(r.currentPhase),task:xo(r.currentTask),file:o},completed:{phases:A(s,20),tasks:A(i,30)},remaining:{phases:A(a,20),tasks:A(c,30),todos:l},nextAction:d[0],blockers:A(r.blockers.slice().reverse(),10),decisions:A(r.decisions.slice().reverse(),10),files:{current:o,recent:f,active:A(r.activeFiles??[],10),modified:A(r.modifiedFiles??[],20),created:A(r.createdFiles??[],20),deleted:A(r.deletedFiles??[],20)},tests:{status:Eu(r.tests,r.checks),recent:p,checks:(r.checks??[]).slice(-10).map(v=>({kind:v.kind,status:v.status,command:v.command}))},evidence:{commands:A((r.commands??[]).slice().reverse(),20),references:Nu([r.currentRequest,r.currentActivity,r.goal,r.plan,...r.decisions,...r.blockers,...r.warnings,...r.nextActions,...r.filesTouched,...r.commands??[],...r.tests,...(r.checks??[]).map(v=>v.command)])},attention:A(e.attention??[],20),progress:r.progress},{capturedAt:h,source:g,...S}=m;return{...m,stateDigest:Ou(S)}}function Ku(e){return!!(e.currentRequest||e.currentActivity||e.goal||e.plan||e.phases.length>0||e.tasks.length>0||e.nextActions.length>0||e.blockers.length>0||e.decisions.length>0||e.filesTouched.length>0)}function Io(e,t,n,r,o){if(!Ku(n))return null;let s=lo(e,!1),a=[...s?s.rules.filter(l=>l.mode==="enforce").map(l=>l.text):[],...n.warnings].slice(0,20),c=Co({project:e,identity:t,state:n,reason:r,sequence:o,attention:a}),u=c.stateDigest;return{version:1,id:w([e.id,t.sessionKey,u].join("|")).slice(0,24),projectId:e.id,projectName:e.name,createdAt:new Date().toISOString(),reason:r,sourceSession:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,sequence:o},currentRequest:n.currentRequest,currentActivity:n.currentActivity,goal:n.goal,plan:n.plan,progress:n.progress,currentPhase:n.currentPhase,currentTask:n.currentTask,incompletePhases:n.phases.filter(l=>l.status!=="completed"&&l.status!=="cancelled"),incompleteTasks:n.tasks.filter(l=>l.status!=="completed"&&l.status!=="cancelled"),nextActions:c.remaining.todos.slice(0,10),blockers:n.blockers.slice(-10),decisions:n.decisions.slice(-10),warnings:n.warnings.slice(-10),attention:a,filesTouched:n.filesTouched.slice(-20),activeFiles:n.activeFiles?.slice(-10),modifiedFiles:n.modifiedFiles?.slice(-20),createdFiles:n.createdFiles?.slice(-20),deletedFiles:n.deletedFiles?.slice(-20),tests:n.tests.slice(-15),checks:n.checks?.slice(-10),stateDigest:u,continuity:c}}function jo(e,t){let n=tn(e.rootPath,".toolnet","work","handoffs");_u(n,{recursive:!0});let r=tn(n,`${t.id}.json`);Ru(r)||O(r,t),O(tn(e.rootPath,".toolnet","work","handoff-latest.json"),t)}function Ao(e){let t=Io(e.project,e.identity,e.state,e.reason,e.sequence);return t?(jo(e.project,t),t):null}var pt=class{constructor(t){this.options=t}options;async capture(t,n){let r=en(this.options.project);r||(r=await to(this.options.project,this.options.storage)),r||(r=await Ee(this.options.project,this.options.storage));let o=Io(this.options.project,this.options.identity,r,t,n);if(!o)return null;jo(this.options.project,o);let s=`projects/${this.options.project.id}/work/handoffs/${o.id}.json`;return await this.options.storage.exists(s)||await this.options.storage.put(s,JSON.stringify(o,null,2)+`
|
|
104
|
+
`,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(o,null,2)+`
|
|
105
|
+
`,"application/json"),o}};import{existsSync as Lu,readFileSync as $u,writeFileSync as Fu}from"node:fs";import{join as Wu}from"node:path";var Po="<!-- TOOLNET:STABLE-WORK:BEGIN -->",nn="<!-- TOOLNET:STABLE-WORK:END -->";function rn(e){switch(e.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function W(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${n}`)]:[]}function Mo(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${rn(n)} ${n.title}`)]:[]}function Du(e){let t=[Po,"# ToolNet Stable Work State","",`Updated: ${e.updatedAt}`];return e.lastSession&&t.push(`Last agent: ${e.lastSession.agent}`,`Last session: ${e.lastSession.nativeSessionId}`),e.currentRequest&&t.push("","Current request:",e.currentRequest),e.currentActivity&&t.push("","Current activity:",e.currentActivity),e.goal&&t.push("","Goal:",e.goal),e.plan&&t.push("","Plan:",e.plan),e.currentPhase&&t.push("","Current phase:",`${rn(e.currentPhase)} ${e.currentPhase.title}`),e.currentTask&&t.push("","Current task:",`${rn(e.currentTask)} ${e.currentTask.title}`),t.push(...Mo("Phases",e.phases)),t.push(...Mo("TODO / Tasks",e.tasks)),t.push(...W("Next actions",e.nextActions)),t.push(...W("Blockers",e.blockers)),t.push(...W("Important decisions",e.decisions)),t.push(...W("Active files",e.activeFiles??[])),t.push(...W("Modified files",e.modifiedFiles??[])),t.push(...W("Created files",e.createdFiles??[])),t.push(...W("Deleted files",e.deletedFiles??[])),t.push(...W("Files touched",e.filesTouched)),t.push(...W("Recent commands",e.commands??[])),t.push(...W("Checks",(e.checks??[]).map(n=>`[${n.status}] ${n.kind}: ${n.command}`))),t.push("","Progress:",`- Phases: ${e.progress.phasesCompleted}/${e.progress.phasesTotal}`,`- Tasks: ${e.progress.tasksCompleted}/${e.progress.tasksTotal}`,`- Blocked: ${e.progress.blocked}`,"","Continuation:","- Resume current unfinished task.","- Never redo completed TODO/Phase unless explicitly requested.","- Ask ToolNet Memory for deeper history only when necessary.",nn),t.join(`
|
|
106
|
+
`)}function To(e,t){let n=Wu(e.rootPath,".toolnet","current.md"),r="";if(Lu(n))try{r=$u(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let o=Du(t),s=r.indexOf(Po),i=r.indexOf(nn),a;s>=0&&i>=s?a=[r.slice(0,s).trimEnd(),o,r.slice(i+nn.length).trimStart()].filter(Boolean).join(`
|
|
107
107
|
|
|
108
108
|
`):a=r.trim()?`${r.trim()}
|
|
109
109
|
|
|
110
|
-
${
|
|
111
|
-
`,{encoding:"utf8",mode:384})}import{existsSync as
|
|
112
|
-
`,{encoding:"utf8",mode:384}),Eu(n,e)}function lt(e,t){return[...e].filter(n=>n.kind===t).sort((n,r)=>{let s=n.occurredAt.localeCompare(r.occurredAt);return s!==0?s:n.sequence-r.sequence}).at(-1)}function js(e,t){let n=lt(t.observations,"file"),r=lt(t.observations,"next_action"),s=lt(t.observations,"blocker"),o=lt(t.observations,"decision"),i={version:1,projectId:e.id,agent:t.agent,nativeSessionId:t.nativeSessionId,updatedAt:t.workState.updatedAt,currentRequest:t.workState.currentRequest,currentActivity:t.workState.currentActivity,currentTask:t.workState.currentTask?.title,currentPhase:t.workState.currentPhase?.title,lastTouchedFile:n?.text??t.workState.activeFiles?.at(-1)??t.workState.filesTouched.at(-1),latestNextAction:r?.text??t.workState.nextActions.at(-1),latestBlocker:s?.text??t.workState.blockers.at(-1),latestDecision:o?.text??t.workState.decisions.at(-1)};return Ku(_u(e),i),i}import{existsSync as As,mkdirSync as Lu,readFileSync as $u}from"node:fs";import{join as en}from"node:path";function Ms(e){return en(e.rootPath,".toolnet","memory","checkpoints")}function Ps(e){return en(Ms(e),"latest.json")}function Fu(e){let t=Ps(e);if(!As(t))return null;try{let n=JSON.parse($u(t,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==e.id?null:n}catch{return null}}function Wu(e){return["rule","architecture","decision","fix"].includes(e)}function Du(e,t){return t.length===0?[]:Ve(e,t).candidates.filter(r=>Wu(r.kind)&&r.knowledgeClass!=="transient"&&r.importanceScore>=.65).map(r=>({fingerprint:r.fingerprint,kind:r.kind,content:r.content,knowledgeClass:r.knowledgeClass,importanceScore:r.importanceScore,confidence:r.confidence,createdAt:r.createdAt,agent:e.agent,nativeSessionId:e.nativeSessionId}))}function zu(e,t){let n=new Map;for(let r of[...e,...t]){let s=n.get(r.fingerprint);(!s||r.importanceScore>s.importanceScore)&&n.set(r.fingerprint,r)}return Array.from(n.values()).sort((r,s)=>s.importanceScore-r.importanceScore||s.createdAt.localeCompare(r.createdAt)).slice(0,80)}function qu(e){return{request:e.currentRequest,activity:e.currentActivity,goal:e.goal,phase:e.currentPhase?{title:e.currentPhase.title,status:e.currentPhase.status}:void 0,task:e.currentTask?{title:e.currentTask.title,status:e.currentTask.status}:void 0,phases:e.phases.map(t=>({title:t.title,status:t.status})),tasks:e.tasks.map(t=>({title:t.title,status:t.status})),activeFiles:e.activeFiles??[],modifiedFiles:e.modifiedFiles??[],createdFiles:e.createdFiles??[],deletedFiles:e.deletedFiles??[],checks:e.checks??[],blockers:e.blockers,decisions:e.decisions,nextActions:e.nextActions}}function Ts(e,t,n,r){let s=Fu(e),o=zu(s?.durableFacts??[],Du(t,n)),i=n.at(-1)?.sequence??s?.source.sequence??0,a=r.phases.filter(y=>y.status==="completed").map(y=>y.title),c=r.tasks.filter(y=>y.status==="completed").map(y=>y.title),u=r.phases.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),d=r.tasks.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),l={work:qu(r),durableFacts:o.map(y=>y.fingerprint).sort()},p=v(JSON.stringify(l)).slice(0,32),f={schema:"toolnet.memory.checkpoint.v1",version:1,project:{id:e.id,name:e.name},source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,sequence:i},capturedAt:new Date().toISOString(),request:r.currentRequest,activity:r.currentActivity,goal:r.goal,current:{phase:r.currentPhase,task:r.currentTask},completed:{phases:a,tasks:c},remaining:{phases:u,tasks:d},files:{active:r.activeFiles??[],modified:r.modifiedFiles??[],created:r.createdFiles??[],deleted:r.deletedFiles??[]},checks:r.checks??[],blockers:r.blockers.slice(-10),decisions:r.decisions.slice(-15),nextActions:r.nextActions.slice(0,10),durableFacts:o,stateDigest:p},g=Ms(e);Lu(g,{recursive:!0,mode:448});let S=en(g,`${p}.json`);return As(S)||E(S,f),E(Ps(e),f),f}function Es(e,t,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=rt(t,n);if(r.length===0)return{updated:!1,observations:0};let s=hs(e,r);Is(e,s),js(e,{agent:t.agent,nativeSessionId:t.nativeSessionId,observations:r,workState:s});try{Ts(e,t,n,s)}catch{}try{bs({project:e,identity:t,state:s,reason:"continuous-checkpoint",sequence:n.at(-1)?.sequence??0})}catch{}return{updated:!0,observations:r.length}}var dt=class{identity;wal;remote;sanitizer=new Y;learner;continuity;semantic;handoff;project;title;metadata;constructor(t){this.project=t.project,this.identity=wn(t.project,t.agent,t.nativeSessionId),this.title=t.title,this.metadata=this.sanitizer.sanitizeValue(t.metadata??{}),this.wal=new qe(this.identity,t.eventContext),this.remote=new Le(t.storage,t.maxEventsPerChunk??100,t.maxChunkBytes??512*1024),this.learner=new tt({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.continuity=new ot({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.semantic=new at({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.handoff=new ut({project:t.project,storage:t.storage,identity:this.identity})}sanitizeEvent(t){let n=t.provenance?{...t.provenance,metadata:this.sanitizer.sanitizeValue(t.provenance.metadata)}:void 0;return{...t,data:this.sanitizer.sanitizeValue(t.data??{}),provenance:n}}checkpointLocal(t){if(t.length!==0)try{Es(this.project,this.identity,t)}catch{}}start(t={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:t,provenance:{source:this.identity.agent}})}record(t){let n=this.wal.append([this.sanitizeEvent(t)]);return this.checkpointLocal(n),n[0]}recordMany(t){let n=this.wal.append(t.map(r=>this.sanitizeEvent(r)));return this.checkpointLocal(n),n}setSourceCursor(t,n){this.wal.setSourceCursor(t,n)}async flush(){let t=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,t.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(t.events.length>0){let s=t.events[t.events.length-1];this.wal.markRemote(s.sequence,t.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&t.events.length>0)try{let s=t.events[t.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(t={}){return this.record({type:"session_idle",data:t,provenance:{source:this.identity.agent}}),this.flush()}async end(t={}){return this.record({type:"session_end",data:t,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{homedir as Bu}from"node:os";import{join as Os,resolve as pt}from"node:path";function tn(){let e=process.env.XDG_CONFIG_HOME??Os(Bu(),".config");return Os(e,"toolnet-memory","toolnet-cli-bindings.json")}function Ns(e){return e.endsWith(".json")?e.slice(0,-5):e}function Ju(){return{version:1,sessions:{}}}function nn(e){let t=Ke(e);if(!t)return Ju();if(t.version!==1||!t.sessions||typeof t.sessions!="object")throw new Error(`Invalid ToolNet CLI binding registry: ${e}`);return t}function rn(e){return pt(e.rootPath)}function sn(e,t,n={}){let r=Ns(t);if(!r)throw new Error("ToolNet CLI native session ID is required.");let s=n.bindingFile??tn(),o=nn(s),i=o.sessions[r],a=rn(e);if(i){if(i.projectId!==e.id||pt(i.projectRoot)!==a)throw new Error(`ToolNet CLI session ${r} is already bound to another project: ${i.projectRoot}`);return i}let c={nativeSessionId:r,projectId:e.id,projectRoot:a,boundAt:new Date().toISOString()};return o.sessions[r]=c,E(s,o),c}function on(e,t,n={}){let r=Ns(t),s=n.bindingFile??tn(),i=nn(s).sessions[r];if(!i)throw new Error(`ToolNet CLI session ${r} is not bound to this project. Run sync once with --bind.`);let a=rn(e);if(i.projectId!==e.id||pt(i.projectRoot)!==a)throw new Error(`ToolNet CLI session ${r} belongs to another project: ${i.projectRoot}`);return i}function Rs(e,t={}){let n=t.bindingFile??tn(),r=nn(n),s=rn(e);return Object.values(r.sessions).filter(o=>o.projectId===e.id&&pt(o.projectRoot)===s).sort((o,i)=>o.nativeSessionId.localeCompare(i.nativeSessionId))}function cn(){return process.env.TOOLNETCLI_SESSIONS_DIR?process.env.TOOLNETCLI_SESSIONS_DIR:process.env.TOOLNETAPI_SESSIONS_DIR?process.env.TOOLNETAPI_SESSIONS_DIR:process.env.DATA_DIR?an(process.env.DATA_DIR,"sessions"):an(Gu(),".toolnetcli","sessions")}function _s(e){return e.endsWith(".json")?e.slice(0,-5):e}function un(e,t=cn()){return an(t,`${_s(e)}.json`)}function Uu(e){return!e||typeof e!="object"||Array.isArray(e)?{}:e}function Yu(e){return Array.isArray(e)?e.filter(t=>!!t&&typeof t=="object"&&!Array.isArray(t)):[]}function ft(e){return typeof e=="string"?e:void 0}function Xu(e){if(typeof e!="string")return;let t=new Date(e);if(!Number.isNaN(t.getTime()))return t.toISOString()}function Qu(e,t,n){let r=v(_e({nativeSessionId:e,index:t,message:n})).slice(0,20);return`toolnet-cli:message:${t}:${r}`}function Zu(e,t,n,r,s){let o=ft(s.role),i="message";o==="user"&&(i="user_prompt"),o==="assistant"&&(i="assistant_message");let a={index:r,content:ft(s.content)??""};return s.tool_calls!==void 0&&(a.toolCalls=s.tool_calls),s.tool_call_id!==void 0&&(a.toolCallId=s.tool_call_id),s.name!==void 0&&(a.name=s.name),{type:i,timestamp:n,role:o,source:"toolnet-cli",sourceEventId:Qu(e,r,s),sourceSequence:r,data:a,provenance:{source:"toolnet-cli",sourcePath:t,sourceOffset:r,metadata:{nativeSessionId:e}}}}function el(e){if(!Vu(e))throw new Error(`ToolNet CLI session not found: ${e}`);let t;try{t=JSON.parse(Hu(e,"utf8"))}catch{throw new Error(`Invalid ToolNet CLI session JSON: ${e}`)}if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`Invalid ToolNet CLI session root: ${e}`);return t}async function mt(e){let t=_s(e.nativeSessionId);if(!t)throw new Error("ToolNet CLI native session ID is required.");e.bind?sn(e.project,t,{bindingFile:e.bindingFile}):on(e.project,t,{bindingFile:e.bindingFile}),e.bind?sn(e.project,e.nativeSessionId,{bindingFile:e.bindingFile}):on(e.project,e.nativeSessionId,{bindingFile:e.bindingFile});let n=un(t,e.sessionsDir),r=el(n),s=ft(r.sessionId);if(s&&s!==t)throw new Error(`ToolNet CLI session ID mismatch: requested=${t}, file=${s}`);let o=Yu(r.messages),i=Uu(r.metadata),a=Xu(r.updatedAt),c=new dt({project:e.project,storage:e.storage,agent:"toolnet-cli",nativeSessionId:t,title:ft(i.name),metadata:{nativeSource:"toolnet-cli-session-json",sourceFile:n,model:i.model,agentMode:i.agentMode},eventContext:{source:"toolnet-cli",cwd:e.project.rootPath}});c.status().lastSequence===0&&c.start({nativeSource:"toolnet-cli-session-json",sourceFile:n});let d="toolnet-cli.message-count",l=c.status().sourceCursors[d],p=Number(l),f=Number.isInteger(p)&&p>=0?p:0;f>o.length&&(f=0);let g=o.slice(f).map((h,k)=>Zu(t,n,a,f+k,h)),S=c.recordMany(g);if(c.setSourceCursor(d,o.length),e.localOnly){let h=c.status();return{nativeSessionId:t,sourceFile:n,importedMessages:g.length,recordedEvents:S.length,eventCount:h.lastSequence,durability:"local"}}e.idle?await c.idle({nativeSource:"toolnet-cli-session-json",sourceFile:n}):await c.flush();let y=c.status();return{nativeSessionId:t,sourceFile:n,importedMessages:g.length,recordedEvents:S.length,eventCount:y.lastSequence,durability:"remote"}}function nl(){return tl("sh",["-lc","command -v toolnet >/dev/null 2>&1"],{stdio:"ignore"}).status===0}function gt(e={}){let t=hn(),n=Ne({cwd:e.cwd}),r=cn(),s=ln(t),o=nl(),i=ln(n),a=ln(r),c=[];return s||c.push(`Config directory missing: ${t}`),o||c.push("ToolNet CLI binary not found (toolnet)"),{installed:s&&o,state:s?o?"installed":"missing-binary":"missing-config",mcp:{configured:i,configFile:n},nativeSource:{available:a,sessionsDir:r},capabilities:{...Ct},errors:c}}import{existsSync as rl}from"node:fs";async function yt(e){let t=Rs(e.project,{bindingFile:e.bindingFile}),n=[],r=0,s=0,o=0,i=0,a=0;for(let c of t){let u=c.nativeSessionId,d=un(u,e.sessionsDir);if(!rl(d)){s+=1,n.push({nativeSessionId:u,status:"missing"});continue}try{let l=await mt({project:e.project,storage:e.storage,nativeSessionId:u,sessionsDir:e.sessionsDir,bindingFile:e.bindingFile,localOnly:e.localOnly,idle:e.idle});r+=1,i+=l.importedMessages,a+=l.recordedEvents,n.push({nativeSessionId:u,status:"synced",result:l})}catch(l){o+=1,n.push({nativeSessionId:u,status:"error",error:l instanceof Error?l.message:String(l)})}}return{bound:t.length,synced:r,missing:s,failed:o,importedMessages:i,recordedEvents:a,sessions:n}}function Ks(e){let t=e.intervalMs&&e.intervalMs>=250?e.intervalMs:2e3,n=!0,r=!1,s=0,o=0,i=0,a=0,c=0,u,d;async function l(){if(r)return{bound:0,synced:0,missing:0,failed:0,importedMessages:0,recordedEvents:0,sessions:[]};r=!0,s+=1,u=new Date().toISOString();try{let p=await yt({project:e.project,storage:e.storage,sessionsDir:e.sessionsDir,bindingFile:e.bindingFile,localOnly:e.localOnly});return o+=1,a+=p.importedMessages,c+=p.recordedEvents,e.onSync?.(p),p}catch(p){i+=1;let f=p instanceof Error?p:new Error(String(p));throw e.onError?.(f),f}finally{r=!1}}return d=setInterval(()=>{!n||r||l().catch(()=>{})},t),{runOnce:l,stop(){n&&(n=!1,d&&(clearInterval(d),d=void 0))},status(){return{running:n,intervalMs:t,runs:s,successfulRuns:o,failedRuns:i,importedMessages:a,recordedEvents:c,lastRunAt:u}}}}import{createHash as sl}from"node:crypto";import{existsSync as dn,mkdirSync as ol,readFileSync as il,renameSync as al,writeFileSync as cl}from"node:fs";import{basename as ul,dirname as ht,join as St,parse as Fs,resolve as Te}from"node:path";var Ws=".toolnet",ll="project.json";function dl(e){return sl("sha256").update(e).digest("hex").slice(0,16)}function pn(e){return St(e,Ws,ll)}function pl(e){return dn(pn(e))}function fl(e,t){let n=Te(e),r=Fs(n).root;for(;;){if(pl(n))return n;if(n===r||t&&n===Te(t))break;let s=ht(n);if(s===n)break;n=s}return null}function ml(e){let t=Te(e),n=Fs(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>dn(St(t,o))))return t;if(t===n)break;let s=ht(t);if(s===t)break;t=s}return Te(e)}function gl(e){let t;try{t=JSON.parse(il(e,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${e}: ${s instanceof Error?s.message:String(s)}`)}if(!t||typeof t!="object")throw new Error(`Invalid ToolNet project manifest: ${e}`);let n=t;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${e}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${e}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:ht(ht(e)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function Ls(e,t){let n=St(e,Ws);ol(n,{recursive:!0});let r=pn(e),s=`${r}.tmp-${process.pid}`;cl(s,JSON.stringify(t,null,2)+`
|
|
113
|
-
`,{encoding:"utf8",mode:384}),
|
|
114
|
-
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(t){if(t=
|
|
110
|
+
${o}`:o,Fu(n,`${a.trim()}
|
|
111
|
+
`,{encoding:"utf8",mode:384})}import{existsSync as Tm,mkdirSync as zu,readFileSync as Em,renameSync as qu,writeFileSync as Vu}from"node:fs";import{dirname as Ju,join as Bu}from"node:path";function Hu(e){return Bu(e.rootPath,".toolnet","context","session-origin.json")}function Gu(e,t){zu(Ju(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;Vu(n,`${JSON.stringify(t,null,2)}
|
|
112
|
+
`,{encoding:"utf8",mode:384}),qu(n,e)}function ft(e,t){return[...e].filter(n=>n.kind===t).sort((n,r)=>{let o=n.occurredAt.localeCompare(r.occurredAt);return o!==0?o:n.sequence-r.sequence}).at(-1)}function Eo(e,t){let n=ft(t.observations,"file"),r=ft(t.observations,"next_action"),o=ft(t.observations,"blocker"),s=ft(t.observations,"decision"),i={version:1,projectId:e.id,agent:t.agent,nativeSessionId:t.nativeSessionId,updatedAt:t.workState.updatedAt,currentRequest:t.workState.currentRequest,currentActivity:t.workState.currentActivity,currentTask:t.workState.currentTask?.title,currentPhase:t.workState.currentPhase?.title,lastTouchedFile:n?.text??t.workState.activeFiles?.at(-1)??t.workState.filesTouched.at(-1),latestNextAction:r?.text??t.workState.nextActions.at(-1),latestBlocker:o?.text??t.workState.blockers.at(-1),latestDecision:s?.text??t.workState.decisions.at(-1)};return Gu(Hu(e),i),i}import{existsSync as Oo,mkdirSync as Uu,readFileSync as Yu}from"node:fs";import{join as on}from"node:path";function No(e){return on(e.rootPath,".toolnet","memory","checkpoints")}function Ro(e){return on(No(e),"latest.json")}function Xu(e){let t=Ro(e);if(!Oo(t))return null;try{let n=JSON.parse(Yu(t,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==e.id?null:n}catch{return null}}function Zu(e){return["rule","architecture","decision","fix"].includes(e)}function Qu(e,t){return t.length===0?[]:Ue(e,t).candidates.filter(r=>Zu(r.kind)&&r.knowledgeClass!=="transient"&&r.importanceScore>=.65).map(r=>({fingerprint:r.fingerprint,kind:r.kind,content:r.content,knowledgeClass:r.knowledgeClass,importanceScore:r.importanceScore,confidence:r.confidence,createdAt:r.createdAt,agent:e.agent,nativeSessionId:e.nativeSessionId}))}function el(e,t){let n=new Map;for(let r of[...e,...t]){let o=n.get(r.fingerprint);(!o||r.importanceScore>o.importanceScore)&&n.set(r.fingerprint,r)}return Array.from(n.values()).sort((r,o)=>o.importanceScore-r.importanceScore||o.createdAt.localeCompare(r.createdAt)).slice(0,80)}function tl(e){return{request:e.currentRequest,activity:e.currentActivity,goal:e.goal,phase:e.currentPhase?{title:e.currentPhase.title,status:e.currentPhase.status}:void 0,task:e.currentTask?{title:e.currentTask.title,status:e.currentTask.status}:void 0,phases:e.phases.map(t=>({title:t.title,status:t.status})),tasks:e.tasks.map(t=>({title:t.title,status:t.status})),activeFiles:e.activeFiles??[],modifiedFiles:e.modifiedFiles??[],createdFiles:e.createdFiles??[],deletedFiles:e.deletedFiles??[],checks:e.checks??[],blockers:e.blockers,decisions:e.decisions,nextActions:e.nextActions}}function _o(e,t,n,r){let o=Xu(e),s=el(o?.durableFacts??[],Qu(t,n)),i=n.at(-1)?.sequence??o?.source.sequence??0,a=r.phases.filter(g=>g.status==="completed").map(g=>g.title),c=r.tasks.filter(g=>g.status==="completed").map(g=>g.title),u=r.phases.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),d=r.tasks.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),l={work:tl(r),durableFacts:s.map(g=>g.fingerprint).sort()},p=w(JSON.stringify(l)).slice(0,32),f={schema:"toolnet.memory.checkpoint.v1",version:1,project:{id:e.id,name:e.name},source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,sequence:i},capturedAt:new Date().toISOString(),request:r.currentRequest,activity:r.currentActivity,goal:r.goal,current:{phase:r.currentPhase,task:r.currentTask},completed:{phases:a,tasks:c},remaining:{phases:u,tasks:d},files:{active:r.activeFiles??[],modified:r.modifiedFiles??[],created:r.createdFiles??[],deleted:r.deletedFiles??[]},checks:r.checks??[],blockers:r.blockers.slice(-10),decisions:r.decisions.slice(-15),nextActions:r.nextActions.slice(0,10),durableFacts:s,stateDigest:p},m=No(e);Uu(m,{recursive:!0,mode:448});let h=on(m,`${p}.json`);return Oo(h)||O(h,f),O(Ro(e),f),f}function Ko(e,t,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=it(t,n);if(r.length===0)return{updated:!1,observations:0};let o=bo(e,r);To(e,o),Eo(e,{agent:t.agent,nativeSessionId:t.nativeSessionId,observations:r,workState:o});try{_o(e,t,n,o)}catch{}try{Ao({project:e,identity:t,state:o,reason:"continuous-checkpoint",sequence:n.at(-1)?.sequence??0})}catch{}return{updated:!0,observations:r.length}}var mt=class{identity;wal;remote;sanitizer=new J;learner;continuity;semantic;handoff;project;title;metadata;constructor(t){this.project=t.project,this.identity=In(t.project,t.agent,t.nativeSessionId),this.title=t.title,this.metadata=this.sanitizer.sanitizeValue(t.metadata??{}),this.wal=new Be(this.identity,t.eventContext),this.remote=new We(t.storage,t.maxEventsPerChunk??100,t.maxChunkBytes??512*1024),this.learner=new ot({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.continuity=new ct({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.semantic=new lt({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.handoff=new pt({project:t.project,storage:t.storage,identity:this.identity})}sanitizeEvent(t){let n=t.provenance?{...t.provenance,metadata:this.sanitizer.sanitizeValue(t.provenance.metadata)}:void 0;return{...t,data:this.sanitizer.sanitizeValue(t.data??{}),provenance:n}}checkpointLocal(t){if(t.length!==0)try{Ko(this.project,this.identity,t)}catch{}}start(t={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:t,provenance:{source:this.identity.agent}})}record(t){let n=this.wal.append([this.sanitizeEvent(t)]);return this.checkpointLocal(n),n[0]}recordMany(t){let n=this.wal.append(t.map(r=>this.sanitizeEvent(r)));return this.checkpointLocal(n),n}setSourceCursor(t,n){this.wal.setSourceCursor(t,n)}async flush(){let t=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,t.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(t.events.length>0){let o=t.events[t.events.length-1];this.wal.markRemote(o.sequence,t.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&t.events.length>0)try{let o=t.events[t.events.length-1],s=["session_idle","session_end","session_compact"].includes(o.type)?o.type:"checkpoint";await this.handoff.capture(s,o.sequence)}catch{}return r}async idle(t={}){return this.record({type:"session_idle",data:t,provenance:{source:this.identity.agent}}),this.flush()}async end(t={}){return this.record({type:"session_end",data:t,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{homedir as nl}from"node:os";import{join as Lo,resolve as gt}from"node:path";function sn(){let e=process.env.XDG_CONFIG_HOME??Lo(nl(),".config");return Lo(e,"toolnet-memory","toolnet-cli-bindings.json")}function $o(e){return e.endsWith(".json")?e.slice(0,-5):e}function rl(){return{version:1,sessions:{}}}function an(e){let t=Fe(e);if(!t)return rl();if(t.version!==1||!t.sessions||typeof t.sessions!="object")throw new Error(`Invalid ToolNet CLI binding registry: ${e}`);return t}function cn(e){return gt(e.rootPath)}function un(e,t,n={}){let r=$o(t);if(!r)throw new Error("ToolNet CLI native session ID is required.");let o=n.bindingFile??sn(),s=an(o),i=s.sessions[r],a=cn(e);if(i){if(i.projectId!==e.id||gt(i.projectRoot)!==a)throw new Error(`ToolNet CLI session ${r} is already bound to another project: ${i.projectRoot}`);return i}let c={nativeSessionId:r,projectId:e.id,projectRoot:a,boundAt:new Date().toISOString()};return s.sessions[r]=c,O(o,s),c}function ln(e,t,n={}){let r=$o(t),o=n.bindingFile??sn(),i=an(o).sessions[r];if(!i)throw new Error(`ToolNet CLI session ${r} is not bound to this project. Run sync once with --bind.`);let a=cn(e);if(i.projectId!==e.id||gt(i.projectRoot)!==a)throw new Error(`ToolNet CLI session ${r} belongs to another project: ${i.projectRoot}`);return i}function Fo(e,t={}){let n=t.bindingFile??sn(),r=an(n),o=cn(e);return Object.values(r.sessions).filter(s=>s.projectId===e.id&>(s.projectRoot)===o).sort((s,i)=>s.nativeSessionId.localeCompare(i.nativeSessionId))}function pn(){return process.env.TOOLNETCLI_SESSIONS_DIR?process.env.TOOLNETCLI_SESSIONS_DIR:process.env.TOOLNETAPI_SESSIONS_DIR?process.env.TOOLNETAPI_SESSIONS_DIR:process.env.DATA_DIR?dn(process.env.DATA_DIR,"sessions"):dn(il(),".toolnetcli","sessions")}function Wo(e){return e.endsWith(".json")?e.slice(0,-5):e}function fn(e,t=pn()){return dn(t,`${Wo(e)}.json`)}function al(e){return!e||typeof e!="object"||Array.isArray(e)?{}:e}function cl(e){return Array.isArray(e)?e.filter(t=>!!t&&typeof t=="object"&&!Array.isArray(t)):[]}function yt(e){return typeof e=="string"?e:void 0}function ul(e){if(typeof e!="string")return;let t=new Date(e);if(!Number.isNaN(t.getTime()))return t.toISOString()}function ll(e,t,n){let r=w($e({nativeSessionId:e,index:t,message:n})).slice(0,20);return`toolnet-cli:message:${t}:${r}`}function dl(e,t,n,r,o){let s=yt(o.role),i="message";s==="user"&&(i="user_prompt"),s==="assistant"&&(i="assistant_message");let a={index:r,content:yt(o.content)??""};return o.tool_calls!==void 0&&(a.toolCalls=o.tool_calls),o.tool_call_id!==void 0&&(a.toolCallId=o.tool_call_id),o.name!==void 0&&(a.name=o.name),{type:i,timestamp:n,role:s,source:"toolnet-cli",sourceEventId:ll(e,r,o),sourceSequence:r,data:a,provenance:{source:"toolnet-cli",sourcePath:t,sourceOffset:r,metadata:{nativeSessionId:e}}}}function pl(e){if(!ol(e))throw new Error(`ToolNet CLI session not found: ${e}`);let t;try{t=JSON.parse(sl(e,"utf8"))}catch{throw new Error(`Invalid ToolNet CLI session JSON: ${e}`)}if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`Invalid ToolNet CLI session root: ${e}`);return t}async function ht(e){let t=Wo(e.nativeSessionId);if(!t)throw new Error("ToolNet CLI native session ID is required.");e.bind?un(e.project,t,{bindingFile:e.bindingFile}):ln(e.project,t,{bindingFile:e.bindingFile}),e.bind?un(e.project,e.nativeSessionId,{bindingFile:e.bindingFile}):ln(e.project,e.nativeSessionId,{bindingFile:e.bindingFile});let n=fn(t,e.sessionsDir),r=pl(n),o=yt(r.sessionId);if(o&&o!==t)throw new Error(`ToolNet CLI session ID mismatch: requested=${t}, file=${o}`);let s=cl(r.messages),i=al(r.metadata),a=ul(r.updatedAt),c=new mt({project:e.project,storage:e.storage,agent:"toolnet-cli",nativeSessionId:t,title:yt(i.name),metadata:{nativeSource:"toolnet-cli-session-json",sourceFile:n,model:i.model,agentMode:i.agentMode},eventContext:{source:"toolnet-cli",cwd:e.project.rootPath}});c.status().lastSequence===0&&c.start({nativeSource:"toolnet-cli-session-json",sourceFile:n});let d="toolnet-cli.message-count",l=c.status().sourceCursors[d],p=Number(l),f=Number.isInteger(p)&&p>=0?p:0;f>s.length&&(f=0);let m=s.slice(f).map((S,v)=>dl(t,n,a,f+v,S)),h=c.recordMany(m);if(c.setSourceCursor(d,s.length),e.localOnly){let S=c.status();return{nativeSessionId:t,sourceFile:n,importedMessages:m.length,recordedEvents:h.length,eventCount:S.lastSequence,durability:"local"}}e.idle?await c.idle({nativeSource:"toolnet-cli-session-json",sourceFile:n}):await c.flush();let g=c.status();return{nativeSessionId:t,sourceFile:n,importedMessages:m.length,recordedEvents:h.length,eventCount:g.lastSequence,durability:"remote"}}function ml(){return fl("sh",["-lc","command -v toolnet >/dev/null 2>&1"],{stdio:"ignore"}).status===0}function St(e={}){let t=kn(),n=Ke({cwd:e.cwd}),r=pn(),o=mn(t),s=ml(),i=mn(n),a=mn(r),c=[];return o||c.push(`Config directory missing: ${t}`),s||c.push("ToolNet CLI binary not found (toolnet)"),{installed:o&&s,state:o?s?"installed":"missing-binary":"missing-config",mcp:{configured:i,configFile:n},nativeSource:{available:a,sessionsDir:r},capabilities:{...Mt},errors:c}}import{existsSync as gl}from"node:fs";async function kt(e){let t=Fo(e.project,{bindingFile:e.bindingFile}),n=[],r=0,o=0,s=0,i=0,a=0;for(let c of t){let u=c.nativeSessionId,d=fn(u,e.sessionsDir);if(!gl(d)){o+=1,n.push({nativeSessionId:u,status:"missing"});continue}try{let l=await ht({project:e.project,storage:e.storage,nativeSessionId:u,sessionsDir:e.sessionsDir,bindingFile:e.bindingFile,localOnly:e.localOnly,idle:e.idle});r+=1,i+=l.importedMessages,a+=l.recordedEvents,n.push({nativeSessionId:u,status:"synced",result:l})}catch(l){s+=1,n.push({nativeSessionId:u,status:"error",error:l instanceof Error?l.message:String(l)})}}return{bound:t.length,synced:r,missing:o,failed:s,importedMessages:i,recordedEvents:a,sessions:n}}function Do(e){let t=e.intervalMs&&e.intervalMs>=250?e.intervalMs:2e3,n=!0,r=!1,o=0,s=0,i=0,a=0,c=0,u,d;async function l(){if(r)return{bound:0,synced:0,missing:0,failed:0,importedMessages:0,recordedEvents:0,sessions:[]};r=!0,o+=1,u=new Date().toISOString();try{let p=await kt({project:e.project,storage:e.storage,sessionsDir:e.sessionsDir,bindingFile:e.bindingFile,localOnly:e.localOnly});return s+=1,a+=p.importedMessages,c+=p.recordedEvents,e.onSync?.(p),p}catch(p){i+=1;let f=p instanceof Error?p:new Error(String(p));throw e.onError?.(f),f}finally{r=!1}}return d=setInterval(()=>{!n||r||l().catch(()=>{})},t),{runOnce:l,stop(){n&&(n=!1,d&&(clearInterval(d),d=void 0))},status(){return{running:n,intervalMs:t,runs:o,successfulRuns:s,failedRuns:i,importedMessages:a,recordedEvents:c,lastRunAt:u}}}}import{createHash as yl}from"node:crypto";import{existsSync as vt,mkdirSync as hl,readFileSync as Sl,renameSync as kl,writeFileSync as vl}from"node:fs";import{basename as wl,dirname as wt,join as Oe,parse as Bo,resolve as le}from"node:path";var Ho=".toolnet",bl="project.json";function xl(e){return yl("sha256").update(e).digest("hex").slice(0,16)}function bt(e){return Oe(e,Ho,bl)}function Cl(e){return vt(bt(e))}function zo(e,t){let n=le(e),r=Bo(n).root;for(;;){if(Cl(n))return n;if(n===r||t&&n===le(t))break;let o=wt(n);if(o===n)break;n=o}return null}function qo(e){let t=le(e),n=Bo(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(s=>vt(Oe(t,s))))return t;if(t===n)break;let o=wt(t);if(o===t)break;t=o}return le(e)}function Vo(e){let t;try{t=JSON.parse(Sl(e,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${e}: ${o instanceof Error?o.message:String(o)}`)}if(!t||typeof t!="object")throw new Error(`Invalid ToolNet project manifest: ${e}`);let n=t;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${e}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${e}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:wt(wt(e)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function Jo(e,t){let n=Oe(e,Ho);hl(n,{recursive:!0});let r=bt(e),o=`${r}.tmp-${process.pid}`;vl(o,JSON.stringify(t,null,2)+`
|
|
113
|
+
`,{encoding:"utf8",mode:384}),kl(o,r)}function gn(e,t){return{id:e.id,name:e.name,remote:e.remote,rootPath:t,createdAt:e.createdAt,updatedAt:e.updatedAt,graphVersion:e.graphVersion,memoryVersion:e.memoryVersion,metadata:e.metadata}}var de=class{findExisting(t=process.cwd()){let n=le(t),r=qo(n),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>vt(Oe(r,c))),i=zo(n,s?r:void 0);if(!i)return null;let a=Vo(bt(i));return gn(a,i)}requireExisting(t=process.cwd()){let n=this.findExisting(t);if(!n)throw new Error("PROJECT_NOT_INITIALIZED");return n}detect(t=process.cwd()){let n=le(t),r=qo(n),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>vt(Oe(r,d))),i=zo(n,s?r:void 0);if(i){let d=bt(i),l=Vo(d);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),Jo(i,l)),gn(l,i)}let a=new Date().toISOString(),c=wl(r),u={version:1,id:xl(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return Jo(r,u),gn(u,r)}};import{homedir as Hl}from"node:os";import{join as Gl}from"node:path";import{DeleteObjectCommand as Il,GetObjectCommand as jl,HeadObjectCommand as Al,ListObjectsV2Command as Ml,PutObjectCommand as Pl,S3Client as Tl}from"@aws-sdk/client-s3";import{getSignedUrl as El}from"@aws-sdk/s3-request-presigner";var xt=class{name="huggingface";client;bucket;constructor(t){this.bucket=t.bucket,this.client=new Tl({region:"us-east-1",endpoint:`https://s3.hf.co/${t.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,n,r="application/octet-stream"){let o=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Pl({Bucket:this.bucket,Key:t,Body:o,ContentType:r}))}async get(t){let n=await El(this.client,new jl({Bucket:this.bucket,Key:t}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await this.client.send(new Al({Bucket:this.bucket,Key:t})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(t){await this.client.send(new Il({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let o=await this.client.send(new Ml({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let s of o.Contents??[])s.Key&&n.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return n}};import{access as Go,mkdir as Ol,readFile as Nl,readdir as Rl,rm as _l,stat as Uo,writeFile as Kl}from"node:fs/promises";import{dirname as Ll,join as $l,relative as Yo,resolve as Fl}from"node:path";var Ne=class{constructor(t){this.root=t}root;name="local";path(t){let n=t.replace(/^\/+/,"");return Fl(this.root,n)}async put(t,n){let r=this.path(t);await Ol(Ll(r),{recursive:!0}),await Kl(r,n)}async get(t){try{return await Nl(this.path(t))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await Go(this.path(t)),!0}catch{return!1}}async delete(t){await _l(this.path(t),{force:!0})}async list(t=""){let n=this.path(t),r=[];try{await Go(n)}catch{return r}let o=async i=>{let a=await Rl(i,{withFileTypes:!0});for(let c of a){let u=$l(i,c.name);if(c.isDirectory()){await o(u);continue}let d=await Uo(u);r.push({key:Yo(this.root,u),size:d.size,updatedAt:d.mtime.toISOString()})}},s=await Uo(n);return s.isDirectory()?await o(n):r.push({key:Yo(this.root,n),size:s.size,updatedAt:s.mtime.toISOString()}),r}};import{DeleteObjectCommand as Wl,GetObjectCommand as Dl,HeadObjectCommand as zl,ListObjectsV2Command as ql,PutObjectCommand as Vl,S3Client as Jl}from"@aws-sdk/client-s3";import{getSignedUrl as Bl}from"@aws-sdk/s3-request-presigner";var Re=class{name;client;bucket;constructor(t){this.name=t.name??"s3",this.bucket=t.bucket,this.client=new Jl({region:t.region??"us-east-1",endpoint:t.endpoint||void 0,forcePathStyle:t.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,n,r="application/octet-stream"){let o=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Vl({Bucket:this.bucket,Key:t,Body:o,ContentType:r}))}async get(t){let n=await Bl(this.client,new Dl({Bucket:this.bucket,Key:t}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await this.client.send(new zl({Bucket:this.bucket,Key:t})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(t){await this.client.send(new Wl({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let o=await this.client.send(new ql({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let s of o.Contents??[])s.Key&&n.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return n}};function yn(e,t){return console.warn(t),new Ne(e)}function Xo(e){let t=e.localRoot??Gl(Hl(),".toolnet-memory","storage");if(e.provider==="r2"){let n=e.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Re({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):yn(t,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(e.provider==="s3"){let n=e.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new Re({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):yn(t,"[storage] S3 credentials missing. Using local fallback.")}if(e.provider==="huggingface"){let n=e.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new xt({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):yn(t,"[storage] Hugging Face credentials missing. Using local fallback.")}return new Ne(t)}function Ul(e){return new Promise(t=>setTimeout(t,e))}async function Zo(e,t={}){let n=Math.max(1,t.attempts??3),r=t.baseDelayMs??150,o=t.maxDelayMs??2e3,s;for(let i=1;i<=n;i++)try{return await e()}catch(a){if(s=a,i>=n)break;let c=Math.min(o,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await Ul(c+u)}throw s}var Yl=new Set(["put","get","getText","delete","list"]);function Qo(e,t={}){return new Proxy(e,{get(n,r){let o=Reflect.get(n,r,n);return typeof o!="function"?o:Yl.has(r)?(...s)=>Zo(()=>Promise.resolve(o.apply(n,s)),t):o.bind(n)}})}function es(e){let t=e.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!t||t==="."||t==="..")throw new Error("Invalid project storage folder");return t}function ts(e){let t=e.replace(/^\/+/,"");if(t.startsWith("memories/"))return"memory/records/"+t.slice(9);if(t.startsWith("vectors/"))return"memory/vectors/"+t.slice(8);if(t.startsWith("graph/"))return"code/graph/"+t.slice(6);let n=t.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=t.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=t.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let o=t.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=t.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=t.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:t))}var Ct=class{constructor(t,n,r,o){this.provider=t;this.name=t.name,this.projectId=n,this.projectName=r,this.folder=es(o??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let t=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,o=await this.provider.getText(t);if(o){let i;try{i=JSON.parse(o)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${t}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(t,JSON.stringify(s,null,2)+`
|
|
114
|
+
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(t){if(t=ts(t),t===this.sourcePrefix)return this.targetPrefix;if(t.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+t.slice(this.sourcePrefix.length);if(t===this.targetPrefix||t.startsWith(`${this.targetPrefix}/`))return t;if(t.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${t}`].join(" "));return t}async put(t,n,r){return await this.ensureRegistered(),this.provider.put(this.key(t),n,r)}async get(t){return await this.ensureRegistered(),this.provider.get(this.key(t))}async getText(t){return await this.ensureRegistered(),this.provider.getText(this.key(t))}async delete(t){return await this.ensureRegistered(),this.provider.delete(this.key(t))}async exists(t){return await this.ensureRegistered(),this.provider.exists(this.key(t))}async list(t){return await this.ensureRegistered(),this.provider.list(this.key(t))}};function Y(e,t){let n=e.indexOf(t);return n>=0?e[n+1]:void 0}function hn(e){let t=Ge(),n=Qo(Xo({provider:t.storage.provider,huggingface:t.storage.huggingface,localRoot:t.storage.localRoot}),{attempts:3});return new Ct(n,e.id,e.name,e.remote??e.name)}function Xl(){let e=St({cwd:process.cwd()});console.log("ToolNet CLI Integration"),console.log("======================="),console.log(""),console.log(`State : ${e.state}`),console.log(`MCP : ${e.mcp.configured?"ready":"missing"} \u2014 ${e.mcp.configFile}`),console.log(`Memory: ${e.capabilities.level}`),console.log(`Capture: ${e.capabilities.nativeCapture?"native":"not available"}`),console.log(`Native source: ${e.nativeSource.available?"available":"missing"} \u2014 ${e.nativeSource.sessionsDir}`);for(let t of e.errors)console.log(`Error : ${t}`);return console.log(""),e.installed}async function Zl(){let e=process.argv.slice(2),t=e[0],n=e.includes("--json");if(t==="watch-bound"){let a=Y(e,"--project")??process.cwd(),c=new de().detect(a),u=hn(c),d=Y(e,"--interval-ms"),l=d!==void 0?Number(d):void 0,p=Number.isFinite(l)&&l!==void 0?l:void 0,f=Do({project:c,storage:u,sessionsDir:Y(e,"--sessions-dir"),localOnly:e.includes("--local-only"),intervalMs:p,onSync(g){g.importedMessages===0&&g.recordedEvents===0&&g.failed===0||console.log(JSON.stringify({event:"toolnet-cli-bound-sync",...g},null,2))},onError(g){console.error(`ToolNet CLI watcher error: ${g.message}`)}}),m=await f.runOnce();console.log(JSON.stringify({event:"toolnet-cli-watcher-started",first:m,watcher:f.status()},null,2));let h=()=>{f.stop(),console.log(JSON.stringify({event:"toolnet-cli-watcher-stopped",watcher:f.status()},null,2))};process.once("SIGINT",h),process.once("SIGTERM",h);return}if(t==="sync-bound"){let a=Y(e,"--project")??process.cwd(),c=new de().detect(a),u=hn(c),d=await kt({project:c,storage:u,sessionsDir:Y(e,"--sessions-dir"),localOnly:e.includes("--local-only"),idle:e.includes("--idle")});console.log(JSON.stringify(d,null,2)),d.failed>0&&(process.exitCode=1);return}if(t==="sync"){let a=e[1];if(!a)throw new Error("Usage: toolnet-memory integrate:toolnet-cli sync <session-id> --bind [--project PATH]");let c=Y(e,"--project")??process.cwd(),u=new de().detect(c),d=hn(u),l=await ht({project:u,storage:d,nativeSessionId:a,sessionsDir:Y(e,"--sessions-dir"),localOnly:e.includes("--local-only"),idle:e.includes("--idle"),bind:e.includes("--bind"),bindingFile:Y(e,"--binding-file")});console.log(JSON.stringify(l,null,2));return}if(e.includes("--status")||e[0]==="status"){let a=St({cwd:process.cwd()});n?console.log(JSON.stringify(a,null,2)):Xl(),a.installed||(process.exitCode=1);return}let o=e.includes("--force"),s=wn({force:o,cwd:process.cwd()}),i=St({cwd:process.cwd()});if(!i.installed)throw new Error(`ToolNet CLI integration installation did not verify successfully (state=${i.state}).`);if(n){console.log(JSON.stringify({installed:!0,changed:s.changed,files:s.files,status:i},null,2));return}console.log(`ToolNet CLI MCP: ${s.mcp.configured?"configured":"not configured"}`),console.log(`Memory: ${i.capabilities.level}`),console.log(`Native source: ${i.nativeSource.available?"available":"missing"}`),s.changed?console.log(`Config updated: ${s.mcp.configFile}`):console.log("Config unchanged (already configured)"),console.log(""),console.log("ToolNet CLI integration ready.")}Zl().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});
|