toolnet-memory 0.2.20 → 0.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle/codex.js CHANGED
@@ -1,26 +1,34 @@
1
- import{existsSync as di,readFileSync as pi}from"node:fs";import{spawn as fi}from"node:child_process";import{homedir as mi}from"node:os";import{join as gi}from"node:path";import{existsSync as Pn,readFileSync as On}from"node:fs";import{homedir as En}from"node:os";import{join as Tn}from"node:path";function Cn(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 An(){let t=process.env.TOOLNET_GLOBAL_ENV??Tn(En(),".config","toolnet-memory",".env");if(!Pn(t))return;let e=On(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]=Cn(r.slice(s+1)))}}An();function B(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function z(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function G(){return{memory:{autoCapture:B(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:B(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:B(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:B(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:B(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 Mn}from"node:crypto";import{existsSync as Pe,mkdirSync as Rn,readFileSync as Nn,renameSync as _n,writeFileSync as $n}from"node:fs";import{basename as Fn,dirname as X,join as Q,parse as Ue,resolve as J}from"node:path";var Ye=".toolnet",Ln="project.json";function Wn(t){return Mn("sha256").update(t).digest("hex").slice(0,16)}function Oe(t){return Q(t,Ye,Ln)}function Dn(t){return Pe(Oe(t))}function Kn(t,e){let n=J(t),r=Ue(n).root;for(;;){if(Dn(n))return n;if(n===r||e&&n===J(e))break;let s=X(n);if(s===n)break;n=s}return null}function Bn(t){let e=J(t),n=Ue(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>Pe(Q(e,o))))return e;if(e===n)break;let s=X(e);if(s===e)break;e=s}return J(t)}function zn(t){let e;try{e=JSON.parse(Nn(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:X(X(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 He(t,e){let n=Q(t,Ye);Rn(n,{recursive:!0});let r=Oe(t),s=`${r}.tmp-${process.pid}`;$n(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),_n(s,r)}function Ve(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 _=class{detect(e=process.cwd()){let n=J(e),r=Bn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>Pe(Q(r,f))),i=Kn(n,o?r:void 0);if(i){let f=Oe(i),l=zn(f);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),He(i,l)),Ve(l,i)}let c=new Date().toISOString(),u=Fn(r),a={version:1,id:Wn(r),name:u,remote:u,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return He(r,a),Ve(a,r)}};var Jn=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],Z=class{scan(e){let n=[];for(let r of Jn){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 q=class{scanner=new Z;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 fr}from"node:os";import{join as mr}from"node:path";import{DeleteObjectCommand as qn,GetObjectCommand as Hn,HeadObjectCommand as Vn,ListObjectsV2Command as Un,PutObjectCommand as Yn,S3Client as Gn}from"@aws-sdk/client-s3";import{getSignedUrl as Xn}from"@aws-sdk/s3-request-presigner";var ee=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Gn({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 Yn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Xn(this.client,new Hn({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 Vn({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 qn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Un({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 Ge,mkdir as Qn,readFile as Zn,readdir as er,rm as tr,stat as Xe,writeFile as nr}from"node:fs/promises";import{dirname as rr,join as sr,relative as Qe,resolve as or}from"node:path";var H=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return or(this.root,n)}async put(e,n){let r=this.path(e);await Qn(rr(r),{recursive:!0}),await nr(r,n)}async get(e){try{return await Zn(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 Ge(this.path(e)),!0}catch{return!1}}async delete(e){await tr(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ge(n)}catch{return r}let s=async i=>{let c=await er(i,{withFileTypes:!0});for(let u of c){let a=sr(i,u.name);if(u.isDirectory()){await s(a);continue}let f=await Xe(a);r.push({key:Qe(this.root,a),size:f.size,updatedAt:f.mtime.toISOString()})}},o=await Xe(n);return o.isDirectory()?await s(n):r.push({key:Qe(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as ir,GetObjectCommand as ar,HeadObjectCommand as cr,ListObjectsV2Command as ur,PutObjectCommand as lr,S3Client as dr}from"@aws-sdk/client-s3";import{getSignedUrl as pr}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 dr({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 lr({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await pr(this.client,new ar({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 cr({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 ir({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new ur({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 Ee(t,e){return console.warn(e),new H(t)}function Ze(t){let e=t.localRoot??mr(fr(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new V({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ee(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 V({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ee(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 ee({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ee(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new H(e)}function gr(t){return new Promise(e=>setTimeout(e,t))}async function et(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(c){if(o=c,i>=n)break;let u=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,u*.2));await gr(u+a)}throw o}var hr=new Set(["put","get","getText","delete","list"]);function tt(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:hr.has(r)?(...o)=>et(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function nt(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 rt(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 te=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=nt(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(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}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=rt(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{join as wr}from"node:path";import{createHash as yr}from"node:crypto";import{dirname as Sr}from"node:path";import{mkdirSync as kr,readFileSync as vr,renameSync as xr,writeFileSync as br}from"node:fs";function k(t){return yr("sha256").update(t).digest("hex")}function Te(t){if(Array.isArray(t))return t.map(Te);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Te(e[r]);return n}return t}function st(t){return JSON.stringify(Te(t))}function ot(t){try{return JSON.parse(vr(t,"utf8"))}catch{return null}}function I(t,e){kr(Sr(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;br(n,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),xr(n,t)}function it(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=k(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 at(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=it(r.toLowerCase(),"agent"),i=it(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:wr(t.rootPath,".toolnet","sessions",o,i)}}function ct(t){return String(t).padStart(12,"0")}var ne=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)+`
6
- `,"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 c=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!c)continue;let u=Number(c[1]),a=Number(c[2]);!Number.isFinite(u)||!Number.isFinite(a)||(s.push({key:i.key,start:u,end:a}),o=Math.max(o,a))}return s.sort((i,c)=>i.start-c.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
7
- `,"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),c=n.filter(g=>g.sequence>i.maxSequence),u=0;for(let g of this.split(c)){let y=g[0],b=g[g.length-1],C=g.map(E=>JSON.stringify(E)).join(`
1
+ import{existsSync as Ii,readFileSync as Pi}from"node:fs";import{spawn as Ci}from"node:child_process";import{homedir as Oi}from"node:os";import{join as Mi}from"node:path";import{existsSync as Tn,readFileSync as An}from"node:fs";import{homedir as Rn}from"node:os";import{join as Nn}from"node:path";function _n(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 $n(){let t=process.env.TOOLNET_GLOBAL_ENV??Nn(Rn(),".config","toolnet-memory",".env");if(!Tn(t))return;let e=An(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]=_n(r.slice(s+1)))}}$n();function q(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function J(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function X(){return{memory:{autoCapture:q(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:q(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:q(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:q(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:J(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:J(process.env.MEMORY_RERANK_TOP,10),finalContext:J(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:J(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:q(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:J(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Fn}from"node:crypto";import{existsSync as Me,mkdirSync as Ln,readFileSync as Wn,renameSync as Dn,writeFileSync as Kn}from"node:fs";import{basename as zn,dirname as Z,join as ee,parse as Qe,resolve as H}from"node:path";var Xe=".toolnet",Bn="project.json";function qn(t){return Fn("sha256").update(t).digest("hex").slice(0,16)}function Ee(t){return ee(t,Xe,Bn)}function Jn(t){return Me(Ee(t))}function Hn(t,e){let n=H(t),r=Qe(n).root;for(;;){if(Jn(n))return n;if(n===r||e&&n===H(e))break;let s=Z(n);if(s===n)break;n=s}return null}function Vn(t){let e=H(t),n=Qe(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>Me(ee(e,o))))return e;if(e===n)break;let s=Z(e);if(s===e)break;e=s}return H(t)}function Un(t){let e;try{e=JSON.parse(Wn(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:Z(Z(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 Ye(t,e){let n=ee(t,Xe);Ln(n,{recursive:!0});let r=Ee(t),s=`${r}.tmp-${process.pid}`;Kn(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Dn(s,r)}function Ge(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 F=class{detect(e=process.cwd()){let n=H(e),r=Vn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>Me(ee(r,f))),i=Hn(n,o?r:void 0);if(i){let f=Ee(i),l=Un(f);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),Ye(i,l)),Ge(l,i)}let u=new Date().toISOString(),c=zn(r),a={version:1,id:qn(r),name:c,remote:c,rootPath:r,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return Ye(r,a),Ge(a,r)}};var Yn=[{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}],te=class{scan(e){let n=[];for(let r of Yn){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 V=class{scanner=new te;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 Sr}from"node:os";import{join as kr}from"node:path";import{DeleteObjectCommand as Gn,GetObjectCommand as Qn,HeadObjectCommand as Xn,ListObjectsV2Command as Zn,PutObjectCommand as er,S3Client as tr}from"@aws-sdk/client-s3";import{getSignedUrl as nr}from"@aws-sdk/s3-request-presigner";var ne=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new tr({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 er({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await nr(this.client,new Qn({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 Xn({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 Gn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Zn({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 Ze,mkdir as rr,readFile as sr,readdir as or,rm as ir,stat as et,writeFile as ar}from"node:fs/promises";import{dirname as cr,join as ur,relative as tt,resolve as lr}from"node:path";var U=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return lr(this.root,n)}async put(e,n){let r=this.path(e);await rr(cr(r),{recursive:!0}),await ar(r,n)}async get(e){try{return await sr(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 Ze(this.path(e)),!0}catch{return!1}}async delete(e){await ir(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ze(n)}catch{return r}let s=async i=>{let u=await or(i,{withFileTypes:!0});for(let c of u){let a=ur(i,c.name);if(c.isDirectory()){await s(a);continue}let f=await et(a);r.push({key:tt(this.root,a),size:f.size,updatedAt:f.mtime.toISOString()})}},o=await et(n);return o.isDirectory()?await s(n):r.push({key:tt(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as dr,GetObjectCommand as pr,HeadObjectCommand as fr,ListObjectsV2Command as mr,PutObjectCommand as gr,S3Client as hr}from"@aws-sdk/client-s3";import{getSignedUrl as yr}from"@aws-sdk/s3-request-presigner";var Y=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new hr({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 gr({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await yr(this.client,new pr({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 fr({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 dr({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new mr({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 Te(t,e){return console.warn(e),new U(t)}function nt(t){let e=t.localRoot??kr(Sr(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Y({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Te(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 Y({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Te(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 ne({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Te(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new U(e)}function vr(t){return new Promise(e=>setTimeout(e,t))}async function rt(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(u){if(o=u,i>=n)break;let c=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,c*.2));await vr(c+a)}throw o}var br=new Set(["put","get","getText","delete","list"]);function st(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:br.has(r)?(...o)=>rt(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function ot(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 it(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 re=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=ot(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(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"&&(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=it(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{join as Or}from"node:path";import{createHash as xr}from"node:crypto";import{dirname as wr}from"node:path";import{mkdirSync as jr,readFileSync as Ir,renameSync as Pr,writeFileSync as Cr}from"node:fs";function k(t){return xr("sha256").update(t).digest("hex")}function Ae(t){if(Array.isArray(t))return t.map(Ae);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Ae(e[r]);return n}return t}function at(t){return JSON.stringify(Ae(t))}function ct(t){try{return JSON.parse(Ir(t,"utf8"))}catch{return null}}function I(t,e){jr(wr(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;Cr(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Pr(n,t)}function ut(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=k(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 lt(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=ut(r.toLowerCase(),"agent"),i=ut(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:Or(t.rootPath,".toolnet","sessions",o,i)}}function dt(t){return String(t).padStart(12,"0")}var se=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)+`
6
+ `,"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 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 n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
7
+ `,"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),u=n.filter(h=>h.sequence>i.maxSequence),c=0;for(let h of this.split(u)){let g=h[0],x=h[h.length-1],T=h.map(M=>JSON.stringify(M)).join(`
8
8
  `)+`
9
- `,A=k(C).slice(0,16),j=[e.remotePrefix,"events",`${ct(y.sequence)}-${ct(b.sequence)}-${A}.jsonl`].join("/");await this.storage.exists(j)||await this.storage.put(j,C,"application/x-ndjson"),u+=g.length}let a=await this.scan(e),f=n[n.length-1],l=o?.status??"active";f?.type==="session_end"||f?.type==="session_idle"?l="idle":f?.type==="error"?l="error":n.length>0&&(l="active");let m=new Date().toISOString(),d=n[0],S={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:f?.timestamp??m,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:f?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(S.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:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:u,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:l}}};import{closeSync as Ce,existsSync as jr,fsyncSync as Ir,mkdirSync as Pr,openSync as Ae,readSync as Or,rmSync as ut,statSync as lt,writeSync as Er}from"node:fs";import{join as Me}from"node:path";var Tr=12e4,Cr=80,Ar=2e3;function Mr(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var re=class{constructor(e){this.identity=e;Pr(e.localDirectory,{recursive:!0}),this.eventsFile=Me(e.localDirectory,"events.jsonl"),this.stateFile=Me(e.localDirectory,"state.json"),this.lockFile=Me(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 ot(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){I(this.stateFile,e)}acquireLock(){for(let e=0;e<Cr;e+=1)try{return Ae(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-lt(this.lockFile).mtimeMs>Tr){ut(this.lockFile,{force:!0});continue}}catch{}Mr(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{Ce(n),ut(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 m=l.timestamp??new Date().toISOString(),d=l.data??{},S=l.provenance?.rawDigest??k(st(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,m,S].join("|"),g=k(h).slice(0,32);if(r.has(g))continue;s+=1;let y={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:S}};l.role!==void 0&&(y.role=l.role),l.sourceEventId!==void 0&&(y.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(y.sourceSequence=l.sourceSequence),o.push(y),r.add(g)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
9
+ `,A=k(T).slice(0,16),j=[e.remotePrefix,"events",`${dt(g.sequence)}-${dt(x.sequence)}-${A}.jsonl`].join("/");await this.storage.exists(j)||await this.storage.put(j,T,"application/x-ndjson"),c+=h.length}let a=await this.scan(e),f=n[n.length-1],l=o?.status??"active";f?.type==="session_end"||f?.type==="session_idle"?l="idle":f?.type==="error"?l="error":n.length>0&&(l="active");let m=new Date().toISOString(),d=n[0],S={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:f?.timestamp??m,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:f?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(S.title=s.title??o?.title);let y={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,y),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:c,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:l}}};import{closeSync as Re,existsSync as Mr,fsyncSync as Er,mkdirSync as Tr,openSync as Ne,readSync as Ar,rmSync as pt,statSync as ft,writeSync as Rr}from"node:fs";import{join as _e}from"node:path";var Nr=12e4,_r=80,$r=2e3;function Fr(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var oe=class{constructor(e){this.identity=e;Tr(e.localDirectory,{recursive:!0}),this.eventsFile=_e(e.localDirectory,"events.jsonl"),this.stateFile=_e(e.localDirectory,"state.json"),this.lockFile=_e(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){I(this.stateFile,e)}acquireLock(){for(let e=0;e<_r;e+=1)try{return Ne(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-ft(this.lockFile).mtimeMs>Nr){pt(this.lockFile,{force:!0});continue}}catch{}Fr(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{Re(n),pt(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 m=l.timestamp??new Date().toISOString(),d=l.data??{},S=l.provenance?.rawDigest??k(at(d)),y=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,S].join("|"),h=k(y).slice(0,32);if(r.has(h))continue;s+=1;let g={version:1,id:h,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:S}};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(h)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
10
10
  `)+`
11
- `,c=Ae(this.eventsFile,"a",384);try{Er(c,i,null,"utf8"),Ir(c)}finally{Ce(c)}let u=o[o.length-1],a="active";u.type==="session_end"||u.type==="session_idle"?a="idle":u.type==="error"&&(a="error");let f=Array.from(r).slice(-Ar);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:f}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!jr(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=lt(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=Ae(this.eventsFile,"r");try{Or(i,o,0,s,r)}finally{Ce(i)}return{events:o.toString("utf8").split(`
12
- `).filter(Boolean).map(a=>JSON.parse(a)),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 Ur,existsSync as Yr,openSync as Gr,readSync as Xr,statSync as Qr}from"node:fs";function dt(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 gt=[/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],Rr=[/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],Nr=[/\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],_r=[/\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],$r=[/đã 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],pt=[/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],Fr=[/\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],Lr=[/đườ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],Wr=[/\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],ft=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Dr=new Set(["payload","data","content","message","messages","parts","summary"]);function P(t,e){return e.some(n=>n.test(t))}function ht(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Kr(t){return ht(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Br(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,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||ft.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Re(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(ft.has(s)||Dr.has(s))&&Re(o,s,n,r+1)}}function zr(t){let e=[];Re(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=ht(o);if(Br(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function mt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Jr(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&&P(t,gt)?{kind:"rule",confidence:.98}:r&&P(t,Rr)?{kind:"rule",confidence:.92}:P(t,Nr)?{kind:P(t,pt)?"architecture":"decision",confidence:r?.93:.86}:r&&P(t,_r)?{kind:"todo",confidence:.87}:P(t,pt)&&P(t,Fr)?{kind:"architecture",confidence:r?.88:.82}:s&&P(t,$r)?{kind:"fix",confidence:.8}:r&&P(t,Lr)&&P(t,Wr)?{kind:"context",confidence:.79}:null}function qr(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Hr(t,e,n){return t==="rule"&&P(n,gt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":dt(e,n)}function yt(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,c=mt(o);i&&c&&s.set(i,c)}for(let o of e){let i=mt(o),c=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&c&&(i=s.get(c)??"");for(let u of zr(o)){let a=Jr(u,i,o);if(!a||a.confidence<.75)continue;let f=qr(a.kind),l=Kr(u),m=k([t.projectId,a.kind,l].join("|"));if(r.has(m))continue;r.add(m);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:f,content:u,confidence:a.confidence,importance:Hr(a.kind,f,u),tags:[f],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function St(t){return String(t).padStart(12,"0")}function Vr(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var se=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(f=>f.sequence)),o=Math.max(...n.map(f=>f.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},c=JSON.stringify(i,null,2)+`
13
- `,u=k(r.map(f=>f.fingerprint).sort().join("|")).slice(0,16),a=[Vr(e),"batches",`${St(s)}-${St(o)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,c,"application/json"),a}};function Zr(t,e){if(!Yr(t))return{events:[],nextOffset:e};let n=Qr(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=Gr(t,"r");try{Xr(i,o,0,s,r)}finally{Ur(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
14
- `);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
15
- `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var oe=class{constructor(e){this.options=e;this.journal=new se(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Zr(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=yt(this.options.identity,s.events),i=!1;return o.length>0&&(i=!!await this.journal.write(this.options.identity,s.events,o)),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:o.length,journalWritten:i,nextOffset:s.nextOffset}}};import{closeSync as is,existsSync as as,openSync as cs,readSync as us,statSync as ls}from"node:fs";var es=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 vt(t){return F(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(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))$(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(es.has(r)||["data","payload","parts","messages"].includes(r))&&$(s,e,n+1)}}function ie(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 kt(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,n,r,s={}){let o=F(r),i=s.key??vt(o);return{version:1,id:k([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 ts(t,e,n){let r=F(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(w(t,e,"goal",i[1],{confidence:.97}));let c=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);c?.[1]&&s.push(w(t,e,"plan",c[1],{confidence:.95}));let u=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=u.exec(r));){let m=Number(a[1]),d=F(a[2]??""),S=d&&!kt(d)?`Phase ${m} - ${d}`:`Phase ${m}`;s.push(w(t,e,"phase",S,{key:`phase:${m}`,order:m,status:ie(r),confidence:.93}))}let f=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);f?.[2]&&s.push(w(t,e,"task",f[2],{status:f[1].trim()?"completed":ie(f[2]),confidence:.96}));let l=r.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]),S=kt(d);s.push(w(t,e,"task",S&&m!==void 0?`TODO ${m}`:d,{key:m!==void 0?`task:${m}`:vt(d),order:m,status:ie(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 m=r.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(r)&&s.push(w(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(w(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(w(t,e,"decision",r,{confidence:.9})),s}function ae(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 u=[];$(i.data,u);for(let a of u)s(w(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];$(i.data,u);for(let a of u)s(w(t,i,"task",a,{status:ie(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let a=i.data[u];typeof a=="string"&&a&&s(w(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let u=[];$(i.data,u);for(let a of u)s(w(t,i,"test",a,{confidence:1}))}let c=[];$(i.data,c);for(let u of c)for(let a of u.split(/\n+/u))for(let f of ts(t,i,a))s(f)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function xt(t){return String(t).padStart(12,"0")}var ce=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.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)+`
16
- `,c=k(n.map(a=>a.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${xt(r)}-${xt(s)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as bt}from"node:path";import{mkdirSync as ns}from"node:fs";function rs(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function L(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=rs(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 wt(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??k(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 os(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,c)=>i.key.localeCompare(c.key))){let i=await e.getText(o.key);if(i)try{let c=JSON.parse(i);c.version===1&&Array.isArray(c.observations)&&s.push(c)}catch{}}return s}async function ue(t,e){let r=(await os(t,e)).flatMap(p=>p.observations).sort((p,v)=>{let K=p.occurredAt.localeCompare(v.occurredAt);if(K!==0)return K;let qe=p.sequence-v.sequence;return qe!==0?qe:p.id.localeCompare(v.id)}),s=new Map,o=new Map,i,c,u,a=[],f=[],l=[],m=[],d=[],S=[];for(let p of r)switch(p.kind){case"goal":i=p.text;break;case"plan":c=p.text;break;case"phase":s.set(p.key,wt(s.get(p.key),p));break;case"task":o.set(p.key,wt(o.get(p.key),p));break;case"decision":a.push(p.text);break;case"blocker":f.push(p.text);break;case"warning":l.push(p.text);break;case"next_action":m.push(p.text);break;case"file":d.push(p.text);break;case"test":S.push(p.text);break;case"session":u={agent:p.agent,nativeSessionId:p.nativeSessionId,sessionKey:p.sessionKey,updatedAt:p.occurredAt};break}let h=Array.from(s.values()).sort((p,v)=>(p.order??Number.MAX_SAFE_INTEGER)-(v.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((p,v)=>(p.order??Number.MAX_SAFE_INTEGER)-(v.order??Number.MAX_SAFE_INTEGER)),y=h.find(p=>p.status==="in_progress")??h.find(p=>p.status==="blocked")??h.find(p=>p.status==="pending"),b=g.find(p=>p.status==="in_progress")??g.find(p=>p.status==="blocked")??g.find(p=>p.status==="pending"),C=L([...m,...b?[b.title]:[],...!b&&y?[y.title]:[],...g.filter(p=>p.status==="pending").slice(0,5).map(p=>p.title)],8),A=L([...f,...h.filter(p=>p.status==="blocked").map(p=>p.title),...g.filter(p=>p.status==="blocked").map(p=>p.title)],20),j={version:1,projectId:t.id,projectName:t.name,goal:i,plan:c,phases:h,tasks:g,decisions:L(a,20),blockers:A,warnings:L(l,20),nextActions:C,filesTouched:L(d,30),tests:L(S,20),currentPhase:y,currentTask:b,progress:{phasesTotal:h.length,phasesCompleted:h.filter(p=>p.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(p=>p.status==="completed").length,blocked:h.filter(p=>p.status==="blocked").length+g.filter(p=>p.status==="blocked").length},lastSession:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},E=bt(t.rootPath,".toolnet","work");return ns(E,{recursive:!0}),I(bt(E,"current.json"),j),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(j,null,2)+`
17
- `,"application/json"),j}async function le(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}}function ds(t,e){if(!as(t))return{events:[],nextOffset:e};let n=ls(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=cs(t,"r");try{us(i,o,0,s,r)}finally{is(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
18
- `);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
19
- `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var de=class{constructor(e){this.options=e;this.journal=new ce(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=ds(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=ae(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ue(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as vs,existsSync as xs,openSync as bs,readSync as ws,statSync as js}from"node:fs";var ps=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function W(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ne(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))Ne(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(ps.has(r)||["data","payload","parts","messages"].includes(r))&&Ne(s,e,n+1)}}function O(t,e,n,r,s,o=.95){let i=W(r);return{version:1,id:k([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 T(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 W(t.slice(r.length+1))}return null}function fs(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function ms(t){return W(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function jt(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=[];Ne(o.data,i);for(let c of i){let u={type:"project"},a=null;for(let f of c.split(/\r?\n/u)){let l=W(f);if(!l){a=null;continue}let m=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let v=Number(m[1]);u={type:"phase",key:`phase:${v}`,order:v,title:W(m[2]??"")},a=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let v=Number(d[1]);u={type:"task",key:`task:${v}`,order:v,title:W(d[2]??"")},a=null;continue}let S=T(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(O(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let h=T(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(O(t,o,u.type==="phase"?"phase_objective":"objective",h,u,.98)),a=null;continue}let g=T(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(O(t,o,u.type==="phase"?"phase_why":"why",g,u,.98)),a=null;continue}let y=T(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(y){s(O(t,o,"desired_outcome",y,{type:"project"},.98)),a=null;continue}let b=T(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(O(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let C=T(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(C){s(O(t,o,"phase_deliverable",C,u,.97)),a=null;continue}let A=T(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(A){s(O(t,o,"acceptance_criterion",A,u,.98)),a="acceptance_criterion";continue}let j=T(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(j){s(O(t,o,"dependency",j,u,.97)),a="dependency";continue}let E=T(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(E){s(O(t,o,"open_question",E,u,.95)),a="open_question";continue}let p=T(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(p){s(O(t,o,"constraint",p,u,.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&&fs(f)){s(O(t,o,a,ms(f),u,.96));continue}a=null}}}return n}function It(t){return String(t).padStart(12,"0")}var pe=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.evidence.sequence)),s=Math.max(...n.map(u=>u.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=k(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${It(r)}-${It(s)}-${i}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,JSON.stringify(o,null,2)+`
20
- `,"application/json"),c}};import{mkdirSync as gs}from"node:fs";import{join as Pt}from"node:path";function hs(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function ys(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 M(t,e){return ys(e,t)?e:t}function R(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 Ss(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,c)=>i.key.localeCompare(c.key))){let i=await e.getText(o.key);if(i)try{let c=JSON.parse(i);c.version===1&&Array.isArray(c.observations)&&s.push(c)}catch{}}return s}function ks(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function Ot(t,e){let r=(await Ss(t,e)).flatMap(h=>h.observations).sort((h,g)=>{let y=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return y!==0?y:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),s,o,i,c,u,a=new Map,f=[],l=[],m=[];for(let h of r){let g=hs(h);if(h.scope==="phase"&&h.scopeKey){let y=a.get(h.scopeKey)??ks(h);switch(h.kind){case"phase_objective":y.objective=M(y.objective,g);break;case"phase_why":y.why=M(y.why,g);break;case"phase_deliverable":y.deliverable=M(y.deliverable,g);break;case"acceptance_criterion":y.acceptanceCriteria.push(g);break;case"dependency":y.dependencies.push(g);break;case"open_question":y.openQuestions.push(g);break;case"constraint":y.constraints.push(g);break;case"note":y.notes.push(g);break}a.set(y.key,y);continue}switch(h.kind){case"mission":s=M(s,g);break;case"objective":o=M(o,g);break;case"why":i=M(i,g);break;case"desired_outcome":c=M(c,g);break;case"plan_rationale":u=M(u,g);break;case"open_question":f.push(g);break;case"constraint":l.push(g);break;case"note":m.push(g);break}}for(let h of a.values())h.acceptanceCriteria=R(h.acceptanceCriteria,20),h.dependencies=R(h.dependencies,15),h.openQuestions=R(h.openQuestions,15),h.constraints=R(h.constraints,15),h.notes=R(h.notes,20);let d={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:c,planRationale:u,phases:Array.from(a.values()).sort((h,g)=>h.order-g.order),openQuestions:R(f,20),constraints:R(l,20),notes:R(m,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=Pt(t.rootPath,".toolnet","work");return gs(S,{recursive:!0}),I(Pt(S,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
21
- `,"application/json"),d}async function Et(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 Is(t,e){if(!xs(t))return{events:[],nextOffset:e};let n=js(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=bs(t,"r");try{ws(o,s,0,s.length,r)}finally{vs(o)}let i=s.toString("utf8"),c=i.lastIndexOf(`
22
- `);if(c<0)return{events:[],nextOffset:r};let u=i.slice(0,c+1);return{events:u.split(`
23
- `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var fe=class{constructor(e){this.options=e;this.journal=new pe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Is(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=jt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Ot(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{mkdirSync as _s}from"node:fs";import{join as _e}from"node:path";import{existsSync as At,mkdirSync as Ps,readFileSync as Os,statSync as Tt,writeFileSync as Es}from"node:fs";import{dirname as Ts,join as Cs}from"node:path";var Ct=64*1024,As=`# ToolNet Project Operating Manual
11
+ `,u=Ne(this.eventsFile,"a",384);try{Rr(u,i,null,"utf8"),Er(u)}finally{Re(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 f=Array.from(r).slice(-$r);return this.saveStateUnsafe({...n,status:a,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:f}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Mr(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=ft(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=Ne(this.eventsFile,"r");try{Ar(i,o,0,s,r)}finally{Re(i)}return{events:o.toString("utf8").split(`
12
+ `).filter(Boolean).map(a=>JSON.parse(a)),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 ds,existsSync as ps,openSync as fs,readSync as ms,statSync as gs}from"node:fs";function mt(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 St=[/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],Lr=[/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],Wr=[/\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],Dr=[/\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],Kr=[/đã 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],gt=[/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],zr=[/\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],Br=[/đườ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],qr=[/\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],ht=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Jr=new Set(["payload","data","content","message","messages","parts","summary"]);function P(t,e){return e.some(n=>n.test(t))}function kt(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Hr(t){return kt(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Vr(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 $e(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||ht.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))$e(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(ht.has(s)||Jr.has(s))&&$e(o,s,n,r+1)}}function Ur(t){let e=[];$e(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=kt(o);if(Vr(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function yt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Yr(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&&P(t,St)?{kind:"rule",confidence:.98}:r&&P(t,Lr)?{kind:"rule",confidence:.92}:P(t,Wr)?{kind:P(t,gt)?"architecture":"decision",confidence:r?.93:.86}:r&&P(t,Dr)?{kind:"todo",confidence:.87}:P(t,gt)&&P(t,zr)?{kind:"architecture",confidence:r?.88:.82}:s&&P(t,Kr)?{kind:"fix",confidence:.8}:r&&P(t,Br)&&P(t,qr)?{kind:"context",confidence:.79}:null}function Gr(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Qr(t,e,n){return t==="rule"&&P(n,St)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":mt(e,n)}function vt(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,u=yt(o);i&&u&&s.set(i,u)}for(let o of e){let i=yt(o),u=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&u&&(i=s.get(u)??"");for(let c of Ur(o)){let a=Yr(c,i,o);if(!a||a.confidence<.75)continue;let f=Gr(a.kind),l=Hr(c),m=k([t.projectId,a.kind,l].join("|"));if(r.has(m))continue;r.add(m);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:f,content:c,confidence:a.confidence,importance:Qr(a.kind,f,c),tags:[f],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function ie(t){return t?Math.ceil(t.length/3.5):0}function ae(t,e){if(!t)return"";if(ie(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
13
+ `),u=Math.max(o,i);return u>r*.7?s.slice(0,u+1):s}function $(){let t=X(),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),u=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:u,archiveRemote:c}}function bt(t){return(t||$()).rawTranscript}function xt(t){return(t||$()).durableMemoryMaxItemsPerSession}function wt(t){return(t||$()).sessionSummaryMaxTokens}function jt(t){return(t||$()).archiveRemote}function Xr(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 Zr(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 es(t,e){let n=[],r=new Set;for(let i of t){let u=i.split(`
14
+ `).filter(c=>c.trim());for(let c of u){let a=c.trim();if(a.length<15)continue;let f=a.toLowerCase().replace(/\s+/g," ");if(r.has(f))continue;r.add(f);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=Zr(a,l);if(m<.3)continue;let d=Xr(a);n.push({category:l,text:d,importance:m,sourceSessionId:e})}}let s=$(),o=xt(s);return n.sort((i,u)=>u.importance-i.importance).slice(0,o)}function ts(t){let e=$(),n=wt(e),o=t.join(`
15
+
16
+ `).split(`
17
+ `).filter(i=>{let u=i.trim();return u.length>20&&!u.startsWith("npm")&&!u.startsWith("\u2713")&&!u.startsWith("Error:")}).slice(0,20).join(`
18
+ `);return ae(o,n)}function ce(t,e){let r=(Array.isArray(t)?t:t.split(`
19
+
20
+ `).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=es(r,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),f=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(r),decisions:o,projectRules:i,filesChanged:u,bugsFixed:c,commands:l,blockers:a,nextActions:f,durableFacts:s}}function R(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 ns(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 rs(t){switch(t){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function ss(t){let e=rs(t.importance);return Math.max(0,Math.min(1,e*.75+t.confidence*.25))}function os(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 is(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 as(t){let e=os(t),n=ss(t),r=is(t.content);return{...t,knowledgeClass:e,importanceScore:n,retrievalTerms:r,tags:R([...t.tags,`class:${e}`,`kind:${t.kind}`])}}function cs(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 us(t,e,n){let r=ce(cs(e),t.nativeSessionId),s=n.filter(a=>a.kind==="todo").map(a=>a.content),o=n.flatMap(a=>a.provenance.sourcePaths),i=n.filter(a=>a.kind==="architecture").map(a=>a.content),u=R([...s,...r.nextActions]),c=R([...r.nextActions,...s]);return{summary:r.summary,state:{task:c[0]??u[0],decisions:R(r.decisions),files:R([...r.filesChanged,...o]),todos:u,completed:R(r.bugsFixed),blockers:R(r.blockers),nextActions:c,architecture:R(i)}}}function It(t,e){let n=ns(e),r=vt(t,n).map(as),s=r.filter(a=>a.knowledgeClass!=="transient").sort((a,f)=>f.importanceScore-a.importanceScore),{summary:o,state:i}=us(t,n,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=>r.filter(f=>f.knowledgeClass===a).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:u,stats:{inputEvents:e.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:s.length,permanent:c("permanent"),task:c("task"),session:c("session"),transient:c("transient")}}}function Pt(t){return String(t).padStart(12,"0")}function ls(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var ue=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(f=>f.sequence)),o=Math.max(...n.map(f=>f.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},u=JSON.stringify(i,null,2)+`
21
+ `,c=k(r.map(f=>f.fingerprint).sort().join("|")).slice(0,16),a=[ls(e),"batches",`${Pt(s)}-${Pt(o)}-${c}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,u,"application/json"),a}};function hs(t,e){if(!ps(t))return{events:[],nextOffset:e};let n=gs(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=fs(t,"r");try{ms(i,o,0,s,r)}finally{ds(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
22
+ `);if(c<0)return{events:[],nextOffset:r};let a=u.slice(0,c+1);return{events:a.split(`
23
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var le=class{constructor(e){this.options=e;this.journal=new ue(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=hs(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=It(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}}};import{closeSync as ws,existsSync as js,openSync as Is,readSync as Ps,statSync as Cs}from"node:fs";var ys=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function W(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ot(t){return W(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function L(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))L(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(ys.has(r)||["data","payload","parts","messages"].includes(r))&&L(s,e,n+1)}}function de(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 Ct(t){let e=W(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,n,r,s={}){let o=W(r),i=s.key??Ot(o);return{version:1,id:k([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 Ss(t,e,n){let r=W(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(w(t,e,"goal",i[1],{confidence:.97}));let u=r.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(r));){let m=Number(a[1]),d=W(a[2]??""),S=d&&!Ct(d)?`Phase ${m} - ${d}`:`Phase ${m}`;s.push(w(t,e,"phase",S,{key:`phase:${m}`,order:m,status:de(r),confidence:.93}))}let f=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);f?.[2]&&s.push(w(t,e,"task",f[2],{status:f[1].trim()?"completed":de(f[2]),confidence:.96}));let l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let m=l[1]?Number(l[1]):void 0,d=W(l[2]),S=Ct(d);s.push(w(t,e,"task",S&&m!==void 0?`TODO ${m}`:d,{key:m!==void 0?`task:${m}`:Ot(d),order:m,status:de(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 m=r.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(r)&&s.push(w(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(w(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(w(t,e,"decision",r,{confidence:.9})),s}function pe(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=[];L(i.data,c);for(let a of c)s(w(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let c=[];L(i.data,c);for(let a of c)s(w(t,i,"task",a,{status:de(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=[];L(i.data,c);for(let a of c)s(w(t,i,"test",a,{confidence:1}))}let u=[];L(i.data,u);for(let c of u)for(let a of c.split(/\n+/u))for(let f of Ss(t,i,a))s(f)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function Mt(t){return String(t).padStart(12,"0")}var fe=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.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)+`
24
+ `,u=k(n.map(a=>a.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Mt(r)}-${Mt(s)}-${u}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Et}from"node:path";import{mkdirSync as ks}from"node:fs";function vs(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function D(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=vs(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function bs(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 Tt(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&&bs(e)?t.title:e.text;return{id:t?.id??k(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 xs(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,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 me(t,e){let r=(await xs(t,e)).flatMap(p=>p.observations).sort((p,v)=>{let B=p.occurredAt.localeCompare(v.occurredAt);if(B!==0)return B;let Ue=p.sequence-v.sequence;return Ue!==0?Ue:p.id.localeCompare(v.id)}),s=new Map,o=new Map,i,u,c,a=[],f=[],l=[],m=[],d=[],S=[];for(let p of r)switch(p.kind){case"goal":i=p.text;break;case"plan":u=p.text;break;case"phase":s.set(p.key,Tt(s.get(p.key),p));break;case"task":o.set(p.key,Tt(o.get(p.key),p));break;case"decision":a.push(p.text);break;case"blocker":f.push(p.text);break;case"warning":l.push(p.text);break;case"next_action":m.push(p.text);break;case"file":d.push(p.text);break;case"test":S.push(p.text);break;case"session":c={agent:p.agent,nativeSessionId:p.nativeSessionId,sessionKey:p.sessionKey,updatedAt:p.occurredAt};break}let y=Array.from(s.values()).sort((p,v)=>(p.order??Number.MAX_SAFE_INTEGER)-(v.order??Number.MAX_SAFE_INTEGER)),h=Array.from(o.values()).sort((p,v)=>(p.order??Number.MAX_SAFE_INTEGER)-(v.order??Number.MAX_SAFE_INTEGER)),g=y.find(p=>p.status==="in_progress")??y.find(p=>p.status==="blocked")??y.find(p=>p.status==="pending"),x=h.find(p=>p.status==="in_progress")??h.find(p=>p.status==="blocked")??h.find(p=>p.status==="pending"),T=D([...m,...x?[x.title]:[],...!x&&g?[g.title]:[],...h.filter(p=>p.status==="pending").slice(0,5).map(p=>p.title)],8),A=D([...f,...y.filter(p=>p.status==="blocked").map(p=>p.title),...h.filter(p=>p.status==="blocked").map(p=>p.title)],20),j={version:1,projectId:t.id,projectName:t.name,goal:i,plan:u,phases:y,tasks:h,decisions:D(a,20),blockers:A,warnings:D(l,20),nextActions:T,filesTouched:D(d,30),tests:D(S,20),currentPhase:g,currentTask:x,progress:{phasesTotal:y.length,phasesCompleted:y.filter(p=>p.status==="completed").length,tasksTotal:h.length,tasksCompleted:h.filter(p=>p.status==="completed").length,blocked:y.filter(p=>p.status==="blocked").length+h.filter(p=>p.status==="blocked").length},lastSession:c,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},M=Et(t.rootPath,".toolnet","work");return ks(M,{recursive:!0}),I(Et(M,"current.json"),j),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(j,null,2)+`
25
+ `,"application/json"),j}async function ge(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}}function Os(t,e){if(!js(t))return{events:[],nextOffset:e};let n=Cs(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=Is(t,"r");try{Ps(i,o,0,s,r)}finally{ws(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
26
+ `);if(c<0)return{events:[],nextOffset:r};let a=u.slice(0,c+1);return{events:a.split(`
27
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var he=class{constructor(e){this.options=e;this.journal=new fe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Os(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=pe(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await me(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as Fs,existsSync as Ls,openSync as Ws,readSync as Ds,statSync as Ks}from"node:fs";var Ms=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function K(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Fe(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))Fe(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Ms.has(r)||["data","payload","parts","messages"].includes(r))&&Fe(s,e,n+1)}}function C(t,e,n,r,s,o=.95){let i=K(r);return{version:1,id:k([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 E(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 K(t.slice(r.length+1))}return null}function Es(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Ts(t){return K(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function At(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=[];Fe(o.data,i);for(let u of i){let c={type:"project"},a=null;for(let f of u.split(/\r?\n/u)){let l=K(f);if(!l){a=null;continue}let m=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let v=Number(m[1]);c={type:"phase",key:`phase:${v}`,order:v,title:K(m[2]??"")},a=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let v=Number(d[1]);c={type:"task",key:`task:${v}`,order:v,title:K(d[2]??"")},a=null;continue}let S=E(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(C(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let y=E(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(y){s(C(t,o,c.type==="phase"?"phase_objective":"objective",y,c,.98)),a=null;continue}let h=E(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(h){s(C(t,o,c.type==="phase"?"phase_why":"why",h,c,.98)),a=null;continue}let g=E(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(C(t,o,"desired_outcome",g,{type:"project"},.98)),a=null;continue}let x=E(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(x){s(C(t,o,"plan_rationale",x,{type:"project"},.98)),a=null;continue}let T=E(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(T){s(C(t,o,"phase_deliverable",T,c,.97)),a=null;continue}let A=E(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(A){s(C(t,o,"acceptance_criterion",A,c,.98)),a="acceptance_criterion";continue}let j=E(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(j){s(C(t,o,"dependency",j,c,.97)),a="dependency";continue}let M=E(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(M){s(C(t,o,"open_question",M,c,.95)),a="open_question";continue}let p=E(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(p){s(C(t,o,"constraint",p,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&&Es(f)){s(C(t,o,a,Ts(f),c,.96));continue}a=null}}}return n}function Rt(t){return String(t).padStart(12,"0")}var ye=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=k(n.map(c=>c.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${Rt(r)}-${Rt(s)}-${i}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,JSON.stringify(o,null,2)+`
28
+ `,"application/json"),u}};import{mkdirSync as As}from"node:fs";import{join as Nt}from"node:path";function Rs(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Ns(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 N(t,e){return Ns(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 _s(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,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 $s(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function _t(t,e){let r=(await _s(t,e)).flatMap(y=>y.observations).sort((y,h)=>{let g=y.evidence.occurredAt.localeCompare(h.evidence.occurredAt);return g!==0?g:y.evidence.sessionKey===h.evidence.sessionKey?y.evidence.sequence-h.evidence.sequence:y.id.localeCompare(h.id)}),s,o,i,u,c,a=new Map,f=[],l=[],m=[];for(let y of r){let h=Rs(y);if(y.scope==="phase"&&y.scopeKey){let g=a.get(y.scopeKey)??$s(y);switch(y.kind){case"phase_objective":g.objective=N(g.objective,h);break;case"phase_why":g.why=N(g.why,h);break;case"phase_deliverable":g.deliverable=N(g.deliverable,h);break;case"acceptance_criterion":g.acceptanceCriteria.push(h);break;case"dependency":g.dependencies.push(h);break;case"open_question":g.openQuestions.push(h);break;case"constraint":g.constraints.push(h);break;case"note":g.notes.push(h);break}a.set(g.key,g);continue}switch(y.kind){case"mission":s=N(s,h);break;case"objective":o=N(o,h);break;case"why":i=N(i,h);break;case"desired_outcome":u=N(u,h);break;case"plan_rationale":c=N(c,h);break;case"open_question":f.push(h);break;case"constraint":l.push(h);break;case"note":m.push(h);break}}for(let y of a.values())y.acceptanceCriteria=_(y.acceptanceCriteria,20),y.dependencies=_(y.dependencies,15),y.openQuestions=_(y.openQuestions,15),y.constraints=_(y.constraints,15),y.notes=_(y.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((y,h)=>y.order-h.order),openQuestions:_(f,20),constraints:_(l,20),notes:_(m,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=Nt(t.rootPath,".toolnet","work");return As(S,{recursive:!0}),I(Nt(S,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
29
+ `,"application/json"),d}async function $t(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 zs(t,e){if(!Ls(t))return{events:[],nextOffset:e};let n=Ks(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=Ws(t,"r");try{Ds(o,s,0,s.length,r)}finally{Fs(o)}let i=s.toString("utf8"),u=i.lastIndexOf(`
30
+ `);if(u<0)return{events:[],nextOffset:r};let c=i.slice(0,u+1);return{events:c.split(`
31
+ `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var Se=class{constructor(e){this.options=e;this.journal=new ye(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=zs(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=At(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await _t(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{mkdirSync as eo}from"node:fs";import{join as Le}from"node:path";import{existsSync as Wt,mkdirSync as Bs,readFileSync as qs,statSync as Ft,writeFileSync as Js}from"node:fs";import{dirname as Hs,join as Vs}from"node:path";var Lt=64*1024,Us=`# ToolNet Project Operating Manual
24
32
 
25
33
  This file contains persistent instructions for AI agents working on this project.
26
34
 
@@ -63,58 +71,51 @@ Things an AI agent should always remember.
63
71
  <!--
64
72
  - [advisory] Prefer small focused files.
65
73
  -->
66
- `;function me(t){return Cs(t.rootPath,".toolnet","PROJECT.md")}function Ms(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=Ms(s[2]);if(!i)continue;let c=`${o}:${i.toLowerCase()}`;n.has(c)||(n.add(c),e.push({id:k(c).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Ns(t){let e=me(t);return At(e)||(Ps(Ts(e),{recursive:!0}),Es(e,As,{encoding:"utf8",mode:384})),e}function ge(t,e=!1){let n=e?Ns(t):me(t);if(!At(n))return null;if(Tt(n).size>Ct)throw new Error(`PROJECT.md exceeds ${Ct} bytes`);let s=Os(n,"utf8");return{path:n,content:s,digest:k(s),rules:Rs(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Tt(n).mtimeMs).toISOString()}}function $s(t){return{goal:t.goal,plan:t.plan,phases:t.phases.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),tasks:t.tasks.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),decisions:t.decisions,blockers:t.blockers,warnings:t.warnings,nextActions:t.nextActions,filesTouched:t.filesTouched,tests:t.tests}}function Fs(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 he=class{constructor(e){this.options=e}options;async capture(e,n){let r=await le(this.options.project,this.options.storage);if(r||(r=await ue(this.options.project,this.options.storage)),!Fs(r))return null;let s=ge(this.options.project,!1),o=s?s.rules.filter(m=>m.mode==="enforce").map(m=>m.text):[],i=k(JSON.stringify($s(r))),c=k([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),u=new Date().toISOString(),a={version:1,id:c,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:u,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:[...o,...r.warnings].slice(0,20),filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:i},f=`projects/${this.options.project.id}/work/handoffs/${c}.json`;await this.options.storage.exists(f)||await this.options.storage.put(f,JSON.stringify(a,null,2)+`
67
- `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(a,null,2)+`
68
- `,"application/json");let l=_e(this.options.project.rootPath,".toolnet","work","handoffs");return _s(l,{recursive:!0}),I(_e(l,`${c}.json`),a),I(_e(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};async function Mt(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}}var ye=class{identity;wal;remote;sanitizer=new q;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=at(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new re(this.identity),this.remote=new ne(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new oe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new de({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new fe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new he({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 Ls,readFileSync as Ws,readdirSync as Ds,statSync as Rt}from"node:fs";import{homedir as Ks}from"node:os";import{join as Se,resolve as Nt}from"node:path";function _t(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function Bs(){return process.env.CODEX_HOME??Se(Ks(),".codex")}function U(t){let e="";try{e=Ws(t,"utf8").slice(0,128*1024)}catch{return{raw:{}}}for(let n of e.split(`
69
- `))if(n)try{let r=_t(JSON.parse(n));if(r.type!=="session_meta")continue;let s=_t(r.payload),o=[s.id,s.thread_id,s.threadId,s.session_id,s.sessionId].find(c=>typeof c=="string"),i=typeof s.cwd=="string"?s.cwd:void 0;return{threadId:o,cwd:i,raw:s}}catch{}return{raw:{}}}function $e(t,e){if(!Ls(t))return;let n;try{n=Ds(t,{withFileTypes:!0})}catch{return}for(let r of n){let s=Se(t,r.name);if(r.isDirectory()){$e(s,e);continue}r.isFile()&&r.name.endsWith(".jsonl")&&e.push(s)}}function Fe(){let t=Bs(),e=[];return $e(Se(t,"sessions"),e),$e(Se(t,"archived_sessions"),e),e.sort((n,r)=>{try{return Rt(r).mtimeMs-Rt(n).mtimeMs}catch{return 0}})}function Le(t){let e=Fe(),n=e.find(r=>r.includes(t));if(n)return n;for(let r of e)if(U(r).threadId===t)return r;return null}function ke(t,e){let n=Nt(t),r=Nt(e);return r===n||r.startsWith(n+"/")||n.startsWith(r+"/")}import{closeSync as zs,existsSync as Js,openSync as qs,readSync as Hs,statSync as Vs}from"node:fs";function $t(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function Us(t){let e=t.timestamp;if(typeof e=="string"){let n=new Date(e);if(!Number.isNaN(n.getTime()))return n.toISOString()}return new Date().toISOString()}function Ys(t){let e=typeof t.type=="string"?t.type.toLowerCase():"",n=$t(t.payload),r=typeof n.type=="string"?n.type.toLowerCase():"",s=typeof n.role=="string"?n.role.toLowerCase():void 0;return e==="session_meta"?{type:"custom"}:s==="user"||r==="user_message"?{type:"user_prompt",role:"user"}:s==="assistant"||r==="agent_message"||r==="assistant_message"?{type:"assistant_message",role:"assistant"}:r.includes("function_call")||r.includes("tool_call")||r.includes("exec_command_begin")||r.includes("exec_command_start")?{type:"tool_call"}:r.includes("function_call_output")||r.includes("tool_result")||r.includes("exec_command_end")||r.includes("exec_command_complete")?{type:"tool_result"}:r.includes("error")?{type:"error"}:e.includes("compacted")||r.includes("compacted")?{type:"session_compact"}:{type:"custom",role:s}}function Ft(t,e=0){if(!Js(t))return{events:[],nextOffset:e,reset:!1};let n=Vs(t).size,r=e>n,s=r?0:e;if(s>=n)return{events:[],nextOffset:n,reset:r};let o=n-s,i=Buffer.alloc(o),c=qs(t,"r");try{Hs(c,i,0,o,s)}finally{zs(c)}let u=i.toString("utf8"),a=u.lastIndexOf(`
70
- `);if(a<0)return{events:[],nextOffset:s,reset:r};let f=u.slice(0,a+1),l=0,m=[];for(let d of f.split(`
74
+ `;function ke(t){return Vs(t.rootPath,".toolnet","PROJECT.md")}function Ys(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Gs(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=Ys(s[2]);if(!i)continue;let u=`${o}:${i.toLowerCase()}`;n.has(u)||(n.add(u),e.push({id:k(u).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Qs(t){let e=ke(t);return Wt(e)||(Bs(Hs(e),{recursive:!0}),Js(e,Us,{encoding:"utf8",mode:384})),e}function ve(t,e=!1){let n=e?Qs(t):ke(t);if(!Wt(n))return null;if(Ft(n).size>Lt)throw new Error(`PROJECT.md exceeds ${Lt} bytes`);let s=qs(n,"utf8");return{path:n,content:s,digest:k(s),rules:Gs(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Ft(n).mtimeMs).toISOString()}}function O(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 Dt(t){if(t)return{id:t.id,title:t.title,status:t.status}}function Xs(t){let e=t.slice(-10).join(`
75
+ `).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(e)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(e)?"passing":"unknown"}function Zs(t){return k(JSON.stringify(t))}function Kt(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),u=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),a=O(r.nextActions,10),f=O([...c,...a],15),l=O(r.tests.slice().reverse(),10),m=O(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:Dt(r.currentPhase),task:Dt(r.currentTask),file:s},completed:{phases:O(o,20),tasks:O(i,30)},remaining:{phases:O(u,20),tasks:O(c,30),todos:f},nextAction:a[0],blockers:O(r.blockers.slice().reverse(),10),decisions:O(r.decisions.slice().reverse(),10),files:{current:s,recent:m},tests:{status:Xs(r.tests),recent:l},attention:O(t.attention??[],20),progress:r.progress},{capturedAt:S,source:y,...h}=d;return{...d,stateDigest:Zs(h)}}function to(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 be=class{constructor(e){this.options=e}options;async capture(e,n){let r=await ge(this.options.project,this.options.storage);if(r||(r=await me(this.options.project,this.options.storage)),!to(r))return null;let s=ve(this.options.project,!1),i=[...s?s.rules.filter(S=>S.mode==="enforce").map(S=>S.text):[],...r.warnings].slice(0,20),u=Kt({project:this.options.project,identity:this.options.identity,state:r,reason:e,sequence:n,attention:i}),c=u.stateDigest,a=k([this.options.project.id,this.options.identity.sessionKey,c].join("|")).slice(0,24),f=new Date().toISOString(),l={version:1,id:a,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:f,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(S=>S.status!=="completed"&&S.status!=="cancelled"),incompleteTasks:r.tasks.filter(S=>S.status!=="completed"&&S.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: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)+`
76
+ `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(l,null,2)+`
77
+ `,"application/json");let d=Le(this.options.project.rootPath,".toolnet","work","handoffs");return eo(d,{recursive:!0}),I(Le(d,`${a}.json`),l),I(Le(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),l),l}};async function zt(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}}var xe=class{identity;wal;remote;sanitizer=new V;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=lt(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 se(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new le({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new he({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new Se({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new be({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 no,readFileSync as ro,readdirSync as so,statSync as Bt}from"node:fs";import{homedir as oo}from"node:os";import{join as we,resolve as qt}from"node:path";function Jt(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function io(){return process.env.CODEX_HOME??we(oo(),".codex")}function G(t){let e="";try{e=ro(t,"utf8").slice(0,128*1024)}catch{return{raw:{}}}for(let n of e.split(`
78
+ `))if(n)try{let r=Jt(JSON.parse(n));if(r.type!=="session_meta")continue;let s=Jt(r.payload),o=[s.id,s.thread_id,s.threadId,s.session_id,s.sessionId].find(u=>typeof u=="string"),i=typeof s.cwd=="string"?s.cwd:void 0;return{threadId:o,cwd:i,raw:s}}catch{}return{raw:{}}}function We(t,e){if(!no(t))return;let n;try{n=so(t,{withFileTypes:!0})}catch{return}for(let r of n){let s=we(t,r.name);if(r.isDirectory()){We(s,e);continue}r.isFile()&&r.name.endsWith(".jsonl")&&e.push(s)}}function De(){let t=io(),e=[];return We(we(t,"sessions"),e),We(we(t,"archived_sessions"),e),e.sort((n,r)=>{try{return Bt(r).mtimeMs-Bt(n).mtimeMs}catch{return 0}})}function Ke(t){let e=De(),n=e.find(r=>r.includes(t));if(n)return n;for(let r of e)if(G(r).threadId===t)return r;return null}function je(t,e){let n=qt(t),r=qt(e);return r===n||r.startsWith(n+"/")||n.startsWith(r+"/")}import{closeSync as ao,existsSync as co,openSync as uo,readSync as lo,statSync as po}from"node:fs";function Ht(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function fo(t){let e=t.timestamp;if(typeof e=="string"){let n=new Date(e);if(!Number.isNaN(n.getTime()))return n.toISOString()}return new Date().toISOString()}function mo(t){let e=typeof t.type=="string"?t.type.toLowerCase():"",n=Ht(t.payload),r=typeof n.type=="string"?n.type.toLowerCase():"",s=typeof n.role=="string"?n.role.toLowerCase():void 0;return e==="session_meta"?{type:"custom"}:s==="user"||r==="user_message"?{type:"user_prompt",role:"user"}:s==="assistant"||r==="agent_message"||r==="assistant_message"?{type:"assistant_message",role:"assistant"}:r.includes("function_call")||r.includes("tool_call")||r.includes("exec_command_begin")||r.includes("exec_command_start")?{type:"tool_call"}:r.includes("function_call_output")||r.includes("tool_result")||r.includes("exec_command_end")||r.includes("exec_command_complete")?{type:"tool_result"}:r.includes("error")?{type:"error"}:e.includes("compacted")||r.includes("compacted")?{type:"session_compact"}:{type:"custom",role:s}}function Vt(t,e=0){if(!co(t))return{events:[],nextOffset:e,reset:!1};let n=po(t).size,r=e>n,s=r?0:e;if(s>=n)return{events:[],nextOffset:n,reset:r};let o=n-s,i=Buffer.alloc(o),u=uo(t,"r");try{lo(u,i,0,o,s)}finally{ao(u)}let c=i.toString("utf8"),a=c.lastIndexOf(`
79
+ `);if(a<0)return{events:[],nextOffset:s,reset:r};let f=c.slice(0,a+1),l=0,m=[];for(let d of f.split(`
71
80
  `)){if(!d)continue;let S=Buffer.byteLength(d+`
72
- `,"utf8"),h=s+l;l+=S;let g;try{g=JSON.parse(d)}catch{continue}let y=$t(g),b=Ys(y);m.push({type:b.type,timestamp:Us(y),role:b.role,sourceEventId:`rollout:${h}`,sourceSequence:h,data:y,provenance:{source:"codex-rollout",sourcePath:t,sourceOffset:h}})}return{events:m,nextOffset:s+Buffer.byteLength(f,"utf8"),reset:r}}var Gs=[/^<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*$/],Xs=[/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],Qs=["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 Zs(t){let e=t.toLowerCase();return Qs.some(n=>e.includes(n))}function eo(t){if(!t.trim())return!0;for(let e of Gs)if(e.test(t))return!0;return Zs(t),!1}function to(t){let e=t;for(let n of Xs)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function We(t){let e=t.trim();return e?eo(e)?{content:"",filtered:!0,reason:"noise"}:{content:to(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function ve(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=We(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=ve(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=We(s);return o.filtered?null:o.content}return s&&typeof s=="object"?ve(s):s}).filter(s=>s!==null):e[n]=r;return e}function Lt(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&&We(r).filtered)return!0}return!1}function xe(t){return t?Math.ceil(t.length/3.5):0}function be(t,e){if(!t)return"";if(xe(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
73
- `),c=Math.max(o,i);return c>r*.7?s.slice(0,c+1):s}function N(){let t=G(),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),c=n,u=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:c,archiveRemote:u}}function Wt(t){return(t||N()).rawTranscript}function Dt(t){return(t||N()).durableMemoryMaxItemsPerSession}function Kt(t){return(t||N()).sessionSummaryMaxTokens}function Bt(t){return(t||N()).archiveRemote}function no(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 ro(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 so(t,e){let n=[],r=new Set;for(let i of t){let c=i.split(`
74
- `).filter(u=>u.trim());for(let u of c){let a=u.trim();if(a.length<15)continue;let f=a.toLowerCase().replace(/\s+/g," ");if(r.has(f))continue;r.add(f);let 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=ro(a,l);if(m<.3)continue;let d=no(a);n.push({category:l,text:d,importance:m,sourceSessionId:e})}}let s=N(),o=Dt(s);return n.sort((i,c)=>c.importance-i.importance).slice(0,o)}function oo(t){let e=N(),n=Kt(e),o=t.join(`
75
-
76
- `).split(`
77
- `).filter(i=>{let c=i.trim();return c.length>20&&!c.startsWith("npm")&&!c.startsWith("\u2713")&&!c.startsWith("Error:")}).slice(0,20).join(`
78
- `);return be(o,n)}function zt(t,e){let r=(Array.isArray(t)?t:t.split(`
79
-
80
- `).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=so(r,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),c=s.filter(d=>d.category==="file").map(d=>d.text),u=s.filter(d=>d.category==="fix").map(d=>d.text),a=s.filter(d=>d.category==="blocker").map(d=>d.text),f=s.filter(d=>d.category==="next_action").map(d=>d.text),l=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:oo(r),decisions:o,projectRules:i,filesChanged:c,bugsFixed:u,commands:l,blockers:a,nextActions:f,durableFacts:s}}import{existsSync as io,mkdirSync as ao,readFileSync as co,renameSync as uo,writeFileSync as lo}from"node:fs";import{dirname as po,join as fo}from"node:path";function mo(t,e){ao(po(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;lo(n,`${JSON.stringify(e,null,2)}
81
- `,{encoding:"utf8",mode:384}),uo(n,t)}function Yt(t){return fo(t.rootPath,".toolnet","work","current.json")}function go(t){let e=Yt(t);if(!io(e))return null;try{let n=JSON.parse(co(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function De(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function D(t,e,n){let r=[],s=new Set;for(let o of[...t,...e].reverse()){let i=De(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function ho(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 Jt(t,e){let n=e.status??t?.status??"pending",r=n;t?.status==="completed"&&n!=="completed"&&(r="completed"),t&&n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status);let s=t&&ho(e)?t.title:e.text;return{id:t?.id??e.id,title:s,status:r,order:e.order??t?.order,confidence:Math.max(t?.confidence??0,e.confidence),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}function qt(t){let e=new Map;for(let n of t){let r=n.order!==void 0?`order:${n.order}`:De(n.title);e.set(r,n)}return e}function Ht(t){return t.order!==void 0?`order:${t.order}`:De(t.key||t.text)}function Vt(t){return Array.from(t).sort((e,n)=>{let r=e.order??Number.MAX_SAFE_INTEGER,s=n.order??Number.MAX_SAFE_INTEGER;return r!==s?r-s:e.updatedAt.localeCompare(n.updatedAt)})}function Ut(t){return t.find(e=>e.status==="in_progress")??t.find(e=>e.status==="blocked")??t.find(e=>e.status==="pending")}function Gt(t,e){let n=go(t),r=qt(n?.phases??[]),s=qt(n?.tasks??[]),o=n?.goal,i=n?.plan,c=n?.lastSession,u=[],a=[],f=[],l=[],m=[],d=[],S=[...e].sort((p,v)=>{let K=p.occurredAt.localeCompare(v.occurredAt);return K!==0?K:p.sequence-v.sequence});for(let p of S)switch(p.kind){case"goal":o=p.text;break;case"plan":i=p.text;break;case"phase":{let v=Ht(p);r.set(v,Jt(r.get(v),p));break}case"task":{let v=Ht(p);s.set(v,Jt(s.get(v),p));break}case"decision":u.push(p.text);break;case"blocker":a.push(p.text);break;case"warning":f.push(p.text);break;case"next_action":l.push(p.text);break;case"file":m.push(p.text);break;case"test":d.push(p.text);break;case"session":c={agent:p.agent,nativeSessionId:p.nativeSessionId,sessionKey:p.sessionKey,updatedAt:p.occurredAt};break}let h=Vt(r.values()),g=Vt(s.values()),y=Ut(h),b=Ut(g),C=D(n?.nextActions??[],[...l,...b?[b.title]:[],...!b&&y?[y.title]:[],...g.filter(p=>p.status==="pending").slice(0,5).map(p=>p.title)],8),A=D(n?.blockers??[],[...a,...h.filter(p=>p.status==="blocked").map(p=>p.title),...g.filter(p=>p.status==="blocked").map(p=>p.title)],20),j=S.length>0?S[S.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),E={version:1,projectId:t.id,projectName:t.name,goal:o,plan:i,phases:h,tasks:g,decisions:D(n?.decisions??[],u,20),blockers:A,warnings:D(n?.warnings??[],f,20),nextActions:C,filesTouched:D(n?.filesTouched??[],m,30),tests:D(n?.tests??[],d,20),currentPhase:y,currentTask:b,progress:{phasesTotal:h.length,phasesCompleted:h.filter(p=>p.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(p=>p.status==="completed").length,blocked:h.filter(p=>p.status==="blocked").length+g.filter(p=>p.status==="blocked").length},lastSession:c,updatedAt:j};return mo(Yt(t),E),E}import{existsSync as yo,readFileSync as So,writeFileSync as ko}from"node:fs";import{join as vo}from"node:path";var Qt="<!-- TOOLNET:STABLE-WORK:BEGIN -->",Ke="<!-- TOOLNET:STABLE-WORK:END -->";function Be(t){switch(t.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function we(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${n}`)]:[]}function Xt(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${Be(n)} ${n.title}`)]:[]}function xo(t){let e=[Qt,"# ToolNet Stable Work State","",`Updated: ${t.updatedAt}`];return t.lastSession&&e.push(`Last agent: ${t.lastSession.agent}`,`Last session: ${t.lastSession.nativeSessionId}`),t.goal&&e.push("","Goal:",t.goal),t.plan&&e.push("","Plan:",t.plan),t.currentPhase&&e.push("","Current phase:",`${Be(t.currentPhase)} ${t.currentPhase.title}`),t.currentTask&&e.push("","Current task:",`${Be(t.currentTask)} ${t.currentTask.title}`),e.push(...Xt("Phases",t.phases)),e.push(...Xt("TODO / Tasks",t.tasks)),e.push(...we("Next actions",t.nextActions)),e.push(...we("Blockers",t.blockers)),e.push(...we("Important decisions",t.decisions)),e.push(...we("Files touched",t.filesTouched)),e.push("","Progress:",`- Phases: ${t.progress.phasesCompleted}/${t.progress.phasesTotal}`,`- Tasks: ${t.progress.tasksCompleted}/${t.progress.tasksTotal}`,`- Blocked: ${t.progress.blocked}`,"","Continuation:","- Resume current unfinished task.","- Never redo completed TODO/Phase unless explicitly requested.","- Ask ToolNet Memory for deeper history only when necessary.",Ke),e.join(`
82
- `)}function Zt(t,e){let n=vo(t.rootPath,".toolnet","current.md"),r="";if(yo(n))try{r=So(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let s=xo(e),o=r.indexOf(Qt),i=r.indexOf(Ke),c;o>=0&&i>=o?c=[r.slice(0,o).trimEnd(),s,r.slice(i+Ke.length).trimStart()].filter(Boolean).join(`
83
-
84
- `):c=r.trim()?`${r.trim()}
85
-
86
- ${s}`:s,ko(n,`${c.trim()}
87
- `,{encoding:"utf8",mode:384})}import{existsSync as bo,mkdirSync as wo,readFileSync as jo,renameSync as Io,writeFileSync as Po}from"node:fs";import{dirname as Oo,join as Eo}from"node:path";function en(t){return Eo(t.rootPath,".toolnet","context","session-origin.json")}function To(t,e){wo(Oo(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;Po(n,`${JSON.stringify(e,null,2)}
88
- `,{encoding:"utf8",mode:384}),Io(n,t)}function je(t,e){return[...t].filter(n=>n.kind===e).sort((n,r)=>{let s=n.occurredAt.localeCompare(r.occurredAt);return s!==0?s:n.sequence-r.sequence}).at(-1)}function tn(t,e){let n=je(e.observations,"file"),r=je(e.observations,"next_action"),s=je(e.observations,"blocker"),o=je(e.observations,"decision"),i={version:1,projectId:t.id,agent:e.agent,nativeSessionId:e.nativeSessionId,updatedAt:e.workState.updatedAt,currentTask:e.workState.currentTask?.title,currentPhase:e.workState.currentPhase?.title,lastTouchedFile:n?.text??e.workState.filesTouched.at(-1),latestNextAction:r?.text??e.workState.nextActions.at(-1),latestBlocker:s?.text??e.workState.blockers.at(-1),latestDecision:o?.text??e.workState.decisions.at(-1)};return To(en(t),i),i}function Co(t){let e=en(t);if(!bo(e))return null;try{let n=JSON.parse(jo(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function nn(t){let e=Co(t);if(!e)return null;let n=["Previous session:",`- Agent: ${e.agent}`,`- Session: ${e.nativeSessionId}`];return e.currentPhase&&n.push(`- Current phase: ${e.currentPhase}`),e.currentTask&&n.push(`- Current task: ${e.currentTask}`),e.lastTouchedFile&&n.push(`- Last touched file: ${e.lastTouchedFile}`),e.latestBlocker&&n.push(`- Blocker: ${e.latestBlocker}`),e.latestNextAction&&n.push(`- Next action: ${e.latestNextAction}`),e.latestDecision&&n.push(`- Important decision: ${e.latestDecision}`),n.join(`
89
- `)}async function Y(t){let e=t.threadId.trim();if(!e)throw new Error("Codex thread ID is required");let n=U(t.rolloutPath),r=t.cwd??n.cwd;if(r&&!ke(t.project.rootPath,r))throw new Error(`Codex thread does not belong to project: ${r}`);if(n.threadId&&n.threadId!==e)throw new Error(`Codex rollout thread mismatch: expected ${e}, got ${n.threadId}`);let s=new ye({project:t.project,storage:t.storage,agent:"codex",nativeSessionId:e,metadata:{source:"codex-rollout",rolloutPath:t.rolloutPath,cwd:r,client:t.client}}),o=s.status(),i=o.sourceCursors["codex.rollout.path"],c=Number(o.sourceCursors["codex.rollout.offset"]??0);i&&i!==t.rolloutPath&&(c=0),(!Number.isFinite(c)||c<0)&&(c=0);let u=Ft(t.rolloutPath,c),a=[];o.lastSequence===0&&a.push({type:"session_start",sourceEventId:`codex:${e}:start`,data:{threadId:e,cwd:r,rolloutPath:t.rolloutPath,sessionMeta:n.raw},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}}),i&&i!==t.rolloutPath&&a.push({type:"custom",sourceEventId:`codex:${e}:rollout-rotation:${t.rolloutPath}`,data:{event:"rollout_rotation",previousPath:i,rolloutPath:t.rolloutPath},provenance:{source:"codex-rollout"}}),u.reset&&a.push({type:"custom",sourceEventId:`codex:${e}:rollout-reset:${u.nextOffset}`,data:{event:"rollout_reset"},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}});let f=u.events.filter(d=>!Lt(d.data)).map(d=>({...d,data:ve(d.data)}));if(a.push(...f),t.idle&&f.length>0)try{let d={projectId:t.project.id,projectName:t.project.name,projectRoot:t.project.rootPath,agent:"codex",nativeSessionId:e,sessionKey:`codex:${e}`,remotePrefix:`projects/${t.project.id}/sessions/codex/${e}`,localDirectory:""},S=f.map((y,b)=>({version:1,id:`codex-work-${e}-${y.sourceSequence??b}`,sequence:b+1,projectId:t.project.id,agent:"codex",nativeSessionId:e,type:y.type,timestamp:y.timestamp??new Date().toISOString(),role:y.role,sourceEventId:y.sourceEventId,sourceSequence:y.sourceSequence,data:y.data??{},provenance:y.provenance??{}})),h=ae(d,S),g=Gt(t.project,h);Zt(t.project,g),tn(t.project,{agent:"codex",nativeSessionId:e,observations:h,workState:g})}catch{}t.idle&&t.turnId&&a.push({type:"session_idle",sourceEventId:`codex:${e}:turn:${t.turnId}:idle`,data:{turnId:t.turnId,client:t.client},provenance:{source:"codex-notify"}});let l=s.recordMany(a);if(s.setSourceCursor("codex.rollout.path",t.rolloutPath),s.setSourceCursor("codex.rollout.offset",u.nextOffset),t.turnId&&s.setSourceCursor("codex.last.turn",t.turnId),t.idle&&f.length>0)try{let d=f.map(h=>JSON.stringify(h.data)),S=zt(d,e);s.setSourceCursor("codex.session.summary",S.summary),s.setSourceCursor("codex.session.facts_count",S.durableFacts.length),Wt()&&!Bt()&&s.setSourceCursor("codex.raw_transcript.archived","local")}catch{}let m=await s.flush();return{threadId:e,imported:l.length,rolloutEvents:u.events.length,eventCount:m.eventCount,chunkCount:m.chunkCount,status:m.status,rolloutOffset:u.nextOffset,reset:u.reset}}import{existsSync as Ao}from"node:fs";import{dirname as Mo,join as Ro,parse as No,resolve as _o}from"node:path";function rn(t){let e=_o(t),n=No(e).root;for(;;){if(Ao(Ro(e,".toolnet","project.json")))return new _().detect(e);if(e===n)break;let r=Mo(e);if(r===e)break;e=r}return null}async function sn(t,e,n=100){let r=[];for(let s of Fe()){let o=U(s);if(!(!o.threadId||!o.cwd)&&ke(t.rootPath,o.cwd)&&(r.push(await Y({project:t,storage:e,threadId:o.threadId,rolloutPath:s,cwd:o.cwd})),r.length>=n))break}return r}import{existsSync as $o,mkdirSync as on,readFileSync as Fo,writeFileSync as an}from"node:fs";import{homedir as cn}from"node:os";import{dirname as un,join as ze}from"node:path";function Lo(t){let e=[],n=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,r;for(;r=n.exec(t);){let s=r[1]??r[2]??"";try{e.push(r[1]!==void 0?JSON.parse(`"${s}"`):s)}catch{e.push(s)}}return e}function ln(t={}){let e=t.configFile??ze(process.env.CODEX_HOME??ze(cn(),".codex"),"config.toml"),n=t.previousFile??ze(cn(),".config","toolnet-memory","codex-notify-previous.json");on(un(e),{recursive:!0}),on(un(n),{recursive:!0});let r=$o(e)?Fo(e,"utf8"):"",s=t.binary??"toolnet-memory",o=`notify = [${JSON.stringify(s)}, "session:codex-notify"]`,i=r.split(`
90
- `),c=i.findIndex(m=>/^\s*\[/.test(m));c<0&&(c=i.length);let u=-1,a=-1;for(let m=0;m<c;m+=1)if(/^\s*notify\s*=/.test(i[m])){if(u=m,a=m,i[m].includes("[")&&!i[m].includes("]"))for(;a+1<c&&(a+=1,!i[a].includes("]")););break}let f=[];if(u>=0){let m=i.slice(u,a+1).join(`
91
- `);f=Lo(m),i.splice(u,a-u+1,o)}else c=i.findIndex(m=>/^\s*\[/.test(m)),c<0&&(c=i.length),i.splice(c,0,o);let l=f.length>=2&&f[f.length-1]==="session:codex-notify";return f.length>0&&!l&&an(n,JSON.stringify(f,null,2)+`
81
+ `,"utf8"),y=s+l;l+=S;let h;try{h=JSON.parse(d)}catch{continue}let g=Ht(h),x=mo(g);m.push({type:x.type,timestamp:fo(g),role:x.role,sourceEventId:`rollout:${y}`,sourceSequence:y,data:g,provenance:{source:"codex-rollout",sourcePath:t,sourceOffset:y}})}return{events:m,nextOffset:s+Buffer.byteLength(f,"utf8"),reset:r}}var go=[/^<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*$/],ho=[/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],yo=["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 So(t){let e=t.toLowerCase();return yo.some(n=>e.includes(n))}function ko(t){if(!t.trim())return!0;for(let e of go)if(e.test(t))return!0;return So(t),!1}function vo(t){let e=t;for(let n of ho)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function ze(t){let e=t.trim();return e?ko(e)?{content:"",filtered:!0,reason:"noise"}:{content:vo(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function Ie(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=ze(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=Ie(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=ze(s);return o.filtered?null:o.content}return s&&typeof s=="object"?Ie(s):s}).filter(s=>s!==null):e[n]=r;return e}function Ut(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&&ze(r).filtered)return!0}return!1}import{existsSync as bo,mkdirSync as xo,readFileSync as wo,renameSync as jo,writeFileSync as Io}from"node:fs";import{dirname as Po,join as Co}from"node:path";function Oo(t,e){xo(Po(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;Io(n,`${JSON.stringify(e,null,2)}
82
+ `,{encoding:"utf8",mode:384}),jo(n,t)}function en(t){return Co(t.rootPath,".toolnet","work","current.json")}function Mo(t){let e=en(t);if(!bo(e))return null;try{let n=JSON.parse(wo(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function Be(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function z(t,e,n){let r=[],s=new Set;for(let o of[...t,...e].reverse()){let i=Be(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function Eo(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 Yt(t,e){let n=e.status??t?.status??"pending",r=n;t?.status==="completed"&&n!=="completed"&&(r="completed"),t&&n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status);let s=t&&Eo(e)?t.title:e.text;return{id:t?.id??e.id,title:s,status:r,order:e.order??t?.order,confidence:Math.max(t?.confidence??0,e.confidence),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}function Gt(t){let e=new Map;for(let n of t){let r=n.order!==void 0?`order:${n.order}`:Be(n.title);e.set(r,n)}return e}function Qt(t){return t.order!==void 0?`order:${t.order}`:Be(t.key||t.text)}function Xt(t){return Array.from(t).sort((e,n)=>{let r=e.order??Number.MAX_SAFE_INTEGER,s=n.order??Number.MAX_SAFE_INTEGER;return r!==s?r-s:e.updatedAt.localeCompare(n.updatedAt)})}function Zt(t){return t.find(e=>e.status==="in_progress")??t.find(e=>e.status==="blocked")??t.find(e=>e.status==="pending")}function tn(t,e){let n=Mo(t),r=Gt(n?.phases??[]),s=Gt(n?.tasks??[]),o=n?.goal,i=n?.plan,u=n?.lastSession,c=[],a=[],f=[],l=[],m=[],d=[],S=[...e].sort((p,v)=>{let B=p.occurredAt.localeCompare(v.occurredAt);return B!==0?B:p.sequence-v.sequence});for(let p of S)switch(p.kind){case"goal":o=p.text;break;case"plan":i=p.text;break;case"phase":{let v=Qt(p);r.set(v,Yt(r.get(v),p));break}case"task":{let v=Qt(p);s.set(v,Yt(s.get(v),p));break}case"decision":c.push(p.text);break;case"blocker":a.push(p.text);break;case"warning":f.push(p.text);break;case"next_action":l.push(p.text);break;case"file":m.push(p.text);break;case"test":d.push(p.text);break;case"session":u={agent:p.agent,nativeSessionId:p.nativeSessionId,sessionKey:p.sessionKey,updatedAt:p.occurredAt};break}let y=Xt(r.values()),h=Xt(s.values()),g=Zt(y),x=Zt(h),T=z(n?.nextActions??[],[...l,...x?[x.title]:[],...!x&&g?[g.title]:[],...h.filter(p=>p.status==="pending").slice(0,5).map(p=>p.title)],8),A=z(n?.blockers??[],[...a,...y.filter(p=>p.status==="blocked").map(p=>p.title),...h.filter(p=>p.status==="blocked").map(p=>p.title)],20),j=S.length>0?S[S.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),M={version:1,projectId:t.id,projectName:t.name,goal:o,plan:i,phases:y,tasks:h,decisions:z(n?.decisions??[],c,20),blockers:A,warnings:z(n?.warnings??[],f,20),nextActions:T,filesTouched:z(n?.filesTouched??[],m,30),tests:z(n?.tests??[],d,20),currentPhase:g,currentTask:x,progress:{phasesTotal:y.length,phasesCompleted:y.filter(p=>p.status==="completed").length,tasksTotal:h.length,tasksCompleted:h.filter(p=>p.status==="completed").length,blocked:y.filter(p=>p.status==="blocked").length+h.filter(p=>p.status==="blocked").length},lastSession:u,updatedAt:j};return Oo(en(t),M),M}import{existsSync as To,readFileSync as Ao,writeFileSync as Ro}from"node:fs";import{join as No}from"node:path";var rn="<!-- TOOLNET:STABLE-WORK:BEGIN -->",qe="<!-- TOOLNET:STABLE-WORK:END -->";function Je(t){switch(t.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function Pe(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${n}`)]:[]}function nn(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${Je(n)} ${n.title}`)]:[]}function _o(t){let e=[rn,"# ToolNet Stable Work State","",`Updated: ${t.updatedAt}`];return t.lastSession&&e.push(`Last agent: ${t.lastSession.agent}`,`Last session: ${t.lastSession.nativeSessionId}`),t.goal&&e.push("","Goal:",t.goal),t.plan&&e.push("","Plan:",t.plan),t.currentPhase&&e.push("","Current phase:",`${Je(t.currentPhase)} ${t.currentPhase.title}`),t.currentTask&&e.push("","Current task:",`${Je(t.currentTask)} ${t.currentTask.title}`),e.push(...nn("Phases",t.phases)),e.push(...nn("TODO / Tasks",t.tasks)),e.push(...Pe("Next actions",t.nextActions)),e.push(...Pe("Blockers",t.blockers)),e.push(...Pe("Important decisions",t.decisions)),e.push(...Pe("Files touched",t.filesTouched)),e.push("","Progress:",`- Phases: ${t.progress.phasesCompleted}/${t.progress.phasesTotal}`,`- Tasks: ${t.progress.tasksCompleted}/${t.progress.tasksTotal}`,`- Blocked: ${t.progress.blocked}`,"","Continuation:","- Resume current unfinished task.","- Never redo completed TODO/Phase unless explicitly requested.","- Ask ToolNet Memory for deeper history only when necessary.",qe),e.join(`
83
+ `)}function sn(t,e){let n=No(t.rootPath,".toolnet","current.md"),r="";if(To(n))try{r=Ao(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let s=_o(e),o=r.indexOf(rn),i=r.indexOf(qe),u;o>=0&&i>=o?u=[r.slice(0,o).trimEnd(),s,r.slice(i+qe.length).trimStart()].filter(Boolean).join(`
84
+
85
+ `):u=r.trim()?`${r.trim()}
86
+
87
+ ${s}`:s,Ro(n,`${u.trim()}
88
+ `,{encoding:"utf8",mode:384})}import{existsSync as $o,mkdirSync as Fo,readFileSync as Lo,renameSync as Wo,writeFileSync as Do}from"node:fs";import{dirname as Ko,join as zo}from"node:path";function on(t){return zo(t.rootPath,".toolnet","context","session-origin.json")}function Bo(t,e){Fo(Ko(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;Do(n,`${JSON.stringify(e,null,2)}
89
+ `,{encoding:"utf8",mode:384}),Wo(n,t)}function Ce(t,e){return[...t].filter(n=>n.kind===e).sort((n,r)=>{let s=n.occurredAt.localeCompare(r.occurredAt);return s!==0?s:n.sequence-r.sequence}).at(-1)}function an(t,e){let n=Ce(e.observations,"file"),r=Ce(e.observations,"next_action"),s=Ce(e.observations,"blocker"),o=Ce(e.observations,"decision"),i={version:1,projectId:t.id,agent:e.agent,nativeSessionId:e.nativeSessionId,updatedAt:e.workState.updatedAt,currentTask:e.workState.currentTask?.title,currentPhase:e.workState.currentPhase?.title,lastTouchedFile:n?.text??e.workState.filesTouched.at(-1),latestNextAction:r?.text??e.workState.nextActions.at(-1),latestBlocker:s?.text??e.workState.blockers.at(-1),latestDecision:o?.text??e.workState.decisions.at(-1)};return Bo(on(t),i),i}function qo(t){let e=on(t);if(!$o(e))return null;try{let n=JSON.parse(Lo(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function cn(t){let e=qo(t);if(!e)return null;let n=["Previous session:",`- Agent: ${e.agent}`,`- Session: ${e.nativeSessionId}`];return e.currentPhase&&n.push(`- Current phase: ${e.currentPhase}`),e.currentTask&&n.push(`- Current task: ${e.currentTask}`),e.lastTouchedFile&&n.push(`- Last touched file: ${e.lastTouchedFile}`),e.latestBlocker&&n.push(`- Blocker: ${e.latestBlocker}`),e.latestNextAction&&n.push(`- Next action: ${e.latestNextAction}`),e.latestDecision&&n.push(`- Important decision: ${e.latestDecision}`),n.join(`
90
+ `)}async function Q(t){let e=t.threadId.trim();if(!e)throw new Error("Codex thread ID is required");let n=G(t.rolloutPath),r=t.cwd??n.cwd;if(r&&!je(t.project.rootPath,r))throw new Error(`Codex thread does not belong to project: ${r}`);if(n.threadId&&n.threadId!==e)throw new Error(`Codex rollout thread mismatch: expected ${e}, got ${n.threadId}`);let s=new xe({project:t.project,storage:t.storage,agent:"codex",nativeSessionId:e,metadata:{source:"codex-rollout",rolloutPath:t.rolloutPath,cwd:r,client:t.client}}),o=s.status(),i=o.sourceCursors["codex.rollout.path"],u=Number(o.sourceCursors["codex.rollout.offset"]??0);i&&i!==t.rolloutPath&&(u=0),(!Number.isFinite(u)||u<0)&&(u=0);let c=Vt(t.rolloutPath,u),a=[];o.lastSequence===0&&a.push({type:"session_start",sourceEventId:`codex:${e}:start`,data:{threadId:e,cwd:r,rolloutPath:t.rolloutPath,sessionMeta:n.raw},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}}),i&&i!==t.rolloutPath&&a.push({type:"custom",sourceEventId:`codex:${e}:rollout-rotation:${t.rolloutPath}`,data:{event:"rollout_rotation",previousPath:i,rolloutPath:t.rolloutPath},provenance:{source:"codex-rollout"}}),c.reset&&a.push({type:"custom",sourceEventId:`codex:${e}:rollout-reset:${c.nextOffset}`,data:{event:"rollout_reset"},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}});let f=c.events.filter(d=>!Ut(d.data)).map(d=>({...d,data:Ie(d.data)}));if(a.push(...f),t.idle&&f.length>0)try{let d={projectId:t.project.id,projectName:t.project.name,projectRoot:t.project.rootPath,agent:"codex",nativeSessionId:e,sessionKey:`codex:${e}`,remotePrefix:`projects/${t.project.id}/sessions/codex/${e}`,localDirectory:""},S=f.map((g,x)=>({version:1,id:`codex-work-${e}-${g.sourceSequence??x}`,sequence:x+1,projectId:t.project.id,agent:"codex",nativeSessionId:e,type:g.type,timestamp:g.timestamp??new Date().toISOString(),role:g.role,sourceEventId:g.sourceEventId,sourceSequence:g.sourceSequence,data:g.data??{},provenance:g.provenance??{}})),y=pe(d,S),h=tn(t.project,y);sn(t.project,h),an(t.project,{agent:"codex",nativeSessionId:e,observations:y,workState:h})}catch{}t.idle&&t.turnId&&a.push({type:"session_idle",sourceEventId:`codex:${e}:turn:${t.turnId}:idle`,data:{turnId:t.turnId,client:t.client},provenance:{source:"codex-notify"}});let l=s.recordMany(a);if(s.setSourceCursor("codex.rollout.path",t.rolloutPath),s.setSourceCursor("codex.rollout.offset",c.nextOffset),t.turnId&&s.setSourceCursor("codex.last.turn",t.turnId),t.idle&&f.length>0)try{let d=f.map(y=>JSON.stringify(y.data)),S=ce(d,e);s.setSourceCursor("codex.session.summary",S.summary),s.setSourceCursor("codex.session.facts_count",S.durableFacts.length),bt()&&!jt()&&s.setSourceCursor("codex.raw_transcript.archived","local")}catch{}let m=await s.flush();return{threadId:e,imported:l.length,rolloutEvents:c.events.length,eventCount:m.eventCount,chunkCount:m.chunkCount,status:m.status,rolloutOffset:c.nextOffset,reset:c.reset}}import{existsSync as Jo}from"node:fs";import{dirname as Ho,join as Vo,parse as Uo,resolve as Yo}from"node:path";function un(t){let e=Yo(t),n=Uo(e).root;for(;;){if(Jo(Vo(e,".toolnet","project.json")))return new F().detect(e);if(e===n)break;let r=Ho(e);if(r===e)break;e=r}return null}async function ln(t,e,n=100){let r=[];for(let s of De()){let o=G(s);if(!(!o.threadId||!o.cwd)&&je(t.rootPath,o.cwd)&&(r.push(await Q({project:t,storage:e,threadId:o.threadId,rolloutPath:s,cwd:o.cwd})),r.length>=n))break}return r}import{existsSync as Go,mkdirSync as dn,readFileSync as Qo,writeFileSync as pn}from"node:fs";import{homedir as fn}from"node:os";import{dirname as mn,join as He}from"node:path";function Xo(t){let e=[],n=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,r;for(;r=n.exec(t);){let s=r[1]??r[2]??"";try{e.push(r[1]!==void 0?JSON.parse(`"${s}"`):s)}catch{e.push(s)}}return e}function gn(t={}){let e=t.configFile??He(process.env.CODEX_HOME??He(fn(),".codex"),"config.toml"),n=t.previousFile??He(fn(),".config","toolnet-memory","codex-notify-previous.json");dn(mn(e),{recursive:!0}),dn(mn(n),{recursive:!0});let r=Go(e)?Qo(e,"utf8"):"",s=t.binary??"toolnet-memory",o=`notify = [${JSON.stringify(s)}, "session:codex-notify"]`,i=r.split(`
91
+ `),u=i.findIndex(m=>/^\s*\[/.test(m));u<0&&(u=i.length);let c=-1,a=-1;for(let m=0;m<u;m+=1)if(/^\s*notify\s*=/.test(i[m])){if(c=m,a=m,i[m].includes("[")&&!i[m].includes("]"))for(;a+1<u&&(a+=1,!i[a].includes("]")););break}let f=[];if(c>=0){let m=i.slice(c,a+1).join(`
92
+ `);f=Xo(m),i.splice(c,a-c+1,o)}else u=i.findIndex(m=>/^\s*\[/.test(m)),u<0&&(u=i.length),i.splice(u,0,o);let l=f.length>=2&&f[f.length-1]==="session:codex-notify";return f.length>0&&!l&&pn(n,JSON.stringify(f,null,2)+`
92
93
  `,{encoding:"utf8",mode:384}),r=i.join(`
93
94
  `),r.endsWith(`
94
95
  `)||(r+=`
95
- `),an(e,r,{encoding:"utf8",mode:384}),{configFile:e,previousFile:n,preservedPrevious:f.length>0&&!l}}import{existsSync as Wo,mkdirSync as Do,readFileSync as Ko,writeFileSync as Bo}from"node:fs";import{homedir as zo}from"node:os";import{dirname as Jo,join as dn}from"node:path";function qo(t){return`'${t.replace(/'/g,"'\\''")}'`}function pn(t={}){let e=t.hooksFile??dn(process.env.CODEX_HOME??dn(zo(),".codex"),"hooks.json");Do(Jo(e),{recursive:!0});let n={};if(Wo(e))try{n=JSON.parse(Ko(e,"utf8"))}catch(c){throw new Error(`Invalid existing Codex hooks.json: ${c instanceof Error?c.message:String(c)}`)}let r=n.hooks&&typeof n.hooks=="object"&&!Array.isArray(n.hooks)?n.hooks:{};n.hooks=r;let o=(Array.isArray(r.SessionStart)?r.SessionStart:[]).filter(c=>{try{return!JSON.stringify(c).includes("session:codex-context")}catch{return!0}}),i=t.binary??"toolnet-memory";return o.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${qo(i)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),r.SessionStart=o,Bo(e,JSON.stringify(n,null,2)+`
96
- `,{encoding:"utf8",mode:384}),e}import{existsSync as Tl,mkdirSync as Yo,readFileSync as Cl,writeFileSync as Go}from"node:fs";import{dirname as Xo,join as mn}from"node:path";function Je(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 x(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 Ho(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(x(s,280)),e.length>=16))break}return e}function Vo(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.trim(),o=s.toLowerCase(),c=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(a=>o.startsWith(a));if(!c)continue;let u=s.slice(c.length).trim();u&&(c.includes("enforce")?e.push(u):n.push(u))}return{enforce:e,advisory:n}}function Uo(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
97
- `);if(Je(s)<=e){n.push(r);continue}let o=Je(n.join(`
98
- `)),i=Math.max(0,e-o);if(i>=16){let c=Math.floor(i*3.2),u=x(r,c);u&&n.push(u)}break}return n.join(`
99
- `).trim()}async function fn(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=ge(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=Vo(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,c=r?Ho(r):[],u=await le(t.project,t.storage),a=await Et(t.project,t.storage),f=await Mt(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: ${me(t.project)}`),o.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of o.slice(0,24))l.push(`- [ENFORCE] ${x(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${x(d,220)}`)}if(a&&(a.mission&&l.push("","MISSION",x(a.mission.value,420)),a.activeObjective&&l.push("","CURRENT OBJECTIVE",x(a.activeObjective.value,420)),a.why&&l.push("","WHY THIS WORK MATTERS",x(a.why.value,420)),a.desiredOutcome&&l.push("","DESIRED OUTCOME",x(a.desiredOutcome.value,420)),a.planRationale&&l.push("","WHY THIS APPROACH",x(a.planRationale.value,420))),u){if(l.push("","ACTIVE WORK"),u.goal&&l.push(`Goal: ${x(u.goal,320)}`),u.plan&&l.push(`Plan: ${x(u.plan,320)}`),l.push(`Progress: phases ${u.progress.phasesCompleted}/${u.progress.phasesTotal}; tasks ${u.progress.tasksCompleted}/${u.progress.tasksTotal}; blocked ${u.progress.blocked}`),u.currentPhase&&l.push(`Current phase: ${u.currentPhase.title} [${u.currentPhase.status}]`),u.currentPhase&&a){let d=a.phases.find(S=>S.order===u.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${x(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${x(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${x(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(S=>x(S.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(S=>{l.push(`- ${x(S.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(S=>{l.push(`- ${x(S.value,260)}`)})))}u.currentTask&&l.push(`Current task: ${u.currentTask.title} [${u.currentTask.status}]`),u.nextActions.length&&(l.push("","NEXT ACTIONS"),u.nextActions.slice(0,6).forEach((d,S)=>{l.push(`${S+1}. ${x(d,260)}`)})),u.blockers.length&&(l.push("","BLOCKERS"),u.blockers.slice(0,5).forEach(d=>{l.push(`- ${x(d,260)}`)})),u.warnings.length&&(l.push("","ATTENTION"),u.warnings.slice(-5).forEach(d=>{l.push(`- ${x(d,260)}`)})),u.decisions.length&&(l.push("","RECENT DECISIONS"),u.decisions.slice(-5).forEach(d=>{l.push(`- ${x(d,260)}`)})),u.lastSession&&l.push("",`Last work session: ${u.lastSession.agent} / ${u.lastSession.nativeSessionId}`)}if(a&&a.openQuestions.length&&(l.push("","UNRESOLVED QUESTIONS"),a.openQuestions.slice(0,5).forEach(d=>{l.push(`- ${x(d.value,260)}`)})),f&&l.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),c.length){l.push("","OPERATING NOTES");for(let d of c)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let m=Uo(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:m,estimatedTokens:Je(m),maxTokens:e,hasManual:!!r,hasWorkState:!!u,hasHandoff:!!f,generatedAt:new Date().toISOString()}}function Qo(t){return mn(t.rootPath,".toolnet","context","startup.md")}function Zo(t){return mn(t.rootPath,".toolnet","context","startup.json")}function ei(t,e){let n=Qo(t);Yo(Xo(n),{recursive:!0}),Go(n,e.text.endsWith(`
96
+ `),pn(e,r,{encoding:"utf8",mode:384}),{configFile:e,previousFile:n,preservedPrevious:f.length>0&&!l}}import{existsSync as Zo,mkdirSync as ei,readFileSync as ti,writeFileSync as ni}from"node:fs";import{homedir as ri}from"node:os";import{dirname as si,join as hn}from"node:path";function oi(t){return`'${t.replace(/'/g,"'\\''")}'`}function yn(t={}){let e=t.hooksFile??hn(process.env.CODEX_HOME??hn(ri(),".codex"),"hooks.json");ei(si(e),{recursive:!0});let n={};if(Zo(e))try{n=JSON.parse(ti(e,"utf8"))}catch(u){throw new Error(`Invalid existing Codex hooks.json: ${u instanceof Error?u.message:String(u)}`)}let r=n.hooks&&typeof n.hooks=="object"&&!Array.isArray(n.hooks)?n.hooks:{};n.hooks=r;let o=(Array.isArray(r.SessionStart)?r.SessionStart:[]).filter(u=>{try{return!JSON.stringify(u).includes("session:codex-context")}catch{return!0}}),i=t.binary??"toolnet-memory";return o.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${oi(i)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),r.SessionStart=o,ni(e,JSON.stringify(n,null,2)+`
97
+ `,{encoding:"utf8",mode:384}),e}import{existsSync as td,mkdirSync as ui,readFileSync as nd,writeFileSync as li}from"node:fs";import{dirname as di,join as kn}from"node:path";function Ve(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 b(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 ii(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(b(s,280)),e.length>=16))break}return e}function ai(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.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):n.push(c))}return{enforce:e,advisory:n}}function ci(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
98
+ `);if(Ve(s)<=e){n.push(r);continue}let o=Ve(n.join(`
99
+ `)),i=Math.max(0,e-o);if(i>=16){let u=Math.floor(i*3.2),c=b(r,u);c&&n.push(c)}break}return n.join(`
100
+ `).trim()}async function Sn(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=ve(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=ai(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,u=r?ii(r):[],c=await ge(t.project,t.storage),a=await $t(t.project,t.storage),f=await zt(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: ${ke(t.project)}`),o.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of o.slice(0,24))l.push(`- [ENFORCE] ${b(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${b(d,220)}`)}if(a&&(a.mission&&l.push("","MISSION",b(a.mission.value,420)),a.activeObjective&&l.push("","CURRENT OBJECTIVE",b(a.activeObjective.value,420)),a.why&&l.push("","WHY THIS WORK MATTERS",b(a.why.value,420)),a.desiredOutcome&&l.push("","DESIRED OUTCOME",b(a.desiredOutcome.value,420)),a.planRationale&&l.push("","WHY THIS APPROACH",b(a.planRationale.value,420))),c){if(l.push("","ACTIVE WORK"),c.goal&&l.push(`Goal: ${b(c.goal,320)}`),c.plan&&l.push(`Plan: ${b(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(S=>S.order===c.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${b(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${b(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${b(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(S=>b(S.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(S=>{l.push(`- ${b(S.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(S=>{l.push(`- ${b(S.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,S)=>{l.push(`${S+1}. ${b(d,260)}`)})),c.blockers.length&&(l.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(d=>{l.push(`- ${b(d,260)}`)})),c.warnings.length&&(l.push("","ATTENTION"),c.warnings.slice(-5).forEach(d=>{l.push(`- ${b(d,260)}`)})),c.decisions.length&&(l.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(d=>{l.push(`- ${b(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(`- ${b(d.value,260)}`)})),f&&l.push(`Latest handoff: ${f.reason} / ${f.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=ci(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:m,estimatedTokens:Ve(m),maxTokens:e,hasManual:!!r,hasWorkState:!!c,hasHandoff:!!f,generatedAt:new Date().toISOString()}}function pi(t){return kn(t.rootPath,".toolnet","context","startup.md")}function fi(t){return kn(t.rootPath,".toolnet","context","startup.json")}function mi(t,e){let n=pi(t);ui(di(n),{recursive:!0}),li(n,e.text.endsWith(`
100
101
  `)?e.text:e.text+`
101
- `,{encoding:"utf8",mode:384}),I(Zo(t),e)}async function gn(t,e,n=800){let s=(await fn({project:t,storage:e,maxTokens:n})).text;xe(s)>n&&(s=be(s,n),s+=`
102
+ `,{encoding:"utf8",mode:384}),I(fi(t),e)}async function vn(t,e,n=800){let s=(await Sn({project:t,storage:e,maxTokens:n})).text;ie(s)>n&&(s=ae(s,n),s+=`
102
103
 
103
104
  [Context trimmed by ToolNet Memory token budget]
104
- `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:k(s),estimatedTokens:xe(s),generatedAt:new Date().toISOString()};return ei(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
105
+ `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:k(s),estimatedTokens:ie(s),generatedAt:new Date().toISOString()};return mi(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
105
106
  `,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
106
- `,"application/json"),i}import{existsSync as ii,readFileSync as ai}from"node:fs";import{join as ci}from"node:path";import{existsSync as hn,mkdirSync as ti,readFileSync as yn,renameSync as ni,writeFileSync as ri}from"node:fs";import{dirname as si,join as Sn}from"node:path";function kn(t){return Sn(t.rootPath,".toolnet","context","handoff.md")}function vn(t){return Sn(t.rootPath,".toolnet","context","handoff.json")}function xn(t,e){ti(si(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;ri(n,e.endsWith(`
107
+ `,"application/json"),i}import{existsSync as vi,readFileSync as bi}from"node:fs";import{join as xi}from"node:path";import{existsSync as bn,mkdirSync as gi,readFileSync as xn,renameSync as hi,writeFileSync as yi}from"node:fs";import{dirname as Si,join as wn}from"node:path";function jn(t){return wn(t.rootPath,".toolnet","context","handoff.md")}function In(t){return wn(t.rootPath,".toolnet","context","handoff.json")}function Pn(t,e){gi(Si(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;yi(n,e.endsWith(`
107
108
  `)?e:`${e}
108
- `,{encoding:"utf8",mode:384}),ni(n,t)}function oi(t,e){xn(t,`${JSON.stringify(e,null,2)}
109
- `)}function bn(t,e){let n=e.replace(/\r\n/g,`
110
- `).trim();if(!n)return null;let r={version:1,projectId:t.id,projectName:t.name,text:n,digest:k(n),generatedAt:new Date().toISOString()};return xn(kn(t),n),oi(vn(t),r),r}function wn(t){let e=kn(t);if(!hn(e))return null;try{let n=yn(e,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=vn(t);if(hn(s))try{let o=JSON.parse(yn(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:t.id,projectName:t.name,text:n,digest:k(n),generatedAt:r}}catch{return null}}function ui(t){let e=ci(t.rootPath,".toolnet","current.md");if(!ii(e))return null;try{return ai(e,"utf8").trim()}catch{return null}}function li(t,e){let n=e.replace(/\r\n/g,`
109
+ `,{encoding:"utf8",mode:384}),hi(n,t)}function ki(t,e){Pn(t,`${JSON.stringify(e,null,2)}
110
+ `)}function Cn(t,e){let n=e.replace(/\r\n/g,`
111
+ `).trim();if(!n)return null;let r={version:1,projectId:t.id,projectName:t.name,text:n,digest:k(n),generatedAt:new Date().toISOString()};return Pn(jn(t),n),ki(In(t),r),r}function On(t){let e=jn(t);if(!bn(e))return null;try{let n=xn(e,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=In(t);if(bn(s))try{let o=JSON.parse(xn(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:t.id,projectName:t.name,text:n,digest:k(n),generatedAt:r}}catch{return null}}function wi(t){let e=xi(t.rootPath,".toolnet","current.md");if(!vi(e))return null;try{return bi(e,"utf8").trim()}catch{return null}}function ji(t,e){let n=e.replace(/\r\n/g,`
111
112
  `).trim(),r=2400,s=n.length>r?`${n.slice(0,r)}
112
113
 
113
- [Current work truncated for fast handoff]`:n,o=nn(t);return["# ToolNet Fast Handoff","",`Project: ${t.name}`,"",...o?[o,""]:[],s,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
114
- `)}function jn(t){let e=ui(t);if(e===null)return{updated:!1,reason:"missing-current",chars:0};if(!e.trim())return{updated:!1,reason:"empty-current",chars:0};let n=li(t,e);return wn(t)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(bn(t,n),{updated:!0,reason:"updated",chars:n.length})}function Ie(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function In(t){let e=G(),n=tt(Ze({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new te(n,t.id,t.name,t.remote??t.name)}async function hi(t){for(let e=0;e<10;e+=1){let n=Le(t);if(n)return n;await new Promise(r=>setTimeout(r,150))}return null}function yi(t){let e=gi(mi(),".config","toolnet-memory","codex-notify-previous.json");if(di(e))try{let n=JSON.parse(pi(e,"utf8"));if(!Array.isArray(n)||n.length===0||!n.every(s=>typeof s=="string"))return;fi(n[0],[...n.slice(1),t],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function Si(t){let e;try{e=JSON.parse(t)}catch{return}if(e.type!=="agent-turn-complete")return;let r=typeof e["thread-id"]=="string"?e["thread-id"]:"",s=typeof e["turn-id"]=="string"?e["turn-id"]:"",o=typeof e.cwd=="string"?e.cwd:"",i=typeof e.client=="string"?e.client:void 0;if(!r||!o)return;let c=rn(o);if(!c)return;let u=await hi(r);if(!u)return;let a=In(c);await Y({project:c,storage:a,threadId:r,rolloutPath:u,cwd:o,turnId:s,client:i,idle:!0});try{await gn(c,a,800)}catch{}try{jn(c)}catch{}}async function ki(){let[t="help",...e]=process.argv.slice(2);if(t==="install-notify"){let o=Ie(e,"--bin"),i=ln({binary:o}),c=pn({binary:o});console.log(`\u2705 Codex notify installed: ${i.configFile}`),i.preservedPrevious&&console.log(`\u2705 Previous notify preserved: ${i.previousFile}`),console.log(`\u2705 Codex SessionStart context hook: ${c}`);return}if(t==="notify"){let o=e[e.length-1]??"";try{await Si(o)}finally{yi(o)}return}let n=Ie(e,"--project")??process.cwd(),r=new _().detect(n),s=In(r);if(t==="sync"){let o=e[0];if(!o)throw new Error("Usage: sync <thread-id>");let i=Ie(e,"--rollout")??Le(o);if(!i)throw new Error(`Codex rollout not found for ${o}`);let c=await Y({project:r,storage:s,threadId:o,rolloutPath:i,idle:e.includes("--idle")});console.log(JSON.stringify(c,null,2));return}if(t==="recover"){let o=Number(Ie(e,"--limit")??100),i=await sn(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((c,u)=>c+u.imported,0)},null,2));return}console.log(`Codex Session Adapter
114
+ [Current work truncated for fast handoff]`:n,o=cn(t);return["# ToolNet Fast Handoff","",`Project: ${t.name}`,"",...o?[o,""]:[],s,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
115
+ `)}function Mn(t){let e=wi(t);if(e===null)return{updated:!1,reason:"missing-current",chars:0};if(!e.trim())return{updated:!1,reason:"empty-current",chars:0};let n=ji(t,e);return On(t)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(Cn(t,n),{updated:!0,reason:"updated",chars:n.length})}function Oe(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function En(t){let e=X(),n=st(nt({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new re(n,t.id,t.name,t.remote??t.name)}async function Ei(t){for(let e=0;e<10;e+=1){let n=Ke(t);if(n)return n;await new Promise(r=>setTimeout(r,150))}return null}function Ti(t){let e=Mi(Oi(),".config","toolnet-memory","codex-notify-previous.json");if(Ii(e))try{let n=JSON.parse(Pi(e,"utf8"));if(!Array.isArray(n)||n.length===0||!n.every(s=>typeof s=="string"))return;Ci(n[0],[...n.slice(1),t],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function Ai(t){let e;try{e=JSON.parse(t)}catch{return}if(e.type!=="agent-turn-complete")return;let r=typeof e["thread-id"]=="string"?e["thread-id"]:"",s=typeof e["turn-id"]=="string"?e["turn-id"]:"",o=typeof e.cwd=="string"?e.cwd:"",i=typeof e.client=="string"?e.client:void 0;if(!r||!o)return;let u=un(o);if(!u)return;let c=await Ei(r);if(!c)return;let a=En(u);await Q({project:u,storage:a,threadId:r,rolloutPath:c,cwd:o,turnId:s,client:i,idle:!0});try{await vn(u,a,800)}catch{}try{Mn(u)}catch{}}async function Ri(){let[t="help",...e]=process.argv.slice(2);if(t==="install-notify"){let o=Oe(e,"--bin"),i=gn({binary:o}),u=yn({binary:o});console.log(`\u2705 Codex notify installed: ${i.configFile}`),i.preservedPrevious&&console.log(`\u2705 Previous notify preserved: ${i.previousFile}`),console.log(`\u2705 Codex SessionStart context hook: ${u}`);return}if(t==="notify"){let o=e[e.length-1]??"";try{await Ai(o)}finally{Ti(o)}return}let n=Oe(e,"--project")??process.cwd(),r=new F().detect(n),s=En(r);if(t==="sync"){let o=e[0];if(!o)throw new Error("Usage: sync <thread-id>");let i=Oe(e,"--rollout")??Ke(o);if(!i)throw new Error(`Codex rollout not found for ${o}`);let u=await Q({project:r,storage:s,threadId:o,rolloutPath:i,idle:e.includes("--idle")});console.log(JSON.stringify(u,null,2));return}if(t==="recover"){let o=Number(Oe(e,"--limit")??100),i=await ln(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((u,c)=>u+c.imported,0)},null,2));return}console.log(`Codex Session Adapter
115
116
 
116
117
  Commands:
117
118
  install-notify
118
119
  sync <thread-id> [--project PATH]
119
120
  recover [--project PATH] [--limit N]
120
- `)}ki().catch(t=>{process.argv[2]==="notify"&&process.exit(0),console.error(t instanceof Error?t.message:t),process.exit(1)});
121
+ `)}Ri().catch(t=>{process.argv[2]==="notify"&&process.exit(0),console.error(t instanceof Error?t.message:t),process.exit(1)});