toolnet-memory 0.2.15 → 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/README.md +74 -0
- package/bin/toolnet-memory +36 -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/doctor.js +5 -3
- package/bundle/full-index.js +8 -8
- 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/provider.js +3 -0
- package/bundle/runtime.js +11 -11
- package/bundle/semantic.js +6 -6
- package/bundle/setup.js +67 -17
- package/package.json +1 -2
package/bundle/codex.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
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}),an(s,r)}function We(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 _=class{detect(e=process.cwd()){let n=B(e),r=mn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>xe(G(r,f))),i=fn(n,o?r:void 0);if(i){let f=ke(i),l=gn(f);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),Ke(i,l)),We(l,i)}let u=new Date().toISOString(),c=un(r),a={version:1,id:dn(r),name:c,remote:c,rootPath:r,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return Ke(r,a),We(a,r)}};var hn=[{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}],X=class{scan(e){let n=[];for(let r of hn){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var z=class{scanner=new X;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as Kn}from"node:os";import{join as Wn}from"node:path";import{DeleteObjectCommand as yn,GetObjectCommand as Sn,HeadObjectCommand as vn,ListObjectsV2Command as bn,PutObjectCommand as xn,S3Client as kn}from"@aws-sdk/client-s3";import{getSignedUrl as wn}from"@aws-sdk/s3-request-presigner";var Q=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new kn({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new xn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await wn(this.client,new Sn({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new vn({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new yn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new bn({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as ze,mkdir as jn,readFile as In,readdir as Pn,rm as En,stat as Je,writeFile as On}from"node:fs/promises";import{dirname as Cn,join as Tn,relative as qe,resolve as Mn}from"node:path";var J=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Mn(this.root,n)}async put(e,n){let r=this.path(e);await jn(Cn(r),{recursive:!0}),await On(r,n)}async get(e){try{return await In(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await ze(this.path(e)),!0}catch{return!1}}async delete(e){await En(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await ze(n)}catch{return r}let s=async i=>{let u=await Pn(i,{withFileTypes:!0});for(let c of u){let a=Tn(i,c.name);if(c.isDirectory()){await s(a);continue}let f=await Je(a);r.push({key:qe(this.root,a),size:f.size,updatedAt:f.mtime.toISOString()})}},o=await Je(n);return o.isDirectory()?await s(n):r.push({key:qe(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as An,GetObjectCommand as Rn,HeadObjectCommand as Nn,ListObjectsV2Command as _n,PutObjectCommand as $n,S3Client as Ln}from"@aws-sdk/client-s3";import{getSignedUrl as Fn}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 Ln({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new $n({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Fn(this.client,new Rn({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Nn({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new An({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new _n({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function we(t,e){return console.warn(e),new J(t)}function Ve(t){let e=t.localRoot??Wn(Kn(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new q({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):we(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new q({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):we(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Q({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):we(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new J(e)}function Dn(t){return new Promise(e=>setTimeout(e,t))}async function Ue(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(u){if(o=u,i>=n)break;let c=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,c*.2));await Dn(c+a)}throw o}var Bn=new Set(["put","get","getText","delete","list"]);function He(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:Bn.has(r)?(...o)=>Ue(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Ye(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 Ge(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var Z=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Ye(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(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"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
|
|
4
|
-
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=
|
|
5
|
-
`,{encoding:"utf8",mode:384}),
|
|
6
|
-
`,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let
|
|
7
|
-
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),
|
|
1
|
+
import{existsSync as di,readFileSync as pi}from"node:fs";import{spawn as fi}from"node:child_process";import{homedir as mi}from"node:os";import{join as gi}from"node:path";import{existsSync as Pn,readFileSync as On}from"node:fs";import{homedir as En}from"node:os";import{join as Tn}from"node:path";function Cn(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 An(){let t=process.env.TOOLNET_GLOBAL_ENV??Tn(En(),".config","toolnet-memory",".env");if(!Pn(t))return;let e=On(t,"utf8");for(let n of e.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let o=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=Cn(r.slice(s+1)))}}An();function B(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function z(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function G(){return{memory:{autoCapture:B(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:B(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:B(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:B(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:z(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:z(process.env.MEMORY_RERANK_TOP,10),finalContext:z(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:z(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:B(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:z(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Mn}from"node:crypto";import{existsSync as Pe,mkdirSync as Rn,readFileSync as Nn,renameSync as _n,writeFileSync as $n}from"node:fs";import{basename as Fn,dirname as X,join as Q,parse as Ue,resolve as J}from"node:path";var Ye=".toolnet",Ln="project.json";function Wn(t){return Mn("sha256").update(t).digest("hex").slice(0,16)}function Oe(t){return Q(t,Ye,Ln)}function Dn(t){return Pe(Oe(t))}function Kn(t,e){let n=J(t),r=Ue(n).root;for(;;){if(Dn(n))return n;if(n===r||e&&n===J(e))break;let s=X(n);if(s===n)break;n=s}return null}function Bn(t){let e=J(t),n=Ue(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>Pe(Q(e,o))))return e;if(e===n)break;let s=X(e);if(s===e)break;e=s}return J(t)}function zn(t){let e;try{e=JSON.parse(Nn(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let n=e;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:X(X(t)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function He(t,e){let n=Q(t,Ye);Rn(n,{recursive:!0});let r=Oe(t),s=`${r}.tmp-${process.pid}`;$n(s,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),_n(s,r)}function Ve(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 _=class{detect(e=process.cwd()){let n=J(e),r=Bn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>Pe(Q(r,f))),i=Kn(n,o?r:void 0);if(i){let f=Oe(i),l=zn(f);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),He(i,l)),Ve(l,i)}let c=new Date().toISOString(),u=Fn(r),a={version:1,id:Wn(r),name:u,remote:u,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return He(r,a),Ve(a,r)}};var Jn=[{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}],Z=class{scan(e){let n=[];for(let r of Jn){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var q=class{scanner=new Z;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as fr}from"node:os";import{join as mr}from"node:path";import{DeleteObjectCommand as qn,GetObjectCommand as Hn,HeadObjectCommand as Vn,ListObjectsV2Command as Un,PutObjectCommand as Yn,S3Client as Gn}from"@aws-sdk/client-s3";import{getSignedUrl as Xn}from"@aws-sdk/s3-request-presigner";var ee=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Gn({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Yn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Xn(this.client,new Hn({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Vn({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new qn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Un({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as Ge,mkdir as Qn,readFile as Zn,readdir as er,rm as tr,stat as Xe,writeFile as nr}from"node:fs/promises";import{dirname as rr,join as sr,relative as Qe,resolve as or}from"node:path";var H=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return or(this.root,n)}async put(e,n){let r=this.path(e);await Qn(rr(r),{recursive:!0}),await nr(r,n)}async get(e){try{return await Zn(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await Ge(this.path(e)),!0}catch{return!1}}async delete(e){await tr(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ge(n)}catch{return r}let s=async i=>{let c=await er(i,{withFileTypes:!0});for(let u of c){let a=sr(i,u.name);if(u.isDirectory()){await s(a);continue}let f=await Xe(a);r.push({key:Qe(this.root,a),size:f.size,updatedAt:f.mtime.toISOString()})}},o=await Xe(n);return o.isDirectory()?await s(n):r.push({key:Qe(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as ir,GetObjectCommand as ar,HeadObjectCommand as cr,ListObjectsV2Command as ur,PutObjectCommand as lr,S3Client as dr}from"@aws-sdk/client-s3";import{getSignedUrl as pr}from"@aws-sdk/s3-request-presigner";var V=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new dr({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new lr({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await pr(this.client,new ar({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new cr({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new ir({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new ur({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function Ee(t,e){return console.warn(e),new H(t)}function Ze(t){let e=t.localRoot??mr(fr(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new V({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ee(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new V({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ee(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new ee({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Ee(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new H(e)}function gr(t){return new Promise(e=>setTimeout(e,t))}async function et(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(c){if(o=c,i>=n)break;let u=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,u*.2));await gr(u+a)}throw o}var hr=new Set(["put","get","getText","delete","list"]);function tt(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:hr.has(r)?(...o)=>et(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function nt(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 rt(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var te=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=nt(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
|
|
4
|
+
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=rt(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{join as wr}from"node:path";import{createHash as yr}from"node:crypto";import{dirname as Sr}from"node:path";import{mkdirSync as kr,readFileSync as vr,renameSync as xr,writeFileSync as br}from"node:fs";function k(t){return yr("sha256").update(t).digest("hex")}function Te(t){if(Array.isArray(t))return t.map(Te);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Te(e[r]);return n}return t}function st(t){return JSON.stringify(Te(t))}function ot(t){try{return JSON.parse(vr(t,"utf8"))}catch{return null}}function I(t,e){kr(Sr(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;br(n,JSON.stringify(e,null,2)+`
|
|
5
|
+
`,{encoding:"utf8",mode:384}),xr(n,t)}function it(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=k(n).slice(0,12);if(!r||r==="."||r==="..")return`${e}--${s}`;let o=r.slice(0,100);return o===n&&n.length<=100?o:`${o.slice(0,85)}--${s}`}function at(t,e,n){let r=e.trim(),s=n.trim();if(!r)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=it(r.toLowerCase(),"agent"),i=it(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:r,nativeSessionId:s,sessionKey:`${r}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:wr(t.rootPath,".toolnet","sessions",o,i)}}function ct(t){return String(t).padStart(12,"0")}var ne=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
|
|
6
|
+
`,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let c=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!c)continue;let u=Number(c[1]),a=Number(c[2]);!Number.isFinite(u)||!Number.isFinite(a)||(s.push({key:i.key,start:u,end:a}),o=Math.max(o,a))}return s.sort((i,c)=>i.start-c.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
|
|
7
|
+
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),c=n.filter(g=>g.sequence>i.maxSequence),u=0;for(let g of this.split(c)){let y=g[0],b=g[g.length-1],C=g.map(E=>JSON.stringify(E)).join(`
|
|
8
8
|
`)+`
|
|
9
|
-
`,
|
|
9
|
+
`,A=k(C).slice(0,16),j=[e.remotePrefix,"events",`${ct(y.sequence)}-${ct(b.sequence)}-${A}.jsonl`].join("/");await this.storage.exists(j)||await this.storage.put(j,C,"application/x-ndjson"),u+=g.length}let a=await this.scan(e),f=n[n.length-1],l=o?.status??"active";f?.type==="session_end"||f?.type==="session_idle"?l="idle":f?.type==="error"?l="error":n.length>0&&(l="active");let m=new Date().toISOString(),d=n[0],S={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:l,createdAt:o?.createdAt??d?.timestamp??m,updatedAt:f?.timestamp??m,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:f?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(S.title=s.title??o?.title);let h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:u,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:l}}};import{closeSync as Ce,existsSync as jr,fsyncSync as Ir,mkdirSync as Pr,openSync as Ae,readSync as Or,rmSync as ut,statSync as lt,writeSync as Er}from"node:fs";import{join as Me}from"node:path";var Tr=12e4,Cr=80,Ar=2e3;function Mr(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var re=class{constructor(e){this.identity=e;Pr(e.localDirectory,{recursive:!0}),this.eventsFile=Me(e.localDirectory,"events.jsonl"),this.stateFile=Me(e.localDirectory,"state.json"),this.lockFile=Me(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 ot(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){I(this.stateFile,e)}acquireLock(){for(let e=0;e<Cr;e+=1)try{return Ae(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-lt(this.lockFile).mtimeMs>Tr){ut(this.lockFile,{force:!0});continue}}catch{}Mr(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{Ce(n),ut(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let l of e){let m=l.timestamp??new Date().toISOString(),d=l.data??{},S=l.provenance?.rawDigest??k(st(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,m,S].join("|"),g=k(h).slice(0,32);if(r.has(g))continue;s+=1;let y={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:m,data:d,provenance:{...l.provenance,rawDigest:S}};l.role!==void 0&&(y.role=l.role),l.sourceEventId!==void 0&&(y.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(y.sourceSequence=l.sourceSequence),o.push(y),r.add(g)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
|
|
10
10
|
`)+`
|
|
11
|
-
`,
|
|
12
|
-
`).filter(Boolean).map(a=>JSON.parse(a)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as
|
|
13
|
-
`,
|
|
14
|
-
`);if(
|
|
15
|
-
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var
|
|
16
|
-
`,
|
|
17
|
-
`,"application/json"),
|
|
18
|
-
`);if(
|
|
19
|
-
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var
|
|
20
|
-
`,"application/json"),
|
|
21
|
-
`,"application/json"),d}async function
|
|
22
|
-
`);if(
|
|
23
|
-
`).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(
|
|
11
|
+
`,c=Ae(this.eventsFile,"a",384);try{Er(c,i,null,"utf8"),Ir(c)}finally{Ce(c)}let u=o[o.length-1],a="active";u.type==="session_end"||u.type==="session_idle"?a="idle":u.type==="error"&&(a="error");let f=Array.from(r).slice(-Ar);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:f}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!jr(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=lt(this.eventsFile).size,r=Math.min(e.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let s=n-r,o=Buffer.alloc(s),i=Ae(this.eventsFile,"r");try{Or(i,o,0,s,r)}finally{Ce(i)}return{events:o.toString("utf8").split(`
|
|
12
|
+
`).filter(Boolean).map(a=>JSON.parse(a)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as Ur,existsSync as Yr,openSync as Gr,readSync as Xr,statSync as Qr}from"node:fs";function dt(t,e){let n=e.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var gt=[/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],Rr=[/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],Nr=[/\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],_r=[/\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],$r=[/đã 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],pt=[/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],Fr=[/\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],Lr=[/đườ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],Wr=[/\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],ft=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Dr=new Set(["payload","data","content","message","messages","parts","summary"]);function P(t,e){return e.some(n=>n.test(t))}function ht(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Kr(t){return ht(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Br(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 Re(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||ft.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Re(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(ft.has(s)||Dr.has(s))&&Re(o,s,n,r+1)}}function zr(t){let e=[];Re(t.data,void 0,e);let n=[],r=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=ht(o);if(Br(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function mt(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Jr(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&P(t,gt)?{kind:"rule",confidence:.98}:r&&P(t,Rr)?{kind:"rule",confidence:.92}:P(t,Nr)?{kind:P(t,pt)?"architecture":"decision",confidence:r?.93:.86}:r&&P(t,_r)?{kind:"todo",confidence:.87}:P(t,pt)&&P(t,Fr)?{kind:"architecture",confidence:r?.88:.82}:s&&P(t,$r)?{kind:"fix",confidence:.8}:r&&P(t,Lr)&&P(t,Wr)?{kind:"context",confidence:.79}:null}function qr(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Hr(t,e,n){return t==="rule"&&P(n,gt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":dt(e,n)}function yt(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,c=mt(o);i&&c&&s.set(i,c)}for(let o of e){let i=mt(o),c=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&c&&(i=s.get(c)??"");for(let u of zr(o)){let a=Jr(u,i,o);if(!a||a.confidence<.75)continue;let f=qr(a.kind),l=Kr(u),m=k([t.projectId,a.kind,l].join("|"));if(r.has(m))continue;r.add(m);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:f,content:u,confidence:a.confidence,importance:Hr(a.kind,f,u),tags:[f],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function St(t){return String(t).padStart(12,"0")}function Vr(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var se=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(f=>f.sequence)),o=Math.max(...n.map(f=>f.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},c=JSON.stringify(i,null,2)+`
|
|
13
|
+
`,u=k(r.map(f=>f.fingerprint).sort().join("|")).slice(0,16),a=[Vr(e),"batches",`${St(s)}-${St(o)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,c,"application/json"),a}};function Zr(t,e){if(!Yr(t))return{events:[],nextOffset:e};let n=Qr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=Gr(t,"r");try{Xr(i,o,0,s,r)}finally{Ur(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
|
|
14
|
+
`);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
|
|
15
|
+
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var oe=class{constructor(e){this.options=e;this.journal=new se(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Zr(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=yt(this.options.identity,s.events),i=!1;return o.length>0&&(i=!!await this.journal.write(this.options.identity,s.events,o)),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:o.length,journalWritten:i,nextOffset:s.nextOffset}}};import{closeSync as is,existsSync as as,openSync as cs,readSync as us,statSync as ls}from"node:fs";var es=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function F(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function vt(t){return F(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))$(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(es.has(r)||["data","payload","parts","messages"].includes(r))&&$(s,e,n+1)}}function ie(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 kt(t){let e=F(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function w(t,e,n,r,s={}){let o=F(r),i=s.key??vt(o);return{version:1,id:k([t.projectId,n,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function ts(t,e,n){let r=F(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(w(t,e,"goal",i[1],{confidence:.97}));let c=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);c?.[1]&&s.push(w(t,e,"plan",c[1],{confidence:.95}));let u=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=u.exec(r));){let m=Number(a[1]),d=F(a[2]??""),S=d&&!kt(d)?`Phase ${m} - ${d}`:`Phase ${m}`;s.push(w(t,e,"phase",S,{key:`phase:${m}`,order:m,status:ie(r),confidence:.93}))}let f=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);f?.[2]&&s.push(w(t,e,"task",f[2],{status:f[1].trim()?"completed":ie(f[2]),confidence:.96}));let l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let m=l[1]?Number(l[1]):void 0,d=F(l[2]),S=kt(d);s.push(w(t,e,"task",S&&m!==void 0?`TODO ${m}`:d,{key:m!==void 0?`task:${m}`:vt(d),order:m,status:ie(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let m=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");m&&s.push(w(t,e,"next_action",m,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(w(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(w(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(w(t,e,"decision",r,{confidence:.9})),s}function ae(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let u=[];$(i.data,u);for(let a of u)s(w(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];$(i.data,u);for(let a of u)s(w(t,i,"task",a,{status:ie(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let a=i.data[u];typeof a=="string"&&a&&s(w(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let u=[];$(i.data,u);for(let a of u)s(w(t,i,"test",a,{confidence:1}))}let c=[];$(i.data,c);for(let u of c)for(let a of u.split(/\n+/u))for(let f of ts(t,i,a))s(f)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function xt(t){return String(t).padStart(12,"0")}var ce=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
|
|
16
|
+
`,c=k(n.map(a=>a.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${xt(r)}-${xt(s)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as bt}from"node:path";import{mkdirSync as ns}from"node:fs";function rs(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function L(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=rs(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function ss(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 wt(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&ss(e)?t.title:e.text;return{id:t?.id??k(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function os(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,c)=>i.key.localeCompare(c.key))){let i=await e.getText(o.key);if(i)try{let c=JSON.parse(i);c.version===1&&Array.isArray(c.observations)&&s.push(c)}catch{}}return s}async function ue(t,e){let r=(await os(t,e)).flatMap(p=>p.observations).sort((p,v)=>{let K=p.occurredAt.localeCompare(v.occurredAt);if(K!==0)return K;let qe=p.sequence-v.sequence;return qe!==0?qe:p.id.localeCompare(v.id)}),s=new Map,o=new Map,i,c,u,a=[],f=[],l=[],m=[],d=[],S=[];for(let p of r)switch(p.kind){case"goal":i=p.text;break;case"plan":c=p.text;break;case"phase":s.set(p.key,wt(s.get(p.key),p));break;case"task":o.set(p.key,wt(o.get(p.key),p));break;case"decision":a.push(p.text);break;case"blocker":f.push(p.text);break;case"warning":l.push(p.text);break;case"next_action":m.push(p.text);break;case"file":d.push(p.text);break;case"test":S.push(p.text);break;case"session":u={agent:p.agent,nativeSessionId:p.nativeSessionId,sessionKey:p.sessionKey,updatedAt:p.occurredAt};break}let h=Array.from(s.values()).sort((p,v)=>(p.order??Number.MAX_SAFE_INTEGER)-(v.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((p,v)=>(p.order??Number.MAX_SAFE_INTEGER)-(v.order??Number.MAX_SAFE_INTEGER)),y=h.find(p=>p.status==="in_progress")??h.find(p=>p.status==="blocked")??h.find(p=>p.status==="pending"),b=g.find(p=>p.status==="in_progress")??g.find(p=>p.status==="blocked")??g.find(p=>p.status==="pending"),C=L([...m,...b?[b.title]:[],...!b&&y?[y.title]:[],...g.filter(p=>p.status==="pending").slice(0,5).map(p=>p.title)],8),A=L([...f,...h.filter(p=>p.status==="blocked").map(p=>p.title),...g.filter(p=>p.status==="blocked").map(p=>p.title)],20),j={version:1,projectId:t.id,projectName:t.name,goal:i,plan:c,phases:h,tasks:g,decisions:L(a,20),blockers:A,warnings:L(l,20),nextActions:C,filesTouched:L(d,30),tests:L(S,20),currentPhase:y,currentTask:b,progress:{phasesTotal:h.length,phasesCompleted:h.filter(p=>p.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(p=>p.status==="completed").length,blocked:h.filter(p=>p.status==="blocked").length+g.filter(p=>p.status==="blocked").length},lastSession:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},E=bt(t.rootPath,".toolnet","work");return ns(E,{recursive:!0}),I(bt(E,"current.json"),j),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(j,null,2)+`
|
|
17
|
+
`,"application/json"),j}async function le(t,e){let n=await e.getText(`projects/${t.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function ds(t,e){if(!as(t))return{events:[],nextOffset:e};let n=ls(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=cs(t,"r");try{us(i,o,0,s,r)}finally{is(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
|
|
18
|
+
`);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
|
|
19
|
+
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var de=class{constructor(e){this.options=e;this.journal=new ce(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=ds(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=ae(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ue(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as vs,existsSync as xs,openSync as bs,readSync as ws,statSync as js}from"node:fs";var ps=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function W(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ne(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))Ne(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(ps.has(r)||["data","payload","parts","messages"].includes(r))&&Ne(s,e,n+1)}}function O(t,e,n,r,s,o=.95){let i=W(r);return{version:1,id:k([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function T(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return W(t.slice(r.length+1))}return null}function fs(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function ms(t){return W(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function jt(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Ne(o.data,i);for(let c of i){let u={type:"project"},a=null;for(let f of c.split(/\r?\n/u)){let l=W(f);if(!l){a=null;continue}let m=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let v=Number(m[1]);u={type:"phase",key:`phase:${v}`,order:v,title:W(m[2]??"")},a=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let v=Number(d[1]);u={type:"task",key:`task:${v}`,order:v,title:W(d[2]??"")},a=null;continue}let S=T(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(O(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let h=T(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(O(t,o,u.type==="phase"?"phase_objective":"objective",h,u,.98)),a=null;continue}let g=T(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(O(t,o,u.type==="phase"?"phase_why":"why",g,u,.98)),a=null;continue}let y=T(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(y){s(O(t,o,"desired_outcome",y,{type:"project"},.98)),a=null;continue}let b=T(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(O(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let C=T(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(C){s(O(t,o,"phase_deliverable",C,u,.97)),a=null;continue}let A=T(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(A){s(O(t,o,"acceptance_criterion",A,u,.98)),a="acceptance_criterion";continue}let j=T(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(j){s(O(t,o,"dependency",j,u,.97)),a="dependency";continue}let E=T(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(E){s(O(t,o,"open_question",E,u,.95)),a="open_question";continue}let p=T(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(p){s(O(t,o,"constraint",p,u,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){a="constraint";continue}if(a&&fs(f)){s(O(t,o,a,ms(f),u,.96));continue}a=null}}}return n}function It(t){return String(t).padStart(12,"0")}var pe=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.evidence.sequence)),s=Math.max(...n.map(u=>u.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=k(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${It(r)}-${It(s)}-${i}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,JSON.stringify(o,null,2)+`
|
|
20
|
+
`,"application/json"),c}};import{mkdirSync as gs}from"node:fs";import{join as Pt}from"node:path";function hs(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function ys(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function M(t,e){return ys(e,t)?e:t}function R(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function Ss(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,c)=>i.key.localeCompare(c.key))){let i=await e.getText(o.key);if(i)try{let c=JSON.parse(i);c.version===1&&Array.isArray(c.observations)&&s.push(c)}catch{}}return s}function ks(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function Ot(t,e){let r=(await Ss(t,e)).flatMap(h=>h.observations).sort((h,g)=>{let y=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return y!==0?y:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),s,o,i,c,u,a=new Map,f=[],l=[],m=[];for(let h of r){let g=hs(h);if(h.scope==="phase"&&h.scopeKey){let y=a.get(h.scopeKey)??ks(h);switch(h.kind){case"phase_objective":y.objective=M(y.objective,g);break;case"phase_why":y.why=M(y.why,g);break;case"phase_deliverable":y.deliverable=M(y.deliverable,g);break;case"acceptance_criterion":y.acceptanceCriteria.push(g);break;case"dependency":y.dependencies.push(g);break;case"open_question":y.openQuestions.push(g);break;case"constraint":y.constraints.push(g);break;case"note":y.notes.push(g);break}a.set(y.key,y);continue}switch(h.kind){case"mission":s=M(s,g);break;case"objective":o=M(o,g);break;case"why":i=M(i,g);break;case"desired_outcome":c=M(c,g);break;case"plan_rationale":u=M(u,g);break;case"open_question":f.push(g);break;case"constraint":l.push(g);break;case"note":m.push(g);break}}for(let h of a.values())h.acceptanceCriteria=R(h.acceptanceCriteria,20),h.dependencies=R(h.dependencies,15),h.openQuestions=R(h.openQuestions,15),h.constraints=R(h.constraints,15),h.notes=R(h.notes,20);let d={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:c,planRationale:u,phases:Array.from(a.values()).sort((h,g)=>h.order-g.order),openQuestions:R(f,20),constraints:R(l,20),notes:R(m,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=Pt(t.rootPath,".toolnet","work");return gs(S,{recursive:!0}),I(Pt(S,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
|
|
21
|
+
`,"application/json"),d}async function Et(t,e){let n=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Is(t,e){if(!xs(t))return{events:[],nextOffset:e};let n=js(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=bs(t,"r");try{ws(o,s,0,s.length,r)}finally{vs(o)}let i=s.toString("utf8"),c=i.lastIndexOf(`
|
|
22
|
+
`);if(c<0)return{events:[],nextOffset:r};let u=i.slice(0,c+1);return{events:u.split(`
|
|
23
|
+
`).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var fe=class{constructor(e){this.options=e;this.journal=new pe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Is(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=jt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Ot(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as _s}from"node:fs";import{join as _e}from"node:path";import{existsSync as At,mkdirSync as Ps,readFileSync as Os,statSync as Tt,writeFileSync as Es}from"node:fs";import{dirname as Ts,join as Cs}from"node:path";var Ct=64*1024,As=`# ToolNet Project Operating Manual
|
|
24
24
|
|
|
25
25
|
This file contains persistent instructions for AI agents working on this project.
|
|
26
26
|
|
|
@@ -63,41 +63,58 @@ Things an AI agent should always remember.
|
|
|
63
63
|
<!--
|
|
64
64
|
- [advisory] Prefer small focused files.
|
|
65
65
|
-->
|
|
66
|
-
`;function
|
|
66
|
+
`;function me(t){return Cs(t.rootPath,".toolnet","PROJECT.md")}function Ms(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Rs(t){let e=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=r.exec(t);){let o=s[1].toLowerCase(),i=Ms(s[2]);if(!i)continue;let c=`${o}:${i.toLowerCase()}`;n.has(c)||(n.add(c),e.push({id:k(c).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Ns(t){let e=me(t);return At(e)||(Ps(Ts(e),{recursive:!0}),Es(e,As,{encoding:"utf8",mode:384})),e}function ge(t,e=!1){let n=e?Ns(t):me(t);if(!At(n))return null;if(Tt(n).size>Ct)throw new Error(`PROJECT.md exceeds ${Ct} bytes`);let s=Os(n,"utf8");return{path:n,content:s,digest:k(s),rules:Rs(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Tt(n).mtimeMs).toISOString()}}function $s(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 Fs(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 he=class{constructor(e){this.options=e}options;async capture(e,n){let r=await le(this.options.project,this.options.storage);if(r||(r=await ue(this.options.project,this.options.storage)),!Fs(r))return null;let s=ge(this.options.project,!1),o=s?s.rules.filter(m=>m.mode==="enforce").map(m=>m.text):[],i=k(JSON.stringify($s(r))),c=k([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),u=new Date().toISOString(),a={version:1,id:c,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:u,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),incompleteTasks:r.tasks.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:[...o,...r.warnings].slice(0,20),filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:i},f=`projects/${this.options.project.id}/work/handoffs/${c}.json`;await this.options.storage.exists(f)||await this.options.storage.put(f,JSON.stringify(a,null,2)+`
|
|
67
67
|
`,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(a,null,2)+`
|
|
68
|
-
`,"application/json");let l=
|
|
69
|
-
`))if(n)try{let r=
|
|
70
|
-
`);if(a<0)return{events:[],nextOffset:s,reset:r};let f=
|
|
71
|
-
`)){if(!d)continue;let
|
|
72
|
-
`,"utf8"),h=s+l;l+=
|
|
73
|
-
`),
|
|
74
|
-
`).filter(
|
|
68
|
+
`,"application/json");let l=_e(this.options.project.rootPath,".toolnet","work","handoffs");return _s(l,{recursive:!0}),I(_e(l,`${c}.json`),a),I(_e(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};async function Mt(t,e){let n=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}var ye=class{identity;wal;remote;sanitizer=new q;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=at(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new re(this.identity),this.remote=new ne(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new oe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new de({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new fe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new he({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as Ls,readFileSync as Ws,readdirSync as Ds,statSync as Rt}from"node:fs";import{homedir as Ks}from"node:os";import{join as Se,resolve as Nt}from"node:path";function _t(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function Bs(){return process.env.CODEX_HOME??Se(Ks(),".codex")}function U(t){let e="";try{e=Ws(t,"utf8").slice(0,128*1024)}catch{return{raw:{}}}for(let n of e.split(`
|
|
69
|
+
`))if(n)try{let r=_t(JSON.parse(n));if(r.type!=="session_meta")continue;let s=_t(r.payload),o=[s.id,s.thread_id,s.threadId,s.session_id,s.sessionId].find(c=>typeof c=="string"),i=typeof s.cwd=="string"?s.cwd:void 0;return{threadId:o,cwd:i,raw:s}}catch{}return{raw:{}}}function $e(t,e){if(!Ls(t))return;let n;try{n=Ds(t,{withFileTypes:!0})}catch{return}for(let r of n){let s=Se(t,r.name);if(r.isDirectory()){$e(s,e);continue}r.isFile()&&r.name.endsWith(".jsonl")&&e.push(s)}}function Fe(){let t=Bs(),e=[];return $e(Se(t,"sessions"),e),$e(Se(t,"archived_sessions"),e),e.sort((n,r)=>{try{return Rt(r).mtimeMs-Rt(n).mtimeMs}catch{return 0}})}function Le(t){let e=Fe(),n=e.find(r=>r.includes(t));if(n)return n;for(let r of e)if(U(r).threadId===t)return r;return null}function ke(t,e){let n=Nt(t),r=Nt(e);return r===n||r.startsWith(n+"/")||n.startsWith(r+"/")}import{closeSync as zs,existsSync as Js,openSync as qs,readSync as Hs,statSync as Vs}from"node:fs";function $t(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function Us(t){let e=t.timestamp;if(typeof e=="string"){let n=new Date(e);if(!Number.isNaN(n.getTime()))return n.toISOString()}return new Date().toISOString()}function Ys(t){let e=typeof t.type=="string"?t.type.toLowerCase():"",n=$t(t.payload),r=typeof n.type=="string"?n.type.toLowerCase():"",s=typeof n.role=="string"?n.role.toLowerCase():void 0;return e==="session_meta"?{type:"custom"}:s==="user"||r==="user_message"?{type:"user_prompt",role:"user"}:s==="assistant"||r==="agent_message"||r==="assistant_message"?{type:"assistant_message",role:"assistant"}:r.includes("function_call")||r.includes("tool_call")||r.includes("exec_command_begin")||r.includes("exec_command_start")?{type:"tool_call"}:r.includes("function_call_output")||r.includes("tool_result")||r.includes("exec_command_end")||r.includes("exec_command_complete")?{type:"tool_result"}:r.includes("error")?{type:"error"}:e.includes("compacted")||r.includes("compacted")?{type:"session_compact"}:{type:"custom",role:s}}function Ft(t,e=0){if(!Js(t))return{events:[],nextOffset:e,reset:!1};let n=Vs(t).size,r=e>n,s=r?0:e;if(s>=n)return{events:[],nextOffset:n,reset:r};let o=n-s,i=Buffer.alloc(o),c=qs(t,"r");try{Hs(c,i,0,o,s)}finally{zs(c)}let u=i.toString("utf8"),a=u.lastIndexOf(`
|
|
70
|
+
`);if(a<0)return{events:[],nextOffset:s,reset:r};let f=u.slice(0,a+1),l=0,m=[];for(let d of f.split(`
|
|
71
|
+
`)){if(!d)continue;let S=Buffer.byteLength(d+`
|
|
72
|
+
`,"utf8"),h=s+l;l+=S;let g;try{g=JSON.parse(d)}catch{continue}let y=$t(g),b=Ys(y);m.push({type:b.type,timestamp:Us(y),role:b.role,sourceEventId:`rollout:${h}`,sourceSequence:h,data:y,provenance:{source:"codex-rollout",sourcePath:t,sourceOffset:h}})}return{events:m,nextOffset:s+Buffer.byteLength(f,"utf8"),reset:r}}var Gs=[/^<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*$/],Xs=[/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],Qs=["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 Zs(t){let e=t.toLowerCase();return Qs.some(n=>e.includes(n))}function eo(t){if(!t.trim())return!0;for(let e of Gs)if(e.test(t))return!0;return Zs(t),!1}function to(t){let e=t;for(let n of Xs)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function We(t){let e=t.trim();return e?eo(e)?{content:"",filtered:!0,reason:"noise"}:{content:to(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function ve(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=We(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=ve(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=We(s);return o.filtered?null:o.content}return s&&typeof s=="object"?ve(s):s}).filter(s=>s!==null):e[n]=r;return e}function Lt(t){let e=typeof t.type=="string"?t.type.toLowerCase():"";if(e.includes("system")||e.includes("ephemeral")||e==="tool_call"&&!t.result)return!0;if(t.data&&typeof t.data=="object"){let n=t.data,r=typeof n.content=="string"?n.content:"";if(r&&We(r).filtered)return!0}return!1}function xe(t){return t?Math.ceil(t.length/3.5):0}function be(t,e){if(!t)return"";if(xe(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
|
|
73
|
+
`),c=Math.max(o,i);return c>r*.7?s.slice(0,c+1):s}function N(){let t=G(),e=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||e==="archive"||e==="full",r=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),c=n,u=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:c,archiveRemote:u}}function Wt(t){return(t||N()).rawTranscript}function Dt(t){return(t||N()).durableMemoryMaxItemsPerSession}function Kt(t){return(t||N()).sessionSummaryMaxTokens}function Bt(t){return(t||N()).archiveRemote}function no(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 ro(t,e){let n=t.toLowerCase(),r=.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)n.includes(i)&&(r+=.15);e==="rule"||e==="architecture"||e==="blocker"?r+=.2:e==="decision"||e==="deploy"?r+=.15:(e==="fix"||e==="next_action")&&(r+=.1),t.length<20?r-=.3:t.length>500&&(r-=.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)&&(r-=.4);return Math.max(0,Math.min(1,r))}function so(t,e){let n=[],r=new Set;for(let i of t){let c=i.split(`
|
|
74
|
+
`).filter(u=>u.trim());for(let u of c){let a=u.trim();if(a.length<15)continue;let f=a.toLowerCase().replace(/\s+/g," ");if(r.has(f))continue;r.add(f);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 m=ro(a,l);if(m<.3)continue;let d=no(a);n.push({category:l,text:d,importance:m,sourceSessionId:e})}}let s=N(),o=Dt(s);return n.sort((i,c)=>c.importance-i.importance).slice(0,o)}function oo(t){let e=N(),n=Kt(e),o=t.join(`
|
|
75
75
|
|
|
76
76
|
`).split(`
|
|
77
|
-
`).filter(i=>{let
|
|
78
|
-
`);return
|
|
77
|
+
`).filter(i=>{let c=i.trim();return c.length>20&&!c.startsWith("npm")&&!c.startsWith("\u2713")&&!c.startsWith("Error:")}).slice(0,20).join(`
|
|
78
|
+
`);return be(o,n)}function zt(t,e){let r=(Array.isArray(t)?t:t.split(`
|
|
79
79
|
|
|
80
|
-
`).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=
|
|
81
|
-
|
|
82
|
-
`)
|
|
80
|
+
`).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=so(r,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),c=s.filter(d=>d.category==="file").map(d=>d.text),u=s.filter(d=>d.category==="fix").map(d=>d.text),a=s.filter(d=>d.category==="blocker").map(d=>d.text),f=s.filter(d=>d.category==="next_action").map(d=>d.text),l=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:oo(r),decisions:o,projectRules:i,filesChanged:c,bugsFixed:u,commands:l,blockers:a,nextActions:f,durableFacts:s}}import{existsSync as io,mkdirSync as ao,readFileSync as co,renameSync as uo,writeFileSync as lo}from"node:fs";import{dirname as po,join as fo}from"node:path";function mo(t,e){ao(po(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;lo(n,`${JSON.stringify(e,null,2)}
|
|
81
|
+
`,{encoding:"utf8",mode:384}),uo(n,t)}function Yt(t){return fo(t.rootPath,".toolnet","work","current.json")}function go(t){let e=Yt(t);if(!io(e))return null;try{let n=JSON.parse(co(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function De(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function D(t,e,n){let r=[],s=new Set;for(let o of[...t,...e].reverse()){let i=De(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function ho(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 Jt(t,e){let n=e.status??t?.status??"pending",r=n;t?.status==="completed"&&n!=="completed"&&(r="completed"),t&&n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status);let s=t&&ho(e)?t.title:e.text;return{id:t?.id??e.id,title:s,status:r,order:e.order??t?.order,confidence:Math.max(t?.confidence??0,e.confidence),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}function qt(t){let e=new Map;for(let n of t){let r=n.order!==void 0?`order:${n.order}`:De(n.title);e.set(r,n)}return e}function Ht(t){return t.order!==void 0?`order:${t.order}`:De(t.key||t.text)}function Vt(t){return Array.from(t).sort((e,n)=>{let r=e.order??Number.MAX_SAFE_INTEGER,s=n.order??Number.MAX_SAFE_INTEGER;return r!==s?r-s:e.updatedAt.localeCompare(n.updatedAt)})}function Ut(t){return t.find(e=>e.status==="in_progress")??t.find(e=>e.status==="blocked")??t.find(e=>e.status==="pending")}function Gt(t,e){let n=go(t),r=qt(n?.phases??[]),s=qt(n?.tasks??[]),o=n?.goal,i=n?.plan,c=n?.lastSession,u=[],a=[],f=[],l=[],m=[],d=[],S=[...e].sort((p,v)=>{let K=p.occurredAt.localeCompare(v.occurredAt);return K!==0?K:p.sequence-v.sequence});for(let p of S)switch(p.kind){case"goal":o=p.text;break;case"plan":i=p.text;break;case"phase":{let v=Ht(p);r.set(v,Jt(r.get(v),p));break}case"task":{let v=Ht(p);s.set(v,Jt(s.get(v),p));break}case"decision":u.push(p.text);break;case"blocker":a.push(p.text);break;case"warning":f.push(p.text);break;case"next_action":l.push(p.text);break;case"file":m.push(p.text);break;case"test":d.push(p.text);break;case"session":c={agent:p.agent,nativeSessionId:p.nativeSessionId,sessionKey:p.sessionKey,updatedAt:p.occurredAt};break}let h=Vt(r.values()),g=Vt(s.values()),y=Ut(h),b=Ut(g),C=D(n?.nextActions??[],[...l,...b?[b.title]:[],...!b&&y?[y.title]:[],...g.filter(p=>p.status==="pending").slice(0,5).map(p=>p.title)],8),A=D(n?.blockers??[],[...a,...h.filter(p=>p.status==="blocked").map(p=>p.title),...g.filter(p=>p.status==="blocked").map(p=>p.title)],20),j=S.length>0?S[S.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),E={version:1,projectId:t.id,projectName:t.name,goal:o,plan:i,phases:h,tasks:g,decisions:D(n?.decisions??[],u,20),blockers:A,warnings:D(n?.warnings??[],f,20),nextActions:C,filesTouched:D(n?.filesTouched??[],m,30),tests:D(n?.tests??[],d,20),currentPhase:y,currentTask:b,progress:{phasesTotal:h.length,phasesCompleted:h.filter(p=>p.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(p=>p.status==="completed").length,blocked:h.filter(p=>p.status==="blocked").length+g.filter(p=>p.status==="blocked").length},lastSession:c,updatedAt:j};return mo(Yt(t),E),E}import{existsSync as yo,readFileSync as So,writeFileSync as ko}from"node:fs";import{join as vo}from"node:path";var Qt="<!-- TOOLNET:STABLE-WORK:BEGIN -->",Ke="<!-- TOOLNET:STABLE-WORK:END -->";function Be(t){switch(t.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function we(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${n}`)]:[]}function Xt(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${Be(n)} ${n.title}`)]:[]}function xo(t){let e=[Qt,"# ToolNet Stable Work State","",`Updated: ${t.updatedAt}`];return t.lastSession&&e.push(`Last agent: ${t.lastSession.agent}`,`Last session: ${t.lastSession.nativeSessionId}`),t.goal&&e.push("","Goal:",t.goal),t.plan&&e.push("","Plan:",t.plan),t.currentPhase&&e.push("","Current phase:",`${Be(t.currentPhase)} ${t.currentPhase.title}`),t.currentTask&&e.push("","Current task:",`${Be(t.currentTask)} ${t.currentTask.title}`),e.push(...Xt("Phases",t.phases)),e.push(...Xt("TODO / Tasks",t.tasks)),e.push(...we("Next actions",t.nextActions)),e.push(...we("Blockers",t.blockers)),e.push(...we("Important decisions",t.decisions)),e.push(...we("Files touched",t.filesTouched)),e.push("","Progress:",`- Phases: ${t.progress.phasesCompleted}/${t.progress.phasesTotal}`,`- Tasks: ${t.progress.tasksCompleted}/${t.progress.tasksTotal}`,`- Blocked: ${t.progress.blocked}`,"","Continuation:","- Resume current unfinished task.","- Never redo completed TODO/Phase unless explicitly requested.","- Ask ToolNet Memory for deeper history only when necessary.",Ke),e.join(`
|
|
82
|
+
`)}function Zt(t,e){let n=vo(t.rootPath,".toolnet","current.md"),r="";if(yo(n))try{r=So(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let s=xo(e),o=r.indexOf(Qt),i=r.indexOf(Ke),c;o>=0&&i>=o?c=[r.slice(0,o).trimEnd(),s,r.slice(i+Ke.length).trimStart()].filter(Boolean).join(`
|
|
83
|
+
|
|
84
|
+
`):c=r.trim()?`${r.trim()}
|
|
85
|
+
|
|
86
|
+
${s}`:s,ko(n,`${c.trim()}
|
|
87
|
+
`,{encoding:"utf8",mode:384})}import{existsSync as bo,mkdirSync as wo,readFileSync as jo,renameSync as Io,writeFileSync as Po}from"node:fs";import{dirname as Oo,join as Eo}from"node:path";function en(t){return Eo(t.rootPath,".toolnet","context","session-origin.json")}function To(t,e){wo(Oo(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;Po(n,`${JSON.stringify(e,null,2)}
|
|
88
|
+
`,{encoding:"utf8",mode:384}),Io(n,t)}function je(t,e){return[...t].filter(n=>n.kind===e).sort((n,r)=>{let s=n.occurredAt.localeCompare(r.occurredAt);return s!==0?s:n.sequence-r.sequence}).at(-1)}function tn(t,e){let n=je(e.observations,"file"),r=je(e.observations,"next_action"),s=je(e.observations,"blocker"),o=je(e.observations,"decision"),i={version:1,projectId:t.id,agent:e.agent,nativeSessionId:e.nativeSessionId,updatedAt:e.workState.updatedAt,currentTask:e.workState.currentTask?.title,currentPhase:e.workState.currentPhase?.title,lastTouchedFile:n?.text??e.workState.filesTouched.at(-1),latestNextAction:r?.text??e.workState.nextActions.at(-1),latestBlocker:s?.text??e.workState.blockers.at(-1),latestDecision:o?.text??e.workState.decisions.at(-1)};return To(en(t),i),i}function Co(t){let e=en(t);if(!bo(e))return null;try{let n=JSON.parse(jo(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function nn(t){let e=Co(t);if(!e)return null;let n=["Previous session:",`- Agent: ${e.agent}`,`- Session: ${e.nativeSessionId}`];return e.currentPhase&&n.push(`- Current phase: ${e.currentPhase}`),e.currentTask&&n.push(`- Current task: ${e.currentTask}`),e.lastTouchedFile&&n.push(`- Last touched file: ${e.lastTouchedFile}`),e.latestBlocker&&n.push(`- Blocker: ${e.latestBlocker}`),e.latestNextAction&&n.push(`- Next action: ${e.latestNextAction}`),e.latestDecision&&n.push(`- Important decision: ${e.latestDecision}`),n.join(`
|
|
89
|
+
`)}async function Y(t){let e=t.threadId.trim();if(!e)throw new Error("Codex thread ID is required");let n=U(t.rolloutPath),r=t.cwd??n.cwd;if(r&&!ke(t.project.rootPath,r))throw new Error(`Codex thread does not belong to project: ${r}`);if(n.threadId&&n.threadId!==e)throw new Error(`Codex rollout thread mismatch: expected ${e}, got ${n.threadId}`);let s=new ye({project:t.project,storage:t.storage,agent:"codex",nativeSessionId:e,metadata:{source:"codex-rollout",rolloutPath:t.rolloutPath,cwd:r,client:t.client}}),o=s.status(),i=o.sourceCursors["codex.rollout.path"],c=Number(o.sourceCursors["codex.rollout.offset"]??0);i&&i!==t.rolloutPath&&(c=0),(!Number.isFinite(c)||c<0)&&(c=0);let u=Ft(t.rolloutPath,c),a=[];o.lastSequence===0&&a.push({type:"session_start",sourceEventId:`codex:${e}:start`,data:{threadId:e,cwd:r,rolloutPath:t.rolloutPath,sessionMeta:n.raw},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}}),i&&i!==t.rolloutPath&&a.push({type:"custom",sourceEventId:`codex:${e}:rollout-rotation:${t.rolloutPath}`,data:{event:"rollout_rotation",previousPath:i,rolloutPath:t.rolloutPath},provenance:{source:"codex-rollout"}}),u.reset&&a.push({type:"custom",sourceEventId:`codex:${e}:rollout-reset:${u.nextOffset}`,data:{event:"rollout_reset"},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}});let f=u.events.filter(d=>!Lt(d.data)).map(d=>({...d,data:ve(d.data)}));if(a.push(...f),t.idle&&f.length>0)try{let d={projectId:t.project.id,projectName:t.project.name,projectRoot:t.project.rootPath,agent:"codex",nativeSessionId:e,sessionKey:`codex:${e}`,remotePrefix:`projects/${t.project.id}/sessions/codex/${e}`,localDirectory:""},S=f.map((y,b)=>({version:1,id:`codex-work-${e}-${y.sourceSequence??b}`,sequence:b+1,projectId:t.project.id,agent:"codex",nativeSessionId:e,type:y.type,timestamp:y.timestamp??new Date().toISOString(),role:y.role,sourceEventId:y.sourceEventId,sourceSequence:y.sourceSequence,data:y.data??{},provenance:y.provenance??{}})),h=ae(d,S),g=Gt(t.project,h);Zt(t.project,g),tn(t.project,{agent:"codex",nativeSessionId:e,observations:h,workState:g})}catch{}t.idle&&t.turnId&&a.push({type:"session_idle",sourceEventId:`codex:${e}:turn:${t.turnId}:idle`,data:{turnId:t.turnId,client:t.client},provenance:{source:"codex-notify"}});let l=s.recordMany(a);if(s.setSourceCursor("codex.rollout.path",t.rolloutPath),s.setSourceCursor("codex.rollout.offset",u.nextOffset),t.turnId&&s.setSourceCursor("codex.last.turn",t.turnId),t.idle&&f.length>0)try{let d=f.map(h=>JSON.stringify(h.data)),S=zt(d,e);s.setSourceCursor("codex.session.summary",S.summary),s.setSourceCursor("codex.session.facts_count",S.durableFacts.length),Wt()&&!Bt()&&s.setSourceCursor("codex.raw_transcript.archived","local")}catch{}let m=await s.flush();return{threadId:e,imported:l.length,rolloutEvents:u.events.length,eventCount:m.eventCount,chunkCount:m.chunkCount,status:m.status,rolloutOffset:u.nextOffset,reset:u.reset}}import{existsSync as Ao}from"node:fs";import{dirname as Mo,join as Ro,parse as No,resolve as _o}from"node:path";function rn(t){let e=_o(t),n=No(e).root;for(;;){if(Ao(Ro(e,".toolnet","project.json")))return new _().detect(e);if(e===n)break;let r=Mo(e);if(r===e)break;e=r}return null}async function sn(t,e,n=100){let r=[];for(let s of Fe()){let o=U(s);if(!(!o.threadId||!o.cwd)&&ke(t.rootPath,o.cwd)&&(r.push(await Y({project:t,storage:e,threadId:o.threadId,rolloutPath:s,cwd:o.cwd})),r.length>=n))break}return r}import{existsSync as $o,mkdirSync as on,readFileSync as Fo,writeFileSync as an}from"node:fs";import{homedir as cn}from"node:os";import{dirname as un,join as ze}from"node:path";function Lo(t){let e=[],n=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,r;for(;r=n.exec(t);){let s=r[1]??r[2]??"";try{e.push(r[1]!==void 0?JSON.parse(`"${s}"`):s)}catch{e.push(s)}}return e}function ln(t={}){let e=t.configFile??ze(process.env.CODEX_HOME??ze(cn(),".codex"),"config.toml"),n=t.previousFile??ze(cn(),".config","toolnet-memory","codex-notify-previous.json");on(un(e),{recursive:!0}),on(un(n),{recursive:!0});let r=$o(e)?Fo(e,"utf8"):"",s=t.binary??"toolnet-memory",o=`notify = [${JSON.stringify(s)}, "session:codex-notify"]`,i=r.split(`
|
|
90
|
+
`),c=i.findIndex(m=>/^\s*\[/.test(m));c<0&&(c=i.length);let u=-1,a=-1;for(let m=0;m<c;m+=1)if(/^\s*notify\s*=/.test(i[m])){if(u=m,a=m,i[m].includes("[")&&!i[m].includes("]"))for(;a+1<c&&(a+=1,!i[a].includes("]")););break}let f=[];if(u>=0){let m=i.slice(u,a+1).join(`
|
|
91
|
+
`);f=Lo(m),i.splice(u,a-u+1,o)}else c=i.findIndex(m=>/^\s*\[/.test(m)),c<0&&(c=i.length),i.splice(c,0,o);let l=f.length>=2&&f[f.length-1]==="session:codex-notify";return f.length>0&&!l&&an(n,JSON.stringify(f,null,2)+`
|
|
83
92
|
`,{encoding:"utf8",mode:384}),r=i.join(`
|
|
84
93
|
`),r.endsWith(`
|
|
85
94
|
`)||(r+=`
|
|
86
|
-
`),
|
|
87
|
-
`,{encoding:"utf8",mode:384}),e}import{existsSync as
|
|
88
|
-
`);if(
|
|
89
|
-
`)),i=Math.max(0,e-o);if(i>=16){let
|
|
90
|
-
`).trim()}async function
|
|
95
|
+
`),an(e,r,{encoding:"utf8",mode:384}),{configFile:e,previousFile:n,preservedPrevious:f.length>0&&!l}}import{existsSync as Wo,mkdirSync as Do,readFileSync as Ko,writeFileSync as Bo}from"node:fs";import{homedir as zo}from"node:os";import{dirname as Jo,join as dn}from"node:path";function qo(t){return`'${t.replace(/'/g,"'\\''")}'`}function pn(t={}){let e=t.hooksFile??dn(process.env.CODEX_HOME??dn(zo(),".codex"),"hooks.json");Do(Jo(e),{recursive:!0});let n={};if(Wo(e))try{n=JSON.parse(Ko(e,"utf8"))}catch(c){throw new Error(`Invalid existing Codex hooks.json: ${c instanceof Error?c.message:String(c)}`)}let r=n.hooks&&typeof n.hooks=="object"&&!Array.isArray(n.hooks)?n.hooks:{};n.hooks=r;let o=(Array.isArray(r.SessionStart)?r.SessionStart:[]).filter(c=>{try{return!JSON.stringify(c).includes("session:codex-context")}catch{return!0}}),i=t.binary??"toolnet-memory";return o.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${qo(i)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),r.SessionStart=o,Bo(e,JSON.stringify(n,null,2)+`
|
|
96
|
+
`,{encoding:"utf8",mode:384}),e}import{existsSync as Tl,mkdirSync as Yo,readFileSync as Cl,writeFileSync as Go}from"node:fs";import{dirname as Xo,join as mn}from"node:path";function Je(t){if(!t)return 0;let e=Array.from(t).length,n=t.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,n*1.3))}function x(t,e){let n=t.replace(/\s+/g," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function Ho(t){let e=[],n=!1;for(let r of t.split(/\r?\n/u)){let s=r.trim();if(s.includes("<!--")&&(n=!0),n){s.includes("-->")&&(n=!1);continue}let o=s.toLowerCase();if(!(!s||s.startsWith("#")||s==="```"||o.startsWith("- [enforce]")||o.startsWith("* [enforce]")||o.startsWith("- [advisory]")||o.startsWith("* [advisory]"))&&(s=s.replace(/^[-*]\s+/u,""),s&&e.push(x(s,280)),e.length>=16))break}return e}function Vo(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.trim(),o=s.toLowerCase(),c=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(a=>o.startsWith(a));if(!c)continue;let u=s.slice(c.length).trim();u&&(c.includes("enforce")?e.push(u):n.push(u))}return{enforce:e,advisory:n}}function Uo(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
|
|
97
|
+
`);if(Je(s)<=e){n.push(r);continue}let o=Je(n.join(`
|
|
98
|
+
`)),i=Math.max(0,e-o);if(i>=16){let c=Math.floor(i*3.2),u=x(r,c);u&&n.push(u)}break}return n.join(`
|
|
99
|
+
`).trim()}async function fn(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=ge(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=Vo(r),o=n?n.rules.filter(d=>d.mode==="enforce").map(d=>d.text):s.enforce,i=n?n.rules.filter(d=>d.mode==="advisory").map(d=>d.text):s.advisory,c=r?Ho(r):[],u=await le(t.project,t.storage),a=await Et(t.project,t.storage),f=await Mt(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."),r&&l.push(`Full operating manual: ${me(t.project)}`),o.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of o.slice(0,24))l.push(`- [ENFORCE] ${x(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${x(d,220)}`)}if(a&&(a.mission&&l.push("","MISSION",x(a.mission.value,420)),a.activeObjective&&l.push("","CURRENT OBJECTIVE",x(a.activeObjective.value,420)),a.why&&l.push("","WHY THIS WORK MATTERS",x(a.why.value,420)),a.desiredOutcome&&l.push("","DESIRED OUTCOME",x(a.desiredOutcome.value,420)),a.planRationale&&l.push("","WHY THIS APPROACH",x(a.planRationale.value,420))),u){if(l.push("","ACTIVE WORK"),u.goal&&l.push(`Goal: ${x(u.goal,320)}`),u.plan&&l.push(`Plan: ${x(u.plan,320)}`),l.push(`Progress: phases ${u.progress.phasesCompleted}/${u.progress.phasesTotal}; tasks ${u.progress.tasksCompleted}/${u.progress.tasksTotal}; blocked ${u.progress.blocked}`),u.currentPhase&&l.push(`Current phase: ${u.currentPhase.title} [${u.currentPhase.status}]`),u.currentPhase&&a){let d=a.phases.find(S=>S.order===u.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${x(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${x(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${x(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(S=>x(S.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(S=>{l.push(`- ${x(S.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(S=>{l.push(`- ${x(S.value,260)}`)})))}u.currentTask&&l.push(`Current task: ${u.currentTask.title} [${u.currentTask.status}]`),u.nextActions.length&&(l.push("","NEXT ACTIONS"),u.nextActions.slice(0,6).forEach((d,S)=>{l.push(`${S+1}. ${x(d,260)}`)})),u.blockers.length&&(l.push("","BLOCKERS"),u.blockers.slice(0,5).forEach(d=>{l.push(`- ${x(d,260)}`)})),u.warnings.length&&(l.push("","ATTENTION"),u.warnings.slice(-5).forEach(d=>{l.push(`- ${x(d,260)}`)})),u.decisions.length&&(l.push("","RECENT DECISIONS"),u.decisions.slice(-5).forEach(d=>{l.push(`- ${x(d,260)}`)})),u.lastSession&&l.push("",`Last work session: ${u.lastSession.agent} / ${u.lastSession.nativeSessionId}`)}if(a&&a.openQuestions.length&&(l.push("","UNRESOLVED QUESTIONS"),a.openQuestions.slice(0,5).forEach(d=>{l.push(`- ${x(d.value,260)}`)})),f&&l.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),c.length){l.push("","OPERATING NOTES");for(let d of c)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let m=Uo(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:m,estimatedTokens:Je(m),maxTokens:e,hasManual:!!r,hasWorkState:!!u,hasHandoff:!!f,generatedAt:new Date().toISOString()}}function Qo(t){return mn(t.rootPath,".toolnet","context","startup.md")}function Zo(t){return mn(t.rootPath,".toolnet","context","startup.json")}function ei(t,e){let n=Qo(t);Yo(Xo(n),{recursive:!0}),Go(n,e.text.endsWith(`
|
|
91
100
|
`)?e.text:e.text+`
|
|
92
|
-
`,{encoding:"utf8",mode:384}),
|
|
101
|
+
`,{encoding:"utf8",mode:384}),I(Zo(t),e)}async function gn(t,e,n=800){let s=(await fn({project:t,storage:e,maxTokens:n})).text;xe(s)>n&&(s=be(s,n),s+=`
|
|
93
102
|
|
|
94
103
|
[Context trimmed by ToolNet Memory token budget]
|
|
95
|
-
`);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:
|
|
104
|
+
`);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:k(s),estimatedTokens:xe(s),generatedAt:new Date().toISOString()};return ei(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
|
|
96
105
|
`,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
|
|
97
|
-
`,"application/json"),i}
|
|
106
|
+
`,"application/json"),i}import{existsSync as ii,readFileSync as ai}from"node:fs";import{join as ci}from"node:path";import{existsSync as hn,mkdirSync as ti,readFileSync as yn,renameSync as ni,writeFileSync as ri}from"node:fs";import{dirname as si,join as Sn}from"node:path";function kn(t){return Sn(t.rootPath,".toolnet","context","handoff.md")}function vn(t){return Sn(t.rootPath,".toolnet","context","handoff.json")}function xn(t,e){ti(si(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;ri(n,e.endsWith(`
|
|
107
|
+
`)?e:`${e}
|
|
108
|
+
`,{encoding:"utf8",mode:384}),ni(n,t)}function oi(t,e){xn(t,`${JSON.stringify(e,null,2)}
|
|
109
|
+
`)}function bn(t,e){let n=e.replace(/\r\n/g,`
|
|
110
|
+
`).trim();if(!n)return null;let r={version:1,projectId:t.id,projectName:t.name,text:n,digest:k(n),generatedAt:new Date().toISOString()};return xn(kn(t),n),oi(vn(t),r),r}function wn(t){let e=kn(t);if(!hn(e))return null;try{let n=yn(e,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=vn(t);if(hn(s))try{let o=JSON.parse(yn(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:t.id,projectName:t.name,text:n,digest:k(n),generatedAt:r}}catch{return null}}function ui(t){let e=ci(t.rootPath,".toolnet","current.md");if(!ii(e))return null;try{return ai(e,"utf8").trim()}catch{return null}}function li(t,e){let n=e.replace(/\r\n/g,`
|
|
111
|
+
`).trim(),r=2400,s=n.length>r?`${n.slice(0,r)}
|
|
112
|
+
|
|
113
|
+
[Current work truncated for fast handoff]`:n,o=nn(t);return["# ToolNet Fast Handoff","",`Project: ${t.name}`,"",...o?[o,""]:[],s,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
|
|
114
|
+
`)}function jn(t){let e=ui(t);if(e===null)return{updated:!1,reason:"missing-current",chars:0};if(!e.trim())return{updated:!1,reason:"empty-current",chars:0};let n=li(t,e);return wn(t)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(bn(t,n),{updated:!0,reason:"updated",chars:n.length})}function Ie(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function In(t){let e=G(),n=tt(Ze({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new te(n,t.id,t.name,t.remote??t.name)}async function hi(t){for(let e=0;e<10;e+=1){let n=Le(t);if(n)return n;await new Promise(r=>setTimeout(r,150))}return null}function yi(t){let e=gi(mi(),".config","toolnet-memory","codex-notify-previous.json");if(di(e))try{let n=JSON.parse(pi(e,"utf8"));if(!Array.isArray(n)||n.length===0||!n.every(s=>typeof s=="string"))return;fi(n[0],[...n.slice(1),t],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function Si(t){let e;try{e=JSON.parse(t)}catch{return}if(e.type!=="agent-turn-complete")return;let r=typeof e["thread-id"]=="string"?e["thread-id"]:"",s=typeof e["turn-id"]=="string"?e["turn-id"]:"",o=typeof e.cwd=="string"?e.cwd:"",i=typeof e.client=="string"?e.client:void 0;if(!r||!o)return;let c=rn(o);if(!c)return;let u=await hi(r);if(!u)return;let a=In(c);await Y({project:c,storage:a,threadId:r,rolloutPath:u,cwd:o,turnId:s,client:i,idle:!0});try{await gn(c,a,800)}catch{}try{jn(c)}catch{}}async function ki(){let[t="help",...e]=process.argv.slice(2);if(t==="install-notify"){let o=Ie(e,"--bin"),i=ln({binary:o}),c=pn({binary:o});console.log(`\u2705 Codex notify installed: ${i.configFile}`),i.preservedPrevious&&console.log(`\u2705 Previous notify preserved: ${i.previousFile}`),console.log(`\u2705 Codex SessionStart context hook: ${c}`);return}if(t==="notify"){let o=e[e.length-1]??"";try{await Si(o)}finally{yi(o)}return}let n=Ie(e,"--project")??process.cwd(),r=new _().detect(n),s=In(r);if(t==="sync"){let o=e[0];if(!o)throw new Error("Usage: sync <thread-id>");let i=Ie(e,"--rollout")??Le(o);if(!i)throw new Error(`Codex rollout not found for ${o}`);let c=await Y({project:r,storage:s,threadId:o,rolloutPath:i,idle:e.includes("--idle")});console.log(JSON.stringify(c,null,2));return}if(t==="recover"){let o=Number(Ie(e,"--limit")??100),i=await sn(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((c,u)=>c+u.imported,0)},null,2));return}console.log(`Codex Session Adapter
|
|
98
115
|
|
|
99
116
|
Commands:
|
|
100
117
|
install-notify
|
|
101
118
|
sync <thread-id> [--project PATH]
|
|
102
119
|
recover [--project PATH] [--limit N]
|
|
103
|
-
`)}
|
|
120
|
+
`)}ki().catch(t=>{process.argv[2]==="notify"&&process.exit(0),console.error(t instanceof Error?t.message:t),process.exit(1)});
|