toolnet-memory 0.2.21 → 0.3.1

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,12 +1,12 @@
1
- import{existsSync as Vt,readFileSync as Gt}from"node:fs";import{homedir as Yt}from"node:os";import{join as Qt}from"node:path";function Xt(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
- `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function Zt(){let t=process.env.TOOLNET_GLOBAL_ENV??Qt(Yt(),".config","toolnet-memory",".env");if(!Vt(t))return;let e=Gt(t,"utf8");for(let r of e.split(/\r?\n/)){let n=r.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let s=n.indexOf("=");if(s<=0)continue;let o=n.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=Xt(n.slice(s+1)))}}Zt();function W(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function z(t,e){if(!t)return e;let r=Number(t);return Number.isFinite(r)?r:e}function Y(){return{memory:{autoCapture:W(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:W(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:W(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:W(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:z(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:z(process.env.MEMORY_RERANK_TOP,10),finalContext:z(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:z(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:W(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:z(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as er}from"node:crypto";import{existsSync as be,mkdirSync as tr,readFileSync as rr,renameSync as nr,writeFileSync as sr}from"node:fs";import{basename as or,dirname as Q,join as Z,parse as Ke,resolve as q}from"node:path";var Be=".toolnet",ir="project.json";function ar(t){return er("sha256").update(t).digest("hex").slice(0,16)}function we(t){return Z(t,Be,ir)}function cr(t){return be(we(t))}function ur(t,e){let r=q(t),n=Ke(r).root;for(;;){if(cr(r))return r;if(r===n||e&&r===q(e))break;let s=Q(r);if(s===r)break;r=s}return null}function lr(t){let e=q(t),r=Ke(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(o=>be(Z(e,o))))return e;if(e===r)break;let s=Q(e);if(s===e)break;e=s}return q(t)}function dr(t){let e;try{e=JSON.parse(rr(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let r=e;if(typeof r.id!="string"||!r.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof r.name!="string"||!r.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let n=new Date().toISOString();return{version:1,id:r.id,name:r.name,remote:typeof r.remote=="string"&&r.remote.trim()?r.remote:r.name,rootPath:typeof r.rootPath=="string"?r.rootPath:Q(Q(t)),createdAt:typeof r.createdAt=="string"?r.createdAt:n,updatedAt:typeof r.updatedAt=="string"?r.updatedAt:n,graphVersion:typeof r.graphVersion=="number"?r.graphVersion:0,memoryVersion:typeof r.memoryVersion=="number"?r.memoryVersion:0,metadata:r.metadata&&typeof r.metadata=="object"?r.metadata:void 0}}function De(t,e){let r=Z(t,Be);tr(r,{recursive:!0});let n=we(t),s=`${n}.tmp-${process.pid}`;sr(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),nr(s,n)}function Fe(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var X=class{detect(e=process.cwd()){let r=q(e),n=lr(r),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>be(Z(n,p))),i=ur(r,o?n:void 0);if(i){let p=we(i),l=dr(p);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),De(i,l)),Fe(l,i)}let u=new Date().toISOString(),c=or(n),a={version:1,id:ar(n),name:c,remote:c,rootPath:n,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return De(n,a),Fe(a,n)}};var pr=[{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}],ee=class{scan(e){let r=[];for(let n of pr){let s=new RegExp(n.regex.source,n.regex.flags);for(let o of e.matchAll(s))r.push({type:n.type,value:o[0]})}return r}hasSecrets(e){return this.scan(e).length>0}};var H=class{scanner=new ee;sanitize(e){let r=e,n=this.scanner.scan(e),s=new Set;for(let o of n)s.add(o.type),r=r.split(o.value).join(`[REDACTED:${o.type}]`);return{text:r,redacted:n.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(r=>this.sanitizeValue(r));if(e&&typeof e=="object"){let r={};for(let[n,s]of Object.entries(e)){let o=n.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?r[n]="[REDACTED]":r[n]=this.sanitizeValue(s)}return r}return e}};import{homedir as Nr}from"node:os";import{join as Lr}from"node:path";import{DeleteObjectCommand as fr,GetObjectCommand as mr,HeadObjectCommand as gr,ListObjectsV2Command as hr,PutObjectCommand as yr,S3Client as kr}from"@aws-sdk/client-s3";import{getSignedUrl as Sr}from"@aws-sdk/s3-request-presigner";var te=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new kr({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,r,n="application/octet-stream"){let s=typeof r=="string"?Buffer.from(r,"utf8"):r;await this.client.send(new yr({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await Sr(this.client,new mr({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(r,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await this.client.send(new gr({Bucket:this.bucket,Key:e})),!0}catch(r){if(typeof r=="object"&&r!==null&&"$metadata"in r&&r.$metadata?.httpStatusCode===404)return!1;throw r}}async delete(e){await this.client.send(new fr({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new hr({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let o of s.Contents??[])o.Key&&r.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return r}};import{access as Ue,mkdir as vr,readFile as br,readdir as wr,rm as xr,stat as We,writeFile as Ar}from"node:fs/promises";import{dirname as Ir,join as jr,relative as ze,resolve as Er}from"node:path";var J=class{constructor(e){this.root=e}root;name="local";path(e){let r=e.replace(/^\/+/,"");return Er(this.root,r)}async put(e,r){let n=this.path(e);await vr(Ir(n),{recursive:!0}),await Ar(n,r)}async get(e){try{return await br(this.path(e))}catch(r){if(typeof r=="object"&&r!==null&&"code"in r&&r.code==="ENOENT")return null;throw r}}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await Ue(this.path(e)),!0}catch{return!1}}async delete(e){await xr(this.path(e),{force:!0})}async list(e=""){let r=this.path(e),n=[];try{await Ue(r)}catch{return n}let s=async i=>{let u=await wr(i,{withFileTypes:!0});for(let c of u){let a=jr(i,c.name);if(c.isDirectory()){await s(a);continue}let p=await We(a);n.push({key:ze(this.root,a),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await We(r);return o.isDirectory()?await s(r):n.push({key:ze(this.root,r),size:o.size,updatedAt:o.mtime.toISOString()}),n}};import{DeleteObjectCommand as Pr,GetObjectCommand as Mr,HeadObjectCommand as Or,ListObjectsV2Command as Tr,PutObjectCommand as _r,S3Client as Cr}from"@aws-sdk/client-s3";import{getSignedUrl as Rr}from"@aws-sdk/s3-request-presigner";var V=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Cr({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,r,n="application/octet-stream"){let s=typeof r=="string"?Buffer.from(r,"utf8"):r;await this.client.send(new _r({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await Rr(this.client,new Mr({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(r,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`${this.name} download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await this.client.send(new Or({Bucket:this.bucket,Key:e})),!0}catch(r){if(typeof r=="object"&&r!==null&&"$metadata"in r&&r.$metadata?.httpStatusCode===404)return!1;throw r}}async delete(e){await this.client.send(new Pr({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new Tr({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let o of s.Contents??[])o.Key&&r.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return r}};function xe(t,e){return console.warn(e),new J(t)}function qe(t){let e=t.localRoot??Lr(Nr(),".toolnet-memory","storage");if(t.provider==="r2"){let r=t.r2;return r?.accountId&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new V({name:"r2",endpoint:`https://${r.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:r.bucket,forcePathStyle:!0,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):xe(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let r=t.s3;return r?.bucket&&r.accessKeyId&&r.secretAccessKey?new V({name:"s3",endpoint:r.endpoint,region:r.region??"us-east-1",bucket:r.bucket,forcePathStyle:r.forcePathStyle??!1,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):xe(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let r=t.huggingface;return r?.namespace&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new te({namespace:r.namespace,bucket:r.bucket,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):xe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new J(e)}function $r(t){return new Promise(e=>setTimeout(e,t))}async function He(t,e={}){let r=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=r;i++)try{return await t()}catch(u){if(o=u,i>=r)break;let c=Math.min(s,n*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,c*.2));await $r(c+a)}throw o}var Dr=new Set(["put","get","getText","delete","list"]);function Je(t,e={}){return new Proxy(t,{get(r,n){let s=Reflect.get(r,n,r);return typeof s!="function"?s:Dr.has(n)?(...o)=>He(()=>Promise.resolve(s.apply(r,o)),e):s.bind(r)}})}function Ve(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Ge(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let r=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var re=class{constructor(e,r,n,s){this.provider=e;this.name=e.name,this.projectId=r,this.projectName=n,this.folder=Ve(s??n),this.sourcePrefix=`projects/${r}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,r=new Date().toISOString(),n=r,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(u){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${u instanceof Error?u.message:String(u)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(n=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:r};await this.provider.put(e,JSON.stringify(o,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Ge(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,r,n){return await this.ensureRegistered(),this.provider.put(this.key(e),r,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{createHash as Fr}from"node:crypto";import{dirname as Kr}from"node:path";import{mkdirSync as Br,readFileSync as Ur,renameSync as Wr,writeFileSync as zr}from"node:fs";function S(t){return Fr("sha256").update(t).digest("hex")}function Ae(t){if(Array.isArray(t))return t.map(Ae);if(t&&typeof t=="object"){let e=t,r={};for(let n of Object.keys(e).sort())r[n]=Ae(e[n]);return r}return t}function Ye(t){return JSON.stringify(Ae(t))}function Qe(t){try{return JSON.parse(Ur(t,"utf8"))}catch{return null}}function A(t,e){Br(Kr(t),{recursive:!0});let r=`${t}.${process.pid}.tmp`;zr(r,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),Wr(r,t)}var qr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function F(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ze(t){return F(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function D(t,e,r=0){if(!(r>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let n of t.slice(0,50))D(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(qr.has(n)||["data","payload","parts","messages"].includes(n))&&D(s,e,r+1)}}function ne(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function Xe(t){let e=F(t);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(e)}function w(t,e,r,n,s={}){let o=F(n),i=s.key??Ze(o);return{version:1,id:S([t.projectId,r,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:r,key:i,text:o,status:s.status,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function Hr(t,e,r){let n=F(r);if(n.length<5||n.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(n),i=n.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(w(t,e,"goal",i[1],{confidence:.97}));let u=n.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);u?.[1]&&s.push(w(t,e,"plan",u[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=c.exec(n));){let m=Number(a[1]),d=F(a[2]??""),y=d&&!Xe(d)?`Phase ${m} - ${d}`:`Phase ${m}`;s.push(w(t,e,"phase",y,{key:`phase:${m}`,order:m,status:ne(n),confidence:.93}))}let p=r.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(w(t,e,"task",p[2],{status:p[1].trim()?"completed":ne(p[2]),confidence:.96}));let l=n.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let m=l[1]?Number(l[1]):void 0,d=F(l[2]),y=Xe(d);s.push(w(t,e,"task",y&&m!==void 0?`TODO ${m}`:d,{key:m!==void 0?`task:${m}`:Ze(d),order:m,status:ne(n),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(n)){let m=n.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");m&&s.push(w(t,e,"next_action",m,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(n)&&s.push(w(t,e,"blocker",n,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(n)&&s.push(w(t,e,"warning",n,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(n)&&s.push(w(t,e,"decision",n,{confidence:.9})),s}function et(t,e){if(e.length===0)return[];let r=[],n=new Set;function s(i){n.has(i.id)||(n.add(i.id),r.push(i))}for(let i of e){if(i.type==="decision"){let c=[];D(i.data,c);for(let a of c)s(w(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let c=[];D(i.data,c);for(let a of c)s(w(t,i,"task",a,{status:ne(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let a=i.data[c];typeof a=="string"&&a&&s(w(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let c=[];D(i.data,c);for(let a of c)s(w(t,i,"test",a,{confidence:1}))}let u=[];D(i.data,u);for(let c of u)for(let a of c.split(/\n+/u))for(let p of Hr(t,i,a))s(p)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),r}function tt(t){return String(t).padStart(12,"0")}var se=class{constructor(e){this.storage=e}storage;async write(e,r){if(r.length===0)return null;let n=Math.min(...r.map(a=>a.sequence)),s=Math.max(...r.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:n,lastSequence:s,observations:r},i=JSON.stringify(o,null,2)+`
6
- `,u=S(r.map(a=>a.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${tt(n)}-${tt(s)}-${u}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as rt}from"node:path";import{mkdirSync as Jr}from"node:fs";function Vr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function K(t,e=20){let r=[],n=new Set;for(let s of t.slice().reverse()){let o=Vr(s);if(!(!o||n.has(o))&&(n.add(o),r.push(s),r.length>=e))break}return r.reverse()}function Gr(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function nt(t,e){let r=e.status??t?.status??"pending",n=r;t&&(t.status==="completed"&&r!=="completed"?n="completed":r==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(n=t.status));let s=t&&Gr(e)?t.title:e.text;return{id:t?.id??S(e.key).slice(0,24),title:s,status:n,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function Yr(t,e){let r=`projects/${t.id}/work/observations/`,n=await e.list(r),s=[];for(let o of n.filter(i=>i.key.endsWith(".json")).sort((i,u)=>i.key.localeCompare(u.key))){let i=await e.getText(o.key);if(i)try{let u=JSON.parse(i);u.version===1&&Array.isArray(u.observations)&&s.push(u)}catch{}}return s}async function oe(t,e){let n=(await Yr(t,e)).flatMap(f=>f.observations).sort((f,x)=>{let Le=f.occurredAt.localeCompare(x.occurredAt);if(Le!==0)return Le;let $e=f.sequence-x.sequence;return $e!==0?$e:f.id.localeCompare(x.id)}),s=new Map,o=new Map,i,u,c,a=[],p=[],l=[],m=[],d=[],y=[];for(let f of n)switch(f.kind){case"goal":i=f.text;break;case"plan":u=f.text;break;case"phase":s.set(f.key,nt(s.get(f.key),f));break;case"task":o.set(f.key,nt(o.get(f.key),f));break;case"decision":a.push(f.text);break;case"blocker":p.push(f.text);break;case"warning":l.push(f.text);break;case"next_action":m.push(f.text);break;case"file":d.push(f.text);break;case"test":y.push(f.text);break;case"session":c={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let k=Array.from(s.values()).sort((f,x)=>(f.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((f,x)=>(f.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),h=k.find(f=>f.status==="in_progress")??k.find(f=>f.status==="blocked")??k.find(f=>f.status==="pending"),b=g.find(f=>f.status==="in_progress")??g.find(f=>f.status==="blocked")??g.find(f=>f.status==="pending"),R=K([...m,...b?[b.title]:[],...!b&&h?[h.title]:[],...g.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),$=K([...p,...k.filter(f=>f.status==="blocked").map(f=>f.title),...g.filter(f=>f.status==="blocked").map(f=>f.title)],20),M={version:1,projectId:t.id,projectName:t.name,goal:i,plan:u,phases:k,tasks:g,decisions:K(a,20),blockers:$,warnings:K(l,20),nextActions:R,filesTouched:K(d,30),tests:K(y,20),currentPhase:h,currentTask:b,progress:{phasesTotal:k.length,phasesCompleted:k.filter(f=>f.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(f=>f.status==="completed").length,blocked:k.filter(f=>f.status==="blocked").length+g.filter(f=>f.status==="blocked").length},lastSession:c,updatedAt:n.length?n[n.length-1].occurredAt:new Date().toISOString()},N=rt(t.rootPath,".toolnet","work");return Jr(N,{recursive:!0}),A(rt(N,"current.json"),M),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(M,null,2)+`
7
- `,"application/json"),M}async function B(t,e){let r=await e.getText(`projects/${t.id}/work/current.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}import{closeSync as Qr,existsSync as Xr,openSync as Zr,readSync as en,statSync as tn}from"node:fs";function rn(t,e){if(!Xr(t))return{events:[],nextOffset:e};let r=tn(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=r-n,o=Buffer.alloc(s),i=Zr(t,"r");try{en(i,o,0,s,n)}finally{Qr(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
8
- `);if(c<0)return{events:[],nextOffset:n};let a=u.slice(0,c+1);return{events:a.split(`
9
- `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(a,"utf8")}}var ie=class{constructor(e){this.options=e;this.journal=new se(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),r=Number(e.sourceCursors["work.continuity.offset"]??0),n=rn(this.options.wal.eventsFile,Number.isFinite(r)?r:0);if(n.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:n.nextOffset};let s=et(this.options.identity,n.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await oe(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",n.nextOffset),{scannedEvents:n.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:n.nextOffset}}};import{mkdirSync as gn}from"node:fs";import{join as Ie}from"node:path";import{existsSync as it,mkdirSync as nn,readFileSync as sn,statSync as st,writeFileSync as on}from"node:fs";import{dirname as an,join as cn}from"node:path";var ot=64*1024,un=`# ToolNet Project Operating Manual
1
+ import{existsSync as kr,readFileSync as Sr}from"node:fs";import{homedir as vr}from"node:os";import{join as wr}from"node:path";function br(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function xr(){let t=process.env.TOOLNET_GLOBAL_ENV??wr(vr(),".config","toolnet-memory",".env");if(!kr(t))return;let e=Sr(t,"utf8");for(let n of e.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]=br(r.slice(s+1)))}}xr();function Y(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function Q(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function pe(){return{memory:{autoCapture:Y(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:Y(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:Y(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:Y(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:Q(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:Q(process.env.MEMORY_RERANK_TOP,10),finalContext:Q(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:Q(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:Y(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:Q(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Ar}from"node:crypto";import{existsSync as qe,mkdirSync as Ir,readFileSync as jr,renameSync as Pr,writeFileSync as Er}from"node:fs";import{basename as Mr,dirname as fe,join as ge,parse as St,resolve as X}from"node:path";var vt=".toolnet",Cr="project.json";function Tr(t){return Ar("sha256").update(t).digest("hex").slice(0,16)}function Ve(t){return ge(t,vt,Cr)}function Or(t){return qe(Ve(t))}function _r(t,e){let n=X(t),r=St(n).root;for(;;){if(Or(n))return n;if(n===r||e&&n===X(e))break;let s=fe(n);if(s===n)break;n=s}return null}function Rr(t){let e=X(t),n=St(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>qe(ge(e,o))))return e;if(e===n)break;let s=fe(e);if(s===e)break;e=s}return X(t)}function Nr(t){let e;try{e=JSON.parse(jr(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let n=e;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);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:fe(fe(t)),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 ht(t,e){let n=ge(t,vt);Ir(n,{recursive:!0});let r=Ve(t),s=`${r}.tmp-${process.pid}`;Er(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Pr(s,r)}function kt(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var me=class{detect(e=process.cwd()){let n=X(e),r=Rr(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>qe(ge(r,p))),i=_r(n,o?r:void 0);if(i){let p=Ve(i),l=Nr(p);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),ht(i,l)),kt(l,i)}let a=new Date().toISOString(),c=Mr(r),u={version:1,id:Tr(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return ht(r,u),kt(u,r)}};var Lr=[{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}],ye=class{scan(e){let n=[];for(let r of Lr){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var Z=class{scanner=new ye;sanitize(e){let n=e,r=this.scanner.scan(e),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(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as os}from"node:os";import{join as is}from"node:path";import{DeleteObjectCommand as $r,GetObjectCommand as Kr,HeadObjectCommand as Dr,ListObjectsV2Command as Fr,PutObjectCommand as Wr,S3Client as Br}from"@aws-sdk/client-s3";import{getSignedUrl as zr}from"@aws-sdk/s3-request-presigner";var he=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Br({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Wr({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await zr(this.client,new Kr({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Dr({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new $r({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Fr({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as wt,mkdir as Ur,readFile as qr,readdir as Vr,rm as Gr,stat as bt,writeFile as Hr}from"node:fs/promises";import{dirname as Jr,join as Yr,relative as xt,resolve as Qr}from"node:path";var ee=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Qr(this.root,n)}async put(e,n){let r=this.path(e);await Ur(Jr(r),{recursive:!0}),await Hr(r,n)}async get(e){try{return await qr(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await wt(this.path(e)),!0}catch{return!1}}async delete(e){await Gr(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await wt(n)}catch{return r}let s=async i=>{let a=await Vr(i,{withFileTypes:!0});for(let c of a){let u=Yr(i,c.name);if(c.isDirectory()){await s(u);continue}let p=await bt(u);r.push({key:xt(this.root,u),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await bt(n);return o.isDirectory()?await s(n):r.push({key:xt(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Xr,GetObjectCommand as Zr,HeadObjectCommand as es,ListObjectsV2Command as ts,PutObjectCommand as ns,S3Client as rs}from"@aws-sdk/client-s3";import{getSignedUrl as ss}from"@aws-sdk/s3-request-presigner";var te=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new rs({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new ns({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await ss(this.client,new Zr({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new es({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new Xr({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new ts({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function Ge(t,e){return console.warn(e),new ee(t)}function At(t){let e=t.localRoot??is(os(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new te({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ge(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new te({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ge(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new he({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ge(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new ee(e)}function as(t){return new Promise(e=>setTimeout(e,t))}async function It(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(a){if(o=a,i>=n)break;let c=Math.min(s,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await as(c+u)}throw o}var cs=new Set(["put","get","getText","delete","list"]);function jt(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:cs.has(r)?(...o)=>It(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Pt(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Et(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var ke=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Pt(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Et(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{createHash as us}from"node:crypto";import{dirname as ls}from"node:path";import{mkdirSync as ds,readFileSync as ps,renameSync as fs,writeFileSync as ms}from"node:fs";function S(t){return us("sha256").update(t).digest("hex")}function He(t){if(Array.isArray(t))return t.map(He);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=He(e[r]);return n}return t}function Mt(t){return JSON.stringify(He(t))}function Ct(t){try{return JSON.parse(ps(t,"utf8"))}catch{return null}}function j(t,e){ds(ls(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;ms(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),fs(n,t)}var gs=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function q(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ot(t){return q(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function U(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))U(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(gs.has(r)||["data","payload","parts","messages"].includes(r))&&U(s,e,n+1)}}function Se(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function Tt(t){let e=q(t);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(e)}function I(t,e,n,r,s={}){let o=q(r),i=s.key??Ot(o);return{version:1,id:S([t.projectId,n,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function ys(t,e,n){let r=q(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(I(t,e,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&s.push(I(t,e,"plan",a[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,u;for(;!o&&(u=c.exec(r));){let f=Number(u[1]),d=q(u[2]??""),m=d&&!Tt(d)?`Phase ${f} - ${d}`:`Phase ${f}`;s.push(I(t,e,"phase",m,{key:`phase:${f}`,order:f,status:Se(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(I(t,e,"task",p[2],{status:p[1].trim()?"completed":Se(p[2]),confidence:.96}));let l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let f=l[1]?Number(l[1]):void 0,d=q(l[2]),m=Tt(d);s.push(I(t,e,"task",m&&f!==void 0?`TODO ${f}`:d,{key:f!==void 0?`task:${f}`:Ot(d),order:f,status:Se(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 f=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");f&&s.push(I(t,e,"next_action",f,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(I(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(I(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(I(t,e,"decision",r,{confidence:.9})),s}function _t(t,e){if(e.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 e){if(i.type==="decision"){let c=[];U(i.data,c);for(let u of c)s(I(t,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];U(i.data,c);for(let u of c)s(I(t,i,"task",u,{status:Se(u),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let u=i.data[c];typeof u=="string"&&u&&s(I(t,i,"file",u,{confidence:1}))}if(i.type==="test"){let c=[];U(i.data,c);for(let u of c)s(I(t,i,"test",u,{confidence:1}))}let a=[];U(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let p of ys(t,i,u))s(p)}let o=e[e.length-1];return s(I(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function Rt(t){return String(t).padStart(12,"0")}var ve=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.sequence)),s=Math.max(...n.map(u=>u.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
6
+ `,a=S(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Rt(r)}-${Rt(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Nt}from"node:path";import{mkdirSync as hs}from"node:fs";function ks(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function V(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=ks(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Ss(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function Lt(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&Ss(e)?t.title:e.text;return{id:t?.id??S(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function vs(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}async function we(t,e){let r=(await vs(t,e)).flatMap(k=>k.observations).sort((k,x)=>{let de=k.occurredAt.localeCompare(x.occurredAt);if(de!==0)return de;let yt=k.sequence-x.sequence;return yt!==0?yt:k.id.localeCompare(x.id)}),s=new Map,o=new Map,i,a,c,u=[],p=[],l=[],f=[],d=[],m=[];for(let k of r)switch(k.kind){case"goal":i=k.text;break;case"plan":a=k.text;break;case"phase":s.set(k.key,Lt(s.get(k.key),k));break;case"task":o.set(k.key,Lt(o.get(k.key),k));break;case"decision":u.push(k.text);break;case"blocker":p.push(k.text);break;case"warning":l.push(k.text);break;case"next_action":f.push(k.text);break;case"file":d.push(k.text);break;case"test":m.push(k.text);break;case"session":c={agent:k.agent,nativeSessionId:k.nativeSessionId,sessionKey:k.sessionKey,updatedAt:k.occurredAt};break}let h=Array.from(s.values()).sort((k,x)=>(k.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),y=Array.from(o.values()).sort((k,x)=>(k.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),g=h.find(k=>k.status==="in_progress")??h.find(k=>k.status==="blocked")??h.find(k=>k.status==="pending"),v=y.find(k=>k.status==="in_progress")??y.find(k=>k.status==="blocked")??y.find(k=>k.status==="pending"),P=V([...f,...v?[v.title]:[],...!v&&g?[g.title]:[],...y.filter(k=>k.status==="pending").slice(0,5).map(k=>k.title)],8),T=V([...p,...h.filter(k=>k.status==="blocked").map(k=>k.title),...y.filter(k=>k.status==="blocked").map(k=>k.title)],20),A={version:1,projectId:t.id,projectName:t.name,goal:i,plan:a,phases:h,tasks:y,decisions:V(u,20),blockers:T,warnings:V(l,20),nextActions:P,filesTouched:V(d,30),tests:V(m,20),currentPhase:g,currentTask:v,progress:{phasesTotal:h.length,phasesCompleted:h.filter(k=>k.status==="completed").length,tasksTotal:y.length,tasksCompleted:y.filter(k=>k.status==="completed").length,blocked:h.filter(k=>k.status==="blocked").length+y.filter(k=>k.status==="blocked").length},lastSession:c,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},R=Nt(t.rootPath,".toolnet","work");return hs(R,{recursive:!0}),j(Nt(R,"current.json"),A),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(A,null,2)+`
7
+ `,"application/json"),A}async function G(t,e){let n=await e.getText(`projects/${t.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}import{closeSync as ws,existsSync as bs,openSync as xs,readSync as As,statSync as Is}from"node:fs";function js(t,e){if(!bs(t))return{events:[],nextOffset:e};let n=Is(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=xs(t,"r");try{As(i,o,0,s,r)}finally{ws(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
8
+ `);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
9
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var be=class{constructor(e){this.options=e;this.journal=new ve(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=js(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=_t(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await we(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as Ks}from"node:fs";import{join as Je}from"node:path";import{existsSync as Dt,mkdirSync as Ps,readFileSync as Es,statSync as $t,writeFileSync as Ms}from"node:fs";import{dirname as Cs,join as Ts}from"node:path";var Kt=64*1024,Os=`# ToolNet Project Operating Manual
10
10
 
11
11
  This file contains persistent instructions for AI agents working on this project.
12
12
 
@@ -49,42 +49,42 @@ Things an AI agent should always remember.
49
49
  <!--
50
50
  - [advisory] Prefer small focused files.
51
51
  -->
52
- `;function ae(t){return cn(t.rootPath,".toolnet","PROJECT.md")}function ln(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function dn(t){let e=[],r=new Set,n=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=n.exec(t);){let o=s[1].toLowerCase(),i=ln(s[2]);if(!i)continue;let u=`${o}:${i.toLowerCase()}`;r.has(u)||(r.add(u),e.push({id:S(u).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function pn(t){let e=ae(t);return it(e)||(nn(an(e),{recursive:!0}),on(e,un,{encoding:"utf8",mode:384})),e}function ce(t,e=!1){let r=e?pn(t):ae(t);if(!it(r))return null;if(st(r).size>ot)throw new Error(`PROJECT.md exceeds ${ot} bytes`);let s=sn(r,"utf8");return{path:r,content:s,digest:S(s),rules:dn(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(st(r).mtimeMs).toISOString()}}function I(t,e){let r=new Set,n=[];for(let s of t){let o=s.replace(/\s+/g," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!r.has(i)&&(r.add(i),n.push(o),n.length>=e))break}return n}function at(t){if(t)return{id:t.id,title:t.title,status:t.status}}function fn(t){let e=t.slice(-10).join(`
53
- `).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(e)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(e)?"passing":"unknown"}function mn(t){return S(JSON.stringify(t))}function ct(t){let{project:e,identity:r,state:n}=t,s=n.filesTouched.at(-1),o=n.phases.filter(h=>h.status==="completed").map(h=>h.title),i=n.tasks.filter(h=>h.status==="completed").map(h=>h.title),u=n.phases.filter(h=>h.status!=="completed"&&h.status!=="cancelled").map(h=>h.title),c=n.tasks.filter(h=>h.status!=="completed"&&h.status!=="cancelled").map(h=>h.title),a=I(n.nextActions,10),p=I([...c,...a],15),l=I(n.tests.slice().reverse(),10),m=I(n.filesTouched.slice().reverse(),20),d={schema:"toolnet.handoff.v2",version:2,project:{id:e.id,name:e.name},source:{agent:r.agent,nativeSessionId:r.nativeSessionId,sessionKey:r.sessionKey,sequence:t.sequence,reason:t.reason},capturedAt:t.capturedAt??new Date().toISOString(),goal:n.goal,current:{phase:at(n.currentPhase),task:at(n.currentTask),file:s},completed:{phases:I(o,20),tasks:I(i,30)},remaining:{phases:I(u,20),tasks:I(c,30),todos:p},nextAction:a[0],blockers:I(n.blockers.slice().reverse(),10),decisions:I(n.decisions.slice().reverse(),10),files:{current:s,recent:m},tests:{status:fn(n.tests),recent:l},attention:I(t.attention??[],20),progress:n.progress},{capturedAt:y,source:k,...g}=d;return{...d,stateDigest:mn(g)}}function hn(t){return t.phases.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.tasks.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.nextActions.length>0||t.blockers.length>0}var ue=class{constructor(e){this.options=e}options;async capture(e,r){let n=await B(this.options.project,this.options.storage);if(n||(n=await oe(this.options.project,this.options.storage)),!hn(n))return null;let s=ce(this.options.project,!1),i=[...s?s.rules.filter(y=>y.mode==="enforce").map(y=>y.text):[],...n.warnings].slice(0,20),u=ct({project:this.options.project,identity:this.options.identity,state:n,reason:e,sequence:r,attention:i}),c=u.stateDigest,a=S([this.options.project.id,this.options.identity.sessionKey,c].join("|")).slice(0,24),p=new Date().toISOString(),l={version:1,id:a,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:p,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:r},goal:n.goal,plan:n.plan,progress:n.progress,currentPhase:n.currentPhase,currentTask:n.currentTask,incompletePhases:n.phases.filter(y=>y.status!=="completed"&&y.status!=="cancelled"),incompleteTasks:n.tasks.filter(y=>y.status!=="completed"&&y.status!=="cancelled"),nextActions:n.nextActions.slice(0,10),blockers:n.blockers.slice(0,10),decisions:n.decisions.slice(-10),warnings:n.warnings.slice(-10),attention:i,filesTouched:n.filesTouched.slice(-20),tests:n.tests.slice(-15),stateDigest:c,continuity:u},m=`projects/${this.options.project.id}/work/handoffs/${a}.json`;await this.options.storage.exists(m)||await this.options.storage.put(m,JSON.stringify(l,null,2)+`
52
+ `;function xe(t){return Ts(t.rootPath,".toolnet","PROJECT.md")}function _s(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Rs(t){let e=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=r.exec(t);){let o=s[1].toLowerCase(),i=_s(s[2]);if(!i)continue;let a=`${o}:${i.toLowerCase()}`;n.has(a)||(n.add(a),e.push({id:S(a).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Ns(t){let e=xe(t);return Dt(e)||(Ps(Cs(e),{recursive:!0}),Ms(e,Os,{encoding:"utf8",mode:384})),e}function Ae(t,e=!1){let n=e?Ns(t):xe(t);if(!Dt(n))return null;if($t(n).size>Kt)throw new Error(`PROJECT.md exceeds ${Kt} bytes`);let s=Es(n,"utf8");return{path:n,content:s,digest:S(s),rules:Rs(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date($t(n).mtimeMs).toISOString()}}function E(t,e){let n=new Set,r=[];for(let s of t){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>=e))break}return r}function Ft(t){if(t)return{id:t.id,title:t.title,status:t.status}}function Ls(t){let e=t.slice(-10).join(`
53
+ `).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(e)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(e)?"passing":"unknown"}function $s(t){return S(JSON.stringify(t))}function Wt(t){let{project:e,identity:n,state:r}=t,s=r.filesTouched.at(-1),o=r.phases.filter(g=>g.status==="completed").map(g=>g.title),i=r.tasks.filter(g=>g.status==="completed").map(g=>g.title),a=r.phases.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),c=r.tasks.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),u=E(r.nextActions,10),p=E([...c,...u],15),l=E(r.tests.slice().reverse(),10),f=E(r.filesTouched.slice().reverse(),20),d={schema:"toolnet.handoff.v2",version:2,project:{id:e.id,name:e.name},source:{agent:n.agent,nativeSessionId:n.nativeSessionId,sessionKey:n.sessionKey,sequence:t.sequence,reason:t.reason},capturedAt:t.capturedAt??new Date().toISOString(),goal:r.goal,current:{phase:Ft(r.currentPhase),task:Ft(r.currentTask),file:s},completed:{phases:E(o,20),tasks:E(i,30)},remaining:{phases:E(a,20),tasks:E(c,30),todos:p},nextAction:u[0],blockers:E(r.blockers.slice().reverse(),10),decisions:E(r.decisions.slice().reverse(),10),files:{current:s,recent:f},tests:{status:Ls(r.tests),recent:l},attention:E(t.attention??[],20),progress:r.progress},{capturedAt:m,source:h,...y}=d;return{...d,stateDigest:$s(y)}}function Ds(t){return t.phases.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.tasks.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.nextActions.length>0||t.blockers.length>0}var Ie=class{constructor(e){this.options=e}options;async capture(e,n){let r=await G(this.options.project,this.options.storage);if(r||(r=await we(this.options.project,this.options.storage)),!Ds(r))return null;let s=Ae(this.options.project,!1),i=[...s?s.rules.filter(m=>m.mode==="enforce").map(m=>m.text):[],...r.warnings].slice(0,20),a=Wt({project:this.options.project,identity:this.options.identity,state:r,reason:e,sequence:n,attention:i}),c=a.stateDigest,u=S([this.options.project.id,this.options.identity.sessionKey,c].join("|")).slice(0,24),p=new Date().toISOString(),l={version:1,id:u,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:p,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),incompleteTasks:r.tasks.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:i,filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:c,continuity:a},f=`projects/${this.options.project.id}/work/handoffs/${u}.json`;await this.options.storage.exists(f)||await this.options.storage.put(f,JSON.stringify(l,null,2)+`
54
54
  `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(l,null,2)+`
55
- `,"application/json");let d=Ie(this.options.project.rootPath,".toolnet","work","handoffs");return gn(d,{recursive:!0}),A(Ie(d,`${a}.json`),l),A(Ie(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),l),l}};async function ut(t,e){let r=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}import{mkdirSync as yn}from"node:fs";import{join as lt}from"node:path";function kn(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Sn(t,e){if(!e)return!0;let r=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return r!==0?r>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function O(t,e){return Sn(e,t)?e:t}function T(t,e=30){let r=new Set,n=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||r.has(o)||(r.add(o),n.push(s))}return n.slice(-e)}async function vn(t,e){let r=`projects/${t.id}/work/semantic/observations/`,n=await e.list(r),s=[];for(let o of n.filter(i=>i.key.endsWith(".json")).sort((i,u)=>i.key.localeCompare(u.key))){let i=await e.getText(o.key);if(i)try{let u=JSON.parse(i);u.version===1&&Array.isArray(u.observations)&&s.push(u)}catch{}}return s}function bn(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function dt(t,e){let n=(await vn(t,e)).flatMap(k=>k.observations).sort((k,g)=>{let h=k.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return h!==0?h:k.evidence.sessionKey===g.evidence.sessionKey?k.evidence.sequence-g.evidence.sequence:k.id.localeCompare(g.id)}),s,o,i,u,c,a=new Map,p=[],l=[],m=[];for(let k of n){let g=kn(k);if(k.scope==="phase"&&k.scopeKey){let h=a.get(k.scopeKey)??bn(k);switch(k.kind){case"phase_objective":h.objective=O(h.objective,g);break;case"phase_why":h.why=O(h.why,g);break;case"phase_deliverable":h.deliverable=O(h.deliverable,g);break;case"acceptance_criterion":h.acceptanceCriteria.push(g);break;case"dependency":h.dependencies.push(g);break;case"open_question":h.openQuestions.push(g);break;case"constraint":h.constraints.push(g);break;case"note":h.notes.push(g);break}a.set(h.key,h);continue}switch(k.kind){case"mission":s=O(s,g);break;case"objective":o=O(o,g);break;case"why":i=O(i,g);break;case"desired_outcome":u=O(u,g);break;case"plan_rationale":c=O(c,g);break;case"open_question":p.push(g);break;case"constraint":l.push(g);break;case"note":m.push(g);break}}for(let k of a.values())k.acceptanceCriteria=T(k.acceptanceCriteria,20),k.dependencies=T(k.dependencies,15),k.openQuestions=T(k.openQuestions,15),k.constraints=T(k.constraints,15),k.notes=T(k.notes,20);let d={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:u,planRationale:c,phases:Array.from(a.values()).sort((k,g)=>k.order-g.order),openQuestions:T(p,20),constraints:T(l,20),notes:T(m,20),updatedAt:n.length?n[n.length-1].evidence.occurredAt:new Date().toISOString()},y=lt(t.rootPath,".toolnet","work");return yn(y,{recursive:!0}),A(lt(y,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
56
- `,"application/json"),d}async function pt(t,e){let r=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}function je(t){if(!t)return 0;let e=Array.from(t).length,r=t.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,r*1.3))}function v(t,e){let r=t.replace(/\s+/g," ").trim();return r.length<=e?r:r.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function wn(t){let e=[],r=!1;for(let n of t.split(/\r?\n/u)){let s=n.trim();if(s.includes("<!--")&&(r=!0),r){s.includes("-->")&&(r=!1);continue}let o=s.toLowerCase();if(!(!s||s.startsWith("#")||s==="```"||o.startsWith("- [enforce]")||o.startsWith("* [enforce]")||o.startsWith("- [advisory]")||o.startsWith("* [advisory]"))&&(s=s.replace(/^[-*]\s+/u,""),s&&e.push(v(s,280)),e.length>=16))break}return e}function xn(t){let e=[],r=[];for(let n of t.split(/\\r?\\n/u)){let s=n.trim(),o=s.toLowerCase(),u=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(a=>o.startsWith(a));if(!u)continue;let c=s.slice(u.length).trim();c&&(u.includes("enforce")?e.push(c):r.push(c))}return{enforce:e,advisory:r}}function An(t,e){let r=[];for(let n of t){let s=[...r,n].join(`
57
- `);if(je(s)<=e){r.push(n);continue}let o=je(r.join(`
58
- `)),i=Math.max(0,e-o);if(i>=16){let u=Math.floor(i*3.2),c=v(n,u);c&&r.push(c)}break}return r.join(`
59
- `).trim()}async function ft(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),r=ce(t.project,!1),n=r?.content??"";n||(n=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=xn(n),o=r?r.rules.filter(d=>d.mode==="enforce").map(d=>d.text):s.enforce,i=r?r.rules.filter(d=>d.mode==="advisory").map(d=>d.text):s.advisory,u=n?wn(n):[],c=await B(t.project,t.storage),a=await pt(t.project,t.storage),p=await ut(t.project,t.storage),l=[];if(l.push("[TOOLNET PROJECT CONTEXT]"),l.push(`Project: ${t.project.name}`),l.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),n&&l.push(`Full operating manual: ${ae(t.project)}`),o.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of o.slice(0,24))l.push(`- [ENFORCE] ${v(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${v(d,220)}`)}if(a&&(a.mission&&l.push("","MISSION",v(a.mission.value,420)),a.activeObjective&&l.push("","CURRENT OBJECTIVE",v(a.activeObjective.value,420)),a.why&&l.push("","WHY THIS WORK MATTERS",v(a.why.value,420)),a.desiredOutcome&&l.push("","DESIRED OUTCOME",v(a.desiredOutcome.value,420)),a.planRationale&&l.push("","WHY THIS APPROACH",v(a.planRationale.value,420))),c){if(l.push("","ACTIVE WORK"),c.goal&&l.push(`Goal: ${v(c.goal,320)}`),c.plan&&l.push(`Plan: ${v(c.plan,320)}`),l.push(`Progress: phases ${c.progress.phasesCompleted}/${c.progress.phasesTotal}; tasks ${c.progress.tasksCompleted}/${c.progress.tasksTotal}; blocked ${c.progress.blocked}`),c.currentPhase&&l.push(`Current phase: ${c.currentPhase.title} [${c.currentPhase.status}]`),c.currentPhase&&a){let d=a.phases.find(y=>y.order===c.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${v(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${v(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${v(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(y=>v(y.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(y=>{l.push(`- ${v(y.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(y=>{l.push(`- ${v(y.value,260)}`)})))}c.currentTask&&l.push(`Current task: ${c.currentTask.title} [${c.currentTask.status}]`),c.nextActions.length&&(l.push("","NEXT ACTIONS"),c.nextActions.slice(0,6).forEach((d,y)=>{l.push(`${y+1}. ${v(d,260)}`)})),c.blockers.length&&(l.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(d=>{l.push(`- ${v(d,260)}`)})),c.warnings.length&&(l.push("","ATTENTION"),c.warnings.slice(-5).forEach(d=>{l.push(`- ${v(d,260)}`)})),c.decisions.length&&(l.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(d=>{l.push(`- ${v(d,260)}`)})),c.lastSession&&l.push("",`Last work session: ${c.lastSession.agent} / ${c.lastSession.nativeSessionId}`)}if(a&&a.openQuestions.length&&(l.push("","UNRESOLVED QUESTIONS"),a.openQuestions.slice(0,5).forEach(d=>{l.push(`- ${v(d.value,260)}`)})),p&&l.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),u.length){l.push("","OPERATING NOTES");for(let d of u)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let m=An(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:m,estimatedTokens:je(m),maxTokens:e,hasManual:!!n,hasWorkState:!!c,hasHandoff:!!p,generatedAt:new Date().toISOString()}}var In=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function U(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ee(t,e,r=0){if(!(r>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let n of t.slice(0,50))Ee(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(In.has(n)||["data","payload","parts","messages"].includes(n))&&Ee(s,e,r+1)}}function j(t,e,r,n,s,o=.95){let i=U(n);return{version:1,id:S([t.projectId,r,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:r,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function P(t,e){let r=t.toLowerCase();for(let n of e){let s=n.toLowerCase();if(r.startsWith(`${s}:`)||r.startsWith(`${s} -`)||r.startsWith(`${s} \u2014`))return U(t.slice(n.length+1))}return null}function jn(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function En(t){return U(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function mt(t,e){let r=[],n=new Set;function s(o){!o.value||o.value.length<3||n.has(o.id)||(n.add(o.id),r.push(o))}for(let o of e){let i=[];Ee(o.data,i);for(let u of i){let c={type:"project"},a=null;for(let p of u.split(/\r?\n/u)){let l=U(p);if(!l){a=null;continue}let m=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let x=Number(m[1]);c={type:"phase",key:`phase:${x}`,order:x,title:U(m[2]??"")},a=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let x=Number(d[1]);c={type:"task",key:`task:${x}`,order:x,title:U(d[2]??"")},a=null;continue}let y=P(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(y){s(j(t,o,"mission",y,{type:"project"},.99)),a=null;continue}let k=P(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(k){s(j(t,o,c.type==="phase"?"phase_objective":"objective",k,c,.98)),a=null;continue}let g=P(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(j(t,o,c.type==="phase"?"phase_why":"why",g,c,.98)),a=null;continue}let h=P(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){s(j(t,o,"desired_outcome",h,{type:"project"},.98)),a=null;continue}let b=P(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(b){s(j(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let R=P(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(R){s(j(t,o,"phase_deliverable",R,c,.97)),a=null;continue}let $=P(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if($){s(j(t,o,"acceptance_criterion",$,c,.98)),a="acceptance_criterion";continue}let M=P(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(M){s(j(t,o,"dependency",M,c,.97)),a="dependency";continue}let N=P(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(N){s(j(t,o,"open_question",N,c,.95)),a="open_question";continue}let f=P(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(f){s(j(t,o,"constraint",f,c,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){a="constraint";continue}if(a&&jn(p)){s(j(t,o,a,En(p),c,.96));continue}a=null}}}return r}function gt(t){return String(t).padStart(12,"0")}var le=class{constructor(e){this.storage=e}storage;async write(e,r){if(r.length===0)return null;let n=Math.min(...r.map(c=>c.evidence.sequence)),s=Math.max(...r.map(c=>c.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:n,lastSequence:s,createdAt:new Date().toISOString(),observations:r},i=S(r.map(c=>c.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${gt(n)}-${gt(s)}-${i}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,JSON.stringify(o,null,2)+`
60
- `,"application/json"),u}};import{closeSync as Pn,existsSync as Mn,openSync as On,readSync as Tn,statSync as _n}from"node:fs";function Cn(t,e){if(!Mn(t))return{events:[],nextOffset:e};let r=_n(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=Buffer.alloc(r-n),o=On(t,"r");try{Tn(o,s,0,s.length,n)}finally{Pn(o)}let i=s.toString("utf8"),u=i.lastIndexOf(`
61
- `);if(u<0)return{events:[],nextOffset:n};let c=i.slice(0,u+1);return{events:c.split(`
62
- `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(c,"utf8")}}var de=class{constructor(e){this.options=e;this.journal=new le(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),r=Number(e.sourceCursors["work.semantic.offset"]??0),n=Cn(this.options.wal.eventsFile,Number.isFinite(r)?r:0);if(n.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:n.nextOffset};let s=mt(this.options.identity,n.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await dt(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",n.nextOffset),{scannedEvents:n.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:n.nextOffset}}};import{existsSync as Rn,mkdirSync as Nn,readFileSync as Ln,writeFileSync as $n}from"node:fs";import{dirname as Dn,join as ht}from"node:path";function pe(t){return t?Math.ceil(t.length/3.5):0}function fe(t,e){if(!t)return"";if(pe(t)<=e)return t;let n=Math.floor(e*3.5),s=t.slice(0,n),o=s.lastIndexOf("."),i=s.lastIndexOf(`
63
- `),u=Math.max(o,i);return u>n*.7?s.slice(0,u+1):s}function yt(t){return ht(t.rootPath,".toolnet","context","startup.md")}function Fn(t){return ht(t.rootPath,".toolnet","context","startup.json")}function kt(t,e){let r=yt(t);Nn(Dn(r),{recursive:!0}),$n(r,e.text.endsWith(`
55
+ `,"application/json");let d=Je(this.options.project.rootPath,".toolnet","work","handoffs");return Ks(d,{recursive:!0}),j(Je(d,`${u}.json`),l),j(Je(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),l),l}};async function Bt(t,e){let n=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}import{mkdirSync as Fs}from"node:fs";import{join as zt}from"node:path";function Ws(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Bs(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function L(t,e){return Bs(e,t)?e:t}function $(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function zs(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}function Us(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function Ut(t,e){let r=(await zs(t,e)).flatMap(h=>h.observations).sort((h,y)=>{let g=h.evidence.occurredAt.localeCompare(y.evidence.occurredAt);return g!==0?g:h.evidence.sessionKey===y.evidence.sessionKey?h.evidence.sequence-y.evidence.sequence:h.id.localeCompare(y.id)}),s,o,i,a,c,u=new Map,p=[],l=[],f=[];for(let h of r){let y=Ws(h);if(h.scope==="phase"&&h.scopeKey){let g=u.get(h.scopeKey)??Us(h);switch(h.kind){case"phase_objective":g.objective=L(g.objective,y);break;case"phase_why":g.why=L(g.why,y);break;case"phase_deliverable":g.deliverable=L(g.deliverable,y);break;case"acceptance_criterion":g.acceptanceCriteria.push(y);break;case"dependency":g.dependencies.push(y);break;case"open_question":g.openQuestions.push(y);break;case"constraint":g.constraints.push(y);break;case"note":g.notes.push(y);break}u.set(g.key,g);continue}switch(h.kind){case"mission":s=L(s,y);break;case"objective":o=L(o,y);break;case"why":i=L(i,y);break;case"desired_outcome":a=L(a,y);break;case"plan_rationale":c=L(c,y);break;case"open_question":p.push(y);break;case"constraint":l.push(y);break;case"note":f.push(y);break}}for(let h of u.values())h.acceptanceCriteria=$(h.acceptanceCriteria,20),h.dependencies=$(h.dependencies,15),h.openQuestions=$(h.openQuestions,15),h.constraints=$(h.constraints,15),h.notes=$(h.notes,20);let d={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:a,planRationale:c,phases:Array.from(u.values()).sort((h,y)=>h.order-y.order),openQuestions:$(p,20),constraints:$(l,20),notes:$(f,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},m=zt(t.rootPath,".toolnet","work");return Fs(m,{recursive:!0}),j(zt(m,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
56
+ `,"application/json"),d}async function qt(t,e){let n=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Ye(t){if(!t)return 0;let e=Array.from(t).length,n=t.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,n*1.3))}function w(t,e){let n=t.replace(/\s+/g," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function qs(t){let e=[],n=!1;for(let r of t.split(/\r?\n/u)){let s=r.trim();if(s.includes("<!--")&&(n=!0),n){s.includes("-->")&&(n=!1);continue}let o=s.toLowerCase();if(!(!s||s.startsWith("#")||s==="```"||o.startsWith("- [enforce]")||o.startsWith("* [enforce]")||o.startsWith("- [advisory]")||o.startsWith("* [advisory]"))&&(s=s.replace(/^[-*]\s+/u,""),s&&e.push(w(s,280)),e.length>=16))break}return e}function Vs(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.trim(),o=s.toLowerCase(),a=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(u=>o.startsWith(u));if(!a)continue;let c=s.slice(a.length).trim();c&&(a.includes("enforce")?e.push(c):n.push(c))}return{enforce:e,advisory:n}}function Gs(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
57
+ `);if(Ye(s)<=e){n.push(r);continue}let o=Ye(n.join(`
58
+ `)),i=Math.max(0,e-o);if(i>=16){let a=Math.floor(i*3.2),c=w(r,a);c&&n.push(c)}break}return n.join(`
59
+ `).trim()}async function Vt(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=Ae(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=Vs(r),o=n?n.rules.filter(d=>d.mode==="enforce").map(d=>d.text):s.enforce,i=n?n.rules.filter(d=>d.mode==="advisory").map(d=>d.text):s.advisory,a=r?qs(r):[],c=await G(t.project,t.storage),u=await qt(t.project,t.storage),p=await Bt(t.project,t.storage),l=[];if(l.push("[TOOLNET PROJECT CONTEXT]"),l.push(`Project: ${t.project.name}`),l.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),r&&l.push(`Full operating manual: ${xe(t.project)}`),o.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of o.slice(0,24))l.push(`- [ENFORCE] ${w(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${w(d,220)}`)}if(u&&(u.mission&&l.push("","MISSION",w(u.mission.value,420)),u.activeObjective&&l.push("","CURRENT OBJECTIVE",w(u.activeObjective.value,420)),u.why&&l.push("","WHY THIS WORK MATTERS",w(u.why.value,420)),u.desiredOutcome&&l.push("","DESIRED OUTCOME",w(u.desiredOutcome.value,420)),u.planRationale&&l.push("","WHY THIS APPROACH",w(u.planRationale.value,420))),c){if(l.push("","ACTIVE WORK"),c.goal&&l.push(`Goal: ${w(c.goal,320)}`),c.plan&&l.push(`Plan: ${w(c.plan,320)}`),l.push(`Progress: phases ${c.progress.phasesCompleted}/${c.progress.phasesTotal}; tasks ${c.progress.tasksCompleted}/${c.progress.tasksTotal}; blocked ${c.progress.blocked}`),c.currentPhase&&l.push(`Current phase: ${c.currentPhase.title} [${c.currentPhase.status}]`),c.currentPhase&&u){let d=u.phases.find(m=>m.order===c.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${w(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${w(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${w(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(m=>w(m.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(m=>{l.push(`- ${w(m.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(m=>{l.push(`- ${w(m.value,260)}`)})))}c.currentTask&&l.push(`Current task: ${c.currentTask.title} [${c.currentTask.status}]`),c.nextActions.length&&(l.push("","NEXT ACTIONS"),c.nextActions.slice(0,6).forEach((d,m)=>{l.push(`${m+1}. ${w(d,260)}`)})),c.blockers.length&&(l.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(d=>{l.push(`- ${w(d,260)}`)})),c.warnings.length&&(l.push("","ATTENTION"),c.warnings.slice(-5).forEach(d=>{l.push(`- ${w(d,260)}`)})),c.decisions.length&&(l.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(d=>{l.push(`- ${w(d,260)}`)})),c.lastSession&&l.push("",`Last work session: ${c.lastSession.agent} / ${c.lastSession.nativeSessionId}`)}if(u&&u.openQuestions.length&&(l.push("","UNRESOLVED QUESTIONS"),u.openQuestions.slice(0,5).forEach(d=>{l.push(`- ${w(d.value,260)}`)})),p&&l.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),a.length){l.push("","OPERATING NOTES");for(let d of a)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let f=Gs(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:f,estimatedTokens:Ye(f),maxTokens:e,hasManual:!!r,hasWorkState:!!c,hasHandoff:!!p,generatedAt:new Date().toISOString()}}var Hs=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function H(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Qe(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))Qe(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Hs.has(r)||["data","payload","parts","messages"].includes(r))&&Qe(s,e,n+1)}}function M(t,e,n,r,s,o=.95){let i=H(r);return{version:1,id:S([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function O(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return H(t.slice(r.length+1))}return null}function Js(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Ys(t){return H(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function Gt(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Qe(o.data,i);for(let a of i){let c={type:"project"},u=null;for(let p of a.split(/\r?\n/u)){let l=H(p);if(!l){u=null;continue}let f=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let x=Number(f[1]);c={type:"phase",key:`phase:${x}`,order:x,title:H(f[2]??"")},u=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let x=Number(d[1]);c={type:"task",key:`task:${x}`,order:x,title:H(d[2]??"")},u=null;continue}let m=O(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(m){s(M(t,o,"mission",m,{type:"project"},.99)),u=null;continue}let h=O(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(M(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),u=null;continue}let y=O(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(M(t,o,c.type==="phase"?"phase_why":"why",y,c,.98)),u=null;continue}let g=O(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(g){s(M(t,o,"desired_outcome",g,{type:"project"},.98)),u=null;continue}let v=O(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(v){s(M(t,o,"plan_rationale",v,{type:"project"},.98)),u=null;continue}let P=O(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(P){s(M(t,o,"phase_deliverable",P,c,.97)),u=null;continue}let T=O(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(T){s(M(t,o,"acceptance_criterion",T,c,.98)),u="acceptance_criterion";continue}let A=O(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(A){s(M(t,o,"dependency",A,c,.97)),u="dependency";continue}let R=O(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(R){s(M(t,o,"open_question",R,c,.95)),u="open_question";continue}let k=O(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(k){s(M(t,o,"constraint",k,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){u="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){u="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){u="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){u="constraint";continue}if(u&&Js(p)){s(M(t,o,u,Ys(p),c,.96));continue}u=null}}}return n}function Ht(t){return String(t).padStart(12,"0")}var je=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.evidence.sequence)),s=Math.max(...n.map(c=>c.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=S(n.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${Ht(r)}-${Ht(s)}-${i}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,JSON.stringify(o,null,2)+`
60
+ `,"application/json"),a}};import{closeSync as Qs,existsSync as Xs,openSync as Zs,readSync as eo,statSync as to}from"node:fs";function no(t,e){if(!Xs(t))return{events:[],nextOffset:e};let n=to(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=Zs(t,"r");try{eo(o,s,0,s.length,r)}finally{Qs(o)}let i=s.toString("utf8"),a=i.lastIndexOf(`
61
+ `);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
62
+ `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var Pe=class{constructor(e){this.options=e;this.journal=new je(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=no(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=Gt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Ut(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{existsSync as ro,mkdirSync as so,readFileSync as oo,writeFileSync as io}from"node:fs";import{dirname as ao,join as Jt}from"node:path";function Ee(t){return t?Math.ceil(t.length/3.5):0}function Me(t,e){if(!t)return"";if(Ee(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
63
+ `),a=Math.max(o,i);return a>r*.7?s.slice(0,a+1):s}function Yt(t){return Jt(t.rootPath,".toolnet","context","startup.md")}function co(t){return Jt(t.rootPath,".toolnet","context","startup.json")}function Qt(t,e){let n=Yt(t);so(ao(n),{recursive:!0}),io(n,e.text.endsWith(`
64
64
  `)?e.text:e.text+`
65
- `,{encoding:"utf8",mode:384}),A(Fn(t),e)}async function Pe(t,e,r=800){let s=(await ft({project:t,storage:e,maxTokens:r})).text;pe(s)>r&&(s=fe(s,r),s+=`
65
+ `,{encoding:"utf8",mode:384}),j(co(t),e)}async function Xe(t,e,n=800){let s=(await Vt({project:t,storage:e,maxTokens:n})).text;Ee(s)>n&&(s=Me(s,n),s+=`
66
66
 
67
67
  [Context trimmed by ToolNet Memory token budget]
68
- `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:S(s),estimatedTokens:pe(s),generatedAt:new Date().toISOString()};return kt(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
68
+ `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:S(s),estimatedTokens:Ee(s),generatedAt:new Date().toISOString()};return Qt(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
69
69
  `,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
70
- `,"application/json"),i}async function St(t,e,r=900){try{let s=await e.getText(`projects/${t.id}/context/startup.md`);if(s&&s.trim()){let o=s.trim(),i={version:1,projectId:t.id,projectName:t.name,text:o,digest:S(o),estimatedTokens:Math.ceil(o.length/3.5),generatedAt:new Date().toISOString()};return kt(t,i),i}}catch{}let n=yt(t);if(Rn(n))try{let s=Ln(n,"utf8").trim();if(s)return{version:1,projectId:t.id,projectName:t.name,text:s,digest:S(s),estimatedTokens:Math.ceil(s.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await Pe(t,e,r)}catch{return null}}import{existsSync as bt,mkdirSync as Kn,readFileSync as wt}from"node:fs";import{homedir as Bn}from"node:os";import{dirname as Un,join as Oe}from"node:path";var Me="memory_agent_ask";function vt(){return`
70
+ `,"application/json"),i}async function Xt(t,e,n=900){try{let s=await e.getText(`projects/${t.id}/context/startup.md`);if(s&&s.trim()){let o=s.trim(),i={version:1,projectId:t.id,projectName:t.name,text:o,digest:S(o),estimatedTokens:Math.ceil(o.length/3.5),generatedAt:new Date().toISOString()};return Qt(t,i),i}}catch{}let r=Yt(t);if(ro(r))try{let s=oo(r,"utf8").trim();if(s)return{version:1,projectId:t.id,projectName:t.name,text:s,digest:S(s),estimatedTokens:Math.ceil(s.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await Xe(t,e,n)}catch{return null}}import{existsSync as dn,mkdirSync as Po,readFileSync as pn}from"node:fs";import{homedir as Eo}from"node:os";import{dirname as Mo,join as rt}from"node:path";var Ze="memory_agent_ask";function Zt(){return`
71
71
  [TOOLNET MEMORY AGENT]
72
72
 
73
73
  Tool:
74
- - ${Me}
74
+ - ${Ze}
75
75
 
76
76
  For resume/continue requests:
77
77
 
78
78
  1. Use the injected ToolNet continuity handoff FIRST.
79
79
  2. If the handoff is missing or ambiguous, invoke
80
- ${Me} directly BEFORE repository/history exploration.
80
+ ${Ze} directly BEFORE repository/history exploration.
81
81
  3. NEVER reconstruct prior work from:
82
82
  - .toolnet/sessions/**
83
83
  - state.json
84
84
  - events.jsonl
85
85
  - raw transcripts
86
86
  4. NEVER search for the implementation/schema of
87
- ${Me}; invoke the MCP tool directly.
87
+ ${Ze}; invoke the MCP tool directly.
88
88
  5. Inspect git/source only AFTER continuity context is known.
89
89
 
90
90
  Use:
@@ -92,27 +92,47 @@ Use:
92
92
  - mode="ai" for ambiguous or combined continuity questions.
93
93
 
94
94
  Current repository evidence overrides stale memory.
95
- `.trim()}function Wn(t,e,r){let n=r??Oe(Bn(),".config","toolnet-memory","injections","agy");return Oe(n,`${t.id}-${e}.json`)}function zn(t){if(!bt(t))return null;try{return JSON.parse(wt(t,"utf8"))}catch{return null}}function _(t,e=280){let r=(t??"").replace(/\s+/g," ").trim();return r.length<=e?r:r.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function qn(t){let e=Oe(t.rootPath,".toolnet","work","current.json");if(!bt(e))return null;try{let r=JSON.parse(wt(e,"utf8"));if(r.version===1&&r.projectId===t.id)return r}catch{}return null}function Hn(t,e){let r=e.tasks.filter(i=>i.status==="completed").slice(-3).map(i=>_(i.title,220)),n=Array.from(new Set([...e.currentTask?[e.currentTask.title]:[],...e.tasks.filter(i=>i.status==="in_progress"||i.status==="blocked"||i.status==="pending").slice(0,4).map(i=>i.title)].map(i=>_(i,220)).filter(Boolean))),s=e.filesTouched.at(-1),o=["[TOOLNET CONTINUITY HANDOFF]",`Project: ${t.name}`];return e.currentTask?.title?o.push(`Task: ${_(e.currentTask.title)}`):e.currentPhase?.title?o.push(`Task: ${_(e.currentPhase.title)}`):e.goal&&o.push(`Task: ${_(e.goal)}`),r.length&&o.push(`Completed: ${r.join("; ")}`),s&&o.push(`Current file: ${_(s,260)}`),n.length&&o.push(`TODO: ${n.join("; ")}`),e.nextActions.length&&o.push(`Next action: ${_(e.nextActions[0])}`),e.blockers.length&&o.push(`Blocker: ${_(e.blockers[0])}`),o.push("","CONTINUATION CONTRACT:","- Continue from this compact handoff; do not reconstruct the prior session.","- NEVER inspect .toolnet/sessions/**, state.json, events.jsonl, or raw transcripts.","- If this handoff is insufficient, invoke memory_agent_ask directly.","- Do not search for memory_agent_ask implementation/schema.","- Inspect git/source only to validate current code after continuity is resolved."),o.join(`
96
- `)}async function Jn(t){let e=qn(t.project);if(!e)try{e=await B(t.project,t.storage)}catch{e=null}let r=e?Hn(t.project,e):"";if(!r)try{r=(await St(t.project,t.storage,700))?.text??""}catch{r=""}return[r,vt()].filter(Boolean).join(`
97
-
98
- `).trim()}async function xt(t){let e=t.now??Date.now(),r=t.resumeAfterMs??360*60*1e3,n=Wn(t.project,t.conversationId,t.markerDirectory),s=zn(n),o=s?Date.parse(s.injectedAt):0,i=o?e-o:Number.POSITIVE_INFINITY;if(s&&i<6e4)return{};let u=t.invocationNum===0,c=i>=r;if(s&&!u&&!c)return{};let a=await Jn({project:t.project,storage:t.storage});return a?(Kn(Un(n),{recursive:!0}),A(n,{digest:S(a),injectedAt:new Date(e).toISOString()}),{injectSteps:[{ephemeralMessage:a}]}):{}}import{existsSync as Zn}from"node:fs";import{dirname as es,join as ts,parse as rs,resolve as ns}from"node:path";function It(t){for(let e of t){let r=ns(e),n=rs(r).root;for(;;){if(Zn(ts(r,".toolnet","project.json")))return new X().detect(r);if(r===n)break;let s=es(r);if(s===r)break;r=s}}return null}import{homedir as Ht}from"node:os";import{join as io,resolve as ao}from"node:path";import{join as ss}from"node:path";function jt(t,e){let r=t.trim(),n=r.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=S(r).slice(0,12);if(!n||n==="."||n==="..")return`${e}--${s}`;let o=n.slice(0,100);return o===r&&r.length<=100?o:`${o.slice(0,85)}--${s}`}function Et(t,e,r){let n=e.trim(),s=r.trim();if(!n)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=jt(n.toLowerCase(),"agent"),i=jt(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:n,nativeSessionId:s,sessionKey:`${n}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:ss(t.rootPath,".toolnet","sessions",o,i)}}function Pt(t){return String(t).padStart(12,"0")}var me=class{constructor(e,r=100,n=512*1024){this.storage=e;this.maxEventsPerChunk=r;this.maxChunkBytes=n;if(r<1)throw new Error("maxEventsPerChunk must be positive");if(n<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let r=await this.storage.getText(e);return r?JSON.parse(r):null}async putJson(e,r){await this.storage.put(e,JSON.stringify(r,null,2)+`
99
- `,"application/json")}async scan(e){let r=`${e.remotePrefix}/events/`,n=await this.storage.list(r),s=[],o=0;for(let i of n){let u=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!u)continue;let c=Number(u[1]),a=Number(u[2]);!Number.isFinite(c)||!Number.isFinite(a)||(s.push({key:i.key,start:c,end:a}),o=Math.max(o,a))}return s.sort((i,u)=>i.start-u.start),{chunks:s,maxSequence:o}}split(e){let r=[],n=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
100
- `,"utf8");n.length>0&&(n.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(r.push(n),n=[],s=0),n.push(o),s+=i}return n.length>0&&r.push(n),r}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let r=await this.scan(e);return{maxSequence:r.maxSequence,chunkCount:r.chunks.length}}async append(e,r,n,s={}){let o=await this.loadManifest(e),i=await this.scan(e),u=r.filter(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(u)){let h=g[0],b=g[g.length-1],R=g.map(N=>JSON.stringify(N)).join(`
95
+ `.trim()}import{createHash as uo}from"node:crypto";import{chmodSync as tn,existsSync as lo,mkdirSync as po,readFileSync as fo,renameSync as mo,writeFileSync as nn}from"node:fs";import{dirname as rn,join as Ce}from"node:path";var nt="toolnet.context-offload.v1",go="toolnet.context-offload-asset.v1",yo=256,ho=new Set(["tool_call","tool_result","file_read","file_write","file_edit","command","test","artifact"]);function sn(t){return Ce(t,".toolnet","offload")}function ko(t){return Ce(sn(t),"assets")}function on(t){return Ce(sn(t),"graph.json")}function an(t){po(t,{recursive:!0,mode:448});try{tn(t,448)}catch{}}function So(t,e){an(rn(t));let n=`${t}.${process.pid}.${Date.now()}.tmp`;nn(n,e,{encoding:"utf8",mode:384}),mo(n,t);try{tn(t,384)}catch{}}function tt(t){return Array.isArray(t)?t.map(tt):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).sort(([e],[n])=>e.localeCompare(n)).map(([e,n])=>[e,tt(n)])):t}function vo(t){return uo("sha256").update(JSON.stringify(tt(t)),"utf8").digest("hex")}function et(){return{schema:nt,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function cn(t){let e=on(t);if(!lo(e))return et();try{let n=JSON.parse(fo(e,"utf8"));return n.schema!==nt||n.version!==1||!Array.isArray(n.nodes)?et():n}catch{return et()}}function wo(t,e){So(on(t),JSON.stringify(e,null,2)+`
96
+ `)}function bo(t,e=260){if(typeof t!="string")return null;let n=t.replace(/\s+/gu," ").trim();return n?n.slice(0,e):null}function xo(t){let e=[...t.provenance.files??[],t.provenance.sourcePath],n=[];for(let r of e){let s=bo(r);if(!(!s||n.includes(s))&&(n.push(s),n.length===3))break}return n}function Ao(t){return`${t.agent}:${t.sourceEventId??t.id}`.replace(/\s+/gu," ").trim().slice(0,120)}function Io(t,e){an(rn(t));try{return nn(t,e,{encoding:"utf8",flag:"wx",mode:384}),!0}catch(n){if(n.code==="EEXIST")return!1;throw n}}function jo(t,e){let n=t.nodes.find(s=>s.id===e.id),r=n?{...n,kind:e.kind,bytes:e.bytes,sourceRefs:Array.from(new Set([...n.sourceRefs,...e.sourceRefs])).slice(-8),files:Array.from(new Set([...n.files,...e.files])).slice(0,6)}:e;return{schema:nt,version:1,updatedAt:new Date().toISOString(),nodes:[...t.nodes.filter(s=>s.id!==e.id),r].slice(-yo)}}function un(t,e){let n=cn(t),r=0,s=0,o=0,i=[];for(let a of e){if(!ho.has(a.type))continue;r+=1;let c=vo({type:a.type,data:a.data}),u={schema:go,version:1,assetId:c,event:{type:a.type,agent:a.agent,nativeSessionId:a.nativeSessionId,timestamp:a.timestamp,sourceEventId:a.sourceEventId,provenance:a.provenance,data:a.data}},p=JSON.stringify(u,null,2)+`
97
+ `;Io(Ce(ko(t),`${c}.json`),p)?s+=1:o+=1,i.push(c),n=jo(n,{id:c,kind:a.type,bytes:Buffer.byteLength(p,"utf8"),createdAt:a.timestamp,sourceRefs:[Ao(a)],files:xo(a)})}return r>0&&wo(t,n),{eligible:r,written:s,deduped:o,graphNodes:n.nodes.length,assetIds:i}}function en(t,e){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:n.slice(0,e-1).trimEnd()+"\u2026"}function ln(t,e={}){let n=cn(t);if(n.nodes.length===0)return"";let r=Math.max(1,Math.min(12,e.maxAssets??6)),s=Math.max(320,Math.min(2400,e.maxChars??900)),o=["[TOOLNET CONTEXT OFFLOAD GRAPH]","Large tool/file payloads stay outside prompt context.","Read only a needed asset with MCP context_offload_read."];for(let i of n.nodes.slice(-r).reverse()){let a=en(i.sourceRefs.at(-1)??"unknown",72),c=i.files.length>0?` files=${en(i.files.join(","),120)}`:"",u=`event:${a} --offloads--> asset:${i.id.slice(0,12)} kind=${i.kind} bytes=${i.bytes}${c}`;if([...o,u].join(`
98
+ `).length>s)break;o.push(u)}return o.join(`
99
+ `)}function Co(t,e,n){let r=n??rt(Eo(),".config","toolnet-memory","injections","agy");return rt(r,`${t.id}-${e}.json`)}function To(t){if(!dn(t))return null;try{return JSON.parse(pn(t,"utf8"))}catch{return null}}function K(t,e=280){let n=(t??"").replace(/\s+/g," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function Oo(t){let e=rt(t.rootPath,".toolnet","work","current.json");if(!dn(e))return null;try{let n=JSON.parse(pn(e,"utf8"));if(n.version===1&&n.projectId===t.id)return n}catch{}return null}function _o(t,e){let n=e.tasks.filter(i=>i.status==="completed").slice(-3).map(i=>K(i.title,220)),r=Array.from(new Set([...e.currentTask?[e.currentTask.title]:[],...e.tasks.filter(i=>i.status==="in_progress"||i.status==="blocked"||i.status==="pending").slice(0,4).map(i=>i.title)].map(i=>K(i,220)).filter(Boolean))),s=e.filesTouched.at(-1),o=["[TOOLNET CONTINUITY HANDOFF]",`Project: ${t.name}`];return e.currentTask?.title?o.push(`Task: ${K(e.currentTask.title)}`):e.currentPhase?.title?o.push(`Task: ${K(e.currentPhase.title)}`):e.goal&&o.push(`Task: ${K(e.goal)}`),n.length&&o.push(`Completed: ${n.join("; ")}`),s&&o.push(`Current file: ${K(s,260)}`),r.length&&o.push(`TODO: ${r.join("; ")}`),e.nextActions.length&&o.push(`Next action: ${K(e.nextActions[0])}`),e.blockers.length&&o.push(`Blocker: ${K(e.blockers[0])}`),o.push("","CONTINUATION CONTRACT:","- Continue from this compact handoff; do not reconstruct the prior session.","- NEVER inspect .toolnet/sessions/**, state.json, events.jsonl, or raw transcripts.","- If this handoff is insufficient, invoke memory_agent_ask directly.","- Do not search for memory_agent_ask implementation/schema.","- Inspect git/source only to validate current code after continuity is resolved."),o.join(`
100
+ `)}async function Ro(t){let e=Oo(t.project);if(!e)try{e=await G(t.project,t.storage)}catch{e=null}let n=e?_o(t.project,e):"";if(!n)try{n=(await Xt(t.project,t.storage,700))?.text??""}catch{n=""}let r=ln(t.project.rootPath,{maxAssets:6,maxChars:900});return[n,r,Zt()].filter(Boolean).join(`
101
+
102
+ `).trim()}async function fn(t){let e=t.now??Date.now(),n=t.resumeAfterMs??360*60*1e3,r=Co(t.project,t.conversationId,t.markerDirectory),s=To(r),o=s?Date.parse(s.injectedAt):0,i=o?e-o:Number.POSITIVE_INFINITY;if(s&&i<6e4)return{};let a=t.invocationNum===0,c=i>=n;if(s&&!a&&!c)return{};let u=await Ro({project:t.project,storage:t.storage});return u?(Po(Mo(r),{recursive:!0}),j(r,{digest:S(u),injectedAt:new Date(e).toISOString()}),{injectSteps:[{ephemeralMessage:u}]}):{}}import{existsSync as Fo}from"node:fs";import{dirname as Wo,join as Bo,parse as zo,resolve as Uo}from"node:path";function gn(t){for(let e of t){let n=Uo(e),r=zo(n).root;for(;;){if(Fo(Bo(n,".toolnet","project.json")))return new me().detect(n);if(n===r)break;let s=Wo(n);if(s===n)break;n=s}}return null}import{homedir as yr}from"node:os";import{join as qa,resolve as Va}from"node:path";import{join as qo}from"node:path";function yn(t,e){let n=t.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`${e}--${s}`;let o=r.slice(0,100);return o===n&&n.length<=100?o:`${o.slice(0,85)}--${s}`}function hn(t,e,n){let r=e.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=yn(r.toLowerCase(),"agent"),i=yn(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:r,nativeSessionId:s,sessionKey:`${r}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:qo(t.rootPath,".toolnet","sessions",o,i)}}function kn(t){return String(t).padStart(12,"0")}var Te=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
103
+ `,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let a=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!a)continue;let c=Number(a[1]),u=Number(a[2]);!Number.isFinite(c)||!Number.isFinite(u)||(s.push({key:i.key,start:c,end:u}),o=Math.max(o,u))}return s.sort((i,a)=>i.start-a.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
104
+ `,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),a=n.filter(y=>y.sequence>i.maxSequence),c=0;for(let y of this.split(a)){let g=y[0],v=y[y.length-1],P=y.map(R=>JSON.stringify(R)).join(`
101
105
  `)+`
102
- `,$=S(R).slice(0,16),M=[e.remotePrefix,"events",`${Pt(h.sequence)}-${Pt(b.sequence)}-${$}.jsonl`].join("/");await this.storage.exists(M)||await this.storage.put(M,R,"application/x-ndjson"),c+=g.length}let a=await this.scan(e),p=r[r.length-1],l=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?l="idle":p?.type==="error"?l="error":r.length>0&&(l="active");let m=new Date().toISOString(),d=r[0],y={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:l,createdAt:o?.createdAt??d?.timestamp??m,updatedAt:p?.timestamp??m,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(y.title=s.title??o?.title);let k={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:r.length>0?r[r.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:n,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,k),await this.putJson(`${e.remotePrefix}/session.json`,y),{uploadedEvents:c,lastRemoteSequence:a.maxSequence,eventCount:y.eventCount,chunkCount:y.chunkCount,status:l}}};import{closeSync as Te,existsSync as os,fsyncSync as is,mkdirSync as as,openSync as _e,readSync as cs,rmSync as Mt,statSync as Ot,writeSync as us}from"node:fs";import{join as Ce}from"node:path";var ls=12e4,ds=80,ps=2e3;function fs(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ge=class{constructor(e){this.identity=e;as(e.localDirectory,{recursive:!0}),this.eventsFile=Ce(e.localDirectory,"events.jsonl"),this.stateFile=Ce(e.localDirectory,"state.json"),this.lockFile=Ce(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return Qe(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){A(this.stateFile,e)}acquireLock(){for(let e=0;e<ds;e+=1)try{return _e(this.lockFile,"wx",384)}catch(r){if(r.code!=="EEXIST")throw r;try{if(Date.now()-Ot(this.lockFile).mtimeMs>ls){Mt(this.lockFile,{force:!0});continue}}catch{}fs(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let r=this.acquireLock();try{return e()}finally{Te(r),Mt(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let r=this.loadStateUnsafe(),n=new Set(r.recentEventIds),s=r.lastSequence,o=[];for(let l of e){let m=l.timestamp??new Date().toISOString(),d=l.data??{},y=l.provenance?.rawDigest??S(Ye(d)),k=l.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,l.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,l.type,m,y].join("|"),g=S(k).slice(0,32);if(n.has(g))continue;s+=1;let h={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:m,data:d,provenance:{...l.provenance,rawDigest:y}};l.role!==void 0&&(h.role=l.role),l.sourceEventId!==void 0&&(h.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(h.sourceSequence=l.sourceSequence),o.push(h),n.add(g)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
106
+ `,T=S(P).slice(0,16),A=[e.remotePrefix,"events",`${kn(g.sequence)}-${kn(v.sequence)}-${T}.jsonl`].join("/");await this.storage.exists(A)||await this.storage.put(A,P,"application/x-ndjson"),c+=y.length}let u=await this.scan(e),p=n[n.length-1],l=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?l="idle":p?.type==="error"?l="error":n.length>0&&(l="active");let f=new Date().toISOString(),d=n[0],m={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:l,createdAt:o?.createdAt??d?.timestamp??f,updatedAt:p?.timestamp??f,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:u.maxSequence,chunkCount:u.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(m.title=s.title??o?.title);let h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:u.maxSequence,lastRemoteSequence:u.maxSequence,sourceCursors:r,updatedAt:f};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,m),{uploadedEvents:c,lastRemoteSequence:u.maxSequence,eventCount:m.eventCount,chunkCount:m.chunkCount,status:l}}};import{closeSync as st,existsSync as Vo,fsyncSync as Go,mkdirSync as Ho,openSync as ot,readSync as Jo,rmSync as Sn,statSync as vn,writeSync as Yo}from"node:fs";import{join as it}from"node:path";var Qo=12e4,Xo=80,Zo=2e3;function ei(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var Oe=class{constructor(e){this.identity=e;Ho(e.localDirectory,{recursive:!0}),this.eventsFile=it(e.localDirectory,"events.jsonl"),this.stateFile=it(e.localDirectory,"state.json"),this.lockFile=it(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return Ct(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){j(this.stateFile,e)}acquireLock(){for(let e=0;e<Xo;e+=1)try{return ot(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-vn(this.lockFile).mtimeMs>Qo){Sn(this.lockFile,{force:!0});continue}}catch{}ei(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{st(n),Sn(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let l of e){let f=l.timestamp??new Date().toISOString(),d=l.data??{},m=l.provenance?.rawDigest??S(Mt(d)),h=l.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,l.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,l.type,f,m].join("|"),y=S(h).slice(0,32);if(r.has(y))continue;s+=1;let g={version:1,id:y,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:f,data:d,provenance:{...l.provenance,rawDigest:m}};l.role!==void 0&&(g.role=l.role),l.sourceEventId!==void 0&&(g.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(g.sourceSequence=l.sourceSequence),o.push(g),r.add(y)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
103
107
  `)+`
104
- `,u=_e(this.eventsFile,"a",384);try{us(u,i,null,"utf8"),is(u)}finally{Te(u)}let c=o[o.length-1],a="active";c.type==="session_end"||c.type==="session_idle"?a="idle":c.type==="error"&&(a="error");let p=Array.from(n).slice(-ps);return this.saveStateUnsafe({...r,status:a,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!os(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let r=Ot(this.eventsFile).size,n=Math.min(e.remoteByteOffset,r);if(r<=n)return{events:[],startOffset:n,endOffset:r};let s=r-n,o=Buffer.alloc(s),i=_e(this.eventsFile,"r");try{cs(i,o,0,s,n)}finally{Te(i)}return{events:o.toString("utf8").split(`
105
- `).filter(Boolean).map(a=>JSON.parse(a)),startOffset:n,endOffset:r}})}markRemote(e,r){this.withLock(()=>{let n=this.loadStateUnsafe();this.saveStateUnsafe({...n,lastRemoteSequence:Math.max(n.lastRemoteSequence,e),remoteByteOffset:Math.max(n.remoteByteOffset,r),updatedAt:new Date().toISOString()})})}setSourceCursor(e,r){this.withLock(()=>{let n=this.loadStateUnsafe();this.saveStateUnsafe({...n,sourceCursors:{...n.sourceCursors,[e]:String(r)},updatedAt:new Date().toISOString()})})}};import{closeSync as Bs,existsSync as Us,openSync as Ws,readSync as zs,statSync as qs}from"node:fs";function Tt(t,e){let r=e.toLowerCase();return r.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||r.includes("tuy\u1EC7t \u0111\u1ED1i")||r.includes("must not")||r.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||r.includes("error")||r.includes("failed")||r.includes("exception")?"normal":"temporary"}var Nt=[/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],ms=[/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],gs=[/\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],hs=[/\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],ys=[/đã 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],_t=[/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],ks=[/\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],Ss=[/đườ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],vs=[/\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],Ct=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),bs=new Set(["payload","data","content","message","messages","parts","summary"]);function E(t,e){return e.some(r=>r.test(t))}function Lt(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function ws(t){return Lt(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function xs(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function Re(t,e,r,n=0){if(!(n>6)){if(typeof t=="string"){(!e||Ct.has(e))&&r.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Re(s,e,r,n+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(Ct.has(s)||bs.has(s))&&Re(o,s,r,n+1)}}function As(t){let e=[];Re(t.data,void 0,e);let r=[],n=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=Lt(o);if(xs(i)&&!n.has(i)&&(n.add(i),r.push(i),r.length>=50))return r}return r}function Rt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Is(t,e,r){if(r.type==="decision")return{kind:"decision",confidence:1};if(r.type==="todo")return{kind:"todo",confidence:1};let n=e==="user"||r.type==="user_prompt",s=e==="assistant"||r.type==="assistant_message";return n&&E(t,Nt)?{kind:"rule",confidence:.98}:n&&E(t,ms)?{kind:"rule",confidence:.92}:E(t,gs)?{kind:E(t,_t)?"architecture":"decision",confidence:n?.93:.86}:n&&E(t,hs)?{kind:"todo",confidence:.87}:E(t,_t)&&E(t,ks)?{kind:"architecture",confidence:n?.88:.82}:s&&E(t,ys)?{kind:"fix",confidence:.8}:n&&E(t,Ss)&&E(t,vs)?{kind:"context",confidence:.79}:null}function js(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Es(t,e,r){return t==="rule"&&E(r,Nt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":Tt(e,r)}function $t(t,e){let r=[],n=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,u=Rt(o);i&&u&&s.set(i,u)}for(let o of e){let i=Rt(o),u=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&u&&(i=s.get(u)??"");for(let c of As(o)){let a=Is(c,i,o);if(!a||a.confidence<.75)continue;let p=js(a.kind),l=ws(c),m=S([t.projectId,a.kind,l].join("|"));if(n.has(m))continue;n.add(m);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],y=o.sourceEventId?[o.sourceEventId]:[];r.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:p,content:c,confidence:a.confidence,importance:Es(a.kind,p,c),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:y,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return r}function L(){let t=Y(),e=process.env.TOOLNET_SESSION_SAVE||"summary",r=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||e==="archive"||e==="full",n=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),u=r,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:r,memoryPromotion:n,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:u,archiveRemote:c}}function Dt(t){return(t||L()).rawTranscript}function Ft(t){return(t||L()).durableMemoryMaxItemsPerSession}function Kt(t){return(t||L()).sessionSummaryMaxTokens}function Bt(t){return(t||L()).archiveRemote}function Ps(t){return t.replace(/\b[A-Za-z0-9_-]{20,}\b/g,"[REDACTED]").replace(/api[_-]?key[:\s=]+[^\s]+/gi,"api_key=[REDACTED]").replace(/token[:\s=]+[^\s]+/gi,"token=[REDACTED]").replace(/secret[:\s=]+[^\s]+/gi,"secret=[REDACTED]").replace(/password[:\s=]+[^\s]+/gi,"password=[REDACTED]")}function Ms(t,e){let r=t.toLowerCase(),n=.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)r.includes(i)&&(n+=.15);e==="rule"||e==="architecture"||e==="blocker"?n+=.2:e==="decision"||e==="deploy"?n+=.15:(e==="fix"||e==="next_action")&&(n+=.1),t.length<20?n-=.3:t.length>500&&(n-=.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(t)&&(n-=.4);return Math.max(0,Math.min(1,n))}function Os(t,e){let r=[],n=new Set;for(let i of t){let u=i.split(`
106
- `).filter(c=>c.trim());for(let c of u){let a=c.trim();if(a.length<15)continue;let p=a.toLowerCase().replace(/\s+/g," ");if(n.has(p))continue;n.add(p);let l="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)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(a)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(a)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(a)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(a)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(a)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(a)&&(l="file");let m=Ms(a,l);if(m<.3)continue;let d=Ps(a);r.push({category:l,text:d,importance:m,sourceSessionId:e})}}let s=L(),o=Ft(s);return r.sort((i,u)=>u.importance-i.importance).slice(0,o)}function Ts(t){let e=L(),r=Kt(e),o=t.join(`
108
+ `,a=ot(this.eventsFile,"a",384);try{Yo(a,i,null,"utf8"),Go(a)}finally{st(a)}let c=o[o.length-1],u="active";c.type==="session_end"||c.type==="session_idle"?u="idle":c.type==="error"&&(u="error");let p=Array.from(r).slice(-Zo);return this.saveStateUnsafe({...n,status:u,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Vo(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=vn(this.eventsFile).size,r=Math.min(e.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let s=n-r,o=Buffer.alloc(s),i=ot(this.eventsFile,"r");try{Jo(i,o,0,s,r)}finally{st(i)}return{events:o.toString("utf8").split(`
109
+ `).filter(Boolean).map(u=>JSON.parse(u)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as ja,existsSync as Pa,openSync as Ea,readSync as Ma,statSync as Ca}from"node:fs";function wn(t,e){let n=e.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var In=[/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],ti=[/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],ni=[/\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],ri=[/\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],si=[/đã 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],bn=[/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],oi=[/\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],ii=[/đườ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],ai=[/\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],xn=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),ci=new Set(["payload","data","content","message","messages","parts","summary"]);function C(t,e){return e.some(n=>n.test(t))}function jn(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function ui(t){return jn(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function li(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function at(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||xn.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))at(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(xn.has(s)||ci.has(s))&&at(o,s,n,r+1)}}function di(t){let e=[];at(t.data,void 0,e);let n=[],r=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=jn(o);if(li(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function An(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function pi(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&C(t,In)?{kind:"rule",confidence:.98}:r&&C(t,ti)?{kind:"rule",confidence:.92}:C(t,ni)?{kind:C(t,bn)?"architecture":"decision",confidence:r?.93:.86}:r&&C(t,ri)?{kind:"todo",confidence:.87}:C(t,bn)&&C(t,oi)?{kind:"architecture",confidence:r?.88:.82}:s&&C(t,si)?{kind:"fix",confidence:.8}:r&&C(t,ii)&&C(t,ai)?{kind:"context",confidence:.79}:null}function fi(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function mi(t,e,n){return t==="rule"&&C(n,In)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":wn(e,n)}function Pn(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,a=An(o);i&&a&&s.set(i,a)}for(let o of e){let i=An(o),a=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&a&&(i=s.get(a)??"");for(let c of di(o)){let u=pi(c,i,o);if(!u||u.confidence<.75)continue;let p=fi(u.kind),l=ui(c),f=S([t.projectId,u.kind,l].join("|"));if(r.has(f))continue;r.add(f);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],m=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:f,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:u.kind,type:p,content:c,confidence:u.confidence,importance:mi(u.kind,p,c),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:m,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}import{createHash as gi}from"node:crypto";var yi=["project-knowledge","implementation","continuation","session-context"],hi={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function ct(t){return gi("sha256").update(t).digest("hex")}function _e(t,e){return`${t}:${ct(e).slice(0,24)}`}function ki(t){try{return ct(JSON.stringify(t))}catch{return ct(String(t))}}function F(t){let e=new Set,n=[];for(let r of t){let s=r?.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function Mn(t,e=420){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:`${n.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`}function Si(t){return t==="rule"||t==="architecture"?"project-knowledge":t==="decision"||t==="fix"?"implementation":t==="todo"?"continuation":"session-context"}function En(t){return t.length===0?0:t.reduce((e,n)=>e+n,0)/t.length}function vi(t){return t.slice().sort((e,n)=>n.importanceScore-e.importanceScore||n.confidence-e.confidence||e.id.localeCompare(n.id)).slice(0,5).map(e=>Mn(e.content)).join(" | ")}function wi(t){return t.slice().sort((e,n)=>n.importanceScore-e.importanceScore||n.confidence-e.confidence||e.id.localeCompare(n.id)).slice(0,6).map(e=>Mn(e.content)).join(`
110
+ `)}function Cn(t,e){let n=t.slice().sort((f,d)=>f.sequence-d.sequence||f.timestamp.localeCompare(d.timestamp)||f.id.localeCompare(d.id)),r=n.map(f=>({id:_e("raw",[f.projectId,f.agent,f.nativeSessionId,f.id,String(f.sequence)].join("|")),level:"raw",eventId:f.id,sourceEventId:f.sourceEventId,sequence:f.sequence,type:f.type,role:f.role,timestamp:f.timestamp,sourcePath:f.provenance.sourcePath,payloadDigest:ki(f.data)})),s=new Map,o=new Map;n.forEach((f,d)=>{let m=r[d];m&&(s.set(f.id,m.id),f.sourceEventId&&o.set(f.sourceEventId,m.id))});let i=e.map(f=>{let d=F([...f.provenance.eventIds.map(m=>s.get(m)),...f.provenance.sourceEventIds.map(m=>o.get(m))]);return{id:_e("fact",f.fingerprint),level:"fact",fingerprint:f.fingerprint,kind:f.kind,type:f.type,content:f.content,knowledgeClass:f.knowledgeClass,importanceScore:f.importanceScore,confidence:f.confidence,tags:F([...f.tags,"level:fact",`class:${f.knowledgeClass}`,`kind:${f.kind}`]),rawIds:d,sourcePaths:F(f.provenance.sourcePaths)}}),a=new Map;for(let f of i){let d=Si(f.kind),m=a.get(d)??[];m.push(f),a.set(d,m)}let c=[];for(let f of yi){let d=a.get(f);if(!d?.length)continue;let m=d.slice().sort((y,g)=>g.importanceScore-y.importanceScore||g.confidence-y.confidence||y.id.localeCompare(g.id)),h=m.map(y=>y.id);c.push({id:_e("scene",`${f}|${h.join("|")}`),level:"scene",kind:f,title:hi[f],summary:vi(m),factIds:h,importanceScore:Math.max(...m.map(y=>y.importanceScore)),confidence:En(m.map(y=>y.confidence)),tags:F(["level:scene",`scene:${f}`,...m.flatMap(y=>y.tags)]),sourcePaths:F(m.flatMap(y=>y.sourcePaths))})}let u=new Map(i.map(f=>[f.id,f])),p=[];for(let f of c){let m=f.factIds.map(g=>u.get(g)).filter(g=>!!g).filter(g=>(g.knowledgeClass==="permanent"||g.knowledgeClass==="task")&&g.importanceScore>=.55);if(m.length===0)continue;let h=m.some(g=>g.knowledgeClass==="permanent")?"permanent":"task",y=wi(m);p.push({id:_e("knowledge",`${f.id}|${h}|${m.map(g=>g.id).join("|")}`),level:"knowledge",knowledgeClass:h,title:f.title,content:y,sceneIds:[f.id],factIds:m.map(g=>g.id),importanceScore:Math.max(...m.map(g=>g.importanceScore)),confidence:En(m.map(g=>g.confidence)),tags:F(["level:knowledge",`class:${h}`,`scene:${f.kind}`,...m.flatMap(g=>g.tags)]),sourcePaths:F(m.flatMap(g=>g.sourcePaths))})}let l=[];for(let f of i)for(let d of f.rawIds)l.push({from:d,to:f.id,type:"supports"});for(let f of c)for(let d of f.factIds)l.push({from:d,to:f.id,type:"belongs_to"});for(let f of p)for(let d of f.sceneIds)l.push({from:d,to:f.id,type:"promotes_to"});return{schema:"toolnet.memory-hierarchy.v1",version:1,raw:r,facts:i,scenes:c,knowledge:p,links:l,stats:{raw:r.length,facts:i.length,scenes:c.length,knowledge:p.length,links:l.length}}}function W(){let t=pe(),e=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||e==="archive"||e==="full",r=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",s=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),o=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),a=n,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:a,archiveRemote:c}}function Tn(t){return(t||W()).rawTranscript}function On(t){return(t||W()).durableMemoryMaxItemsPerSession}function _n(t){return(t||W()).sessionSummaryMaxTokens}function Rn(t){return(t||W()).archiveRemote}function bi(t){return t.replace(/\b[A-Za-z0-9_-]{20,}\b/g,"[REDACTED]").replace(/api[_-]?key[:\s=]+[^\s]+/gi,"api_key=[REDACTED]").replace(/token[:\s=]+[^\s]+/gi,"token=[REDACTED]").replace(/secret[:\s=]+[^\s]+/gi,"secret=[REDACTED]").replace(/password[:\s=]+[^\s]+/gi,"password=[REDACTED]")}function xi(t,e){let n=t.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);e==="rule"||e==="architecture"||e==="blocker"?r+=.2:e==="decision"||e==="deploy"?r+=.15:(e==="fix"||e==="next_action")&&(r+=.1),t.length<20?r-=.3:t.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(t)&&(r-=.4);return Math.max(0,Math.min(1,r))}function Ai(t,e){let n=[],r=new Set;for(let i of t){let a=i.split(`
111
+ `).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let p=u.toLowerCase().replace(/\s+/g," ");if(r.has(p))continue;r.add(p);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(u)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(u)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(l="file");let f=xi(u,l);if(f<.3)continue;let d=bi(u);n.push({category:l,text:d,importance:f,sourceSessionId:e})}}let s=W(),o=On(s);return n.sort((i,a)=>a.importance-i.importance).slice(0,o)}function Ii(t){let e=W(),n=_n(e),o=t.join(`
107
112
 
108
113
  `).split(`
109
- `).filter(i=>{let u=i.trim();return u.length>20&&!u.startsWith("npm")&&!u.startsWith("\u2713")&&!u.startsWith("Error:")}).slice(0,20).join(`
110
- `);return fe(o,r)}function he(t,e){let n=(Array.isArray(t)?t:t.split(`
111
-
112
- `).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=Os(n,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),u=s.filter(d=>d.category==="file").map(d=>d.text),c=s.filter(d=>d.category==="fix").map(d=>d.text),a=s.filter(d=>d.category==="blocker").map(d=>d.text),p=s.filter(d=>d.category==="next_action").map(d=>d.text),l=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:Ts(n),decisions:o,projectRules:i,filesChanged:u,bugsFixed:c,commands:l,blockers:a,nextActions:p,durableFacts:s}}function C(t){let e=new Set,r=[];for(let n of t){let s=n?.replace(/\s+/g," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),r.push(s))}return r}function _s(t){let e=new Map;for(let r of t){if(!r||!r.id||!Number.isFinite(r.sequence))continue;let n=r.sourceEventId?`${r.agent}:${r.sourceEventId}`:r.id,s=e.get(n);(!s||r.sequence>s.sequence)&&e.set(n,r)}return[...e.values()].sort((r,n)=>r.sequence-n.sequence||r.timestamp.localeCompare(n.timestamp))}function Cs(t){switch(t){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function Rs(t){let e=Cs(t.importance);return Math.max(0,Math.min(1,e*.75+t.confidence*.25))}function Ns(t){return t.importance==="temporary"||t.confidence<.78?"transient":t.kind==="rule"||t.kind==="architecture"?"permanent":t.kind==="decision"||t.kind==="todo"||t.kind==="fix"?"task":"session"}function Ls(t){let e=t.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}_./:-]+/gu)??[],r=new Set;for(let n of e)if(!(n.length<2||/^\d+$/u.test(n))&&(r.add(n),r.size>=40))break;return[...r]}function $s(t){let e=Ns(t),r=Rs(t),n=Ls(t.content);return{...t,knowledgeClass:e,importanceScore:r,retrievalTerms:n,tags:C([...t.tags,`class:${e}`,`kind:${t.kind}`])}}function Ds(t){return t.map(e=>{try{return JSON.stringify({type:e.type,role:e.role,data:e.data,provenance:{sourcePath:e.provenance.sourcePath,files:e.provenance.files}})}catch{return""}}).filter(Boolean)}function Fs(t,e,r){let n=he(Ds(e),t.nativeSessionId),s=r.filter(a=>a.kind==="todo").map(a=>a.content),o=r.flatMap(a=>a.provenance.sourcePaths),i=r.filter(a=>a.kind==="architecture").map(a=>a.content),u=C([...s,...n.nextActions]),c=C([...n.nextActions,...s]);return{summary:n.summary,state:{task:c[0]??u[0],decisions:C(n.decisions),files:C([...n.filesChanged,...o]),todos:u,completed:C(n.bugsFixed),blockers:C(n.blockers),nextActions:c,architecture:C(i)}}}function Ut(t,e){let r=_s(e),n=$t(t,r).map($s),s=n.filter(a=>a.knowledgeClass!=="transient").sort((a,p)=>p.importanceScore-a.importanceScore),{summary:o,state:i}=Fs(t,r,s),u=s.map(a=>({fingerprint:a.fingerprint,kind:a.kind,knowledgeClass:a.knowledgeClass,importanceScore:a.importanceScore,content:a.content,terms:a.retrievalTerms})),c=a=>n.filter(p=>p.knowledgeClass===a).length;return{version:2,normalizedEvents:r,summary:o,state:i,candidates:s,retrievalIndex:u,stats:{inputEvents:e.length,normalizedEvents:r.length,extractedCandidates:n.length,persistedCandidates:s.length,permanent:c("permanent"),task:c("task"),session:c("session"),transient:c("transient")}}}function Wt(t){return String(t).padStart(12,"0")}function Ks(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var ye=class{constructor(e){this.storage=e}storage;async write(e,r,n){if(n.length===0||r.length===0)return null;let s=Math.min(...r.map(p=>p.sequence)),o=Math.max(...r.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:n.length,candidates:n},u=JSON.stringify(i,null,2)+`
113
- `,c=S(n.map(p=>p.fingerprint).sort().join("|")).slice(0,16),a=[Ks(e),"batches",`${Wt(s)}-${Wt(o)}-${c}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,u,"application/json"),a}};function Hs(t,e){if(!Us(t))return{events:[],nextOffset:e};let r=qs(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=r-n,o=Buffer.alloc(s),i=Ws(t,"r");try{zs(i,o,0,s,n)}finally{Bs(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
114
- `);if(c<0)return{events:[],nextOffset:n};let a=u.slice(0,c+1);return{events:a.split(`
115
- `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(a,"utf8")}}var ke=class{constructor(e){this.options=e;this.journal=new ye(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),r=Number(e.sourceCursors["memory.learner.offset"]??0),n=Number.isFinite(r)?r:0,s=Hs(this.options.wal.eventsFile,n);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Ut(this.options.identity,s.events),i=o.candidates,u=!1;return i.length>0&&(u=!!await this.journal.write(this.options.identity,s.events,i)),this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:i.length,journalWritten:u,nextOffset:s.nextOffset}}};var Se=class{identity;wal;remote;sanitizer=new H;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=Et(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new ge(this.identity),this.remote=new me(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new ke({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ie({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new de({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new ue({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let r=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:r}}start(e={}){let r=this.wal.loadState();return this.record({type:r.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(r=>this.sanitizeEvent(r)))}setSourceCursor(e,r){this.wal.setSourceCursor(e,r)}async flush(){let e=this.wal.readPending(),r=this.wal.loadState(),n=await this.remote.append(this.identity,e.events,r.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return n}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as Js,openSync as Vs,closeSync as Gs,readSync as Ys,statSync as Qs}from"node:fs";function Xs(t){let e=typeof t.role=="string"?t.role:"",r=typeof t.type=="string"?t.type.toLowerCase():"";return e==="user"||r.includes("user")?"user_prompt":e==="assistant"||r.includes("assistant")||r.includes("model")?"assistant_message":r.includes("tool")||"toolCall"in t||"tool_call"in t?"tool_call":r.includes("error")?"error":"message"}function Zs(t){let e=[t.timestamp,t.createdAt,t.time,t.created_at];for(let r of e){if(typeof r=="string"){let n=new Date(r);if(!Number.isNaN(n.getTime()))return n.toISOString()}if(typeof r=="number"){let n=r;n<1e11&&(n*=1e3);let s=new Date(n);if(!Number.isNaN(s.getTime()))return s.toISOString()}}return new Date().toISOString()}function zt(t,e={offset:0}){if(!Js(t))return{events:[],nextOffset:e.offset,reset:!1};let r=Qs(t).size,n=e.offset>r,s=n?0:e.offset;if(s===r)return{events:[],nextOffset:r,reset:n};let o=r-s,i=Buffer.alloc(o),u=Vs(t,"r");try{Ys(u,i,0,o,s)}finally{Gs(u)}let c=i.toString("utf8"),a=c.lastIndexOf(`
116
- `);if(a<0)return{events:[],nextOffset:s,reset:n};let p=c.slice(0,a+1),l=Buffer.byteLength(p,"utf8"),m=[],d=0;for(let y of p.split(`
117
- `)){if(!y)continue;let k=Buffer.byteLength(y+`
118
- `,"utf8"),g=s+d;d+=k;let h;try{h=JSON.parse(y)}catch{m.push({type:"custom",sourceEventId:`transcript:${g}`,sourceSequence:g,data:{format:"raw-line",content:y},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:g}});continue}let b=h&&typeof h=="object"&&!Array.isArray(h)?h:{value:h};m.push({type:Xs(b),timestamp:Zs(b),role:typeof b.role=="string"?b.role:void 0,sourceEventId:`transcript:${g}`,sourceSequence:g,data:b,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:g}})}return{events:m,nextOffset:s+l,reset:n}}var eo=[/^<SYSTEM MESSAGE>/i,/^<EPHEMERAL MESSAGE>/i,/^<system>/i,/^<ephemeral>/i,/^ManageTask:/i,/^Task \d+ status:/i,/^Task \d+ killed/i,/^Task \d+ loading/i,/^Thought for \d+ tokens/i,/^Prioritizing Tool Usage/i,/^Tool call:/i,/^Tool response:/i,/^npm notice/i,/^npm WARN/i,/^added \d+ packages/i,/^removed \d+ packages/i,/^up to date/i,/^\d+ packages are looking for funding/i,/^run `npm fund` for details/i,/^[\d.]+%/,/^\[={10,}\]/,/^Loading\.\.\./i,/^Processing\.\.\./i,/^bash-\d+\.\d+\$/,/^\$ /,/^\s*$/],to=[/api[_-]?key[:\s=]+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/secret[:\s=]+[^\s]+/gi,/password[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/authorization:\s*[^\s]+/gi],ro=["decision","decided","rule","convention","architecture","pattern","fixed","resolved","implemented","created","updated","deleted","deployed","blocker","blocked","issue","bug","error","next","todo","action","requirement","must","should","important"];function no(t){let e=t.toLowerCase();return ro.some(r=>e.includes(r))}function so(t){if(!t.trim())return!0;for(let e of eo)if(e.test(t))return!0;return no(t),!1}function oo(t){let e=t;for(let r of to)e=e.replace(r,n=>{let s=n.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Ne(t){let e=t.trim();return e?so(e)?{content:"",filtered:!0,reason:"noise"}:{content:oo(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function ve(t){let e={};for(let[r,n]of Object.entries(t))if(typeof n=="string"){let s=Ne(n);s.filtered||(e[r]=s.content)}else n&&typeof n=="object"&&!Array.isArray(n)?e[r]=ve(n):Array.isArray(n)?e[r]=n.map(s=>{if(typeof s=="string"){let o=Ne(s);return o.filtered?null:o.content}return s&&typeof s=="object"?ve(s):s}).filter(s=>s!==null):e[r]=n;return e}function qt(t){let e=typeof t.type=="string"?t.type.toLowerCase():"";if(e.includes("system")||e.includes("ephemeral")||e==="tool_call"&&!t.result)return!0;if(t.data&&typeof t.data=="object"){let r=t.data,n=typeof r.content=="string"?r.content:"";if(n&&Ne(n).filtered)return!0}return!1}function co(t){return t==="~"?Ht():t.startsWith("~/")?io(Ht(),t.slice(2)):t}async function Jt(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let r=ao(co(t.transcriptPath)),n=new Se({project:t.project,storage:t.storage,agent:"agy",nativeSessionId:e,metadata:{source:"antigravity-hook",transcriptPath:r,workspacePaths:t.workspacePaths??[],artifactDirectoryPath:t.artifactDirectoryPath,modelName:t.modelName}}),s=n.status(),o=s.sourceCursors["agy.transcript.offset"],i=o?Number(o):0,u=zt(r,{offset:Number.isFinite(i)?i:0}),c=[];s.lastSequence===0&&c.push({type:"session_start",sourceEventId:`agy:${e}:start`,data:{workspacePaths:t.workspacePaths??[],transcriptPath:r,modelName:t.modelName},provenance:{source:"antigravity-hook",sourcePath:r}}),u.reset&&c.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${u.nextOffset}`,data:{event:"transcript_reset",transcriptPath:r},provenance:{source:"agy-transcript",sourcePath:r}});let a=u.events.filter(m=>!qt(m.data)).map(m=>({...m,data:ve(m.data)}));c.push(...a),t.phase==="stop"&&(t.error&&c.push({type:"error",sourceEventId:["agy",e,"stop-error",t.terminationReason??"",u.nextOffset].join(":"),data:{error:t.error,terminationReason:t.terminationReason,fullyIdle:t.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),t.fullyIdle&&c.push({type:"session_idle",sourceEventId:["agy",e,"idle",u.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let p=n.recordMany(c);if(n.setSourceCursor("agy.transcript.offset",u.nextOffset),t.phase&&n.setSourceCursor("agy.last.phase",t.phase),t.phase==="stop"&&a.length>0)try{let m=a.map(y=>JSON.stringify(y.data)),d=he(m,e);n.setSourceCursor("agy.session.summary",d.summary),n.setSourceCursor("agy.session.facts_count",d.durableFacts.length),Dt()&&(Bt()||n.setSourceCursor("agy.raw_transcript.archived","local"))}catch{}let l=await n.flush();return{conversationId:e,imported:p.length,eventCount:l.eventCount,chunkCount:l.chunkCount,status:l.status,transcriptOffset:u.nextOffset,reset:u.reset}}async function uo(){let t="";for await(let e of process.stdin)t+=e.toString();if(!t.trim())return{};try{return JSON.parse(t)}catch{return{}}}function G(t){return Array.isArray(t)?t.filter(e=>typeof e=="string"):[]}function lo(t){let e=typeof t.common=="object"&&t.common!==null?t.common:{},r=typeof t.pre_invocation_hook_args=="object"&&t.pre_invocation_hook_args!==null?t.pre_invocation_hook_args:{},n=typeof t.post_invocation_hook_args=="object"&&t.post_invocation_hook_args!==null?t.post_invocation_hook_args:{},s=typeof t.stop_hook_args=="object"&&t.stop_hook_args!==null?t.stop_hook_args:{},o=(typeof e.conversation_id=="string"?e.conversation_id:"")||(typeof t.conversationId=="string"?t.conversationId:"")||(typeof t.conversation_id=="string"?t.conversation_id:""),i=(typeof e.transcript_path=="string"?e.transcript_path:"")||(typeof t.transcriptPath=="string"?t.transcriptPath:"")||(typeof t.transcript_path=="string"?t.transcript_path:""),u=G(e.workspace_paths).length>0?G(e.workspace_paths):G(t.workspacePaths).length>0?G(t.workspacePaths):G(t.workspace_paths),c=typeof r.invocation_num=="number"?r.invocation_num:typeof t.invocationNum=="number"?t.invocationNum:typeof t.invocation_num=="number"?t.invocation_num:void 0,a=(typeof e.artifact_directory_path=="string"?e.artifact_directory_path:"")||(typeof t.artifactDirectoryPath=="string"?t.artifactDirectoryPath:"")||(typeof t.artifact_directory_path=="string"?t.artifact_directory_path:"")||void 0,p=(typeof e.model_name=="string"?e.model_name:"")||(typeof t.modelName=="string"?t.modelName:"")||(typeof t.model_name=="string"?t.model_name:"")||void 0,l=s.fully_idle===!0||t.fullyIdle===!0||t.fully_idle===!0,m=(typeof s.termination_reason=="string"?s.termination_reason:"")||(typeof t.terminationReason=="string"?t.terminationReason:"")||(typeof t.termination_reason=="string"?t.termination_reason:"")||void 0,d=(typeof s.error=="string"&&s.error?s.error:"")||(typeof t.error=="string"&&t.error?t.error:"")||void 0;return{conversationId:o,transcriptPath:i,workspacePaths:u,invocationNum:c,artifactDirectoryPath:a,modelName:p,fullyIdle:l,terminationReason:m,error:d}}function po(t){let e=typeof t.toolCall=="object"&&t.toolCall!==null?t.toolCall:{},r=typeof e.args=="object"&&e.args!==null?e.args:{},n="";try{n=JSON.stringify(r).replace(/\\\\/g,"/").toLowerCase()}catch{n=""}return n.includes(".toolnet/sessions")?{decision:"deny",reason:"ToolNet continuity guard: do not replay raw .toolnet/sessions history. Use the injected continuity handoff. If deeper history is required, invoke memory_agent_ask directly."}:{decision:"allow"}}async function fo(){let t=process.argv[2]??"post",e=await uo();if(t==="pre-tool"){process.stdout.write(JSON.stringify(po(e)));return}let r=lo(e),n=r.conversationId,s=r.transcriptPath,o=r.workspacePaths,i=It(o),u={};if(i&&n)try{let c=Y(),a=Je(qe({provider:c.storage.provider,huggingface:c.storage.huggingface,localRoot:c.storage.localRoot}),{attempts:2}),p=new re(a,i.id,i.name,i.remote??i.name);if(s)try{await Jt({project:i,storage:p,conversationId:n,transcriptPath:s,workspacePaths:o,artifactDirectoryPath:r.artifactDirectoryPath,modelName:r.modelName,phase:t,fullyIdle:r.fullyIdle,terminationReason:r.terminationReason,error:r.error})}catch{}if(t==="pre")try{u=await xt({project:i,storage:p,conversationId:n,invocationNum:r.invocationNum})}catch{u={}}if(t==="stop")try{await Pe(i,p,800)}catch{}}catch{}if(t==="stop"){process.stdout.write(JSON.stringify({decision:"stop"}));return}process.stdout.write(JSON.stringify(u))}fo().catch(()=>{process.argv[2]==="stop"?process.stdout.write('{"decision":"stop"}'):process.argv[2]==="pre-tool"?process.stdout.write('{"decision":"allow"}'):process.stdout.write("{}"),process.exitCode=0});export{po as buildAgyPreToolUseOutput,lo as normalizeAgyInput};
114
+ `).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).join(`
115
+ `);return Me(o,n)}function Re(t,e){let r=(Array.isArray(t)?t:t.split(`
116
+
117
+ `).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=Ai(r,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),a=s.filter(d=>d.category==="file").map(d=>d.text),c=s.filter(d=>d.category==="fix").map(d=>d.text),u=s.filter(d=>d.category==="blocker").map(d=>d.text),p=s.filter(d=>d.category==="next_action").map(d=>d.text),l=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:Ii(r),decisions:o,projectRules:i,filesChanged:a,bugsFixed:c,commands:l,blockers:u,nextActions:p,durableFacts:s}}function D(t){let e=new Set,n=[];for(let r of t){let s=r?.replace(/\s+/g," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function ji(t){let e=new Map;for(let n of t){if(!n||!n.id||!Number.isFinite(n.sequence))continue;let r=n.sourceEventId?`${n.agent}:${n.sourceEventId}`:n.id,s=e.get(r);(!s||n.sequence>s.sequence)&&e.set(r,n)}return[...e.values()].sort((n,r)=>n.sequence-r.sequence||n.timestamp.localeCompare(r.timestamp))}function Pi(t){switch(t){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function Ei(t){let e=Pi(t.importance);return Math.max(0,Math.min(1,e*.75+t.confidence*.25))}function Mi(t){return t.importance==="temporary"||t.confidence<.78?"transient":t.kind==="rule"||t.kind==="architecture"?"permanent":t.kind==="decision"||t.kind==="todo"||t.kind==="fix"?"task":"session"}function Ci(t){let e=t.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}_./:-]+/gu)??[],n=new Set;for(let r of e)if(!(r.length<2||/^\d+$/u.test(r))&&(n.add(r),n.size>=40))break;return[...n]}function Ti(t){let e=Mi(t),n=Ei(t),r=Ci(t.content);return{...t,knowledgeClass:e,importanceScore:n,retrievalTerms:r,tags:D([...t.tags,"level:fact",`class:${e}`,`kind:${t.kind}`])}}function Oi(t){return t.map(e=>{try{return JSON.stringify({type:e.type,role:e.role,data:e.data,provenance:{sourcePath:e.provenance.sourcePath,files:e.provenance.files}})}catch{return""}}).filter(Boolean)}function _i(t,e,n){let r=Re(Oi(e),t.nativeSessionId),s=n.filter(u=>u.kind==="todo").map(u=>u.content),o=n.flatMap(u=>u.provenance.sourcePaths),i=n.filter(u=>u.kind==="architecture").map(u=>u.content),a=D([...s,...r.nextActions]),c=D([...r.nextActions,...s]);return{summary:r.summary,state:{task:c[0]??a[0],decisions:D(r.decisions),files:D([...r.filesChanged,...o]),todos:a,completed:D(r.bugsFixed),blockers:D(r.blockers),nextActions:c,architecture:D(i)}}}function Nn(t,e){let n=ji(e),r=Pn(t,n).map(Ti),s=r.filter(p=>p.knowledgeClass!=="transient").sort((p,l)=>l.importanceScore-p.importanceScore),{summary:o,state:i}=_i(t,n,s),a=s.map(p=>({fingerprint:p.fingerprint,kind:p.kind,knowledgeClass:p.knowledgeClass,importanceScore:p.importanceScore,content:p.content,terms:p.retrievalTerms})),c=Cn(n,s),u=p=>r.filter(l=>l.knowledgeClass===p).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:a,hierarchy:c,stats:{inputEvents:e.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:s.length,permanent:u("permanent"),task:u("task"),session:u("session"),transient:u("transient")}}}import{createHash as Wi}from"node:crypto";import{existsSync as Bi,readdirSync as zi,readFileSync as Ui}from"node:fs";import{basename as qi,join as Xn}from"node:path";import{randomUUID as Kn}from"node:crypto";var b=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function ne(t){let e=new Set,n=[];for(let r of t){let s=r.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function z(t){let e=t.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!e)throw new b("Invalid Wiki slug",400);return e}function Ln(t){let e=[];for(let n of t.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&e.push(z(r))}return ne(e)}function Ri(t){return t.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function $n(t){return{id:`revision-${Kn()}`,pageId:t.id,slug:t.slug,revision:t.revision,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...t.tags],links:[...t.links],createdAt:t.updatedAt}}function B(t){return structuredClone(t)}var Ne=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(e){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=e(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let e=await this.ensureState(),n=new Set(e.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:e.projectId,pages:e.pages.length,revisions:e.revisions.length,tags:ne(e.pages.flatMap(r=>r.tags)).sort((r,s)=>r.localeCompare(s)),links:e.pages.reduce((r,s)=>r+s.links.length,0),orphanPages:e.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:e.pages.filter(r=>r.tags.some(s=>s.startsWith("toolnet-auto-"))).length,updatedAt:e.updatedAt}}async listPages(){let e=await this.ensureState();return B([...e.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(e){let n=await this.ensureState(),r=z(e),s=n.pages.find(o=>o.slug===r||o.id===e);if(!s)throw new b(`Wiki page not found: ${e}`,404);return B(s)}async createPage(e){return this.mutate(n=>{let r=e.title.trim(),s=e.content.trim();if(!r)throw new b("Wiki title is required",400);let o=z(e.slug??r);if(n.pages.some(c=>c.slug===o))throw new b(`Wiki page already exists: ${o}`,409);let i=new Date().toISOString(),a={id:`wiki-${Kn()}`,slug:o,title:r,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:s,tags:ne(e.tags??[]),links:Ln(s),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push($n(a)),B(a)})}async updatePage(e,n){return this.mutate(r=>{let s=z(e),o=r.pages.find(i=>i.slug===s||i.id===e);if(!o)throw new b(`Wiki page not found: ${e}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new b("Wiki title is required",400);o.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?o.summary=i:delete o.summary}return n.content!==void 0&&(o.content=n.content.trim(),o.links=Ln(o.content)),n.tags!==void 0&&(o.tags=ne(n.tags)),o.revision+=1,o.updatedAt=new Date().toISOString(),r.revisions.push($n(o)),B(o)})}async history(e){let n=await this.getPage(e),r=await this.ensureState();return B(r.revisions.filter(s=>s.pageId===n.id).sort((s,o)=>o.revision-s.revision))}async backlinks(e){let n=await this.getPage(e),r=await this.ensureState();return B(r.pages.filter(s=>s.links.includes(n.slug)).sort((s,o)=>s.title.localeCompare(o.title)))}async search(e,n=10){let r=await this.ensureState(),s=ne(Ri(e));if(s.length===0)return[];let o=Math.max(1,Math.min(20,Math.floor(n))),i=[];for(let a of r.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),p=a.summary?.toLowerCase()??"",l=a.content.toLowerCase(),f=a.tags.map(m=>m.toLowerCase()),d=0;for(let m of s)u===m&&(d+=12),c===m&&(d+=10),c.includes(m)&&(d+=6),u.includes(m)&&(d+=5),f.some(h=>h===m)?d+=5:f.some(h=>h.includes(m))&&(d+=3),p.includes(m)&&(d+=2),l.includes(m)&&(d+=1);d>0&&i.push({page:B(a),score:d})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,o)}};var Dn="wiki/state.v1.json";function Ni(t){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:t.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function Li(t,e){let n=JSON.parse(t);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==e.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var Le=class{constructor(e,n){this.storage=e;this.project=n}storage;project;async load(){let e=await this.storage.getText(Dn);if(!e){let n=Ni(this.project);return await this.save(n),n}return Li(e,this.project)}async save(e){await this.storage.put(Dn,JSON.stringify(e,null,2),"application/json")}};import{createHash as $i,randomUUID as Fn}from"node:crypto";var Wn="wiki/governance.v1.json",qn="toolnet.knowledge-governance.v1",Bn=500,re={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function Ki(t,e=0,n=1){return Math.max(e,Math.min(n,t))}function ut(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function zn(t){return $i("sha256").update(t.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function Di(t){let e=[t.title,t.summary??"",t.content.slice(0,2e3),...t.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(e)}function Fi(t){let e=t.sourceType==="skill"?.96:t.sourceType==="memory"?.94:.88,n=t.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(e+=.03),t.content.length>=200&&(e+=.02),t.content.length<80&&(e-=.05),t.title.length<4&&(e-=.05),Ki(e)}function Un(t){let e=new Date().toISOString();return{schema:qn,version:1,projectId:t,policy:{...re},reviews:[],audit:[],createdAt:e,updatedAt:e}}function Vn(t){let e=t.autoApproveThreshold??re.autoApproveThreshold,n=t.criticalApproveThreshold??re.criticalApproveThreshold,r=t.staleAfterDays??re.staleAfterDays;if(!Number.isFinite(e)||e<.5||e>1)throw new b("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new b("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new b("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:n,staleAfterDays:r}}var $e=class{constructor(e,n){this.storage=e;this.project=n}storage;project;async load(){let e=await this.storage.getText(Wn);if(!e){let n=Un(this.project.id);return await this.save(n),n}try{let n=JSON.parse(e);if(n.schema!==qn||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:Vn(n.policy??re)}}catch{let n=Un(this.project.id);return await this.save(n),n}}async save(e){await this.storage.put(Wn,JSON.stringify(e,null,2),"application/json")}},Ke=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(e,n,r,s={}){e.audit.push({id:Fn(),action:n,principal:r,...s.reviewId?{reviewId:s.reviewId}:{},...s.sourceKey?{sourceKey:s.sourceKey}:{},timestamp:new Date().toISOString(),...s.metadata?{metadata:s.metadata}:{}}),e.audit.length>Bn&&(e.audit=e.audit.slice(-Bn))}async mutate(e){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=await e(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(e,n){return this.mutate(r=>(r.policy=Vn({...r.policy,...e}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let e=await this.ensureState(),n=r=>e.reviews.filter(s=>s.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:e.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:e.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:e.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:e.audit.length,policy:{...e.policy},updatedAt:e.updatedAt}}async listReviews(e){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!e||r.status===e).sort((r,s)=>s.updatedAt.localeCompare(r.updatedAt)))}async auditLog(e=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(e)));return structuredClone(n.audit.slice(-r).reverse())}async assess(e,n){let r=await this.ensureState(),s=Fi(e),o=ut(e.title),i=n.filter(p=>p.slug!==e.slug&&ut(p.title)===o&&zn(p.content)!==zn(e.content)).map(p=>p.slug),a=Di(e),c=[];s<r.policy.autoApproveThreshold&&c.push(`confidence:${s.toFixed(2)}`),a&&s<r.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:s,risk:u,requiresReview:i.length>0||s<r.policy.autoApproveThreshold||a&&s<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(e,n){let r=await this.assess(e,n);return this.mutate(s=>{let o=s.reviews.find(c=>c.sourceKey===e.sourceKey&&c.digest===e.digest);if(o?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(o)};if(o?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(o)};if(!r.requiresReview)return this.audit(s,"knowledge:auto-approved","system",{sourceKey:e.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(o?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(o)};let i=new Date().toISOString(),a={id:Fn(),sourceKey:e.sourceKey,sourceType:e.sourceType,slug:e.slug,marker:e.marker,digest:e.digest,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...new Set([...e.tags,e.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};return s.reviews.push(a),this.audit(s,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(a)}})}async markApplied(e,n){await this.mutate(r=>{let s=r.reviews.find(o=>o.sourceKey===e&&o.digest===n&&o.status==="approved");s&&(s.appliedAt=new Date().toISOString(),s.updatedAt=s.appliedAt,this.audit(r,"knowledge:applied",s.reviewedBy??"system",{reviewId:s.id,sourceKey:e}))})}async decide(e,n,r){return this.mutate(async s=>{let o=s.reviews.find(u=>u.id===e);if(!o)throw new b(`Governance review not found: ${e}`,404);if(o.status!=="pending")throw new b("Governance review is already resolved",409);let i=new Date().toISOString();if(o.reviewedAt=i,o.reviewedBy=n.principal,o.updatedAt=i,n.note?.trim()&&(o.reviewNote=n.note.trim()),n.action==="reject")return o.status="rejected",this.audit(s,"knowledge:rejected",n.principal,{reviewId:e,sourceKey:o.sourceKey}),structuredClone(o);if(n.action==="supersede")return o.status="superseded",n.targetReviewId&&(o.supersededBy=n.targetReviewId),this.audit(s,"knowledge:superseded",n.principal,{reviewId:e,sourceKey:o.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(o);if(n.action==="merge"){if(!n.targetReviewId)throw new b("targetReviewId is required for merge",400);let u=s.reviews.find(p=>p.id===n.targetReviewId);if(!u)throw new b("Merge target review not found",404);return o.status="superseded",o.mergedInto=u.id,this.audit(s,"knowledge:merged",n.principal,{reviewId:e,sourceKey:o.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(o)}o.status="approved";let c=(await r.listPages()).find(u=>u.slug===o.slug);if(c&&!c.tags.includes(o.marker))throw new b(`Wiki page '${o.slug}' is manually managed`,409);return c?await r.updatePage(o.slug,{title:o.title,summary:o.summary??"",content:o.content,tags:o.tags}):await r.createPage({slug:o.slug,title:o.title,...o.summary?{summary:o.summary}:{},content:o.content,tags:o.tags}),o.appliedAt=i,this.audit(s,"knowledge:approved",n.principal,{reviewId:e,sourceKey:o.sourceKey}),structuredClone(o)})}async quality(e){let n=await this.ensureState(),r=await e.listPages(),s=Date.now(),o=n.policy.staleAfterDays*864e5,i=r.map(p=>{let l=s-Date.parse(p.updatedAt);return{slug:p.slug,title:p.title,updatedAt:p.updatedAt,ageDays:Math.max(0,Math.floor(l/864e5)),stale:Number.isFinite(l)&&l>o}}).filter(p=>p.stale).map(({stale:p,...l})=>l),a=new Map;for(let p of r){let l=ut(p.title),f=a.get(l)??[];f.push(p),a.set(l,f)}let c=[...a.entries()].filter(([,p])=>p.length>1).map(([p,l])=>({title:p,pages:l.map(f=>f.slug)})),u=n.reviews.filter(p=>p.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(p=>p.tags.some(l=>l.startsWith("toolnet-auto-"))).length,manualPages:r.filter(p=>!p.tags.some(l=>l.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(p=>p.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(p=>p.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var Zn="wiki/automation.v1.json",er="toolnet.wiki-automation.v1",pt=8e3,Gn=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function oe(t){return Wi("sha256").update(JSON.stringify(t)).digest("hex")}function se(t){if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function Hn(t){return Array.isArray(t)?t:[]}function tr(t){return typeof t!="string"?void 0:t.replace(/\s+/gu," ").trim()||void 0}function lt(t){return Array.isArray(t)?t.map(tr).filter(e=>!!e):[]}function _(t,e){for(let n of e){let r=tr(t[n]);if(r)return r}}function ie(t){let e=new Set,n=[];for(let r of t){let s=r.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function De(t,e=0,n=""){if(e>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(Gn.has(r))return[];if(typeof t=="string"){let i=t.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(t))return t.flatMap(i=>De(i,e+1,n));let s=se(t);if(!s)return[];let o=[];for(let[i,a]of Object.entries(s)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();Gn.has(c)||o.push(...De(a,e+1,i))}return o}function Jn(t){let n=ie(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(s=>De(t[s],0,s)));return(n.length>0?n:ie(De(t))).join(`
118
+
119
+ `).slice(0,pt)}function Yn(t,e){return _(t,["id","key","fingerprint","knowledgeId","sceneId"])??e}function Qn(t,e){return _(t,["title","name","topic","label","task","kind","type"])??e}function Vi(t){return(_(t,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function Gi(t){return(_(t,["kind","sceneKind","type"])??"").toLowerCase()}function Hi(t){let e=se(t);if(!e)return[];let n=[],r=Hn(e.knowledge);for(let[o,i]of r.entries()){let a=se(i);if(!a)continue;let c=Vi(a);if(c==="session"||c==="transient")continue;let u=Jn(a);if(u.length<20)continue;let p=Yn(a,oe(a).slice(0,16)),l=Qn(a,`Durable Memory ${o+1}`);n.push({sourceKey:`memory:${p}`,sourceType:"memory",title:l,summary:_(a,["summary","description"]),content:u,tags:ie(["toolnet","auto","memory",...c?[c]:[]])})}let s=Hn(e.scenes);for(let[o,i]of s.entries()){let a=se(i);if(!a)continue;let c=Gi(a);if(c==="session-context")continue;let u=Jn(a);if(u.length<20)continue;let p=Yn(a,oe(a).slice(0,16)),l=Qn(a,`Knowledge Scene ${o+1}`);n.push({sourceKey:`scene:${p}`,sourceType:"scene",title:l,summary:_(a,["summary","description"]),content:u,tags:ie(["toolnet","auto","scene",...c?[c]:[]])})}return n}function Ji(t){return Xn(t,".toolnet","memory","skills")}function Yi(t){let e=Ji(t);if(!Bi(e))return{candidates:[],failed:0};let n=[],r=0,s=zi(e).filter(o=>o.endsWith(".json")).sort();for(let o of s)try{let i=JSON.parse(Ui(Xn(e,o),"utf8")),a=se(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let c=_(a,["id","fingerprint"])??qi(o,".json"),u=_(a,["task"])??"",p=_(a,["title"])||u||`Reusable Skill ${c.slice(0,8)}`,l=_(a,["summary"])??void 0,f=lt(a.steps),d=lt(a.verification),m=lt(a.files),h=[];u&&h.push(`## Task
120
+ ${u}`),l&&h.push(`## Summary
121
+ ${l}`),f.length>0&&h.push(`## Procedure
122
+ ${f.map((g,v)=>`${v+1}. ${g}`).join(`
123
+ `)}`),d.length>0&&h.push(`## Verification
124
+ ${d.map(g=>`- ${g}`).join(`
125
+ `)}`),m.length>0&&h.push(`## Relevant Files
126
+ ${m.map(g=>`- \`${g}\``).join(`
127
+ `)}`);let y=h.join(`
128
+
129
+ `).slice(0,pt);if(y.length<20)continue;n.push({sourceKey:`skill:${c}`,sourceType:"skill",title:p,summary:l,content:y,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function dt(t){let e=new Date().toISOString();return{schema:er,version:1,projectId:t,entries:[],createdAt:e,updatedAt:e}}async function Qi(t,e){let n=await t.getText(Zn);if(!n)return dt(e);try{let r=JSON.parse(n);return r.schema!==er||r.version!==1||r.projectId!==e||!Array.isArray(r.entries)?dt(e):r}catch{return dt(e)}}async function Xi(t,e){await t.put(Zn,JSON.stringify(e,null,2),"application/json")}function Zi(t){return`toolnet-auto-${oe(t).slice(0,12)}`}function ea(t){let e=z(t.title).slice(0,72),n=oe(t.sourceKey).slice(0,10);return z(`auto-${t.sourceType}-${e}-${n}`)}function ta(t){return[`> Auto-generated by ToolNet Knowledge Automation from ${t.sourceType==="skill"?"reusable Skill Memory":t.sourceType==="scene"?"semantic memory scene":"durable memory"}.`,"",t.content].join(`
130
+ `).slice(0,pt)}function na(t){return oe({sourceType:t.sourceType,title:t.title,summary:t.summary,content:t.content,tags:t.tags})}function ra(t,e){return t.tags.includes(e)}async function nr(t){let e=Hi(t.hierarchy),n=Yi(t.project.rootPath),r=new Map;for(let d of[...e,...n.candidates])r.set(d.sourceKey,d);let s=[...r.values()].sort((d,m)=>d.sourceKey.localeCompare(m.sourceKey)),o={schema:"toolnet.wiki-automation-result.v1",scanned:e.length+n.candidates.length,eligible:s.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new Ne(new Le(t.storage,t.project));await i.initialize();let a=new Ke(new $e(t.storage,t.project));await a.initialize();let c=await Qi(t.storage,t.project.id),u=await i.listPages(),p=new Map(u.map(d=>[d.slug,d])),l=new Map(c.entries.map(d=>[d.sourceKey,d]));for(let d of s)try{let m=Zi(d.sourceKey),h=na(d),y=l.get(d.sourceKey),g=y?.slug??ea(d),v=p.get(g);if(v&&!ra(v,m)){o.skipped+=1;continue}let P=ie([...d.tags,m]),T=ta(d),A=await a.gate({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:g,marker:m,digest:h,title:d.title,...d.summary?{summary:d.summary}:{},content:T,tags:P},[...p.values()]);if(!A.allowed){A.mode==="pending-review"?o.reviewPending+=1:o.skipped+=1;continue}A.mode==="auto-approved"?o.autoApproved+=1:A.mode==="review-approved"&&(o.reviewApproved+=1),v?y?.digest!==h?(v=await i.updatePage(g,{title:d.title,summary:d.summary??"",content:T,tags:P}),p.set(v.slug,v),o.updated+=1,o.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:v.slug,action:"updated"})):(o.unchanged+=1,o.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:g,action:"unchanged"})):(v=await i.createPage({slug:g,title:d.title,summary:d.summary,content:T,tags:P}),p.set(v.slug,v),o.created+=1,o.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:v.slug,action:"created"}));let R=new Date().toISOString(),k={sourceKey:d.sourceKey,sourceType:d.sourceType,slug:g,digest:h,marker:m,updatedAt:R},x=c.entries.findIndex(de=>de.sourceKey===d.sourceKey);x>=0?c.entries[x]=k:c.entries.push(k),l.set(d.sourceKey,k),await a.markApplied(d.sourceKey,h)}catch(m){if(m instanceof b&&m.statusCode===409){o.skipped+=1;continue}o.failed+=1}let f=new Date().toISOString();return c.updatedAt=f,c.lastRunAt=f,c.entries.sort((d,m)=>d.sourceKey.localeCompare(m.sourceKey)),await Xi(t.storage,c),o}import{createHash as sa}from"node:crypto";import{chmodSync as sr,existsSync as oa,mkdirSync as ia,readFileSync as Of,readdirSync as _f,renameSync as aa,statSync as Rf,writeFileSync as ca}from"node:fs";import{join as or}from"node:path";var ua="toolnet.skill-memory.v1",rr=5,la=16,da=24,pa=32;function fa(t){return sa("sha256").update(t).digest("hex")}function ce(t,e=Number.MAX_SAFE_INTEGER){let n=new Set,r=[];for(let s of t){let o=s.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=e))break}return r}function ft(t,e=360){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function ma(t){return t.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/giu,"Bearer [REDACTED]").replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu,"[REDACTED]").replace(/\b(api[_-]?key|token|password|passwd|secret)\b(\s*[:=]\s*)(["']?)[^\s"'`]+/giu,"$1$2[REDACTED]")}function N(t,e=360){return t&&ft(ma(t),e)||void 0}function ue(t,e){for(let n of e){let r=t[n];if(typeof r=="string"&&r.trim())return r}}function ir(t,e){for(let n of e){let r=t[n];if(typeof r=="number"&&Number.isFinite(r))return r;if(typeof r=="string"&&r.trim()&&Number.isFinite(Number(r)))return Number(r)}}function ar(t,e){for(let n of e){let r=t[n];if(typeof r=="boolean")return r;if(typeof r=="string"){let s=r.trim().toLowerCase();if(["true","yes","pass","passed","success","succeeded","ok"].includes(s))return!0;if(["false","no","fail","failed","error"].includes(s))return!1}}}function cr(t){let e=t.data??{};if(ar(e,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=ir(e,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let s=ue(e,["status","result","outcome"]);return!!(s&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(s))}function ae(t){let e=t.data??{};if(cr(t))return!1;if(ar(e,["passed","pass","success","succeeded","ok"])===!0||ir(e,["exitCode","exit_code","code","statusCode"])===0)return!0;let s=ue(e,["status","result","outcome"]);return s&&/\b(pass(?:ed)?|success(?:ful)?|succeeded|ok|green|complete(?:d)?)\b/iu.test(s)?!0:t.type==="commit"||t.type==="deploy"}function ur(t){let e=t.data??{},n=ue(e,["path","file","filePath","filename","target"]);if(n)return N(n,260);let r=t.provenance?.files;return N(r?.[0],260)}function mt(t){return N(ue(t.data??{},["command","cmd","script"]),420)}function J(t){return N(ue(t.data??{},["name","test","suite","title","message","text","result","status"]),300)}function ga(t){let e=[];for(let n of[...t].sort((r,s)=>r.sequence-s.sequence))if(ae(n)){if(n.type==="test"){let r=J(n)??mt(n)??"Tests passed";e.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=J(n);e.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=J(n);e.push(r?`Deploy: ${r}`:"Deployment completed")}}return ce(e,10)}function ya(t,e){let n=[];for(let r of[...t].sort((s,o)=>s.sequence-o.sequence))switch(r.type){case"file_write":case"file_edit":{let s=ur(r);s&&n.push(`Update ${s}`);break}case"command":{if(cr(r))break;let s=mt(r);s&&n.push(`Run: ${s}`);break}case"test":{if(!ae(r))break;let s=J(r)??mt(r)??"project tests";n.push(`Verify: ${s}`);break}case"commit":{if(!ae(r))break;let s=J(r);n.push(s?`Commit: ${s}`:"Commit verified changes");break}case"deploy":{if(!ae(r))break;let s=J(r);n.push(s?`Deploy: ${s}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of e.files.slice(0,8)){let s=N(r,260);s&&n.push(`Update ${s}`)}return ce(n,la)}function ha(t,e){let n=[...e.files];for(let r of t){let s=ur(r);s&&n.push(s);for(let o of r.provenance?.files??[]){let i=N(o,260);i&&n.push(i)}}return ce(n,da)}function ka(t){return ce(t.filter(e=>["file_write","file_edit","command","test","commit","deploy"].includes(e.type)).map(e=>e.id),pa)}function Sa(t){return t.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function lr(t,e,n){if(e.length===0)return[];let r=ga(e),s=ce(n.completed.map(m=>N(m,280)??""),rr);if(!(s.length>0||e.some(m=>["test","commit","deploy"].includes(m.type)&&ae(m))))return[];let i=N(n.task,280)??N(n.nextActions[0],280),a=s.length>0?s:i?[i]:[];if(a.length===0)return[];let c=ya(e,n);if(c.length===0)return[];let u=ha(e,n),p=ka(e),l=Math.min(...e.map(m=>m.sequence)),f=Math.max(...e.map(m=>m.sequence)),d=Sa(e);return a.slice(0,rr).map(m=>{let h=[`Reusable procedure learned from successful task: ${m}.`,u.length>0?`Files: ${u.slice(0,6).join(", ")}.`:"",r.length>0?`Verification: ${r.slice(0,4).join("; ")}.`:""].filter(Boolean),y=JSON.stringify({projectId:t.projectId,task:m,steps:c,verification:r,files:u}),g=fa(y);return{schema:ua,version:1,id:`skill-${g.slice(0,24)}`,fingerprint:g,projectId:t.projectId,title:ft(`SOP: ${m}`,180),task:m,summary:ft(h.join(" "),900),steps:c,verification:r,files:u,source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:l,lastSequence:f,eventIds:p},createdAt:d}})}function va(t){return or(t.rootPath,".toolnet","memory","skills")}function wa(t){let e=va(t);return ia(e,{recursive:!0,mode:448}),sr(e,448),e}function dr(t,e){if(e.length===0)return{written:0,deduped:0,files:[]};let n=wa(t),r=0,s=0,o=[];for(let i of e){if(i.projectId!==t.id)throw new Error(`Skill project mismatch: ${i.projectId} != ${t.id}`);let a=or(n,`${i.id}.json`);if(o.push(a),oa(a)){s+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;ca(c,JSON.stringify(i,null,2)+`
131
+ `,{encoding:"utf8",mode:384}),aa(c,a),sr(a,384),r+=1}return{written:r,deduped:s,files:o}}function pr(t){return String(t).padStart(12,"0")}function ba(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var Fe=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(p=>p.sequence)),o=Math.max(...n.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},a=JSON.stringify(i,null,2)+`
132
+ `,c=S(r.map(p=>p.fingerprint).sort().join("|")).slice(0,16),u=[ba(e),"batches",`${pr(s)}-${pr(o)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,a,"application/json"),u}};import{createHash as xa}from"node:crypto";function fr(t){return String(t).padStart(12,"0")}function Aa(t){return xa("sha256").update(t).digest("hex")}function Ia(t){return t.remotePrefix.replace("/sessions/","/memory/hierarchy/")}var We=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(n.length===0||r.facts.length===0)return null;let s=Math.min(...n.map(u=>u.sequence)),o=Math.max(...n.map(u=>u.sequence)),i={schema:"toolnet.memory-hierarchy-batch.v1",version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,hierarchy:r},a=Aa([...r.facts.map(u=>u.id),...r.knowledge.map(u=>u.id)].sort().join("|")).slice(0,16),c=[Ia(e),"batches",`${fr(s)}-${fr(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,`${JSON.stringify(i,null,2)}
133
+ `,"application/json"),c}};function Ta(t,e){if(!Pa(t))return{events:[],nextOffset:e};let n=Ca(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=Ea(t,"r");try{Ma(i,o,0,s,r)}finally{ja(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
134
+ `);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
135
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Be=class{constructor(e){this.options=e;this.journal=new Fe(e.storage),this.hierarchyJournal=new We(e.storage)}options;journal;hierarchyJournal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Ta(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Nn(this.options.identity,s.events),i=o.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,s.events,i));let c=!1;o.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,s.events,o.hierarchy));let u=lr(this.options.identity,s.events,o.state),p=dr(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",o.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",o.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",o.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",o.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",o.hierarchy.stats.knowledge),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.journal_written",c?1:0),this.options.wal.setSourceCursor("memory.skill.assets",u.length),this.options.wal.setSourceCursor("memory.skill.written",p.written),this.options.wal.setSourceCursor("memory.skill.deduped",p.deduped);try{let l=un(this.options.project.rootPath,s.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",l.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",l.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",l.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",l.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let l=await nr({project:this.options.project,storage:this.options.storage,hierarchy:o.hierarchy});this.options.wal.setSourceCursor("memory.wiki_automation.scanned",l.scanned),this.options.wal.setSourceCursor("memory.wiki_automation.eligible",l.eligible),this.options.wal.setSourceCursor("memory.wiki_automation.created",l.created),this.options.wal.setSourceCursor("memory.wiki_automation.updated",l.updated),this.options.wal.setSourceCursor("memory.wiki_automation.unchanged",l.unchanged),this.options.wal.setSourceCursor("memory.wiki_automation.skipped",l.skipped),this.options.wal.setSourceCursor("memory.wiki_automation.failed",l.failed),this.options.wal.setSourceCursor("memory.wiki_automation.review_pending",l.reviewPending),this.options.wal.setSourceCursor("memory.wiki_automation.auto_approved",l.autoApproved),this.options.wal.setSourceCursor("memory.wiki_automation.review_approved",l.reviewApproved)}catch{this.options.wal.setSourceCursor("memory.wiki_automation.failed",1)}return this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:i.length,journalWritten:a,nextOffset:s.nextOffset}}};var ze=class{identity;wal;remote;sanitizer=new Z;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=hn(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new Oe(this.identity),this.remote=new Te(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new Be({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new be({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new Pe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new Ie({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as Oa,openSync as _a,closeSync as Ra,readSync as Na,statSync as La}from"node:fs";function $a(t){let e=typeof t.role=="string"?t.role:"",n=typeof t.type=="string"?t.type.toLowerCase():"";return e==="user"||n.includes("user")?"user_prompt":e==="assistant"||n.includes("assistant")||n.includes("model")?"assistant_message":n.includes("tool")||"toolCall"in t||"tool_call"in t?"tool_call":n.includes("error")?"error":"message"}function Ka(t){let e=[t.timestamp,t.createdAt,t.time,t.created_at];for(let n of e){if(typeof n=="string"){let r=new Date(n);if(!Number.isNaN(r.getTime()))return r.toISOString()}if(typeof n=="number"){let r=n;r<1e11&&(r*=1e3);let s=new Date(r);if(!Number.isNaN(s.getTime()))return s.toISOString()}}return new Date().toISOString()}function mr(t,e={offset:0}){if(!Oa(t))return{events:[],nextOffset:e.offset,reset:!1};let n=La(t).size,r=e.offset>n,s=r?0:e.offset;if(s===n)return{events:[],nextOffset:n,reset:r};let o=n-s,i=Buffer.alloc(o),a=_a(t,"r");try{Na(a,i,0,o,s)}finally{Ra(a)}let c=i.toString("utf8"),u=c.lastIndexOf(`
136
+ `);if(u<0)return{events:[],nextOffset:s,reset:r};let p=c.slice(0,u+1),l=Buffer.byteLength(p,"utf8"),f=[],d=0;for(let m of p.split(`
137
+ `)){if(!m)continue;let h=Buffer.byteLength(m+`
138
+ `,"utf8"),y=s+d;d+=h;let g;try{g=JSON.parse(m)}catch{f.push({type:"custom",sourceEventId:`transcript:${y}`,sourceSequence:y,data:{format:"raw-line",content:m},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:y}});continue}let v=g&&typeof g=="object"&&!Array.isArray(g)?g:{value:g};f.push({type:$a(v),timestamp:Ka(v),role:typeof v.role=="string"?v.role:void 0,sourceEventId:`transcript:${y}`,sourceSequence:y,data:v,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:y}})}return{events:f,nextOffset:s+l,reset:r}}var Da=[/^<SYSTEM MESSAGE>/i,/^<EPHEMERAL MESSAGE>/i,/^<system>/i,/^<ephemeral>/i,/^ManageTask:/i,/^Task \d+ status:/i,/^Task \d+ killed/i,/^Task \d+ loading/i,/^Thought for \d+ tokens/i,/^Prioritizing Tool Usage/i,/^Tool call:/i,/^Tool response:/i,/^npm notice/i,/^npm WARN/i,/^added \d+ packages/i,/^removed \d+ packages/i,/^up to date/i,/^\d+ packages are looking for funding/i,/^run `npm fund` for details/i,/^[\d.]+%/,/^\[={10,}\]/,/^Loading\.\.\./i,/^Processing\.\.\./i,/^bash-\d+\.\d+\$/,/^\$ /,/^\s*$/],Fa=[/api[_-]?key[:\s=]+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/secret[:\s=]+[^\s]+/gi,/password[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/authorization:\s*[^\s]+/gi],Wa=["decision","decided","rule","convention","architecture","pattern","fixed","resolved","implemented","created","updated","deleted","deployed","blocker","blocked","issue","bug","error","next","todo","action","requirement","must","should","important"];function Ba(t){let e=t.toLowerCase();return Wa.some(n=>e.includes(n))}function za(t){if(!t.trim())return!0;for(let e of Da)if(e.test(t))return!0;return Ba(t),!1}function Ua(t){let e=t;for(let n of Fa)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function gt(t){let e=t.trim();return e?za(e)?{content:"",filtered:!0,reason:"noise"}:{content:Ua(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function Ue(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=gt(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=Ue(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=gt(s);return o.filtered?null:o.content}return s&&typeof s=="object"?Ue(s):s}).filter(s=>s!==null):e[n]=r;return e}function gr(t){let e=typeof t.type=="string"?t.type.toLowerCase():"";if(e.includes("system")||e.includes("ephemeral")||e==="tool_call"&&!t.result)return!0;if(t.data&&typeof t.data=="object"){let n=t.data,r=typeof n.content=="string"?n.content:"";if(r&&gt(r).filtered)return!0}return!1}function Ga(t){return t==="~"?yr():t.startsWith("~/")?qa(yr(),t.slice(2)):t}async function hr(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let n=Va(Ga(t.transcriptPath)),r=new ze({project:t.project,storage:t.storage,agent:"agy",nativeSessionId:e,metadata:{source:"antigravity-hook",transcriptPath:n,workspacePaths:t.workspacePaths??[],artifactDirectoryPath:t.artifactDirectoryPath,modelName:t.modelName}}),s=r.status(),o=s.sourceCursors["agy.transcript.offset"],i=o?Number(o):0,a=mr(n,{offset:Number.isFinite(i)?i:0}),c=[];s.lastSequence===0&&c.push({type:"session_start",sourceEventId:`agy:${e}:start`,data:{workspacePaths:t.workspacePaths??[],transcriptPath:n,modelName:t.modelName},provenance:{source:"antigravity-hook",sourcePath:n}}),a.reset&&c.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${a.nextOffset}`,data:{event:"transcript_reset",transcriptPath:n},provenance:{source:"agy-transcript",sourcePath:n}});let u=a.events.filter(f=>!gr(f.data)).map(f=>({...f,data:Ue(f.data)}));c.push(...u),t.phase==="stop"&&(t.error&&c.push({type:"error",sourceEventId:["agy",e,"stop-error",t.terminationReason??"",a.nextOffset].join(":"),data:{error:t.error,terminationReason:t.terminationReason,fullyIdle:t.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),t.fullyIdle&&c.push({type:"session_idle",sourceEventId:["agy",e,"idle",a.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let p=r.recordMany(c);if(r.setSourceCursor("agy.transcript.offset",a.nextOffset),t.phase&&r.setSourceCursor("agy.last.phase",t.phase),t.phase==="stop"&&u.length>0)try{let f=u.map(m=>JSON.stringify(m.data)),d=Re(f,e);r.setSourceCursor("agy.session.summary",d.summary),r.setSourceCursor("agy.session.facts_count",d.durableFacts.length),Tn()&&(Rn()||r.setSourceCursor("agy.raw_transcript.archived","local"))}catch{}let l=await r.flush();return{conversationId:e,imported:p.length,eventCount:l.eventCount,chunkCount:l.chunkCount,status:l.status,transcriptOffset:a.nextOffset,reset:a.reset}}async function Ha(){let t="";for await(let e of process.stdin)t+=e.toString();if(!t.trim())return{};try{return JSON.parse(t)}catch{return{}}}function le(t){return Array.isArray(t)?t.filter(e=>typeof e=="string"):[]}function Ja(t){let e=typeof t.common=="object"&&t.common!==null?t.common:{},n=typeof t.pre_invocation_hook_args=="object"&&t.pre_invocation_hook_args!==null?t.pre_invocation_hook_args:{},r=typeof t.post_invocation_hook_args=="object"&&t.post_invocation_hook_args!==null?t.post_invocation_hook_args:{},s=typeof t.stop_hook_args=="object"&&t.stop_hook_args!==null?t.stop_hook_args:{},o=(typeof e.conversation_id=="string"?e.conversation_id:"")||(typeof t.conversationId=="string"?t.conversationId:"")||(typeof t.conversation_id=="string"?t.conversation_id:""),i=(typeof e.transcript_path=="string"?e.transcript_path:"")||(typeof t.transcriptPath=="string"?t.transcriptPath:"")||(typeof t.transcript_path=="string"?t.transcript_path:""),a=le(e.workspace_paths).length>0?le(e.workspace_paths):le(t.workspacePaths).length>0?le(t.workspacePaths):le(t.workspace_paths),c=typeof n.invocation_num=="number"?n.invocation_num:typeof t.invocationNum=="number"?t.invocationNum:typeof t.invocation_num=="number"?t.invocation_num:void 0,u=(typeof e.artifact_directory_path=="string"?e.artifact_directory_path:"")||(typeof t.artifactDirectoryPath=="string"?t.artifactDirectoryPath:"")||(typeof t.artifact_directory_path=="string"?t.artifact_directory_path:"")||void 0,p=(typeof e.model_name=="string"?e.model_name:"")||(typeof t.modelName=="string"?t.modelName:"")||(typeof t.model_name=="string"?t.model_name:"")||void 0,l=s.fully_idle===!0||t.fullyIdle===!0||t.fully_idle===!0,f=(typeof s.termination_reason=="string"?s.termination_reason:"")||(typeof t.terminationReason=="string"?t.terminationReason:"")||(typeof t.termination_reason=="string"?t.termination_reason:"")||void 0,d=(typeof s.error=="string"&&s.error?s.error:"")||(typeof t.error=="string"&&t.error?t.error:"")||void 0;return{conversationId:o,transcriptPath:i,workspacePaths:a,invocationNum:c,artifactDirectoryPath:u,modelName:p,fullyIdle:l,terminationReason:f,error:d}}function Ya(t){let e=typeof t.toolCall=="object"&&t.toolCall!==null?t.toolCall:{},n=typeof e.args=="object"&&e.args!==null?e.args:{},r="";try{r=JSON.stringify(n).replace(/\\\\/g,"/").toLowerCase()}catch{r=""}return r.includes(".toolnet/sessions")?{decision:"deny",reason:"ToolNet continuity guard: do not replay raw .toolnet/sessions history. Use the injected continuity handoff. If deeper history is required, invoke memory_agent_ask directly."}:{decision:"allow"}}async function Qa(){let t=process.argv[2]??"post",e=await Ha();if(t==="pre-tool"){process.stdout.write(JSON.stringify(Ya(e)));return}let n=Ja(e),r=n.conversationId,s=n.transcriptPath,o=n.workspacePaths,i=gn(o),a={};if(i&&r)try{let c=pe(),u=jt(At({provider:c.storage.provider,huggingface:c.storage.huggingface,localRoot:c.storage.localRoot}),{attempts:2}),p=new ke(u,i.id,i.name,i.remote??i.name);if(s)try{await hr({project:i,storage:p,conversationId:r,transcriptPath:s,workspacePaths:o,artifactDirectoryPath:n.artifactDirectoryPath,modelName:n.modelName,phase:t,fullyIdle:n.fullyIdle,terminationReason:n.terminationReason,error:n.error})}catch{}if(t==="pre")try{a=await fn({project:i,storage:p,conversationId:r,invocationNum:n.invocationNum})}catch{a={}}if(t==="stop")try{await Xe(i,p,800)}catch{}}catch{}if(t==="stop"){process.stdout.write(JSON.stringify({decision:"stop"}));return}process.stdout.write(JSON.stringify(a))}Qa().catch(()=>{process.argv[2]==="stop"?process.stdout.write('{"decision":"stop"}'):process.argv[2]==="pre-tool"?process.stdout.write('{"decision":"allow"}'):process.stdout.write("{}"),process.exitCode=0});export{Ya as buildAgyPreToolUseOutput,Ja as normalizeAgyInput};