toolnet-memory 0.3.3 → 0.3.5

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.
@@ -1,43 +1,44 @@
1
- import{existsSync as Ye,mkdirSync as We,readFileSync as Ue,renameSync as Qe,rmSync as Ze,writeFileSync as Xe}from"node:fs";import{isAbsolute as qe,join as re,relative as et}from"node:path";import{existsSync as ie,readFileSync as ae}from"node:fs";import{homedir as ce}from"node:os";import{join as ue}from"node:path";function de(e){let t=e.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?(t=t.slice(1,-1),t.replace(/\\n/g,`
2
- `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function le(){let e=process.env.TOOLNET_GLOBAL_ENV??ue(ce(),".config","toolnet-memory",".env");if(!ie(e))return;let t=ae(e,"utf8");for(let n of t.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let s=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=de(r.slice(o+1)))}}le();import{createHash as fe}from"node:crypto";import{existsSync as w,mkdirSync as pe,readFileSync as me,renameSync as ge,writeFileSync as ye}from"node:fs";import{basename as he,dirname as h,join as x,parse as _,resolve as g}from"node:path";var P=".toolnet",Se="project.json";function xe(e){return fe("sha256").update(e).digest("hex").slice(0,16)}function v(e){return x(e,P,Se)}function ke(e){return w(v(e))}function be(e,t){let n=g(e),r=_(n).root;for(;;){if(ke(n))return n;if(n===r||t&&n===g(t))break;let o=h(n);if(o===n)break;n=o}return null}function we(e){let t=g(e),n=_(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(s=>w(x(t,s))))return t;if(t===n)break;let o=h(t);if(o===t)break;t=o}return g(e)}function ve(e){let t;try{t=JSON.parse(me(e,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${e}: ${o instanceof Error?o.message:String(o)}`)}if(!t||typeof t!="object")throw new Error(`Invalid ToolNet project manifest: ${e}`);let n=t;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${e}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${e}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:h(h(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 j(e,t){let n=x(e,P);pe(n,{recursive:!0});let r=v(e),o=`${r}.tmp-${process.pid}`;ye(o,JSON.stringify(t,null,2)+`
3
- `,{encoding:"utf8",mode:384}),ge(o,r)}function I(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 S=class{detect(t=process.cwd()){let n=g(t),r=we(n),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>w(x(r,p))),i=be(n,s?r:void 0);if(i){let p=v(i),l=ve(p);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),j(i,l)),I(l,i)}let c=new Date().toISOString(),a=he(r),u={version:1,id:xe(r),name:a,remote:a,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return j(r,u),I(u,r)}};import*as f from"fs";import*as d from"path";function A(e){return e?Math.ceil(e.length/3.5):0}function Ae(e,t){if(!e)return"";if(A(e)<=t)return e;let r=Math.floor(t*3.5),o=e.slice(0,r),s=o.lastIndexOf("."),i=o.lastIndexOf(`
4
- `),c=Math.max(s,i);return c>r*.7?o.slice(0,c+1):o}function N(e,t){if(!e)return"";let n=e.split(`
5
- `).filter(s=>s.trim());if(n.length<=t)return e;let r=n.slice(0,t),o=n.length-t;return[...r,`... (${o} more items omitted)`].join(`
6
- `)}function Ce(e,t){let{maxTokens:n,trimMarker:r="[Context trimmed by ToolNet Memory token budget]"}=t;if(e.length===0)return"";let o=[...e].sort((a,u)=>u.priority-a.priority),s=[],i=0,c=!1;for(let a of o){let u=`# ${a.title}
7
-
8
- `,p=A(u),l=A(a.content),y=p+l;if(i+y<=n)s.push(u+a.content),i+=y;else{let m=n-i-p;if(m>50){let k=Ae(a.content,m);s.push(u+k),i=n,c=!0}else c=!0;break}}return c&&s.push(`
1
+ import{existsSync as Xs,mkdirSync as Zs,readFileSync as Qs,renameSync as eo,rmSync as to,writeFileSync as no}from"node:fs";import{isAbsolute as ro,join as rn,relative as so}from"node:path";import{existsSync as un,readFileSync as ln}from"node:fs";import{homedir as dn}from"node:os";import{join as fn}from"node:path";function mn(e){let t=e.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?(t=t.slice(1,-1),t.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function pn(){let e=process.env.TOOLNET_GLOBAL_ENV??fn(dn(),".config","toolnet-memory",".env");if(!un(e))return;let t=ln(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]=mn(r.slice(s+1)))}}pn();function D(e,t){return e===void 0?t:["1","true","yes","on"].includes(e.toLowerCase())}function K(e,t){if(!e)return t;let n=Number(e);return Number.isFinite(n)?n:t}function Te(){return{memory:{autoCapture:D(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:D(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:D(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:D(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:K(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:K(process.env.MEMORY_RERANK_TOP,10),finalContext:K(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:K(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:D(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:K(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as gn}from"node:crypto";import{existsSync as oe,mkdirSync as hn,readFileSync as yn,renameSync as kn,writeFileSync as Sn}from"node:fs";import{basename as bn,dirname as U,join as X,parse as Pe,resolve as z}from"node:path";var Re=".toolnet",xn="project.json";function wn(e){return gn("sha256").update(e).digest("hex").slice(0,16)}function ie(e){return X(e,Re,xn)}function vn(e){return oe(ie(e))}function In(e,t){let n=z(e),r=Pe(n).root;for(;;){if(vn(n))return n;if(n===r||t&&n===z(t))break;let s=U(n);if(s===n)break;n=s}return null}function An(e){let t=z(e),n=Pe(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>oe(X(t,o))))return t;if(t===n)break;let s=U(t);if(s===t)break;t=s}return z(e)}function Mn(e){let t;try{t=JSON.parse(yn(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:U(U(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 je(e,t){let n=X(e,Re);hn(n,{recursive:!0});let r=ie(e),s=`${r}.tmp-${process.pid}`;Sn(s,JSON.stringify(t,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),kn(s,r)}function Oe(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 Y=class{detect(t=process.cwd()){let n=z(t),r=An(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>oe(X(r,f))),i=In(n,o?r:void 0);if(i){let f=ie(i),m=Mn(f);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),je(i,m)),Oe(m,i)}let d=new Date().toISOString(),u=bn(r),a={version:1,id:wn(r),name:u,remote:u,rootPath:r,createdAt:d,updatedAt:d,graphVersion:0,memoryVersion:0};return je(r,a),Oe(a,r)}};var Cn=[{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}],Z=class{scan(t){let n=[];for(let r of Cn){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 q=class{scanner=new Z;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*as C from"fs";import*as I from"path";function ce(e){return e?Math.ceil(e.length/3.5):0}function ae(e,t){if(!e)return"";if(ce(e)<=t)return e;let r=Math.floor(t*3.5),s=e.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
4
+ `),d=Math.max(o,i);return d>r*.7?s.slice(0,d+1):s}function Ne(e,t){if(!e)return"";let n=e.split(`
5
+ `).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(`
6
+ `)}function En(e,t){let{maxTokens:n,trimMarker:r="[Context trimmed by ToolNet Memory token budget]"}=t;if(e.length===0)return"";let s=[...e].sort((u,a)=>a.priority-u.priority),o=[],i=0,d=!1;for(let u of s){let a=`# ${u.title}
7
+
8
+ `,f=ce(a),m=ce(u.content),c=f+m;if(i+c<=n)o.push(a+u.content),i+=c;else{let l=n-i-f;if(l>50){let g=ae(u.content,l);o.push(a+g),i=n,d=!0}else d=!0;break}}return d&&o.push(`
9
9
  ${r}
10
- `),s.join(`
10
+ `),o.join(`
11
11
 
12
12
  ---
13
13
 
14
- `)}function F(e,t){let n=[{title:"Profile",content:N(e,10),priority:100},{title:"Current Work",content:N(t,15),priority:90}];return Ce(n,{maxTokens:800})}import{chmodSync as Zt,existsSync as Me,mkdirSync as Xt,readFileSync as Ee,renameSync as qt,writeFileSync as en}from"node:fs";import{dirname as nn,join as $}from"node:path";var L="toolnet.context-offload.v1";function Re(e){return $(e,".toolnet","offload")}function Te(e){return $(Re(e),"graph.json")}function C(){return{schema:L,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function Oe(e){let t=Te(e);if(!Me(t))return C();try{let n=JSON.parse(Ee(t,"utf8"));return n.schema!==L||n.version!==1||!Array.isArray(n.nodes)?C():n}catch{return C()}}function D(e,t){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:n.slice(0,t-1).trimEnd()+"\u2026"}function H(e,t={}){let n=Oe(e);if(n.nodes.length===0)return"";let r=Math.max(1,Math.min(12,t.maxAssets??6)),o=Math.max(320,Math.min(2400,t.maxChars??900)),s=["[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 c=D(i.sourceRefs.at(-1)??"unknown",72),a=i.files.length>0?` files=${D(i.files.join(","),120)}`:"",u=`event:${c} --offloads--> asset:${i.id.slice(0,12)} kind=${i.kind} bytes=${i.bytes}${a}`;if([...s,u].join(`
15
- `).length>o)break;s.push(u)}return s.join(`
16
- `)}import{existsSync as z,mkdirSync as Ie,readFileSync as V,renameSync as _e,writeFileSync as Pe}from"node:fs";import{dirname as Ne,join as G}from"node:path";import{createHash as je}from"node:crypto";function M(e){return je("sha256").update(e).digest("hex")}function B(e){return G(e.rootPath,".toolnet","context","handoff.md")}function J(e){return G(e.rootPath,".toolnet","context","handoff.json")}function K(e,t){Ie(Ne(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;Pe(n,t.endsWith(`
14
+ `)}function _e(e,t){let n=[{title:"Profile",content:Ne(e,10),priority:100},{title:"Current Work",content:Ne(t,15),priority:90}];return En(n,{maxTokens:800})}import{chmodSync as ti,existsSync as Tn,mkdirSync as ni,readFileSync as jn,renameSync as ri,writeFileSync as si}from"node:fs";import{dirname as ii,join as Le}from"node:path";var $e="toolnet.context-offload.v1";function On(e){return Le(e,".toolnet","offload")}function Pn(e){return Le(On(e),"graph.json")}function ue(){return{schema:$e,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function Rn(e){let t=Pn(e);if(!Tn(t))return ue();try{let n=JSON.parse(jn(t,"utf8"));return n.schema!==$e||n.version!==1||!Array.isArray(n.nodes)?ue():n}catch{return ue()}}function Fe(e,t){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:n.slice(0,t-1).trimEnd()+"\u2026"}function We(e,t={}){let n=Rn(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 d=Fe(i.sourceRefs.at(-1)??"unknown",72),u=i.files.length>0?` files=${Fe(i.files.join(","),120)}`:"",a=`event:${d} --offloads--> asset:${i.id.slice(0,12)} kind=${i.kind} bytes=${i.bytes}${u}`;if([...o,a].join(`
15
+ `).length>s)break;o.push(a)}return o.join(`
16
+ `)}import{existsSync as ze,mkdirSync as Dn,readFileSync as qe,renameSync as Kn,writeFileSync as zn}from"node:fs";import{dirname as qn,join as He}from"node:path";import{createHash as Nn}from"node:crypto";import{dirname as _n}from"node:path";import{mkdirSync as Fn,readFileSync as Ln,renameSync as $n,writeFileSync as Wn}from"node:fs";function S(e){return Nn("sha256").update(e).digest("hex")}function le(e){if(Array.isArray(e))return e.map(le);if(e&&typeof e=="object"){let t=e,n={};for(let r of Object.keys(t).sort())n[r]=le(t[r]);return n}return e}function De(e){return JSON.stringify(le(e))}function Ke(e){try{return JSON.parse(Ln(e,"utf8"))}catch{return null}}function T(e,t){Fn(_n(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;Wn(n,JSON.stringify(t,null,2)+`
17
+ `,{encoding:"utf8",mode:384}),$n(n,e)}function Je(e){return He(e.rootPath,".toolnet","context","handoff.md")}function Be(e){return He(e.rootPath,".toolnet","context","handoff.json")}function Ve(e,t){Dn(qn(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;zn(n,t.endsWith(`
17
18
  `)?t:`${t}
18
- `,{encoding:"utf8",mode:384}),_e(n,e)}function Fe(e,t){K(e,`${JSON.stringify(t,null,2)}
19
- `)}function Y(e,t){let n=t.replace(/\r\n/g,`
20
- `).trim();if(!n)return null;let r={version:1,projectId:e.id,projectName:e.name,text:n,digest:M(n),generatedAt:new Date().toISOString()};return K(B(e),n),Fe(J(e),r),r}function E(e){let t=B(e);if(!z(t))return null;try{let n=V(t,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),o=J(e);if(z(o))try{let s=JSON.parse(V(o,"utf8"));typeof s.generatedAt=="string"&&(r=s.generatedAt)}catch{}return{version:1,projectId:e.id,projectName:e.name,text:n,digest:M(n),generatedAt:r}}catch{return null}}function W(e,t=1800){let n=E(e);if(!n?.text)return null;let r=n.text;return r.length>t&&(r=`${r.slice(0,t)}
19
+ `,{encoding:"utf8",mode:384}),Kn(n,e)}function Hn(e,t){Ve(e,`${JSON.stringify(t,null,2)}
20
+ `)}function Ge(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:S(n),generatedAt:new Date().toISOString()};return Ve(Je(e),n),Hn(Be(e),r),r}function de(e){let t=Je(e);if(!ze(t))return null;try{let n=qe(t,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=Be(e);if(ze(s))try{let o=JSON.parse(qe(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:e.id,projectName:e.name,text:n,digest:S(n),generatedAt:r}}catch{return null}}function Ue(e,t=1800){let n=de(e);if(!n?.text)return null;let r=n.text;return r.length>t&&(r=`${r.slice(0,t)}
21
22
 
22
23
  [Fast handoff truncated]`),["[TOOLNET FAST HANDOFF]","",`Project: ${e.name}`,`Updated: ${n.generatedAt}`,"",r].join(`
23
- `)}var R="memory_agent_ask";function U(){return`
24
+ `)}var fe="memory_agent_ask";function Ye(){return`
24
25
  [TOOLNET MEMORY AGENT]
25
26
 
26
27
  Tool:
27
- - ${R}
28
+ - ${fe}
28
29
 
29
30
  For resume/continue requests:
30
31
 
31
32
  1. Use the injected ToolNet continuity handoff FIRST.
32
33
  2. If the handoff is missing or ambiguous, invoke
33
- ${R} directly BEFORE repository/history exploration.
34
+ ${fe} directly BEFORE repository/history exploration.
34
35
  3. NEVER reconstruct prior work from:
35
36
  - .toolnet/sessions/**
36
37
  - state.json
37
38
  - events.jsonl
38
39
  - raw transcripts
39
40
  4. NEVER search for the implementation/schema of
40
- ${R}; invoke the MCP tool directly.
41
+ ${fe}; invoke the MCP tool directly.
41
42
  5. Inspect git/source only AFTER continuity context is known.
42
43
 
43
44
  Use:
@@ -45,34 +46,99 @@ Use:
45
46
  - mode="ai" for ambiguous or combined continuity questions.
46
47
 
47
48
  Current repository evidence overrides stale memory.
48
- `.trim()}function T(e){let t=d.resolve(e),n=d.parse(t).root;for(;t!==n;){let r=d.join(t,".toolnet");if(f.existsSync(r)&&f.statSync(r).isDirectory())return t;t=d.dirname(t)}return null}function Q(e){try{return f.existsSync(e)?f.readFileSync(e,"utf-8").trim():null}catch{return null}}function Z(e){return e.split(`
49
- `).filter(r=>{let o=r.toUpperCase();return!(o.includes("SECRET")||o.includes("TOKEN")||o.includes("API_KEY")||o.includes("APIKEY")||o.includes("PASSWORD")||o.includes("PASS="))}).join(`
50
- `)}function X(e={}){let t=e.projectPath||process.cwd(),n=T(t);if(!n)return null;let r=d.join(n,".toolnet","project.json"),o="Unknown";try{if(f.existsSync(r)){let b=JSON.parse(f.readFileSync(r,"utf-8"));o=b.name||b.projectName||"Unknown"}}catch{}let s=d.join(n,".toolnet","profile.md"),i=d.join(n,".toolnet","current.md"),c=Q(s)||"",a=Q(i)||"";c=Z(c),a=Z(a);let u=`[TOOLNET PROJECT CONTEXT]
49
+ `.trim()}function me(e){let t=I.resolve(e),n=I.parse(t).root;for(;t!==n;){let r=I.join(t,".toolnet");if(C.existsSync(r)&&C.statSync(r).isDirectory())return t;t=I.dirname(t)}return null}function Xe(e){try{return C.existsSync(e)?C.readFileSync(e,"utf-8").trim():null}catch{return null}}function Ze(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 Qe(e={}){let t=e.projectPath||process.cwd(),n=me(t);if(!n)return null;let r=I.join(n,".toolnet","project.json"),s="Unknown";try{if(C.existsSync(r)){let h=JSON.parse(C.readFileSync(r,"utf-8"));s=h.name||h.projectName||"Unknown"}}catch{}let o=I.join(n,".toolnet","profile.md"),i=I.join(n,".toolnet","current.md"),d=Xe(o)||"",u=Xe(i)||"";d=Ze(d),u=Ze(u);let a=`[TOOLNET PROJECT CONTEXT]
51
52
 
52
- Project: ${o}
53
+ Project: ${s}
53
54
  Root: ${n}
54
55
 
55
- `,p=F(c,a),l=W({id:"",name:o,rootPath:n},1600),y=l?`
56
-
57
- ${l}
58
- `:"",m=H(n,{maxAssets:6,maxChars:900}),k=m?`
56
+ `,f=_e(d,u),m=Ue({id:"",name:s,rootPath:n},1600),c=m?`
59
57
 
60
58
  ${m}
61
- `:"",se=`
59
+ `:"",l=We(n,{maxAssets:6,maxChars:900}),g=l?`
60
+
61
+ ${l}
62
+ `:"",b=`
62
63
 
63
- ${U()}
64
+ ${Ye()}
64
65
 
65
66
  Forbidden At Startup:
66
67
  - Do not run session:agy-recover, handoff:latest, or brief automatically.
67
68
  - Do not perform deep recovery merely because an agent starts.
68
69
  - If the user asks to resume previous work and fast context is insufficient,
69
70
  use memory_agent_ask before guessing.
70
- `;return u+p+y+k+se}import{existsSync as Ve,readFileSync as Ge}from"node:fs";import{join as Be}from"node:path";import{existsSync as De,mkdirSync as xn,readFileSync as $e,renameSync as kn,writeFileSync as bn}from"node:fs";import{dirname as vn,join as Le}from"node:path";function He(e){return Le(e.rootPath,".toolnet","context","session-origin.json")}function ze(e){let t=He(e);if(!De(t))return null;try{let n=JSON.parse($e(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function q(e){let t=ze(e);if(!t)return null;let n=["Previous session:",`- Agent: ${t.agent}`,`- Session: ${t.nativeSessionId}`];return 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(`
71
- `)}function Je(e){let t=Be(e.rootPath,".toolnet","current.md");if(!Ve(t))return null;try{return Ge(t,"utf8").trim()}catch{return null}}function Ke(e,t){let n=t.replace(/\r\n/g,`
72
- `).trim(),r=2400,o=n.length>r?`${n.slice(0,r)}
71
+ `;return a+f+c+g+b}import{existsSync as er,readFileSync as tr}from"node:fs";import{join as nr}from"node:path";import{existsSync as Jn,mkdirSync as Bn,readFileSync as Vn,renameSync as Gn,writeFileSync as Un}from"node:fs";import{dirname as Yn,join as Xn}from"node:path";function et(e){return Xn(e.rootPath,".toolnet","context","session-origin.json")}function Zn(e,t){Bn(Yn(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;Un(n,`${JSON.stringify(t,null,2)}
72
+ `,{encoding:"utf8",mode:384}),Gn(n,e)}function Q(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 tt(e,t){let n=Q(t.observations,"file"),r=Q(t.observations,"next_action"),s=Q(t.observations,"blocker"),o=Q(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 Zn(et(e),i),i}function Qn(e){let t=et(e);if(!Jn(t))return null;try{let n=JSON.parse(Vn(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function nt(e){let t=Qn(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(`
73
+ `)}function rr(e){let t=nr(e.rootPath,".toolnet","current.md");if(!er(t))return null;try{return tr(t,"utf8").trim()}catch{return null}}function sr(e,t){let n=t.replace(/\r\n/g,`
74
+ `).trim(),r=2400,s=n.length>r?`${n.slice(0,r)}
75
+
76
+ [Current work truncated for fast handoff]`:n,o=nt(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(`
77
+ `)}function pe(e){let t=rr(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=sr(e,t);return de(e)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(Ge(e,n),{updated:!0,reason:"updated",chars:n.length})}import{join as or}from"node:path";function rt(e,t){let n=e.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=S(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 st(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=rt(r.toLowerCase(),"agent"),i=rt(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:or(e.rootPath,".toolnet","sessions",o,i)}}import{closeSync as he,existsSync as dr,fsyncSync as fr,mkdirSync as mr,openSync as ye,readSync as pr,rmSync as it,statSync as ct,writeSync as gr}from"node:fs";import{join as ke}from"node:path";var ir=new Set(["thinking","reasoning","reasoningcontent","chainofthought","cot","analysistext","internalreasoning","modelthinking"]),cr=new Set(["reasoning","thinking","chain_of_thought","chain-of-thought","internal_reasoning","internal-reasoning"]);function ar(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,"")}function ur(e){for(let t of["type","kind"]){let n=e[t];if(typeof n=="string"){let r=n.toLowerCase();if(cr.has(r))return n}}return null}function ge(e,t=0){if(t>12)return"[ToolNet nested value omitted]";if(Array.isArray(e))return e.map(o=>ge(o,t+1));if(!e||typeof e!="object")return e;let n=e,r=ur(n);if(r)return{type:r,omitted:"[private reasoning omitted]"};let s={};for(let[o,i]of Object.entries(n))ir.has(ar(o))||(s[o]=ge(i,t+1));return s}function lr(e){if(!e)return new Date().toISOString();let t=new Date(e);return Number.isNaN(t.getTime())?new Date().toISOString():t.toISOString()}function P(e){return e?.trim()||void 0}function ot(e,t={}){let n={...e.provenance??{}},r=P(e.source)??P(t.source)??P(n.source);return{...e,timestamp:lr(e.timestamp),source:r,turnId:P(e.turnId)??P(t.turnId),cwd:P(e.cwd)??P(t.cwd),data:ge(e.data??{}),provenance:n}}var hr=12e4,yr=80,kr=2e3;function Sr(e){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}var ee=class{constructor(t,n={}){this.identity=t;this.eventContext=n;mr(t.localDirectory,{recursive:!0}),this.eventsFile=ke(t.localDirectory,"events.jsonl"),this.stateFile=ke(t.localDirectory,"state.json"),this.lockFile=ke(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 Ke(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(t){T(this.stateFile,t)}acquireLock(){for(let t=0;t<yr;t+=1)try{return ye(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-ct(this.lockFile).mtimeMs>hr){it(this.lockFile,{force:!0});continue}}catch{}Sr(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(t){let n=this.acquireLock();try{return t()}finally{he(n),it(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 m of t){let c=ot(m,this.eventContext),l=c.timestamp??new Date().toISOString(),g=c.data??{},b=c.provenance?.rawDigest??S(De(g)),h=c.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,c.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,c.type,l,b].join("|"),k=S(h).slice(0,32);if(r.has(k))continue;s+=1;let y={version:1,id:k,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,sessionId:this.identity.nativeSessionId,type:c.type,timestamp:l,source:c.source??c.provenance?.source??this.identity.agent,data:g,provenance:{...c.provenance,rawDigest:b}};c.role!==void 0&&(y.role=c.role),c.turnId!==void 0&&(y.turnId=c.turnId),c.cwd!==void 0&&(y.cwd=c.cwd),c.sourceEventId!==void 0&&(y.sourceEventId=c.sourceEventId),c.sourceSequence!==void 0&&(y.sourceSequence=c.sourceSequence),o.push(y),r.add(k)}if(o.length===0)return[];let i=o.map(m=>JSON.stringify(m)).join(`
78
+ `)+`
79
+ `,d=ye(this.eventsFile,"a",384);try{gr(d,i,null,"utf8"),fr(d)}finally{he(d)}let u=o[o.length-1],a="active";u.type==="session_end"||u.type==="session_idle"?a="idle":u.type==="error"&&(a="error");let f=Array.from(r).slice(-kr);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastLocalEventAt:u.timestamp,lastSequence:u.sequence,recentEventIds:f}),o})}readPending(){return this.withLock(()=>{let t=this.loadStateUnsafe();if(!dr(this.eventsFile))return{events:[],startOffset:t.remoteByteOffset,endOffset:t.remoteByteOffset};let n=ct(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=ye(this.eventsFile,"r");try{pr(i,o,0,s,r)}finally{he(i)}return{events:o.toString("utf8").split(`
80
+ `).filter(Boolean).map(a=>JSON.parse(a)),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()})})}};function at(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function J(e){return e.toLowerCase().replace(/[^a-z0-9]/gu,"")}function H(e,t,n=0){if(n>8)return;if(Array.isArray(e)){for(let s of e.slice(0,50))H(s,t,n+1);return}let r=at(e);if(r)for(let[s,o]of Object.entries(r))t(s,o,r),H(o,t,n+1)}function $(e,t){let n=[];return H(e,(r,s)=>{t.has(J(r))&&typeof s=="string"&&s.trim()&&n.push(s.trim())}),n}function br(e){let t=e.trim();if(!t.startsWith("{"))return null;try{return at(JSON.parse(t))}catch{return null}}function xr(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 H(t,(r,s,o)=>{if(n)return;let i=J(r);if(["tool","toolname"].includes(i)&&typeof s=="string"){n=s.trim().toLowerCase();return}if(i!=="name"||typeof s!="string")return;let d=typeof o.type=="string"?o.type.toLowerCase():"";(d.includes("tool")||d.includes("function")||d.includes("command"))&&(n=s.trim().toLowerCase())}),n}function wr(e){let t=$(e.data,new Set(["command","cmd","script"])),n=$(e.data,new Set(["arguments","args"]));for(let r of n){let s=br(r);if(s)for(let o of $(s,new Set(["command","cmd","script"])))t.push(o)}return Array.from(new Set(t.map(r=>r.trim()).filter(Boolean)))}function vr(e){let t=$(e.data,new Set(["filepath","file_path","filename","file","path","target"].map(J)));return Array.from(new Set(t.map(n=>n.trim()).filter(n=>n.length>0&&n.length<1e3&&!n.includes(`
81
+ `))))}function Ir(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 Ar(e){let t=$(e.data,new Set(["patch","diff","arguments","input"].map(J))),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 d=i[1]?.trim();d&&n.push({kind:"file",text:d,fileAction:o.action,confidence:.99})}}return n}function Mr(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 Cr(e){let t=null;return H(e,(n,r)=>{if(t===null&&["exitcode","code"].includes(J(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 Er(e){return $(e,new Set(["status","state","result","output","outputsummary","message","text"]))}function Tr(e){let t=Cr(e.data);if(t!==null)return t===0?"passed":"failed";let n=Er(e.data).join(`
82
+ `).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 jr(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 ut(e){let t=[],n=xr(e),r=Ir(e,n);if(r)for(let s of vr(e))t.push({kind:"file",text:s,fileAction:r,confidence:e.type==="file_edit"||e.type==="file_write"?1:.96});t.push(...Ar(e));for(let s of wr(e)){t.push({kind:"command",text:s,confidence:.98});let o=Mr(s);o&&t.push({kind:"test",text:s,checkKind:o,checkStatus:Tr(e),confidence:.98})}return jr(t)}var Or=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function N(e){return e.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function dt(e){return N(e).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function R(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))R(r,t,n+1);return}if(!(!e||typeof e!="object"))for(let[r,s]of Object.entries(e))(Or.has(r)||["data","payload","parts","messages"].includes(r))&&R(s,t,n+1)}}function te(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 lt(e){let t=N(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 x(e,t,n,r,s={}){let o=N(r),i=s.key??dt(o);return{version:1,id:S([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 Pr(e,t,n){let r=N(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(x(e,t,"goal",i[1],{confidence:.97}));let d=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);d?.[1]&&s.push(x(e,t,"plan",d[1],{confidence:.95}));let u=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=u.exec(r));){let c=Number(a[1]),l=N(a[2]??""),g=l&&!lt(l)?`Phase ${c} - ${l}`:`Phase ${c}`;s.push(x(e,t,"phase",g,{key:`phase:${c}`,order:c,status:te(r),confidence:.93}))}let f=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);f?.[2]&&s.push(x(e,t,"task",f[2],{status:f[1].trim()?"completed":te(f[2]),confidence:.96}));let m=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(m?.[2]){let c=m[1]?Number(m[1]):void 0,l=N(m[2]),g=lt(l);s.push(x(e,t,"task",g&&c!==void 0?`TODO ${c}`:l,{key:c!==void 0?`task:${c}`:dt(l),order:c,status:te(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 c=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");c&&s.push(x(e,t,"next_action",c,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(x(e,t,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(x(e,t,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(x(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(x(e,t,"activity",r,{confidence:.86})),s}function ft(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 u=[];R(i.data,u);let a=u.map(f=>N(f)).find(f=>f.length>=8&&f.length<=1200&&!/^\[?toolnet\b/iu.test(f));a&&s(x(e,i,"request",a,{confidence:.96}))}for(let u of ut(i))s(x(e,i,u.kind,u.text,{fileAction:u.fileAction,checkKind:u.checkKind,checkStatus:u.checkStatus,status:u.kind==="test"?u.checkStatus==="passed"?"completed":u.checkStatus==="failed"?"blocked":u.checkStatus==="running"?"in_progress":"pending":void 0,confidence:u.confidence}));if(i.type==="decision"){let u=[];R(i.data,u);for(let a of u)s(x(e,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];R(i.data,u);for(let a of u)s(x(e,i,"task",a,{status:te(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let a=i.data[u];typeof a=="string"&&a&&s(x(e,i,"file",a,{fileAction:"modified",confidence:1}))}if(i.type==="test"){let u=[];R(i.data,u);for(let a of u)s(x(e,i,"test",a,{confidence:1}))}let d=[];R(i.data,d);for(let u of d)for(let a of u.split(/\n+/u))for(let f of Pr(e,i,a))s(f)}let o=t[t.length-1];return s(x(e,o,"session",`${e.agent}:${e.nativeSessionId}`,{key:e.sessionKey,confidence:1})),n}import{existsSync as Rr,mkdirSync as Nr,readFileSync as _r,renameSync as Fr,writeFileSync as Lr}from"node:fs";import{dirname as $r,join as Wr}from"node:path";function Dr(e,t){Nr($r(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;Lr(n,`${JSON.stringify(t,null,2)}
83
+ `,{encoding:"utf8",mode:384}),Fr(n,e)}function kt(e){return Wr(e.rootPath,".toolnet","work","current.json")}function St(e){let t=kt(e);if(!Rr(t))return null;try{let n=JSON.parse(_r(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function ne(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function A(e,t,n){let r=[],s=new Set;for(let o of[...e,...t].reverse()){let i=ne(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function Kr(e,t,n=20){let r=new Map;for(let s of[...e,...t]){let o=`${s.kind}|${ne(s.command)}`;r.delete(o),r.set(o,s)}return Array.from(r.values()).slice(-n)}function zr(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 mt(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&&zr(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 pt(e){let t=new Map;for(let n of e){let r=n.order!==void 0?`order:${n.order}`:ne(n.title);t.set(r,n)}return t}function gt(e){return e.order!==void 0?`order:${e.order}`:ne(e.key||e.text)}function ht(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 yt(e){return e.find(t=>t.status==="in_progress")??e.find(t=>t.status==="blocked")??e.find(t=>t.status==="pending")}function bt(e,t){let n=St(e),r=pt(n?.phases??[]),s=pt(n?.tasks??[]),o=n?.currentRequest,i=n?.currentActivity,d=n?.goal,u=n?.plan,a=n?.lastSession,f=[],m=[],c=[],l=[],g=[],b=[...n?.activeFiles??[]],h=[],k=[],y=[],Ae=[],Me=[],Ce=[],V=[...t].sort((p,v)=>{let W=p.occurredAt.localeCompare(v.occurredAt);return W!==0?W:p.sequence-v.sequence});for(let p of V)switch(p.kind){case"request":o=p.text;break;case"activity":i=p.text;break;case"goal":d=p.text;break;case"plan":u=p.text;break;case"phase":{let v=gt(p);r.set(v,mt(r.get(v),p));break}case"task":{let v=gt(p);s.set(v,mt(s.get(v),p));break}case"decision":f.push(p.text);break;case"blocker":m.push(p.text);break;case"warning":c.push(p.text);break;case"next_action":l.push(p.text);break;case"file":{g.push(p.text);let v=p.fileAction??"active",W=b.indexOf(p.text);W>=0&&b.splice(W,1),v!=="deleted"&&b.push(p.text),v==="modified"?h.push(p.text):v==="created"?k.push(p.text):v==="deleted"&&y.push(p.text);break}case"command":Ae.push(p.text);break;case"test":Me.push(p.text),p.checkKind&&Ce.push({kind:p.checkKind,command:p.text,status:p.checkStatus??"unknown",updatedAt:p.occurredAt,agent:p.agent,nativeSessionId:p.nativeSessionId});break;case"session":a={agent:p.agent,nativeSessionId:p.nativeSessionId,sessionKey:p.sessionKey,updatedAt:p.occurredAt};break}let L=ht(r.values()),O=ht(s.values()),se=yt(L),G=yt(O),on=A(n?.nextActions??[],[...l,...G?[G.title]:[],...!G&&se?[se.title]:[],...O.filter(p=>p.status==="pending").slice(0,5).map(p=>p.title)],8),cn=A(n?.blockers??[],[...m,...L.filter(p=>p.status==="blocked").map(p=>p.title),...O.filter(p=>p.status==="blocked").map(p=>p.title)],20),an=V.length>0?V[V.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),Ee={version:1,projectId:e.id,projectName:e.name,currentRequest:o,currentActivity:i,goal:d,plan:u,phases:L,tasks:O,decisions:A(n?.decisions??[],f,20),blockers:cn,warnings:A(n?.warnings??[],c,20),nextActions:on,filesTouched:A(n?.filesTouched??[],g,30),activeFiles:A([],b,5),modifiedFiles:A(n?.modifiedFiles??[],h,30),createdFiles:A(n?.createdFiles??[],k,30),deletedFiles:A(n?.deletedFiles??[],y,30),commands:A(n?.commands??[],Ae,20),tests:A(n?.tests??[],Me,20),checks:Kr(n?.checks??[],Ce,20),currentPhase:se,currentTask:G,progress:{phasesTotal:L.length,phasesCompleted:L.filter(p=>p.status==="completed").length,tasksTotal:O.length,tasksCompleted:O.filter(p=>p.status==="completed").length,blocked:L.filter(p=>p.status==="blocked").length+O.filter(p=>p.status==="blocked").length},lastSession:a,updatedAt:an};return Dr(kt(e),Ee),Ee}import{existsSync as qr,readFileSync as Hr,writeFileSync as Jr}from"node:fs";import{join as Br}from"node:path";var wt="<!-- TOOLNET:STABLE-WORK:BEGIN -->",Se="<!-- TOOLNET:STABLE-WORK:END -->";function be(e){switch(e.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function E(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${n}`)]:[]}function xt(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${be(n)} ${n.title}`)]:[]}function Vr(e){let t=[wt,"# 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:",`${be(e.currentPhase)} ${e.currentPhase.title}`),e.currentTask&&t.push("","Current task:",`${be(e.currentTask)} ${e.currentTask.title}`),t.push(...xt("Phases",e.phases)),t.push(...xt("TODO / Tasks",e.tasks)),t.push(...E("Next actions",e.nextActions)),t.push(...E("Blockers",e.blockers)),t.push(...E("Important decisions",e.decisions)),t.push(...E("Active files",e.activeFiles??[])),t.push(...E("Modified files",e.modifiedFiles??[])),t.push(...E("Created files",e.createdFiles??[])),t.push(...E("Deleted files",e.deletedFiles??[])),t.push(...E("Files touched",e.filesTouched)),t.push(...E("Recent commands",e.commands??[])),t.push(...E("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.",Se),t.join(`
84
+ `)}function vt(e,t){let n=Br(e.rootPath,".toolnet","current.md"),r="";if(qr(n))try{r=Hr(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let s=Vr(t),o=r.indexOf(wt),i=r.indexOf(Se),d;o>=0&&i>=o?d=[r.slice(0,o).trimEnd(),s,r.slice(i+Se.length).trimStart()].filter(Boolean).join(`
85
+
86
+ `):d=r.trim()?`${r.trim()}
87
+
88
+ ${s}`:s,Jr(n,`${d.trim()}
89
+ `,{encoding:"utf8",mode:384})}import{existsSync as os,mkdirSync as is}from"node:fs";import{join as xe}from"node:path";import{existsSync as Mt,mkdirSync as Gr,readFileSync as Ur,statSync as It,writeFileSync as Yr}from"node:fs";import{dirname as Xr,join as Zr}from"node:path";var At=64*1024,Qr=`# ToolNet Project Operating Manual
90
+
91
+ This file contains persistent instructions for AI agents working on this project.
92
+
93
+ ## Critical Rules
94
+
95
+ <!--
96
+ Examples:
97
+
98
+ - [enforce] Never edit production files directly.
99
+ - [enforce] Edit source only in /path/to/source.
100
+ - [enforce] Deploy only with ./deploy.sh --apply
101
+ -->
102
+
103
+ ## Workflow
104
+
105
+ <!--
106
+ Describe the correct working process.
107
+ -->
108
+
109
+ ## Architecture
110
+
111
+ <!--
112
+ Important architecture conventions.
113
+ -->
114
+
115
+ ## Verification
116
+
117
+ <!--
118
+ Tests / QA required after changes.
119
+ -->
120
+
121
+ ## Known Gotchas
122
+
123
+ <!--
124
+ Things an AI agent should always remember.
125
+ -->
126
+
127
+ ## Preferences
128
+
129
+ <!--
130
+ - [advisory] Prefer small focused files.
131
+ -->
132
+ `;function Ct(e){return Zr(e.rootPath,".toolnet","PROJECT.md")}function es(e){return e.normalize("NFKC").replace(/\s+/g," ").trim()}function ts(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=es(s[2]);if(!i)continue;let d=`${o}:${i.toLowerCase()}`;n.has(d)||(n.add(d),t.push({id:S(d).slice(0,24),mode:o,text:i,source:"manual"}))}return t}function ns(e){let t=Ct(e);return Mt(t)||(Gr(Xr(t),{recursive:!0}),Yr(t,Qr,{encoding:"utf8",mode:384})),t}function Et(e,t=!1){let n=t?ns(e):Ct(e);if(!Mt(n))return null;if(It(n).size>At)throw new Error(`PROJECT.md exceeds ${At} bytes`);let s=Ur(n,"utf8");return{path:n,content:s,digest:S(s),rules:ts(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(It(n).mtimeMs).toISOString()}}function w(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 Tt(e){if(e)return{id:e.id,title:e.title,status:e.status}}function rs(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(`
133
+ `).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function ss(e){return S(JSON.stringify(e))}function jt(e){let{project:t,identity:n,state:r}=e,s=r.activeFiles?.at(-1)??r.filesTouched.at(-1),o=r.phases.filter(y=>y.status==="completed").map(y=>y.title),i=r.tasks.filter(y=>y.status==="completed").map(y=>y.title),d=r.phases.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),u=r.tasks.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),a=new Set(r.tasks.filter(y=>y.status==="completed").map(y=>y.title.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),f=w(r.nextActions.filter(y=>!a.has(y.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),10),m=w([...u,...f],15),c=w(r.tests.slice().reverse(),10),l=w([...(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:Tt(r.currentPhase),task:Tt(r.currentTask),file:s},completed:{phases:w(o,20),tasks:w(i,30)},remaining:{phases:w(d,20),tasks:w(u,30),todos:m},nextAction:f[0],blockers:w(r.blockers.slice().reverse(),10),decisions:w(r.decisions.slice().reverse(),10),files:{current:s,recent:l,active:w(r.activeFiles??[],10),modified:w(r.modifiedFiles??[],20),created:w(r.createdFiles??[],20),deleted:w(r.deletedFiles??[],20)},tests:{status:rs(r.tests,r.checks),recent:c,checks:(r.checks??[]).slice(-10).map(y=>({kind:y.kind,status:y.status,command:y.command}))},attention:w(e.attention??[],20),progress:r.progress},{capturedAt:b,source:h,...k}=g;return{...g,stateDigest:ss(k)}}function cs(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 as(e,t,n,r,s){if(!cs(n))return null;let o=Et(e,!1),d=[...o?o.rules.filter(m=>m.mode==="enforce").map(m=>m.text):[],...n.warnings].slice(0,20),u=jt({project:e,identity:t,state:n,reason:r,sequence:s,attention:d}),a=u.stateDigest;return{version:1,id:S([e.id,t.sessionKey,a].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(m=>m.status!=="completed"&&m.status!=="cancelled"),incompleteTasks:n.tasks.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),nextActions:u.remaining.todos.slice(0,10),blockers:n.blockers.slice(-10),decisions:n.decisions.slice(-10),warnings:n.warnings.slice(-10),attention:d,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:a,continuity:u}}function us(e,t){let n=xe(e.rootPath,".toolnet","work","handoffs");is(n,{recursive:!0});let r=xe(n,`${t.id}.json`);os(r)||T(r,t),T(xe(e.rootPath,".toolnet","work","handoff-latest.json"),t)}function Ot(e){let t=as(e.project,e.identity,e.state,e.reason,e.sequence);return t?(us(e.project,t),t):null}import{existsSync as Gt,mkdirSync as zs,readFileSync as qs}from"node:fs";import{join as Ie}from"node:path";function Pt(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 Ft=[/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],ls=[/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],ds=[/\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],fs=[/\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],ms=[/đã 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],Rt=[/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],ps=[/\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],gs=[/đườ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],hs=[/\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],Nt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),ys=new Set(["payload","data","content","message","messages","parts","summary"]);function M(e,t){return t.some(n=>n.test(e))}function Lt(e){return e.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function ks(e){return Lt(e).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Ss(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 we(e,t,n,r=0){if(!(r>6)){if(typeof e=="string"){(!t||Nt.has(t))&&n.push(e);return}if(Array.isArray(e)){for(let s of e.slice(0,50))we(s,t,n,r+1);return}if(!(!e||typeof e!="object"))for(let[s,o]of Object.entries(e))(Nt.has(s)||ys.has(s))&&we(o,s,n,r+1)}}function bs(e){let t=[];we(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=Lt(o);if(Ss(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function _t(e){return(e.role??(typeof e.data.role=="string"?e.data.role:"")).toLowerCase()}function xs(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&&M(e,Ft)?{kind:"rule",confidence:.98}:r&&M(e,ls)?{kind:"rule",confidence:.92}:M(e,ds)?{kind:M(e,Rt)?"architecture":"decision",confidence:r?.93:.86}:r&&M(e,fs)?{kind:"todo",confidence:.87}:M(e,Rt)&&M(e,ps)?{kind:"architecture",confidence:r?.88:.82}:s&&M(e,ms)?{kind:"fix",confidence:.8}:r&&M(e,gs)&&M(e,hs)?{kind:"context",confidence:.79}:null}function ws(e){switch(e){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function vs(e,t,n){return e==="rule"&&M(n,Ft)?"critical":e==="architecture"||e==="decision"||e==="rule"?"high":e==="fix"||e==="context"?"normal":Pt(t,n)}function $t(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,d=_t(o);i&&d&&s.set(i,d)}for(let o of t){let i=_t(o),d=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&d&&(i=s.get(d)??"");for(let u of bs(o)){let a=xs(u,i,o);if(!a||a.confidence<.75)continue;let f=ws(a.kind),m=ks(u),c=S([e.projectId,a.kind,m].join("|"));if(r.has(c))continue;r.add(c);let l=o.provenance.sourcePath?[o.provenance.sourcePath]:[],g=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:c,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,kind:a.kind,type:f,content:u,confidence:a.confidence,importance:vs(a.kind,f,u),tags:[f],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 Is}from"node:crypto";var As=["project-knowledge","implementation","continuation","session-context"],Ms={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function ve(e){return Is("sha256").update(e).digest("hex")}function re(e,t){return`${e}:${ve(t).slice(0,24)}`}function Cs(e){try{return ve(JSON.stringify(e))}catch{return ve(String(e))}}function _(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 Dt(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 Es(e){return e==="rule"||e==="architecture"?"project-knowledge":e==="decision"||e==="fix"?"implementation":e==="todo"?"continuation":"session-context"}function Wt(e){return e.length===0?0:e.reduce((t,n)=>t+n,0)/e.length}function Ts(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=>Dt(t.content)).join(" | ")}function js(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=>Dt(t.content)).join(`
134
+ `)}function Kt(e,t){let n=e.slice().sort((c,l)=>c.sequence-l.sequence||c.timestamp.localeCompare(l.timestamp)||c.id.localeCompare(l.id)),r=n.map(c=>({id:re("raw",[c.projectId,c.agent,c.nativeSessionId,c.id,String(c.sequence)].join("|")),level:"raw",eventId:c.id,sourceEventId:c.sourceEventId,sequence:c.sequence,type:c.type,role:c.role,timestamp:c.timestamp,sourcePath:c.provenance.sourcePath,payloadDigest:Cs(c.data)})),s=new Map,o=new Map;n.forEach((c,l)=>{let g=r[l];g&&(s.set(c.id,g.id),c.sourceEventId&&o.set(c.sourceEventId,g.id))});let i=t.map(c=>{let l=_([...c.provenance.eventIds.map(g=>s.get(g)),...c.provenance.sourceEventIds.map(g=>o.get(g))]);return{id:re("fact",c.fingerprint),level:"fact",fingerprint:c.fingerprint,kind:c.kind,type:c.type,content:c.content,knowledgeClass:c.knowledgeClass,importanceScore:c.importanceScore,confidence:c.confidence,tags:_([...c.tags,"level:fact",`class:${c.knowledgeClass}`,`kind:${c.kind}`]),rawIds:l,sourcePaths:_(c.provenance.sourcePaths)}}),d=new Map;for(let c of i){let l=Es(c.kind),g=d.get(l)??[];g.push(c),d.set(l,g)}let u=[];for(let c of As){let l=d.get(c);if(!l?.length)continue;let g=l.slice().sort((h,k)=>k.importanceScore-h.importanceScore||k.confidence-h.confidence||h.id.localeCompare(k.id)),b=g.map(h=>h.id);u.push({id:re("scene",`${c}|${b.join("|")}`),level:"scene",kind:c,title:Ms[c],summary:Ts(g),factIds:b,importanceScore:Math.max(...g.map(h=>h.importanceScore)),confidence:Wt(g.map(h=>h.confidence)),tags:_(["level:scene",`scene:${c}`,...g.flatMap(h=>h.tags)]),sourcePaths:_(g.flatMap(h=>h.sourcePaths))})}let a=new Map(i.map(c=>[c.id,c])),f=[];for(let c of u){let g=c.factIds.map(k=>a.get(k)).filter(k=>!!k).filter(k=>(k.knowledgeClass==="permanent"||k.knowledgeClass==="task")&&k.importanceScore>=.55);if(g.length===0)continue;let b=g.some(k=>k.knowledgeClass==="permanent")?"permanent":"task",h=js(g);f.push({id:re("knowledge",`${c.id}|${b}|${g.map(k=>k.id).join("|")}`),level:"knowledge",knowledgeClass:b,title:c.title,content:h,sceneIds:[c.id],factIds:g.map(k=>k.id),importanceScore:Math.max(...g.map(k=>k.importanceScore)),confidence:Wt(g.map(k=>k.confidence)),tags:_(["level:knowledge",`class:${b}`,`scene:${c.kind}`,...g.flatMap(k=>k.tags)]),sourcePaths:_(g.flatMap(k=>k.sourcePaths))})}let m=[];for(let c of i)for(let l of c.rawIds)m.push({from:l,to:c.id,type:"supports"});for(let c of u)for(let l of c.factIds)m.push({from:l,to:c.id,type:"belongs_to"});for(let c of f)for(let l of c.sceneIds)m.push({from:l,to:c.id,type:"promotes_to"});return{schema:"toolnet.memory-hierarchy.v1",version:1,raw:r,facts:i,scenes:u,knowledge:f,links:m,stats:{raw:r.length,facts:i.length,scenes:u.length,knowledge:f.length,links:m.length}}}function B(){let e=Te(),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),d=n,u=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||t==="full";return{sessionSave:t,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:d,archiveRemote:u}}function zt(e){return(e||B()).durableMemoryMaxItemsPerSession}function qt(e){return(e||B()).sessionSummaryMaxTokens}var Ht=new q;function Jt(e){let t=e.trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{let r=JSON.parse(t);return JSON.stringify(Ht.sanitizeValue(r))}catch{}let n=Ht.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 Os(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 Ps(e,t){let n=[],r=new Set;for(let i of e){let d=i.split(`
135
+ `).filter(u=>u.trim());for(let u of d){let a=u.trim();if(a.length<15)continue;let f=a.toLowerCase().replace(/\s+/g," ");if(r.has(f))continue;r.add(f);let m="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(a)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(a)?m="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(a)?m="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(a)?m="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(a)?m="next_action":/\b(deploy|release|publish|ship)\b/i.test(a)?m="deploy":/\b(architecture|design|structure|pattern)\b/i.test(a)?m="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(a)&&(m="file");let c=Os(a,m);if(c<.3)continue;let l=Jt(a);n.push({category:m,text:l,importance:c,sourceSessionId:t})}}let s=B(),o=zt(s);return n.sort((i,d)=>d.importance-i.importance).slice(0,o)}function Rs(e){let t=B(),n=qt(t),o=e.join(`
136
+
137
+ `).split(`
138
+ `).filter(i=>{let d=i.trim();return d.length>20&&!d.startsWith("npm")&&!d.startsWith("\u2713")&&!d.startsWith("Error:")}).slice(0,20).map(i=>Jt(i)).join(`
139
+ `);return ae(o,n)}function Bt(e,t){let r=(Array.isArray(e)?e:e.split(`
73
140
 
74
- [Current work truncated for fast handoff]`:n,s=q(e);return["# ToolNet Fast Handoff","",`Project: ${e.name}`,"",...s?[s,""]:[],o,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
75
- `)}function O(e){let t=Je(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=Ke(e,t);return E(e)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(Y(e,n),{updated:!0,reason:"updated",chars:n.length})}var ee=3200;function te(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function tt(e){return e.length<=ee?e:`${e.slice(0,ee)}
141
+ `).filter(l=>l.trim())).map(l=>typeof l=="string"?l:JSON.stringify(l)).filter(l=>l.trim()),s=Ps(r,t),o=s.filter(l=>l.category==="decision").map(l=>l.text),i=s.filter(l=>l.category==="rule").map(l=>l.text),d=s.filter(l=>l.category==="file").map(l=>l.text),u=s.filter(l=>l.category==="fix").map(l=>l.text),a=s.filter(l=>l.category==="blocker").map(l=>l.text),f=s.filter(l=>l.category==="next_action").map(l=>l.text),m=s.filter(l=>l.category==="deploy").map(l=>l.text);return{summary:Rs(r),decisions:o,projectRules:i,filesChanged:d,bugsFixed:u,commands:m,blockers:a,nextActions:f,durableFacts:s}}function j(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 Ns(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 _s(e){switch(e){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function Fs(e){let t=_s(e.importance);return Math.max(0,Math.min(1,t*.75+e.confidence*.25))}function Ls(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 $s(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 Ws(e){let t=Ls(e),n=Fs(e),r=$s(e.content);return{...e,knowledgeClass:t,importanceScore:n,retrievalTerms:r,tags:j([...e.tags,"level:fact",`class:${t}`,`kind:${e.kind}`])}}function Ds(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 Ks(e,t,n){let r=Bt(Ds(t),e.nativeSessionId),s=n.filter(a=>a.kind==="todo").map(a=>a.content),o=n.flatMap(a=>a.provenance.sourcePaths),i=n.filter(a=>a.kind==="architecture").map(a=>a.content),d=j([...s,...r.nextActions]),u=j([...r.nextActions,...s]);return{summary:r.summary,state:{task:u[0]??d[0],decisions:j(r.decisions),files:j([...r.filesChanged,...o]),todos:d,completed:j(r.bugsFixed),blockers:j(r.blockers),nextActions:u,architecture:j(i)}}}function Vt(e,t){let n=Ns(t),r=$t(e,n).map(Ws),s=r.filter(f=>f.knowledgeClass!=="transient").sort((f,m)=>m.importanceScore-f.importanceScore),{summary:o,state:i}=Ks(e,n,s),d=s.map(f=>({fingerprint:f.fingerprint,kind:f.kind,knowledgeClass:f.knowledgeClass,importanceScore:f.importanceScore,content:f.content,terms:f.retrievalTerms})),u=Kt(n,s),a=f=>r.filter(m=>m.knowledgeClass===f).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:d,hierarchy:u,stats:{inputEvents:t.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:s.length,permanent:a("permanent"),task:a("task"),session:a("session"),transient:a("transient")}}}function Ut(e){return Ie(e.rootPath,".toolnet","memory","checkpoints")}function Yt(e){return Ie(Ut(e),"latest.json")}function Hs(e){let t=Yt(e);if(!Gt(t))return null;try{let n=JSON.parse(qs(t,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==e.id?null:n}catch{return null}}function Js(e){return["rule","architecture","decision","fix"].includes(e)}function Bs(e,t){return t.length===0?[]:Vt(e,t).candidates.filter(r=>Js(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 Vs(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 Gs(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 Xt(e,t,n,r){let s=Hs(e),o=Vs(s?.durableFacts??[],Bs(t,n)),i=n.at(-1)?.sequence??s?.source.sequence??0,d=r.phases.filter(h=>h.status==="completed").map(h=>h.title),u=r.tasks.filter(h=>h.status==="completed").map(h=>h.title),a=r.phases.filter(h=>h.status!=="completed"&&h.status!=="cancelled").map(h=>h.title),f=r.tasks.filter(h=>h.status!=="completed"&&h.status!=="cancelled").map(h=>h.title),m={work:Gs(r),durableFacts:o.map(h=>h.fingerprint).sort()},c=S(JSON.stringify(m)).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:d,tasks:u},remaining:{phases:a,tasks:f},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:c},g=Ut(e);zs(g,{recursive:!0,mode:448});let b=Ie(g,`${c}.json`);return Gt(b)||T(b,l),T(Yt(e),l),l}function Zt(e,t,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=ft(t,n);if(r.length===0)return{updated:!1,observations:0};let s=bt(e,r);vt(e,s),tt(e,{agent:t.agent,nativeSessionId:t.nativeSessionId,observations:r,workState:s});try{Xt(e,t,n,s)}catch{}try{Ot({project:e,identity:t,state:s,reason:"continuous-checkpoint",sequence:n.at(-1)?.sequence??0})}catch{}return{updated:!0,observations:r.length}}function Us(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function F(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Ys(e){let t=F(e.timestamp);if(t){let n=new Date(t);if(!Number.isNaN(n.getTime()))return n.toISOString()}return new Date().toISOString()}function Qt(e,t){let n=F(e.hook_event_name);if(!n)return[];let r=F(e.session_id)??"claude",s=F(e.cwd)??t.rootPath,o=F(e.tool_name),i=F(e.tool_use_id),d=Us(e.tool_input),u=F(d.file_path),a=["claude",r,n,i??"",u??""].join(":"),f={timestamp:Ys(e),cwd:s,source:"claude",provenance:{source:"claude-hook"}};return n==="SessionStart"?[{...f,type:"session_start",sourceEventId:`${a}:start`,data:{sessionId:r,cwd:s}}]:n==="PostToolUse"?(o==="Edit"||o==="Write")&&u?[{...f,type:o==="Edit"?"file_edit":"file_write",sourceEventId:`${a}:file`,data:{tool:o,filePath:u},provenance:{source:"claude-hook",files:[u]}}]:[{...f,type:"tool_result",sourceEventId:`${a}:tool-result`,data:{tool:o}}]:n==="Stop"?[{...f,type:"session_idle",sourceEventId:`${a}:idle`,data:{sessionId:r}}]:[{...f,type:"custom",sourceEventId:`${a}:custom`,data:{hookEvent:n}}]}var en=3200;function tn(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function oo(e){return e.length<=en?e:`${e.slice(0,en)}
76
142
 
77
- [ToolNet startup context truncated]`}function nt(e){let t=T(e);return t?new S().detect(t)??null:null}function rt(e){return re(e.rootPath,".toolnet","context","session-origin.json")}function ot(e,t){if(!qe(t))return t;let n=et(e.rootPath,t);return n.startsWith("..")?t:n}function ne(e,t){let n=rt(e),r={};if(Ye(n))try{let u=JSON.parse(Ue(n,"utf8"));te(u)&&u.projectId===e.id&&(r=u)}catch{}let o,s=t.tool_input;te(s)&&typeof s.file_path=="string"&&(o=ot(e,s.file_path));let i=typeof t.session_id=="string"?t.session_id:typeof r.nativeSessionId=="string"?r.nativeSessionId:"claude",c={...r,version:1,projectId:e.id,agent:"claude",nativeSessionId:i,updatedAt:new Date().toISOString()};o&&(c.lastTouchedFile=o),We(re(e.rootPath,".toolnet","context"),{recursive:!0,mode:448});let a=`${n}.tmp-${process.pid}-${Date.now()}`;try{Xe(a,JSON.stringify(c,null,2)+`
78
- `,{encoding:"utf8",mode:384}),Qe(a,n)}finally{Ze(a,{force:!0})}}function oe(e){let t=typeof e.hook_event_name=="string"?e.hook_event_name:"",n=typeof e.cwd=="string"?e.cwd:"";if(!n)return{};let r=nt(n);if(!r)return{};try{if(t==="SessionStart"){let o=X({projectPath:n});return o?.trim()?{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:tt(o)}}:{}}if(t==="PostToolUse"){ne(r,e);try{O(r)}catch{}return{}}if(t==="Stop"){ne(r,e);try{O(r)}catch{}return{}}return{}}catch{return{}}}async function st(){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 it(){let e=await st(),t=oe(e);process.stdout.write(JSON.stringify(t))}it().catch(()=>{process.stdout.write("{}"),process.exitCode=0});
143
+ [ToolNet startup context truncated]`}function io(e){let t=me(e);return t?new Y().detect(t)??null:null}function co(e){return rn(e.rootPath,".toolnet","context","session-origin.json")}function ao(e,t){if(!ro(t))return t;let n=so(e.rootPath,t);return n.startsWith("..")?t:n}function uo(e,t){let n=typeof t.session_id=="string"&&t.session_id.trim()?t.session_id.trim():"claude",r=Qt(t,e);if(r.length===0)return;let s=st(e,"claude",n),i=new ee(s,{source:"claude",cwd:typeof t.cwd=="string"?t.cwd:e.rootPath}).append(r);Zt(e,s,i)}function nn(e,t){let n=co(e),r={};if(Xs(n))try{let a=JSON.parse(Qs(n,"utf8"));tn(a)&&a.projectId===e.id&&(r=a)}catch{}let s,o=t.tool_input;tn(o)&&typeof o.file_path=="string"&&(s=ao(e,o.file_path));let i=typeof t.session_id=="string"?t.session_id:typeof r.nativeSessionId=="string"?r.nativeSessionId:"claude",d={...r,version:1,projectId:e.id,agent:"claude",nativeSessionId:i,updatedAt:new Date().toISOString()};s&&(d.lastTouchedFile=s),Zs(rn(e.rootPath,".toolnet","context"),{recursive:!0,mode:448});let u=`${n}.tmp-${process.pid}-${Date.now()}`;try{no(u,JSON.stringify(d,null,2)+`
144
+ `,{encoding:"utf8",mode:384}),eo(u,n)}finally{to(u,{force:!0})}}function sn(e){let t=typeof e.hook_event_name=="string"?e.hook_event_name:"",n=typeof e.cwd=="string"?e.cwd:"";if(!n)return{};let r=io(n);if(!r)return{};try{try{uo(r,e)}catch{}if(t==="SessionStart"){let s=Qe({projectPath:n});return s?.trim()?{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:oo(s)}}:{}}if(t==="PostToolUse"){nn(r,e);try{pe(r)}catch{}return{}}if(t==="Stop"){nn(r,e);try{pe(r)}catch{}return{}}return{}}catch{return{}}}async function lo(){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 fo(){let e=await lo(),t=sn(e);process.stdout.write(JSON.stringify(t))}fo().catch(()=>{process.stdout.write("{}"),process.exitCode=0});
@@ -1,37 +1,37 @@
1
- import*as f from"fs";import*as d from"path";function C(e){return e?Math.ceil(e.length/3.5):0}function Q(e,n){if(!e)return"";if(C(e)<=n)return e;let r=Math.floor(n*3.5),o=e.slice(0,r),s=o.lastIndexOf("."),i=o.lastIndexOf(`
1
+ import*as f from"fs";import*as d from"path";function k(e){return e?Math.ceil(e.length/3.5):0}function Q(e,n){if(!e)return"";if(k(e)<=n)return e;let r=Math.floor(n*3.5),o=e.slice(0,r),s=o.lastIndexOf("."),i=o.lastIndexOf(`
2
2
  `),a=Math.max(s,i);return a>r*.7?o.slice(0,a+1):o}function R(e,n){if(!e)return"";let t=e.split(`
3
3
  `).filter(s=>s.trim());if(t.length<=n)return e;let r=t.slice(0,n),o=t.length-n;return[...r,`... (${o} more items omitted)`].join(`
4
4
  `)}function Z(e,n){let{maxTokens:t,trimMarker:r="[Context trimmed by ToolNet Memory token budget]"}=n;if(e.length===0)return"";let o=[...e].sort((c,u)=>u.priority-c.priority),s=[],i=0,a=!1;for(let c of o){let u=`# ${c.title}
5
5
 
6
- `,p=C(u),l=C(c.content),h=p+l;if(i+h<=t)s.push(u+c.content),i+=h;else{let g=t-i-p;if(g>50){let b=Q(c.content,g);s.push(u+b),i=t,a=!0}else a=!0;break}}return a&&s.push(`
6
+ `,p=k(u),l=k(c.content),h=p+l;if(i+h<=t)s.push(u+c.content),i+=h;else{let g=t-i-p;if(g>50){let b=Q(c.content,g);s.push(u+b),i=t,a=!0}else a=!0;break}}return a&&s.push(`
7
7
  ${r}
8
8
  `),s.join(`
9
9
 
10
10
  ---
11
11
 
12
- `)}function T(e,n){let t=[{title:"Profile",content:R(e,10),priority:100},{title:"Current Work",content:R(n,15),priority:90}];return Z(t,{maxTokens:800})}import{chmodSync as Fe,existsSync as X,mkdirSync as $e,readFileSync as q,renameSync as Le,writeFileSync as ze}from"node:fs";import{dirname as Ve,join as _}from"node:path";var I="toolnet.context-offload.v1";function ee(e){return _(e,".toolnet","offload")}function te(e){return _(ee(e),"graph.json")}function E(){return{schema:I,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function ne(e){let n=te(e);if(!X(n))return E();try{let t=JSON.parse(q(n,"utf8"));return t.schema!==I||t.version!==1||!Array.isArray(t.nodes)?E():t}catch{return E()}}function O(e,n){let t=e.replace(/\s+/gu," ").trim();return t.length<=n?t:t.slice(0,n-1).trimEnd()+"\u2026"}function j(e,n={}){let t=ne(e);if(t.nodes.length===0)return"";let r=Math.max(1,Math.min(12,n.maxAssets??6)),o=Math.max(320,Math.min(2400,n.maxChars??900)),s=["[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 t.nodes.slice(-r).reverse()){let a=O(i.sourceRefs.at(-1)??"unknown",72),c=i.files.length>0?` files=${O(i.files.join(","),120)}`:"",u=`event:${a} --offloads--> asset:${i.id.slice(0,12)} kind=${i.kind} bytes=${i.bytes}${c}`;if([...s,u].join(`
12
+ `)}function T(e,n){let t=[{title:"Profile",content:R(e,10),priority:100},{title:"Current Work",content:R(n,15),priority:90}];return Z(t,{maxTokens:800})}import{chmodSync as Fe,existsSync as X,mkdirSync as $e,readFileSync as q,renameSync as Le,writeFileSync as ze}from"node:fs";import{dirname as Ve,join as _}from"node:path";var I="toolnet.context-offload.v1";function ee(e){return _(e,".toolnet","offload")}function te(e){return _(ee(e),"graph.json")}function v(){return{schema:I,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function ne(e){let n=te(e);if(!X(n))return v();try{let t=JSON.parse(q(n,"utf8"));return t.schema!==I||t.version!==1||!Array.isArray(t.nodes)?v():t}catch{return v()}}function O(e,n){let t=e.replace(/\s+/gu," ").trim();return t.length<=n?t:t.slice(0,n-1).trimEnd()+"\u2026"}function j(e,n={}){let t=ne(e);if(t.nodes.length===0)return"";let r=Math.max(1,Math.min(12,n.maxAssets??6)),o=Math.max(320,Math.min(2400,n.maxChars??900)),s=["[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 t.nodes.slice(-r).reverse()){let a=O(i.sourceRefs.at(-1)??"unknown",72),c=i.files.length>0?` files=${O(i.files.join(","),120)}`:"",u=`event:${a} --offloads--> asset:${i.id.slice(0,12)} kind=${i.kind} bytes=${i.bytes}${c}`;if([...s,u].join(`
13
13
  `).length>o)break;s.push(u)}return s.join(`
14
14
  `)}import{existsSync as P,mkdirSync as Je,readFileSync as D,renameSync as Ue,writeFileSync as We}from"node:fs";import{dirname as Ze,join as F}from"node:path";import{createHash as re}from"node:crypto";function N(e){return re("sha256").update(e).digest("hex")}function oe(e){return F(e.rootPath,".toolnet","context","handoff.md")}function se(e){return F(e.rootPath,".toolnet","context","handoff.json")}function ie(e){let n=oe(e);if(!P(n))return null;try{let t=D(n,"utf8").trim();if(!t)return null;let r=new Date(0).toISOString(),o=se(e);if(P(o))try{let s=JSON.parse(D(o,"utf8"));typeof s.generatedAt=="string"&&(r=s.generatedAt)}catch{}return{version:1,projectId:e.id,projectName:e.name,text:t,digest:N(t),generatedAt:r}}catch{return null}}function $(e,n=1800){let t=ie(e);if(!t?.text)return null;let r=t.text;return r.length>n&&(r=`${r.slice(0,n)}
15
15
 
16
16
  [Fast handoff truncated]`),["[TOOLNET FAST HANDOFF]","",`Project: ${e.name}`,`Updated: ${t.generatedAt}`,"",r].join(`
17
- `)}var k="memory_agent_ask";function L(){return`
17
+ `)}var C="memory_agent_ask";function L(){return`
18
18
  [TOOLNET MEMORY AGENT]
19
19
 
20
20
  Tool:
21
- - ${k}
21
+ - ${C}
22
22
 
23
23
  For resume/continue requests:
24
24
 
25
25
  1. Use the injected ToolNet continuity handoff FIRST.
26
26
  2. If the handoff is missing or ambiguous, invoke
27
- ${k} directly BEFORE repository/history exploration.
27
+ ${C} directly BEFORE repository/history exploration.
28
28
  3. NEVER reconstruct prior work from:
29
29
  - .toolnet/sessions/**
30
30
  - state.json
31
31
  - events.jsonl
32
32
  - raw transcripts
33
33
  4. NEVER search for the implementation/schema of
34
- ${k}; invoke the MCP tool directly.
34
+ ${C}; invoke the MCP tool directly.
35
35
  5. Inspect git/source only AFTER continuity context is known.
36
36
 
37
37
  Use:
@@ -61,9 +61,9 @@ Forbidden At Startup:
61
61
  - Do not perform deep recovery merely because an agent starts.
62
62
  - If the user asks to resume previous work and fast context is insufficient,
63
63
  use memory_agent_ask before guessing.
64
- `;return u+p+h+b+W}import{existsSync as ve}from"node:fs";import{dirname as Me,join as Re,parse as Te,resolve as Oe}from"node:path";import{existsSync as ce,readFileSync as ue}from"node:fs";import{homedir as de}from"node:os";import{join as le}from"node:path";function fe(e){let n=e.trim();return n.length>=2&&n.startsWith('"')&&n.endsWith('"')?(n=n.slice(1,-1),n.replace(/\\n/g,`
65
- `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):n.length>=2&&n.startsWith("'")&&n.endsWith("'")?n.slice(1,-1):n}function pe(){let e=process.env.TOOLNET_GLOBAL_ENV??le(de(),".config","toolnet-memory",".env");if(!ce(e))return;let n=ue(e,"utf8");for(let t of n.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let s=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=fe(r.slice(o+1)))}}pe();import{createHash as me}from"node:crypto";import{existsSync as v,mkdirSync as ge,readFileSync as ye,renameSync as he,writeFileSync as Se}from"node:fs";import{basename as xe,dirname as S,join as w,parse as K,resolve as y}from"node:path";var Y=".toolnet",we="project.json";function be(e){return me("sha256").update(e).digest("hex").slice(0,16)}function M(e){return w(e,Y,we)}function Ae(e){return v(M(e))}function Ce(e,n){let t=y(e),r=K(t).root;for(;;){if(Ae(t))return t;if(t===r||n&&t===y(n))break;let o=S(t);if(o===t)break;t=o}return null}function Ee(e){let n=y(e),t=K(n).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(s=>v(w(n,s))))return n;if(n===t)break;let o=S(n);if(o===n)break;n=o}return y(e)}function ke(e){let n;try{n=JSON.parse(ye(e,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${e}: ${o instanceof Error?o.message:String(o)}`)}if(!n||typeof n!="object")throw new Error(`Invalid ToolNet project manifest: ${e}`);let t=n;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${e}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${e}`);let r=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:S(S(e)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function H(e,n){let t=w(e,Y);ge(t,{recursive:!0});let r=M(e),o=`${r}.tmp-${process.pid}`;Se(o,JSON.stringify(n,null,2)+`
66
- `,{encoding:"utf8",mode:384}),he(o,r)}function B(e,n){return{id:e.id,name:e.name,remote:e.remote,rootPath:n,createdAt:e.createdAt,updatedAt:e.updatedAt,graphVersion:e.graphVersion,memoryVersion:e.memoryVersion,metadata:e.metadata}}var x=class{detect(n=process.cwd()){let t=y(n),r=Ee(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>v(w(r,p))),i=Ce(t,s?r:void 0);if(i){let p=M(i),l=ke(p);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),H(i,l)),B(l,i)}let a=new Date().toISOString(),c=xe(r),u={version:1,id:be(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return H(r,u),B(u,r)}};function J(e){let n=Oe(e),t=Te(n).root;for(;;){if(ve(Re(n,".toolnet","project.json")))return new x().detect(n);if(n===t)break;let r=Me(n);if(r===n)break;n=r}return null}var U=3200;async function _e(){let e="";for await(let n of process.stdin)e+=n.toString();if(!e.trim())return{};try{return JSON.parse(e)}catch{return{}}}function m(){process.stdout.write("{}")}function Ie(e){return e.length<=U?e:`${e.slice(0,U)}
64
+ `;return u+p+h+b+W}import{existsSync as Ee}from"node:fs";import{dirname as Me,join as Re,parse as Te,resolve as Oe}from"node:path";import{existsSync as ce,readFileSync as ue}from"node:fs";import{homedir as de}from"node:os";import{join as le}from"node:path";function fe(e){let n=e.trim();return n.length>=2&&n.startsWith('"')&&n.endsWith('"')?(n=n.slice(1,-1),n.replace(/\\n/g,`
65
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):n.length>=2&&n.startsWith("'")&&n.endsWith("'")?n.slice(1,-1):n}function pe(){let e=process.env.TOOLNET_GLOBAL_ENV??le(de(),".config","toolnet-memory",".env");if(!ce(e))return;let n=ue(e,"utf8");for(let t of n.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let s=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=fe(r.slice(o+1)))}}pe();import{createHash as me}from"node:crypto";import{existsSync as E,mkdirSync as ge,readFileSync as ye,renameSync as he,writeFileSync as Se}from"node:fs";import{basename as xe,dirname as S,join as w,parse as B,resolve as y}from"node:path";var Y=".toolnet",we="project.json";function be(e){return me("sha256").update(e).digest("hex").slice(0,16)}function M(e){return w(e,Y,we)}function Ae(e){return E(M(e))}function ke(e,n){let t=y(e),r=B(t).root;for(;;){if(Ae(t))return t;if(t===r||n&&t===y(n))break;let o=S(t);if(o===t)break;t=o}return null}function ve(e){let n=y(e),t=B(n).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(s=>E(w(n,s))))return n;if(n===t)break;let o=S(n);if(o===n)break;n=o}return y(e)}function Ce(e){let n;try{n=JSON.parse(ye(e,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${e}: ${o instanceof Error?o.message:String(o)}`)}if(!n||typeof n!="object")throw new Error(`Invalid ToolNet project manifest: ${e}`);let t=n;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${e}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${e}`);let r=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:S(S(e)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function H(e,n){let t=w(e,Y);ge(t,{recursive:!0});let r=M(e),o=`${r}.tmp-${process.pid}`;Se(o,JSON.stringify(n,null,2)+`
66
+ `,{encoding:"utf8",mode:384}),he(o,r)}function K(e,n){return{id:e.id,name:e.name,remote:e.remote,rootPath:n,createdAt:e.createdAt,updatedAt:e.updatedAt,graphVersion:e.graphVersion,memoryVersion:e.memoryVersion,metadata:e.metadata}}var x=class{detect(n=process.cwd()){let t=y(n),r=ve(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>E(w(r,p))),i=ke(t,s?r:void 0);if(i){let p=M(i),l=Ce(p);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),H(i,l)),K(l,i)}let a=new Date().toISOString(),c=xe(r),u={version:1,id:be(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return H(r,u),K(u,r)}};function J(e){let n=Oe(e),t=Te(n).root;for(;;){if(Ee(Re(n,".toolnet","project.json")))return new x().detect(n);if(n===t)break;let r=Me(n);if(r===n)break;n=r}return null}var U=3200;async function _e(){let e="";for await(let n of process.stdin)e+=n.toString();if(!e.trim())return{};try{return JSON.parse(e)}catch{return{}}}function m(){process.stdout.write("{}")}function Ie(e){return e.length<=U?e:`${e.slice(0,U)}
67
67
 
68
68
  [ToolNet startup context truncated]`}function je(e,n,t){if(process.env.TOOLNET_CODEX_STARTUP_DEBUG!=="1")return;let r=Date.now()-e;process.stderr.write(`[toolnet-memory] codex SessionStart ${r}ms cwd=${n} chars=${t}
69
69
  `)}async function Ne(){let e=Date.now(),n=await _e();if(n.hook_event_name!=="SessionStart"){m();return}let t=typeof n.cwd=="string"?n.cwd:"";if(!t){m();return}if(!J(t)){m();return}try{let o=V({projectPath:t});if(!o?.trim()){m();return}let s=Ie(o),i={hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:s}};je(e,t,s.length),process.stdout.write(JSON.stringify(i))}catch{m()}}Ne().catch(()=>{m(),process.exitCode=0});