toolnet-memory 0.2.11 → 0.2.12

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,12 +1,12 @@
1
- import{existsSync as At,readFileSync as Rt}from"node:fs";import{homedir as Tt}from"node:os";import{join as Nt}from"node:path";function Ct(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 Mt(){let t=process.env.TOOLNET_GLOBAL_ENV??Nt(Tt(),".config","toolnet-memory",".env");if(!At(t))return;let e=Rt(t,"utf8");for(let r of e.split(/\r?\n/)){let n=r.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let s=n.indexOf("=");if(s<=0)continue;let o=n.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=Ct(n.slice(s+1)))}}Mt();function K(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function z(t,e){if(!t)return e;let r=Number(t);return Number.isFinite(r)?r:e}function Ee(){return{memory:{autoCapture:K(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:K(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:K(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:K(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:z(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:z(process.env.MEMORY_RERANK_TOP,10),finalContext:z(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:z(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:K(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:z(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as _t}from"node:crypto";import{existsSync as fe,mkdirSync as $t,readFileSync as Lt,renameSync as Kt,writeFileSync as zt}from"node:fs";import{basename as Wt,dirname as J,join as U,parse as Te,resolve as W}from"node:path";var Ne=".toolnet",Dt="project.json";function Bt(t){return _t("sha256").update(t).digest("hex").slice(0,16)}function me(t){return U(t,Ne,Dt)}function Ft(t){return fe(me(t))}function qt(t,e){let r=W(t),n=Te(r).root;for(;;){if(Ft(r))return r;if(r===n||e&&r===W(e))break;let s=J(r);if(s===r)break;r=s}return null}function Jt(t){let e=W(t),r=Te(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(o=>fe(U(e,o))))return e;if(e===r)break;let s=J(e);if(s===e)break;e=s}return W(t)}function Vt(t){let e;try{e=JSON.parse(Lt(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 r=e;if(typeof r.id!="string"||!r.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof r.name!="string"||!r.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let n=new Date().toISOString();return{version:1,id:r.id,name:r.name,remote:typeof r.remote=="string"&&r.remote.trim()?r.remote:r.name,rootPath:typeof r.rootPath=="string"?r.rootPath:J(J(t)),createdAt:typeof r.createdAt=="string"?r.createdAt:n,updatedAt:typeof r.updatedAt=="string"?r.updatedAt:n,graphVersion:typeof r.graphVersion=="number"?r.graphVersion:0,memoryVersion:typeof r.memoryVersion=="number"?r.memoryVersion:0,metadata:r.metadata&&typeof r.metadata=="object"?r.metadata:void 0}}function Ae(t,e){let r=U(t,Ne);$t(r,{recursive:!0});let n=me(t),s=`${n}.tmp-${process.pid}`;zt(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Kt(s,n)}function Re(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var V=class{detect(e=process.cwd()){let r=W(e),n=Jt(r),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>fe(U(n,f))),i=qt(r,o?n:void 0);if(i){let f=me(i),u=Vt(f);return u.rootPath!==i&&(u.rootPath=i,u.updatedAt=new Date().toISOString(),Ae(i,u)),Re(u,i)}let l=new Date().toISOString(),a=Wt(n),c={version:1,id:Bt(n),name:a,remote:a,rootPath:n,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return Ae(n,c),Re(c,n)}};var Ut=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],H=class{scan(e){let r=[];for(let n of Ut){let s=new RegExp(n.regex.source,n.regex.flags);for(let o of e.matchAll(s))r.push({type:n.type,value:o[0]})}return r}hasSecrets(e){return this.scan(e).length>0}};var D=class{scanner=new H;sanitize(e){let r=e,n=this.scanner.scan(e),s=new Set;for(let o of n)s.add(o.type),r=r.split(o.value).join(`[REDACTED:${o.type}]`);return{text:r,redacted:n.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(r=>this.sanitizeValue(r));if(e&&typeof e=="object"){let r={};for(let[n,s]of Object.entries(e)){let o=n.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?r[n]="[REDACTED]":r[n]=this.sanitizeValue(s)}return r}return e}};import{homedir as hr}from"node:os";import{join as yr}from"node:path";import{DeleteObjectCommand as Ht,GetObjectCommand as Yt,HeadObjectCommand as Gt,ListObjectsV2Command as Qt,PutObjectCommand as Xt,S3Client as Zt}from"@aws-sdk/client-s3";import{getSignedUrl as er}from"@aws-sdk/s3-request-presigner";var Y=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Zt({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,r,n="application/octet-stream"){let s=typeof r=="string"?Buffer.from(r,"utf8"):r;await this.client.send(new Xt({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await er(this.client,new Yt({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(r,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await this.client.send(new Gt({Bucket:this.bucket,Key:e})),!0}catch(r){if(typeof r=="object"&&r!==null&&"$metadata"in r&&r.$metadata?.httpStatusCode===404)return!1;throw r}}async delete(e){await this.client.send(new Ht({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new Qt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let o of s.Contents??[])o.Key&&r.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return r}};import{access as Ce,mkdir as tr,readFile as rr,readdir as nr,rm as sr,stat as Me,writeFile as or}from"node:fs/promises";import{dirname as ir,join as ar,relative as _e,resolve as cr}from"node:path";var B=class{constructor(e){this.root=e}root;name="local";path(e){let r=e.replace(/^\/+/,"");return cr(this.root,r)}async put(e,r){let n=this.path(e);await tr(ir(n),{recursive:!0}),await or(n,r)}async get(e){try{return await rr(this.path(e))}catch(r){if(typeof r=="object"&&r!==null&&"code"in r&&r.code==="ENOENT")return null;throw r}}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await Ce(this.path(e)),!0}catch{return!1}}async delete(e){await sr(this.path(e),{force:!0})}async list(e=""){let r=this.path(e),n=[];try{await Ce(r)}catch{return n}let s=async i=>{let l=await nr(i,{withFileTypes:!0});for(let a of l){let c=ar(i,a.name);if(a.isDirectory()){await s(c);continue}let f=await Me(c);n.push({key:_e(this.root,c),size:f.size,updatedAt:f.mtime.toISOString()})}},o=await Me(r);return o.isDirectory()?await s(r):n.push({key:_e(this.root,r),size:o.size,updatedAt:o.mtime.toISOString()}),n}};import{DeleteObjectCommand as ur,GetObjectCommand as lr,HeadObjectCommand as pr,ListObjectsV2Command as dr,PutObjectCommand as fr,S3Client as mr}from"@aws-sdk/client-s3";import{getSignedUrl as gr}from"@aws-sdk/s3-request-presigner";var F=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new mr({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,r,n="application/octet-stream"){let s=typeof r=="string"?Buffer.from(r,"utf8"):r;await this.client.send(new fr({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await gr(this.client,new lr({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(r,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`${this.name} download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await this.client.send(new pr({Bucket:this.bucket,Key:e})),!0}catch(r){if(typeof r=="object"&&r!==null&&"$metadata"in r&&r.$metadata?.httpStatusCode===404)return!1;throw r}}async delete(e){await this.client.send(new ur({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new dr({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let o of s.Contents??[])o.Key&&r.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return r}};function ge(t,e){return console.warn(e),new B(t)}function $e(t){let e=t.localRoot??yr(hr(),".toolnet-memory","storage");if(t.provider==="r2"){let r=t.r2;return r?.accountId&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new F({name:"r2",endpoint:`https://${r.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:r.bucket,forcePathStyle:!0,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):ge(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let r=t.s3;return r?.bucket&&r.accessKeyId&&r.secretAccessKey?new F({name:"s3",endpoint:r.endpoint,region:r.region??"us-east-1",bucket:r.bucket,forcePathStyle:r.forcePathStyle??!1,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):ge(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let r=t.huggingface;return r?.namespace&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new Y({namespace:r.namespace,bucket:r.bucket,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):ge(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new B(e)}function Sr(t){return new Promise(e=>setTimeout(e,t))}async function Le(t,e={}){let r=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=r;i++)try{return await t()}catch(l){if(o=l,i>=r)break;let a=Math.min(s,n*2**(i-1)),c=Math.floor(Math.random()*Math.max(1,a*.2));await Sr(a+c)}throw o}var vr=new Set(["put","get","getText","delete","list"]);function Ke(t,e={}){return new Proxy(t,{get(r,n){let s=Reflect.get(r,n,r);return typeof s!="function"?s:vr.has(n)?(...o)=>Le(()=>Promise.resolve(s.apply(r,o)),e):s.bind(r)}})}function ze(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 We(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 r=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var G=class{constructor(e,r,n,s){this.provider=e;this.name=e.name,this.projectId=r,this.projectName=n,this.folder=ze(s??n),this.sourcePrefix=`projects/${r}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,r=new Date().toISOString(),n=r,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}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"&&(n=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:r};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=We(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,r,n){return await this.ensureRegistered(),this.provider.put(this.key(e),r,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{createHash as kr}from"node:crypto";import{dirname as br}from"node:path";import{mkdirSync as wr,readFileSync as jr,renameSync as xr,writeFileSync as Ir}from"node:fs";function v(t){return kr("sha256").update(t).digest("hex")}function he(t){if(Array.isArray(t))return t.map(he);if(t&&typeof t=="object"){let e=t,r={};for(let n of Object.keys(e).sort())r[n]=he(e[n]);return r}return t}function De(t){return JSON.stringify(he(t))}function Be(t){try{return JSON.parse(jr(t,"utf8"))}catch{return null}}function x(t,e){wr(br(t),{recursive:!0});let r=`${t}.${process.pid}.tmp`;Ir(r,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),xr(r,t)}var Pr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function _(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function qe(t){return _(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function M(t,e,r=0){if(!(r>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let n of t.slice(0,50))M(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(Pr.has(n)||["data","payload","parts","messages"].includes(n))&&M(s,e,r+1)}}function Q(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 Fe(t){let e=_(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function w(t,e,r,n,s={}){let o=_(n),i=s.key??qe(o);return{version:1,id:v([t.projectId,r,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:r,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 Or(t,e,r){let n=_(r);if(n.length<5||n.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(n),i=n.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(w(t,e,"goal",i[1],{confidence:.97}));let l=n.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);l?.[1]&&s.push(w(t,e,"plan",l[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(n));){let m=Number(c[1]),p=_(c[2]??""),y=p&&!Fe(p)?`Phase ${m} - ${p}`:`Phase ${m}`;s.push(w(t,e,"phase",y,{key:`phase:${m}`,order:m,status:Q(n),confidence:.93}))}let f=r.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);f?.[2]&&s.push(w(t,e,"task",f[2],{status:f[1].trim()?"completed":Q(f[2]),confidence:.96}));let u=n.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(u?.[2]){let m=u[1]?Number(u[1]):void 0,p=_(u[2]),y=Fe(p);s.push(w(t,e,"task",y&&m!==void 0?`TODO ${m}`:p,{key:m!==void 0?`task:${m}`:qe(p),order:m,status:Q(n),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(n)){let m=n.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");m&&s.push(w(t,e,"next_action",m,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(n)&&s.push(w(t,e,"blocker",n,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(n)&&s.push(w(t,e,"warning",n,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(n)&&s.push(w(t,e,"decision",n,{confidence:.9})),s}function Je(t,e){if(e.length===0)return[];let r=[],n=new Set;function s(i){n.has(i.id)||(n.add(i.id),r.push(i))}for(let i of e){if(i.type==="decision"){let a=[];M(i.data,a);for(let c of a)s(w(t,i,"decision",c,{confidence:1}))}if(i.type==="todo"){let a=[];M(i.data,a);for(let c of a)s(w(t,i,"task",c,{status:Q(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=[];M(i.data,a);for(let c of a)s(w(t,i,"test",c,{confidence:1}))}let l=[];M(i.data,l);for(let a of l)for(let c of a.split(/\n+/u))for(let f of Or(t,i,c))s(f)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),r}function Ve(t){return String(t).padStart(12,"0")}var X=class{constructor(e){this.storage=e}storage;async write(e,r){if(r.length===0)return null;let n=Math.min(...r.map(c=>c.sequence)),s=Math.max(...r.map(c=>c.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:n,lastSequence:s,observations:r},i=JSON.stringify(o,null,2)+`
6
- `,l=v(r.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Ve(n)}-${Ve(s)}-${l}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,i,"application/json"),a}};import{join as Ue}from"node:path";import{mkdirSync as Er}from"node:fs";function Ar(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(t,e=20){let r=[],n=new Set;for(let s of t.slice().reverse()){let o=Ar(s);if(!(!o||n.has(o))&&(n.add(o),r.push(s),r.length>=e))break}return r.reverse()}function Rr(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 He(t,e){let r=e.status??t?.status??"pending",n=r;t&&(t.status==="completed"&&r!=="completed"?n="completed":r==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(n=t.status));let s=t&&Rr(e)?t.title:e.text;return{id:t?.id??v(e.key).slice(0,24),title:s,status:n,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 Tr(t,e){let r=`projects/${t.id}/work/observations/`,n=await e.list(r),s=[];for(let o of n.filter(i=>i.key.endsWith(".json")).sort((i,l)=>i.key.localeCompare(l.key))){let i=await e.getText(o.key);if(i)try{let l=JSON.parse(i);l.version===1&&Array.isArray(l.observations)&&s.push(l)}catch{}}return s}async function Z(t,e){let n=(await Tr(t,e)).flatMap(d=>d.observations).sort((d,j)=>{let Pe=d.occurredAt.localeCompare(j.occurredAt);if(Pe!==0)return Pe;let Oe=d.sequence-j.sequence;return Oe!==0?Oe:d.id.localeCompare(j.id)}),s=new Map,o=new Map,i,l,a,c=[],f=[],u=[],m=[],p=[],y=[];for(let d of n)switch(d.kind){case"goal":i=d.text;break;case"plan":l=d.text;break;case"phase":s.set(d.key,He(s.get(d.key),d));break;case"task":o.set(d.key,He(o.get(d.key),d));break;case"decision":c.push(d.text);break;case"blocker":f.push(d.text);break;case"warning":u.push(d.text);break;case"next_action":m.push(d.text);break;case"file":p.push(d.text);break;case"test":y.push(d.text);break;case"session":a={agent:d.agent,nativeSessionId:d.nativeSessionId,sessionKey:d.sessionKey,updatedAt:d.occurredAt};break}let h=Array.from(s.values()).sort((d,j)=>(d.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((d,j)=>(d.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),S=h.find(d=>d.status==="in_progress")??h.find(d=>d.status==="blocked")??h.find(d=>d.status==="pending"),b=g.find(d=>d.status==="in_progress")??g.find(d=>d.status==="blocked")??g.find(d=>d.status==="pending"),T=$([...m,...b?[b.title]:[],...!b&&S?[S.title]:[],...g.filter(d=>d.status==="pending").slice(0,5).map(d=>d.title)],8),C=$([...f,...h.filter(d=>d.status==="blocked").map(d=>d.title),...g.filter(d=>d.status==="blocked").map(d=>d.title)],20),E={version:1,projectId:t.id,projectName:t.name,goal:i,plan:l,phases:h,tasks:g,decisions:$(c,20),blockers:C,warnings:$(u,20),nextActions:T,filesTouched:$(p,30),tests:$(y,20),currentPhase:S,currentTask:b,progress:{phasesTotal:h.length,phasesCompleted:h.filter(d=>d.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(d=>d.status==="completed").length,blocked:h.filter(d=>d.status==="blocked").length+g.filter(d=>d.status==="blocked").length},lastSession:a,updatedAt:n.length?n[n.length-1].occurredAt:new Date().toISOString()},N=Ue(t.rootPath,".toolnet","work");return Er(N,{recursive:!0}),x(Ue(N,"current.json"),E),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(E,null,2)+`
7
- `,"application/json"),E}async function ee(t,e){let r=await e.getText(`projects/${t.id}/work/current.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}import{closeSync as Nr,existsSync as Cr,openSync as Mr,readSync as _r,statSync as $r}from"node:fs";function Lr(t,e){if(!Cr(t))return{events:[],nextOffset:e};let r=$r(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=r-n,o=Buffer.alloc(s),i=Mr(t,"r");try{_r(i,o,0,s,n)}finally{Nr(i)}let l=o.toString("utf8"),a=l.lastIndexOf(`
8
- `);if(a<0)return{events:[],nextOffset:n};let c=l.slice(0,a+1);return{events:c.split(`
9
- `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(c,"utf8")}}var te=class{constructor(e){this.options=e;this.journal=new X(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),r=Number(e.sourceCursors["work.continuity.offset"]??0),n=Lr(this.options.wal.eventsFile,Number.isFinite(r)?r:0);if(n.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:n.nextOffset};let s=Je(this.options.identity,n.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Z(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",n.nextOffset),{scannedEvents:n.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:n.nextOffset}}};import{mkdirSync as Ur}from"node:fs";import{join as ye}from"node:path";import{existsSync as Qe,mkdirSync as Kr,readFileSync as zr,statSync as Ye,writeFileSync as Wr}from"node:fs";import{dirname as Dr,join as Br}from"node:path";var Ge=64*1024,Fr=`# ToolNet Project Operating Manual
1
+ import{existsSync as Lt,readFileSync as Dt}from"node:fs";import{homedir as Kt}from"node:os";import{join as Ft}from"node:path";function Wt(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 zt(){let t=process.env.TOOLNET_GLOBAL_ENV??Ft(Kt(),".config","toolnet-memory",".env");if(!Lt(t))return;let e=Dt(t,"utf8");for(let r of e.split(/\r?\n/)){let n=r.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let s=n.indexOf("=");if(s<=0)continue;let o=n.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=Wt(n.slice(s+1)))}}zt();function K(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function F(t,e){if(!t)return e;let r=Number(t);return Number.isFinite(r)?r:e}function V(){return{memory:{autoCapture:K(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:K(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:K(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:K(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:F(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:F(process.env.MEMORY_RERANK_TOP,10),finalContext:F(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:F(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:K(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:F(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Bt}from"node:crypto";import{existsSync as ye,mkdirSync as qt,readFileSync as Jt,renameSync as Vt,writeFileSync as Ut}from"node:fs";import{basename as Ht,dirname as U,join as Y,parse as Ne,resolve as W}from"node:path";var _e=".toolnet",Yt="project.json";function Gt(t){return Bt("sha256").update(t).digest("hex").slice(0,16)}function Se(t){return Y(t,_e,Yt)}function Qt(t){return ye(Se(t))}function Xt(t,e){let r=W(t),n=Ne(r).root;for(;;){if(Qt(r))return r;if(r===n||e&&r===W(e))break;let s=U(r);if(s===r)break;r=s}return null}function Zt(t){let e=W(t),r=Ne(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(o=>ye(Y(e,o))))return e;if(e===r)break;let s=U(e);if(s===e)break;e=s}return W(t)}function er(t){let e;try{e=JSON.parse(Jt(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 r=e;if(typeof r.id!="string"||!r.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof r.name!="string"||!r.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let n=new Date().toISOString();return{version:1,id:r.id,name:r.name,remote:typeof r.remote=="string"&&r.remote.trim()?r.remote:r.name,rootPath:typeof r.rootPath=="string"?r.rootPath:U(U(t)),createdAt:typeof r.createdAt=="string"?r.createdAt:n,updatedAt:typeof r.updatedAt=="string"?r.updatedAt:n,graphVersion:typeof r.graphVersion=="number"?r.graphVersion:0,memoryVersion:typeof r.memoryVersion=="number"?r.memoryVersion:0,metadata:r.metadata&&typeof r.metadata=="object"?r.metadata:void 0}}function Re(t,e){let r=Y(t,_e);qt(r,{recursive:!0});let n=Se(t),s=`${n}.tmp-${process.pid}`;Ut(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Vt(s,n)}function Ce(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 r=W(e),n=Zt(r),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>ye(Y(n,d))),i=Xt(r,o?n:void 0);if(i){let d=Se(i),l=er(d);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),Re(i,l)),Ce(l,i)}let u=new Date().toISOString(),c=Ht(n),a={version:1,id:Gt(n),name:c,remote:c,rootPath:n,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return Re(n,a),Ce(a,n)}};var tr=[{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 r=[];for(let n of tr){let s=new RegExp(n.regex.source,n.regex.flags);for(let o of e.matchAll(s))r.push({type:n.type,value:o[0]})}return r}hasSecrets(e){return this.scan(e).length>0}};var z=class{scanner=new G;sanitize(e){let r=e,n=this.scanner.scan(e),s=new Set;for(let o of n)s.add(o.type),r=r.split(o.value).join(`[REDACTED:${o.type}]`);return{text:r,redacted:n.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(r=>this.sanitizeValue(r));if(e&&typeof e=="object"){let r={};for(let[n,s]of Object.entries(e)){let o=n.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?r[n]="[REDACTED]":r[n]=this.sanitizeValue(s)}return r}return e}};import{homedir as xr}from"node:os";import{join as Ir}from"node:path";import{DeleteObjectCommand as rr,GetObjectCommand as nr,HeadObjectCommand as sr,ListObjectsV2Command as or,PutObjectCommand as ir,S3Client as ar}from"@aws-sdk/client-s3";import{getSignedUrl as cr}from"@aws-sdk/s3-request-presigner";var Q=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new ar({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,r,n="application/octet-stream"){let s=typeof r=="string"?Buffer.from(r,"utf8"):r;await this.client.send(new ir({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await cr(this.client,new nr({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(r,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await this.client.send(new sr({Bucket:this.bucket,Key:e})),!0}catch(r){if(typeof r=="object"&&r!==null&&"$metadata"in r&&r.$metadata?.httpStatusCode===404)return!1;throw r}}async delete(e){await this.client.send(new rr({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new or({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let o of s.Contents??[])o.Key&&r.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return r}};import{access as $e,mkdir as ur,readFile as lr,readdir as pr,rm as dr,stat as Le,writeFile as fr}from"node:fs/promises";import{dirname as mr,join as gr,relative as De,resolve as hr}from"node:path";var B=class{constructor(e){this.root=e}root;name="local";path(e){let r=e.replace(/^\/+/,"");return hr(this.root,r)}async put(e,r){let n=this.path(e);await ur(mr(n),{recursive:!0}),await fr(n,r)}async get(e){try{return await lr(this.path(e))}catch(r){if(typeof r=="object"&&r!==null&&"code"in r&&r.code==="ENOENT")return null;throw r}}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await $e(this.path(e)),!0}catch{return!1}}async delete(e){await dr(this.path(e),{force:!0})}async list(e=""){let r=this.path(e),n=[];try{await $e(r)}catch{return n}let s=async i=>{let u=await pr(i,{withFileTypes:!0});for(let c of u){let a=gr(i,c.name);if(c.isDirectory()){await s(a);continue}let d=await Le(a);n.push({key:De(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await Le(r);return o.isDirectory()?await s(r):n.push({key:De(this.root,r),size:o.size,updatedAt:o.mtime.toISOString()}),n}};import{DeleteObjectCommand as yr,GetObjectCommand as Sr,HeadObjectCommand as vr,ListObjectsV2Command as br,PutObjectCommand as kr,S3Client as wr}from"@aws-sdk/client-s3";import{getSignedUrl as jr}from"@aws-sdk/s3-request-presigner";var q=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new wr({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,r,n="application/octet-stream"){let s=typeof r=="string"?Buffer.from(r,"utf8"):r;await this.client.send(new kr({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await jr(this.client,new Sr({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(r,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`${this.name} download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let r=await this.get(e);return r?Buffer.from(r).toString("utf8"):null}async exists(e){try{return await this.client.send(new vr({Bucket:this.bucket,Key:e})),!0}catch(r){if(typeof r=="object"&&r!==null&&"$metadata"in r&&r.$metadata?.httpStatusCode===404)return!1;throw r}}async delete(e){await this.client.send(new yr({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new br({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let o of s.Contents??[])o.Key&&r.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return r}};function ve(t,e){return console.warn(e),new B(t)}function Ke(t){let e=t.localRoot??Ir(xr(),".toolnet-memory","storage");if(t.provider==="r2"){let r=t.r2;return r?.accountId&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new q({name:"r2",endpoint:`https://${r.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:r.bucket,forcePathStyle:!0,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):ve(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let r=t.s3;return r?.bucket&&r.accessKeyId&&r.secretAccessKey?new q({name:"s3",endpoint:r.endpoint,region:r.region??"us-east-1",bucket:r.bucket,forcePathStyle:r.forcePathStyle??!1,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):ve(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let r=t.huggingface;return r?.namespace&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new Q({namespace:r.namespace,bucket:r.bucket,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):ve(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new B(e)}function Pr(t){return new Promise(e=>setTimeout(e,t))}async function Fe(t,e={}){let r=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=r;i++)try{return await t()}catch(u){if(o=u,i>=r)break;let c=Math.min(s,n*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,c*.2));await Pr(c+a)}throw o}var Or=new Set(["put","get","getText","delete","list"]);function We(t,e={}){return new Proxy(t,{get(r,n){let s=Reflect.get(r,n,r);return typeof s!="function"?s:Or.has(n)?(...o)=>Fe(()=>Promise.resolve(s.apply(r,o)),e):s.bind(r)}})}function ze(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 Be(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 r=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var X=class{constructor(e,r,n,s){this.provider=e;this.name=e.name,this.projectId=r,this.projectName=n,this.folder=ze(s??n),this.sourcePrefix=`projects/${r}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,r=new Date().toISOString(),n=r,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(u){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${u instanceof Error?u.message:String(u)}`)}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"&&(n=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:r};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=Be(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,r,n){return await this.ensureRegistered(),this.provider.put(this.key(e),r,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{createHash as Er}from"node:crypto";import{dirname as Ar}from"node:path";import{mkdirSync as Tr,readFileSync as Mr,renameSync as Rr,writeFileSync as Cr}from"node:fs";function v(t){return Er("sha256").update(t).digest("hex")}function be(t){if(Array.isArray(t))return t.map(be);if(t&&typeof t=="object"){let e=t,r={};for(let n of Object.keys(e).sort())r[n]=be(e[n]);return r}return t}function qe(t){return JSON.stringify(be(t))}function Je(t){try{return JSON.parse(Mr(t,"utf8"))}catch{return null}}function x(t,e){Tr(Ar(t),{recursive:!0});let r=`${t}.${process.pid}.tmp`;Cr(r,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Rr(r,t)}var Nr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function $(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ue(t){return $(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function _(t,e,r=0){if(!(r>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let n of t.slice(0,50))_(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(Nr.has(n)||["data","payload","parts","messages"].includes(n))&&_(s,e,r+1)}}function Z(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function Ve(t){let e=$(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function w(t,e,r,n,s={}){let o=$(n),i=s.key??Ue(o);return{version:1,id:v([t.projectId,r,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:r,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 _r(t,e,r){let n=$(r);if(n.length<5||n.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(n),i=n.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(w(t,e,"goal",i[1],{confidence:.97}));let u=n.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);u?.[1]&&s.push(w(t,e,"plan",u[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=c.exec(n));){let f=Number(a[1]),p=$(a[2]??""),y=p&&!Ve(p)?`Phase ${f} - ${p}`:`Phase ${f}`;s.push(w(t,e,"phase",y,{key:`phase:${f}`,order:f,status:Z(n),confidence:.93}))}let d=r.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);d?.[2]&&s.push(w(t,e,"task",d[2],{status:d[1].trim()?"completed":Z(d[2]),confidence:.96}));let l=n.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let f=l[1]?Number(l[1]):void 0,p=$(l[2]),y=Ve(p);s.push(w(t,e,"task",y&&f!==void 0?`TODO ${f}`:p,{key:f!==void 0?`task:${f}`:Ue(p),order:f,status:Z(n),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(n)){let f=n.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");f&&s.push(w(t,e,"next_action",f,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(n)&&s.push(w(t,e,"blocker",n,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(n)&&s.push(w(t,e,"warning",n,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(n)&&s.push(w(t,e,"decision",n,{confidence:.9})),s}function He(t,e){if(e.length===0)return[];let r=[],n=new Set;function s(i){n.has(i.id)||(n.add(i.id),r.push(i))}for(let i of e){if(i.type==="decision"){let c=[];_(i.data,c);for(let a of c)s(w(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let c=[];_(i.data,c);for(let a of c)s(w(t,i,"task",a,{status:Z(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let a=i.data[c];typeof a=="string"&&a&&s(w(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let c=[];_(i.data,c);for(let a of c)s(w(t,i,"test",a,{confidence:1}))}let u=[];_(i.data,u);for(let c of u)for(let a of c.split(/\n+/u))for(let d of _r(t,i,a))s(d)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),r}function Ye(t){return String(t).padStart(12,"0")}var ee=class{constructor(e){this.storage=e}storage;async write(e,r){if(r.length===0)return null;let n=Math.min(...r.map(a=>a.sequence)),s=Math.max(...r.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:n,lastSequence:s,observations:r},i=JSON.stringify(o,null,2)+`
6
+ `,u=v(r.map(a=>a.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Ye(n)}-${Ye(s)}-${u}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Ge}from"node:path";import{mkdirSync as $r}from"node:fs";function Lr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function L(t,e=20){let r=[],n=new Set;for(let s of t.slice().reverse()){let o=Lr(s);if(!(!o||n.has(o))&&(n.add(o),r.push(s),r.length>=e))break}return r.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 Qe(t,e){let r=e.status??t?.status??"pending",n=r;t&&(t.status==="completed"&&r!=="completed"?n="completed":r==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(n=t.status));let s=t&&Dr(e)?t.title:e.text;return{id:t?.id??v(e.key).slice(0,24),title:s,status:n,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 Kr(t,e){let r=`projects/${t.id}/work/observations/`,n=await e.list(r),s=[];for(let o of n.filter(i=>i.key.endsWith(".json")).sort((i,u)=>i.key.localeCompare(u.key))){let i=await e.getText(o.key);if(i)try{let u=JSON.parse(i);u.version===1&&Array.isArray(u.observations)&&s.push(u)}catch{}}return s}async function te(t,e){let n=(await Kr(t,e)).flatMap(m=>m.observations).sort((m,j)=>{let Te=m.occurredAt.localeCompare(j.occurredAt);if(Te!==0)return Te;let Me=m.sequence-j.sequence;return Me!==0?Me:m.id.localeCompare(j.id)}),s=new Map,o=new Map,i,u,c,a=[],d=[],l=[],f=[],p=[],y=[];for(let m of n)switch(m.kind){case"goal":i=m.text;break;case"plan":u=m.text;break;case"phase":s.set(m.key,Qe(s.get(m.key),m));break;case"task":o.set(m.key,Qe(o.get(m.key),m));break;case"decision":a.push(m.text);break;case"blocker":d.push(m.text);break;case"warning":l.push(m.text);break;case"next_action":f.push(m.text);break;case"file":p.push(m.text);break;case"test":y.push(m.text);break;case"session":c={agent:m.agent,nativeSessionId:m.nativeSessionId,sessionKey:m.sessionKey,updatedAt:m.occurredAt};break}let h=Array.from(s.values()).sort((m,j)=>(m.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((m,j)=>(m.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),S=h.find(m=>m.status==="in_progress")??h.find(m=>m.status==="blocked")??h.find(m=>m.status==="pending"),k=g.find(m=>m.status==="in_progress")??g.find(m=>m.status==="blocked")??g.find(m=>m.status==="pending"),M=L([...f,...k?[k.title]:[],...!k&&S?[S.title]:[],...g.filter(m=>m.status==="pending").slice(0,5).map(m=>m.title)],8),N=L([...d,...h.filter(m=>m.status==="blocked").map(m=>m.title),...g.filter(m=>m.status==="blocked").map(m=>m.title)],20),E={version:1,projectId:t.id,projectName:t.name,goal:i,plan:u,phases:h,tasks:g,decisions:L(a,20),blockers:N,warnings:L(l,20),nextActions:M,filesTouched:L(p,30),tests:L(y,20),currentPhase:S,currentTask:k,progress:{phasesTotal:h.length,phasesCompleted:h.filter(m=>m.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(m=>m.status==="completed").length,blocked:h.filter(m=>m.status==="blocked").length+g.filter(m=>m.status==="blocked").length},lastSession:c,updatedAt:n.length?n[n.length-1].occurredAt:new Date().toISOString()},R=Ge(t.rootPath,".toolnet","work");return $r(R,{recursive:!0}),x(Ge(R,"current.json"),E),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(E,null,2)+`
7
+ `,"application/json"),E}async function re(t,e){let r=await e.getText(`projects/${t.id}/work/current.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}import{closeSync as Fr,existsSync as Wr,openSync as zr,readSync as Br,statSync as qr}from"node:fs";function Jr(t,e){if(!Wr(t))return{events:[],nextOffset:e};let r=qr(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=r-n,o=Buffer.alloc(s),i=zr(t,"r");try{Br(i,o,0,s,n)}finally{Fr(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
8
+ `);if(c<0)return{events:[],nextOffset:n};let a=u.slice(0,c+1);return{events:a.split(`
9
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(a,"utf8")}}var ne=class{constructor(e){this.options=e;this.journal=new ee(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),r=Number(e.sourceCursors["work.continuity.offset"]??0),n=Jr(this.options.wal.eventsFile,Number.isFinite(r)?r:0);if(n.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:n.nextOffset};let s=He(this.options.identity,n.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await te(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",n.nextOffset),{scannedEvents:n.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:n.nextOffset}}};import{mkdirSync as tn}from"node:fs";import{join as ke}from"node:path";import{existsSync as et,mkdirSync as Vr,readFileSync as Ur,statSync as Xe,writeFileSync as Hr}from"node:fs";import{dirname as Yr,join as Gr}from"node:path";var Ze=64*1024,Qr=`# ToolNet Project Operating Manual
10
10
 
11
11
  This file contains persistent instructions for AI agents working on this project.
12
12
 
@@ -49,30 +49,41 @@ Things an AI agent should always remember.
49
49
  <!--
50
50
  - [advisory] Prefer small focused files.
51
51
  -->
52
- `;function re(t){return Br(t.rootPath,".toolnet","PROJECT.md")}function qr(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Jr(t){let e=[],r=new Set,n=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=n.exec(t);){let o=s[1].toLowerCase(),i=qr(s[2]);if(!i)continue;let l=`${o}:${i.toLowerCase()}`;r.has(l)||(r.add(l),e.push({id:v(l).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Vr(t){let e=re(t);return Qe(e)||(Kr(Dr(e),{recursive:!0}),Wr(e,Fr,{encoding:"utf8",mode:384})),e}function ne(t,e=!1){let r=e?Vr(t):re(t);if(!Qe(r))return null;if(Ye(r).size>Ge)throw new Error(`PROJECT.md exceeds ${Ge} bytes`);let s=zr(r,"utf8");return{path:r,content:s,digest:v(s),rules:Jr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Ye(r).mtimeMs).toISOString()}}function Hr(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 Yr(t){return t.phases.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.tasks.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.nextActions.length>0||t.blockers.length>0}var se=class{constructor(e){this.options=e}options;async capture(e,r){let n=await ee(this.options.project,this.options.storage);if(n||(n=await Z(this.options.project,this.options.storage)),!Yr(n))return null;let s=ne(this.options.project,!1),o=s?s.rules.filter(m=>m.mode==="enforce").map(m=>m.text):[],i=v(JSON.stringify(Hr(n))),l=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),a=new Date().toISOString(),c={version:1,id:l,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:r},goal:n.goal,plan:n.plan,progress:n.progress,currentPhase:n.currentPhase,currentTask:n.currentTask,incompletePhases:n.phases.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),incompleteTasks:n.tasks.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),nextActions:n.nextActions.slice(0,10),blockers:n.blockers.slice(0,10),decisions:n.decisions.slice(-10),warnings:n.warnings.slice(-10),attention:[...o,...n.warnings].slice(0,20),filesTouched:n.filesTouched.slice(-20),tests:n.tests.slice(-15),stateDigest:i},f=`projects/${this.options.project.id}/work/handoffs/${l}.json`;await this.options.storage.exists(f)||await this.options.storage.put(f,JSON.stringify(c,null,2)+`
53
- `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(c,null,2)+`
54
- `,"application/json");let u=ye(this.options.project.rootPath,".toolnet","work","handoffs");return Ur(u,{recursive:!0}),x(ye(u,`${l}.json`),c),x(ye(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),c),c}};async function Xe(t,e){let r=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}import{mkdirSync as Gr}from"node:fs";import{join as Ze}from"node:path";function Qr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Xr(t,e){if(!e)return!0;let r=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return r!==0?r>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function A(t,e){return Xr(e,t)?e:t}function R(t,e=30){let r=new Set,n=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||r.has(o)||(r.add(o),n.push(s))}return n.slice(-e)}async function Zr(t,e){let r=`projects/${t.id}/work/semantic/observations/`,n=await e.list(r),s=[];for(let o of n.filter(i=>i.key.endsWith(".json")).sort((i,l)=>i.key.localeCompare(l.key))){let i=await e.getText(o.key);if(i)try{let l=JSON.parse(i);l.version===1&&Array.isArray(l.observations)&&s.push(l)}catch{}}return s}function en(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function et(t,e){let n=(await Zr(t,e)).flatMap(h=>h.observations).sort((h,g)=>{let S=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return S!==0?S:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),s,o,i,l,a,c=new Map,f=[],u=[],m=[];for(let h of n){let g=Qr(h);if(h.scope==="phase"&&h.scopeKey){let S=c.get(h.scopeKey)??en(h);switch(h.kind){case"phase_objective":S.objective=A(S.objective,g);break;case"phase_why":S.why=A(S.why,g);break;case"phase_deliverable":S.deliverable=A(S.deliverable,g);break;case"acceptance_criterion":S.acceptanceCriteria.push(g);break;case"dependency":S.dependencies.push(g);break;case"open_question":S.openQuestions.push(g);break;case"constraint":S.constraints.push(g);break;case"note":S.notes.push(g);break}c.set(S.key,S);continue}switch(h.kind){case"mission":s=A(s,g);break;case"objective":o=A(o,g);break;case"why":i=A(i,g);break;case"desired_outcome":l=A(l,g);break;case"plan_rationale":a=A(a,g);break;case"open_question":f.push(g);break;case"constraint":u.push(g);break;case"note":m.push(g);break}}for(let h of c.values())h.acceptanceCriteria=R(h.acceptanceCriteria,20),h.dependencies=R(h.dependencies,15),h.openQuestions=R(h.openQuestions,15),h.constraints=R(h.constraints,15),h.notes=R(h.notes,20);let p={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:l,planRationale:a,phases:Array.from(c.values()).sort((h,g)=>h.order-g.order),openQuestions:R(f,20),constraints:R(u,20),notes:R(m,20),updatedAt:n.length?n[n.length-1].evidence.occurredAt:new Date().toISOString()},y=Ze(t.rootPath,".toolnet","work");return Gr(y,{recursive:!0}),x(Ze(y,"semantic-current.json"),p),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(p,null,2)+`
55
- `,"application/json"),p}async function tt(t,e){let r=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}function Se(t){if(!t)return 0;let e=Array.from(t).length,r=t.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,r*1.3))}function k(t,e){let r=t.replace(/\s+/g," ").trim();return r.length<=e?r:r.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function tn(t){let e=[],r=!1;for(let n of t.split(/\r?\n/u)){let s=n.trim();if(s.includes("<!--")&&(r=!0),r){s.includes("-->")&&(r=!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(k(s,280)),e.length>=16))break}return e}function rn(t){let e=[],r=[];for(let n of t.split(/\\r?\\n/u)){let s=n.trim(),o=s.toLowerCase(),l=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(c=>o.startsWith(c));if(!l)continue;let a=s.slice(l.length).trim();a&&(l.includes("enforce")?e.push(a):r.push(a))}return{enforce:e,advisory:r}}function nn(t,e){let r=[];for(let n of t){let s=[...r,n].join(`
56
- `);if(Se(s)<=e){r.push(n);continue}let o=Se(r.join(`
57
- `)),i=Math.max(0,e-o);if(i>=16){let l=Math.floor(i*3.2),a=k(n,l);a&&r.push(a)}break}return r.join(`
58
- `).trim()}async function rt(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),r=ne(t.project,!1),n=r?.content??"";n||(n=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=rn(n),o=r?r.rules.filter(p=>p.mode==="enforce").map(p=>p.text):s.enforce,i=r?r.rules.filter(p=>p.mode==="advisory").map(p=>p.text):s.advisory,l=n?tn(n):[],a=await ee(t.project,t.storage),c=await tt(t.project,t.storage),f=await Xe(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."),n&&u.push(`Full operating manual: ${re(t.project)}`),o.length){u.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let p of o.slice(0,24))u.push(`- [ENFORCE] ${k(p,240)}`)}if(i.length){u.push("","PROJECT PREFERENCES");for(let p of i.slice(0,10))u.push(`- ${k(p,220)}`)}if(c&&(c.mission&&u.push("","MISSION",k(c.mission.value,420)),c.activeObjective&&u.push("","CURRENT OBJECTIVE",k(c.activeObjective.value,420)),c.why&&u.push("","WHY THIS WORK MATTERS",k(c.why.value,420)),c.desiredOutcome&&u.push("","DESIRED OUTCOME",k(c.desiredOutcome.value,420)),c.planRationale&&u.push("","WHY THIS APPROACH",k(c.planRationale.value,420))),a){if(u.push("","ACTIVE WORK"),a.goal&&u.push(`Goal: ${k(a.goal,320)}`),a.plan&&u.push(`Plan: ${k(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 p=c.phases.find(y=>y.order===a.currentPhase?.order);p&&(p.objective&&u.push(`Phase objective: ${k(p.objective.value,340)}`),p.why?u.push(`Why this phase: ${k(p.why.value,340)}`):u.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),p.deliverable&&u.push(`Deliverable: ${k(p.deliverable.value,340)}`),p.dependencies.length&&u.push(`Depends on: ${p.dependencies.slice(0,4).map(y=>k(y.value,180)).join("; ")}`),p.acceptanceCriteria.length&&(u.push("","DEFINITION OF DONE"),p.acceptanceCriteria.slice(0,6).forEach(y=>{u.push(`- ${k(y.value,260)}`)})),p.openQuestions.length&&(u.push("","OPEN QUESTIONS FOR CURRENT PHASE"),p.openQuestions.slice(0,4).forEach(y=>{u.push(`- ${k(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((p,y)=>{u.push(`${y+1}. ${k(p,260)}`)})),a.blockers.length&&(u.push("","BLOCKERS"),a.blockers.slice(0,5).forEach(p=>{u.push(`- ${k(p,260)}`)})),a.warnings.length&&(u.push("","ATTENTION"),a.warnings.slice(-5).forEach(p=>{u.push(`- ${k(p,260)}`)})),a.decisions.length&&(u.push("","RECENT DECISIONS"),a.decisions.slice(-5).forEach(p=>{u.push(`- ${k(p,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(p=>{u.push(`- ${k(p.value,260)}`)})),f&&u.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),l.length){u.push("","OPERATING NOTES");for(let p of l)u.push(`- ${p}`)}u.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let m=nn(u,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:m,estimatedTokens:Se(m),maxTokens:e,hasManual:!!n,hasWorkState:!!a,hasHandoff:!!f,generatedAt:new Date().toISOString()}}var sn=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 ve(t,e,r=0){if(!(r>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let n of t.slice(0,50))ve(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(sn.has(n)||["data","payload","parts","messages"].includes(n))&&ve(s,e,r+1)}}function I(t,e,r,n,s,o=.95){let i=L(n);return{version:1,id:v([t.projectId,r,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:r,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function O(t,e){let r=t.toLowerCase();for(let n of e){let s=n.toLowerCase();if(r.startsWith(`${s}:`)||r.startsWith(`${s} -`)||r.startsWith(`${s} \u2014`))return L(t.slice(n.length+1))}return null}function on(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function an(t){return L(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function nt(t,e){let r=[],n=new Set;function s(o){!o.value||o.value.length<3||n.has(o.id)||(n.add(o.id),r.push(o))}for(let o of e){let i=[];ve(o.data,i);for(let l of i){let a={type:"project"},c=null;for(let f of l.split(/\r?\n/u)){let u=L(f);if(!u){c=null;continue}let m=u.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let j=Number(m[1]);a={type:"phase",key:`phase:${j}`,order:j,title:L(m[2]??"")},c=null;continue}let p=u.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(p){let j=Number(p[1]);a={type:"task",key:`task:${j}`,order:j,title:L(p[2]??"")},c=null;continue}let y=O(u,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(y){s(I(t,o,"mission",y,{type:"project"},.99)),c=null;continue}let h=O(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(I(t,o,a.type==="phase"?"phase_objective":"objective",h,a,.98)),c=null;continue}let g=O(u,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(I(t,o,a.type==="phase"?"phase_why":"why",g,a,.98)),c=null;continue}let S=O(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(I(t,o,"desired_outcome",S,{type:"project"},.98)),c=null;continue}let b=O(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(b){s(I(t,o,"plan_rationale",b,{type:"project"},.98)),c=null;continue}let T=O(u,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(T){s(I(t,o,"phase_deliverable",T,a,.97)),c=null;continue}let C=O(u,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(C){s(I(t,o,"acceptance_criterion",C,a,.98)),c="acceptance_criterion";continue}let E=O(u,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(E){s(I(t,o,"dependency",E,a,.97)),c="dependency";continue}let N=O(u,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(N){s(I(t,o,"open_question",N,a,.95)),c="open_question";continue}let d=O(u,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(d){s(I(t,o,"constraint",d,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&&on(f)){s(I(t,o,c,an(f),a,.96));continue}c=null}}}return r}function st(t){return String(t).padStart(12,"0")}var oe=class{constructor(e){this.storage=e}storage;async write(e,r){if(r.length===0)return null;let n=Math.min(...r.map(a=>a.evidence.sequence)),s=Math.max(...r.map(a=>a.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:n,lastSequence:s,createdAt:new Date().toISOString(),observations:r},i=v(r.map(a=>a.id).sort().join("|")).slice(0,16),l=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${st(n)}-${st(s)}-${i}.json`].join("/");return await this.storage.exists(l)||await this.storage.put(l,JSON.stringify(o,null,2)+`
59
- `,"application/json"),l}};import{closeSync as cn,existsSync as un,openSync as ln,readSync as pn,statSync as dn}from"node:fs";function fn(t,e){if(!un(t))return{events:[],nextOffset:e};let r=dn(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=Buffer.alloc(r-n),o=ln(t,"r");try{pn(o,s,0,s.length,n)}finally{cn(o)}let i=s.toString("utf8"),l=i.lastIndexOf(`
60
- `);if(l<0)return{events:[],nextOffset:n};let a=i.slice(0,l+1);return{events:a.split(`
61
- `).filter(Boolean).flatMap(c=>{try{return[JSON.parse(c)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(a,"utf8")}}var ie=class{constructor(e){this.options=e;this.journal=new oe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),r=Number(e.sourceCursors["work.semantic.offset"]??0),n=fn(this.options.wal.eventsFile,Number.isFinite(r)?r:0);if(n.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:n.nextOffset};let s=nt(this.options.identity,n.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await et(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",n.nextOffset),{scannedEvents:n.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:n.nextOffset}}};import{existsSync as mn,mkdirSync as gn,readFileSync as hn,writeFileSync as yn}from"node:fs";import{dirname as Sn,join as ot}from"node:path";function it(t){return ot(t.rootPath,".toolnet","context","startup.md")}function vn(t){return ot(t.rootPath,".toolnet","context","startup.json")}function at(t,e){let r=it(t);gn(Sn(r),{recursive:!0}),yn(r,e.text.endsWith(`
52
+ `;function se(t){return Gr(t.rootPath,".toolnet","PROJECT.md")}function Xr(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Zr(t){let e=[],r=new Set,n=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=n.exec(t);){let o=s[1].toLowerCase(),i=Xr(s[2]);if(!i)continue;let u=`${o}:${i.toLowerCase()}`;r.has(u)||(r.add(u),e.push({id:v(u).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function en(t){let e=se(t);return et(e)||(Vr(Yr(e),{recursive:!0}),Hr(e,Qr,{encoding:"utf8",mode:384})),e}function oe(t,e=!1){let r=e?en(t):se(t);if(!et(r))return null;if(Xe(r).size>Ze)throw new Error(`PROJECT.md exceeds ${Ze} bytes`);let s=Ur(r,"utf8");return{path:r,content:s,digest:v(s),rules:Zr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Xe(r).mtimeMs).toISOString()}}function rn(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 nn(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 ie=class{constructor(e){this.options=e}options;async capture(e,r){let n=await re(this.options.project,this.options.storage);if(n||(n=await te(this.options.project,this.options.storage)),!nn(n))return null;let s=oe(this.options.project,!1),o=s?s.rules.filter(f=>f.mode==="enforce").map(f=>f.text):[],i=v(JSON.stringify(rn(n))),u=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),c=new Date().toISOString(),a={version:1,id:u,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:c,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:r},goal:n.goal,plan:n.plan,progress:n.progress,currentPhase:n.currentPhase,currentTask:n.currentTask,incompletePhases:n.phases.filter(f=>f.status!=="completed"&&f.status!=="cancelled"),incompleteTasks:n.tasks.filter(f=>f.status!=="completed"&&f.status!=="cancelled"),nextActions:n.nextActions.slice(0,10),blockers:n.blockers.slice(0,10),decisions:n.decisions.slice(-10),warnings:n.warnings.slice(-10),attention:[...o,...n.warnings].slice(0,20),filesTouched:n.filesTouched.slice(-20),tests:n.tests.slice(-15),stateDigest:i},d=`projects/${this.options.project.id}/work/handoffs/${u}.json`;await this.options.storage.exists(d)||await this.options.storage.put(d,JSON.stringify(a,null,2)+`
53
+ `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(a,null,2)+`
54
+ `,"application/json");let l=ke(this.options.project.rootPath,".toolnet","work","handoffs");return tn(l,{recursive:!0}),x(ke(l,`${u}.json`),a),x(ke(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};async function tt(t,e){let r=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}import{mkdirSync as sn}from"node:fs";import{join as rt}from"node:path";function on(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function an(t,e){if(!e)return!0;let r=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return r!==0?r>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function A(t,e){return an(e,t)?e:t}function T(t,e=30){let r=new Set,n=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||r.has(o)||(r.add(o),n.push(s))}return n.slice(-e)}async function cn(t,e){let r=`projects/${t.id}/work/semantic/observations/`,n=await e.list(r),s=[];for(let o of n.filter(i=>i.key.endsWith(".json")).sort((i,u)=>i.key.localeCompare(u.key))){let i=await e.getText(o.key);if(i)try{let u=JSON.parse(i);u.version===1&&Array.isArray(u.observations)&&s.push(u)}catch{}}return s}function un(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function nt(t,e){let n=(await cn(t,e)).flatMap(h=>h.observations).sort((h,g)=>{let S=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return S!==0?S:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),s,o,i,u,c,a=new Map,d=[],l=[],f=[];for(let h of n){let g=on(h);if(h.scope==="phase"&&h.scopeKey){let S=a.get(h.scopeKey)??un(h);switch(h.kind){case"phase_objective":S.objective=A(S.objective,g);break;case"phase_why":S.why=A(S.why,g);break;case"phase_deliverable":S.deliverable=A(S.deliverable,g);break;case"acceptance_criterion":S.acceptanceCriteria.push(g);break;case"dependency":S.dependencies.push(g);break;case"open_question":S.openQuestions.push(g);break;case"constraint":S.constraints.push(g);break;case"note":S.notes.push(g);break}a.set(S.key,S);continue}switch(h.kind){case"mission":s=A(s,g);break;case"objective":o=A(o,g);break;case"why":i=A(i,g);break;case"desired_outcome":u=A(u,g);break;case"plan_rationale":c=A(c,g);break;case"open_question":d.push(g);break;case"constraint":l.push(g);break;case"note":f.push(g);break}}for(let h of a.values())h.acceptanceCriteria=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 p={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:u,planRationale:c,phases:Array.from(a.values()).sort((h,g)=>h.order-g.order),openQuestions:T(d,20),constraints:T(l,20),notes:T(f,20),updatedAt:n.length?n[n.length-1].evidence.occurredAt:new Date().toISOString()},y=rt(t.rootPath,".toolnet","work");return sn(y,{recursive:!0}),x(rt(y,"semantic-current.json"),p),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(p,null,2)+`
55
+ `,"application/json"),p}async function st(t,e){let r=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}function we(t){if(!t)return 0;let e=Array.from(t).length,r=t.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,r*1.3))}function b(t,e){let r=t.replace(/\s+/g," ").trim();return r.length<=e?r:r.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function ln(t){let e=[],r=!1;for(let n of t.split(/\r?\n/u)){let s=n.trim();if(s.includes("<!--")&&(r=!0),r){s.includes("-->")&&(r=!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 pn(t){let e=[],r=[];for(let n of t.split(/\\r?\\n/u)){let s=n.trim(),o=s.toLowerCase(),u=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(a=>o.startsWith(a));if(!u)continue;let c=s.slice(u.length).trim();c&&(u.includes("enforce")?e.push(c):r.push(c))}return{enforce:e,advisory:r}}function dn(t,e){let r=[];for(let n of t){let s=[...r,n].join(`
56
+ `);if(we(s)<=e){r.push(n);continue}let o=we(r.join(`
57
+ `)),i=Math.max(0,e-o);if(i>=16){let u=Math.floor(i*3.2),c=b(n,u);c&&r.push(c)}break}return r.join(`
58
+ `).trim()}async function ot(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),r=oe(t.project,!1),n=r?.content??"";n||(n=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=pn(n),o=r?r.rules.filter(p=>p.mode==="enforce").map(p=>p.text):s.enforce,i=r?r.rules.filter(p=>p.mode==="advisory").map(p=>p.text):s.advisory,u=n?ln(n):[],c=await re(t.project,t.storage),a=await st(t.project,t.storage),d=await tt(t.project,t.storage),l=[];if(l.push("[TOOLNET PROJECT CONTEXT]"),l.push(`Project: ${t.project.name}`),l.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),n&&l.push(`Full operating manual: ${se(t.project)}`),o.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let p of o.slice(0,24))l.push(`- [ENFORCE] ${b(p,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let p of i.slice(0,10))l.push(`- ${b(p,220)}`)}if(a&&(a.mission&&l.push("","MISSION",b(a.mission.value,420)),a.activeObjective&&l.push("","CURRENT OBJECTIVE",b(a.activeObjective.value,420)),a.why&&l.push("","WHY THIS WORK MATTERS",b(a.why.value,420)),a.desiredOutcome&&l.push("","DESIRED OUTCOME",b(a.desiredOutcome.value,420)),a.planRationale&&l.push("","WHY THIS APPROACH",b(a.planRationale.value,420))),c){if(l.push("","ACTIVE WORK"),c.goal&&l.push(`Goal: ${b(c.goal,320)}`),c.plan&&l.push(`Plan: ${b(c.plan,320)}`),l.push(`Progress: phases ${c.progress.phasesCompleted}/${c.progress.phasesTotal}; tasks ${c.progress.tasksCompleted}/${c.progress.tasksTotal}; blocked ${c.progress.blocked}`),c.currentPhase&&l.push(`Current phase: ${c.currentPhase.title} [${c.currentPhase.status}]`),c.currentPhase&&a){let p=a.phases.find(y=>y.order===c.currentPhase?.order);p&&(p.objective&&l.push(`Phase objective: ${b(p.objective.value,340)}`),p.why?l.push(`Why this phase: ${b(p.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),p.deliverable&&l.push(`Deliverable: ${b(p.deliverable.value,340)}`),p.dependencies.length&&l.push(`Depends on: ${p.dependencies.slice(0,4).map(y=>b(y.value,180)).join("; ")}`),p.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),p.acceptanceCriteria.slice(0,6).forEach(y=>{l.push(`- ${b(y.value,260)}`)})),p.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),p.openQuestions.slice(0,4).forEach(y=>{l.push(`- ${b(y.value,260)}`)})))}c.currentTask&&l.push(`Current task: ${c.currentTask.title} [${c.currentTask.status}]`),c.nextActions.length&&(l.push("","NEXT ACTIONS"),c.nextActions.slice(0,6).forEach((p,y)=>{l.push(`${y+1}. ${b(p,260)}`)})),c.blockers.length&&(l.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(p=>{l.push(`- ${b(p,260)}`)})),c.warnings.length&&(l.push("","ATTENTION"),c.warnings.slice(-5).forEach(p=>{l.push(`- ${b(p,260)}`)})),c.decisions.length&&(l.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(p=>{l.push(`- ${b(p,260)}`)})),c.lastSession&&l.push("",`Last work session: ${c.lastSession.agent} / ${c.lastSession.nativeSessionId}`)}if(a&&a.openQuestions.length&&(l.push("","UNRESOLVED QUESTIONS"),a.openQuestions.slice(0,5).forEach(p=>{l.push(`- ${b(p.value,260)}`)})),d&&l.push(`Latest handoff: ${d.reason} / ${d.sourceSession.agent}`),u.length){l.push("","OPERATING NOTES");for(let p of u)l.push(`- ${p}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let f=dn(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:f,estimatedTokens:we(f),maxTokens:e,hasManual:!!n,hasWorkState:!!c,hasHandoff:!!d,generatedAt:new Date().toISOString()}}var fn=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 je(t,e,r=0){if(!(r>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let n of t.slice(0,50))je(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(fn.has(n)||["data","payload","parts","messages"].includes(n))&&je(s,e,r+1)}}function I(t,e,r,n,s,o=.95){let i=D(n);return{version:1,id:v([t.projectId,r,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:r,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function O(t,e){let r=t.toLowerCase();for(let n of e){let s=n.toLowerCase();if(r.startsWith(`${s}:`)||r.startsWith(`${s} -`)||r.startsWith(`${s} \u2014`))return D(t.slice(n.length+1))}return null}function mn(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function gn(t){return D(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function it(t,e){let r=[],n=new Set;function s(o){!o.value||o.value.length<3||n.has(o.id)||(n.add(o.id),r.push(o))}for(let o of e){let i=[];je(o.data,i);for(let u of i){let c={type:"project"},a=null;for(let d of u.split(/\r?\n/u)){let l=D(d);if(!l){a=null;continue}let f=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let j=Number(f[1]);c={type:"phase",key:`phase:${j}`,order:j,title:D(f[2]??"")},a=null;continue}let p=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(p){let j=Number(p[1]);c={type:"task",key:`task:${j}`,order:j,title:D(p[2]??"")},a=null;continue}let y=O(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(y){s(I(t,o,"mission",y,{type:"project"},.99)),a=null;continue}let h=O(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(I(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),a=null;continue}let g=O(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(I(t,o,c.type==="phase"?"phase_why":"why",g,c,.98)),a=null;continue}let S=O(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(S){s(I(t,o,"desired_outcome",S,{type:"project"},.98)),a=null;continue}let k=O(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(k){s(I(t,o,"plan_rationale",k,{type:"project"},.98)),a=null;continue}let M=O(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(M){s(I(t,o,"phase_deliverable",M,c,.97)),a=null;continue}let N=O(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(N){s(I(t,o,"acceptance_criterion",N,c,.98)),a="acceptance_criterion";continue}let E=O(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(E){s(I(t,o,"dependency",E,c,.97)),a="dependency";continue}let R=O(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(R){s(I(t,o,"open_question",R,c,.95)),a="open_question";continue}let m=O(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(m){s(I(t,o,"constraint",m,c,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){a="constraint";continue}if(a&&mn(d)){s(I(t,o,a,gn(d),c,.96));continue}a=null}}}return r}function at(t){return String(t).padStart(12,"0")}var ae=class{constructor(e){this.storage=e}storage;async write(e,r){if(r.length===0)return null;let n=Math.min(...r.map(c=>c.evidence.sequence)),s=Math.max(...r.map(c=>c.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:n,lastSequence:s,createdAt:new Date().toISOString(),observations:r},i=v(r.map(c=>c.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${at(n)}-${at(s)}-${i}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,JSON.stringify(o,null,2)+`
59
+ `,"application/json"),u}};import{closeSync as hn,existsSync as yn,openSync as Sn,readSync as vn,statSync as bn}from"node:fs";function kn(t,e){if(!yn(t))return{events:[],nextOffset:e};let r=bn(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=Buffer.alloc(r-n),o=Sn(t,"r");try{vn(o,s,0,s.length,n)}finally{hn(o)}let i=s.toString("utf8"),u=i.lastIndexOf(`
60
+ `);if(u<0)return{events:[],nextOffset:n};let c=i.slice(0,u+1);return{events:c.split(`
61
+ `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(c,"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(),r=Number(e.sourceCursors["work.semantic.offset"]??0),n=kn(this.options.wal.eventsFile,Number.isFinite(r)?r:0);if(n.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:n.nextOffset};let s=it(this.options.identity,n.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await nt(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",n.nextOffset),{scannedEvents:n.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:n.nextOffset}}};import{existsSync as wn,mkdirSync as jn,readFileSync as xn,writeFileSync as In}from"node:fs";import{dirname as Pn,join as ct}from"node:path";function ue(t){return t?Math.ceil(t.length/3.5):0}function le(t,e){if(!t)return"";if(ue(t)<=e)return t;let n=Math.floor(e*3.5),s=t.slice(0,n),o=s.lastIndexOf("."),i=s.lastIndexOf(`
62
+ `),u=Math.max(o,i);return u>n*.7?s.slice(0,u+1):s}function ut(t){return ct(t.rootPath,".toolnet","context","startup.md")}function On(t){return ct(t.rootPath,".toolnet","context","startup.json")}function lt(t,e){let r=ut(t);jn(Pn(r),{recursive:!0}),In(r,e.text.endsWith(`
62
63
  `)?e.text:e.text+`
63
- `,{encoding:"utf8",mode:384}),x(vn(t),e)}async function ke(t,e,r=900){let n=await rt({project:t,storage:e,maxTokens:r}),s={version:1,projectId:t.id,projectName:t.name,text:n.text,digest:v(n.text),estimatedTokens:n.estimatedTokens,generatedAt:new Date().toISOString()};return at(t,s),await e.put(`projects/${t.id}/context/startup.md`,s.text+`
64
- `,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(s,null,2)+`
65
- `,"application/json"),s}async function ct(t,e,r=900){try{let s=await e.getText(`projects/${t.id}/context/startup.md`);if(s&&s.trim()){let o=s.trim(),i={version:1,projectId:t.id,projectName:t.name,text:o,digest:v(o),estimatedTokens:Math.ceil(o.length/3.5),generatedAt:new Date().toISOString()};return at(t,i),i}}catch{}let n=it(t);if(mn(n))try{let s=hn(n,"utf8").trim();if(s)return{version:1,projectId:t.id,projectName:t.name,text:s,digest:v(s),estimatedTokens:Math.ceil(s.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await ke(t,e,r)}catch{return null}}import{existsSync as kn,mkdirSync as bn,readFileSync as wn}from"node:fs";import{homedir as jn}from"node:os";import{dirname as xn,join as ut}from"node:path";function In(t,e,r){let n=r??ut(jn(),".config","toolnet-memory","injections","agy");return ut(n,`${t.id}-${e}.json`)}function Pn(t){if(!kn(t))return null;try{return JSON.parse(wn(t,"utf8"))}catch{return null}}async function lt(t){let e=t.now??Date.now(),r=t.resumeAfterMs??360*60*1e3,n=In(t.project,t.conversationId,t.markerDirectory),s=Pn(n),o=s?Date.parse(s.injectedAt):0,i=o?e-o:Number.POSITIVE_INFINITY;if(s&&i<6e4)return{};let l=t.invocationNum===0,a=i>=r;if(s&&!l&&!a)return{};let c=await ct(t.project,t.storage,900);return c?.text?(bn(xn(n),{recursive:!0}),x(n,{digest:c.digest,injectedAt:new Date(e).toISOString()}),{injectSteps:[{userMessage:c.text}]}):{}}import{existsSync as On}from"node:fs";import{dirname as En,join as An,parse as Rn,resolve as Tn}from"node:path";function pt(t){for(let e of t){let r=Tn(e),n=Rn(r).root;for(;;){if(On(An(r,".toolnet","project.json")))return new V().detect(r);if(r===n)break;let s=En(r);if(s===r)break;r=s}}return null}import{homedir as Ot}from"node:os";import{join as ws,resolve as js}from"node:path";import{join as Nn}from"node:path";function dt(t,e){let r=t.trim(),n=r.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=v(r).slice(0,12);if(!n||n==="."||n==="..")return`${e}--${s}`;let o=n.slice(0,100);return o===r&&r.length<=100?o:`${o.slice(0,85)}--${s}`}function ft(t,e,r){let n=e.trim(),s=r.trim();if(!n)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=dt(n.toLowerCase(),"agent"),i=dt(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:n,nativeSessionId:s,sessionKey:`${n}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:Nn(t.rootPath,".toolnet","sessions",o,i)}}function mt(t){return String(t).padStart(12,"0")}var ae=class{constructor(e,r=100,n=512*1024){this.storage=e;this.maxEventsPerChunk=r;this.maxChunkBytes=n;if(r<1)throw new Error("maxEventsPerChunk must be positive");if(n<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let r=await this.storage.getText(e);return r?JSON.parse(r):null}async putJson(e,r){await this.storage.put(e,JSON.stringify(r,null,2)+`
66
- `,"application/json")}async scan(e){let r=`${e.remotePrefix}/events/`,n=await this.storage.list(r),s=[],o=0;for(let i of n){let l=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!l)continue;let a=Number(l[1]),c=Number(l[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,l)=>i.start-l.start),{chunks:s,maxSequence:o}}split(e){let r=[],n=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
67
- `,"utf8");n.length>0&&(n.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(r.push(n),n=[],s=0),n.push(o),s+=i}return n.length>0&&r.push(n),r}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let r=await this.scan(e);return{maxSequence:r.maxSequence,chunkCount:r.chunks.length}}async append(e,r,n,s={}){let o=await this.loadManifest(e),i=await this.scan(e),l=r.filter(g=>g.sequence>i.maxSequence),a=0;for(let g of this.split(l)){let S=g[0],b=g[g.length-1],T=g.map(N=>JSON.stringify(N)).join(`
64
+ `,{encoding:"utf8",mode:384}),x(On(t),e)}async function xe(t,e,r=800){let s=(await ot({project:t,storage:e,maxTokens:r})).text;ue(s)>r&&(s=le(s,r),s+=`
65
+
66
+ [Context trimmed by ToolNet Memory token budget]
67
+ `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:v(s),estimatedTokens:ue(s),generatedAt:new Date().toISOString()};return lt(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
68
+ `,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
69
+ `,"application/json"),i}async function pt(t,e,r=900){try{let s=await e.getText(`projects/${t.id}/context/startup.md`);if(s&&s.trim()){let o=s.trim(),i={version:1,projectId:t.id,projectName:t.name,text:o,digest:v(o),estimatedTokens:Math.ceil(o.length/3.5),generatedAt:new Date().toISOString()};return lt(t,i),i}}catch{}let n=ut(t);if(wn(n))try{let s=xn(n,"utf8").trim();if(s)return{version:1,projectId:t.id,projectName:t.name,text:s,digest:v(s),estimatedTokens:Math.ceil(s.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await xe(t,e,r)}catch{return null}}import{existsSync as En,mkdirSync as An,readFileSync as Tn}from"node:fs";import{homedir as Mn}from"node:os";import{dirname as Rn,join as dt}from"node:path";function Cn(t,e,r){let n=r??dt(Mn(),".config","toolnet-memory","injections","agy");return dt(n,`${t.id}-${e}.json`)}function Nn(t){if(!En(t))return null;try{return JSON.parse(Tn(t,"utf8"))}catch{return null}}async function ft(t){let e=t.now??Date.now(),r=t.resumeAfterMs??360*60*1e3,n=Cn(t.project,t.conversationId,t.markerDirectory),s=Nn(n),o=s?Date.parse(s.injectedAt):0,i=o?e-o:Number.POSITIVE_INFINITY;if(s&&i<6e4)return{};let u=t.invocationNum===0,c=i>=r;if(s&&!u&&!c)return{};let a=await pt(t.project,t.storage,900);return a?.text?(An(Rn(n),{recursive:!0}),x(n,{digest:a.digest,injectedAt:new Date(e).toISOString()}),{injectSteps:[{userMessage:a.text}]}):{}}import{existsSync as _n}from"node:fs";import{dirname as $n,join as Ln,parse as Dn,resolve as Kn}from"node:path";function mt(t){for(let e of t){let r=Kn(e),n=Dn(r).root;for(;;){if(_n(Ln(r,".toolnet","project.json")))return new H().detect(r);if(r===n)break;let s=$n(r);if(s===r)break;r=s}}return null}import{homedir as _t}from"node:os";import{join as Ns,resolve as _s}from"node:path";import{join as Fn}from"node:path";function gt(t,e){let r=t.trim(),n=r.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=v(r).slice(0,12);if(!n||n==="."||n==="..")return`${e}--${s}`;let o=n.slice(0,100);return o===r&&r.length<=100?o:`${o.slice(0,85)}--${s}`}function ht(t,e,r){let n=e.trim(),s=r.trim();if(!n)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=gt(n.toLowerCase(),"agent"),i=gt(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:n,nativeSessionId:s,sessionKey:`${n}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:Fn(t.rootPath,".toolnet","sessions",o,i)}}function yt(t){return String(t).padStart(12,"0")}var pe=class{constructor(e,r=100,n=512*1024){this.storage=e;this.maxEventsPerChunk=r;this.maxChunkBytes=n;if(r<1)throw new Error("maxEventsPerChunk must be positive");if(n<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let r=await this.storage.getText(e);return r?JSON.parse(r):null}async putJson(e,r){await this.storage.put(e,JSON.stringify(r,null,2)+`
70
+ `,"application/json")}async scan(e){let r=`${e.remotePrefix}/events/`,n=await this.storage.list(r),s=[],o=0;for(let i of n){let u=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!u)continue;let c=Number(u[1]),a=Number(u[2]);!Number.isFinite(c)||!Number.isFinite(a)||(s.push({key:i.key,start:c,end:a}),o=Math.max(o,a))}return s.sort((i,u)=>i.start-u.start),{chunks:s,maxSequence:o}}split(e){let r=[],n=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
71
+ `,"utf8");n.length>0&&(n.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(r.push(n),n=[],s=0),n.push(o),s+=i}return n.length>0&&r.push(n),r}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let r=await this.scan(e);return{maxSequence:r.maxSequence,chunkCount:r.chunks.length}}async append(e,r,n,s={}){let o=await this.loadManifest(e),i=await this.scan(e),u=r.filter(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(u)){let S=g[0],k=g[g.length-1],M=g.map(R=>JSON.stringify(R)).join(`
68
72
  `)+`
69
- `,C=v(T).slice(0,16),E=[e.remotePrefix,"events",`${mt(S.sequence)}-${mt(b.sequence)}-${C}.jsonl`].join("/");await this.storage.exists(E)||await this.storage.put(E,T,"application/x-ndjson"),a+=g.length}let c=await this.scan(e),f=r[r.length-1],u=o?.status??"active";f?.type==="session_end"||f?.type==="session_idle"?u="idle":f?.type==="error"?u="error":r.length>0&&(u="active");let m=new Date().toISOString(),p=r[0],y={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:u,createdAt:o?.createdAt??p?.timestamp??m,updatedAt:f?.timestamp??m,firstEventAt:o?.firstEventAt??p?.timestamp,lastEventAt:f?.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:r.length>0?r[r.length-1].sequence:c.maxSequence,lastRemoteSequence:c.maxSequence,sourceCursors:n,updatedAt:m};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 be,existsSync as Cn,fsyncSync as Mn,mkdirSync as _n,openSync as we,readSync as $n,rmSync as gt,statSync as ht,writeSync as Ln}from"node:fs";import{join as je}from"node:path";var Kn=12e4,zn=80,Wn=2e3;function Dn(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ce=class{constructor(e){this.identity=e;_n(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 Be(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){x(this.stateFile,e)}acquireLock(){for(let e=0;e<zn;e+=1)try{return we(this.lockFile,"wx",384)}catch(r){if(r.code!=="EEXIST")throw r;try{if(Date.now()-ht(this.lockFile).mtimeMs>Kn){gt(this.lockFile,{force:!0});continue}}catch{}Dn(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let r=this.acquireLock();try{return e()}finally{be(r),gt(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let r=this.loadStateUnsafe(),n=new Set(r.recentEventIds),s=r.lastSequence,o=[];for(let u of e){let m=u.timestamp??new Date().toISOString(),p=u.data??{},y=u.provenance?.rawDigest??v(De(p)),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,m,y].join("|"),g=v(h).slice(0,32);if(n.has(g))continue;s+=1;let S={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:u.type,timestamp:m,data:p,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),n.add(g)}if(o.length===0)return[];let i=o.map(u=>JSON.stringify(u)).join(`
73
+ `,N=v(M).slice(0,16),E=[e.remotePrefix,"events",`${yt(S.sequence)}-${yt(k.sequence)}-${N}.jsonl`].join("/");await this.storage.exists(E)||await this.storage.put(E,M,"application/x-ndjson"),c+=g.length}let a=await this.scan(e),d=r[r.length-1],l=o?.status??"active";d?.type==="session_end"||d?.type==="session_idle"?l="idle":d?.type==="error"?l="error":r.length>0&&(l="active");let f=new Date().toISOString(),p=r[0],y={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:l,createdAt:o?.createdAt??p?.timestamp??f,updatedAt:d?.timestamp??f,firstEventAt:o?.firstEventAt??p?.timestamp,lastEventAt:d?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(y.title=s.title??o?.title);let h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:r.length>0?r[r.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:n,updatedAt:f};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,y),{uploadedEvents:c,lastRemoteSequence:a.maxSequence,eventCount:y.eventCount,chunkCount:y.chunkCount,status:l}}};import{closeSync as Ie,existsSync as Wn,fsyncSync as zn,mkdirSync as Bn,openSync as Pe,readSync as qn,rmSync as St,statSync as vt,writeSync as Jn}from"node:fs";import{join as Oe}from"node:path";var Vn=12e4,Un=80,Hn=2e3;function Yn(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var de=class{constructor(e){this.identity=e;Bn(e.localDirectory,{recursive:!0}),this.eventsFile=Oe(e.localDirectory,"events.jsonl"),this.stateFile=Oe(e.localDirectory,"state.json"),this.lockFile=Oe(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 Je(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){x(this.stateFile,e)}acquireLock(){for(let e=0;e<Un;e+=1)try{return Pe(this.lockFile,"wx",384)}catch(r){if(r.code!=="EEXIST")throw r;try{if(Date.now()-vt(this.lockFile).mtimeMs>Vn){St(this.lockFile,{force:!0});continue}}catch{}Yn(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let r=this.acquireLock();try{return e()}finally{Ie(r),St(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let r=this.loadStateUnsafe(),n=new Set(r.recentEventIds),s=r.lastSequence,o=[];for(let l of e){let f=l.timestamp??new Date().toISOString(),p=l.data??{},y=l.provenance?.rawDigest??v(qe(p)),h=l.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,l.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,l.type,f,y].join("|"),g=v(h).slice(0,32);if(n.has(g))continue;s+=1;let S={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:f,data:p,provenance:{...l.provenance,rawDigest:y}};l.role!==void 0&&(S.role=l.role),l.sourceEventId!==void 0&&(S.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(S.sourceSequence=l.sourceSequence),o.push(S),n.add(g)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
70
74
  `)+`
71
- `,l=we(this.eventsFile,"a",384);try{Ln(l,i,null,"utf8"),Mn(l)}finally{be(l)}let a=o[o.length-1],c="active";a.type==="session_end"||a.type==="session_idle"?c="idle":a.type==="error"&&(c="error");let f=Array.from(n).slice(-Wn);return this.saveStateUnsafe({...r,status:c,updatedAt:a.timestamp,lastSequence:a.sequence,recentEventIds:f}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Cn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let r=ht(this.eventsFile).size,n=Math.min(e.remoteByteOffset,r);if(r<=n)return{events:[],startOffset:n,endOffset:r};let s=r-n,o=Buffer.alloc(s),i=we(this.eventsFile,"r");try{$n(i,o,0,s,n)}finally{be(i)}return{events:o.toString("utf8").split(`
72
- `).filter(Boolean).map(c=>JSON.parse(c)),startOffset:n,endOffset:r}})}markRemote(e,r){this.withLock(()=>{let n=this.loadStateUnsafe();this.saveStateUnsafe({...n,lastRemoteSequence:Math.max(n.lastRemoteSequence,e),remoteByteOffset:Math.max(n.remoteByteOffset,r),updatedAt:new Date().toISOString()})})}setSourceCursor(e,r){this.withLock(()=>{let n=this.loadStateUnsafe();this.saveStateUnsafe({...n,sourceCursors:{...n.sourceCursors,[e]:String(r)},updatedAt:new Date().toISOString()})})}};import{closeSync as ns,existsSync as ss,openSync as os,readSync as is,statSync as as}from"node:fs";function yt(t,e){let r=e.toLowerCase();return r.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||r.includes("tuy\u1EC7t \u0111\u1ED1i")||r.includes("must not")||r.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||r.includes("error")||r.includes("failed")||r.includes("exception")?"normal":"temporary"}var bt=[/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],Bn=[/từ giờ/iu,/về sau/iu,/mỗi lần/iu,/luôn luôn/iu,/\bluôn\b/iu,/quy tắc/iu,/workflow/iu,/\balways\b/iu,/\brequired\b/iu,/\bmust\b/iu,/from now on/iu],Fn=[/\bchốt\b/iu,/quyết định/iu,/sẽ dùng/iu,/chọn .+ thay/iu,/đổi sang/iu,/chuyển sang/iu,/\bdecided\b/iu,/\bchosen\b/iu,/we will use/iu,/use .+ instead/iu,/switch(?:ed)? to/iu],qn=[/\btodo\b/iu,/cần làm/iu,/cần thêm/iu,/cần sửa/iu,/cần kiểm tra/iu,/tiếp theo/iu,/bước tiếp theo/iu,/còn phải/iu,/còn cần/iu,/next step/iu,/\bneed to\b/iu,/\bremaining\b/iu,/follow[- ]?up/iu],Jn=[/đã sửa/iu,/đã fix/iu,/đã khắc phục/iu,/đã xử lý/iu,/hoàn tất/iu,/hoàn thành/iu,/\bfixed\b/iu,/\bresolved\b/iu,/\bimplemented\b/iu,/\bcompleted\b/iu,/\bpasses?\b/iu],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],Vn=[/\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],Un=[/đườ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],Hn=[/\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],vt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Yn=new Set(["payload","data","content","message","messages","parts","summary"]);function P(t,e){return e.some(r=>r.test(t))}function wt(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Gn(t){return wt(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Qn(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 xe(t,e,r,n=0){if(!(n>6)){if(typeof t=="string"){(!e||vt.has(e))&&r.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))xe(s,e,r,n+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(vt.has(s)||Yn.has(s))&&xe(o,s,r,n+1)}}function Xn(t){let e=[];xe(t.data,void 0,e);let r=[],n=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=wt(o);if(Qn(i)&&!n.has(i)&&(n.add(i),r.push(i),r.length>=50))return r}return r}function kt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Zn(t,e,r){if(r.type==="decision")return{kind:"decision",confidence:1};if(r.type==="todo")return{kind:"todo",confidence:1};let n=e==="user"||r.type==="user_prompt",s=e==="assistant"||r.type==="assistant_message";return n&&P(t,bt)?{kind:"rule",confidence:.98}:n&&P(t,Bn)?{kind:"rule",confidence:.92}:P(t,Fn)?{kind:P(t,St)?"architecture":"decision",confidence:n?.93:.86}:n&&P(t,qn)?{kind:"todo",confidence:.87}:P(t,St)&&P(t,Vn)?{kind:"architecture",confidence:n?.88:.82}:s&&P(t,Jn)?{kind:"fix",confidence:.8}:n&&P(t,Un)&&P(t,Hn)?{kind:"context",confidence:.79}:null}function es(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function ts(t,e,r){return t==="rule"&&P(r,bt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":yt(e,r)}function jt(t,e){let r=[],n=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,l=kt(o);i&&l&&s.set(i,l)}for(let o of e){let i=kt(o),l=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&l&&(i=s.get(l)??"");for(let a of Xn(o)){let c=Zn(a,i,o);if(!c||c.confidence<.75)continue;let f=es(c.kind),u=Gn(a),m=v([t.projectId,c.kind,u].join("|"));if(n.has(m))continue;n.add(m);let p=o.provenance.sourcePath?[o.provenance.sourcePath]:[],y=o.sourceEventId?[o.sourceEventId]:[];r.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:c.kind,type:f,content:a,confidence:c.confidence,importance:ts(c.kind,f,a),tags:[f],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:y,sourcePaths:p,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return r}function xt(t){return String(t).padStart(12,"0")}function rs(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var ue=class{constructor(e){this.storage=e}storage;async write(e,r,n){if(n.length===0||r.length===0)return null;let s=Math.min(...r.map(f=>f.sequence)),o=Math.max(...r.map(f=>f.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:n.length,candidates:n},l=JSON.stringify(i,null,2)+`
73
- `,a=v(n.map(f=>f.fingerprint).sort().join("|")).slice(0,16),c=[rs(e),"batches",`${xt(s)}-${xt(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,l,"application/json"),c}};function cs(t,e){if(!ss(t))return{events:[],nextOffset:e};let r=as(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=r-n,o=Buffer.alloc(s),i=os(t,"r");try{is(i,o,0,s,n)}finally{ns(i)}let l=o.toString("utf8"),a=l.lastIndexOf(`
74
- `);if(a<0)return{events:[],nextOffset:n};let c=l.slice(0,a+1);return{events:c.split(`
75
- `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(c,"utf8")}}var le=class{constructor(e){this.options=e;this.journal=new ue(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),r=Number(e.sourceCursors["memory.learner.offset"]??0),n=Number.isFinite(r)?r:0,s=cs(this.options.wal.eventsFile,n);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=jt(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}}};var pe=class{identity;wal;remote;sanitizer=new D;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=ft(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new ce(this.identity),this.remote=new ae(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new le({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new te({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new ie({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new se({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let r=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:r}}start(e={}){let r=this.wal.loadState();return this.record({type:r.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(r=>this.sanitizeEvent(r)))}setSourceCursor(e,r){this.wal.setSourceCursor(e,r)}async flush(){let e=this.wal.readPending(),r=this.wal.loadState(),n=await this.remote.append(this.identity,e.events,r.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 n}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as us,openSync as ls,closeSync as ps,readSync as ds,statSync as fs}from"node:fs";function ms(t){let e=typeof t.role=="string"?t.role:"",r=typeof t.type=="string"?t.type.toLowerCase():"";return e==="user"||r.includes("user")?"user_prompt":e==="assistant"||r.includes("assistant")||r.includes("model")?"assistant_message":r.includes("tool")||"toolCall"in t||"tool_call"in t?"tool_call":r.includes("error")?"error":"message"}function gs(t){let e=[t.timestamp,t.createdAt,t.time,t.created_at];for(let r of e){if(typeof r=="string"){let n=new Date(r);if(!Number.isNaN(n.getTime()))return n.toISOString()}if(typeof r=="number"){let n=r;n<1e11&&(n*=1e3);let s=new Date(n);if(!Number.isNaN(s.getTime()))return s.toISOString()}}return new Date().toISOString()}function It(t,e={offset:0}){if(!us(t))return{events:[],nextOffset:e.offset,reset:!1};let r=fs(t).size,n=e.offset>r,s=n?0:e.offset;if(s===r)return{events:[],nextOffset:r,reset:n};let o=r-s,i=Buffer.alloc(o),l=ls(t,"r");try{ds(l,i,0,o,s)}finally{ps(l)}let a=i.toString("utf8"),c=a.lastIndexOf(`
76
- `);if(c<0)return{events:[],nextOffset:s,reset:n};let f=a.slice(0,c+1),u=Buffer.byteLength(f,"utf8"),m=[],p=0;for(let y of f.split(`
75
+ `,u=Pe(this.eventsFile,"a",384);try{Jn(u,i,null,"utf8"),zn(u)}finally{Ie(u)}let c=o[o.length-1],a="active";c.type==="session_end"||c.type==="session_idle"?a="idle":c.type==="error"&&(a="error");let d=Array.from(n).slice(-Hn);return this.saveStateUnsafe({...r,status:a,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:d}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Wn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let r=vt(this.eventsFile).size,n=Math.min(e.remoteByteOffset,r);if(r<=n)return{events:[],startOffset:n,endOffset:r};let s=r-n,o=Buffer.alloc(s),i=Pe(this.eventsFile,"r");try{qn(i,o,0,s,n)}finally{Ie(i)}return{events:o.toString("utf8").split(`
76
+ `).filter(Boolean).map(a=>JSON.parse(a)),startOffset:n,endOffset:r}})}markRemote(e,r){this.withLock(()=>{let n=this.loadStateUnsafe();this.saveStateUnsafe({...n,lastRemoteSequence:Math.max(n.lastRemoteSequence,e),remoteByteOffset:Math.max(n.remoteByteOffset,r),updatedAt:new Date().toISOString()})})}setSourceCursor(e,r){this.withLock(()=>{let n=this.loadStateUnsafe();this.saveStateUnsafe({...n,sourceCursors:{...n.sourceCursors,[e]:String(r)},updatedAt:new Date().toISOString()})})}};import{closeSync as ps,existsSync as ds,openSync as fs,readSync as ms,statSync as gs}from"node:fs";function bt(t,e){let r=e.toLowerCase();return r.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||r.includes("tuy\u1EC7t \u0111\u1ED1i")||r.includes("must not")||r.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||r.includes("error")||r.includes("failed")||r.includes("exception")?"normal":"temporary"}var xt=[/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],Gn=[/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],Qn=[/\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],Xn=[/\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],Zn=[/đã 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],kt=[/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],es=[/\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],ts=[/đườ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],rs=[/\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],wt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),ns=new Set(["payload","data","content","message","messages","parts","summary"]);function P(t,e){return e.some(r=>r.test(t))}function It(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function ss(t){return It(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function os(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 Ee(t,e,r,n=0){if(!(n>6)){if(typeof t=="string"){(!e||wt.has(e))&&r.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Ee(s,e,r,n+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(wt.has(s)||ns.has(s))&&Ee(o,s,r,n+1)}}function is(t){let e=[];Ee(t.data,void 0,e);let r=[],n=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=It(o);if(os(i)&&!n.has(i)&&(n.add(i),r.push(i),r.length>=50))return r}return r}function jt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function as(t,e,r){if(r.type==="decision")return{kind:"decision",confidence:1};if(r.type==="todo")return{kind:"todo",confidence:1};let n=e==="user"||r.type==="user_prompt",s=e==="assistant"||r.type==="assistant_message";return n&&P(t,xt)?{kind:"rule",confidence:.98}:n&&P(t,Gn)?{kind:"rule",confidence:.92}:P(t,Qn)?{kind:P(t,kt)?"architecture":"decision",confidence:n?.93:.86}:n&&P(t,Xn)?{kind:"todo",confidence:.87}:P(t,kt)&&P(t,es)?{kind:"architecture",confidence:n?.88:.82}:s&&P(t,Zn)?{kind:"fix",confidence:.8}:n&&P(t,ts)&&P(t,rs)?{kind:"context",confidence:.79}:null}function cs(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function us(t,e,r){return t==="rule"&&P(r,xt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":bt(e,r)}function Pt(t,e){let r=[],n=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,u=jt(o);i&&u&&s.set(i,u)}for(let o of e){let i=jt(o),u=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&u&&(i=s.get(u)??"");for(let c of is(o)){let a=as(c,i,o);if(!a||a.confidence<.75)continue;let d=cs(a.kind),l=ss(c),f=v([t.projectId,a.kind,l].join("|"));if(n.has(f))continue;n.add(f);let p=o.provenance.sourcePath?[o.provenance.sourcePath]:[],y=o.sourceEventId?[o.sourceEventId]:[];r.push({version:1,fingerprint:f,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:d,content:c,confidence:a.confidence,importance:us(a.kind,d,c),tags:[d],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:y,sourcePaths:p,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return r}function Ot(t){return String(t).padStart(12,"0")}function ls(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var fe=class{constructor(e){this.storage=e}storage;async write(e,r,n){if(n.length===0||r.length===0)return null;let s=Math.min(...r.map(d=>d.sequence)),o=Math.max(...r.map(d=>d.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:n.length,candidates:n},u=JSON.stringify(i,null,2)+`
77
+ `,c=v(n.map(d=>d.fingerprint).sort().join("|")).slice(0,16),a=[ls(e),"batches",`${Ot(s)}-${Ot(o)}-${c}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,u,"application/json"),a}};function hs(t,e){if(!ds(t))return{events:[],nextOffset:e};let r=gs(t).size,n=Number.isFinite(e)?Math.max(0,e):0;if(n>r&&(n=0),n===r)return{events:[],nextOffset:r};let s=r-n,o=Buffer.alloc(s),i=fs(t,"r");try{ms(i,o,0,s,n)}finally{ps(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
78
+ `);if(c<0)return{events:[],nextOffset:n};let a=u.slice(0,c+1);return{events:a.split(`
79
+ `).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(a,"utf8")}}var me=class{constructor(e){this.options=e;this.journal=new fe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),r=Number(e.sourceCursors["memory.learner.offset"]??0),n=Number.isFinite(r)?r:0,s=hs(this.options.wal.eventsFile,n);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Pt(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}}};var ge=class{identity;wal;remote;sanitizer=new z;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=ht(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new de(this.identity),this.remote=new pe(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new me({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ne({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 ie({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let r=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:r}}start(e={}){let r=this.wal.loadState();return this.record({type:r.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(r=>this.sanitizeEvent(r)))}setSourceCursor(e,r){this.wal.setSourceCursor(e,r)}async flush(){let e=this.wal.readPending(),r=this.wal.loadState(),n=await this.remote.append(this.identity,e.events,r.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 n}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as ys,openSync as Ss,closeSync as vs,readSync as bs,statSync as ks}from"node:fs";function ws(t){let e=typeof t.role=="string"?t.role:"",r=typeof t.type=="string"?t.type.toLowerCase():"";return e==="user"||r.includes("user")?"user_prompt":e==="assistant"||r.includes("assistant")||r.includes("model")?"assistant_message":r.includes("tool")||"toolCall"in t||"tool_call"in t?"tool_call":r.includes("error")?"error":"message"}function js(t){let e=[t.timestamp,t.createdAt,t.time,t.created_at];for(let r of e){if(typeof r=="string"){let n=new Date(r);if(!Number.isNaN(n.getTime()))return n.toISOString()}if(typeof r=="number"){let n=r;n<1e11&&(n*=1e3);let s=new Date(n);if(!Number.isNaN(s.getTime()))return s.toISOString()}}return new Date().toISOString()}function Et(t,e={offset:0}){if(!ys(t))return{events:[],nextOffset:e.offset,reset:!1};let r=ks(t).size,n=e.offset>r,s=n?0:e.offset;if(s===r)return{events:[],nextOffset:r,reset:n};let o=r-s,i=Buffer.alloc(o),u=Ss(t,"r");try{bs(u,i,0,o,s)}finally{vs(u)}let c=i.toString("utf8"),a=c.lastIndexOf(`
80
+ `);if(a<0)return{events:[],nextOffset:s,reset:n};let d=c.slice(0,a+1),l=Buffer.byteLength(d,"utf8"),f=[],p=0;for(let y of d.split(`
77
81
  `)){if(!y)continue;let h=Buffer.byteLength(y+`
78
- `,"utf8"),g=s+p;p+=h;let S;try{S=JSON.parse(y)}catch{m.push({type:"custom",sourceEventId:`transcript:${g}`,sourceSequence:g,data:{format:"raw-line",content:y},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:g}});continue}let b=S&&typeof S=="object"&&!Array.isArray(S)?S:{value:S};m.push({type:ms(b),timestamp:gs(b),role:typeof b.role=="string"?b.role:void 0,sourceEventId:`transcript:${g}`,sourceSequence:g,data:b,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:g}})}return{events:m,nextOffset:s+u,reset:n}}var hs=[/^<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*$/],ys=[/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 vs(t){let e=t.toLowerCase();return Ss.some(r=>e.includes(r))}function ks(t){if(!t.trim())return!0;for(let e of hs)if(e.test(t))return!0;return vs(t),!1}function bs(t){let e=t;for(let r of ys)e=e.replace(r,n=>{let s=n.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Ie(t){let e=t.trim();return e?ks(e)?{content:"",filtered:!0,reason:"noise"}:{content:bs(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function de(t){let e={};for(let[r,n]of Object.entries(t))if(typeof n=="string"){let s=Ie(n);s.filtered||(e[r]=s.content)}else n&&typeof n=="object"&&!Array.isArray(n)?e[r]=de(n):Array.isArray(n)?e[r]=n.map(s=>{if(typeof s=="string"){let o=Ie(s);return o.filtered?null:o.content}return s&&typeof s=="object"?de(s):s}).filter(s=>s!==null):e[r]=n;return e}function Pt(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 r=t.data,n=typeof r.content=="string"?r.content:"";if(n&&Ie(n).filtered)return!0}return!1}function xs(t){return t==="~"?Ot():t.startsWith("~/")?ws(Ot(),t.slice(2)):t}async function Et(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let r=js(xs(t.transcriptPath)),n=new pe({project:t.project,storage:t.storage,agent:"agy",nativeSessionId:e,metadata:{source:"antigravity-hook",transcriptPath:r,workspacePaths:t.workspacePaths??[],artifactDirectoryPath:t.artifactDirectoryPath,modelName:t.modelName}}),s=n.status(),o=s.sourceCursors["agy.transcript.offset"],i=o?Number(o):0,l=It(r,{offset:Number.isFinite(i)?i:0}),a=[];s.lastSequence===0&&a.push({type:"session_start",sourceEventId:`agy:${e}:start`,data:{workspacePaths:t.workspacePaths??[],transcriptPath:r,modelName:t.modelName},provenance:{source:"antigravity-hook",sourcePath:r}}),l.reset&&a.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${l.nextOffset}`,data:{event:"transcript_reset",transcriptPath:r},provenance:{source:"agy-transcript",sourcePath:r}});let c=l.events.filter(m=>!Pt(m.data)).map(m=>({...m,data:de(m.data)}));a.push(...c),t.phase==="stop"&&(t.error&&a.push({type:"error",sourceEventId:["agy",e,"stop-error",t.terminationReason??"",l.nextOffset].join(":"),data:{error:t.error,terminationReason:t.terminationReason,fullyIdle:t.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),t.fullyIdle&&a.push({type:"session_idle",sourceEventId:["agy",e,"idle",l.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let f=n.recordMany(a);n.setSourceCursor("agy.transcript.offset",l.nextOffset),t.phase&&n.setSourceCursor("agy.last.phase",t.phase);let u=await n.flush();return{conversationId:e,imported:f.length,eventCount:u.eventCount,chunkCount:u.chunkCount,status:u.status,transcriptOffset:l.nextOffset,reset:l.reset}}async function Is(){let t="";for await(let e of process.stdin)t+=e.toString();if(!t.trim())return{};try{return JSON.parse(t)}catch{return{}}}function q(t){return Array.isArray(t)?t.filter(e=>typeof e=="string"):[]}function Ps(t){let e=typeof t.common=="object"&&t.common!==null?t.common:{},r=typeof t.pre_invocation_hook_args=="object"&&t.pre_invocation_hook_args!==null?t.pre_invocation_hook_args:{},n=typeof t.post_invocation_hook_args=="object"&&t.post_invocation_hook_args!==null?t.post_invocation_hook_args:{},s=typeof t.stop_hook_args=="object"&&t.stop_hook_args!==null?t.stop_hook_args:{},o=(typeof e.conversation_id=="string"?e.conversation_id:"")||(typeof t.conversationId=="string"?t.conversationId:"")||(typeof t.conversation_id=="string"?t.conversation_id:""),i=(typeof e.transcript_path=="string"?e.transcript_path:"")||(typeof t.transcriptPath=="string"?t.transcriptPath:"")||(typeof t.transcript_path=="string"?t.transcript_path:""),l=q(e.workspace_paths).length>0?q(e.workspace_paths):q(t.workspacePaths).length>0?q(t.workspacePaths):q(t.workspace_paths),a=typeof r.invocation_num=="number"?r.invocation_num:typeof t.invocationNum=="number"?t.invocationNum:typeof t.invocation_num=="number"?t.invocation_num:void 0,c=(typeof e.artifact_directory_path=="string"?e.artifact_directory_path:"")||(typeof t.artifactDirectoryPath=="string"?t.artifactDirectoryPath:"")||(typeof t.artifact_directory_path=="string"?t.artifact_directory_path:"")||void 0,f=(typeof e.model_name=="string"?e.model_name:"")||(typeof t.modelName=="string"?t.modelName:"")||(typeof t.model_name=="string"?t.model_name:"")||void 0,u=s.fully_idle===!0||t.fullyIdle===!0||t.fully_idle===!0,m=(typeof s.termination_reason=="string"?s.termination_reason:"")||(typeof t.terminationReason=="string"?t.terminationReason:"")||(typeof t.termination_reason=="string"?t.termination_reason:"")||void 0,p=(typeof s.error=="string"&&s.error?s.error:"")||(typeof t.error=="string"&&t.error?t.error:"")||void 0;return{conversationId:o,transcriptPath:i,workspacePaths:l,invocationNum:a,artifactDirectoryPath:c,modelName:f,fullyIdle:u,terminationReason:m,error:p}}async function Os(){let t=process.argv[2]??"post",e=await Is(),r=Ps(e),n=r.conversationId,s=r.transcriptPath,o=r.workspacePaths,i=pt(o),l={};if(i&&n)try{let a=Ee(),c=Ke($e({provider:a.storage.provider,huggingface:a.storage.huggingface,localRoot:a.storage.localRoot}),{attempts:2}),f=new G(c,i.id,i.name,i.remote??i.name);if(s)try{await Et({project:i,storage:f,conversationId:n,transcriptPath:s,workspacePaths:o,artifactDirectoryPath:r.artifactDirectoryPath,modelName:r.modelName,phase:t,fullyIdle:r.fullyIdle,terminationReason:r.terminationReason,error:r.error})}catch{}if(t==="pre")try{l=await lt({project:i,storage:f,conversationId:n,invocationNum:r.invocationNum})}catch{l={}}if(t==="stop")try{await ke(i,f,900)}catch{}}catch{}if(t==="stop"){process.stdout.write(JSON.stringify({decision:"stop"}));return}process.stdout.write(JSON.stringify(l))}Os().catch(()=>{process.argv[2]==="stop"?process.stdout.write('{"decision":"stop"}'):process.stdout.write("{}"),process.exitCode=0});export{Ps as normalizeAgyInput};
82
+ `,"utf8"),g=s+p;p+=h;let S;try{S=JSON.parse(y)}catch{f.push({type:"custom",sourceEventId:`transcript:${g}`,sourceSequence:g,data:{format:"raw-line",content:y},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:g}});continue}let k=S&&typeof S=="object"&&!Array.isArray(S)?S:{value:S};f.push({type:ws(k),timestamp:js(k),role:typeof k.role=="string"?k.role:void 0,sourceEventId:`transcript:${g}`,sourceSequence:g,data:k,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:g}})}return{events:f,nextOffset:s+l,reset:n}}var xs=[/^<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*$/],Is=[/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],Ps=["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 Ps.some(r=>e.includes(r))}function Es(t){if(!t.trim())return!0;for(let e of xs)if(e.test(t))return!0;return Os(t),!1}function As(t){let e=t;for(let r of Is)e=e.replace(r,n=>{let s=n.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Ae(t){let e=t.trim();return e?Es(e)?{content:"",filtered:!0,reason:"noise"}:{content:As(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function he(t){let e={};for(let[r,n]of Object.entries(t))if(typeof n=="string"){let s=Ae(n);s.filtered||(e[r]=s.content)}else n&&typeof n=="object"&&!Array.isArray(n)?e[r]=he(n):Array.isArray(n)?e[r]=n.map(s=>{if(typeof s=="string"){let o=Ae(s);return o.filtered?null:o.content}return s&&typeof s=="object"?he(s):s}).filter(s=>s!==null):e[r]=n;return e}function At(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 r=t.data,n=typeof r.content=="string"?r.content:"";if(n&&Ae(n).filtered)return!0}return!1}function C(){let t=V(),e=process.env.TOOLNET_SESSION_SAVE||"summary",r=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||e==="archive"||e==="full",n=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",s=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),o=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),u=r,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:r,memoryPromotion:n,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:u,archiveRemote:c}}function Tt(t){return(t||C()).rawTranscript}function Mt(t){return(t||C()).durableMemoryMaxItemsPerSession}function Rt(t){return(t||C()).sessionSummaryMaxTokens}function Ct(t){return(t||C()).archiveRemote}function Ts(t){return t.replace(/\b[A-Za-z0-9_-]{20,}\b/g,"[REDACTED]").replace(/api[_-]?key[:\s=]+[^\s]+/gi,"api_key=[REDACTED]").replace(/token[:\s=]+[^\s]+/gi,"token=[REDACTED]").replace(/secret[:\s=]+[^\s]+/gi,"secret=[REDACTED]").replace(/password[:\s=]+[^\s]+/gi,"password=[REDACTED]")}function Ms(t,e){let r=t.toLowerCase(),n=.5,s=["nh\u1EDB","remember","quy t\u1EAFc","rule","t\u1EEB gi\u1EDD","from now","kh\xF4ng \u0111\u01B0\u1EE3c","must not","lu\xF4n lu\xF4n","always","never","critical","important","blocker","deploy","production","architecture"];for(let i of s)r.includes(i)&&(n+=.15);e==="rule"||e==="architecture"||e==="blocker"?n+=.2:e==="decision"||e==="deploy"?n+=.15:(e==="fix"||e==="next_action")&&(n+=.1),t.length<20?n-=.3:t.length>500&&(n-=.1);let o=[/npm (notice|warn|ERR)/i,/\d+ packages? in \d+/i,/found \d+ vulnerabilities/i,/up to date/i,/added \d+ packages/i,/^(ok|done|success|error|warning)$/i];for(let i of o)i.test(t)&&(n-=.4);return Math.max(0,Math.min(1,n))}function Rs(t,e){let r=[],n=new Set;for(let i of t){let u=i.split(`
83
+ `).filter(c=>c.trim());for(let c of u){let a=c.trim();if(a.length<15)continue;let d=a.toLowerCase().replace(/\s+/g," ");if(n.has(d))continue;n.add(d);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(a)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(a)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(a)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(a)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(a)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(a)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(a)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(a)&&(l="file");let f=Ms(a,l);if(f<.3)continue;let p=Ts(a);r.push({category:l,text:p,importance:f,sourceSessionId:e})}}let s=C(),o=Mt(s);return r.sort((i,u)=>u.importance-i.importance).slice(0,o)}function Cs(t){let e=C(),r=Rt(e),o=t.join(`
84
+
85
+ `).split(`
86
+ `).filter(i=>{let u=i.trim();return u.length>20&&!u.startsWith("npm")&&!u.startsWith("\u2713")&&!u.startsWith("Error:")}).slice(0,20).join(`
87
+ `);return le(o,r)}function Nt(t,e){let n=(Array.isArray(t)?t:t.split(`
88
+
89
+ `).filter(p=>p.trim())).map(p=>typeof p=="string"?p:JSON.stringify(p)).filter(p=>p.trim()),s=Rs(n,e),o=s.filter(p=>p.category==="decision").map(p=>p.text),i=s.filter(p=>p.category==="rule").map(p=>p.text),u=s.filter(p=>p.category==="file").map(p=>p.text),c=s.filter(p=>p.category==="fix").map(p=>p.text),a=s.filter(p=>p.category==="blocker").map(p=>p.text),d=s.filter(p=>p.category==="next_action").map(p=>p.text),l=s.filter(p=>p.category==="deploy").map(p=>p.text);return{summary:Cs(n),decisions:o,projectRules:i,filesChanged:u,bugsFixed:c,commands:l,blockers:a,nextActions:d,durableFacts:s}}function $s(t){return t==="~"?_t():t.startsWith("~/")?Ns(_t(),t.slice(2)):t}async function $t(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let r=_s($s(t.transcriptPath)),n=new ge({project:t.project,storage:t.storage,agent:"agy",nativeSessionId:e,metadata:{source:"antigravity-hook",transcriptPath:r,workspacePaths:t.workspacePaths??[],artifactDirectoryPath:t.artifactDirectoryPath,modelName:t.modelName}}),s=n.status(),o=s.sourceCursors["agy.transcript.offset"],i=o?Number(o):0,u=Et(r,{offset:Number.isFinite(i)?i:0}),c=[];s.lastSequence===0&&c.push({type:"session_start",sourceEventId:`agy:${e}:start`,data:{workspacePaths:t.workspacePaths??[],transcriptPath:r,modelName:t.modelName},provenance:{source:"antigravity-hook",sourcePath:r}}),u.reset&&c.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${u.nextOffset}`,data:{event:"transcript_reset",transcriptPath:r},provenance:{source:"agy-transcript",sourcePath:r}});let a=u.events.filter(f=>!At(f.data)).map(f=>({...f,data:he(f.data)}));c.push(...a),t.phase==="stop"&&(t.error&&c.push({type:"error",sourceEventId:["agy",e,"stop-error",t.terminationReason??"",u.nextOffset].join(":"),data:{error:t.error,terminationReason:t.terminationReason,fullyIdle:t.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),t.fullyIdle&&c.push({type:"session_idle",sourceEventId:["agy",e,"idle",u.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let d=n.recordMany(c);if(n.setSourceCursor("agy.transcript.offset",u.nextOffset),t.phase&&n.setSourceCursor("agy.last.phase",t.phase),t.phase==="stop"&&a.length>0)try{let f=a.map(y=>JSON.stringify(y.data)),p=Nt(f,e);n.setSourceCursor("agy.session.summary",p.summary),n.setSourceCursor("agy.session.facts_count",p.durableFacts.length),Tt()&&(Ct()||n.setSourceCursor("agy.raw_transcript.archived","local"))}catch{}let l=await n.flush();return{conversationId:e,imported:d.length,eventCount:l.eventCount,chunkCount:l.chunkCount,status:l.status,transcriptOffset:u.nextOffset,reset:u.reset}}async function Ls(){let t="";for await(let e of process.stdin)t+=e.toString();if(!t.trim())return{};try{return JSON.parse(t)}catch{return{}}}function J(t){return Array.isArray(t)?t.filter(e=>typeof e=="string"):[]}function Ds(t){let e=typeof t.common=="object"&&t.common!==null?t.common:{},r=typeof t.pre_invocation_hook_args=="object"&&t.pre_invocation_hook_args!==null?t.pre_invocation_hook_args:{},n=typeof t.post_invocation_hook_args=="object"&&t.post_invocation_hook_args!==null?t.post_invocation_hook_args:{},s=typeof t.stop_hook_args=="object"&&t.stop_hook_args!==null?t.stop_hook_args:{},o=(typeof e.conversation_id=="string"?e.conversation_id:"")||(typeof t.conversationId=="string"?t.conversationId:"")||(typeof t.conversation_id=="string"?t.conversation_id:""),i=(typeof e.transcript_path=="string"?e.transcript_path:"")||(typeof t.transcriptPath=="string"?t.transcriptPath:"")||(typeof t.transcript_path=="string"?t.transcript_path:""),u=J(e.workspace_paths).length>0?J(e.workspace_paths):J(t.workspacePaths).length>0?J(t.workspacePaths):J(t.workspace_paths),c=typeof r.invocation_num=="number"?r.invocation_num:typeof t.invocationNum=="number"?t.invocationNum:typeof t.invocation_num=="number"?t.invocation_num:void 0,a=(typeof e.artifact_directory_path=="string"?e.artifact_directory_path:"")||(typeof t.artifactDirectoryPath=="string"?t.artifactDirectoryPath:"")||(typeof t.artifact_directory_path=="string"?t.artifact_directory_path:"")||void 0,d=(typeof e.model_name=="string"?e.model_name:"")||(typeof t.modelName=="string"?t.modelName:"")||(typeof t.model_name=="string"?t.model_name:"")||void 0,l=s.fully_idle===!0||t.fullyIdle===!0||t.fully_idle===!0,f=(typeof s.termination_reason=="string"?s.termination_reason:"")||(typeof t.terminationReason=="string"?t.terminationReason:"")||(typeof t.termination_reason=="string"?t.termination_reason:"")||void 0,p=(typeof s.error=="string"&&s.error?s.error:"")||(typeof t.error=="string"&&t.error?t.error:"")||void 0;return{conversationId:o,transcriptPath:i,workspacePaths:u,invocationNum:c,artifactDirectoryPath:a,modelName:d,fullyIdle:l,terminationReason:f,error:p}}async function Ks(){let t=process.argv[2]??"post",e=await Ls(),r=Ds(e),n=r.conversationId,s=r.transcriptPath,o=r.workspacePaths,i=mt(o),u={};if(i&&n)try{let c=V(),a=We(Ke({provider:c.storage.provider,huggingface:c.storage.huggingface,localRoot:c.storage.localRoot}),{attempts:2}),d=new X(a,i.id,i.name,i.remote??i.name);if(s)try{await $t({project:i,storage:d,conversationId:n,transcriptPath:s,workspacePaths:o,artifactDirectoryPath:r.artifactDirectoryPath,modelName:r.modelName,phase:t,fullyIdle:r.fullyIdle,terminationReason:r.terminationReason,error:r.error})}catch{}if(t==="pre")try{u=await ft({project:i,storage:d,conversationId:n,invocationNum:r.invocationNum})}catch{u={}}if(t==="stop")try{await xe(i,d,800)}catch{}}catch{}if(t==="stop"){process.stdout.write(JSON.stringify({decision:"stop"}));return}process.stdout.write(JSON.stringify(u))}Ks().catch(()=>{process.argv[2]==="stop"?process.stdout.write('{"decision":"stop"}'):process.stdout.write("{}"),process.exitCode=0});export{Ds as normalizeAgyInput};