toolnet-memory 0.3.9 → 0.3.11

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.
@@ -0,0 +1,206 @@
1
+ import*as F from"fs";import*as N from"path";function dt(e){return e?Math.ceil(e.length/3.5):0}function pt(e,t){if(!e)return"";if(dt(e)<=t)return e;let r=Math.floor(t*3.5),s=e.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
2
+ `),a=Math.max(o,i);return a>r*.7?s.slice(0,a+1):s}function Xt(e,t){if(!e)return"";let n=e.split(`
3
+ `).filter(o=>o.trim());if(n.length<=t)return e;let r=n.slice(0,t),s=n.length-t;return[...r,`... (${s} more items omitted)`].join(`
4
+ `)}function Fs(e,t){let{maxTokens:n,trimMarker:r="[Context trimmed by ToolNet Memory token budget]"}=t;if(e.length===0)return"";let s=[...e].sort((c,u)=>u.priority-c.priority),o=[],i=0,a=!1;for(let c of s){let u=`# ${c.title}
5
+
6
+ `,m=dt(u),p=dt(c.content),d=m+p;if(i+d<=n)o.push(u+c.content),i+=d;else{let l=n-i-m;if(l>50){let g=pt(c.content,l);o.push(u+g),i=n,a=!0}else a=!0;break}}return a&&o.push(`
7
+ ${r}
8
+ `),o.join(`
9
+
10
+ ---
11
+
12
+ `)}function Qt(e,t){let n=[{title:"Profile",content:Xt(e,10),priority:100},{title:"Current Work",content:Xt(t,15),priority:90}];return Fs(n,{maxTokens:800})}import{createHash as Ws}from"node:crypto";import{chmodSync as en,existsSync as Ls,mkdirSync as Ds,readFileSync as zs,renameSync as qs,writeFileSync as tn}from"node:fs";import{dirname as nn,join as Ce}from"node:path";var gt="toolnet.context-offload.v1",Hs="toolnet.context-offload-asset.v1",Js=256,Vs=new Set(["tool_call","tool_result","file_read","file_write","file_edit","command","test","artifact"]);function rn(e){return Ce(e,".toolnet","offload")}function Bs(e){return Ce(rn(e),"assets")}function sn(e){return Ce(rn(e),"graph.json")}function on(e){Ds(e,{recursive:!0,mode:448});try{en(e,448)}catch{}}function Gs(e,t){on(nn(e));let n=`${e}.${process.pid}.${Date.now()}.tmp`;tn(n,t,{encoding:"utf8",mode:384}),qs(n,e);try{en(e,384)}catch{}}function ft(e){return Array.isArray(e)?e.map(ft):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,ft(n)])):e}function Us(e){return Ws("sha256").update(JSON.stringify(ft(e)),"utf8").digest("hex")}function mt(){return{schema:gt,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function an(e){let t=sn(e);if(!Ls(t))return mt();try{let n=JSON.parse(zs(t,"utf8"));return n.schema!==gt||n.version!==1||!Array.isArray(n.nodes)?mt():n}catch{return mt()}}function Ys(e,t){Gs(sn(e),JSON.stringify(t,null,2)+`
13
+ `)}function Xs(e,t=260){if(typeof e!="string")return null;let n=e.replace(/\s+/gu," ").trim();return n?n.slice(0,t):null}function Qs(e){let t=[...e.provenance.files??[],e.provenance.sourcePath],n=[];for(let r of t){let s=Xs(r);if(!(!s||n.includes(s))&&(n.push(s),n.length===3))break}return n}function Zs(e){return`${e.agent}:${e.sourceEventId??e.id}`.replace(/\s+/gu," ").trim().slice(0,120)}function eo(e,t){on(nn(e));try{return tn(e,t,{encoding:"utf8",flag:"wx",mode:384}),!0}catch(n){if(n.code==="EEXIST")return!1;throw n}}function to(e,t){let n=e.nodes.find(s=>s.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:gt,version:1,updatedAt:new Date().toISOString(),nodes:[...e.nodes.filter(s=>s.id!==t.id),r].slice(-Js)}}function cn(e,t){let n=an(e),r=0,s=0,o=0,i=[];for(let a of t){if(!Vs.has(a.type))continue;r+=1;let c=Us({type:a.type,data:a.data}),u={schema:Hs,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}},m=JSON.stringify(u,null,2)+`
14
+ `;eo(Ce(Bs(e),`${c}.json`),m)?s+=1:o+=1,i.push(c),n=to(n,{id:c,kind:a.type,bytes:Buffer.byteLength(m,"utf8"),createdAt:a.timestamp,sourceRefs:[Zs(a)],files:Qs(a)})}return r>0&&Ys(e,n),{eligible:r,written:s,deduped:o,graphNodes:n.nodes.length,assetIds:i}}function Zt(e,t){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:n.slice(0,t-1).trimEnd()+"\u2026"}function un(e,t={}){let n=an(e);if(n.nodes.length===0)return"";let r=Math.max(1,Math.min(12,t.maxAssets??6)),s=Math.max(320,Math.min(2400,t.maxChars??900)),o=["[TOOLNET CONTEXT OFFLOAD GRAPH]","Large tool/file payloads stay outside prompt context.","Read only a needed asset with MCP context_offload_read."];for(let i of n.nodes.slice(-r).reverse()){let a=Zt(i.sourceRefs.at(-1)??"unknown",72),c=i.files.length>0?` files=${Zt(i.files.join(","),120)}`:"",u=`event:${a} --offloads--> asset:${i.id.slice(0,12)} kind=${i.kind} bytes=${i.bytes}${c}`;if([...o,u].join(`
15
+ `).length>s)break;o.push(u)}return o.join(`
16
+ `)}import{existsSync as dn,mkdirSync as co,readFileSync as pn,renameSync as uo,writeFileSync as lo}from"node:fs";import{dirname as po,join as mn}from"node:path";import{createHash as no}from"node:crypto";import{dirname as ro}from"node:path";import{mkdirSync as so,readFileSync as oo,renameSync as io,writeFileSync as ao}from"node:fs";function w(e){return no("sha256").update(e).digest("hex")}function yt(e){if(Array.isArray(e))return e.map(yt);if(e&&typeof e=="object"){let t=e,n={};for(let r of Object.keys(t).sort())n[r]=yt(t[r]);return n}return e}function Pe(e){return JSON.stringify(yt(e))}function ln(e){try{return JSON.parse(oo(e,"utf8"))}catch{return null}}function R(e,t){so(ro(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;ao(n,JSON.stringify(t,null,2)+`
17
+ `,{encoding:"utf8",mode:384}),io(n,e)}function fn(e){return mn(e.rootPath,".toolnet","context","handoff.md")}function gn(e){return mn(e.rootPath,".toolnet","context","handoff.json")}function yn(e,t){co(po(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;lo(n,t.endsWith(`
18
+ `)?t:`${t}
19
+ `,{encoding:"utf8",mode:384}),uo(n,e)}function mo(e,t){yn(e,`${JSON.stringify(t,null,2)}
20
+ `)}function hn(e,t){let n=t.replace(/\r\n/g,`
21
+ `).trim();if(!n)return null;let r={version:1,projectId:e.id,projectName:e.name,text:n,digest:w(n),generatedAt:new Date().toISOString()};return yn(fn(e),n),mo(gn(e),r),r}function ht(e){let t=fn(e);if(!dn(t))return null;try{let n=pn(t,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=gn(e);if(dn(s))try{let o=JSON.parse(pn(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:e.id,projectName:e.name,text:n,digest:w(n),generatedAt:r}}catch{return null}}function Sn(e,t=1800){let n=ht(e);if(!n?.text)return null;let r=n.text;return r.length>t&&(r=`${r.slice(0,t)}
22
+
23
+ [Fast handoff truncated]`),["[TOOLNET FAST HANDOFF]","",`Project: ${e.name}`,`Updated: ${n.generatedAt}`,"",r].join(`
24
+ `)}var St="memory_agent_ask";function kn(){return`
25
+ [TOOLNET MEMORY AGENT]
26
+
27
+ Tool:
28
+ - ${St}
29
+
30
+ For resume/continue requests:
31
+
32
+ 1. Use the injected ToolNet continuity handoff FIRST.
33
+ 2. If the handoff is missing or ambiguous, invoke
34
+ ${St} directly BEFORE repository/history exploration.
35
+ 3. NEVER reconstruct prior work from:
36
+ - .toolnet/sessions/**
37
+ - state.json
38
+ - events.jsonl
39
+ - raw transcripts
40
+ 4. NEVER search for the implementation/schema of
41
+ ${St}; invoke the MCP tool directly.
42
+ 5. Inspect git/source only AFTER continuity context is known.
43
+
44
+ Use:
45
+ - mode="local" for current task, last file, blocker or next action.
46
+ - mode="ai" for ambiguous or combined continuity questions.
47
+
48
+ Current repository evidence overrides stale memory.
49
+ `.trim()}function kt(e){let t=N.resolve(e),n=N.parse(t).root;for(;t!==n;){let r=N.join(t,".toolnet");if(F.existsSync(r)&&F.statSync(r).isDirectory())return t;t=N.dirname(t)}return null}function wn(e){try{return F.existsSync(e)?F.readFileSync(e,"utf-8").trim():null}catch{return null}}function vn(e){return e.split(`
50
+ `).filter(r=>{let s=r.toUpperCase();return!(s.includes("SECRET")||s.includes("TOKEN")||s.includes("API_KEY")||s.includes("APIKEY")||s.includes("PASSWORD")||s.includes("PASS="))}).join(`
51
+ `)}function bn(e={}){let t=e.projectPath||process.cwd(),n=kt(t);if(!n)return null;let r=N.join(n,".toolnet","project.json"),s="Unknown";try{if(F.existsSync(r)){let y=JSON.parse(F.readFileSync(r,"utf-8"));s=y.name||y.projectName||"Unknown"}}catch{}let o=N.join(n,".toolnet","profile.md"),i=N.join(n,".toolnet","current.md"),a=wn(o)||"",c=wn(i)||"";a=vn(a),c=vn(c);let u=`[TOOLNET PROJECT CONTEXT]
52
+
53
+ Project: ${s}
54
+ Root: ${n}
55
+
56
+ `,m=Qt(a,c),p=Sn({id:"",name:s,rootPath:n},1600),d=p?`
57
+
58
+ ${p}
59
+ `:"",l=un(n,{maxAssets:6,maxChars:900}),g=l?`
60
+
61
+ ${l}
62
+ `:"",S=`
63
+
64
+ ${kn()}
65
+
66
+ Forbidden At Startup:
67
+ - Do not run session:agy-recover, handoff:latest, or brief automatically.
68
+ - Do not perform deep recovery merely because an agent starts.
69
+ - If the user asks to resume previous work and fast context is insufficient,
70
+ use memory_agent_ask before guessing.
71
+ `;return u+m+d+g+S}var xn=6500,fo=[/\bcontinue\b/i,/\bresume\b/i,/\bpick\s+up\b/i,/\bcarry\s+on\b/i,/\bfinish\s+(?:the\s+)?(?:previous|last|unfinished|remaining)\b/i,/\bwhere\s+(?:did\s+we|were\s+we)\b/i,/\bwhat\s+was\s+(?:the\s+)?(?:last|previous)\b/i,/(?:^|[\s,.;:!?])tiếp\s+tục(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])làm\s+tiếp(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])làm\s+nốt(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])tiếp\s+phần(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])phần\s+đang\s+dở(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])đang\s+làm\s+(?:gì|đến\s+đâu)(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])dừng\s+(?:ở|tại)\s+đâu(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])task\s+(?:lúc\s+nãy|trước|đang\s+dở)(?:$|[\s,.;:!?])/iu];function In(e,t){return e.length<=xn?e:`${e.slice(0,xn)}
72
+
73
+ [ToolNet ${t} context truncated]`}function jn(e){return e.replace(/\\/g,"/").toLowerCase()}function wt(e,t,n=0){if(!(n>6||t.length>=250)){if(typeof e=="string"){t.push(e);return}if(Array.isArray(e)){for(let r of e)if(wt(r,t,n+1),t.length>=250)break;return}if(e&&typeof e=="object"){for(let r of Object.values(e))if(wt(r,t,n+1),t.length>=250)break}}}function go(e){let t=jn(e);if(t.includes(".toolnet/sessions/")||t.endsWith(".toolnet/sessions")||t.includes(".gemini/antigravity-cli/brain/")||t.endsWith(".gemini/antigravity-cli/brain")||t.includes("/transcript.jsonl")||t.endsWith("transcript.jsonl")||t.includes(".toolnet/")&&(t.endsWith("/events.jsonl")||t.endsWith("/state.json")||t.includes("/sessions/")))return!0;let n=process.env.CURSOR_TRANSCRIPT_PATH;return!!(n&&jn(n)===t)}function yo(e){let t=e.trim();return t?fo.some(n=>n.test(t)):!1}function vt(e,t){if(!e.trim())return"";let n="";try{n=bn({projectPath:e})?.trim()??""}catch{n=""}let r=`
74
+ [TOOLNET CONTINUITY]
75
+
76
+ ToolNet Memory is the continuity source for this repository.
77
+
78
+ When the user asks to continue, resume, pick up, or finish previous work:
79
+ 1. Use this injected ToolNet fast handoff first.
80
+ 2. If the handoff is missing, stale, or ambiguous, invoke the MCP tool
81
+ memory_agent_ask before exploring prior history.
82
+ 3. Prefer mode="local" for current task, last file, blocker, completed work,
83
+ TODOs, and next action.
84
+ 4. Use mode="ai" only when continuity requires synthesis.
85
+ 5. Never reconstruct prior work from .toolnet/sessions/**, events.jsonl,
86
+ state.json, raw transcripts, or another agent's private history.
87
+ 6. After continuity is known, verify current git/source truth and continue.
88
+ 7. Do not ask the user to repeat context ToolNet already provides.
89
+
90
+ Current repository evidence overrides stale memory.
91
+ `.trim();return In(n?`${n}
92
+
93
+ ${r}`:r,t)}function An(e,t,n){if(!yo(e))return"";let r=vt(t,n),s=`
94
+ [TOOLNET RESUME REQUEST]
95
+
96
+ The current user message explicitly asks to continue previous work.
97
+ Use memory_agent_ask now if the fast handoff does not contain a clear,
98
+ current next action. Do not reconstruct continuity from raw session files.
99
+ `.trim();return In(r?`${r}
100
+
101
+ ${s}`:s,n)}function Cn(e){let t=[];return wt(e,t),t.find(go)?{blocked:!0,reason:"ToolNet continuity guard: do not read or reconstruct previous work from raw ToolNet/agent session history. Use the injected ToolNet handoff first; if it is insufficient, invoke the MCP tool memory_agent_ask directly. Then verify normal repository/git source truth."}:{blocked:!1}}function P(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Pn(e,t=process.env){return P(t.TOOLNET_HOOK_EVENT)??P(e.hook_event_name)??P(e.hookEventName)??""}function En(e,t=process.env){let n=P(e.session_id)??P(e.sessionId)??P(e.conversation_id)??P(t.TOOLNET_CURSOR_SESSION_ID)??"",r=P(e.cwd)??P(e.workspaceRoot)??P(t.CURSOR_PROJECT_DIR)??P(t.CLAUDE_PROJECT_DIR)??"",s=vt(r,"Cursor"),o={env:{TOOLNET_CURSOR_SESSION_ID:n}};return s&&(o.additional_context=s),o}function Mn(e,t=process.env){let n=P(e.prompt)??"",r=P(e.cwd)??P(e.workspaceRoot)??P(t.CURSOR_PROJECT_DIR)??P(t.CLAUDE_PROJECT_DIR)??"";return An(n,r,"Cursor")}function Tn(e){return Cn(e.tool_input??e.toolInput??e.updated_input??e)}function On(e){return{permission:"deny",user_message:e,agent_message:e}}import{existsSync as Nu}from"node:fs";import{join as _u}from"node:path";import{existsSync as ho,readFileSync as So}from"node:fs";import{homedir as ko}from"node:os";import{join as wo}from"node:path";function vo(e){let t=e.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?(t=t.slice(1,-1),t.replace(/\\n/g,`
102
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function bo(){let e=process.env.TOOLNET_GLOBAL_ENV??wo(ko(),".config","toolnet-memory",".env");if(!ho(e))return;let t=So(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 s=r.indexOf("=");if(s<=0)continue;let o=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=vo(r.slice(s+1)))}}bo();function ue(e,t){return e===void 0?t:["1","true","yes","on"].includes(e.toLowerCase())}function le(e,t){if(!e)return t;let n=Number(e);return Number.isFinite(n)?n:t}function Ee(){return{memory:{autoCapture:ue(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:ue(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:ue(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:ue(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:le(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:le(process.env.MEMORY_RERANK_TOP,10),finalContext:le(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:le(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:ue(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:le(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as xo}from"node:crypto";import{existsSync as bt,mkdirSync as jo,readFileSync as Io,renameSync as Ao,writeFileSync as Co}from"node:fs";import{basename as Po,dirname as Me,join as Oe,parse as _n,resolve as de}from"node:path";var Kn=".toolnet",Eo="project.json";function Mo(e){return xo("sha256").update(e).digest("hex").slice(0,16)}function xt(e){return Oe(e,Kn,Eo)}function To(e){return bt(xt(e))}function Oo(e,t){let n=de(e),r=_n(n).root;for(;;){if(To(n))return n;if(n===r||t&&n===de(t))break;let s=Me(n);if(s===n)break;n=s}return null}function Ro(e){let t=de(e),n=_n(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>bt(Oe(t,o))))return t;if(t===n)break;let s=Me(t);if(s===t)break;t=s}return de(e)}function No(e){let t;try{t=JSON.parse(Io(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:Me(Me(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 Rn(e,t){let n=Oe(e,Kn);jo(n,{recursive:!0});let r=xt(e),s=`${r}.tmp-${process.pid}`;Co(s,JSON.stringify(t,null,2)+`
103
+ `,{encoding:"utf8",mode:384}),Ao(s,r)}function Nn(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 Te=class{detect(t=process.cwd()){let n=de(t),r=Ro(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>bt(Oe(r,m))),i=Oo(n,o?r:void 0);if(i){let m=xt(i),p=No(m);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),Rn(i,p)),Nn(p,i)}let a=new Date().toISOString(),c=Po(r),u={version:1,id:Mo(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return Rn(r,u),Nn(u,r)}};var _o=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],Re=class{scan(t){let n=[];for(let r of _o){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of t.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(t){return this.scan(t).length>0}};var Y=class{scanner=new Re;sanitize(t){let n=t,r=this.scanner.scan(t),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}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,s]of Object.entries(t)){let o=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return t}};import{homedir as si}from"node:os";import{join as oi}from"node:path";import{DeleteObjectCommand as Ko,GetObjectCommand as $o,HeadObjectCommand as Fo,ListObjectsV2Command as Wo,PutObjectCommand as Lo,S3Client as Do}from"@aws-sdk/client-s3";import{getSignedUrl as zo}from"@aws-sdk/s3-request-presigner";var Ne=class{name="huggingface";client;bucket;constructor(t){this.bucket=t.bucket,this.client=new Do({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 s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Lo({Bucket:this.bucket,Key:t,Body:s,ContentType:r}))}async get(t){let n=await zo(this.client,new $o({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 Fo({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 Ko({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let s=await this.client.send(new Wo({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as $n,mkdir as qo,readFile as Ho,readdir as Jo,rm as Vo,stat as Fn,writeFile as Bo}from"node:fs/promises";import{dirname as Go,join as Uo,relative as Wn,resolve as Yo}from"node:path";var pe=class{constructor(t){this.root=t}root;name="local";path(t){let n=t.replace(/^\/+/,"");return Yo(this.root,n)}async put(t,n){let r=this.path(t);await qo(Go(r),{recursive:!0}),await Bo(r,n)}async get(t){try{return await Ho(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 $n(this.path(t)),!0}catch{return!1}}async delete(t){await Vo(this.path(t),{force:!0})}async list(t=""){let n=this.path(t),r=[];try{await $n(n)}catch{return r}let s=async i=>{let a=await Jo(i,{withFileTypes:!0});for(let c of a){let u=Uo(i,c.name);if(c.isDirectory()){await s(u);continue}let m=await Fn(u);r.push({key:Wn(this.root,u),size:m.size,updatedAt:m.mtime.toISOString()})}},o=await Fn(n);return o.isDirectory()?await s(n):r.push({key:Wn(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Xo,GetObjectCommand as Qo,HeadObjectCommand as Zo,ListObjectsV2Command as ei,PutObjectCommand as ti,S3Client as ni}from"@aws-sdk/client-s3";import{getSignedUrl as ri}from"@aws-sdk/s3-request-presigner";var me=class{name;client;bucket;constructor(t){this.name=t.name??"s3",this.bucket=t.bucket,this.client=new ni({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 s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new ti({Bucket:this.bucket,Key:t,Body:s,ContentType:r}))}async get(t){let n=await ri(this.client,new Qo({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 Zo({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 Xo({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let s=await this.client.send(new ei({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function jt(e,t){return console.warn(t),new pe(e)}function Ln(e){let t=e.localRoot??oi(si(),".toolnet-memory","storage");if(e.provider==="r2"){let n=e.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new me({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):jt(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 me({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):jt(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 Ne({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):jt(t,"[storage] Hugging Face credentials missing. Using local fallback.")}return new pe(t)}function ii(e){return new Promise(t=>setTimeout(t,e))}async function Dn(e,t={}){let n=Math.max(1,t.attempts??3),r=t.baseDelayMs??150,s=t.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await e()}catch(a){if(o=a,i>=n)break;let c=Math.min(s,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await ii(c+u)}throw o}var ai=new Set(["put","get","getText","delete","list"]);function zn(e,t={}){return new Proxy(e,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:ai.has(r)?(...o)=>Dn(()=>Promise.resolve(s.apply(n,o)),t):s.bind(n)}})}function qn(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 Hn(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 s=t.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=t.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=t.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:t))}var _e=class{constructor(t,n,r,s){this.provider=t;this.name=t.name,this.projectId=n,this.projectName=r,this.folder=qn(s??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,s=await this.provider.getText(t);if(s){let i;try{i=JSON.parse(s)}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 o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(t,JSON.stringify(o,null,2)+`
104
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(t){if(t=Hn(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))}};import{existsSync as hi,readFileSync as Si}from"node:fs";import{join as ki}from"node:path";import{existsSync as ci,mkdirSync as ui,readFileSync as li,renameSync as di,writeFileSync as pi}from"node:fs";import{dirname as mi,join as fi}from"node:path";function Jn(e){return fi(e.rootPath,".toolnet","context","session-origin.json")}function gi(e,t){ui(mi(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;pi(n,`${JSON.stringify(t,null,2)}
105
+ `,{encoding:"utf8",mode:384}),di(n,e)}function Ke(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 Vn(e,t){let n=Ke(t.observations,"file"),r=Ke(t.observations,"next_action"),s=Ke(t.observations,"blocker"),o=Ke(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 gi(Jn(e),i),i}function yi(e){let t=Jn(e);if(!ci(t))return null;try{let n=JSON.parse(li(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function Bn(e){let t=yi(e);if(!t)return null;let n=["Previous session:",`- Agent: ${t.agent}`,`- Session: ${t.nativeSessionId}`];return t.currentRequest&&n.push(`- Current request: ${t.currentRequest}`),t.currentActivity&&n.push(`- Current activity: ${t.currentActivity}`),t.currentPhase&&n.push(`- Current phase: ${t.currentPhase}`),t.currentTask&&n.push(`- Current task: ${t.currentTask}`),t.lastTouchedFile&&n.push(`- Last touched file: ${t.lastTouchedFile}`),t.latestBlocker&&n.push(`- Blocker: ${t.latestBlocker}`),t.latestNextAction&&n.push(`- Next action: ${t.latestNextAction}`),t.latestDecision&&n.push(`- Important decision: ${t.latestDecision}`),n.join(`
106
+ `)}function wi(e){let t=ki(e.rootPath,".toolnet","current.md");if(!hi(t))return null;try{return Si(t,"utf8").trim()}catch{return null}}function vi(e,t){let n=t.replace(/\r\n/g,`
107
+ `).trim(),r=2400,s=n.length>r?`${n.slice(0,r)}
108
+
109
+ [Current work truncated for fast handoff]`:n,o=Bn(e);return["# ToolNet Fast Handoff","",`Project: ${e.name}`,"",...o?[o,""]:[],s,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
110
+ `)}function Gn(e){let t=wi(e);if(t===null)return{updated:!1,reason:"missing-current",chars:0};if(!t.trim())return{updated:!1,reason:"empty-current",chars:0};let n=vi(e,t);return ht(e)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(hn(e,n),{updated:!0,reason:"updated",chars:n.length})}import{join as bi}from"node:path";function Un(e,t){let n=e.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=w(n).slice(0,12);if(!r||r==="."||r==="..")return`${t}--${s}`;let o=r.slice(0,100);return o===n&&n.length<=100?o:`${o.slice(0,85)}--${s}`}function $e(e,t,n){let r=t.trim(),s=n.trim();if(!r)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=Un(r.toLowerCase(),"agent"),i=Un(s,"session");return{projectId:e.id,projectName:e.name,projectRoot:e.rootPath,agent:r,nativeSessionId:s,sessionKey:`${r}:${s}`,remotePrefix:["projects",e.id,"sessions",o,i].join("/"),localDirectory:bi(e.rootPath,".toolnet","sessions",o,i)}}function Yn(e){return String(e).padStart(12,"0")}var Fe=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)+`
111
+ `,"application/json")}async scan(t){let n=`${t.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=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)||(s.push({key:i.key,start:c,end:u}),o=Math.max(o,u))}return s.sort((i,a)=>i.start-a.start),{chunks:s,maxSequence:o}}split(t){let n=[],r=[],s=0;for(let o of t){let i=Buffer.byteLength(JSON.stringify(o)+`
112
+ `,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=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,s={}){let o=await this.loadManifest(t),i=await this.scan(t),a=n.filter(y=>y.sequence>i.maxSequence),c=0;for(let y of this.split(a)){let h=y[0],k=y[y.length-1],E=y.map(O=>JSON.stringify(O)).join(`
113
+ `)+`
114
+ `,T=w(E).slice(0,16),C=[t.remotePrefix,"events",`${Yn(h.sequence)}-${Yn(k.sequence)}-${T}.jsonl`].join("/");await this.storage.exists(C)||await this.storage.put(C,E,"application/x-ndjson"),c+=y.length}let u=await this.scan(t),m=n[n.length-1],p=o?.status??"active";m?.type==="session_end"||m?.type==="session_idle"?p="idle":m?.type==="error"?p="error":n.length>0&&(p="active");let d=new Date().toISOString(),l=n[0],g={version:1,projectId:t.projectId,projectName:t.projectName,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,status:p,createdAt:o?.createdAt??l?.timestamp??d,updatedAt:m?.timestamp??d,firstEventAt:o?.firstEventAt??l?.timestamp,lastEventAt:m?.timestamp??o?.lastEventAt,eventCount:u.maxSequence,chunkCount:u.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(g.title=s.title??o?.title);let S={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:d};return await this.putJson(`${t.remotePrefix}/cursor.json`,S),await this.putJson(`${t.remotePrefix}/session.json`,g),{uploadedEvents:c,lastRemoteSequence:u.maxSequence,eventCount:g.eventCount,chunkCount:g.chunkCount,status:p}}};import{closeSync as At,existsSync as Pi,fsyncSync as Ei,mkdirSync as Mi,openSync as Ct,readSync as Ti,rmSync as Qn,statSync as Zn,writeSync as Oi}from"node:fs";import{join as Pt}from"node:path";var xi=new Set(["thinking","reasoning","reasoningcontent","chainofthought","cot","analysistext","internalreasoning","modelthinking"]),ji=new Set(["reasoning","thinking","chain_of_thought","chain-of-thought","internal_reasoning","internal-reasoning"]);function Ii(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,"")}function Ai(e){for(let t of["type","kind"]){let n=e[t];if(typeof n=="string"){let r=n.toLowerCase();if(ji.has(r))return n}}return null}function It(e,t=0){if(t>12)return"[ToolNet nested value omitted]";if(Array.isArray(e))return e.map(o=>It(o,t+1));if(!e||typeof e!="object")return e;let n=e,r=Ai(n);if(r)return{type:r,omitted:"[private reasoning omitted]"};let s={};for(let[o,i]of Object.entries(n))xi.has(Ii(o))||(s[o]=It(i,t+1));return s}function Ci(e){if(!e)return new Date().toISOString();let t=new Date(e);return Number.isNaN(t.getTime())?new Date().toISOString():t.toISOString()}function X(e){return e?.trim()||void 0}function Xn(e,t={}){let n={...e.provenance??{}},r=X(e.source)??X(t.source)??X(n.source);return{...e,timestamp:Ci(e.timestamp),source:r,turnId:X(e.turnId)??X(t.turnId),cwd:X(e.cwd)??X(t.cwd),data:It(e.data??{}),provenance:n}}var Ri=12e4,Ni=80,_i=2e3;function Ki(e){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}var re=class{constructor(t,n={}){this.identity=t;this.eventContext=n;Mi(t.localDirectory,{recursive:!0}),this.eventsFile=Pt(t.localDirectory,"events.jsonl"),this.stateFile=Pt(t.localDirectory,"state.json"),this.lockFile=Pt(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 ln(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(t){R(this.stateFile,t)}acquireLock(){for(let t=0;t<Ni;t+=1)try{return Ct(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-Zn(this.lockFile).mtimeMs>Ri){Qn(this.lockFile,{force:!0});continue}}catch{}Ki(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(t){let n=this.acquireLock();try{return t()}finally{At(n),Qn(this.lockFile,{force:!0})}}append(t){return t.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let p of t){let d=Xn(p,this.eventContext),l=d.timestamp??new Date().toISOString(),g=d.data??{},S=d.provenance?.rawDigest??w(Pe(g)),y=d.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,d.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,d.type,l,S].join("|"),h=w(y).slice(0,32);if(r.has(h))continue;s+=1;let k={version:1,id:h,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,sessionId:this.identity.nativeSessionId,type:d.type,timestamp:l,source:d.source??d.provenance?.source??this.identity.agent,data:g,provenance:{...d.provenance,rawDigest:S}};d.role!==void 0&&(k.role=d.role),d.turnId!==void 0&&(k.turnId=d.turnId),d.cwd!==void 0&&(k.cwd=d.cwd),d.sourceEventId!==void 0&&(k.sourceEventId=d.sourceEventId),d.sourceSequence!==void 0&&(k.sourceSequence=d.sourceSequence),o.push(k),r.add(h)}if(o.length===0)return[];let i=o.map(p=>JSON.stringify(p)).join(`
115
+ `)+`
116
+ `,a=Ct(this.eventsFile,"a",384);try{Oi(a,i,null,"utf8"),Ei(a)}finally{At(a)}let c=o[o.length-1],u="active";c.type==="session_end"||c.type==="session_idle"?u="idle":c.type==="error"&&(u="error");let m=Array.from(r).slice(-_i);return this.saveStateUnsafe({...n,status:u,updatedAt:c.timestamp,lastLocalEventAt:c.timestamp,lastSequence:c.sequence,recentEventIds:m}),o})}readPending(){return this.withLock(()=>{let t=this.loadStateUnsafe();if(!Pi(this.eventsFile))return{events:[],startOffset:t.remoteByteOffset,endOffset:t.remoteByteOffset};let n=Zn(this.eventsFile).size,r=Math.min(t.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let s=n-r,o=Buffer.alloc(s),i=Ct(this.eventsFile,"r");try{Ti(i,o,0,s,r)}finally{At(i)}return{events:o.toString("utf8").split(`
117
+ `).filter(Boolean).map(u=>JSON.parse(u)),startOffset:r,endOffset:n}})}markRemote(t,n){this.withLock(()=>{let r=this.loadStateUnsafe(),s=new Date().toISOString();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,t),remoteByteOffset:Math.max(r.remoteByteOffset,n),lastRemoteAt:s,updatedAt:s})})}setSourceCursor(t,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[t]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as ac,existsSync as cc,openSync as uc,readSync as lc,statSync as dc}from"node:fs";function er(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 sr=[/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],$i=[/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],Fi=[/\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],Wi=[/\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],Li=[/đã 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],tr=[/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],Di=[/\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],zi=[/đườ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],qi=[/\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],nr=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Hi=new Set(["payload","data","content","message","messages","parts","summary"]);function _(e,t){return t.some(n=>n.test(e))}function or(e){return e.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Ji(e){return or(e).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Vi(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 Et(e,t,n,r=0){if(!(r>6)){if(typeof e=="string"){(!t||nr.has(t))&&n.push(e);return}if(Array.isArray(e)){for(let s of e.slice(0,50))Et(s,t,n,r+1);return}if(!(!e||typeof e!="object"))for(let[s,o]of Object.entries(e))(nr.has(s)||Hi.has(s))&&Et(o,s,n,r+1)}}function Bi(e){let t=[];Et(e.data,void 0,t);let n=[],r=new Set;for(let s of t)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=or(o);if(Vi(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function rr(e){return(e.role??(typeof e.data.role=="string"?e.data.role:"")).toLowerCase()}function Gi(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",s=t==="assistant"||n.type==="assistant_message";return r&&_(e,sr)?{kind:"rule",confidence:.98}:r&&_(e,$i)?{kind:"rule",confidence:.92}:_(e,Fi)?{kind:_(e,tr)?"architecture":"decision",confidence:r?.93:.86}:r&&_(e,Wi)?{kind:"todo",confidence:.87}:_(e,tr)&&_(e,Di)?{kind:"architecture",confidence:r?.88:.82}:s&&_(e,Li)?{kind:"fix",confidence:.8}:r&&_(e,zi)&&_(e,qi)?{kind:"context",confidence:.79}:null}function Ui(e){switch(e){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Yi(e,t,n){return e==="rule"&&_(n,sr)?"critical":e==="architecture"||e==="decision"||e==="rule"?"high":e==="fix"||e==="context"?"normal":er(t,n)}function ir(e,t){let n=[],r=new Set,s=new Map;for(let o of t){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,a=rr(o);i&&a&&s.set(i,a)}for(let o of t){let i=rr(o),a=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&a&&(i=s.get(a)??"");for(let c of Bi(o)){let u=Gi(c,i,o);if(!u||u.confidence<.75)continue;let m=Ui(u.kind),p=Ji(c),d=w([e.projectId,u.kind,p].join("|"));if(r.has(d))continue;r.add(d);let l=o.provenance.sourcePath?[o.provenance.sourcePath]:[],g=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:d,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,kind:u.kind,type:m,content:c,confidence:u.confidence,importance:Yi(u.kind,m,c),tags:[m],provenance:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventIds:[o.id],sourceEventIds:g,sourcePaths:l,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}import{createHash as Xi}from"node:crypto";var Qi=["project-knowledge","implementation","continuation","session-context"],Zi={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function Mt(e){return Xi("sha256").update(e).digest("hex")}function We(e,t){return`${e}:${Mt(t).slice(0,24)}`}function ea(e){try{return Mt(JSON.stringify(e))}catch{return Mt(String(e))}}function Q(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 cr(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 ta(e){return e==="rule"||e==="architecture"?"project-knowledge":e==="decision"||e==="fix"?"implementation":e==="todo"?"continuation":"session-context"}function ar(e){return e.length===0?0:e.reduce((t,n)=>t+n,0)/e.length}function na(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=>cr(t.content)).join(" | ")}function ra(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=>cr(t.content)).join(`
118
+ `)}function ur(e,t){let n=e.slice().sort((d,l)=>d.sequence-l.sequence||d.timestamp.localeCompare(l.timestamp)||d.id.localeCompare(l.id)),r=n.map(d=>({id:We("raw",[d.projectId,d.agent,d.nativeSessionId,d.id,String(d.sequence)].join("|")),level:"raw",eventId:d.id,sourceEventId:d.sourceEventId,sequence:d.sequence,type:d.type,role:d.role,timestamp:d.timestamp,sourcePath:d.provenance.sourcePath,payloadDigest:ea(d.data)})),s=new Map,o=new Map;n.forEach((d,l)=>{let g=r[l];g&&(s.set(d.id,g.id),d.sourceEventId&&o.set(d.sourceEventId,g.id))});let i=t.map(d=>{let l=Q([...d.provenance.eventIds.map(g=>s.get(g)),...d.provenance.sourceEventIds.map(g=>o.get(g))]);return{id:We("fact",d.fingerprint),level:"fact",fingerprint:d.fingerprint,kind:d.kind,type:d.type,content:d.content,knowledgeClass:d.knowledgeClass,importanceScore:d.importanceScore,confidence:d.confidence,tags:Q([...d.tags,"level:fact",`class:${d.knowledgeClass}`,`kind:${d.kind}`]),rawIds:l,sourcePaths:Q(d.provenance.sourcePaths)}}),a=new Map;for(let d of i){let l=ta(d.kind),g=a.get(l)??[];g.push(d),a.set(l,g)}let c=[];for(let d of Qi){let l=a.get(d);if(!l?.length)continue;let g=l.slice().sort((y,h)=>h.importanceScore-y.importanceScore||h.confidence-y.confidence||y.id.localeCompare(h.id)),S=g.map(y=>y.id);c.push({id:We("scene",`${d}|${S.join("|")}`),level:"scene",kind:d,title:Zi[d],summary:na(g),factIds:S,importanceScore:Math.max(...g.map(y=>y.importanceScore)),confidence:ar(g.map(y=>y.confidence)),tags:Q(["level:scene",`scene:${d}`,...g.flatMap(y=>y.tags)]),sourcePaths:Q(g.flatMap(y=>y.sourcePaths))})}let u=new Map(i.map(d=>[d.id,d])),m=[];for(let d of c){let g=d.factIds.map(h=>u.get(h)).filter(h=>!!h).filter(h=>(h.knowledgeClass==="permanent"||h.knowledgeClass==="task")&&h.importanceScore>=.55);if(g.length===0)continue;let S=g.some(h=>h.knowledgeClass==="permanent")?"permanent":"task",y=ra(g);m.push({id:We("knowledge",`${d.id}|${S}|${g.map(h=>h.id).join("|")}`),level:"knowledge",knowledgeClass:S,title:d.title,content:y,sceneIds:[d.id],factIds:g.map(h=>h.id),importanceScore:Math.max(...g.map(h=>h.importanceScore)),confidence:ar(g.map(h=>h.confidence)),tags:Q(["level:knowledge",`class:${S}`,`scene:${d.kind}`,...g.flatMap(h=>h.tags)]),sourcePaths:Q(g.flatMap(h=>h.sourcePaths))})}let p=[];for(let d of i)for(let l of d.rawIds)p.push({from:l,to:d.id,type:"supports"});for(let d of c)for(let l of d.factIds)p.push({from:l,to:d.id,type:"belongs_to"});for(let d of m)for(let l of d.sceneIds)p.push({from:l,to:d.id,type:"promotes_to"});return{schema:"toolnet.memory-hierarchy.v1",version:1,raw:r,facts:i,scenes:c,knowledge:m,links:p,stats:{raw:r.length,facts:i.length,scenes:c.length,knowledge:m.length,links:p.length}}}function fe(){let e=Ee(),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",s=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),o=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:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:a,archiveRemote:c}}function lr(e){return(e||fe()).durableMemoryMaxItemsPerSession}function dr(e){return(e||fe()).sessionSummaryMaxTokens}var pr=new Y;function mr(e){let t=e.trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{let r=JSON.parse(t);return JSON.stringify(pr.sanitizeValue(r))}catch{}let n=pr.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 sa(e,t){let n=e.toLowerCase(),r=.5,s=["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 s)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 o=[/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 o)i.test(e)&&(r-=.4);return Math.max(0,Math.min(1,r))}function oa(e,t){let n=[],r=new Set;for(let i of e){let a=i.split(`
119
+ `).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let m=u.toLowerCase().replace(/\s+/g," ");if(r.has(m))continue;r.add(m);let p="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)?p="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?p="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?p="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?p="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?p="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?p="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(p="file");let d=sa(u,p);if(d<.3)continue;let l=mr(u);n.push({category:p,text:l,importance:d,sourceSessionId:t})}}let s=fe(),o=lr(s);return n.sort((i,a)=>a.importance-i.importance).slice(0,o)}function ia(e){let t=fe(),n=dr(t),o=e.join(`
120
+
121
+ `).split(`
122
+ `).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).map(i=>mr(i)).join(`
123
+ `);return pt(o,n)}function fr(e,t){let r=(Array.isArray(e)?e:e.split(`
124
+
125
+ `).filter(l=>l.trim())).map(l=>typeof l=="string"?l:JSON.stringify(l)).filter(l=>l.trim()),s=oa(r,t),o=s.filter(l=>l.category==="decision").map(l=>l.text),i=s.filter(l=>l.category==="rule").map(l=>l.text),a=s.filter(l=>l.category==="file").map(l=>l.text),c=s.filter(l=>l.category==="fix").map(l=>l.text),u=s.filter(l=>l.category==="blocker").map(l=>l.text),m=s.filter(l=>l.category==="next_action").map(l=>l.text),p=s.filter(l=>l.category==="deploy").map(l=>l.text);return{summary:ia(r),decisions:o,projectRules:i,filesChanged:a,bugsFixed:c,commands:p,blockers:u,nextActions:m,durableFacts:s}}function B(e){let t=new Set,n=[];for(let r of e){let s=r?.replace(/\s+/g," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();t.has(o)||(t.add(o),n.push(s))}return n}function aa(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,s=t.get(r);(!s||n.sequence>s.sequence)&&t.set(r,n)}return[...t.values()].sort((n,r)=>n.sequence-r.sequence||n.timestamp.localeCompare(r.timestamp))}function ca(e){switch(e){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function ua(e){let t=ca(e.importance);return Math.max(0,Math.min(1,t*.75+e.confidence*.25))}function la(e){return e.importance==="temporary"||e.confidence<.78?"transient":e.kind==="rule"||e.kind==="architecture"?"permanent":e.kind==="decision"||e.kind==="todo"||e.kind==="fix"?"task":"session"}function da(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 pa(e){let t=la(e),n=ua(e),r=da(e.content);return{...e,knowledgeClass:t,importanceScore:n,retrievalTerms:r,tags:B([...e.tags,"level:fact",`class:${t}`,`kind:${e.kind}`])}}function ma(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 fa(e,t,n){let r=fr(ma(t),e.nativeSessionId),s=n.filter(u=>u.kind==="todo").map(u=>u.content),o=n.flatMap(u=>u.provenance.sourcePaths),i=n.filter(u=>u.kind==="architecture").map(u=>u.content),a=B([...s,...r.nextActions]),c=B([...r.nextActions,...s]);return{summary:r.summary,state:{task:c[0]??a[0],decisions:B(r.decisions),files:B([...r.filesChanged,...o]),todos:a,completed:B(r.bugsFixed),blockers:B(r.blockers),nextActions:c,architecture:B(i)}}}function Le(e,t){let n=aa(t),r=ir(e,n).map(pa),s=r.filter(m=>m.knowledgeClass!=="transient").sort((m,p)=>p.importanceScore-m.importanceScore),{summary:o,state:i}=fa(e,n,s),a=s.map(m=>({fingerprint:m.fingerprint,kind:m.kind,knowledgeClass:m.knowledgeClass,importanceScore:m.importanceScore,content:m.content,terms:m.retrievalTerms})),c=ur(n,s),u=m=>r.filter(p=>p.knowledgeClass===m).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:a,hierarchy:c,stats:{inputEvents:t.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:s.length,permanent:u("permanent"),task:u("task"),session:u("session"),transient:u("transient")}}}import{createHash as ba}from"node:crypto";import{existsSync as xa,readdirSync as ja,readFileSync as Ia}from"node:fs";import{basename as Aa,join as Tr}from"node:path";import{randomUUID as hr}from"node:crypto";var j=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function ge(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 j("Invalid Wiki slug",400);return t}function gr(e){let t=[];for(let n of e.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&t.push(ee(r))}return ge(t)}function ga(e){return e.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(t=>t.trim()).filter(t=>t.length>=2)}function yr(e){return{id:`revision-${hr()}`,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 De=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:ge(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 j(`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 j("Wiki title is required",400);let o=ee(t.slug??r);if(n.pages.some(c=>c.slug===o))throw new j(`Wiki page already exists: ${o}`,409);let i=new Date().toISOString(),a={id:`wiki-${hr()}`,slug:o,title:r,...t.summary?.trim()?{summary:t.summary.trim()}:{},content:s,tags:ge(t.tags??[]),links:gr(s),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(yr(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 j(`Wiki page not found: ${t}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new j("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=gr(o.content)),n.tags!==void 0&&(o.tags=ge(n.tags)),o.revision+=1,o.updatedAt=new Date().toISOString(),r.revisions.push(yr(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=ge(ga(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(),m=a.summary?.toLowerCase()??"",p=a.content.toLowerCase(),d=a.tags.map(g=>g.toLowerCase()),l=0;for(let g of s)u===g&&(l+=12),c===g&&(l+=10),c.includes(g)&&(l+=6),u.includes(g)&&(l+=5),d.some(S=>S===g)?l+=5:d.some(S=>S.includes(g))&&(l+=3),m.includes(g)&&(l+=2),p.includes(g)&&(l+=1);l>0&&i.push({page:Z(a),score:l})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,o)}};var Sr="wiki/state.v1.json";function ya(e){let t=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:e.id,pages:[],revisions:[],createdAt:t,updatedAt:t}}function ha(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(Sr);if(!t){let n=ya(this.project);return await this.save(n),n}return ha(t,this.project)}async save(t){await this.storage.put(Sr,JSON.stringify(t,null,2),"application/json")}};import{createHash as Sa,randomUUID as kr}from"node:crypto";var wr="wiki/governance.v1.json",jr="toolnet.knowledge-governance.v1",vr=500,ye={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function ka(e,t=0,n=1){return Math.max(t,Math.min(n,e))}function Tt(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function br(e){return Sa("sha256").update(e.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function wa(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 va(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),ka(t)}function xr(e){let t=new Date().toISOString();return{schema:jr,version:1,projectId:e,policy:{...ye},reviews:[],audit:[],createdAt:t,updatedAt:t}}function Ir(e){let t=e.autoApproveThreshold??ye.autoApproveThreshold,n=e.criticalApproveThreshold??ye.criticalApproveThreshold,r=e.staleAfterDays??ye.staleAfterDays;if(!Number.isFinite(t)||t<.5||t>1)throw new j("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new j("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new j("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(wr);if(!t){let n=xr(this.project.id);return await this.save(n),n}try{let n=JSON.parse(t);if(n.schema!==jr||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:Ir(n.policy??ye)}}catch{let n=xr(this.project.id);return await this.save(n),n}}async save(t){await this.storage.put(wr,JSON.stringify(t,null,2),"application/json")}},He=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:kr(),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>vr&&(t.audit=t.audit.slice(-vr))}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=Ir({...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=va(t),o=Tt(t.title),i=n.filter(m=>m.slug!==t.slug&&Tt(m.title)===o&&br(m.content)!==br(t.content)).map(m=>m.slug),a=wa(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:kr(),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 j(`Governance review not found: ${t}`,404);if(o.status!=="pending")throw new j("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 j("targetReviewId is required for merge",400);let u=s.reviews.find(m=>m.id===n.targetReviewId);if(!u)throw new j("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 j(`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(m=>{let p=s-Date.parse(m.updatedAt);return{slug:m.slug,title:m.title,updatedAt:m.updatedAt,ageDays:Math.max(0,Math.floor(p/864e5)),stale:Number.isFinite(p)&&p>o}}).filter(m=>m.stale).map(({stale:m,...p})=>p),a=new Map;for(let m of r){let p=Tt(m.title),d=a.get(p)??[];d.push(m),a.set(p,d)}let c=[...a.entries()].filter(([,m])=>m.length>1).map(([m,p])=>({title:m,pages:p.map(d=>d.slug)})),u=n.reviews.filter(m=>m.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(m=>m.tags.some(p=>p.startsWith("toolnet-auto-"))).length,manualPages:r.filter(m=>!m.tags.some(p=>p.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(m=>m.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(m=>m.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var Or="wiki/automation.v1.json",Rr="toolnet.wiki-automation.v1",Nt=8e3,Ar=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function Se(e){return ba("sha256").update(JSON.stringify(e)).digest("hex")}function he(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function Cr(e){return Array.isArray(e)?e:[]}function Nr(e){return typeof e!="string"?void 0:e.replace(/\s+/gu," ").trim()||void 0}function Ot(e){return Array.isArray(e)?e.map(Nr).filter(t=>!!t):[]}function W(e,t){for(let n of t){let r=Nr(e[n]);if(r)return r}}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 Je(e,t=0,n=""){if(t>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(Ar.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=>Je(i,t+1,n));let s=he(e);if(!s)return[];let o=[];for(let[i,a]of Object.entries(s)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();Ar.has(c)||o.push(...Je(a,t+1,i))}return o}function Pr(e){let n=ke(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(s=>Je(e[s],0,s)));return(n.length>0?n:ke(Je(e))).join(`
126
+
127
+ `).slice(0,Nt)}function Er(e,t){return W(e,["id","key","fingerprint","knowledgeId","sceneId"])??t}function Mr(e,t){return W(e,["title","name","topic","label","task","kind","type"])??t}function Ca(e){return(W(e,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function Pa(e){return(W(e,["kind","sceneKind","type"])??"").toLowerCase()}function Ea(e){let t=he(e);if(!t)return[];let n=[],r=Cr(t.knowledge);for(let[o,i]of r.entries()){let a=he(i);if(!a)continue;let c=Ca(a);if(c==="session"||c==="transient")continue;let u=Pr(a);if(u.length<20)continue;let m=Er(a,Se(a).slice(0,16)),p=Mr(a,`Durable Memory ${o+1}`);n.push({sourceKey:`memory:${m}`,sourceType:"memory",title:p,summary:W(a,["summary","description"]),content:u,tags:ke(["toolnet","auto","memory",...c?[c]:[]])})}let s=Cr(t.scenes);for(let[o,i]of s.entries()){let a=he(i);if(!a)continue;let c=Pa(a);if(c==="session-context")continue;let u=Pr(a);if(u.length<20)continue;let m=Er(a,Se(a).slice(0,16)),p=Mr(a,`Knowledge Scene ${o+1}`);n.push({sourceKey:`scene:${m}`,sourceType:"scene",title:p,summary:W(a,["summary","description"]),content:u,tags:ke(["toolnet","auto","scene",...c?[c]:[]])})}return n}function Ma(e){return Tr(e,".toolnet","memory","skills")}function Ta(e){let t=Ma(e);if(!xa(t))return{candidates:[],failed:0};let n=[],r=0,s=ja(t).filter(o=>o.endsWith(".json")).sort();for(let o of s)try{let i=JSON.parse(Ia(Tr(t,o),"utf8")),a=he(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let c=W(a,["id","fingerprint"])??Aa(o,".json"),u=W(a,["task"])??"",m=W(a,["title"])||u||`Reusable Skill ${c.slice(0,8)}`,p=W(a,["summary"])??void 0,d=Ot(a.steps),l=Ot(a.verification),g=Ot(a.files),S=[];u&&S.push(`## Task
128
+ ${u}`),p&&S.push(`## Summary
129
+ ${p}`),d.length>0&&S.push(`## Procedure
130
+ ${d.map((h,k)=>`${k+1}. ${h}`).join(`
131
+ `)}`),l.length>0&&S.push(`## Verification
132
+ ${l.map(h=>`- ${h}`).join(`
133
+ `)}`),g.length>0&&S.push(`## Relevant Files
134
+ ${g.map(h=>`- \`${h}\``).join(`
135
+ `)}`);let y=S.join(`
136
+
137
+ `).slice(0,Nt);if(y.length<20)continue;n.push({sourceKey:`skill:${c}`,sourceType:"skill",title:m,summary:p,content:y,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function Rt(e){let t=new Date().toISOString();return{schema:Rr,version:1,projectId:e,entries:[],createdAt:t,updatedAt:t}}async function Oa(e,t){let n=await e.getText(Or);if(!n)return Rt(t);try{let r=JSON.parse(n);return r.schema!==Rr||r.version!==1||r.projectId!==t||!Array.isArray(r.entries)?Rt(t):r}catch{return Rt(t)}}async function Ra(e,t){await e.put(Or,JSON.stringify(t,null,2),"application/json")}function Na(e){return`toolnet-auto-${Se(e).slice(0,12)}`}function _a(e){let t=ee(e.title).slice(0,72),n=Se(e.sourceKey).slice(0,10);return ee(`auto-${e.sourceType}-${t}-${n}`)}function Ka(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(`
138
+ `).slice(0,Nt)}function $a(e){return Se({sourceType:e.sourceType,title:e.title,summary:e.summary,content:e.content,tags:e.tags})}function Fa(e,t){return e.tags.includes(t)}async function _r(e){let t=Ea(e.hierarchy),n=Ta(e.project.rootPath),r=new Map;for(let l of[...t,...n.candidates])r.set(l.sourceKey,l);let s=[...r.values()].sort((l,g)=>l.sourceKey.localeCompare(g.sourceKey)),o={schema:"toolnet.wiki-automation-result.v1",scanned:t.length+n.candidates.length,eligible:s.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new De(new ze(e.storage,e.project));await i.initialize();let a=new He(new qe(e.storage,e.project));await a.initialize();let c=await Oa(e.storage,e.project.id),u=await i.listPages(),m=new Map(u.map(l=>[l.slug,l])),p=new Map(c.entries.map(l=>[l.sourceKey,l]));for(let l of s)try{let g=Na(l.sourceKey),S=$a(l),y=p.get(l.sourceKey),h=y?.slug??_a(l),k=m.get(h);if(k&&!Fa(k,g)){o.skipped+=1;continue}let E=ke([...l.tags,g]),T=Ka(l),C=await a.gate({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,marker:g,digest:S,title:l.title,...l.summary?{summary:l.summary}:{},content:T,tags:E},[...m.values()]);if(!C.allowed){C.mode==="pending-review"?o.reviewPending+=1:o.skipped+=1;continue}C.mode==="auto-approved"?o.autoApproved+=1:C.mode==="review-approved"&&(o.reviewApproved+=1),k?y?.digest!==S?(k=await i.updatePage(h,{title:l.title,summary:l.summary??"",content:T,tags:E}),m.set(k.slug,k),o.updated+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"updated"})):(o.unchanged+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,action:"unchanged"})):(k=await i.createPage({slug:h,title:l.title,summary:l.summary,content:T,tags:E}),m.set(k.slug,k),o.created+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"created"}));let O=new Date().toISOString(),x={sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,digest:S,marker:g,updatedAt:O},v=c.entries.findIndex(q=>q.sourceKey===l.sourceKey);v>=0?c.entries[v]=x:c.entries.push(x),p.set(l.sourceKey,x),await a.markApplied(l.sourceKey,S)}catch(g){if(g instanceof j&&g.statusCode===409){o.skipped+=1;continue}o.failed+=1}let d=new Date().toISOString();return c.updatedAt=d,c.lastRunAt=d,c.entries.sort((l,g)=>l.sourceKey.localeCompare(g.sourceKey)),await Ra(e.storage,c),o}import{createHash as Wa}from"node:crypto";import{chmodSync as $r,existsSync as La,mkdirSync as Da,readFileSync as vm,readdirSync as bm,renameSync as za,statSync as xm,writeFileSync as qa}from"node:fs";import{join as Fr}from"node:path";var Ha="toolnet.skill-memory.v1",Kr=5,Ja=16,Va=24,Ba=32;function Ga(e){return Wa("sha256").update(e).digest("hex")}function ve(e,t=Number.MAX_SAFE_INTEGER){let n=new Set,r=[];for(let s of e){let o=s.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=t))break}return r}function _t(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 Ua(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 J(e,t=360){return e&&_t(Ua(e),t)||void 0}function be(e,t){for(let n of t){let r=e[n];if(typeof r=="string"&&r.trim())return r}}function Wr(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 Lr(e,t){for(let n of t){let r=e[n];if(typeof r=="boolean")return r;if(typeof r=="string"){let s=r.trim().toLowerCase();if(["true","yes","pass","passed","success","succeeded","ok"].includes(s))return!0;if(["false","no","fail","failed","error"].includes(s))return!1}}}function Dr(e){let t=e.data??{};if(Lr(t,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=Wr(t,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let s=be(t,["status","result","outcome"]);return!!(s&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(s))}function we(e){let t=e.data??{};if(Dr(e))return!1;if(Lr(t,["passed","pass","success","succeeded","ok"])===!0||Wr(t,["exitCode","exit_code","code","statusCode"])===0)return!0;let s=be(t,["status","result","outcome"]);return s&&/\b(pass(?:ed)?|success(?:ful)?|succeeded|ok|green|complete(?:d)?)\b/iu.test(s)?!0:e.type==="commit"||e.type==="deploy"}function zr(e){let t=e.data??{},n=be(t,["path","file","filePath","filename","target"]);if(n)return J(n,260);let r=e.provenance?.files;return J(r?.[0],260)}function Kt(e){return J(be(e.data??{},["command","cmd","script"]),420)}function se(e){return J(be(e.data??{},["name","test","suite","title","message","text","result","status"]),300)}function Ya(e){let t=[];for(let n of[...e].sort((r,s)=>r.sequence-s.sequence))if(we(n)){if(n.type==="test"){let r=se(n)??Kt(n)??"Tests passed";t.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=se(n);t.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=se(n);t.push(r?`Deploy: ${r}`:"Deployment completed")}}return ve(t,10)}function Xa(e,t){let n=[];for(let r of[...e].sort((s,o)=>s.sequence-o.sequence))switch(r.type){case"file_write":case"file_edit":{let s=zr(r);s&&n.push(`Update ${s}`);break}case"command":{if(Dr(r))break;let s=Kt(r);s&&n.push(`Run: ${s}`);break}case"test":{if(!we(r))break;let s=se(r)??Kt(r)??"project tests";n.push(`Verify: ${s}`);break}case"commit":{if(!we(r))break;let s=se(r);n.push(s?`Commit: ${s}`:"Commit verified changes");break}case"deploy":{if(!we(r))break;let s=se(r);n.push(s?`Deploy: ${s}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of t.files.slice(0,8)){let s=J(r,260);s&&n.push(`Update ${s}`)}return ve(n,Ja)}function Qa(e,t){let n=[...t.files];for(let r of e){let s=zr(r);s&&n.push(s);for(let o of r.provenance?.files??[]){let i=J(o,260);i&&n.push(i)}}return ve(n,Va)}function Za(e){return ve(e.filter(t=>["file_write","file_edit","command","test","commit","deploy"].includes(t.type)).map(t=>t.id),Ba)}function ec(e){return e.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function qr(e,t,n){if(t.length===0)return[];let r=Ya(t),s=ve(n.completed.map(g=>J(g,280)??""),Kr);if(!(s.length>0||t.some(g=>["test","commit","deploy"].includes(g.type)&&we(g))))return[];let i=J(n.task,280)??J(n.nextActions[0],280),a=s.length>0?s:i?[i]:[];if(a.length===0)return[];let c=Xa(t,n);if(c.length===0)return[];let u=Qa(t,n),m=Za(t),p=Math.min(...t.map(g=>g.sequence)),d=Math.max(...t.map(g=>g.sequence)),l=ec(t);return a.slice(0,Kr).map(g=>{let S=[`Reusable procedure learned from successful task: ${g}.`,u.length>0?`Files: ${u.slice(0,6).join(", ")}.`:"",r.length>0?`Verification: ${r.slice(0,4).join("; ")}.`:""].filter(Boolean),y=JSON.stringify({projectId:e.projectId,task:g,steps:c,verification:r,files:u}),h=Ga(y);return{schema:Ha,version:1,id:`skill-${h.slice(0,24)}`,fingerprint:h,projectId:e.projectId,title:_t(`SOP: ${g}`,180),task:g,summary:_t(S.join(" "),900),steps:c,verification:r,files:u,source:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:p,lastSequence:d,eventIds:m},createdAt:l}})}function tc(e){return Fr(e.rootPath,".toolnet","memory","skills")}function nc(e){let t=tc(e);return Da(t,{recursive:!0,mode:448}),$r(t,448),t}function Hr(e,t){if(t.length===0)return{written:0,deduped:0,files:[]};let n=nc(e),r=0,s=0,o=[];for(let i of t){if(i.projectId!==e.id)throw new Error(`Skill project mismatch: ${i.projectId} != ${e.id}`);let a=Fr(n,`${i.id}.json`);if(o.push(a),La(a)){s+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;qa(c,JSON.stringify(i,null,2)+`
139
+ `,{encoding:"utf8",mode:384}),za(c,a),$r(a,384),r+=1}return{written:r,deduped:s,files:o}}function Jr(e){return String(e).padStart(12,"0")}function rc(e){return e.remotePrefix.replace("/sessions/","/memory/learned/")}var Ve=class{constructor(t){this.storage=t}storage;async write(t,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(m=>m.sequence)),o=Math.max(...n.map(m=>m.sequence)),i={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},a=JSON.stringify(i,null,2)+`
140
+ `,c=w(r.map(m=>m.fingerprint).sort().join("|")).slice(0,16),u=[rc(t),"batches",`${Jr(s)}-${Jr(o)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,a,"application/json"),u}};import{createHash as sc}from"node:crypto";function Vr(e){return String(e).padStart(12,"0")}function oc(e){return sc("sha256").update(e).digest("hex")}function ic(e){return e.remotePrefix.replace("/sessions/","/memory/hierarchy/")}var Be=class{constructor(t){this.storage=t}storage;async write(t,n,r){if(n.length===0||r.facts.length===0)return null;let s=Math.min(...n.map(u=>u.sequence)),o=Math.max(...n.map(u=>u.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:s,lastSequence:o,hierarchy:r},a=oc([...r.facts.map(u=>u.id),...r.knowledge.map(u=>u.id)].sort().join("|")).slice(0,16),c=[ic(t),"batches",`${Vr(s)}-${Vr(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,`${JSON.stringify(i,null,2)}
141
+ `,"application/json"),c}};function pc(e,t){if(!cc(e))return{events:[],nextOffset:t};let n=dc(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=uc(e,"r");try{lc(i,o,0,s,r)}finally{ac(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
142
+ `);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
143
+ `).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Ge=class{constructor(t){this.options=t;this.journal=new Ve(t.storage),this.hierarchyJournal=new Be(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,s=pc(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Le(this.options.identity,s.events),i=o.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,s.events,i));let c=!1;o.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,s.events,o.hierarchy));let u=qr(this.options.identity,s.events,o.state),m=Hr(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",o.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",o.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",o.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",o.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",o.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",m.written),this.options.wal.setSourceCursor("memory.skill.deduped",m.deduped);try{let p=cn(this.options.project.rootPath,s.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",p.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",p.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",p.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",p.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let p=await _r({project:this.options.project,storage:this.options.storage,hierarchy:o.hierarchy});this.options.wal.setSourceCursor("memory.wiki_automation.scanned",p.scanned),this.options.wal.setSourceCursor("memory.wiki_automation.eligible",p.eligible),this.options.wal.setSourceCursor("memory.wiki_automation.created",p.created),this.options.wal.setSourceCursor("memory.wiki_automation.updated",p.updated),this.options.wal.setSourceCursor("memory.wiki_automation.unchanged",p.unchanged),this.options.wal.setSourceCursor("memory.wiki_automation.skipped",p.skipped),this.options.wal.setSourceCursor("memory.wiki_automation.failed",p.failed),this.options.wal.setSourceCursor("memory.wiki_automation.review_pending",p.reviewPending),this.options.wal.setSourceCursor("memory.wiki_automation.auto_approved",p.autoApproved),this.options.wal.setSourceCursor("memory.wiki_automation.review_approved",p.reviewApproved)}catch{this.options.wal.setSourceCursor("memory.wiki_automation.failed",1)}return this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:i.length,journalWritten:a,nextOffset:s.nextOffset}}};import{closeSync as Mc,existsSync as Tc,openSync as Oc,readSync as Rc,statSync as Nc}from"node:fs";function Br(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function je(e){return e.toLowerCase().replace(/[^a-z0-9]/gu,"")}function xe(e,t,n=0){if(n>8)return;if(Array.isArray(e)){for(let s of e.slice(0,50))xe(s,t,n+1);return}let r=Br(e);if(r)for(let[s,o]of Object.entries(r))t(s,o,r),xe(o,t,n+1)}function oe(e,t){let n=[];return xe(e,(r,s)=>{t.has(je(r))&&typeof s=="string"&&s.trim()&&n.push(s.trim())}),n}function mc(e){let t=e.trim();if(!t.startsWith("{"))return null;try{return Br(JSON.parse(t))}catch{return null}}function fc(e){let t=e.data;for(let r of["tool","toolName","tool_name"]){let s=t[r];if(typeof s=="string"&&s.trim())return s.trim().toLowerCase()}let n="";return xe(t,(r,s,o)=>{if(n)return;let i=je(r);if(["tool","toolname"].includes(i)&&typeof s=="string"){n=s.trim().toLowerCase();return}if(i!=="name"||typeof s!="string")return;let a=typeof o.type=="string"?o.type.toLowerCase():"";(a.includes("tool")||a.includes("function")||a.includes("command"))&&(n=s.trim().toLowerCase())}),n}function gc(e){let t=oe(e.data,new Set(["command","cmd","script"])),n=oe(e.data,new Set(["arguments","args"]));for(let r of n){let s=mc(r);if(s)for(let o of oe(s,new Set(["command","cmd","script"])))t.push(o)}return Array.from(new Set(t.map(r=>r.trim()).filter(Boolean)))}function yc(e){let t=oe(e.data,new Set(["filepath","file_path","filename","file","path","target"].map(je)));return Array.from(new Set(t.map(n=>n.trim()).filter(n=>n.length>0&&n.length<1e3&&!n.includes(`
144
+ `))))}function hc(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 Sc(e){let t=oe(e.data,new Set(["patch","diff","arguments","input"].map(je))),n=[];for(let r of t){let s=[{regex:/^\*\*\* Update File:\s*(.+)$/gimu,action:"modified"},{regex:/^\*\*\* Add File:\s*(.+)$/gimu,action:"created"},{regex:/^\*\*\* Delete File:\s*(.+)$/gimu,action:"deleted"}];for(let o of s)for(let i of r.matchAll(o.regex)){let a=i[1]?.trim();a&&n.push({kind:"file",text:a,fileAction:o.action,confidence:.99})}}return n}function kc(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 wc(e){let t=null;return xe(e,(n,r)=>{if(t===null&&["exitcode","code"].includes(je(n))){if(typeof r=="number"&&Number.isFinite(r)){t=r;return}if(typeof r=="string"){let s=Number(r);Number.isFinite(s)&&(t=s)}}}),t}function vc(e){return oe(e,new Set(["status","state","result","output","outputsummary","message","text"]))}function bc(e){let t=wc(e.data);if(t!==null)return t===0?"passed":"failed";let n=vc(e.data).join(`
145
+ `).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 xc(e){let t=[],n=new Set;for(let r of e){let s=[r.kind,r.fileAction??"",r.checkKind??"",r.checkStatus??"",r.text].join("|");n.has(s)||(n.add(s),t.push(r))}return t}function Gr(e){let t=[],n=fc(e),r=hc(e,n);if(r)for(let s of yc(e))t.push({kind:"file",text:s,fileAction:r,confidence:e.type==="file_edit"||e.type==="file_write"?1:.96});t.push(...Sc(e));for(let s of gc(e)){t.push({kind:"command",text:s,confidence:.98});let o=kc(s);o&&t.push({kind:"test",text:s,checkKind:o,checkStatus:bc(e),confidence:.98})}return xc(t)}var jc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function ne(e){return e.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Yr(e){return ne(e).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function te(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))te(r,t,n+1);return}if(!(!e||typeof e!="object"))for(let[r,s]of Object.entries(e))(jc.has(r)||["data","payload","parts","messages"].includes(r))&&te(s,t,n+1)}}function Ue(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 Ur(e){let t=ne(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 I(e,t,n,r,s={}){let o=ne(r),i=s.key??Yr(o);return{version:1,id:w([e.projectId,n,i,t.id,o,s.status??"",s.fileAction??"",s.checkKind??"",s.checkStatus??"",s.order??""].join("|")).slice(0,32),projectId:e.projectId,kind:n,key:i,text:o,status:s.status,fileAction:s.fileAction,checkKind:s.checkKind,checkStatus:s.checkStatus,order:s.order,confidence:s.confidence??.85,occurredAt:t.timestamp,sequence:t.sequence,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventId:t.id,sourceEventId:t.sourceEventId}}function Ic(e,t,n){let r=ne(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?: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]&&s.push(I(e,t,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&s.push(I(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(;!o&&(u=c.exec(r));){let d=Number(u[1]),l=ne(u[2]??""),g=l&&!Ur(l)?`Phase ${d} - ${l}`:`Phase ${d}`;s.push(I(e,t,"phase",g,{key:`phase:${d}`,order:d,status:Ue(r),confidence:.93}))}let m=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);m?.[2]&&s.push(I(e,t,"task",m[2],{status:m[1].trim()?"completed":Ue(m[2]),confidence:.96}));let p=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(p?.[2]){let d=p[1]?Number(p[1]):void 0,l=ne(p[2]),g=Ur(l);s.push(I(e,t,"task",g&&d!==void 0?`TODO ${d}`:l,{key:d!==void 0?`task:${d}`:Yr(l),order:d,status:Ue(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 d=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");d&&s.push(I(e,t,"next_action",d,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(I(e,t,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(I(e,t,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(I(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)&&s.push(I(e,t,"activity",r,{confidence:.86})),s}function Ye(e,t){if(t.length===0)return[];let n=[],r=new Set;function s(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=[];te(i.data,c);let u=c.map(m=>ne(m)).find(m=>m.length>=8&&m.length<=1200&&!/^\[?toolnet\b/iu.test(m));u&&s(I(e,i,"request",u,{confidence:.96}))}for(let c of Gr(i))s(I(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=[];te(i.data,c);for(let u of c)s(I(e,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];te(i.data,c);for(let u of c)s(I(e,i,"task",u,{status:Ue(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&&s(I(e,i,"file",u,{fileAction:"modified",confidence:1}))}if(i.type==="test"){let c=[];te(i.data,c);for(let u of c)s(I(e,i,"test",u,{confidence:1}))}let a=[];te(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let m of Ic(e,i,u))s(m)}let o=t[t.length-1];return s(I(e,o,"session",`${e.agent}:${e.nativeSessionId}`,{key:e.sessionKey,confidence:1})),n}function Xr(e){return String(e).padStart(12,"0")}var Xe=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.sequence)),s=Math.max(...n.map(u=>u.sequence)),o={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
146
+ `,a=w(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${t.projectId}`,"work","observations",t.agent,t.nativeSessionId,`${Xr(r)}-${Xr(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Qr}from"node:path";import{mkdirSync as Ac}from"node:fs";function es(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function L(e,t=20){let n=[],r=new Set;for(let s of e.slice().reverse()){let o=es(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=t))break}return n.reverse()}function Cc(e,t=20){let n=new Map;for(let r of e){let s=`${r.kind}|${es(r.command)}`;n.delete(s),n.set(s,r)}return Array.from(n.values()).slice(-t)}function Pc(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 s=e&&Pc(t)?e.title:t.text;return{id:e?.id??w(t.key).slice(0,24),title:s,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 Ec(e,t){let n=`projects/${e.id}/work/observations/`,r=await t.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await t.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}async function Qe(e,t){let r=(await Ec(e,t)).flatMap(f=>f.observations).sort((f,b)=>{let V=f.occurredAt.localeCompare(b.occurredAt);if(V!==0)return V;let Yt=f.sequence-b.sequence;return Yt!==0?Yt:f.id.localeCompare(b.id)}),s=new Map,o=new Map,i,a,c,u,m,p=[],d=[],l=[],g=[],S=[],y=new Map,h=[],k=[],E=[],T=[],C=[],O=[];for(let f of r)switch(f.kind){case"request":i=f.text;break;case"activity":a=f.text;break;case"goal":c=f.text;break;case"plan":u=f.text;break;case"phase":s.set(f.key,Zr(s.get(f.key),f));break;case"task":o.set(f.key,Zr(o.get(f.key),f));break;case"decision":p.push(f.text);break;case"blocker":d.push(f.text);break;case"warning":l.push(f.text);break;case"next_action":g.push(f.text);break;case"file":{S.push(f.text);let b=f.fileAction??"active";y.delete(f.text),y.set(f.text,b),b==="modified"?h.push(f.text):b==="created"?k.push(f.text):b==="deleted"&&E.push(f.text);break}case"command":T.push(f.text);break;case"test":C.push(f.text),f.checkKind&&O.push({kind:f.checkKind,command:f.text,status:f.checkStatus??"unknown",updatedAt:f.occurredAt,agent:f.agent,nativeSessionId:f.nativeSessionId});break;case"session":m={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let x=Array.from(s.values()).sort((f,b)=>(f.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),v=Array.from(o.values()).sort((f,b)=>(f.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),q=x.find(f=>f.status==="in_progress")??x.find(f=>f.status==="blocked")??x.find(f=>f.status==="pending"),H=v.find(f=>f.status==="in_progress")??v.find(f=>f.status==="blocked")??v.find(f=>f.status==="pending"),ut=L([...g,...H?[H.title]:[],...!H&&q?[q.title]:[],...v.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),lt=L([...d,...x.filter(f=>f.status==="blocked").map(f=>f.title),...v.filter(f=>f.status==="blocked").map(f=>f.title)],20),ae={version:1,projectId:e.id,projectName:e.name,currentRequest:i,currentActivity:a,goal:c,plan:u,phases:x,tasks:v,decisions:L(p,20),blockers:lt,warnings:L(l,20),nextActions:ut,filesTouched:L(S,30),activeFiles:Array.from(y.entries()).filter(([,f])=>f!=="deleted").map(([f])=>f).slice(-5),modifiedFiles:L(h,30),createdFiles:L(k,30),deletedFiles:L(E,30),commands:L(T,20),tests:L(C,20),checks:Cc(O,20),currentPhase:q,currentTask:H,progress:{phasesTotal:x.length,phasesCompleted:x.filter(f=>f.status==="completed").length,tasksTotal:v.length,tasksCompleted:v.filter(f=>f.status==="completed").length,blocked:x.filter(f=>f.status==="blocked").length+v.filter(f=>f.status==="blocked").length},lastSession:m,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},ce=Qr(e.rootPath,".toolnet","work");return Ac(ce,{recursive:!0}),R(Qr(ce,"current.json"),ae),await t.put(`projects/${e.id}/work/current.json`,JSON.stringify(ae,null,2)+`
147
+ `,"application/json"),ae}async function ts(e,t){let n=await t.getText(`projects/${e.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function _c(e,t){if(!Tc(e))return{events:[],nextOffset:t};let n=Nc(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=Oc(e,"r");try{Rc(i,o,0,s,r)}finally{Mc(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
148
+ `);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
149
+ `).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Ze=class{constructor(t){this.options=t;this.journal=new Xe(t.storage)}options;journal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["work.continuity.offset"]??0),r=_c(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 s=Ye(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Qe(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as Hc,existsSync as Jc,openSync as Vc,readSync as Bc,statSync as Gc}from"node:fs";var Kc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function ie(e){return e.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function $t(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))$t(r,t,n+1);return}if(!(!e||typeof e!="object"))for(let[r,s]of Object.entries(e))(Kc.has(r)||["data","payload","parts","messages"].includes(r))&&$t(s,t,n+1)}}function K(e,t,n,r,s,o=.95){let i=ie(r);return{version:1,id:w([e.projectId,n,s.type,s.key??"",i.toLowerCase(),t.id].join("|")).slice(0,32),projectId:e.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventId:t.id,sourceEventId:t.sourceEventId,sequence:t.sequence,occurredAt:t.timestamp}}}function D(e,t){let n=e.toLowerCase();for(let r of t){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return ie(e.slice(r.length+1))}return null}function $c(e){let t=e.trimStart();return t.startsWith("- ")||t.startsWith("* ")||/^\d+[.)]\s+/u.test(t)}function Fc(e){return ie(e.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function ns(e,t){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of t){let i=[];$t(o.data,i);for(let a of i){let c={type:"project"},u=null;for(let m of a.split(/\r?\n/u)){let p=ie(m);if(!p){u=null;continue}let d=p.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let v=Number(d[1]);c={type:"phase",key:`phase:${v}`,order:v,title:ie(d[2]??"")},u=null;continue}let l=p.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let v=Number(l[1]);c={type:"task",key:`task:${v}`,order:v,title:ie(l[2]??"")},u=null;continue}let g=D(p,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(g){s(K(e,o,"mission",g,{type:"project"},.99)),u=null;continue}let S=D(p,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(S){s(K(e,o,c.type==="phase"?"phase_objective":"objective",S,c,.98)),u=null;continue}let y=D(p,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(K(e,o,c.type==="phase"?"phase_why":"why",y,c,.98)),u=null;continue}let h=D(p,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){s(K(e,o,"desired_outcome",h,{type:"project"},.98)),u=null;continue}let k=D(p,["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(k){s(K(e,o,"plan_rationale",k,{type:"project"},.98)),u=null;continue}let E=D(p,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(E){s(K(e,o,"phase_deliverable",E,c,.97)),u=null;continue}let T=D(p,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(T){s(K(e,o,"acceptance_criterion",T,c,.98)),u="acceptance_criterion";continue}let C=D(p,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(C){s(K(e,o,"dependency",C,c,.97)),u="dependency";continue}let O=D(p,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(O){s(K(e,o,"open_question",O,c,.95)),u="open_question";continue}let x=D(p,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(x){s(K(e,o,"constraint",x,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(p)){u="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(p)){u="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(p)){u="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(p)){u="constraint";continue}if(u&&$c(m)){s(K(e,o,u,Fc(m),c,.96));continue}u=null}}}return n}function rs(e){return String(e).padStart(12,"0")}var et=class{constructor(t){this.storage=t}storage;async write(t,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.evidence.sequence)),s=Math.max(...n.map(c=>c.evidence.sequence)),o={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=w(n.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${t.projectId}`,"work","semantic","observations",t.agent,t.nativeSessionId,`${rs(r)}-${rs(s)}-${i}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,JSON.stringify(o,null,2)+`
150
+ `,"application/json"),a}};import{mkdirSync as Wc}from"node:fs";import{join as ss}from"node:path";function Lc(e){return{value:e.value,confidence:e.confidence,evidence:e.evidence}}function Dc(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 Dc(t,e)?t:e}function U(e,t=30){let n=new Set,r=[];for(let s of e){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-t)}async function zc(e,t){let n=`projects/${e.id}/work/semantic/observations/`,r=await t.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await t.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}function qc(e){return{key:e.scopeKey??`phase:${e.scopeOrder??0}`,order:e.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function os(e,t){let r=(await zc(e,t)).flatMap(S=>S.observations).sort((S,y)=>{let h=S.evidence.occurredAt.localeCompare(y.evidence.occurredAt);return h!==0?h:S.evidence.sessionKey===y.evidence.sessionKey?S.evidence.sequence-y.evidence.sequence:S.id.localeCompare(y.id)}),s,o,i,a,c,u=new Map,m=[],p=[],d=[];for(let S of r){let y=Lc(S);if(S.scope==="phase"&&S.scopeKey){let h=u.get(S.scopeKey)??qc(S);switch(S.kind){case"phase_objective":h.objective=G(h.objective,y);break;case"phase_why":h.why=G(h.why,y);break;case"phase_deliverable":h.deliverable=G(h.deliverable,y);break;case"acceptance_criterion":h.acceptanceCriteria.push(y);break;case"dependency":h.dependencies.push(y);break;case"open_question":h.openQuestions.push(y);break;case"constraint":h.constraints.push(y);break;case"note":h.notes.push(y);break}u.set(h.key,h);continue}switch(S.kind){case"mission":s=G(s,y);break;case"objective":o=G(o,y);break;case"why":i=G(i,y);break;case"desired_outcome":a=G(a,y);break;case"plan_rationale":c=G(c,y);break;case"open_question":m.push(y);break;case"constraint":p.push(y);break;case"note":d.push(y);break}}for(let S of u.values())S.acceptanceCriteria=U(S.acceptanceCriteria,20),S.dependencies=U(S.dependencies,15),S.openQuestions=U(S.openQuestions,15),S.constraints=U(S.constraints,15),S.notes=U(S.notes,20);let l={version:1,projectId:e.id,projectName:e.name,mission:s,activeObjective:o,why:i,desiredOutcome:a,planRationale:c,phases:Array.from(u.values()).sort((S,y)=>S.order-y.order),openQuestions:U(m,20),constraints:U(p,20),notes:U(d,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},g=ss(e.rootPath,".toolnet","work");return Wc(g,{recursive:!0}),R(ss(g,"semantic-current.json"),l),await t.put(`projects/${e.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
151
+ `,"application/json"),l}function Uc(e,t){if(!Jc(e))return{events:[],nextOffset:t};let n=Gc(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=Vc(e,"r");try{Bc(o,s,0,s.length,r)}finally{Hc(o)}let i=s.toString("utf8"),a=i.lastIndexOf(`
152
+ `);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
153
+ `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var tt=class{constructor(t){this.options=t;this.journal=new et(t.storage)}options;journal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["work.semantic.offset"]??0),r=Uc(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 s=ns(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await os(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{existsSync as hu,mkdirSync as Su}from"node:fs";import{join as Wt}from"node:path";import{existsSync as cs,mkdirSync as Yc,readFileSync as Xc,statSync as is,writeFileSync as Qc}from"node:fs";import{dirname as Zc,join as eu}from"node:path";var as=64*1024,tu=`# ToolNet Project Operating Manual
154
+
155
+ This file contains persistent instructions for AI agents working on this project.
156
+
157
+ ## Critical Rules
158
+
159
+ <!--
160
+ Examples:
161
+
162
+ - [enforce] Never edit production files directly.
163
+ - [enforce] Edit source only in /path/to/source.
164
+ - [enforce] Deploy only with ./deploy.sh --apply
165
+ -->
166
+
167
+ ## Workflow
168
+
169
+ <!--
170
+ Describe the correct working process.
171
+ -->
172
+
173
+ ## Architecture
174
+
175
+ <!--
176
+ Important architecture conventions.
177
+ -->
178
+
179
+ ## Verification
180
+
181
+ <!--
182
+ Tests / QA required after changes.
183
+ -->
184
+
185
+ ## Known Gotchas
186
+
187
+ <!--
188
+ Things an AI agent should always remember.
189
+ -->
190
+
191
+ ## Preferences
192
+
193
+ <!--
194
+ - [advisory] Prefer small focused files.
195
+ -->
196
+ `;function us(e){return eu(e.rootPath,".toolnet","PROJECT.md")}function nu(e){return e.normalize("NFKC").replace(/\s+/g," ").trim()}function ru(e){let t=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=r.exec(e);){let o=s[1].toLowerCase(),i=nu(s[2]);if(!i)continue;let a=`${o}:${i.toLowerCase()}`;n.has(a)||(n.add(a),t.push({id:w(a).slice(0,24),mode:o,text:i,source:"manual"}))}return t}function su(e){let t=us(e);return cs(t)||(Yc(Zc(t),{recursive:!0}),Qc(t,tu,{encoding:"utf8",mode:384})),t}function ls(e,t=!1){let n=t?su(e):us(e);if(!cs(n))return null;if(is(n).size>as)throw new Error(`PROJECT.md exceeds ${as} bytes`);let s=Xc(n,"utf8");return{path:n,content:s,digest:w(s),rules:ru(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(is(n).mtimeMs).toISOString()}}import{existsSync as ou,mkdirSync as iu,readFileSync as au,renameSync as cu,writeFileSync as uu}from"node:fs";import{dirname as lu,join as du}from"node:path";function pu(e,t){iu(lu(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;uu(n,`${JSON.stringify(t,null,2)}
197
+ `,{encoding:"utf8",mode:384}),cu(n,e)}function ys(e){return du(e.rootPath,".toolnet","work","current.json")}function Ft(e){let t=ys(e);if(!ou(t))return null;try{let n=JSON.parse(au(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function nt(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(e,t,n){let r=[],s=new Set;for(let o of[...e,...t].reverse()){let i=nt(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function mu(e,t,n=20){let r=new Map;for(let s of[...e,...t]){let o=`${s.kind}|${nt(s.command)}`;r.delete(o),r.set(o,s)}return Array.from(r.values()).slice(-n)}function fu(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 ds(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 s=e&&fu(t)?e.title:t.text;return{id:e?.id??t.id,title:s,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 ps(e){let t=new Map;for(let n of e){let r=n.order!==void 0?`order:${n.order}`:nt(n.title);t.set(r,n)}return t}function ms(e){return e.order!==void 0?`order:${e.order}`:nt(e.key||e.text)}function fs(e){return Array.from(e).sort((t,n)=>{let r=t.order??Number.MAX_SAFE_INTEGER,s=n.order??Number.MAX_SAFE_INTEGER;return r!==s?r-s:t.updatedAt.localeCompare(n.updatedAt)})}function gs(e){return e.find(t=>t.status==="in_progress")??e.find(t=>t.status==="blocked")??e.find(t=>t.status==="pending")}function hs(e,t){let n=Ft(e),r=ps(n?.phases??[]),s=ps(n?.tasks??[]),o=n?.currentRequest,i=n?.currentActivity,a=n?.goal,c=n?.plan,u=n?.lastSession,m=[],p=[],d=[],l=[],g=[],S=[...n?.activeFiles??[]],y=[],h=[],k=[],E=[],T=[],C=[],O=[...t].sort((f,b)=>{let V=f.occurredAt.localeCompare(b.occurredAt);return V!==0?V:f.sequence-b.sequence});for(let f of O)switch(f.kind){case"request":o=f.text;break;case"activity":i=f.text;break;case"goal":a=f.text;break;case"plan":c=f.text;break;case"phase":{let b=ms(f);r.set(b,ds(r.get(b),f));break}case"task":{let b=ms(f);s.set(b,ds(s.get(b),f));break}case"decision":m.push(f.text);break;case"blocker":p.push(f.text);break;case"warning":d.push(f.text);break;case"next_action":l.push(f.text);break;case"file":{g.push(f.text);let b=f.fileAction??"active",V=S.indexOf(f.text);V>=0&&S.splice(V,1),b!=="deleted"&&S.push(f.text),b==="modified"?y.push(f.text):b==="created"?h.push(f.text):b==="deleted"&&k.push(f.text);break}case"command":E.push(f.text);break;case"test":T.push(f.text),f.checkKind&&C.push({kind:f.checkKind,command:f.text,status:f.checkStatus??"unknown",updatedAt:f.occurredAt,agent:f.agent,nativeSessionId:f.nativeSessionId});break;case"session":u={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let x=fs(r.values()),v=fs(s.values()),q=gs(x),H=gs(v),ut=$(n?.nextActions??[],[...l,...H?[H.title]:[],...!H&&q?[q.title]:[],...v.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),lt=$(n?.blockers??[],[...p,...x.filter(f=>f.status==="blocked").map(f=>f.title),...v.filter(f=>f.status==="blocked").map(f=>f.title)],20),ae=O.length>0?O[O.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),ce={version:1,projectId:e.id,projectName:e.name,currentRequest:o,currentActivity:i,goal:a,plan:c,phases:x,tasks:v,decisions:$(n?.decisions??[],m,20),blockers:lt,warnings:$(n?.warnings??[],d,20),nextActions:ut,filesTouched:$(n?.filesTouched??[],g,30),activeFiles:$([],S,5),modifiedFiles:$(n?.modifiedFiles??[],y,30),createdFiles:$(n?.createdFiles??[],h,30),deletedFiles:$(n?.deletedFiles??[],k,30),commands:$(n?.commands??[],E,20),tests:$(n?.tests??[],T,20),checks:mu(n?.checks??[],C,20),currentPhase:q,currentTask:H,progress:{phasesTotal:x.length,phasesCompleted:x.filter(f=>f.status==="completed").length,tasksTotal:v.length,tasksCompleted:v.filter(f=>f.status==="completed").length,blocked:x.filter(f=>f.status==="blocked").length+v.filter(f=>f.status==="blocked").length},lastSession:u,updatedAt:ae};return pu(ys(e),ce),ce}function M(e,t){let n=new Set,r=[];for(let s of e){let o=s.replace(/\s+/g," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=t))break}return r}function Ss(e){if(e)return{id:e.id,title:e.title,status:e.status}}function gu(e,t=[]){let n=t.slice(-10);if(n.some(s=>s.status==="failed"))return"failing";if(n.some(s=>s.status==="passed"))return"passing";let r=e.slice(-10).join(`
198
+ `).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function yu(e){return w(JSON.stringify(e))}function ks(e){let{project:t,identity:n,state:r}=e,s=r.activeFiles?.at(-1)??r.filesTouched.at(-1),o=r.phases.filter(k=>k.status==="completed").map(k=>k.title),i=r.tasks.filter(k=>k.status==="completed").map(k=>k.title),a=r.phases.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),c=r.tasks.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),u=new Set(r.tasks.filter(k=>k.status==="completed").map(k=>k.title.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),m=M(r.nextActions.filter(k=>!u.has(k.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),10),p=M([...c,...m],15),d=M(r.tests.slice().reverse(),10),l=M([...(r.activeFiles??[]).slice().reverse(),...r.filesTouched.slice().reverse()],20),g={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:Ss(r.currentPhase),task:Ss(r.currentTask),file:s},completed:{phases:M(o,20),tasks:M(i,30)},remaining:{phases:M(a,20),tasks:M(c,30),todos:p},nextAction:m[0],blockers:M(r.blockers.slice().reverse(),10),decisions:M(r.decisions.slice().reverse(),10),files:{current:s,recent:l,active:M(r.activeFiles??[],10),modified:M(r.modifiedFiles??[],20),created:M(r.createdFiles??[],20),deleted:M(r.deletedFiles??[],20)},tests:{status:gu(r.tests,r.checks),recent:d,checks:(r.checks??[]).slice(-10).map(k=>({kind:k.kind,status:k.status,command:k.command}))},attention:M(e.attention??[],20),progress:r.progress},{capturedAt:S,source:y,...h}=g;return{...g,stateDigest:yu(h)}}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 ws(e,t,n,r,s){if(!ku(n))return null;let o=ls(e,!1),a=[...o?o.rules.filter(p=>p.mode==="enforce").map(p=>p.text):[],...n.warnings].slice(0,20),c=ks({project:e,identity:t,state:n,reason:r,sequence:s,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:s},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(p=>p.status!=="completed"&&p.status!=="cancelled"),incompleteTasks:n.tasks.filter(p=>p.status!=="completed"&&p.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 vs(e,t){let n=Wt(e.rootPath,".toolnet","work","handoffs");Su(n,{recursive:!0});let r=Wt(n,`${t.id}.json`);hu(r)||R(r,t),R(Wt(e.rootPath,".toolnet","work","handoff-latest.json"),t)}function bs(e){let t=ws(e.project,e.identity,e.state,e.reason,e.sequence);return t?(vs(e.project,t),t):null}var rt=class{constructor(t){this.options=t}options;async capture(t,n){let r=Ft(this.options.project);r||(r=await ts(this.options.project,this.options.storage)),r||(r=await Qe(this.options.project,this.options.storage));let s=ws(this.options.project,this.options.identity,r,t,n);if(!s)return null;vs(this.options.project,s);let o=`projects/${this.options.project.id}/work/handoffs/${s.id}.json`;return await this.options.storage.exists(o)||await this.options.storage.put(o,JSON.stringify(s,null,2)+`
199
+ `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(s,null,2)+`
200
+ `,"application/json"),s}};import{existsSync as wu,readFileSync as vu,writeFileSync as bu}from"node:fs";import{join as xu}from"node:path";var js="<!-- TOOLNET:STABLE-WORK:BEGIN -->",Lt="<!-- TOOLNET:STABLE-WORK:END -->";function Dt(e){switch(e.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function z(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${n}`)]:[]}function xs(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${Dt(n)} ${n.title}`)]:[]}function ju(e){let t=[js,"# 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:",`${Dt(e.currentPhase)} ${e.currentPhase.title}`),e.currentTask&&t.push("","Current task:",`${Dt(e.currentTask)} ${e.currentTask.title}`),t.push(...xs("Phases",e.phases)),t.push(...xs("TODO / Tasks",e.tasks)),t.push(...z("Next actions",e.nextActions)),t.push(...z("Blockers",e.blockers)),t.push(...z("Important decisions",e.decisions)),t.push(...z("Active files",e.activeFiles??[])),t.push(...z("Modified files",e.modifiedFiles??[])),t.push(...z("Created files",e.createdFiles??[])),t.push(...z("Deleted files",e.deletedFiles??[])),t.push(...z("Files touched",e.filesTouched)),t.push(...z("Recent commands",e.commands??[])),t.push(...z("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.",Lt),t.join(`
201
+ `)}function Is(e,t){let n=xu(e.rootPath,".toolnet","current.md"),r="";if(wu(n))try{r=vu(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let s=ju(t),o=r.indexOf(js),i=r.indexOf(Lt),a;o>=0&&i>=o?a=[r.slice(0,o).trimEnd(),s,r.slice(i+Lt.length).trimStart()].filter(Boolean).join(`
202
+
203
+ `):a=r.trim()?`${r.trim()}
204
+
205
+ ${s}`:s,bu(n,`${a.trim()}
206
+ `,{encoding:"utf8",mode:384})}import{existsSync as As,mkdirSync as Iu,readFileSync as Au}from"node:fs";import{join as zt}from"node:path";function Cs(e){return zt(e.rootPath,".toolnet","memory","checkpoints")}function Ps(e){return zt(Cs(e),"latest.json")}function Cu(e){let t=Ps(e);if(!As(t))return null;try{let n=JSON.parse(Au(t,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==e.id?null:n}catch{return null}}function Pu(e){return["rule","architecture","decision","fix"].includes(e)}function Eu(e,t){return t.length===0?[]:Le(e,t).candidates.filter(r=>Pu(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 Mu(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 Tu(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 Es(e,t,n,r){let s=Cu(e),o=Mu(s?.durableFacts??[],Eu(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),m=r.tasks.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),p={work:Tu(r),durableFacts:o.map(y=>y.fingerprint).sort()},d=w(JSON.stringify(p)).slice(0,32),l={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:m},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:d},g=Cs(e);Iu(g,{recursive:!0,mode:448});let S=zt(g,`${d}.json`);return As(S)||R(S,l),R(Ps(e),l),l}function st(e,t,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=Ye(t,n);if(r.length===0)return{updated:!1,observations:0};let s=hs(e,r);Is(e,s),Vn(e,{agent:t.agent,nativeSessionId:t.nativeSessionId,observations:r,workState:s});try{Es(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 ot=class{identity;wal;remote;sanitizer=new Y;learner;continuity;semantic;handoff;project;title;metadata;constructor(t){this.project=t.project,this.identity=$e(t.project,t.agent,t.nativeSessionId),this.title=t.title,this.metadata=this.sanitizer.sanitizeValue(t.metadata??{}),this.wal=new re(this.identity,t.eventContext),this.remote=new Fe(t.storage,t.maxEventsPerChunk??100,t.maxChunkBytes??512*1024),this.learner=new Ge({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.continuity=new Ze({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.semantic=new tt({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.handoff=new rt({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{st(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)}};var it=4e3,qt=20,Ht=30,Ms=4,Jt=20;function Vt(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function at(e,t=0){if(t>=Ms)return typeof e=="string"?e.length>it?`${e.slice(0,it)}\u2026`:e:Array.isArray(e)?`[array:${e.length}]`:Vt(e)?`[object:${Object.keys(e).length}]`:e;if(typeof e=="string")return e.length>it?`${e.slice(0,it)}\u2026`:e;if(Array.isArray(e)){let n=e.slice(0,qt).map(r=>at(r,t+1));return e.length>qt&&n.push(`[+${e.length-qt} items]`),n}if(Vt(e)){let n={},r=Object.entries(e);for(let[s,o]of r.slice(0,Ht))n[s]=at(o,t+1);return r.length>Ht&&(n.__truncatedKeys=r.length-Ht),n}return e}function Bt(e,t,n=0){if(!(n>Ms||t.size>=Jt)){if(Array.isArray(e)){for(let r of e)if(Bt(r,t,n+1),t.size>=Jt)break;return}if(Vt(e))for(let[r,s]of Object.entries(e)){let o=r.toLowerCase().replace(/[^a-z]/g,"");if((o==="path"||o==="filepath"||o==="filename")&&typeof s=="string"&&s.trim()&&t.add(s.trim()),Bt(s,t,n+1),t.size>=Jt)break}}}function Ie(e){try{return w(Pe(e)).slice(0,20)}catch{return w(String(e)).slice(0,20)}}function Ou(e){if(typeof e=="number"&&Number.isFinite(e)){let t=new Date(e);if(!Number.isNaN(t.getTime()))return t.toISOString()}if(typeof e=="string"&&e.trim()){let t=new Date(e);if(!Number.isNaN(t.getTime()))return t.toISOString()}return new Date().toISOString()}function Ru(e,t){let n=(e??"").toLowerCase();return n==="read"||n==="view"||n.includes("read_file")||n.includes("list_dir")||n.includes("listdir")||n.includes("grep")||n.includes("glob")||n.includes("search")?null:t.length>0&&(n.includes("edit")||n.includes("patch")||n.includes("replace"))?"file_edit":t.length>0&&(n.includes("write")||n.includes("create")||n.includes("delete"))?"file_write":n.includes("bash")||n.includes("shell")||n.includes("terminal")||n.includes("command")||n.includes("execute")?"command":"tool_result"}function Gt(e,t){let r={timestamp:Ou(e.timestamp),cwd:e.cwd,source:e.agent,provenance:{source:`${e.agent}-hook`}};if(e.event==="SessionStart")return[{...r,type:"session_start",sourceEventId:`${e.agent}:${e.sessionId}:start`,data:{sessionId:e.sessionId,cwd:e.cwd}}];if(e.event==="UserPromptSubmit"){let s=e.prompt?.trim();return s?[{...r,type:"user_prompt",role:"user",sourceEventId:`${e.agent}:${e.sessionId}:prompt:`+Ie(s),data:{content:s}}]:[]}if(e.event==="PostToolUse"){let s=new Set;Bt(e.toolInput,s);let o=[...s],i=Ru(e.toolName,o);if(!i)return[];let a=at(e.toolInput),c=at(e.toolResponse);return[{...r,type:i,sourceEventId:[e.agent,e.sessionId,"tool",Ie({toolName:e.toolName,input:a,response:c})].join(":"),data:{tool:e.toolName,input:a,response:c,files:o},provenance:{source:`${e.agent}-hook`,files:o.length>0?o:void 0}}]}if(e.event==="AssistantMessage"){let s=e.assistantResponse?.trim();return s?[{...r,type:"assistant_message",role:"assistant",sourceEventId:`${e.agent}:${e.sessionId}:assistant:`+Ie(s),data:{content:s}}]:[]}if(e.event==="Stop"){let s=[],o=e.assistantResponse?.trim();return o&&s.push({...r,type:"assistant_message",role:"assistant",sourceEventId:`${e.agent}:${e.sessionId}:assistant:`+Ie(o),data:{content:o}}),s.push({...r,type:"session_idle",sourceEventId:`${e.agent}:${e.sessionId}:idle:`+Ie({sessionId:e.sessionId,response:o??""}),data:{sessionId:e.sessionId}}),s}return[]}function Ku(e){let t=kt(e);if(!t||!Nu(_u(t,".toolnet","project.json")))return null;try{return new Te().detect(t)}catch{return null}}function $u(e,t){let n=Gt(t,e);if(n.length===0)return 0;let r=$e(e,t.agent,t.sessionId),o=new re(r,{source:t.agent,cwd:t.cwd}).append(n);return st(e,r,o),o.length}async function Fu(e,t,n,r){let s=Ee(),o=zn(Ln({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),{attempts:2}),i=new _e(o,e.id,e.name,e.remote??e.name);await new ot({project:e,storage:i,agent:t,nativeSessionId:n,metadata:{source:`${t}-hook`},eventContext:{source:t,cwd:r}}).flush()}async function Ts(e,t={}){if(!e.cwd||!e.sessionId)return{active:!1,captured:0,flushed:!1};let n=Ku(e.cwd);if(!n)return{active:!1,captured:0,flushed:!1};let r=0;try{r=$u(n,e)}catch(o){return{active:!0,projectRoot:n.rootPath,sessionId:e.sessionId,captured:0,flushed:!1,error:o instanceof Error?o.message:String(o)}}if(e.event==="PostToolUse"||e.event==="AssistantMessage"||e.event==="Stop")try{Gn(n)}catch{}if(e.event!=="Stop")return{active:!0,projectRoot:n.rootPath,sessionId:e.sessionId,captured:r,flushed:!1};let s=t.flushSession??Fu;try{return await s(n,e.agent,e.sessionId,e.cwd),{active:!0,projectRoot:n.rootPath,sessionId:e.sessionId,captured:r,flushed:!0}}catch(o){return{active:!0,projectRoot:n.rootPath,sessionId:e.sessionId,captured:r,flushed:!1,error:o instanceof Error?o.message:String(o)}}}function Os(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Ae(...e){for(let t of e){let n=Os(t);if(n)return n}}function Wu(e){switch(Os(e)){case"sessionStart":case"SessionStart":return"SessionStart";case"beforeSubmitPrompt":case"UserPromptSubmit":case"userPromptSubmit":return"UserPromptSubmit";case"postToolUse":case"PostToolUse":return"PostToolUse";case"afterAgentResponse":return"AssistantMessage";case"stop":case"Stop":return"Stop";default:return null}}function Rs(e,t=process.env){let n=Wu(t.TOOLNET_HOOK_EVENT??e.hook_event_name??e.hookEventName);if(!n)return null;let r=Ae(e.session_id,e.sessionId,e.conversation_id,t.TOOLNET_CURSOR_SESSION_ID),s=Ae(e.cwd,e.workspaceRoot,t.CURSOR_PROJECT_DIR,t.CLAUDE_PROJECT_DIR);return!r||!s?null:{agent:"cursor",event:n,sessionId:r,cwd:s,timestamp:typeof e.timestamp=="string"||typeof e.timestamp=="number"?e.timestamp:void 0,prompt:Ae(e.prompt),toolName:Ae(e.tool_name,e.toolName,e.tool),toolInput:e.tool_input??e.toolInput??e.tool_args??e.toolArgs??e.input,toolResponse:e.tool_response??e.tool_result??e.toolResult??e.result??e.output,assistantResponse:Ae(e.text,e.assistant_response,e.assistantResponse,e.last_assistant_message)}}async function Ns(e,t={},n=process.env){let r=Rs(e,n);return r?Ts(r,t):{active:!1,captured:0,flushed:!1}}import{createHash as Lu}from"node:crypto";import{closeSync as Du,existsSync as zu,mkdirSync as qu,openSync as Hu,readFileSync as Ju,rmSync as Vu,statSync as _s,writeFileSync as Bu}from"node:fs";import{tmpdir as Gu}from"node:os";import{join as Ks}from"node:path";function A(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Ut(e){if(Array.isArray(e))return e.map(Ut);if(e&&typeof e=="object"){let t=e;return Object.fromEntries(Object.keys(t).sort().map(n=>[n,Ut(t[n])]))}return e}function ct(e){return A(e.sessionId)??A(e.session_id)??A(e.conversation_id)??A(e.conversationId)??"unknown-session"}function Uu(e){return A(e.toolUseId)??A(e.tool_use_id)??A(e.toolCallId)??A(e.tool_call_id)??A(e.callId)??A(e.call_id)??A(e.generation_id)??A(e.generationId)}function Yu(e){return A(e.prompt)??A(e.userPrompt)??A(e.user_prompt)??A(e.originalPrompt)??A(e.original_prompt)}function Xu(e){let t=e.timestamp;return typeof t=="string"||typeof t=="number"?String(t):void 0}function Qu(e){let t=Uu(e.input),n=Yu(e.input),r=Xu(e.input),s=t?{agent:e.agent,event:e.event,session:ct(e.input),nativeId:t}:n?{agent:e.agent,event:e.event,session:ct(e.input),prompt:n,timestamp:r}:{agent:e.agent,event:e.event,session:ct(e.input),input:Ut(e.input)};return Lu("sha256").update(JSON.stringify(s)).digest("hex")}function Zu(e){return e.directory??Ks(Gu(),"toolnet-memory-hook-dedupe")}function el(e){try{let t=JSON.parse(Ju(e,"utf8"));return typeof t.createdAt=="number"?t.createdAt:_s(e).mtimeMs}catch{try{return _s(e).mtimeMs}catch{return}}}function tl(e,t,n){let r=el(e);return r===void 0||t-r>n}function $s(e){let t=e.ttlMs??1e4,n=e.nowMs??Date.now(),r=Zu(e),s=Qu(e),o=Ks(r,`${s}.json`);qu(r,{recursive:!0,mode:448});for(let i=0;i<2;i+=1)try{let a=Hu(o,"wx",384);try{Bu(a,JSON.stringify({createdAt:n,agent:e.agent,event:e.event,sessionId:ct(e.input)}),"utf8")}finally{Du(a)}return{duplicate:!1,key:s,file:o}}catch(a){if((a&&typeof a=="object"&&"code"in a?String(a.code):"")!=="EEXIST")throw a;if(i===0&&zu(o)&&tl(o,n,t)){Vu(o,{force:!0});continue}return{duplicate:!0,key:s,file:o}}return{duplicate:!0,key:s,file:o}}async function nl(){let e="";for await(let t of process.stdin)e+=t.toString();if(!e.trim())return{};try{return JSON.parse(e)}catch{return{}}}async function rl(){let e=await nl(),t=Pn(e);if(t==="preToolUse"||t==="PreToolUse"){let n=Tn(e);n.blocked&&(process.stdout.write(JSON.stringify(On(n.reason??"ToolNet continuity guard blocked this tool."))),process.exitCode=2);return}if(!(t&&$s({agent:"cursor",event:t,input:e,directory:process.env.TOOLNET_HOOK_DEDUPE_DIR}).duplicate)){if(await Ns(e),t==="sessionStart"||t==="SessionStart"){process.stdout.write(JSON.stringify(En(e)));return}(t==="beforeSubmitPrompt"||t==="UserPromptSubmit")&&Mn(e)}}rl().catch(()=>{process.exitCode=0});