toolnet-memory 0.2.10 → 0.2.11

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 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)+`
1
+ import{existsSync as jt,readFileSync as xt}from"node:fs";import{homedir as It}from"node:os";import{join as Pt}from"node:path";function Ot(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 At(){let t=process.env.TOOLNET_GLOBAL_ENV??Pt(It(),".config","toolnet-memory",".env");if(!jt(t))return;let e=xt(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]=Ot(r.slice(s+1)))}}At();function L(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function K(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function xe(){return{memory:{autoCapture:L(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:L(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:L(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:L(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:K(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:K(process.env.MEMORY_RERANK_TOP,10),finalContext:K(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:K(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:L(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:K(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Et}from"node:crypto";import{existsSync as le,mkdirSync as Rt,readFileSync as Ct,renameSync as Mt,writeFileSync as Tt}from"node:fs";import{basename as Nt,dirname as B,join as J,parse as Oe,resolve as z}from"node:path";var Ae=".toolnet",_t="project.json";function $t(t){return Et("sha256").update(t).digest("hex").slice(0,16)}function pe(t){return J(t,Ae,_t)}function Lt(t){return le(pe(t))}function Kt(t,e){let n=z(t),r=Oe(n).root;for(;;){if(Lt(n))return n;if(n===r||e&&n===z(e))break;let s=B(n);if(s===n)break;n=s}return null}function zt(t){let e=z(t),n=Oe(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>le(J(e,o))))return e;if(e===n)break;let s=B(e);if(s===e)break;e=s}return z(t)}function Wt(t){let e;try{e=JSON.parse(Ct(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:B(B(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 Ie(t,e){let n=J(t,Ae);Rt(n,{recursive:!0});let r=pe(t),s=`${r}.tmp-${process.pid}`;Tt(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Mt(s,r)}function Pe(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=zt(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>le(J(r,d))),i=Kt(n,o?r:void 0);if(i){let d=pe(i),l=Wt(d);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),Ie(i,l)),Pe(l,i)}let c=new Date().toISOString(),u=Nt(r),a={version:1,id:$t(r),name:u,remote:u,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return Ie(r,a),Pe(a,r)}};var Ft=[{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 Ft){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 pn}from"node:os";import{join as dn}from"node:path";import{DeleteObjectCommand as Dt,GetObjectCommand as Bt,HeadObjectCommand as qt,ListObjectsV2Command as Jt,PutObjectCommand as Vt,S3Client as Ut}from"@aws-sdk/client-s3";import{getSignedUrl as Ht}from"@aws-sdk/s3-request-presigner";var U=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ut({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 Vt({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Ht(this.client,new Bt({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 qt({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 Dt({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Jt({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 Ee,mkdir as Yt,readFile as Gt,readdir as Xt,rm as Qt,stat as Re,writeFile as Zt}from"node:fs/promises";import{dirname as en,join as tn,relative as Ce,resolve as nn}from"node:path";var F=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return nn(this.root,n)}async put(e,n){let r=this.path(e);await Yt(en(r),{recursive:!0}),await Zt(r,n)}async get(e){try{return await Gt(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 Ee(this.path(e)),!0}catch{return!1}}async delete(e){await Qt(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ee(n)}catch{return r}let s=async i=>{let c=await Xt(i,{withFileTypes:!0});for(let u of c){let a=tn(i,u.name);if(u.isDirectory()){await s(a);continue}let d=await Re(a);r.push({key:Ce(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await Re(n);return o.isDirectory()?await s(n):r.push({key:Ce(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as rn,GetObjectCommand as sn,HeadObjectCommand as on,ListObjectsV2Command as an,PutObjectCommand as cn,S3Client as un}from"@aws-sdk/client-s3";import{getSignedUrl as ln}from"@aws-sdk/s3-request-presigner";var D=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new un({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 cn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await ln(this.client,new sn({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 on({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new rn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new an({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 de(t,e){return console.warn(e),new F(t)}function Me(t){let e=t.localRoot??dn(pn(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new D({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):de(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 D({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):de(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}):de(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new F(e)}function fn(t){return new Promise(e=>setTimeout(e,t))}async function Te(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 fn(u+a)}throw o}var mn=new Set(["put","get","getText","delete","list"]);function Ne(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:mn.has(r)?(...o)=>Te(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function _e(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function $e(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=_e(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=$e(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 ke}from"node:os";import{join as yt,resolve as Yr}from"node:path";import{join as kn}from"node:path";import{createHash as gn}from"node:crypto";import{dirname as yn}from"node:path";import{mkdirSync as hn,readFileSync as Sn,renameSync as vn,writeFileSync as bn}from"node:fs";function v(t){return gn("sha256").update(t).digest("hex")}function fe(t){if(Array.isArray(t))return t.map(fe);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=fe(e[r]);return n}return t}function Le(t){return JSON.stringify(fe(t))}function Ke(t){try{return JSON.parse(Sn(t,"utf8"))}catch{return null}}function O(t,e){hn(yn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;bn(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),vn(n,t)}function ze(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=v(n).slice(0,12);if(!r||r==="."||r==="..")return`${e}--${s}`;let o=r.slice(0,100);return o===n&&n.length<=100?o:`${o.slice(0,85)}--${s}`}function We(t,e,n){let r=e.trim(),s=n.trim();if(!r)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=ze(r.toLowerCase(),"agent"),i=ze(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:r,nativeSessionId:s,sessionKey:`${r}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:kn(t.rootPath,".toolnet","sessions",o,i)}}function Fe(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],R=m.map(M=>JSON.stringify(M)).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(C=>JSON.stringify(C)).join(`
8
8
  `)+`
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(`
9
+ `,M=v(R).slice(0,16),P=[e.remotePrefix,"events",`${Fe(y.sequence)}-${Fe(b.sequence)}-${M}.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],l=o?.status??"active";d?.type==="session_end"||d?.type==="session_idle"?l="idle":d?.type==="error"?l="error":n.length>0&&(l="active");let f=new Date().toISOString(),h=n[0],S={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:l,createdAt:o?.createdAt??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:l}}};import{closeSync as me,existsSync as wn,fsyncSync as jn,mkdirSync as xn,openSync as ge,readSync as In,rmSync as De,statSync as Be,writeSync as Pn}from"node:fs";import{join as ye}from"node:path";var On=12e4,An=80,En=2e3;function Rn(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var G=class{constructor(e){this.identity=e;xn(e.localDirectory,{recursive:!0}),this.eventsFile=ye(e.localDirectory,"events.jsonl"),this.stateFile=ye(e.localDirectory,"state.json"),this.lockFile=ye(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 Ke(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){O(this.stateFile,e)}acquireLock(){for(let e=0;e<An;e+=1)try{return ge(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-Be(this.lockFile).mtimeMs>On){De(this.lockFile,{force:!0});continue}}catch{}Rn(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{me(n),De(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let l of e){let f=l.timestamp??new Date().toISOString(),h=l.data??{},S=l.provenance?.rawDigest??v(Le(h)),g=l.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,l.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,l.type,f,S].join("|"),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:l.type,timestamp:f,data:h,provenance:{...l.provenance,rawDigest:S}};l.role!==void 0&&(y.role=l.role),l.sourceEventId!==void 0&&(y.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(y.sourceSequence=l.sourceSequence),o.push(y),r.add(m)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
10
10
  `)+`
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(`
11
+ `,c=ge(this.eventsFile,"a",384);try{Pn(c,i,null,"utf8"),jn(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(-En);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:d}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!wn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=Be(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=ge(this.eventsFile,"r");try{In(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 Vn,existsSync as Un,openSync as Hn,readSync as Yn,statSync as Gn}from"node:fs";function qe(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 He=[/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],Cn=[/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],Mn=[/\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],Tn=[/\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],Nn=[/đã 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],Je=[/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],_n=[/\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],$n=[/đườ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],Ln=[/\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],Ve=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Kn=new Set(["payload","data","content","message","messages","parts","summary"]);function j(t,e){return e.some(n=>n.test(t))}function Ye(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function zn(t){return Ye(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Wn(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 he(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||Ve.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))he(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(Ve.has(s)||Kn.has(s))&&he(o,s,n,r+1)}}function Fn(t){let e=[];he(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=Ye(o);if(Wn(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function Ue(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Dn(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,He)?{kind:"rule",confidence:.98}:r&&j(t,Cn)?{kind:"rule",confidence:.92}:j(t,Mn)?{kind:j(t,Je)?"architecture":"decision",confidence:r?.93:.86}:r&&j(t,Tn)?{kind:"todo",confidence:.87}:j(t,Je)&&j(t,_n)?{kind:"architecture",confidence:r?.88:.82}:s&&j(t,Nn)?{kind:"fix",confidence:.8}:r&&j(t,$n)&&j(t,Ln)?{kind:"context",confidence:.79}:null}function Bn(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function qn(t,e,n){return t==="rule"&&j(n,He)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":qe(e,n)}function Ge(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=Ue(o);i&&c&&s.set(i,c)}for(let o of e){let i=Ue(o),c=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&c&&(i=s.get(c)??"");for(let u of Fn(o)){let a=Dn(u,i,o);if(!a||a.confidence<.75)continue;let d=Bn(a.kind),l=zn(u),f=v([t.projectId,a.kind,l].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:qn(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 Xe(t){return String(t).padStart(12,"0")}function Jn(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=[Jn(e),"batches",`${Xe(s)}-${Xe(o)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,c,"application/json"),a}};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(`
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 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(`
15
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}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=Xn(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Ge(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 sr,existsSync as or,openSync as ir,readSync as ar,statSync as cr}from"node:fs";var Qn=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function N(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ze(t){return N(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))(Qn.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 Qe(t){let e=N(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function k(t,e,n,r,s={}){let o=N(r),i=s.key??Ze(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 Zn(t,e,n){let r=N(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(k(t,e,"goal",i[1],{confidence:.97}));let c=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);c?.[1]&&s.push(k(t,e,"plan",c[1],{confidence:.95}));let u=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=u.exec(r));){let f=Number(a[1]),h=N(a[2]??""),S=h&&!Qe(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 l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let f=l[1]?Number(l[1]):void 0,h=N(l[2]),S=Qe(h);s.push(k(t,e,"task",S&&f!==void 0?`TODO ${f}`:h,{key:f!==void 0?`task:${f}`:Ze(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 et(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(k(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];T(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=[];T(i.data,u);for(let a of u)s(k(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 Zn(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 tt(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,`${tt(r)}-${tt(s)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as nt}from"node:path";import{mkdirSync as er}from"node:fs";function tr(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=tr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function nr(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 rt(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&&nr(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 rr(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 rr(t,e)).flatMap(p=>p.observations).sort((p,w)=>{let we=p.occurredAt.localeCompare(w.occurredAt);if(we!==0)return we;let je=p.sequence-w.sequence;return je!==0?je:p.id.localeCompare(w.id)}),s=new Map,o=new Map,i,c,u,a=[],d=[],l=[],f=[],h=[],S=[];for(let p of r)switch(p.kind){case"goal":i=p.text;break;case"plan":c=p.text;break;case"phase":s.set(p.key,rt(s.get(p.key),p));break;case"task":o.set(p.key,rt(o.get(p.key),p));break;case"decision":a.push(p.text);break;case"blocker":d.push(p.text);break;case"warning":l.push(p.text);break;case"next_action":f.push(p.text);break;case"file":h.push(p.text);break;case"test":S.push(p.text);break;case"session":u={agent:p.agent,nativeSessionId:p.nativeSessionId,sessionKey:p.sessionKey,updatedAt:p.occurredAt};break}let g=Array.from(s.values()).sort((p,w)=>(p.order??Number.MAX_SAFE_INTEGER)-(w.order??Number.MAX_SAFE_INTEGER)),m=Array.from(o.values()).sort((p,w)=>(p.order??Number.MAX_SAFE_INTEGER)-(w.order??Number.MAX_SAFE_INTEGER)),y=g.find(p=>p.status==="in_progress")??g.find(p=>p.status==="blocked")??g.find(p=>p.status==="pending"),b=m.find(p=>p.status==="in_progress")??m.find(p=>p.status==="blocked")??m.find(p=>p.status==="pending"),R=_([...f,...b?[b.title]:[],...!b&&y?[y.title]:[],...m.filter(p=>p.status==="pending").slice(0,5).map(p=>p.title)],8),M=_([...d,...g.filter(p=>p.status==="blocked").map(p=>p.title),...m.filter(p=>p.status==="blocked").map(p=>p.title)],20),P={version:1,projectId:t.id,projectName:t.name,goal:i,plan:c,phases:g,tasks:m,decisions:_(a,20),blockers:M,warnings:_(l,20),nextActions:R,filesTouched:_(h,30),tests:_(S,20),currentPhase:y,currentTask:b,progress:{phasesTotal:g.length,phasesCompleted:g.filter(p=>p.status==="completed").length,tasksTotal:m.length,tasksCompleted:m.filter(p=>p.status==="completed").length,blocked:g.filter(p=>p.status==="blocked").length+m.filter(p=>p.status==="blocked").length},lastSession:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},C=nt(t.rootPath,".toolnet","work");return er(C,{recursive:!0}),O(nt(C,"current.json"),P),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(P,null,2)+`
17
+ `,"application/json"),P}async function st(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 ur(t,e){if(!or(t))return{events:[],nextOffset:e};let n=cr(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=ir(t,"r");try{ar(i,o,0,s,r)}finally{sr(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 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(`
19
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}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=ur(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=et(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 Sr,existsSync as vr,openSync as br,readSync as kr,statSync as wr}from"node:fs";var lr=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 Se(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))Se(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(lr.has(r)||["data","payload","parts","messages"].includes(r))&&Se(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 pr(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function dr(t){return $(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function ot(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Se(o.data,i);for(let c of i){let u={type:"project"},a=null;for(let d of c.split(/\r?\n/u)){let l=$(d);if(!l){a=null;continue}let f=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let w=Number(f[1]);u={type:"phase",key:`phase:${w}`,order:w,title:$(f[2]??"")},a=null;continue}let h=l.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(l,["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(l,["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(l,["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(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(y){s(x(t,o,"desired_outcome",y,{type:"project"},.98)),a=null;continue}let b=I(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(b){s(x(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let R=I(l,["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 M=I(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(M){s(x(t,o,"acceptance_criterion",M,u,.98)),a="acceptance_criterion";continue}let P=I(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(P){s(x(t,o,"dependency",P,u,.97)),a="dependency";continue}let C=I(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(C){s(x(t,o,"open_question",C,u,.95)),a="open_question";continue}let p=I(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(p){s(x(t,o,"constraint",p,u,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){a="constraint";continue}if(a&&pr(d)){s(x(t,o,a,dr(d),u,.96));continue}a=null}}}return n}function it(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,`${it(r)}-${it(s)}-${i}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,JSON.stringify(o,null,2)+`
20
+ `,"application/json"),c}};import{mkdirSync as fr}from"node:fs";import{join as at}from"node:path";function mr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function gr(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 gr(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 yr(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 hr(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function ct(t,e){let r=(await yr(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=[],l=[],f=[];for(let g of r){let m=mr(g);if(g.scope==="phase"&&g.scopeKey){let y=a.get(g.scopeKey)??hr(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":l.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(l,20),notes:E(f,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=at(t.rootPath,".toolnet","work");return fr(S,{recursive:!0}),O(at(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 jr(t,e){if(!vr(t))return{events:[],nextOffset:e};let n=wr(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=br(t,"r");try{kr(o,s,0,s.length,r)}finally{Sr(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 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
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=jr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=ot(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ct(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 Tr}from"node:fs";import{join as ve}from"node:path";import{existsSync as pt,mkdirSync as xr,readFileSync as Ir,statSync as ut,writeFileSync as Pr}from"node:fs";import{dirname as Or,join as Ar}from"node:path";var lt=64*1024,Er=`# 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 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)+`
66
+ `;function dt(t){return Ar(t.rootPath,".toolnet","PROJECT.md")}function Rr(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Cr(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=Rr(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 Mr(t){let e=dt(t);return pt(e)||(xr(Or(e),{recursive:!0}),Pr(e,Er,{encoding:"utf8",mode:384})),e}function ft(t,e=!1){let n=e?Mr(t):dt(t);if(!pt(n))return null;if(ut(n).size>lt)throw new Error(`PROJECT.md exceeds ${lt} bytes`);let s=Ir(n,"utf8");return{path:n,content:s,digest:v(s),rules:Cr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(ut(n).mtimeMs).toISOString()}}function Nr(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 _r(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 st(this.options.project,this.options.storage);if(r||(r=await te(this.options.project,this.options.storage)),!_r(r))return null;let s=ft(this.options.project,!1),o=s?s.rules.filter(f=>f.mode==="enforce").map(f=>f.text):[],i=v(JSON.stringify(Nr(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=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
- `);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(`
68
+ `,"application/json");let l=ve(this.options.project.rootPath,".toolnet","work","handoffs");return Tr(l,{recursive:!0}),O(ve(l,`${c}.json`),a),O(ve(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=We(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 $r,openSync as Lr,closeSync as Kr,readSync as zr,statSync as Wr}from"node:fs";function Fr(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 Dr(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 mt(t,e={offset:0}){if(!$r(t))return{events:[],nextOffset:e.offset,reset:!1};let n=Wr(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=Lr(t,"r");try{zr(c,i,0,o,s)}finally{Kr(c)}let u=i.toString("utf8"),a=u.lastIndexOf(`
69
+ `);if(a<0)return{events:[],nextOffset:s,reset:r};let d=u.slice(0,a+1),l=Buffer.byteLength(d,"utf8"),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: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(`
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:Fr(b),timestamp:Dr(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+l,reset:r}}var Br=[/^<SYSTEM MESSAGE>/i,/^<EPHEMERAL MESSAGE>/i,/^<system>/i,/^<ephemeral>/i,/^ManageTask:/i,/^Task \d+ status:/i,/^Task \d+ killed/i,/^Task \d+ loading/i,/^Thought for \d+ tokens/i,/^Prioritizing Tool Usage/i,/^Tool call:/i,/^Tool response:/i,/^npm notice/i,/^npm WARN/i,/^added \d+ packages/i,/^removed \d+ packages/i,/^up to date/i,/^\d+ packages are looking for funding/i,/^run `npm fund` for details/i,/^[\d.]+%/,/^\[={10,}\]/,/^Loading\.\.\./i,/^Processing\.\.\./i,/^bash-\d+\.\d+\$/,/^\$ /,/^\s*$/],qr=[/api[_-]?key[:\s=]+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/secret[:\s=]+[^\s]+/gi,/password[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/authorization:\s*[^\s]+/gi],Jr=["decision","decided","rule","convention","architecture","pattern","fixed","resolved","implemented","created","updated","deleted","deployed","blocker","blocked","issue","bug","error","next","todo","action","requirement","must","should","important"];function Vr(t){let e=t.toLowerCase();return Jr.some(n=>e.includes(n))}function Ur(t){if(!t.trim())return!0;for(let e of Br)if(e.test(t))return!0;return Vr(t),!1}function Hr(t){let e=t;for(let n of qr)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function be(t){let e=t.trim();return e?Ur(e)?{content:"",filtered:!0,reason:"noise"}:{content:Hr(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function ae(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=be(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=ae(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=be(s);return o.filtered?null:o.content}return s&&typeof s=="object"?ae(s):s}).filter(s=>s!==null):e[n]=r;return e}function gt(t){let e=typeof t.type=="string"?t.type.toLowerCase():"";if(e.includes("system")||e.includes("ephemeral")||e==="tool_call"&&!t.result)return!0;if(t.data&&typeof t.data=="object"){let n=t.data,r=typeof n.content=="string"?n.content:"";if(r&&be(r).filtered)return!0}return!1}function Gr(t){return t==="~"?ke():t.startsWith("~/")?yt(ke(),t.slice(2)):t}async function ce(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let n=Yr(Gr(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=mt(n,{offset:Number.isFinite(i)?i:0}),u=[];s.lastSequence===0&&u.push({type:"session_start",sourceEventId:`agy:${e}:start`,data:{workspacePaths:t.workspacePaths??[],transcriptPath:n,modelName:t.modelName},provenance:{source:"antigravity-hook",sourcePath:n}}),c.reset&&u.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${c.nextOffset}`,data:{event:"transcript_reset",transcriptPath:n},provenance:{source:"agy-transcript",sourcePath:n}});let a=c.events.filter(f=>!gt(f.data)).map(f=>({...f,data:ae(f.data)}));u.push(...a),t.phase==="stop"&&(t.error&&u.push({type:"error",sourceEventId:["agy",e,"stop-error",t.terminationReason??"",c.nextOffset].join(":"),data:{error:t.error,terminationReason:t.terminationReason,fullyIdle:t.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),t.fullyIdle&&u.push({type:"session_idle",sourceEventId:["agy",e,"idle",c.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let d=r.recordMany(u);r.setSourceCursor("agy.transcript.offset",c.nextOffset),t.phase&&r.setSourceCursor("agy.last.phase",t.phase);let l=await r.flush();return{conversationId:e,imported:d.length,eventCount:l.eventCount,chunkCount:l.chunkCount,status:l.status,transcriptOffset:c.nextOffset,reset:c.reset}}function ht(t){return yt(ke(),".gemini","antigravity-cli","brain",t,".system_generated","logs","transcript.jsonl")}import{existsSync as Xr,mkdirSync as Qr,readFileSync as Zr,writeFileSync as es}from"node:fs";import{homedir as ts}from"node:os";import{dirname as ns,join as rs}from"node:path";function ss(t){return`'${t.replace(/'/g,"'\\''")}'`}function St(t={}){let e=t.hooksFile??rs(ts(),".gemini","config","hooks.json");Qr(ns(e),{recursive:!0});let n={};if(Xr(e))try{n=JSON.parse(Zr(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=`${ss(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}]},es(e,JSON.stringify(n,null,2)+`
72
+ `,{encoding:"utf8",mode:384}),e}import{existsSync as vt}from"node:fs";import{homedir as os}from"node:os";import{join as is,resolve as bt}from"node:path";import{DatabaseSync as as}from"node:sqlite";function kt(t){if(t.startsWith("file://"))try{return decodeURIComponent(new URL(t).pathname)}catch{return t}return t}function cs(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(kt)}catch{}return[kt(t)]}function us(t,e){let n=bt(t.rootPath);return e.some(r=>{let s=bt(r);return s===n||s.startsWith(n+"/")||n.startsWith(s+"/")})}async function wt(t,e,n=10){console.log(`Recovering Agy sessions for project: ${t.name}`),console.log(`Limit: ${n} sessions`),console.log("");let r=process.env.AGY_SUMMARY_DB??is(os(),".gemini","antigravity-cli","conversation_summaries.db");if(!vt(r))throw new Error(`Agy summary database not found: ${r}`);let s=new as(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=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
82
+ `).all();s.close();let i=[],c=0,u=Math.min(o.length,n);for(let a of o){let d=typeof a.conversation_id=="string"?a.conversation_id:"";if(!d)continue;let l=cs(a.workspace_uris);if(!us(t,l))continue;let f=ht(d);if(!vt(f))continue;c++,console.log(`[${c}/${u}] Processing conversation: ${d.slice(0,8)}...`);let h=await ce({project:t,storage:e,conversationId:d,transcriptPath:f,workspacePaths:l,modelName:typeof a.agent_name=="string"?a.agent_name:void 0,phase:"recover"});if(console.log(` \u2713 Imported ${h.imported} events (${h.eventCount} total, ${h.chunkCount} chunks)`),i.push(h),i.length>=n)break}return console.log(""),console.log(`\u2713 Recovery complete: ${i.length} sessions processed`),console.log(`Total events: ${i.reduce((a,d)=>a+d.eventCount,0)}`),console.log(`Total chunks: ${i.reduce((a,d)=>a+d.chunkCount,0)}`),i}function ue(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function ls(t){let e=xe(),n=Ne(Me({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 ps(){let[t="help",...e]=process.argv.slice(2);if(t==="install-hooks"){let o=St({binary:ue(e,"--bin")});console.log(`\u2705 Agy hooks installed: ${o}`);return}let n=ue(e,"--project")??process.cwd(),r=new q().detect(n),s=ls(r);if(t==="sync"){let o=e[0],i=ue(e,"--transcript");if(!o||!i)throw new Error("Usage: sync <conversation-id> --transcript <path>");let c=await ce({project:r,storage:s,conversationId:o,transcriptPath:i,phase:"recover"});console.log(JSON.stringify(c,null,2));return}if(t==="recover"){let o=Number(ue(e,"--limit")??100),i=await wt(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
- `)}ns().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});
88
+ `)}ps().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});