toolnet-memory 0.3.11 → 0.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +432 -163
- package/bundle/agy-hook.js +38 -38
- package/bundle/agy.js +23 -23
- package/bundle/api.js +19 -16
- package/bundle/claude-hook.js +9 -9
- package/bundle/codex.js +28 -28
- package/bundle/context-runtime.js +4 -4
- package/bundle/context.js +12 -12
- package/bundle/continuity-certify.js +16 -13
- package/bundle/copilot-hook.js +13 -13
- package/bundle/cursor-hook.js +13 -13
- package/bundle/grok-hook.js +13 -13
- package/bundle/kiro-hook.js +14 -14
- package/bundle/mcp.js +21 -18
- package/bundle/opencode.js +27 -27
- package/package.json +1 -1
package/bundle/codex.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{existsSync as il,readFileSync as al}from"node:fs";import{spawn as cl}from"node:child_process";import{homedir as ul}from"node:os";import{join as ll}from"node:path";import{existsSync as As,readFileSync as Is}from"node:fs";import{homedir as Ps}from"node:os";import{join as Ms}from"node:path";function Es(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
|
|
2
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 Ts(){let t=process.env.TOOLNET_GLOBAL_ENV??Ms(Ps(),".config","toolnet-memory",".env");if(!As(t))return;let e=Is(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]=Es(r.slice(s+1)))}}Ts();function ce(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function ue(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function Ce(){return{memory:{autoCapture:ce(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:ce(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:ce(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:ce(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:ue(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:ue(process.env.MEMORY_RERANK_TOP,10),finalContext:ue(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:ue(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:ce(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:ue(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Os}from"node:crypto";import{existsSync as gt,mkdirSync as Rs,readFileSync as Ns,renameSync as _s,writeFileSync as $s}from"node:fs";import{basename as Ks,dirname as Ae,join as Ie,parse as Ut,resolve as le}from"node:path";var Yt=".toolnet",Fs="project.json";function Ws(t){return Os("sha256").update(t).digest("hex").slice(0,16)}function yt(t){return Ie(t,Yt,Fs)}function Ls(t){return gt(yt(t))}function Ds(t,e){let n=le(t),r=Ut(n).root;for(;;){if(Ls(n))return n;if(n===r||e&&n===le(e))break;let s=Ae(n);if(s===n)break;n=s}return null}function zs(t){let e=le(t),n=Ut(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>gt(Ie(e,o))))return e;if(e===n)break;let s=Ae(e);if(s===e)break;e=s}return le(t)}function qs(t){let e;try{e=JSON.parse(Ns(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:Ae(Ae(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 Ht(t,e){let n=Ie(t,Yt);Rs(n,{recursive:!0});let r=yt(t),s=`${r}.tmp-${process.pid}`;$s(s,JSON.stringify(e,null,2)+`
|
|
3
3
|
`,{encoding:"utf8",mode:384}),_s(s,r)}function Gt(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 te=class{detect(e=process.cwd()){let n=le(e),r=zs(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>gt(Ie(r,f))),i=Ds(n,o?r:void 0);if(i){let f=yt(i),d=qs(f);return d.rootPath!==i&&(d.rootPath=i,d.updatedAt=new Date().toISOString(),Ht(i,d)),Gt(d,i)}let a=new Date().toISOString(),c=Ks(r),u={version:1,id:Ws(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return Ht(r,u),Gt(u,r)}};var Bs=[{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}],Pe=class{scan(e){let n=[];for(let r of Bs){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 H=class{scanner=new Pe;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.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as mo}from"node:os";import{join as go}from"node:path";import{DeleteObjectCommand as Vs,GetObjectCommand as Js,HeadObjectCommand as Hs,ListObjectsV2Command as Gs,PutObjectCommand as Us,S3Client as Ys}from"@aws-sdk/client-s3";import{getSignedUrl as Xs}from"@aws-sdk/s3-request-presigner";var Me=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ys({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 Us({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Xs(this.client,new Js({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 Hs({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 Vs({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Gs({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 Xt,mkdir as Qs,readFile as Zs,readdir as eo,rm as to,stat as Qt,writeFile as no}from"node:fs/promises";import{dirname as ro,join as so,relative as Zt,resolve as oo}from"node:path";var de=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return oo(this.root,n)}async put(e,n){let r=this.path(e);await Qs(ro(r),{recursive:!0}),await no(r,n)}async get(e){try{return await Zs(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 Xt(this.path(e)),!0}catch{return!1}}async delete(e){await to(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Xt(n)}catch{return r}let s=async i=>{let a=await eo(i,{withFileTypes:!0});for(let c of a){let u=so(i,c.name);if(c.isDirectory()){await s(u);continue}let f=await Qt(u);r.push({key:Zt(this.root,u),size:f.size,updatedAt:f.mtime.toISOString()})}},o=await Qt(n);return o.isDirectory()?await s(n):r.push({key:Zt(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as io,GetObjectCommand as ao,HeadObjectCommand as co,ListObjectsV2Command as uo,PutObjectCommand as lo,S3Client as po}from"@aws-sdk/client-s3";import{getSignedUrl as fo}from"@aws-sdk/s3-request-presigner";var pe=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new po({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 lo({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await fo(this.client,new ao({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 co({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 io({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new uo({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 ht(t,e){return console.warn(e),new de(t)}function en(t){let e=t.localRoot??go(mo(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new pe({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):ht(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 pe({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):ht(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 Me({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):ht(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new de(e)}function yo(t){return new Promise(e=>setTimeout(e,t))}async function tn(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(a){if(o=a,i>=n)break;let c=Math.min(s,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await yo(c+u)}throw o}var ho=new Set(["put","get","getText","delete","list"]);function nn(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:ho.has(r)?(...o)=>tn(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function rn(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 sn(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 Ee=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=rn(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(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}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
4
|
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=sn(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 jo}from"node:path";import{createHash as So}from"node:crypto";import{dirname as ko}from"node:path";import{mkdirSync as wo,readFileSync as vo,renameSync as bo,writeFileSync as xo}from"node:fs";function w(t){return So("sha256").update(t).digest("hex")}function St(t){if(Array.isArray(t))return t.map(St);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=St(e[r]);return n}return t}function on(t){return JSON.stringify(St(t))}function an(t){try{return JSON.parse(vo(t,"utf8"))}catch{return null}}function O(t,e){wo(ko(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;xo(n,JSON.stringify(e,null,2)+`
|
|
5
5
|
`,{encoding:"utf8",mode:384}),bo(n,t)}function cn(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=w(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 un(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=cn(r.toLowerCase(),"agent"),i=cn(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:jo(t.rootPath,".toolnet","sessions",o,i)}}function ln(t){return String(t).padStart(12,"0")}var Te=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
|
|
6
6
|
`,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let a=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!a)continue;let c=Number(a[1]),u=Number(a[2]);!Number.isFinite(c)||!Number.isFinite(u)||(s.push({key:i.key,start:c,end:u}),o=Math.max(o,u))}return s.sort((i,a)=>i.start-a.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),a=n.filter(y=>y.sequence>i.maxSequence),c=0;for(let y of this.split(a)){let h=y[0],k=y[y.length-1],
|
|
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),a=n.filter(y=>y.sequence>i.maxSequence),c=0;for(let y of this.split(a)){let h=y[0],k=y[y.length-1],M=y.map(T=>JSON.stringify(T)).join(`
|
|
8
8
|
`)+`
|
|
9
|
-
`,E=w(
|
|
9
|
+
`,E=w(M).slice(0,16),P=[e.remotePrefix,"events",`${ln(h.sequence)}-${ln(k.sequence)}-${E}.jsonl`].join("/");await this.storage.exists(P)||await this.storage.put(P,M,"application/x-ndjson"),c+=y.length}let u=await this.scan(e),f=n[n.length-1],d=o?.status??"active";f?.type==="session_end"||f?.type==="session_idle"?d="idle":f?.type==="error"?d="error":n.length>0&&(d="active");let p=new Date().toISOString(),l=n[0],g={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:d,createdAt:o?.createdAt??l?.timestamp??p,updatedAt:f?.timestamp??p,firstEventAt:o?.firstEventAt??l?.timestamp,lastEventAt:f?.timestamp??o?.lastEventAt,eventCount:u.maxSequence,chunkCount:u.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(g.title=s.title??o?.title);let S={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:u.maxSequence,lastRemoteSequence:u.maxSequence,sourceCursors:r,updatedAt:p};return await this.putJson(`${e.remotePrefix}/cursor.json`,S),await this.putJson(`${e.remotePrefix}/session.json`,g),{uploadedEvents:c,lastRemoteSequence:u.maxSequence,eventCount:g.eventCount,chunkCount:g.chunkCount,status:d}}};import{closeSync as wt,existsSync as Eo,fsyncSync as To,mkdirSync as Oo,openSync as vt,readSync as Ro,rmSync as pn,statSync as fn,writeSync as No}from"node:fs";import{join as bt}from"node:path";var Co=new Set(["thinking","reasoning","reasoningcontent","chainofthought","cot","analysistext","internalreasoning","modelthinking"]),Ao=new Set(["reasoning","thinking","chain_of_thought","chain-of-thought","internal_reasoning","internal-reasoning"]);function Io(t){return t.toLowerCase().replace(/[^a-z0-9]+/gu,"")}function Po(t){for(let e of["type","kind"]){let n=t[e];if(typeof n=="string"){let r=n.toLowerCase();if(Ao.has(r))return n}}return null}function kt(t,e=0){if(e>12)return"[ToolNet nested value omitted]";if(Array.isArray(t))return t.map(o=>kt(o,e+1));if(!t||typeof t!="object")return t;let n=t,r=Po(n);if(r)return{type:r,omitted:"[private reasoning omitted]"};let s={};for(let[o,i]of Object.entries(n))Co.has(Io(o))||(s[o]=kt(i,e+1));return s}function Mo(t){if(!t)return new Date().toISOString();let e=new Date(t);return Number.isNaN(e.getTime())?new Date().toISOString():e.toISOString()}function G(t){return t?.trim()||void 0}function dn(t,e={}){let n={...t.provenance??{}},r=G(t.source)??G(e.source)??G(n.source);return{...t,timestamp:Mo(t.timestamp),source:r,turnId:G(t.turnId)??G(e.turnId),cwd:G(t.cwd)??G(e.cwd),data:kt(t.data??{}),provenance:n}}var _o=12e4,$o=80,Ko=2e3;function Fo(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var Oe=class{constructor(e,n={}){this.identity=e;this.eventContext=n;Oo(e.localDirectory,{recursive:!0}),this.eventsFile=bt(e.localDirectory,"events.jsonl"),this.stateFile=bt(e.localDirectory,"state.json"),this.lockFile=bt(e.localDirectory,"journal.lock")}identity;eventContext;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 an(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){O(this.stateFile,e)}acquireLock(){for(let e=0;e<$o;e+=1)try{return vt(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-fn(this.lockFile).mtimeMs>_o){pn(this.lockFile,{force:!0});continue}}catch{}Fo(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{wt(n),pn(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 d of e){let p=dn(d,this.eventContext),l=p.timestamp??new Date().toISOString(),g=p.data??{},S=p.provenance?.rawDigest??w(on(g)),y=p.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,p.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,p.type,l,S].join("|"),h=w(y).slice(0,32);if(r.has(h))continue;s+=1;let k={version:1,id:h,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,sessionId:this.identity.nativeSessionId,type:p.type,timestamp:l,source:p.source??p.provenance?.source??this.identity.agent,data:g,provenance:{...p.provenance,rawDigest:S}};p.role!==void 0&&(k.role=p.role),p.turnId!==void 0&&(k.turnId=p.turnId),p.cwd!==void 0&&(k.cwd=p.cwd),p.sourceEventId!==void 0&&(k.sourceEventId=p.sourceEventId),p.sourceSequence!==void 0&&(k.sourceSequence=p.sourceSequence),o.push(k),r.add(h)}if(o.length===0)return[];let i=o.map(d=>JSON.stringify(d)).join(`
|
|
10
10
|
`)+`
|
|
11
11
|
`,a=vt(this.eventsFile,"a",384);try{No(a,i,null,"utf8"),To(a)}finally{wt(a)}let c=o[o.length-1],u="active";c.type==="session_end"||c.type==="session_idle"?u="idle":c.type==="error"&&(u="error");let f=Array.from(r).slice(-Ko);return this.saveStateUnsafe({...n,status:u,updatedAt:c.timestamp,lastLocalEventAt:c.timestamp,lastSequence:c.sequence,recentEventIds:f}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Eo(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=fn(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=vt(this.eventsFile,"r");try{Ro(i,o,0,s,r)}finally{wt(i)}return{events:o.toString("utf8").split(`
|
|
12
12
|
`).filter(Boolean).map(u=>JSON.parse(u)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe(),s=new Date().toISOString();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),lastRemoteAt:s,updatedAt:s})})}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 Ia,existsSync as Pa,openSync as Ma,readSync as Ea,statSync as Ta}from"node:fs";function mn(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 Sn=[/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],Wo=[/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],Lo=[/\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],Do=[/\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],zo=[/đã 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],gn=[/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],qo=[/\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],Bo=[/đườ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],Vo=[/\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],yn=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Jo=new Set(["payload","data","content","message","messages","parts","summary"]);function R(t,e){return e.some(n=>n.test(t))}function kn(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Ho(t){return kn(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Go(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 xt(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||yn.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))xt(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(yn.has(s)||Jo.has(s))&&xt(o,s,n,r+1)}}function Uo(t){let e=[];xt(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=kn(o);if(Go(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function hn(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Yo(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&&R(t,Sn)?{kind:"rule",confidence:.98}:r&&R(t,Wo)?{kind:"rule",confidence:.92}:R(t,Lo)?{kind:R(t,gn)?"architecture":"decision",confidence:r?.93:.86}:r&&R(t,Do)?{kind:"todo",confidence:.87}:R(t,gn)&&R(t,qo)?{kind:"architecture",confidence:r?.88:.82}:s&&R(t,zo)?{kind:"fix",confidence:.8}:r&&R(t,Bo)&&R(t,Vo)?{kind:"context",confidence:.79}:null}function Xo(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Qo(t,e,n){return t==="rule"&&R(n,Sn)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":mn(e,n)}function wn(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,a=hn(o);i&&a&&s.set(i,a)}for(let o of e){let i=hn(o),a=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&a&&(i=s.get(a)??"");for(let c of Uo(o)){let u=Yo(c,i,o);if(!u||u.confidence<.75)continue;let f=Xo(u.kind),d=Ho(c),p=w([t.projectId,u.kind,d].join("|"));if(r.has(p))continue;r.add(p);let l=o.provenance.sourcePath?[o.provenance.sourcePath]:[],g=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:p,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:u.kind,type:f,content:c,confidence:u.confidence,importance:Qo(u.kind,f,c),tags:[f],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:g,sourcePaths:l,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}import{createHash as Zo}from"node:crypto";var ei=["project-knowledge","implementation","continuation","session-context"],ti={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function jt(t){return Zo("sha256").update(t).digest("hex")}function Re(t,e){return`${t}:${jt(e).slice(0,24)}`}function ni(t){try{return jt(JSON.stringify(t))}catch{return jt(String(t))}}function U(t){let e=new Set,n=[];for(let r of t){let s=r?.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function bn(t,e=420){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:`${n.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`}function ri(t){return t==="rule"||t==="architecture"?"project-knowledge":t==="decision"||t==="fix"?"implementation":t==="todo"?"continuation":"session-context"}function vn(t){return t.length===0?0:t.reduce((e,n)=>e+n,0)/t.length}function si(t){return t.slice().sort((e,n)=>n.importanceScore-e.importanceScore||n.confidence-e.confidence||e.id.localeCompare(n.id)).slice(0,5).map(e=>bn(e.content)).join(" | ")}function oi(t){return t.slice().sort((e,n)=>n.importanceScore-e.importanceScore||n.confidence-e.confidence||e.id.localeCompare(n.id)).slice(0,6).map(e=>bn(e.content)).join(`
|
|
@@ -33,7 +33,7 @@ ${g.map(h=>`- \`${h}\``).join(`
|
|
|
33
33
|
`)}`);let y=S.join(`
|
|
34
34
|
|
|
35
35
|
`).slice(0,Tt);if(y.length<20)continue;n.push({sourceKey:`skill:${c}`,sourceType:"skill",title:f,summary:d,content:y,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function Et(t){let e=new Date().toISOString();return{schema:tr,version:1,projectId:t,entries:[],createdAt:e,updatedAt:e}}async function Qi(t,e){let n=await t.getText(er);if(!n)return Et(e);try{let r=JSON.parse(n);return r.schema!==tr||r.version!==1||r.projectId!==e||!Array.isArray(r.entries)?Et(e):r}catch{return Et(e)}}async function Zi(t,e){await t.put(er,JSON.stringify(e,null,2),"application/json")}function ea(t){return`toolnet-auto-${ye(t).slice(0,12)}`}function ta(t){let e=Q(t.title).slice(0,72),n=ye(t.sourceKey).slice(0,10);return Q(`auto-${t.sourceType}-${e}-${n}`)}function na(t){return[`> Auto-generated by ToolNet Knowledge Automation from ${t.sourceType==="skill"?"reusable Skill Memory":t.sourceType==="scene"?"semantic memory scene":"durable memory"}.`,"",t.content].join(`
|
|
36
|
-
`).slice(0,Tt)}function ra(t){return ye({sourceType:t.sourceType,title:t.title,summary:t.summary,content:t.content,tags:t.tags})}function sa(t,e){return t.tags.includes(e)}async function rr(t){let e=Ui(t.hierarchy),n=Xi(t.project.rootPath),r=new Map;for(let l of[...e,...n.candidates])r.set(l.sourceKey,l);let s=[...r.values()].sort((l,g)=>l.sourceKey.localeCompare(g.sourceKey)),o={schema:"toolnet.wiki-automation-result.v1",scanned:e.length+n.candidates.length,eligible:s.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new We(new Le(t.storage,t.project));await i.initialize();let a=new ze(new De(t.storage,t.project));await a.initialize();let c=await Qi(t.storage,t.project.id),u=await i.listPages(),f=new Map(u.map(l=>[l.slug,l])),d=new Map(c.entries.map(l=>[l.sourceKey,l]));for(let l of s)try{let g=ea(l.sourceKey),S=ra(l),y=d.get(l.sourceKey),h=y?.slug??ta(l),k=f.get(h);if(k&&!sa(k,g)){o.skipped+=1;continue}let
|
|
36
|
+
`).slice(0,Tt)}function ra(t){return ye({sourceType:t.sourceType,title:t.title,summary:t.summary,content:t.content,tags:t.tags})}function sa(t,e){return t.tags.includes(e)}async function rr(t){let e=Ui(t.hierarchy),n=Xi(t.project.rootPath),r=new Map;for(let l of[...e,...n.candidates])r.set(l.sourceKey,l);let s=[...r.values()].sort((l,g)=>l.sourceKey.localeCompare(g.sourceKey)),o={schema:"toolnet.wiki-automation-result.v1",scanned:e.length+n.candidates.length,eligible:s.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new We(new Le(t.storage,t.project));await i.initialize();let a=new ze(new De(t.storage,t.project));await a.initialize();let c=await Qi(t.storage,t.project.id),u=await i.listPages(),f=new Map(u.map(l=>[l.slug,l])),d=new Map(c.entries.map(l=>[l.sourceKey,l]));for(let l of s)try{let g=ea(l.sourceKey),S=ra(l),y=d.get(l.sourceKey),h=y?.slug??ta(l),k=f.get(h);if(k&&!sa(k,g)){o.skipped+=1;continue}let M=he([...l.tags,g]),E=na(l),P=await a.gate({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,marker:g,digest:S,title:l.title,...l.summary?{summary:l.summary}:{},content:E,tags:M},[...f.values()]);if(!P.allowed){P.mode==="pending-review"?o.reviewPending+=1:o.skipped+=1;continue}P.mode==="auto-approved"?o.autoApproved+=1:P.mode==="review-approved"&&(o.reviewApproved+=1),k?y?.digest!==S?(k=await i.updatePage(h,{title:l.title,summary:l.summary??"",content:E,tags:M}),f.set(k.slug,k),o.updated+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"updated"})):(o.unchanged+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,action:"unchanged"})):(k=await i.createPage({slug:h,title:l.title,summary:l.summary,content:E,tags:M}),f.set(k.slug,k),o.created+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"created"}));let T=new Date().toISOString(),x={sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,digest:S,marker:g,updatedAt:T},v=c.entries.findIndex(L=>L.sourceKey===l.sourceKey);v>=0?c.entries[v]=x:c.entries.push(x),d.set(l.sourceKey,x),await a.markApplied(l.sourceKey,S)}catch(g){if(g instanceof C&&g.statusCode===409){o.skipped+=1;continue}o.failed+=1}let p=new Date().toISOString();return c.updatedAt=p,c.lastRunAt=p,c.entries.sort((l,g)=>l.sourceKey.localeCompare(g.sourceKey)),await Zi(t.storage,c),o}import{createHash as oa}from"node:crypto";import{chmodSync as or,existsSync as ia,mkdirSync as aa,readFileSync as lf,readdirSync as df,renameSync as ca,statSync as pf,writeFileSync as ua}from"node:fs";import{join as ir}from"node:path";var la="toolnet.skill-memory.v1",sr=5,da=16,pa=24,fa=32;function ma(t){return oa("sha256").update(t).digest("hex")}function ke(t,e=Number.MAX_SAFE_INTEGER){let n=new Set,r=[];for(let s of t){let o=s.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=e))break}return r}function Ot(t,e=360){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function ga(t){return t.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/giu,"Bearer [REDACTED]").replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu,"[REDACTED]").replace(/\b(api[_-]?key|token|password|passwd|secret)\b(\s*[:=]\s*)(["']?)[^\s"'`]+/giu,"$1$2[REDACTED]")}function z(t,e=360){return t&&Ot(ga(t),e)||void 0}function we(t,e){for(let n of e){let r=t[n];if(typeof r=="string"&&r.trim())return r}}function ar(t,e){for(let n of e){let r=t[n];if(typeof r=="number"&&Number.isFinite(r))return r;if(typeof r=="string"&&r.trim()&&Number.isFinite(Number(r)))return Number(r)}}function cr(t,e){for(let n of e){let r=t[n];if(typeof r=="boolean")return r;if(typeof r=="string"){let s=r.trim().toLowerCase();if(["true","yes","pass","passed","success","succeeded","ok"].includes(s))return!0;if(["false","no","fail","failed","error"].includes(s))return!1}}}function ur(t){let e=t.data??{};if(cr(e,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=ar(e,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let s=we(e,["status","result","outcome"]);return!!(s&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(s))}function Se(t){let e=t.data??{};if(ur(t))return!1;if(cr(e,["passed","pass","success","succeeded","ok"])===!0||ar(e,["exitCode","exit_code","code","statusCode"])===0)return!0;let s=we(e,["status","result","outcome"]);return s&&/\b(pass(?:ed)?|success(?:ful)?|succeeded|ok|green|complete(?:d)?)\b/iu.test(s)?!0:t.type==="commit"||t.type==="deploy"}function lr(t){let e=t.data??{},n=we(e,["path","file","filePath","filename","target"]);if(n)return z(n,260);let r=t.provenance?.files;return z(r?.[0],260)}function Rt(t){return z(we(t.data??{},["command","cmd","script"]),420)}function ne(t){return z(we(t.data??{},["name","test","suite","title","message","text","result","status"]),300)}function ya(t){let e=[];for(let n of[...t].sort((r,s)=>r.sequence-s.sequence))if(Se(n)){if(n.type==="test"){let r=ne(n)??Rt(n)??"Tests passed";e.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=ne(n);e.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=ne(n);e.push(r?`Deploy: ${r}`:"Deployment completed")}}return ke(e,10)}function ha(t,e){let n=[];for(let r of[...t].sort((s,o)=>s.sequence-o.sequence))switch(r.type){case"file_write":case"file_edit":{let s=lr(r);s&&n.push(`Update ${s}`);break}case"command":{if(ur(r))break;let s=Rt(r);s&&n.push(`Run: ${s}`);break}case"test":{if(!Se(r))break;let s=ne(r)??Rt(r)??"project tests";n.push(`Verify: ${s}`);break}case"commit":{if(!Se(r))break;let s=ne(r);n.push(s?`Commit: ${s}`:"Commit verified changes");break}case"deploy":{if(!Se(r))break;let s=ne(r);n.push(s?`Deploy: ${s}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of e.files.slice(0,8)){let s=z(r,260);s&&n.push(`Update ${s}`)}return ke(n,da)}function Sa(t,e){let n=[...e.files];for(let r of t){let s=lr(r);s&&n.push(s);for(let o of r.provenance?.files??[]){let i=z(o,260);i&&n.push(i)}}return ke(n,pa)}function ka(t){return ke(t.filter(e=>["file_write","file_edit","command","test","commit","deploy"].includes(e.type)).map(e=>e.id),fa)}function wa(t){return t.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function dr(t,e,n){if(e.length===0)return[];let r=ya(e),s=ke(n.completed.map(g=>z(g,280)??""),sr);if(!(s.length>0||e.some(g=>["test","commit","deploy"].includes(g.type)&&Se(g))))return[];let i=z(n.task,280)??z(n.nextActions[0],280),a=s.length>0?s:i?[i]:[];if(a.length===0)return[];let c=ha(e,n);if(c.length===0)return[];let u=Sa(e,n),f=ka(e),d=Math.min(...e.map(g=>g.sequence)),p=Math.max(...e.map(g=>g.sequence)),l=wa(e);return a.slice(0,sr).map(g=>{let S=[`Reusable procedure learned from successful task: ${g}.`,u.length>0?`Files: ${u.slice(0,6).join(", ")}.`:"",r.length>0?`Verification: ${r.slice(0,4).join("; ")}.`:""].filter(Boolean),y=JSON.stringify({projectId:t.projectId,task:g,steps:c,verification:r,files:u}),h=ma(y);return{schema:la,version:1,id:`skill-${h.slice(0,24)}`,fingerprint:h,projectId:t.projectId,title:Ot(`SOP: ${g}`,180),task:g,summary:Ot(S.join(" "),900),steps:c,verification:r,files:u,source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:d,lastSequence:p,eventIds:f},createdAt:l}})}function va(t){return ir(t.rootPath,".toolnet","memory","skills")}function ba(t){let e=va(t);return aa(e,{recursive:!0,mode:448}),or(e,448),e}function pr(t,e){if(e.length===0)return{written:0,deduped:0,files:[]};let n=ba(t),r=0,s=0,o=[];for(let i of e){if(i.projectId!==t.id)throw new Error(`Skill project mismatch: ${i.projectId} != ${t.id}`);let a=ir(n,`${i.id}.json`);if(o.push(a),ia(a)){s+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;ua(c,JSON.stringify(i,null,2)+`
|
|
37
37
|
`,{encoding:"utf8",mode:384}),ca(c,a),or(a,384),r+=1}return{written:r,deduped:s,files:o}}function fr(t){return String(t).padStart(12,"0")}function xa(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var Be=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},a=JSON.stringify(i,null,2)+`
|
|
38
38
|
`,c=w(r.map(f=>f.fingerprint).sort().join("|")).slice(0,16),u=[xa(e),"batches",`${fr(s)}-${fr(o)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,a,"application/json"),u}};import{createHash as ja}from"node:crypto";function mr(t){return String(t).padStart(12,"0")}function Ca(t){return ja("sha256").update(t).digest("hex")}function Aa(t){return t.remotePrefix.replace("/sessions/","/memory/hierarchy/")}var Ve=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(n.length===0||r.facts.length===0)return null;let s=Math.min(...n.map(u=>u.sequence)),o=Math.max(...n.map(u=>u.sequence)),i={schema:"toolnet.memory-hierarchy-batch.v1",version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,hierarchy:r},a=Ca([...r.facts.map(u=>u.id),...r.knowledge.map(u=>u.id)].sort().join("|")).slice(0,16),c=[Aa(e),"batches",`${mr(s)}-${mr(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,`${JSON.stringify(i,null,2)}
|
|
39
39
|
`,"application/json"),c}};function Oa(t,e){if(!Pa(t))return{events:[],nextOffset:e};let n=Ta(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=Ma(t,"r");try{Ea(i,o,0,s,r)}finally{Ia(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
@@ -41,14 +41,14 @@ ${g.map(h=>`- \`${h}\``).join(`
|
|
|
41
41
|
`).filter(Boolean).flatMap(d=>{try{return[JSON.parse(d)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Je=class{constructor(e){this.options=e;this.journal=new Be(e.storage),this.hierarchyJournal=new Ve(e.storage)}options;journal;hierarchyJournal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Oa(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Ke(this.options.identity,s.events),i=o.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,s.events,i));let c=!1;o.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,s.events,o.hierarchy));let u=dr(this.options.identity,s.events,o.state),f=pr(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",o.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",o.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",o.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",o.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",o.hierarchy.stats.knowledge),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.journal_written",c?1:0),this.options.wal.setSourceCursor("memory.skill.assets",u.length),this.options.wal.setSourceCursor("memory.skill.written",f.written),this.options.wal.setSourceCursor("memory.skill.deduped",f.deduped);try{let d=$n(this.options.project.rootPath,s.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",d.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",d.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",d.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",d.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let d=await rr({project:this.options.project,storage:this.options.storage,hierarchy:o.hierarchy});this.options.wal.setSourceCursor("memory.wiki_automation.scanned",d.scanned),this.options.wal.setSourceCursor("memory.wiki_automation.eligible",d.eligible),this.options.wal.setSourceCursor("memory.wiki_automation.created",d.created),this.options.wal.setSourceCursor("memory.wiki_automation.updated",d.updated),this.options.wal.setSourceCursor("memory.wiki_automation.unchanged",d.unchanged),this.options.wal.setSourceCursor("memory.wiki_automation.skipped",d.skipped),this.options.wal.setSourceCursor("memory.wiki_automation.failed",d.failed),this.options.wal.setSourceCursor("memory.wiki_automation.review_pending",d.reviewPending),this.options.wal.setSourceCursor("memory.wiki_automation.auto_approved",d.autoApproved),this.options.wal.setSourceCursor("memory.wiki_automation.review_approved",d.reviewApproved)}catch{this.options.wal.setSourceCursor("memory.wiki_automation.failed",1)}return this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:i.length,journalWritten:a,nextOffset:s.nextOffset}}};import{closeSync as Ya,existsSync as Xa,openSync as Qa,readSync as Za,statSync as ec}from"node:fs";function gr(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function be(t){return t.toLowerCase().replace(/[^a-z0-9]/gu,"")}function ve(t,e,n=0){if(n>8)return;if(Array.isArray(t)){for(let s of t.slice(0,50))ve(s,e,n+1);return}let r=gr(t);if(r)for(let[s,o]of Object.entries(r))e(s,o,r),ve(o,e,n+1)}function re(t,e){let n=[];return ve(t,(r,s)=>{e.has(be(r))&&typeof s=="string"&&s.trim()&&n.push(s.trim())}),n}function Ra(t){let e=t.trim();if(!e.startsWith("{"))return null;try{return gr(JSON.parse(e))}catch{return null}}function Na(t){let e=t.data;for(let r of["tool","toolName","tool_name"]){let s=e[r];if(typeof s=="string"&&s.trim())return s.trim().toLowerCase()}let n="";return ve(e,(r,s,o)=>{if(n)return;let i=be(r);if(["tool","toolname"].includes(i)&&typeof s=="string"){n=s.trim().toLowerCase();return}if(i!=="name"||typeof s!="string")return;let a=typeof o.type=="string"?o.type.toLowerCase():"";(a.includes("tool")||a.includes("function")||a.includes("command"))&&(n=s.trim().toLowerCase())}),n}function _a(t){let e=re(t.data,new Set(["command","cmd","script"])),n=re(t.data,new Set(["arguments","args"]));for(let r of n){let s=Ra(r);if(s)for(let o of re(s,new Set(["command","cmd","script"])))e.push(o)}return Array.from(new Set(e.map(r=>r.trim()).filter(Boolean)))}function $a(t){let e=re(t.data,new Set(["filepath","file_path","filename","file","path","target"].map(be)));return Array.from(new Set(e.map(n=>n.trim()).filter(n=>n.length>0&&n.length<1e3&&!n.includes(`
|
|
42
42
|
`))))}function Ka(t,e){return t.type==="file_edit"||t.type==="file_write"?"modified":/\b(delete|remove|unlink)\b/iu.test(e)?"deleted":/\b(create|add[_-]?file|new[_-]?file)\b/iu.test(e)?"created":/\b(edit|write|patch|apply[_-]?patch|replace|update[_-]?file)\b/iu.test(e)?"modified":null}function Fa(t){let e=re(t.data,new Set(["patch","diff","arguments","input"].map(be))),n=[];for(let r of e){let s=[{regex:/^\*\*\* Update File:\s*(.+)$/gimu,action:"modified"},{regex:/^\*\*\* Add File:\s*(.+)$/gimu,action:"created"},{regex:/^\*\*\* Delete File:\s*(.+)$/gimu,action:"deleted"}];for(let o of s)for(let i of r.matchAll(o.regex)){let a=i[1]?.trim();a&&n.push({kind:"file",text:a,fileAction:o.action,confidence:.99})}}return n}function Wa(t){let e=t.toLowerCase();return/\b(typecheck|type-check)\b/u.test(e)||/\btsc\b[\s\S]*--noemit\b/u.test(e)?"typecheck":/\b(eslint|lint)\b/u.test(e)?"lint":/\b(vitest|jest|pytest)\b/u.test(e)||/\bgo\s+test\b/u.test(e)||/\bcargo\s+test\b/u.test(e)||/\b(npm|pnpm|yarn)\s+(run\s+)?test\b/u.test(e)?"test":/\b(npm|pnpm|yarn)\s+(run\s+)?build\b/u.test(e)||/\bcargo\s+build\b/u.test(e)||/\bgo\s+build\b/u.test(e)||/\btsc\b/u.test(e)?"build":null}function La(t){let e=null;return ve(t,(n,r)=>{if(e===null&&["exitcode","code"].includes(be(n))){if(typeof r=="number"&&Number.isFinite(r)){e=r;return}if(typeof r=="string"){let s=Number(r);Number.isFinite(s)&&(e=s)}}}),e}function Da(t){return re(t,new Set(["status","state","result","output","outputsummary","message","text"]))}function za(t){let e=La(t.data);if(e!==null)return e===0?"passed":"failed";let n=Da(t.data).join(`
|
|
43
43
|
`).toLowerCase();return/\b(error|failed|failure|failing)\b/u.test(n)&&!/\b0\s+failed\b/u.test(n)?"failed":/\b(success|successful|completed|passed|green)\b/u.test(n)||/\b\d+\s+passed\b/u.test(n)?"passed":/\b(running|started|in[_ -]?progress)\b/u.test(n)?"running":"unknown"}function qa(t){let e=[],n=new Set;for(let r of t){let s=[r.kind,r.fileAction??"",r.checkKind??"",r.checkStatus??"",r.text].join("|");n.has(s)||(n.add(s),e.push(r))}return e}function yr(t){let e=[],n=Na(t),r=Ka(t,n);if(r)for(let s of $a(t))e.push({kind:"file",text:s,fileAction:r,confidence:t.type==="file_edit"||t.type==="file_write"?1:.96});e.push(...Fa(t));for(let s of _a(t)){e.push({kind:"command",text:s,confidence:.98});let o=Wa(s);o&&e.push({kind:"test",text:s,checkKind:o,checkStatus:za(t),confidence:.98})}return qa(e)}var Ba=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function ee(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Sr(t){return ee(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function Z(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))Z(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Ba.has(r)||["data","payload","parts","messages"].includes(r))&&Z(s,e,n+1)}}function He(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 hr(t){let e=ee(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 A(t,e,n,r,s={}){let o=ee(r),i=s.key??Sr(o);return{version:1,id:w([t.projectId,n,i,e.id,o,s.status??"",s.fileAction??"",s.checkKind??"",s.checkStatus??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,fileAction:s.fileAction,checkKind:s.checkKind,checkStatus:s.checkStatus,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 Va(t,e,n){let r=ee(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(A(t,e,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&s.push(A(t,e,"plan",a[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,u;for(;!o&&(u=c.exec(r));){let p=Number(u[1]),l=ee(u[2]??""),g=l&&!hr(l)?`Phase ${p} - ${l}`:`Phase ${p}`;s.push(A(t,e,"phase",g,{key:`phase:${p}`,order:p,status:He(r),confidence:.93}))}let f=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);f?.[2]&&s.push(A(t,e,"task",f[2],{status:f[1].trim()?"completed":He(f[2]),confidence:.96}));let d=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(d?.[2]){let p=d[1]?Number(d[1]):void 0,l=ee(d[2]),g=hr(l);s.push(A(t,e,"task",g&&p!==void 0?`TODO ${p}`:l,{key:p!==void 0?`task:${p}`:Sr(l),order:p,status:He(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 p=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");p&&s.push(A(t,e,"next_action",p,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(A(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(A(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(A(t,e,"decision",r,{confidence:.9})),r.length<=300&&/^(?:đang\s+(?:sửa|cập nhật|triển khai|xử lý|làm|refactor|fix)|(?:i(?:'m| am)\s+)?(?:working on|implementing|fixing|refactoring|updating|editing)\b)/iu.test(r)&&s.push(A(t,e,"activity",r,{confidence:.86})),s}function se(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==="user_prompt"||i.role==="user"){let c=[];Z(i.data,c);let u=c.map(f=>ee(f)).find(f=>f.length>=8&&f.length<=1200&&!/^\[?toolnet\b/iu.test(f));u&&s(A(t,i,"request",u,{confidence:.96}))}for(let c of yr(i))s(A(t,i,c.kind,c.text,{fileAction:c.fileAction,checkKind:c.checkKind,checkStatus:c.checkStatus,status:c.kind==="test"?c.checkStatus==="passed"?"completed":c.checkStatus==="failed"?"blocked":c.checkStatus==="running"?"in_progress":"pending":void 0,confidence:c.confidence}));if(i.type==="decision"){let c=[];Z(i.data,c);for(let u of c)s(A(t,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];Z(i.data,c);for(let u of c)s(A(t,i,"task",u,{status:He(u),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let u=i.data[c];typeof u=="string"&&u&&s(A(t,i,"file",u,{fileAction:"modified",confidence:1}))}if(i.type==="test"){let c=[];Z(i.data,c);for(let u of c)s(A(t,i,"test",u,{confidence:1}))}let a=[];Z(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let f of Va(t,i,u))s(f)}let o=e[e.length-1];return s(A(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function kr(t){return String(t).padStart(12,"0")}var Ge=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.sequence)),s=Math.max(...n.map(u=>u.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)+`
|
|
44
|
-
`,a=w(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${kr(r)}-${kr(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as wr}from"node:path";import{mkdirSync as Ja}from"node:fs";function br(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function K(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=br(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Ha(t,e=20){let n=new Map;for(let r of t){let s=`${r.kind}|${br(r.command)}`;n.delete(s),n.set(s,r)}return Array.from(n.values()).slice(-e)}function Ga(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 vr(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&&Ga(e)?t.title:e.text;return{id:t?.id??w(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 Ua(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,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}async function Ue(t,e){let r=(await Ua(t,e)).flatMap(m=>m.observations).sort((m,b)=>{let q=m.occurredAt.localeCompare(b.occurredAt);if(q!==0)return q;let Jt=m.sequence-b.sequence;return Jt!==0?Jt:m.id.localeCompare(b.id)}),s=new Map,o=new Map,i,a,c,u,f,d=[],p=[],l=[],g=[],S=[],y=new Map,h=[],k=[],
|
|
44
|
+
`,a=w(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${kr(r)}-${kr(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as wr}from"node:path";import{mkdirSync as Ja}from"node:fs";function br(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function K(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=br(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Ha(t,e=20){let n=new Map;for(let r of t){let s=`${r.kind}|${br(r.command)}`;n.delete(s),n.set(s,r)}return Array.from(n.values()).slice(-e)}function Ga(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 vr(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&&Ga(e)?t.title:e.text;return{id:t?.id??w(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 Ua(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,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}async function Ue(t,e){let r=(await Ua(t,e)).flatMap(m=>m.observations).sort((m,b)=>{let q=m.occurredAt.localeCompare(b.occurredAt);if(q!==0)return q;let Jt=m.sequence-b.sequence;return Jt!==0?Jt:m.id.localeCompare(b.id)}),s=new Map,o=new Map,i,a,c,u,f,d=[],p=[],l=[],g=[],S=[],y=new Map,h=[],k=[],M=[],E=[],P=[],T=[];for(let m of r)switch(m.kind){case"request":i=m.text;break;case"activity":a=m.text;break;case"goal":c=m.text;break;case"plan":u=m.text;break;case"phase":s.set(m.key,vr(s.get(m.key),m));break;case"task":o.set(m.key,vr(o.get(m.key),m));break;case"decision":d.push(m.text);break;case"blocker":p.push(m.text);break;case"warning":l.push(m.text);break;case"next_action":g.push(m.text);break;case"file":{S.push(m.text);let b=m.fileAction??"active";y.delete(m.text),y.set(m.text,b),b==="modified"?h.push(m.text):b==="created"?k.push(m.text):b==="deleted"&&M.push(m.text);break}case"command":E.push(m.text);break;case"test":P.push(m.text),m.checkKind&&T.push({kind:m.checkKind,command:m.text,status:m.checkStatus??"unknown",updatedAt:m.occurredAt,agent:m.agent,nativeSessionId:m.nativeSessionId});break;case"session":f={agent:m.agent,nativeSessionId:m.nativeSessionId,sessionKey:m.sessionKey,updatedAt:m.occurredAt};break}let x=Array.from(s.values()).sort((m,b)=>(m.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),v=Array.from(o.values()).sort((m,b)=>(m.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),L=x.find(m=>m.status==="in_progress")??x.find(m=>m.status==="blocked")??x.find(m=>m.status==="pending"),D=v.find(m=>m.status==="in_progress")??v.find(m=>m.status==="blocked")??v.find(m=>m.status==="pending"),ft=K([...g,...D?[D.title]:[],...!D&&L?[L.title]:[],...v.filter(m=>m.status==="pending").slice(0,5).map(m=>m.title)],8),mt=K([...p,...x.filter(m=>m.status==="blocked").map(m=>m.title),...v.filter(m=>m.status==="blocked").map(m=>m.title)],20),ie={version:1,projectId:t.id,projectName:t.name,currentRequest:i,currentActivity:a,goal:c,plan:u,phases:x,tasks:v,decisions:K(d,20),blockers:mt,warnings:K(l,20),nextActions:ft,filesTouched:K(S,30),activeFiles:Array.from(y.entries()).filter(([,m])=>m!=="deleted").map(([m])=>m).slice(-5),modifiedFiles:K(h,30),createdFiles:K(k,30),deletedFiles:K(M,30),commands:K(E,20),tests:K(P,20),checks:Ha(T,20),currentPhase:L,currentTask:D,progress:{phasesTotal:x.length,phasesCompleted:x.filter(m=>m.status==="completed").length,tasksTotal:v.length,tasksCompleted:v.filter(m=>m.status==="completed").length,blocked:x.filter(m=>m.status==="blocked").length+v.filter(m=>m.status==="blocked").length},lastSession:f,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},ae=wr(t.rootPath,".toolnet","work");return Ja(ae,{recursive:!0}),O(wr(ae,"current.json"),ie),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(ie,null,2)+`
|
|
45
45
|
`,"application/json"),ie}async function Ye(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 tc(t,e){if(!Xa(t))return{events:[],nextOffset:e};let n=ec(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=Qa(t,"r");try{Za(i,o,0,s,r)}finally{Ya(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
46
46
|
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
47
|
-
`).filter(Boolean).flatMap(d=>{try{return[JSON.parse(d)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Xe=class{constructor(e){this.options=e;this.journal=new Ge(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=tc(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=se(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 lc,existsSync as dc,openSync as pc,readSync as fc,statSync as mc}from"node:fs";var nc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function oe(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Nt(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))Nt(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(nc.has(r)||["data","payload","parts","messages"].includes(r))&&Nt(s,e,n+1)}}function N(t,e,n,r,s,o=.95){let i=oe(r);return{version:1,id:w([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 F(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 oe(t.slice(r.length+1))}return null}function rc(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function sc(t){return oe(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function xr(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=[];Nt(o.data,i);for(let a of i){let c={type:"project"},u=null;for(let f of a.split(/\r?\n/u)){let d=oe(f);if(!d){u=null;continue}let p=d.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(p){let v=Number(p[1]);c={type:"phase",key:`phase:${v}`,order:v,title:oe(p[2]??"")},u=null;continue}let l=d.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let v=Number(l[1]);c={type:"task",key:`task:${v}`,order:v,title:oe(l[2]??"")},u=null;continue}let g=F(d,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(g){s(N(t,o,"mission",g,{type:"project"},.99)),u=null;continue}let S=F(d,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(S){s(N(t,o,c.type==="phase"?"phase_objective":"objective",S,c,.98)),u=null;continue}let y=F(d,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(N(t,o,c.type==="phase"?"phase_why":"why",y,c,.98)),u=null;continue}let h=F(d,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){s(N(t,o,"desired_outcome",h,{type:"project"},.98)),u=null;continue}let k=F(d,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(k){s(N(t,o,"plan_rationale",k,{type:"project"},.98)),u=null;continue}let
|
|
47
|
+
`).filter(Boolean).flatMap(d=>{try{return[JSON.parse(d)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Xe=class{constructor(e){this.options=e;this.journal=new Ge(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=tc(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=se(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 lc,existsSync as dc,openSync as pc,readSync as fc,statSync as mc}from"node:fs";var nc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function oe(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Nt(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))Nt(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(nc.has(r)||["data","payload","parts","messages"].includes(r))&&Nt(s,e,n+1)}}function N(t,e,n,r,s,o=.95){let i=oe(r);return{version:1,id:w([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 F(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 oe(t.slice(r.length+1))}return null}function rc(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function sc(t){return oe(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function xr(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=[];Nt(o.data,i);for(let a of i){let c={type:"project"},u=null;for(let f of a.split(/\r?\n/u)){let d=oe(f);if(!d){u=null;continue}let p=d.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(p){let v=Number(p[1]);c={type:"phase",key:`phase:${v}`,order:v,title:oe(p[2]??"")},u=null;continue}let l=d.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let v=Number(l[1]);c={type:"task",key:`task:${v}`,order:v,title:oe(l[2]??"")},u=null;continue}let g=F(d,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(g){s(N(t,o,"mission",g,{type:"project"},.99)),u=null;continue}let S=F(d,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(S){s(N(t,o,c.type==="phase"?"phase_objective":"objective",S,c,.98)),u=null;continue}let y=F(d,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(N(t,o,c.type==="phase"?"phase_why":"why",y,c,.98)),u=null;continue}let h=F(d,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){s(N(t,o,"desired_outcome",h,{type:"project"},.98)),u=null;continue}let k=F(d,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(k){s(N(t,o,"plan_rationale",k,{type:"project"},.98)),u=null;continue}let M=F(d,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(M){s(N(t,o,"phase_deliverable",M,c,.97)),u=null;continue}let E=F(d,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(E){s(N(t,o,"acceptance_criterion",E,c,.98)),u="acceptance_criterion";continue}let P=F(d,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(P){s(N(t,o,"dependency",P,c,.97)),u="dependency";continue}let T=F(d,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(T){s(N(t,o,"open_question",T,c,.95)),u="open_question";continue}let x=F(d,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(x){s(N(t,o,"constraint",x,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(d)){u="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(d)){u="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(d)){u="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(d)){u="constraint";continue}if(u&&rc(f)){s(N(t,o,u,sc(f),c,.96));continue}u=null}}}return n}function jr(t){return String(t).padStart(12,"0")}var Qe=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.evidence.sequence)),s=Math.max(...n.map(c=>c.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=w(n.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${jr(r)}-${jr(s)}-${i}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,JSON.stringify(o,null,2)+`
|
|
48
48
|
`,"application/json"),a}};import{mkdirSync as oc}from"node:fs";import{join as Cr}from"node:path";function ic(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function ac(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 V(t,e){return ac(e,t)?e:t}function J(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 cc(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,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}function uc(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function Ar(t,e){let r=(await cc(t,e)).flatMap(S=>S.observations).sort((S,y)=>{let h=S.evidence.occurredAt.localeCompare(y.evidence.occurredAt);return h!==0?h:S.evidence.sessionKey===y.evidence.sessionKey?S.evidence.sequence-y.evidence.sequence:S.id.localeCompare(y.id)}),s,o,i,a,c,u=new Map,f=[],d=[],p=[];for(let S of r){let y=ic(S);if(S.scope==="phase"&&S.scopeKey){let h=u.get(S.scopeKey)??uc(S);switch(S.kind){case"phase_objective":h.objective=V(h.objective,y);break;case"phase_why":h.why=V(h.why,y);break;case"phase_deliverable":h.deliverable=V(h.deliverable,y);break;case"acceptance_criterion":h.acceptanceCriteria.push(y);break;case"dependency":h.dependencies.push(y);break;case"open_question":h.openQuestions.push(y);break;case"constraint":h.constraints.push(y);break;case"note":h.notes.push(y);break}u.set(h.key,h);continue}switch(S.kind){case"mission":s=V(s,y);break;case"objective":o=V(o,y);break;case"why":i=V(i,y);break;case"desired_outcome":a=V(a,y);break;case"plan_rationale":c=V(c,y);break;case"open_question":f.push(y);break;case"constraint":d.push(y);break;case"note":p.push(y);break}}for(let S of u.values())S.acceptanceCriteria=J(S.acceptanceCriteria,20),S.dependencies=J(S.dependencies,15),S.openQuestions=J(S.openQuestions,15),S.constraints=J(S.constraints,15),S.notes=J(S.notes,20);let l={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:a,planRationale:c,phases:Array.from(u.values()).sort((S,y)=>S.order-y.order),openQuestions:J(f,20),constraints:J(d,20),notes:J(p,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},g=Cr(t.rootPath,".toolnet","work");return oc(g,{recursive:!0}),O(Cr(g,"semantic-current.json"),l),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
|
|
49
49
|
`,"application/json"),l}async function Ir(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 gc(t,e){if(!dc(t))return{events:[],nextOffset:e};let n=mc(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=pc(t,"r");try{fc(o,s,0,s.length,r)}finally{lc(o)}let i=s.toString("utf8"),a=i.lastIndexOf(`
|
|
50
50
|
`);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
|
|
51
|
-
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var Ze=class{constructor(e){this.options=e;this.journal=new Qe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=gc(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=xr(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Ar(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{existsSync as
|
|
51
|
+
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var Ze=class{constructor(e){this.options=e;this.journal=new Qe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=gc(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=xr(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Ar(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{existsSync as Fc,mkdirSync as Wc}from"node:fs";import{join as $t}from"node:path";import{existsSync as Er,mkdirSync as yc,readFileSync as hc,statSync as Pr,writeFileSync as Sc}from"node:fs";import{dirname as kc,join as wc}from"node:path";var Mr=64*1024,vc=`# ToolNet Project Operating Manual
|
|
52
52
|
|
|
53
53
|
This file contains persistent instructions for AI agents working on this project.
|
|
54
54
|
|
|
@@ -92,50 +92,50 @@ Things an AI agent should always remember.
|
|
|
92
92
|
- [advisory] Prefer small focused files.
|
|
93
93
|
-->
|
|
94
94
|
`;function et(t){return wc(t.rootPath,".toolnet","PROJECT.md")}function bc(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function xc(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=bc(s[2]);if(!i)continue;let a=`${o}:${i.toLowerCase()}`;n.has(a)||(n.add(a),e.push({id:w(a).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function jc(t){let e=et(t);return Er(e)||(yc(kc(e),{recursive:!0}),Sc(e,vc,{encoding:"utf8",mode:384})),e}function tt(t,e=!1){let n=e?jc(t):et(t);if(!Er(n))return null;if(Pr(n).size>Mr)throw new Error(`PROJECT.md exceeds ${Mr} bytes`);let s=hc(n,"utf8");return{path:n,content:s,digest:w(s),rules:xc(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Pr(n).mtimeMs).toISOString()}}import{existsSync as Cc,mkdirSync as Ac,readFileSync as Ic,renameSync as Pc,writeFileSync as Mc}from"node:fs";import{dirname as Ec,join as Tc}from"node:path";function Oc(t,e){Ac(Ec(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;Mc(n,`${JSON.stringify(e,null,2)}
|
|
95
|
-
`,{encoding:"utf8",mode:384}),Pc(n,t)}function $r(t){return Tc(t.rootPath,".toolnet","work","current.json")}function _t(t){let e=$r(t);if(!Cc(e))return null;try{let n=JSON.parse(Ic(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function nt(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function _(t,e,n){let r=[],s=new Set;for(let o of[...t,...e].reverse()){let i=nt(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function Rc(t,e,n=20){let r=new Map;for(let s of[...t,...e]){let o=`${s.kind}|${nt(s.command)}`;r.delete(o),r.set(o,s)}return Array.from(r.values()).slice(-n)}function Nc(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 Tr(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&&Nc(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 Or(t){let e=new Map;for(let n of t){let r=n.order!==void 0?`order:${n.order}`:nt(n.title);e.set(r,n)}return e}function Rr(t){return t.order!==void 0?`order:${t.order}`:nt(t.key||t.text)}function Nr(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 _r(t){return t.find(e=>e.status==="in_progress")??t.find(e=>e.status==="blocked")??t.find(e=>e.status==="pending")}function rt(t,e){let n=_t(t),r=Or(n?.phases??[]),s=Or(n?.tasks??[]),o=n?.currentRequest,i=n?.currentActivity,a=n?.goal,c=n?.plan,u=n?.lastSession,f=[],d=[],p=[],l=[],g=[],S=[...n?.activeFiles??[]],y=[],h=[],k=[],
|
|
96
|
-
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function $c(t){return w(JSON.stringify(t))}function Fr(t){let{project:e,identity:n,state:r}=t,s=r.activeFiles?.at(-1)??r.filesTouched.at(-1),o=r.phases.filter(k=>k.status==="completed").map(k=>k.title),i=r.tasks.filter(k=>k.status==="completed").map(k=>k.title),a=r.phases.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),c=r.tasks.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),u=new Set(r.tasks.filter(k=>k.status==="completed").map(k=>k.title.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),f=
|
|
95
|
+
`,{encoding:"utf8",mode:384}),Pc(n,t)}function $r(t){return Tc(t.rootPath,".toolnet","work","current.json")}function _t(t){let e=$r(t);if(!Cc(e))return null;try{let n=JSON.parse(Ic(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function nt(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function _(t,e,n){let r=[],s=new Set;for(let o of[...t,...e].reverse()){let i=nt(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function Rc(t,e,n=20){let r=new Map;for(let s of[...t,...e]){let o=`${s.kind}|${nt(s.command)}`;r.delete(o),r.set(o,s)}return Array.from(r.values()).slice(-n)}function Nc(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 Tr(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&&Nc(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 Or(t){let e=new Map;for(let n of t){let r=n.order!==void 0?`order:${n.order}`:nt(n.title);e.set(r,n)}return e}function Rr(t){return t.order!==void 0?`order:${t.order}`:nt(t.key||t.text)}function Nr(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 _r(t){return t.find(e=>e.status==="in_progress")??t.find(e=>e.status==="blocked")??t.find(e=>e.status==="pending")}function rt(t,e){let n=_t(t),r=Or(n?.phases??[]),s=Or(n?.tasks??[]),o=n?.currentRequest,i=n?.currentActivity,a=n?.goal,c=n?.plan,u=n?.lastSession,f=[],d=[],p=[],l=[],g=[],S=[...n?.activeFiles??[]],y=[],h=[],k=[],M=[],E=[],P=[],T=[...e].sort((m,b)=>{let q=m.occurredAt.localeCompare(b.occurredAt);return q!==0?q:m.sequence-b.sequence});for(let m of T)switch(m.kind){case"request":o=m.text;break;case"activity":i=m.text;break;case"goal":a=m.text;break;case"plan":c=m.text;break;case"phase":{let b=Rr(m);r.set(b,Tr(r.get(b),m));break}case"task":{let b=Rr(m);s.set(b,Tr(s.get(b),m));break}case"decision":f.push(m.text);break;case"blocker":d.push(m.text);break;case"warning":p.push(m.text);break;case"next_action":l.push(m.text);break;case"file":{g.push(m.text);let b=m.fileAction??"active",q=S.indexOf(m.text);q>=0&&S.splice(q,1),b!=="deleted"&&S.push(m.text),b==="modified"?y.push(m.text):b==="created"?h.push(m.text):b==="deleted"&&k.push(m.text);break}case"command":M.push(m.text);break;case"test":E.push(m.text),m.checkKind&&P.push({kind:m.checkKind,command:m.text,status:m.checkStatus??"unknown",updatedAt:m.occurredAt,agent:m.agent,nativeSessionId:m.nativeSessionId});break;case"session":u={agent:m.agent,nativeSessionId:m.nativeSessionId,sessionKey:m.sessionKey,updatedAt:m.occurredAt};break}let x=Nr(r.values()),v=Nr(s.values()),L=_r(x),D=_r(v),ft=_(n?.nextActions??[],[...l,...D?[D.title]:[],...!D&&L?[L.title]:[],...v.filter(m=>m.status==="pending").slice(0,5).map(m=>m.title)],8),mt=_(n?.blockers??[],[...d,...x.filter(m=>m.status==="blocked").map(m=>m.title),...v.filter(m=>m.status==="blocked").map(m=>m.title)],20),ie=T.length>0?T[T.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),ae={version:1,projectId:t.id,projectName:t.name,currentRequest:o,currentActivity:i,goal:a,plan:c,phases:x,tasks:v,decisions:_(n?.decisions??[],f,20),blockers:mt,warnings:_(n?.warnings??[],p,20),nextActions:ft,filesTouched:_(n?.filesTouched??[],g,30),activeFiles:_([],S,5),modifiedFiles:_(n?.modifiedFiles??[],y,30),createdFiles:_(n?.createdFiles??[],h,30),deletedFiles:_(n?.deletedFiles??[],k,30),commands:_(n?.commands??[],M,20),tests:_(n?.tests??[],E,20),checks:Rc(n?.checks??[],P,20),currentPhase:L,currentTask:D,progress:{phasesTotal:x.length,phasesCompleted:x.filter(m=>m.status==="completed").length,tasksTotal:v.length,tasksCompleted:v.filter(m=>m.status==="completed").length,blocked:x.filter(m=>m.status==="blocked").length+v.filter(m=>m.status==="blocked").length},lastSession:u,updatedAt:ie};return Oc($r(t),ae),ae}function I(t,e){let n=new Set,r=[];for(let s of t){let o=s.replace(/\s+/g," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=e))break}return r}function Kr(t){if(t)return{id:t.id,title:t.title,status:t.status}}function _c(t,e=[]){let n=e.slice(-10);if(n.some(s=>s.status==="failed"))return"failing";if(n.some(s=>s.status==="passed"))return"passing";let r=t.slice(-10).join(`
|
|
96
|
+
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function $c(t){return w(JSON.stringify(t))}function Kc(t){let e=[];for(let n of t){if(!n)continue;let r=n.match(/https?:\/\/[^\s<>"'`)\]}]+/giu)??[];for(let s of r){let o=s.replace(/[.,;:!?]+$/gu,"").trim();o&&e.push(o)}}return I(e,30)}function Fr(t){let{project:e,identity:n,state:r}=t,s=r.activeFiles?.at(-1)??r.filesTouched.at(-1),o=r.phases.filter(k=>k.status==="completed").map(k=>k.title),i=r.tasks.filter(k=>k.status==="completed").map(k=>k.title),a=r.phases.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),c=r.tasks.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),u=new Set(r.tasks.filter(k=>k.status==="completed").map(k=>k.title.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),f=I(r.nextActions.filter(k=>!u.has(k.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),10),d=I([...c,...f],15),p=I(r.tests.slice().reverse(),10),l=I([...(r.activeFiles??[]).slice().reverse(),...r.filesTouched.slice().reverse()],20),g={schema:"toolnet.handoff.v2",version:2,project:{id:e.id,name:e.name},source:{agent:n.agent,nativeSessionId:n.nativeSessionId,sessionKey:n.sessionKey,sequence:t.sequence,reason:t.reason},capturedAt:t.capturedAt??new Date().toISOString(),goal:r.goal,request:r.currentRequest,activity:r.currentActivity,current:{phase:Kr(r.currentPhase),task:Kr(r.currentTask),file:s},completed:{phases:I(o,20),tasks:I(i,30)},remaining:{phases:I(a,20),tasks:I(c,30),todos:d},nextAction:f[0],blockers:I(r.blockers.slice().reverse(),10),decisions:I(r.decisions.slice().reverse(),10),files:{current:s,recent:l,active:I(r.activeFiles??[],10),modified:I(r.modifiedFiles??[],20),created:I(r.createdFiles??[],20),deleted:I(r.deletedFiles??[],20)},tests:{status:_c(r.tests,r.checks),recent:p,checks:(r.checks??[]).slice(-10).map(k=>({kind:k.kind,status:k.status,command:k.command}))},evidence:{commands:I((r.commands??[]).slice().reverse(),20),references:Kc([r.currentRequest,r.currentActivity,r.goal,r.plan,...r.decisions,...r.blockers,...r.warnings,...r.nextActions,...r.filesTouched,...r.commands??[],...r.tests,...(r.checks??[]).map(k=>k.command)])},attention:I(t.attention??[],20),progress:r.progress},{capturedAt:S,source:y,...h}=g;return{...g,stateDigest:$c(h)}}function Lc(t){return!!(t.currentRequest||t.currentActivity||t.goal||t.plan||t.phases.length>0||t.tasks.length>0||t.nextActions.length>0||t.blockers.length>0||t.decisions.length>0||t.filesTouched.length>0)}function Wr(t,e,n,r,s){if(!Lc(n))return null;let o=tt(t,!1),a=[...o?o.rules.filter(d=>d.mode==="enforce").map(d=>d.text):[],...n.warnings].slice(0,20),c=Fr({project:t,identity:e,state:n,reason:r,sequence:s,attention:a}),u=c.stateDigest;return{version:1,id:w([t.id,e.sessionKey,u].join("|")).slice(0,24),projectId:t.id,projectName:t.name,createdAt:new Date().toISOString(),reason:r,sourceSession:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,sequence:s},currentRequest:n.currentRequest,currentActivity:n.currentActivity,goal:n.goal,plan:n.plan,progress:n.progress,currentPhase:n.currentPhase,currentTask:n.currentTask,incompletePhases:n.phases.filter(d=>d.status!=="completed"&&d.status!=="cancelled"),incompleteTasks:n.tasks.filter(d=>d.status!=="completed"&&d.status!=="cancelled"),nextActions:c.remaining.todos.slice(0,10),blockers:n.blockers.slice(-10),decisions:n.decisions.slice(-10),warnings:n.warnings.slice(-10),attention:a,filesTouched:n.filesTouched.slice(-20),activeFiles:n.activeFiles?.slice(-10),modifiedFiles:n.modifiedFiles?.slice(-20),createdFiles:n.createdFiles?.slice(-20),deletedFiles:n.deletedFiles?.slice(-20),tests:n.tests.slice(-15),checks:n.checks?.slice(-10),stateDigest:u,continuity:c}}function Lr(t,e){let n=$t(t.rootPath,".toolnet","work","handoffs");Wc(n,{recursive:!0});let r=$t(n,`${e.id}.json`);Fc(r)||O(r,e),O($t(t.rootPath,".toolnet","work","handoff-latest.json"),e)}function Dr(t){let e=Wr(t.project,t.identity,t.state,t.reason,t.sequence);return e?(Lr(t.project,e),e):null}var st=class{constructor(e){this.options=e}options;async capture(e,n){let r=_t(this.options.project);r||(r=await Ye(this.options.project,this.options.storage)),r||(r=await Ue(this.options.project,this.options.storage));let s=Wr(this.options.project,this.options.identity,r,e,n);if(!s)return null;Lr(this.options.project,s);let o=`projects/${this.options.project.id}/work/handoffs/${s.id}.json`;return await this.options.storage.exists(o)||await this.options.storage.put(o,JSON.stringify(s,null,2)+`
|
|
97
97
|
`,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(s,null,2)+`
|
|
98
|
-
`,"application/json"),s}};async function zr(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}}import{existsSync as
|
|
99
|
-
`)}function ot(t,e){let n=
|
|
98
|
+
`,"application/json"),s}};async function zr(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}}import{existsSync as Dc,readFileSync as zc,writeFileSync as qc}from"node:fs";import{join as Bc}from"node:path";var Br="<!-- TOOLNET:STABLE-WORK:BEGIN -->",Kt="<!-- TOOLNET:STABLE-WORK:END -->";function Ft(t){switch(t.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function W(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${n}`)]:[]}function qr(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${Ft(n)} ${n.title}`)]:[]}function Vc(t){let e=[Br,"# ToolNet Stable Work State","",`Updated: ${t.updatedAt}`];return t.lastSession&&e.push(`Last agent: ${t.lastSession.agent}`,`Last session: ${t.lastSession.nativeSessionId}`),t.currentRequest&&e.push("","Current request:",t.currentRequest),t.currentActivity&&e.push("","Current activity:",t.currentActivity),t.goal&&e.push("","Goal:",t.goal),t.plan&&e.push("","Plan:",t.plan),t.currentPhase&&e.push("","Current phase:",`${Ft(t.currentPhase)} ${t.currentPhase.title}`),t.currentTask&&e.push("","Current task:",`${Ft(t.currentTask)} ${t.currentTask.title}`),e.push(...qr("Phases",t.phases)),e.push(...qr("TODO / Tasks",t.tasks)),e.push(...W("Next actions",t.nextActions)),e.push(...W("Blockers",t.blockers)),e.push(...W("Important decisions",t.decisions)),e.push(...W("Active files",t.activeFiles??[])),e.push(...W("Modified files",t.modifiedFiles??[])),e.push(...W("Created files",t.createdFiles??[])),e.push(...W("Deleted files",t.deletedFiles??[])),e.push(...W("Files touched",t.filesTouched)),e.push(...W("Recent commands",t.commands??[])),e.push(...W("Checks",(t.checks??[]).map(n=>`[${n.status}] ${n.kind}: ${n.command}`))),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.",Kt),e.join(`
|
|
99
|
+
`)}function ot(t,e){let n=Bc(t.rootPath,".toolnet","current.md"),r="";if(Dc(n))try{r=zc(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let s=Vc(e),o=r.indexOf(Br),i=r.indexOf(Kt),a;o>=0&&i>=o?a=[r.slice(0,o).trimEnd(),s,r.slice(i+Kt.length).trimStart()].filter(Boolean).join(`
|
|
100
100
|
|
|
101
101
|
`):a=r.trim()?`${r.trim()}
|
|
102
102
|
|
|
103
|
-
${s}`:s,
|
|
104
|
-
`,{encoding:"utf8",mode:384})}import{existsSync as
|
|
105
|
-
`,{encoding:"utf8",mode:384}),
|
|
106
|
-
`)}import{existsSync as Hr,mkdirSync as
|
|
107
|
-
`))if(n)try{let r=es(JSON.parse(n));if(r.type!=="session_meta")continue;let s=es(r.payload),o=[s.id,s.thread_id,s.threadId,s.session_id,s.sessionId].find(a=>typeof a=="string"),i=typeof s.cwd=="string"?s.cwd:void 0;return{threadId:o,cwd:i,raw:s}}catch{}return{raw:{}}}function Lt(t,e){if(!
|
|
103
|
+
${s}`:s,qc(n,`${a.trim()}
|
|
104
|
+
`,{encoding:"utf8",mode:384})}import{existsSync as Jc,mkdirSync as Hc,readFileSync as Gc,renameSync as Uc,writeFileSync as Yc}from"node:fs";import{dirname as Xc,join as Qc}from"node:path";function Vr(t){return Qc(t.rootPath,".toolnet","context","session-origin.json")}function Zc(t,e){Hc(Xc(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;Yc(n,`${JSON.stringify(e,null,2)}
|
|
105
|
+
`,{encoding:"utf8",mode:384}),Uc(n,t)}function it(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 at(t,e){let n=it(e.observations,"file"),r=it(e.observations,"next_action"),s=it(e.observations,"blocker"),o=it(e.observations,"decision"),i={version:1,projectId:t.id,agent:e.agent,nativeSessionId:e.nativeSessionId,updatedAt:e.workState.updatedAt,currentRequest:e.workState.currentRequest,currentActivity:e.workState.currentActivity,currentTask:e.workState.currentTask?.title,currentPhase:e.workState.currentPhase?.title,lastTouchedFile:n?.text??e.workState.activeFiles?.at(-1)??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 Zc(Vr(t),i),i}function eu(t){let e=Vr(t);if(!Jc(e))return null;try{let n=JSON.parse(Gc(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function Jr(t){let e=eu(t);if(!e)return null;let n=["Previous session:",`- Agent: ${e.agent}`,`- Session: ${e.nativeSessionId}`];return e.currentRequest&&n.push(`- Current request: ${e.currentRequest}`),e.currentActivity&&n.push(`- Current activity: ${e.currentActivity}`),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(`
|
|
106
|
+
`)}import{existsSync as Hr,mkdirSync as tu,readFileSync as nu}from"node:fs";import{join as Wt}from"node:path";function Gr(t){return Wt(t.rootPath,".toolnet","memory","checkpoints")}function Ur(t){return Wt(Gr(t),"latest.json")}function ru(t){let e=Ur(t);if(!Hr(e))return null;try{let n=JSON.parse(nu(e,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==t.id?null:n}catch{return null}}function su(t){return["rule","architecture","decision","fix"].includes(t)}function ou(t,e){return e.length===0?[]:Ke(t,e).candidates.filter(r=>su(r.kind)&&r.knowledgeClass!=="transient"&&r.importanceScore>=.65).map(r=>({fingerprint:r.fingerprint,kind:r.kind,content:r.content,knowledgeClass:r.knowledgeClass,importanceScore:r.importanceScore,confidence:r.confidence,createdAt:r.createdAt,agent:t.agent,nativeSessionId:t.nativeSessionId}))}function iu(t,e){let n=new Map;for(let r of[...t,...e]){let s=n.get(r.fingerprint);(!s||r.importanceScore>s.importanceScore)&&n.set(r.fingerprint,r)}return Array.from(n.values()).sort((r,s)=>s.importanceScore-r.importanceScore||s.createdAt.localeCompare(r.createdAt)).slice(0,80)}function au(t){return{request:t.currentRequest,activity:t.currentActivity,goal:t.goal,phase:t.currentPhase?{title:t.currentPhase.title,status:t.currentPhase.status}:void 0,task:t.currentTask?{title:t.currentTask.title,status:t.currentTask.status}:void 0,phases:t.phases.map(e=>({title:e.title,status:e.status})),tasks:t.tasks.map(e=>({title:e.title,status:e.status})),activeFiles:t.activeFiles??[],modifiedFiles:t.modifiedFiles??[],createdFiles:t.createdFiles??[],deletedFiles:t.deletedFiles??[],checks:t.checks??[],blockers:t.blockers,decisions:t.decisions,nextActions:t.nextActions}}function Yr(t,e,n,r){let s=ru(t),o=iu(s?.durableFacts??[],ou(e,n)),i=n.at(-1)?.sequence??s?.source.sequence??0,a=r.phases.filter(y=>y.status==="completed").map(y=>y.title),c=r.tasks.filter(y=>y.status==="completed").map(y=>y.title),u=r.phases.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),f=r.tasks.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),d={work:au(r),durableFacts:o.map(y=>y.fingerprint).sort()},p=w(JSON.stringify(d)).slice(0,32),l={schema:"toolnet.memory.checkpoint.v1",version:1,project:{id:t.id,name:t.name},source:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,sequence:i},capturedAt:new Date().toISOString(),request:r.currentRequest,activity:r.currentActivity,goal:r.goal,current:{phase:r.currentPhase,task:r.currentTask},completed:{phases:a,tasks:c},remaining:{phases:u,tasks:f},files:{active:r.activeFiles??[],modified:r.modifiedFiles??[],created:r.createdFiles??[],deleted:r.deletedFiles??[]},checks:r.checks??[],blockers:r.blockers.slice(-10),decisions:r.decisions.slice(-15),nextActions:r.nextActions.slice(0,10),durableFacts:o,stateDigest:p},g=Gr(t);tu(g,{recursive:!0,mode:448});let S=Wt(g,`${p}.json`);return Hr(S)||O(S,l),O(Ur(t),l),l}function Xr(t,e,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=se(e,n);if(r.length===0)return{updated:!1,observations:0};let s=rt(t,r);ot(t,s),at(t,{agent:e.agent,nativeSessionId:e.nativeSessionId,observations:r,workState:s});try{Yr(t,e,n,s)}catch{}try{Dr({project:t,identity:e,state:s,reason:"continuous-checkpoint",sequence:n.at(-1)?.sequence??0})}catch{}return{updated:!0,observations:r.length}}var ct=class{identity;wal;remote;sanitizer=new H;learner;continuity;semantic;handoff;project;title;metadata;constructor(e){this.project=e.project,this.identity=un(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new Oe(this.identity,e.eventContext),this.remote=new Te(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new Je({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new Xe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new Ze({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new st({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}}checkpointLocal(e){if(e.length!==0)try{Xr(this.project,this.identity,e)}catch{}}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){let n=this.wal.append([this.sanitizeEvent(e)]);return this.checkpointLocal(n),n[0]}recordMany(e){let n=this.wal.append(e.map(r=>this.sanitizeEvent(r)));return this.checkpointLocal(n),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 cu,readFileSync as uu,readdirSync as lu,statSync as Qr}from"node:fs";import{homedir as du}from"node:os";import{join as ut,resolve as Zr}from"node:path";function es(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function pu(){return process.env.CODEX_HOME??ut(du(),".codex")}function xe(t){let e="";try{e=uu(t,"utf8").slice(0,128*1024)}catch{return{raw:{}}}for(let n of e.split(`
|
|
107
|
+
`))if(n)try{let r=es(JSON.parse(n));if(r.type!=="session_meta")continue;let s=es(r.payload),o=[s.id,s.thread_id,s.threadId,s.session_id,s.sessionId].find(a=>typeof a=="string"),i=typeof s.cwd=="string"?s.cwd:void 0;return{threadId:o,cwd:i,raw:s}}catch{}return{raw:{}}}function Lt(t,e){if(!cu(t))return;let n;try{n=lu(t,{withFileTypes:!0})}catch{return}for(let r of n){let s=ut(t,r.name);if(r.isDirectory()){Lt(s,e);continue}r.isFile()&&r.name.endsWith(".jsonl")&&e.push(s)}}function Dt(){let t=pu(),e=[];return Lt(ut(t,"sessions"),e),Lt(ut(t,"archived_sessions"),e),e.sort((n,r)=>{try{return Qr(r).mtimeMs-Qr(n).mtimeMs}catch{return 0}})}function zt(t){let e=Dt(),n=e.find(r=>r.includes(t));if(n)return n;for(let r of e)if(xe(r).threadId===t)return r;return null}function lt(t,e){let n=Zr(t),r=Zr(e);return r===n||r.startsWith(n+"/")||n.startsWith(r+"/")}import{closeSync as fu,existsSync as mu,openSync as gu,readSync as yu,statSync as hu}from"node:fs";function ts(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function Su(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 ku(t){let e=typeof t.type=="string"?t.type.toLowerCase():"",n=ts(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 ns(t,e=0){if(!mu(t))return{events:[],nextOffset:e,reset:!1};let n=hu(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),a=gu(t,"r");try{yu(a,i,0,o,s)}finally{fu(a)}let c=i.toString("utf8"),u=c.lastIndexOf(`
|
|
108
108
|
`);if(u<0)return{events:[],nextOffset:s,reset:r};let f=c.slice(0,u+1),d=0,p=[];for(let l of f.split(`
|
|
109
109
|
`)){if(!l)continue;let g=Buffer.byteLength(l+`
|
|
110
|
-
`,"utf8"),S=s+d;d+=g;let y;try{y=JSON.parse(l)}catch{continue}let h=ts(y),k=
|
|
110
|
+
`,"utf8"),S=s+d;d+=g;let y;try{y=JSON.parse(l)}catch{continue}let h=ts(y),k=ku(h);p.push({type:k.type,timestamp:Su(h),role:k.role,sourceEventId:`rollout:${S}`,sourceSequence:S,data:h,provenance:{source:"codex-rollout",sourcePath:t,sourceOffset:S}})}return{events:p,nextOffset:s+Buffer.byteLength(f,"utf8"),reset:r}}var wu=[/^<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*$/],vu=[/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],bu=["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 xu(t){let e=t.toLowerCase();return bu.some(n=>e.includes(n))}function ju(t){if(!t.trim())return!0;for(let e of wu)if(e.test(t))return!0;return xu(t),!1}function Cu(t){let e=t;for(let n of vu)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function qt(t){let e=t.trim();return e?ju(e)?{content:"",filtered:!0,reason:"noise"}:{content:Cu(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function dt(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=qt(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=dt(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=qt(s);return o.filtered?null:o.content}return s&&typeof s=="object"?dt(s):s}).filter(s=>s!==null):e[n]=r;return e}function rs(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&&qt(r).filtered)return!0}return!1}async function je(t){let e=t.threadId.trim();if(!e)throw new Error("Codex thread ID is required");let n=xe(t.rolloutPath),r=t.cwd??n.cwd;if(r&&!lt(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 ct({project:t.project,storage:t.storage,agent:"codex",nativeSessionId:e,metadata:{source:"codex-rollout",rolloutPath:t.rolloutPath,cwd:r,client:t.client},eventContext:{source:"codex",cwd:r??t.project.rootPath,turnId:t.turnId}}),o=s.status(),i=o.sourceCursors["codex.rollout.path"],a=Number(o.sourceCursors["codex.rollout.offset"]??0);i&&i!==t.rolloutPath&&(a=0),(!Number.isFinite(a)||a<0)&&(a=0);let c=ns(t.rolloutPath,a),u=[];o.lastSequence===0&&u.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&&u.push({type:"custom",sourceEventId:`codex:${e}:rollout-rotation:${t.rolloutPath}`,data:{event:"rollout_rotation",previousPath:i,rolloutPath:t.rolloutPath},provenance:{source:"codex-rollout"}}),c.reset&&u.push({type:"custom",sourceEventId:`codex:${e}:rollout-reset:${c.nextOffset}`,data:{event:"rollout_reset"},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}});let f=c.events.filter(l=>!rs(l.data)).map(l=>({...l,data:dt(l.data)}));if(u.push(...f),f.length>0)try{let l={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:""},g=f.map((h,k)=>({version:1,id:`codex-work-${e}-${h.sourceSequence??k}`,sequence:k+1,projectId:t.project.id,agent:"codex",nativeSessionId:e,type:h.type,timestamp:h.timestamp??new Date().toISOString(),role:h.role,sourceEventId:h.sourceEventId,sourceSequence:h.sourceSequence,data:h.data??{},provenance:h.provenance??{}})),S=se(l,g),y=rt(t.project,S);ot(t.project,y),at(t.project,{agent:"codex",nativeSessionId:e,observations:S,workState:y})}catch{}t.idle&&t.turnId&&u.push({type:"session_idle",sourceEventId:`codex:${e}:turn:${t.turnId}:idle`,data:{turnId:t.turnId,client:t.client},provenance:{source:"codex-notify"}});let d=s.recordMany(u);if(s.setSourceCursor("codex.rollout.path",t.rolloutPath),s.setSourceCursor("codex.rollout.offset",c.nextOffset),t.turnId&&s.setSourceCursor("codex.last.turn",t.turnId),t.idle&&f.length>0)try{let l=f.map(S=>JSON.stringify(S.data)),g=$e(l,e);s.setSourceCursor("codex.session.summary",g.summary),s.setSourceCursor("codex.session.facts_count",g.durableFacts.length),jn()&&!In()&&s.setSourceCursor("codex.raw_transcript.archived","local")}catch{}let p=await s.flush();return{threadId:e,imported:d.length,rolloutEvents:c.events.length,eventCount:p.eventCount,chunkCount:p.chunkCount,status:p.status,rolloutOffset:c.nextOffset,reset:c.reset}}import{existsSync as Au}from"node:fs";import{dirname as Iu,join as Pu,parse as Mu,resolve as Eu}from"node:path";function ss(t){let e=Eu(t),n=Mu(e).root;for(;;){if(Au(Pu(e,".toolnet","project.json")))return new te().detect(e);if(e===n)break;let r=Iu(e);if(r===e)break;e=r}return null}async function os(t,e,n=100){let r=[];for(let s of Dt()){let o=xe(s);if(!(!o.threadId||!o.cwd)&<(t.rootPath,o.cwd)&&(r.push(await je({project:t,storage:e,threadId:o.threadId,rolloutPath:s,cwd:o.cwd})),r.length>=n))break}return r}import{existsSync as Tu,mkdirSync as is,readFileSync as Ou,writeFileSync as as}from"node:fs";import{homedir as cs}from"node:os";import{dirname as us,join as Bt}from"node:path";function Ru(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 ls(t={}){let e=t.configFile??Bt(process.env.CODEX_HOME??Bt(cs(),".codex"),"config.toml"),n=t.previousFile??Bt(cs(),".config","toolnet-memory","codex-notify-previous.json");is(us(e),{recursive:!0}),is(us(n),{recursive:!0});let r=Tu(e)?Ou(e,"utf8"):"",s=t.binary??"toolnet-memory",o=`notify = [${JSON.stringify(s)}, "session:codex-notify"]`,i=r.split(`
|
|
111
111
|
`),a=i.findIndex(p=>/^\s*\[/.test(p));a<0&&(a=i.length);let c=-1,u=-1;for(let p=0;p<a;p+=1)if(/^\s*notify\s*=/.test(i[p])){if(c=p,u=p,i[p].includes("[")&&!i[p].includes("]"))for(;u+1<a&&(u+=1,!i[u].includes("]")););break}let f=[];if(c>=0){let p=i.slice(c,u+1).join(`
|
|
112
|
-
`);f=
|
|
112
|
+
`);f=Ru(p),i.splice(c,u-c+1,o)}else a=i.findIndex(p=>/^\s*\[/.test(p)),a<0&&(a=i.length),i.splice(a,0,o);let d=f.length>=2&&f[f.length-1]==="session:codex-notify";return f.length>0&&!d&&as(n,JSON.stringify(f,null,2)+`
|
|
113
113
|
`,{encoding:"utf8",mode:384}),r=i.join(`
|
|
114
114
|
`),r.endsWith(`
|
|
115
115
|
`)||(r+=`
|
|
116
|
-
`),as(e,r,{encoding:"utf8",mode:384}),{configFile:e,previousFile:n,preservedPrevious:f.length>0&&!d}}import{existsSync as
|
|
117
|
-
`,{encoding:"utf8",mode:384}),e}import{existsSync as
|
|
116
|
+
`),as(e,r,{encoding:"utf8",mode:384}),{configFile:e,previousFile:n,preservedPrevious:f.length>0&&!d}}import{existsSync as Nu,mkdirSync as _u,readFileSync as $u,writeFileSync as Ku}from"node:fs";import{homedir as Fu}from"node:os";import{dirname as Wu,join as ds}from"node:path";function Lu(t){return`'${t.replace(/'/g,"'\\''")}'`}function ps(t={}){let e=t.hooksFile??ds(process.env.CODEX_HOME??ds(Fu(),".codex"),"hooks.json");_u(Wu(e),{recursive:!0});let n={};if(Nu(e))try{n=JSON.parse($u(e,"utf8"))}catch(a){throw new Error(`Invalid existing Codex hooks.json: ${a instanceof Error?a.message:String(a)}`)}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(a=>{try{return!JSON.stringify(a).includes("session:codex-context")}catch{return!0}}),i=t.binary??"toolnet-memory";return o.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${Lu(i)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),r.SessionStart=o,Ku(e,JSON.stringify(n,null,2)+`
|
|
117
|
+
`,{encoding:"utf8",mode:384}),e}import{existsSync as _g,mkdirSync as Bu,readFileSync as $g,writeFileSync as Vu}from"node:fs";import{dirname as Ju,join as ms}from"node:path";function Vt(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 j(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 Du(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(j(s,280)),e.length>=16))break}return e}function zu(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.trim(),o=s.toLowerCase(),a=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(u=>o.startsWith(u));if(!a)continue;let c=s.slice(a.length).trim();c&&(a.includes("enforce")?e.push(c):n.push(c))}return{enforce:e,advisory:n}}function qu(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
|
|
118
118
|
`);if(Vt(s)<=e){n.push(r);continue}let o=Vt(n.join(`
|
|
119
119
|
`)),i=Math.max(0,e-o);if(i>=16){let a=Math.floor(i*3.2),c=j(r,a);c&&n.push(c)}break}return n.join(`
|
|
120
|
-
`).trim()}async function fs(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=tt(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=
|
|
120
|
+
`).trim()}async function fs(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=tt(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=zu(r),o=n?n.rules.filter(l=>l.mode==="enforce").map(l=>l.text):s.enforce,i=n?n.rules.filter(l=>l.mode==="advisory").map(l=>l.text):s.advisory,a=r?Du(r):[],c=await Ye(t.project,t.storage),u=await Ir(t.project,t.storage),f=await zr(t.project,t.storage),d=[];if(d.push("[TOOLNET PROJECT CONTEXT]"),d.push(`Project: ${t.project.name}`),d.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),r&&d.push(`Full operating manual: ${et(t.project)}`),o.length){d.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let l of o.slice(0,24))d.push(`- [ENFORCE] ${j(l,240)}`)}if(i.length){d.push("","PROJECT PREFERENCES");for(let l of i.slice(0,10))d.push(`- ${j(l,220)}`)}if(u&&(u.mission&&d.push("","MISSION",j(u.mission.value,420)),u.activeObjective&&d.push("","CURRENT OBJECTIVE",j(u.activeObjective.value,420)),u.why&&d.push("","WHY THIS WORK MATTERS",j(u.why.value,420)),u.desiredOutcome&&d.push("","DESIRED OUTCOME",j(u.desiredOutcome.value,420)),u.planRationale&&d.push("","WHY THIS APPROACH",j(u.planRationale.value,420))),c){if(d.push("","ACTIVE WORK"),c.goal&&d.push(`Goal: ${j(c.goal,320)}`),c.plan&&d.push(`Plan: ${j(c.plan,320)}`),d.push(`Progress: phases ${c.progress.phasesCompleted}/${c.progress.phasesTotal}; tasks ${c.progress.tasksCompleted}/${c.progress.tasksTotal}; blocked ${c.progress.blocked}`),c.currentPhase&&d.push(`Current phase: ${c.currentPhase.title} [${c.currentPhase.status}]`),c.currentPhase&&u){let l=u.phases.find(g=>g.order===c.currentPhase?.order);l&&(l.objective&&d.push(`Phase objective: ${j(l.objective.value,340)}`),l.why?d.push(`Why this phase: ${j(l.why.value,340)}`):d.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),l.deliverable&&d.push(`Deliverable: ${j(l.deliverable.value,340)}`),l.dependencies.length&&d.push(`Depends on: ${l.dependencies.slice(0,4).map(g=>j(g.value,180)).join("; ")}`),l.acceptanceCriteria.length&&(d.push("","DEFINITION OF DONE"),l.acceptanceCriteria.slice(0,6).forEach(g=>{d.push(`- ${j(g.value,260)}`)})),l.openQuestions.length&&(d.push("","OPEN QUESTIONS FOR CURRENT PHASE"),l.openQuestions.slice(0,4).forEach(g=>{d.push(`- ${j(g.value,260)}`)})))}c.currentTask&&d.push(`Current task: ${c.currentTask.title} [${c.currentTask.status}]`),c.nextActions.length&&(d.push("","NEXT ACTIONS"),c.nextActions.slice(0,6).forEach((l,g)=>{d.push(`${g+1}. ${j(l,260)}`)})),c.blockers.length&&(d.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(l=>{d.push(`- ${j(l,260)}`)})),c.warnings.length&&(d.push("","ATTENTION"),c.warnings.slice(-5).forEach(l=>{d.push(`- ${j(l,260)}`)})),c.decisions.length&&(d.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(l=>{d.push(`- ${j(l,260)}`)})),c.lastSession&&d.push("",`Last work session: ${c.lastSession.agent} / ${c.lastSession.nativeSessionId}`)}if(u&&u.openQuestions.length&&(d.push("","UNRESOLVED QUESTIONS"),u.openQuestions.slice(0,5).forEach(l=>{d.push(`- ${j(l.value,260)}`)})),f&&d.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),a.length){d.push("","OPERATING NOTES");for(let l of a)d.push(`- ${l}`)}d.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let p=qu(d,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:p,estimatedTokens:Vt(p),maxTokens:e,hasManual:!!r,hasWorkState:!!c,hasHandoff:!!f,generatedAt:new Date().toISOString()}}function Hu(t){return ms(t.rootPath,".toolnet","context","startup.md")}function Gu(t){return ms(t.rootPath,".toolnet","context","startup.json")}function Uu(t,e){let n=Hu(t);Bu(Ju(n),{recursive:!0}),Vu(n,e.text.endsWith(`
|
|
121
121
|
`)?e.text:e.text+`
|
|
122
|
-
`,{encoding:"utf8",mode:384}),O(
|
|
122
|
+
`,{encoding:"utf8",mode:384}),O(Gu(t),e)}async function gs(t,e,n=800){let s=(await fs({project:t,storage:e,maxTokens:n})).text;Ne(s)>n&&(s=_e(s,n),s+=`
|
|
123
123
|
|
|
124
124
|
[Context trimmed by ToolNet Memory token budget]
|
|
125
|
-
`);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:w(s),estimatedTokens:Ne(s),generatedAt:new Date().toISOString()};return
|
|
125
|
+
`);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:w(s),estimatedTokens:Ne(s),generatedAt:new Date().toISOString()};return Uu(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
|
|
126
126
|
`,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
|
|
127
|
-
`,"application/json"),i}import{existsSync as
|
|
127
|
+
`,"application/json"),i}import{existsSync as tl,readFileSync as nl}from"node:fs";import{join as rl}from"node:path";import{existsSync as ys,mkdirSync as Yu,readFileSync as hs,renameSync as Xu,writeFileSync as Qu}from"node:fs";import{dirname as Zu,join as Ss}from"node:path";function ks(t){return Ss(t.rootPath,".toolnet","context","handoff.md")}function ws(t){return Ss(t.rootPath,".toolnet","context","handoff.json")}function vs(t,e){Yu(Zu(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;Qu(n,e.endsWith(`
|
|
128
128
|
`)?e:`${e}
|
|
129
|
-
`,{encoding:"utf8",mode:384}),
|
|
129
|
+
`,{encoding:"utf8",mode:384}),Xu(n,t)}function el(t,e){vs(t,`${JSON.stringify(e,null,2)}
|
|
130
130
|
`)}function bs(t,e){let n=e.replace(/\r\n/g,`
|
|
131
|
-
`).trim();if(!n)return null;let r={version:1,projectId:t.id,projectName:t.name,text:n,digest:w(n),generatedAt:new Date().toISOString()};return vs(ks(t),n),
|
|
131
|
+
`).trim();if(!n)return null;let r={version:1,projectId:t.id,projectName:t.name,text:n,digest:w(n),generatedAt:new Date().toISOString()};return vs(ks(t),n),el(ws(t),r),r}function xs(t){let e=ks(t);if(!ys(e))return null;try{let n=hs(e,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=ws(t);if(ys(s))try{let o=JSON.parse(hs(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:t.id,projectName:t.name,text:n,digest:w(n),generatedAt:r}}catch{return null}}function sl(t){let e=rl(t.rootPath,".toolnet","current.md");if(!tl(e))return null;try{return nl(e,"utf8").trim()}catch{return null}}function ol(t,e){let n=e.replace(/\r\n/g,`
|
|
132
132
|
`).trim(),r=2400,s=n.length>r?`${n.slice(0,r)}
|
|
133
133
|
|
|
134
134
|
[Current work truncated for fast handoff]`:n,o=Jr(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(`
|
|
135
|
-
`)}function js(t){let e=
|
|
135
|
+
`)}function js(t){let e=sl(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=ol(t,e);return xs(t)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(bs(t,n),{updated:!0,reason:"updated",chars:n.length})}function pt(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function Cs(t){let e=Ce(),n=nn(en({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new Ee(n,t.id,t.name,t.remote??t.name)}async function dl(t){for(let e=0;e<10;e+=1){let n=zt(t);if(n)return n;await new Promise(r=>setTimeout(r,150))}return null}function pl(t){let e=ll(ul(),".config","toolnet-memory","codex-notify-previous.json");if(il(e))try{let n=JSON.parse(al(e,"utf8"));if(!Array.isArray(n)||n.length===0||!n.every(s=>typeof s=="string"))return;cl(n[0],[...n.slice(1),t],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function fl(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 a=ss(o);if(!a)return;let c=await dl(r);if(!c)return;let u=Cs(a);await je({project:a,storage:u,threadId:r,rolloutPath:c,cwd:o,turnId:s,client:i,idle:!0});try{await gs(a,u,800)}catch{}try{js(a)}catch{}}async function ml(){let[t="help",...e]=process.argv.slice(2);if(t==="install-notify"){let o=pt(e,"--bin"),i=ls({binary:o}),a=ps({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: ${a}`);return}if(t==="notify"){let o=e[e.length-1]??"";try{await fl(o)}finally{pl(o)}return}let n=pt(e,"--project")??process.cwd(),r=new te().detect(n),s=Cs(r);if(t==="sync"){let o=e[0];if(!o)throw new Error("Usage: sync <thread-id>");let i=pt(e,"--rollout")??zt(o);if(!i)throw new Error(`Codex rollout not found for ${o}`);let a=await je({project:r,storage:s,threadId:o,rolloutPath:i,idle:e.includes("--idle")});console.log(JSON.stringify(a,null,2));return}if(t==="recover"){let o=Number(pt(e,"--limit")??100),i=await os(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((a,c)=>a+c.imported,0)},null,2));return}console.log(`Codex Session Adapter
|
|
136
136
|
|
|
137
137
|
Commands:
|
|
138
138
|
install-notify
|
|
139
139
|
sync <thread-id> [--project PATH]
|
|
140
140
|
recover [--project PATH] [--limit N]
|
|
141
|
-
`)}
|
|
141
|
+
`)}ml().catch(t=>{process.argv[2]==="notify"&&process.exit(0),console.error(t instanceof Error?t.message:t),process.exit(1)});
|