toolnet-memory 0.2.21 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,34 +1,52 @@
1
- import{existsSync as an,readFileSync as cn}from"node:fs";import{homedir as un}from"node:os";import{join as ln}from"node:path";function dn(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 pn(){let t=process.env.TOOLNET_GLOBAL_ENV??ln(un(),".config","toolnet-memory",".env");if(!an(t))return;let e=cn(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]=dn(r.slice(s+1)))}}pn();function q(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function V(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function G(){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:V(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:V(process.env.MEMORY_RERANK_TOP,10),finalContext:V(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:V(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:V(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as mn}from"node:crypto";import{existsSync as Ce,mkdirSync as fn,readFileSync as gn,renameSync as yn,writeFileSync as hn}from"node:fs";import{basename as Sn,dirname as Q,join as Z,parse as Je,resolve as J}from"node:path";var He=".toolnet",vn="project.json";function bn(t){return mn("sha256").update(t).digest("hex").slice(0,16)}function Ee(t){return Z(t,He,vn)}function kn(t){return Ce(Ee(t))}function wn(t,e){let n=J(t),r=Je(n).root;for(;;){if(kn(n))return n;if(n===r||e&&n===J(e))break;let s=Q(n);if(s===n)break;n=s}return null}function xn(t){let e=J(t),n=Je(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>Ce(Z(e,o))))return e;if(e===n)break;let s=Q(e);if(s===e)break;e=s}return J(t)}function jn(t){let e;try{e=JSON.parse(gn(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:Q(Q(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 qe(t,e){let n=Z(t,He);fn(n,{recursive:!0});let r=Ee(t),s=`${r}.tmp-${process.pid}`;hn(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),yn(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 X=class{detect(e=process.cwd()){let n=J(e),r=xn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>Ce(Z(r,p))),i=wn(n,o?r:void 0);if(i){let p=Ee(i),l=jn(p);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),qe(i,l)),Ve(l,i)}let u=new Date().toISOString(),c=Sn(r),a={version:1,id:bn(r),name:c,remote:c,rootPath:r,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return qe(r,a),Ve(a,r)}};var In=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],ee=class{scan(e){let n=[];for(let r of In){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 H=class{scanner=new ee;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 Un}from"node:os";import{join as Yn}from"node:path";import{DeleteObjectCommand as Cn,GetObjectCommand as En,HeadObjectCommand as On,ListObjectsV2Command as Pn,PutObjectCommand as Tn,S3Client as Mn}from"@aws-sdk/client-s3";import{getSignedUrl as Rn}from"@aws-sdk/s3-request-presigner";var te=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Mn({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 Tn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Rn(this.client,new En({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 On({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 Cn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Pn({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 Ue,mkdir as An,readFile as Nn,readdir as _n,rm as $n,stat as Ye,writeFile as Ln}from"node:fs/promises";import{dirname as Dn,join as Fn,relative as Ge,resolve as Kn}from"node:path";var U=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Kn(this.root,n)}async put(e,n){let r=this.path(e);await An(Dn(r),{recursive:!0}),await Ln(r,n)}async get(e){try{return await Nn(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 Ue(this.path(e)),!0}catch{return!1}}async delete(e){await $n(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ue(n)}catch{return r}let s=async i=>{let u=await _n(i,{withFileTypes:!0});for(let c of u){let a=Fn(i,c.name);if(c.isDirectory()){await s(a);continue}let p=await Ye(a);r.push({key:Ge(this.root,a),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await Ye(n);return o.isDirectory()?await s(n):r.push({key:Ge(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Wn,GetObjectCommand as zn,HeadObjectCommand as Bn,ListObjectsV2Command as qn,PutObjectCommand as Vn,S3Client as Jn}from"@aws-sdk/client-s3";import{getSignedUrl as Hn}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 Jn({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 Vn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Hn(this.client,new zn({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 Bn({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 Wn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new qn({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 Oe(t,e){return console.warn(e),new U(t)}function Qe(t){let e=t.localRoot??Yn(Un(),".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}):Oe(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}):Oe(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 te({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Oe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new U(e)}function Gn(t){return new Promise(e=>setTimeout(e,t))}async function Xe(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 Gn(c+a)}throw o}var Qn=new Set(["put","get","getText","delete","list"]);function Ze(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:Qn.has(r)?(...o)=>Xe(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function et(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 tt(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 ne=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=et(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=tt(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{existsSync as Ds}from"node:fs";import{execFileSync as Fs}from"node:child_process";import{homedir as Ks}from"node:os";import{isAbsolute as Ws,join as Kt,relative as zs,resolve as Wt}from"node:path";import{DatabaseSync as Bs}from"node:sqlite";import{join as sr}from"node:path";import{createHash as Xn}from"node:crypto";import{dirname as Zn}from"node:path";import{mkdirSync as er,readFileSync as tr,renameSync as nr,writeFileSync as rr}from"node:fs";function v(t){return Xn("sha256").update(t).digest("hex")}function Pe(t){if(Array.isArray(t))return t.map(Pe);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Pe(e[r]);return n}return t}function nt(t){return JSON.stringify(Pe(t))}function rt(t){try{return JSON.parse(tr(t,"utf8"))}catch{return null}}function I(t,e){er(Zn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;rr(n,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),nr(n,t)}function st(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=v(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 ot(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=st(r.toLowerCase(),"agent"),i=st(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:sr(t.rootPath,".toolnet","sessions",o,i)}}function it(t){return String(t).padStart(12,"0")}var re=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(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(u)){let m=g[0],w=g[g.length-1],T=g.map(_=>JSON.stringify(_)).join(`
1
+ import{existsSync as Ar,readFileSync as Er}from"node:fs";import{homedir as Pr}from"node:os";import{join as Mr}from"node:path";function Tr(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 Or(){let t=process.env.TOOLNET_GLOBAL_ENV??Mr(Pr(),".config","toolnet-memory",".env");if(!Ar(t))return;let e=Er(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]=Tr(r.slice(s+1)))}}Or();function X(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function Q(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function pe(){return{memory:{autoCapture:X(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:X(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:X(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:X(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:Q(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:Q(process.env.MEMORY_RERANK_TOP,10),finalContext:Q(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:Q(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:X(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:Q(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Rr}from"node:crypto";import{existsSync as Ye,mkdirSync as Nr,readFileSync as _r,renameSync as $r,writeFileSync as Kr}from"node:fs";import{basename as Lr,dirname as me,join as ge,parse as Ct,resolve as Z}from"node:path";var It=".toolnet",Dr="project.json";function Wr(t){return Rr("sha256").update(t).digest("hex").slice(0,16)}function Xe(t){return ge(t,It,Dr)}function Fr(t){return Ye(Xe(t))}function zr(t,e){let n=Z(t),r=Ct(n).root;for(;;){if(Fr(n))return n;if(n===r||e&&n===Z(e))break;let s=me(n);if(s===n)break;n=s}return null}function Br(t){let e=Z(t),n=Ct(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>Ye(ge(e,o))))return e;if(e===n)break;let s=me(e);if(s===e)break;e=s}return Z(t)}function Vr(t){let e;try{e=JSON.parse(_r(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:me(me(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 xt(t,e){let n=ge(t,It);Nr(n,{recursive:!0});let r=Xe(t),s=`${r}.tmp-${process.pid}`;Kr(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),$r(s,r)}function jt(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 fe=class{detect(e=process.cwd()){let n=Z(e),r=Br(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>Ye(ge(r,p))),i=zr(n,o?r:void 0);if(i){let p=Xe(i),l=Vr(p);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),xt(i,l)),jt(l,i)}let a=new Date().toISOString(),c=Lr(r),u={version:1,id:Wr(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return xt(r,u),jt(u,r)}};var qr=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],ye=class{scan(e){let n=[];for(let r of qr){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 ee=class{scanner=new ye;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as fs}from"node:os";import{join as gs}from"node:path";import{DeleteObjectCommand as Jr,GetObjectCommand as Hr,HeadObjectCommand as Gr,ListObjectsV2Command as Ur,PutObjectCommand as Yr,S3Client as Xr}from"@aws-sdk/client-s3";import{getSignedUrl as Qr}from"@aws-sdk/s3-request-presigner";var he=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Xr({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 Yr({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Qr(this.client,new Hr({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 Gr({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 Jr({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}};import{access as At,mkdir as Zr,readFile as es,readdir as ts,rm as ns,stat as Et,writeFile as rs}from"node:fs/promises";import{dirname as ss,join as os,relative as Pt,resolve as is}from"node:path";var te=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return is(this.root,n)}async put(e,n){let r=this.path(e);await Zr(ss(r),{recursive:!0}),await rs(r,n)}async get(e){try{return await es(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 At(this.path(e)),!0}catch{return!1}}async delete(e){await ns(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await At(n)}catch{return r}let s=async i=>{let a=await ts(i,{withFileTypes:!0});for(let c of a){let u=os(i,c.name);if(c.isDirectory()){await s(u);continue}let p=await Et(u);r.push({key:Pt(this.root,u),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await Et(n);return o.isDirectory()?await s(n):r.push({key:Pt(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as as,GetObjectCommand as cs,HeadObjectCommand as us,ListObjectsV2Command as ls,PutObjectCommand as ds,S3Client as ps}from"@aws-sdk/client-s3";import{getSignedUrl as ms}from"@aws-sdk/s3-request-presigner";var ne=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new ps({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 ds({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await ms(this.client,new cs({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 us({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 as({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new ls({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 Qe(t,e){return console.warn(e),new te(t)}function Mt(t){let e=t.localRoot??gs(fs(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new ne({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Qe(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 ne({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Qe(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new he({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Qe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new te(e)}function ys(t){return new Promise(e=>setTimeout(e,t))}async function Tt(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(a){if(o=a,i>=n)break;let c=Math.min(s,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await ys(c+u)}throw o}var hs=new Set(["put","get","getText","delete","list"]);function Ot(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:hs.has(r)?(...o)=>Tt(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Rt(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 Nt(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 Se=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Rt(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Nt(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{existsSync as ka}from"node:fs";import{execFileSync as ba}from"node:child_process";import{homedir as xa}from"node:os";import{isAbsolute as ja,join as ar,relative as Ca,resolve as cr}from"node:path";import{DatabaseSync as Ia}from"node:sqlite";import{join as js}from"node:path";import{createHash as Ss}from"node:crypto";import{dirname as ws}from"node:path";import{mkdirSync as vs,readFileSync as ks,renameSync as bs,writeFileSync as xs}from"node:fs";function w(t){return Ss("sha256").update(t).digest("hex")}function Ze(t){if(Array.isArray(t))return t.map(Ze);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Ze(e[r]);return n}return t}function _t(t){return JSON.stringify(Ze(t))}function $t(t){try{return JSON.parse(ks(t,"utf8"))}catch{return null}}function E(t,e){vs(ws(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;xs(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),bs(n,t)}function Kt(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=w(n).slice(0,12);if(!r||r==="."||r==="..")return`${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=Kt(r.toLowerCase(),"agent"),i=Kt(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:js(t.rootPath,".toolnet","sessions",o,i)}}function Dt(t){return String(t).padStart(12,"0")}var we=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 a=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!a)continue;let c=Number(a[1]),u=Number(a[2]);!Number.isFinite(c)||!Number.isFinite(u)||(s.push({key:i.key,start:c,end:u}),o=Math.max(o,u))}return s.sort((i,a)=>i.start-a.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
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),a=n.filter(y=>y.sequence>i.maxSequence),c=0;for(let y of this.split(a)){let g=y[0],v=y[y.length-1],A=y.map(_=>JSON.stringify(_)).join(`
8
8
  `)+`
9
- `,D=v(T).slice(0,16),M=[e.remotePrefix,"events",`${it(m.sequence)}-${it(w.sequence)}-${D}.jsonl`].join("/");await this.storage.exists(M)||await this.storage.put(M,T,"application/x-ndjson"),c+=g.length}let a=await this.scan(e),p=n[n.length-1],l=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?l="idle":p?.type==="error"?l="error":n.length>0&&(l="active");let y=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??y,updatedAt:p?.timestamp??y,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(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:y};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:c,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:l}}};import{closeSync as Te,existsSync as or,fsyncSync as ir,mkdirSync as ar,openSync as Me,readSync as cr,rmSync as at,statSync as ct,writeSync as ur}from"node:fs";import{join as Re}from"node:path";var lr=12e4,dr=80,pr=2e3;function mr(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var se=class{constructor(e){this.identity=e;ar(e.localDirectory,{recursive:!0}),this.eventsFile=Re(e.localDirectory,"events.jsonl"),this.stateFile=Re(e.localDirectory,"state.json"),this.lockFile=Re(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 rt(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){I(this.stateFile,e)}acquireLock(){for(let e=0;e<dr;e+=1)try{return Me(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-ct(this.lockFile).mtimeMs>lr){at(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{Te(n),at(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 y=l.timestamp??new Date().toISOString(),d=l.data??{},S=l.provenance?.rawDigest??v(nt(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,y,S].join("|"),g=v(h).slice(0,32);if(r.has(g))continue;s+=1;let m={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:y,data:d,provenance:{...l.provenance,rawDigest:S}};l.role!==void 0&&(m.role=l.role),l.sourceEventId!==void 0&&(m.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(m.sourceSequence=l.sourceSequence),o.push(m),r.add(g)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
9
+ `,O=w(A).slice(0,16),C=[e.remotePrefix,"events",`${Dt(g.sequence)}-${Dt(v.sequence)}-${O}.jsonl`].join("/");await this.storage.exists(C)||await this.storage.put(C,A,"application/x-ndjson"),c+=y.length}let u=await this.scan(e),p=n[n.length-1],l=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?l="idle":p?.type==="error"?l="error":n.length>0&&(l="active");let m=new Date().toISOString(),d=n[0],f={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:l,createdAt:o?.createdAt??d?.timestamp??m,updatedAt:p?.timestamp??m,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:u.maxSequence,chunkCount:u.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(f.title=s.title??o?.title);let h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:u.maxSequence,lastRemoteSequence:u.maxSequence,sourceCursors:r,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,f),{uploadedEvents:c,lastRemoteSequence:u.maxSequence,eventCount:f.eventCount,chunkCount:f.chunkCount,status:l}}};import{closeSync as et,existsSync as Cs,fsyncSync as Is,mkdirSync as As,openSync as tt,readSync as Es,rmSync as Wt,statSync as Ft,writeSync as Ps}from"node:fs";import{join as nt}from"node:path";var Ms=12e4,Ts=80,Os=2e3;function Rs(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ve=class{constructor(e){this.identity=e;As(e.localDirectory,{recursive:!0}),this.eventsFile=nt(e.localDirectory,"events.jsonl"),this.stateFile=nt(e.localDirectory,"state.json"),this.lockFile=nt(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 $t(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){E(this.stateFile,e)}acquireLock(){for(let e=0;e<Ts;e+=1)try{return tt(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-Ft(this.lockFile).mtimeMs>Ms){Wt(this.lockFile,{force:!0});continue}}catch{}Rs(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{et(n),Wt(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??{},f=l.provenance?.rawDigest??w(_t(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,f].join("|"),y=w(h).slice(0,32);if(r.has(y))continue;s+=1;let g={version:1,id:y,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:m,data:d,provenance:{...l.provenance,rawDigest:f}};l.role!==void 0&&(g.role=l.role),l.sourceEventId!==void 0&&(g.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(g.sourceSequence=l.sourceSequence),o.push(g),r.add(y)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
10
10
  `)+`
11
- `,u=Me(this.eventsFile,"a",384);try{ur(u,i,null,"utf8"),ir(u)}finally{Te(u)}let c=o[o.length-1],a="active";c.type==="session_end"||c.type==="session_idle"?a="idle":c.type==="error"&&(a="error");let p=Array.from(r).slice(-pr);return this.saveStateUnsafe({...n,status:a,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!or(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=ct(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=Me(this.eventsFile,"r");try{cr(i,o,0,s,r)}finally{Te(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 Wr,existsSync as zr,openSync as Br,readSync as qr,statSync as Vr}from"node:fs";function ut(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 mt=[/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],fr=[/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],gr=[/\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],yr=[/\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],hr=[/đã 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],lt=[/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],Sr=[/\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],vr=[/đườ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],br=[/\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],dt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),kr=new Set(["payload","data","content","message","messages","parts","summary"]);function C(t,e){return e.some(n=>n.test(t))}function ft(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function wr(t){return ft(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function xr(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 Ae(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||dt.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Ae(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(dt.has(s)||kr.has(s))&&Ae(o,s,n,r+1)}}function jr(t){let e=[];Ae(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=ft(o);if(xr(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function pt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Ir(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&C(t,mt)?{kind:"rule",confidence:.98}:r&&C(t,fr)?{kind:"rule",confidence:.92}:C(t,gr)?{kind:C(t,lt)?"architecture":"decision",confidence:r?.93:.86}:r&&C(t,yr)?{kind:"todo",confidence:.87}:C(t,lt)&&C(t,Sr)?{kind:"architecture",confidence:r?.88:.82}:s&&C(t,hr)?{kind:"fix",confidence:.8}:r&&C(t,vr)&&C(t,br)?{kind:"context",confidence:.79}:null}function Cr(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Er(t,e,n){return t==="rule"&&C(n,mt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":ut(e,n)}function gt(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=pt(o);i&&u&&s.set(i,u)}for(let o of e){let i=pt(o),u=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&u&&(i=s.get(u)??"");for(let c of jr(o)){let a=Ir(c,i,o);if(!a||a.confidence<.75)continue;let p=Cr(a.kind),l=wr(c),y=v([t.projectId,a.kind,l].join("|"));if(r.has(y))continue;r.add(y);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:y,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:p,content:c,confidence:a.confidence,importance:Er(a.kind,p,c),tags:[p],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 oe(t){return t?Math.ceil(t.length/3.5):0}function ie(t,e){if(!t)return"";if(oe(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=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),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 yt(t){return(t||$()).rawTranscript}function ht(t){return(t||$()).durableMemoryMaxItemsPerSession}function St(t){return(t||$()).sessionSummaryMaxTokens}function vt(t){return(t||$()).archiveRemote}function Or(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 Pr(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 Tr(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 p=a.toLowerCase().replace(/\s+/g," ");if(r.has(p))continue;r.add(p);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(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 y=Pr(a,l);if(y<.3)continue;let d=Or(a);n.push({category:l,text:d,importance:y,sourceSessionId:e})}}let s=$(),o=ht(s);return n.sort((i,u)=>u.importance-i.importance).slice(0,o)}function Mr(t){let e=$(),n=St(e),o=t.join(`
11
+ `,a=tt(this.eventsFile,"a",384);try{Ps(a,i,null,"utf8"),Is(a)}finally{et(a)}let c=o[o.length-1],u="active";c.type==="session_end"||c.type==="session_idle"?u="idle":c.type==="error"&&(u="error");let p=Array.from(r).slice(-Os);return this.saveStateUnsafe({...n,status:u,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Cs(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=tt(this.eventsFile,"r");try{Es(i,o,0,s,r)}finally{et(i)}return{events:o.toString("utf8").split(`
12
+ `).filter(Boolean).map(u=>JSON.parse(u)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as ji,existsSync as Ci,openSync as Ii,readSync as Ai,statSync as Ei}from"node:fs";function zt(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 Jt=[/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],Ns=[/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],_s=[/\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],$s=[/\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],Ks=[/đã 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],Bt=[/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],Ls=[/\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],Ds=[/đườ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],Ws=[/\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],Vt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Fs=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 zs(t){return Ht(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Bs(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 rt(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||Vt.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))rt(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(Vt.has(s)||Fs.has(s))&&rt(o,s,n,r+1)}}function Vs(t){let e=[];rt(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(Bs(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function qt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function qs(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,Jt)?{kind:"rule",confidence:.98}:r&&P(t,Ns)?{kind:"rule",confidence:.92}:P(t,_s)?{kind:P(t,Bt)?"architecture":"decision",confidence:r?.93:.86}:r&&P(t,$s)?{kind:"todo",confidence:.87}:P(t,Bt)&&P(t,Ls)?{kind:"architecture",confidence:r?.88:.82}:s&&P(t,Ks)?{kind:"fix",confidence:.8}:r&&P(t,Ds)&&P(t,Ws)?{kind:"context",confidence:.79}:null}function Js(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Hs(t,e,n){return t==="rule"&&P(n,Jt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":zt(e,n)}function Gt(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,a=qt(o);i&&a&&s.set(i,a)}for(let o of e){let i=qt(o),a=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&a&&(i=s.get(a)??"");for(let c of Vs(o)){let u=qs(c,i,o);if(!u||u.confidence<.75)continue;let p=Js(u.kind),l=zs(c),m=w([t.projectId,u.kind,l].join("|"));if(r.has(m))continue;r.add(m);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],f=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:u.kind,type:p,content:c,confidence:u.confidence,importance:Hs(u.kind,p,c),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:f,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}import{createHash as Gs}from"node:crypto";var Us=["project-knowledge","implementation","continuation","session-context"],Ys={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function st(t){return Gs("sha256").update(t).digest("hex")}function ke(t,e){return`${t}:${st(e).slice(0,24)}`}function Xs(t){try{return st(JSON.stringify(t))}catch{return st(String(t))}}function W(t){let e=new Set,n=[];for(let r of t){let s=r?.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function Yt(t,e=420){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:`${n.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`}function Qs(t){return t==="rule"||t==="architecture"?"project-knowledge":t==="decision"||t==="fix"?"implementation":t==="todo"?"continuation":"session-context"}function Ut(t){return t.length===0?0:t.reduce((e,n)=>e+n,0)/t.length}function Zs(t){return t.slice().sort((e,n)=>n.importanceScore-e.importanceScore||n.confidence-e.confidence||e.id.localeCompare(n.id)).slice(0,5).map(e=>Yt(e.content)).join(" | ")}function eo(t){return t.slice().sort((e,n)=>n.importanceScore-e.importanceScore||n.confidence-e.confidence||e.id.localeCompare(n.id)).slice(0,6).map(e=>Yt(e.content)).join(`
13
+ `)}function Xt(t,e){let n=t.slice().sort((m,d)=>m.sequence-d.sequence||m.timestamp.localeCompare(d.timestamp)||m.id.localeCompare(d.id)),r=n.map(m=>({id:ke("raw",[m.projectId,m.agent,m.nativeSessionId,m.id,String(m.sequence)].join("|")),level:"raw",eventId:m.id,sourceEventId:m.sourceEventId,sequence:m.sequence,type:m.type,role:m.role,timestamp:m.timestamp,sourcePath:m.provenance.sourcePath,payloadDigest:Xs(m.data)})),s=new Map,o=new Map;n.forEach((m,d)=>{let f=r[d];f&&(s.set(m.id,f.id),m.sourceEventId&&o.set(m.sourceEventId,f.id))});let i=e.map(m=>{let d=W([...m.provenance.eventIds.map(f=>s.get(f)),...m.provenance.sourceEventIds.map(f=>o.get(f))]);return{id:ke("fact",m.fingerprint),level:"fact",fingerprint:m.fingerprint,kind:m.kind,type:m.type,content:m.content,knowledgeClass:m.knowledgeClass,importanceScore:m.importanceScore,confidence:m.confidence,tags:W([...m.tags,"level:fact",`class:${m.knowledgeClass}`,`kind:${m.kind}`]),rawIds:d,sourcePaths:W(m.provenance.sourcePaths)}}),a=new Map;for(let m of i){let d=Qs(m.kind),f=a.get(d)??[];f.push(m),a.set(d,f)}let c=[];for(let m of Us){let d=a.get(m);if(!d?.length)continue;let f=d.slice().sort((y,g)=>g.importanceScore-y.importanceScore||g.confidence-y.confidence||y.id.localeCompare(g.id)),h=f.map(y=>y.id);c.push({id:ke("scene",`${m}|${h.join("|")}`),level:"scene",kind:m,title:Ys[m],summary:Zs(f),factIds:h,importanceScore:Math.max(...f.map(y=>y.importanceScore)),confidence:Ut(f.map(y=>y.confidence)),tags:W(["level:scene",`scene:${m}`,...f.flatMap(y=>y.tags)]),sourcePaths:W(f.flatMap(y=>y.sourcePaths))})}let u=new Map(i.map(m=>[m.id,m])),p=[];for(let m of c){let f=m.factIds.map(g=>u.get(g)).filter(g=>!!g).filter(g=>(g.knowledgeClass==="permanent"||g.knowledgeClass==="task")&&g.importanceScore>=.55);if(f.length===0)continue;let h=f.some(g=>g.knowledgeClass==="permanent")?"permanent":"task",y=eo(f);p.push({id:ke("knowledge",`${m.id}|${h}|${f.map(g=>g.id).join("|")}`),level:"knowledge",knowledgeClass:h,title:m.title,content:y,sceneIds:[m.id],factIds:f.map(g=>g.id),importanceScore:Math.max(...f.map(g=>g.importanceScore)),confidence:Ut(f.map(g=>g.confidence)),tags:W(["level:knowledge",`class:${h}`,`scene:${m.kind}`,...f.flatMap(g=>g.tags)]),sourcePaths:W(f.flatMap(g=>g.sourcePaths))})}let l=[];for(let m of i)for(let d of m.rawIds)l.push({from:d,to:m.id,type:"supports"});for(let m of c)for(let d of m.factIds)l.push({from:d,to:m.id,type:"belongs_to"});for(let m of p)for(let d of m.sceneIds)l.push({from:d,to:m.id,type:"promotes_to"});return{schema:"toolnet.memory-hierarchy.v1",version:1,raw:r,facts:i,scenes:c,knowledge:p,links:l,stats:{raw:r.length,facts:i.length,scenes:c.length,knowledge:p.length,links:l.length}}}function be(t){return t?Math.ceil(t.length/3.5):0}function xe(t,e){if(!t)return"";if(be(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
14
+ `),a=Math.max(o,i);return a>r*.7?s.slice(0,a+1):s}function F(){let t=pe(),e=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||e==="archive"||e==="full",r=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",s=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),o=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),a=n,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:a,archiveRemote:c}}function Qt(t){return(t||F()).rawTranscript}function Zt(t){return(t||F()).durableMemoryMaxItemsPerSession}function en(t){return(t||F()).sessionSummaryMaxTokens}function tn(t){return(t||F()).archiveRemote}function to(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 no(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 ro(t,e){let n=[],r=new Set;for(let i of t){let a=i.split(`
15
+ `).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let p=u.toLowerCase().replace(/\s+/g," ");if(r.has(p))continue;r.add(p);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(u)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(u)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(l="file");let m=no(u,l);if(m<.3)continue;let d=to(u);n.push({category:l,text:d,importance:m,sourceSessionId:e})}}let s=F(),o=Zt(s);return n.sort((i,a)=>a.importance-i.importance).slice(0,o)}function so(t){let e=F(),n=en(e),o=t.join(`
15
16
 
16
17
  `).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 ie(o,n)}function ae(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=Tr(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),p=s.filter(d=>d.category==="next_action").map(d=>d.text),l=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:Mr(r),decisions:o,projectRules:i,filesChanged:u,bugsFixed:c,commands:l,blockers:a,nextActions:p,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 Rr(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 Ar(t){switch(t){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function Nr(t){let e=Ar(t.importance);return Math.max(0,Math.min(1,e*.75+t.confidence*.25))}function _r(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 $r(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 Lr(t){let e=_r(t),n=Nr(t),r=$r(t.content);return{...t,knowledgeClass:e,importanceScore:n,retrievalTerms:r,tags:R([...t.tags,`class:${e}`,`kind:${t.kind}`])}}function Dr(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 Fr(t,e,n){let r=ae(Dr(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 bt(t,e){let n=Rr(e),r=gt(t,n).map(Lr),s=r.filter(a=>a.knowledgeClass!=="transient").sort((a,p)=>p.importanceScore-a.importanceScore),{summary:o,state:i}=Fr(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(p=>p.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 kt(t){return String(t).padStart(12,"0")}function Kr(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var ce=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(p=>p.sequence)),o=Math.max(...n.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},u=JSON.stringify(i,null,2)+`
21
- `,c=v(r.map(p=>p.fingerprint).sort().join("|")).slice(0,16),a=[Kr(e),"batches",`${kt(s)}-${kt(o)}-${c}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,u,"application/json"),a}};function Jr(t,e){if(!zr(t))return{events:[],nextOffset:e};let n=Vr(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=Br(t,"r");try{qr(i,o,0,s,r)}finally{Wr(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 ue=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["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Jr(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=bt(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 Zr,existsSync as es,openSync as ts,readSync as ns,statSync as rs}from"node:fs";var Hr=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 xt(t){return K(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(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))F(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Hr.has(r)||["data","payload","parts","messages"].includes(r))&&F(s,e,n+1)}}function le(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 wt(t){let e=K(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 x(t,e,n,r,s={}){let o=K(r),i=s.key??xt(o);return{version:1,id:v([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 Ur(t,e,n){let r=K(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(x(t,e,"goal",i[1],{confidence:.97}));let u=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);u?.[1]&&s.push(x(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 y=Number(a[1]),d=K(a[2]??""),S=d&&!wt(d)?`Phase ${y} - ${d}`:`Phase ${y}`;s.push(x(t,e,"phase",S,{key:`phase:${y}`,order:y,status:le(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(x(t,e,"task",p[2],{status:p[1].trim()?"completed":le(p[2]),confidence:.96}));let l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let y=l[1]?Number(l[1]):void 0,d=K(l[2]),S=wt(d);s.push(x(t,e,"task",S&&y!==void 0?`TODO ${y}`:d,{key:y!==void 0?`task:${y}`:xt(d),order:y,status:le(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 y=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");y&&s.push(x(t,e,"next_action",y,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(x(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(x(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(x(t,e,"decision",r,{confidence:.9})),s}function jt(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=[];F(i.data,c);for(let a of c)s(x(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let c=[];F(i.data,c);for(let a of c)s(x(t,i,"task",a,{status:le(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(x(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let c=[];F(i.data,c);for(let a of c)s(x(t,i,"test",a,{confidence:1}))}let u=[];F(i.data,u);for(let c of u)for(let a of c.split(/\n+/u))for(let p of Ur(t,i,a))s(p)}let o=e[e.length-1];return s(x(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function It(t){return String(t).padStart(12,"0")}var de=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=v(n.map(a=>a.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${It(r)}-${It(s)}-${u}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Ct}from"node:path";import{mkdirSync as Yr}from"node:fs";function Gr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function W(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Gr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Qr(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 Et(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&&Qr(e)?t.title:e.text;return{id:t?.id??v(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 Xr(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 pe(t,e){let r=(await Xr(t,e)).flatMap(f=>f.observations).sort((f,j)=>{let ze=f.occurredAt.localeCompare(j.occurredAt);if(ze!==0)return ze;let Be=f.sequence-j.sequence;return Be!==0?Be:f.id.localeCompare(j.id)}),s=new Map,o=new Map,i,u,c,a=[],p=[],l=[],y=[],d=[],S=[];for(let f of r)switch(f.kind){case"goal":i=f.text;break;case"plan":u=f.text;break;case"phase":s.set(f.key,Et(s.get(f.key),f));break;case"task":o.set(f.key,Et(o.get(f.key),f));break;case"decision":a.push(f.text);break;case"blocker":p.push(f.text);break;case"warning":l.push(f.text);break;case"next_action":y.push(f.text);break;case"file":d.push(f.text);break;case"test":S.push(f.text);break;case"session":c={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let h=Array.from(s.values()).sort((f,j)=>(f.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((f,j)=>(f.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),m=h.find(f=>f.status==="in_progress")??h.find(f=>f.status==="blocked")??h.find(f=>f.status==="pending"),w=g.find(f=>f.status==="in_progress")??g.find(f=>f.status==="blocked")??g.find(f=>f.status==="pending"),T=W([...y,...w?[w.title]:[],...!w&&m?[m.title]:[],...g.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),D=W([...p,...h.filter(f=>f.status==="blocked").map(f=>f.title),...g.filter(f=>f.status==="blocked").map(f=>f.title)],20),M={version:1,projectId:t.id,projectName:t.name,goal:i,plan:u,phases:h,tasks:g,decisions:W(a,20),blockers:D,warnings:W(l,20),nextActions:T,filesTouched:W(d,30),tests:W(S,20),currentPhase:m,currentTask:w,progress:{phasesTotal:h.length,phasesCompleted:h.filter(f=>f.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(f=>f.status==="completed").length,blocked:h.filter(f=>f.status==="blocked").length+g.filter(f=>f.status==="blocked").length},lastSession:c,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},_=Ct(t.rootPath,".toolnet","work");return Yr(_,{recursive:!0}),I(Ct(_,"current.json"),M),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(M,null,2)+`
25
- `,"application/json"),M}async function me(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 ss(t,e){if(!es(t))return{events:[],nextOffset:e};let n=rs(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=ts(t,"r");try{ns(i,o,0,s,r)}finally{Zr(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 fe=class{constructor(e){this.options=e;this.journal=new de(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=ss(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 pe(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 ms,existsSync as fs,openSync as gs,readSync as ys,statSync as hs}from"node:fs";var os=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function z(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))(os.has(r)||["data","payload","parts","messages"].includes(r))&&Ne(s,e,n+1)}}function E(t,e,n,r,s,o=.95){let i=z(r);return{version:1,id:v([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 P(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 z(t.slice(r.length+1))}return null}function is(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function as(t){return z(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function Ot(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 u of i){let c={type:"project"},a=null;for(let p of u.split(/\r?\n/u)){let l=z(p);if(!l){a=null;continue}let y=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(y){let j=Number(y[1]);c={type:"phase",key:`phase:${j}`,order:j,title:z(y[2]??"")},a=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let j=Number(d[1]);c={type:"task",key:`task:${j}`,order:j,title:z(d[2]??"")},a=null;continue}let S=P(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(E(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let h=P(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(E(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),a=null;continue}let g=P(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(E(t,o,c.type==="phase"?"phase_why":"why",g,c,.98)),a=null;continue}let m=P(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(m){s(E(t,o,"desired_outcome",m,{type:"project"},.98)),a=null;continue}let w=P(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(w){s(E(t,o,"plan_rationale",w,{type:"project"},.98)),a=null;continue}let T=P(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(T){s(E(t,o,"phase_deliverable",T,c,.97)),a=null;continue}let D=P(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(D){s(E(t,o,"acceptance_criterion",D,c,.98)),a="acceptance_criterion";continue}let M=P(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(M){s(E(t,o,"dependency",M,c,.97)),a="dependency";continue}let _=P(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(_){s(E(t,o,"open_question",_,c,.95)),a="open_question";continue}let f=P(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(f){s(E(t,o,"constraint",f,c,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){a="constraint";continue}if(a&&is(p)){s(E(t,o,a,as(p),c,.96));continue}a=null}}}return n}function Pt(t){return String(t).padStart(12,"0")}var ge=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=v(n.map(c=>c.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${Pt(r)}-${Pt(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 cs}from"node:fs";import{join as Tt}from"node:path";function us(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function ls(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 A(t,e){return ls(e,t)?e:t}function N(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 ds(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 ps(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function Mt(t,e){let r=(await ds(t,e)).flatMap(h=>h.observations).sort((h,g)=>{let m=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return m!==0?m:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),s,o,i,u,c,a=new Map,p=[],l=[],y=[];for(let h of r){let g=us(h);if(h.scope==="phase"&&h.scopeKey){let m=a.get(h.scopeKey)??ps(h);switch(h.kind){case"phase_objective":m.objective=A(m.objective,g);break;case"phase_why":m.why=A(m.why,g);break;case"phase_deliverable":m.deliverable=A(m.deliverable,g);break;case"acceptance_criterion":m.acceptanceCriteria.push(g);break;case"dependency":m.dependencies.push(g);break;case"open_question":m.openQuestions.push(g);break;case"constraint":m.constraints.push(g);break;case"note":m.notes.push(g);break}a.set(m.key,m);continue}switch(h.kind){case"mission":s=A(s,g);break;case"objective":o=A(o,g);break;case"why":i=A(i,g);break;case"desired_outcome":u=A(u,g);break;case"plan_rationale":c=A(c,g);break;case"open_question":p.push(g);break;case"constraint":l.push(g);break;case"note":y.push(g);break}}for(let h of a.values())h.acceptanceCriteria=N(h.acceptanceCriteria,20),h.dependencies=N(h.dependencies,15),h.openQuestions=N(h.openQuestions,15),h.constraints=N(h.constraints,15),h.notes=N(h.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((h,g)=>h.order-g.order),openQuestions:N(p,20),constraints:N(l,20),notes:N(y,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=Tt(t.rootPath,".toolnet","work");return cs(S,{recursive:!0}),I(Tt(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 Rt(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 Ss(t,e){if(!fs(t))return{events:[],nextOffset:e};let n=hs(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=gs(t,"r");try{ys(o,s,0,s.length,r)}finally{ms(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 ye=class{constructor(e){this.options=e;this.journal=new ge(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Ss(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=Ot(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Mt(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 Ts}from"node:fs";import{join as _e}from"node:path";import{existsSync as _t,mkdirSync as vs,readFileSync as bs,statSync as At,writeFileSync as ks}from"node:fs";import{dirname as ws,join as xs}from"node:path";var Nt=64*1024,js=`# ToolNet Project Operating Manual
18
+ `).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).join(`
19
+ `);return xe(o,n)}function je(t,e){let r=(Array.isArray(t)?t:t.split(`
20
+
21
+ `).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=ro(r,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),a=s.filter(d=>d.category==="file").map(d=>d.text),c=s.filter(d=>d.category==="fix").map(d=>d.text),u=s.filter(d=>d.category==="blocker").map(d=>d.text),p=s.filter(d=>d.category==="next_action").map(d=>d.text),l=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:so(r),decisions:o,projectRules:i,filesChanged:a,bugsFixed:c,commands:l,blockers:u,nextActions:p,durableFacts:s}}function K(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 oo(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 io(t){switch(t){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function ao(t){let e=io(t.importance);return Math.max(0,Math.min(1,e*.75+t.confidence*.25))}function co(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 uo(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 lo(t){let e=co(t),n=ao(t),r=uo(t.content);return{...t,knowledgeClass:e,importanceScore:n,retrievalTerms:r,tags:K([...t.tags,"level:fact",`class:${e}`,`kind:${t.kind}`])}}function po(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 mo(t,e,n){let r=je(po(e),t.nativeSessionId),s=n.filter(u=>u.kind==="todo").map(u=>u.content),o=n.flatMap(u=>u.provenance.sourcePaths),i=n.filter(u=>u.kind==="architecture").map(u=>u.content),a=K([...s,...r.nextActions]),c=K([...r.nextActions,...s]);return{summary:r.summary,state:{task:c[0]??a[0],decisions:K(r.decisions),files:K([...r.filesChanged,...o]),todos:a,completed:K(r.bugsFixed),blockers:K(r.blockers),nextActions:c,architecture:K(i)}}}function nn(t,e){let n=oo(e),r=Gt(t,n).map(lo),s=r.filter(p=>p.knowledgeClass!=="transient").sort((p,l)=>l.importanceScore-p.importanceScore),{summary:o,state:i}=mo(t,n,s),a=s.map(p=>({fingerprint:p.fingerprint,kind:p.kind,knowledgeClass:p.knowledgeClass,importanceScore:p.importanceScore,content:p.content,terms:p.retrievalTerms})),c=Xt(n,s),u=p=>r.filter(l=>l.knowledgeClass===p).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:a,hierarchy:c,stats:{inputEvents:e.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:s.length,permanent:u("permanent"),task:u("task"),session:u("session"),transient:u("transient")}}}import{createHash as fo}from"node:crypto";import{chmodSync as rn,existsSync as go,mkdirSync as yo,readFileSync as ho,renameSync as So,writeFileSync as sn}from"node:fs";import{dirname as on,join as Ce}from"node:path";var at="toolnet.context-offload.v1",wo="toolnet.context-offload-asset.v1",vo=256,ko=new Set(["tool_call","tool_result","file_read","file_write","file_edit","command","test","artifact"]);function an(t){return Ce(t,".toolnet","offload")}function bo(t){return Ce(an(t),"assets")}function cn(t){return Ce(an(t),"graph.json")}function un(t){yo(t,{recursive:!0,mode:448});try{rn(t,448)}catch{}}function xo(t,e){un(on(t));let n=`${t}.${process.pid}.${Date.now()}.tmp`;sn(n,e,{encoding:"utf8",mode:384}),So(n,t);try{rn(t,384)}catch{}}function it(t){return Array.isArray(t)?t.map(it):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).sort(([e],[n])=>e.localeCompare(n)).map(([e,n])=>[e,it(n)])):t}function jo(t){return fo("sha256").update(JSON.stringify(it(t)),"utf8").digest("hex")}function ot(){return{schema:at,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function Co(t){let e=cn(t);if(!go(e))return ot();try{let n=JSON.parse(ho(e,"utf8"));return n.schema!==at||n.version!==1||!Array.isArray(n.nodes)?ot():n}catch{return ot()}}function Io(t,e){xo(cn(t),JSON.stringify(e,null,2)+`
22
+ `)}function Ao(t,e=260){if(typeof t!="string")return null;let n=t.replace(/\s+/gu," ").trim();return n?n.slice(0,e):null}function Eo(t){let e=[...t.provenance.files??[],t.provenance.sourcePath],n=[];for(let r of e){let s=Ao(r);if(!(!s||n.includes(s))&&(n.push(s),n.length===3))break}return n}function Po(t){return`${t.agent}:${t.sourceEventId??t.id}`.replace(/\s+/gu," ").trim().slice(0,120)}function Mo(t,e){un(on(t));try{return sn(t,e,{encoding:"utf8",flag:"wx",mode:384}),!0}catch(n){if(n.code==="EEXIST")return!1;throw n}}function To(t,e){let n=t.nodes.find(s=>s.id===e.id),r=n?{...n,kind:e.kind,bytes:e.bytes,sourceRefs:Array.from(new Set([...n.sourceRefs,...e.sourceRefs])).slice(-8),files:Array.from(new Set([...n.files,...e.files])).slice(0,6)}:e;return{schema:at,version:1,updatedAt:new Date().toISOString(),nodes:[...t.nodes.filter(s=>s.id!==e.id),r].slice(-vo)}}function ln(t,e){let n=Co(t),r=0,s=0,o=0,i=[];for(let a of e){if(!ko.has(a.type))continue;r+=1;let c=jo({type:a.type,data:a.data}),u={schema:wo,version:1,assetId:c,event:{type:a.type,agent:a.agent,nativeSessionId:a.nativeSessionId,timestamp:a.timestamp,sourceEventId:a.sourceEventId,provenance:a.provenance,data:a.data}},p=JSON.stringify(u,null,2)+`
23
+ `;Mo(Ce(bo(t),`${c}.json`),p)?s+=1:o+=1,i.push(c),n=To(n,{id:c,kind:a.type,bytes:Buffer.byteLength(p,"utf8"),createdAt:a.timestamp,sourceRefs:[Po(a)],files:Eo(a)})}return r>0&&Io(t,n),{eligible:r,written:s,deduped:o,graphNodes:n.nodes.length,assetIds:i}}import{createHash as Do}from"node:crypto";import{existsSync as Wo,readdirSync as Fo,readFileSync as zo}from"node:fs";import{basename as Bo,join as An}from"node:path";import{randomUUID as mn}from"node:crypto";var x=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function re(t){let e=new Set,n=[];for(let r of t){let s=r.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function B(t){let e=t.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!e)throw new x("Invalid Wiki slug",400);return e}function dn(t){let e=[];for(let n of t.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&e.push(B(r))}return re(e)}function Oo(t){return t.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function pn(t){return{id:`revision-${mn()}`,pageId:t.id,slug:t.slug,revision:t.revision,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...t.tags],links:[...t.links],createdAt:t.updatedAt}}function z(t){return structuredClone(t)}var Ie=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(e){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=e(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let e=await this.ensureState(),n=new Set(e.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:e.projectId,pages:e.pages.length,revisions:e.revisions.length,tags:re(e.pages.flatMap(r=>r.tags)).sort((r,s)=>r.localeCompare(s)),links:e.pages.reduce((r,s)=>r+s.links.length,0),orphanPages:e.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:e.pages.filter(r=>r.tags.some(s=>s.startsWith("toolnet-auto-"))).length,updatedAt:e.updatedAt}}async listPages(){let e=await this.ensureState();return z([...e.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(e){let n=await this.ensureState(),r=B(e),s=n.pages.find(o=>o.slug===r||o.id===e);if(!s)throw new x(`Wiki page not found: ${e}`,404);return z(s)}async createPage(e){return this.mutate(n=>{let r=e.title.trim(),s=e.content.trim();if(!r)throw new x("Wiki title is required",400);let o=B(e.slug??r);if(n.pages.some(c=>c.slug===o))throw new x(`Wiki page already exists: ${o}`,409);let i=new Date().toISOString(),a={id:`wiki-${mn()}`,slug:o,title:r,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:s,tags:re(e.tags??[]),links:dn(s),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(pn(a)),z(a)})}async updatePage(e,n){return this.mutate(r=>{let s=B(e),o=r.pages.find(i=>i.slug===s||i.id===e);if(!o)throw new x(`Wiki page not found: ${e}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new x("Wiki title is required",400);o.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?o.summary=i:delete o.summary}return n.content!==void 0&&(o.content=n.content.trim(),o.links=dn(o.content)),n.tags!==void 0&&(o.tags=re(n.tags)),o.revision+=1,o.updatedAt=new Date().toISOString(),r.revisions.push(pn(o)),z(o)})}async history(e){let n=await this.getPage(e),r=await this.ensureState();return z(r.revisions.filter(s=>s.pageId===n.id).sort((s,o)=>o.revision-s.revision))}async backlinks(e){let n=await this.getPage(e),r=await this.ensureState();return z(r.pages.filter(s=>s.links.includes(n.slug)).sort((s,o)=>s.title.localeCompare(o.title)))}async search(e,n=10){let r=await this.ensureState(),s=re(Oo(e));if(s.length===0)return[];let o=Math.max(1,Math.min(20,Math.floor(n))),i=[];for(let a of r.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),p=a.summary?.toLowerCase()??"",l=a.content.toLowerCase(),m=a.tags.map(f=>f.toLowerCase()),d=0;for(let f of s)u===f&&(d+=12),c===f&&(d+=10),c.includes(f)&&(d+=6),u.includes(f)&&(d+=5),m.some(h=>h===f)?d+=5:m.some(h=>h.includes(f))&&(d+=3),p.includes(f)&&(d+=2),l.includes(f)&&(d+=1);d>0&&i.push({page:z(a),score:d})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,o)}};var fn="wiki/state.v1.json";function Ro(t){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:t.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function No(t,e){let n=JSON.parse(t);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==e.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var Ae=class{constructor(e,n){this.storage=e;this.project=n}storage;project;async load(){let e=await this.storage.getText(fn);if(!e){let n=Ro(this.project);return await this.save(n),n}return No(e,this.project)}async save(e){await this.storage.put(fn,JSON.stringify(e,null,2),"application/json")}};import{createHash as _o,randomUUID as gn}from"node:crypto";var yn="wiki/governance.v1.json",vn="toolnet.knowledge-governance.v1",hn=500,se={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function $o(t,e=0,n=1){return Math.max(e,Math.min(n,t))}function ct(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function Sn(t){return _o("sha256").update(t.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function Ko(t){let e=[t.title,t.summary??"",t.content.slice(0,2e3),...t.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(e)}function Lo(t){let e=t.sourceType==="skill"?.96:t.sourceType==="memory"?.94:.88,n=t.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(e+=.03),t.content.length>=200&&(e+=.02),t.content.length<80&&(e-=.05),t.title.length<4&&(e-=.05),$o(e)}function wn(t){let e=new Date().toISOString();return{schema:vn,version:1,projectId:t,policy:{...se},reviews:[],audit:[],createdAt:e,updatedAt:e}}function kn(t){let e=t.autoApproveThreshold??se.autoApproveThreshold,n=t.criticalApproveThreshold??se.criticalApproveThreshold,r=t.staleAfterDays??se.staleAfterDays;if(!Number.isFinite(e)||e<.5||e>1)throw new x("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new x("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new x("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:n,staleAfterDays:r}}var Ee=class{constructor(e,n){this.storage=e;this.project=n}storage;project;async load(){let e=await this.storage.getText(yn);if(!e){let n=wn(this.project.id);return await this.save(n),n}try{let n=JSON.parse(e);if(n.schema!==vn||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:kn(n.policy??se)}}catch{let n=wn(this.project.id);return await this.save(n),n}}async save(e){await this.storage.put(yn,JSON.stringify(e,null,2),"application/json")}},Pe=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(e,n,r,s={}){e.audit.push({id:gn(),action:n,principal:r,...s.reviewId?{reviewId:s.reviewId}:{},...s.sourceKey?{sourceKey:s.sourceKey}:{},timestamp:new Date().toISOString(),...s.metadata?{metadata:s.metadata}:{}}),e.audit.length>hn&&(e.audit=e.audit.slice(-hn))}async mutate(e){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=await e(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(e,n){return this.mutate(r=>(r.policy=kn({...r.policy,...e}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let e=await this.ensureState(),n=r=>e.reviews.filter(s=>s.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:e.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:e.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:e.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:e.audit.length,policy:{...e.policy},updatedAt:e.updatedAt}}async listReviews(e){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!e||r.status===e).sort((r,s)=>s.updatedAt.localeCompare(r.updatedAt)))}async auditLog(e=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(e)));return structuredClone(n.audit.slice(-r).reverse())}async assess(e,n){let r=await this.ensureState(),s=Lo(e),o=ct(e.title),i=n.filter(p=>p.slug!==e.slug&&ct(p.title)===o&&Sn(p.content)!==Sn(e.content)).map(p=>p.slug),a=Ko(e),c=[];s<r.policy.autoApproveThreshold&&c.push(`confidence:${s.toFixed(2)}`),a&&s<r.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:s,risk:u,requiresReview:i.length>0||s<r.policy.autoApproveThreshold||a&&s<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(e,n){let r=await this.assess(e,n);return this.mutate(s=>{let o=s.reviews.find(c=>c.sourceKey===e.sourceKey&&c.digest===e.digest);if(o?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(o)};if(o?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(o)};if(!r.requiresReview)return this.audit(s,"knowledge:auto-approved","system",{sourceKey:e.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(o?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(o)};let i=new Date().toISOString(),a={id:gn(),sourceKey:e.sourceKey,sourceType:e.sourceType,slug:e.slug,marker:e.marker,digest:e.digest,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...new Set([...e.tags,e.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};return s.reviews.push(a),this.audit(s,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(a)}})}async markApplied(e,n){await this.mutate(r=>{let s=r.reviews.find(o=>o.sourceKey===e&&o.digest===n&&o.status==="approved");s&&(s.appliedAt=new Date().toISOString(),s.updatedAt=s.appliedAt,this.audit(r,"knowledge:applied",s.reviewedBy??"system",{reviewId:s.id,sourceKey:e}))})}async decide(e,n,r){return this.mutate(async s=>{let o=s.reviews.find(u=>u.id===e);if(!o)throw new x(`Governance review not found: ${e}`,404);if(o.status!=="pending")throw new x("Governance review is already resolved",409);let i=new Date().toISOString();if(o.reviewedAt=i,o.reviewedBy=n.principal,o.updatedAt=i,n.note?.trim()&&(o.reviewNote=n.note.trim()),n.action==="reject")return o.status="rejected",this.audit(s,"knowledge:rejected",n.principal,{reviewId:e,sourceKey:o.sourceKey}),structuredClone(o);if(n.action==="supersede")return o.status="superseded",n.targetReviewId&&(o.supersededBy=n.targetReviewId),this.audit(s,"knowledge:superseded",n.principal,{reviewId:e,sourceKey:o.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(o);if(n.action==="merge"){if(!n.targetReviewId)throw new x("targetReviewId is required for merge",400);let u=s.reviews.find(p=>p.id===n.targetReviewId);if(!u)throw new x("Merge target review not found",404);return o.status="superseded",o.mergedInto=u.id,this.audit(s,"knowledge:merged",n.principal,{reviewId:e,sourceKey:o.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(o)}o.status="approved";let c=(await r.listPages()).find(u=>u.slug===o.slug);if(c&&!c.tags.includes(o.marker))throw new x(`Wiki page '${o.slug}' is manually managed`,409);return c?await r.updatePage(o.slug,{title:o.title,summary:o.summary??"",content:o.content,tags:o.tags}):await r.createPage({slug:o.slug,title:o.title,...o.summary?{summary:o.summary}:{},content:o.content,tags:o.tags}),o.appliedAt=i,this.audit(s,"knowledge:approved",n.principal,{reviewId:e,sourceKey:o.sourceKey}),structuredClone(o)})}async quality(e){let n=await this.ensureState(),r=await e.listPages(),s=Date.now(),o=n.policy.staleAfterDays*864e5,i=r.map(p=>{let l=s-Date.parse(p.updatedAt);return{slug:p.slug,title:p.title,updatedAt:p.updatedAt,ageDays:Math.max(0,Math.floor(l/864e5)),stale:Number.isFinite(l)&&l>o}}).filter(p=>p.stale).map(({stale:p,...l})=>l),a=new Map;for(let p of r){let l=ct(p.title),m=a.get(l)??[];m.push(p),a.set(l,m)}let c=[...a.entries()].filter(([,p])=>p.length>1).map(([p,l])=>({title:p,pages:l.map(m=>m.slug)})),u=n.reviews.filter(p=>p.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(p=>p.tags.some(l=>l.startsWith("toolnet-auto-"))).length,manualPages:r.filter(p=>!p.tags.some(l=>l.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(p=>p.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(p=>p.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var En="wiki/automation.v1.json",Pn="toolnet.wiki-automation.v1",dt=8e3,bn=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function ie(t){return Do("sha256").update(JSON.stringify(t)).digest("hex")}function oe(t){if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function xn(t){return Array.isArray(t)?t:[]}function Mn(t){return typeof t!="string"?void 0:t.replace(/\s+/gu," ").trim()||void 0}function ut(t){return Array.isArray(t)?t.map(Mn).filter(e=>!!e):[]}function R(t,e){for(let n of e){let r=Mn(t[n]);if(r)return r}}function ae(t){let e=new Set,n=[];for(let r of t){let s=r.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function Me(t,e=0,n=""){if(e>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(bn.has(r))return[];if(typeof t=="string"){let i=t.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(t))return t.flatMap(i=>Me(i,e+1,n));let s=oe(t);if(!s)return[];let o=[];for(let[i,a]of Object.entries(s)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();bn.has(c)||o.push(...Me(a,e+1,i))}return o}function jn(t){let n=ae(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(s=>Me(t[s],0,s)));return(n.length>0?n:ae(Me(t))).join(`
24
+
25
+ `).slice(0,dt)}function Cn(t,e){return R(t,["id","key","fingerprint","knowledgeId","sceneId"])??e}function In(t,e){return R(t,["title","name","topic","label","task","kind","type"])??e}function Vo(t){return(R(t,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function qo(t){return(R(t,["kind","sceneKind","type"])??"").toLowerCase()}function Jo(t){let e=oe(t);if(!e)return[];let n=[],r=xn(e.knowledge);for(let[o,i]of r.entries()){let a=oe(i);if(!a)continue;let c=Vo(a);if(c==="session"||c==="transient")continue;let u=jn(a);if(u.length<20)continue;let p=Cn(a,ie(a).slice(0,16)),l=In(a,`Durable Memory ${o+1}`);n.push({sourceKey:`memory:${p}`,sourceType:"memory",title:l,summary:R(a,["summary","description"]),content:u,tags:ae(["toolnet","auto","memory",...c?[c]:[]])})}let s=xn(e.scenes);for(let[o,i]of s.entries()){let a=oe(i);if(!a)continue;let c=qo(a);if(c==="session-context")continue;let u=jn(a);if(u.length<20)continue;let p=Cn(a,ie(a).slice(0,16)),l=In(a,`Knowledge Scene ${o+1}`);n.push({sourceKey:`scene:${p}`,sourceType:"scene",title:l,summary:R(a,["summary","description"]),content:u,tags:ae(["toolnet","auto","scene",...c?[c]:[]])})}return n}function Ho(t){return An(t,".toolnet","memory","skills")}function Go(t){let e=Ho(t);if(!Wo(e))return{candidates:[],failed:0};let n=[],r=0,s=Fo(e).filter(o=>o.endsWith(".json")).sort();for(let o of s)try{let i=JSON.parse(zo(An(e,o),"utf8")),a=oe(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let c=R(a,["id","fingerprint"])??Bo(o,".json"),u=R(a,["task"])??"",p=R(a,["title"])||u||`Reusable Skill ${c.slice(0,8)}`,l=R(a,["summary"])??void 0,m=ut(a.steps),d=ut(a.verification),f=ut(a.files),h=[];u&&h.push(`## Task
26
+ ${u}`),l&&h.push(`## Summary
27
+ ${l}`),m.length>0&&h.push(`## Procedure
28
+ ${m.map((g,v)=>`${v+1}. ${g}`).join(`
29
+ `)}`),d.length>0&&h.push(`## Verification
30
+ ${d.map(g=>`- ${g}`).join(`
31
+ `)}`),f.length>0&&h.push(`## Relevant Files
32
+ ${f.map(g=>`- \`${g}\``).join(`
33
+ `)}`);let y=h.join(`
34
+
35
+ `).slice(0,dt);if(y.length<20)continue;n.push({sourceKey:`skill:${c}`,sourceType:"skill",title:p,summary:l,content:y,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function lt(t){let e=new Date().toISOString();return{schema:Pn,version:1,projectId:t,entries:[],createdAt:e,updatedAt:e}}async function Uo(t,e){let n=await t.getText(En);if(!n)return lt(e);try{let r=JSON.parse(n);return r.schema!==Pn||r.version!==1||r.projectId!==e||!Array.isArray(r.entries)?lt(e):r}catch{return lt(e)}}async function Yo(t,e){await t.put(En,JSON.stringify(e,null,2),"application/json")}function Xo(t){return`toolnet-auto-${ie(t).slice(0,12)}`}function Qo(t){let e=B(t.title).slice(0,72),n=ie(t.sourceKey).slice(0,10);return B(`auto-${t.sourceType}-${e}-${n}`)}function Zo(t){return[`> Auto-generated by ToolNet Knowledge Automation from ${t.sourceType==="skill"?"reusable Skill Memory":t.sourceType==="scene"?"semantic memory scene":"durable memory"}.`,"",t.content].join(`
36
+ `).slice(0,dt)}function ei(t){return ie({sourceType:t.sourceType,title:t.title,summary:t.summary,content:t.content,tags:t.tags})}function ti(t,e){return t.tags.includes(e)}async function Tn(t){let e=Jo(t.hierarchy),n=Go(t.project.rootPath),r=new Map;for(let d of[...e,...n.candidates])r.set(d.sourceKey,d);let s=[...r.values()].sort((d,f)=>d.sourceKey.localeCompare(f.sourceKey)),o={schema:"toolnet.wiki-automation-result.v1",scanned:e.length+n.candidates.length,eligible:s.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new Ie(new Ae(t.storage,t.project));await i.initialize();let a=new Pe(new Ee(t.storage,t.project));await a.initialize();let c=await Uo(t.storage,t.project.id),u=await i.listPages(),p=new Map(u.map(d=>[d.slug,d])),l=new Map(c.entries.map(d=>[d.sourceKey,d]));for(let d of s)try{let f=Xo(d.sourceKey),h=ei(d),y=l.get(d.sourceKey),g=y?.slug??Qo(d),v=p.get(g);if(v&&!ti(v,f)){o.skipped+=1;continue}let A=ae([...d.tags,f]),O=Zo(d),C=await a.gate({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:g,marker:f,digest:h,title:d.title,...d.summary?{summary:d.summary}:{},content:O,tags:A},[...p.values()]);if(!C.allowed){C.mode==="pending-review"?o.reviewPending+=1:o.skipped+=1;continue}C.mode==="auto-approved"?o.autoApproved+=1:C.mode==="review-approved"&&(o.reviewApproved+=1),v?y?.digest!==h?(v=await i.updatePage(g,{title:d.title,summary:d.summary??"",content:O,tags:A}),p.set(v.slug,v),o.updated+=1,o.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:v.slug,action:"updated"})):(o.unchanged+=1,o.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:g,action:"unchanged"})):(v=await i.createPage({slug:g,title:d.title,summary:d.summary,content:O,tags:A}),p.set(v.slug,v),o.created+=1,o.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:v.slug,action:"created"}));let _=new Date().toISOString(),S={sourceKey:d.sourceKey,sourceType:d.sourceType,slug:g,digest:h,marker:f,updatedAt:_},j=c.entries.findIndex(de=>de.sourceKey===d.sourceKey);j>=0?c.entries[j]=S:c.entries.push(S),l.set(d.sourceKey,S),await a.markApplied(d.sourceKey,h)}catch(f){if(f instanceof x&&f.statusCode===409){o.skipped+=1;continue}o.failed+=1}let m=new Date().toISOString();return c.updatedAt=m,c.lastRunAt=m,c.entries.sort((d,f)=>d.sourceKey.localeCompare(f.sourceKey)),await Yo(t.storage,c),o}import{createHash as ni}from"node:crypto";import{chmodSync as Rn,existsSync as ri,mkdirSync as si,readFileSync as Dl,readdirSync as Wl,renameSync as oi,statSync as Fl,writeFileSync as ii}from"node:fs";import{join as Nn}from"node:path";var ai="toolnet.skill-memory.v1",On=5,ci=16,ui=24,li=32;function di(t){return ni("sha256").update(t).digest("hex")}function ue(t,e=Number.MAX_SAFE_INTEGER){let n=new Set,r=[];for(let s of t){let o=s.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=e))break}return r}function pt(t,e=360){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function pi(t){return t.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/giu,"Bearer [REDACTED]").replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu,"[REDACTED]").replace(/\b(api[_-]?key|token|password|passwd|secret)\b(\s*[:=]\s*)(["']?)[^\s"'`]+/giu,"$1$2[REDACTED]")}function $(t,e=360){return t&&pt(pi(t),e)||void 0}function le(t,e){for(let n of e){let r=t[n];if(typeof r=="string"&&r.trim())return r}}function _n(t,e){for(let n of e){let r=t[n];if(typeof r=="number"&&Number.isFinite(r))return r;if(typeof r=="string"&&r.trim()&&Number.isFinite(Number(r)))return Number(r)}}function $n(t,e){for(let n of e){let r=t[n];if(typeof r=="boolean")return r;if(typeof r=="string"){let s=r.trim().toLowerCase();if(["true","yes","pass","passed","success","succeeded","ok"].includes(s))return!0;if(["false","no","fail","failed","error"].includes(s))return!1}}}function Kn(t){let e=t.data??{};if($n(e,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=_n(e,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let s=le(e,["status","result","outcome"]);return!!(s&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(s))}function ce(t){let e=t.data??{};if(Kn(t))return!1;if($n(e,["passed","pass","success","succeeded","ok"])===!0||_n(e,["exitCode","exit_code","code","statusCode"])===0)return!0;let s=le(e,["status","result","outcome"]);return s&&/\b(pass(?:ed)?|success(?:ful)?|succeeded|ok|green|complete(?:d)?)\b/iu.test(s)?!0:t.type==="commit"||t.type==="deploy"}function Ln(t){let e=t.data??{},n=le(e,["path","file","filePath","filename","target"]);if(n)return $(n,260);let r=t.provenance?.files;return $(r?.[0],260)}function mt(t){return $(le(t.data??{},["command","cmd","script"]),420)}function q(t){return $(le(t.data??{},["name","test","suite","title","message","text","result","status"]),300)}function mi(t){let e=[];for(let n of[...t].sort((r,s)=>r.sequence-s.sequence))if(ce(n)){if(n.type==="test"){let r=q(n)??mt(n)??"Tests passed";e.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=q(n);e.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=q(n);e.push(r?`Deploy: ${r}`:"Deployment completed")}}return ue(e,10)}function fi(t,e){let n=[];for(let r of[...t].sort((s,o)=>s.sequence-o.sequence))switch(r.type){case"file_write":case"file_edit":{let s=Ln(r);s&&n.push(`Update ${s}`);break}case"command":{if(Kn(r))break;let s=mt(r);s&&n.push(`Run: ${s}`);break}case"test":{if(!ce(r))break;let s=q(r)??mt(r)??"project tests";n.push(`Verify: ${s}`);break}case"commit":{if(!ce(r))break;let s=q(r);n.push(s?`Commit: ${s}`:"Commit verified changes");break}case"deploy":{if(!ce(r))break;let s=q(r);n.push(s?`Deploy: ${s}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of e.files.slice(0,8)){let s=$(r,260);s&&n.push(`Update ${s}`)}return ue(n,ci)}function gi(t,e){let n=[...e.files];for(let r of t){let s=Ln(r);s&&n.push(s);for(let o of r.provenance?.files??[]){let i=$(o,260);i&&n.push(i)}}return ue(n,ui)}function yi(t){return ue(t.filter(e=>["file_write","file_edit","command","test","commit","deploy"].includes(e.type)).map(e=>e.id),li)}function hi(t){return t.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function Dn(t,e,n){if(e.length===0)return[];let r=mi(e),s=ue(n.completed.map(f=>$(f,280)??""),On);if(!(s.length>0||e.some(f=>["test","commit","deploy"].includes(f.type)&&ce(f))))return[];let i=$(n.task,280)??$(n.nextActions[0],280),a=s.length>0?s:i?[i]:[];if(a.length===0)return[];let c=fi(e,n);if(c.length===0)return[];let u=gi(e,n),p=yi(e),l=Math.min(...e.map(f=>f.sequence)),m=Math.max(...e.map(f=>f.sequence)),d=hi(e);return a.slice(0,On).map(f=>{let h=[`Reusable procedure learned from successful task: ${f}.`,u.length>0?`Files: ${u.slice(0,6).join(", ")}.`:"",r.length>0?`Verification: ${r.slice(0,4).join("; ")}.`:""].filter(Boolean),y=JSON.stringify({projectId:t.projectId,task:f,steps:c,verification:r,files:u}),g=di(y);return{schema:ai,version:1,id:`skill-${g.slice(0,24)}`,fingerprint:g,projectId:t.projectId,title:pt(`SOP: ${f}`,180),task:f,summary:pt(h.join(" "),900),steps:c,verification:r,files:u,source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:l,lastSequence:m,eventIds:p},createdAt:d}})}function Si(t){return Nn(t.rootPath,".toolnet","memory","skills")}function wi(t){let e=Si(t);return si(e,{recursive:!0,mode:448}),Rn(e,448),e}function Wn(t,e){if(e.length===0)return{written:0,deduped:0,files:[]};let n=wi(t),r=0,s=0,o=[];for(let i of e){if(i.projectId!==t.id)throw new Error(`Skill project mismatch: ${i.projectId} != ${t.id}`);let a=Nn(n,`${i.id}.json`);if(o.push(a),ri(a)){s+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;ii(c,JSON.stringify(i,null,2)+`
37
+ `,{encoding:"utf8",mode:384}),oi(c,a),Rn(a,384),r+=1}return{written:r,deduped:s,files:o}}function Fn(t){return String(t).padStart(12,"0")}function vi(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var Te=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(p=>p.sequence)),o=Math.max(...n.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},a=JSON.stringify(i,null,2)+`
38
+ `,c=w(r.map(p=>p.fingerprint).sort().join("|")).slice(0,16),u=[vi(e),"batches",`${Fn(s)}-${Fn(o)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,a,"application/json"),u}};import{createHash as ki}from"node:crypto";function zn(t){return String(t).padStart(12,"0")}function bi(t){return ki("sha256").update(t).digest("hex")}function xi(t){return t.remotePrefix.replace("/sessions/","/memory/hierarchy/")}var Oe=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(n.length===0||r.facts.length===0)return null;let s=Math.min(...n.map(u=>u.sequence)),o=Math.max(...n.map(u=>u.sequence)),i={schema:"toolnet.memory-hierarchy-batch.v1",version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,hierarchy:r},a=bi([...r.facts.map(u=>u.id),...r.knowledge.map(u=>u.id)].sort().join("|")).slice(0,16),c=[xi(e),"batches",`${zn(s)}-${zn(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,`${JSON.stringify(i,null,2)}
39
+ `,"application/json"),c}};function Pi(t,e){if(!Ci(t))return{events:[],nextOffset:e};let n=Ei(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=Ii(t,"r");try{Ai(i,o,0,s,r)}finally{ji(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
40
+ `);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
41
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Re=class{constructor(e){this.options=e;this.journal=new Te(e.storage),this.hierarchyJournal=new Oe(e.storage)}options;journal;hierarchyJournal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Pi(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=nn(this.options.identity,s.events),i=o.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,s.events,i));let c=!1;o.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,s.events,o.hierarchy));let u=Dn(this.options.identity,s.events,o.state),p=Wn(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",o.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",o.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",o.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",o.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",o.hierarchy.stats.knowledge),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.journal_written",c?1:0),this.options.wal.setSourceCursor("memory.skill.assets",u.length),this.options.wal.setSourceCursor("memory.skill.written",p.written),this.options.wal.setSourceCursor("memory.skill.deduped",p.deduped);try{let l=ln(this.options.project.rootPath,s.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",l.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",l.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",l.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",l.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let l=await Tn({project:this.options.project,storage:this.options.storage,hierarchy:o.hierarchy});this.options.wal.setSourceCursor("memory.wiki_automation.scanned",l.scanned),this.options.wal.setSourceCursor("memory.wiki_automation.eligible",l.eligible),this.options.wal.setSourceCursor("memory.wiki_automation.created",l.created),this.options.wal.setSourceCursor("memory.wiki_automation.updated",l.updated),this.options.wal.setSourceCursor("memory.wiki_automation.unchanged",l.unchanged),this.options.wal.setSourceCursor("memory.wiki_automation.skipped",l.skipped),this.options.wal.setSourceCursor("memory.wiki_automation.failed",l.failed),this.options.wal.setSourceCursor("memory.wiki_automation.review_pending",l.reviewPending),this.options.wal.setSourceCursor("memory.wiki_automation.auto_approved",l.autoApproved),this.options.wal.setSourceCursor("memory.wiki_automation.review_approved",l.reviewApproved)}catch{this.options.wal.setSourceCursor("memory.wiki_automation.failed",1)}return this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:i.length,journalWritten:a,nextOffset:s.nextOffset}}};import{closeSync as $i,existsSync as Ki,openSync as Li,readSync as Di,statSync as Wi}from"node:fs";var Mi=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function H(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Vn(t){return H(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function J(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))J(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Mi.has(r)||["data","payload","parts","messages"].includes(r))&&J(s,e,n+1)}}function Ne(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function Bn(t){let e=H(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function I(t,e,n,r,s={}){let o=H(r),i=s.key??Vn(o);return{version:1,id:w([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 Ti(t,e,n){let r=H(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(I(t,e,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&s.push(I(t,e,"plan",a[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,u;for(;!o&&(u=c.exec(r));){let m=Number(u[1]),d=H(u[2]??""),f=d&&!Bn(d)?`Phase ${m} - ${d}`:`Phase ${m}`;s.push(I(t,e,"phase",f,{key:`phase:${m}`,order:m,status:Ne(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(I(t,e,"task",p[2],{status:p[1].trim()?"completed":Ne(p[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=H(l[2]),f=Bn(d);s.push(I(t,e,"task",f&&m!==void 0?`TODO ${m}`:d,{key:m!==void 0?`task:${m}`:Vn(d),order:m,status:Ne(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(I(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(I(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(I(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(I(t,e,"decision",r,{confidence:.9})),s}function qn(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=[];J(i.data,c);for(let u of c)s(I(t,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];J(i.data,c);for(let u of c)s(I(t,i,"task",u,{status:Ne(u),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let u=i.data[c];typeof u=="string"&&u&&s(I(t,i,"file",u,{confidence:1}))}if(i.type==="test"){let c=[];J(i.data,c);for(let u of c)s(I(t,i,"test",u,{confidence:1}))}let a=[];J(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let p of Ti(t,i,u))s(p)}let o=e[e.length-1];return s(I(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function Jn(t){return String(t).padStart(12,"0")}var _e=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.sequence)),s=Math.max(...n.map(u=>u.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
42
+ `,a=w(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Jn(r)}-${Jn(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Hn}from"node:path";import{mkdirSync as Oi}from"node:fs";function Ri(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function G(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Ri(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Ni(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 Gn(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&&Ni(e)?t.title:e.text;return{id:t?.id??w(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 _i(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}async function $e(t,e){let r=(await _i(t,e)).flatMap(S=>S.observations).sort((S,j)=>{let de=S.occurredAt.localeCompare(j.occurredAt);if(de!==0)return de;let bt=S.sequence-j.sequence;return bt!==0?bt:S.id.localeCompare(j.id)}),s=new Map,o=new Map,i,a,c,u=[],p=[],l=[],m=[],d=[],f=[];for(let S of r)switch(S.kind){case"goal":i=S.text;break;case"plan":a=S.text;break;case"phase":s.set(S.key,Gn(s.get(S.key),S));break;case"task":o.set(S.key,Gn(o.get(S.key),S));break;case"decision":u.push(S.text);break;case"blocker":p.push(S.text);break;case"warning":l.push(S.text);break;case"next_action":m.push(S.text);break;case"file":d.push(S.text);break;case"test":f.push(S.text);break;case"session":c={agent:S.agent,nativeSessionId:S.nativeSessionId,sessionKey:S.sessionKey,updatedAt:S.occurredAt};break}let h=Array.from(s.values()).sort((S,j)=>(S.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),y=Array.from(o.values()).sort((S,j)=>(S.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),g=h.find(S=>S.status==="in_progress")??h.find(S=>S.status==="blocked")??h.find(S=>S.status==="pending"),v=y.find(S=>S.status==="in_progress")??y.find(S=>S.status==="blocked")??y.find(S=>S.status==="pending"),A=G([...m,...v?[v.title]:[],...!v&&g?[g.title]:[],...y.filter(S=>S.status==="pending").slice(0,5).map(S=>S.title)],8),O=G([...p,...h.filter(S=>S.status==="blocked").map(S=>S.title),...y.filter(S=>S.status==="blocked").map(S=>S.title)],20),C={version:1,projectId:t.id,projectName:t.name,goal:i,plan:a,phases:h,tasks:y,decisions:G(u,20),blockers:O,warnings:G(l,20),nextActions:A,filesTouched:G(d,30),tests:G(f,20),currentPhase:g,currentTask:v,progress:{phasesTotal:h.length,phasesCompleted:h.filter(S=>S.status==="completed").length,tasksTotal:y.length,tasksCompleted:y.filter(S=>S.status==="completed").length,blocked:h.filter(S=>S.status==="blocked").length+y.filter(S=>S.status==="blocked").length},lastSession:c,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},_=Hn(t.rootPath,".toolnet","work");return Oi(_,{recursive:!0}),E(Hn(_,"current.json"),C),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(C,null,2)+`
43
+ `,"application/json"),C}async function Ke(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 Fi(t,e){if(!Ki(t))return{events:[],nextOffset:e};let n=Wi(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=Li(t,"r");try{Di(i,o,0,s,r)}finally{$i(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
44
+ `);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
45
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Le=class{constructor(e){this.options=e;this.journal=new _e(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Fi(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=qn(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await $e(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 Yi,existsSync as Xi,openSync as Qi,readSync as Zi,statSync as ea}from"node:fs";var zi=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function U(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function ft(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))ft(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(zi.has(r)||["data","payload","parts","messages"].includes(r))&&ft(s,e,n+1)}}function M(t,e,n,r,s,o=.95){let i=U(r);return{version:1,id:w([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 N(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 U(t.slice(r.length+1))}return null}function Bi(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Vi(t){return U(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function Un(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=[];ft(o.data,i);for(let a of i){let c={type:"project"},u=null;for(let p of a.split(/\r?\n/u)){let l=U(p);if(!l){u=null;continue}let m=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let j=Number(m[1]);c={type:"phase",key:`phase:${j}`,order:j,title:U(m[2]??"")},u=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let j=Number(d[1]);c={type:"task",key:`task:${j}`,order:j,title:U(d[2]??"")},u=null;continue}let f=N(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(f){s(M(t,o,"mission",f,{type:"project"},.99)),u=null;continue}let h=N(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(M(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),u=null;continue}let y=N(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(M(t,o,c.type==="phase"?"phase_why":"why",y,c,.98)),u=null;continue}let g=N(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(g){s(M(t,o,"desired_outcome",g,{type:"project"},.98)),u=null;continue}let v=N(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(v){s(M(t,o,"plan_rationale",v,{type:"project"},.98)),u=null;continue}let A=N(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(A){s(M(t,o,"phase_deliverable",A,c,.97)),u=null;continue}let O=N(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(O){s(M(t,o,"acceptance_criterion",O,c,.98)),u="acceptance_criterion";continue}let C=N(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(C){s(M(t,o,"dependency",C,c,.97)),u="dependency";continue}let _=N(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(_){s(M(t,o,"open_question",_,c,.95)),u="open_question";continue}let S=N(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(S){s(M(t,o,"constraint",S,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){u="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){u="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){u="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){u="constraint";continue}if(u&&Bi(p)){s(M(t,o,u,Vi(p),c,.96));continue}u=null}}}return n}function Yn(t){return String(t).padStart(12,"0")}var De=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=w(n.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${Yn(r)}-${Yn(s)}-${i}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,JSON.stringify(o,null,2)+`
46
+ `,"application/json"),a}};import{mkdirSync as qi}from"node:fs";import{join as Xn}from"node:path";function Ji(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Hi(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function L(t,e){return Hi(e,t)?e:t}function D(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 Gi(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}function Ui(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function Qn(t,e){let r=(await Gi(t,e)).flatMap(h=>h.observations).sort((h,y)=>{let g=h.evidence.occurredAt.localeCompare(y.evidence.occurredAt);return g!==0?g:h.evidence.sessionKey===y.evidence.sessionKey?h.evidence.sequence-y.evidence.sequence:h.id.localeCompare(y.id)}),s,o,i,a,c,u=new Map,p=[],l=[],m=[];for(let h of r){let y=Ji(h);if(h.scope==="phase"&&h.scopeKey){let g=u.get(h.scopeKey)??Ui(h);switch(h.kind){case"phase_objective":g.objective=L(g.objective,y);break;case"phase_why":g.why=L(g.why,y);break;case"phase_deliverable":g.deliverable=L(g.deliverable,y);break;case"acceptance_criterion":g.acceptanceCriteria.push(y);break;case"dependency":g.dependencies.push(y);break;case"open_question":g.openQuestions.push(y);break;case"constraint":g.constraints.push(y);break;case"note":g.notes.push(y);break}u.set(g.key,g);continue}switch(h.kind){case"mission":s=L(s,y);break;case"objective":o=L(o,y);break;case"why":i=L(i,y);break;case"desired_outcome":a=L(a,y);break;case"plan_rationale":c=L(c,y);break;case"open_question":p.push(y);break;case"constraint":l.push(y);break;case"note":m.push(y);break}}for(let h of u.values())h.acceptanceCriteria=D(h.acceptanceCriteria,20),h.dependencies=D(h.dependencies,15),h.openQuestions=D(h.openQuestions,15),h.constraints=D(h.constraints,15),h.notes=D(h.notes,20);let d={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:a,planRationale:c,phases:Array.from(u.values()).sort((h,y)=>h.order-y.order),openQuestions:D(p,20),constraints:D(l,20),notes:D(m,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},f=Xn(t.rootPath,".toolnet","work");return qi(f,{recursive:!0}),E(Xn(f,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
47
+ `,"application/json"),d}async function Zn(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 ta(t,e){if(!Xi(t))return{events:[],nextOffset:e};let n=ea(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=Qi(t,"r");try{Zi(o,s,0,s.length,r)}finally{Yi(o)}let i=s.toString("utf8"),a=i.lastIndexOf(`
48
+ `);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
49
+ `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var We=class{constructor(e){this.options=e;this.journal=new De(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=ta(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=Un(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Qn(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 ma}from"node:fs";import{join as gt}from"node:path";import{existsSync as nr,mkdirSync as na,readFileSync as ra,statSync as er,writeFileSync as sa}from"node:fs";import{dirname as oa,join as ia}from"node:path";var tr=64*1024,aa=`# ToolNet Project Operating Manual
32
50
 
33
51
  This file contains persistent instructions for AI agents working on this project.
34
52
 
@@ -71,30 +89,30 @@ Things an AI agent should always remember.
71
89
  <!--
72
90
  - [advisory] Prefer small focused files.
73
91
  -->
74
- `;function he(t){return xs(t.rootPath,".toolnet","PROJECT.md")}function Is(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Cs(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=Is(s[2]);if(!i)continue;let u=`${o}:${i.toLowerCase()}`;n.has(u)||(n.add(u),e.push({id:v(u).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Es(t){let e=he(t);return _t(e)||(vs(ws(e),{recursive:!0}),ks(e,js,{encoding:"utf8",mode:384})),e}function Se(t,e=!1){let n=e?Es(t):he(t);if(!_t(n))return null;if(At(n).size>Nt)throw new Error(`PROJECT.md exceeds ${Nt} bytes`);let s=bs(n,"utf8");return{path:n,content:s,digest:v(s),rules:Cs(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(At(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 $t(t){if(t)return{id:t.id,title:t.title,status:t.status}}function Os(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 Ps(t){return v(JSON.stringify(t))}function Lt(t){let{project:e,identity:n,state:r}=t,s=r.filesTouched.at(-1),o=r.phases.filter(m=>m.status==="completed").map(m=>m.title),i=r.tasks.filter(m=>m.status==="completed").map(m=>m.title),u=r.phases.filter(m=>m.status!=="completed"&&m.status!=="cancelled").map(m=>m.title),c=r.tasks.filter(m=>m.status!=="completed"&&m.status!=="cancelled").map(m=>m.title),a=O(r.nextActions,10),p=O([...c,...a],15),l=O(r.tests.slice().reverse(),10),y=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:$t(r.currentPhase),task:$t(r.currentTask),file:s},completed:{phases:O(o,20),tasks:O(i,30)},remaining:{phases:O(u,20),tasks:O(c,30),todos:p},nextAction:a[0],blockers:O(r.blockers.slice().reverse(),10),decisions:O(r.decisions.slice().reverse(),10),files:{current:s,recent:y},tests:{status:Os(r.tests),recent:l},attention:O(t.attention??[],20),progress:r.progress},{capturedAt:S,source:h,...g}=d;return{...d,stateDigest:Ps(g)}}function Ms(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 ve=class{constructor(e){this.options=e}options;async capture(e,n){let r=await me(this.options.project,this.options.storage);if(r||(r=await pe(this.options.project,this.options.storage)),!Ms(r))return null;let s=Se(this.options.project,!1),i=[...s?s.rules.filter(S=>S.mode==="enforce").map(S=>S.text):[],...r.warnings].slice(0,20),u=Lt({project:this.options.project,identity:this.options.identity,state:r,reason:e,sequence:n,attention:i}),c=u.stateDigest,a=v([this.options.project.id,this.options.identity.sessionKey,c].join("|")).slice(0,24),p=new Date().toISOString(),l={version:1,id:a,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:p,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence: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},y=`projects/${this.options.project.id}/work/handoffs/${a}.json`;await this.options.storage.exists(y)||await this.options.storage.put(y,JSON.stringify(l,null,2)+`
92
+ `;function Fe(t){return ia(t.rootPath,".toolnet","PROJECT.md")}function ca(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function ua(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=ca(s[2]);if(!i)continue;let a=`${o}:${i.toLowerCase()}`;n.has(a)||(n.add(a),e.push({id:w(a).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function la(t){let e=Fe(t);return nr(e)||(na(oa(e),{recursive:!0}),sa(e,aa,{encoding:"utf8",mode:384})),e}function ze(t,e=!1){let n=e?la(t):Fe(t);if(!nr(n))return null;if(er(n).size>tr)throw new Error(`PROJECT.md exceeds ${tr} bytes`);let s=ra(n,"utf8");return{path:n,content:s,digest:w(s),rules:ua(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(er(n).mtimeMs).toISOString()}}function T(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 rr(t){if(t)return{id:t.id,title:t.title,status:t.status}}function da(t){let e=t.slice(-10).join(`
93
+ `).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(e)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(e)?"passing":"unknown"}function pa(t){return w(JSON.stringify(t))}function sr(t){let{project:e,identity:n,state:r}=t,s=r.filesTouched.at(-1),o=r.phases.filter(g=>g.status==="completed").map(g=>g.title),i=r.tasks.filter(g=>g.status==="completed").map(g=>g.title),a=r.phases.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),c=r.tasks.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),u=T(r.nextActions,10),p=T([...c,...u],15),l=T(r.tests.slice().reverse(),10),m=T(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:rr(r.currentPhase),task:rr(r.currentTask),file:s},completed:{phases:T(o,20),tasks:T(i,30)},remaining:{phases:T(a,20),tasks:T(c,30),todos:p},nextAction:u[0],blockers:T(r.blockers.slice().reverse(),10),decisions:T(r.decisions.slice().reverse(),10),files:{current:s,recent:m},tests:{status:da(r.tests),recent:l},attention:T(t.attention??[],20),progress:r.progress},{capturedAt:f,source:h,...y}=d;return{...d,stateDigest:pa(y)}}function fa(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 Ke(this.options.project,this.options.storage);if(r||(r=await $e(this.options.project,this.options.storage)),!fa(r))return null;let s=ze(this.options.project,!1),i=[...s?s.rules.filter(f=>f.mode==="enforce").map(f=>f.text):[],...r.warnings].slice(0,20),a=sr({project:this.options.project,identity:this.options.identity,state:r,reason:e,sequence:n,attention:i}),c=a.stateDigest,u=w([this.options.project.id,this.options.identity.sessionKey,c].join("|")).slice(0,24),p=new Date().toISOString(),l={version:1,id:u,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:p,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(f=>f.status!=="completed"&&f.status!=="cancelled"),incompleteTasks:r.tasks.filter(f=>f.status!=="completed"&&f.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:i,filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:c,continuity:a},m=`projects/${this.options.project.id}/work/handoffs/${u}.json`;await this.options.storage.exists(m)||await this.options.storage.put(m,JSON.stringify(l,null,2)+`
76
94
  `,"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=_e(this.options.project.rootPath,".toolnet","work","handoffs");return Ts(d,{recursive:!0}),I(_e(d,`${a}.json`),l),I(_e(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),l),l}};async function Dt(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 be=class{identity;wal;remote;sanitizer=new H;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=ot(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new se(this.identity),this.remote=new re(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new ue({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new fe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new ye({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new ve({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)}};var Rs=[/^<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*$/],As=[/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],Ns=["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 _s(t){let e=t.toLowerCase();return Ns.some(n=>e.includes(n))}function $s(t){if(!t.trim())return!0;for(let e of Rs)if(e.test(t))return!0;return _s(t),!1}function Ls(t){let e=t;for(let n of As)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function $e(t){let e=t.trim();return e?$s(e)?{content:"",filtered:!0,reason:"noise"}:{content:Ls(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function ke(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=$e(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=ke(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=$e(s);return o.filtered?null:o.content}return s&&typeof s=="object"?ke(s):s}).filter(s=>s!==null):e[n]=r;return e}function Ft(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&&$e(r).filtered)return!0}return!1}function Jt(){try{let e=Fs("opencode",["db","path"],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5e3}).trim();if(e)return e}catch{}if(process.env.OPENCODE_DB)return process.env.OPENCODE_DB;let t=process.env.XDG_DATA_HOME??Kt(Ks(),".local","share");return Kt(t,"opencode","opencode.db")}function k(t){return typeof t=="string"?t:""}function L(t){if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="bigint")return Number(t);if(typeof t=="string"){let e=Number(t);if(Number.isFinite(e))return e}return 0}function Le(t){if(t&&typeof t=="object"&&!Buffer.isBuffer(t))return t;if(typeof t!="string")return{};try{let e=JSON.parse(t);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{}return{}}function B(t){let e=L(t);if(e<=0)return new Date().toISOString();e<1e11&&(e*=1e3);let n=new Date(e);return Number.isNaN(n.getTime())?new Date().toISOString():n.toISOString()}function we(t,e){if(!e)return!1;let n=Wt(t),r=Wt(e);if(n===r)return!0;let s=zs(n,r);return s!==""&&s!==".."&&!s.startsWith(`..${process.platform==="win32"?"\\":"/"}`)&&!Ws(s)}function zt(t){if(!t)return{time:-1,id:""};try{let e=JSON.parse(t);return{time:typeof e.time=="number"?e.time:-1,id:typeof e.id=="string"?e.id:""}}catch{return{time:-1,id:""}}}function Bt(t){return JSON.stringify(t)}function Ht(t){if(!Ds(t))throw new Error(`OpenCode database not found: ${t}`);let e=new Bs(t,{readOnly:!0});return e.exec("PRAGMA query_only = ON"),e.exec("PRAGMA busy_timeout = 3000"),e}function qs(t,e){let n=t.prepare(`
95
+ `,"application/json");let d=gt(this.options.project.rootPath,".toolnet","work","handoffs");return ma(d,{recursive:!0}),E(gt(d,`${u}.json`),l),E(gt(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),l),l}};async function or(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 Ve=class{identity;wal;remote;sanitizer=new ee;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 ve(this.identity),this.remote=new we(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new Re({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new Le({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new We({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)}};var ga=[/^<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*$/],ya=[/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],ha=["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 Sa(t){let e=t.toLowerCase();return ha.some(n=>e.includes(n))}function wa(t){if(!t.trim())return!0;for(let e of ga)if(e.test(t))return!0;return Sa(t),!1}function va(t){let e=t;for(let n of ya)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function yt(t){let e=t.trim();return e?wa(e)?{content:"",filtered:!0,reason:"noise"}:{content:va(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function qe(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=yt(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=qe(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=yt(s);return o.filtered?null:o.content}return s&&typeof s=="object"?qe(s):s}).filter(s=>s!==null):e[n]=r;return e}function ir(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&&yt(r).filtered)return!0}return!1}function mr(){try{let e=ba("opencode",["db","path"],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5e3}).trim();if(e)return e}catch{}if(process.env.OPENCODE_DB)return process.env.OPENCODE_DB;let t=process.env.XDG_DATA_HOME??ar(xa(),".local","share");return ar(t,"opencode","opencode.db")}function b(t){return typeof t=="string"?t:""}function V(t){if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="bigint")return Number(t);if(typeof t=="string"){let e=Number(t);if(Number.isFinite(e))return e}return 0}function ht(t){if(t&&typeof t=="object"&&!Buffer.isBuffer(t))return t;if(typeof t!="string")return{};try{let e=JSON.parse(t);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{}return{}}function Y(t){let e=V(t);if(e<=0)return new Date().toISOString();e<1e11&&(e*=1e3);let n=new Date(e);return Number.isNaN(n.getTime())?new Date().toISOString():n.toISOString()}function Je(t,e){if(!e)return!1;let n=cr(t),r=cr(e);if(n===r)return!0;let s=Ca(n,r);return s!==""&&s!==".."&&!s.startsWith(`..${process.platform==="win32"?"\\":"/"}`)&&!ja(s)}function ur(t){if(!t)return{time:-1,id:""};try{let e=JSON.parse(t);return{time:typeof e.time=="number"?e.time:-1,id:typeof e.id=="string"?e.id:""}}catch{return{time:-1,id:""}}}function lr(t){return JSON.stringify(t)}function fr(t){if(!ka(t))throw new Error(`OpenCode database not found: ${t}`);let e=new Ia(t,{readOnly:!0});return e.exec("PRAGMA query_only = ON"),e.exec("PRAGMA busy_timeout = 3000"),e}function Aa(t,e){let n=t.prepare(`
78
96
  SELECT *
79
97
  FROM "session"
80
98
  WHERE id = ?
81
99
  LIMIT 1
82
- `).get(e);if(!n)throw new Error(`OpenCode session not found: ${e}`);return n}function Ut(t,e,n){let r=k(e.directory);if(r&&we(n.rootPath,r))return!0;let s=k(e.project_id);if(s){try{let o=t.prepare(`
100
+ `).get(e);if(!n)throw new Error(`OpenCode session not found: ${e}`);return n}function gr(t,e,n){let r=b(e.directory);if(r&&Je(n.rootPath,r))return!0;let s=b(e.project_id);if(s){try{let o=t.prepare(`
83
101
  SELECT *
84
102
  FROM "project"
85
103
  WHERE id = ?
86
104
  LIMIT 1
87
- `).get(s);if(o)for(let i of["worktree","directory","path"]){let u=k(o[i]);if(u&&we(n.rootPath,u))return!0}}catch{}try{if(t.prepare(`
105
+ `).get(s);if(o)for(let i of["worktree","directory","path"]){let a=b(o[i]);if(a&&Je(n.rootPath,a))return!0}}catch{}try{if(t.prepare(`
88
106
  SELECT directory
89
107
  FROM "project_directory"
90
108
  WHERE project_id = ?
91
- `).all(s).some(i=>we(n.rootPath,k(i.directory))))return!0}catch{}}try{let o=t.prepare(`
109
+ `).all(s).some(i=>Je(n.rootPath,b(i.directory))))return!0}catch{}}try{let o=t.prepare(`
92
110
  SELECT data
93
111
  FROM "message"
94
112
  WHERE session_id = ?
95
113
  ORDER BY time_created DESC
96
114
  LIMIT 20
97
- `).all(k(e.id));for(let i of o){let u=Le(i.data),c=u.path&&typeof u.path=="object"?u.path:{};for(let a of[k(c.cwd),k(c.root)])if(a&&we(n.rootPath,a))return!0}}catch{}return!1}function qt(t,e,n,r){let s=`
115
+ `).all(b(e.id));for(let i of o){let a=ht(i.data),c=a.path&&typeof a.path=="object"?a.path:{};for(let u of[b(c.cwd),b(c.root)])if(u&&Je(n.rootPath,u))return!0}}catch{}return!1}function dr(t,e,n,r){let s=`
98
116
  SELECT *,
99
117
  COALESCE(
100
118
  time_updated,
@@ -125,10 +143,10 @@ Things an AI agent should always remember.
125
143
  0
126
144
  ) ASC,
127
145
  id ASC
128
- `;return t.prepare(s).all(n,r.time,r.time,r.id)}function Vt(t,e){let n=t[t.length-1];return n?{time:L(n.__clock),id:k(n.id)}:e}function Vs(t,e){let n=Le(e.data),r=k(n.role),s=L(e.__clock),o=k(e.id),i="message";return r==="user"?i="user_prompt":r==="assistant"&&(i="assistant_message"),{clock:s,order:0,event:{type:i,timestamp:B(s),role:r||void 0,sourceEventId:`message:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{messageId:o,...n},provenance:{source:"opencode",sourcePath:t,sourceTable:"message",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}function Js(t){let e={...t},n=t.state&&typeof t.state=="object"&&!Array.isArray(t.state)?{...t.state}:void 0;if(n){let r=n.output;if(typeof r=="string"){let s=r.replace(/\r\n/g,`
146
+ `;return t.prepare(s).all(n,r.time,r.time,r.id)}function pr(t,e){let n=t[t.length-1];return n?{time:V(n.__clock),id:b(n.id)}:e}function Ea(t,e){let n=ht(e.data),r=b(n.role),s=V(e.__clock),o=b(e.id),i="message";return r==="user"?i="user_prompt":r==="assistant"&&(i="assistant_message"),{clock:s,order:0,event:{type:i,timestamp:Y(s),role:r||void 0,sourceEventId:`message:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{messageId:o,...n},provenance:{source:"opencode",sourcePath:t,sourceTable:"message",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}function Pa(t){let e={...t},n=t.state&&typeof t.state=="object"&&!Array.isArray(t.state)?{...t.state}:void 0;if(n){let r=n.output;if(typeof r=="string"){let s=r.replace(/\r\n/g,`
129
147
  `),o=500;n.outputSummary=s.length<=o?s:`${s.slice(0,350)}
130
148
  ...[ToolNet truncated ${s.length-o} chars]...
131
- ${s.slice(-150)}`,delete n.output}else r!==void 0&&(n.outputSummary="[non-text tool output omitted]",delete n.output);if(n.input&&typeof n.input=="object"&&!Array.isArray(n.input)){let s={...n.input};for(let[o,i]of Object.entries(s))typeof i=="string"&&i.length>1e3&&(s[o]=`${i.slice(0,1e3)}...[ToolNet truncated]`);n.input=s}e.state=n}return e}function Hs(t,e){let n=Le(e.data),r=k(n.type),s=L(e.__clock),o=k(e.id),i=k(e.message_id),u="message_part";return r==="tool"?u="tool_call":r==="snapshot"&&(u="artifact"),{clock:s,order:1,event:{type:u,timestamp:B(s),sourceEventId:`part:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{partId:o,messageId:i,...r==="tool"?Js(n):n},provenance:{source:"opencode",sourcePath:t,sourceTable:"part",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}async function De(t){let e=t.dbPath??Jt(),n=Ht(e);try{let r=qs(n,t.nativeSessionId);if(!Ut(n,r,t.project))throw new Error(["OpenCode session does not belong to current ToolNet project.",`Session: ${t.nativeSessionId}`,`Project: ${t.project.rootPath}`,`Session directory: ${k(r.directory)||"unknown"}`].join(" "));let s=new be({project:t.project,storage:t.storage,agent:"opencode",nativeSessionId:t.nativeSessionId,title:k(r.title)||void 0,metadata:{source:"opencode.db",openCodeProjectId:k(r.project_id)||void 0,directory:k(r.directory)||void 0}}),o=s.status(),i=zt(o.sourceCursors["opencode.message"]),u=zt(o.sourceCursors["opencode.part"]),c=qt(n,"message",t.nativeSessionId,i),a=qt(n,"part",t.nativeSessionId,u),p=[];if(o.lastSequence===0){let m=L(r.time_created);p.push({clock:m,order:-1,event:{type:"session_start",timestamp:B(m),sourceEventId:`session:${t.nativeSessionId}:created:${m}`,data:{title:k(r.title)||void 0,directory:k(r.directory)||void 0,openCodeProjectId:k(r.project_id)||void 0},provenance:{source:"opencode",sourcePath:e,sourceTable:"session",sourceRowId:t.nativeSessionId}}})}p.push(...c.map(m=>Vs(e,m))),p.push(...a.map(m=>Hs(e,m)));let l=L(r.time_updated)||L(r.time_created);t.compacted&&p.push({clock:l,order:98,event:{type:"session_compact",timestamp:B(l),sourceEventId:`session:${t.nativeSessionId}:compact:${l}`,data:{},provenance:{source:"opencode"}}}),t.error?p.push({clock:l,order:99,event:{type:"error",timestamp:B(l),sourceEventId:`session:${t.nativeSessionId}:error:${l}`,data:{source:"session.error"},provenance:{source:"opencode"}}}):t.idle&&p.push({clock:l,order:100,event:{type:"session_idle",timestamp:B(l),sourceEventId:`session:${t.nativeSessionId}:idle:${l}`,data:{},provenance:{source:"opencode"}}}),p.sort((m,w)=>m.clock-w.clock||m.order-w.order);let y=p.filter(m=>!Ft(m.event.data)).map(m=>({...m,event:{...m.event,data:ke(m.event.data)}})),d=s.recordMany(y.map(m=>m.event)),S=Vt(c,i),h=Vt(a,u);if(s.setSourceCursor("opencode.message",Bt(S)),s.setSourceCursor("opencode.part",Bt(h)),t.idle&&y.length>0)try{let m=y.map(T=>JSON.stringify(T.event.data)),w=ae(m,t.nativeSessionId);s.setSourceCursor("opencode.session.summary",w.summary),s.setSourceCursor("opencode.session.facts_count",w.durableFacts.length),yt()&&!vt()&&s.setSourceCursor("opencode.raw_transcript.archived","local")}catch{}let g=await s.flush();return{nativeSessionId:t.nativeSessionId,importedMessages:c.length,importedParts:a.length,recordedEvents:d.length,eventCount:g.eventCount,chunkCount:g.chunkCount,status:g.status}}finally{n.close()}}async function Yt(t){let e=t.dbPath??Jt(),n=Ht(e),r=[];try{let o=n.prepare(`
149
+ ${s.slice(-150)}`,delete n.output}else r!==void 0&&(n.outputSummary="[non-text tool output omitted]",delete n.output);if(n.input&&typeof n.input=="object"&&!Array.isArray(n.input)){let s={...n.input};for(let[o,i]of Object.entries(s))typeof i=="string"&&i.length>1e3&&(s[o]=`${i.slice(0,1e3)}...[ToolNet truncated]`);n.input=s}e.state=n}return e}function Ma(t,e){let n=ht(e.data),r=b(n.type),s=V(e.__clock),o=b(e.id),i=b(e.message_id),a="message_part";return r==="tool"?a="tool_call":r==="snapshot"&&(a="artifact"),{clock:s,order:1,event:{type:a,timestamp:Y(s),sourceEventId:`part:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{partId:o,messageId:i,...r==="tool"?Pa(n):n},provenance:{source:"opencode",sourcePath:t,sourceTable:"part",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}async function St(t){let e=t.dbPath??mr(),n=fr(e);try{let r=Aa(n,t.nativeSessionId);if(!gr(n,r,t.project))throw new Error(["OpenCode session does not belong to current ToolNet project.",`Session: ${t.nativeSessionId}`,`Project: ${t.project.rootPath}`,`Session directory: ${b(r.directory)||"unknown"}`].join(" "));let s=new Ve({project:t.project,storage:t.storage,agent:"opencode",nativeSessionId:t.nativeSessionId,title:b(r.title)||void 0,metadata:{source:"opencode.db",openCodeProjectId:b(r.project_id)||void 0,directory:b(r.directory)||void 0}}),o=s.status(),i=ur(o.sourceCursors["opencode.message"]),a=ur(o.sourceCursors["opencode.part"]),c=dr(n,"message",t.nativeSessionId,i),u=dr(n,"part",t.nativeSessionId,a),p=[];if(o.lastSequence===0){let g=V(r.time_created);p.push({clock:g,order:-1,event:{type:"session_start",timestamp:Y(g),sourceEventId:`session:${t.nativeSessionId}:created:${g}`,data:{title:b(r.title)||void 0,directory:b(r.directory)||void 0,openCodeProjectId:b(r.project_id)||void 0},provenance:{source:"opencode",sourcePath:e,sourceTable:"session",sourceRowId:t.nativeSessionId}}})}p.push(...c.map(g=>Ea(e,g))),p.push(...u.map(g=>Ma(e,g)));let l=V(r.time_updated)||V(r.time_created);t.compacted&&p.push({clock:l,order:98,event:{type:"session_compact",timestamp:Y(l),sourceEventId:`session:${t.nativeSessionId}:compact:${l}`,data:{},provenance:{source:"opencode"}}}),t.error?p.push({clock:l,order:99,event:{type:"error",timestamp:Y(l),sourceEventId:`session:${t.nativeSessionId}:error:${l}`,data:{source:"session.error"},provenance:{source:"opencode"}}}):t.idle&&p.push({clock:l,order:100,event:{type:"session_idle",timestamp:Y(l),sourceEventId:`session:${t.nativeSessionId}:idle:${l}`,data:{},provenance:{source:"opencode"}}}),p.sort((g,v)=>g.clock-v.clock||g.order-v.order);let m=p.filter(g=>!ir(g.event.data)).map(g=>({...g,event:{...g.event,data:qe(g.event.data)}})),d=s.recordMany(m.map(g=>g.event)),f=pr(c,i),h=pr(u,a);if(s.setSourceCursor("opencode.message",lr(f)),s.setSourceCursor("opencode.part",lr(h)),t.idle&&m.length>0)try{let g=m.map(A=>JSON.stringify(A.event.data)),v=je(g,t.nativeSessionId);s.setSourceCursor("opencode.session.summary",v.summary),s.setSourceCursor("opencode.session.facts_count",v.durableFacts.length),Qt()&&!tn()&&s.setSourceCursor("opencode.raw_transcript.archived","local")}catch{}let y=await s.flush();return{nativeSessionId:t.nativeSessionId,importedMessages:c.length,importedParts:u.length,recordedEvents:d.length,eventCount:y.eventCount,chunkCount:y.chunkCount,status:y.status}}finally{n.close()}}async function yr(t){let e=t.dbPath??mr(),n=fr(e),r=[];try{let o=n.prepare(`
132
150
  SELECT *
133
151
  FROM "session"
134
152
  ORDER BY
@@ -137,11 +155,11 @@ ${s.slice(-150)}`,delete n.output}else r!==void 0&&(n.outputSummary="[non-text t
137
155
  time_created,
138
156
  0
139
157
  ) DESC
140
- `).all();for(let i of o){if(!Ut(n,i,t.project))continue;let u=k(i.id);if(u&&r.push(u),r.length>=(t.limit??100))break}}finally{n.close()}let s=[];for(let o of r)s.push(await De({project:t.project,storage:t.storage,nativeSessionId:o,dbPath:e}));return s}import{existsSync as Gs,mkdirSync as en,readFileSync as Qs,writeFileSync as tn}from"node:fs";import{join as Xs}from"node:path";import{homedir as Us}from"node:os";import{join as xe}from"node:path";function je(t={}){let e=t.xdgConfigHome??process.env.XDG_CONFIG_HOME?.trim();return e?xe(e,"opencode"):xe(t.home??Us(),".config","opencode")}function Gt(t={}){return xe(je(t),"plugins")}function Qt(t={}){return xe(je(t),"AGENTS.md")}var Ys="memory_agent_ask";function Xt(){return`
158
+ `).all();for(let i of o){if(!gr(n,i,t.project))continue;let a=b(i.id);if(a&&r.push(a),r.length>=(t.limit??100))break}}finally{n.close()}let s=[];for(let o of r)s.push(await St({project:t.project,storage:t.storage,nativeSessionId:o,dbPath:e}));return s}import{existsSync as Ra,mkdirSync as kr,readFileSync as Na,writeFileSync as br}from"node:fs";import{join as _a}from"node:path";import{homedir as Ta}from"node:os";import{join as He}from"node:path";function Ge(t={}){let e=t.xdgConfigHome??process.env.XDG_CONFIG_HOME?.trim();return e?He(e,"opencode"):He(t.home??Ta(),".config","opencode")}function hr(t={}){return He(Ge(t),"plugins")}function Sr(t={}){return He(Ge(t),"AGENTS.md")}var Oa="memory_agent_ask";function wr(){return`
141
159
  [TOOLNET MEMORY AGENT]
142
160
 
143
161
  Tool available:
144
- - ${Ys}
162
+ - ${Oa}
145
163
 
146
164
  Use it automatically BEFORE guessing when:
147
165
 
@@ -188,7 +206,7 @@ Rules:
188
206
  - After receiving the ToolNet answer, continue the task
189
207
  instead of asking the user to repeat known context.
190
208
  - If ToolNet says information is not recorded, say so.
191
- `.trim()}var Zt="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",Fe="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function Zs(){let t=Qt();en(je(),{recursive:!0});let e=`${Zt}
209
+ `.trim()}var vr="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",wt="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function $a(){let t=Sr();kr(Ge(),{recursive:!0});let e=`${vr}
192
210
  ## ToolNet Memory
193
211
 
194
212
  ToolNet Memory is available for projects that already contain a valid \`.toolnet/project.json\`.
@@ -204,12 +222,12 @@ Rules:
204
222
  7. Current repository evidence has priority over stale memory when they conflict.
205
223
 
206
224
 
207
- ${Xt()}
225
+ ${wr()}
208
226
 
209
- ${Fe}`,n=Gs(t)?Qs(t,"utf8"):"",r=n.indexOf(Zt),s=n.indexOf(Fe);return r>=0&&s>=r?n=n.slice(0,r)+e+n.slice(s+Fe.length):(n=n.trimEnd(),n&&(n+=`
227
+ ${wt}`,n=Ra(t)?Na(t,"utf8"):"",r=n.indexOf(vr),s=n.indexOf(wt);return r>=0&&s>=r?n=n.slice(0,r)+e+n.slice(s+wt.length):(n=n.trimEnd(),n&&(n+=`
210
228
 
211
- `),n+=e),tn(t,n.trimEnd()+`
212
- `,{encoding:"utf8",mode:384}),t}function nn(t={}){let e=t.directory??Gt();en(e,{recursive:!0}),Zs();let n=Xs(e,"toolnet-memory.js"),r=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",s=`
229
+ `),n+=e),br(t,n.trimEnd()+`
230
+ `,{encoding:"utf8",mode:384}),t}function xr(t={}){let e=t.directory??hr();kr(e,{recursive:!0}),$a();let n=_a(e,"toolnet-memory.js"),r=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",s=`
213
231
  // Generated by ToolNet Memory.
214
232
  // OpenCode integration:
215
233
  // - project gated
@@ -837,20 +855,20 @@ export const ToolNetMemoryPlugin =
837
855
  },
838
856
  }
839
857
  }
840
- `;return tn(n,s.trimStart(),{encoding:"utf8",mode:384}),n}import{existsSync as fu,mkdirSync as ro,readFileSync as gu,writeFileSync as so}from"node:fs";import{dirname as oo,join as sn}from"node:path";function Ke(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 eo(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 to(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 no(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
841
- `);if(Ke(s)<=e){n.push(r);continue}let o=Ke(n.join(`
842
- `)),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(`
843
- `).trim()}async function rn(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=Se(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=to(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?eo(r):[],c=await me(t.project,t.storage),a=await Rt(t.project,t.storage),p=await Dt(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: ${he(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)}`)})),p&&l.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),u.length){l.push("","OPERATING NOTES");for(let d of u)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let y=no(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:y,estimatedTokens:Ke(y),maxTokens:e,hasManual:!!r,hasWorkState:!!c,hasHandoff:!!p,generatedAt:new Date().toISOString()}}function io(t){return sn(t.rootPath,".toolnet","context","startup.md")}function ao(t){return sn(t.rootPath,".toolnet","context","startup.json")}function co(t,e){let n=io(t);ro(oo(n),{recursive:!0}),so(n,e.text.endsWith(`
858
+ `;return br(n,s.trimStart(),{encoding:"utf8",mode:384}),n}import{existsSync as Mp,mkdirSync as Wa,readFileSync as Tp,writeFileSync as Fa}from"node:fs";import{dirname as za,join as Cr}from"node:path";function vt(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 k(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 Ka(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(k(s,280)),e.length>=16))break}return e}function La(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.trim(),o=s.toLowerCase(),a=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(u=>o.startsWith(u));if(!a)continue;let c=s.slice(a.length).trim();c&&(a.includes("enforce")?e.push(c):n.push(c))}return{enforce:e,advisory:n}}function Da(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
859
+ `);if(vt(s)<=e){n.push(r);continue}let o=vt(n.join(`
860
+ `)),i=Math.max(0,e-o);if(i>=16){let a=Math.floor(i*3.2),c=k(r,a);c&&n.push(c)}break}return n.join(`
861
+ `).trim()}async function jr(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=ze(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=La(r),o=n?n.rules.filter(d=>d.mode==="enforce").map(d=>d.text):s.enforce,i=n?n.rules.filter(d=>d.mode==="advisory").map(d=>d.text):s.advisory,a=r?Ka(r):[],c=await Ke(t.project,t.storage),u=await Zn(t.project,t.storage),p=await or(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: ${Fe(t.project)}`),o.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of o.slice(0,24))l.push(`- [ENFORCE] ${k(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${k(d,220)}`)}if(u&&(u.mission&&l.push("","MISSION",k(u.mission.value,420)),u.activeObjective&&l.push("","CURRENT OBJECTIVE",k(u.activeObjective.value,420)),u.why&&l.push("","WHY THIS WORK MATTERS",k(u.why.value,420)),u.desiredOutcome&&l.push("","DESIRED OUTCOME",k(u.desiredOutcome.value,420)),u.planRationale&&l.push("","WHY THIS APPROACH",k(u.planRationale.value,420))),c){if(l.push("","ACTIVE WORK"),c.goal&&l.push(`Goal: ${k(c.goal,320)}`),c.plan&&l.push(`Plan: ${k(c.plan,320)}`),l.push(`Progress: phases ${c.progress.phasesCompleted}/${c.progress.phasesTotal}; tasks ${c.progress.tasksCompleted}/${c.progress.tasksTotal}; blocked ${c.progress.blocked}`),c.currentPhase&&l.push(`Current phase: ${c.currentPhase.title} [${c.currentPhase.status}]`),c.currentPhase&&u){let d=u.phases.find(f=>f.order===c.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${k(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${k(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${k(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(f=>k(f.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(f=>{l.push(`- ${k(f.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(f=>{l.push(`- ${k(f.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,f)=>{l.push(`${f+1}. ${k(d,260)}`)})),c.blockers.length&&(l.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(d=>{l.push(`- ${k(d,260)}`)})),c.warnings.length&&(l.push("","ATTENTION"),c.warnings.slice(-5).forEach(d=>{l.push(`- ${k(d,260)}`)})),c.decisions.length&&(l.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(d=>{l.push(`- ${k(d,260)}`)})),c.lastSession&&l.push("",`Last work session: ${c.lastSession.agent} / ${c.lastSession.nativeSessionId}`)}if(u&&u.openQuestions.length&&(l.push("","UNRESOLVED QUESTIONS"),u.openQuestions.slice(0,5).forEach(d=>{l.push(`- ${k(d.value,260)}`)})),p&&l.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),a.length){l.push("","OPERATING NOTES");for(let d of a)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let m=Da(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:m,estimatedTokens:vt(m),maxTokens:e,hasManual:!!r,hasWorkState:!!c,hasHandoff:!!p,generatedAt:new Date().toISOString()}}function Ba(t){return Cr(t.rootPath,".toolnet","context","startup.md")}function Va(t){return Cr(t.rootPath,".toolnet","context","startup.json")}function qa(t,e){let n=Ba(t);Wa(za(n),{recursive:!0}),Fa(n,e.text.endsWith(`
844
862
  `)?e.text:e.text+`
845
- `,{encoding:"utf8",mode:384}),I(ao(t),e)}async function on(t,e,n=800){let s=(await rn({project:t,storage:e,maxTokens:n})).text;oe(s)>n&&(s=ie(s,n),s+=`
863
+ `,{encoding:"utf8",mode:384}),E(Va(t),e)}async function Ir(t,e,n=800){let s=(await jr({project:t,storage:e,maxTokens:n})).text;be(s)>n&&(s=xe(s,n),s+=`
846
864
 
847
865
  [Context trimmed by ToolNet Memory token budget]
848
- `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:v(s),estimatedTokens:oe(s),generatedAt:new Date().toISOString()};return co(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
866
+ `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:w(s),estimatedTokens:be(s),generatedAt:new Date().toISOString()};return qa(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
849
867
  `,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
850
- `,"application/json"),i}function Ie(t,e){let n=t.indexOf(e);if(!(n<0))return t[n+1]}function We(t,e){return t.includes(e)}function uo(t){let e=G(),n=Ze(Qe({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new ne(n,t.id,t.name,t.remote??t.name)}async function lo(){let[t="help",...e]=process.argv.slice(2);if(t==="install-plugin"){let i=nn({binary:Ie(e,"--bin")});console.log(`\u2705 OpenCode plugin installed: ${i}`),console.log("OpenCode will load it automatically on next start.");return}let n=Ie(e,"--project")??process.cwd(),r=new X().detect(n),s=uo(r),o=Ie(e,"--db");if(t==="sync"){let i=e.find(l=>!l.startsWith("--")&&l!==n&&l!==o);if(!i)throw new Error("Usage: session:opencode-sync <session-id>");let u=We(e,"--idle"),c=We(e,"--error"),a=We(e,"--compacted"),p=await De({project:r,storage:s,nativeSessionId:i,dbPath:o,idle:u,error:c,compacted:a});if(u||a||c)try{await on(r,s,800)}catch{}console.log(JSON.stringify(p,null,2));return}if(t==="recover"){let i=Ie(e,"--limit"),u=i?Number(i):100,c=await Yt({project:r,storage:s,dbPath:o,limit:Number.isFinite(u)?u:100});console.log(JSON.stringify({project:r.name,sessions:c.length,importedMessages:c.reduce((a,p)=>a+p.importedMessages,0),importedParts:c.reduce((a,p)=>a+p.importedParts,0)},null,2));return}console.log(`OpenCode Session Adapter
868
+ `,"application/json"),i}function Ue(t,e){let n=t.indexOf(e);if(!(n<0))return t[n+1]}function kt(t,e){return t.includes(e)}function Ja(t){let e=pe(),n=Ot(Mt({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new Se(n,t.id,t.name,t.remote??t.name)}async function Ha(){let[t="help",...e]=process.argv.slice(2);if(t==="install-plugin"){let i=xr({binary:Ue(e,"--bin")});console.log(`\u2705 OpenCode plugin installed: ${i}`),console.log("OpenCode will load it automatically on next start.");return}let n=Ue(e,"--project")??process.cwd(),r=new fe().detect(n),s=Ja(r),o=Ue(e,"--db");if(t==="sync"){let i=e.find(l=>!l.startsWith("--")&&l!==n&&l!==o);if(!i)throw new Error("Usage: session:opencode-sync <session-id>");let a=kt(e,"--idle"),c=kt(e,"--error"),u=kt(e,"--compacted"),p=await St({project:r,storage:s,nativeSessionId:i,dbPath:o,idle:a,error:c,compacted:u});if(a||u||c)try{await Ir(r,s,800)}catch{}console.log(JSON.stringify(p,null,2));return}if(t==="recover"){let i=Ue(e,"--limit"),a=i?Number(i):100,c=await yr({project:r,storage:s,dbPath:o,limit:Number.isFinite(a)?a:100});console.log(JSON.stringify({project:r.name,sessions:c.length,importedMessages:c.reduce((u,p)=>u+p.importedMessages,0),importedParts:c.reduce((u,p)=>u+p.importedParts,0)},null,2));return}console.log(`OpenCode Session Adapter
851
869
 
852
870
  Commands:
853
871
  sync <session-id> [--project PATH] [--idle]
854
872
  recover [--project PATH] [--limit N]
855
873
  install-plugin [--bin PATH]
856
- `)}lo().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});
874
+ `)}Ha().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});