toolnet-memory 0.2.9 → 0.2.10

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,26 @@
1
- import{existsSync as St,readFileSync as vt}from"node:fs";import{homedir as bt}from"node:os";import{join as wt}from"node:path";function jt(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 kt(){let t=process.env.TOOLNET_GLOBAL_ENV??wt(bt(),".config","toolnet-memory",".env");if(!St(t))return;let e=vt(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]=jt(r.slice(s+1)))}}kt();function K(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function L(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function be(){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:L(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:L(process.env.MEMORY_RERANK_TOP,10),finalContext:L(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:L(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:L(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as xt}from"node:crypto";import{existsSync as ce,mkdirSync as It,readFileSync as Pt,renameSync as Ot,writeFileSync as At}from"node:fs";import{basename as Et,dirname as q,join as D,parse as ke,resolve as z}from"node:path";var xe=".toolnet",Mt="project.json";function Rt(t){return xt("sha256").update(t).digest("hex").slice(0,16)}function ue(t){return D(t,xe,Mt)}function Nt(t){return ce(ue(t))}function Tt(t,e){let n=z(t),r=ke(n).root;for(;;){if(Nt(n))return n;if(n===r||e&&n===z(e))break;let s=q(n);if(s===n)break;n=s}return null}function Ct(t){let e=z(t),n=ke(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>ce(D(e,o))))return e;if(e===n)break;let s=q(e);if(s===e)break;e=s}return z(t)}function _t(t){let e;try{e=JSON.parse(Pt(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let n=e;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:q(q(t)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function we(t,e){let n=D(t,xe);It(n,{recursive:!0});let r=ue(t),s=`${r}.tmp-${process.pid}`;At(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Ot(s,r)}function je(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 B=class{detect(e=process.cwd()){let n=z(e),r=Ct(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>ce(D(r,d))),i=Tt(n,o?r:void 0);if(i){let d=ue(i),p=_t(d);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),we(i,p)),je(p,i)}let c=new Date().toISOString(),u=Et(r),a={version:1,id:Rt(r),name:u,remote:u,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return we(r,a),je(a,r)}};var $t=[{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}],J=class{scan(e){let n=[];for(let r of $t){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 W=class{scanner=new J;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 Zt}from"node:os";import{join as Qt}from"node:path";import{DeleteObjectCommand as Lt,GetObjectCommand as zt,HeadObjectCommand as Wt,ListObjectsV2Command as Ft,PutObjectCommand as Kt,S3Client as qt}from"@aws-sdk/client-s3";import{getSignedUrl as Bt}from"@aws-sdk/s3-request-presigner";var V=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new qt({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 Kt({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Bt(this.client,new zt({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 Wt({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 Lt({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Ft({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 Ie,mkdir as Dt,readFile as Jt,readdir as Vt,rm as Ut,stat as Pe,writeFile as Ht}from"node:fs/promises";import{dirname as Yt,join as Gt,relative as Oe,resolve as Xt}from"node:path";var F=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Xt(this.root,n)}async put(e,n){let r=this.path(e);await Dt(Yt(r),{recursive:!0}),await Ht(r,n)}async get(e){try{return await Jt(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 Ie(this.path(e)),!0}catch{return!1}}async delete(e){await Ut(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ie(n)}catch{return r}let s=async i=>{let c=await Vt(i,{withFileTypes:!0});for(let u of c){let a=Gt(i,u.name);if(u.isDirectory()){await s(a);continue}let d=await Pe(a);r.push({key:Oe(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await Pe(n);return o.isDirectory()?await s(n):r.push({key:Oe(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};function Ae(t){let e=t.localRoot??Qt(Zt(),".toolnet-memory","storage");if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new V({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new F(e))}return new F(e)}function en(t){return new Promise(e=>setTimeout(e,t))}async function Ee(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 en(u+a)}throw o}var tn=new Set(["put","get","getText","delete","list"]);function Me(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:tn.has(r)?(...o)=>Ee(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Re(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 Ne(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 U=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Re(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=Ne(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 he}from"node:os";import{join as lt,resolve as Rr}from"node:path";import{join as un}from"node:path";import{createHash as nn}from"node:crypto";import{dirname as rn}from"node:path";import{mkdirSync as sn,readFileSync as on,renameSync as an,writeFileSync as cn}from"node:fs";function v(t){return nn("sha256").update(t).digest("hex")}function pe(t){if(Array.isArray(t))return t.map(pe);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=pe(e[r]);return n}return t}function Te(t){return JSON.stringify(pe(t))}function Ce(t){try{return JSON.parse(on(t,"utf8"))}catch{return null}}function O(t,e){sn(rn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;cn(n,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),an(n,t)}function _e(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 $e(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=_e(r.toLowerCase(),"agent"),i=_e(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:un(t.rootPath,".toolnet","sessions",o,i)}}function Le(t){return String(t).padStart(12,"0")}var H=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 bt,readFileSync as kt}from"node:fs";import{homedir as wt}from"node:os";import{join as jt}from"node:path";function xt(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function It(){let t=process.env.TOOLNET_GLOBAL_ENV??jt(wt(),".config","toolnet-memory",".env");if(!bt(t))return;let e=kt(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]=xt(r.slice(s+1)))}}It();function K(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function L(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function we(){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:L(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:L(process.env.MEMORY_RERANK_TOP,10),finalContext:L(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:L(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:L(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Pt}from"node:crypto";import{existsSync as ue,mkdirSync as Ot,readFileSync as At,renameSync as Et,writeFileSync as Rt}from"node:fs";import{basename as Mt,dirname as D,join as J,parse as Ie,resolve as z}from"node:path";var Pe=".toolnet",Ct="project.json";function Nt(t){return Pt("sha256").update(t).digest("hex").slice(0,16)}function pe(t){return J(t,Pe,Ct)}function Tt(t){return ue(pe(t))}function _t(t,e){let n=z(t),r=Ie(n).root;for(;;){if(Tt(n))return n;if(n===r||e&&n===z(e))break;let s=D(n);if(s===n)break;n=s}return null}function $t(t){let e=z(t),n=Ie(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>ue(J(e,o))))return e;if(e===n)break;let s=D(e);if(s===e)break;e=s}return z(t)}function Kt(t){let e;try{e=JSON.parse(At(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:D(D(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 je(t,e){let n=J(t,Pe);Ot(n,{recursive:!0});let r=pe(t),s=`${r}.tmp-${process.pid}`;Rt(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Et(s,r)}function xe(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 q=class{detect(e=process.cwd()){let n=z(e),r=$t(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>ue(J(r,d))),i=_t(n,o?r:void 0);if(i){let d=pe(i),p=Kt(d);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),je(i,p)),xe(p,i)}let c=new Date().toISOString(),u=Mt(r),a={version:1,id:Nt(r),name:u,remote:u,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return je(r,a),xe(a,r)}};var Lt=[{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}],V=class{scan(e){let n=[];for(let r of Lt){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 W=class{scanner=new V;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 cn}from"node:os";import{join as un}from"node:path";import{DeleteObjectCommand as zt,GetObjectCommand as Wt,HeadObjectCommand as Ft,ListObjectsV2Command as Bt,PutObjectCommand as Dt,S3Client as qt}from"@aws-sdk/client-s3";import{getSignedUrl as Jt}from"@aws-sdk/s3-request-presigner";var U=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new qt({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 Dt({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Jt(this.client,new Wt({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 Ft({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 zt({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Bt({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 Oe,mkdir as Vt,readFile as Ut,readdir as Ht,rm as Yt,stat as Ae,writeFile as Gt}from"node:fs/promises";import{dirname as Xt,join as Qt,relative as Ee,resolve as Zt}from"node:path";var F=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Zt(this.root,n)}async put(e,n){let r=this.path(e);await Vt(Xt(r),{recursive:!0}),await Gt(r,n)}async get(e){try{return await Ut(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 Oe(this.path(e)),!0}catch{return!1}}async delete(e){await Yt(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Oe(n)}catch{return r}let s=async i=>{let c=await Ht(i,{withFileTypes:!0});for(let u of c){let a=Qt(i,u.name);if(u.isDirectory()){await s(a);continue}let d=await Ae(a);r.push({key:Ee(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await Ae(n);return o.isDirectory()?await s(n):r.push({key:Ee(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as en,GetObjectCommand as tn,HeadObjectCommand as nn,ListObjectsV2Command as rn,PutObjectCommand as sn,S3Client as on}from"@aws-sdk/client-s3";import{getSignedUrl as an}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 on({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 sn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await an(this.client,new tn({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 nn({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 en({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new rn({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 le(t,e){return console.warn(e),new F(t)}function Re(t){let e=t.localRoot??un(cn(),".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}):le(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}):le(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 U({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):le(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new F(e)}function pn(t){return new Promise(e=>setTimeout(e,t))}async function Me(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 pn(u+a)}throw o}var ln=new Set(["put","get","getText","delete","list"]);function Ce(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:ln.has(r)?(...o)=>Me(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Ne(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 Te(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 H=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Ne(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=Te(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 ve}from"node:os";import{join as mt,resolve as Wr}from"node:path";import{join as Sn}from"node:path";import{createHash as dn}from"node:crypto";import{dirname as mn}from"node:path";import{mkdirSync as fn,readFileSync as gn,renameSync as yn,writeFileSync as hn}from"node:fs";function v(t){return dn("sha256").update(t).digest("hex")}function de(t){if(Array.isArray(t))return t.map(de);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=de(e[r]);return n}return t}function _e(t){return JSON.stringify(de(t))}function $e(t){try{return JSON.parse(gn(t,"utf8"))}catch{return null}}function O(t,e){fn(mn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;hn(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),yn(n,t)}function Ke(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 Le(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=Ke(r.toLowerCase(),"agent"),i=Ke(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:Sn(t.rootPath,".toolnet","sessions",o,i)}}function ze(t){return String(t).padStart(12,"0")}var Y=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(m=>m.sequence>i.maxSequence),u=0;for(let m of this.split(c)){let y=m[0],b=m[m.length-1],M=m.map(R=>JSON.stringify(R)).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(m=>m.sequence>i.maxSequence),u=0;for(let m of this.split(c)){let y=m[0],b=m[m.length-1],R=m.map(M=>JSON.stringify(M)).join(`
8
8
  `)+`
9
- `,N=v(M).slice(0,16),P=[e.remotePrefix,"events",`${Le(y.sequence)}-${Le(b.sequence)}-${N}.jsonl`].join("/");await this.storage.exists(P)||await this.storage.put(P,M,"application/x-ndjson"),u+=m.length}let a=await this.scan(e),d=n[n.length-1],p=o?.status??"active";d?.type==="session_end"||d?.type==="session_idle"?p="idle":d?.type==="error"?p="error":n.length>0&&(p="active");let f=new Date().toISOString(),h=n[0],S={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:p,createdAt:o?.createdAt??h?.timestamp??f,updatedAt:d?.timestamp??f,firstEventAt:o?.firstEventAt??h?.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 g={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`,g),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:u,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:p}}};import{closeSync as le,existsSync as pn,fsyncSync as ln,mkdirSync as dn,openSync as de,readSync as mn,rmSync as ze,statSync as We,writeSync as fn}from"node:fs";import{join as me}from"node:path";var gn=12e4,yn=80,hn=2e3;function Sn(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var Y=class{constructor(e){this.identity=e;dn(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 Ce(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){O(this.stateFile,e)}acquireLock(){for(let e=0;e<yn;e+=1)try{return de(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-We(this.lockFile).mtimeMs>gn){ze(this.lockFile,{force:!0});continue}}catch{}Sn(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{le(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 p of e){let f=p.timestamp??new Date().toISOString(),h=p.data??{},S=p.provenance?.rawDigest??v(Te(h)),g=p.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,p.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,p.type,f,S].join("|"),m=v(g).slice(0,32);if(r.has(m))continue;s+=1;let y={version:1,id:m,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:p.type,timestamp:f,data:h,provenance:{...p.provenance,rawDigest:S}};p.role!==void 0&&(y.role=p.role),p.sourceEventId!==void 0&&(y.sourceEventId=p.sourceEventId),p.sourceSequence!==void 0&&(y.sourceSequence=p.sourceSequence),o.push(y),r.add(m)}if(o.length===0)return[];let i=o.map(p=>JSON.stringify(p)).join(`
9
+ `,C=v(R).slice(0,16),P=[e.remotePrefix,"events",`${ze(y.sequence)}-${ze(b.sequence)}-${C}.jsonl`].join("/");await this.storage.exists(P)||await this.storage.put(P,R,"application/x-ndjson"),u+=m.length}let a=await this.scan(e),d=n[n.length-1],p=o?.status??"active";d?.type==="session_end"||d?.type==="session_idle"?p="idle":d?.type==="error"?p="error":n.length>0&&(p="active");let f=new Date().toISOString(),h=n[0],S={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:p,createdAt:o?.createdAt??h?.timestamp??f,updatedAt:d?.timestamp??f,firstEventAt:o?.firstEventAt??h?.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 g={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`,g),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:u,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:p}}};import{closeSync as me,existsSync as vn,fsyncSync as bn,mkdirSync as kn,openSync as fe,readSync as wn,rmSync as We,statSync as Fe,writeSync as jn}from"node:fs";import{join as ge}from"node:path";var xn=12e4,In=80,Pn=2e3;function On(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var G=class{constructor(e){this.identity=e;kn(e.localDirectory,{recursive:!0}),this.eventsFile=ge(e.localDirectory,"events.jsonl"),this.stateFile=ge(e.localDirectory,"state.json"),this.lockFile=ge(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 $e(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){O(this.stateFile,e)}acquireLock(){for(let e=0;e<In;e+=1)try{return fe(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-Fe(this.lockFile).mtimeMs>xn){We(this.lockFile,{force:!0});continue}}catch{}On(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{me(n),We(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 p of e){let f=p.timestamp??new Date().toISOString(),h=p.data??{},S=p.provenance?.rawDigest??v(_e(h)),g=p.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,p.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,p.type,f,S].join("|"),m=v(g).slice(0,32);if(r.has(m))continue;s+=1;let y={version:1,id:m,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:p.type,timestamp:f,data:h,provenance:{...p.provenance,rawDigest:S}};p.role!==void 0&&(y.role=p.role),p.sourceEventId!==void 0&&(y.sourceEventId=p.sourceEventId),p.sourceSequence!==void 0&&(y.sourceSequence=p.sourceSequence),o.push(y),r.add(m)}if(o.length===0)return[];let i=o.map(p=>JSON.stringify(p)).join(`
10
10
  `)+`
11
- `,c=de(this.eventsFile,"a",384);try{fn(c,i,null,"utf8"),ln(c)}finally{le(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(-hn);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:d}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!pn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=We(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=de(this.eventsFile,"r");try{mn(i,o,0,s,r)}finally{le(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 Cn,existsSync as _n,openSync as $n,readSync as Ln,statSync as zn}from"node:fs";function Fe(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 De=[/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],vn=[/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],bn=[/\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],wn=[/\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],jn=[/đã 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],Ke=[/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],kn=[/\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],xn=[/đườ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],In=[/\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],qe=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Pn=new Set(["payload","data","content","message","messages","parts","summary"]);function k(t,e){return e.some(n=>n.test(t))}function Je(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function On(t){return Je(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function An(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 fe(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||qe.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))fe(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(qe.has(s)||Pn.has(s))&&fe(o,s,n,r+1)}}function En(t){let e=[];fe(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=Je(o);if(An(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function Be(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Mn(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&&k(t,De)?{kind:"rule",confidence:.98}:r&&k(t,vn)?{kind:"rule",confidence:.92}:k(t,bn)?{kind:k(t,Ke)?"architecture":"decision",confidence:r?.93:.86}:r&&k(t,wn)?{kind:"todo",confidence:.87}:k(t,Ke)&&k(t,kn)?{kind:"architecture",confidence:r?.88:.82}:s&&k(t,jn)?{kind:"fix",confidence:.8}:r&&k(t,xn)&&k(t,In)?{kind:"context",confidence:.79}:null}function Rn(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Nn(t,e,n){return t==="rule"&&k(n,De)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":Fe(e,n)}function Ve(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=Be(o);i&&c&&s.set(i,c)}for(let o of e){let i=Be(o),c=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&c&&(i=s.get(c)??"");for(let u of En(o)){let a=Mn(u,i,o);if(!a||a.confidence<.75)continue;let d=Rn(a.kind),p=On(u),f=v([t.projectId,a.kind,p].join("|"));if(r.has(f))continue;r.add(f);let h=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:Nn(a.kind,d,u),tags:[d],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:h,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function Ue(t){return String(t).padStart(12,"0")}function Tn(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var G=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=[Tn(e),"batches",`${Ue(s)}-${Ue(o)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,c,"application/json"),a}};function Wn(t,e){if(!_n(t))return{events:[],nextOffset:e};let n=zn(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=$n(t,"r");try{Ln(i,o,0,s,r)}finally{Cn(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
11
+ `,c=fe(this.eventsFile,"a",384);try{jn(c,i,null,"utf8"),bn(c)}finally{me(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(-Pn);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:d}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!vn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=Fe(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=fe(this.eventsFile,"r");try{wn(i,o,0,s,r)}finally{me(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 Dn,existsSync as qn,openSync as Jn,readSync as Vn,statSync as Un}from"node:fs";function Be(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 Ve=[/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],An=[/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],En=[/\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],Rn=[/\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],Mn=[/đã 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],De=[/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],Cn=[/\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],Nn=[/đườ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],Tn=[/\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],qe=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),_n=new Set(["payload","data","content","message","messages","parts","summary"]);function j(t,e){return e.some(n=>n.test(t))}function Ue(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function $n(t){return Ue(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Kn(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 ye(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||qe.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))ye(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(qe.has(s)||_n.has(s))&&ye(o,s,n,r+1)}}function Ln(t){let e=[];ye(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=Ue(o);if(Kn(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function Je(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function zn(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&&j(t,Ve)?{kind:"rule",confidence:.98}:r&&j(t,An)?{kind:"rule",confidence:.92}:j(t,En)?{kind:j(t,De)?"architecture":"decision",confidence:r?.93:.86}:r&&j(t,Rn)?{kind:"todo",confidence:.87}:j(t,De)&&j(t,Cn)?{kind:"architecture",confidence:r?.88:.82}:s&&j(t,Mn)?{kind:"fix",confidence:.8}:r&&j(t,Nn)&&j(t,Tn)?{kind:"context",confidence:.79}:null}function Wn(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Fn(t,e,n){return t==="rule"&&j(n,Ve)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":Be(e,n)}function He(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=Je(o);i&&c&&s.set(i,c)}for(let o of e){let i=Je(o),c=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&c&&(i=s.get(c)??"");for(let u of Ln(o)){let a=zn(u,i,o);if(!a||a.confidence<.75)continue;let d=Wn(a.kind),p=$n(u),f=v([t.projectId,a.kind,p].join("|"));if(r.has(f))continue;r.add(f);let h=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:Fn(a.kind,d,u),tags:[d],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:h,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function Ye(t){return String(t).padStart(12,"0")}function Bn(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var X=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=[Bn(e),"batches",`${Ye(s)}-${Ye(o)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,c,"application/json"),a}};function Hn(t,e){if(!qn(t))return{events:[],nextOffset:e};let n=Un(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=Jn(t,"r");try{Vn(i,o,0,s,r)}finally{Dn(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
14
14
  `);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
15
- `).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var X=class{constructor(e){this.options=e;this.journal=new G(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=Wn(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Ve(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 Vn,existsSync as Un,openSync as Hn,readSync as Yn,statSync as Gn}from"node:fs";var Fn=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function C(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ye(t){return C(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function T(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))T(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Fn.has(r)||["data","payload","parts","messages"].includes(r))&&T(s,e,n+1)}}function Z(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 He(t){let e=C(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function w(t,e,n,r,s={}){let o=C(r),i=s.key??Ye(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 Kn(t,e,n){let r=C(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(w(t,e,"goal",i[1],{confidence:.97}));let c=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);c?.[1]&&s.push(w(t,e,"plan",c[1],{confidence:.95}));let u=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=u.exec(r));){let f=Number(a[1]),h=C(a[2]??""),S=h&&!He(h)?`Phase ${f} - ${h}`:`Phase ${f}`;s.push(w(t,e,"phase",S,{key:`phase:${f}`,order:f,status:Z(r),confidence:.93}))}let d=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);d?.[2]&&s.push(w(t,e,"task",d[2],{status:d[1].trim()?"completed":Z(d[2]),confidence:.96}));let p=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(p?.[2]){let f=p[1]?Number(p[1]):void 0,h=C(p[2]),S=He(h);s.push(w(t,e,"task",S&&f!==void 0?`TODO ${f}`:h,{key:f!==void 0?`task:${f}`:Ye(h),order:f,status:Z(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(w(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(w(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(w(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(w(t,e,"decision",r,{confidence:.9})),s}function Ge(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=[];T(i.data,u);for(let a of u)s(w(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];T(i.data,u);for(let a of u)s(w(t,i,"task",a,{status:Z(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let a=i.data[u];typeof a=="string"&&a&&s(w(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let u=[];T(i.data,u);for(let a of u)s(w(t,i,"test",a,{confidence:1}))}let c=[];T(i.data,c);for(let u of c)for(let a of u.split(/\n+/u))for(let d of Kn(t,i,a))s(d)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function Xe(t){return String(t).padStart(12,"0")}var Q=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,`${Xe(r)}-${Xe(s)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as Ze}from"node:path";import{mkdirSync as qn}from"node:fs";function Bn(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=Bn(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Dn(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 Qe(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&&Dn(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 Jn(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 ee(t,e){let r=(await Jn(t,e)).flatMap(l=>l.observations).sort((l,j)=>{let Se=l.occurredAt.localeCompare(j.occurredAt);if(Se!==0)return Se;let ve=l.sequence-j.sequence;return ve!==0?ve:l.id.localeCompare(j.id)}),s=new Map,o=new Map,i,c,u,a=[],d=[],p=[],f=[],h=[],S=[];for(let l of r)switch(l.kind){case"goal":i=l.text;break;case"plan":c=l.text;break;case"phase":s.set(l.key,Qe(s.get(l.key),l));break;case"task":o.set(l.key,Qe(o.get(l.key),l));break;case"decision":a.push(l.text);break;case"blocker":d.push(l.text);break;case"warning":p.push(l.text);break;case"next_action":f.push(l.text);break;case"file":h.push(l.text);break;case"test":S.push(l.text);break;case"session":u={agent:l.agent,nativeSessionId:l.nativeSessionId,sessionKey:l.sessionKey,updatedAt:l.occurredAt};break}let g=Array.from(s.values()).sort((l,j)=>(l.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),m=Array.from(o.values()).sort((l,j)=>(l.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),y=g.find(l=>l.status==="in_progress")??g.find(l=>l.status==="blocked")??g.find(l=>l.status==="pending"),b=m.find(l=>l.status==="in_progress")??m.find(l=>l.status==="blocked")??m.find(l=>l.status==="pending"),M=_([...f,...b?[b.title]:[],...!b&&y?[y.title]:[],...m.filter(l=>l.status==="pending").slice(0,5).map(l=>l.title)],8),N=_([...d,...g.filter(l=>l.status==="blocked").map(l=>l.title),...m.filter(l=>l.status==="blocked").map(l=>l.title)],20),P={version:1,projectId:t.id,projectName:t.name,goal:i,plan:c,phases:g,tasks:m,decisions:_(a,20),blockers:N,warnings:_(p,20),nextActions:M,filesTouched:_(h,30),tests:_(S,20),currentPhase:y,currentTask:b,progress:{phasesTotal:g.length,phasesCompleted:g.filter(l=>l.status==="completed").length,tasksTotal:m.length,tasksCompleted:m.filter(l=>l.status==="completed").length,blocked:g.filter(l=>l.status==="blocked").length+m.filter(l=>l.status==="blocked").length},lastSession:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},R=Ze(t.rootPath,".toolnet","work");return qn(R,{recursive:!0}),O(Ze(R,"current.json"),P),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(P,null,2)+`
17
- `,"application/json"),P}async function et(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 Xn(t,e){if(!Un(t))return{events:[],nextOffset:e};let n=Gn(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=Hn(t,"r");try{Yn(i,o,0,s,r)}finally{Vn(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
15
+ `).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var Q=class{constructor(e){this.options=e;this.journal=new X(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=Hn(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=He(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 tr,existsSync as nr,openSync as rr,readSync as sr,statSync as or}from"node:fs";var Yn=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function T(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Xe(t){return T(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function N(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))N(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Yn.has(r)||["data","payload","parts","messages"].includes(r))&&N(s,e,n+1)}}function Z(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 Ge(t){let e=T(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=T(r),i=s.key??Xe(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 Gn(t,e,n){let r=T(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]),h=T(a[2]??""),S=h&&!Ge(h)?`Phase ${f} - ${h}`:`Phase ${f}`;s.push(k(t,e,"phase",S,{key:`phase:${f}`,order:f,status:Z(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":Z(d[2]),confidence:.96}));let p=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(p?.[2]){let f=p[1]?Number(p[1]):void 0,h=T(p[2]),S=Ge(h);s.push(k(t,e,"task",S&&f!==void 0?`TODO ${f}`:h,{key:f!==void 0?`task:${f}`:Xe(h),order:f,status:Z(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 Qe(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let u=[];N(i.data,u);for(let a of u)s(k(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];N(i.data,u);for(let a of u)s(k(t,i,"task",a,{status:Z(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let a=i.data[u];typeof a=="string"&&a&&s(k(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let u=[];N(i.data,u);for(let a of u)s(k(t,i,"test",a,{confidence:1}))}let c=[];N(i.data,c);for(let u of c)for(let a of u.split(/\n+/u))for(let d of Gn(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 Ze(t){return String(t).padStart(12,"0")}var ee=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,`${Ze(r)}-${Ze(s)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as et}from"node:path";import{mkdirSync as Xn}from"node:fs";function Qn(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=Qn(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Zn(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function tt(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&Zn(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 er(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 te(t,e){let r=(await er(t,e)).flatMap(l=>l.observations).sort((l,w)=>{let be=l.occurredAt.localeCompare(w.occurredAt);if(be!==0)return be;let ke=l.sequence-w.sequence;return ke!==0?ke:l.id.localeCompare(w.id)}),s=new Map,o=new Map,i,c,u,a=[],d=[],p=[],f=[],h=[],S=[];for(let l of r)switch(l.kind){case"goal":i=l.text;break;case"plan":c=l.text;break;case"phase":s.set(l.key,tt(s.get(l.key),l));break;case"task":o.set(l.key,tt(o.get(l.key),l));break;case"decision":a.push(l.text);break;case"blocker":d.push(l.text);break;case"warning":p.push(l.text);break;case"next_action":f.push(l.text);break;case"file":h.push(l.text);break;case"test":S.push(l.text);break;case"session":u={agent:l.agent,nativeSessionId:l.nativeSessionId,sessionKey:l.sessionKey,updatedAt:l.occurredAt};break}let g=Array.from(s.values()).sort((l,w)=>(l.order??Number.MAX_SAFE_INTEGER)-(w.order??Number.MAX_SAFE_INTEGER)),m=Array.from(o.values()).sort((l,w)=>(l.order??Number.MAX_SAFE_INTEGER)-(w.order??Number.MAX_SAFE_INTEGER)),y=g.find(l=>l.status==="in_progress")??g.find(l=>l.status==="blocked")??g.find(l=>l.status==="pending"),b=m.find(l=>l.status==="in_progress")??m.find(l=>l.status==="blocked")??m.find(l=>l.status==="pending"),R=_([...f,...b?[b.title]:[],...!b&&y?[y.title]:[],...m.filter(l=>l.status==="pending").slice(0,5).map(l=>l.title)],8),C=_([...d,...g.filter(l=>l.status==="blocked").map(l=>l.title),...m.filter(l=>l.status==="blocked").map(l=>l.title)],20),P={version:1,projectId:t.id,projectName:t.name,goal:i,plan:c,phases:g,tasks:m,decisions:_(a,20),blockers:C,warnings:_(p,20),nextActions:R,filesTouched:_(h,30),tests:_(S,20),currentPhase:y,currentTask:b,progress:{phasesTotal:g.length,phasesCompleted:g.filter(l=>l.status==="completed").length,tasksTotal:m.length,tasksCompleted:m.filter(l=>l.status==="completed").length,blocked:g.filter(l=>l.status==="blocked").length+m.filter(l=>l.status==="blocked").length},lastSession:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},M=et(t.rootPath,".toolnet","work");return Xn(M,{recursive:!0}),O(et(M,"current.json"),P),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(P,null,2)+`
17
+ `,"application/json"),P}async function nt(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 ir(t,e){if(!nr(t))return{events:[],nextOffset:e};let n=or(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=rr(t,"r");try{sr(i,o,0,s,r)}finally{tr(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
18
18
  `);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
19
- `).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var te=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["work.continuity.offset"]??0),r=Xn(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=Ge(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ee(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 ar,openSync as cr,readSync as ur,statSync as pr}from"node:fs";var Zn=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function $(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function ge(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))ge(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Zn.has(r)||["data","payload","parts","messages"].includes(r))&&ge(s,e,n+1)}}function x(t,e,n,r,s,o=.95){let i=$(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 $(t.slice(r.length+1))}return null}function Qn(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function er(t){return $(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function tt(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=[];ge(o.data,i);for(let c of i){let u={type:"project"},a=null;for(let d of c.split(/\r?\n/u)){let p=$(d);if(!p){a=null;continue}let f=p.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let j=Number(f[1]);u={type:"phase",key:`phase:${j}`,order:j,title:$(f[2]??"")},a=null;continue}let h=p.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(h){let j=Number(h[1]);u={type:"task",key:`task:${j}`,order:j,title:$(h[2]??"")},a=null;continue}let S=I(p,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(x(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let g=I(p,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(g){s(x(t,o,u.type==="phase"?"phase_objective":"objective",g,u,.98)),a=null;continue}let m=I(p,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(m){s(x(t,o,u.type==="phase"?"phase_why":"why",m,u,.98)),a=null;continue}let y=I(p,["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(x(t,o,"desired_outcome",y,{type:"project"},.98)),a=null;continue}let b=I(p,["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(x(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let M=I(p,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(M){s(x(t,o,"phase_deliverable",M,u,.97)),a=null;continue}let N=I(p,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(N){s(x(t,o,"acceptance_criterion",N,u,.98)),a="acceptance_criterion";continue}let P=I(p,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(P){s(x(t,o,"dependency",P,u,.97)),a="dependency";continue}let R=I(p,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(R){s(x(t,o,"open_question",R,u,.95)),a="open_question";continue}let l=I(p,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(l){s(x(t,o,"constraint",l,u,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(p)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(p)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(p)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(p)){a="constraint";continue}if(a&&Qn(d)){s(x(t,o,a,er(d),u,.96));continue}a=null}}}return 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(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,`${nt(r)}-${nt(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 tr}from"node:fs";import{join as rt}from"node:path";function nr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function rr(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function A(t,e){return rr(e,t)?e:t}function E(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 sr(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 or(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function st(t,e){let r=(await sr(t,e)).flatMap(g=>g.observations).sort((g,m)=>{let y=g.evidence.occurredAt.localeCompare(m.evidence.occurredAt);return y!==0?y:g.evidence.sessionKey===m.evidence.sessionKey?g.evidence.sequence-m.evidence.sequence:g.id.localeCompare(m.id)}),s,o,i,c,u,a=new Map,d=[],p=[],f=[];for(let g of r){let m=nr(g);if(g.scope==="phase"&&g.scopeKey){let y=a.get(g.scopeKey)??or(g);switch(g.kind){case"phase_objective":y.objective=A(y.objective,m);break;case"phase_why":y.why=A(y.why,m);break;case"phase_deliverable":y.deliverable=A(y.deliverable,m);break;case"acceptance_criterion":y.acceptanceCriteria.push(m);break;case"dependency":y.dependencies.push(m);break;case"open_question":y.openQuestions.push(m);break;case"constraint":y.constraints.push(m);break;case"note":y.notes.push(m);break}a.set(y.key,y);continue}switch(g.kind){case"mission":s=A(s,m);break;case"objective":o=A(o,m);break;case"why":i=A(i,m);break;case"desired_outcome":c=A(c,m);break;case"plan_rationale":u=A(u,m);break;case"open_question":d.push(m);break;case"constraint":p.push(m);break;case"note":f.push(m);break}}for(let g of a.values())g.acceptanceCriteria=E(g.acceptanceCriteria,20),g.dependencies=E(g.dependencies,15),g.openQuestions=E(g.openQuestions,15),g.constraints=E(g.constraints,15),g.notes=E(g.notes,20);let h={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:c,planRationale:u,phases:Array.from(a.values()).sort((g,m)=>g.order-m.order),openQuestions:E(d,20),constraints:E(p,20),notes:E(f,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=rt(t.rootPath,".toolnet","work");return tr(S,{recursive:!0}),O(rt(S,"semantic-current.json"),h),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(h,null,2)+`
21
- `,"application/json"),h}function lr(t,e){if(!ar(t))return{events:[],nextOffset:e};let n=pr(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=cr(t,"r");try{ur(o,s,0,s.length,r)}finally{ir(o)}let i=s.toString("utf8"),c=i.lastIndexOf(`
19
+ `).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var ne=class{constructor(e){this.options=e;this.journal=new ee(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=ir(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=Qe(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await te(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as gr,existsSync as yr,openSync as hr,readSync as Sr,statSync as vr}from"node:fs";var ar=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function $(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function he(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))he(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(ar.has(r)||["data","payload","parts","messages"].includes(r))&&he(s,e,n+1)}}function x(t,e,n,r,s,o=.95){let i=$(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 $(t.slice(r.length+1))}return null}function cr(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function ur(t){return $(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function rt(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=[];he(o.data,i);for(let c of i){let u={type:"project"},a=null;for(let d of c.split(/\r?\n/u)){let p=$(d);if(!p){a=null;continue}let f=p.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:$(f[2]??"")},a=null;continue}let h=p.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(h){let w=Number(h[1]);u={type:"task",key:`task:${w}`,order:w,title:$(h[2]??"")},a=null;continue}let S=I(p,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(x(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let g=I(p,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(g){s(x(t,o,u.type==="phase"?"phase_objective":"objective",g,u,.98)),a=null;continue}let m=I(p,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(m){s(x(t,o,u.type==="phase"?"phase_why":"why",m,u,.98)),a=null;continue}let y=I(p,["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(x(t,o,"desired_outcome",y,{type:"project"},.98)),a=null;continue}let b=I(p,["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(x(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let R=I(p,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(R){s(x(t,o,"phase_deliverable",R,u,.97)),a=null;continue}let C=I(p,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(C){s(x(t,o,"acceptance_criterion",C,u,.98)),a="acceptance_criterion";continue}let P=I(p,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(P){s(x(t,o,"dependency",P,u,.97)),a="dependency";continue}let M=I(p,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(M){s(x(t,o,"open_question",M,u,.95)),a="open_question";continue}let l=I(p,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(l){s(x(t,o,"constraint",l,u,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(p)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(p)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(p)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(p)){a="constraint";continue}if(a&&cr(d)){s(x(t,o,a,ur(d),u,.96));continue}a=null}}}return n}function st(t){return String(t).padStart(12,"0")}var re=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,`${st(r)}-${st(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 pr}from"node:fs";import{join as ot}from"node:path";function lr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function dr(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function A(t,e){return dr(e,t)?e:t}function E(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 mr(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 fr(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 mr(t,e)).flatMap(g=>g.observations).sort((g,m)=>{let y=g.evidence.occurredAt.localeCompare(m.evidence.occurredAt);return y!==0?y:g.evidence.sessionKey===m.evidence.sessionKey?g.evidence.sequence-m.evidence.sequence:g.id.localeCompare(m.id)}),s,o,i,c,u,a=new Map,d=[],p=[],f=[];for(let g of r){let m=lr(g);if(g.scope==="phase"&&g.scopeKey){let y=a.get(g.scopeKey)??fr(g);switch(g.kind){case"phase_objective":y.objective=A(y.objective,m);break;case"phase_why":y.why=A(y.why,m);break;case"phase_deliverable":y.deliverable=A(y.deliverable,m);break;case"acceptance_criterion":y.acceptanceCriteria.push(m);break;case"dependency":y.dependencies.push(m);break;case"open_question":y.openQuestions.push(m);break;case"constraint":y.constraints.push(m);break;case"note":y.notes.push(m);break}a.set(y.key,y);continue}switch(g.kind){case"mission":s=A(s,m);break;case"objective":o=A(o,m);break;case"why":i=A(i,m);break;case"desired_outcome":c=A(c,m);break;case"plan_rationale":u=A(u,m);break;case"open_question":d.push(m);break;case"constraint":p.push(m);break;case"note":f.push(m);break}}for(let g of a.values())g.acceptanceCriteria=E(g.acceptanceCriteria,20),g.dependencies=E(g.dependencies,15),g.openQuestions=E(g.openQuestions,15),g.constraints=E(g.constraints,15),g.notes=E(g.notes,20);let h={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:c,planRationale:u,phases:Array.from(a.values()).sort((g,m)=>g.order-m.order),openQuestions:E(d,20),constraints:E(p,20),notes:E(f,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=ot(t.rootPath,".toolnet","work");return pr(S,{recursive:!0}),O(ot(S,"semantic-current.json"),h),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(h,null,2)+`
21
+ `,"application/json"),h}function br(t,e){if(!yr(t))return{events:[],nextOffset:e};let n=vr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=hr(t,"r");try{Sr(o,s,0,s.length,r)}finally{gr(o)}let i=s.toString("utf8"),c=i.lastIndexOf(`
22
22
  `);if(c<0)return{events:[],nextOffset:r};let u=i.slice(0,c+1);return{events:u.split(`
23
- `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var re=class{constructor(e){this.options=e;this.journal=new ne(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=lr(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 st(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 wr}from"node:fs";import{join as ye}from"node:path";import{existsSync as at,mkdirSync as dr,readFileSync as mr,statSync as ot,writeFileSync as fr}from"node:fs";import{dirname as gr,join as yr}from"node:path";var it=64*1024,hr=`# ToolNet Project Operating Manual
23
+ `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var se=class{constructor(e){this.options=e;this.journal=new re(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=br(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=rt(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 Rr}from"node:fs";import{join as Se}from"node:path";import{existsSync as ut,mkdirSync as kr,readFileSync as wr,statSync as at,writeFileSync as jr}from"node:fs";import{dirname as xr,join as Ir}from"node:path";var ct=64*1024,Pr=`# ToolNet Project Operating Manual
24
24
 
25
25
  This file contains persistent instructions for AI agents working on this project.
26
26
 
@@ -63,13 +63,13 @@ Things an AI agent should always remember.
63
63
  <!--
64
64
  - [advisory] Prefer small focused files.
65
65
  -->
66
- `;function ct(t){return yr(t.rootPath,".toolnet","PROJECT.md")}function Sr(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function vr(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=Sr(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 br(t){let e=ct(t);return at(e)||(dr(gr(e),{recursive:!0}),fr(e,hr,{encoding:"utf8",mode:384})),e}function ut(t,e=!1){let n=e?br(t):ct(t);if(!at(n))return null;if(ot(n).size>it)throw new Error(`PROJECT.md exceeds ${it} bytes`);let s=mr(n,"utf8");return{path:n,content:s,digest:v(s),rules:vr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(ot(n).mtimeMs).toISOString()}}function jr(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 kr(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 se=class{constructor(e){this.options=e}options;async capture(e,n){let r=await et(this.options.project,this.options.storage);if(r||(r=await ee(this.options.project,this.options.storage)),!kr(r))return null;let s=ut(this.options.project,!1),o=s?s.rules.filter(f=>f.mode==="enforce").map(f=>f.text):[],i=v(JSON.stringify(jr(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(f=>f.status!=="completed"&&f.status!=="cancelled"),incompleteTasks:r.tasks.filter(f=>f.status!=="completed"&&f.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:[...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)+`
66
+ `;function pt(t){return Ir(t.rootPath,".toolnet","PROJECT.md")}function Or(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Ar(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=Or(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 Er(t){let e=pt(t);return ut(e)||(kr(xr(e),{recursive:!0}),jr(e,Pr,{encoding:"utf8",mode:384})),e}function lt(t,e=!1){let n=e?Er(t):pt(t);if(!ut(n))return null;if(at(n).size>ct)throw new Error(`PROJECT.md exceeds ${ct} bytes`);let s=wr(n,"utf8");return{path:n,content:s,digest:v(s),rules:Ar(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(at(n).mtimeMs).toISOString()}}function Mr(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 Cr(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 oe=class{constructor(e){this.options=e}options;async capture(e,n){let r=await nt(this.options.project,this.options.storage);if(r||(r=await te(this.options.project,this.options.storage)),!Cr(r))return null;let s=lt(this.options.project,!1),o=s?s.rules.filter(f=>f.mode==="enforce").map(f=>f.text):[],i=v(JSON.stringify(Mr(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(f=>f.status!=="completed"&&f.status!=="cancelled"),incompleteTasks:r.tasks.filter(f=>f.status!=="completed"&&f.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:[...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
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 p=ye(this.options.project.rootPath,".toolnet","work","handoffs");return wr(p,{recursive:!0}),O(ye(p,`${c}.json`),a),O(ye(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};var oe=class{identity;wal;remote;sanitizer=new W;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=$e(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new Y(this.identity),this.remote=new H(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new X({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new te({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new re({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new se({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 xr,openSync as Ir,closeSync as Pr,readSync as Or,statSync as Ar}from"node:fs";function Er(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 Mr(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 pt(t,e={offset:0}){if(!xr(t))return{events:[],nextOffset:e.offset,reset:!1};let n=Ar(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=Ir(t,"r");try{Or(c,i,0,o,s)}finally{Pr(c)}let u=i.toString("utf8"),a=u.lastIndexOf(`
68
+ `,"application/json");let p=Se(this.options.project.rootPath,".toolnet","work","handoffs");return Rr(p,{recursive:!0}),O(Se(p,`${c}.json`),a),O(Se(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};var ie=class{identity;wal;remote;sanitizer=new W;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=Le(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new G(this.identity),this.remote=new Y(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new Q({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ne({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new se({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new oe({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 Nr,openSync as Tr,closeSync as _r,readSync as $r,statSync as Kr}from"node:fs";function Lr(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 zr(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 dt(t,e={offset:0}){if(!Nr(t))return{events:[],nextOffset:e.offset,reset:!1};let n=Kr(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=Tr(t,"r");try{$r(c,i,0,o,s)}finally{_r(c)}let u=i.toString("utf8"),a=u.lastIndexOf(`
69
69
  `);if(a<0)return{events:[],nextOffset:s,reset:r};let d=u.slice(0,a+1),p=Buffer.byteLength(d,"utf8"),f=[],h=0;for(let S of d.split(`
70
70
  `)){if(!S)continue;let g=Buffer.byteLength(S+`
71
- `,"utf8"),m=s+h;h+=g;let y;try{y=JSON.parse(S)}catch{f.push({type:"custom",sourceEventId:`transcript:${m}`,sourceSequence:m,data:{format:"raw-line",content:S},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}});continue}let b=y&&typeof y=="object"&&!Array.isArray(y)?y:{value:y};f.push({type:Er(b),timestamp:Mr(b),role:typeof b.role=="string"?b.role:void 0,sourceEventId:`transcript:${m}`,sourceSequence:m,data:b,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}})}return{events:f,nextOffset:s+p,reset:r}}function Nr(t){return t==="~"?he():t.startsWith("~/")?lt(he(),t.slice(2)):t}async function ie(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let n=Rr(Nr(t.transcriptPath)),r=new oe({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=pt(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}}),u.push(...c.events),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 a=r.recordMany(u);r.setSourceCursor("agy.transcript.offset",c.nextOffset),t.phase&&r.setSourceCursor("agy.last.phase",t.phase);let d=await r.flush();return{conversationId:e,imported:a.length,eventCount:d.eventCount,chunkCount:d.chunkCount,status:d.status,transcriptOffset:c.nextOffset,reset:c.reset}}function dt(t){return lt(he(),".gemini","antigravity-cli","brain",t,".system_generated","logs","transcript.jsonl")}import{existsSync as Tr,mkdirSync as Cr,readFileSync as _r,writeFileSync as $r}from"node:fs";import{homedir as Lr}from"node:os";import{dirname as zr,join as Wr}from"node:path";function Fr(t){return`'${t.replace(/'/g,"'\\''")}'`}function mt(t={}){let e=t.hooksFile??Wr(Lr(),".gemini","config","hooks.json");Cr(zr(e),{recursive:!0});let n={};if(Tr(e))try{n=JSON.parse(_r(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=`${Fr(r)} session:agy-hook`;return n["toolnet-memory"]={enabled:!0,PreInvocation:[{type:"command",command:`${s} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${s} post`,timeout:15}],Stop:[{type:"command",command:`${s} stop`,timeout:30}]},$r(e,JSON.stringify(n,null,2)+`
72
- `,{encoding:"utf8",mode:384}),e}import{existsSync as ft}from"node:fs";import{homedir as Kr}from"node:os";import{join as qr,resolve as gt}from"node:path";import{DatabaseSync as Br}from"node:sqlite";function yt(t){if(t.startsWith("file://"))try{return decodeURIComponent(new URL(t).pathname)}catch{return t}return t}function Dr(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(yt)}catch{}return[yt(t)]}function Jr(t,e){let n=gt(t.rootPath);return e.some(r=>{let s=gt(r);return s===n||s.startsWith(n+"/")||n.startsWith(s+"/")})}async function ht(t,e,n=100){let r=process.env.AGY_SUMMARY_DB??qr(Kr(),".gemini","antigravity-cli","conversation_summaries.db");if(!ft(r))throw new Error(`Agy summary database not found: ${r}`);let s=new Br(r,{readOnly:!0});s.exec("PRAGMA query_only = ON");let o=s.prepare(`
71
+ `,"utf8"),m=s+h;h+=g;let y;try{y=JSON.parse(S)}catch{f.push({type:"custom",sourceEventId:`transcript:${m}`,sourceSequence:m,data:{format:"raw-line",content:S},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}});continue}let b=y&&typeof y=="object"&&!Array.isArray(y)?y:{value:y};f.push({type:Lr(b),timestamp:zr(b),role:typeof b.role=="string"?b.role:void 0,sourceEventId:`transcript:${m}`,sourceSequence:m,data:b,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}})}return{events:f,nextOffset:s+p,reset:r}}function Fr(t){return t==="~"?ve():t.startsWith("~/")?mt(ve(),t.slice(2)):t}async function ae(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let n=Wr(Fr(t.transcriptPath)),r=new ie({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=dt(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}}),u.push(...c.events),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 a=r.recordMany(u);r.setSourceCursor("agy.transcript.offset",c.nextOffset),t.phase&&r.setSourceCursor("agy.last.phase",t.phase);let d=await r.flush();return{conversationId:e,imported:a.length,eventCount:d.eventCount,chunkCount:d.chunkCount,status:d.status,transcriptOffset:c.nextOffset,reset:c.reset}}function ft(t){return mt(ve(),".gemini","antigravity-cli","brain",t,".system_generated","logs","transcript.jsonl")}import{existsSync as Br,mkdirSync as Dr,readFileSync as qr,writeFileSync as Jr}from"node:fs";import{homedir as Vr}from"node:os";import{dirname as Ur,join as Hr}from"node:path";function Yr(t){return`'${t.replace(/'/g,"'\\''")}'`}function gt(t={}){let e=t.hooksFile??Hr(Vr(),".gemini","config","hooks.json");Dr(Ur(e),{recursive:!0});let n={};if(Br(e))try{n=JSON.parse(qr(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=`${Yr(r)} session:agy-hook`;return n["toolnet-memory"]={enabled:!0,PreInvocation:[{type:"command",command:`${s} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${s} post`,timeout:15}],Stop:[{type:"command",command:`${s} stop`,timeout:30}]},Jr(e,JSON.stringify(n,null,2)+`
72
+ `,{encoding:"utf8",mode:384}),e}import{existsSync as yt}from"node:fs";import{homedir as Gr}from"node:os";import{join as Xr,resolve as ht}from"node:path";import{DatabaseSync as Qr}from"node:sqlite";function St(t){if(t.startsWith("file://"))try{return decodeURIComponent(new URL(t).pathname)}catch{return t}return t}function Zr(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(St)}catch{}return[St(t)]}function es(t,e){let n=ht(t.rootPath);return e.some(r=>{let s=ht(r);return s===n||s.startsWith(n+"/")||n.startsWith(s+"/")})}async function vt(t,e,n=100){let r=process.env.AGY_SUMMARY_DB??Xr(Gr(),".gemini","antigravity-cli","conversation_summaries.db");if(!yt(r))throw new Error(`Agy summary database not found: ${r}`);let s=new Qr(r,{readOnly:!0});s.exec("PRAGMA query_only = ON");let o=s.prepare(`
73
73
  SELECT
74
74
  conversation_id,
75
75
  title,
@@ -79,10 +79,10 @@ Things an AI agent should always remember.
79
79
  FROM conversation_summaries
80
80
  ORDER BY
81
81
  last_user_input_time DESC
82
- `).all();s.close();let i=[];for(let c of o){let u=typeof c.conversation_id=="string"?c.conversation_id:"";if(!u)continue;let a=Dr(c.workspace_uris);if(!Jr(t,a))continue;let d=dt(u);if(ft(d)&&(i.push(await ie({project:t,storage:e,conversationId:u,transcriptPath:d,workspacePaths:a,modelName:typeof c.agent_name=="string"?c.agent_name:void 0,phase:"recover"})),i.length>=n))break}return i}function ae(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function Vr(t){let e=be(),n=Me(Ae({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new U(n,t.id,t.name,t.remote??t.name)}async function Ur(){let[t="help",...e]=process.argv.slice(2);if(t==="install-hooks"){let o=mt({binary:ae(e,"--bin")});console.log(`\u2705 Agy hooks installed: ${o}`);return}let n=ae(e,"--project")??process.cwd(),r=new B().detect(n),s=Vr(r);if(t==="sync"){let o=e[0],i=ae(e,"--transcript");if(!o||!i)throw new Error("Usage: sync <conversation-id> --transcript <path>");let c=await ie({project:r,storage:s,conversationId:o,transcriptPath:i,phase:"recover"});console.log(JSON.stringify(c,null,2));return}if(t==="recover"){let o=Number(ae(e,"--limit")??100),i=await ht(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
82
+ `).all();s.close();let i=[];for(let c of o){let u=typeof c.conversation_id=="string"?c.conversation_id:"";if(!u)continue;let a=Zr(c.workspace_uris);if(!es(t,a))continue;let d=ft(u);if(yt(d)&&(i.push(await ae({project:t,storage:e,conversationId:u,transcriptPath:d,workspacePaths:a,modelName:typeof c.agent_name=="string"?c.agent_name:void 0,phase:"recover"})),i.length>=n))break}return i}function ce(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function ts(t){let e=we(),n=Ce(Re({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new H(n,t.id,t.name,t.remote??t.name)}async function ns(){let[t="help",...e]=process.argv.slice(2);if(t==="install-hooks"){let o=gt({binary:ce(e,"--bin")});console.log(`\u2705 Agy hooks installed: ${o}`);return}let n=ce(e,"--project")??process.cwd(),r=new q().detect(n),s=ts(r);if(t==="sync"){let o=e[0],i=ce(e,"--transcript");if(!o||!i)throw new Error("Usage: sync <conversation-id> --transcript <path>");let c=await ae({project:r,storage:s,conversationId:o,transcriptPath:i,phase:"recover"});console.log(JSON.stringify(c,null,2));return}if(t==="recover"){let o=Number(ce(e,"--limit")??100),i=await vt(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
83
83
 
84
84
  Commands:
85
85
  install-hooks
86
86
  sync <conversation-id> --transcript <path>
87
87
  recover [--project PATH] [--limit N]
88
- `)}Ur().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});
88
+ `)}ns().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});
@@ -1,8 +1,8 @@
1
- import{existsSync as oe,readFileSync as se}from"node:fs";import{homedir as ie}from"node:os";import{join as ae}from"node:path";function ce(r){let e=r.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 pe(){let r=process.env.TOOLNET_GLOBAL_ENV??ae(ie(),".config","toolnet-memory",".env");if(!oe(r))return;let e=se(r,"utf8");for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let o=n.indexOf("=");if(o<=0)continue;let a=n.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(a)&&process.env[a]===void 0&&(process.env[a]=ce(n.slice(o+1)))}}pe();function v(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function y(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function N(){return{memory:{autoCapture:v(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:v(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:v(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:v(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:y(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:y(process.env.MEMORY_RERANK_TOP,10),finalContext:y(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:y(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:y(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ue}from"node:crypto";import{existsSync as I,mkdirSync as le,readFileSync as de,renameSync as me,writeFileSync as fe}from"node:fs";import{basename as ge,dirname as k,join as x,parse as _,resolve as S}from"node:path";var W=".toolnet",he="project.json";function ye(r){return ue("sha256").update(r).digest("hex").slice(0,16)}function A(r){return x(r,W,he)}function Se(r){return I(A(r))}function je(r,e){let t=S(r),n=_(t).root;for(;;){if(Se(t))return t;if(t===n||e&&t===S(e))break;let o=k(t);if(o===t)break;t=o}return null}function ve(r){let e=S(r),t=_(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(a=>I(x(e,a))))return e;if(e===t)break;let o=k(e);if(o===e)break;e=o}return S(r)}function ke(r){let e;try{e=JSON.parse(de(r,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${r}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:k(k(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:n,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:n,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function C(r,e){let t=x(r,W);le(t,{recursive:!0});let n=A(r),o=`${n}.tmp-${process.pid}`;fe(o,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),me(o,n)}function $(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var w=class{detect(e=process.cwd()){let t=S(e),n=ve(t),a=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>I(x(n,f))),c=je(t,a?n:void 0);if(c){let f=A(c),s=ke(f);return s.rootPath!==c&&(s.rootPath=c,s.updatedAt=new Date().toISOString(),C(c,s)),$(s,c)}let l=new Date().toISOString(),i=ge(n),u={version:1,id:ye(n),name:i,remote:i,rootPath:n,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return C(n,u),$(u,n)}};import{homedir as We}from"node:os";import{join as Be}from"node:path";import{DeleteObjectCommand as we,GetObjectCommand as xe,HeadObjectCommand as be,ListObjectsV2Command as Pe,PutObjectCommand as Oe,S3Client as Ie}from"@aws-sdk/client-s3";import{getSignedUrl as Ae}from"@aws-sdk/s3-request-presigner";var b=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ie({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,t,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Oe({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Ae(this.client,new xe({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new be({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new we({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new Pe({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let a of o.Contents??[])a.Key&&t.push({key:a.Key,size:a.Size,updatedAt:a.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}};import{access as B,mkdir as Me,readFile as Te,readdir as Ee,rm as Re,stat as D,writeFile as Ne}from"node:fs/promises";import{dirname as Ce,join as $e,relative as L,resolve as _e}from"node:path";var j=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return _e(this.root,t)}async put(e,t){let n=this.path(e);await Me(Ce(n),{recursive:!0}),await Ne(n,t)}async get(e){try{return await Te(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await B(this.path(e)),!0}catch{return!1}}async delete(e){await Re(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await B(t)}catch{return n}let o=async c=>{let l=await Ee(c,{withFileTypes:!0});for(let i of l){let u=$e(c,i.name);if(i.isDirectory()){await o(u);continue}let f=await D(u);n.push({key:L(this.root,u),size:f.size,updatedAt:f.mtime.toISOString()})}},a=await D(t);return a.isDirectory()?await o(t):n.push({key:L(this.root,t),size:a.size,updatedAt:a.mtime.toISOString()}),n}};function K(r){let e=r.localRoot??Be(We(),".toolnet-memory","storage");if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new b({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new j(e))}return new j(e)}function De(r){return new Promise(e=>setTimeout(e,r))}async function z(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,o=e.maxDelayMs??2e3,a;for(let c=1;c<=t;c++)try{return await r()}catch(l){if(a=l,c>=t)break;let i=Math.min(o,n*2**(c-1)),u=Math.floor(Math.random()*Math.max(1,i*.2));await De(i+u)}throw a}var Le=new Set(["put","get","getText","delete","list"]);function F(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:Le.has(n)?(...a)=>z(()=>Promise.resolve(o.apply(t,a)),e):o.bind(t)}})}function V(r){let e=r.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 J(r){let e=r.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 t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let o=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:e))}var P=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=V(o??n),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),n=t,o=await this.provider.getText(e);if(o){let c;try{c=JSON.parse(o)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}if(typeof c.id=="string"&&c.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${c.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof c.createdAt=="string"&&(n=c.createdAt)}let a={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:t};await this.provider.put(e,JSON.stringify(a,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=J(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,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{createHash as Ke}from"node:crypto";import{dirname as ze}from"node:path";import{mkdirSync as Fe,readFileSync as on,renameSync as Ve,writeFileSync as Je}from"node:fs";function m(r){return Ke("sha256").update(r).digest("hex")}function h(r,e){Fe(ze(r),{recursive:!0});let t=`${r}.${process.pid}.tmp`;Je(t,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),Ve(t,r)}async function M(r,e){let t=await e.getText(`projects/${r.id}/work/current.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}import{existsSync as U,mkdirSync as He,readFileSync as Ue,statSync as q,writeFileSync as Ye}from"node:fs";import{dirname as Ge,join as Qe}from"node:path";var H=64*1024,Xe=`# ToolNet Project Operating Manual
1
+ import{existsSync as ie,readFileSync as ae}from"node:fs";import{homedir as ce}from"node:os";import{join as ue}from"node:path";function pe(r){let e=r.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 le(){let r=process.env.TOOLNET_GLOBAL_ENV??ue(ce(),".config","toolnet-memory",".env");if(!ie(r))return;let e=ae(r,"utf8");for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let s=n.indexOf("=");if(s<=0)continue;let i=n.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=pe(n.slice(s+1)))}}le();function y(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function S(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function $(){return{memory:{autoCapture:y(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:y(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:y(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:y(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:S(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:S(process.env.MEMORY_RERANK_TOP,10),finalContext:S(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:S(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:y(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:S(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as de}from"node:crypto";import{existsSync as A,mkdirSync as me,readFileSync as fe,renameSync as ge,writeFileSync as he}from"node:fs";import{basename as ye,dirname as b,join as x,parse as W,resolve as j}from"node:path";var B=".toolnet",Se="project.json";function je(r){return de("sha256").update(r).digest("hex").slice(0,16)}function E(r){return x(r,B,Se)}function ke(r){return A(E(r))}function ve(r,e){let t=j(r),n=W(t).root;for(;;){if(ke(t))return t;if(t===n||e&&t===j(e))break;let s=b(t);if(s===t)break;t=s}return null}function be(r){let e=j(r),t=W(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>A(x(e,i))))return e;if(e===t)break;let s=b(e);if(s===e)break;e=s}return j(r)}function we(r){let e;try{e=JSON.parse(fe(r,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${r}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:b(b(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:n,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:n,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function _(r,e){let t=x(r,B);me(t,{recursive:!0});let n=E(r),s=`${n}.tmp-${process.pid}`;he(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ge(s,n)}function K(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var w=class{detect(e=process.cwd()){let t=j(e),n=be(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>A(x(n,f))),c=ve(t,i?n:void 0);if(c){let f=E(c),o=we(f);return o.rootPath!==c&&(o.rootPath=c,o.updatedAt=new Date().toISOString(),_(c,o)),K(o,c)}let l=new Date().toISOString(),a=ye(n),p={version:1,id:je(n),name:a,remote:a,rootPath:n,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return _(n,p),K(p,n)}};import{homedir as Ue}from"node:os";import{join as qe}from"node:path";import{DeleteObjectCommand as xe,GetObjectCommand as Pe,HeadObjectCommand as Oe,ListObjectsV2Command as Ie,PutObjectCommand as Ae,S3Client as Ee}from"@aws-sdk/client-s3";import{getSignedUrl as Te}from"@aws-sdk/s3-request-presigner";var P=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ee({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,t,n="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ae({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let t=await Te(this.client,new Pe({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Oe({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new xe({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let s=await this.client.send(new Ie({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let i of s.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return t}};import{access as D,mkdir as Me,readFile as Re,readdir as Ce,rm as Ne,stat as L,writeFile as $e}from"node:fs/promises";import{dirname as _e,join as Ke,relative as z,resolve as We}from"node:path";var k=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return We(this.root,t)}async put(e,t){let n=this.path(e);await Me(_e(n),{recursive:!0}),await $e(n,t)}async get(e){try{return await Re(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await D(this.path(e)),!0}catch{return!1}}async delete(e){await Ne(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await D(t)}catch{return n}let s=async c=>{let l=await Ce(c,{withFileTypes:!0});for(let a of l){let p=Ke(c,a.name);if(a.isDirectory()){await s(p);continue}let f=await L(p);n.push({key:z(this.root,p),size:f.size,updatedAt:f.mtime.toISOString()})}},i=await L(t);return i.isDirectory()?await s(t):n.push({key:z(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),n}};import{DeleteObjectCommand as Be,GetObjectCommand as De,HeadObjectCommand as Le,ListObjectsV2Command as ze,PutObjectCommand as Ve,S3Client as Fe}from"@aws-sdk/client-s3";import{getSignedUrl as Je}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 Fe({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,t,n="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ve({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let t=await Je(this.client,new De({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`${this.name} download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Le({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new Be({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let s=await this.client.send(new ze({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let i of s.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return t}};function T(r,e){return console.warn(e),new k(r)}function V(r){let e=r.localRoot??qe(Ue(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new v({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new v({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new P({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new k(e)}function He(r){return new Promise(e=>setTimeout(e,r))}async function F(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,s=e.maxDelayMs??2e3,i;for(let c=1;c<=t;c++)try{return await r()}catch(l){if(i=l,c>=t)break;let a=Math.min(s,n*2**(c-1)),p=Math.floor(Math.random()*Math.max(1,a*.2));await He(a+p)}throw i}var Ye=new Set(["put","get","getText","delete","list"]);function J(r,e={}){return new Proxy(r,{get(t,n){let s=Reflect.get(t,n,t);return typeof s!="function"?s:Ye.has(n)?(...i)=>F(()=>Promise.resolve(s.apply(t,i)),e):s.bind(t)}})}function U(r){let e=r.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 q(r){let e=r.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 t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var O=class{constructor(e,t,n,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=U(s??n),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),n=t,s=await this.provider.getText(e);if(s){let c;try{c=JSON.parse(s)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}if(typeof c.id=="string"&&c.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${c.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof c.createdAt=="string"&&(n=c.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=q(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,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{createHash as Ge}from"node:crypto";import{dirname as Qe}from"node:path";import{mkdirSync as Xe,readFileSync as vn,renameSync as Ze,writeFileSync as et}from"node:fs";function m(r){return Ge("sha256").update(r).digest("hex")}function h(r,e){Xe(Qe(r),{recursive:!0});let t=`${r}.${process.pid}.tmp`;et(t,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Ze(t,r)}async function M(r,e){let t=await e.getText(`projects/${r.id}/work/current.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}import{existsSync as G,mkdirSync as rt,readFileSync as nt,statSync as H,writeFileSync as st}from"node:fs";import{dirname as ot,join as it}from"node:path";var Y=64*1024,at=`# ToolNet Project Operating Manual
6
6
 
7
7
  This file contains persistent instructions for AI agents working on this project.
8
8
 
@@ -45,11 +45,11 @@ Things an AI agent should always remember.
45
45
  <!--
46
46
  - [advisory] Prefer small focused files.
47
47
  -->
48
- `;function O(r){return Qe(r.rootPath,".toolnet","PROJECT.md")}function Ze(r){return r.normalize("NFKC").replace(/\s+/g," ").trim()}function et(r){let e=[],t=new Set,n=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,o;for(;o=n.exec(r);){let a=o[1].toLowerCase(),c=Ze(o[2]);if(!c)continue;let l=`${a}:${c.toLowerCase()}`;t.has(l)||(t.add(l),e.push({id:m(l).slice(0,24),mode:a,text:c,source:"manual"}))}return e}function tt(r){let e=O(r);return U(e)||(He(Ge(e),{recursive:!0}),Ye(e,Xe,{encoding:"utf8",mode:384})),e}function T(r,e=!1){let t=e?tt(r):O(r);if(!U(t))return null;if(q(t).size>H)throw new Error(`PROJECT.md exceeds ${H} bytes`);let o=Ue(t,"utf8");return{path:t,content:o,digest:m(o),rules:et(o),bytes:Buffer.byteLength(o,"utf8"),updatedAt:new Date(q(t).mtimeMs).toISOString()}}async function Y(r,e){let t=await e.getText(`projects/${r.id}/work/handoff-latest.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function G(r,e){let t=await e.getText(`projects/${r.id}/work/semantic/current.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}function E(r){if(!r)return 0;let e=Array.from(r).length,t=r.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,t*1.3))}function d(r,e){let t=r.replace(/\s+/g," ").trim();return t.length<=e?t:t.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function rt(r){let e=[],t=!1;for(let n of r.split(/\r?\n/u)){let o=n.trim();if(o.includes("<!--")&&(t=!0),t){o.includes("-->")&&(t=!1);continue}let a=o.toLowerCase();if(!(!o||o.startsWith("#")||o==="```"||a.startsWith("- [enforce]")||a.startsWith("* [enforce]")||a.startsWith("- [advisory]")||a.startsWith("* [advisory]"))&&(o=o.replace(/^[-*]\s+/u,""),o&&e.push(d(o,280)),e.length>=16))break}return e}function nt(r){let e=[],t=[];for(let n of r.split(/\\r?\\n/u)){let o=n.trim(),a=o.toLowerCase(),l=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(u=>a.startsWith(u));if(!l)continue;let i=o.slice(l.length).trim();i&&(l.includes("enforce")?e.push(i):t.push(i))}return{enforce:e,advisory:t}}function ot(r,e){let t=[];for(let n of r){let o=[...t,n].join(`
49
- `);if(E(o)<=e){t.push(n);continue}let a=E(t.join(`
50
- `)),c=Math.max(0,e-a);if(c>=16){let l=Math.floor(c*3.2),i=d(n,l);i&&t.push(i)}break}return t.join(`
51
- `).trim()}async function Q(r){let e=Math.max(256,Math.min(2e3,r.maxTokens??1e3)),t=T(r.project,!1),n=t?.content??"";n||(n=await r.storage.getText(`projects/${r.project.id}/project/manual.md`)??"");let o=nt(n),a=t?t.rules.filter(p=>p.mode==="enforce").map(p=>p.text):o.enforce,c=t?t.rules.filter(p=>p.mode==="advisory").map(p=>p.text):o.advisory,l=n?rt(n):[],i=await M(r.project,r.storage),u=await G(r.project,r.storage),f=await Y(r.project,r.storage),s=[];if(s.push("[TOOLNET PROJECT CONTEXT]"),s.push(`Project: ${r.project.name}`),s.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),n&&s.push(`Full operating manual: ${O(r.project)}`),a.length){s.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let p of a.slice(0,24))s.push(`- [ENFORCE] ${d(p,240)}`)}if(c.length){s.push("","PROJECT PREFERENCES");for(let p of c.slice(0,10))s.push(`- ${d(p,220)}`)}if(u&&(u.mission&&s.push("","MISSION",d(u.mission.value,420)),u.activeObjective&&s.push("","CURRENT OBJECTIVE",d(u.activeObjective.value,420)),u.why&&s.push("","WHY THIS WORK MATTERS",d(u.why.value,420)),u.desiredOutcome&&s.push("","DESIRED OUTCOME",d(u.desiredOutcome.value,420)),u.planRationale&&s.push("","WHY THIS APPROACH",d(u.planRationale.value,420))),i){if(s.push("","ACTIVE WORK"),i.goal&&s.push(`Goal: ${d(i.goal,320)}`),i.plan&&s.push(`Plan: ${d(i.plan,320)}`),s.push(`Progress: phases ${i.progress.phasesCompleted}/${i.progress.phasesTotal}; tasks ${i.progress.tasksCompleted}/${i.progress.tasksTotal}; blocked ${i.progress.blocked}`),i.currentPhase&&s.push(`Current phase: ${i.currentPhase.title} [${i.currentPhase.status}]`),i.currentPhase&&u){let p=u.phases.find(g=>g.order===i.currentPhase?.order);p&&(p.objective&&s.push(`Phase objective: ${d(p.objective.value,340)}`),p.why?s.push(`Why this phase: ${d(p.why.value,340)}`):s.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),p.deliverable&&s.push(`Deliverable: ${d(p.deliverable.value,340)}`),p.dependencies.length&&s.push(`Depends on: ${p.dependencies.slice(0,4).map(g=>d(g.value,180)).join("; ")}`),p.acceptanceCriteria.length&&(s.push("","DEFINITION OF DONE"),p.acceptanceCriteria.slice(0,6).forEach(g=>{s.push(`- ${d(g.value,260)}`)})),p.openQuestions.length&&(s.push("","OPEN QUESTIONS FOR CURRENT PHASE"),p.openQuestions.slice(0,4).forEach(g=>{s.push(`- ${d(g.value,260)}`)})))}i.currentTask&&s.push(`Current task: ${i.currentTask.title} [${i.currentTask.status}]`),i.nextActions.length&&(s.push("","NEXT ACTIONS"),i.nextActions.slice(0,6).forEach((p,g)=>{s.push(`${g+1}. ${d(p,260)}`)})),i.blockers.length&&(s.push("","BLOCKERS"),i.blockers.slice(0,5).forEach(p=>{s.push(`- ${d(p,260)}`)})),i.warnings.length&&(s.push("","ATTENTION"),i.warnings.slice(-5).forEach(p=>{s.push(`- ${d(p,260)}`)})),i.decisions.length&&(s.push("","RECENT DECISIONS"),i.decisions.slice(-5).forEach(p=>{s.push(`- ${d(p,260)}`)})),i.lastSession&&s.push("",`Last work session: ${i.lastSession.agent} / ${i.lastSession.nativeSessionId}`)}if(u&&u.openQuestions.length&&(s.push("","UNRESOLVED QUESTIONS"),u.openQuestions.slice(0,5).forEach(p=>{s.push(`- ${d(p.value,260)}`)})),f&&s.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),l.length){s.push("","OPERATING NOTES");for(let p of l)s.push(`- ${p}`)}s.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let R=ot(s,e);return{version:1,projectId:r.project.id,projectName:r.project.name,text:R,estimatedTokens:E(R),maxTokens:e,hasManual:!!n,hasWorkState:!!i,hasHandoff:!!f,generatedAt:new Date().toISOString()}}import{existsSync as st,mkdirSync as it,readFileSync as at,writeFileSync as ct}from"node:fs";import{dirname as pt,join as X}from"node:path";function Z(r){return X(r.rootPath,".toolnet","context","startup.md")}function ut(r){return X(r.rootPath,".toolnet","context","startup.json")}function ee(r,e){let t=Z(r);it(pt(t),{recursive:!0}),ct(t,e.text.endsWith(`
48
+ `;function I(r){return it(r.rootPath,".toolnet","PROJECT.md")}function ct(r){return r.normalize("NFKC").replace(/\s+/g," ").trim()}function ut(r){let e=[],t=new Set,n=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=n.exec(r);){let i=s[1].toLowerCase(),c=ct(s[2]);if(!c)continue;let l=`${i}:${c.toLowerCase()}`;t.has(l)||(t.add(l),e.push({id:m(l).slice(0,24),mode:i,text:c,source:"manual"}))}return e}function pt(r){let e=I(r);return G(e)||(rt(ot(e),{recursive:!0}),st(e,at,{encoding:"utf8",mode:384})),e}function R(r,e=!1){let t=e?pt(r):I(r);if(!G(t))return null;if(H(t).size>Y)throw new Error(`PROJECT.md exceeds ${Y} bytes`);let s=nt(t,"utf8");return{path:t,content:s,digest:m(s),rules:ut(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(H(t).mtimeMs).toISOString()}}async function Q(r,e){let t=await e.getText(`projects/${r.id}/work/handoff-latest.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function X(r,e){let t=await e.getText(`projects/${r.id}/work/semantic/current.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}function C(r){if(!r)return 0;let e=Array.from(r).length,t=r.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,t*1.3))}function d(r,e){let t=r.replace(/\s+/g," ").trim();return t.length<=e?t:t.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function lt(r){let e=[],t=!1;for(let n of r.split(/\r?\n/u)){let s=n.trim();if(s.includes("<!--")&&(t=!0),t){s.includes("-->")&&(t=!1);continue}let i=s.toLowerCase();if(!(!s||s.startsWith("#")||s==="```"||i.startsWith("- [enforce]")||i.startsWith("* [enforce]")||i.startsWith("- [advisory]")||i.startsWith("* [advisory]"))&&(s=s.replace(/^[-*]\s+/u,""),s&&e.push(d(s,280)),e.length>=16))break}return e}function dt(r){let e=[],t=[];for(let n of r.split(/\\r?\\n/u)){let s=n.trim(),i=s.toLowerCase(),l=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(p=>i.startsWith(p));if(!l)continue;let a=s.slice(l.length).trim();a&&(l.includes("enforce")?e.push(a):t.push(a))}return{enforce:e,advisory:t}}function mt(r,e){let t=[];for(let n of r){let s=[...t,n].join(`
49
+ `);if(C(s)<=e){t.push(n);continue}let i=C(t.join(`
50
+ `)),c=Math.max(0,e-i);if(c>=16){let l=Math.floor(c*3.2),a=d(n,l);a&&t.push(a)}break}return t.join(`
51
+ `).trim()}async function Z(r){let e=Math.max(256,Math.min(2e3,r.maxTokens??1e3)),t=R(r.project,!1),n=t?.content??"";n||(n=await r.storage.getText(`projects/${r.project.id}/project/manual.md`)??"");let s=dt(n),i=t?t.rules.filter(u=>u.mode==="enforce").map(u=>u.text):s.enforce,c=t?t.rules.filter(u=>u.mode==="advisory").map(u=>u.text):s.advisory,l=n?lt(n):[],a=await M(r.project,r.storage),p=await X(r.project,r.storage),f=await Q(r.project,r.storage),o=[];if(o.push("[TOOLNET PROJECT CONTEXT]"),o.push(`Project: ${r.project.name}`),o.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),n&&o.push(`Full operating manual: ${I(r.project)}`),i.length){o.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let u of i.slice(0,24))o.push(`- [ENFORCE] ${d(u,240)}`)}if(c.length){o.push("","PROJECT PREFERENCES");for(let u of c.slice(0,10))o.push(`- ${d(u,220)}`)}if(p&&(p.mission&&o.push("","MISSION",d(p.mission.value,420)),p.activeObjective&&o.push("","CURRENT OBJECTIVE",d(p.activeObjective.value,420)),p.why&&o.push("","WHY THIS WORK MATTERS",d(p.why.value,420)),p.desiredOutcome&&o.push("","DESIRED OUTCOME",d(p.desiredOutcome.value,420)),p.planRationale&&o.push("","WHY THIS APPROACH",d(p.planRationale.value,420))),a){if(o.push("","ACTIVE WORK"),a.goal&&o.push(`Goal: ${d(a.goal,320)}`),a.plan&&o.push(`Plan: ${d(a.plan,320)}`),o.push(`Progress: phases ${a.progress.phasesCompleted}/${a.progress.phasesTotal}; tasks ${a.progress.tasksCompleted}/${a.progress.tasksTotal}; blocked ${a.progress.blocked}`),a.currentPhase&&o.push(`Current phase: ${a.currentPhase.title} [${a.currentPhase.status}]`),a.currentPhase&&p){let u=p.phases.find(g=>g.order===a.currentPhase?.order);u&&(u.objective&&o.push(`Phase objective: ${d(u.objective.value,340)}`),u.why?o.push(`Why this phase: ${d(u.why.value,340)}`):o.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),u.deliverable&&o.push(`Deliverable: ${d(u.deliverable.value,340)}`),u.dependencies.length&&o.push(`Depends on: ${u.dependencies.slice(0,4).map(g=>d(g.value,180)).join("; ")}`),u.acceptanceCriteria.length&&(o.push("","DEFINITION OF DONE"),u.acceptanceCriteria.slice(0,6).forEach(g=>{o.push(`- ${d(g.value,260)}`)})),u.openQuestions.length&&(o.push("","OPEN QUESTIONS FOR CURRENT PHASE"),u.openQuestions.slice(0,4).forEach(g=>{o.push(`- ${d(g.value,260)}`)})))}a.currentTask&&o.push(`Current task: ${a.currentTask.title} [${a.currentTask.status}]`),a.nextActions.length&&(o.push("","NEXT ACTIONS"),a.nextActions.slice(0,6).forEach((u,g)=>{o.push(`${g+1}. ${d(u,260)}`)})),a.blockers.length&&(o.push("","BLOCKERS"),a.blockers.slice(0,5).forEach(u=>{o.push(`- ${d(u,260)}`)})),a.warnings.length&&(o.push("","ATTENTION"),a.warnings.slice(-5).forEach(u=>{o.push(`- ${d(u,260)}`)})),a.decisions.length&&(o.push("","RECENT DECISIONS"),a.decisions.slice(-5).forEach(u=>{o.push(`- ${d(u,260)}`)})),a.lastSession&&o.push("",`Last work session: ${a.lastSession.agent} / ${a.lastSession.nativeSessionId}`)}if(p&&p.openQuestions.length&&(o.push("","UNRESOLVED QUESTIONS"),p.openQuestions.slice(0,5).forEach(u=>{o.push(`- ${d(u.value,260)}`)})),f&&o.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),l.length){o.push("","OPERATING NOTES");for(let u of l)o.push(`- ${u}`)}o.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let N=mt(o,e);return{version:1,projectId:r.project.id,projectName:r.project.name,text:N,estimatedTokens:C(N),maxTokens:e,hasManual:!!n,hasWorkState:!!a,hasHandoff:!!f,generatedAt:new Date().toISOString()}}import{existsSync as ft,mkdirSync as gt,readFileSync as ht,writeFileSync as yt}from"node:fs";import{dirname as St,join as ee}from"node:path";function te(r){return ee(r.rootPath,".toolnet","context","startup.md")}function jt(r){return ee(r.rootPath,".toolnet","context","startup.json")}function re(r,e){let t=te(r);gt(St(t),{recursive:!0}),yt(t,e.text.endsWith(`
52
52
  `)?e.text:e.text+`
53
- `,{encoding:"utf8",mode:384}),h(ut(r),e)}async function lt(r,e,t=900){let n=await Q({project:r,storage:e,maxTokens:t}),o={version:1,projectId:r.id,projectName:r.name,text:n.text,digest:m(n.text),estimatedTokens:n.estimatedTokens,generatedAt:new Date().toISOString()};return ee(r,o),await e.put(`projects/${r.id}/context/startup.md`,o.text+`
54
- `,"text/markdown"),await e.put(`projects/${r.id}/context/startup.json`,JSON.stringify(o,null,2)+`
55
- `,"application/json"),o}async function te(r,e,t=900){try{let o=await e.getText(`projects/${r.id}/context/startup.md`);if(o&&o.trim()){let a=o.trim(),c={version:1,projectId:r.id,projectName:r.name,text:a,digest:m(a),estimatedTokens:Math.ceil(a.length/3.5),generatedAt:new Date().toISOString()};return ee(r,c),c}}catch{}let n=Z(r);if(st(n))try{let o=at(n,"utf8").trim();if(o)return{version:1,projectId:r.id,projectName:r.name,text:o,digest:m(o),estimatedTokens:Math.ceil(o.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await lt(r,e,t)}catch{return null}}async function re(r){let e=await te(r.project,r.storage,900);return e?.text?{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:e.text}}:{}}import{existsSync as dt}from"node:fs";import{dirname as mt,join as ft,parse as gt,resolve as ht}from"node:path";function ne(r){let e=ht(r),t=gt(e).root;for(;;){if(dt(ft(e,".toolnet","project.json")))return new w().detect(e);if(e===t)break;let n=mt(e);if(n===e)break;e=n}return null}async function yt(){let r="";for await(let e of process.stdin)r+=e.toString();if(!r.trim())return{};try{return JSON.parse(r)}catch{return{}}}async function St(){let r=await yt();if(r.hook_event_name!=="SessionStart"){process.stdout.write("{}");return}let e=typeof r.cwd=="string"?r.cwd:"";if(!e){process.stdout.write("{}");return}let t=ne(e);if(!t){process.stdout.write("{}");return}try{let n=N(),o=F(K({provider:n.storage.provider,huggingface:n.storage.huggingface,localRoot:n.storage.localRoot}),{attempts:2}),a=new P(o,t.id,t.name,t.remote??t.name),c=await re({project:t,storage:a});process.stdout.write(JSON.stringify(c))}catch{process.stdout.write("{}")}}St().catch(()=>{process.stdout.write("{}"),process.exitCode=0});
53
+ `,{encoding:"utf8",mode:384}),h(jt(r),e)}async function kt(r,e,t=900){let n=await Z({project:r,storage:e,maxTokens:t}),s={version:1,projectId:r.id,projectName:r.name,text:n.text,digest:m(n.text),estimatedTokens:n.estimatedTokens,generatedAt:new Date().toISOString()};return re(r,s),await e.put(`projects/${r.id}/context/startup.md`,s.text+`
54
+ `,"text/markdown"),await e.put(`projects/${r.id}/context/startup.json`,JSON.stringify(s,null,2)+`
55
+ `,"application/json"),s}async function ne(r,e,t=900){try{let s=await e.getText(`projects/${r.id}/context/startup.md`);if(s&&s.trim()){let i=s.trim(),c={version:1,projectId:r.id,projectName:r.name,text:i,digest:m(i),estimatedTokens:Math.ceil(i.length/3.5),generatedAt:new Date().toISOString()};return re(r,c),c}}catch{}let n=te(r);if(ft(n))try{let s=ht(n,"utf8").trim();if(s)return{version:1,projectId:r.id,projectName:r.name,text:s,digest:m(s),estimatedTokens:Math.ceil(s.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await kt(r,e,t)}catch{return null}}async function se(r){let e=await ne(r.project,r.storage,900);return e?.text?{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:e.text}}:{}}import{existsSync as vt}from"node:fs";import{dirname as bt,join as wt,parse as xt,resolve as Pt}from"node:path";function oe(r){let e=Pt(r),t=xt(e).root;for(;;){if(vt(wt(e,".toolnet","project.json")))return new w().detect(e);if(e===t)break;let n=bt(e);if(n===e)break;e=n}return null}async function Ot(){let r="";for await(let e of process.stdin)r+=e.toString();if(!r.trim())return{};try{return JSON.parse(r)}catch{return{}}}async function It(){let r=await Ot();if(r.hook_event_name!=="SessionStart"){process.stdout.write("{}");return}let e=typeof r.cwd=="string"?r.cwd:"";if(!e){process.stdout.write("{}");return}let t=oe(e);if(!t){process.stdout.write("{}");return}try{let n=$(),s=J(V({provider:n.storage.provider,huggingface:n.storage.huggingface,localRoot:n.storage.localRoot}),{attempts:2}),i=new O(s,t.id,t.name,t.remote??t.name),c=await se({project:t,storage:i});process.stdout.write(JSON.stringify(c))}catch{process.stdout.write("{}")}}It().catch(()=>{process.stdout.write("{}"),process.exitCode=0});