toolnet-memory 0.2.16 → 0.2.17
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/bin/toolnet-memory +18 -0
- package/bundle/agy-hook.js +45 -29
- package/bundle/auto-integrate.js +64 -14
- package/bundle/codex-context.js +39 -45
- package/bundle/codex.js +60 -43
- package/bundle/context-runtime.js +95 -22
- package/bundle/handoff-refresh.js +12 -0
- package/bundle/mcp.js +50 -7
- package/bundle/memory-agent.js +49 -0
- package/bundle/memory-query.js +7 -0
- package/bundle/opencode.js +82 -34
- package/bundle/setup.js +66 -16
- package/package.json +1 -2
package/bin/toolnet-memory
CHANGED
|
@@ -41,6 +41,21 @@ run() {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
case "$COMMAND" in
|
|
44
|
+
ask)
|
|
45
|
+
shift
|
|
46
|
+
run bundle/memory-query.js src/work-continuity/memory-query-cli.ts "$@"
|
|
47
|
+
;;
|
|
48
|
+
|
|
49
|
+
ask-ai)
|
|
50
|
+
shift
|
|
51
|
+
run bundle/memory-agent.js src/work-continuity/memory-agent-cli.ts "$@"
|
|
52
|
+
;;
|
|
53
|
+
|
|
54
|
+
handoff:refresh)
|
|
55
|
+
shift
|
|
56
|
+
run bundle/handoff-refresh.js src/work-continuity/handoff-cli.ts "$@"
|
|
57
|
+
;;
|
|
58
|
+
|
|
44
59
|
update)
|
|
45
60
|
shift
|
|
46
61
|
run bundle/update.js src/production/update.ts "$@"
|
|
@@ -521,6 +536,9 @@ PROJECT MANUAL:
|
|
|
521
536
|
toolnet-memory project:manual-show [--project PATH]
|
|
522
537
|
toolnet-memory project:manual-sync [--project PATH]
|
|
523
538
|
|
|
539
|
+
MEMORY AGENT QUERY:
|
|
540
|
+
toolnet-memory ask "<question>" Ask concise project-memory questions
|
|
541
|
+
|
|
524
542
|
WORK CONTINUITY:
|
|
525
543
|
toolnet-memory work:status [--project PATH]
|
|
526
544
|
toolnet-memory work:json [--project PATH]
|
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}),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=
|
|
5
|
-
`,{encoding:"utf8",mode:384}),
|
|
6
|
-
`,u=v(r.map(a=>a.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${
|
|
7
|
-
`,"application/json"),
|
|
1
|
+
import{existsSync as Kt,readFileSync as Bt}from"node:fs";import{homedir as Ut}from"node:os";import{join as Wt}from"node:path";function zt(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 qt(){let t=process.env.TOOLNET_GLOBAL_ENV??Wt(Ut(),".config","toolnet-memory",".env");if(!Kt(t))return;let e=Bt(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]=zt(n.slice(s+1)))}}qt();function F(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function K(t,e){if(!t)return e;let r=Number(t);return Number.isFinite(r)?r:e}function J(){return{memory:{autoCapture:F(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:F(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:F(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:F(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:K(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:K(process.env.MEMORY_RERANK_TOP,10),finalContext:K(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:K(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:F(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:K(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Jt}from"node:crypto";import{existsSync as ye,mkdirSync as Ht,readFileSync as Vt,renameSync as Gt,writeFileSync as Yt}from"node:fs";import{basename as Qt,dirname as H,join as G,parse as Re,resolve as B}from"node:path";var Ce=".toolnet",Xt="project.json";function Zt(t){return Jt("sha256").update(t).digest("hex").slice(0,16)}function Se(t){return G(t,Ce,Xt)}function er(t){return ye(Se(t))}function tr(t,e){let r=B(t),n=Re(r).root;for(;;){if(er(r))return r;if(r===n||e&&r===B(e))break;let s=H(r);if(s===r)break;r=s}return null}function rr(t){let e=B(t),r=Re(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(o=>ye(G(e,o))))return e;if(e===r)break;let s=H(e);if(s===e)break;e=s}return B(t)}function nr(t){let e;try{e=JSON.parse(Vt(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let 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:H(H(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 Me(t,e){let r=G(t,Ce);Ht(r,{recursive:!0});let n=Se(t),s=`${n}.tmp-${process.pid}`;Yt(s,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),Gt(s,n)}function Ne(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=B(e),n=rr(r),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>ye(G(n,p))),i=tr(r,o?n:void 0);if(i){let p=Se(i),l=nr(p);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),Me(i,l)),Ne(l,i)}let u=new Date().toISOString(),c=Qt(n),a={version:1,id:Zt(n),name:c,remote:c,rootPath:n,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return Me(n,a),Ne(a,n)}};var sr=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],Y=class{scan(e){let r=[];for(let n of sr){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 U=class{scanner=new Y;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 jr}from"node:os";import{join as Or}from"node:path";import{DeleteObjectCommand as or,GetObjectCommand as ir,HeadObjectCommand as ar,ListObjectsV2Command as cr,PutObjectCommand as ur,S3Client as lr}from"@aws-sdk/client-s3";import{getSignedUrl as dr}from"@aws-sdk/s3-request-presigner";var Q=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new lr({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 ur({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await dr(this.client,new ir({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 ar({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 or({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new cr({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 Le,mkdir as pr,readFile as fr,readdir as mr,rm as gr,stat as $e,writeFile as hr}from"node:fs/promises";import{dirname as yr,join as Sr,relative as De,resolve as vr}from"node:path";var W=class{constructor(e){this.root=e}root;name="local";path(e){let r=e.replace(/^\/+/,"");return vr(this.root,r)}async put(e,r){let n=this.path(e);await pr(yr(n),{recursive:!0}),await hr(n,r)}async get(e){try{return await fr(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 Le(this.path(e)),!0}catch{return!1}}async delete(e){await gr(this.path(e),{force:!0})}async list(e=""){let r=this.path(e),n=[];try{await Le(r)}catch{return n}let s=async i=>{let u=await mr(i,{withFileTypes:!0});for(let c of u){let a=Sr(i,c.name);if(c.isDirectory()){await s(a);continue}let p=await $e(a);n.push({key:De(this.root,a),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await $e(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 kr,GetObjectCommand as br,HeadObjectCommand as wr,ListObjectsV2Command as xr,PutObjectCommand as Ar,S3Client as Er}from"@aws-sdk/client-s3";import{getSignedUrl as Ir}from"@aws-sdk/s3-request-presigner";var z=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Er({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 Ar({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let r=await Ir(this.client,new br({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 wr({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 kr({Bucket:this.bucket,Key:e}))}async list(e=""){let r=[],n;do{let s=await this.client.send(new xr({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 W(t)}function Fe(t){let e=t.localRoot??Or(jr(),".toolnet-memory","storage");if(t.provider==="r2"){let r=t.r2;return r?.accountId&&r.bucket&&r.accessKeyId&&r.secretAccessKey?new z({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 z({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 W(e)}function Pr(t){return new Promise(e=>setTimeout(e,t))}async function Ke(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 Tr=new Set(["put","get","getText","delete","list"]);function Be(t,e={}){return new Proxy(t,{get(r,n){let s=Reflect.get(r,n,r);return typeof s!="function"?s:Tr.has(n)?(...o)=>Ke(()=>Promise.resolve(s.apply(r,o)),e):s.bind(r)}})}function Ue(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 X=class{constructor(e,r,n,s){this.provider=e;this.name=e.name,this.projectId=r,this.projectName=n,this.folder=Ue(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=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 _r}from"node:crypto";import{dirname as Mr}from"node:path";import{mkdirSync as Nr,readFileSync as Rr,renameSync as Cr,writeFileSync as Lr}from"node:fs";function v(t){return _r("sha256").update(t).digest("hex")}function ke(t){if(Array.isArray(t))return t.map(ke);if(t&&typeof t=="object"){let e=t,r={};for(let n of Object.keys(e).sort())r[n]=ke(e[n]);return r}return t}function ze(t){return JSON.stringify(ke(t))}function qe(t){try{return JSON.parse(Rr(t,"utf8"))}catch{return null}}function A(t,e){Nr(Mr(t),{recursive:!0});let r=`${t}.${process.pid}.tmp`;Lr(r,JSON.stringify(e,null,2)+`
|
|
5
|
+
`,{encoding:"utf8",mode:384}),Cr(r,t)}var $r=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 He(t){return L(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))($r.has(n)||["data","payload","parts","messages"].includes(n))&&C(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 Je(t){let e=L(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function w(t,e,r,n,s={}){let o=L(n),i=s.key??He(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 Dr(t,e,r){let n=L(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]),d=L(a[2]??""),y=d&&!Je(d)?`Phase ${f} - ${d}`:`Phase ${f}`;s.push(w(t,e,"phase",y,{key:`phase:${f}`,order:f,status:Z(n),confidence:.93}))}let p=r.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(w(t,e,"task",p[2],{status:p[1].trim()?"completed":Z(p[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,d=L(l[2]),y=Je(d);s.push(w(t,e,"task",y&&f!==void 0?`TODO ${f}`:d,{key:f!==void 0?`task:${f}`:He(d),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 Ve(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=[];C(i.data,c);for(let a of c)s(w(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let c=[];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=[];C(i.data,c);for(let a of c)s(w(t,i,"test",a,{confidence:1}))}let u=[];C(i.data,u);for(let c of u)for(let a of c.split(/\n+/u))for(let p of Dr(t,i,a))s(p)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),r}function Ge(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,`${Ge(n)}-${Ge(s)}-${u}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Ye}from"node:path";import{mkdirSync as Fr}from"node:fs";function Kr(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=Kr(s);if(!(!o||n.has(o))&&(n.add(o),r.push(s),r.length>=e))break}return r.reverse()}function Br(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&&Br(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 Ur(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 Ur(t,e)).flatMap(m=>m.observations).sort((m,x)=>{let Te=m.occurredAt.localeCompare(x.occurredAt);if(Te!==0)return Te;let _e=m.sequence-x.sequence;return _e!==0?_e:m.id.localeCompare(x.id)}),s=new Map,o=new Map,i,u,c,a=[],p=[],l=[],f=[],d=[],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":p.push(m.text);break;case"warning":l.push(m.text);break;case"next_action":f.push(m.text);break;case"file":d.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,x)=>(m.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((m,x)=>(m.order??Number.MAX_SAFE_INTEGER)-(x.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"),b=g.find(m=>m.status==="in_progress")??g.find(m=>m.status==="blocked")??g.find(m=>m.status==="pending"),_=$([...f,...b?[b.title]:[],...!b&&S?[S.title]:[],...g.filter(m=>m.status==="pending").slice(0,5).map(m=>m.title)],8),R=$([...p,...h.filter(m=>m.status==="blocked").map(m=>m.title),...g.filter(m=>m.status==="blocked").map(m=>m.title)],20),O={version:1,projectId:t.id,projectName:t.name,goal:i,plan:u,phases:h,tasks:g,decisions:$(a,20),blockers:R,warnings:$(l,20),nextActions:_,filesTouched:$(d,30),tests:$(y,20),currentPhase:S,currentTask:b,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()},M=Ye(t.rootPath,".toolnet","work");return Fr(M,{recursive:!0}),A(Ye(M,"current.json"),O),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(O,null,2)+`
|
|
7
|
+
`,"application/json"),O}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 Wr,existsSync as zr,openSync as qr,readSync as Jr,statSync as Hr}from"node:fs";function Vr(t,e){if(!zr(t))return{events:[],nextOffset:e};let r=Hr(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=qr(t,"r");try{Jr(i,o,0,s,n)}finally{Wr(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
|
|
8
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=
|
|
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=Vr(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=Ve(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 sn}from"node:fs";import{join as be}from"node:path";import{existsSync as et,mkdirSync as Gr,readFileSync as Yr,statSync as Xe,writeFileSync as Qr}from"node:fs";import{dirname as Xr,join as Zr}from"node:path";var Ze=64*1024,en=`# ToolNet Project Operating Manual
|
|
10
10
|
|
|
11
11
|
This file contains persistent instructions for AI agents working on this project.
|
|
12
12
|
|
|
@@ -49,41 +49,57 @@ Things an AI agent should always remember.
|
|
|
49
49
|
<!--
|
|
50
50
|
- [advisory] Prefer small focused files.
|
|
51
51
|
-->
|
|
52
|
-
`;function se(t){return
|
|
52
|
+
`;function se(t){return Zr(t.rootPath,".toolnet","PROJECT.md")}function tn(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function rn(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=tn(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 nn(t){let e=se(t);return et(e)||(Gr(Xr(e),{recursive:!0}),Qr(e,en,{encoding:"utf8",mode:384})),e}function oe(t,e=!1){let r=e?nn(t):se(t);if(!et(r))return null;if(Xe(r).size>Ze)throw new Error(`PROJECT.md exceeds ${Ze} bytes`);let s=Yr(r,"utf8");return{path:r,content:s,digest:v(s),rules:rn(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Xe(r).mtimeMs).toISOString()}}function on(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 an(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)),!an(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(on(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},p=`projects/${this.options.project.id}/work/handoffs/${u}.json`;await this.options.storage.exists(p)||await this.options.storage.put(p,JSON.stringify(a,null,2)+`
|
|
53
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=
|
|
55
|
-
`,"application/json"),
|
|
54
|
+
`,"application/json");let l=be(this.options.project.rootPath,".toolnet","work","handoffs");return sn(l,{recursive:!0}),A(be(l,`${u}.json`),a),A(be(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 cn}from"node:fs";import{join as rt}from"node:path";function un(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function ln(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 P(t,e){return ln(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 dn(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 pn(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 dn(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,p=[],l=[],f=[];for(let h of n){let g=un(h);if(h.scope==="phase"&&h.scopeKey){let S=a.get(h.scopeKey)??pn(h);switch(h.kind){case"phase_objective":S.objective=P(S.objective,g);break;case"phase_why":S.why=P(S.why,g);break;case"phase_deliverable":S.deliverable=P(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=P(s,g);break;case"objective":o=P(o,g);break;case"why":i=P(i,g);break;case"desired_outcome":u=P(u,g);break;case"plan_rationale":c=P(c,g);break;case"open_question":p.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 d={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(p,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 cn(y,{recursive:!0}),A(rt(y,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
|
|
55
|
+
`,"application/json"),d}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 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 fn(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 mn(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 gn(t,e){let r=[];for(let n of t){let s=[...r,n].join(`
|
|
56
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=
|
|
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=
|
|
59
|
-
`,"application/json"),u}};import{closeSync as
|
|
57
|
+
`)),i=Math.max(0,e-o);if(i>=16){let u=Math.floor(i*3.2),c=k(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=mn(n),o=r?r.rules.filter(d=>d.mode==="enforce").map(d=>d.text):s.enforce,i=r?r.rules.filter(d=>d.mode==="advisory").map(d=>d.text):s.advisory,u=n?fn(n):[],c=await re(t.project,t.storage),a=await st(t.project,t.storage),p=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 d of o.slice(0,24))l.push(`- [ENFORCE] ${k(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${k(d,220)}`)}if(a&&(a.mission&&l.push("","MISSION",k(a.mission.value,420)),a.activeObjective&&l.push("","CURRENT OBJECTIVE",k(a.activeObjective.value,420)),a.why&&l.push("","WHY THIS WORK MATTERS",k(a.why.value,420)),a.desiredOutcome&&l.push("","DESIRED OUTCOME",k(a.desiredOutcome.value,420)),a.planRationale&&l.push("","WHY THIS APPROACH",k(a.planRationale.value,420))),c){if(l.push("","ACTIVE WORK"),c.goal&&l.push(`Goal: ${k(c.goal,320)}`),c.plan&&l.push(`Plan: ${k(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 d=a.phases.find(y=>y.order===c.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${k(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${k(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${k(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(y=>k(y.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(y=>{l.push(`- ${k(y.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(y=>{l.push(`- ${k(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((d,y)=>{l.push(`${y+1}. ${k(d,260)}`)})),c.blockers.length&&(l.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(d=>{l.push(`- ${k(d,260)}`)})),c.warnings.length&&(l.push("","ATTENTION"),c.warnings.slice(-5).forEach(d=>{l.push(`- ${k(d,260)}`)})),c.decisions.length&&(l.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(d=>{l.push(`- ${k(d,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(d=>{l.push(`- ${k(d.value,260)}`)})),p&&l.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),u.length){l.push("","OPERATING NOTES");for(let d of u)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let f=gn(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:!!p,generatedAt:new Date().toISOString()}}var hn=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 xe(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))xe(n,e,r+1);return}if(!(!t||typeof t!="object"))for(let[n,s]of Object.entries(t))(hn.has(n)||["data","payload","parts","messages"].includes(n))&&xe(s,e,r+1)}}function E(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 j(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 yn(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Sn(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=[];xe(o.data,i);for(let u of i){let c={type:"project"},a=null;for(let p of u.split(/\r?\n/u)){let l=D(p);if(!l){a=null;continue}let f=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let x=Number(f[1]);c={type:"phase",key:`phase:${x}`,order:x,title:D(f[2]??"")},a=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let x=Number(d[1]);c={type:"task",key:`task:${x}`,order:x,title:D(d[2]??"")},a=null;continue}let y=j(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(y){s(E(t,o,"mission",y,{type:"project"},.99)),a=null;continue}let h=j(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(E(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),a=null;continue}let g=j(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(E(t,o,c.type==="phase"?"phase_why":"why",g,c,.98)),a=null;continue}let S=j(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(E(t,o,"desired_outcome",S,{type:"project"},.98)),a=null;continue}let b=j(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(b){s(E(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let _=j(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(_){s(E(t,o,"phase_deliverable",_,c,.97)),a=null;continue}let R=j(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(R){s(E(t,o,"acceptance_criterion",R,c,.98)),a="acceptance_criterion";continue}let O=j(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(O){s(E(t,o,"dependency",O,c,.97)),a="dependency";continue}let M=j(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(M){s(E(t,o,"open_question",M,c,.95)),a="open_question";continue}let m=j(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(m){s(E(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&&yn(p)){s(E(t,o,a,Sn(p),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 vn,existsSync as kn,openSync as bn,readSync as wn,statSync as xn}from"node:fs";function An(t,e){if(!kn(t))return{events:[],nextOffset:e};let r=xn(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=bn(t,"r");try{wn(o,s,0,s.length,n)}finally{vn(o)}let i=s.toString("utf8"),u=i.lastIndexOf(`
|
|
60
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=
|
|
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
|
|
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=An(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 En,mkdirSync as In,readFileSync as jn,writeFileSync as On}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 Tn(t){return ct(t.rootPath,".toolnet","context","startup.json")}function lt(t,e){let r=ut(t);In(Pn(r),{recursive:!0}),On(r,e.text.endsWith(`
|
|
63
63
|
`)?e.text:e.text+`
|
|
64
|
-
`,{encoding:"utf8",mode:384}),
|
|
64
|
+
`,{encoding:"utf8",mode:384}),A(Tn(t),e)}async function Ae(t,e,r=800){let s=(await ot({project:t,storage:e,maxTokens:r})).text;ue(s)>r&&(s=le(s,r),s+=`
|
|
65
65
|
|
|
66
66
|
[Context trimmed by ToolNet Memory token budget]
|
|
67
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
68
|
`,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
|
|
69
|
-
`,"application/json"),i}async function
|
|
69
|
+
`,"application/json"),i}async function dt(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(En(n))try{let s=jn(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 Ae(t,e,r)}catch{return null}}import{existsSync as _n,mkdirSync as Mn,readFileSync as Nn}from"node:fs";import{homedir as Rn}from"node:os";import{dirname as Cn,join as mt}from"node:path";var pt="memory_agent_ask";function ft(){return`
|
|
70
|
+
[TOOLNET MEMORY AGENT]
|
|
71
|
+
|
|
72
|
+
Tool:
|
|
73
|
+
- ${pt}
|
|
74
|
+
|
|
75
|
+
If the user asks to resume previous work and the fast context
|
|
76
|
+
is insufficient, call ${pt} before guessing.
|
|
77
|
+
|
|
78
|
+
Use:
|
|
79
|
+
- mode="local" for current task, last file, blocker or next action.
|
|
80
|
+
- mode="ai" for ambiguous or combined continuity questions.
|
|
81
|
+
|
|
82
|
+
Current repository evidence overrides stale memory.
|
|
83
|
+
`.trim()}function Ln(t,e,r){let n=r??mt(Rn(),".config","toolnet-memory","injections","agy");return mt(n,`${t.id}-${e}.json`)}function $n(t){if(!_n(t))return null;try{return JSON.parse(Nn(t,"utf8"))}catch{return null}}async function gt(t){let e=t.now??Date.now(),r=t.resumeAfterMs??360*60*1e3,n=Ln(t.project,t.conversationId,t.markerDirectory),s=$n(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 dt(t.project,t.storage,900);return a?.text?(Mn(Cn(n),{recursive:!0}),A(n,{digest:a.digest,injectedAt:new Date(e).toISOString()}),{injectSteps:[{userMessage:`${a.text}
|
|
84
|
+
|
|
85
|
+
${ft()}`}]}):{}}import{existsSync as Un}from"node:fs";import{dirname as Wn,join as zn,parse as qn,resolve as Jn}from"node:path";function yt(t){for(let e of t){let r=Jn(e),n=qn(r).root;for(;;){if(Un(zn(r,".toolnet","project.json")))return new V().detect(r);if(r===n)break;let s=Wn(r);if(s===r)break;r=s}}return null}import{homedir as Dt}from"node:os";import{join as Bs,resolve as Us}from"node:path";import{join as Hn}from"node:path";function St(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 vt(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=St(n.toLowerCase(),"agent"),i=St(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:Hn(t.rootPath,".toolnet","sessions",o,i)}}function kt(t){return String(t).padStart(12,"0")}var de=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
86
|
`,"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],
|
|
87
|
+
`,"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],b=g[g.length-1],_=g.map(M=>JSON.stringify(M)).join(`
|
|
72
88
|
`)+`
|
|
73
|
-
`,
|
|
89
|
+
`,R=v(_).slice(0,16),O=[e.remotePrefix,"events",`${kt(S.sequence)}-${kt(b.sequence)}-${R}.jsonl`].join("/");await this.storage.exists(O)||await this.storage.put(O,_,"application/x-ndjson"),c+=g.length}let a=await this.scan(e),p=r[r.length-1],l=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?l="idle":p?.type==="error"?l="error":r.length>0&&(l="active");let f=new Date().toISOString(),d=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??d?.timestamp??f,updatedAt:p?.timestamp??f,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:p?.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 Ee,existsSync as Vn,fsyncSync as Gn,mkdirSync as Yn,openSync as Ie,readSync as Qn,rmSync as bt,statSync as wt,writeSync as Xn}from"node:fs";import{join as je}from"node:path";var Zn=12e4,es=80,ts=2e3;function rs(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var pe=class{constructor(e){this.identity=e;Yn(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 qe(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){A(this.stateFile,e)}acquireLock(){for(let e=0;e<es;e+=1)try{return Ie(this.lockFile,"wx",384)}catch(r){if(r.code!=="EEXIST")throw r;try{if(Date.now()-wt(this.lockFile).mtimeMs>Zn){bt(this.lockFile,{force:!0});continue}}catch{}rs(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let r=this.acquireLock();try{return e()}finally{Ee(r),bt(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(),d=l.data??{},y=l.provenance?.rawDigest??v(ze(d)),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:d,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(`
|
|
74
90
|
`)+`
|
|
75
|
-
`,u=
|
|
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
|
|
77
|
-
`,c=v(n.map(
|
|
91
|
+
`,u=Ie(this.eventsFile,"a",384);try{Xn(u,i,null,"utf8"),Gn(u)}finally{Ee(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 p=Array.from(n).slice(-ts);return this.saveStateUnsafe({...r,status:a,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Vn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let r=wt(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=Ie(this.eventsFile,"r");try{Qn(i,o,0,s,n)}finally{Ee(i)}return{events:o.toString("utf8").split(`
|
|
92
|
+
`).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 Ss,existsSync as vs,openSync as ks,readSync as bs,statSync as ws}from"node:fs";function xt(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 jt=[/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],ns=[/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],ss=[/\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],os=[/\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],is=[/đã 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],At=[/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],as=[/\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],cs=[/đườ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],us=[/\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],Et=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),ls=new Set(["payload","data","content","message","messages","parts","summary"]);function I(t,e){return e.some(r=>r.test(t))}function Ot(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function ds(t){return Ot(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function ps(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 Oe(t,e,r,n=0){if(!(n>6)){if(typeof t=="string"){(!e||Et.has(e))&&r.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Oe(s,e,r,n+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(Et.has(s)||ls.has(s))&&Oe(o,s,r,n+1)}}function fs(t){let e=[];Oe(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=Ot(o);if(ps(i)&&!n.has(i)&&(n.add(i),r.push(i),r.length>=50))return r}return r}function It(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function ms(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&&I(t,jt)?{kind:"rule",confidence:.98}:n&&I(t,ns)?{kind:"rule",confidence:.92}:I(t,ss)?{kind:I(t,At)?"architecture":"decision",confidence:n?.93:.86}:n&&I(t,os)?{kind:"todo",confidence:.87}:I(t,At)&&I(t,as)?{kind:"architecture",confidence:n?.88:.82}:s&&I(t,is)?{kind:"fix",confidence:.8}:n&&I(t,cs)&&I(t,us)?{kind:"context",confidence:.79}:null}function gs(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function hs(t,e,r){return t==="rule"&&I(r,jt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":xt(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=It(o);i&&u&&s.set(i,u)}for(let o of e){let i=It(o),u=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&u&&(i=s.get(u)??"");for(let c of fs(o)){let a=ms(c,i,o);if(!a||a.confidence<.75)continue;let p=gs(a.kind),l=ds(c),f=v([t.projectId,a.kind,l].join("|"));if(n.has(f))continue;n.add(f);let d=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:p,content:c,confidence:a.confidence,importance:hs(a.kind,p,c),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:y,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return r}function Tt(t){return String(t).padStart(12,"0")}function ys(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(p=>p.sequence)),o=Math.max(...r.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:n.length,candidates:n},u=JSON.stringify(i,null,2)+`
|
|
93
|
+
`,c=v(n.map(p=>p.fingerprint).sort().join("|")).slice(0,16),a=[ys(e),"batches",`${Tt(s)}-${Tt(o)}-${c}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,u,"application/json"),a}};function xs(t,e){if(!vs(t))return{events:[],nextOffset:e};let r=ws(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=ks(t,"r");try{bs(i,o,0,s,n)}finally{Ss(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
|
|
78
94
|
`);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=
|
|
80
|
-
`);if(a<0)return{events:[],nextOffset:s,reset:n};let
|
|
95
|
+
`).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=xs(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 U;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=vt(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new pe(this.identity),this.remote=new de(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 As,openSync as Es,closeSync as Is,readSync as js,statSync as Os}from"node:fs";function Ps(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 Ts(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 _t(t,e={offset:0}){if(!As(t))return{events:[],nextOffset:e.offset,reset:!1};let r=Os(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=Es(t,"r");try{js(u,i,0,o,s)}finally{Is(u)}let c=i.toString("utf8"),a=c.lastIndexOf(`
|
|
96
|
+
`);if(a<0)return{events:[],nextOffset:s,reset:n};let p=c.slice(0,a+1),l=Buffer.byteLength(p,"utf8"),f=[],d=0;for(let y of p.split(`
|
|
81
97
|
`)){if(!y)continue;let h=Buffer.byteLength(y+`
|
|
82
|
-
`,"utf8"),g=s+
|
|
83
|
-
`).filter(c=>c.trim());for(let c of u){let a=c.trim();if(a.length<15)continue;let
|
|
98
|
+
`,"utf8"),g=s+d;d+=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 b=S&&typeof S=="object"&&!Array.isArray(S)?S:{value:S};f.push({type:Ps(b),timestamp:Ts(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:f,nextOffset:s+l,reset:n}}var _s=[/^<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*$/],Ms=[/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],Ns=["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 Rs(t){let e=t.toLowerCase();return Ns.some(r=>e.includes(r))}function Cs(t){if(!t.trim())return!0;for(let e of _s)if(e.test(t))return!0;return Rs(t),!1}function Ls(t){let e=t;for(let r of Ms)e=e.replace(r,n=>{let s=n.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Pe(t){let e=t.trim();return e?Cs(e)?{content:"",filtered:!0,reason:"noise"}:{content:Ls(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=Pe(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=Pe(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 Mt(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&&Pe(n).filtered)return!0}return!1}function N(){let t=J(),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 Nt(t){return(t||N()).rawTranscript}function Rt(t){return(t||N()).durableMemoryMaxItemsPerSession}function Ct(t){return(t||N()).sessionSummaryMaxTokens}function Lt(t){return(t||N()).archiveRemote}function $s(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 Ds(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 Fs(t,e){let r=[],n=new Set;for(let i of t){let u=i.split(`
|
|
99
|
+
`).filter(c=>c.trim());for(let c of u){let a=c.trim();if(a.length<15)continue;let p=a.toLowerCase().replace(/\s+/g," ");if(n.has(p))continue;n.add(p);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=Ds(a,l);if(f<.3)continue;let d=$s(a);r.push({category:l,text:d,importance:f,sourceSessionId:e})}}let s=N(),o=Rt(s);return r.sort((i,u)=>u.importance-i.importance).slice(0,o)}function Ks(t){let e=N(),r=Ct(e),o=t.join(`
|
|
84
100
|
|
|
85
101
|
`).split(`
|
|
86
102
|
`).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
|
|
103
|
+
`);return le(o,r)}function $t(t,e){let n=(Array.isArray(t)?t:t.split(`
|
|
88
104
|
|
|
89
|
-
`).filter(
|
|
105
|
+
`).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=Fs(n,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),u=s.filter(d=>d.category==="file").map(d=>d.text),c=s.filter(d=>d.category==="fix").map(d=>d.text),a=s.filter(d=>d.category==="blocker").map(d=>d.text),p=s.filter(d=>d.category==="next_action").map(d=>d.text),l=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:Ks(n),decisions:o,projectRules:i,filesChanged:u,bugsFixed:c,commands:l,blockers:a,nextActions:p,durableFacts:s}}function Ws(t){return t==="~"?Dt():t.startsWith("~/")?Bs(Dt(),t.slice(2)):t}async function Ft(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let r=Us(Ws(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=_t(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=>!Mt(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 p=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)),d=$t(f,e);n.setSourceCursor("agy.session.summary",d.summary),n.setSourceCursor("agy.session.facts_count",d.durableFacts.length),Nt()&&(Lt()||n.setSourceCursor("agy.raw_transcript.archived","local"))}catch{}let l=await n.flush();return{conversationId:e,imported:p.length,eventCount:l.eventCount,chunkCount:l.chunkCount,status:l.status,transcriptOffset:u.nextOffset,reset:u.reset}}async function zs(){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 qs(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),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,p=(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,d=(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:p,fullyIdle:l,terminationReason:f,error:d}}async function Js(){let t=process.argv[2]??"post",e=await zs(),r=qs(e),n=r.conversationId,s=r.transcriptPath,o=r.workspacePaths,i=yt(o),u={};if(i&&n)try{let c=J(),a=Be(Fe({provider:c.storage.provider,huggingface:c.storage.huggingface,localRoot:c.storage.localRoot}),{attempts:2}),p=new X(a,i.id,i.name,i.remote??i.name);if(s)try{await Ft({project:i,storage:p,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 gt({project:i,storage:p,conversationId:n,invocationNum:r.invocationNum})}catch{u={}}if(t==="stop")try{await Ae(i,p,800)}catch{}}catch{}if(t==="stop"){process.stdout.write(JSON.stringify({decision:"stop"}));return}process.stdout.write(JSON.stringify(u))}Js().catch(()=>{process.argv[2]==="stop"?process.stdout.write('{"decision":"stop"}'):process.stdout.write("{}"),process.exitCode=0});export{qs as normalizeAgyInput};
|