toolnet-memory 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle/agy.js CHANGED
@@ -1,52 +1,26 @@
1
- import{existsSync as kr,readFileSync as br}from"node:fs";import{homedir as xr}from"node:os";import{join as jr}from"node:path";function Ar(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 Ir(){let t=process.env.TOOLNET_GLOBAL_ENV??jr(xr(),".config","toolnet-memory",".env");if(!kr(t))return;let e=br(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]=Ar(r.slice(s+1)))}}Ir();function G(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function U(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function le(){return{memory:{autoCapture:G(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:G(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:G(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:G(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:U(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:U(process.env.MEMORY_RERANK_TOP,10),finalContext:U(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:U(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:G(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:U(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Pr}from"node:crypto";import{existsSync as Be,mkdirSync as Cr,readFileSync as Mr,renameSync as Er,writeFileSync as Or}from"node:fs";import{basename as Tr,dirname as de,join as me,parse as ht,resolve as Y}from"node:path";var St=".toolnet",Rr="project.json";function Nr(t){return Pr("sha256").update(t).digest("hex").slice(0,16)}function Je(t){return me(t,St,Rr)}function _r(t){return Be(Je(t))}function Kr(t,e){let n=Y(t),r=ht(n).root;for(;;){if(_r(n))return n;if(n===r||e&&n===Y(e))break;let s=de(n);if(s===n)break;n=s}return null}function $r(t){let e=Y(t),n=ht(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>Be(me(e,o))))return e;if(e===n)break;let s=de(e);if(s===e)break;e=s}return Y(t)}function Lr(t){let e;try{e=JSON.parse(Mr(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:de(de(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 gt(t,e){let n=me(t,St);Cr(n,{recursive:!0});let r=Je(t),s=`${r}.tmp-${process.pid}`;Or(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Er(s,r)}function yt(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 pe=class{detect(e=process.cwd()){let n=Y(e),r=$r(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>Be(me(r,p))),i=Kr(n,o?r:void 0);if(i){let p=Je(i),d=Lr(p);return d.rootPath!==i&&(d.rootPath=i,d.updatedAt=new Date().toISOString(),gt(i,d)),yt(d,i)}let a=new Date().toISOString(),u=Tr(r),c={version:1,id:Nr(r),name:u,remote:u,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return gt(r,c),yt(c,r)}};var Wr=[{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}],fe=class{scan(e){let n=[];for(let r of Wr){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 X=class{scanner=new fe;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 cs}from"node:os";import{join as us}from"node:path";import{DeleteObjectCommand as Dr,GetObjectCommand as Fr,HeadObjectCommand as zr,ListObjectsV2Command as qr,PutObjectCommand as Vr,S3Client as Br}from"@aws-sdk/client-s3";import{getSignedUrl as Jr}from"@aws-sdk/s3-request-presigner";var ge=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Br({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Vr({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Jr(this.client,new Fr({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 zr({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new Dr({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new qr({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as wt,mkdir as Hr,readFile as Gr,readdir as Ur,rm as Yr,stat as vt,writeFile as Xr}from"node:fs/promises";import{dirname as Qr,join as Zr,relative as kt,resolve as es}from"node:path";var Q=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return es(this.root,n)}async put(e,n){let r=this.path(e);await Hr(Qr(r),{recursive:!0}),await Xr(r,n)}async get(e){try{return await Gr(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await wt(this.path(e)),!0}catch{return!1}}async delete(e){await Yr(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await wt(n)}catch{return r}let s=async i=>{let a=await Ur(i,{withFileTypes:!0});for(let u of a){let c=Zr(i,u.name);if(u.isDirectory()){await s(c);continue}let p=await vt(c);r.push({key:kt(this.root,c),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await vt(n);return o.isDirectory()?await s(n):r.push({key:kt(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as ts,GetObjectCommand as ns,HeadObjectCommand as rs,ListObjectsV2Command as ss,PutObjectCommand as os,S3Client as is}from"@aws-sdk/client-s3";import{getSignedUrl as as}from"@aws-sdk/s3-request-presigner";var Z=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new is({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 os({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await as(this.client,new ns({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 rs({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 ts({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new ss({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 He(t,e){return console.warn(e),new Q(t)}function bt(t){let e=t.localRoot??us(cs(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Z({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):He(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 Z({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):He(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 ge({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):He(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new Q(e)}function ls(t){return new Promise(e=>setTimeout(e,t))}async function xt(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 u=Math.min(s,r*2**(i-1)),c=Math.floor(Math.random()*Math.max(1,u*.2));await ls(u+c)}throw o}var ds=new Set(["put","get","getText","delete","list"]);function jt(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:ds.has(r)?(...o)=>xt(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function At(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function It(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var ye=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=At(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=It(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{homedir as pt}from"node:os";import{join as nr,resolve as xa}from"node:path";import{join as Ss}from"node:path";import{createHash as ps}from"node:crypto";import{dirname as ms}from"node:path";import{mkdirSync as fs,readFileSync as gs,renameSync as ys,writeFileSync as hs}from"node:fs";function v(t){return ps("sha256").update(t).digest("hex")}function Ge(t){if(Array.isArray(t))return t.map(Ge);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Ge(e[r]);return n}return t}function Pt(t){return JSON.stringify(Ge(t))}function Ct(t){try{return JSON.parse(gs(t,"utf8"))}catch{return null}}function R(t,e){fs(ms(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;hs(n,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),ys(n,t)}function Mt(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 Et(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=Mt(r.toLowerCase(),"agent"),i=Mt(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:Ss(t.rootPath,".toolnet","sessions",o,i)}}function Ot(t){return String(t).padStart(12,"0")}var he=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 u=Number(a[1]),c=Number(a[2]);!Number.isFinite(u)||!Number.isFinite(c)||(s.push({key:i.key,start:u,end:c}),o=Math.max(o,c))}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),u=0;for(let y of this.split(a)){let g=y[0],w=y[y.length-1],A=y.map(T=>JSON.stringify(T)).join(`
1
+ import{existsSync as Mt,readFileSync as Tt}from"node:fs";import{homedir as Rt}from"node:os";import{join as Ct}from"node:path";function Nt(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 _t(){let t=process.env.TOOLNET_GLOBAL_ENV??Ct(Rt(),".config","toolnet-memory",".env");if(!Mt(t))return;let e=Tt(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]=Nt(r.slice(s+1)))}}_t();function K(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function F(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function q(){return{memory:{autoCapture:K(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:K(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:K(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:K(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:F(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:F(process.env.MEMORY_RERANK_TOP,10),finalContext:F(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:F(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:K(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:F(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as $t}from"node:crypto";import{existsSync as de,mkdirSync as Lt,readFileSync as Kt,renameSync as Ft,writeFileSync as zt}from"node:fs";import{basename as Dt,dirname as J,join as U,parse as Ee,resolve as z}from"node:path";var Ae=".toolnet",Wt="project.json";function Bt(t){return $t("sha256").update(t).digest("hex").slice(0,16)}function fe(t){return U(t,Ae,Wt)}function qt(t){return de(fe(t))}function Jt(t,e){let n=z(t),r=Ee(n).root;for(;;){if(qt(n))return n;if(n===r||e&&n===z(e))break;let s=J(n);if(s===n)break;n=s}return null}function Vt(t){let e=z(t),n=Ee(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>de(U(e,o))))return e;if(e===n)break;let s=J(e);if(s===e)break;e=s}return z(t)}function Ut(t){let e;try{e=JSON.parse(Kt(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:J(J(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 Pe(t,e){let n=U(t,Ae);Lt(n,{recursive:!0});let r=fe(t),s=`${r}.tmp-${process.pid}`;zt(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Ft(s,r)}function Oe(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 V=class{detect(e=process.cwd()){let n=z(e),r=Vt(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>de(U(r,d))),i=Jt(n,o?r:void 0);if(i){let d=fe(i),l=Ut(d);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),Pe(i,l)),Oe(l,i)}let c=new Date().toISOString(),u=Dt(r),a={version:1,id:Bt(r),name:u,remote:u,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return Pe(r,a),Oe(a,r)}};var Ht=[{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}],H=class{scan(e){let n=[];for(let r of Ht){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 D=class{scanner=new H;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 Sn}from"node:os";import{join as vn}from"node:path";import{DeleteObjectCommand as Yt,GetObjectCommand as Gt,HeadObjectCommand as Xt,ListObjectsV2Command as Zt,PutObjectCommand as Qt,S3Client as en}from"@aws-sdk/client-s3";import{getSignedUrl as tn}from"@aws-sdk/s3-request-presigner";var Y=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new en({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 Qt({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await tn(this.client,new Gt({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 Xt({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 Yt({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Zt({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 Me,mkdir as nn,readFile as rn,readdir as sn,rm as on,stat as Te,writeFile as an}from"node:fs/promises";import{dirname as cn,join as un,relative as Re,resolve as ln}from"node:path";var W=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return ln(this.root,n)}async put(e,n){let r=this.path(e);await nn(cn(r),{recursive:!0}),await an(r,n)}async get(e){try{return await rn(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 Me(this.path(e)),!0}catch{return!1}}async delete(e){await on(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Me(n)}catch{return r}let s=async i=>{let c=await sn(i,{withFileTypes:!0});for(let u of c){let a=un(i,u.name);if(u.isDirectory()){await s(a);continue}let d=await Te(a);r.push({key:Re(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await Te(n);return o.isDirectory()?await s(n):r.push({key:Re(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as pn,GetObjectCommand as dn,HeadObjectCommand as fn,ListObjectsV2Command as mn,PutObjectCommand as gn,S3Client as yn}from"@aws-sdk/client-s3";import{getSignedUrl as hn}from"@aws-sdk/s3-request-presigner";var B=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new yn({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 gn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await hn(this.client,new dn({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 fn({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 pn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new mn({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 me(t,e){return console.warn(e),new W(t)}function Ce(t){let e=t.localRoot??vn(Sn(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new B({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):me(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 B({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):me(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 Y({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):me(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new W(e)}function bn(t){return new Promise(e=>setTimeout(e,t))}async function Ne(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(c){if(o=c,i>=n)break;let u=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,u*.2));await bn(u+a)}throw o}var kn=new Set(["put","get","getText","delete","list"]);function _e(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:kn.has(r)?(...o)=>Ne(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function $e(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 Le(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 G=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=$e(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Le(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{homedir as xe}from"node:os";import{join as xt,resolve as as}from"node:path";import{join as En}from"node:path";import{createHash as wn}from"node:crypto";import{dirname as xn}from"node:path";import{mkdirSync as jn,readFileSync as In,renameSync as Pn,writeFileSync as On}from"node:fs";function v(t){return wn("sha256").update(t).digest("hex")}function ge(t){if(Array.isArray(t))return t.map(ge);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=ge(e[r]);return n}return t}function Ke(t){return JSON.stringify(ge(t))}function Fe(t){try{return JSON.parse(In(t,"utf8"))}catch{return null}}function O(t,e){jn(xn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;On(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Pn(n,t)}function ze(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 De(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=ze(r.toLowerCase(),"agent"),i=ze(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:En(t.rootPath,".toolnet","sessions",o,i)}}function We(t){return String(t).padStart(12,"0")}var X=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
6
+ `,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let c=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!c)continue;let u=Number(c[1]),a=Number(c[2]);!Number.isFinite(u)||!Number.isFinite(a)||(s.push({key:i.key,start:u,end:a}),o=Math.max(o,a))}return s.sort((i,c)=>i.start-c.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
7
+ `,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),c=n.filter(g=>g.sequence>i.maxSequence),u=0;for(let g of this.split(c)){let h=g[0],b=g[g.length-1],M=g.map(T=>JSON.stringify(T)).join(`
8
8
  `)+`
9
- `,M=v(A).slice(0,16),x=[e.remotePrefix,"events",`${Ot(g.sequence)}-${Ot(w.sequence)}-${M}.jsonl`].join("/");await this.storage.exists(x)||await this.storage.put(x,A,"application/x-ndjson"),u+=y.length}let c=await this.scan(e),p=n[n.length-1],d=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?d="idle":p?.type==="error"?d="error":n.length>0&&(d="active");let m=new Date().toISOString(),l=n[0],f={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:d,createdAt:o?.createdAt??l?.timestamp??m,updatedAt:p?.timestamp??m,firstEventAt:o?.firstEventAt??l?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:c.maxSequence,chunkCount:c.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:c.maxSequence,lastRemoteSequence:c.maxSequence,sourceCursors:r,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,f),{uploadedEvents:u,lastRemoteSequence:c.maxSequence,eventCount:f.eventCount,chunkCount:f.chunkCount,status:d}}};import{closeSync as Ue,existsSync as ws,fsyncSync as vs,mkdirSync as ks,openSync as Ye,readSync as bs,rmSync as Tt,statSync as Rt,writeSync as xs}from"node:fs";import{join as Xe}from"node:path";var js=12e4,As=80,Is=2e3;function Ps(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var Se=class{constructor(e){this.identity=e;ks(e.localDirectory,{recursive:!0}),this.eventsFile=Xe(e.localDirectory,"events.jsonl"),this.stateFile=Xe(e.localDirectory,"state.json"),this.lockFile=Xe(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return Ct(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){R(this.stateFile,e)}acquireLock(){for(let e=0;e<As;e+=1)try{return Ye(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-Rt(this.lockFile).mtimeMs>js){Tt(this.lockFile,{force:!0});continue}}catch{}Ps(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{Ue(n),Tt(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 d of e){let m=d.timestamp??new Date().toISOString(),l=d.data??{},f=d.provenance?.rawDigest??v(Pt(l)),h=d.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,d.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,d.type,m,f].join("|"),y=v(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:d.type,timestamp:m,data:l,provenance:{...d.provenance,rawDigest:f}};d.role!==void 0&&(g.role=d.role),d.sourceEventId!==void 0&&(g.sourceEventId=d.sourceEventId),d.sourceSequence!==void 0&&(g.sourceSequence=d.sourceSequence),o.push(g),r.add(y)}if(o.length===0)return[];let i=o.map(d=>JSON.stringify(d)).join(`
9
+ `,C=v(M).slice(0,16),P=[e.remotePrefix,"events",`${We(h.sequence)}-${We(b.sequence)}-${C}.jsonl`].join("/");await this.storage.exists(P)||await this.storage.put(P,M,"application/x-ndjson"),u+=g.length}let a=await this.scan(e),d=n[n.length-1],l=o?.status??"active";d?.type==="session_end"||d?.type==="session_idle"?l="idle":d?.type==="error"?l="error":n.length>0&&(l="active");let m=new Date().toISOString(),p=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??p?.timestamp??m,updatedAt:d?.timestamp??m,firstEventAt:o?.firstEventAt??p?.timestamp,lastEventAt:d?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(S.title=s.title??o?.title);let y={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,y),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:u,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:l}}};import{closeSync as ye,existsSync as An,fsyncSync as Mn,mkdirSync as Tn,openSync as he,readSync as Rn,rmSync as Be,statSync as qe,writeSync as Cn}from"node:fs";import{join as Se}from"node:path";var Nn=12e4,_n=80,$n=2e3;function Ln(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var Z=class{constructor(e){this.identity=e;Tn(e.localDirectory,{recursive:!0}),this.eventsFile=Se(e.localDirectory,"events.jsonl"),this.stateFile=Se(e.localDirectory,"state.json"),this.lockFile=Se(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 Fe(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){O(this.stateFile,e)}acquireLock(){for(let e=0;e<_n;e+=1)try{return he(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-qe(this.lockFile).mtimeMs>Nn){Be(this.lockFile,{force:!0});continue}}catch{}Ln(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{ye(n),Be(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(),p=l.data??{},S=l.provenance?.rawDigest??v(Ke(p)),y=l.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,l.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,l.type,m,S].join("|"),g=v(y).slice(0,32);if(r.has(g))continue;s+=1;let h={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:m,data:p,provenance:{...l.provenance,rawDigest:S}};l.role!==void 0&&(h.role=l.role),l.sourceEventId!==void 0&&(h.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(h.sourceSequence=l.sourceSequence),o.push(h),r.add(g)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
10
10
  `)+`
11
- `,a=Ye(this.eventsFile,"a",384);try{xs(a,i,null,"utf8"),vs(a)}finally{Ue(a)}let u=o[o.length-1],c="active";u.type==="session_end"||u.type==="session_idle"?c="idle":u.type==="error"&&(c="error");let p=Array.from(r).slice(-Is);return this.saveStateUnsafe({...n,status:c,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!ws(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=Rt(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=Ye(this.eventsFile,"r");try{bs(i,o,0,s,r)}finally{Ue(i)}return{events:o.toString("utf8").split(`
12
- `).filter(Boolean).map(c=>JSON.parse(c)),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 wi,existsSync as vi,openSync as ki,readSync as bi,statSync as xi}from"node:fs";function Nt(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 Lt=[/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],Cs=[/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],Ms=[/\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],Es=[/\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],Os=[/đã sửa/iu,/đã fix/iu,/đã khắc phục/iu,/đã xử lý/iu,/hoàn tất/iu,/hoàn thành/iu,/\bfixed\b/iu,/\bresolved\b/iu,/\bimplemented\b/iu,/\bcompleted\b/iu,/\bpasses?\b/iu],_t=[/kiến trúc/iu,/pipeline/iu,/adapter/iu,/schema/iu,/runtime/iu,/namespace/iu,/storage/iu,/lưu trữ/iu,/workflow/iu,/session core/iu,/memory engine/iu,/retrieval/iu],Ts=[/\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],Rs=[/đườ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],Ns=[/\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],Kt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),_s=new Set(["payload","data","content","message","messages","parts","summary"]);function I(t,e){return e.some(n=>n.test(t))}function Wt(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Ks(t){return Wt(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function $s(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 Qe(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||Kt.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Qe(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(Kt.has(s)||_s.has(s))&&Qe(o,s,n,r+1)}}function Ls(t){let e=[];Qe(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=Wt(o);if($s(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function $t(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Ws(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&&I(t,Lt)?{kind:"rule",confidence:.98}:r&&I(t,Cs)?{kind:"rule",confidence:.92}:I(t,Ms)?{kind:I(t,_t)?"architecture":"decision",confidence:r?.93:.86}:r&&I(t,Es)?{kind:"todo",confidence:.87}:I(t,_t)&&I(t,Ts)?{kind:"architecture",confidence:r?.88:.82}:s&&I(t,Os)?{kind:"fix",confidence:.8}:r&&I(t,Rs)&&I(t,Ns)?{kind:"context",confidence:.79}:null}function Ds(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Fs(t,e,n){return t==="rule"&&I(n,Lt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":Nt(e,n)}function Dt(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=$t(o);i&&a&&s.set(i,a)}for(let o of e){let i=$t(o),a=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&a&&(i=s.get(a)??"");for(let u of Ls(o)){let c=Ws(u,i,o);if(!c||c.confidence<.75)continue;let p=Ds(c.kind),d=Ks(u),m=v([t.projectId,c.kind,d].join("|"));if(r.has(m))continue;r.add(m);let l=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:c.kind,type:p,content:u,confidence:c.confidence,importance:Fs(c.kind,p,u),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:f,sourcePaths:l,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}import{createHash as zs}from"node:crypto";var qs=["project-knowledge","implementation","continuation","session-context"],Vs={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function Ze(t){return zs("sha256").update(t).digest("hex")}function we(t,e){return`${t}:${Ze(e).slice(0,24)}`}function Bs(t){try{return Ze(JSON.stringify(t))}catch{return Ze(String(t))}}function L(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 zt(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 Js(t){return t==="rule"||t==="architecture"?"project-knowledge":t==="decision"||t==="fix"?"implementation":t==="todo"?"continuation":"session-context"}function Ft(t){return t.length===0?0:t.reduce((e,n)=>e+n,0)/t.length}function Hs(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=>zt(e.content)).join(" | ")}function Gs(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=>zt(e.content)).join(`
13
- `)}function qt(t,e){let n=t.slice().sort((m,l)=>m.sequence-l.sequence||m.timestamp.localeCompare(l.timestamp)||m.id.localeCompare(l.id)),r=n.map(m=>({id:we("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:Bs(m.data)})),s=new Map,o=new Map;n.forEach((m,l)=>{let f=r[l];f&&(s.set(m.id,f.id),m.sourceEventId&&o.set(m.sourceEventId,f.id))});let i=e.map(m=>{let l=L([...m.provenance.eventIds.map(f=>s.get(f)),...m.provenance.sourceEventIds.map(f=>o.get(f))]);return{id:we("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:L([...m.tags,"level:fact",`class:${m.knowledgeClass}`,`kind:${m.kind}`]),rawIds:l,sourcePaths:L(m.provenance.sourcePaths)}}),a=new Map;for(let m of i){let l=Js(m.kind),f=a.get(l)??[];f.push(m),a.set(l,f)}let u=[];for(let m of qs){let l=a.get(m);if(!l?.length)continue;let f=l.slice().sort((y,g)=>g.importanceScore-y.importanceScore||g.confidence-y.confidence||y.id.localeCompare(g.id)),h=f.map(y=>y.id);u.push({id:we("scene",`${m}|${h.join("|")}`),level:"scene",kind:m,title:Vs[m],summary:Hs(f),factIds:h,importanceScore:Math.max(...f.map(y=>y.importanceScore)),confidence:Ft(f.map(y=>y.confidence)),tags:L(["level:scene",`scene:${m}`,...f.flatMap(y=>y.tags)]),sourcePaths:L(f.flatMap(y=>y.sourcePaths))})}let c=new Map(i.map(m=>[m.id,m])),p=[];for(let m of u){let f=m.factIds.map(g=>c.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=Gs(f);p.push({id:we("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:Ft(f.map(g=>g.confidence)),tags:L(["level:knowledge",`class:${h}`,`scene:${m.kind}`,...f.flatMap(g=>g.tags)]),sourcePaths:L(f.flatMap(g=>g.sourcePaths))})}let d=[];for(let m of i)for(let l of m.rawIds)d.push({from:l,to:m.id,type:"supports"});for(let m of u)for(let l of m.factIds)d.push({from:l,to:m.id,type:"belongs_to"});for(let m of p)for(let l of m.sceneIds)d.push({from:l,to:m.id,type:"promotes_to"});return{schema:"toolnet.memory-hierarchy.v1",version:1,raw:r,facts:i,scenes:u,knowledge:p,links:d,stats:{raw:r.length,facts:i.length,scenes:u.length,knowledge:p.length,links:d.length}}}function Us(t){return t?Math.ceil(t.length/3.5):0}function Vt(t,e){if(!t)return"";if(Us(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 W(){let t=le(),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,u=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:u}}function Bt(t){return(t||W()).rawTranscript}function Jt(t){return(t||W()).durableMemoryMaxItemsPerSession}function Ht(t){return(t||W()).sessionSummaryMaxTokens}function Gt(t){return(t||W()).archiveRemote}function Ys(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 Xs(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 Qs(t,e){let n=[],r=new Set;for(let i of t){let a=i.split(`
15
- `).filter(u=>u.trim());for(let u of a){let c=u.trim();if(c.length<15)continue;let p=c.toLowerCase().replace(/\s+/g," ");if(r.has(p))continue;r.add(p);let d="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(c)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(c)?d="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(c)?d="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(c)?d="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(c)?d="next_action":/\b(deploy|release|publish|ship)\b/i.test(c)?d="deploy":/\b(architecture|design|structure|pattern)\b/i.test(c)?d="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(c)&&(d="file");let m=Xs(c,d);if(m<.3)continue;let l=Ys(c);n.push({category:d,text:l,importance:m,sourceSessionId:e})}}let s=W(),o=Jt(s);return n.sort((i,a)=>a.importance-i.importance).slice(0,o)}function Zs(t){let e=W(),n=Ht(e),o=t.join(`
16
-
17
- `).split(`
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 Vt(o,n)}function ve(t,e){let r=(Array.isArray(t)?t:t.split(`
20
-
21
- `).filter(l=>l.trim())).map(l=>typeof l=="string"?l:JSON.stringify(l)).filter(l=>l.trim()),s=Qs(r,e),o=s.filter(l=>l.category==="decision").map(l=>l.text),i=s.filter(l=>l.category==="rule").map(l=>l.text),a=s.filter(l=>l.category==="file").map(l=>l.text),u=s.filter(l=>l.category==="fix").map(l=>l.text),c=s.filter(l=>l.category==="blocker").map(l=>l.text),p=s.filter(l=>l.category==="next_action").map(l=>l.text),d=s.filter(l=>l.category==="deploy").map(l=>l.text);return{summary:Zs(r),decisions:o,projectRules:i,filesChanged:a,bugsFixed:u,commands:d,blockers:c,nextActions:p,durableFacts:s}}function _(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 eo(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 to(t){switch(t){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function no(t){let e=to(t.importance);return Math.max(0,Math.min(1,e*.75+t.confidence*.25))}function ro(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 so(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 oo(t){let e=ro(t),n=no(t),r=so(t.content);return{...t,knowledgeClass:e,importanceScore:n,retrievalTerms:r,tags:_([...t.tags,"level:fact",`class:${e}`,`kind:${t.kind}`])}}function io(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 ao(t,e,n){let r=ve(io(e),t.nativeSessionId),s=n.filter(c=>c.kind==="todo").map(c=>c.content),o=n.flatMap(c=>c.provenance.sourcePaths),i=n.filter(c=>c.kind==="architecture").map(c=>c.content),a=_([...s,...r.nextActions]),u=_([...r.nextActions,...s]);return{summary:r.summary,state:{task:u[0]??a[0],decisions:_(r.decisions),files:_([...r.filesChanged,...o]),todos:a,completed:_(r.bugsFixed),blockers:_(r.blockers),nextActions:u,architecture:_(i)}}}function Ut(t,e){let n=eo(e),r=Dt(t,n).map(oo),s=r.filter(p=>p.knowledgeClass!=="transient").sort((p,d)=>d.importanceScore-p.importanceScore),{summary:o,state:i}=ao(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})),u=qt(n,s),c=p=>r.filter(d=>d.knowledgeClass===p).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:a,hierarchy: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")}}}import{createHash as co}from"node:crypto";import{chmodSync as Yt,existsSync as uo,mkdirSync as lo,readFileSync as po,renameSync as mo,writeFileSync as Xt}from"node:fs";import{dirname as Qt,join as ke}from"node:path";var nt="toolnet.context-offload.v1",fo="toolnet.context-offload-asset.v1",go=256,yo=new Set(["tool_call","tool_result","file_read","file_write","file_edit","command","test","artifact"]);function Zt(t){return ke(t,".toolnet","offload")}function ho(t){return ke(Zt(t),"assets")}function en(t){return ke(Zt(t),"graph.json")}function tn(t){lo(t,{recursive:!0,mode:448});try{Yt(t,448)}catch{}}function So(t,e){tn(Qt(t));let n=`${t}.${process.pid}.${Date.now()}.tmp`;Xt(n,e,{encoding:"utf8",mode:384}),mo(n,t);try{Yt(t,384)}catch{}}function tt(t){return Array.isArray(t)?t.map(tt):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).sort(([e],[n])=>e.localeCompare(n)).map(([e,n])=>[e,tt(n)])):t}function wo(t){return co("sha256").update(JSON.stringify(tt(t)),"utf8").digest("hex")}function et(){return{schema:nt,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function vo(t){let e=en(t);if(!uo(e))return et();try{let n=JSON.parse(po(e,"utf8"));return n.schema!==nt||n.version!==1||!Array.isArray(n.nodes)?et():n}catch{return et()}}function ko(t,e){So(en(t),JSON.stringify(e,null,2)+`
22
- `)}function bo(t,e=260){if(typeof t!="string")return null;let n=t.replace(/\s+/gu," ").trim();return n?n.slice(0,e):null}function xo(t){let e=[...t.provenance.files??[],t.provenance.sourcePath],n=[];for(let r of e){let s=bo(r);if(!(!s||n.includes(s))&&(n.push(s),n.length===3))break}return n}function jo(t){return`${t.agent}:${t.sourceEventId??t.id}`.replace(/\s+/gu," ").trim().slice(0,120)}function Ao(t,e){tn(Qt(t));try{return Xt(t,e,{encoding:"utf8",flag:"wx",mode:384}),!0}catch(n){if(n.code==="EEXIST")return!1;throw n}}function Io(t,e){let n=t.nodes.find(s=>s.id===e.id),r=n?{...n,kind:e.kind,bytes:e.bytes,sourceRefs:Array.from(new Set([...n.sourceRefs,...e.sourceRefs])).slice(-8),files:Array.from(new Set([...n.files,...e.files])).slice(0,6)}:e;return{schema:nt,version:1,updatedAt:new Date().toISOString(),nodes:[...t.nodes.filter(s=>s.id!==e.id),r].slice(-go)}}function nn(t,e){let n=vo(t),r=0,s=0,o=0,i=[];for(let a of e){if(!yo.has(a.type))continue;r+=1;let u=wo({type:a.type,data:a.data}),c={schema:fo,version:1,assetId:u,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(c,null,2)+`
23
- `;Ao(ke(ho(t),`${u}.json`),p)?s+=1:o+=1,i.push(u),n=Io(n,{id:u,kind:a.type,bytes:Buffer.byteLength(p,"utf8"),createdAt:a.timestamp,sourceRefs:[jo(a)],files:xo(a)})}return r>0&&ko(t,n),{eligible:r,written:s,deduped:o,graphNodes:n.nodes.length,assetIds:i}}import{createHash as No}from"node:crypto";import{existsSync as _o,readdirSync as Ko,readFileSync as $o}from"node:fs";import{basename as Lo,join as vn}from"node:path";import{randomUUID as on}from"node:crypto";var k=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function ee(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 F(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 k("Invalid Wiki slug",400);return e}function rn(t){let e=[];for(let n of t.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&e.push(F(r))}return ee(e)}function Po(t){return t.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function sn(t){return{id:`revision-${on()}`,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 D(t){return structuredClone(t)}var be=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:ee(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 D([...e.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(e){let n=await this.ensureState(),r=F(e),s=n.pages.find(o=>o.slug===r||o.id===e);if(!s)throw new k(`Wiki page not found: ${e}`,404);return D(s)}async createPage(e){return this.mutate(n=>{let r=e.title.trim(),s=e.content.trim();if(!r)throw new k("Wiki title is required",400);let o=F(e.slug??r);if(n.pages.some(u=>u.slug===o))throw new k(`Wiki page already exists: ${o}`,409);let i=new Date().toISOString(),a={id:`wiki-${on()}`,slug:o,title:r,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:s,tags:ee(e.tags??[]),links:rn(s),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(sn(a)),D(a)})}async updatePage(e,n){return this.mutate(r=>{let s=F(e),o=r.pages.find(i=>i.slug===s||i.id===e);if(!o)throw new k(`Wiki page not found: ${e}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new k("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=rn(o.content)),n.tags!==void 0&&(o.tags=ee(n.tags)),o.revision+=1,o.updatedAt=new Date().toISOString(),r.revisions.push(sn(o)),D(o)})}async history(e){let n=await this.getPage(e),r=await this.ensureState();return D(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 D(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=ee(Po(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 u=a.title.toLowerCase(),c=a.slug.toLowerCase(),p=a.summary?.toLowerCase()??"",d=a.content.toLowerCase(),m=a.tags.map(f=>f.toLowerCase()),l=0;for(let f of s)c===f&&(l+=12),u===f&&(l+=10),u.includes(f)&&(l+=6),c.includes(f)&&(l+=5),m.some(h=>h===f)?l+=5:m.some(h=>h.includes(f))&&(l+=3),p.includes(f)&&(l+=2),d.includes(f)&&(l+=1);l>0&&i.push({page:D(a),score:l})}return i.sort((a,u)=>u.score-a.score||u.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,o)}};var an="wiki/state.v1.json";function Co(t){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:t.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function Mo(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 xe=class{constructor(e,n){this.storage=e;this.project=n}storage;project;async load(){let e=await this.storage.getText(an);if(!e){let n=Co(this.project);return await this.save(n),n}return Mo(e,this.project)}async save(e){await this.storage.put(an,JSON.stringify(e,null,2),"application/json")}};import{createHash as Eo,randomUUID as cn}from"node:crypto";var un="wiki/governance.v1.json",mn="toolnet.knowledge-governance.v1",ln=500,te={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function Oo(t,e=0,n=1){return Math.max(e,Math.min(n,t))}function rt(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function dn(t){return Eo("sha256").update(t.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function To(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 Ro(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),Oo(e)}function pn(t){let e=new Date().toISOString();return{schema:mn,version:1,projectId:t,policy:{...te},reviews:[],audit:[],createdAt:e,updatedAt:e}}function fn(t){let e=t.autoApproveThreshold??te.autoApproveThreshold,n=t.criticalApproveThreshold??te.criticalApproveThreshold,r=t.staleAfterDays??te.staleAfterDays;if(!Number.isFinite(e)||e<.5||e>1)throw new k("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new k("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new k("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:n,staleAfterDays:r}}var je=class{constructor(e,n){this.storage=e;this.project=n}storage;project;async load(){let e=await this.storage.getText(un);if(!e){let n=pn(this.project.id);return await this.save(n),n}try{let n=JSON.parse(e);if(n.schema!==mn||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:fn(n.policy??te)}}catch{let n=pn(this.project.id);return await this.save(n),n}}async save(e){await this.storage.put(un,JSON.stringify(e,null,2),"application/json")}},Ae=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:cn(),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>ln&&(e.audit=e.audit.slice(-ln))}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=fn({...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=Ro(e),o=rt(e.title),i=n.filter(p=>p.slug!==e.slug&&rt(p.title)===o&&dn(p.content)!==dn(e.content)).map(p=>p.slug),a=To(e),u=[];s<r.policy.autoApproveThreshold&&u.push(`confidence:${s.toFixed(2)}`),a&&s<r.policy.criticalApproveThreshold&&u.push("critical-knowledge"),i.length>0&&u.push("conflicting-knowledge");let c=i.length>0?"conflict":a?"critical":"normal";return{confidence:s,risk:c,requiresReview:i.length>0||s<r.policy.autoApproveThreshold||a&&s<r.policy.criticalApproveThreshold,reasons:u,conflicts:i}}async gate(e,n){let r=await this.assess(e,n);return this.mutate(s=>{let o=s.reviews.find(u=>u.sourceKey===e.sourceKey&&u.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:cn(),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(c=>c.id===e);if(!o)throw new k(`Governance review not found: ${e}`,404);if(o.status!=="pending")throw new k("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 k("targetReviewId is required for merge",400);let c=s.reviews.find(p=>p.id===n.targetReviewId);if(!c)throw new k("Merge target review not found",404);return o.status="superseded",o.mergedInto=c.id,this.audit(s,"knowledge:merged",n.principal,{reviewId:e,sourceKey:o.sourceKey,metadata:{targetReviewId:c.id}}),structuredClone(o)}o.status="approved";let u=(await r.listPages()).find(c=>c.slug===o.slug);if(u&&!u.tags.includes(o.marker))throw new k(`Wiki page '${o.slug}' is manually managed`,409);return u?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 d=s-Date.parse(p.updatedAt);return{slug:p.slug,title:p.title,updatedAt:p.updatedAt,ageDays:Math.max(0,Math.floor(d/864e5)),stale:Number.isFinite(d)&&d>o}}).filter(p=>p.stale).map(({stale:p,...d})=>d),a=new Map;for(let p of r){let d=rt(p.title),m=a.get(d)??[];m.push(p),a.set(d,m)}let u=[...a.entries()].filter(([,p])=>p.length>1).map(([p,d])=>({title:p,pages:d.map(m=>m.slug)})),c=n.reviews.filter(p=>p.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(p=>p.tags.some(d=>d.startsWith("toolnet-auto-"))).length,manualPages:r.filter(p=>!p.tags.some(d=>d.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:u,pendingReviews:c.length,lowConfidenceReviews:c.filter(p=>p.confidence<n.policy.autoApproveThreshold).length,conflicts:c.filter(p=>p.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var kn="wiki/automation.v1.json",bn="toolnet.wiki-automation.v1",it=8e3,gn=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function re(t){return No("sha256").update(JSON.stringify(t)).digest("hex")}function ne(t){if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function yn(t){return Array.isArray(t)?t:[]}function xn(t){return typeof t!="string"?void 0:t.replace(/\s+/gu," ").trim()||void 0}function st(t){return Array.isArray(t)?t.map(xn).filter(e=>!!e):[]}function E(t,e){for(let n of e){let r=xn(t[n]);if(r)return r}}function se(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 Ie(t,e=0,n=""){if(e>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(gn.has(r))return[];if(typeof t=="string"){let i=t.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(t))return t.flatMap(i=>Ie(i,e+1,n));let s=ne(t);if(!s)return[];let o=[];for(let[i,a]of Object.entries(s)){let u=i.replace(/[^a-z0-9]/giu,"").toLowerCase();gn.has(u)||o.push(...Ie(a,e+1,i))}return o}function hn(t){let n=se(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(s=>Ie(t[s],0,s)));return(n.length>0?n:se(Ie(t))).join(`
24
-
25
- `).slice(0,it)}function Sn(t,e){return E(t,["id","key","fingerprint","knowledgeId","sceneId"])??e}function wn(t,e){return E(t,["title","name","topic","label","task","kind","type"])??e}function Wo(t){return(E(t,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function Do(t){return(E(t,["kind","sceneKind","type"])??"").toLowerCase()}function Fo(t){let e=ne(t);if(!e)return[];let n=[],r=yn(e.knowledge);for(let[o,i]of r.entries()){let a=ne(i);if(!a)continue;let u=Wo(a);if(u==="session"||u==="transient")continue;let c=hn(a);if(c.length<20)continue;let p=Sn(a,re(a).slice(0,16)),d=wn(a,`Durable Memory ${o+1}`);n.push({sourceKey:`memory:${p}`,sourceType:"memory",title:d,summary:E(a,["summary","description"]),content:c,tags:se(["toolnet","auto","memory",...u?[u]:[]])})}let s=yn(e.scenes);for(let[o,i]of s.entries()){let a=ne(i);if(!a)continue;let u=Do(a);if(u==="session-context")continue;let c=hn(a);if(c.length<20)continue;let p=Sn(a,re(a).slice(0,16)),d=wn(a,`Knowledge Scene ${o+1}`);n.push({sourceKey:`scene:${p}`,sourceType:"scene",title:d,summary:E(a,["summary","description"]),content:c,tags:se(["toolnet","auto","scene",...u?[u]:[]])})}return n}function zo(t){return vn(t,".toolnet","memory","skills")}function qo(t){let e=zo(t);if(!_o(e))return{candidates:[],failed:0};let n=[],r=0,s=Ko(e).filter(o=>o.endsWith(".json")).sort();for(let o of s)try{let i=JSON.parse($o(vn(e,o),"utf8")),a=ne(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let u=E(a,["id","fingerprint"])??Lo(o,".json"),c=E(a,["task"])??"",p=E(a,["title"])||c||`Reusable Skill ${u.slice(0,8)}`,d=E(a,["summary"])??void 0,m=st(a.steps),l=st(a.verification),f=st(a.files),h=[];c&&h.push(`## Task
26
- ${c}`),d&&h.push(`## Summary
27
- ${d}`),m.length>0&&h.push(`## Procedure
28
- ${m.map((g,w)=>`${w+1}. ${g}`).join(`
29
- `)}`),l.length>0&&h.push(`## Verification
30
- ${l.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,it);if(y.length<20)continue;n.push({sourceKey:`skill:${u}`,sourceType:"skill",title:p,summary:d,content:y,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function ot(t){let e=new Date().toISOString();return{schema:bn,version:1,projectId:t,entries:[],createdAt:e,updatedAt:e}}async function Vo(t,e){let n=await t.getText(kn);if(!n)return ot(e);try{let r=JSON.parse(n);return r.schema!==bn||r.version!==1||r.projectId!==e||!Array.isArray(r.entries)?ot(e):r}catch{return ot(e)}}async function Bo(t,e){await t.put(kn,JSON.stringify(e,null,2),"application/json")}function Jo(t){return`toolnet-auto-${re(t).slice(0,12)}`}function Ho(t){let e=F(t.title).slice(0,72),n=re(t.sourceKey).slice(0,10);return F(`auto-${t.sourceType}-${e}-${n}`)}function Go(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,it)}function Uo(t){return re({sourceType:t.sourceType,title:t.title,summary:t.summary,content:t.content,tags:t.tags})}function Yo(t,e){return t.tags.includes(e)}async function jn(t){let e=Fo(t.hierarchy),n=qo(t.project.rootPath),r=new Map;for(let l of[...e,...n.candidates])r.set(l.sourceKey,l);let s=[...r.values()].sort((l,f)=>l.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 be(new xe(t.storage,t.project));await i.initialize();let a=new Ae(new je(t.storage,t.project));await a.initialize();let u=await Vo(t.storage,t.project.id),c=await i.listPages(),p=new Map(c.map(l=>[l.slug,l])),d=new Map(u.entries.map(l=>[l.sourceKey,l]));for(let l of s)try{let f=Jo(l.sourceKey),h=Uo(l),y=d.get(l.sourceKey),g=y?.slug??Ho(l),w=p.get(g);if(w&&!Yo(w,f)){o.skipped+=1;continue}let A=se([...l.tags,f]),M=Go(l),x=await a.gate({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:g,marker:f,digest:h,title:l.title,...l.summary?{summary:l.summary}:{},content:M,tags:A},[...p.values()]);if(!x.allowed){x.mode==="pending-review"?o.reviewPending+=1:o.skipped+=1;continue}x.mode==="auto-approved"?o.autoApproved+=1:x.mode==="review-approved"&&(o.reviewApproved+=1),w?y?.digest!==h?(w=await i.updatePage(g,{title:l.title,summary:l.summary??"",content:M,tags:A}),p.set(w.slug,w),o.updated+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:w.slug,action:"updated"})):(o.unchanged+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:g,action:"unchanged"})):(w=await i.createPage({slug:g,title:l.title,summary:l.summary,content:M,tags:A}),p.set(w.slug,w),o.created+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:w.slug,action:"created"}));let T=new Date().toISOString(),S={sourceKey:l.sourceKey,sourceType:l.sourceType,slug:g,digest:h,marker:f,updatedAt:T},b=u.entries.findIndex(ue=>ue.sourceKey===l.sourceKey);b>=0?u.entries[b]=S:u.entries.push(S),d.set(l.sourceKey,S),await a.markApplied(l.sourceKey,h)}catch(f){if(f instanceof k&&f.statusCode===409){o.skipped+=1;continue}o.failed+=1}let m=new Date().toISOString();return u.updatedAt=m,u.lastRunAt=m,u.entries.sort((l,f)=>l.sourceKey.localeCompare(f.sourceKey)),await Bo(t.storage,u),o}import{createHash as Xo}from"node:crypto";import{chmodSync as In,existsSync as Qo,mkdirSync as Zo,readFileSync as Jl,readdirSync as Hl,renameSync as ei,statSync as Gl,writeFileSync as ti}from"node:fs";import{join as Pn}from"node:path";var ni="toolnet.skill-memory.v1",An=5,ri=16,si=24,oi=32;function ii(t){return Xo("sha256").update(t).digest("hex")}function ie(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 at(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 ai(t){return t.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/giu,"Bearer [REDACTED]").replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu,"[REDACTED]").replace(/\b(api[_-]?key|token|password|passwd|secret)\b(\s*[:=]\s*)(["']?)[^\s"'`]+/giu,"$1$2[REDACTED]")}function N(t,e=360){return t&&at(ai(t),e)||void 0}function ae(t,e){for(let n of e){let r=t[n];if(typeof r=="string"&&r.trim())return r}}function Cn(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 Mn(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 En(t){let e=t.data??{};if(Mn(e,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=Cn(e,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let s=ae(e,["status","result","outcome"]);return!!(s&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(s))}function oe(t){let e=t.data??{};if(En(t))return!1;if(Mn(e,["passed","pass","success","succeeded","ok"])===!0||Cn(e,["exitCode","exit_code","code","statusCode"])===0)return!0;let s=ae(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 On(t){let e=t.data??{},n=ae(e,["path","file","filePath","filename","target"]);if(n)return N(n,260);let r=t.provenance?.files;return N(r?.[0],260)}function ct(t){return N(ae(t.data??{},["command","cmd","script"]),420)}function z(t){return N(ae(t.data??{},["name","test","suite","title","message","text","result","status"]),300)}function ci(t){let e=[];for(let n of[...t].sort((r,s)=>r.sequence-s.sequence))if(oe(n)){if(n.type==="test"){let r=z(n)??ct(n)??"Tests passed";e.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=z(n);e.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=z(n);e.push(r?`Deploy: ${r}`:"Deployment completed")}}return ie(e,10)}function ui(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=On(r);s&&n.push(`Update ${s}`);break}case"command":{if(En(r))break;let s=ct(r);s&&n.push(`Run: ${s}`);break}case"test":{if(!oe(r))break;let s=z(r)??ct(r)??"project tests";n.push(`Verify: ${s}`);break}case"commit":{if(!oe(r))break;let s=z(r);n.push(s?`Commit: ${s}`:"Commit verified changes");break}case"deploy":{if(!oe(r))break;let s=z(r);n.push(s?`Deploy: ${s}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of e.files.slice(0,8)){let s=N(r,260);s&&n.push(`Update ${s}`)}return ie(n,ri)}function li(t,e){let n=[...e.files];for(let r of t){let s=On(r);s&&n.push(s);for(let o of r.provenance?.files??[]){let i=N(o,260);i&&n.push(i)}}return ie(n,si)}function di(t){return ie(t.filter(e=>["file_write","file_edit","command","test","commit","deploy"].includes(e.type)).map(e=>e.id),oi)}function pi(t){return t.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function Tn(t,e,n){if(e.length===0)return[];let r=ci(e),s=ie(n.completed.map(f=>N(f,280)??""),An);if(!(s.length>0||e.some(f=>["test","commit","deploy"].includes(f.type)&&oe(f))))return[];let i=N(n.task,280)??N(n.nextActions[0],280),a=s.length>0?s:i?[i]:[];if(a.length===0)return[];let u=ui(e,n);if(u.length===0)return[];let c=li(e,n),p=di(e),d=Math.min(...e.map(f=>f.sequence)),m=Math.max(...e.map(f=>f.sequence)),l=pi(e);return a.slice(0,An).map(f=>{let h=[`Reusable procedure learned from successful task: ${f}.`,c.length>0?`Files: ${c.slice(0,6).join(", ")}.`:"",r.length>0?`Verification: ${r.slice(0,4).join("; ")}.`:""].filter(Boolean),y=JSON.stringify({projectId:t.projectId,task:f,steps:u,verification:r,files:c}),g=ii(y);return{schema:ni,version:1,id:`skill-${g.slice(0,24)}`,fingerprint:g,projectId:t.projectId,title:at(`SOP: ${f}`,180),task:f,summary:at(h.join(" "),900),steps:u,verification:r,files:c,source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:d,lastSequence:m,eventIds:p},createdAt:l}})}function mi(t){return Pn(t.rootPath,".toolnet","memory","skills")}function fi(t){let e=mi(t);return Zo(e,{recursive:!0,mode:448}),In(e,448),e}function Rn(t,e){if(e.length===0)return{written:0,deduped:0,files:[]};let n=fi(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=Pn(n,`${i.id}.json`);if(o.push(a),Qo(a)){s+=1;continue}let u=`${a}.${process.pid}.${Date.now()}.tmp`;ti(u,JSON.stringify(i,null,2)+`
37
- `,{encoding:"utf8",mode:384}),ei(u,a),In(a,384),r+=1}return{written:r,deduped:s,files:o}}function Nn(t){return String(t).padStart(12,"0")}function gi(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var Pe=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
- `,u=v(r.map(p=>p.fingerprint).sort().join("|")).slice(0,16),c=[gi(e),"batches",`${Nn(s)}-${Nn(o)}-${u}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,a,"application/json"),c}};import{createHash as yi}from"node:crypto";function _n(t){return String(t).padStart(12,"0")}function hi(t){return yi("sha256").update(t).digest("hex")}function Si(t){return t.remotePrefix.replace("/sessions/","/memory/hierarchy/")}var Ce=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(c=>c.sequence)),o=Math.max(...n.map(c=>c.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=hi([...r.facts.map(c=>c.id),...r.knowledge.map(c=>c.id)].sort().join("|")).slice(0,16),u=[Si(e),"batches",`${_n(s)}-${_n(o)}-${a}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,`${JSON.stringify(i,null,2)}
39
- `,"application/json"),u}};function ji(t,e){if(!vi(t))return{events:[],nextOffset:e};let n=xi(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=ki(t,"r");try{bi(i,o,0,s,r)}finally{wi(i)}let a=o.toString("utf8"),u=a.lastIndexOf(`
40
- `);if(u<0)return{events:[],nextOffset:r};let c=a.slice(0,u+1);return{events:c.split(`
41
- `).filter(Boolean).flatMap(d=>{try{return[JSON.parse(d)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var Me=class{constructor(e){this.options=e;this.journal=new Pe(e.storage),this.hierarchyJournal=new Ce(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=ji(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Ut(this.options.identity,s.events),i=o.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,s.events,i));let u=!1;o.hierarchy.facts.length>0&&(u=!!await this.hierarchyJournal.write(this.options.identity,s.events,o.hierarchy));let c=Tn(this.options.identity,s.events,o.state),p=Rn(this.options.project,c);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",u?1:0),this.options.wal.setSourceCursor("memory.skill.assets",c.length),this.options.wal.setSourceCursor("memory.skill.written",p.written),this.options.wal.setSourceCursor("memory.skill.deduped",p.deduped);try{let d=nn(this.options.project.rootPath,s.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",d.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",d.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",d.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",d.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let d=await jn({project:this.options.project,storage:this.options.storage,hierarchy:o.hierarchy});this.options.wal.setSourceCursor("memory.wiki_automation.scanned",d.scanned),this.options.wal.setSourceCursor("memory.wiki_automation.eligible",d.eligible),this.options.wal.setSourceCursor("memory.wiki_automation.created",d.created),this.options.wal.setSourceCursor("memory.wiki_automation.updated",d.updated),this.options.wal.setSourceCursor("memory.wiki_automation.unchanged",d.unchanged),this.options.wal.setSourceCursor("memory.wiki_automation.skipped",d.skipped),this.options.wal.setSourceCursor("memory.wiki_automation.failed",d.failed),this.options.wal.setSourceCursor("memory.wiki_automation.review_pending",d.reviewPending),this.options.wal.setSourceCursor("memory.wiki_automation.auto_approved",d.autoApproved),this.options.wal.setSourceCursor("memory.wiki_automation.review_approved",d.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 Oi,existsSync as Ti,openSync as Ri,readSync as Ni,statSync as _i}from"node:fs";var Ai=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function V(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function $n(t){return V(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function q(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))q(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Ai.has(r)||["data","payload","parts","messages"].includes(r))&&q(s,e,n+1)}}function Ee(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 Kn(t){let e=V(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 j(t,e,n,r,s={}){let o=V(r),i=s.key??$n(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 Ii(t,e,n){let r=V(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(j(t,e,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&s.push(j(t,e,"plan",a[1],{confidence:.95}));let u=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,c;for(;!o&&(c=u.exec(r));){let m=Number(c[1]),l=V(c[2]??""),f=l&&!Kn(l)?`Phase ${m} - ${l}`:`Phase ${m}`;s.push(j(t,e,"phase",f,{key:`phase:${m}`,order:m,status:Ee(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(j(t,e,"task",p[2],{status:p[1].trim()?"completed":Ee(p[2]),confidence:.96}));let d=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(d?.[2]){let m=d[1]?Number(d[1]):void 0,l=V(d[2]),f=Kn(l);s.push(j(t,e,"task",f&&m!==void 0?`TODO ${m}`:l,{key:m!==void 0?`task:${m}`:$n(l),order:m,status:Ee(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(j(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(j(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(j(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(j(t,e,"decision",r,{confidence:.9})),s}function Ln(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let u=[];q(i.data,u);for(let c of u)s(j(t,i,"decision",c,{confidence:1}))}if(i.type==="todo"){let u=[];q(i.data,u);for(let c of u)s(j(t,i,"task",c,{status:Ee(c),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let c=i.data[u];typeof c=="string"&&c&&s(j(t,i,"file",c,{confidence:1}))}if(i.type==="test"){let u=[];q(i.data,u);for(let c of u)s(j(t,i,"test",c,{confidence:1}))}let a=[];q(i.data,a);for(let u of a)for(let c of u.split(/\n+/u))for(let p of Ii(t,i,c))s(p)}let o=e[e.length-1];return s(j(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function Wn(t){return String(t).padStart(12,"0")}var Oe=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.sequence)),s=Math.max(...n.map(c=>c.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=v(n.map(c=>c.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Wn(r)}-${Wn(s)}-${a}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as Dn}from"node:path";import{mkdirSync as Pi}from"node:fs";function Ci(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function B(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Ci(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Mi(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 Fn(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&&Mi(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 Ei(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 Te(t,e){let r=(await Ei(t,e)).flatMap(S=>S.observations).sort((S,b)=>{let ue=S.occurredAt.localeCompare(b.occurredAt);if(ue!==0)return ue;let ft=S.sequence-b.sequence;return ft!==0?ft:S.id.localeCompare(b.id)}),s=new Map,o=new Map,i,a,u,c=[],p=[],d=[],m=[],l=[],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,Fn(s.get(S.key),S));break;case"task":o.set(S.key,Fn(o.get(S.key),S));break;case"decision":c.push(S.text);break;case"blocker":p.push(S.text);break;case"warning":d.push(S.text);break;case"next_action":m.push(S.text);break;case"file":l.push(S.text);break;case"test":f.push(S.text);break;case"session":u={agent:S.agent,nativeSessionId:S.nativeSessionId,sessionKey:S.sessionKey,updatedAt:S.occurredAt};break}let h=Array.from(s.values()).sort((S,b)=>(S.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),y=Array.from(o.values()).sort((S,b)=>(S.order??Number.MAX_SAFE_INTEGER)-(b.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"),w=y.find(S=>S.status==="in_progress")??y.find(S=>S.status==="blocked")??y.find(S=>S.status==="pending"),A=B([...m,...w?[w.title]:[],...!w&&g?[g.title]:[],...y.filter(S=>S.status==="pending").slice(0,5).map(S=>S.title)],8),M=B([...p,...h.filter(S=>S.status==="blocked").map(S=>S.title),...y.filter(S=>S.status==="blocked").map(S=>S.title)],20),x={version:1,projectId:t.id,projectName:t.name,goal:i,plan:a,phases:h,tasks:y,decisions:B(c,20),blockers:M,warnings:B(d,20),nextActions:A,filesTouched:B(l,30),tests:B(f,20),currentPhase:g,currentTask:w,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:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},T=Dn(t.rootPath,".toolnet","work");return Pi(T,{recursive:!0}),R(Dn(T,"current.json"),x),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(x,null,2)+`
43
- `,"application/json"),x}async function zn(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 Ki(t,e){if(!Ti(t))return{events:[],nextOffset:e};let n=_i(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=Ri(t,"r");try{Ni(i,o,0,s,r)}finally{Oi(i)}let a=o.toString("utf8"),u=a.lastIndexOf(`
44
- `);if(u<0)return{events:[],nextOffset:r};let c=a.slice(0,u+1);return{events:c.split(`
45
- `).filter(Boolean).flatMap(d=>{try{return[JSON.parse(d)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var Re=class{constructor(e){this.options=e;this.journal=new Oe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Ki(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=Ln(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Te(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 Bi,existsSync as Ji,openSync as Hi,readSync as Gi,statSync as Ui}from"node:fs";var $i=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function J(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function ut(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))ut(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))($i.has(r)||["data","payload","parts","messages"].includes(r))&&ut(s,e,n+1)}}function P(t,e,n,r,s,o=.95){let i=J(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 O(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return J(t.slice(r.length+1))}return null}function Li(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Wi(t){return J(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function qn(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=[];ut(o.data,i);for(let a of i){let u={type:"project"},c=null;for(let p of a.split(/\r?\n/u)){let d=J(p);if(!d){c=null;continue}let m=d.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let b=Number(m[1]);u={type:"phase",key:`phase:${b}`,order:b,title:J(m[2]??"")},c=null;continue}let l=d.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let b=Number(l[1]);u={type:"task",key:`task:${b}`,order:b,title:J(l[2]??"")},c=null;continue}let f=O(d,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(f){s(P(t,o,"mission",f,{type:"project"},.99)),c=null;continue}let h=O(d,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(P(t,o,u.type==="phase"?"phase_objective":"objective",h,u,.98)),c=null;continue}let y=O(d,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(P(t,o,u.type==="phase"?"phase_why":"why",y,u,.98)),c=null;continue}let g=O(d,["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(P(t,o,"desired_outcome",g,{type:"project"},.98)),c=null;continue}let w=O(d,["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(P(t,o,"plan_rationale",w,{type:"project"},.98)),c=null;continue}let A=O(d,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(A){s(P(t,o,"phase_deliverable",A,u,.97)),c=null;continue}let M=O(d,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(M){s(P(t,o,"acceptance_criterion",M,u,.98)),c="acceptance_criterion";continue}let x=O(d,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(x){s(P(t,o,"dependency",x,u,.97)),c="dependency";continue}let T=O(d,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(T){s(P(t,o,"open_question",T,u,.95)),c="open_question";continue}let S=O(d,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(S){s(P(t,o,"constraint",S,u,.97)),c="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(d)){c="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(d)){c="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(d)){c="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(d)){c="constraint";continue}if(c&&Li(p)){s(P(t,o,c,Wi(p),u,.96));continue}c=null}}}return n}function Vn(t){return String(t).padStart(12,"0")}var Ne=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.evidence.sequence)),s=Math.max(...n.map(u=>u.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=v(n.map(u=>u.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${Vn(r)}-${Vn(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 Di}from"node:fs";import{join as Bn}from"node:path";function Fi(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function zi(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 K(t,e){return zi(e,t)?e:t}function $(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function qi(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 Vi(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function Jn(t,e){let r=(await qi(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,u,c=new Map,p=[],d=[],m=[];for(let h of r){let y=Fi(h);if(h.scope==="phase"&&h.scopeKey){let g=c.get(h.scopeKey)??Vi(h);switch(h.kind){case"phase_objective":g.objective=K(g.objective,y);break;case"phase_why":g.why=K(g.why,y);break;case"phase_deliverable":g.deliverable=K(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}c.set(g.key,g);continue}switch(h.kind){case"mission":s=K(s,y);break;case"objective":o=K(o,y);break;case"why":i=K(i,y);break;case"desired_outcome":a=K(a,y);break;case"plan_rationale":u=K(u,y);break;case"open_question":p.push(y);break;case"constraint":d.push(y);break;case"note":m.push(y);break}}for(let h of c.values())h.acceptanceCriteria=$(h.acceptanceCriteria,20),h.dependencies=$(h.dependencies,15),h.openQuestions=$(h.openQuestions,15),h.constraints=$(h.constraints,15),h.notes=$(h.notes,20);let l={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:a,planRationale:u,phases:Array.from(c.values()).sort((h,y)=>h.order-y.order),openQuestions:$(p,20),constraints:$(d,20),notes:$(m,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},f=Bn(t.rootPath,".toolnet","work");return Di(f,{recursive:!0}),R(Bn(f,"semantic-current.json"),l),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
47
- `,"application/json"),l}function Yi(t,e){if(!Ji(t))return{events:[],nextOffset:e};let n=Ui(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=Hi(t,"r");try{Gi(o,s,0,s.length,r)}finally{Bi(o)}let i=s.toString("utf8"),a=i.lastIndexOf(`
48
- `);if(a<0)return{events:[],nextOffset:r};let u=i.slice(0,a+1);return{events:u.split(`
49
- `).filter(Boolean).flatMap(c=>{try{return[JSON.parse(c)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var _e=class{constructor(e){this.options=e;this.journal=new Ne(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Yi(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 Jn(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 ca}from"node:fs";import{join as lt}from"node:path";import{existsSync as Un,mkdirSync as Xi,readFileSync as Qi,statSync as Hn,writeFileSync as Zi}from"node:fs";import{dirname as ea,join as ta}from"node:path";var Gn=64*1024,na=`# ToolNet Project Operating Manual
11
+ `,c=he(this.eventsFile,"a",384);try{Cn(c,i,null,"utf8"),Mn(c)}finally{ye(c)}let u=o[o.length-1],a="active";u.type==="session_end"||u.type==="session_idle"?a="idle":u.type==="error"&&(a="error");let d=Array.from(r).slice(-$n);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:d}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!An(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=qe(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=he(this.eventsFile,"r");try{Rn(i,o,0,s,r)}finally{ye(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 Qn,existsSync as er,openSync as tr,readSync as nr,statSync as rr}from"node:fs";function Je(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 Ye=[/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],Kn=[/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],Fn=[/\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],zn=[/\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],Dn=[/đã 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],Ve=[/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],Wn=[/\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],Bn=[/đườ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],qn=[/\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],Ue=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Jn=new Set(["payload","data","content","message","messages","parts","summary"]);function x(t,e){return e.some(n=>n.test(t))}function Ge(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Vn(t){return Ge(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Un(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 ve(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||Ue.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))ve(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(Ue.has(s)||Jn.has(s))&&ve(o,s,n,r+1)}}function Hn(t){let e=[];ve(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=Ge(o);if(Un(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function He(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Yn(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&&x(t,Ye)?{kind:"rule",confidence:.98}:r&&x(t,Kn)?{kind:"rule",confidence:.92}:x(t,Fn)?{kind:x(t,Ve)?"architecture":"decision",confidence:r?.93:.86}:r&&x(t,zn)?{kind:"todo",confidence:.87}:x(t,Ve)&&x(t,Wn)?{kind:"architecture",confidence:r?.88:.82}:s&&x(t,Dn)?{kind:"fix",confidence:.8}:r&&x(t,Bn)&&x(t,qn)?{kind:"context",confidence:.79}:null}function Gn(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Xn(t,e,n){return t==="rule"&&x(n,Ye)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":Je(e,n)}function Xe(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,c=He(o);i&&c&&s.set(i,c)}for(let o of e){let i=He(o),c=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&c&&(i=s.get(c)??"");for(let u of Hn(o)){let a=Yn(u,i,o);if(!a||a.confidence<.75)continue;let d=Gn(a.kind),l=Vn(u),m=v([t.projectId,a.kind,l].join("|"));if(r.has(m))continue;r.add(m);let p=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:d,content:u,confidence:a.confidence,importance:Xn(a.kind,d,u),tags:[d],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:p,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function Ze(t){return String(t).padStart(12,"0")}function Zn(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var Q=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(d=>d.sequence)),o=Math.max(...n.map(d=>d.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},c=JSON.stringify(i,null,2)+`
13
+ `,u=v(r.map(d=>d.fingerprint).sort().join("|")).slice(0,16),a=[Zn(e),"batches",`${Ze(s)}-${Ze(o)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,c,"application/json"),a}};function sr(t,e){if(!er(t))return{events:[],nextOffset:e};let n=rr(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=tr(t,"r");try{nr(i,o,0,s,r)}finally{Qn(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
14
+ `);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
15
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var ee=class{constructor(e){this.options=e;this.journal=new Q(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=sr(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Xe(this.options.identity,s.events),i=!1;return o.length>0&&(i=!!await this.journal.write(this.options.identity,s.events,o)),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:o.length,journalWritten:i,nextOffset:s.nextOffset}}};import{closeSync as pr,existsSync as dr,openSync as fr,readSync as mr,statSync as gr}from"node:fs";var or=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function _(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function et(t){return _(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function N(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))N(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(or.has(r)||["data","payload","parts","messages"].includes(r))&&N(s,e,n+1)}}function te(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 Qe(t){let e=_(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 k(t,e,n,r,s={}){let o=_(r),i=s.key??et(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 ir(t,e,n){let r=_(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(k(t,e,"goal",i[1],{confidence:.97}));let c=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);c?.[1]&&s.push(k(t,e,"plan",c[1],{confidence:.95}));let u=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=u.exec(r));){let m=Number(a[1]),p=_(a[2]??""),S=p&&!Qe(p)?`Phase ${m} - ${p}`:`Phase ${m}`;s.push(k(t,e,"phase",S,{key:`phase:${m}`,order:m,status:te(r),confidence:.93}))}let d=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);d?.[2]&&s.push(k(t,e,"task",d[2],{status:d[1].trim()?"completed":te(d[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,p=_(l[2]),S=Qe(p);s.push(k(t,e,"task",S&&m!==void 0?`TODO ${m}`:p,{key:m!==void 0?`task:${m}`:et(p),order:m,status:te(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let 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(k(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(k(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(k(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(k(t,e,"decision",r,{confidence:.9})),s}function tt(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let u=[];N(i.data,u);for(let a of u)s(k(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];N(i.data,u);for(let a of u)s(k(t,i,"task",a,{status:te(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let a=i.data[u];typeof a=="string"&&a&&s(k(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let u=[];N(i.data,u);for(let a of u)s(k(t,i,"test",a,{confidence:1}))}let c=[];N(i.data,c);for(let u of c)for(let a of u.split(/\n+/u))for(let d of ir(t,i,a))s(d)}let o=e[e.length-1];return s(k(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function nt(t){return String(t).padStart(12,"0")}var ne=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
16
+ `,c=v(n.map(a=>a.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${nt(r)}-${nt(s)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as rt}from"node:path";import{mkdirSync as ar}from"node:fs";function cr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=cr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function ur(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 st(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&&ur(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 lr(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,c)=>i.key.localeCompare(c.key))){let i=await e.getText(o.key);if(i)try{let c=JSON.parse(i);c.version===1&&Array.isArray(c.observations)&&s.push(c)}catch{}}return s}async function re(t,e){let r=(await lr(t,e)).flatMap(f=>f.observations).sort((f,w)=>{let je=f.occurredAt.localeCompare(w.occurredAt);if(je!==0)return je;let Ie=f.sequence-w.sequence;return Ie!==0?Ie:f.id.localeCompare(w.id)}),s=new Map,o=new Map,i,c,u,a=[],d=[],l=[],m=[],p=[],S=[];for(let f of r)switch(f.kind){case"goal":i=f.text;break;case"plan":c=f.text;break;case"phase":s.set(f.key,st(s.get(f.key),f));break;case"task":o.set(f.key,st(o.get(f.key),f));break;case"decision":a.push(f.text);break;case"blocker":d.push(f.text);break;case"warning":l.push(f.text);break;case"next_action":m.push(f.text);break;case"file":p.push(f.text);break;case"test":S.push(f.text);break;case"session":u={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let y=Array.from(s.values()).sort((f,w)=>(f.order??Number.MAX_SAFE_INTEGER)-(w.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((f,w)=>(f.order??Number.MAX_SAFE_INTEGER)-(w.order??Number.MAX_SAFE_INTEGER)),h=y.find(f=>f.status==="in_progress")??y.find(f=>f.status==="blocked")??y.find(f=>f.status==="pending"),b=g.find(f=>f.status==="in_progress")??g.find(f=>f.status==="blocked")??g.find(f=>f.status==="pending"),M=$([...m,...b?[b.title]:[],...!b&&h?[h.title]:[],...g.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),C=$([...d,...y.filter(f=>f.status==="blocked").map(f=>f.title),...g.filter(f=>f.status==="blocked").map(f=>f.title)],20),P={version:1,projectId:t.id,projectName:t.name,goal:i,plan:c,phases:y,tasks:g,decisions:$(a,20),blockers:C,warnings:$(l,20),nextActions:M,filesTouched:$(p,30),tests:$(S,20),currentPhase:h,currentTask:b,progress:{phasesTotal:y.length,phasesCompleted:y.filter(f=>f.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(f=>f.status==="completed").length,blocked:y.filter(f=>f.status==="blocked").length+g.filter(f=>f.status==="blocked").length},lastSession:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},T=rt(t.rootPath,".toolnet","work");return ar(T,{recursive:!0}),O(rt(T,"current.json"),P),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(P,null,2)+`
17
+ `,"application/json"),P}async function ot(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 yr(t,e){if(!dr(t))return{events:[],nextOffset:e};let n=gr(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=fr(t,"r");try{mr(i,o,0,s,r)}finally{pr(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
18
+ `);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
19
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var se=class{constructor(e){this.options=e;this.journal=new ne(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=yr(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=tt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await re(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 Ir,existsSync as Pr,openSync as Or,readSync as Er,statSync as Ar}from"node:fs";var hr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function L(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function be(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))be(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))&&be(s,e,n+1)}}function j(t,e,n,r,s,o=.95){let i=L(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 I(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 L(t.slice(r.length+1))}return null}function Sr(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function vr(t){return L(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function it(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=[];be(o.data,i);for(let c of i){let u={type:"project"},a=null;for(let d of c.split(/\r?\n/u)){let l=L(d);if(!l){a=null;continue}let m=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let w=Number(m[1]);u={type:"phase",key:`phase:${w}`,order:w,title:L(m[2]??"")},a=null;continue}let p=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(p){let w=Number(p[1]);u={type:"task",key:`task:${w}`,order:w,title:L(p[2]??"")},a=null;continue}let S=I(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(j(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let y=I(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(y){s(j(t,o,u.type==="phase"?"phase_objective":"objective",y,u,.98)),a=null;continue}let g=I(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(j(t,o,u.type==="phase"?"phase_why":"why",g,u,.98)),a=null;continue}let h=I(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){s(j(t,o,"desired_outcome",h,{type:"project"},.98)),a=null;continue}let b=I(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(b){s(j(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let M=I(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(M){s(j(t,o,"phase_deliverable",M,u,.97)),a=null;continue}let C=I(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(C){s(j(t,o,"acceptance_criterion",C,u,.98)),a="acceptance_criterion";continue}let P=I(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(P){s(j(t,o,"dependency",P,u,.97)),a="dependency";continue}let T=I(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(T){s(j(t,o,"open_question",T,u,.95)),a="open_question";continue}let f=I(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(f){s(j(t,o,"constraint",f,u,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){a="constraint";continue}if(a&&Sr(d)){s(j(t,o,a,vr(d),u,.96));continue}a=null}}}return n}function at(t){return String(t).padStart(12,"0")}var oe=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.evidence.sequence)),s=Math.max(...n.map(u=>u.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=v(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${at(r)}-${at(s)}-${i}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,JSON.stringify(o,null,2)+`
20
+ `,"application/json"),c}};import{mkdirSync as br}from"node:fs";import{join as ct}from"node:path";function kr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function wr(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 E(t,e){return wr(e,t)?e:t}function A(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 xr(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,c)=>i.key.localeCompare(c.key))){let i=await e.getText(o.key);if(i)try{let c=JSON.parse(i);c.version===1&&Array.isArray(c.observations)&&s.push(c)}catch{}}return s}function jr(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function ut(t,e){let r=(await xr(t,e)).flatMap(y=>y.observations).sort((y,g)=>{let h=y.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return h!==0?h:y.evidence.sessionKey===g.evidence.sessionKey?y.evidence.sequence-g.evidence.sequence:y.id.localeCompare(g.id)}),s,o,i,c,u,a=new Map,d=[],l=[],m=[];for(let y of r){let g=kr(y);if(y.scope==="phase"&&y.scopeKey){let h=a.get(y.scopeKey)??jr(y);switch(y.kind){case"phase_objective":h.objective=E(h.objective,g);break;case"phase_why":h.why=E(h.why,g);break;case"phase_deliverable":h.deliverable=E(h.deliverable,g);break;case"acceptance_criterion":h.acceptanceCriteria.push(g);break;case"dependency":h.dependencies.push(g);break;case"open_question":h.openQuestions.push(g);break;case"constraint":h.constraints.push(g);break;case"note":h.notes.push(g);break}a.set(h.key,h);continue}switch(y.kind){case"mission":s=E(s,g);break;case"objective":o=E(o,g);break;case"why":i=E(i,g);break;case"desired_outcome":c=E(c,g);break;case"plan_rationale":u=E(u,g);break;case"open_question":d.push(g);break;case"constraint":l.push(g);break;case"note":m.push(g);break}}for(let y of a.values())y.acceptanceCriteria=A(y.acceptanceCriteria,20),y.dependencies=A(y.dependencies,15),y.openQuestions=A(y.openQuestions,15),y.constraints=A(y.constraints,15),y.notes=A(y.notes,20);let p={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:c,planRationale:u,phases:Array.from(a.values()).sort((y,g)=>y.order-g.order),openQuestions:A(d,20),constraints:A(l,20),notes:A(m,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=ct(t.rootPath,".toolnet","work");return br(S,{recursive:!0}),O(ct(S,"semantic-current.json"),p),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(p,null,2)+`
21
+ `,"application/json"),p}function Mr(t,e){if(!Pr(t))return{events:[],nextOffset:e};let n=Ar(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=Or(t,"r");try{Er(o,s,0,s.length,r)}finally{Ir(o)}let i=s.toString("utf8"),c=i.lastIndexOf(`
22
+ `);if(c<0)return{events:[],nextOffset:r};let u=i.slice(0,c+1);return{events:u.split(`
23
+ `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var ie=class{constructor(e){this.options=e;this.journal=new oe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Mr(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=it(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ut(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as zr}from"node:fs";import{join as ke}from"node:path";import{existsSync as dt,mkdirSync as Tr,readFileSync as Rr,statSync as lt,writeFileSync as Cr}from"node:fs";import{dirname as Nr,join as _r}from"node:path";var pt=64*1024,$r=`# ToolNet Project Operating Manual
50
24
 
51
25
  This file contains persistent instructions for AI agents working on this project.
52
26
 
@@ -89,60 +63,21 @@ Things an AI agent should always remember.
89
63
  <!--
90
64
  - [advisory] Prefer small focused files.
91
65
  -->
92
- `;function Yn(t){return ta(t.rootPath,".toolnet","PROJECT.md")}function ra(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function sa(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=ra(s[2]);if(!i)continue;let a=`${o}:${i.toLowerCase()}`;n.has(a)||(n.add(a),e.push({id:v(a).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function oa(t){let e=Yn(t);return Un(e)||(Xi(ea(e),{recursive:!0}),Zi(e,na,{encoding:"utf8",mode:384})),e}function Xn(t,e=!1){let n=e?oa(t):Yn(t);if(!Un(n))return null;if(Hn(n).size>Gn)throw new Error(`PROJECT.md exceeds ${Gn} bytes`);let s=Qi(n,"utf8");return{path:n,content:s,digest:v(s),rules:sa(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Hn(n).mtimeMs).toISOString()}}function C(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 Qn(t){if(t)return{id:t.id,title:t.title,status:t.status}}function ia(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 aa(t){return v(JSON.stringify(t))}function Zn(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),u=r.tasks.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),c=C(r.nextActions,10),p=C([...u,...c],15),d=C(r.tests.slice().reverse(),10),m=C(r.filesTouched.slice().reverse(),20),l={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:Qn(r.currentPhase),task:Qn(r.currentTask),file:s},completed:{phases:C(o,20),tasks:C(i,30)},remaining:{phases:C(a,20),tasks:C(u,30),todos:p},nextAction:c[0],blockers:C(r.blockers.slice().reverse(),10),decisions:C(r.decisions.slice().reverse(),10),files:{current:s,recent:m},tests:{status:ia(r.tests),recent:d},attention:C(t.attention??[],20),progress:r.progress},{capturedAt:f,source:h,...y}=l;return{...l,stateDigest:aa(y)}}function ua(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 Ke=class{constructor(e){this.options=e}options;async capture(e,n){let r=await zn(this.options.project,this.options.storage);if(r||(r=await Te(this.options.project,this.options.storage)),!ua(r))return null;let s=Xn(this.options.project,!1),i=[...s?s.rules.filter(f=>f.mode==="enforce").map(f=>f.text):[],...r.warnings].slice(0,20),a=Zn({project:this.options.project,identity:this.options.identity,state:r,reason:e,sequence:n,attention:i}),u=a.stateDigest,c=v([this.options.project.id,this.options.identity.sessionKey,u].join("|")).slice(0,24),p=new Date().toISOString(),d={version:1,id:c,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:u,continuity:a},m=`projects/${this.options.project.id}/work/handoffs/${c}.json`;await this.options.storage.exists(m)||await this.options.storage.put(m,JSON.stringify(d,null,2)+`
94
- `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(d,null,2)+`
95
- `,"application/json");let l=lt(this.options.project.rootPath,".toolnet","work","handoffs");return ca(l,{recursive:!0}),R(lt(l,`${c}.json`),d),R(lt(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),d),d}};var $e=class{identity;wal;remote;sanitizer=new X;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=Et(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new Se(this.identity),this.remote=new he(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new Me({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new Re({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new _e({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new Ke({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as la,openSync as da,closeSync as pa,readSync as ma,statSync as fa}from"node:fs";function ga(t){let e=typeof t.role=="string"?t.role:"",n=typeof t.type=="string"?t.type.toLowerCase():"";return e==="user"||n.includes("user")?"user_prompt":e==="assistant"||n.includes("assistant")||n.includes("model")?"assistant_message":n.includes("tool")||"toolCall"in t||"tool_call"in t?"tool_call":n.includes("error")?"error":"message"}function ya(t){let e=[t.timestamp,t.createdAt,t.time,t.created_at];for(let n of e){if(typeof n=="string"){let r=new Date(n);if(!Number.isNaN(r.getTime()))return r.toISOString()}if(typeof n=="number"){let r=n;r<1e11&&(r*=1e3);let s=new Date(r);if(!Number.isNaN(s.getTime()))return s.toISOString()}}return new Date().toISOString()}function er(t,e={offset:0}){if(!la(t))return{events:[],nextOffset:e.offset,reset:!1};let n=fa(t).size,r=e.offset>n,s=r?0:e.offset;if(s===n)return{events:[],nextOffset:n,reset:r};let o=n-s,i=Buffer.alloc(o),a=da(t,"r");try{ma(a,i,0,o,s)}finally{pa(a)}let u=i.toString("utf8"),c=u.lastIndexOf(`
96
- `);if(c<0)return{events:[],nextOffset:s,reset:r};let p=u.slice(0,c+1),d=Buffer.byteLength(p,"utf8"),m=[],l=0;for(let f of p.split(`
97
- `)){if(!f)continue;let h=Buffer.byteLength(f+`
98
- `,"utf8"),y=s+l;l+=h;let g;try{g=JSON.parse(f)}catch{m.push({type:"custom",sourceEventId:`transcript:${y}`,sourceSequence:y,data:{format:"raw-line",content:f},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:y}});continue}let w=g&&typeof g=="object"&&!Array.isArray(g)?g:{value:g};m.push({type:ga(w),timestamp:ya(w),role:typeof w.role=="string"?w.role:void 0,sourceEventId:`transcript:${y}`,sourceSequence:y,data:w,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:y}})}return{events:m,nextOffset:s+d,reset:r}}var ha=[/^<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*$/],Sa=[/api[_-]?key[:\s=]+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/secret[:\s=]+[^\s]+/gi,/password[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/authorization:\s*[^\s]+/gi],wa=["decision","decided","rule","convention","architecture","pattern","fixed","resolved","implemented","created","updated","deleted","deployed","blocker","blocked","issue","bug","error","next","todo","action","requirement","must","should","important"];function va(t){let e=t.toLowerCase();return wa.some(n=>e.includes(n))}function ka(t){if(!t.trim())return!0;for(let e of ha)if(e.test(t))return!0;return va(t),!1}function ba(t){let e=t;for(let n of Sa)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function dt(t){let e=t.trim();return e?ka(e)?{content:"",filtered:!0,reason:"noise"}:{content:ba(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function Le(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=dt(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=Le(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=dt(s);return o.filtered?null:o.content}return s&&typeof s=="object"?Le(s):s}).filter(s=>s!==null):e[n]=r;return e}function tr(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&&dt(r).filtered)return!0}return!1}function ja(t){return t==="~"?pt():t.startsWith("~/")?nr(pt(),t.slice(2)):t}async function We(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let n=xa(ja(t.transcriptPath)),r=new $e({project:t.project,storage:t.storage,agent:"agy",nativeSessionId:e,metadata:{source:"antigravity-hook",transcriptPath:n,workspacePaths:t.workspacePaths??[],artifactDirectoryPath:t.artifactDirectoryPath,modelName:t.modelName}}),s=r.status(),o=s.sourceCursors["agy.transcript.offset"],i=o?Number(o):0,a=er(n,{offset:Number.isFinite(i)?i:0}),u=[];s.lastSequence===0&&u.push({type:"session_start",sourceEventId:`agy:${e}:start`,data:{workspacePaths:t.workspacePaths??[],transcriptPath:n,modelName:t.modelName},provenance:{source:"antigravity-hook",sourcePath:n}}),a.reset&&u.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${a.nextOffset}`,data:{event:"transcript_reset",transcriptPath:n},provenance:{source:"agy-transcript",sourcePath:n}});let c=a.events.filter(m=>!tr(m.data)).map(m=>({...m,data:Le(m.data)}));u.push(...c),t.phase==="stop"&&(t.error&&u.push({type:"error",sourceEventId:["agy",e,"stop-error",t.terminationReason??"",a.nextOffset].join(":"),data:{error:t.error,terminationReason:t.terminationReason,fullyIdle:t.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),t.fullyIdle&&u.push({type:"session_idle",sourceEventId:["agy",e,"idle",a.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let p=r.recordMany(u);if(r.setSourceCursor("agy.transcript.offset",a.nextOffset),t.phase&&r.setSourceCursor("agy.last.phase",t.phase),t.phase==="stop"&&c.length>0)try{let m=c.map(f=>JSON.stringify(f.data)),l=ve(m,e);r.setSourceCursor("agy.session.summary",l.summary),r.setSourceCursor("agy.session.facts_count",l.durableFacts.length),Bt()&&(Gt()||r.setSourceCursor("agy.raw_transcript.archived","local"))}catch{}let d=await r.flush();return{conversationId:e,imported:p.length,eventCount:d.eventCount,chunkCount:d.chunkCount,status:d.status,transcriptOffset:a.nextOffset,reset:a.reset}}function rr(t){return nr(pt(),".gemini","antigravity-cli","brain",t,".system_generated","logs","transcript.jsonl")}import{existsSync as qe,mkdirSync as pr,readFileSync as mr,renameSync as za,writeFileSync as qa}from"node:fs";import{dirname as Va,join as ze}from"node:path";import{existsSync as Pa,mkdirSync as Ca,readFileSync as Ma,renameSync as Ea,rmSync as Oa,writeFileSync as Ta}from"node:fs";import{dirname as Ra}from"node:path";import{homedir as Aa}from"node:os";import{join as H}from"node:path";function sr(t={}){return H(t.home??Aa(),".gemini")}function or(t={}){return H(sr(t),"config")}function De(t={}){return H(or(t),"mcp_config.json")}function Fe(t={}){return H(or(t),"hooks.json")}function Ia(t={}){return H(sr(t),"antigravity-cli")}function ir(t="toolnet-memory",e={}){return H(Ia(e),"plugins",t)}function Na(t){return`'${t.replace(/'/g,"'\\''")}'`}function ar(t={}){let e=t.hooksFile??Fe();Ca(Ra(e),{recursive:!0,mode:448});let n={};if(Pa(e)){let i;try{i=JSON.parse(Ma(e,"utf8"))}catch(a){throw new Error(`Invalid existing Agy hooks.json: ${a instanceof Error?a.message:String(a)}`)}if(typeof i!="object"||i===null||Array.isArray(i))throw new Error("Invalid existing Agy hooks.json: root must be a JSON object.");n=i}let r=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",s=`${Na(r)} session:agy-hook`;n["toolnet-memory"]={enabled:!0,PreToolUse:[{matcher:"view_file|list_dir|find_by_name|grep_search|run_command",hooks:[{type:"command",command:`${s} pre-tool`,timeout:5}]}],PreInvocation:[{type:"command",command:`${s} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${s} post`,timeout:15}],Stop:[{type:"command",command:`${s} stop`,timeout:30}]};let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{Ta(o,JSON.stringify(n,null,2)+`
99
- `,{encoding:"utf8",mode:384}),Ea(o,e)}finally{Oa(o,{force:!0})}return e}import{existsSync as _a,mkdirSync as Ka,readFileSync as $a,renameSync as La,writeFileSync as Wa}from"node:fs";import{dirname as Da}from"node:path";function ce(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Fa(t,e){Ka(Da(t),{recursive:!0,mode:448});let n=`${t}.tmp-${process.pid}-${Date.now()}`;Wa(n,`${JSON.stringify(e,null,2)}
100
- `,{encoding:"utf8",mode:384}),La(n,t)}function cr(t){if(!_a(t))return{};let e=$a(t,"utf8").trim();if(!e)return{};let n;try{n=JSON.parse(e)}catch(r){throw new Error(`Invalid existing Agy MCP config: ${r instanceof Error?r.message:String(r)}`)}if(!ce(n))throw new Error("Invalid existing Agy MCP config: root must be a JSON object.");return n}function ur(t,e){return ce(t)?t.command===e&&Array.isArray(t.args)&&t.args.length===1&&t.args[0]==="mcp":!1}function lr(t={}){let e=t.configFile??De(),n=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=t.serverName??"toolnet-memory",s=cr(e),o=s.mcpServers;if(o!==void 0&&!ce(o))throw new Error("Invalid existing Agy MCP config: mcpServers must be an object.");let i=ce(o)?{...o}:{},a=i[r];if(ur(a,n))return{installed:!0,changed:!1,configFile:e,serverName:r,command:n,args:["mcp"]};i[r]={command:n,args:["mcp"]};let u={...s,mcpServers:i};Fa(e,u);let p=cr(e).mcpServers;if(!ce(p)||!ur(p[r],n))throw new Error("Agy MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:e,serverName:r,command:n,args:["mcp"]}}var Ba=`# ToolNet Memory Continuity
101
-
102
- ToolNet Memory is the authoritative continuity layer for previous project work.
103
-
104
- ## Resume / continue behavior
105
-
106
- Whenever the user asks to continue, resume, finish, pick up, return to, or complete previous work:
107
-
108
- 1. FIRST call the ToolNet Memory MCP tool \`memory_agent_ask\`.
109
- 2. Use ToolNet's compact continuity result to determine:
110
- - current task
111
- - completed work
112
- - current or last file
113
- - TODOs
114
- - blockers
115
- - next action
116
- 3. Only AFTER continuity is known may you inspect current source or git to verify repository truth.
117
-
118
- ## Forbidden continuity recovery
119
-
120
- Do NOT reconstruct previous work by reading, listing, searching, or shelling into:
121
-
122
- - \`.toolnet/sessions/**\`
123
- - \`state.json\`
124
- - \`events.jsonl\`
125
- - raw transcripts
126
- - \`~/.gemini/antigravity-cli/brain/**\`
127
- - Antigravity \`transcript.jsonl\`
128
- - another coding agent's internal session history
129
-
130
- Do NOT run Bash/cat/tail/grep against those locations to discover previous work.
131
-
132
- Do NOT search the filesystem for the implementation or schema of \`memory_agent_ask\`.
133
- Invoke the MCP tool directly.
134
-
135
- For direct continuity facts, prefer \`mode="local"\`.
136
- Use \`mode="ai"\` only when continuity is ambiguous or requires synthesis.
137
-
138
- Current repository evidence overrides stale memory after ToolNet has restored the working context.
139
-
140
- Do not ask the user to repeat context already available through ToolNet Memory.
141
- `;function fr(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function mt(t,e){pr(Va(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;qa(n,e,{encoding:"utf8",mode:384}),za(n,t)}function dr(t,e){qe(t)&&mr(t,"utf8")===e||mt(t,e)}function gr(t){if(!qe(t))return{};let e=mr(t,"utf8").trim();if(!e)return{};let n;try{n=JSON.parse(e)}catch(r){throw new Error(`Invalid legacy Antigravity config ${t}: ${r instanceof Error?r.message:String(r)}`)}if(!fr(n))throw new Error(`Invalid legacy Antigravity config ${t}: root must be object`);return n}function Ja(t,e){if(!qe(t))return!1;let n=gr(t);if(!fr(n.mcpServers)||!Object.prototype.hasOwnProperty.call(n.mcpServers,e))return!1;let r={...n.mcpServers};return delete r[e],mt(t,`${JSON.stringify({...n,mcpServers:r},null,2)}
142
- `),!0}function Ha(t){if(!qe(t))return!1;let e=gr(t);if(!Object.prototype.hasOwnProperty.call(e,"toolnet-memory"))return!1;let n={...e};return delete n["toolnet-memory"],mt(t,`${JSON.stringify(n,null,2)}
143
- `),!0}function yr(t={}){let e=t.pluginName??"toolnet-memory",n=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=t.pluginRoot??ir(e),s=ze(r,"plugin.json"),o=ze(r,"mcp_config.json"),i=ze(r,"hooks.json"),a=ze(r,"rules","toolnet-memory-continuity.md");pr(r,{recursive:!0,mode:448}),dr(s,`${JSON.stringify({$schema:"https://antigravity.google/schemas/v1/plugin.json",name:e,description:"Persistent project continuity and memory for Antigravity coding sessions."},null,2)}
144
- `),lr({configFile:o,binary:n,serverName:"toolnet-memory"}),ar({hooksFile:i,binary:n}),dr(a,`${Ba.trim()}
145
- `);let u=t.legacyMcpFile??De(),c=t.legacyHooksFile??Fe(),p=[];return u!==o&&Ja(u,"toolnet-memory")&&p.push(u),c!==i&&Ha(c)&&p.push(c),{installed:!0,pluginRoot:r,files:[s,o,i,a],migratedLegacy:p}}import{existsSync as hr}from"node:fs";import{homedir as Ga}from"node:os";import{join as Ua,resolve as Sr}from"node:path";import{DatabaseSync as Ya}from"node:sqlite";function wr(t){if(t.startsWith("file://"))try{return decodeURIComponent(new URL(t).pathname)}catch{return t}return t}function Xa(t){if(typeof t!="string"||!t)return[];try{let e=JSON.parse(t);if(Array.isArray(e))return e.filter(n=>typeof n=="string").map(wr)}catch{}return[wr(t)]}function Qa(t,e){let n=Sr(t.rootPath);return e.some(r=>{let s=Sr(r);return s===n||s.startsWith(n+"/")||n.startsWith(s+"/")})}async function vr(t,e,n=10){console.log(`Recovering Agy sessions for project: ${t.name}`),console.log(`Limit: ${n} sessions`),console.log("");let r=process.env.AGY_SUMMARY_DB??Ua(Ga(),".gemini","antigravity-cli","conversation_summaries.db");if(!hr(r))throw new Error(`Agy summary database not found: ${r}`);let s=new Ya(r,{readOnly:!0});s.exec("PRAGMA query_only = ON");let o=s.prepare(`
66
+ `;function ft(t){return _r(t.rootPath,".toolnet","PROJECT.md")}function Lr(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Kr(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=Lr(s[2]);if(!i)continue;let c=`${o}:${i.toLowerCase()}`;n.has(c)||(n.add(c),e.push({id:v(c).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Fr(t){let e=ft(t);return dt(e)||(Tr(Nr(e),{recursive:!0}),Cr(e,$r,{encoding:"utf8",mode:384})),e}function mt(t,e=!1){let n=e?Fr(t):ft(t);if(!dt(n))return null;if(lt(n).size>pt)throw new Error(`PROJECT.md exceeds ${pt} bytes`);let s=Rr(n,"utf8");return{path:n,content:s,digest:v(s),rules:Kr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(lt(n).mtimeMs).toISOString()}}function Dr(t){return{goal:t.goal,plan:t.plan,phases:t.phases.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),tasks:t.tasks.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),decisions:t.decisions,blockers:t.blockers,warnings:t.warnings,nextActions:t.nextActions,filesTouched:t.filesTouched,tests:t.tests}}function Wr(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 ae=class{constructor(e){this.options=e}options;async capture(e,n){let r=await ot(this.options.project,this.options.storage);if(r||(r=await re(this.options.project,this.options.storage)),!Wr(r))return null;let s=mt(this.options.project,!1),o=s?s.rules.filter(m=>m.mode==="enforce").map(m=>m.text):[],i=v(JSON.stringify(Dr(r))),c=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),u=new Date().toISOString(),a={version:1,id:c,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:u,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),incompleteTasks:r.tasks.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:[...o,...r.warnings].slice(0,20),filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:i},d=`projects/${this.options.project.id}/work/handoffs/${c}.json`;await this.options.storage.exists(d)||await this.options.storage.put(d,JSON.stringify(a,null,2)+`
67
+ `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(a,null,2)+`
68
+ `,"application/json");let l=ke(this.options.project.rootPath,".toolnet","work","handoffs");return zr(l,{recursive:!0}),O(ke(l,`${c}.json`),a),O(ke(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};var ce=class{identity;wal;remote;sanitizer=new D;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=De(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new Z(this.identity),this.remote=new X(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new ee({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new se({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new ie({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new ae({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as Br,openSync as qr,closeSync as Jr,readSync as Vr,statSync as Ur}from"node:fs";function Hr(t){let e=typeof t.role=="string"?t.role:"",n=typeof t.type=="string"?t.type.toLowerCase():"";return e==="user"||n.includes("user")?"user_prompt":e==="assistant"||n.includes("assistant")||n.includes("model")?"assistant_message":n.includes("tool")||"toolCall"in t||"tool_call"in t?"tool_call":n.includes("error")?"error":"message"}function Yr(t){let e=[t.timestamp,t.createdAt,t.time,t.created_at];for(let n of e){if(typeof n=="string"){let r=new Date(n);if(!Number.isNaN(r.getTime()))return r.toISOString()}if(typeof n=="number"){let r=n;r<1e11&&(r*=1e3);let s=new Date(r);if(!Number.isNaN(s.getTime()))return s.toISOString()}}return new Date().toISOString()}function gt(t,e={offset:0}){if(!Br(t))return{events:[],nextOffset:e.offset,reset:!1};let n=Ur(t).size,r=e.offset>n,s=r?0:e.offset;if(s===n)return{events:[],nextOffset:n,reset:r};let o=n-s,i=Buffer.alloc(o),c=qr(t,"r");try{Vr(c,i,0,o,s)}finally{Jr(c)}let u=i.toString("utf8"),a=u.lastIndexOf(`
69
+ `);if(a<0)return{events:[],nextOffset:s,reset:r};let d=u.slice(0,a+1),l=Buffer.byteLength(d,"utf8"),m=[],p=0;for(let S of d.split(`
70
+ `)){if(!S)continue;let y=Buffer.byteLength(S+`
71
+ `,"utf8"),g=s+p;p+=y;let h;try{h=JSON.parse(S)}catch{m.push({type:"custom",sourceEventId:`transcript:${g}`,sourceSequence:g,data:{format:"raw-line",content:S},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:g}});continue}let b=h&&typeof h=="object"&&!Array.isArray(h)?h:{value:h};m.push({type:Hr(b),timestamp:Yr(b),role:typeof b.role=="string"?b.role:void 0,sourceEventId:`transcript:${g}`,sourceSequence:g,data:b,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:g}})}return{events:m,nextOffset:s+l,reset:r}}var Gr=[/^<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*$/],Xr=[/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],Zr=["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 Qr(t){let e=t.toLowerCase();return Zr.some(n=>e.includes(n))}function es(t){if(!t.trim())return!0;for(let e of Gr)if(e.test(t))return!0;return Qr(t),!1}function ts(t){let e=t;for(let n of Xr)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function we(t){let e=t.trim();return e?es(e)?{content:"",filtered:!0,reason:"noise"}:{content:ts(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function ue(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=we(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=ue(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=we(s);return o.filtered?null:o.content}return s&&typeof s=="object"?ue(s):s}).filter(s=>s!==null):e[n]=r;return e}function yt(t){let e=typeof t.type=="string"?t.type.toLowerCase():"";if(e.includes("system")||e.includes("ephemeral")||e==="tool_call"&&!t.result)return!0;if(t.data&&typeof t.data=="object"){let n=t.data,r=typeof n.content=="string"?n.content:"";if(r&&we(r).filtered)return!0}return!1}function ns(t){return t?Math.ceil(t.length/3.5):0}function ht(t,e){if(!t)return"";if(ns(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
72
+ `),c=Math.max(o,i);return c>r*.7?s.slice(0,c+1):s}function R(){let t=q(),e=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||e==="archive"||e==="full",r=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",s=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),o=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),c=n,u=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:c,archiveRemote:u}}function St(t){return(t||R()).rawTranscript}function vt(t){return(t||R()).durableMemoryMaxItemsPerSession}function bt(t){return(t||R()).sessionSummaryMaxTokens}function kt(t){return(t||R()).archiveRemote}function rs(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 ss(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 os(t,e){let n=[],r=new Set;for(let i of t){let c=i.split(`
73
+ `).filter(u=>u.trim());for(let u of c){let a=u.trim();if(a.length<15)continue;let d=a.toLowerCase().replace(/\s+/g," ");if(r.has(d))continue;r.add(d);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(a)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(a)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(a)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(a)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(a)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(a)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(a)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(a)&&(l="file");let m=ss(a,l);if(m<.3)continue;let p=rs(a);n.push({category:l,text:p,importance:m,sourceSessionId:e})}}let s=R(),o=vt(s);return n.sort((i,c)=>c.importance-i.importance).slice(0,o)}function is(t){let e=R(),n=bt(e),o=t.join(`
74
+
75
+ `).split(`
76
+ `).filter(i=>{let c=i.trim();return c.length>20&&!c.startsWith("npm")&&!c.startsWith("\u2713")&&!c.startsWith("Error:")}).slice(0,20).join(`
77
+ `);return ht(o,n)}function wt(t,e){let r=(Array.isArray(t)?t:t.split(`
78
+
79
+ `).filter(p=>p.trim())).map(p=>typeof p=="string"?p:JSON.stringify(p)).filter(p=>p.trim()),s=os(r,e),o=s.filter(p=>p.category==="decision").map(p=>p.text),i=s.filter(p=>p.category==="rule").map(p=>p.text),c=s.filter(p=>p.category==="file").map(p=>p.text),u=s.filter(p=>p.category==="fix").map(p=>p.text),a=s.filter(p=>p.category==="blocker").map(p=>p.text),d=s.filter(p=>p.category==="next_action").map(p=>p.text),l=s.filter(p=>p.category==="deploy").map(p=>p.text);return{summary:is(r),decisions:o,projectRules:i,filesChanged:c,bugsFixed:u,commands:l,blockers:a,nextActions:d,durableFacts:s}}function cs(t){return t==="~"?xe():t.startsWith("~/")?xt(xe(),t.slice(2)):t}async function le(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let n=as(cs(t.transcriptPath)),r=new ce({project:t.project,storage:t.storage,agent:"agy",nativeSessionId:e,metadata:{source:"antigravity-hook",transcriptPath:n,workspacePaths:t.workspacePaths??[],artifactDirectoryPath:t.artifactDirectoryPath,modelName:t.modelName}}),s=r.status(),o=s.sourceCursors["agy.transcript.offset"],i=o?Number(o):0,c=gt(n,{offset:Number.isFinite(i)?i:0}),u=[];s.lastSequence===0&&u.push({type:"session_start",sourceEventId:`agy:${e}:start`,data:{workspacePaths:t.workspacePaths??[],transcriptPath:n,modelName:t.modelName},provenance:{source:"antigravity-hook",sourcePath:n}}),c.reset&&u.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${c.nextOffset}`,data:{event:"transcript_reset",transcriptPath:n},provenance:{source:"agy-transcript",sourcePath:n}});let a=c.events.filter(m=>!yt(m.data)).map(m=>({...m,data:ue(m.data)}));u.push(...a),t.phase==="stop"&&(t.error&&u.push({type:"error",sourceEventId:["agy",e,"stop-error",t.terminationReason??"",c.nextOffset].join(":"),data:{error:t.error,terminationReason:t.terminationReason,fullyIdle:t.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),t.fullyIdle&&u.push({type:"session_idle",sourceEventId:["agy",e,"idle",c.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let d=r.recordMany(u);if(r.setSourceCursor("agy.transcript.offset",c.nextOffset),t.phase&&r.setSourceCursor("agy.last.phase",t.phase),t.phase==="stop"&&a.length>0)try{let m=a.map(S=>JSON.stringify(S.data)),p=wt(m,e);r.setSourceCursor("agy.session.summary",p.summary),r.setSourceCursor("agy.session.facts_count",p.durableFacts.length),St()&&(kt()||r.setSourceCursor("agy.raw_transcript.archived","local"))}catch{}let l=await r.flush();return{conversationId:e,imported:d.length,eventCount:l.eventCount,chunkCount:l.chunkCount,status:l.status,transcriptOffset:c.nextOffset,reset:c.reset}}function jt(t){return xt(xe(),".gemini","antigravity-cli","brain",t,".system_generated","logs","transcript.jsonl")}import{existsSync as us,mkdirSync as ls,readFileSync as ps,writeFileSync as ds}from"node:fs";import{homedir as fs}from"node:os";import{dirname as ms,join as gs}from"node:path";function ys(t){return`'${t.replace(/'/g,"'\\''")}'`}function It(t={}){let e=t.hooksFile??gs(fs(),".gemini","config","hooks.json");ls(ms(e),{recursive:!0});let n={};if(us(e))try{n=JSON.parse(ps(e,"utf8"))}catch(o){throw new Error(`Invalid existing Agy hooks.json: ${o instanceof Error?o.message:String(o)}`)}let r=t.binary??"toolnet-memory",s=`${ys(r)} session:agy-hook`;return n["toolnet-memory"]={enabled:!0,PreInvocation:[{type:"command",command:`${s} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${s} post`,timeout:15}],Stop:[{type:"command",command:`${s} stop`,timeout:30}]},ds(e,JSON.stringify(n,null,2)+`
80
+ `,{encoding:"utf8",mode:384}),e}import{existsSync as Pt}from"node:fs";import{homedir as hs}from"node:os";import{join as Ss,resolve as Ot}from"node:path";import{DatabaseSync as vs}from"node:sqlite";function Et(t){if(t.startsWith("file://"))try{return decodeURIComponent(new URL(t).pathname)}catch{return t}return t}function bs(t){if(typeof t!="string"||!t)return[];try{let e=JSON.parse(t);if(Array.isArray(e))return e.filter(n=>typeof n=="string").map(Et)}catch{}return[Et(t)]}function ks(t,e){let n=Ot(t.rootPath);return e.some(r=>{let s=Ot(r);return s===n||s.startsWith(n+"/")||n.startsWith(s+"/")})}async function At(t,e,n=10){console.log(`Recovering Agy sessions for project: ${t.name}`),console.log(`Limit: ${n} sessions`),console.log("");let r=process.env.AGY_SUMMARY_DB??Ss(hs(),".gemini","antigravity-cli","conversation_summaries.db");if(!Pt(r))throw new Error(`Agy summary database not found: ${r}`);let s=new vs(r,{readOnly:!0});s.exec("PRAGMA query_only = ON");let o=s.prepare(`
146
81
  SELECT
147
82
  conversation_id,
148
83
  title,
@@ -152,11 +87,10 @@ Do not ask the user to repeat context already available through ToolNet Memory.
152
87
  FROM conversation_summaries
153
88
  ORDER BY
154
89
  last_user_input_time DESC
155
- `).all();s.close();let i=[],a=0,u=Math.min(o.length,n);for(let c of o){let p=typeof c.conversation_id=="string"?c.conversation_id:"";if(!p)continue;let d=Xa(c.workspace_uris);if(!Qa(t,d))continue;let m=rr(p);if(!hr(m))continue;a++,console.log(`[${a}/${u}] Processing conversation: ${p.slice(0,8)}...`);let l=await We({project:t,storage:e,conversationId:p,transcriptPath:m,workspacePaths:d,modelName:typeof c.agent_name=="string"?c.agent_name:void 0,phase:"recover"});if(console.log(` \u2713 Imported ${l.imported} events (${l.eventCount} total, ${l.chunkCount} chunks)`),i.push(l),i.length>=n)break}return console.log(""),console.log(`\u2713 Recovery complete: ${i.length} sessions processed`),console.log(`Total events: ${i.reduce((c,p)=>c+p.eventCount,0)}`),console.log(`Total chunks: ${i.reduce((c,p)=>c+p.chunkCount,0)}`),i}function Ve(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function Za(t){let e=le(),n=jt(bt({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new ye(n,t.id,t.name,t.remote??t.name)}async function ec(){let[t="help",...e]=process.argv.slice(2);if(t==="install-hooks"||t==="install-plugin"){let o=yr({binary:Ve(e,"--bin")});console.log(`\u2705 ToolNet Antigravity plugin installed: ${o.pluginRoot}`);for(let i of o.files)console.log(` \u2713 ${i}`);o.migratedLegacy.length&&console.log(" \u2713 Legacy ToolNet Agy config migrated"),console.log(""),console.log("Restart Antigravity CLI before testing.");return}let n=Ve(e,"--project")??process.cwd(),r=new pe().detect(n),s=Za(r);if(t==="sync"){let o=e[0],i=Ve(e,"--transcript");if(!o||!i)throw new Error("Usage: sync <conversation-id> --transcript <path>");let a=await We({project:r,storage:s,conversationId:o,transcriptPath:i,phase:"recover"});console.log(JSON.stringify(a,null,2));return}if(t==="recover"){let o=Number(Ve(e,"--limit")??100),i=await vr(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((a,u)=>a+u.imported,0)},null,2));return}console.log(`Agy Session Adapter
90
+ `).all();s.close();let i=[],c=0,u=Math.min(o.length,n);for(let a of o){let d=typeof a.conversation_id=="string"?a.conversation_id:"";if(!d)continue;let l=bs(a.workspace_uris);if(!ks(t,l))continue;let m=jt(d);if(!Pt(m))continue;c++,console.log(`[${c}/${u}] Processing conversation: ${d.slice(0,8)}...`);let p=await le({project:t,storage:e,conversationId:d,transcriptPath:m,workspacePaths:l,modelName:typeof a.agent_name=="string"?a.agent_name:void 0,phase:"recover"});if(console.log(` \u2713 Imported ${p.imported} events (${p.eventCount} total, ${p.chunkCount} chunks)`),i.push(p),i.length>=n)break}return console.log(""),console.log(`\u2713 Recovery complete: ${i.length} sessions processed`),console.log(`Total events: ${i.reduce((a,d)=>a+d.eventCount,0)}`),console.log(`Total chunks: ${i.reduce((a,d)=>a+d.chunkCount,0)}`),i}function pe(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function ws(t){let e=q(),n=_e(Ce({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new G(n,t.id,t.name,t.remote??t.name)}async function xs(){let[t="help",...e]=process.argv.slice(2);if(t==="install-hooks"){let o=It({binary:pe(e,"--bin")});console.log(`\u2705 Agy hooks installed: ${o}`);return}let n=pe(e,"--project")??process.cwd(),r=new V().detect(n),s=ws(r);if(t==="sync"){let o=e[0],i=pe(e,"--transcript");if(!o||!i)throw new Error("Usage: sync <conversation-id> --transcript <path>");let c=await le({project:r,storage:s,conversationId:o,transcriptPath:i,phase:"recover"});console.log(JSON.stringify(c,null,2));return}if(t==="recover"){let o=Number(pe(e,"--limit")??100),i=await At(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((c,u)=>c+u.imported,0)},null,2));return}console.log(`Agy Session Adapter
156
91
 
157
92
  Commands:
158
93
  install-hooks
159
- install-plugin
160
94
  sync <conversation-id> --transcript <path>
161
95
  recover [--project PATH] [--limit N]
162
- `)}ec().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});
96
+ `)}xs().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});