toolnet-memory 0.2.9 → 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.
@@ -1,26 +1,26 @@
1
- import{existsSync as Wt,readFileSync as zt}from"node:fs";import{homedir as Bt}from"node:os";import{join as Ft}from"node:path";function Dt(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
- `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function Kt(){let t=process.env.TOOLNET_GLOBAL_ENV??Ft(Bt(),".config","toolnet-memory",".env");if(!Wt(t))return;let e=zt(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]=Dt(r.slice(s+1)))}}Kt();function J(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function F(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function Ae(){return{memory:{autoCapture:J(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:J(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:J(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:J(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:F(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:F(process.env.MEMORY_RERANK_TOP,10),finalContext:F(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:F(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:F(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as qt}from"node:crypto";import{existsSync as he,mkdirSync as Jt,readFileSync as Vt,renameSync as Ut,writeFileSync as Ht}from"node:fs";import{basename as Yt,dirname as V,join as H,parse as $e,resolve as D}from"node:path";var Le=".toolnet",Gt="project.json";function Qt(t){return qt("sha256").update(t).digest("hex").slice(0,16)}function ye(t){return H(t,Le,Gt)}function Xt(t){return he(ye(t))}function Zt(t,e){let n=D(t),r=$e(n).root;for(;;){if(Xt(n))return n;if(n===r||e&&n===D(e))break;let s=V(n);if(s===n)break;n=s}return null}function en(t){let e=D(t),n=$e(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>he(H(e,o))))return e;if(e===n)break;let s=V(e);if(s===e)break;e=s}return D(t)}function tn(t){let e;try{e=JSON.parse(Vt(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:V(V(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 Ne(t,e){let n=H(t,Le);Jt(n,{recursive:!0});let r=ye(t),s=`${r}.tmp-${process.pid}`;Ht(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Ut(s,r)}function _e(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 U=class{detect(e=process.cwd()){let n=D(e),r=en(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>he(H(r,p))),i=Zt(n,o?r:void 0);if(i){let p=ye(i),u=tn(p);return u.rootPath!==i&&(u.rootPath=i,u.updatedAt=new Date().toISOString(),Ne(i,u)),_e(u,i)}let d=new Date().toISOString(),a=Yt(r),c={version:1,id:Qt(r),name:a,remote:a,rootPath:r,createdAt:d,updatedAt:d,graphVersion:0,memoryVersion:0};return Ne(r,c),_e(c,r)}};var nn=[{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}],Y=class{scan(e){let n=[];for(let r of nn){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 K=class{scanner=new Y;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 vn}from"node:os";import{join as bn}from"node:path";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 dn}from"@aws-sdk/s3-request-presigner";var G=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new un({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 cn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await dn(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(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new on({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new 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}};import{access as We,mkdir as pn,readFile as ln,readdir as fn,rm as mn,stat as ze,writeFile as gn}from"node:fs/promises";import{dirname as hn,join as yn,relative as Be,resolve as Sn}from"node:path";var q=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Sn(this.root,n)}async put(e,n){let r=this.path(e);await pn(hn(r),{recursive:!0}),await gn(r,n)}async get(e){try{return await ln(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 We(this.path(e)),!0}catch{return!1}}async delete(e){await mn(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await We(n)}catch{return r}let s=async i=>{let d=await fn(i,{withFileTypes:!0});for(let a of d){let c=yn(i,a.name);if(a.isDirectory()){await s(c);continue}let p=await ze(c);r.push({key:Be(this.root,c),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await ze(n);return o.isDirectory()?await s(n):r.push({key:Be(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};function Fe(t){let e=t.localRoot??bn(vn(),".toolnet-memory","storage");if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new G({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new q(e))}return new q(e)}function jn(t){return new Promise(e=>setTimeout(e,t))}async function De(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(d){if(o=d,i>=n)break;let a=Math.min(s,r*2**(i-1)),c=Math.floor(Math.random()*Math.max(1,a*.2));await jn(a+c)}throw o}var wn=new Set(["put","get","getText","delete","list"]);function Ke(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:wn.has(r)?(...o)=>De(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function qe(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 Je(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 Q=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=qe(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(d){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${d instanceof Error?d.message:String(d)}`)}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=Je(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{existsSync as qr}from"node:fs";import{homedir as Jr}from"node:os";import{isAbsolute as Vr,join as Ur,relative as Hr,resolve as wt}from"node:path";import{DatabaseSync as Yr}from"node:sqlite";import{join as Cn}from"node:path";import{createHash as kn}from"node:crypto";import{dirname as xn}from"node:path";import{mkdirSync as In,readFileSync as On,renameSync as Pn,writeFileSync as En}from"node:fs";function v(t){return kn("sha256").update(t).digest("hex")}function Se(t){if(Array.isArray(t))return t.map(Se);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Se(e[r]);return n}return t}function Ve(t){return JSON.stringify(Se(t))}function Ue(t){try{return JSON.parse(On(t,"utf8"))}catch{return null}}function x(t,e){In(xn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;En(n,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),Pn(n,t)}function He(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 Ye(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=He(r.toLowerCase(),"agent"),i=He(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:Cn(t.rootPath,".toolnet","sessions",o,i)}}function Ge(t){return String(t).padStart(12,"0")}var X=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
1
+ import{existsSync as zt,readFileSync as qt}from"node:fs";import{homedir as Jt}from"node:os";import{join as Vt}from"node:path";function Ut(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 Ht(){let t=process.env.TOOLNET_GLOBAL_ENV??Vt(Jt(),".config","toolnet-memory",".env");if(!zt(t))return;let e=qt(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]=Ut(r.slice(s+1)))}}Ht();function B(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function F(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function Le(){return{memory:{autoCapture:B(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:B(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:B(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:B(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:F(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:F(process.env.MEMORY_RERANK_TOP,10),finalContext:F(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:F(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:B(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:F(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Yt}from"node:crypto";import{existsSync as Se,mkdirSync as Gt,readFileSync as Qt,renameSync as Xt,writeFileSync as Zt}from"node:fs";import{basename as en,dirname as U,join as Y,parse as We,resolve as z}from"node:path";var Be=".toolnet",tn="project.json";function nn(t){return Yt("sha256").update(t).digest("hex").slice(0,16)}function ve(t){return Y(t,Be,tn)}function rn(t){return Se(ve(t))}function sn(t,e){let n=z(t),r=We(n).root;for(;;){if(rn(n))return n;if(n===r||e&&n===z(e))break;let s=U(n);if(s===n)break;n=s}return null}function on(t){let e=z(t),n=We(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>Se(Y(e,o))))return e;if(e===n)break;let s=U(e);if(s===e)break;e=s}return z(t)}function an(t){let e;try{e=JSON.parse(Qt(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:U(U(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 Ke(t,e){let n=Y(t,Be);Gt(n,{recursive:!0});let r=ve(t),s=`${r}.tmp-${process.pid}`;Zt(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Xt(s,r)}function De(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 H=class{detect(e=process.cwd()){let n=z(e),r=on(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>Se(Y(r,p))),i=sn(n,o?r:void 0);if(i){let p=ve(i),u=an(p);return u.rootPath!==i&&(u.rootPath=i,u.updatedAt=new Date().toISOString(),Ke(i,u)),De(u,i)}let d=new Date().toISOString(),a=en(r),c={version:1,id:nn(r),name:a,remote:a,rootPath:r,createdAt:d,updatedAt:d,graphVersion:0,memoryVersion:0};return Ke(r,c),De(c,r)}};var cn=[{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}],G=class{scan(e){let n=[];for(let r of cn){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var q=class{scanner=new G;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 Rn}from"node:os";import{join as An}from"node:path";import{DeleteObjectCommand as un,GetObjectCommand as dn,HeadObjectCommand as pn,ListObjectsV2Command as ln,PutObjectCommand as fn,S3Client as mn}from"@aws-sdk/client-s3";import{getSignedUrl as gn}from"@aws-sdk/s3-request-presigner";var Q=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new mn({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new fn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await gn(this.client,new dn({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`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 pn({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 un({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new ln({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 Fe,mkdir as hn,readFile as yn,readdir as Sn,rm as vn,stat as ze,writeFile as bn}from"node:fs/promises";import{dirname as kn,join as wn,relative as qe,resolve as jn}from"node:path";var J=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return jn(this.root,n)}async put(e,n){let r=this.path(e);await hn(kn(r),{recursive:!0}),await bn(r,n)}async get(e){try{return await yn(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 Fe(this.path(e)),!0}catch{return!1}}async delete(e){await vn(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Fe(n)}catch{return r}let s=async i=>{let d=await Sn(i,{withFileTypes:!0});for(let a of d){let c=wn(i,a.name);if(a.isDirectory()){await s(c);continue}let p=await ze(c);r.push({key:qe(this.root,c),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await ze(n);return o.isDirectory()?await s(n):r.push({key:qe(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as xn,GetObjectCommand as In,HeadObjectCommand as On,ListObjectsV2Command as En,PutObjectCommand as Pn,S3Client as Cn}from"@aws-sdk/client-s3";import{getSignedUrl as Tn}from"@aws-sdk/s3-request-presigner";var V=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Cn({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 Pn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Tn(this.client,new In({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 xn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new En({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 be(t,e){return console.warn(e),new J(t)}function Je(t){let e=t.localRoot??An(Rn(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new V({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):be(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new V({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):be(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 Q({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):be(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new J(e)}function Mn(t){return new Promise(e=>setTimeout(e,t))}async function Ve(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(d){if(o=d,i>=n)break;let a=Math.min(s,r*2**(i-1)),c=Math.floor(Math.random()*Math.max(1,a*.2));await Mn(a+c)}throw o}var Nn=new Set(["put","get","getText","delete","list"]);function Ue(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:Nn.has(r)?(...o)=>Ve(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function He(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 Ye(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 X=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=He(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(d){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${d instanceof Error?d.message:String(d)}`)}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=Ye(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{existsSync as cs}from"node:fs";import{homedir as us}from"node:os";import{isAbsolute as ds,join as ps,relative as ls,resolve as Et}from"node:path";import{DatabaseSync as fs}from"node:sqlite";import{join as Bn}from"node:path";import{createHash as _n}from"node:crypto";import{dirname as $n}from"node:path";import{mkdirSync as Ln,readFileSync as Kn,renameSync as Dn,writeFileSync as Wn}from"node:fs";function v(t){return _n("sha256").update(t).digest("hex")}function ke(t){if(Array.isArray(t))return t.map(ke);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=ke(e[r]);return n}return t}function Ge(t){return JSON.stringify(ke(t))}function Qe(t){try{return JSON.parse(Kn(t,"utf8"))}catch{return null}}function I(t,e){Ln($n(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;Wn(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Dn(n,t)}function Xe(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 Ze(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=Xe(r.toLowerCase(),"agent"),i=Xe(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:Bn(t.rootPath,".toolnet","sessions",o,i)}}function et(t){return String(t).padStart(12,"0")}var Z=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 d=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!d)continue;let a=Number(d[1]),c=Number(d[2]);!Number.isFinite(a)||!Number.isFinite(c)||(s.push({key:i.key,start:a,end:c}),o=Math.max(o,c))}return s.sort((i,d)=>i.start-d.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),d=n.filter(m=>m.sequence>i.maxSequence),a=0;for(let m of this.split(d)){let S=m[0],E=m[m.length-1],M=m.map(A=>JSON.stringify(A)).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),d=n.filter(m=>m.sequence>i.maxSequence),a=0;for(let m of this.split(d)){let h=m[0],x=m[m.length-1],A=m.map(M=>JSON.stringify(M)).join(`
8
8
  `)+`
9
- `,_=v(M).slice(0,16),C=[e.remotePrefix,"events",`${Ge(S.sequence)}-${Ge(E.sequence)}-${_}.jsonl`].join("/");await this.storage.exists(C)||await this.storage.put(C,M,"application/x-ndjson"),a+=m.length}let c=await this.scan(e),p=n[n.length-1],u=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?u="idle":p?.type==="error"?u="error":n.length>0&&(u="active");let g=new Date().toISOString(),l=n[0],y={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:u,createdAt:o?.createdAt??l?.timestamp??g,updatedAt:p?.timestamp??g,firstEventAt:o?.firstEventAt??l?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:c.maxSequence,chunkCount:c.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(y.title=s.title??o?.title);let h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:c.maxSequence,lastRemoteSequence:c.maxSequence,sourceCursors:r,updatedAt:g};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,y),{uploadedEvents:a,lastRemoteSequence:c.maxSequence,eventCount:y.eventCount,chunkCount:y.chunkCount,status:u}}};import{closeSync as ve,existsSync as Rn,fsyncSync as Tn,mkdirSync as Mn,openSync as be,readSync as An,rmSync as Qe,statSync as Xe,writeSync as Nn}from"node:fs";import{join as je}from"node:path";var _n=12e4,$n=80,Ln=2e3;function Wn(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var Z=class{constructor(e){this.identity=e;Mn(e.localDirectory,{recursive:!0}),this.eventsFile=je(e.localDirectory,"events.jsonl"),this.stateFile=je(e.localDirectory,"state.json"),this.lockFile=je(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 Ue(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){x(this.stateFile,e)}acquireLock(){for(let e=0;e<$n;e+=1)try{return be(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-Xe(this.lockFile).mtimeMs>_n){Qe(this.lockFile,{force:!0});continue}}catch{}Wn(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{ve(n),Qe(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 u of e){let g=u.timestamp??new Date().toISOString(),l=u.data??{},y=u.provenance?.rawDigest??v(Ve(l)),h=u.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,u.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,u.type,g,y].join("|"),m=v(h).slice(0,32);if(r.has(m))continue;s+=1;let S={version:1,id:m,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:u.type,timestamp:g,data:l,provenance:{...u.provenance,rawDigest:y}};u.role!==void 0&&(S.role=u.role),u.sourceEventId!==void 0&&(S.sourceEventId=u.sourceEventId),u.sourceSequence!==void 0&&(S.sourceSequence=u.sourceSequence),o.push(S),r.add(m)}if(o.length===0)return[];let i=o.map(u=>JSON.stringify(u)).join(`
9
+ `,_=v(A).slice(0,16),C=[e.remotePrefix,"events",`${et(h.sequence)}-${et(x.sequence)}-${_}.jsonl`].join("/");await this.storage.exists(C)||await this.storage.put(C,A,"application/x-ndjson"),a+=m.length}let c=await this.scan(e),p=n[n.length-1],u=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?u="idle":p?.type==="error"?u="error":n.length>0&&(u="active");let g=new Date().toISOString(),l=n[0],S={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:u,createdAt:o?.createdAt??l?.timestamp??g,updatedAt:p?.timestamp??g,firstEventAt:o?.firstEventAt??l?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:c.maxSequence,chunkCount:c.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(S.title=s.title??o?.title);let y={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:c.maxSequence,lastRemoteSequence:c.maxSequence,sourceCursors:r,updatedAt:g};return await this.putJson(`${e.remotePrefix}/cursor.json`,y),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:a,lastRemoteSequence:c.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:u}}};import{closeSync as we,existsSync as Fn,fsyncSync as zn,mkdirSync as qn,openSync as je,readSync as Jn,rmSync as tt,statSync as nt,writeSync as Vn}from"node:fs";import{join as xe}from"node:path";var Un=12e4,Hn=80,Yn=2e3;function Gn(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ee=class{constructor(e){this.identity=e;qn(e.localDirectory,{recursive:!0}),this.eventsFile=xe(e.localDirectory,"events.jsonl"),this.stateFile=xe(e.localDirectory,"state.json"),this.lockFile=xe(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return Qe(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){I(this.stateFile,e)}acquireLock(){for(let e=0;e<Hn;e+=1)try{return je(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-nt(this.lockFile).mtimeMs>Un){tt(this.lockFile,{force:!0});continue}}catch{}Gn(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{we(n),tt(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let u of e){let g=u.timestamp??new Date().toISOString(),l=u.data??{},S=u.provenance?.rawDigest??v(Ge(l)),y=u.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,u.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,u.type,g,S].join("|"),m=v(y).slice(0,32);if(r.has(m))continue;s+=1;let h={version:1,id:m,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:u.type,timestamp:g,data:l,provenance:{...u.provenance,rawDigest:S}};u.role!==void 0&&(h.role=u.role),u.sourceEventId!==void 0&&(h.sourceEventId=u.sourceEventId),u.sourceSequence!==void 0&&(h.sourceSequence=u.sourceSequence),o.push(h),r.add(m)}if(o.length===0)return[];let i=o.map(u=>JSON.stringify(u)).join(`
10
10
  `)+`
11
- `,d=be(this.eventsFile,"a",384);try{Nn(d,i,null,"utf8"),Tn(d)}finally{ve(d)}let a=o[o.length-1],c="active";a.type==="session_end"||a.type==="session_idle"?c="idle":a.type==="error"&&(c="error");let p=Array.from(r).slice(-Ln);return this.saveStateUnsafe({...n,status:c,updatedAt:a.timestamp,lastSequence:a.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Rn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=Xe(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=be(this.eventsFile,"r");try{An(i,o,0,s,r)}finally{ve(i)}return{events:o.toString("utf8").split(`
12
- `).filter(Boolean).map(c=>JSON.parse(c)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as er,existsSync as tr,openSync as nr,readSync as rr,statSync as sr}from"node:fs";function Ze(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 rt=[/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],zn=[/từ giờ/iu,/về sau/iu,/mỗi lần/iu,/luôn luôn/iu,/\bluôn\b/iu,/quy tắc/iu,/workflow/iu,/\balways\b/iu,/\brequired\b/iu,/\bmust\b/iu,/from now on/iu],Bn=[/\bchốt\b/iu,/quyết định/iu,/sẽ dùng/iu,/chọn .+ thay/iu,/đổi sang/iu,/chuyển sang/iu,/\bdecided\b/iu,/\bchosen\b/iu,/we will use/iu,/use .+ instead/iu,/switch(?:ed)? to/iu],Fn=[/\btodo\b/iu,/cần làm/iu,/cần thêm/iu,/cần sửa/iu,/cần kiểm tra/iu,/tiếp theo/iu,/bước tiếp theo/iu,/còn phải/iu,/còn cần/iu,/next step/iu,/\bneed to\b/iu,/\bremaining\b/iu,/follow[- ]?up/iu],Dn=[/đã sửa/iu,/đã fix/iu,/đã khắc phục/iu,/đã xử lý/iu,/hoàn tất/iu,/hoàn thành/iu,/\bfixed\b/iu,/\bresolved\b/iu,/\bimplemented\b/iu,/\bcompleted\b/iu,/\bpasses?\b/iu],et=[/kiến trúc/iu,/pipeline/iu,/adapter/iu,/schema/iu,/runtime/iu,/namespace/iu,/storage/iu,/lưu trữ/iu,/workflow/iu,/session core/iu,/memory engine/iu,/retrieval/iu],Kn=[/\bdùng\b/iu,/\btách\b/iu,/\bthay\b/iu,/\bchuyển\b/iu,/\blưu\b/iu,/\bmap\b/iu,/\buse\b/iu,/\bsplit\b/iu,/\bstore\b/iu,/\breplace\b/iu,/\bmove\b/iu],qn=[/đườ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],Jn=[/\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],tt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Vn=new Set(["payload","data","content","message","messages","parts","summary"]);function I(t,e){return e.some(n=>n.test(t))}function st(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Un(t){return st(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Hn(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 we(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||tt.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))we(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(tt.has(s)||Vn.has(s))&&we(o,s,n,r+1)}}function Yn(t){let e=[];we(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=st(o);if(Hn(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function nt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Gn(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&I(t,rt)?{kind:"rule",confidence:.98}:r&&I(t,zn)?{kind:"rule",confidence:.92}:I(t,Bn)?{kind:I(t,et)?"architecture":"decision",confidence:r?.93:.86}:r&&I(t,Fn)?{kind:"todo",confidence:.87}:I(t,et)&&I(t,Kn)?{kind:"architecture",confidence:r?.88:.82}:s&&I(t,Dn)?{kind:"fix",confidence:.8}:r&&I(t,qn)&&I(t,Jn)?{kind:"context",confidence:.79}:null}function Qn(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Xn(t,e,n){return t==="rule"&&I(n,rt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":Ze(e,n)}function ot(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,d=nt(o);i&&d&&s.set(i,d)}for(let o of e){let i=nt(o),d=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&d&&(i=s.get(d)??"");for(let a of Yn(o)){let c=Gn(a,i,o);if(!c||c.confidence<.75)continue;let p=Qn(c.kind),u=Un(a),g=v([t.projectId,c.kind,u].join("|"));if(r.has(g))continue;r.add(g);let l=o.provenance.sourcePath?[o.provenance.sourcePath]:[],y=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:g,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:c.kind,type:p,content:a,confidence:c.confidence,importance:Xn(c.kind,p,a),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:y,sourcePaths:l,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function it(t){return String(t).padStart(12,"0")}function Zn(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var ee=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(p=>p.sequence)),o=Math.max(...n.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},d=JSON.stringify(i,null,2)+`
13
- `,a=v(r.map(p=>p.fingerprint).sort().join("|")).slice(0,16),c=[Zn(e),"batches",`${it(s)}-${it(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,d,"application/json"),c}};function or(t,e){if(!tr(t))return{events:[],nextOffset:e};let n=sr(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=nr(t,"r");try{rr(i,o,0,s,r)}finally{er(i)}let d=o.toString("utf8"),a=d.lastIndexOf(`
11
+ `,d=je(this.eventsFile,"a",384);try{Vn(d,i,null,"utf8"),zn(d)}finally{we(d)}let a=o[o.length-1],c="active";a.type==="session_end"||a.type==="session_idle"?c="idle":a.type==="error"&&(c="error");let p=Array.from(r).slice(-Yn);return this.saveStateUnsafe({...n,status:c,updatedAt:a.timestamp,lastSequence:a.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Fn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=nt(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=je(this.eventsFile,"r");try{Jn(i,o,0,s,r)}finally{we(i)}return{events:o.toString("utf8").split(`
12
+ `).filter(Boolean).map(c=>JSON.parse(c)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as lr,existsSync as fr,openSync as mr,readSync as gr,statSync as hr}from"node:fs";function rt(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 at=[/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],Qn=[/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],Xn=[/\bchốt\b/iu,/quyết định/iu,/sẽ dùng/iu,/chọn .+ thay/iu,/đổi sang/iu,/chuyển sang/iu,/\bdecided\b/iu,/\bchosen\b/iu,/we will use/iu,/use .+ instead/iu,/switch(?:ed)? to/iu],Zn=[/\btodo\b/iu,/cần làm/iu,/cần thêm/iu,/cần sửa/iu,/cần kiểm tra/iu,/tiếp theo/iu,/bước tiếp theo/iu,/còn phải/iu,/còn cần/iu,/next step/iu,/\bneed to\b/iu,/\bremaining\b/iu,/follow[- ]?up/iu],er=[/đã 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],st=[/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],tr=[/\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],nr=[/đườ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],rr=[/\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],ot=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),sr=new Set(["payload","data","content","message","messages","parts","summary"]);function O(t,e){return e.some(n=>n.test(t))}function ct(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function or(t){return ct(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function ir(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 Ie(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||ot.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Ie(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(ot.has(s)||sr.has(s))&&Ie(o,s,n,r+1)}}function ar(t){let e=[];Ie(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=ct(o);if(ir(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function it(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function cr(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&&O(t,at)?{kind:"rule",confidence:.98}:r&&O(t,Qn)?{kind:"rule",confidence:.92}:O(t,Xn)?{kind:O(t,st)?"architecture":"decision",confidence:r?.93:.86}:r&&O(t,Zn)?{kind:"todo",confidence:.87}:O(t,st)&&O(t,tr)?{kind:"architecture",confidence:r?.88:.82}:s&&O(t,er)?{kind:"fix",confidence:.8}:r&&O(t,nr)&&O(t,rr)?{kind:"context",confidence:.79}:null}function ur(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function dr(t,e,n){return t==="rule"&&O(n,at)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":rt(e,n)}function ut(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,d=it(o);i&&d&&s.set(i,d)}for(let o of e){let i=it(o),d=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&d&&(i=s.get(d)??"");for(let a of ar(o)){let c=cr(a,i,o);if(!c||c.confidence<.75)continue;let p=ur(c.kind),u=or(a),g=v([t.projectId,c.kind,u].join("|"));if(r.has(g))continue;r.add(g);let l=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:g,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:c.kind,type:p,content:a,confidence:c.confidence,importance:dr(c.kind,p,a),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:l,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function dt(t){return String(t).padStart(12,"0")}function pr(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var te=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(p=>p.sequence)),o=Math.max(...n.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},d=JSON.stringify(i,null,2)+`
13
+ `,a=v(r.map(p=>p.fingerprint).sort().join("|")).slice(0,16),c=[pr(e),"batches",`${dt(s)}-${dt(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,d,"application/json"),c}};function yr(t,e){if(!fr(t))return{events:[],nextOffset:e};let n=hr(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=mr(t,"r");try{gr(i,o,0,s,r)}finally{lr(i)}let d=o.toString("utf8"),a=d.lastIndexOf(`
14
14
  `);if(a<0)return{events:[],nextOffset:r};let c=d.slice(0,a+1);return{events:c.split(`
15
- `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var te=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["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=or(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=ot(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 lr,existsSync as fr,openSync as mr,readSync as gr,statSync as hr}from"node:fs";var ir=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function L(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function ct(t){return L(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))$(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(ir.has(r)||["data","payload","parts","messages"].includes(r))&&$(s,e,n+1)}}function ne(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function at(t){let e=L(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function w(t,e,n,r,s={}){let o=L(r),i=s.key??ct(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 ar(t,e,n){let r=L(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(w(t,e,"goal",i[1],{confidence:.97}));let d=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);d?.[1]&&s.push(w(t,e,"plan",d[1],{confidence:.95}));let a=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,c;for(;!o&&(c=a.exec(r));){let g=Number(c[1]),l=L(c[2]??""),y=l&&!at(l)?`Phase ${g} - ${l}`:`Phase ${g}`;s.push(w(t,e,"phase",y,{key:`phase:${g}`,order:g,status:ne(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(w(t,e,"task",p[2],{status:p[1].trim()?"completed":ne(p[2]),confidence:.96}));let u=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(u?.[2]){let g=u[1]?Number(u[1]):void 0,l=L(u[2]),y=at(l);s.push(w(t,e,"task",y&&g!==void 0?`TODO ${g}`:l,{key:g!==void 0?`task:${g}`:ct(l),order:g,status:ne(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let g=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");g&&s.push(w(t,e,"next_action",g,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(w(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(w(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(w(t,e,"decision",r,{confidence:.9})),s}function ut(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 a=[];$(i.data,a);for(let c of a)s(w(t,i,"decision",c,{confidence:1}))}if(i.type==="todo"){let a=[];$(i.data,a);for(let c of a)s(w(t,i,"task",c,{status:ne(c),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let a of["filePath","path","file"]){let c=i.data[a];typeof c=="string"&&c&&s(w(t,i,"file",c,{confidence:1}))}if(i.type==="test"){let a=[];$(i.data,a);for(let c of a)s(w(t,i,"test",c,{confidence:1}))}let d=[];$(i.data,d);for(let a of d)for(let c of a.split(/\n+/u))for(let p of ar(t,i,c))s(p)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function dt(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(c=>c.sequence)),s=Math.max(...n.map(c=>c.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
16
- `,d=v(n.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${dt(r)}-${dt(s)}-${d}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,i,"application/json"),a}};import{join as pt}from"node:path";import{mkdirSync as cr}from"node:fs";function ur(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function W(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=ur(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function dr(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 lt(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&&dr(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 pr(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,d)=>i.key.localeCompare(d.key))){let i=await e.getText(o.key);if(i)try{let d=JSON.parse(i);d.version===1&&Array.isArray(d.observations)&&s.push(d)}catch{}}return s}async function se(t,e){let r=(await pr(t,e)).flatMap(f=>f.observations).sort((f,k)=>{let Te=f.occurredAt.localeCompare(k.occurredAt);if(Te!==0)return Te;let Me=f.sequence-k.sequence;return Me!==0?Me:f.id.localeCompare(k.id)}),s=new Map,o=new Map,i,d,a,c=[],p=[],u=[],g=[],l=[],y=[];for(let f of r)switch(f.kind){case"goal":i=f.text;break;case"plan":d=f.text;break;case"phase":s.set(f.key,lt(s.get(f.key),f));break;case"task":o.set(f.key,lt(o.get(f.key),f));break;case"decision":c.push(f.text);break;case"blocker":p.push(f.text);break;case"warning":u.push(f.text);break;case"next_action":g.push(f.text);break;case"file":l.push(f.text);break;case"test":y.push(f.text);break;case"session":a={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let h=Array.from(s.values()).sort((f,k)=>(f.order??Number.MAX_SAFE_INTEGER)-(k.order??Number.MAX_SAFE_INTEGER)),m=Array.from(o.values()).sort((f,k)=>(f.order??Number.MAX_SAFE_INTEGER)-(k.order??Number.MAX_SAFE_INTEGER)),S=h.find(f=>f.status==="in_progress")??h.find(f=>f.status==="blocked")??h.find(f=>f.status==="pending"),E=m.find(f=>f.status==="in_progress")??m.find(f=>f.status==="blocked")??m.find(f=>f.status==="pending"),M=W([...g,...E?[E.title]:[],...!E&&S?[S.title]:[],...m.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),_=W([...p,...h.filter(f=>f.status==="blocked").map(f=>f.title),...m.filter(f=>f.status==="blocked").map(f=>f.title)],20),C={version:1,projectId:t.id,projectName:t.name,goal:i,plan:d,phases:h,tasks:m,decisions:W(c,20),blockers:_,warnings:W(u,20),nextActions:M,filesTouched:W(l,30),tests:W(y,20),currentPhase:S,currentTask:E,progress:{phasesTotal:h.length,phasesCompleted:h.filter(f=>f.status==="completed").length,tasksTotal:m.length,tasksCompleted:m.filter(f=>f.status==="completed").length,blocked:h.filter(f=>f.status==="blocked").length+m.filter(f=>f.status==="blocked").length},lastSession:a,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},A=pt(t.rootPath,".toolnet","work");return cr(A,{recursive:!0}),x(pt(A,"current.json"),C),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(C,null,2)+`
17
- `,"application/json"),C}async function oe(t,e){let n=await e.getText(`projects/${t.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function yr(t,e){if(!fr(t))return{events:[],nextOffset:e};let n=hr(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=mr(t,"r");try{gr(i,o,0,s,r)}finally{lr(i)}let d=o.toString("utf8"),a=d.lastIndexOf(`
15
+ `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var ne=class{constructor(e){this.options=e;this.journal=new te(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=yr(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=ut(this.options.identity,s.events),i=!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 xr,existsSync as Ir,openSync as Or,readSync as Er,statSync as Pr}from"node:fs";var Sr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function L(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function lt(t){return L(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))$(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Sr.has(r)||["data","payload","parts","messages"].includes(r))&&$(s,e,n+1)}}function re(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 pt(t){let e=L(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function w(t,e,n,r,s={}){let o=L(r),i=s.key??lt(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 vr(t,e,n){let r=L(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(w(t,e,"goal",i[1],{confidence:.97}));let d=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);d?.[1]&&s.push(w(t,e,"plan",d[1],{confidence:.95}));let a=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,c;for(;!o&&(c=a.exec(r));){let g=Number(c[1]),l=L(c[2]??""),S=l&&!pt(l)?`Phase ${g} - ${l}`:`Phase ${g}`;s.push(w(t,e,"phase",S,{key:`phase:${g}`,order:g,status:re(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(w(t,e,"task",p[2],{status:p[1].trim()?"completed":re(p[2]),confidence:.96}));let u=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(u?.[2]){let g=u[1]?Number(u[1]):void 0,l=L(u[2]),S=pt(l);s.push(w(t,e,"task",S&&g!==void 0?`TODO ${g}`:l,{key:g!==void 0?`task:${g}`:lt(l),order:g,status:re(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 g=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");g&&s.push(w(t,e,"next_action",g,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(w(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(w(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(w(t,e,"decision",r,{confidence:.9})),s}function ft(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 a=[];$(i.data,a);for(let c of a)s(w(t,i,"decision",c,{confidence:1}))}if(i.type==="todo"){let a=[];$(i.data,a);for(let c of a)s(w(t,i,"task",c,{status:re(c),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let a of["filePath","path","file"]){let c=i.data[a];typeof c=="string"&&c&&s(w(t,i,"file",c,{confidence:1}))}if(i.type==="test"){let a=[];$(i.data,a);for(let c of a)s(w(t,i,"test",c,{confidence:1}))}let d=[];$(i.data,d);for(let a of d)for(let c of a.split(/\n+/u))for(let p of vr(t,i,c))s(p)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function mt(t){return String(t).padStart(12,"0")}var se=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.sequence)),s=Math.max(...n.map(c=>c.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
16
+ `,d=v(n.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${mt(r)}-${mt(s)}-${d}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,i,"application/json"),a}};import{join as gt}from"node:path";import{mkdirSync as br}from"node:fs";function kr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function K(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=kr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function wr(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 ht(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&&wr(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 jr(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,d)=>i.key.localeCompare(d.key))){let i=await e.getText(o.key);if(i)try{let d=JSON.parse(i);d.version===1&&Array.isArray(d.observations)&&s.push(d)}catch{}}return s}async function oe(t,e){let r=(await jr(t,e)).flatMap(f=>f.observations).sort((f,j)=>{let _e=f.occurredAt.localeCompare(j.occurredAt);if(_e!==0)return _e;let $e=f.sequence-j.sequence;return $e!==0?$e:f.id.localeCompare(j.id)}),s=new Map,o=new Map,i,d,a,c=[],p=[],u=[],g=[],l=[],S=[];for(let f of r)switch(f.kind){case"goal":i=f.text;break;case"plan":d=f.text;break;case"phase":s.set(f.key,ht(s.get(f.key),f));break;case"task":o.set(f.key,ht(o.get(f.key),f));break;case"decision":c.push(f.text);break;case"blocker":p.push(f.text);break;case"warning":u.push(f.text);break;case"next_action":g.push(f.text);break;case"file":l.push(f.text);break;case"test":S.push(f.text);break;case"session":a={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let y=Array.from(s.values()).sort((f,j)=>(f.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),m=Array.from(o.values()).sort((f,j)=>(f.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),h=y.find(f=>f.status==="in_progress")??y.find(f=>f.status==="blocked")??y.find(f=>f.status==="pending"),x=m.find(f=>f.status==="in_progress")??m.find(f=>f.status==="blocked")??m.find(f=>f.status==="pending"),A=K([...g,...x?[x.title]:[],...!x&&h?[h.title]:[],...m.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),_=K([...p,...y.filter(f=>f.status==="blocked").map(f=>f.title),...m.filter(f=>f.status==="blocked").map(f=>f.title)],20),C={version:1,projectId:t.id,projectName:t.name,goal:i,plan:d,phases:y,tasks:m,decisions:K(c,20),blockers:_,warnings:K(u,20),nextActions:A,filesTouched:K(l,30),tests:K(S,20),currentPhase:h,currentTask:x,progress:{phasesTotal:y.length,phasesCompleted:y.filter(f=>f.status==="completed").length,tasksTotal:m.length,tasksCompleted:m.filter(f=>f.status==="completed").length,blocked:y.filter(f=>f.status==="blocked").length+m.filter(f=>f.status==="blocked").length},lastSession:a,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},M=gt(t.rootPath,".toolnet","work");return br(M,{recursive:!0}),I(gt(M,"current.json"),C),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(C,null,2)+`
17
+ `,"application/json"),C}async function ie(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 Cr(t,e){if(!Ir(t))return{events:[],nextOffset:e};let n=Pr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=Or(t,"r");try{Er(i,o,0,s,r)}finally{xr(i)}let d=o.toString("utf8"),a=d.lastIndexOf(`
18
18
  `);if(a<0)return{events:[],nextOffset:r};let c=d.slice(0,a+1);return{events:c.split(`
19
- `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var ie=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.continuity.offset"]??0),r=yr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=ut(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await se(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 Or,existsSync as Pr,openSync as Er,readSync as Cr,statSync as Rr}from"node:fs";var Sr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function z(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function ke(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))ke(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Sr.has(r)||["data","payload","parts","messages"].includes(r))&&ke(s,e,n+1)}}function O(t,e,n,r,s,o=.95){let i=z(r);return{version:1,id:v([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function P(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return z(t.slice(r.length+1))}return null}function vr(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function br(t){return z(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function ft(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=[];ke(o.data,i);for(let d of i){let a={type:"project"},c=null;for(let p of d.split(/\r?\n/u)){let u=z(p);if(!u){c=null;continue}let g=u.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(g){let k=Number(g[1]);a={type:"phase",key:`phase:${k}`,order:k,title:z(g[2]??"")},c=null;continue}let l=u.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let k=Number(l[1]);a={type:"task",key:`task:${k}`,order:k,title:z(l[2]??"")},c=null;continue}let y=P(u,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(y){s(O(t,o,"mission",y,{type:"project"},.99)),c=null;continue}let h=P(u,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(O(t,o,a.type==="phase"?"phase_objective":"objective",h,a,.98)),c=null;continue}let m=P(u,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(m){s(O(t,o,a.type==="phase"?"phase_why":"why",m,a,.98)),c=null;continue}let S=P(u,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(S){s(O(t,o,"desired_outcome",S,{type:"project"},.98)),c=null;continue}let E=P(u,["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(E){s(O(t,o,"plan_rationale",E,{type:"project"},.98)),c=null;continue}let M=P(u,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(M){s(O(t,o,"phase_deliverable",M,a,.97)),c=null;continue}let _=P(u,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(_){s(O(t,o,"acceptance_criterion",_,a,.98)),c="acceptance_criterion";continue}let C=P(u,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(C){s(O(t,o,"dependency",C,a,.97)),c="dependency";continue}let A=P(u,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(A){s(O(t,o,"open_question",A,a,.95)),c="open_question";continue}let f=P(u,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(f){s(O(t,o,"constraint",f,a,.97)),c="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(u)){c="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(u)){c="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(u)){c="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(u)){c="constraint";continue}if(c&&vr(p)){s(O(t,o,c,br(p),a,.96));continue}c=null}}}return n}function mt(t){return String(t).padStart(12,"0")}var ae=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.evidence.sequence)),s=Math.max(...n.map(a=>a.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(a=>a.id).sort().join("|")).slice(0,16),d=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${mt(r)}-${mt(s)}-${i}.json`].join("/");return await this.storage.exists(d)||await this.storage.put(d,JSON.stringify(o,null,2)+`
20
- `,"application/json"),d}};import{mkdirSync as jr}from"node:fs";import{join as gt}from"node:path";function wr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function kr(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 R(t,e){return kr(e,t)?e:t}function T(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function xr(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,d)=>i.key.localeCompare(d.key))){let i=await e.getText(o.key);if(i)try{let d=JSON.parse(i);d.version===1&&Array.isArray(d.observations)&&s.push(d)}catch{}}return s}function Ir(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function ht(t,e){let r=(await xr(t,e)).flatMap(h=>h.observations).sort((h,m)=>{let S=h.evidence.occurredAt.localeCompare(m.evidence.occurredAt);return S!==0?S:h.evidence.sessionKey===m.evidence.sessionKey?h.evidence.sequence-m.evidence.sequence:h.id.localeCompare(m.id)}),s,o,i,d,a,c=new Map,p=[],u=[],g=[];for(let h of r){let m=wr(h);if(h.scope==="phase"&&h.scopeKey){let S=c.get(h.scopeKey)??Ir(h);switch(h.kind){case"phase_objective":S.objective=R(S.objective,m);break;case"phase_why":S.why=R(S.why,m);break;case"phase_deliverable":S.deliverable=R(S.deliverable,m);break;case"acceptance_criterion":S.acceptanceCriteria.push(m);break;case"dependency":S.dependencies.push(m);break;case"open_question":S.openQuestions.push(m);break;case"constraint":S.constraints.push(m);break;case"note":S.notes.push(m);break}c.set(S.key,S);continue}switch(h.kind){case"mission":s=R(s,m);break;case"objective":o=R(o,m);break;case"why":i=R(i,m);break;case"desired_outcome":d=R(d,m);break;case"plan_rationale":a=R(a,m);break;case"open_question":p.push(m);break;case"constraint":u.push(m);break;case"note":g.push(m);break}}for(let h of c.values())h.acceptanceCriteria=T(h.acceptanceCriteria,20),h.dependencies=T(h.dependencies,15),h.openQuestions=T(h.openQuestions,15),h.constraints=T(h.constraints,15),h.notes=T(h.notes,20);let l={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:d,planRationale:a,phases:Array.from(c.values()).sort((h,m)=>h.order-m.order),openQuestions:T(p,20),constraints:T(u,20),notes:T(g,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},y=gt(t.rootPath,".toolnet","work");return jr(y,{recursive:!0}),x(gt(y,"semantic-current.json"),l),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
21
- `,"application/json"),l}async function yt(t,e){let n=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Tr(t,e){if(!Pr(t))return{events:[],nextOffset:e};let n=Rr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=Er(t,"r");try{Cr(o,s,0,s.length,r)}finally{Or(o)}let i=s.toString("utf8"),d=i.lastIndexOf(`
19
+ `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var ae=class{constructor(e){this.options=e;this.journal=new se(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Cr(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=ft(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await oe(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 Kr,existsSync as Dr,openSync as Wr,readSync as Br,statSync as Fr}from"node:fs";var Tr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function D(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Oe(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))Oe(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Tr.has(r)||["data","payload","parts","messages"].includes(r))&&Oe(s,e,n+1)}}function E(t,e,n,r,s,o=.95){let i=D(r);return{version:1,id:v([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function P(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return D(t.slice(r.length+1))}return null}function Rr(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Ar(t){return D(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function yt(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Oe(o.data,i);for(let d of i){let a={type:"project"},c=null;for(let p of d.split(/\r?\n/u)){let u=D(p);if(!u){c=null;continue}let g=u.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(g){let j=Number(g[1]);a={type:"phase",key:`phase:${j}`,order:j,title:D(g[2]??"")},c=null;continue}let l=u.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let j=Number(l[1]);a={type:"task",key:`task:${j}`,order:j,title:D(l[2]??"")},c=null;continue}let S=P(u,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(E(t,o,"mission",S,{type:"project"},.99)),c=null;continue}let y=P(u,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(y){s(E(t,o,a.type==="phase"?"phase_objective":"objective",y,a,.98)),c=null;continue}let m=P(u,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(m){s(E(t,o,a.type==="phase"?"phase_why":"why",m,a,.98)),c=null;continue}let h=P(u,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){s(E(t,o,"desired_outcome",h,{type:"project"},.98)),c=null;continue}let x=P(u,["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(x){s(E(t,o,"plan_rationale",x,{type:"project"},.98)),c=null;continue}let A=P(u,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(A){s(E(t,o,"phase_deliverable",A,a,.97)),c=null;continue}let _=P(u,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(_){s(E(t,o,"acceptance_criterion",_,a,.98)),c="acceptance_criterion";continue}let C=P(u,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(C){s(E(t,o,"dependency",C,a,.97)),c="dependency";continue}let M=P(u,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(M){s(E(t,o,"open_question",M,a,.95)),c="open_question";continue}let f=P(u,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(f){s(E(t,o,"constraint",f,a,.97)),c="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(u)){c="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(u)){c="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(u)){c="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(u)){c="constraint";continue}if(c&&Rr(p)){s(E(t,o,c,Ar(p),a,.96));continue}c=null}}}return n}function St(t){return String(t).padStart(12,"0")}var ce=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.evidence.sequence)),s=Math.max(...n.map(a=>a.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(a=>a.id).sort().join("|")).slice(0,16),d=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${St(r)}-${St(s)}-${i}.json`].join("/");return await this.storage.exists(d)||await this.storage.put(d,JSON.stringify(o,null,2)+`
20
+ `,"application/json"),d}};import{mkdirSync as Mr}from"node:fs";import{join as vt}from"node:path";function Nr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function _r(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 T(t,e){return _r(e,t)?e:t}function R(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 $r(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,d)=>i.key.localeCompare(d.key))){let i=await e.getText(o.key);if(i)try{let d=JSON.parse(i);d.version===1&&Array.isArray(d.observations)&&s.push(d)}catch{}}return s}function Lr(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function bt(t,e){let r=(await $r(t,e)).flatMap(y=>y.observations).sort((y,m)=>{let h=y.evidence.occurredAt.localeCompare(m.evidence.occurredAt);return h!==0?h:y.evidence.sessionKey===m.evidence.sessionKey?y.evidence.sequence-m.evidence.sequence:y.id.localeCompare(m.id)}),s,o,i,d,a,c=new Map,p=[],u=[],g=[];for(let y of r){let m=Nr(y);if(y.scope==="phase"&&y.scopeKey){let h=c.get(y.scopeKey)??Lr(y);switch(y.kind){case"phase_objective":h.objective=T(h.objective,m);break;case"phase_why":h.why=T(h.why,m);break;case"phase_deliverable":h.deliverable=T(h.deliverable,m);break;case"acceptance_criterion":h.acceptanceCriteria.push(m);break;case"dependency":h.dependencies.push(m);break;case"open_question":h.openQuestions.push(m);break;case"constraint":h.constraints.push(m);break;case"note":h.notes.push(m);break}c.set(h.key,h);continue}switch(y.kind){case"mission":s=T(s,m);break;case"objective":o=T(o,m);break;case"why":i=T(i,m);break;case"desired_outcome":d=T(d,m);break;case"plan_rationale":a=T(a,m);break;case"open_question":p.push(m);break;case"constraint":u.push(m);break;case"note":g.push(m);break}}for(let y of c.values())y.acceptanceCriteria=R(y.acceptanceCriteria,20),y.dependencies=R(y.dependencies,15),y.openQuestions=R(y.openQuestions,15),y.constraints=R(y.constraints,15),y.notes=R(y.notes,20);let l={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:d,planRationale:a,phases:Array.from(c.values()).sort((y,m)=>y.order-m.order),openQuestions:R(p,20),constraints:R(u,20),notes:R(g,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=vt(t.rootPath,".toolnet","work");return Mr(S,{recursive:!0}),I(vt(S,"semantic-current.json"),l),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
21
+ `,"application/json"),l}async function kt(t,e){let n=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function zr(t,e){if(!Dr(t))return{events:[],nextOffset:e};let n=Fr(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=Wr(t,"r");try{Br(o,s,0,s.length,r)}finally{Kr(o)}let i=s.toString("utf8"),d=i.lastIndexOf(`
22
22
  `);if(d<0)return{events:[],nextOffset:r};let a=i.slice(0,d+1);return{events:a.split(`
23
- `).filter(Boolean).flatMap(c=>{try{return[JSON.parse(c)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var ce=class{constructor(e){this.options=e;this.journal=new ae(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Tr(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=ft(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ht(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 Fr}from"node:fs";import{join as xe}from"node:path";import{existsSync as bt,mkdirSync as Mr,readFileSync as Ar,statSync as St,writeFileSync as Nr}from"node:fs";import{dirname as _r,join as $r}from"node:path";var vt=64*1024,Lr=`# ToolNet Project Operating Manual
23
+ `).filter(Boolean).flatMap(c=>{try{return[JSON.parse(c)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var ue=class{constructor(e){this.options=e;this.journal=new ce(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=zr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=yt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await bt(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as Zr}from"node:fs";import{join as Ee}from"node:path";import{existsSync as xt,mkdirSync as qr,readFileSync as Jr,statSync as wt,writeFileSync as Vr}from"node:fs";import{dirname as Ur,join as Hr}from"node:path";var jt=64*1024,Yr=`# ToolNet Project Operating Manual
24
24
 
25
25
  This file contains persistent instructions for AI agents working on this project.
26
26
 
@@ -63,29 +63,29 @@ Things an AI agent should always remember.
63
63
  <!--
64
64
  - [advisory] Prefer small focused files.
65
65
  -->
66
- `;function ue(t){return $r(t.rootPath,".toolnet","PROJECT.md")}function Wr(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function zr(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=Wr(s[2]);if(!i)continue;let d=`${o}:${i.toLowerCase()}`;n.has(d)||(n.add(d),e.push({id:v(d).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Br(t){let e=ue(t);return bt(e)||(Mr(_r(e),{recursive:!0}),Nr(e,Lr,{encoding:"utf8",mode:384})),e}function de(t,e=!1){let n=e?Br(t):ue(t);if(!bt(n))return null;if(St(n).size>vt)throw new Error(`PROJECT.md exceeds ${vt} bytes`);let s=Ar(n,"utf8");return{path:n,content:s,digest:v(s),rules:zr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(St(n).mtimeMs).toISOString()}}function Dr(t){return{goal:t.goal,plan:t.plan,phases:t.phases.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),tasks:t.tasks.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),decisions:t.decisions,blockers:t.blockers,warnings:t.warnings,nextActions:t.nextActions,filesTouched:t.filesTouched,tests:t.tests}}function Kr(t){return t.phases.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.tasks.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.nextActions.length>0||t.blockers.length>0}var pe=class{constructor(e){this.options=e}options;async capture(e,n){let r=await oe(this.options.project,this.options.storage);if(r||(r=await se(this.options.project,this.options.storage)),!Kr(r))return null;let s=de(this.options.project,!1),o=s?s.rules.filter(g=>g.mode==="enforce").map(g=>g.text):[],i=v(JSON.stringify(Dr(r))),d=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),a=new Date().toISOString(),c={version:1,id:d,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:a,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(g=>g.status!=="completed"&&g.status!=="cancelled"),incompleteTasks:r.tasks.filter(g=>g.status!=="completed"&&g.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},p=`projects/${this.options.project.id}/work/handoffs/${d}.json`;await this.options.storage.exists(p)||await this.options.storage.put(p,JSON.stringify(c,null,2)+`
66
+ `;function de(t){return Hr(t.rootPath,".toolnet","PROJECT.md")}function Gr(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Qr(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=Gr(s[2]);if(!i)continue;let d=`${o}:${i.toLowerCase()}`;n.has(d)||(n.add(d),e.push({id:v(d).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Xr(t){let e=de(t);return xt(e)||(qr(Ur(e),{recursive:!0}),Vr(e,Yr,{encoding:"utf8",mode:384})),e}function pe(t,e=!1){let n=e?Xr(t):de(t);if(!xt(n))return null;if(wt(n).size>jt)throw new Error(`PROJECT.md exceeds ${jt} bytes`);let s=Jr(n,"utf8");return{path:n,content:s,digest:v(s),rules:Qr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(wt(n).mtimeMs).toISOString()}}function es(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 ts(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 le=class{constructor(e){this.options=e}options;async capture(e,n){let r=await ie(this.options.project,this.options.storage);if(r||(r=await oe(this.options.project,this.options.storage)),!ts(r))return null;let s=pe(this.options.project,!1),o=s?s.rules.filter(g=>g.mode==="enforce").map(g=>g.text):[],i=v(JSON.stringify(es(r))),d=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),a=new Date().toISOString(),c={version:1,id:d,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:a,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(g=>g.status!=="completed"&&g.status!=="cancelled"),incompleteTasks:r.tasks.filter(g=>g.status!=="completed"&&g.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},p=`projects/${this.options.project.id}/work/handoffs/${d}.json`;await this.options.storage.exists(p)||await this.options.storage.put(p,JSON.stringify(c,null,2)+`
67
67
  `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(c,null,2)+`
68
- `,"application/json");let u=xe(this.options.project.rootPath,".toolnet","work","handoffs");return Fr(u,{recursive:!0}),x(xe(u,`${d}.json`),c),x(xe(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),c),c}};async function jt(t,e){let n=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}var le=class{identity;wal;remote;sanitizer=new K;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=Ye(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new Z(this.identity),this.remote=new X(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new te({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ie({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new ce({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new pe({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)}};function Pt(){return process.env.OPENCODE_DB_PATH??Ur(Jr(),".local","share","opencode","opencode.db")}function j(t){return typeof t=="string"?t:""}function N(t){if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="bigint")return Number(t);if(typeof t=="string"){let e=Number(t);if(Number.isFinite(e))return e}return 0}function Ie(t){if(t&&typeof t=="object"&&!Buffer.isBuffer(t))return t;if(typeof t!="string")return{};try{let e=JSON.parse(t);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{}return{}}function B(t){let e=N(t);if(e<=0)return new Date().toISOString();e<1e11&&(e*=1e3);let n=new Date(e);return Number.isNaN(n.getTime())?new Date().toISOString():n.toISOString()}function fe(t,e){if(!e)return!1;let n=wt(t),r=wt(e);if(n===r)return!0;let s=Hr(n,r);return s!==""&&s!==".."&&!s.startsWith(`..${process.platform==="win32"?"\\":"/"}`)&&!Vr(s)}function kt(t){if(!t)return{time:-1,id:""};try{let e=JSON.parse(t);return{time:typeof e.time=="number"?e.time:-1,id:typeof e.id=="string"?e.id:""}}catch{return{time:-1,id:""}}}function xt(t){return JSON.stringify(t)}function Et(t){if(!qr(t))throw new Error(`OpenCode database not found: ${t}`);let e=new Yr(t,{readOnly:!0});return e.exec("PRAGMA query_only = ON"),e.exec("PRAGMA busy_timeout = 3000"),e}function Gr(t,e){let n=t.prepare(`
68
+ `,"application/json");let u=Ee(this.options.project.rootPath,".toolnet","work","handoffs");return Zr(u,{recursive:!0}),I(Ee(u,`${d}.json`),c),I(Ee(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),c),c}};async function It(t,e){let n=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}var fe=class{identity;wal;remote;sanitizer=new q;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=Ze(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new ee(this.identity),this.remote=new Z(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new ne({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ae({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new ue({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new le({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};var ns=[/^<SYSTEM MESSAGE>/i,/^<EPHEMERAL MESSAGE>/i,/^<system>/i,/^<ephemeral>/i,/^ManageTask:/i,/^Task \d+ status:/i,/^Task \d+ killed/i,/^Task \d+ loading/i,/^Thought for \d+ tokens/i,/^Prioritizing Tool Usage/i,/^Tool call:/i,/^Tool response:/i,/^npm notice/i,/^npm WARN/i,/^added \d+ packages/i,/^removed \d+ packages/i,/^up to date/i,/^\d+ packages are looking for funding/i,/^run `npm fund` for details/i,/^[\d.]+%/,/^\[={10,}\]/,/^Loading\.\.\./i,/^Processing\.\.\./i,/^bash-\d+\.\d+\$/,/^\$ /,/^\s*$/],rs=[/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],ss=["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 os(t){let e=t.toLowerCase();return ss.some(n=>e.includes(n))}function is(t){if(!t.trim())return!0;for(let e of ns)if(e.test(t))return!0;return os(t),!1}function as(t){let e=t;for(let n of rs)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Pe(t){let e=t.trim();return e?is(e)?{content:"",filtered:!0,reason:"noise"}:{content:as(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function me(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=Pe(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=me(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=Pe(s);return o.filtered?null:o.content}return s&&typeof s=="object"?me(s):s}).filter(s=>s!==null):e[n]=r;return e}function Ot(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&&Pe(r).filtered)return!0}return!1}function At(){return process.env.OPENCODE_DB_PATH??ps(us(),".local","share","opencode","opencode.db")}function k(t){return typeof t=="string"?t:""}function N(t){if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="bigint")return Number(t);if(typeof t=="string"){let e=Number(t);if(Number.isFinite(e))return e}return 0}function Ce(t){if(t&&typeof t=="object"&&!Buffer.isBuffer(t))return t;if(typeof t!="string")return{};try{let e=JSON.parse(t);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{}return{}}function W(t){let e=N(t);if(e<=0)return new Date().toISOString();e<1e11&&(e*=1e3);let n=new Date(e);return Number.isNaN(n.getTime())?new Date().toISOString():n.toISOString()}function ge(t,e){if(!e)return!1;let n=Et(t),r=Et(e);if(n===r)return!0;let s=ls(n,r);return s!==""&&s!==".."&&!s.startsWith(`..${process.platform==="win32"?"\\":"/"}`)&&!ds(s)}function Pt(t){if(!t)return{time:-1,id:""};try{let e=JSON.parse(t);return{time:typeof e.time=="number"?e.time:-1,id:typeof e.id=="string"?e.id:""}}catch{return{time:-1,id:""}}}function Ct(t){return JSON.stringify(t)}function Mt(t){if(!cs(t))throw new Error(`OpenCode database not found: ${t}`);let e=new fs(t,{readOnly:!0});return e.exec("PRAGMA query_only = ON"),e.exec("PRAGMA busy_timeout = 3000"),e}function ms(t,e){let n=t.prepare(`
69
69
  SELECT *
70
70
  FROM "session"
71
71
  WHERE id = ?
72
72
  LIMIT 1
73
- `).get(e);if(!n)throw new Error(`OpenCode session not found: ${e}`);return n}function Ct(t,e,n){let r=j(e.directory);if(r&&fe(n.rootPath,r))return!0;let s=j(e.project_id);if(s){try{let o=t.prepare(`
73
+ `).get(e);if(!n)throw new Error(`OpenCode session not found: ${e}`);return n}function Nt(t,e,n){let r=k(e.directory);if(r&&ge(n.rootPath,r))return!0;let s=k(e.project_id);if(s){try{let o=t.prepare(`
74
74
  SELECT *
75
75
  FROM "project"
76
76
  WHERE id = ?
77
77
  LIMIT 1
78
- `).get(s);if(o)for(let i of["worktree","directory","path"]){let d=j(o[i]);if(d&&fe(n.rootPath,d))return!0}}catch{}try{if(t.prepare(`
78
+ `).get(s);if(o)for(let i of["worktree","directory","path"]){let d=k(o[i]);if(d&&ge(n.rootPath,d))return!0}}catch{}try{if(t.prepare(`
79
79
  SELECT directory
80
80
  FROM "project_directory"
81
81
  WHERE project_id = ?
82
- `).all(s).some(i=>fe(n.rootPath,j(i.directory))))return!0}catch{}}try{let o=t.prepare(`
82
+ `).all(s).some(i=>ge(n.rootPath,k(i.directory))))return!0}catch{}}try{let o=t.prepare(`
83
83
  SELECT data
84
84
  FROM "message"
85
85
  WHERE session_id = ?
86
86
  ORDER BY time_created DESC
87
87
  LIMIT 20
88
- `).all(j(e.id));for(let i of o){let d=Ie(i.data),a=d.path&&typeof d.path=="object"?d.path:{};for(let c of[j(a.cwd),j(a.root)])if(c&&fe(n.rootPath,c))return!0}}catch{}return!1}function It(t,e,n,r){let s=`
88
+ `).all(k(e.id));for(let i of o){let d=Ce(i.data),a=d.path&&typeof d.path=="object"?d.path:{};for(let c of[k(a.cwd),k(a.root)])if(c&&ge(n.rootPath,c))return!0}}catch{}return!1}function Tt(t,e,n,r){let s=`
89
89
  SELECT *,
90
90
  COALESCE(
91
91
  time_updated,
@@ -116,7 +116,7 @@ Things an AI agent should always remember.
116
116
  0
117
117
  ) ASC,
118
118
  id ASC
119
- `;return t.prepare(s).all(n,r.time,r.time,r.id)}function Ot(t,e){let n=t[t.length-1];return n?{time:N(n.__clock),id:j(n.id)}:e}function Qr(t,e){let n=Ie(e.data),r=j(n.role),s=N(e.__clock),o=j(e.id),i="message";return r==="user"?i="user_prompt":r==="assistant"&&(i="assistant_message"),{clock:s,order:0,event:{type:i,timestamp:B(s),role:r||void 0,sourceEventId:`message:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{messageId:o,...n},provenance:{source:"opencode",sourcePath:t,sourceTable:"message",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}function Xr(t,e){let n=Ie(e.data),r=j(n.type),s=N(e.__clock),o=j(e.id),i=j(e.message_id),d="message_part";return r==="tool"?d="tool_call":r==="snapshot"&&(d="artifact"),{clock:s,order:1,event:{type:d,timestamp:B(s),sourceEventId:`part:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{partId:o,messageId:i,...n},provenance:{source:"opencode",sourcePath:t,sourceTable:"part",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}async function Oe(t){let e=t.dbPath??Pt(),n=Et(e);try{let r=Gr(n,t.nativeSessionId);if(!Ct(n,r,t.project))throw new Error(["OpenCode session does not belong to current ToolNet project.",`Session: ${t.nativeSessionId}`,`Project: ${t.project.rootPath}`,`Session directory: ${j(r.directory)||"unknown"}`].join(" "));let s=new le({project:t.project,storage:t.storage,agent:"opencode",nativeSessionId:t.nativeSessionId,title:j(r.title)||void 0,metadata:{source:"opencode.db",openCodeProjectId:j(r.project_id)||void 0,directory:j(r.directory)||void 0}}),o=s.status(),i=kt(o.sourceCursors["opencode.message"]),d=kt(o.sourceCursors["opencode.part"]),a=It(n,"message",t.nativeSessionId,i),c=It(n,"part",t.nativeSessionId,d),p=[];if(o.lastSequence===0){let m=N(r.time_created);p.push({clock:m,order:-1,event:{type:"session_start",timestamp:B(m),sourceEventId:`session:${t.nativeSessionId}:created:${m}`,data:{title:j(r.title)||void 0,directory:j(r.directory)||void 0,openCodeProjectId:j(r.project_id)||void 0},provenance:{source:"opencode",sourcePath:e,sourceTable:"session",sourceRowId:t.nativeSessionId}}})}p.push(...a.map(m=>Qr(e,m))),p.push(...c.map(m=>Xr(e,m)));let u=N(r.time_updated)||N(r.time_created);t.compacted&&p.push({clock:u,order:98,event:{type:"session_compact",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:compact:${u}`,data:{},provenance:{source:"opencode"}}}),t.error?p.push({clock:u,order:99,event:{type:"error",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:error:${u}`,data:{source:"session.error"},provenance:{source:"opencode"}}}):t.idle&&p.push({clock:u,order:100,event:{type:"session_idle",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:idle:${u}`,data:{},provenance:{source:"opencode"}}}),p.sort((m,S)=>m.clock-S.clock||m.order-S.order);let g=s.recordMany(p.map(m=>m.event)),l=Ot(a,i),y=Ot(c,d);s.setSourceCursor("opencode.message",xt(l)),s.setSourceCursor("opencode.part",xt(y));let h=await s.flush();return{nativeSessionId:t.nativeSessionId,importedMessages:a.length,importedParts:c.length,recordedEvents:g.length,eventCount:h.eventCount,chunkCount:h.chunkCount,status:h.status}}finally{n.close()}}async function Rt(t){let e=t.dbPath??Pt(),n=Et(e),r=[];try{let o=n.prepare(`
119
+ `;return t.prepare(s).all(n,r.time,r.time,r.id)}function Rt(t,e){let n=t[t.length-1];return n?{time:N(n.__clock),id:k(n.id)}:e}function gs(t,e){let n=Ce(e.data),r=k(n.role),s=N(e.__clock),o=k(e.id),i="message";return r==="user"?i="user_prompt":r==="assistant"&&(i="assistant_message"),{clock:s,order:0,event:{type:i,timestamp:W(s),role:r||void 0,sourceEventId:`message:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{messageId:o,...n},provenance:{source:"opencode",sourcePath:t,sourceTable:"message",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}function hs(t,e){let n=Ce(e.data),r=k(n.type),s=N(e.__clock),o=k(e.id),i=k(e.message_id),d="message_part";return r==="tool"?d="tool_call":r==="snapshot"&&(d="artifact"),{clock:s,order:1,event:{type:d,timestamp:W(s),sourceEventId:`part:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{partId:o,messageId:i,...n},provenance:{source:"opencode",sourcePath:t,sourceTable:"part",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}async function Te(t){let e=t.dbPath??At(),n=Mt(e);try{let r=ms(n,t.nativeSessionId);if(!Nt(n,r,t.project))throw new Error(["OpenCode session does not belong to current ToolNet project.",`Session: ${t.nativeSessionId}`,`Project: ${t.project.rootPath}`,`Session directory: ${k(r.directory)||"unknown"}`].join(" "));let s=new fe({project:t.project,storage:t.storage,agent:"opencode",nativeSessionId:t.nativeSessionId,title:k(r.title)||void 0,metadata:{source:"opencode.db",openCodeProjectId:k(r.project_id)||void 0,directory:k(r.directory)||void 0}}),o=s.status(),i=Pt(o.sourceCursors["opencode.message"]),d=Pt(o.sourceCursors["opencode.part"]),a=Tt(n,"message",t.nativeSessionId,i),c=Tt(n,"part",t.nativeSessionId,d),p=[];if(o.lastSequence===0){let h=N(r.time_created);p.push({clock:h,order:-1,event:{type:"session_start",timestamp:W(h),sourceEventId:`session:${t.nativeSessionId}:created:${h}`,data:{title:k(r.title)||void 0,directory:k(r.directory)||void 0,openCodeProjectId:k(r.project_id)||void 0},provenance:{source:"opencode",sourcePath:e,sourceTable:"session",sourceRowId:t.nativeSessionId}}})}p.push(...a.map(h=>gs(e,h))),p.push(...c.map(h=>hs(e,h)));let u=N(r.time_updated)||N(r.time_created);t.compacted&&p.push({clock:u,order:98,event:{type:"session_compact",timestamp:W(u),sourceEventId:`session:${t.nativeSessionId}:compact:${u}`,data:{},provenance:{source:"opencode"}}}),t.error?p.push({clock:u,order:99,event:{type:"error",timestamp:W(u),sourceEventId:`session:${t.nativeSessionId}:error:${u}`,data:{source:"session.error"},provenance:{source:"opencode"}}}):t.idle&&p.push({clock:u,order:100,event:{type:"session_idle",timestamp:W(u),sourceEventId:`session:${t.nativeSessionId}:idle:${u}`,data:{},provenance:{source:"opencode"}}}),p.sort((h,x)=>h.clock-x.clock||h.order-x.order);let g=p.filter(h=>!Ot(h.event.data)).map(h=>({...h,event:{...h.event,data:me(h.event.data)}})),l=s.recordMany(g.map(h=>h.event)),S=Rt(a,i),y=Rt(c,d);s.setSourceCursor("opencode.message",Ct(S)),s.setSourceCursor("opencode.part",Ct(y));let m=await s.flush();return{nativeSessionId:t.nativeSessionId,importedMessages:a.length,importedParts:c.length,recordedEvents:l.length,eventCount:m.eventCount,chunkCount:m.chunkCount,status:m.status}}finally{n.close()}}async function _t(t){let e=t.dbPath??At(),n=Mt(e),r=[];try{let o=n.prepare(`
120
120
  SELECT *
121
121
  FROM "session"
122
122
  ORDER BY
@@ -125,7 +125,7 @@ Things an AI agent should always remember.
125
125
  time_created,
126
126
  0
127
127
  ) DESC
128
- `).all();for(let i of o){if(!Ct(n,i,t.project))continue;let d=j(i.id);if(d&&r.push(d),r.length>=(t.limit??100))break}}finally{n.close()}let s=[];for(let o of r)s.push(await Oe({project:t.project,storage:t.storage,nativeSessionId:o,dbPath:e}));return s}import{existsSync as Zr,mkdirSync as Mt,readFileSync as es,writeFileSync as At}from"node:fs";import{homedir as Ee}from"node:os";import{join as me}from"node:path";var Tt="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",Pe="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function ts(){let t=me(Ee(),".config","opencode","AGENTS.md");Mt(me(Ee(),".config","opencode"),{recursive:!0});let e=`${Tt}
128
+ `).all();for(let i of o){if(!Nt(n,i,t.project))continue;let d=k(i.id);if(d&&r.push(d),r.length>=(t.limit??100))break}}finally{n.close()}let s=[];for(let o of r)s.push(await Te({project:t.project,storage:t.storage,nativeSessionId:o,dbPath:e}));return s}import{existsSync as ys,mkdirSync as Lt,readFileSync as Ss,writeFileSync as Kt}from"node:fs";import{homedir as Ae}from"node:os";import{join as he}from"node:path";var $t="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",Re="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function vs(){let t=he(Ae(),".config","opencode","AGENTS.md");Lt(he(Ae(),".config","opencode"),{recursive:!0});let e=`${$t}
129
129
  ## ToolNet Memory \u2014 Project Continuity
130
130
 
131
131
  When the current workspace belongs to a ToolNet project, identified by a nearest ancestor containing \`.toolnet/project.json\`:
@@ -138,10 +138,10 @@ When the current workspace belongs to a ToolNet project, identified by a nearest
138
138
  6. Never invent missing rationale. If ToolNet says a reason was not explicitly recorded, inspect the implementation or ask rather than guessing.
139
139
 
140
140
  This applies automatically to every ToolNet-managed project.
141
- ${Pe}`,n=Zr(t)?es(t,"utf8"):"",r=n.indexOf(Tt),s=n.indexOf(Pe);return r>=0&&s>=r?n=n.slice(0,r)+e+n.slice(s+Pe.length):(n=n.trimEnd(),n&&(n+=`
141
+ ${Re}`,n=ys(t)?Ss(t,"utf8"):"",r=n.indexOf($t),s=n.indexOf(Re);return r>=0&&s>=r?n=n.slice(0,r)+e+n.slice(s+Re.length):(n=n.trimEnd(),n&&(n+=`
142
142
 
143
- `),n+=e),At(t,n.trimEnd()+`
144
- `,{encoding:"utf8",mode:384}),t}function Nt(t={}){let e=t.directory??me(Ee(),".config","opencode","plugins");Mt(e,{recursive:!0}),ts();let n=me(e,"toolnet-memory.js"),r=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",s=`// Generated by ToolNet Memory.
143
+ `),n+=e),Kt(t,n.trimEnd()+`
144
+ `,{encoding:"utf8",mode:384}),t}function Dt(t={}){let e=t.directory??he(Ae(),".config","opencode","plugins");Lt(e,{recursive:!0}),vs();let n=he(e,"toolnet-memory.js"),r=t.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",s=`// Generated by ToolNet Memory.
145
145
  // OpenCode session capture + continuity bootstrap.
146
146
 
147
147
  function getSessionId(event) {
@@ -298,17 +298,17 @@ export const ToolNetMemoryPlugin = async ({ directory }) => {
298
298
  },
299
299
  }
300
300
  }
301
- `;return At(n,s,{encoding:"utf8",mode:384}),n}import{existsSync as Ta,mkdirSync as os,readFileSync as Ma,writeFileSync as is}from"node:fs";import{dirname as as,join as $t}from"node:path";function Ce(t){if(!t)return 0;let e=Array.from(t).length,n=t.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,n*1.3))}function b(t,e){let n=t.replace(/\s+/g," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function ns(t){let e=[],n=!1;for(let r of t.split(/\r?\n/u)){let s=r.trim();if(s.includes("<!--")&&(n=!0),n){s.includes("-->")&&(n=!1);continue}let o=s.toLowerCase();if(!(!s||s.startsWith("#")||s==="```"||o.startsWith("- [enforce]")||o.startsWith("* [enforce]")||o.startsWith("- [advisory]")||o.startsWith("* [advisory]"))&&(s=s.replace(/^[-*]\s+/u,""),s&&e.push(b(s,280)),e.length>=16))break}return e}function rs(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.trim(),o=s.toLowerCase(),d=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(c=>o.startsWith(c));if(!d)continue;let a=s.slice(d.length).trim();a&&(d.includes("enforce")?e.push(a):n.push(a))}return{enforce:e,advisory:n}}function ss(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
302
- `);if(Ce(s)<=e){n.push(r);continue}let o=Ce(n.join(`
301
+ `;return Kt(n,s,{encoding:"utf8",mode:384}),n}import{existsSync as sc,mkdirSync as js,readFileSync as oc,writeFileSync as xs}from"node:fs";import{dirname as Is,join as Bt}from"node:path";function Me(t){if(!t)return 0;let e=Array.from(t).length,n=t.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,n*1.3))}function b(t,e){let n=t.replace(/\s+/g," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function bs(t){let e=[],n=!1;for(let r of t.split(/\r?\n/u)){let s=r.trim();if(s.includes("<!--")&&(n=!0),n){s.includes("-->")&&(n=!1);continue}let o=s.toLowerCase();if(!(!s||s.startsWith("#")||s==="```"||o.startsWith("- [enforce]")||o.startsWith("* [enforce]")||o.startsWith("- [advisory]")||o.startsWith("* [advisory]"))&&(s=s.replace(/^[-*]\s+/u,""),s&&e.push(b(s,280)),e.length>=16))break}return e}function ks(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.trim(),o=s.toLowerCase(),d=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(c=>o.startsWith(c));if(!d)continue;let a=s.slice(d.length).trim();a&&(d.includes("enforce")?e.push(a):n.push(a))}return{enforce:e,advisory:n}}function ws(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
302
+ `);if(Me(s)<=e){n.push(r);continue}let o=Me(n.join(`
303
303
  `)),i=Math.max(0,e-o);if(i>=16){let d=Math.floor(i*3.2),a=b(r,d);a&&n.push(a)}break}return n.join(`
304
- `).trim()}async function _t(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=de(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=rs(r),o=n?n.rules.filter(l=>l.mode==="enforce").map(l=>l.text):s.enforce,i=n?n.rules.filter(l=>l.mode==="advisory").map(l=>l.text):s.advisory,d=r?ns(r):[],a=await oe(t.project,t.storage),c=await yt(t.project,t.storage),p=await jt(t.project,t.storage),u=[];if(u.push("[TOOLNET PROJECT CONTEXT]"),u.push(`Project: ${t.project.name}`),u.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),r&&u.push(`Full operating manual: ${ue(t.project)}`),o.length){u.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let l of o.slice(0,24))u.push(`- [ENFORCE] ${b(l,240)}`)}if(i.length){u.push("","PROJECT PREFERENCES");for(let l of i.slice(0,10))u.push(`- ${b(l,220)}`)}if(c&&(c.mission&&u.push("","MISSION",b(c.mission.value,420)),c.activeObjective&&u.push("","CURRENT OBJECTIVE",b(c.activeObjective.value,420)),c.why&&u.push("","WHY THIS WORK MATTERS",b(c.why.value,420)),c.desiredOutcome&&u.push("","DESIRED OUTCOME",b(c.desiredOutcome.value,420)),c.planRationale&&u.push("","WHY THIS APPROACH",b(c.planRationale.value,420))),a){if(u.push("","ACTIVE WORK"),a.goal&&u.push(`Goal: ${b(a.goal,320)}`),a.plan&&u.push(`Plan: ${b(a.plan,320)}`),u.push(`Progress: phases ${a.progress.phasesCompleted}/${a.progress.phasesTotal}; tasks ${a.progress.tasksCompleted}/${a.progress.tasksTotal}; blocked ${a.progress.blocked}`),a.currentPhase&&u.push(`Current phase: ${a.currentPhase.title} [${a.currentPhase.status}]`),a.currentPhase&&c){let l=c.phases.find(y=>y.order===a.currentPhase?.order);l&&(l.objective&&u.push(`Phase objective: ${b(l.objective.value,340)}`),l.why?u.push(`Why this phase: ${b(l.why.value,340)}`):u.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),l.deliverable&&u.push(`Deliverable: ${b(l.deliverable.value,340)}`),l.dependencies.length&&u.push(`Depends on: ${l.dependencies.slice(0,4).map(y=>b(y.value,180)).join("; ")}`),l.acceptanceCriteria.length&&(u.push("","DEFINITION OF DONE"),l.acceptanceCriteria.slice(0,6).forEach(y=>{u.push(`- ${b(y.value,260)}`)})),l.openQuestions.length&&(u.push("","OPEN QUESTIONS FOR CURRENT PHASE"),l.openQuestions.slice(0,4).forEach(y=>{u.push(`- ${b(y.value,260)}`)})))}a.currentTask&&u.push(`Current task: ${a.currentTask.title} [${a.currentTask.status}]`),a.nextActions.length&&(u.push("","NEXT ACTIONS"),a.nextActions.slice(0,6).forEach((l,y)=>{u.push(`${y+1}. ${b(l,260)}`)})),a.blockers.length&&(u.push("","BLOCKERS"),a.blockers.slice(0,5).forEach(l=>{u.push(`- ${b(l,260)}`)})),a.warnings.length&&(u.push("","ATTENTION"),a.warnings.slice(-5).forEach(l=>{u.push(`- ${b(l,260)}`)})),a.decisions.length&&(u.push("","RECENT DECISIONS"),a.decisions.slice(-5).forEach(l=>{u.push(`- ${b(l,260)}`)})),a.lastSession&&u.push("",`Last work session: ${a.lastSession.agent} / ${a.lastSession.nativeSessionId}`)}if(c&&c.openQuestions.length&&(u.push("","UNRESOLVED QUESTIONS"),c.openQuestions.slice(0,5).forEach(l=>{u.push(`- ${b(l.value,260)}`)})),p&&u.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),d.length){u.push("","OPERATING NOTES");for(let l of d)u.push(`- ${l}`)}u.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let g=ss(u,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:g,estimatedTokens:Ce(g),maxTokens:e,hasManual:!!r,hasWorkState:!!a,hasHandoff:!!p,generatedAt:new Date().toISOString()}}function cs(t){return $t(t.rootPath,".toolnet","context","startup.md")}function us(t){return $t(t.rootPath,".toolnet","context","startup.json")}function ds(t,e){let n=cs(t);os(as(n),{recursive:!0}),is(n,e.text.endsWith(`
304
+ `).trim()}async function Wt(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=pe(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=ks(r),o=n?n.rules.filter(l=>l.mode==="enforce").map(l=>l.text):s.enforce,i=n?n.rules.filter(l=>l.mode==="advisory").map(l=>l.text):s.advisory,d=r?bs(r):[],a=await ie(t.project,t.storage),c=await kt(t.project,t.storage),p=await It(t.project,t.storage),u=[];if(u.push("[TOOLNET PROJECT CONTEXT]"),u.push(`Project: ${t.project.name}`),u.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),r&&u.push(`Full operating manual: ${de(t.project)}`),o.length){u.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let l of o.slice(0,24))u.push(`- [ENFORCE] ${b(l,240)}`)}if(i.length){u.push("","PROJECT PREFERENCES");for(let l of i.slice(0,10))u.push(`- ${b(l,220)}`)}if(c&&(c.mission&&u.push("","MISSION",b(c.mission.value,420)),c.activeObjective&&u.push("","CURRENT OBJECTIVE",b(c.activeObjective.value,420)),c.why&&u.push("","WHY THIS WORK MATTERS",b(c.why.value,420)),c.desiredOutcome&&u.push("","DESIRED OUTCOME",b(c.desiredOutcome.value,420)),c.planRationale&&u.push("","WHY THIS APPROACH",b(c.planRationale.value,420))),a){if(u.push("","ACTIVE WORK"),a.goal&&u.push(`Goal: ${b(a.goal,320)}`),a.plan&&u.push(`Plan: ${b(a.plan,320)}`),u.push(`Progress: phases ${a.progress.phasesCompleted}/${a.progress.phasesTotal}; tasks ${a.progress.tasksCompleted}/${a.progress.tasksTotal}; blocked ${a.progress.blocked}`),a.currentPhase&&u.push(`Current phase: ${a.currentPhase.title} [${a.currentPhase.status}]`),a.currentPhase&&c){let l=c.phases.find(S=>S.order===a.currentPhase?.order);l&&(l.objective&&u.push(`Phase objective: ${b(l.objective.value,340)}`),l.why?u.push(`Why this phase: ${b(l.why.value,340)}`):u.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),l.deliverable&&u.push(`Deliverable: ${b(l.deliverable.value,340)}`),l.dependencies.length&&u.push(`Depends on: ${l.dependencies.slice(0,4).map(S=>b(S.value,180)).join("; ")}`),l.acceptanceCriteria.length&&(u.push("","DEFINITION OF DONE"),l.acceptanceCriteria.slice(0,6).forEach(S=>{u.push(`- ${b(S.value,260)}`)})),l.openQuestions.length&&(u.push("","OPEN QUESTIONS FOR CURRENT PHASE"),l.openQuestions.slice(0,4).forEach(S=>{u.push(`- ${b(S.value,260)}`)})))}a.currentTask&&u.push(`Current task: ${a.currentTask.title} [${a.currentTask.status}]`),a.nextActions.length&&(u.push("","NEXT ACTIONS"),a.nextActions.slice(0,6).forEach((l,S)=>{u.push(`${S+1}. ${b(l,260)}`)})),a.blockers.length&&(u.push("","BLOCKERS"),a.blockers.slice(0,5).forEach(l=>{u.push(`- ${b(l,260)}`)})),a.warnings.length&&(u.push("","ATTENTION"),a.warnings.slice(-5).forEach(l=>{u.push(`- ${b(l,260)}`)})),a.decisions.length&&(u.push("","RECENT DECISIONS"),a.decisions.slice(-5).forEach(l=>{u.push(`- ${b(l,260)}`)})),a.lastSession&&u.push("",`Last work session: ${a.lastSession.agent} / ${a.lastSession.nativeSessionId}`)}if(c&&c.openQuestions.length&&(u.push("","UNRESOLVED QUESTIONS"),c.openQuestions.slice(0,5).forEach(l=>{u.push(`- ${b(l.value,260)}`)})),p&&u.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),d.length){u.push("","OPERATING NOTES");for(let l of d)u.push(`- ${l}`)}u.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let g=ws(u,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:g,estimatedTokens:Me(g),maxTokens:e,hasManual:!!r,hasWorkState:!!a,hasHandoff:!!p,generatedAt:new Date().toISOString()}}function Os(t){return Bt(t.rootPath,".toolnet","context","startup.md")}function Es(t){return Bt(t.rootPath,".toolnet","context","startup.json")}function Ps(t,e){let n=Os(t);js(Is(n),{recursive:!0}),xs(n,e.text.endsWith(`
305
305
  `)?e.text:e.text+`
306
- `,{encoding:"utf8",mode:384}),x(us(t),e)}async function Lt(t,e,n=900){let r=await _t({project:t,storage:e,maxTokens:n}),s={version:1,projectId:t.id,projectName:t.name,text:r.text,digest:v(r.text),estimatedTokens:r.estimatedTokens,generatedAt:new Date().toISOString()};return ds(t,s),await e.put(`projects/${t.id}/context/startup.md`,s.text+`
306
+ `,{encoding:"utf8",mode:384}),I(Es(t),e)}async function Ft(t,e,n=900){let r=await Wt({project:t,storage:e,maxTokens:n}),s={version:1,projectId:t.id,projectName:t.name,text:r.text,digest:v(r.text),estimatedTokens:r.estimatedTokens,generatedAt:new Date().toISOString()};return Ps(t,s),await e.put(`projects/${t.id}/context/startup.md`,s.text+`
307
307
  `,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(s,null,2)+`
308
- `,"application/json"),s}function ge(t,e){let n=t.indexOf(e);if(!(n<0))return t[n+1]}function Re(t,e){return t.includes(e)}function ps(t){let e=Ae(),n=Ke(Fe({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new Q(n,t.id,t.name,t.remote??t.name)}async function ls(){let[t="help",...e]=process.argv.slice(2);if(t==="install-plugin"){let i=Nt({binary:ge(e,"--bin")});console.log(`\u2705 OpenCode plugin installed: ${i}`),console.log("OpenCode will load it automatically on next start.");return}let n=ge(e,"--project")??process.cwd(),r=new U().detect(n),s=ps(r),o=ge(e,"--db");if(t==="sync"){let i=e.find(u=>!u.startsWith("--")&&u!==n&&u!==o);if(!i)throw new Error("Usage: session:opencode-sync <session-id>");let d=Re(e,"--idle"),a=Re(e,"--error"),c=Re(e,"--compacted"),p=await Oe({project:r,storage:s,nativeSessionId:i,dbPath:o,idle:d,error:a,compacted:c});if(d||c||a)try{await Lt(r,s,900)}catch{}console.log(JSON.stringify(p,null,2));return}if(t==="recover"){let i=ge(e,"--limit"),d=i?Number(i):100,a=await Rt({project:r,storage:s,dbPath:o,limit:Number.isFinite(d)?d:100});console.log(JSON.stringify({project:r.name,sessions:a.length,importedMessages:a.reduce((c,p)=>c+p.importedMessages,0),importedParts:a.reduce((c,p)=>c+p.importedParts,0)},null,2));return}console.log(`OpenCode Session Adapter
308
+ `,"application/json"),s}function ye(t,e){let n=t.indexOf(e);if(!(n<0))return t[n+1]}function Ne(t,e){return t.includes(e)}function Cs(t){let e=Le(),n=Ue(Je({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new X(n,t.id,t.name,t.remote??t.name)}async function Ts(){let[t="help",...e]=process.argv.slice(2);if(t==="install-plugin"){let i=Dt({binary:ye(e,"--bin")});console.log(`\u2705 OpenCode plugin installed: ${i}`),console.log("OpenCode will load it automatically on next start.");return}let n=ye(e,"--project")??process.cwd(),r=new H().detect(n),s=Cs(r),o=ye(e,"--db");if(t==="sync"){let i=e.find(u=>!u.startsWith("--")&&u!==n&&u!==o);if(!i)throw new Error("Usage: session:opencode-sync <session-id>");let d=Ne(e,"--idle"),a=Ne(e,"--error"),c=Ne(e,"--compacted"),p=await Te({project:r,storage:s,nativeSessionId:i,dbPath:o,idle:d,error:a,compacted:c});if(d||c||a)try{await Ft(r,s,900)}catch{}console.log(JSON.stringify(p,null,2));return}if(t==="recover"){let i=ye(e,"--limit"),d=i?Number(i):100,a=await _t({project:r,storage:s,dbPath:o,limit:Number.isFinite(d)?d:100});console.log(JSON.stringify({project:r.name,sessions:a.length,importedMessages:a.reduce((c,p)=>c+p.importedMessages,0),importedParts:a.reduce((c,p)=>c+p.importedParts,0)},null,2));return}console.log(`OpenCode Session Adapter
309
309
 
310
310
  Commands:
311
311
  sync <session-id> [--project PATH] [--idle]
312
312
  recover [--project PATH] [--limit N]
313
313
  install-plugin [--bin PATH]
314
- `)}ls().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});
314
+ `)}Ts().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});