toolnet-memory 0.2.20 → 0.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle/agy.js CHANGED
@@ -1,26 +1,34 @@
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 _t(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 Nt(){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]=_t(r.slice(s+1)))}}Nt();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 _e(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 Ne(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)=>_e(()=>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)+`
1
+ import{existsSync as en,readFileSync as tn}from"node:fs";import{homedir as nn}from"node:os";import{join as rn}from"node:path";function sn(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 on(){let t=process.env.TOOLNET_GLOBAL_ENV??rn(nn(),".config","toolnet-memory",".env");if(!en(t))return;let e=tn(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]=sn(r.slice(s+1)))}}on();function z(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function W(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function H(){return{memory:{autoCapture:z(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:z(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:z(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:z(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:W(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:W(process.env.MEMORY_RERANK_TOP,10),finalContext:W(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:W(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:z(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:W(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as an}from"node:crypto";import{existsSync as ke,mkdirSync as cn,readFileSync as un,renameSync as ln,writeFileSync as pn}from"node:fs";import{basename as dn,dirname as Y,join as Q,parse as Fe,resolve as B}from"node:path";var De=".toolnet",mn="project.json";function fn(t){return an("sha256").update(t).digest("hex").slice(0,16)}function we(t){return Q(t,De,mn)}function gn(t){return ke(we(t))}function yn(t,e){let n=B(t),r=Fe(n).root;for(;;){if(gn(n))return n;if(n===r||e&&n===B(e))break;let s=Y(n);if(s===n)break;n=s}return null}function hn(t){let e=B(t),n=Fe(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>ke(Q(e,o))))return e;if(e===n)break;let s=Y(e);if(s===e)break;e=s}return B(t)}function Sn(t){let e;try{e=JSON.parse(un(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:Y(Y(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 $e(t,e){let n=Q(t,De);cn(n,{recursive:!0});let r=we(t),s=`${r}.tmp-${process.pid}`;pn(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ln(s,r)}function Le(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 G=class{detect(e=process.cwd()){let n=B(e),r=hn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>ke(Q(r,d))),i=yn(n,o?r:void 0);if(i){let d=we(i),l=Sn(d);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),$e(i,l)),Le(l,i)}let c=new Date().toISOString(),u=dn(r),a={version:1,id:fn(r),name:u,remote:u,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return $e(r,a),Le(a,r)}};var vn=[{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}],X=class{scan(e){let n=[];for(let r of vn){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var q=class{scanner=new X;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 Wn}from"node:os";import{join as Bn}from"node:path";import{DeleteObjectCommand as bn,GetObjectCommand as kn,HeadObjectCommand as wn,ListObjectsV2Command as xn,PutObjectCommand as jn,S3Client as In}from"@aws-sdk/client-s3";import{getSignedUrl as Pn}from"@aws-sdk/s3-request-presigner";var Z=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new In({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 jn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Pn(this.client,new kn({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 wn({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 bn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new xn({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 Ke,mkdir as Mn,readFile as An,readdir as On,rm as En,stat as ze,writeFile as Cn}from"node:fs/promises";import{dirname as Tn,join as Rn,relative as We,resolve as Nn}from"node:path";var J=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Nn(this.root,n)}async put(e,n){let r=this.path(e);await Mn(Tn(r),{recursive:!0}),await Cn(r,n)}async get(e){try{return await An(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 Ke(this.path(e)),!0}catch{return!1}}async delete(e){await En(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ke(n)}catch{return r}let s=async i=>{let c=await On(i,{withFileTypes:!0});for(let u of c){let a=Rn(i,u.name);if(u.isDirectory()){await s(a);continue}let d=await ze(a);r.push({key:We(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await ze(n);return o.isDirectory()?await s(n):r.push({key:We(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as _n,GetObjectCommand as $n,HeadObjectCommand as Ln,ListObjectsV2Command as Fn,PutObjectCommand as Dn,S3Client as Kn}from"@aws-sdk/client-s3";import{getSignedUrl as zn}from"@aws-sdk/s3-request-presigner";var V=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Kn({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 Dn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await zn(this.client,new $n({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 Ln({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 _n({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Fn({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 xe(t,e){return console.warn(e),new J(t)}function Be(t){let e=t.localRoot??Bn(Wn(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new V({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new V({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(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 Z({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new J(e)}function qn(t){return new Promise(e=>setTimeout(e,t))}async function qe(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 qn(u+a)}throw o}var Jn=new Set(["put","get","getText","delete","list"]);function Je(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:Jn.has(r)?(...o)=>qe(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Ve(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Ue(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 ee=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Ve(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=Ue(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 Te}from"node:os";import{join as _t,resolve as Ks}from"node:path";import{join as Xn}from"node:path";import{createHash as Vn}from"node:crypto";import{dirname as Un}from"node:path";import{mkdirSync as Hn,readFileSync as Yn,renameSync as Gn,writeFileSync as Qn}from"node:fs";function v(t){return Vn("sha256").update(t).digest("hex")}function je(t){if(Array.isArray(t))return t.map(je);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=je(e[r]);return n}return t}function He(t){return JSON.stringify(je(t))}function Ye(t){try{return JSON.parse(Yn(t,"utf8"))}catch{return null}}function A(t,e){Hn(Un(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;Qn(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Gn(n,t)}function Ge(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 Qe(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=Ge(r.toLowerCase(),"agent"),i=Ge(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:Xn(t.rootPath,".toolnet","sessions",o,i)}}function Xe(t){return String(t).padStart(12,"0")}var te=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
6
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(`
7
+ `,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),c=n.filter(g=>g.sequence>i.maxSequence),u=0;for(let g of this.split(c)){let y=g[0],b=g[g.length-1],T=g.map(R=>JSON.stringify(R)).join(`
8
8
  `)+`
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 _n=12e4,Nn=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<Nn;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>_n){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(`
9
+ `,_=v(T).slice(0,16),M=[e.remotePrefix,"events",`${Xe(y.sequence)}-${Xe(b.sequence)}-${_}.jsonl`].join("/");await this.storage.exists(M)||await this.storage.put(M,T,"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 f=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??f,updatedAt:d?.timestamp??f,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 h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:f};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:u,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:l}}};import{closeSync as Ie,existsSync as Zn,fsyncSync as er,mkdirSync as tr,openSync as Pe,readSync as nr,rmSync as Ze,statSync as et,writeSync as rr}from"node:fs";import{join as Me}from"node:path";var sr=12e4,or=80,ir=2e3;function ar(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ne=class{constructor(e){this.identity=e;tr(e.localDirectory,{recursive:!0}),this.eventsFile=Me(e.localDirectory,"events.jsonl"),this.stateFile=Me(e.localDirectory,"state.json"),this.lockFile=Me(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return Ye(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){A(this.stateFile,e)}acquireLock(){for(let e=0;e<or;e+=1)try{return Pe(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-et(this.lockFile).mtimeMs>sr){Ze(this.lockFile,{force:!0});continue}}catch{}ar(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{Ie(n),Ze(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let l of e){let f=l.timestamp??new Date().toISOString(),p=l.data??{},S=l.provenance?.rawDigest??v(He(p)),h=l.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,l.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,l.type,f,S].join("|"),g=v(h).slice(0,32);if(r.has(g))continue;s+=1;let y={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:f,data:p,provenance:{...l.provenance,rawDigest:S}};l.role!==void 0&&(y.role=l.role),l.sourceEventId!==void 0&&(y.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(y.sourceSequence=l.sourceSequence),o.push(y),r.add(g)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
10
10
  `)+`
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(`
11
+ `,c=Pe(this.eventsFile,"a",384);try{rr(c,i,null,"utf8"),er(c)}finally{Ie(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(-ir);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:d}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Zn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=et(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=Pe(this.eventsFile,"r");try{nr(i,o,0,s,r)}finally{Ie(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 $r,existsSync as Lr,openSync as Fr,readSync as Dr,statSync as Kr}from"node:fs";function tt(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 ot=[/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],cr=[/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],ur=[/\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],lr=[/\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],pr=[/đã 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],nt=[/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],dr=[/\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],mr=[/đườ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],fr=[/\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],rt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),gr=new Set(["payload","data","content","message","messages","parts","summary"]);function x(t,e){return e.some(n=>n.test(t))}function it(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function yr(t){return it(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function hr(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function Ae(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||rt.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Ae(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(rt.has(s)||gr.has(s))&&Ae(o,s,n,r+1)}}function Sr(t){let e=[];Ae(t.data,void 0,e);let n=[],r=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=it(o);if(hr(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function st(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function vr(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,ot)?{kind:"rule",confidence:.98}:r&&x(t,cr)?{kind:"rule",confidence:.92}:x(t,ur)?{kind:x(t,nt)?"architecture":"decision",confidence:r?.93:.86}:r&&x(t,lr)?{kind:"todo",confidence:.87}:x(t,nt)&&x(t,dr)?{kind:"architecture",confidence:r?.88:.82}:s&&x(t,pr)?{kind:"fix",confidence:.8}:r&&x(t,mr)&&x(t,fr)?{kind:"context",confidence:.79}:null}function br(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function kr(t,e,n){return t==="rule"&&x(n,ot)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":tt(e,n)}function at(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=st(o);i&&c&&s.set(i,c)}for(let o of e){let i=st(o),c=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&c&&(i=s.get(c)??"");for(let u of Sr(o)){let a=vr(u,i,o);if(!a||a.confidence<.75)continue;let d=br(a.kind),l=yr(u),f=v([t.projectId,a.kind,l].join("|"));if(r.has(f))continue;r.add(f);let p=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:f,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:d,content:u,confidence:a.confidence,importance:kr(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 wr(t){return t?Math.ceil(t.length/3.5):0}function ct(t,e){if(!t)return"";if(wr(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
13
+ `),c=Math.max(o,i);return c>r*.7?s.slice(0,c+1):s}function N(){let t=H(),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 ut(t){return(t||N()).rawTranscript}function lt(t){return(t||N()).durableMemoryMaxItemsPerSession}function pt(t){return(t||N()).sessionSummaryMaxTokens}function dt(t){return(t||N()).archiveRemote}function xr(t){return t.replace(/\b[A-Za-z0-9_-]{20,}\b/g,"[REDACTED]").replace(/api[_-]?key[:\s=]+[^\s]+/gi,"api_key=[REDACTED]").replace(/token[:\s=]+[^\s]+/gi,"token=[REDACTED]").replace(/secret[:\s=]+[^\s]+/gi,"secret=[REDACTED]").replace(/password[:\s=]+[^\s]+/gi,"password=[REDACTED]")}function jr(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 Ir(t,e){let n=[],r=new Set;for(let i of t){let c=i.split(`
14
+ `).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 f=jr(a,l);if(f<.3)continue;let p=xr(a);n.push({category:l,text:p,importance:f,sourceSessionId:e})}}let s=N(),o=lt(s);return n.sort((i,c)=>c.importance-i.importance).slice(0,o)}function Pr(t){let e=N(),n=pt(e),o=t.join(`
15
+
16
+ `).split(`
17
+ `).filter(i=>{let c=i.trim();return c.length>20&&!c.startsWith("npm")&&!c.startsWith("\u2713")&&!c.startsWith("Error:")}).slice(0,20).join(`
18
+ `);return ct(o,n)}function re(t,e){let r=(Array.isArray(t)?t:t.split(`
19
+
20
+ `).filter(p=>p.trim())).map(p=>typeof p=="string"?p:JSON.stringify(p)).filter(p=>p.trim()),s=Ir(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:Pr(r),decisions:o,projectRules:i,filesChanged:c,bugsFixed:u,commands:l,blockers:a,nextActions:d,durableFacts:s}}function O(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 Mr(t){let e=new Map;for(let n of t){if(!n||!n.id||!Number.isFinite(n.sequence))continue;let r=n.sourceEventId?`${n.agent}:${n.sourceEventId}`:n.id,s=e.get(r);(!s||n.sequence>s.sequence)&&e.set(r,n)}return[...e.values()].sort((n,r)=>n.sequence-r.sequence||n.timestamp.localeCompare(r.timestamp))}function Ar(t){switch(t){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function Or(t){let e=Ar(t.importance);return Math.max(0,Math.min(1,e*.75+t.confidence*.25))}function Er(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 Cr(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 Tr(t){let e=Er(t),n=Or(t),r=Cr(t.content);return{...t,knowledgeClass:e,importanceScore:n,retrievalTerms:r,tags:O([...t.tags,`class:${e}`,`kind:${t.kind}`])}}function Rr(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 Nr(t,e,n){let r=re(Rr(e),t.nativeSessionId),s=n.filter(a=>a.kind==="todo").map(a=>a.content),o=n.flatMap(a=>a.provenance.sourcePaths),i=n.filter(a=>a.kind==="architecture").map(a=>a.content),c=O([...s,...r.nextActions]),u=O([...r.nextActions,...s]);return{summary:r.summary,state:{task:u[0]??c[0],decisions:O(r.decisions),files:O([...r.filesChanged,...o]),todos:c,completed:O(r.bugsFixed),blockers:O(r.blockers),nextActions:u,architecture:O(i)}}}function mt(t,e){let n=Mr(e),r=at(t,n).map(Tr),s=r.filter(a=>a.knowledgeClass!=="transient").sort((a,d)=>d.importanceScore-a.importanceScore),{summary:o,state:i}=Nr(t,n,s),c=s.map(a=>({fingerprint:a.fingerprint,kind:a.kind,knowledgeClass:a.knowledgeClass,importanceScore:a.importanceScore,content:a.content,terms:a.retrievalTerms})),u=a=>r.filter(d=>d.knowledgeClass===a).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:c,stats:{inputEvents:e.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:s.length,permanent:u("permanent"),task:u("task"),session:u("session"),transient:u("transient")}}}function ft(t){return String(t).padStart(12,"0")}function _r(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var se=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(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)+`
21
+ `,u=v(r.map(d=>d.fingerprint).sort().join("|")).slice(0,16),a=[_r(e),"batches",`${ft(s)}-${ft(o)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,c,"application/json"),a}};function zr(t,e){if(!Lr(t))return{events:[],nextOffset:e};let n=Kr(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{Dr(i,o,0,s,r)}finally{$r(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
14
22
  `);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 N(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function et(t){return N(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function _(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))_(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(or.has(r)||["data","payload","parts","messages"].includes(r))&&_(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=N(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=N(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(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=N(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=N(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=[];_(i.data,u);for(let a of u)s(k(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];_(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=[];_(i.data,u);for(let a of u)s(k(t,i,"test",a,{confidence:1}))}let c=[];_(i.data,c);for(let u of c)for(let a of u.split(/\n+/u))for(let 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(`
23
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var oe=class{constructor(e){this.options=e;this.journal=new se(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=zr(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=mt(this.options.identity,s.events),i=o.candidates,c=!1;return i.length>0&&(c=!!await this.journal.write(this.options.identity,s.events,i)),this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:i.length,journalWritten:c,nextOffset:s.nextOffset}}};import{closeSync as Hr,existsSync as Yr,openSync as Gr,readSync as Qr,statSync as Xr}from"node:fs";var Wr=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 yt(t){return L(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))$(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Wr.has(r)||["data","payload","parts","messages"].includes(r))&&$(s,e,n+1)}}function ie(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function gt(t){let e=L(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=L(r),i=s.key??yt(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 Br(t,e,n){let r=L(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 f=Number(a[1]),p=L(a[2]??""),S=p&&!gt(p)?`Phase ${f} - ${p}`:`Phase ${f}`;s.push(k(t,e,"phase",S,{key:`phase:${f}`,order:f,status:ie(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":ie(d[2]),confidence:.96}));let l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let f=l[1]?Number(l[1]):void 0,p=L(l[2]),S=gt(p);s.push(k(t,e,"task",S&&f!==void 0?`TODO ${f}`:p,{key:f!==void 0?`task:${f}`:yt(p),order:f,status:ie(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let f=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");f&&s.push(k(t,e,"next_action",f,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(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 ht(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let u=[];$(i.data,u);for(let a of u)s(k(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];$(i.data,u);for(let a of u)s(k(t,i,"task",a,{status:ie(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let a=i.data[u];typeof a=="string"&&a&&s(k(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let u=[];$(i.data,u);for(let a of u)s(k(t,i,"test",a,{confidence:1}))}let c=[];$(i.data,c);for(let u of c)for(let a of u.split(/\n+/u))for(let d of Br(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 St(t){return String(t).padStart(12,"0")}var ae=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
24
+ `,c=v(n.map(a=>a.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${St(r)}-${St(s)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as vt}from"node:path";import{mkdirSync as qr}from"node:fs";function Jr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Jr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Vr(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 bt(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&&Vr(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 Ur(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 ce(t,e){let r=(await Ur(t,e)).flatMap(m=>m.observations).sort((m,w)=>{let Ne=m.occurredAt.localeCompare(w.occurredAt);if(Ne!==0)return Ne;let _e=m.sequence-w.sequence;return _e!==0?_e:m.id.localeCompare(w.id)}),s=new Map,o=new Map,i,c,u,a=[],d=[],l=[],f=[],p=[],S=[];for(let m of r)switch(m.kind){case"goal":i=m.text;break;case"plan":c=m.text;break;case"phase":s.set(m.key,bt(s.get(m.key),m));break;case"task":o.set(m.key,bt(o.get(m.key),m));break;case"decision":a.push(m.text);break;case"blocker":d.push(m.text);break;case"warning":l.push(m.text);break;case"next_action":f.push(m.text);break;case"file":p.push(m.text);break;case"test":S.push(m.text);break;case"session":u={agent:m.agent,nativeSessionId:m.nativeSessionId,sessionKey:m.sessionKey,updatedAt:m.occurredAt};break}let h=Array.from(s.values()).sort((m,w)=>(m.order??Number.MAX_SAFE_INTEGER)-(w.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((m,w)=>(m.order??Number.MAX_SAFE_INTEGER)-(w.order??Number.MAX_SAFE_INTEGER)),y=h.find(m=>m.status==="in_progress")??h.find(m=>m.status==="blocked")??h.find(m=>m.status==="pending"),b=g.find(m=>m.status==="in_progress")??g.find(m=>m.status==="blocked")??g.find(m=>m.status==="pending"),T=F([...f,...b?[b.title]:[],...!b&&y?[y.title]:[],...g.filter(m=>m.status==="pending").slice(0,5).map(m=>m.title)],8),_=F([...d,...h.filter(m=>m.status==="blocked").map(m=>m.title),...g.filter(m=>m.status==="blocked").map(m=>m.title)],20),M={version:1,projectId:t.id,projectName:t.name,goal:i,plan:c,phases:h,tasks:g,decisions:F(a,20),blockers:_,warnings:F(l,20),nextActions:T,filesTouched:F(p,30),tests:F(S,20),currentPhase:y,currentTask:b,progress:{phasesTotal:h.length,phasesCompleted:h.filter(m=>m.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(m=>m.status==="completed").length,blocked:h.filter(m=>m.status==="blocked").length+g.filter(m=>m.status==="blocked").length},lastSession:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},R=vt(t.rootPath,".toolnet","work");return qr(R,{recursive:!0}),A(vt(R,"current.json"),M),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(M,null,2)+`
25
+ `,"application/json"),M}async function kt(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 Zr(t,e){if(!Yr(t))return{events:[],nextOffset:e};let n=Xr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=Gr(t,"r");try{Qr(i,o,0,s,r)}finally{Hr(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
18
26
  `);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(`
27
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var ue=class{constructor(e){this.options=e;this.journal=new ae(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Zr(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=ht(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ce(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 cs,existsSync as us,openSync as ls,readSync as ps,statSync as ds}from"node:fs";var es=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function D(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Oe(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))Oe(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(es.has(r)||["data","payload","parts","messages"].includes(r))&&Oe(s,e,n+1)}}function j(t,e,n,r,s,o=.95){let i=D(r);return{version:1,id:v([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function P(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return D(t.slice(r.length+1))}return null}function ts(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function ns(t){return D(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function wt(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=[];Oe(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=D(d);if(!l){a=null;continue}let f=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let w=Number(f[1]);u={type:"phase",key:`phase:${w}`,order:w,title:D(f[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:D(p[2]??"")},a=null;continue}let S=P(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(j(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let h=P(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(j(t,o,u.type==="phase"?"phase_objective":"objective",h,u,.98)),a=null;continue}let g=P(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(j(t,o,u.type==="phase"?"phase_why":"why",g,u,.98)),a=null;continue}let y=P(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(y){s(j(t,o,"desired_outcome",y,{type:"project"},.98)),a=null;continue}let b=P(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(b){s(j(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let T=P(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(T){s(j(t,o,"phase_deliverable",T,u,.97)),a=null;continue}let _=P(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(_){s(j(t,o,"acceptance_criterion",_,u,.98)),a="acceptance_criterion";continue}let M=P(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(M){s(j(t,o,"dependency",M,u,.97)),a="dependency";continue}let R=P(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(R){s(j(t,o,"open_question",R,u,.95)),a="open_question";continue}let m=P(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(m){s(j(t,o,"constraint",m,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&&ts(d)){s(j(t,o,a,ns(d),u,.96));continue}a=null}}}return n}function xt(t){return String(t).padStart(12,"0")}var le=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,`${xt(r)}-${xt(s)}-${i}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,JSON.stringify(o,null,2)+`
28
+ `,"application/json"),c}};import{mkdirSync as rs}from"node:fs";import{join as jt}from"node:path";function ss(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function os(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 os(e,t)?e:t}function C(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 is(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 as(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function It(t,e){let r=(await is(t,e)).flatMap(h=>h.observations).sort((h,g)=>{let y=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return y!==0?y:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),s,o,i,c,u,a=new Map,d=[],l=[],f=[];for(let h of r){let g=ss(h);if(h.scope==="phase"&&h.scopeKey){let y=a.get(h.scopeKey)??as(h);switch(h.kind){case"phase_objective":y.objective=E(y.objective,g);break;case"phase_why":y.why=E(y.why,g);break;case"phase_deliverable":y.deliverable=E(y.deliverable,g);break;case"acceptance_criterion":y.acceptanceCriteria.push(g);break;case"dependency":y.dependencies.push(g);break;case"open_question":y.openQuestions.push(g);break;case"constraint":y.constraints.push(g);break;case"note":y.notes.push(g);break}a.set(y.key,y);continue}switch(h.kind){case"mission":s=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":f.push(g);break}}for(let h of a.values())h.acceptanceCriteria=C(h.acceptanceCriteria,20),h.dependencies=C(h.dependencies,15),h.openQuestions=C(h.openQuestions,15),h.constraints=C(h.constraints,15),h.notes=C(h.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((h,g)=>h.order-g.order),openQuestions:C(d,20),constraints:C(l,20),notes:C(f,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=jt(t.rootPath,".toolnet","work");return rs(S,{recursive:!0}),A(jt(S,"semantic-current.json"),p),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(p,null,2)+`
29
+ `,"application/json"),p}function ms(t,e){if(!us(t))return{events:[],nextOffset:e};let n=ds(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=ls(t,"r");try{ps(o,s,0,s.length,r)}finally{cs(o)}let i=s.toString("utf8"),c=i.lastIndexOf(`
22
30
  `);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 _r,join as Nr}from"node:path";var pt=64*1024,$r=`# ToolNet Project Operating Manual
31
+ `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var pe=class{constructor(e){this.options=e;this.journal=new le(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=ms(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=wt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await It(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 Is}from"node:fs";import{join as Ee}from"node:path";import{existsSync as At,mkdirSync as fs,readFileSync as gs,statSync as Pt,writeFileSync as ys}from"node:fs";import{dirname as hs,join as Ss}from"node:path";var Mt=64*1024,vs=`# ToolNet Project Operating Manual
24
32
 
25
33
  This file contains persistent instructions for AI agents working on this project.
26
34
 
@@ -63,21 +71,60 @@ Things an AI agent should always remember.
63
71
  <!--
64
72
  - [advisory] Prefer small focused files.
65
73
  -->
66
- `;function ft(t){return Nr(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(_r(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,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}]},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(`
74
+ `;function Ot(t){return Ss(t.rootPath,".toolnet","PROJECT.md")}function bs(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function ks(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=bs(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 ws(t){let e=Ot(t);return At(e)||(fs(hs(e),{recursive:!0}),ys(e,vs,{encoding:"utf8",mode:384})),e}function Et(t,e=!1){let n=e?ws(t):Ot(t);if(!At(n))return null;if(Pt(n).size>Mt)throw new Error(`PROJECT.md exceeds ${Mt} bytes`);let s=gs(n,"utf8");return{path:n,content:s,digest:v(s),rules:ks(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Pt(n).mtimeMs).toISOString()}}function I(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 Ct(t){if(t)return{id:t.id,title:t.title,status:t.status}}function xs(t){let e=t.slice(-10).join(`
75
+ `).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(e)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(e)?"passing":"unknown"}function js(t){return v(JSON.stringify(t))}function Tt(t){let{project:e,identity:n,state:r}=t,s=r.filesTouched.at(-1),o=r.phases.filter(y=>y.status==="completed").map(y=>y.title),i=r.tasks.filter(y=>y.status==="completed").map(y=>y.title),c=r.phases.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),u=r.tasks.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),a=I(r.nextActions,10),d=I([...u,...a],15),l=I(r.tests.slice().reverse(),10),f=I(r.filesTouched.slice().reverse(),20),p={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:Ct(r.currentPhase),task:Ct(r.currentTask),file:s},completed:{phases:I(o,20),tasks:I(i,30)},remaining:{phases:I(c,20),tasks:I(u,30),todos:d},nextAction:a[0],blockers:I(r.blockers.slice().reverse(),10),decisions:I(r.decisions.slice().reverse(),10),files:{current:s,recent:f},tests:{status:xs(r.tests),recent:l},attention:I(t.attention??[],20),progress:r.progress},{capturedAt:S,source:h,...g}=p;return{...p,stateDigest:js(g)}}function Ps(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 de=class{constructor(e){this.options=e}options;async capture(e,n){let r=await kt(this.options.project,this.options.storage);if(r||(r=await ce(this.options.project,this.options.storage)),!Ps(r))return null;let s=Et(this.options.project,!1),i=[...s?s.rules.filter(S=>S.mode==="enforce").map(S=>S.text):[],...r.warnings].slice(0,20),c=Tt({project:this.options.project,identity:this.options.identity,state:r,reason:e,sequence:n,attention:i}),u=c.stateDigest,a=v([this.options.project.id,this.options.identity.sessionKey,u].join("|")).slice(0,24),d=new Date().toISOString(),l={version:1,id:a,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:d,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(S=>S.status!=="completed"&&S.status!=="cancelled"),incompleteTasks:r.tasks.filter(S=>S.status!=="completed"&&S.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:i,filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:u,continuity:c},f=`projects/${this.options.project.id}/work/handoffs/${a}.json`;await this.options.storage.exists(f)||await this.options.storage.put(f,JSON.stringify(l,null,2)+`
76
+ `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(l,null,2)+`
77
+ `,"application/json");let p=Ee(this.options.project.rootPath,".toolnet","work","handoffs");return Is(p,{recursive:!0}),A(Ee(p,`${a}.json`),l),A(Ee(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),l),l}};var me=class{identity;wal;remote;sanitizer=new q;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=Qe(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new ne(this.identity),this.remote=new te(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new oe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ue({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new pe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new de({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 Ms,openSync as As,closeSync as Os,readSync as Es,statSync as Cs}from"node:fs";function Ts(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 Rs(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 Rt(t,e={offset:0}){if(!Ms(t))return{events:[],nextOffset:e.offset,reset:!1};let n=Cs(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=As(t,"r");try{Es(c,i,0,o,s)}finally{Os(c)}let u=i.toString("utf8"),a=u.lastIndexOf(`
78
+ `);if(a<0)return{events:[],nextOffset:s,reset:r};let d=u.slice(0,a+1),l=Buffer.byteLength(d,"utf8"),f=[],p=0;for(let S of d.split(`
79
+ `)){if(!S)continue;let h=Buffer.byteLength(S+`
80
+ `,"utf8"),g=s+p;p+=h;let y;try{y=JSON.parse(S)}catch{f.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=y&&typeof y=="object"&&!Array.isArray(y)?y:{value:y};f.push({type:Ts(b),timestamp:Rs(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:f,nextOffset:s+l,reset:r}}var Ns=[/^<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*$/],_s=[/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],$s=["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 Ls(t){let e=t.toLowerCase();return $s.some(n=>e.includes(n))}function Fs(t){if(!t.trim())return!0;for(let e of Ns)if(e.test(t))return!0;return Ls(t),!1}function Ds(t){let e=t;for(let n of _s)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Ce(t){let e=t.trim();return e?Fs(e)?{content:"",filtered:!0,reason:"noise"}:{content:Ds(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function fe(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=Ce(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=fe(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=Ce(s);return o.filtered?null:o.content}return s&&typeof s=="object"?fe(s):s}).filter(s=>s!==null):e[n]=r;return e}function Nt(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&&Ce(r).filtered)return!0}return!1}function zs(t){return t==="~"?Te():t.startsWith("~/")?_t(Te(),t.slice(2)):t}async function ge(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let n=Ks(zs(t.transcriptPath)),r=new me({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=Rt(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(f=>!Nt(f.data)).map(f=>({...f,data:fe(f.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 f=a.map(S=>JSON.stringify(S.data)),p=re(f,e);r.setSourceCursor("agy.session.summary",p.summary),r.setSourceCursor("agy.session.facts_count",p.durableFacts.length),ut()&&(dt()||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 $t(t){return _t(Te(),".gemini","antigravity-cli","brain",t,".system_generated","logs","transcript.jsonl")}import{existsSync as ve,mkdirSync as Jt,readFileSync as Vt,renameSync as oo,writeFileSync as io}from"node:fs";import{dirname as ao,join as Se}from"node:path";import{existsSync as qs,mkdirSync as Js,readFileSync as Vs,renameSync as Us,rmSync as Hs,writeFileSync as Ys}from"node:fs";import{dirname as Gs}from"node:path";import{homedir as Ws}from"node:os";import{join as K}from"node:path";function Lt(t={}){return K(t.home??Ws(),".gemini")}function Ft(t={}){return K(Lt(t),"config")}function ye(t={}){return K(Ft(t),"mcp_config.json")}function he(t={}){return K(Ft(t),"hooks.json")}function Bs(t={}){return K(Lt(t),"antigravity-cli")}function Dt(t="toolnet-memory",e={}){return K(Bs(e),"plugins",t)}function Qs(t){return`'${t.replace(/'/g,"'\\''")}'`}function Kt(t={}){let e=t.hooksFile??he();Js(Gs(e),{recursive:!0,mode:448});let n={};if(qs(e)){let i;try{i=JSON.parse(Vs(e,"utf8"))}catch(c){throw new Error(`Invalid existing Agy hooks.json: ${c instanceof Error?c.message:String(c)}`)}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=`${Qs(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{Ys(o,JSON.stringify(n,null,2)+`
81
+ `,{encoding:"utf8",mode:384}),Us(o,e)}finally{Hs(o,{force:!0})}return e}import{existsSync as Xs,mkdirSync as Zs,readFileSync as eo,renameSync as to,writeFileSync as no}from"node:fs";import{dirname as ro}from"node:path";function U(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function so(t,e){Zs(ro(t),{recursive:!0,mode:448});let n=`${t}.tmp-${process.pid}-${Date.now()}`;no(n,`${JSON.stringify(e,null,2)}
82
+ `,{encoding:"utf8",mode:384}),to(n,t)}function zt(t){if(!Xs(t))return{};let e=eo(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(!U(n))throw new Error("Invalid existing Agy MCP config: root must be a JSON object.");return n}function Wt(t,e){return U(t)?t.command===e&&Array.isArray(t.args)&&t.args.length===1&&t.args[0]==="mcp":!1}function Bt(t={}){let e=t.configFile??ye(),n=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=t.serverName??"toolnet-memory",s=zt(e),o=s.mcpServers;if(o!==void 0&&!U(o))throw new Error("Invalid existing Agy MCP config: mcpServers must be an object.");let i=U(o)?{...o}:{},c=i[r];if(Wt(c,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};so(e,u);let d=zt(e).mcpServers;if(!U(d)||!Wt(d[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 co=`# ToolNet Memory Continuity
83
+
84
+ ToolNet Memory is the authoritative continuity layer for previous project work.
85
+
86
+ ## Resume / continue behavior
87
+
88
+ Whenever the user asks to continue, resume, finish, pick up, return to, or complete previous work:
89
+
90
+ 1. FIRST call the ToolNet Memory MCP tool \`memory_agent_ask\`.
91
+ 2. Use ToolNet's compact continuity result to determine:
92
+ - current task
93
+ - completed work
94
+ - current or last file
95
+ - TODOs
96
+ - blockers
97
+ - next action
98
+ 3. Only AFTER continuity is known may you inspect current source or git to verify repository truth.
99
+
100
+ ## Forbidden continuity recovery
101
+
102
+ Do NOT reconstruct previous work by reading, listing, searching, or shelling into:
103
+
104
+ - \`.toolnet/sessions/**\`
105
+ - \`state.json\`
106
+ - \`events.jsonl\`
107
+ - raw transcripts
108
+ - \`~/.gemini/antigravity-cli/brain/**\`
109
+ - Antigravity \`transcript.jsonl\`
110
+ - another coding agent's internal session history
111
+
112
+ Do NOT run Bash/cat/tail/grep against those locations to discover previous work.
113
+
114
+ Do NOT search the filesystem for the implementation or schema of \`memory_agent_ask\`.
115
+ Invoke the MCP tool directly.
116
+
117
+ For direct continuity facts, prefer \`mode="local"\`.
118
+ Use \`mode="ai"\` only when continuity is ambiguous or requires synthesis.
119
+
120
+ Current repository evidence overrides stale memory after ToolNet has restored the working context.
121
+
122
+ Do not ask the user to repeat context already available through ToolNet Memory.
123
+ `;function Ut(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Re(t,e){Jt(ao(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;io(n,e,{encoding:"utf8",mode:384}),oo(n,t)}function qt(t,e){ve(t)&&Vt(t,"utf8")===e||Re(t,e)}function Ht(t){if(!ve(t))return{};let e=Vt(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(!Ut(n))throw new Error(`Invalid legacy Antigravity config ${t}: root must be object`);return n}function uo(t,e){if(!ve(t))return!1;let n=Ht(t);if(!Ut(n.mcpServers)||!Object.prototype.hasOwnProperty.call(n.mcpServers,e))return!1;let r={...n.mcpServers};return delete r[e],Re(t,`${JSON.stringify({...n,mcpServers:r},null,2)}
124
+ `),!0}function lo(t){if(!ve(t))return!1;let e=Ht(t);if(!Object.prototype.hasOwnProperty.call(e,"toolnet-memory"))return!1;let n={...e};return delete n["toolnet-memory"],Re(t,`${JSON.stringify(n,null,2)}
125
+ `),!0}function Yt(t={}){let e=t.pluginName??"toolnet-memory",n=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=t.pluginRoot??Dt(e),s=Se(r,"plugin.json"),o=Se(r,"mcp_config.json"),i=Se(r,"hooks.json"),c=Se(r,"rules","toolnet-memory-continuity.md");Jt(r,{recursive:!0,mode:448}),qt(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)}
126
+ `),Bt({configFile:o,binary:n,serverName:"toolnet-memory"}),Kt({hooksFile:i,binary:n}),qt(c,`${co.trim()}
127
+ `);let u=t.legacyMcpFile??ye(),a=t.legacyHooksFile??he(),d=[];return u!==o&&uo(u,"toolnet-memory")&&d.push(u),a!==i&&lo(a)&&d.push(a),{installed:!0,pluginRoot:r,files:[s,o,i,c],migratedLegacy:d}}import{existsSync as Gt}from"node:fs";import{homedir as po}from"node:os";import{join as mo,resolve as Qt}from"node:path";import{DatabaseSync as fo}from"node:sqlite";function Xt(t){if(t.startsWith("file://"))try{return decodeURIComponent(new URL(t).pathname)}catch{return t}return t}function go(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(Xt)}catch{}return[Xt(t)]}function yo(t,e){let n=Qt(t.rootPath);return e.some(r=>{let s=Qt(r);return s===n||s.startsWith(n+"/")||n.startsWith(s+"/")})}async function Zt(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??mo(po(),".gemini","antigravity-cli","conversation_summaries.db");if(!Gt(r))throw new Error(`Agy summary database not found: ${r}`);let s=new fo(r,{readOnly:!0});s.exec("PRAGMA query_only = ON");let o=s.prepare(`
81
128
  SELECT
82
129
  conversation_id,
83
130
  title,
@@ -87,10 +134,11 @@ Things an AI agent should always remember.
87
134
  FROM conversation_summaries
88
135
  ORDER BY
89
136
  last_user_input_time DESC
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=Ne(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
137
+ `).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=go(a.workspace_uris);if(!yo(t,l))continue;let f=$t(d);if(!Gt(f))continue;c++,console.log(`[${c}/${u}] Processing conversation: ${d.slice(0,8)}...`);let p=await ge({project:t,storage:e,conversationId:d,transcriptPath:f,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 be(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function ho(t){let e=H(),n=Je(Be({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new ee(n,t.id,t.name,t.remote??t.name)}async function So(){let[t="help",...e]=process.argv.slice(2);if(t==="install-hooks"||t==="install-plugin"){let o=Yt({binary:be(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=be(e,"--project")??process.cwd(),r=new G().detect(n),s=ho(r);if(t==="sync"){let o=e[0],i=be(e,"--transcript");if(!o||!i)throw new Error("Usage: sync <conversation-id> --transcript <path>");let c=await ge({project:r,storage:s,conversationId:o,transcriptPath:i,phase:"recover"});console.log(JSON.stringify(c,null,2));return}if(t==="recover"){let o=Number(be(e,"--limit")??100),i=await Zt(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
91
138
 
92
139
  Commands:
93
140
  install-hooks
141
+ install-plugin
94
142
  sync <conversation-id> --transcript <path>
95
143
  recover [--project PATH] [--limit N]
96
- `)}xs().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});
144
+ `)}So().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});