toolnet-memory 0.2.9 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +30 -10
- package/LICENSE +21 -0
- package/README.md +146 -376
- package/bundle/agy-hook.js +25 -25
- package/bundle/agy.js +23 -23
- package/bundle/codex-context.js +12 -12
- package/bundle/codex.js +29 -29
- package/bundle/context-runtime.js +13 -13
- package/bundle/context.js +13 -13
- package/bundle/doctor.js +3 -3
- package/bundle/full-index.js +8 -8
- package/bundle/graph-index.js +4 -4
- package/bundle/impact.js +4 -4
- package/bundle/incremental.js +4 -4
- package/bundle/learner.js +5 -5
- package/bundle/mcp.js +7 -7
- package/bundle/opencode.js +34 -34
- package/bundle/project-manual.js +7 -7
- package/bundle/runtime.js +11 -11
- package/bundle/semantic.js +6 -6
- package/bundle/setup.js +57 -32
- package/bundle/snapshot.js +4 -4
- package/bundle/work-continuity.js +7 -7
- package/package.json +24 -1
package/bundle/agy-hook.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import{existsSync as
|
|
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
|
|
3
|
-
`,{encoding:"utf8",mode:384}),Tt(s,n)}function Pe(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var J=class{detect(e=process.cwd()){let r=W(e),n=Ft(r),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>le(V(n,d))),i=Wt(r,o?n:void 0);if(i){let d=de(i),p=Bt(d);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),Ie(i,p)),Pe(p,i)}let u=new Date().toISOString(),a=Ct(n),c={version:1,id:Lt(n),name:a,remote:a,rootPath:n,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return Ie(n,c),Pe(c,n)}};var Dt=[{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}],U=class{scan(e){let r=[];for(let n of Dt){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 F=class{scanner=new U;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 sr}from"node:os";import{join as or}from"node:path";import{DeleteObjectCommand as Kt,GetObjectCommand as qt,HeadObjectCommand as Jt,ListObjectsV2Command as Vt,PutObjectCommand as Ut,S3Client as Ht}from"@aws-sdk/client-s3";import{getSignedUrl as Yt}from"@aws-sdk/s3-request-presigner";var H=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ht({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 Ut({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await Yt(this.client,new qt({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 Jt({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 Kt({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new Vt({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 Ae,mkdir as Gt,readFile as Qt,readdir as Xt,rm as Zt,stat as Ne,writeFile as er}from"node:fs/promises";import{dirname as tr,join as rr,relative as Me,resolve as nr}from"node:path";var B=class{constructor(e){this.root=e}root;name="local";path(e){let r=e.replace(/^\/+/,"");return nr(this.root,r)}async put(e,r){let n=this.path(e);await Gt(tr(n),{recursive:!0}),await er(n,r)}async get(e){try{return await Qt(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 Ae(this.path(e)),!0}catch{return!1}}async delete(e){await Zt(this.path(e),{force:!0})}async list(e=""){let r=this.path(e),n=[];try{await Ae(r)}catch{return n}let s=async i=>{let u=await Xt(i,{withFileTypes:!0});for(let a of u){let c=rr(i,a.name);if(a.isDirectory()){await s(c);continue}let d=await Ne(c);n.push({key:Me(this.root,c),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await Ne(r);return o.isDirectory()?await s(r):n.push({key:Me(this.root,r),size:o.size,updatedAt:o.mtime.toISOString()}),n}};function Re(t){let e=t.localRoot??or(sr(),".toolnet-memory","storage");if(t.provider==="huggingface"){let r=t.huggingface;return r?.namespace&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new H({namespace:r.namespace,bucket:r.bucket,accessKeyId:r.accessKeyId,secretAccessKey:r.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new B(e))}return new B(e)}function ir(t){return new Promise(e=>setTimeout(e,t))}async function Te(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 a=Math.min(s,n*2**(i-1)),c=Math.floor(Math.random()*Math.max(1,a*.2));await ir(a+c)}throw o}var ar=new Set(["put","get","getText","delete","list"]);function _e(t,e={}){return new Proxy(t,{get(r,n){let s=Reflect.get(r,n,r);return typeof s!="function"?s:ar.has(n)?(...o)=>Te(()=>Promise.resolve(s.apply(r,o)),e):s.bind(r)}})}function Ce(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function $e(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let 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 Y=class{constructor(e,r,n,s){this.provider=e;this.name=e.name,this.projectId=r,this.projectName=n,this.folder=Ce(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
|
|
5
|
-
`,{encoding:"utf8",mode:384}),
|
|
6
|
-
`,u=v(r.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${
|
|
7
|
-
`,"application/json"),E}async function
|
|
1
|
+
import{existsSync as Pt,readFileSync as Ot}from"node:fs";import{homedir as Et}from"node:os";import{join as At}from"node:path";function Nt(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 Rt(){let t=process.env.TOOLNET_GLOBAL_ENV??At(Et(),".config","toolnet-memory",".env");if(!Pt(t))return;let e=Ot(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]=Nt(n.slice(s+1)))}}Rt();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 Pe(){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 Tt}from"node:crypto";import{existsSync as de,mkdirSync as Mt,readFileSync as Ct,renameSync as _t,writeFileSync as $t}from"node:fs";import{basename as Lt,dirname as J,join as U,parse as Ae,resolve as W}from"node:path";var Ne=".toolnet",Kt="project.json";function zt(t){return Tt("sha256").update(t).digest("hex").slice(0,16)}function fe(t){return U(t,Ne,Kt)}function Wt(t){return de(fe(t))}function Bt(t,e){let r=W(t),n=Ae(r).root;for(;;){if(Wt(r))return r;if(r===n||e&&r===W(e))break;let s=J(r);if(s===r)break;r=s}return null}function Dt(t){let e=W(t),r=Ae(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(o=>de(U(e,o))))return e;if(e===r)break;let s=J(e);if(s===e)break;e=s}return W(t)}function Ft(t){let e;try{e=JSON.parse(Ct(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let 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 Oe(t,e){let r=U(t,Ne);Mt(r,{recursive:!0});let n=fe(t),s=`${n}.tmp-${process.pid}`;$t(s,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),_t(s,n)}function Ee(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=Dt(r),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>de(U(n,d))),i=Bt(r,o?n:void 0);if(i){let d=fe(i),p=Ft(d);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),Oe(i,p)),Ee(p,i)}let u=new Date().toISOString(),a=Lt(n),c={version:1,id:zt(n),name:a,remote:a,rootPath:n,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return Oe(n,c),Ee(c,n)}};var qt=[{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 qt){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 B=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 fr}from"node:os";import{join as mr}from"node:path";import{DeleteObjectCommand as Jt,GetObjectCommand as Vt,HeadObjectCommand as Ut,ListObjectsV2Command as Ht,PutObjectCommand as Yt,S3Client as Gt}from"@aws-sdk/client-s3";import{getSignedUrl as Qt}from"@aws-sdk/s3-request-presigner";var Y=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Gt({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 Yt({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await Qt(this.client,new Vt({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 Ut({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 Jt({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new Ht({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 Re,mkdir as Xt,readFile as Zt,readdir as er,rm as tr,stat as Te,writeFile as rr}from"node:fs/promises";import{dirname as nr,join as sr,relative as Me,resolve as or}from"node:path";var D=class{constructor(e){this.root=e}root;name="local";path(e){let r=e.replace(/^\/+/,"");return or(this.root,r)}async put(e,r){let n=this.path(e);await Xt(nr(n),{recursive:!0}),await rr(n,r)}async get(e){try{return await Zt(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 Re(this.path(e)),!0}catch{return!1}}async delete(e){await tr(this.path(e),{force:!0})}async list(e=""){let r=this.path(e),n=[];try{await Re(r)}catch{return n}let s=async i=>{let u=await er(i,{withFileTypes:!0});for(let a of u){let c=sr(i,a.name);if(a.isDirectory()){await s(c);continue}let d=await Te(c);n.push({key:Me(this.root,c),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await Te(r);return o.isDirectory()?await s(r):n.push({key:Me(this.root,r),size:o.size,updatedAt:o.mtime.toISOString()}),n}};import{DeleteObjectCommand as ir,GetObjectCommand as ar,HeadObjectCommand as cr,ListObjectsV2Command as ur,PutObjectCommand as pr,S3Client as lr}from"@aws-sdk/client-s3";import{getSignedUrl as dr}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 lr({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 pr({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await dr(this.client,new ar({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 cr({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 ir({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new ur({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 me(t,e){return console.warn(e),new D(t)}function Ce(t){let e=t.localRoot??mr(fr(),".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}):me(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}):me(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}):me(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new D(e)}function gr(t){return new Promise(e=>setTimeout(e,t))}async function _e(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 a=Math.min(s,n*2**(i-1)),c=Math.floor(Math.random()*Math.max(1,a*.2));await gr(a+c)}throw o}var hr=new Set(["put","get","getText","delete","list"]);function $e(t,e={}){return new Proxy(t,{get(r,n){let s=Reflect.get(r,n,r);return typeof s!="function"?s:hr.has(n)?(...o)=>_e(()=>Promise.resolve(s.apply(r,o)),e):s.bind(r)}})}function Le(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 Ke(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=Le(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=Ke(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 yr}from"node:crypto";import{dirname as Sr}from"node:path";import{mkdirSync as vr,readFileSync as kr,renameSync as br,writeFileSync as wr}from"node:fs";function v(t){return yr("sha256").update(t).digest("hex")}function ge(t){if(Array.isArray(t))return t.map(ge);if(t&&typeof t=="object"){let e=t,r={};for(let n of Object.keys(e).sort())r[n]=ge(e[n]);return r}return t}function ze(t){return JSON.stringify(ge(t))}function We(t){try{return JSON.parse(kr(t,"utf8"))}catch{return null}}function x(t,e){vr(Sr(t),{recursive:!0});let r=`${t}.${process.pid}.tmp`;wr(r,JSON.stringify(e,null,2)+`
|
|
5
|
+
`,{encoding:"utf8",mode:384}),br(r,t)}var jr=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 De(t){return _(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function C(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))C(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(jr.has(n)||["data","payload","parts","messages"].includes(n))&&C(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 Be(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??De(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 xr(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 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 g=Number(c[1]),l=_(c[2]??""),y=l&&!Be(l)?`Phase ${g} - ${l}`:`Phase ${g}`;s.push(w(t,e,"phase",y,{key:`phase:${g}`,order:g,status:Q(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":Q(d[2]),confidence:.96}));let p=n.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(p?.[2]){let g=p[1]?Number(p[1]):void 0,l=_(p[2]),y=Be(l);s.push(w(t,e,"task",y&&g!==void 0?`TODO ${g}`:l,{key:g!==void 0?`task:${g}`:De(l),order:g,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 g=n.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");g&&s.push(w(t,e,"next_action",g,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(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 Fe(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=[];C(i.data,a);for(let c of a)s(w(t,i,"decision",c,{confidence:1}))}if(i.type==="todo"){let a=[];C(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=[];C(i.data,a);for(let c of a)s(w(t,i,"test",c,{confidence:1}))}let u=[];C(i.data,u);for(let a of u)for(let c of a.split(/\n+/u))for(let d of xr(t,i,c))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 qe(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
|
+
`,u=v(r.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${qe(n)}-${qe(s)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,i,"application/json"),a}};import{join as Je}from"node:path";import{mkdirSync as Ir}from"node:fs";function Pr(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=Pr(s);if(!(!o||n.has(o))&&(n.add(o),r.push(s),r.length>=e))break}return r.reverse()}function Or(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 Ve(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&&Or(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 Er(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 Z(t,e){let n=(await Er(t,e)).flatMap(f=>f.observations).sort((f,j)=>{let xe=f.occurredAt.localeCompare(j.occurredAt);if(xe!==0)return xe;let Ie=f.sequence-j.sequence;return Ie!==0?Ie:f.id.localeCompare(j.id)}),s=new Map,o=new Map,i,u,a,c=[],d=[],p=[],g=[],l=[],y=[];for(let f of n)switch(f.kind){case"goal":i=f.text;break;case"plan":u=f.text;break;case"phase":s.set(f.key,Ve(s.get(f.key),f));break;case"task":o.set(f.key,Ve(o.get(f.key),f));break;case"decision":c.push(f.text);break;case"blocker":d.push(f.text);break;case"warning":p.push(f.text);break;case"next_action":g.push(f.text);break;case"file":l.push(f.text);break;case"test":y.push(f.text);break;case"session":a={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let h=Array.from(s.values()).sort((f,j)=>(f.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),m=Array.from(o.values()).sort((f,j)=>(f.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),S=h.find(f=>f.status==="in_progress")??h.find(f=>f.status==="blocked")??h.find(f=>f.status==="pending"),b=m.find(f=>f.status==="in_progress")??m.find(f=>f.status==="blocked")??m.find(f=>f.status==="pending"),R=$([...g,...b?[b.title]:[],...!b&&S?[S.title]:[],...m.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),M=$([...d,...h.filter(f=>f.status==="blocked").map(f=>f.title),...m.filter(f=>f.status==="blocked").map(f=>f.title)],20),E={version:1,projectId:t.id,projectName:t.name,goal:i,plan:u,phases:h,tasks:m,decisions:$(c,20),blockers:M,warnings:$(p,20),nextActions:R,filesTouched:$(l,30),tests:$(y,20),currentPhase:S,currentTask:b,progress:{phasesTotal:h.length,phasesCompleted:h.filter(f=>f.status==="completed").length,tasksTotal:m.length,tasksCompleted:m.filter(f=>f.status==="completed").length,blocked:h.filter(f=>f.status==="blocked").length+m.filter(f=>f.status==="blocked").length},lastSession:a,updatedAt:n.length?n[n.length-1].occurredAt:new Date().toISOString()},T=Je(t.rootPath,".toolnet","work");return Ir(T,{recursive:!0}),x(Je(T,"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 Ar,existsSync as Nr,openSync as Rr,readSync as Tr,statSync as Mr}from"node:fs";function Cr(t,e){if(!Nr(t))return{events:[],nextOffset:e};let r=Mr(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=Rr(t,"r");try{Tr(i,o,0,s,n)}finally{Ar(i)}let u=o.toString("utf8"),a=u.lastIndexOf(`
|
|
8
8
|
`);if(a<0)return{events:[],nextOffset:n};let c=u.slice(0,a+1);return{events:c.split(`
|
|
9
|
-
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(c,"utf8")}}var
|
|
9
|
+
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}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=Cr(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=Fe(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 qr}from"node:fs";import{join as he}from"node:path";import{existsSync as Ye,mkdirSync as _r,readFileSync as $r,statSync as Ue,writeFileSync as Lr}from"node:fs";import{dirname as Kr,join as zr}from"node:path";var He=64*1024,Wr=`# 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,30 @@ Things an AI agent should always remember.
|
|
|
49
49
|
<!--
|
|
50
50
|
- [advisory] Prefer small focused files.
|
|
51
51
|
-->
|
|
52
|
-
`;function
|
|
52
|
+
`;function re(t){return zr(t.rootPath,".toolnet","PROJECT.md")}function Br(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Dr(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=Br(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 Fr(t){let e=re(t);return Ye(e)||(_r(Kr(e),{recursive:!0}),Lr(e,Wr,{encoding:"utf8",mode:384})),e}function ne(t,e=!1){let r=e?Fr(t):re(t);if(!Ye(r))return null;if(Ue(r).size>He)throw new Error(`PROJECT.md exceeds ${He} bytes`);let s=$r(r,"utf8");return{path:r,content:s,digest:v(s),rules:Dr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Ue(r).mtimeMs).toISOString()}}function Jr(t){return{goal:t.goal,plan:t.plan,phases:t.phases.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),tasks:t.tasks.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),decisions:t.decisions,blockers:t.blockers,warnings:t.warnings,nextActions:t.nextActions,filesTouched:t.filesTouched,tests:t.tests}}function Vr(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)),!Vr(n))return null;let s=ne(this.options.project,!1),o=s?s.rules.filter(g=>g.mode==="enforce").map(g=>g.text):[],i=v(JSON.stringify(Jr(n))),u=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),a=new Date().toISOString(),c={version:1,id:u,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(g=>g.status!=="completed"&&g.status!=="cancelled"),incompleteTasks:n.tasks.filter(g=>g.status!=="completed"&&g.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(c,null,2)+`
|
|
53
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 p=
|
|
55
|
-
`,"application/json"),l}async function
|
|
56
|
-
`);if(
|
|
57
|
-
`)),i=Math.max(0,e-o);if(i>=16){let u=Math.floor(i*3.2),a=
|
|
58
|
-
`).trim()}async function
|
|
59
|
-
`,"application/json"),u}};import{closeSync as
|
|
54
|
+
`,"application/json");let p=he(this.options.project.rootPath,".toolnet","work","handoffs");return qr(p,{recursive:!0}),x(he(p,`${u}.json`),c),x(he(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),c),c}};async function Ge(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 Ur}from"node:fs";import{join as Qe}from"node:path";function Hr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Yr(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 Yr(e,t)?e:t}function N(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 Gr(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 Qr(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function Xe(t,e){let n=(await Gr(t,e)).flatMap(h=>h.observations).sort((h,m)=>{let S=h.evidence.occurredAt.localeCompare(m.evidence.occurredAt);return S!==0?S:h.evidence.sessionKey===m.evidence.sessionKey?h.evidence.sequence-m.evidence.sequence:h.id.localeCompare(m.id)}),s,o,i,u,a,c=new Map,d=[],p=[],g=[];for(let h of n){let m=Hr(h);if(h.scope==="phase"&&h.scopeKey){let S=c.get(h.scopeKey)??Qr(h);switch(h.kind){case"phase_objective":S.objective=A(S.objective,m);break;case"phase_why":S.why=A(S.why,m);break;case"phase_deliverable":S.deliverable=A(S.deliverable,m);break;case"acceptance_criterion":S.acceptanceCriteria.push(m);break;case"dependency":S.dependencies.push(m);break;case"open_question":S.openQuestions.push(m);break;case"constraint":S.constraints.push(m);break;case"note":S.notes.push(m);break}c.set(S.key,S);continue}switch(h.kind){case"mission":s=A(s,m);break;case"objective":o=A(o,m);break;case"why":i=A(i,m);break;case"desired_outcome":u=A(u,m);break;case"plan_rationale":a=A(a,m);break;case"open_question":d.push(m);break;case"constraint":p.push(m);break;case"note":g.push(m);break}}for(let h of c.values())h.acceptanceCriteria=N(h.acceptanceCriteria,20),h.dependencies=N(h.dependencies,15),h.openQuestions=N(h.openQuestions,15),h.constraints=N(h.constraints,15),h.notes=N(h.notes,20);let l={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:u,planRationale:a,phases:Array.from(c.values()).sort((h,m)=>h.order-m.order),openQuestions:N(d,20),constraints:N(p,20),notes:N(g,20),updatedAt:n.length?n[n.length-1].evidence.occurredAt:new Date().toISOString()},y=Qe(t.rootPath,".toolnet","work");return Ur(y,{recursive:!0}),x(Qe(y,"semantic-current.json"),l),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
|
|
55
|
+
`,"application/json"),l}async function Ze(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 ye(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 Xr(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 Zr(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(c=>o.startsWith(c));if(!u)continue;let a=s.slice(u.length).trim();a&&(u.includes("enforce")?e.push(a):r.push(a))}return{enforce:e,advisory:r}}function en(t,e){let r=[];for(let n of t){let s=[...r,n].join(`
|
|
56
|
+
`);if(ye(s)<=e){r.push(n);continue}let o=ye(r.join(`
|
|
57
|
+
`)),i=Math.max(0,e-o);if(i>=16){let u=Math.floor(i*3.2),a=k(n,u);a&&r.push(a)}break}return r.join(`
|
|
58
|
+
`).trim()}async function et(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=Zr(n),o=r?r.rules.filter(l=>l.mode==="enforce").map(l=>l.text):s.enforce,i=r?r.rules.filter(l=>l.mode==="advisory").map(l=>l.text):s.advisory,u=n?Xr(n):[],a=await ee(t.project,t.storage),c=await Ze(t.project,t.storage),d=await Ge(t.project,t.storage),p=[];if(p.push("[TOOLNET PROJECT CONTEXT]"),p.push(`Project: ${t.project.name}`),p.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),n&&p.push(`Full operating manual: ${re(t.project)}`),o.length){p.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let l of o.slice(0,24))p.push(`- [ENFORCE] ${k(l,240)}`)}if(i.length){p.push("","PROJECT PREFERENCES");for(let l of i.slice(0,10))p.push(`- ${k(l,220)}`)}if(c&&(c.mission&&p.push("","MISSION",k(c.mission.value,420)),c.activeObjective&&p.push("","CURRENT OBJECTIVE",k(c.activeObjective.value,420)),c.why&&p.push("","WHY THIS WORK MATTERS",k(c.why.value,420)),c.desiredOutcome&&p.push("","DESIRED OUTCOME",k(c.desiredOutcome.value,420)),c.planRationale&&p.push("","WHY THIS APPROACH",k(c.planRationale.value,420))),a){if(p.push("","ACTIVE WORK"),a.goal&&p.push(`Goal: ${k(a.goal,320)}`),a.plan&&p.push(`Plan: ${k(a.plan,320)}`),p.push(`Progress: phases ${a.progress.phasesCompleted}/${a.progress.phasesTotal}; tasks ${a.progress.tasksCompleted}/${a.progress.tasksTotal}; blocked ${a.progress.blocked}`),a.currentPhase&&p.push(`Current phase: ${a.currentPhase.title} [${a.currentPhase.status}]`),a.currentPhase&&c){let l=c.phases.find(y=>y.order===a.currentPhase?.order);l&&(l.objective&&p.push(`Phase objective: ${k(l.objective.value,340)}`),l.why?p.push(`Why this phase: ${k(l.why.value,340)}`):p.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),l.deliverable&&p.push(`Deliverable: ${k(l.deliverable.value,340)}`),l.dependencies.length&&p.push(`Depends on: ${l.dependencies.slice(0,4).map(y=>k(y.value,180)).join("; ")}`),l.acceptanceCriteria.length&&(p.push("","DEFINITION OF DONE"),l.acceptanceCriteria.slice(0,6).forEach(y=>{p.push(`- ${k(y.value,260)}`)})),l.openQuestions.length&&(p.push("","OPEN QUESTIONS FOR CURRENT PHASE"),l.openQuestions.slice(0,4).forEach(y=>{p.push(`- ${k(y.value,260)}`)})))}a.currentTask&&p.push(`Current task: ${a.currentTask.title} [${a.currentTask.status}]`),a.nextActions.length&&(p.push("","NEXT ACTIONS"),a.nextActions.slice(0,6).forEach((l,y)=>{p.push(`${y+1}. ${k(l,260)}`)})),a.blockers.length&&(p.push("","BLOCKERS"),a.blockers.slice(0,5).forEach(l=>{p.push(`- ${k(l,260)}`)})),a.warnings.length&&(p.push("","ATTENTION"),a.warnings.slice(-5).forEach(l=>{p.push(`- ${k(l,260)}`)})),a.decisions.length&&(p.push("","RECENT DECISIONS"),a.decisions.slice(-5).forEach(l=>{p.push(`- ${k(l,260)}`)})),a.lastSession&&p.push("",`Last work session: ${a.lastSession.agent} / ${a.lastSession.nativeSessionId}`)}if(c&&c.openQuestions.length&&(p.push("","UNRESOLVED QUESTIONS"),c.openQuestions.slice(0,5).forEach(l=>{p.push(`- ${k(l.value,260)}`)})),d&&p.push(`Latest handoff: ${d.reason} / ${d.sourceSession.agent}`),u.length){p.push("","OPERATING NOTES");for(let l of u)p.push(`- ${l}`)}p.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let g=en(p,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:g,estimatedTokens:ye(g),maxTokens:e,hasManual:!!n,hasWorkState:!!a,hasHandoff:!!d,generatedAt:new Date().toISOString()}}var tn=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 Se(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))Se(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(tn.has(n)||["data","payload","parts","messages"].includes(n))&&Se(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 rn(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function nn(t){return L(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function tt(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=[];Se(o.data,i);for(let u of i){let a={type:"project"},c=null;for(let d of u.split(/\r?\n/u)){let p=L(d);if(!p){c=null;continue}let g=p.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(g){let j=Number(g[1]);a={type:"phase",key:`phase:${j}`,order:j,title:L(g[2]??"")},c=null;continue}let l=p.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let j=Number(l[1]);a={type:"task",key:`task:${j}`,order:j,title:L(l[2]??"")},c=null;continue}let y=O(p,["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(p,["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 m=O(p,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(m){s(I(t,o,a.type==="phase"?"phase_why":"why",m,a,.98)),c=null;continue}let S=O(p,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(S){s(I(t,o,"desired_outcome",S,{type:"project"},.98)),c=null;continue}let b=O(p,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(b){s(I(t,o,"plan_rationale",b,{type:"project"},.98)),c=null;continue}let R=O(p,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(R){s(I(t,o,"phase_deliverable",R,a,.97)),c=null;continue}let M=O(p,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(M){s(I(t,o,"acceptance_criterion",M,a,.98)),c="acceptance_criterion";continue}let E=O(p,["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 T=O(p,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(T){s(I(t,o,"open_question",T,a,.95)),c="open_question";continue}let f=O(p,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(f){s(I(t,o,"constraint",f,a,.97)),c="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(p)){c="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(p)){c="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(p)){c="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(p)){c="constraint";continue}if(c&&rn(d)){s(I(t,o,c,nn(d),a,.96));continue}c=null}}}return r}function rt(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),u=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${rt(n)}-${rt(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 sn,existsSync as on,openSync as an,readSync as cn,statSync as un}from"node:fs";function pn(t,e){if(!on(t))return{events:[],nextOffset:e};let r=un(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=an(t,"r");try{cn(o,s,0,s.length,n)}finally{sn(o)}let i=s.toString("utf8"),u=i.lastIndexOf(`
|
|
60
60
|
`);if(u<0)return{events:[],nextOffset:n};let a=i.slice(0,u+1);return{events:a.split(`
|
|
61
|
-
`).filter(Boolean).flatMap(c=>{try{return[JSON.parse(c)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(a,"utf8")}}var
|
|
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=pn(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=tt(this.options.identity,n.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Xe(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 ln,mkdirSync as dn,readFileSync as fn,writeFileSync as mn}from"node:fs";import{dirname as gn,join as nt}from"node:path";function st(t){return nt(t.rootPath,".toolnet","context","startup.md")}function hn(t){return nt(t.rootPath,".toolnet","context","startup.json")}function ot(t,e){let r=st(t);dn(gn(r),{recursive:!0}),mn(r,e.text.endsWith(`
|
|
62
62
|
`)?e.text:e.text+`
|
|
63
|
-
`,{encoding:"utf8",mode:384}),x(
|
|
63
|
+
`,{encoding:"utf8",mode:384}),x(hn(t),e)}async function ve(t,e,r=900){let n=await et({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 ot(t,s),await e.put(`projects/${t.id}/context/startup.md`,s.text+`
|
|
64
64
|
`,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(s,null,2)+`
|
|
65
|
-
`,"application/json"),s}async function
|
|
65
|
+
`,"application/json"),s}async function it(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 ot(t,i),i}}catch{}let n=st(t);if(ln(n))try{let s=fn(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 ve(t,e,r)}catch{return null}}import{existsSync as yn,mkdirSync as Sn,readFileSync as vn}from"node:fs";import{homedir as kn}from"node:os";import{dirname as bn,join as at}from"node:path";function wn(t,e,r){let n=r??at(kn(),".config","toolnet-memory","injections","agy");return at(n,`${t.id}-${e}.json`)}function jn(t){if(!yn(t))return null;try{return JSON.parse(vn(t,"utf8"))}catch{return null}}async function ct(t){let e=t.now??Date.now(),r=t.resumeAfterMs??360*60*1e3,n=wn(t.project,t.conversationId,t.markerDirectory),s=jn(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,a=i>=r;if(s&&!u&&!a)return{};let c=await it(t.project,t.storage,900);return c?.text?(Sn(bn(n),{recursive:!0}),x(n,{digest:c.digest,injectedAt:new Date(e).toISOString()}),{injectSteps:[{userMessage:c.text}]}):{}}import{existsSync as xn}from"node:fs";import{dirname as In,join as Pn,parse as On,resolve as En}from"node:path";function ut(t){for(let e of t){let r=En(e),n=On(r).root;for(;;){if(xn(Pn(r,".toolnet","project.json")))return new V().detect(r);if(r===n)break;let s=In(r);if(s===r)break;r=s}}return null}import{homedir as xt}from"node:os";import{join as fs,resolve as ms}from"node:path";import{join as An}from"node:path";function pt(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 lt(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=pt(n.toLowerCase(),"agent"),i=pt(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:An(t.rootPath,".toolnet","sessions",o,i)}}function dt(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
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 u=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!u)continue;let a=Number(u[1]),c=Number(u[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,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)+`
|
|
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),u=r.filter(m=>m.sequence>i.maxSequence),a=0;for(let m of this.split(u)){let S=m[0],
|
|
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),u=r.filter(m=>m.sequence>i.maxSequence),a=0;for(let m of this.split(u)){let S=m[0],b=m[m.length-1],R=m.map(T=>JSON.stringify(T)).join(`
|
|
68
68
|
`)+`
|
|
69
|
-
`,
|
|
69
|
+
`,M=v(R).slice(0,16),E=[e.remotePrefix,"events",`${dt(S.sequence)}-${dt(b.sequence)}-${M}.jsonl`].join("/");await this.storage.exists(E)||await this.storage.put(E,R,"application/x-ndjson"),a+=m.length}let c=await this.scan(e),d=r[r.length-1],p=o?.status??"active";d?.type==="session_end"||d?.type==="session_idle"?p="idle":d?.type==="error"?p="error":r.length>0&&(p="active");let g=new Date().toISOString(),l=r[0],y={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:p,createdAt:o?.createdAt??l?.timestamp??g,updatedAt:d?.timestamp??g,firstEventAt:o?.firstEventAt??l?.timestamp,lastEventAt:d?.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:g};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,y),{uploadedEvents:a,lastRemoteSequence:c.maxSequence,eventCount:y.eventCount,chunkCount:y.chunkCount,status:p}}};import{closeSync as ke,existsSync as Nn,fsyncSync as Rn,mkdirSync as Tn,openSync as be,readSync as Mn,rmSync as ft,statSync as mt,writeSync as Cn}from"node:fs";import{join as we}from"node:path";var _n=12e4,$n=80,Ln=2e3;function Kn(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ce=class{constructor(e){this.identity=e;Tn(e.localDirectory,{recursive:!0}),this.eventsFile=we(e.localDirectory,"events.jsonl"),this.stateFile=we(e.localDirectory,"state.json"),this.lockFile=we(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 We(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){x(this.stateFile,e)}acquireLock(){for(let e=0;e<$n;e+=1)try{return be(this.lockFile,"wx",384)}catch(r){if(r.code!=="EEXIST")throw r;try{if(Date.now()-mt(this.lockFile).mtimeMs>_n){ft(this.lockFile,{force:!0});continue}}catch{}Kn(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let r=this.acquireLock();try{return e()}finally{ke(r),ft(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 p of e){let g=p.timestamp??new Date().toISOString(),l=p.data??{},y=p.provenance?.rawDigest??v(ze(l)),h=p.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,p.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,p.type,g,y].join("|"),m=v(h).slice(0,32);if(n.has(m))continue;s+=1;let S={version:1,id:m,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:p.type,timestamp:g,data:l,provenance:{...p.provenance,rawDigest:y}};p.role!==void 0&&(S.role=p.role),p.sourceEventId!==void 0&&(S.sourceEventId=p.sourceEventId),p.sourceSequence!==void 0&&(S.sourceSequence=p.sourceSequence),o.push(S),n.add(m)}if(o.length===0)return[];let i=o.map(p=>JSON.stringify(p)).join(`
|
|
70
70
|
`)+`
|
|
71
|
-
`,u=
|
|
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
|
|
73
|
-
`,a=v(n.map(d=>d.fingerprint).sort().join("|")).slice(0,16),c=[
|
|
71
|
+
`,u=be(this.eventsFile,"a",384);try{Cn(u,i,null,"utf8"),Rn(u)}finally{ke(u)}let a=o[o.length-1],c="active";a.type==="session_end"||a.type==="session_idle"?c="idle":a.type==="error"&&(c="error");let d=Array.from(n).slice(-Ln);return this.saveStateUnsafe({...r,status:c,updatedAt:a.timestamp,lastSequence:a.sequence,recentEventIds:d}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Nn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let r=mt(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=be(this.eventsFile,"r");try{Mn(i,o,0,s,n)}finally{ke(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 es,existsSync as ts,openSync as rs,readSync as ns,statSync as ss}from"node:fs";function gt(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 vt=[/không được/iu,/tuyệt đối/iu,/bắt buộc/iu,/đừng\s+/iu,/must not/iu,/do not/iu,/don't/iu,/\bnever\b/iu],zn=[/từ giờ/iu,/về sau/iu,/mỗi lần/iu,/luôn luôn/iu,/\bluôn\b/iu,/quy tắc/iu,/workflow/iu,/\balways\b/iu,/\brequired\b/iu,/\bmust\b/iu,/from now on/iu],Wn=[/\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],Bn=[/\btodo\b/iu,/cần làm/iu,/cần thêm/iu,/cần sửa/iu,/cần kiểm tra/iu,/tiếp theo/iu,/bước tiếp theo/iu,/còn phải/iu,/còn cần/iu,/next step/iu,/\bneed to\b/iu,/\bremaining\b/iu,/follow[- ]?up/iu],Dn=[/đã sửa/iu,/đã fix/iu,/đã khắc phục/iu,/đã xử lý/iu,/hoàn tất/iu,/hoàn thành/iu,/\bfixed\b/iu,/\bresolved\b/iu,/\bimplemented\b/iu,/\bcompleted\b/iu,/\bpasses?\b/iu],ht=[/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],Fn=[/\bdùng\b/iu,/\btách\b/iu,/\bthay\b/iu,/\bchuyển\b/iu,/\blưu\b/iu,/\bmap\b/iu,/\buse\b/iu,/\bsplit\b/iu,/\bstore\b/iu,/\breplace\b/iu,/\bmove\b/iu],qn=[/đường dẫn/iu,/\bpath\b/iu,/\bport\b/iu,/\bendpoint\b/iu,/\bdomain\b/iu,/\bbucket\b/iu,/\brepository\b/iu,/\brepo\b/iu,/\bbranch\b/iu,/\/[A-Za-z0-9._/-]{4,}/u],Jn=[/\blà\b/iu,/\bở\b/iu,/\bdùng\b/iu,/\bnằm\b/iu,/\bis\b/iu,/\buse\b/iu,/located/iu,/runs on/iu],yt=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Vn=new Set(["payload","data","content","message","messages","parts","summary"]);function P(t,e){return e.some(r=>r.test(t))}function kt(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Un(t){return kt(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Hn(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function je(t,e,r,n=0){if(!(n>6)){if(typeof t=="string"){(!e||yt.has(e))&&r.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))je(s,e,r,n+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(yt.has(s)||Vn.has(s))&&je(o,s,r,n+1)}}function Yn(t){let e=[];je(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=kt(o);if(Hn(i)&&!n.has(i)&&(n.add(i),r.push(i),r.length>=50))return r}return r}function St(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Gn(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,vt)?{kind:"rule",confidence:.98}:n&&P(t,zn)?{kind:"rule",confidence:.92}:P(t,Wn)?{kind:P(t,ht)?"architecture":"decision",confidence:n?.93:.86}:n&&P(t,Bn)?{kind:"todo",confidence:.87}:P(t,ht)&&P(t,Fn)?{kind:"architecture",confidence:n?.88:.82}:s&&P(t,Dn)?{kind:"fix",confidence:.8}:n&&P(t,qn)&&P(t,Jn)?{kind:"context",confidence:.79}:null}function Qn(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Xn(t,e,r){return t==="rule"&&P(r,vt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":gt(e,r)}function bt(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=St(o);i&&u&&s.set(i,u)}for(let o of e){let i=St(o),u=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&u&&(i=s.get(u)??"");for(let a of Yn(o)){let c=Gn(a,i,o);if(!c||c.confidence<.75)continue;let d=Qn(c.kind),p=Un(a),g=v([t.projectId,c.kind,p].join("|"));if(n.has(g))continue;n.add(g);let l=o.provenance.sourcePath?[o.provenance.sourcePath]:[],y=o.sourceEventId?[o.sourceEventId]:[];r.push({version:1,fingerprint:g,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:c.kind,type:d,content:a,confidence:c.confidence,importance:Xn(c.kind,d,a),tags:[d],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:y,sourcePaths:l,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return r}function wt(t){return String(t).padStart(12,"0")}function Zn(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(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)+`
|
|
73
|
+
`,a=v(n.map(d=>d.fingerprint).sort().join("|")).slice(0,16),c=[Zn(e),"batches",`${wt(s)}-${wt(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,u,"application/json"),c}};function os(t,e){if(!ts(t))return{events:[],nextOffset:e};let r=ss(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=rs(t,"r");try{ns(i,o,0,s,n)}finally{es(i)}let u=o.toString("utf8"),a=u.lastIndexOf(`
|
|
74
74
|
`);if(a<0)return{events:[],nextOffset:n};let c=u.slice(0,a+1);return{events:c.split(`
|
|
75
|
-
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(c,"utf8")}}var
|
|
75
|
+
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:n+Buffer.byteLength(c,"utf8")}}var pe=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=os(this.options.wal.eventsFile,n);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=bt(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 le=class{identity;wal;remote;sanitizer=new B;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=lt(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 pe({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 is,openSync as as,closeSync as cs,readSync as us,statSync as ps}from"node:fs";function ls(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 ds(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 jt(t,e={offset:0}){if(!is(t))return{events:[],nextOffset:e.offset,reset:!1};let r=ps(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=as(t,"r");try{us(u,i,0,o,s)}finally{cs(u)}let a=i.toString("utf8"),c=a.lastIndexOf(`
|
|
76
76
|
`);if(c<0)return{events:[],nextOffset:s,reset:n};let d=a.slice(0,c+1),p=Buffer.byteLength(d,"utf8"),g=[],l=0;for(let y of d.split(`
|
|
77
77
|
`)){if(!y)continue;let h=Buffer.byteLength(y+`
|
|
78
|
-
`,"utf8"),m=s+l;l+=h;let S;try{S=JSON.parse(y)}catch{g.push({type:"custom",sourceEventId:`transcript:${m}`,sourceSequence:m,data:{format:"raw-line",content:y},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}});continue}let
|
|
78
|
+
`,"utf8"),m=s+l;l+=h;let S;try{S=JSON.parse(y)}catch{g.push({type:"custom",sourceEventId:`transcript:${m}`,sourceSequence:m,data:{format:"raw-line",content:y},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}});continue}let b=S&&typeof S=="object"&&!Array.isArray(S)?S:{value:S};g.push({type:ls(b),timestamp:ds(b),role:typeof b.role=="string"?b.role:void 0,sourceEventId:`transcript:${m}`,sourceSequence:m,data:b,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}})}return{events:g,nextOffset:s+p,reset:n}}function gs(t){return t==="~"?xt():t.startsWith("~/")?fs(xt(),t.slice(2)):t}async function It(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let r=ms(gs(t.transcriptPath)),n=new le({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=jt(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}}),u.reset&&a.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${u.nextOffset}`,data:{event:"transcript_reset",transcriptPath:r},provenance:{source:"agy-transcript",sourcePath:r}}),a.push(...u.events),t.phase==="stop"&&(t.error&&a.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&&a.push({type:"session_idle",sourceEventId:["agy",e,"idle",u.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let c=n.recordMany(a);n.setSourceCursor("agy.transcript.offset",u.nextOffset),t.phase&&n.setSourceCursor("agy.last.phase",t.phase);let d=await n.flush();return{conversationId:e,imported:c.length,eventCount:d.eventCount,chunkCount:d.chunkCount,status:d.status,transcriptOffset:u.nextOffset,reset:u.reset}}async function hs(){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 ys(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=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,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,p=s.fully_idle===!0||t.fullyIdle===!0||t.fully_idle===!0,g=(typeof s.termination_reason=="string"?s.termination_reason:"")||(typeof t.terminationReason=="string"?t.terminationReason:"")||(typeof t.termination_reason=="string"?t.termination_reason:"")||void 0,l=(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:a,artifactDirectoryPath:c,modelName:d,fullyIdle:p,terminationReason:g,error:l}}async function Ss(){let t=process.argv[2]??"post",e=await hs(),r=ys(e),n=r.conversationId,s=r.transcriptPath,o=r.workspacePaths,i=ut(o),u={};if(i&&n)try{let a=Pe(),c=$e(Ce({provider:a.storage.provider,huggingface:a.storage.huggingface,localRoot:a.storage.localRoot}),{attempts:2}),d=new G(c,i.id,i.name,i.remote??i.name);if(s)try{await It({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 ct({project:i,storage:d,conversationId:n,invocationNum:r.invocationNum})}catch{u={}}if(t==="stop")try{await ve(i,d,900)}catch{}}catch{}if(t==="stop"){process.stdout.write(JSON.stringify({decision:"stop"}));return}process.stdout.write(JSON.stringify(u))}Ss().catch(()=>{process.argv[2]==="stop"?process.stdout.write('{"decision":"stop"}'):process.stdout.write("{}"),process.exitCode=0});export{ys as normalizeAgyInput};
|