toolnet-memory 0.3.16 → 0.3.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +74 -0
- package/.release-target +1 -1
- package/README.md +157 -7
- package/bin/toolnet-memory +12 -0
- package/bundle/agy-hook.js +59 -59
- package/bundle/agy.js +58 -58
- package/bundle/api.js +15 -15
- package/bundle/audit.js +2 -0
- package/bundle/background-refresh.js +7 -7
- package/bundle/code-capabilities.js +2 -0
- package/bundle/codex.js +63 -63
- package/bundle/context-runtime.js +41 -41
- package/bundle/context.js +15 -15
- package/bundle/copilot-hook.js +73 -73
- package/bundle/cursor-hook.js +73 -73
- package/bundle/docker-healthcheck.js +3 -0
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +20 -19
- package/bundle/gc.js +5 -3
- package/bundle/graph-cli.js +1 -1
- package/bundle/graph-index.js +5 -4
- package/bundle/graph-ui.js +4 -3
- package/bundle/grok-hook.js +52 -52
- package/bundle/handoff-refresh.js +2 -2
- package/bundle/help-cli.js +4 -4
- package/bundle/impact.js +5 -4
- package/bundle/incremental.js +5 -5
- package/bundle/init.js +35 -35
- package/bundle/kiro-hook.js +74 -74
- package/bundle/learner.js +8 -6
- package/bundle/mcp.js +19 -17
- package/bundle/memory-agent.js +4 -4
- package/bundle/memory-query.js +3 -3
- package/bundle/opencode.js +73 -73
- package/bundle/project-manual.js +7 -7
- package/bundle/public/index.html +1089 -2306
- package/bundle/runtime.js +16 -13
- package/bundle/semantic.js +6 -5
- package/bundle/service.js +11 -6
- package/bundle/snapshot.js +6 -4
- package/bundle/status-cli.js +4 -4
- package/bundle/toolnet-cli.js +49 -49
- package/bundle/work-continuity.js +7 -7
- package/package.json +26 -2
- package/release-manifest.json +57 -1
package/bundle/agy-hook.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import{existsSync as
|
|
2
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function
|
|
3
|
-
`,{encoding:"utf8",mode:384}),Es(o,r)}function Q(e,t){return{id:e.id,name:e.name,remote:e.remote,rootPath:t,createdAt:e.createdAt,updatedAt:e.updatedAt,graphVersion:e.graphVersion,memoryVersion:e.memoryVersion,metadata:e.metadata}}function Rt(e){return{version:1,scheme:he,canonicalRemote:e.canonicalRemote,fingerprint:e.fingerprint,repositoryName:e.repositoryName}}function _s(e){let t=e.metadata?.toolnetIdentity;if(!t||typeof t!="object"||Array.isArray(t))return null;let n=t;return typeof n.fingerprint=="string"?n.fingerprint:null}var Ve=class{adopt(t,n){let r=Ot(X(t));if(!n.id.trim())throw new Error("PROJECT_ADOPTION_INVALID_ID");if(!n.name.trim())throw new Error("PROJECT_ADOPTION_INVALID_NAME");if(!n.remote.trim())throw new Error("PROJECT_ADOPTION_INVALID_REMOTE");if(Mn(r)){let a=De(ie(r));if(a.id!==n.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${n.id}`].join(" "));return Q(a,r)}let o=new Date().toISOString(),s={...n.metadata};n.gitIdentity&&(s.toolnetIdentity=Rt(n.gitIdentity));let i={version:1,id:n.id.trim(),name:n.name.trim(),remote:n.remote.trim(),rootPath:r,createdAt:n.createdAt??o,updatedAt:o,graphVersion:n.graphVersion??0,memoryVersion:n.memoryVersion??0,metadata:Object.keys(s).length?s:void 0};return ze(r,i),Q(i,r)}recordGitIdentity(t,n,r={}){let o=this.requireExisting(t),s=ie(o.rootPath),i=De(s),a=_s(i);if(a&&a!==n.fingerprint&&!r.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${a}`,`current=${n.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let c=i.metadata?.toolnetIdentity;return c&&typeof c=="object"&&!Array.isArray(c)&&c.fingerprint===n.fingerprint||(i.metadata={...i.metadata,toolnetIdentity:Rt(n)},i.updatedAt=new Date().toISOString(),ze(o.rootPath,i)),Q(i,o.rootPath)}findExisting(t=process.cwd()){let n=X(t),r=Ot(n),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>qe(ke(r,c))),i=bn(n,s?r:void 0);if(!i)return null;let a=De(ie(i));return Q(a,i)}requireExisting(t=process.cwd()){let n=this.findExisting(t);if(!n)throw new Error("PROJECT_NOT_INITIALIZED");return n}detect(t=process.cwd()){let n=X(t),r=Ot(n),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>qe(ke(r,l))),i=bn(n,s?r:void 0);if(i){let l=ie(i),f=De(l);return f.rootPath!==i&&(f.rootPath=i,f.updatedAt=new Date().toISOString(),ze(i,f)),Q(f,i)}let a=new Date().toISOString(),c=Os(r),u=wn(r),p={version:1,id:u?vn(u.canonicalRemote):Ns(r),name:c,remote:u?.repositoryName??c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:u?{toolnetIdentity:Rt(u)}:void 0};return ze(r,p),Q(p,r)}};var $s=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_-]{20,}\b/g,confidence:"exact"},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g,confidence:"exact"},{type:"aws_access_key",regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,confidence:"exact"},{type:"github_token",regex:/\b(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{40,255})\b/g,confidence:"exact"},{type:"stripe_secret_key",regex:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,confidence:"exact"},{type:"google_api_key",regex:/\bAIza[A-Za-z0-9_-]{30,}\b/g,confidence:"exact"},{type:"slack_token",regex:/\bxox[baprs]-[A-Za-z0-9-]{16,}\b/g,confidence:"exact"},{type:"npm_token",regex:/\bnpm_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._~+/=-]{16,}\b/gi,confidence:"high"},{type:"jwt",regex:/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,confidence:"exact"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,confidence:"exact"},{type:"password_assignment",regex:/\b(?:password|passwd|pwd)\s*[:=]\s*["']?[^"' \t\r\n]{6,}["']?/gi,confidence:"high"},{type:"secret_assignment",regex:/\b(?:secret|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)\s*[:=]\s*["']?[^"' \t\r\n]{8,}["']?/gi,confidence:"high"},{type:"cookie",regex:/\b(?:cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi,confidence:"high"},{type:"url_credentials",regex:/\bhttps?:\/\/[^:/@\s]+:[^/@\s]{4,}@[^/\s]+/gi,confidence:"high"}],Fs=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function An(e){return e.normalize("NFKC").trim().toLowerCase()}function Ks(e){if(e.length===0)return 0;let t=new Map;for(let r of e)t.set(r,(t.get(r)??0)+1);let n=0;for(let r of t.values()){let o=r/e.length;n-=o*Math.log2(o)}return n}function Ls(e){return/^[a-f0-9]{32}$/iu.test(e)||/^[a-f0-9]{40}$/iu.test(e)||/^[a-f0-9]{64}$/iu.test(e)}function Ws(e,t,n){let r=e.slice(Math.max(0,t-48),t),o=e.slice(n,Math.min(e.length,n+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${o}`)}function Ds(e,t){return e.start<t.end&&t.start<e.end}function In(e){return e.sort((t,n)=>t.start!==n.start?t.start-n.start:n.end-n.start-(t.end-t.start))}var He=class{allowValues=new Set;enableEntropyHeuristic;constructor(t={}){for(let n of t.allowValues??[]){let r=An(n);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=t.enableEntropyHeuristic??!0}scan(t){let n=[];for(let s of $s){let i=new RegExp(s.regex.source,s.regex.flags);for(let a of t.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||n.push({type:s.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:s.confidence})}this.enableEntropyHeuristic&&n.push(...this.entropyMatches(t));let r=In(n),o=[];for(let s of r)o.some(i=>Ds(i,s))||o.push(s);return In(o)}hasSecrets(t){return this.scan(t).length>0}allowed(t){let n=An(t);return Fs.has(n)?!0:this.allowValues.has(n)}entropyMatches(t){let n=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let o of t.matchAll(r)){if(o.index===void 0||!o[0])continue;let s=o[0];this.allowed(s)||Ls(s)||!/[A-Za-z]/u.test(s)||!/[0-9]/u.test(s)||Ws(t,o.index,o.index+s.length)&&(Ks(s)<3.7||n.push({type:"high_entropy_secret",value:s,start:o.index,end:o.index+s.length,confidence:"heuristic"}))}return n}};var V=class{scanner;constructor(t={}){this.scanner=new He(t)}sanitize(t){let n=this.scanner.scan(t);if(n.length===0)return{text:t,redacted:0,secretTypes:[]};let r=t,o=[...n].sort((i,a)=>a.start-i.start),s=new Set;for(let i of o)s.add(i.type),r=r.slice(0,i.start)+`[REDACTED:${i.type}]`+r.slice(i.end);return{text:r,redacted:n.length,secretTypes:[...s].sort()}}sanitizeValue(t){if(typeof t=="string")return this.sanitize(t).text;if(Array.isArray(t))return t.map(n=>this.sanitizeValue(n));if(t&&typeof t=="object"){let n={};for(let[r,o]of Object.entries(t)){let s=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")){n[r]="[REDACTED]";continue}n[r]=this.sanitizeValue(o)}return n}return t}};var zs=new V;function Se(e){return zs.sanitizeValue(e)}import{homedir as di}from"node:os";import{join as fi}from"node:path";import{DeleteObjectCommand as qs,GetObjectCommand as Bs,HeadObjectCommand as Vs,ListObjectsV2Command as Hs,PutObjectCommand as Js,S3Client as Gs}from"@aws-sdk/client-s3";import{getSignedUrl as Us}from"@aws-sdk/s3-request-presigner";var Je=class{name="huggingface";client;bucket;constructor(t){this.bucket=t.bucket,this.client=new Gs({region:"us-east-1",endpoint:`https://s3.hf.co/${t.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,n,r="application/octet-stream"){let o=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Js({Bucket:this.bucket,Key:t,Body:o,ContentType:r}))}async get(t){let n=await Us(this.client,new Bs({Bucket:this.bucket,Key:t}),{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(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await this.client.send(new Vs({Bucket:this.bucket,Key:t})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(t){await this.client.send(new qs({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let o=await this.client.send(new Hs({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let s of o.Contents??[])s.Key&&n.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return n}};import{access as Cn,mkdir as Ys,readFile as Qs,readdir as Xs,rm as Zs,stat as Pn,writeFile as ei}from"node:fs/promises";import{dirname as ti,join as ni,relative as En,resolve as ri}from"node:path";var ve=class{constructor(t){this.root=t}root;name="local";path(t){let n=t.replace(/^\/+/,"");return ri(this.root,n)}async put(t,n){let r=this.path(t);await Ys(ti(r),{recursive:!0}),await ei(r,n)}async get(t){try{return await Qs(this.path(t))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await Cn(this.path(t)),!0}catch{return!1}}async delete(t){await Zs(this.path(t),{force:!0})}async list(t=""){let n=this.path(t),r=[];try{await Cn(n)}catch{return r}let o=async i=>{let a=await Xs(i,{withFileTypes:!0});for(let c of a){let u=ni(i,c.name);if(c.isDirectory()){await o(u);continue}let p=await Pn(u);r.push({key:En(this.root,u),size:p.size,updatedAt:p.mtime.toISOString()})}},s=await Pn(n);return s.isDirectory()?await o(n):r.push({key:En(this.root,n),size:s.size,updatedAt:s.mtime.toISOString()}),r}};import{DeleteObjectCommand as oi,GetObjectCommand as si,HeadObjectCommand as ii,ListObjectsV2Command as ai,PutObjectCommand as ci,S3Client as ui}from"@aws-sdk/client-s3";import{getSignedUrl as li}from"@aws-sdk/s3-request-presigner";var we=class{name;client;bucket;constructor(t){this.name=t.name??"s3",this.bucket=t.bucket,this.client=new ui({region:t.region??"us-east-1",endpoint:t.endpoint||void 0,forcePathStyle:t.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,n,r="application/octet-stream"){let o=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new ci({Bucket:this.bucket,Key:t,Body:o,ContentType:r}))}async get(t){let n=await li(this.client,new si({Bucket:this.bucket,Key:t}),{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(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await this.client.send(new ii({Bucket:this.bucket,Key:t})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(t){await this.client.send(new oi({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let o=await this.client.send(new ai({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let s of o.Contents??[])s.Key&&n.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return n}};function Nt(e,t){return console.warn(t),new ve(e)}function Tn(e){let t=e.localRoot??fi(di(),".toolnet-memory","storage");if(e.provider==="r2"){let n=e.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new we({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Nt(t,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(e.provider==="s3"){let n=e.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new we({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Nt(t,"[storage] S3 credentials missing. Using local fallback.")}if(e.provider==="huggingface"){let n=e.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Je({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):Nt(t,"[storage] Hugging Face credentials missing. Using local fallback.")}return new ve(t)}function pi(e){return new Promise(t=>setTimeout(t,e))}async function On(e,t={}){let n=Math.max(1,t.attempts??3),r=t.baseDelayMs??150,o=t.maxDelayMs??2e3,s;for(let i=1;i<=n;i++)try{return await e()}catch(a){if(s=a,i>=n)break;let c=Math.min(o,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await pi(c+u)}throw s}var mi=new Set(["put","get","getText","delete","list"]);function Rn(e,t={}){return new Proxy(e,{get(n,r){let o=Reflect.get(n,r,n);return typeof o!="function"?o:mi.has(r)?(...s)=>On(()=>Promise.resolve(o.apply(n,s)),t):o.bind(n)}})}function Nn(e){let t=e.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!t||t==="."||t==="..")throw new Error("Invalid project storage folder");return t}function _n(e){let t=e.replace(/^\/+/,"");if(t.startsWith("memories/"))return"memory/records/"+t.slice(9);if(t.startsWith("vectors/"))return"memory/vectors/"+t.slice(8);if(t.startsWith("graph/"))return"code/graph/"+t.slice(6);let n=t.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=t.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=t.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let o=t.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=t.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=t.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:t))}var Ge=class{constructor(t,n,r,o){this.provider=t;this.name=t.name,this.projectId=n,this.projectName=r,this.folder=Nn(o??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let t=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,o=await this.provider.getText(t);if(o){let i;try{i=JSON.parse(o)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${t}: ${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 s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(t,JSON.stringify(s,null,2)+`
|
|
4
|
-
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(t){if(t=
|
|
5
|
-
`,{encoding:"utf8",mode:384}),
|
|
6
|
-
`))))}function
|
|
7
|
-
`).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
|
|
1
|
+
import{existsSync as _s,readFileSync as $s}from"node:fs";import{homedir as Ks}from"node:os";import{join as Fs}from"node:path";function Ls(e){let t=e.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?(t=t.slice(1,-1),t.replace(/\\n/g,`
|
|
2
|
+
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function Ds(){let e=process.env.TOOLNET_GLOBAL_ENV??Fs(Ks(),".config","toolnet-memory",".env");if(!_s(e))return;let t=$s(e,"utf8");for(let n of t.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let s=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=Ls(r.slice(o+1)))}}Ds();function ke(e,t){return e===void 0?t:["1","true","yes","on"].includes(e.toLowerCase())}function Se(e,t){if(!e)return t;let n=Number(e);return Number.isFinite(n)?n:t}function Ve(){return{memory:{autoCapture:ke(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:ke(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:ke(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:ke(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:Se(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:Se(process.env.MEMORY_RERANK_TOP,10),finalContext:Se(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:Se(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:ke(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:Se(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Js}from"node:crypto";import{existsSync as Ge,mkdirSync as Gs,readFileSync as Us,renameSync as Ys,writeFileSync as Qs}from"node:fs";import{basename as Xs,dirname as Ue,join as we,parse as Rn,resolve as Z}from"node:path";import{createHash as En}from"node:crypto";import{spawnSync as Ws}from"node:child_process";var ve="git-remote-v1",zs=new Set(["github.com","gitlab.com","bitbucket.org"]);function Pn(e,t){let n=t.replaceAll("\\","/").replace(/^\/+/u,"").replace(/\/+$/u,"").replace(/\.git$/iu,"").replace(/\/+/gu,"/");return!n||n==="."||n===".."||n.split("/").some(r=>!r||r==="."||r==="..")?null:(zs.has(e)&&(n=n.toLowerCase()),n)}function qs(e){let t;try{t=new URL(e)}catch{return null}if(!["https:","http:","ssh:","git:"].includes(t.protocol))return null;let n=t.hostname.trim().toLowerCase();if(!n)return null;let r=t.protocol==="https:"&&t.port==="443"||t.protocol==="http:"&&t.port==="80"||t.protocol==="ssh:"&&t.port==="22",o=t.port&&!r?`${n}:${t.port}`:n,s=Pn(n,t.pathname);return s?`${o}/${s}`:null}function Bs(e){let t=e.match(/^(?:[^@\s/:]+@)?([^:/\s]+):(.+)$/u);if(!t)return null;let n=t[1]?.trim().toLowerCase();if(!n||n.length===1)return null;let r=Pn(n,t[2]??"");return r?`${n}/${r}`:null}function jn(e){let t=e.trim();return t?t.includes("://")?qs(t):Bs(t):null}function Vs(e){return En("sha256").update(`${ve}:${e}`).digest("hex")}function Cn(e){return En("sha256").update(`toolnet-project:${ve}:${e}`).digest("hex").slice(0,16)}function Hs(e){return e.split("/").filter(Boolean).at(-1)?.trim()||null}function $t(e,t){let n=Ws("git",["-C",e,...t],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return n.error||n.status!==0?null:n.stdout?.trim()||null}function Mn(e,t){let n=Hs(e);return n?{scheme:ve,canonicalRemote:e,fingerprint:Vs(e),repositoryName:n,source:t}:null}function Tn(e){let t=$t(e,["remote","get-url","origin"]);if(t){let o=jn(t);if(o)return Mn(o,"origin")}let n=$t(e,["remote"]);if(!n)return null;let r=new Set;for(let o of n.split(/\r?\n/u).map(s=>s.trim()).filter(Boolean)){let s=$t(e,["remote","get-url",o]);if(!s)continue;let i=jn(s);i&&r.add(i)}return r.size!==1?null:Mn([...r][0],"unique-remote")}var Nn=".toolnet",Zs="project.json";function ei(e){return Js("sha256").update(e).digest("hex").slice(0,16)}function ce(e){return we(e,Nn,Zs)}function _n(e){return Ge(ce(e))}function On(e,t){let n=Z(e),r=Rn(n).root;for(;;){if(_n(n))return n;if(n===r||t&&n===Z(t))break;let o=Ue(n);if(o===n)break;n=o}return null}function Kt(e){let t=Z(e),n=Rn(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(s=>Ge(we(t,s))))return t;if(t===n)break;let o=Ue(t);if(o===t)break;t=o}return Z(e)}function He(e){let t;try{t=JSON.parse(Us(e,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${e}: ${o instanceof Error?o.message:String(o)}`)}if(!t||typeof t!="object")throw new Error(`Invalid ToolNet project manifest: ${e}`);let n=t;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${e}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${e}`);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:Ue(Ue(e)),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 Je(e,t){let n=we(e,Nn);Gs(n,{recursive:!0});let r=ce(e),o=`${r}.tmp-${process.pid}`;Qs(o,JSON.stringify(t,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),Ys(o,r)}function X(e,t){return{id:e.id,name:e.name,remote:e.remote,rootPath:t,createdAt:e.createdAt,updatedAt:e.updatedAt,graphVersion:e.graphVersion,memoryVersion:e.memoryVersion,metadata:e.metadata}}function Ft(e){return{version:1,scheme:ve,canonicalRemote:e.canonicalRemote,fingerprint:e.fingerprint,repositoryName:e.repositoryName}}function ti(e){let t=e.metadata?.toolnetIdentity;if(!t||typeof t!="object"||Array.isArray(t))return null;let n=t;return typeof n.fingerprint=="string"?n.fingerprint:null}var Ye=class{adopt(t,n){let r=Kt(Z(t));if(!n.id.trim())throw new Error("PROJECT_ADOPTION_INVALID_ID");if(!n.name.trim())throw new Error("PROJECT_ADOPTION_INVALID_NAME");if(!n.remote.trim())throw new Error("PROJECT_ADOPTION_INVALID_REMOTE");if(_n(r)){let a=He(ce(r));if(a.id!==n.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${n.id}`].join(" "));return X(a,r)}let o=new Date().toISOString(),s={...n.metadata};n.gitIdentity&&(s.toolnetIdentity=Ft(n.gitIdentity));let i={version:1,id:n.id.trim(),name:n.name.trim(),remote:n.remote.trim(),rootPath:r,createdAt:n.createdAt??o,updatedAt:o,graphVersion:n.graphVersion??0,memoryVersion:n.memoryVersion??0,metadata:Object.keys(s).length?s:void 0};return Je(r,i),X(i,r)}recordGitIdentity(t,n,r={}){let o=this.requireExisting(t),s=ce(o.rootPath),i=He(s),a=ti(i);if(a&&a!==n.fingerprint&&!r.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${a}`,`current=${n.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let c=i.metadata?.toolnetIdentity;return c&&typeof c=="object"&&!Array.isArray(c)&&c.fingerprint===n.fingerprint||(i.metadata={...i.metadata,toolnetIdentity:Ft(n)},i.updatedAt=new Date().toISOString(),Je(o.rootPath,i)),X(i,o.rootPath)}findExisting(t=process.cwd()){let n=Z(t),r=Kt(n),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>Ge(we(r,c))),i=On(n,s?r:void 0);if(!i)return null;let a=He(ce(i));return X(a,i)}requireExisting(t=process.cwd()){let n=this.findExisting(t);if(!n)throw new Error("PROJECT_NOT_INITIALIZED");return n}detect(t=process.cwd()){let n=Z(t),r=Kt(n),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>Ge(we(r,l))),i=On(n,s?r:void 0);if(i){let l=ce(i),f=He(l);return f.rootPath!==i&&(f.rootPath=i,f.updatedAt=new Date().toISOString(),Je(i,f)),X(f,i)}let a=new Date().toISOString(),c=Xs(r),u=Tn(r),p={version:1,id:u?Cn(u.canonicalRemote):ei(r),name:c,remote:u?.repositoryName??c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:u?{toolnetIdentity:Ft(u)}:void 0};return Je(r,p),X(p,r)}};var ni=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_-]{20,}\b/g,confidence:"exact"},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g,confidence:"exact"},{type:"aws_access_key",regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,confidence:"exact"},{type:"github_token",regex:/\b(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{40,255})\b/g,confidence:"exact"},{type:"stripe_secret_key",regex:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,confidence:"exact"},{type:"google_api_key",regex:/\bAIza[A-Za-z0-9_-]{30,}\b/g,confidence:"exact"},{type:"slack_token",regex:/\bxox[baprs]-[A-Za-z0-9-]{16,}\b/g,confidence:"exact"},{type:"npm_token",regex:/\bnpm_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._~+/=-]{16,}\b/gi,confidence:"high"},{type:"jwt",regex:/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,confidence:"exact"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,confidence:"exact"},{type:"password_assignment",regex:/\b(?:password|passwd|pwd)\s*[:=]\s*["']?[^"' \t\r\n]{6,}["']?/gi,confidence:"high"},{type:"secret_assignment",regex:/\b(?:secret|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)\s*[:=]\s*["']?[^"' \t\r\n]{8,}["']?/gi,confidence:"high"},{type:"cookie",regex:/\b(?:cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi,confidence:"high"},{type:"url_credentials",regex:/\bhttps?:\/\/[^:/@\s]+:[^/@\s]{4,}@[^/\s]+/gi,confidence:"high"}],ri=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function $n(e){return e.normalize("NFKC").trim().toLowerCase()}function oi(e){if(e.length===0)return 0;let t=new Map;for(let r of e)t.set(r,(t.get(r)??0)+1);let n=0;for(let r of t.values()){let o=r/e.length;n-=o*Math.log2(o)}return n}function si(e){return/^[a-f0-9]{32}$/iu.test(e)||/^[a-f0-9]{40}$/iu.test(e)||/^[a-f0-9]{64}$/iu.test(e)}function ii(e,t,n){let r=e.slice(Math.max(0,t-48),t),o=e.slice(n,Math.min(e.length,n+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${o}`)}function ai(e,t){return e.start<t.end&&t.start<e.end}function Kn(e){return e.sort((t,n)=>t.start!==n.start?t.start-n.start:n.end-n.start-(t.end-t.start))}var Qe=class{allowValues=new Set;enableEntropyHeuristic;constructor(t={}){for(let n of t.allowValues??[]){let r=$n(n);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=t.enableEntropyHeuristic??!0}scan(t){let n=[];for(let s of ni){let i=new RegExp(s.regex.source,s.regex.flags);for(let a of t.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||n.push({type:s.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:s.confidence})}this.enableEntropyHeuristic&&n.push(...this.entropyMatches(t));let r=Kn(n),o=[];for(let s of r)o.some(i=>ai(i,s))||o.push(s);return Kn(o)}hasSecrets(t){return this.scan(t).length>0}allowed(t){let n=$n(t);return ri.has(n)?!0:this.allowValues.has(n)}entropyMatches(t){let n=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let o of t.matchAll(r)){if(o.index===void 0||!o[0])continue;let s=o[0];this.allowed(s)||si(s)||!/[A-Za-z]/u.test(s)||!/[0-9]/u.test(s)||ii(t,o.index,o.index+s.length)&&(oi(s)<3.7||n.push({type:"high_entropy_secret",value:s,start:o.index,end:o.index+s.length,confidence:"heuristic"}))}return n}};var H=class{scanner;constructor(t={}){this.scanner=new Qe(t)}sanitize(t){let n=this.scanner.scan(t);if(n.length===0)return{text:t,redacted:0,secretTypes:[]};let r=t,o=[...n].sort((i,a)=>a.start-i.start),s=new Set;for(let i of o)s.add(i.type),r=r.slice(0,i.start)+`[REDACTED:${i.type}]`+r.slice(i.end);return{text:r,redacted:n.length,secretTypes:[...s].sort()}}sanitizeValue(t){if(typeof t=="string")return this.sanitize(t).text;if(Array.isArray(t))return t.map(n=>this.sanitizeValue(n));if(t&&typeof t=="object"){let n={};for(let[r,o]of Object.entries(t)){let s=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")){n[r]="[REDACTED]";continue}n[r]=this.sanitizeValue(o)}return n}return t}};var ci=new H;function ue(e){return ci.sanitizeValue(e)}import{homedir as Li}from"node:os";import{join as Di}from"node:path";import{DeleteObjectCommand as ui,GetObjectCommand as li,HeadObjectCommand as di,ListObjectsV2Command as fi,PutObjectCommand as pi,S3Client as mi}from"@aws-sdk/client-s3";import{getSignedUrl as gi}from"@aws-sdk/s3-request-presigner";var Xe=class{name="huggingface";client;bucket;constructor(t){this.bucket=t.bucket,this.client=new mi({region:"us-east-1",endpoint:`https://s3.hf.co/${t.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,n,r="application/octet-stream"){let o=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new pi({Bucket:this.bucket,Key:t,Body:o,ContentType:r}))}async get(t){let n=await gi(this.client,new li({Bucket:this.bucket,Key:t}),{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(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await this.client.send(new di({Bucket:this.bucket,Key:t})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(t){await this.client.send(new ui({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let o=await this.client.send(new fi({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let s of o.Contents??[])s.Key&&n.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return n}};import{access as Fn,mkdir as yi,readFile as hi,readdir as ki,rm as Si,stat as Ln,writeFile as vi}from"node:fs/promises";import{dirname as wi,join as bi,relative as Dn,resolve as xi}from"node:path";var be=class{constructor(t){this.root=t}root;name="local";path(t){let n=t.replace(/^\/+/,"");return xi(this.root,n)}async put(t,n){let r=this.path(t);await yi(wi(r),{recursive:!0}),await vi(r,n)}async get(t){try{return await hi(this.path(t))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await Fn(this.path(t)),!0}catch{return!1}}async delete(t){await Si(this.path(t),{force:!0})}async list(t=""){let n=this.path(t),r=[];try{await Fn(n)}catch{return r}let o=async i=>{let a=await ki(i,{withFileTypes:!0});for(let c of a){let u=bi(i,c.name);if(c.isDirectory()){await o(u);continue}let p=await Ln(u);r.push({key:Dn(this.root,u),size:p.size,updatedAt:p.mtime.toISOString()})}},s=await Ln(n);return s.isDirectory()?await o(n):r.push({key:Dn(this.root,n),size:s.size,updatedAt:s.mtime.toISOString()}),r}};import{DeleteObjectCommand as Ai,GetObjectCommand as Ii,HeadObjectCommand as ji,ListObjectsV2Command as Mi,PutObjectCommand as Ei,S3Client as Pi}from"@aws-sdk/client-s3";import{getSignedUrl as Ci}from"@aws-sdk/s3-request-presigner";var xe=class{name;client;bucket;constructor(t){this.name=t.name??"s3",this.bucket=t.bucket,this.client=new Pi({region:t.region??"us-east-1",endpoint:t.endpoint||void 0,forcePathStyle:t.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,n,r="application/octet-stream"){let o=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Ei({Bucket:this.bucket,Key:t,Body:o,ContentType:r}))}async get(t){let n=await Ci(this.client,new Ii({Bucket:this.bucket,Key:t}),{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(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){try{return await this.client.send(new ji({Bucket:this.bucket,Key:t})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(t){await this.client.send(new Ai({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let o=await this.client.send(new Mi({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let s of o.Contents??[])s.Key&&n.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return n}};import{createCipheriv as Ti,createDecipheriv as Oi,createHash as Ri,randomBytes as Ni,timingSafeEqual as _i}from"node:crypto";import{readFileSync as $i}from"node:fs";var ee=Buffer.from("TNMEME01","ascii"),zn=1,Ae=8,Ie=12,Lt=16,qn=ee.length+1+Ae+Ie+Lt,Ki="toolnet-memory:remote-encryption:v1:",Bn="aes-256-gcm",Dt=32,j=class extends Error{constructor(n,r){super(r);this.code=n;this.name="RemoteEncryptionError"}code};function Fi(e){return e?["1","true","yes","on","enabled"].includes(e.trim().toLowerCase()):!1}function Wt(e=process.env){return Fi(e.TOOLNET_REMOTE_ENCRYPTION)}function Wn(e){let t=e.trim();if(!t)throw new j("REMOTE_ENCRYPTION_KEY_EMPTY","Remote encryption key is empty.");let n;if(t.startsWith("hex:")){let r=t.slice(4);if(!/^[0-9a-f]{64}$/iu.test(r))throw new j("REMOTE_ENCRYPTION_KEY_INVALID","hex: remote encryption key must contain exactly 64 hexadecimal characters.");n=Buffer.from(r,"hex")}else if(/^[0-9a-f]{64}$/iu.test(t))n=Buffer.from(t,"hex");else{let r=t.startsWith("base64:")?t.slice(7):t;if(!/^[A-Za-z0-9+/_-]+={0,2}$/u.test(r))throw new j("REMOTE_ENCRYPTION_KEY_INVALID","Remote encryption key must be 32 raw bytes encoded as hexadecimal or base64.");n=Buffer.from(r,r.includes("-")||r.includes("_")?"base64url":"base64")}if(n.length!==Dt)throw new j("REMOTE_ENCRYPTION_KEY_INVALID_LENGTH",`Remote encryption key must decode to exactly ${Dt} bytes.`);return n}function Vn(e=process.env){let t=e.TOOLNET_REMOTE_ENCRYPTION_KEY?.trim(),n=e.TOOLNET_REMOTE_ENCRYPTION_KEY_FILE?.trim();if(t&&n)throw new j("REMOTE_ENCRYPTION_KEY_AMBIGUOUS","Configure either TOOLNET_REMOTE_ENCRYPTION_KEY or TOOLNET_REMOTE_ENCRYPTION_KEY_FILE, not both.");if(t)return Wn(t);if(n){let r;try{r=$i(n,"utf8")}catch(o){throw new j("REMOTE_ENCRYPTION_KEY_FILE_READ_FAILED",[`Unable to read remote encryption key file: ${n}.`,o instanceof Error?o.message:String(o)].join(" "))}return Wn(r)}}function Hn(e){return Ri("sha256").update(e).digest().subarray(0,Ae)}function Jn(e){return Buffer.from(`${Ki}${e}`,"utf8")}function zt(e){return e.byteLength<ee.length?!1:Buffer.from(e).subarray(0,ee.length).equals(ee)}function Gn(e,t,n){if(n.byteLength!==Dt)throw new j("REMOTE_ENCRYPTION_KEY_INVALID_LENGTH","AES-256-GCM requires a 32-byte key.");let r=typeof t=="string"?Buffer.from(t,"utf8"):Buffer.from(t),o=Ni(Ie),s=Ti(Bn,n,o);s.setAAD(Jn(e));let i=Buffer.concat([s.update(r),s.final()]),a=s.getAuthTag(),c=Buffer.alloc(qn),u=0;return ee.copy(c,u),u+=ee.length,c.writeUInt8(zn,u),u+=1,Hn(n).copy(c,u),u+=Ae,o.copy(c,u),u+=Ie,a.copy(c,u),Buffer.concat([c,i])}function Un(e,t,n){let r=Buffer.from(t);if(!zt(r))throw new j("REMOTE_ENCRYPTION_ENVELOPE_REQUIRED","Payload is not a ToolNet encrypted remote object.");if(r.length<qn)throw new j("REMOTE_ENCRYPTION_ENVELOPE_TRUNCATED","Encrypted remote payload is truncated.");let o=ee.length,s=r.readUInt8(o);if(o+=1,s!==zn)throw new j("REMOTE_ENCRYPTION_VERSION_UNSUPPORTED",`Unsupported remote encryption envelope version: ${s}.`);let i=r.subarray(o,o+Ae);o+=Ae;let a=Hn(n);if(!_i(i,a))throw new j("REMOTE_ENCRYPTION_KEY_MISMATCH","Configured remote encryption key does not match this encrypted object.");let c=r.subarray(o,o+Ie);o+=Ie;let u=r.subarray(o,o+Lt);o+=Lt;let p=r.subarray(o),l=Oi(Bn,n,c);l.setAAD(Jn(e)),l.setAuthTag(u);try{return Buffer.concat([l.update(p),l.final()])}catch{throw new j("REMOTE_ENCRYPTION_AUTH_FAILED","Encrypted remote object failed AES-GCM authentication.")}}var qt=class{constructor(t,n){this.inner=t;this.options=n;if(this.name=t.name,n.enabled&&!n.key)throw new j("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote client-side encryption is enabled but no encryption key is configured.")}inner;options;name;async put(t,n,r){if(!this.options.enabled){await this.inner.put(t,n,r);return}let o=this.options.key;if(!o)throw new j("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote encryption key is unavailable.");let s=Gn(t,n,o);await this.inner.put(t,s,"application/octet-stream")}async get(t){let n=await this.inner.get(t);if(!n)return null;if(!zt(n))return n;if(!this.options.enabled)throw new j("REMOTE_ENCRYPTION_REQUIRED",["Remote object is client-side encrypted.","Enable TOOLNET_REMOTE_ENCRYPTION and configure the matching key."].join(" "));let r=this.options.key;if(!r)throw new j("REMOTE_ENCRYPTION_KEY_REQUIRED","Remote object is encrypted but no decryption key is configured.");return Un(t,n,r)}async getText(t){let n=await this.get(t);return n?Buffer.from(n).toString("utf8"):null}async exists(t){return this.inner.exists(t)}async delete(t){await this.inner.delete(t)}async list(t=""){return this.inner.list(t)}};function Yn(e,t=process.env){if(e.name==="local")return Wt(t)&&console.warn("[storage] Remote encryption requested but active storage provider is local; local data remains unchanged."),e;let n=Wt(t),r=n?Vn(t):void 0;return new qt(e,{enabled:n,key:r})}function je(e){return Yn(e)}function Bt(e,t){return console.warn(t),je(new be(e))}function Qn(e){let t=e.localRoot??Di(Li(),".toolnet-memory","storage");if(e.provider==="r2"){let n=e.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?je(new xe({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey})):Bt(t,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(e.provider==="s3"){let n=e.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?je(new xe({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey})):Bt(t,"[storage] S3 credentials missing. Using local fallback.")}if(e.provider==="huggingface"){let n=e.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?je(new Xe({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey})):Bt(t,"[storage] Hugging Face credentials missing. Using local fallback.")}return je(new be(t))}function Wi(e){return new Promise(t=>setTimeout(t,e))}async function Xn(e,t={}){let n=Math.max(1,t.attempts??3),r=t.baseDelayMs??150,o=t.maxDelayMs??2e3,s;for(let i=1;i<=n;i++)try{return await e()}catch(a){if(s=a,i>=n)break;let c=Math.min(o,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await Wi(c+u)}throw s}var zi=new Set(["put","get","getText","delete","list"]);function Zn(e,t={}){return new Proxy(e,{get(n,r){let o=Reflect.get(n,r,n);return typeof o!="function"?o:zi.has(r)?(...s)=>Xn(()=>Promise.resolve(o.apply(n,s)),t):o.bind(n)}})}function er(e){let t=e.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!t||t==="."||t==="..")throw new Error("Invalid project storage folder");return t}function tr(e){let t=e.replace(/^\/+/,"");if(t.startsWith("memories/"))return"memory/records/"+t.slice(9);if(t.startsWith("vectors/"))return"memory/vectors/"+t.slice(8);if(t.startsWith("graph/"))return"code/graph/"+t.slice(6);let n=t.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=t.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=t.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=t.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let o=t.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=t.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=t.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:t))}var Ze=class{constructor(t,n,r,o){this.provider=t;this.name=t.name,this.projectId=n,this.projectName=r,this.folder=er(o??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let t=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,o=await this.provider.getText(t);if(o){let i;try{i=JSON.parse(o)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${t}: ${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 s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(t,JSON.stringify(s,null,2)+`
|
|
4
|
+
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(t){if(t=tr(t),t===this.sourcePrefix)return this.targetPrefix;if(t.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+t.slice(this.sourcePrefix.length);if(t===this.targetPrefix||t.startsWith(`${this.targetPrefix}/`))return t;if(t.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${t}`].join(" "));return t}async put(t,n,r){return await this.ensureRegistered(),this.provider.put(this.key(t),n,r)}async get(t){return await this.ensureRegistered(),this.provider.get(this.key(t))}async getText(t){return await this.ensureRegistered(),this.provider.getText(this.key(t))}async delete(t){return await this.ensureRegistered(),this.provider.delete(this.key(t))}async exists(t){return await this.ensureRegistered(),this.provider.exists(this.key(t))}async list(t){return await this.ensureRegistered(),this.provider.list(this.key(t))}};import{spawn as qi}from"node:child_process";function nr(e){return(e??"").trim()}function rr(e,t={}){let n=nr(e);if(!n)return!1;let r=nr(t.binary??process.env.TOOLNET_MEMORY_BIN)||"toolnet-memory";try{let o=qi(r,["background:refresh","--project",n,"--quiet"],{detached:!0,stdio:"ignore",env:process.env});return o.on("error",()=>{}),o.unref(),!0}catch{return!1}}import{createHash as Bi}from"node:crypto";import{dirname as Vi}from"node:path";import{mkdirSync as Hi,readFileSync as Ji,renameSync as Gi,writeFileSync as Ui}from"node:fs";function w(e){return Bi("sha256").update(e).digest("hex")}function Vt(e){if(Array.isArray(e))return e.map(Vt);if(e&&typeof e=="object"){let t=e,n={};for(let r of Object.keys(t).sort())n[r]=Vt(t[r]);return n}return e}function or(e){return JSON.stringify(Vt(e))}function sr(e){try{return JSON.parse(Ji(e,"utf8"))}catch{return null}}function O(e,t){Hi(Vi(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;Ui(n,JSON.stringify(t,null,2)+`
|
|
5
|
+
`,{encoding:"utf8",mode:384}),Gi(n,e)}function ir(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function Ee(e){return e.toLowerCase().replace(/[^a-z0-9]/gu,"")}function Me(e,t,n=0){if(n>8)return;if(Array.isArray(e)){for(let o of e.slice(0,50))Me(o,t,n+1);return}let r=ir(e);if(r)for(let[o,s]of Object.entries(r))t(o,s,r),Me(s,t,n+1)}function le(e,t){let n=[];return Me(e,(r,o)=>{t.has(Ee(r))&&typeof o=="string"&&o.trim()&&n.push(o.trim())}),n}function Yi(e){let t=e.trim();if(!t.startsWith("{"))return null;try{return ir(JSON.parse(t))}catch{return null}}function Qi(e){let t=e.data;for(let r of["tool","toolName","tool_name"]){let o=t[r];if(typeof o=="string"&&o.trim())return o.trim().toLowerCase()}let n="";return Me(t,(r,o,s)=>{if(n)return;let i=Ee(r);if(["tool","toolname"].includes(i)&&typeof o=="string"){n=o.trim().toLowerCase();return}if(i!=="name"||typeof o!="string")return;let a=typeof s.type=="string"?s.type.toLowerCase():"";(a.includes("tool")||a.includes("function")||a.includes("command"))&&(n=o.trim().toLowerCase())}),n}function Xi(e){let t=le(e.data,new Set(["command","cmd","script"])),n=le(e.data,new Set(["arguments","args"]));for(let r of n){let o=Yi(r);if(o)for(let s of le(o,new Set(["command","cmd","script"])))t.push(s)}return Array.from(new Set(t.map(r=>r.trim()).filter(Boolean)))}function Zi(e){let t=le(e.data,new Set(["filepath","file_path","filename","file","path","target"].map(Ee)));return Array.from(new Set(t.map(n=>n.trim()).filter(n=>n.length>0&&n.length<1e3&&!n.includes(`
|
|
6
|
+
`))))}function ea(e,t){return e.type==="file_edit"||e.type==="file_write"?"modified":/\b(delete|remove|unlink)\b/iu.test(t)?"deleted":/\b(create|add[_-]?file|new[_-]?file)\b/iu.test(t)?"created":/\b(edit|write|patch|apply[_-]?patch|replace|update[_-]?file)\b/iu.test(t)?"modified":null}function ta(e){let t=le(e.data,new Set(["patch","diff","arguments","input"].map(Ee))),n=[];for(let r of t){let o=[{regex:/^\*\*\* Update File:\s*(.+)$/gimu,action:"modified"},{regex:/^\*\*\* Add File:\s*(.+)$/gimu,action:"created"},{regex:/^\*\*\* Delete File:\s*(.+)$/gimu,action:"deleted"}];for(let s of o)for(let i of r.matchAll(s.regex)){let a=i[1]?.trim();a&&n.push({kind:"file",text:a,fileAction:s.action,confidence:.99})}}return n}function na(e){let t=e.toLowerCase();return/\b(typecheck|type-check)\b/u.test(t)||/\btsc\b[\s\S]*--noemit\b/u.test(t)?"typecheck":/\b(eslint|lint)\b/u.test(t)?"lint":/\b(vitest|jest|pytest)\b/u.test(t)||/\bgo\s+test\b/u.test(t)||/\bcargo\s+test\b/u.test(t)||/\b(npm|pnpm|yarn)\s+(run\s+)?test\b/u.test(t)?"test":/\b(npm|pnpm|yarn)\s+(run\s+)?build\b/u.test(t)||/\bcargo\s+build\b/u.test(t)||/\bgo\s+build\b/u.test(t)||/\btsc\b/u.test(t)?"build":null}function ra(e){let t=null;return Me(e,(n,r)=>{if(t===null&&["exitcode","code"].includes(Ee(n))){if(typeof r=="number"&&Number.isFinite(r)){t=r;return}if(typeof r=="string"){let o=Number(r);Number.isFinite(o)&&(t=o)}}}),t}function oa(e){return le(e,new Set(["status","state","result","output","outputsummary","message","text"]))}function sa(e){let t=ra(e.data);if(t!==null)return t===0?"passed":"failed";let n=oa(e.data).join(`
|
|
7
|
+
`).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 ia(e){let t=[],n=new Set;for(let r of e){let o=[r.kind,r.fileAction??"",r.checkKind??"",r.checkStatus??"",r.text].join("|");n.has(o)||(n.add(o),t.push(r))}return t}function ar(e){let t=[],n=Qi(e),r=ea(e,n);if(r)for(let o of Zi(e))t.push({kind:"file",text:o,fileAction:r,confidence:e.type==="file_edit"||e.type==="file_write"?1:.96});t.push(...ta(e));for(let o of Xi(e)){t.push({kind:"command",text:o,confidence:.98});let s=na(o);s&&t.push({kind:"test",text:o,checkKind:s,checkStatus:sa(e),confidence:.98})}return ia(t)}var aa=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function ne(e){return e.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function ur(e){return ne(e).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function te(e,t,n=0){if(!(n>6)){if(typeof e=="string"){t.push(e);return}if(Array.isArray(e)){for(let r of e.slice(0,50))te(r,t,n+1);return}if(!(!e||typeof e!="object"))for(let[r,o]of Object.entries(e))(aa.has(r)||["data","payload","parts","messages"].includes(r))&&te(o,t,n+1)}}function et(e){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(e)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(e)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(e)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(e)?"in_progress":"pending"}function cr(e){let t=ne(e);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(t)}function E(e,t,n,r,o={}){let s=ne(r),i=o.key??ur(s);return{version:1,id:w([e.projectId,n,i,t.id,s,o.status??"",o.fileAction??"",o.checkKind??"",o.checkStatus??"",o.order??""].join("|")).slice(0,32),projectId:e.projectId,kind:n,key:i,text:s,status:o.status,fileAction:o.fileAction,checkKind:o.checkKind,checkStatus:o.checkStatus,order:o.order,confidence:o.confidence??.85,occurredAt:t.timestamp,sequence:t.sequence,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventId:t.id,sourceEventId:t.sourceEventId}}function ca(e,t,n){let r=ne(n);if(r.length<5||r.length>1200)return[];let o=[],s=/^(?: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]&&o.push(E(e,t,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&o.push(E(e,t,"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(;!s&&(u=c.exec(r));){let f=Number(u[1]),d=ne(u[2]??""),m=d&&!cr(d)?`Phase ${f} - ${d}`:`Phase ${f}`;o.push(E(e,t,"phase",m,{key:`phase:${f}`,order:f,status:et(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&o.push(E(e,t,"task",p[2],{status:p[1].trim()?"completed":et(p[2]),confidence:.96}));let l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let f=l[1]?Number(l[1]):void 0,d=ne(l[2]),m=cr(d);o.push(E(e,t,"task",m&&f!==void 0?`TODO ${f}`:d,{key:f!==void 0?`task:${f}`:ur(d),order:f,status:et(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 f=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");f&&o.push(E(e,t,"next_action",f,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&o.push(E(e,t,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&o.push(E(e,t,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&o.push(E(e,t,"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)&&o.push(E(e,t,"activity",r,{confidence:.86})),o}function tt(e,t){if(t.length===0)return[];let n=[],r=new Set;function o(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of t){if(i.type==="user_prompt"||i.role==="user"){let c=[];te(i.data,c);let u=c.map(p=>ne(p)).find(p=>p.length>=8&&p.length<=1200&&!/^\[?toolnet\b/iu.test(p));u&&o(E(e,i,"request",u,{confidence:.96}))}for(let c of ar(i))o(E(e,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=[];te(i.data,c);for(let u of c)o(E(e,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];te(i.data,c);for(let u of c)o(E(e,i,"task",u,{status:et(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&&o(E(e,i,"file",u,{fileAction:"modified",confidence:1}))}if(i.type==="test"){let c=[];te(i.data,c);for(let u of c)o(E(e,i,"test",u,{confidence:1}))}let a=[];te(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let p of ca(e,i,u))o(p)}let s=t[t.length-1];return o(E(e,s,"session",`${e.agent}:${e.nativeSessionId}`,{key:e.sessionKey,confidence:1})),n}function lr(e){return String(e).padStart(12,"0")}var nt=class{constructor(t){this.storage=t}storage;async write(t,n){if(n.length===0)return null;let r=Math.min(...n.map(p=>p.sequence)),o=Math.max(...n.map(p=>p.sequence)),s={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,createdAt:n.map(p=>p.occurredAt).sort().at(-1)??new Date().toISOString(),firstSequence:r,lastSequence:o,observations:n},i=JSON.stringify(s,null,2)+`
|
|
8
8
|
`,a=w(n.map(p=>JSON.stringify(p)).sort().join(`
|
|
9
|
-
`)).slice(0,24),c=w(t.sessionKey).slice(0,12),u=[`projects/${t.projectId}`,"work","observations",`${
|
|
10
|
-
`,"application/json"),
|
|
9
|
+
`)).slice(0,24),c=w(t.sessionKey).slice(0,12),u=[`projects/${t.projectId}`,"work","observations",`${lr(r)}-${lr(o)}-${c}-${a}.json`].join("/");return await this.storage.put(u,i,"application/json"),u}};import{join as dr}from"node:path";import{mkdirSync as ua}from"node:fs";function pr(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(e,t=20){let n=[],r=new Set;for(let o of e.slice().reverse()){let s=pr(o);if(!(!s||r.has(s))&&(r.add(s),n.push(o),n.length>=t))break}return n.reverse()}function la(e,t=20){let n=new Map;for(let r of e){let o=`${r.kind}|${pr(r.command)}`;n.delete(o),n.set(o,r)}return Array.from(n.values()).slice(-t)}function da(e){return e.kind==="phase"?/^Phase\s+\d+$/iu.test(e.text):e.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(e.text):!1}function fr(e,t){let n=t.status??e?.status??"pending",r=n;e&&(e.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(e.status==="in_progress"||e.status==="blocked")&&(r=e.status));let o=e&&da(t)?e.title:t.text;return{id:e?.id??w(t.key).slice(0,24),title:o,status:r,order:t.order??e?.order,confidence:Math.max(t.confidence,e?.confidence??0),updatedAt:t.occurredAt,updatedBy:{agent:t.agent,nativeSessionId:t.nativeSessionId,eventId:t.eventId}}}async function mr(e,t){let n=`projects/${e.id}/work/observations/`,r=await t.list(n),o=[];for(let s of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await t.getText(s.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&o.push(a)}catch{}}return o}async function Pe(e,t){let r=(await mr(e,t)).flatMap(y=>y.observations).sort((y,S)=>{let T=y.occurredAt.localeCompare(S.occurredAt);if(T!==0)return T;let V=y.sequence-S.sequence;return V!==0?V:y.id.localeCompare(S.id)}),o=new Map,s=new Map,i,a,c,u,p,l=[],f=[],d=[],m=[],k=[],g=new Map,h=[],v=[],x=[],R=[],C=[],N=[];for(let y of r)switch(y.kind){case"request":i=y.text;break;case"activity":a=y.text;break;case"goal":c=y.text;break;case"plan":u=y.text;break;case"phase":o.set(y.key,fr(o.get(y.key),y));break;case"task":s.set(y.key,fr(s.get(y.key),y));break;case"decision":l.push(y.text);break;case"blocker":f.push(y.text);break;case"warning":d.push(y.text);break;case"next_action":m.push(y.text);break;case"file":{k.push(y.text);let S=y.fileAction??"active";g.delete(y.text),g.set(y.text,S),S==="modified"?h.push(y.text):S==="created"?v.push(y.text):S==="deleted"&&x.push(y.text);break}case"command":R.push(y.text);break;case"test":C.push(y.text),y.checkKind&&N.push({kind:y.checkKind,command:y.text,status:y.checkStatus??"unknown",updatedAt:y.occurredAt,agent:y.agent,nativeSessionId:y.nativeSessionId});break;case"session":p={agent:y.agent,nativeSessionId:y.nativeSessionId,sessionKey:y.sessionKey,updatedAt:y.occurredAt};break}let A=Array.from(o.values()).sort((y,S)=>(y.order??Number.MAX_SAFE_INTEGER)-(S.order??Number.MAX_SAFE_INTEGER)),b=Array.from(s.values()).sort((y,S)=>(y.order??Number.MAX_SAFE_INTEGER)-(S.order??Number.MAX_SAFE_INTEGER)),z=A.find(y=>y.status==="in_progress")??A.find(y=>y.status==="blocked")??A.find(y=>y.status==="pending"),q=b.find(y=>y.status==="in_progress")??b.find(y=>y.status==="blocked")??b.find(y=>y.status==="pending"),Nt=F([...m,...q?[q.title]:[],...!q&&z?[z.title]:[],...b.filter(y=>y.status==="pending").slice(0,5).map(y=>y.title)],8),_t=F([...f,...A.filter(y=>y.status==="blocked").map(y=>y.title),...b.filter(y=>y.status==="blocked").map(y=>y.title)],20),he={version:1,projectId:e.id,projectName:e.name,currentRequest:i,currentActivity:a,goal:c,plan:u,phases:A,tasks:b,decisions:F(l,20),blockers:_t,warnings:F(d,20),nextActions:Nt,filesTouched:F(k,30),activeFiles:Array.from(g.entries()).filter(([,y])=>y!=="deleted").map(([y])=>y).slice(-5),modifiedFiles:F(h,30),createdFiles:F(v,30),deletedFiles:F(x,30),commands:F(R,20),tests:F(C,20),checks:la(N,20),currentPhase:z,currentTask:q,progress:{phasesTotal:A.length,phasesCompleted:A.filter(y=>y.status==="completed").length,tasksTotal:b.length,tasksCompleted:b.filter(y=>y.status==="completed").length,blocked:A.filter(y=>y.status==="blocked").length+b.filter(y=>y.status==="blocked").length},lastSession:p,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},Be=dr(e.rootPath,".toolnet","work");return ua(Be,{recursive:!0}),O(dr(Be,"current.json"),he),await t.put(`projects/${e.id}/work/current.json`,JSON.stringify(he,null,2)+`
|
|
10
|
+
`,"application/json"),he}async function de(e,t){if((await mr(e,t)).length>0)return Pe(e,t);let r=await t.getText(`projects/${e.id}/work/current.json`);if(!r)return null;try{return JSON.parse(r)}catch{return null}}import{closeSync as fa,existsSync as pa,openSync as ma,readSync as ga,statSync as ya}from"node:fs";function ha(e,t){if(!pa(e))return{events:[],nextOffset:t};let n=ya(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let o=n-r,s=Buffer.alloc(o),i=ma(e,"r");try{ga(i,s,0,o,r)}finally{fa(i)}let a=s.toString("utf8"),c=a.lastIndexOf(`
|
|
11
11
|
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
12
|
-
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var
|
|
12
|
+
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var rt=class{constructor(t){this.options=t;this.journal=new nt(t.storage)}options;journal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["work.continuity.offset"]??0),r=ha(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 o=tt(this.options.identity,r.events),s=!1,i=!1;return o.length>0&&(s=!!await this.journal.write(this.options.identity,o),s&&(await Pe(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:o.length,journalWritten:s,reconciled:i,nextOffset:r.nextOffset}}};import{existsSync as lc,mkdirSync as dc}from"node:fs";import{join as Ht}from"node:path";import{existsSync as hr,mkdirSync as ka,readFileSync as Sa,statSync as gr,writeFileSync as va}from"node:fs";import{dirname as wa,join as ba}from"node:path";var yr=64*1024,xa=`# ToolNet Project Operating Manual
|
|
13
13
|
|
|
14
14
|
This file contains persistent instructions for AI agents working on this project.
|
|
15
15
|
|
|
@@ -52,44 +52,44 @@ Things an AI agent should always remember.
|
|
|
52
52
|
<!--
|
|
53
53
|
- [advisory] Prefer small focused files.
|
|
54
54
|
-->
|
|
55
|
-
`;function
|
|
56
|
-
`,{encoding:"utf8"}),
|
|
57
|
-
`,{encoding:"utf8"}),
|
|
58
|
-
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function
|
|
55
|
+
`;function ot(e){return ba(e.rootPath,".toolnet","PROJECT.md")}function Aa(e){return e.normalize("NFKC").replace(/\s+/g," ").trim()}function Ia(e){let t=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,o;for(;o=r.exec(e);){let s=o[1].toLowerCase(),i=Aa(o[2]);if(!i)continue;let a=`${s}:${i.toLowerCase()}`;n.has(a)||(n.add(a),t.push({id:w(a).slice(0,24),mode:s,text:i,source:"manual"}))}return t}function ja(e){let t=ot(e);return hr(t)||(ka(wa(t),{recursive:!0}),va(t,xa,{encoding:"utf8",mode:384})),t}function st(e,t=!1){let n=t?ja(e):ot(e);if(!hr(n))return null;if(gr(n).size>yr)throw new Error(`PROJECT.md exceeds ${yr} bytes`);let o=Sa(n,"utf8");return{path:n,content:o,digest:w(o),rules:Ia(o),bytes:Buffer.byteLength(o,"utf8"),updatedAt:new Date(gr(n).mtimeMs).toISOString()}}import{randomUUID as Ma}from"node:crypto";import{closeSync as Ea,existsSync as kr,fsyncSync as Pa,mkdirSync as Ca,openSync as Ta,readFileSync as Oa,statSync as Ra,unlinkSync as Sr,writeFileSync as Na}from"node:fs";import{dirname as _a,join as $a}from"node:path";var Ka=new Int32Array(new SharedArrayBuffer(4));function Fa(e){e<=0||Atomics.wait(Ka,0,0,e)}function La(e){return $a(e.rootPath,".toolnet","work",".current.lock")}function Da(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t?.code!=="ESRCH"}}function vr(e){if(!kr(e))return null;try{let t=JSON.parse(Oa(e,"utf8"));return t.version!==1||typeof t.token!="string"||typeof t.pid!="number"||typeof t.acquiredAt!="string"?null:{version:1,token:t.token,pid:t.pid,acquiredAt:t.acquiredAt}}catch{return null}}function Wa(e){try{return Date.now()-Ra(e).mtimeMs}catch{return 0}}function za(e,t){if(!kr(e)||Wa(e)<t)return!1;let n=vr(e);return n?!Da(n.pid):!0}function qa(e,t){if(!za(e,t))return!1;try{return Sr(e),!0}catch{return!1}}function Ba(e,t){let n={version:1,token:t,pid:process.pid,acquiredAt:new Date().toISOString()},r=Ta(e,"wx",384);try{Na(r,`${JSON.stringify(n,null,2)}
|
|
56
|
+
`,{encoding:"utf8"}),Pa(r)}finally{Ea(r)}}function Va(e,t){if(vr(e)?.token===t)try{Sr(e)}catch{}}function Ha(e,t={}){let n=Math.max(100,t.timeoutMs??5e3),r=Math.max(5,t.retryMs??20),o=Math.max(n*2,t.staleMs??3e4),s=La(e);Ca(_a(s),{recursive:!0});let i=Ma(),a=Date.now()+n;for(;;)try{Ba(s,i);let c=!1;return()=>{c||(c=!0,Va(s,i))}}catch(c){if(c?.code!=="EEXIST")throw c;if(qa(s,o))continue;if(Date.now()>=a)throw new Error(`Timed out acquiring project work lock: ${s}`);Fa(r)}}function wr(e,t,n={}){let r=Ha(e,n);try{return t()}finally{r()}}import{closeSync as Ja,existsSync as Ga,fsyncSync as Ua,mkdirSync as Ya,openSync as Qa,readFileSync as Xa,renameSync as Za,writeFileSync as ec}from"node:fs";import{dirname as tc,join as nc}from"node:path";function rc(e,t){Ya(tc(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`,r=Qa(n,"w",384);try{ec(r,`${JSON.stringify(t,null,2)}
|
|
57
|
+
`,{encoding:"utf8"}),Ua(r)}finally{Ja(r)}Za(n,e)}function Mr(e){return nc(e.rootPath,".toolnet","work","current.json")}function Ce(e){let t=Mr(e);if(!Ga(t))return null;try{let n=JSON.parse(Xa(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function it(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(e,t,n){let r=[],o=new Set;for(let s of[...e,...t].reverse()){let i=it(s);if(!(!i||o.has(i))&&(o.add(i),r.push(s),r.length>=n))break}return r.reverse()}function oc(e,t,n=20){let r=new Map;for(let o of[...e,...t]){let s=`${o.kind}|${it(o.command)}`;r.delete(s),r.set(s,o)}return Array.from(r.values()).slice(-n)}function sc(e){return e.kind==="phase"?/^Phase\s+\d+$/iu.test(e.text):e.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(e.text):!1}function br(e,t){let n=t.status??e?.status??"pending",r=n;e?.status==="completed"&&n!=="completed"&&(r="completed"),e&&n==="pending"&&(e.status==="in_progress"||e.status==="blocked")&&(r=e.status);let o=e&&sc(t)?e.title:t.text;return{id:e?.id??t.id,title:o,status:r,order:t.order??e?.order,confidence:Math.max(e?.confidence??0,t.confidence),updatedAt:t.occurredAt,updatedBy:{agent:t.agent,nativeSessionId:t.nativeSessionId,eventId:t.eventId}}}function xr(e){let t=new Map;for(let n of e){let r=n.order!==void 0?`order:${n.order}`:it(n.title);t.set(r,n)}return t}function Ar(e){return e.order!==void 0?`order:${e.order}`:it(e.key||e.text)}function Ir(e){return Array.from(e).sort((t,n)=>{let r=t.order??Number.MAX_SAFE_INTEGER,o=n.order??Number.MAX_SAFE_INTEGER;return r!==o?r-o:t.updatedAt.localeCompare(n.updatedAt)})}function jr(e){return e.find(t=>t.status==="in_progress")??e.find(t=>t.status==="blocked")??e.find(t=>t.status==="pending")}function ic(e,t){let n=Ce(e),r=xr(n?.phases??[]),o=xr(n?.tasks??[]),s=n?.currentRequest,i=n?.currentActivity,a=n?.goal,c=n?.plan,u=n?.lastSession,p=[],l=[],f=[],d=[],m=[],k=[...n?.activeFiles??[]],g=[],h=[],v=[],x=[],R=[],C=[],N=[...t].sort((S,T)=>{let V=S.occurredAt.localeCompare(T.occurredAt);return V!==0?V:S.sequence-T.sequence});for(let S of N)switch(S.kind){case"request":s=S.text;break;case"activity":i=S.text;break;case"goal":a=S.text;break;case"plan":c=S.text;break;case"phase":{let T=Ar(S);r.set(T,br(r.get(T),S));break}case"task":{let T=Ar(S);o.set(T,br(o.get(T),S));break}case"decision":p.push(S.text);break;case"blocker":l.push(S.text);break;case"warning":f.push(S.text);break;case"next_action":d.push(S.text);break;case"file":{m.push(S.text);let T=S.fileAction??"active",V=k.indexOf(S.text);V>=0&&k.splice(V,1),T!=="deleted"&&k.push(S.text),T==="modified"?g.push(S.text):T==="created"?h.push(S.text):T==="deleted"&&v.push(S.text);break}case"command":x.push(S.text);break;case"test":R.push(S.text),S.checkKind&&C.push({kind:S.checkKind,command:S.text,status:S.checkStatus??"unknown",updatedAt:S.occurredAt,agent:S.agent,nativeSessionId:S.nativeSessionId});break;case"session":u={agent:S.agent,nativeSessionId:S.nativeSessionId,sessionKey:S.sessionKey,updatedAt:S.occurredAt};break}let A=Ir(r.values()),b=Ir(o.values()),z=jr(A),q=jr(b),Nt=$(n?.nextActions??[],[...d,...q?[q.title]:[],...!q&&z?[z.title]:[],...b.filter(S=>S.status==="pending").slice(0,5).map(S=>S.title)],8),_t=$(n?.blockers??[],[...l,...A.filter(S=>S.status==="blocked").map(S=>S.title),...b.filter(S=>S.status==="blocked").map(S=>S.title)],20),he=N.length>0?N[N.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),Be={version:1,projectId:e.id,projectName:e.name,currentRequest:s,currentActivity:i,goal:a,plan:c,phases:A,tasks:b,decisions:$(n?.decisions??[],p,20),blockers:_t,warnings:$(n?.warnings??[],f,20),nextActions:Nt,filesTouched:$(n?.filesTouched??[],m,30),activeFiles:$([],k,5),modifiedFiles:$(n?.modifiedFiles??[],g,30),createdFiles:$(n?.createdFiles??[],h,30),deletedFiles:$(n?.deletedFiles??[],v,30),commands:$(n?.commands??[],x,20),tests:$(n?.tests??[],R,20),checks:oc(n?.checks??[],C,20),currentPhase:z,currentTask:q,progress:{phasesTotal:A.length,phasesCompleted:A.filter(S=>S.status==="completed").length,tasksTotal:b.length,tasksCompleted:b.filter(S=>S.status==="completed").length,blocked:A.filter(S=>S.status==="blocked").length+b.filter(S=>S.status==="blocked").length},lastSession:u,updatedAt:he},y=ue(Be);return rc(Mr(e),y),y}function Er(e,t){return wr(e,()=>ic(e,t))}function P(e,t){let n=new Set,r=[];for(let o of e){let s=o.replace(/\s+/g," ").trim();if(!s)continue;let i=s.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(s),r.length>=t))break}return r}function Pr(e){if(e)return{id:e.id,title:e.title,status:e.status}}function ac(e,t=[]){let n=t.slice(-10);if(n.some(o=>o.status==="failed"))return"failing";if(n.some(o=>o.status==="passed"))return"passing";let r=e.slice(-10).join(`
|
|
58
|
+
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function cc(e){return w(JSON.stringify(e))}function uc(e){let t=[];for(let n of e){if(!n)continue;let r=n.match(/https?:\/\/[^\s<>"'`)\]}]+/giu)??[];for(let o of r){let s=o.replace(/[.,;:!?]+$/gu,"").trim();s&&t.push(s)}}return P(t,30)}function Cr(e){let{project:t,identity:n,state:r}=e,o=r.activeFiles?.at(-1)??r.filesTouched.at(-1),s=r.phases.filter(v=>v.status==="completed").map(v=>v.title),i=r.tasks.filter(v=>v.status==="completed").map(v=>v.title),a=r.phases.filter(v=>v.status!=="completed"&&v.status!=="cancelled").map(v=>v.title),c=r.tasks.filter(v=>v.status!=="completed"&&v.status!=="cancelled").map(v=>v.title),u=new Set(r.tasks.filter(v=>v.status==="completed").map(v=>v.title.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),p=P(r.nextActions.filter(v=>!u.has(v.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),10),l=P([...c,...p],15),f=P(r.tests.slice().reverse(),10),d=P([...(r.activeFiles??[]).slice().reverse(),...r.filesTouched.slice().reverse()],20),m={schema:"toolnet.handoff.v2",version:2,project:{id:t.id,name:t.name},source:{agent:n.agent,nativeSessionId:n.nativeSessionId,sessionKey:n.sessionKey,sequence:e.sequence,reason:e.reason},capturedAt:e.capturedAt??new Date().toISOString(),goal:r.goal,request:r.currentRequest,activity:r.currentActivity,current:{phase:Pr(r.currentPhase),task:Pr(r.currentTask),file:o},completed:{phases:P(s,20),tasks:P(i,30)},remaining:{phases:P(a,20),tasks:P(c,30),todos:l},nextAction:p[0],blockers:P(r.blockers.slice().reverse(),10),decisions:P(r.decisions.slice().reverse(),10),files:{current:o,recent:d,active:P(r.activeFiles??[],10),modified:P(r.modifiedFiles??[],20),created:P(r.createdFiles??[],20),deleted:P(r.deletedFiles??[],20)},tests:{status:ac(r.tests,r.checks),recent:f,checks:(r.checks??[]).slice(-10).map(v=>({kind:v.kind,status:v.status,command:v.command}))},evidence:{commands:P((r.commands??[]).slice().reverse(),20),references:uc([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(v=>v.command)])},attention:P(e.attention??[],20),progress:r.progress},{capturedAt:k,source:g,...h}=m;return{...m,stateDigest:cc(h)}}function fc(e){return!!(e.currentRequest||e.currentActivity||e.goal||e.plan||e.phases.length>0||e.tasks.length>0||e.nextActions.length>0||e.blockers.length>0||e.decisions.length>0||e.filesTouched.length>0)}function Tr(e,t,n,r,o){if(!fc(n))return null;let s=st(e,!1),a=[...s?s.rules.filter(l=>l.mode==="enforce").map(l=>l.text):[],...n.warnings].slice(0,20),c=Cr({project:e,identity:t,state:n,reason:r,sequence:o,attention:a}),u=c.stateDigest;return{version:1,id:w([e.id,t.sessionKey,u].join("|")).slice(0,24),projectId:e.id,projectName:e.name,createdAt:new Date().toISOString(),reason:r,sourceSession:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,sequence:o},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(l=>l.status!=="completed"&&l.status!=="cancelled"),incompleteTasks:n.tasks.filter(l=>l.status!=="completed"&&l.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 Or(e,t){let n=Ht(e.rootPath,".toolnet","work","handoffs");dc(n,{recursive:!0});let r=Ht(n,`${t.id}.json`);lc(r)||O(r,t),O(Ht(e.rootPath,".toolnet","work","handoff-latest.json"),t)}function Rr(e){let t=Tr(e.project,e.identity,e.state,e.reason,e.sequence);return t?(Or(e.project,t),t):null}var at=class{constructor(t){this.options=t}options;async capture(t,n){let r=Ce(this.options.project);r||(r=await de(this.options.project,this.options.storage)),r||(r=await Pe(this.options.project,this.options.storage));let o=Tr(this.options.project,this.options.identity,r,t,n);if(!o)return null;Or(this.options.project,o);let s=`projects/${this.options.project.id}/work/handoffs/${o.id}.json`;return await this.options.storage.exists(s)||await this.options.storage.put(s,JSON.stringify(o,null,2)+`
|
|
59
59
|
`,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(o,null,2)+`
|
|
60
|
-
`,"application/json"),o}};async function
|
|
61
|
-
`,"application/json"),d}async function
|
|
62
|
-
`);if(
|
|
63
|
-
`)),i=Math.max(0,t-s);if(i>=16){let a=Math.floor(i*3.2),c=
|
|
64
|
-
`).trim()}async function
|
|
65
|
-
`,"application/json"),c}};import{closeSync as
|
|
60
|
+
`,"application/json"),o}};async function Nr(e,t){let n=await t.getText(`projects/${e.id}/work/handoff-latest.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}import{mkdirSync as pc}from"node:fs";import{join as _r}from"node:path";function mc(e){return{value:e.value,confidence:e.confidence,evidence:e.evidence}}function gc(e,t){if(!t)return!0;let n=e.evidence.occurredAt.localeCompare(t.evidence.occurredAt);return n!==0?n>0:e.evidence.sessionKey===t.evidence.sessionKey?e.evidence.sequence>=t.evidence.sequence:e.confidence>=t.confidence}function J(e,t){return gc(t,e)?t:e}function G(e,t=30){let n=new Set,r=[];for(let o of e){let s=o.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!s||n.has(s)||(n.add(s),r.push(o))}return r.slice(-t)}async function yc(e,t){let n=`projects/${e.id}/work/semantic/observations/`,r=await t.list(n),o=[];for(let s of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await t.getText(s.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&o.push(a)}catch{}}return o}function hc(e){return{key:e.scopeKey??`phase:${e.scopeOrder??0}`,order:e.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function $r(e,t){let r=(await yc(e,t)).flatMap(k=>k.observations).sort((k,g)=>{let h=k.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return h!==0?h:k.evidence.sessionKey===g.evidence.sessionKey?k.evidence.sequence-g.evidence.sequence:k.id.localeCompare(g.id)}),o,s,i,a,c,u=new Map,p=[],l=[],f=[];for(let k of r){let g=mc(k);if(k.scope==="phase"&&k.scopeKey){let h=u.get(k.scopeKey)??hc(k);switch(k.kind){case"phase_objective":h.objective=J(h.objective,g);break;case"phase_why":h.why=J(h.why,g);break;case"phase_deliverable":h.deliverable=J(h.deliverable,g);break;case"acceptance_criterion":h.acceptanceCriteria.push(g);break;case"dependency":h.dependencies.push(g);break;case"open_question":h.openQuestions.push(g);break;case"constraint":h.constraints.push(g);break;case"note":h.notes.push(g);break}u.set(h.key,h);continue}switch(k.kind){case"mission":o=J(o,g);break;case"objective":s=J(s,g);break;case"why":i=J(i,g);break;case"desired_outcome":a=J(a,g);break;case"plan_rationale":c=J(c,g);break;case"open_question":p.push(g);break;case"constraint":l.push(g);break;case"note":f.push(g);break}}for(let k of u.values())k.acceptanceCriteria=G(k.acceptanceCriteria,20),k.dependencies=G(k.dependencies,15),k.openQuestions=G(k.openQuestions,15),k.constraints=G(k.constraints,15),k.notes=G(k.notes,20);let d={version:1,projectId:e.id,projectName:e.name,mission:o,activeObjective:s,why:i,desiredOutcome:a,planRationale:c,phases:Array.from(u.values()).sort((k,g)=>k.order-g.order),openQuestions:G(p,20),constraints:G(l,20),notes:G(f,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},m=_r(e.rootPath,".toolnet","work");return pc(m,{recursive:!0}),O(_r(m,"semantic-current.json"),d),await t.put(`projects/${e.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
|
|
61
|
+
`,"application/json"),d}async function Kr(e,t){let n=await t.getText(`projects/${e.id}/work/semantic/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Jt(e){if(!e)return 0;let t=Array.from(e).length,n=e.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(t/3.5,n*1.3))}function I(e,t){let n=e.replace(/\s+/g," ").trim();return n.length<=t?n:n.slice(0,Math.max(0,t-1)).trimEnd()+"\u2026"}function kc(e){let t=[],n=!1;for(let r of e.split(/\r?\n/u)){let o=r.trim();if(o.includes("<!--")&&(n=!0),n){o.includes("-->")&&(n=!1);continue}let s=o.toLowerCase();if(!(!o||o.startsWith("#")||o==="```"||s.startsWith("- [enforce]")||s.startsWith("* [enforce]")||s.startsWith("- [advisory]")||s.startsWith("* [advisory]"))&&(o=o.replace(/^[-*]\s+/u,""),o&&t.push(I(o,280)),t.length>=16))break}return t}function Sc(e){let t=[],n=[];for(let r of e.split(/\\r?\\n/u)){let o=r.trim(),s=o.toLowerCase(),a=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(u=>s.startsWith(u));if(!a)continue;let c=o.slice(a.length).trim();c&&(a.includes("enforce")?t.push(c):n.push(c))}return{enforce:t,advisory:n}}function vc(e,t){let n=[];for(let r of e){let o=[...n,r].join(`
|
|
62
|
+
`);if(Jt(o)<=t){n.push(r);continue}let s=Jt(n.join(`
|
|
63
|
+
`)),i=Math.max(0,t-s);if(i>=16){let a=Math.floor(i*3.2),c=I(r,a);c&&n.push(c)}break}return n.join(`
|
|
64
|
+
`).trim()}async function Fr(e){let t=Math.max(256,Math.min(2e3,e.maxTokens??1e3)),n=st(e.project,!1),r=n?.content??"";r||(r=await e.storage.getText(`projects/${e.project.id}/project/manual.md`)??"");let o=Sc(r),s=n?n.rules.filter(d=>d.mode==="enforce").map(d=>d.text):o.enforce,i=n?n.rules.filter(d=>d.mode==="advisory").map(d=>d.text):o.advisory,a=r?kc(r):[],c=await de(e.project,e.storage),u=await Kr(e.project,e.storage),p=await Nr(e.project,e.storage),l=[];if(l.push("[TOOLNET PROJECT CONTEXT]"),l.push(`Project: ${e.project.name}`),l.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),r&&l.push(`Full operating manual: ${ot(e.project)}`),s.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of s.slice(0,24))l.push(`- [ENFORCE] ${I(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${I(d,220)}`)}if(u&&(u.mission&&l.push("","MISSION",I(u.mission.value,420)),u.activeObjective&&l.push("","CURRENT OBJECTIVE",I(u.activeObjective.value,420)),u.why&&l.push("","WHY THIS WORK MATTERS",I(u.why.value,420)),u.desiredOutcome&&l.push("","DESIRED OUTCOME",I(u.desiredOutcome.value,420)),u.planRationale&&l.push("","WHY THIS APPROACH",I(u.planRationale.value,420))),c){if(l.push("","ACTIVE WORK"),c.goal&&l.push(`Goal: ${I(c.goal,320)}`),c.plan&&l.push(`Plan: ${I(c.plan,320)}`),l.push(`Progress: phases ${c.progress.phasesCompleted}/${c.progress.phasesTotal}; tasks ${c.progress.tasksCompleted}/${c.progress.tasksTotal}; blocked ${c.progress.blocked}`),c.currentPhase&&l.push(`Current phase: ${c.currentPhase.title} [${c.currentPhase.status}]`),c.currentPhase&&u){let d=u.phases.find(m=>m.order===c.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${I(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${I(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${I(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(m=>I(m.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(m=>{l.push(`- ${I(m.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(m=>{l.push(`- ${I(m.value,260)}`)})))}c.currentTask&&l.push(`Current task: ${c.currentTask.title} [${c.currentTask.status}]`),c.nextActions.length&&(l.push("","NEXT ACTIONS"),c.nextActions.slice(0,6).forEach((d,m)=>{l.push(`${m+1}. ${I(d,260)}`)})),c.blockers.length&&(l.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(d=>{l.push(`- ${I(d,260)}`)})),c.warnings.length&&(l.push("","ATTENTION"),c.warnings.slice(-5).forEach(d=>{l.push(`- ${I(d,260)}`)})),c.decisions.length&&(l.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(d=>{l.push(`- ${I(d,260)}`)})),c.lastSession&&l.push("",`Last work session: ${c.lastSession.agent} / ${c.lastSession.nativeSessionId}`)}if(u&&u.openQuestions.length&&(l.push("","UNRESOLVED QUESTIONS"),u.openQuestions.slice(0,5).forEach(d=>{l.push(`- ${I(d.value,260)}`)})),p&&l.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),a.length){l.push("","OPERATING NOTES");for(let d of a)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let f=vc(l,t);return{version:1,projectId:e.project.id,projectName:e.project.name,text:f,estimatedTokens:Jt(f),maxTokens:t,hasManual:!!r,hasWorkState:!!c,hasHandoff:!!p,generatedAt:new Date().toISOString()}}var wc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function fe(e){return e.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Gt(e,t,n=0){if(!(n>6)){if(typeof e=="string"){t.push(e);return}if(Array.isArray(e)){for(let r of e.slice(0,50))Gt(r,t,n+1);return}if(!(!e||typeof e!="object"))for(let[r,o]of Object.entries(e))(wc.has(r)||["data","payload","parts","messages"].includes(r))&&Gt(o,t,n+1)}}function K(e,t,n,r,o,s=.95){let i=fe(r);return{version:1,id:w([e.projectId,n,o.type,o.key??"",i.toLowerCase(),t.id].join("|")).slice(0,32),projectId:e.projectId,kind:n,value:i,scope:o.type,scopeKey:o.key,scopeOrder:o.order,confidence:s,evidence:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventId:t.id,sourceEventId:t.sourceEventId,sequence:t.sequence,occurredAt:t.timestamp}}}function L(e,t){let n=e.toLowerCase();for(let r of t){let o=r.toLowerCase();if(n.startsWith(`${o}:`)||n.startsWith(`${o} -`)||n.startsWith(`${o} \u2014`))return fe(e.slice(r.length+1))}return null}function bc(e){let t=e.trimStart();return t.startsWith("- ")||t.startsWith("* ")||/^\d+[.)]\s+/u.test(t)}function xc(e){return fe(e.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function Lr(e,t){let n=[],r=new Set;function o(s){!s.value||s.value.length<3||r.has(s.id)||(r.add(s.id),n.push(s))}for(let s of t){let i=[];Gt(s.data,i);for(let a of i){let c={type:"project"},u=null;for(let p of a.split(/\r?\n/u)){let l=fe(p);if(!l){u=null;continue}let f=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let b=Number(f[1]);c={type:"phase",key:`phase:${b}`,order:b,title:fe(f[2]??"")},u=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let b=Number(d[1]);c={type:"task",key:`task:${b}`,order:b,title:fe(d[2]??"")},u=null;continue}let m=L(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(m){o(K(e,s,"mission",m,{type:"project"},.99)),u=null;continue}let k=L(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(k){o(K(e,s,c.type==="phase"?"phase_objective":"objective",k,c,.98)),u=null;continue}let g=L(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){o(K(e,s,c.type==="phase"?"phase_why":"why",g,c,.98)),u=null;continue}let h=L(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){o(K(e,s,"desired_outcome",h,{type:"project"},.98)),u=null;continue}let v=L(l,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(v){o(K(e,s,"plan_rationale",v,{type:"project"},.98)),u=null;continue}let x=L(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(x){o(K(e,s,"phase_deliverable",x,c,.97)),u=null;continue}let R=L(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(R){o(K(e,s,"acceptance_criterion",R,c,.98)),u="acceptance_criterion";continue}let C=L(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(C){o(K(e,s,"dependency",C,c,.97)),u="dependency";continue}let N=L(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(N){o(K(e,s,"open_question",N,c,.95)),u="open_question";continue}let A=L(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(A){o(K(e,s,"constraint",A,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){u="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){u="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){u="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){u="constraint";continue}if(u&&bc(p)){o(K(e,s,u,xc(p),c,.96));continue}u=null}}}return n}function Dr(e){return String(e).padStart(12,"0")}var ct=class{constructor(t){this.storage=t}storage;async write(t,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.evidence.sequence)),o=Math.max(...n.map(u=>u.evidence.sequence)),s={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:r,lastSequence:o,createdAt:new Date().toISOString(),observations:n},i=w(n.map(u=>u.id).sort().join("|")).slice(0,16),a=w(t.sessionKey).slice(0,12),c=[`projects/${t.projectId}`,"work","semantic","observations",`${Dr(r)}-${Dr(o)}-${a}-${i}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,JSON.stringify(s,null,2)+`
|
|
65
|
+
`,"application/json"),c}};import{closeSync as Ac,existsSync as Ic,openSync as jc,readSync as Mc,statSync as Ec}from"node:fs";function Pc(e,t){if(!Ic(e))return{events:[],nextOffset:t};let n=Ec(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let o=Buffer.alloc(n-r),s=jc(e,"r");try{Mc(s,o,0,o.length,r)}finally{Ac(s)}let i=o.toString("utf8"),a=i.lastIndexOf(`
|
|
66
66
|
`);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
|
|
67
|
-
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var
|
|
68
|
-
`),a=Math.max(s,i);return a>r*.7?o.slice(0,a+1):o}function
|
|
67
|
+
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var ut=class{constructor(t){this.options=t;this.journal=new ct(t.storage)}options;journal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["work.semantic.offset"]??0),r=Pc(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 o=Lr(this.options.identity,r.events),s=!1,i=!1;return o.length>0&&(s=!!await this.journal.write(this.options.identity,o),s&&(await $r(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:o.length,journalWritten:s,reconciled:i,nextOffset:r.nextOffset}}};import{existsSync as Cc,mkdirSync as Tc,readFileSync as Oc,writeFileSync as Rc}from"node:fs";import{dirname as Nc,join as Wr}from"node:path";function lt(e){return e?Math.ceil(e.length/3.5):0}function dt(e,t){if(!e)return"";if(lt(e)<=t)return e;let r=Math.floor(t*3.5),o=e.slice(0,r),s=o.lastIndexOf("."),i=o.lastIndexOf(`
|
|
68
|
+
`),a=Math.max(s,i);return a>r*.7?o.slice(0,a+1):o}function zr(e){return Wr(e.rootPath,".toolnet","context","startup.md")}function _c(e){return Wr(e.rootPath,".toolnet","context","startup.json")}function qr(e,t){let n=zr(e);Tc(Nc(n),{recursive:!0}),Rc(n,t.text.endsWith(`
|
|
69
69
|
`)?t.text:t.text+`
|
|
70
|
-
`,{encoding:"utf8",mode:384}),
|
|
70
|
+
`,{encoding:"utf8",mode:384}),O(_c(e),t)}async function Ut(e,t,n=800){let o=(await Fr({project:e,storage:t,maxTokens:n})).text;lt(o)>n&&(o=dt(o,n),o+=`
|
|
71
71
|
|
|
72
72
|
[Context trimmed by ToolNet Memory token budget]
|
|
73
|
-
`);let i={version:1,projectId:e.id,projectName:e.name,text:o,digest:w(o),estimatedTokens:
|
|
73
|
+
`);let i={version:1,projectId:e.id,projectName:e.name,text:o,digest:w(o),estimatedTokens:lt(o),generatedAt:new Date().toISOString()};return qr(e,i),await t.put(`projects/${e.id}/context/startup.md`,i.text+`
|
|
74
74
|
`,"text/markdown"),await t.put(`projects/${e.id}/context/startup.json`,JSON.stringify(i,null,2)+`
|
|
75
|
-
`,"application/json"),i}async function
|
|
75
|
+
`,"application/json"),i}async function Br(e,t,n=900){try{let o=await t.getText(`projects/${e.id}/context/startup.md`);if(o&&o.trim()){let s=o.trim(),i={version:1,projectId:e.id,projectName:e.name,text:s,digest:w(s),estimatedTokens:Math.ceil(s.length/3.5),generatedAt:new Date().toISOString()};return qr(e,i),i}}catch{}let r=zr(e);if(Cc(r))try{let o=Oc(r,"utf8").trim();if(o)return{version:1,projectId:e.id,projectName:e.name,text:o,digest:w(o),estimatedTokens:Math.ceil(o.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await Ut(e,t,n)}catch{return null}}import{existsSync as no,mkdirSync as Zc,readFileSync as ro}from"node:fs";import{homedir as eu}from"node:os";import{dirname as tu,join as en}from"node:path";var Yt="memory_agent_ask";function Vr(){return`
|
|
76
76
|
[TOOLNET MEMORY AGENT]
|
|
77
77
|
|
|
78
78
|
Tool:
|
|
79
|
-
- ${
|
|
79
|
+
- ${Yt}
|
|
80
80
|
|
|
81
81
|
For resume/continue requests:
|
|
82
82
|
|
|
83
83
|
1. Use the injected ToolNet continuity handoff FIRST.
|
|
84
84
|
2. If the handoff is missing or ambiguous, invoke
|
|
85
|
-
${
|
|
85
|
+
${Yt} directly BEFORE repository/history exploration.
|
|
86
86
|
3. NEVER reconstruct prior work from:
|
|
87
87
|
- .toolnet/journal/**, .toolnet/runtime/sources/**, and legacy .toolnet/sessions/**
|
|
88
88
|
- state.json
|
|
89
89
|
- events.jsonl
|
|
90
90
|
- raw transcripts
|
|
91
91
|
4. NEVER search for the implementation/schema of
|
|
92
|
-
${
|
|
92
|
+
${Yt}; invoke the MCP tool directly.
|
|
93
93
|
5. Inspect git/source only AFTER continuity context is known.
|
|
94
94
|
|
|
95
95
|
Use:
|
|
@@ -97,44 +97,44 @@ Use:
|
|
|
97
97
|
- No AI/LLM mode exists.
|
|
98
98
|
|
|
99
99
|
Current repository evidence overrides stale memory.
|
|
100
|
-
`.trim()}import{createHash as
|
|
101
|
-
`)}function
|
|
102
|
-
`;
|
|
100
|
+
`.trim()}import{createHash as $c}from"node:crypto";import{chmodSync as Jr,existsSync as Kc,mkdirSync as Fc,readFileSync as Lc,renameSync as Dc,writeFileSync as Gr}from"node:fs";import{dirname as Ur,join as ft}from"node:path";var Zt="toolnet.context-offload.v1",Wc="toolnet.context-offload-asset.v1",zc=256,qc=new Set(["tool_call","tool_result","file_read","file_write","file_edit","command","test","artifact"]);function Yr(e){return ft(e,".toolnet","offload")}function Bc(e){return ft(Yr(e),"assets")}function Qr(e){return ft(Yr(e),"graph.json")}function Xr(e){Fc(e,{recursive:!0,mode:448});try{Jr(e,448)}catch{}}function Vc(e,t){Xr(Ur(e));let n=`${e}.${process.pid}.${Date.now()}.tmp`;Gr(n,t,{encoding:"utf8",mode:384}),Dc(n,e);try{Jr(e,384)}catch{}}function Xt(e){return Array.isArray(e)?e.map(Xt):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,Xt(n)])):e}function Hc(e){return $c("sha256").update(JSON.stringify(Xt(e)),"utf8").digest("hex")}function Qt(){return{schema:Zt,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function Zr(e){let t=Qr(e);if(!Kc(t))return Qt();try{let n=JSON.parse(Lc(t,"utf8"));return n.schema!==Zt||n.version!==1||!Array.isArray(n.nodes)?Qt():n}catch{return Qt()}}function Jc(e,t){Vc(Qr(e),JSON.stringify(t,null,2)+`
|
|
101
|
+
`)}function Gc(e,t=260){if(typeof e!="string")return null;let n=e.replace(/\s+/gu," ").trim();return n?n.slice(0,t):null}function Uc(e){let t=[...e.provenance.files??[],e.provenance.sourcePath],n=[];for(let r of t){let o=Gc(r);if(!(!o||n.includes(o))&&(n.push(o),n.length===3))break}return n}function Yc(e){return`${e.agent}:${e.sourceEventId??e.id}`.replace(/\s+/gu," ").trim().slice(0,120)}function Qc(e,t){Xr(Ur(e));try{return Gr(e,t,{encoding:"utf8",flag:"wx",mode:384}),!0}catch(n){if(n.code==="EEXIST")return!1;throw n}}function Xc(e,t){let n=e.nodes.find(o=>o.id===t.id),r=n?{...n,kind:t.kind,bytes:t.bytes,sourceRefs:Array.from(new Set([...n.sourceRefs,...t.sourceRefs])).slice(-8),files:Array.from(new Set([...n.files,...t.files])).slice(0,6)}:t;return{schema:Zt,version:1,updatedAt:new Date().toISOString(),nodes:[...e.nodes.filter(o=>o.id!==t.id),r].slice(-zc)}}function eo(e,t){let n=Zr(e),r=0,o=0,s=0,i=[];for(let a of t){if(!qc.has(a.type))continue;r+=1;let c=Hc({type:a.type,data:a.data}),u={schema:Wc,version:1,assetId:c,event:{type:a.type,agent:a.agent,nativeSessionId:a.nativeSessionId,timestamp:a.timestamp,sourceEventId:a.sourceEventId,provenance:a.provenance,data:a.data}},p=JSON.stringify(u,null,2)+`
|
|
102
|
+
`;Qc(ft(Bc(e),`${c}.json`),p)?o+=1:s+=1,i.push(c),n=Xc(n,{id:c,kind:a.type,bytes:Buffer.byteLength(p,"utf8"),createdAt:a.timestamp,sourceRefs:[Yc(a)],files:Uc(a)})}return r>0&&Jc(e,n),{eligible:r,written:o,deduped:s,graphNodes:n.nodes.length,assetIds:i}}function Hr(e,t){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:n.slice(0,t-1).trimEnd()+"\u2026"}function to(e,t={}){let n=Zr(e);if(n.nodes.length===0)return"";let r=Math.max(1,Math.min(12,t.maxAssets??6)),o=Math.max(320,Math.min(2400,t.maxChars??900)),s=["[TOOLNET CONTEXT OFFLOAD GRAPH]","Large tool/file payloads stay outside prompt context.","Read only a needed asset with MCP context_offload_read."];for(let i of n.nodes.slice(-r).reverse()){let a=Hr(i.sourceRefs.at(-1)??"unknown",72),c=i.files.length>0?` files=${Hr(i.files.join(","),120)}`:"",u=`event:${a} --offloads--> asset:${i.id.slice(0,12)} kind=${i.kind} bytes=${i.bytes}${c}`;if([...s,u].join(`
|
|
103
103
|
`).length>o)break;s.push(u)}return s.join(`
|
|
104
|
-
`)}function
|
|
105
|
-
`)}async function
|
|
104
|
+
`)}function nu(e,t,n){let r=n??en(eu(),".config","toolnet-memory","injections","agy");return en(r,`${e.id}-${t}.json`)}function ru(e){if(!no(e))return null;try{return JSON.parse(ro(e,"utf8"))}catch{return null}}function U(e,t=280){let n=(e??"").replace(/\s+/g," ").trim();return n.length<=t?n:n.slice(0,Math.max(0,t-1)).trimEnd()+"\u2026"}function ou(e){let t=en(e.rootPath,".toolnet","work","current.json");if(!no(t))return null;try{let n=JSON.parse(ro(t,"utf8"));if(n.version===1&&n.projectId===e.id)return n}catch{}return null}function su(e,t){let n=t.tasks.filter(i=>i.status==="completed").slice(-3).map(i=>U(i.title,220)),r=Array.from(new Set([...t.currentTask?[t.currentTask.title]:[],...t.tasks.filter(i=>i.status==="in_progress"||i.status==="blocked"||i.status==="pending").slice(0,4).map(i=>i.title)].map(i=>U(i,220)).filter(Boolean))),o=t.filesTouched.at(-1),s=["[TOOLNET CONTINUITY HANDOFF]",`Project: ${e.name}`];return t.currentTask?.title?s.push(`Task: ${U(t.currentTask.title)}`):t.currentPhase?.title?s.push(`Task: ${U(t.currentPhase.title)}`):t.goal&&s.push(`Task: ${U(t.goal)}`),n.length&&s.push(`Completed: ${n.join("; ")}`),o&&s.push(`Current file: ${U(o,260)}`),r.length&&s.push(`TODO: ${r.join("; ")}`),t.nextActions.length&&s.push(`Next action: ${U(t.nextActions[0])}`),t.blockers.length&&s.push(`Blocker: ${U(t.blockers[0])}`),s.push("","CONTINUATION CONTRACT:","- Continue from this compact handoff; do not reconstruct the prior session.","- NEVER inspect .toolnet/sessions/** (legacy), .toolnet/journal/**, or .toolnet/runtime/sources/**, state.json, events.jsonl, or raw transcripts.","- If this handoff is insufficient, invoke memory_agent_ask directly.","- Do not search for memory_agent_ask implementation/schema.","- Inspect git/source only to validate current code after continuity is resolved."),s.join(`
|
|
105
|
+
`)}async function iu(e){let t=ou(e.project);if(!t)try{t=await de(e.project,e.storage)}catch{t=null}let n=t?su(e.project,t):"";if(!n)try{n=(await Br(e.project,e.storage,700))?.text??""}catch{n=""}let r=to(e.project.rootPath,{maxAssets:6,maxChars:900});return[n,r,Vr()].filter(Boolean).join(`
|
|
106
106
|
|
|
107
|
-
`).trim()}async function
|
|
108
|
-
`,{encoding:"utf8",mode:384}),
|
|
109
|
-
`)}function
|
|
107
|
+
`).trim()}async function oo(e){let t=e.now??Date.now(),n=e.resumeAfterMs??360*60*1e3,r=nu(e.project,e.conversationId,e.markerDirectory),o=ru(r),s=o?Date.parse(o.injectedAt):0,i=s?t-s:Number.POSITIVE_INFINITY;if(o&&i<6e4)return{};let a=e.invocationNum===0,c=i>=n;if(o&&!a&&!c)return{};let u=await iu({project:e.project,storage:e.storage});return u?(Zc(tu(r),{recursive:!0}),O(r,{digest:w(u),injectedAt:new Date(t).toISOString()}),{injectSteps:[{ephemeralMessage:u}]}):{}}import{existsSync as Qg,mkdirSync as au,readFileSync as Xg,renameSync as cu,writeFileSync as uu}from"node:fs";import{dirname as lu,join as du}from"node:path";function fu(e){return du(e.rootPath,".toolnet","context","session-origin.json")}function pu(e,t){au(lu(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;uu(n,`${JSON.stringify(t,null,2)}
|
|
108
|
+
`,{encoding:"utf8",mode:384}),cu(n,e)}function pt(e,t){return[...e].filter(n=>n.kind===t).sort((n,r)=>{let o=n.occurredAt.localeCompare(r.occurredAt);return o!==0?o:n.sequence-r.sequence}).at(-1)}function so(e,t){let n=pt(t.observations,"file"),r=pt(t.observations,"next_action"),o=pt(t.observations,"blocker"),s=pt(t.observations,"decision"),i={version:1,projectId:e.id,agent:t.agent,nativeSessionId:t.nativeSessionId,updatedAt:t.workState.updatedAt,currentRequest:t.workState.currentRequest,currentActivity:t.workState.currentActivity,currentTask:t.workState.currentTask?.title,currentPhase:t.workState.currentPhase?.title,lastTouchedFile:n?.text??t.workState.activeFiles?.at(-1)??t.workState.filesTouched.at(-1),latestNextAction:r?.text??t.workState.nextActions.at(-1),latestBlocker:o?.text??t.workState.blockers.at(-1),latestDecision:s?.text??t.workState.decisions.at(-1)};return pu(fu(e),i),i}import{existsSync as mu,readFileSync as gu,writeFileSync as yu}from"node:fs";import{join as hu}from"node:path";var ao="<!-- TOOLNET:STABLE-WORK:BEGIN -->",tn="<!-- TOOLNET:STABLE-WORK:END -->";function nn(e){switch(e.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function D(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${n}`)]:[]}function io(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${nn(n)} ${n.title}`)]:[]}function ku(e){let t=[ao,"# ToolNet Stable Work State","",`Updated: ${e.updatedAt}`];return e.lastSession&&t.push(`Last agent: ${e.lastSession.agent}`,`Last session: ${e.lastSession.nativeSessionId}`),e.currentRequest&&t.push("","Current request:",e.currentRequest),e.currentActivity&&t.push("","Current activity:",e.currentActivity),e.goal&&t.push("","Goal:",e.goal),e.plan&&t.push("","Plan:",e.plan),e.currentPhase&&t.push("","Current phase:",`${nn(e.currentPhase)} ${e.currentPhase.title}`),e.currentTask&&t.push("","Current task:",`${nn(e.currentTask)} ${e.currentTask.title}`),t.push(...io("Phases",e.phases)),t.push(...io("TODO / Tasks",e.tasks)),t.push(...D("Next actions",e.nextActions)),t.push(...D("Blockers",e.blockers)),t.push(...D("Important decisions",e.decisions)),t.push(...D("Active files",e.activeFiles??[])),t.push(...D("Modified files",e.modifiedFiles??[])),t.push(...D("Created files",e.createdFiles??[])),t.push(...D("Deleted files",e.deletedFiles??[])),t.push(...D("Files touched",e.filesTouched)),t.push(...D("Recent commands",e.commands??[])),t.push(...D("Checks",(e.checks??[]).map(n=>`[${n.status}] ${n.kind}: ${n.command}`))),t.push("","Progress:",`- Phases: ${e.progress.phasesCompleted}/${e.progress.phasesTotal}`,`- Tasks: ${e.progress.tasksCompleted}/${e.progress.tasksTotal}`,`- Blocked: ${e.progress.blocked}`,"","Continuation:","- Resume current unfinished task.","- Never redo completed TODO/Phase unless explicitly requested.","- Ask ToolNet Memory for deeper history only when necessary.",tn),t.join(`
|
|
109
|
+
`)}function co(e,t){let n=hu(e.rootPath,".toolnet","current.md"),r="";if(mu(n))try{r=gu(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let o=ku(t),s=r.indexOf(ao),i=r.indexOf(tn),a;s>=0&&i>=s?a=[r.slice(0,s).trimEnd(),o,r.slice(i+tn.length).trimStart()].filter(Boolean).join(`
|
|
110
110
|
|
|
111
111
|
`):a=r.trim()?`${r.trim()}
|
|
112
112
|
|
|
113
|
-
${o}`:o,
|
|
114
|
-
`,{encoding:"utf8",mode:384})}import{existsSync as
|
|
115
|
-
`)}function
|
|
116
|
-
`).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let p=u.toLowerCase().replace(/\s+/g," ");if(r.has(p))continue;r.add(p);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(u)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(u)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(l="file");let f=
|
|
113
|
+
${o}`:o,yu(n,`${a.trim()}
|
|
114
|
+
`,{encoding:"utf8",mode:384})}import{existsSync as Mo,mkdirSync as sl,readFileSync as il}from"node:fs";import{join as un}from"node:path";var vu=new Set(["rule","blocker","architecture","deploy"]),wu=new Set(["fix","todo","context","next_action"]);function rn(e){return e<0?0:e>1?1:e}function uo(e,t){let n=Number.parseFloat(e??"");return Number.isFinite(n)?n:t}function bu(e){return e==="off"?"off":e==="balanced"?"balanced":e==="aggressive"?"aggressive":"conservative"}function on(){return{mode:bu(process.env.TOOLNET_MEMORY_PROMOTION),minScore:rn(uo(process.env.TOOLNET_PROMOTE_MIN_SCORE,.65)),minConfidence:rn(uo(process.env.TOOLNET_PROMOTE_MIN_CONFIDENCE,.78))}}function xu(e){switch(e){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function Au(e){let t=rn(xu(e.importance)*.75+e.confidence*.25);return Math.round(t*1e6)/1e6}function Iu(e){return e.evidence?e.evidence:{userExplicit:!1,sourceVerified:!1,testVerified:!1,crossSessionConfirmations:0,assistantDerived:!1}}function ju(e,t=on()){if(e.importance==="temporary"||e.confidence<t.minConfidence)return"transient";let n=Iu(e);return e.kind==="rule"&&n.userExplicit?"permanent":e.kind==="rule"?"session":e.kind==="architecture"&&(n.userExplicit||n.sourceVerified||n.testVerified||n.crossSessionConfirmations>=2)?"permanent":e.kind==="architecture"?"session":e.kind==="decision"||e.kind==="todo"||e.kind==="next_action"||e.kind==="fix"?"task":"session"}function Mu(e,t=on()){if(t.mode==="off")return Number.POSITIVE_INFINITY;let n=0;t.mode==="balanced"&&(n=.1),t.mode==="aggressive"&&(n=.15);let r=Math.max(t.mode==="aggressive"?.5:.55,t.minScore-n);return vu.has(e)&&(r=Math.max(.5,r-.1)),wu.has(e)&&(r=Math.max(.5,r-.05)),r}function sn(e,t=on()){let n=ju(e,t),r=Au(e),o=Mu(e.kind,t);return n==="transient"?{knowledgeClass:n,score:r,threshold:o,persist:!1}:t.mode==="off"?{knowledgeClass:n,score:r,threshold:o,persist:!1}:{knowledgeClass:n,score:r,threshold:o,persist:r>=o}}function lo(e,t){let n=t.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":e==="rule"||e==="decision"?"high":e==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var go=[/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],Eu=[/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],Pu=[/\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],Cu=[/\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],Tu=[/tiếp theo/iu,/bước tiếp theo/iu,/việc tiếp theo/iu,/sau đó cần/iu,/next step/iu,/next action/iu,/follow[- ]?up/iu],Ou=[/đã 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],fo=[/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],Ru=[/\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],Nu=[/đườ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],_u=[/\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],po=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),$u=new Set(["payload","data","content","message","messages","parts","summary"]);function _(e,t){return t.some(n=>n.test(e))}function yo(e){return e.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Ku(e){return yo(e).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Fu(e){return!(e.length<12||e.length>1e3||(e.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(e))}function an(e,t,n,r=0){if(!(r>6)&&!(typeof e=="string"&&t&&!po.has(t))){if(typeof e=="string"){n.push(e);return}if(Array.isArray(e)){for(let o of e.slice(0,50))an(o,t,n,r+1);return}if(!(!e||typeof e!="object"))for(let[o,s]of Object.entries(e))(po.has(o)||$u.has(o))&&an(s,o,n,r+1)}}function Lu(e){let t=[];an(e.data,void 0,t);let n=[],r=new Set;for(let o of t)for(let s of o.split(/\n+|(?<=[.!?])\s+/u)){let i=yo(s);if(Fu(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function mo(e){return(e.role??(typeof e.data.role=="string"?e.data.role:"")).toLowerCase()}function Du(e,t,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=t==="user"||n.type==="user_prompt",o=t==="assistant"||n.type==="assistant_message";return r&&_(e,go)?{kind:"rule",confidence:.98}:r&&_(e,Eu)?{kind:"rule",confidence:.92}:_(e,Pu)?{kind:_(e,fo)?"architecture":"decision",confidence:r?.93:.86}:r&&_(e,Tu)?{kind:"next_action",confidence:.88}:r&&_(e,Cu)?{kind:"todo",confidence:.87}:_(e,fo)&&_(e,Ru)?{kind:"architecture",confidence:r?.88:.82}:o&&_(e,Ou)?{kind:"fix",confidence:.8}:r&&_(e,Nu)&&_(e,_u)?{kind:"context",confidence:.79}:null}function Wu(e,t,n){let r=t==="user"||n.type==="user_prompt",o=t==="assistant"||n.type==="assistant_message",s=!!n.provenance.sourcePath&&(e==="architecture"||e==="context"||e==="fix"),i=e==="fix"&&/(?:test|tests|pass|passed|passing)/iu.test(JSON.stringify(n.data));return{userExplicit:r,sourceVerified:s,testVerified:i,crossSessionConfirmations:1,assistantDerived:o}}function zu(e){switch(e){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":case"next_action":return"todo";case"fix":case"context":return"code"}}function qu(e,t,n){return e==="rule"&&_(n,go)?"critical":e==="architecture"||e==="decision"||e==="rule"?"high":e==="fix"||e==="context"?"normal":lo(t,n)}function ho(e,t){let n=[],r=new Set,o=new Map;for(let s of t){let i=typeof s.data.messageId=="string"?s.data.messageId:void 0,a=mo(s);i&&a&&o.set(i,a)}for(let s of t){let i=mo(s),a=typeof s.data.messageId=="string"?s.data.messageId:void 0;!i&&a&&(i=o.get(a)??"");for(let c of Lu(s)){let u=Du(c,i,s);if(!u||u.confidence<.75)continue;let p=zu(u.kind),l=Ku(c),f=w([e.projectId,u.kind,l].join("|"));if(r.has(f))continue;r.add(f);let d=s.provenance.sourcePath?[s.provenance.sourcePath]:[],m=s.sourceEventId?[s.sourceEventId]:[];n.push({version:1,fingerprint:f,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,kind:u.kind,type:p,content:c,confidence:u.confidence,importance:qu(u.kind,p,c),evidence:Wu(u.kind,i,s),tags:[p],provenance:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,eventIds:[s.id],sourceEventIds:m,sourcePaths:d,firstSequence:s.sequence,lastSequence:s.sequence},createdAt:s.timestamp})}}return n}import{createHash as Bu}from"node:crypto";var Vu=["project-knowledge","implementation","continuation","session-context"],Hu={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function cn(e){return Bu("sha256").update(e).digest("hex")}function mt(e,t){return`${e}:${cn(t).slice(0,24)}`}function Ju(e){try{return cn(JSON.stringify(e))}catch{return cn(String(e))}}function re(e){let t=new Set,n=[];for(let r of e){let o=r?.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function So(e,t=420){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:`${n.slice(0,Math.max(0,t-1)).trimEnd()}\u2026`}function Gu(e){return e==="rule"||e==="architecture"?"project-knowledge":e==="decision"||e==="fix"?"implementation":e==="todo"?"continuation":"session-context"}function ko(e){return e.length===0?0:e.reduce((t,n)=>t+n,0)/e.length}function Uu(e){return e.slice().sort((t,n)=>n.importanceScore-t.importanceScore||n.confidence-t.confidence||t.id.localeCompare(n.id)).slice(0,5).map(t=>So(t.content)).join(" | ")}function Yu(e){return e.slice().sort((t,n)=>n.importanceScore-t.importanceScore||n.confidence-t.confidence||t.id.localeCompare(n.id)).slice(0,6).map(t=>So(t.content)).join(`
|
|
115
|
+
`)}function vo(e,t){let n=e.slice().sort((f,d)=>f.sequence-d.sequence||f.timestamp.localeCompare(d.timestamp)||f.id.localeCompare(d.id)),r=n.map(f=>({id:mt("raw",[f.projectId,f.agent,f.nativeSessionId,f.id,String(f.sequence)].join("|")),level:"raw",eventId:f.id,sourceEventId:f.sourceEventId,sequence:f.sequence,type:f.type,role:f.role,timestamp:f.timestamp,sourcePath:f.provenance.sourcePath,payloadDigest:Ju(f.data)})),o=new Map,s=new Map;n.forEach((f,d)=>{let m=r[d];m&&(o.set(f.id,m.id),f.sourceEventId&&s.set(f.sourceEventId,m.id))});let i=t.map(f=>{let d=re([...f.provenance.eventIds.map(m=>o.get(m)),...f.provenance.sourceEventIds.map(m=>s.get(m))]);return{id:mt("fact",f.fingerprint),level:"fact",fingerprint:f.fingerprint,kind:f.kind,type:f.type,content:f.content,knowledgeClass:f.knowledgeClass,importanceScore:f.importanceScore,confidence:f.confidence,tags:re([...f.tags,"level:fact",`class:${f.knowledgeClass}`,`kind:${f.kind}`]),rawIds:d,sourcePaths:re(f.provenance.sourcePaths)}}),a=new Map;for(let f of i){let d=Gu(f.kind),m=a.get(d)??[];m.push(f),a.set(d,m)}let c=[];for(let f of Vu){let d=a.get(f);if(!d?.length)continue;let m=d.slice().sort((g,h)=>h.importanceScore-g.importanceScore||h.confidence-g.confidence||g.id.localeCompare(h.id)),k=m.map(g=>g.id);c.push({id:mt("scene",`${f}|${k.join("|")}`),level:"scene",kind:f,title:Hu[f],summary:Uu(m),factIds:k,importanceScore:Math.max(...m.map(g=>g.importanceScore)),confidence:ko(m.map(g=>g.confidence)),tags:re(["level:scene",`scene:${f}`,...m.flatMap(g=>g.tags)]),sourcePaths:re(m.flatMap(g=>g.sourcePaths))})}let u=new Map(i.map(f=>[f.id,f])),p=[];for(let f of c){let m=f.factIds.map(h=>u.get(h)).filter(h=>!!h).filter(h=>(h.knowledgeClass==="permanent"||h.knowledgeClass==="task")&&h.importanceScore>=.55);if(m.length===0)continue;let k=m.some(h=>h.knowledgeClass==="permanent")?"permanent":"task",g=Yu(m);p.push({id:mt("knowledge",`${f.id}|${k}|${m.map(h=>h.id).join("|")}`),level:"knowledge",knowledgeClass:k,title:f.title,content:g,sceneIds:[f.id],factIds:m.map(h=>h.id),importanceScore:Math.max(...m.map(h=>h.importanceScore)),confidence:ko(m.map(h=>h.confidence)),tags:re(["level:knowledge",`class:${k}`,`scene:${f.kind}`,...m.flatMap(h=>h.tags)]),sourcePaths:re(m.flatMap(h=>h.sourcePaths))})}let l=[];for(let f of i)for(let d of f.rawIds)l.push({from:d,to:f.id,type:"supports"});for(let f of c)for(let d of f.factIds)l.push({from:d,to:f.id,type:"belongs_to"});for(let f of p)for(let d of f.sceneIds)l.push({from:d,to:f.id,type:"promotes_to"});return{schema:"toolnet.memory-hierarchy.v1",version:1,raw:r,facts:i,scenes:c,knowledge:p,links:l,stats:{raw:r.length,facts:i.length,scenes:c.length,knowledge:p.length,links:l.length}}}function oe(){let e=Ve(),t=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||t==="archive"||t==="full",r=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",o=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),s=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),a=n,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||t==="full";return{sessionSave:t,rawTranscript:n,memoryPromotion:r,promoteMinScore:o,sessionSummaryMaxTokens:s,durableMemoryMaxItemsPerSession:i,archiveLocal:a,archiveRemote:c}}function wo(e){return(e||oe()).rawTranscript}function bo(e){return(e||oe()).durableMemoryMaxItemsPerSession}function xo(e){return(e||oe()).sessionSummaryMaxTokens}function Ao(e){return(e||oe()).archiveRemote}var Io=new H;function jo(e){let t=e.trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{let r=JSON.parse(t);return JSON.stringify(Io.sanitizeValue(r))}catch{}let n=Io.sanitize(e).text;return n=n.replace(/("(?:api[_-]?key|token|secret|password|cookie|authorization)"\s*:\s*)"[^"]*"/gi,'$1"[REDACTED]"').replace(/('(?:api[_-]?key|token|secret|password|cookie|authorization)'\s*:\s*)'[^']*'/gi,"$1'[REDACTED]'").replace(/\b(api[_-]?key|token|secret|password|cookie|authorization)\b\s*[:=]\s*[^\s,;]+/gi,"$1=[REDACTED]").replace(/\bbearer\s+[A-Za-z0-9._~+/=-]+/gi,"Bearer [REDACTED]"),n}function Qu(e,t){let n=e.toLowerCase(),r=.5,o=["nh\u1EDB","remember","quy t\u1EAFc","rule","t\u1EEB gi\u1EDD","from now","kh\xF4ng \u0111\u01B0\u1EE3c","must not","lu\xF4n lu\xF4n","always","never","critical","important","blocker","deploy","production","architecture"];for(let i of o)n.includes(i)&&(r+=.15);t==="rule"||t==="architecture"||t==="blocker"?r+=.2:t==="decision"||t==="deploy"?r+=.15:(t==="fix"||t==="next_action")&&(r+=.1),e.length<20?r-=.3:e.length>500&&(r-=.1);let s=[/npm (notice|warn|ERR)/i,/\d+ packages? in \d+/i,/found \d+ vulnerabilities/i,/up to date/i,/added \d+ packages/i,/^(ok|done|success|error|warning)$/i];for(let i of s)i.test(e)&&(r-=.4);return Math.max(0,Math.min(1,r))}function Xu(e,t){let n=[],r=new Set;for(let i of e){let a=i.split(`
|
|
116
|
+
`).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let p=u.toLowerCase().replace(/\s+/g," ");if(r.has(p))continue;r.add(p);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(u)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(u)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(l="file");let f=Qu(u,l);if(f<.3)continue;let d=jo(u);n.push({category:l,text:d,importance:f,sourceSessionId:t})}}let o=oe(),s=bo(o);return n.sort((i,a)=>a.importance-i.importance).slice(0,s)}function Zu(e){let t=oe(),n=xo(t),s=e.join(`
|
|
117
117
|
|
|
118
118
|
`).split(`
|
|
119
|
-
`).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).map(i=>
|
|
120
|
-
`);return
|
|
119
|
+
`).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).map(i=>jo(i)).join(`
|
|
120
|
+
`);return dt(s,n)}function gt(e,t){let r=(Array.isArray(e)?e:e.split(`
|
|
121
121
|
|
|
122
|
-
`).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),o=
|
|
122
|
+
`).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),o=Xu(r,t),s=o.filter(d=>d.category==="decision").map(d=>d.text),i=o.filter(d=>d.category==="rule").map(d=>d.text),a=o.filter(d=>d.category==="file").map(d=>d.text),c=o.filter(d=>d.category==="fix").map(d=>d.text),u=o.filter(d=>d.category==="blocker").map(d=>d.text),p=o.filter(d=>d.category==="next_action").map(d=>d.text),l=o.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:Zu(r),decisions:s,projectRules:i,filesChanged:a,bugsFixed:c,commands:l,blockers:u,nextActions:p,durableFacts:o}}function Y(e){let t=new Set,n=[];for(let r of e){let o=r?.replace(/\s+/g," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function el(e){let t=new Map;for(let n of e){if(!n||!n.id||!Number.isFinite(n.sequence))continue;let r=n.sourceEventId?`${n.agent}:${n.sourceEventId}`:n.id,o=t.get(r);(!o||n.sequence>o.sequence)&&t.set(r,n)}return[...t.values()].sort((n,r)=>n.sequence-r.sequence||n.timestamp.localeCompare(r.timestamp))}function tl(e){let t=e.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}_./:-]+/gu)??[],n=new Set;for(let r of t)if(!(r.length<2||/^\d+$/u.test(r))&&(n.add(r),n.size>=40))break;return[...n]}function nl(e){let t=sn(e);return{...e,knowledgeClass:t.knowledgeClass,importanceScore:t.score,retrievalTerms:tl(e.content),tags:Y([...e.tags,"level:fact",`class:${t.knowledgeClass}`,`kind:${e.kind}`])}}function rl(e){return e.map(t=>{try{return JSON.stringify({type:t.type,role:t.role,data:t.data,provenance:{sourcePath:t.provenance.sourcePath,files:t.provenance.files}})}catch{return""}}).filter(Boolean)}function ol(e,t,n){let r=gt(rl(t),e.nativeSessionId),o=n.filter(u=>u.kind==="todo"||u.kind==="next_action").map(u=>u.content),s=n.flatMap(u=>u.provenance.sourcePaths),i=n.filter(u=>u.kind==="architecture").map(u=>u.content),a=Y([...o,...r.nextActions]),c=Y([...r.nextActions,...o]);return{summary:r.summary,state:{task:c[0]??a[0],decisions:Y(r.decisions),files:Y([...r.filesChanged,...s]),todos:a,completed:Y(r.bugsFixed),blockers:Y(r.blockers),nextActions:c,architecture:Y(i)}}}function yt(e,t){let n=el(t),r=ho(e,n).map(nl),o=r.filter(p=>sn(p).persist).sort((p,l)=>l.importanceScore-p.importanceScore),{summary:s,state:i}=ol(e,n,o),a=o.map(p=>({fingerprint:p.fingerprint,kind:p.kind,knowledgeClass:p.knowledgeClass,importanceScore:p.importanceScore,content:p.content,terms:p.retrievalTerms})),c=vo(n,o),u=p=>r.filter(l=>l.knowledgeClass===p).length;return{version:2,normalizedEvents:n,summary:s,state:i,candidates:o,retrievalIndex:a,hierarchy:c,stats:{inputEvents:t.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:o.length,permanent:u("permanent"),task:u("task"),session:u("session"),transient:u("transient")}}}function Eo(e){return un(e.rootPath,".toolnet","memory","checkpoints")}function Po(e){return un(Eo(e),"latest.json")}function al(e){let t=Po(e);if(!Mo(t))return null;try{let n=JSON.parse(il(t,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==e.id?null:n}catch{return null}}function cl(e){return["rule","architecture","decision","fix"].includes(e)}function ul(e,t){return t.length===0?[]:yt(e,t).candidates.filter(r=>cl(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:e.agent,nativeSessionId:e.nativeSessionId}))}function ll(e,t){let n=new Map;for(let r of[...e,...t]){let o=n.get(r.fingerprint);(!o||r.importanceScore>o.importanceScore)&&n.set(r.fingerprint,r)}return Array.from(n.values()).sort((r,o)=>o.importanceScore-r.importanceScore||o.createdAt.localeCompare(r.createdAt)).slice(0,80)}function dl(e){return{request:e.currentRequest,activity:e.currentActivity,goal:e.goal,phase:e.currentPhase?{title:e.currentPhase.title,status:e.currentPhase.status}:void 0,task:e.currentTask?{title:e.currentTask.title,status:e.currentTask.status}:void 0,phases:e.phases.map(t=>({title:t.title,status:t.status})),tasks:e.tasks.map(t=>({title:t.title,status:t.status})),activeFiles:e.activeFiles??[],modifiedFiles:e.modifiedFiles??[],createdFiles:e.createdFiles??[],deletedFiles:e.deletedFiles??[],checks:e.checks??[],blockers:e.blockers,decisions:e.decisions,nextActions:e.nextActions}}function Co(e,t,n,r){let o=al(e),s=ll(o?.durableFacts??[],ul(t,n)),i=n.at(-1)?.sequence??o?.source.sequence??0,a=r.phases.filter(g=>g.status==="completed").map(g=>g.title),c=r.tasks.filter(g=>g.status==="completed").map(g=>g.title),u=r.phases.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),p=r.tasks.filter(g=>g.status!=="completed"&&g.status!=="cancelled").map(g=>g.title),l={work:dl(r),durableFacts:s.map(g=>g.fingerprint).sort()},f=w(JSON.stringify(l)).slice(0,32),d={schema:"toolnet.memory.checkpoint.v1",version:1,project:{id:e.id,name:e.name},source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.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:p},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:s,stateDigest:f},m=Eo(e);sl(m,{recursive:!0,mode:448});let k=un(m,`${f}.json`);return Mo(k)||O(k,d),O(Po(e),d),d}import{existsSync as fl}from"node:fs";import{dirname as pl,join as ml,parse as gl,resolve as yl}from"node:path";function To(e){for(let t of e){let n=yl(t),r=gl(n).root;for(;;){if(fl(ml(n,".toolnet","project.json")))return new Ye().detect(n);if(n===r)break;let o=pl(n);if(o===n)break;n=o}}return null}import{homedir as Rs}from"node:os";import{join as ef,resolve as tf}from"node:path";import{join as hl}from"node:path";function Oo(e,t){let n=e.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),o=w(n).slice(0,12);if(!r||r==="."||r==="..")return`${t}--${o}`;let s=r.slice(0,100);return s===n&&n.length<=100?s:`${s.slice(0,85)}--${o}`}function Ro(e,t,n){let r=t.trim(),o=n.trim();if(!r)throw new Error("Session agent is required");if(!o)throw new Error("Native session ID is required");let s=Oo(r.toLowerCase(),"agent"),i=Oo(o,"session");return{projectId:e.id,projectName:e.name,projectRoot:e.rootPath,agent:r,nativeSessionId:o,sessionKey:`${r}:${o}`,remotePrefix:["projects",e.id,"runtime","sources",s,i].join("/"),localDirectory:hl(e.rootPath,".toolnet","runtime","sources",s,i)}}function No(e){return String(e).padStart(12,"0")}var ht=class{constructor(t,n=100,r=512*1024){this.storage=t;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(t){let n=await this.storage.getText(t);return n?JSON.parse(n):null}async putJson(t,n){await this.storage.put(t,JSON.stringify(n,null,2)+`
|
|
123
123
|
`,"application/json")}async scan(t){let n=`${t.remotePrefix}/events/`,r=await this.storage.list(n),o=[],s=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)||(o.push({key:i.key,start:c,end:u}),s=Math.max(s,u))}return o.sort((i,a)=>i.start-a.start),{chunks:o,maxSequence:s}}split(t){let n=[],r=[],o=0;for(let s of t){let i=Buffer.byteLength(JSON.stringify(s)+`
|
|
124
|
-
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||o+i>this.maxChunkBytes)&&(n.push(r),r=[],o=0),r.push(s),o+=i}return r.length>0&&n.push(r),n}async loadManifest(t){return this.getJson(`${t.remotePrefix}/session.json`)}async loadCursor(t){return this.getJson(`${t.remotePrefix}/cursor.json`)}async recover(t){let n=await this.scan(t);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(t,n,r,o={}){let s=await this.loadManifest(t),i=await this.scan(t),a=n.filter(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(a)){let h=g[0],v=g[g.length-1],x=g.map(
|
|
124
|
+
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||o+i>this.maxChunkBytes)&&(n.push(r),r=[],o=0),r.push(s),o+=i}return r.length>0&&n.push(r),n}async loadManifest(t){return this.getJson(`${t.remotePrefix}/session.json`)}async loadCursor(t){return this.getJson(`${t.remotePrefix}/cursor.json`)}async recover(t){let n=await this.scan(t);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(t,n,r,o={}){let s=await this.loadManifest(t),i=await this.scan(t),a=n.filter(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(a)){let h=g[0],v=g[g.length-1],x=g.map(N=>JSON.stringify(N)).join(`
|
|
125
125
|
`)+`
|
|
126
|
-
`,
|
|
127
|
-
`,null,"utf8"),
|
|
128
|
-
`,null,"utf8"),
|
|
126
|
+
`,R=w(x).slice(0,16),C=[t.remotePrefix,"events",`${No(h.sequence)}-${No(v.sequence)}-${R}.jsonl`].join("/");await this.storage.exists(C)||await this.storage.put(C,x,"application/x-ndjson"),c+=g.length}let u=await this.scan(t),p=n[n.length-1],l=s?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?l="idle":p?.type==="error"?l="error":n.length>0&&(l="active");let f=new Date().toISOString(),d=n[0],m={version:1,projectId:t.projectId,projectName:t.projectName,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,status:l,createdAt:s?.createdAt??d?.timestamp??f,updatedAt:p?.timestamp??f,firstEventAt:s?.firstEventAt??d?.timestamp,lastEventAt:p?.timestamp??s?.lastEventAt,eventCount:u.maxSequence,chunkCount:u.chunks.length,metadata:{...s?.metadata,...o.metadata}};(o.title??s?.title)&&(m.title=o.title??s?.title);let k={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:u.maxSequence,lastRemoteSequence:u.maxSequence,sourceCursors:r,updatedAt:f};return await this.putJson(`${t.remotePrefix}/cursor.json`,k),await this.putJson(`${t.remotePrefix}/session.json`,m),{uploadedEvents:c,lastRemoteSequence:u.maxSequence,eventCount:m.eventCount,chunkCount:m.chunkCount,status:l}}};import{closeSync as Re,existsSync as bt,fsyncSync as hn,mkdirSync as Nl,openSync as Ne,readFileSync as Uo,readSync as _l,rmSync as Ho,statSync as gn,truncateSync as $l,writeSync as Kl}from"node:fs";import{join as yn}from"node:path";var kl=new Set(["thinking","reasoning","reasoningcontent","chainofthought","cot","analysistext","internalreasoning","modelthinking"]),Sl=new Set(["reasoning","thinking","chain_of_thought","chain-of-thought","internal_reasoning","internal-reasoning"]);function vl(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,"")}function wl(e){for(let t of["type","kind"]){let n=e[t];if(typeof n=="string"){let r=n.toLowerCase();if(Sl.has(r))return n}}return null}function ln(e,t=0){if(t>12)return"[ToolNet nested value omitted]";if(Array.isArray(e))return e.map(s=>ln(s,t+1));if(!e||typeof e!="object")return e;let n=e,r=wl(n);if(r)return{type:r,omitted:"[private reasoning omitted]"};let o={};for(let[s,i]of Object.entries(n))kl.has(vl(s))||(o[s]=ln(i,t+1));return o}function bl(e){if(!e)return new Date().toISOString();let t=new Date(e);return Number.isNaN(t.getTime())?new Date().toISOString():t.toISOString()}function se(e){return e?.trim()||void 0}function _o(e,t={}){let n={...e.provenance??{}},r=se(e.source)??se(t.source)??se(n.source);return{...e,timestamp:bl(e.timestamp),source:r,turnId:se(e.turnId)??se(t.turnId),cwd:se(e.cwd)??se(t.cwd),data:ln(e.data??{}),provenance:n}}import{randomUUID as dn}from"node:crypto";import{closeSync as pe,existsSync as me,fsyncSync as Te,mkdirSync as fn,openSync as Oe,readFileSync as pn,readdirSync as xl,renameSync as Al,rmSync as kt,statSync as Il,writeSync as St}from"node:fs";import{join as Q}from"node:path";var jl=12e4,Ml=80,El="reconcile-required";function Pl(e){e<=0||Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}function ge(e){return Q(e,".toolnet","journal")}function Fo(e){return Q(ge(e),"events.jsonl")}function vt(e){return Q(ge(e),El)}function Cl(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t?.code!=="ESRCH"}}function Lo(e){if(!me(e))return null;try{let t=JSON.parse(pn(e,"utf8"));return t.version!==1||typeof t.token!="string"||typeof t.pid!="number"||typeof t.acquiredAt!="string"?null:{version:1,token:t.token,pid:t.pid,acquiredAt:t.acquiredAt}}catch{return null}}function Tl(e){if(!me(e))return!1;let t=0;try{t=Date.now()-Il(e).mtimeMs}catch{return!1}if(t<=jl)return!1;let n=Lo(e);return n?!Cl(n.pid):!0}function Ol(e){if(!Tl(e))return!1;try{return kt(e,{force:!0}),!0}catch{return!1}}function Do(e){for(let t=0;t<Ml;t+=1){let n=dn();try{let r=Oe(e,"wx",384),o={version:1,token:n,pid:process.pid,acquiredAt:new Date().toISOString()};try{return St(r,`${JSON.stringify(o)}
|
|
127
|
+
`,null,"utf8"),Te(r),{fd:r,token:n}}catch(s){throw pe(r),kt(e,{force:!0}),s}}catch(r){if(r?.code!=="EEXIST")throw r;if(Ol(e))continue;Pl(25)}}throw new Error(`Shared project journal is locked: ${e}`)}function Wo(e,t){pe(t.fd),Lo(e)?.token===t.token&&kt(e,{force:!0})}function $o(e){if(!me(e))return[];let t="";try{t=pn(e,"utf8")}catch{return[]}let n=[];for(let r of t.split(/\r?\n/)){let o=r.trim();if(o)try{let s=JSON.parse(o);if(s.version!==1||typeof s.id!="string"||s.id.length===0||typeof s.projectId!="string"||s.projectId.length===0)continue;n.push(s)}catch{}}return n}function zo(e){if(!me(e))return[];let t=[];for(let n of xl(e,{withFileTypes:!0})){let r=Q(e,n.name);if(n.isDirectory()){t.push(...zo(r));continue}n.isFile()&&n.name==="events.jsonl"&&t.push(r)}return t.sort()}function wt(e){let t=null;try{t=Oe(e,"r"),Te(t)}catch{}finally{if(t===null)return;pe(t)}}function Ko(e){let t=vt(e);if(!me(t))return null;try{return pn(t,"utf8").trim()||null}catch{return null}}function mn(e){let t=ge(e);fn(t,{recursive:!0,mode:448});let n=vt(e),r=[dn(),new Date().toISOString()].join("|"),o=Oe(n,"w",384);try{St(o,`${r}
|
|
128
|
+
`,null,"utf8"),Te(o)}finally{pe(o)}wt(t)}function Rl(e,t,n){let r=Q(e,`.events.jsonl.tmp-${process.pid}-${dn()}`),o=Oe(r,"w",384);try{let s=n.length===0?"":`${n.map(i=>JSON.stringify(i)).join(`
|
|
129
129
|
`)}
|
|
130
|
-
`;s&&
|
|
130
|
+
`;s&&St(o,s,null,"utf8"),Te(o)}finally{pe(o)}Al(r,t),wt(e)}function qo(e){let t=ge(e),n=Fo(e),r=Q(e,".toolnet","runtime","sources"),o=Ko(e),s=zo(r),i=[],a=new Set;for(let l of $o(n))a.has(l.id)||(a.add(l.id),i.push(l));let c=i.length,u=[];for(let l of s)for(let f of $o(l))a.has(f.id)||(a.add(f.id),u.push(f));u.sort((l,f)=>{let d=l.timestamp.localeCompare(f.timestamp);return d!==0?d:l.id.localeCompare(f.id)}),i.push(...u),Rl(t,n,i);let p=Ko(e);return o&&p===o&&(kt(vt(e),{force:!0}),wt(t)),{filesScanned:s.length,existingEvents:c,recoveredEvents:u.length,totalEvents:i.length}}function Bo(e){let t=ge(e);fn(t,{recursive:!0,mode:448});let n=Q(t,"journal.lock"),r=Do(n);try{return qo(e)}finally{Wo(n,r)}}function Vo(e,t){if(t.length===0)return;let n=ge(e);fn(n,{recursive:!0,mode:448});let r=Fo(e),o=Q(n,"journal.lock"),s=Do(o);try{if(me(vt(e))){qo(e);return}let i=`${t.map(c=>JSON.stringify(c)).join(`
|
|
131
131
|
`)}
|
|
132
|
-
`,a=
|
|
133
|
-
`),
|
|
132
|
+
`,a=Oe(r,"a",384);try{St(a,i,null,"utf8"),Te(a)}finally{pe(a)}wt(n)}finally{Wo(o,s)}}var Fl=12e4,Ll=80,Jo=2e3;function Dl(e){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}function Yo(e,t){let n=Buffer.isBuffer(t)?t:Buffer.from(t,"utf8"),r=0;for(;r<n.length;){let o=Kl(e,n,r,n.length-r);if(o<=0)throw new Error("Unable to write session WAL");r+=o}}function kn(e){let t=e.trim();if(!t)return null;try{let n=JSON.parse(t);return n.version!==1||typeof n.id!="string"||!n.id||typeof n.sequence!="number"||!Number.isFinite(n.sequence)||typeof n.projectId!="string"||!n.projectId||typeof n.timestamp!="string"?null:n}catch{return null}}function Wl(e){if(!bt(e))return[];let t="";try{t=Uo(e,"utf8")}catch{return[]}let n=[];for(let r of t.split(/\r?\n/)){let o=kn(r);o&&n.push(o)}return n}function Go(e){return e.type==="session_end"||e.type==="session_idle"?"idle":e.type==="error"?"error":"active"}function zl(e){if(!bt(e))return!1;let t;try{t=Uo(e)}catch{return!1}if(t.length===0||t[t.length-1]===10)return!1;let n=t.lastIndexOf(10),r=n>=0?n+1:0,o=t.subarray(r).toString("utf8").trim();if(kn(o)){let i=Ne(e,"a");try{Yo(i,`
|
|
133
|
+
`),hn(i)}finally{Re(i)}return!0}$l(e,r);let s=Ne(e,"a");try{hn(s)}finally{Re(s)}return!0}function ql(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(e[n]!==t[n])return!1;return!0}var xt=class{constructor(t,n={}){this.identity=t;this.eventContext=n;Nl(t.localDirectory,{recursive:!0}),this.eventsFile=yn(t.localDirectory,"events.jsonl"),this.stateFile=yn(t.localDirectory,"state.json"),this.lockFile=yn(t.localDirectory,"journal.lock")}identity;eventContext;eventsFile;stateFile;lockFile;initialState(){let t=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:t,updatedAt:t,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return sr(this.stateFile)??this.initialState()}recoverStateUnsafe(){zl(this.eventsFile);let t=this.loadStateUnsafe(),n=Wl(this.eventsFile);if(n.length===0)return t;let r=n[0];for(let l of n)l.sequence<=r.sequence||(r=l);let o=n.slice(-Jo).map(l=>l.id),s=bt(this.eventsFile)?gn(this.eventsFile).size:0,i=Math.max(t.lastSequence,r.sequence),a=Math.min(t.remoteByteOffset,s),c=r.sequence>t.lastSequence;if(!(c||a!==t.remoteByteOffset||!ql(t.recentEventIds,o)||t.lastLocalEventAt!==r.timestamp))return t;let p={...t,status:Go(r),updatedAt:r.timestamp,lastLocalEventAt:r.timestamp,lastSequence:i,remoteByteOffset:a,recentEventIds:o};if(this.saveStateUnsafe(p),!c)return p;try{mn(this.identity.projectRoot)}catch{return p}try{Bo(this.identity.projectRoot)}catch{}return p}loadState(){return this.withLock(()=>this.recoverStateUnsafe())}saveStateUnsafe(t){O(this.stateFile,t)}acquireLock(){for(let t=0;t<Ll;t+=1)try{return Ne(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-gn(this.lockFile).mtimeMs>Fl){Ho(this.lockFile,{force:!0});continue}}catch{}Dl(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(t){let n=this.acquireLock();try{return t()}finally{Re(n),Ho(this.lockFile,{force:!0})}}append(t){return t.length===0?[]:this.withLock(()=>{let n=this.recoverStateUnsafe(),r=new Set(n.recentEventIds),o=n.lastSequence,s=[];for(let l of t){let f=_o(l,this.eventContext),d=f.timestamp??new Date().toISOString(),m=f.data??{},k=f.provenance?.rawDigest??w(or(m)),g=ue(m),h=f.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,f.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,o+1,f.type,d,k].join("|"),v=w(h).slice(0,32);if(r.has(v))continue;o+=1;let x={version:1,id:v,sequence:o,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,sessionId:this.identity.nativeSessionId,type:f.type,timestamp:d,source:f.source??f.provenance?.source??this.identity.agent,data:g,provenance:{...f.provenance,rawDigest:k}};f.role!==void 0&&(x.role=f.role),f.turnId!==void 0&&(x.turnId=f.turnId),f.cwd!==void 0&&(x.cwd=f.cwd),f.sourceEventId!==void 0&&(x.sourceEventId=f.sourceEventId),f.sourceSequence!==void 0&&(x.sourceSequence=f.sourceSequence),s.push(x),r.add(v)}if(s.length===0)return[];let i=s.map(l=>JSON.stringify(l)).join(`
|
|
134
134
|
`)+`
|
|
135
|
-
`,a=Pe(this.eventsFile,"a",384);try{Eo(a,i),an(a)}finally{Ce(a)}try{Mo(this.identity.projectRoot,s)}catch{try{rn(this.identity.projectRoot)}catch{}}let c=s[s.length-1],u=Co(c),p=Array.from(r).slice(-Io);return this.saveStateUnsafe({...n,status:u,updatedAt:c.timestamp,lastLocalEventAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),s})}readPending(){return this.withLock(()=>{let t=this.recoverStateUnsafe();if(!ht(this.eventsFile))return{events:[],startOffset:t.remoteByteOffset,endOffset:t.remoteByteOffset};let n=on(this.eventsFile).size,r=Math.min(t.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let o=n-r,s=Buffer.alloc(o),i=Pe(this.eventsFile,"r");try{al(i,s,0,o,r)}finally{Ce(i)}let a=[];for(let c of s.toString("utf8").split(/\r?\n/)){let u=cn(c);u&&a.push(u)}return{events:a,startOffset:r,endOffset:n}})}markRemote(t,n){this.withLock(()=>{let r=this.recoverStateUnsafe(),o=new Date().toISOString();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,t),remoteByteOffset:Math.max(r.remoteByteOffset,n),lastRemoteAt:o,updatedAt:o})})}setSourceCursor(t,n){this.withLock(()=>{let r=this.recoverStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[t]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as ad,existsSync as cd,openSync as ud,readSync as ld,statSync as dd}from"node:fs";import{createHash as xl}from"node:crypto";import{existsSync as jl,readdirSync as Ml,readFileSync as Al}from"node:fs";import{basename as Il,join as Jo}from"node:path";import{randomUUID as Ro}from"node:crypto";var A=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function Ee(e){let t=new Set,n=[];for(let r of e){let o=r.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function se(e){let t=e.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!t)throw new A("Invalid Wiki slug",400);return t}function To(e){let t=[];for(let n of e.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&t.push(se(r))}return Ee(t)}function yl(e){return e.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(t=>t.trim()).filter(t=>t.length>=2)}function Oo(e){return{id:`revision-${Ro()}`,pageId:e.id,slug:e.slug,revision:e.revision,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...e.tags],links:[...e.links],createdAt:e.updatedAt}}function oe(e){return structuredClone(e)}var St=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(t){let n,r=this.queue.then(async()=>{let o=await this.ensureState();n=t(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let t=await this.ensureState(),n=new Set(t.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:t.projectId,pages:t.pages.length,revisions:t.revisions.length,tags:Ee(t.pages.flatMap(r=>r.tags)).sort((r,o)=>r.localeCompare(o)),links:t.pages.reduce((r,o)=>r+o.links.length,0),orphanPages:t.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:t.pages.filter(r=>r.tags.some(o=>o.startsWith("toolnet-auto-"))).length,updatedAt:t.updatedAt}}async listPages(){let t=await this.ensureState();return oe([...t.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(t){let n=await this.ensureState(),r=se(t),o=n.pages.find(s=>s.slug===r||s.id===t);if(!o)throw new A(`Wiki page not found: ${t}`,404);return oe(o)}async createPage(t){return this.mutate(n=>{let r=t.title.trim(),o=t.content.trim();if(!r)throw new A("Wiki title is required",400);let s=se(t.slug??r);if(n.pages.some(c=>c.slug===s))throw new A(`Wiki page already exists: ${s}`,409);let i=new Date().toISOString(),a={id:`wiki-${Ro()}`,slug:s,title:r,...t.summary?.trim()?{summary:t.summary.trim()}:{},content:o,tags:Ee(t.tags??[]),links:To(o),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(Oo(a)),oe(a)})}async updatePage(t,n){return this.mutate(r=>{let o=se(t),s=r.pages.find(i=>i.slug===o||i.id===t);if(!s)throw new A(`Wiki page not found: ${t}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new A("Wiki title is required",400);s.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?s.summary=i:delete s.summary}return n.content!==void 0&&(s.content=n.content.trim(),s.links=To(s.content)),n.tags!==void 0&&(s.tags=Ee(n.tags)),s.revision+=1,s.updatedAt=new Date().toISOString(),r.revisions.push(Oo(s)),oe(s)})}async history(t){let n=await this.getPage(t),r=await this.ensureState();return oe(r.revisions.filter(o=>o.pageId===n.id).sort((o,s)=>s.revision-o.revision))}async backlinks(t){let n=await this.getPage(t),r=await this.ensureState();return oe(r.pages.filter(o=>o.links.includes(n.slug)).sort((o,s)=>o.title.localeCompare(s.title)))}async search(t,n=10){let r=await this.ensureState(),o=Ee(yl(t));if(o.length===0)return[];let s=Math.max(1,Math.min(20,Math.floor(n))),i=[];for(let a of r.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),p=a.summary?.toLowerCase()??"",l=a.content.toLowerCase(),f=a.tags.map(m=>m.toLowerCase()),d=0;for(let m of o)u===m&&(d+=12),c===m&&(d+=10),c.includes(m)&&(d+=6),u.includes(m)&&(d+=5),f.some(k=>k===m)?d+=5:f.some(k=>k.includes(m))&&(d+=3),p.includes(m)&&(d+=2),l.includes(m)&&(d+=1);d>0&&i.push({page:oe(a),score:d})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,s)}};var No="wiki/state.v1.json";function hl(e){let t=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:e.id,pages:[],revisions:[],createdAt:t,updatedAt:t}}function kl(e,t){let n=JSON.parse(e);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==t.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var vt=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(No);if(!t){let n=hl(this.project);return await this.save(n),n}return kl(t,this.project)}async save(t){await this.storage.put(No,JSON.stringify(t,null,2),"application/json")}};import{createHash as Sl,randomUUID as _o}from"node:crypto";var $o="wiki/governance.v1.json",Wo="toolnet.knowledge-governance.v1",Fo=500,Te={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function vl(e,t=0,n=1){return Math.max(t,Math.min(n,e))}function un(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function Ko(e){return Sl("sha256").update(e.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function wl(e){let t=[e.title,e.summary??"",e.content.slice(0,2e3),...e.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(t)}function bl(e){let t=e.sourceType==="skill"?.96:e.sourceType==="memory"?.94:.88,n=e.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(t+=.03),e.content.length>=200&&(t+=.02),e.content.length<80&&(t-=.05),e.title.length<4&&(t-=.05),vl(t)}function Lo(e){let t=new Date().toISOString();return{schema:Wo,version:1,projectId:e,policy:{...Te},reviews:[],audit:[],createdAt:t,updatedAt:t}}function Do(e){let t=e.autoApproveThreshold??Te.autoApproveThreshold,n=e.criticalApproveThreshold??Te.criticalApproveThreshold,r=e.staleAfterDays??Te.staleAfterDays;if(!Number.isFinite(t)||t<.5||t>1)throw new A("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new A("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new A("Invalid staleAfterDays",400);return{autoApproveThreshold:t,criticalApproveThreshold:n,staleAfterDays:r}}var wt=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText($o);if(!t){let n=Lo(this.project.id);return await this.save(n),n}try{let n=JSON.parse(t);if(n.schema!==Wo||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:Do(n.policy??Te)}}catch{let n=Lo(this.project.id);return await this.save(n),n}}async save(t){await this.storage.put($o,JSON.stringify(t,null,2),"application/json")}},bt=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(t,n,r,o={}){t.audit.push({id:_o(),action:n,principal:r,...o.reviewId?{reviewId:o.reviewId}:{},...o.sourceKey?{sourceKey:o.sourceKey}:{},timestamp:new Date().toISOString(),...o.metadata?{metadata:o.metadata}:{}}),t.audit.length>Fo&&(t.audit=t.audit.slice(-Fo))}async mutate(t){let n,r=this.queue.then(async()=>{let o=await this.ensureState();n=await t(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(t,n){return this.mutate(r=>(r.policy=Do({...r.policy,...t}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let t=await this.ensureState(),n=r=>t.reviews.filter(o=>o.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:t.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:t.audit.length,policy:{...t.policy},updatedAt:t.updatedAt}}async listReviews(t){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!t||r.status===t).sort((r,o)=>o.updatedAt.localeCompare(r.updatedAt)))}async auditLog(t=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(t)));return structuredClone(n.audit.slice(-r).reverse())}async assess(t,n){let r=await this.ensureState(),o=bl(t),s=un(t.title),i=n.filter(p=>p.slug!==t.slug&&un(p.title)===s&&Ko(p.content)!==Ko(t.content)).map(p=>p.slug),a=wl(t),c=[];o<r.policy.autoApproveThreshold&&c.push(`confidence:${o.toFixed(2)}`),a&&o<r.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:u,requiresReview:i.length>0||o<r.policy.autoApproveThreshold||a&&o<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(t,n){let r=await this.assess(t,n);return this.mutate(o=>{let s=o.reviews.find(c=>c.sourceKey===t.sourceKey&&c.digest===t.digest);if(s?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(s)};if(s?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(s)};if(!r.requiresReview)return this.audit(o,"knowledge:auto-approved","system",{sourceKey:t.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(s?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(s)};let i=new Date().toISOString(),a={id:_o(),sourceKey:t.sourceKey,sourceType:t.sourceType,slug:t.slug,marker:t.marker,digest:t.digest,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...new Set([...t.tags,t.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};return o.reviews.push(a),this.audit(o,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(a)}})}async markApplied(t,n){await this.mutate(r=>{let o=r.reviews.find(s=>s.sourceKey===t&&s.digest===n&&s.status==="approved");o&&(o.appliedAt=new Date().toISOString(),o.updatedAt=o.appliedAt,this.audit(r,"knowledge:applied",o.reviewedBy??"system",{reviewId:o.id,sourceKey:t}))})}async decide(t,n,r){return this.mutate(async o=>{let s=o.reviews.find(u=>u.id===t);if(!s)throw new A(`Governance review not found: ${t}`,404);if(s.status!=="pending")throw new A("Governance review is already resolved",409);let i=new Date().toISOString();if(s.reviewedAt=i,s.reviewedBy=n.principal,s.updatedAt=i,n.note?.trim()&&(s.reviewNote=n.note.trim()),n.action==="reject")return s.status="rejected",this.audit(o,"knowledge:rejected",n.principal,{reviewId:t,sourceKey:s.sourceKey}),structuredClone(s);if(n.action==="supersede")return s.status="superseded",n.targetReviewId&&(s.supersededBy=n.targetReviewId),this.audit(o,"knowledge:superseded",n.principal,{reviewId:t,sourceKey:s.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(s);if(n.action==="merge"){if(!n.targetReviewId)throw new A("targetReviewId is required for merge",400);let u=o.reviews.find(p=>p.id===n.targetReviewId);if(!u)throw new A("Merge target review not found",404);return s.status="superseded",s.mergedInto=u.id,this.audit(o,"knowledge:merged",n.principal,{reviewId:t,sourceKey:s.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(s)}s.status="approved";let c=(await r.listPages()).find(u=>u.slug===s.slug);if(c&&!c.tags.includes(s.marker))throw new A(`Wiki page '${s.slug}' is manually managed`,409);return c?await r.updatePage(s.slug,{title:s.title,summary:s.summary??"",content:s.content,tags:s.tags}):await r.createPage({slug:s.slug,title:s.title,...s.summary?{summary:s.summary}:{},content:s.content,tags:s.tags}),s.appliedAt=i,this.audit(o,"knowledge:approved",n.principal,{reviewId:t,sourceKey:s.sourceKey}),structuredClone(s)})}async quality(t){let n=await this.ensureState(),r=await t.listPages(),o=Date.now(),s=n.policy.staleAfterDays*864e5,i=r.map(p=>{let l=o-Date.parse(p.updatedAt);return{slug:p.slug,title:p.title,updatedAt:p.updatedAt,ageDays:Math.max(0,Math.floor(l/864e5)),stale:Number.isFinite(l)&&l>s}}).filter(p=>p.stale).map(({stale:p,...l})=>l),a=new Map;for(let p of r){let l=un(p.title),f=a.get(l)??[];f.push(p),a.set(l,f)}let c=[...a.entries()].filter(([,p])=>p.length>1).map(([p,l])=>({title:p,pages:l.map(f=>f.slug)})),u=n.reviews.filter(p=>p.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(p=>p.tags.some(l=>l.startsWith("toolnet-auto-"))).length,manualPages:r.filter(p=>!p.tags.some(l=>l.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(p=>p.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(p=>p.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var Go="wiki/automation.v1.json",Uo="toolnet.wiki-automation.v1",fn=8e3,zo=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function Re(e){return xl("sha256").update(JSON.stringify(e)).digest("hex")}function Oe(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function qo(e){return Array.isArray(e)?e:[]}function Yo(e){return typeof e!="string"?void 0:e.replace(/\s+/gu," ").trim()||void 0}function ln(e){return Array.isArray(e)?e.map(Yo).filter(t=>!!t):[]}function W(e,t){for(let n of t){let r=Yo(e[n]);if(r)return r}}function Ne(e){let t=new Set,n=[];for(let r of e){let o=r.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function xt(e,t=0,n=""){if(t>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(zo.has(r))return[];if(typeof e=="string"){let i=e.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(e))return e.flatMap(i=>xt(i,t+1,n));let o=Oe(e);if(!o)return[];let s=[];for(let[i,a]of Object.entries(o)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();zo.has(c)||s.push(...xt(a,t+1,i))}return s}function Bo(e){let n=Ne(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(o=>xt(e[o],0,o)));return(n.length>0?n:Ne(xt(e))).join(`
|
|
135
|
+
`,a=Ne(this.eventsFile,"a",384);try{Yo(a,i),hn(a)}finally{Re(a)}try{Vo(this.identity.projectRoot,s)}catch{try{mn(this.identity.projectRoot)}catch{}}let c=s[s.length-1],u=Go(c),p=Array.from(r).slice(-Jo);return this.saveStateUnsafe({...n,status:u,updatedAt:c.timestamp,lastLocalEventAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),s})}readPending(){return this.withLock(()=>{let t=this.recoverStateUnsafe();if(!bt(this.eventsFile))return{events:[],startOffset:t.remoteByteOffset,endOffset:t.remoteByteOffset};let n=gn(this.eventsFile).size,r=Math.min(t.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let o=n-r,s=Buffer.alloc(o),i=Ne(this.eventsFile,"r");try{_l(i,s,0,o,r)}finally{Re(i)}let a=[];for(let c of s.toString("utf8").split(/\r?\n/)){let u=kn(c);u&&a.push(u)}return{events:a,startOffset:r,endOffset:n}})}markRemote(t,n){this.withLock(()=>{let r=this.recoverStateUnsafe(),o=new Date().toISOString();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,t),remoteByteOffset:Math.max(r.remoteByteOffset,n),lastRemoteAt:o,updatedAt:o})})}setSourceCursor(t,n){this.withLock(()=>{let r=this.recoverStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[t]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as _d,existsSync as $d,openSync as Kd,readSync as Fd,statSync as Ld}from"node:fs";import{createHash as Ql}from"node:crypto";import{existsSync as Xl,readdirSync as Zl,readFileSync as ed}from"node:fs";import{basename as td,join as ps}from"node:path";import{randomUUID as Zo}from"node:crypto";var M=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function _e(e){let t=new Set,n=[];for(let r of e){let o=r.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function ae(e){let t=e.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!t)throw new M("Invalid Wiki slug",400);return t}function Qo(e){let t=[];for(let n of e.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&t.push(ae(r))}return _e(t)}function Bl(e){return e.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(t=>t.trim()).filter(t=>t.length>=2)}function Xo(e){return{id:`revision-${Zo()}`,pageId:e.id,slug:e.slug,revision:e.revision,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...e.tags],links:[...e.links],createdAt:e.updatedAt}}function ie(e){return structuredClone(e)}var At=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(t){let n,r=this.queue.then(async()=>{let o=await this.ensureState();n=t(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let t=await this.ensureState(),n=new Set(t.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:t.projectId,pages:t.pages.length,revisions:t.revisions.length,tags:_e(t.pages.flatMap(r=>r.tags)).sort((r,o)=>r.localeCompare(o)),links:t.pages.reduce((r,o)=>r+o.links.length,0),orphanPages:t.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:t.pages.filter(r=>r.tags.some(o=>o.startsWith("toolnet-auto-"))).length,updatedAt:t.updatedAt}}async listPages(){let t=await this.ensureState();return ie([...t.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(t){let n=await this.ensureState(),r=ae(t),o=n.pages.find(s=>s.slug===r||s.id===t);if(!o)throw new M(`Wiki page not found: ${t}`,404);return ie(o)}async createPage(t){return this.mutate(n=>{let r=t.title.trim(),o=t.content.trim();if(!r)throw new M("Wiki title is required",400);let s=ae(t.slug??r);if(n.pages.some(c=>c.slug===s))throw new M(`Wiki page already exists: ${s}`,409);let i=new Date().toISOString(),a={id:`wiki-${Zo()}`,slug:s,title:r,...t.summary?.trim()?{summary:t.summary.trim()}:{},content:o,tags:_e(t.tags??[]),links:Qo(o),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(Xo(a)),ie(a)})}async updatePage(t,n){return this.mutate(r=>{let o=ae(t),s=r.pages.find(i=>i.slug===o||i.id===t);if(!s)throw new M(`Wiki page not found: ${t}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new M("Wiki title is required",400);s.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?s.summary=i:delete s.summary}return n.content!==void 0&&(s.content=n.content.trim(),s.links=Qo(s.content)),n.tags!==void 0&&(s.tags=_e(n.tags)),s.revision+=1,s.updatedAt=new Date().toISOString(),r.revisions.push(Xo(s)),ie(s)})}async history(t){let n=await this.getPage(t),r=await this.ensureState();return ie(r.revisions.filter(o=>o.pageId===n.id).sort((o,s)=>s.revision-o.revision))}async backlinks(t){let n=await this.getPage(t),r=await this.ensureState();return ie(r.pages.filter(o=>o.links.includes(n.slug)).sort((o,s)=>o.title.localeCompare(s.title)))}async search(t,n=10){let r=await this.ensureState(),o=_e(Bl(t));if(o.length===0)return[];let s=Math.max(1,Math.min(20,Math.floor(n))),i=[];for(let a of r.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),p=a.summary?.toLowerCase()??"",l=a.content.toLowerCase(),f=a.tags.map(m=>m.toLowerCase()),d=0;for(let m of o)u===m&&(d+=12),c===m&&(d+=10),c.includes(m)&&(d+=6),u.includes(m)&&(d+=5),f.some(k=>k===m)?d+=5:f.some(k=>k.includes(m))&&(d+=3),p.includes(m)&&(d+=2),l.includes(m)&&(d+=1);d>0&&i.push({page:ie(a),score:d})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,s)}};var es="wiki/state.v1.json";function Vl(e){let t=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:e.id,pages:[],revisions:[],createdAt:t,updatedAt:t}}function Hl(e,t){let n=JSON.parse(e);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==t.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var It=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(es);if(!t){let n=Vl(this.project);return await this.save(n),n}return Hl(t,this.project)}async save(t){await this.storage.put(es,JSON.stringify(t,null,2),"application/json")}};import{createHash as Jl,randomUUID as ts}from"node:crypto";var ns="wiki/governance.v1.json",is="toolnet.knowledge-governance.v1",rs=500,$e={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function Gl(e,t=0,n=1){return Math.max(t,Math.min(n,e))}function Sn(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function os(e){return Jl("sha256").update(e.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function Ul(e){let t=[e.title,e.summary??"",e.content.slice(0,2e3),...e.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(t)}function Yl(e){let t=e.sourceType==="skill"?.96:e.sourceType==="memory"?.94:.88,n=e.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(t+=.03),e.content.length>=200&&(t+=.02),e.content.length<80&&(t-=.05),e.title.length<4&&(t-=.05),Gl(t)}function ss(e){let t=new Date().toISOString();return{schema:is,version:1,projectId:e,policy:{...$e},reviews:[],audit:[],createdAt:t,updatedAt:t}}function as(e){let t=e.autoApproveThreshold??$e.autoApproveThreshold,n=e.criticalApproveThreshold??$e.criticalApproveThreshold,r=e.staleAfterDays??$e.staleAfterDays;if(!Number.isFinite(t)||t<.5||t>1)throw new M("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new M("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new M("Invalid staleAfterDays",400);return{autoApproveThreshold:t,criticalApproveThreshold:n,staleAfterDays:r}}var jt=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(ns);if(!t){let n=ss(this.project.id);return await this.save(n),n}try{let n=JSON.parse(t);if(n.schema!==is||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:as(n.policy??$e)}}catch{let n=ss(this.project.id);return await this.save(n),n}}async save(t){await this.storage.put(ns,JSON.stringify(t,null,2),"application/json")}},Mt=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(t,n,r,o={}){t.audit.push({id:ts(),action:n,principal:r,...o.reviewId?{reviewId:o.reviewId}:{},...o.sourceKey?{sourceKey:o.sourceKey}:{},timestamp:new Date().toISOString(),...o.metadata?{metadata:o.metadata}:{}}),t.audit.length>rs&&(t.audit=t.audit.slice(-rs))}async mutate(t){let n,r=this.queue.then(async()=>{let o=await this.ensureState();n=await t(o),o.updatedAt=new Date().toISOString(),await this.store.save(o)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(t,n){return this.mutate(r=>(r.policy=as({...r.policy,...t}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let t=await this.ensureState(),n=r=>t.reviews.filter(o=>o.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:t.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:t.audit.length,policy:{...t.policy},updatedAt:t.updatedAt}}async listReviews(t){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!t||r.status===t).sort((r,o)=>o.updatedAt.localeCompare(r.updatedAt)))}async auditLog(t=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(t)));return structuredClone(n.audit.slice(-r).reverse())}async assess(t,n){let r=await this.ensureState(),o=Yl(t),s=Sn(t.title),i=n.filter(p=>p.slug!==t.slug&&Sn(p.title)===s&&os(p.content)!==os(t.content)).map(p=>p.slug),a=Ul(t),c=[];o<r.policy.autoApproveThreshold&&c.push(`confidence:${o.toFixed(2)}`),a&&o<r.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:u,requiresReview:i.length>0||o<r.policy.autoApproveThreshold||a&&o<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(t,n){let r=await this.assess(t,n);return this.mutate(o=>{let s=o.reviews.find(c=>c.sourceKey===t.sourceKey&&c.digest===t.digest);if(s?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(s)};if(s?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(s)};if(!r.requiresReview)return this.audit(o,"knowledge:auto-approved","system",{sourceKey:t.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(s?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(s)};let i=new Date().toISOString(),a={id:ts(),sourceKey:t.sourceKey,sourceType:t.sourceType,slug:t.slug,marker:t.marker,digest:t.digest,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...new Set([...t.tags,t.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};return o.reviews.push(a),this.audit(o,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(a)}})}async markApplied(t,n){await this.mutate(r=>{let o=r.reviews.find(s=>s.sourceKey===t&&s.digest===n&&s.status==="approved");o&&(o.appliedAt=new Date().toISOString(),o.updatedAt=o.appliedAt,this.audit(r,"knowledge:applied",o.reviewedBy??"system",{reviewId:o.id,sourceKey:t}))})}async decide(t,n,r){return this.mutate(async o=>{let s=o.reviews.find(u=>u.id===t);if(!s)throw new M(`Governance review not found: ${t}`,404);if(s.status!=="pending")throw new M("Governance review is already resolved",409);let i=new Date().toISOString();if(s.reviewedAt=i,s.reviewedBy=n.principal,s.updatedAt=i,n.note?.trim()&&(s.reviewNote=n.note.trim()),n.action==="reject")return s.status="rejected",this.audit(o,"knowledge:rejected",n.principal,{reviewId:t,sourceKey:s.sourceKey}),structuredClone(s);if(n.action==="supersede")return s.status="superseded",n.targetReviewId&&(s.supersededBy=n.targetReviewId),this.audit(o,"knowledge:superseded",n.principal,{reviewId:t,sourceKey:s.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(s);if(n.action==="merge"){if(!n.targetReviewId)throw new M("targetReviewId is required for merge",400);let u=o.reviews.find(p=>p.id===n.targetReviewId);if(!u)throw new M("Merge target review not found",404);return s.status="superseded",s.mergedInto=u.id,this.audit(o,"knowledge:merged",n.principal,{reviewId:t,sourceKey:s.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(s)}s.status="approved";let c=(await r.listPages()).find(u=>u.slug===s.slug);if(c&&!c.tags.includes(s.marker))throw new M(`Wiki page '${s.slug}' is manually managed`,409);return c?await r.updatePage(s.slug,{title:s.title,summary:s.summary??"",content:s.content,tags:s.tags}):await r.createPage({slug:s.slug,title:s.title,...s.summary?{summary:s.summary}:{},content:s.content,tags:s.tags}),s.appliedAt=i,this.audit(o,"knowledge:approved",n.principal,{reviewId:t,sourceKey:s.sourceKey}),structuredClone(s)})}async quality(t){let n=await this.ensureState(),r=await t.listPages(),o=Date.now(),s=n.policy.staleAfterDays*864e5,i=r.map(p=>{let l=o-Date.parse(p.updatedAt);return{slug:p.slug,title:p.title,updatedAt:p.updatedAt,ageDays:Math.max(0,Math.floor(l/864e5)),stale:Number.isFinite(l)&&l>s}}).filter(p=>p.stale).map(({stale:p,...l})=>l),a=new Map;for(let p of r){let l=Sn(p.title),f=a.get(l)??[];f.push(p),a.set(l,f)}let c=[...a.entries()].filter(([,p])=>p.length>1).map(([p,l])=>({title:p,pages:l.map(f=>f.slug)})),u=n.reviews.filter(p=>p.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(p=>p.tags.some(l=>l.startsWith("toolnet-auto-"))).length,manualPages:r.filter(p=>!p.tags.some(l=>l.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(p=>p.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(p=>p.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var ms="wiki/automation.v1.json",gs="toolnet.wiki-automation.v1",bn=8e3,cs=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function Fe(e){return Ql("sha256").update(JSON.stringify(e)).digest("hex")}function Ke(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function us(e){return Array.isArray(e)?e:[]}function ys(e){return typeof e!="string"?void 0:e.replace(/\s+/gu," ").trim()||void 0}function vn(e){return Array.isArray(e)?e.map(ys).filter(t=>!!t):[]}function W(e,t){for(let n of t){let r=ys(e[n]);if(r)return r}}function Le(e){let t=new Set,n=[];for(let r of e){let o=r.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();t.has(s)||(t.add(s),n.push(o))}return n}function Et(e,t=0,n=""){if(t>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(cs.has(r))return[];if(typeof e=="string"){let i=e.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(e))return e.flatMap(i=>Et(i,t+1,n));let o=Ke(e);if(!o)return[];let s=[];for(let[i,a]of Object.entries(o)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();cs.has(c)||s.push(...Et(a,t+1,i))}return s}function ls(e){let n=Le(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(o=>Et(e[o],0,o)));return(n.length>0?n:Le(Et(e))).join(`
|
|
136
136
|
|
|
137
|
-
`).slice(0,
|
|
137
|
+
`).slice(0,bn)}function ds(e,t){return W(e,["id","key","fingerprint","knowledgeId","sceneId"])??t}function fs(e,t){return W(e,["title","name","topic","label","task","kind","type"])??t}function nd(e){return(W(e,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function rd(e){return(W(e,["kind","sceneKind","type"])??"").toLowerCase()}function od(e){let t=Ke(e);if(!t)return[];let n=[],r=us(t.knowledge);for(let[s,i]of r.entries()){let a=Ke(i);if(!a)continue;let c=nd(a);if(c==="session"||c==="transient")continue;let u=ls(a);if(u.length<20)continue;let p=ds(a,Fe(a).slice(0,16)),l=fs(a,`Durable Memory ${s+1}`);n.push({sourceKey:`memory:${p}`,sourceType:"memory",title:l,summary:W(a,["summary","description"]),content:u,tags:Le(["toolnet","auto","memory",...c?[c]:[]])})}let o=us(t.scenes);for(let[s,i]of o.entries()){let a=Ke(i);if(!a)continue;let c=rd(a);if(c==="session-context")continue;let u=ls(a);if(u.length<20)continue;let p=ds(a,Fe(a).slice(0,16)),l=fs(a,`Knowledge Scene ${s+1}`);n.push({sourceKey:`scene:${p}`,sourceType:"scene",title:l,summary:W(a,["summary","description"]),content:u,tags:Le(["toolnet","auto","scene",...c?[c]:[]])})}return n}function sd(e){return ps(e,".toolnet","memory","skills")}function id(e){let t=sd(e);if(!Xl(t))return{candidates:[],failed:0};let n=[],r=0,o=Zl(t).filter(s=>s.endsWith(".json")).sort();for(let s of o)try{let i=JSON.parse(ed(ps(t,s),"utf8")),a=Ke(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let c=W(a,["id","fingerprint"])??td(s,".json"),u=W(a,["task"])??"",p=W(a,["title"])||u||`Reusable Skill ${c.slice(0,8)}`,l=W(a,["summary"])??void 0,f=vn(a.steps),d=vn(a.verification),m=vn(a.files),k=[];u&&k.push(`## Task
|
|
138
138
|
${u}`),l&&k.push(`## Summary
|
|
139
139
|
${l}`),f.length>0&&k.push(`## Procedure
|
|
140
140
|
${f.map((h,v)=>`${v+1}. ${h}`).join(`
|
|
@@ -144,13 +144,13 @@ ${d.map(h=>`- ${h}`).join(`
|
|
|
144
144
|
${m.map(h=>`- \`${h}\``).join(`
|
|
145
145
|
`)}`);let g=k.join(`
|
|
146
146
|
|
|
147
|
-
`).slice(0,
|
|
148
|
-
`).slice(0,
|
|
149
|
-
`,{encoding:"utf8",mode:384}),
|
|
150
|
-
`,c=w(r.map(l=>l.fingerprint).sort().join("|")).slice(0,16),u=w(t.sessionKey).slice(0,12),p=[
|
|
151
|
-
`,"application/json"),u}};function
|
|
147
|
+
`).slice(0,bn);if(g.length<20)continue;n.push({sourceKey:`skill:${c}`,sourceType:"skill",title:p,summary:l,content:g,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function wn(e){let t=new Date().toISOString();return{schema:gs,version:1,projectId:e,entries:[],createdAt:t,updatedAt:t}}async function ad(e,t){let n=await e.getText(ms);if(!n)return wn(t);try{let r=JSON.parse(n);return r.schema!==gs||r.version!==1||r.projectId!==t||!Array.isArray(r.entries)?wn(t):r}catch{return wn(t)}}async function cd(e,t){await e.put(ms,JSON.stringify(t,null,2),"application/json")}function ud(e){return`toolnet-auto-${Fe(e).slice(0,12)}`}function ld(e){let t=ae(e.title).slice(0,72),n=Fe(e.sourceKey).slice(0,10);return ae(`auto-${e.sourceType}-${t}-${n}`)}function dd(e){return[`> Auto-generated by ToolNet Knowledge Automation from ${e.sourceType==="skill"?"reusable Skill Memory":e.sourceType==="scene"?"semantic memory scene":"durable memory"}.`,"",e.content].join(`
|
|
148
|
+
`).slice(0,bn)}function fd(e){return Fe({sourceType:e.sourceType,title:e.title,summary:e.summary,content:e.content,tags:e.tags})}function pd(e,t){return e.tags.includes(t)}async function hs(e){let t=od(e.hierarchy),n=id(e.project.rootPath),r=new Map;for(let d of[...t,...n.candidates])r.set(d.sourceKey,d);let o=[...r.values()].sort((d,m)=>d.sourceKey.localeCompare(m.sourceKey)),s={schema:"toolnet.wiki-automation-result.v1",scanned:t.length+n.candidates.length,eligible:o.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new At(new It(e.storage,e.project));await i.initialize();let a=new Mt(new jt(e.storage,e.project));await a.initialize();let c=await ad(e.storage,e.project.id),u=await i.listPages(),p=new Map(u.map(d=>[d.slug,d])),l=new Map(c.entries.map(d=>[d.sourceKey,d]));for(let d of o)try{let m=ud(d.sourceKey),k=fd(d),g=l.get(d.sourceKey),h=g?.slug??ld(d),v=p.get(h);if(v&&!pd(v,m)){s.skipped+=1;continue}let x=Le([...d.tags,m]),R=dd(d),C=await a.gate({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:h,marker:m,digest:k,title:d.title,...d.summary?{summary:d.summary}:{},content:R,tags:x},[...p.values()]);if(!C.allowed){C.mode==="pending-review"?s.reviewPending+=1:s.skipped+=1;continue}C.mode==="auto-approved"?s.autoApproved+=1:C.mode==="review-approved"&&(s.reviewApproved+=1),v?g?.digest!==k?(v=await i.updatePage(h,{title:d.title,summary:d.summary??"",content:R,tags:x}),p.set(v.slug,v),s.updated+=1,s.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:v.slug,action:"updated"})):(s.unchanged+=1,s.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:h,action:"unchanged"})):(v=await i.createPage({slug:h,title:d.title,summary:d.summary,content:R,tags:x}),p.set(v.slug,v),s.created+=1,s.pages.push({sourceKey:d.sourceKey,sourceType:d.sourceType,slug:v.slug,action:"created"}));let N=new Date().toISOString(),A={sourceKey:d.sourceKey,sourceType:d.sourceType,slug:h,digest:k,marker:m,updatedAt:N},b=c.entries.findIndex(z=>z.sourceKey===d.sourceKey);b>=0?c.entries[b]=A:c.entries.push(A),l.set(d.sourceKey,A),await a.markApplied(d.sourceKey,k)}catch(m){if(m instanceof M&&m.statusCode===409){s.skipped+=1;continue}s.failed+=1}let f=new Date().toISOString();return c.updatedAt=f,c.lastRunAt=f,c.entries.sort((d,m)=>d.sourceKey.localeCompare(m.sourceKey)),await cd(e.storage,c),s}import{createHash as md}from"node:crypto";import{chmodSync as Ss,existsSync as gd,mkdirSync as yd,readFileSync as ak,readdirSync as ck,renameSync as hd,statSync as uk,writeFileSync as kd}from"node:fs";import{join as vs}from"node:path";var Sd="toolnet.skill-memory.v1",ks=5,vd=16,wd=24,bd=32;function xd(e){return md("sha256").update(e).digest("hex")}function We(e,t=Number.MAX_SAFE_INTEGER){let n=new Set,r=[];for(let o of e){let s=o.replace(/\s+/gu," ").trim();if(!s)continue;let i=s.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(s),r.length>=t))break}return r}function xn(e,t=360){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:n.slice(0,Math.max(0,t-1)).trimEnd()+"\u2026"}function Ad(e){return e.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 B(e,t=360){return e&&xn(Ad(e),t)||void 0}function ze(e,t){for(let n of t){let r=e[n];if(typeof r=="string"&&r.trim())return r}}function ws(e,t){for(let n of t){let r=e[n];if(typeof r=="number"&&Number.isFinite(r))return r;if(typeof r=="string"&&r.trim()&&Number.isFinite(Number(r)))return Number(r)}}function bs(e,t){for(let n of t){let r=e[n];if(typeof r=="boolean")return r;if(typeof r=="string"){let o=r.trim().toLowerCase();if(["true","yes","pass","passed","success","succeeded","ok"].includes(o))return!0;if(["false","no","fail","failed","error"].includes(o))return!1}}}function xs(e){let t=e.data??{};if(bs(t,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=ws(t,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let o=ze(t,["status","result","outcome"]);return!!(o&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(o))}function De(e){let t=e.data??{};if(xs(e))return!1;if(bs(t,["passed","pass","success","succeeded","ok"])===!0||ws(t,["exitCode","exit_code","code","statusCode"])===0)return!0;let o=ze(t,["status","result","outcome"]);return o&&/\b(pass(?:ed)?|success(?:ful)?|succeeded|ok|green|complete(?:d)?)\b/iu.test(o)?!0:e.type==="commit"||e.type==="deploy"}function As(e){let t=e.data??{},n=ze(t,["path","file","filePath","filename","target"]);if(n)return B(n,260);let r=e.provenance?.files;return B(r?.[0],260)}function An(e){return B(ze(e.data??{},["command","cmd","script"]),420)}function ye(e){return B(ze(e.data??{},["name","test","suite","title","message","text","result","status"]),300)}function Id(e){let t=[];for(let n of[...e].sort((r,o)=>r.sequence-o.sequence))if(De(n)){if(n.type==="test"){let r=ye(n)??An(n)??"Tests passed";t.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=ye(n);t.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=ye(n);t.push(r?`Deploy: ${r}`:"Deployment completed")}}return We(t,10)}function jd(e,t){let n=[];for(let r of[...e].sort((o,s)=>o.sequence-s.sequence))switch(r.type){case"file_write":case"file_edit":{let o=As(r);o&&n.push(`Update ${o}`);break}case"command":{if(xs(r))break;let o=An(r);o&&n.push(`Run: ${o}`);break}case"test":{if(!De(r))break;let o=ye(r)??An(r)??"project tests";n.push(`Verify: ${o}`);break}case"commit":{if(!De(r))break;let o=ye(r);n.push(o?`Commit: ${o}`:"Commit verified changes");break}case"deploy":{if(!De(r))break;let o=ye(r);n.push(o?`Deploy: ${o}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of t.files.slice(0,8)){let o=B(r,260);o&&n.push(`Update ${o}`)}return We(n,vd)}function Md(e,t){let n=[...t.files];for(let r of e){let o=As(r);o&&n.push(o);for(let s of r.provenance?.files??[]){let i=B(s,260);i&&n.push(i)}}return We(n,wd)}function Ed(e){return We(e.filter(t=>["file_write","file_edit","command","test","commit","deploy"].includes(t.type)).map(t=>t.id),bd)}function Pd(e){return e.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function Is(e,t,n){if(t.length===0)return[];let r=Id(t),o=We(n.completed.map(m=>B(m,280)??""),ks);if(!(o.length>0||t.some(m=>["test","commit","deploy"].includes(m.type)&&De(m))))return[];let i=B(n.task,280)??B(n.nextActions[0],280),a=o.length>0?o:i?[i]:[];if(a.length===0)return[];let c=jd(t,n);if(c.length===0)return[];let u=Md(t,n),p=Ed(t),l=Math.min(...t.map(m=>m.sequence)),f=Math.max(...t.map(m=>m.sequence)),d=Pd(t);return a.slice(0,ks).map(m=>{let k=[`Reusable procedure learned from successful task: ${m}.`,u.length>0?`Files: ${u.slice(0,6).join(", ")}.`:"",r.length>0?`Verification: ${r.slice(0,4).join("; ")}.`:""].filter(Boolean),g=JSON.stringify({projectId:e.projectId,task:m,steps:c,verification:r,files:u}),h=xd(g);return{schema:Sd,version:1,id:`skill-${h.slice(0,24)}`,fingerprint:h,projectId:e.projectId,title:xn(`SOP: ${m}`,180),task:m,summary:xn(k.join(" "),900),steps:c,verification:r,files:u,source:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:l,lastSequence:f,eventIds:p},createdAt:d}})}function Cd(e){return vs(e.rootPath,".toolnet","memory","skills")}function Td(e){let t=Cd(e);return yd(t,{recursive:!0,mode:448}),Ss(t,448),t}function js(e,t){if(t.length===0)return{written:0,deduped:0,files:[]};let n=Td(e),r=0,o=0,s=[];for(let i of t){if(i.projectId!==e.id)throw new Error(`Skill project mismatch: ${i.projectId} != ${e.id}`);let a=vs(n,`${i.id}.json`);if(s.push(a),gd(a)){o+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;kd(c,JSON.stringify(i,null,2)+`
|
|
149
|
+
`,{encoding:"utf8",mode:384}),hd(c,a),Ss(a,384),r+=1}return{written:r,deduped:o,files:s}}var wk="0".repeat(64);function Ms(e){return String(e).padStart(12,"0")}function Od(e){return`projects/${e.projectId}/memory/learned`}var Pt=class{constructor(t){this.storage=t}storage;async write(t,n,r){if(r.length===0||n.length===0)return null;let o=Math.min(...n.map(l=>l.sequence)),s=Math.max(...n.map(l=>l.sequence)),i={version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,createdAt:new Date().toISOString(),firstSequence:o,lastSequence:s,candidateCount:r.length,candidates:r},a=JSON.stringify(i,null,2)+`
|
|
150
|
+
`,c=w(r.map(l=>l.fingerprint).sort().join("|")).slice(0,16),u=w(t.sessionKey).slice(0,12),p=[Od(t),"batches",`${Ms(o)}-${Ms(s)}-${u}-${c}.json`].join("/");return await this.storage.exists(p)||await this.storage.put(p,a,"application/json"),p}};import{createHash as Rd}from"node:crypto";function Es(e){return String(e).padStart(12,"0")}function Ps(e){return Rd("sha256").update(e).digest("hex")}function Nd(e){return`projects/${e.projectId}/memory/hierarchy`}var Ct=class{constructor(t){this.storage=t}storage;async write(t,n,r){if(n.length===0||r.facts.length===0)return null;let o=Math.min(...n.map(p=>p.sequence)),s=Math.max(...n.map(p=>p.sequence)),i={schema:"toolnet.memory-hierarchy-batch.v1",version:1,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,createdAt:new Date().toISOString(),firstSequence:o,lastSequence:s,hierarchy:r},a=Ps([...r.facts.map(p=>p.id),...r.knowledge.map(p=>p.id)].sort().join("|")).slice(0,16),c=Ps(t.sessionKey).slice(0,12),u=[Nd(t),"batches",`${Es(o)}-${Es(s)}-${c}-${a}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,`${JSON.stringify(i,null,2)}
|
|
151
|
+
`,"application/json"),u}};function Dd(e,t){if(!$d(e))return{events:[],nextOffset:t};let n=Ld(e).size,r=Number.isFinite(t)?Math.max(0,t):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let o=n-r,s=Buffer.alloc(o),i=Kd(e,"r");try{Fd(i,s,0,o,r)}finally{_d(i)}let a=s.toString("utf8"),c=a.lastIndexOf(`
|
|
152
152
|
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
153
|
-
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var
|
|
153
|
+
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Tt=class{constructor(t){this.options=t;this.journal=new Pt(t.storage),this.hierarchyJournal=new Ct(t.storage)}options;journal;hierarchyJournal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,o=Dd(this.options.wal.eventsFile,r);if(o.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:o.nextOffset};let s=yt(this.options.identity,o.events),i=s.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,o.events,i));let c=!1;s.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,o.events,s.hierarchy));let u=Is(this.options.identity,o.events,s.state),p=js(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",s.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",s.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",s.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",s.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",s.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",s.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",s.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",s.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",s.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",s.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",s.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",p.written),this.options.wal.setSourceCursor("memory.skill.deduped",p.deduped);try{let l=eo(this.options.project.rootPath,o.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",l.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",l.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",l.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",l.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let l=await hs({project:this.options.project,storage:this.options.storage,hierarchy:s.hierarchy});this.options.wal.setSourceCursor("memory.wiki_automation.scanned",l.scanned),this.options.wal.setSourceCursor("memory.wiki_automation.eligible",l.eligible),this.options.wal.setSourceCursor("memory.wiki_automation.created",l.created),this.options.wal.setSourceCursor("memory.wiki_automation.updated",l.updated),this.options.wal.setSourceCursor("memory.wiki_automation.unchanged",l.unchanged),this.options.wal.setSourceCursor("memory.wiki_automation.skipped",l.skipped),this.options.wal.setSourceCursor("memory.wiki_automation.failed",l.failed),this.options.wal.setSourceCursor("memory.wiki_automation.review_pending",l.reviewPending),this.options.wal.setSourceCursor("memory.wiki_automation.auto_approved",l.autoApproved),this.options.wal.setSourceCursor("memory.wiki_automation.review_approved",l.reviewApproved)}catch{this.options.wal.setSourceCursor("memory.wiki_automation.failed",1)}return this.options.wal.setSourceCursor("memory.learner.offset",o.nextOffset),{scannedEvents:o.events.length,candidates:i.length,journalWritten:a,nextOffset:o.nextOffset}}};function Cs(e,t,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=tt(t,n);if(r.length===0)return{updated:!1,observations:0};let o=Er(e,r);co(e,o),so(e,{agent:t.agent,nativeSessionId:t.nativeSessionId,observations:r,workState:o});try{Co(e,t,n,o)}catch{}try{Rr({project:e,identity:t,state:o,reason:"continuous-checkpoint",sequence:n.at(-1)?.sequence??0})}catch{}return{updated:!0,observations:r.length}}var Ot=class{identity;wal;remote;sanitizer=new H;learner;continuity;semantic;handoff;project;title;metadata;constructor(t){this.project=t.project,this.identity=Ro(t.project,t.agent,t.nativeSessionId),this.title=t.title,this.metadata=this.sanitizer.sanitizeValue(t.metadata??{}),this.wal=new xt(this.identity,t.eventContext),this.remote=new ht(t.storage,t.maxEventsPerChunk??100,t.maxChunkBytes??512*1024),this.learner=new Tt({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.continuity=new rt({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.semantic=new ut({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.handoff=new at({project:t.project,storage:t.storage,identity:this.identity})}sanitizeEvent(t){let n=t.provenance?{...t.provenance,metadata:this.sanitizer.sanitizeValue(t.provenance.metadata)}:void 0;return{...t,data:this.sanitizer.sanitizeValue(t.data??{}),provenance:n}}checkpointLocal(t){if(t.length!==0)try{Cs(this.project,this.identity,t)}catch{}}start(t={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:t,provenance:{source:this.identity.agent}})}record(t){let n=this.wal.append([this.sanitizeEvent(t)]);return this.checkpointLocal(n),n[0]}recordMany(t){let n=this.wal.append(t.map(r=>this.sanitizeEvent(r)));return this.checkpointLocal(n),n}setSourceCursor(t,n){this.wal.setSourceCursor(t,n)}async flush(){let t=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,t.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(t.events.length>0){let o=t.events[t.events.length-1];this.wal.markRemote(o.sequence,t.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"&&t.events.length>0)try{let o=t.events[t.events.length-1],s=["session_idle","session_end","session_compact"].includes(o.type)?o.type:"checkpoint";await this.handoff.capture(s,o.sequence)}catch{}return r}async idle(t={}){return this.record({type:"session_idle",data:t,provenance:{source:this.identity.agent}}),this.flush()}async end(t={}){return this.record({type:"session_end",data:t,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as Wd,openSync as zd,closeSync as qd,readSync as Bd,statSync as Vd}from"node:fs";function Hd(e){let t=typeof e.role=="string"?e.role:"",n=typeof e.type=="string"?e.type.toLowerCase():"";return t==="user"||n.includes("user")?"user_prompt":t==="assistant"||n.includes("assistant")||n.includes("model")?"assistant_message":n.includes("tool")||"toolCall"in e||"tool_call"in e?"tool_call":n.includes("error")?"error":"message"}function Jd(e){let t=[e.timestamp,e.createdAt,e.time,e.created_at];for(let n of t){if(typeof n=="string"){let r=new Date(n);if(!Number.isNaN(r.getTime()))return r.toISOString()}if(typeof n=="number"){let r=n;r<1e11&&(r*=1e3);let o=new Date(r);if(!Number.isNaN(o.getTime()))return o.toISOString()}}return new Date().toISOString()}function Ts(e,t={offset:0}){if(!Wd(e))return{events:[],nextOffset:t.offset,reset:!1};let n=Vd(e).size,r=t.offset>n,o=r?0:t.offset;if(o===n)return{events:[],nextOffset:n,reset:r};let s=n-o,i=Buffer.alloc(s),a=zd(e,"r");try{Bd(a,i,0,s,o)}finally{qd(a)}let c=i.toString("utf8"),u=c.lastIndexOf(`
|
|
154
154
|
`);if(u<0)return{events:[],nextOffset:o,reset:r};let p=c.slice(0,u+1),l=Buffer.byteLength(p,"utf8"),f=[],d=0;for(let m of p.split(`
|
|
155
155
|
`)){if(!m)continue;let k=Buffer.byteLength(m+`
|
|
156
|
-
`,"utf8"),g=o+d;d+=k;let h;try{h=JSON.parse(m)}catch{f.push({type:"custom",sourceEventId:`transcript:${g}`,sourceSequence:g,data:{format:"raw-line",content:m},provenance:{source:"agy-transcript",sourcePath:e,sourceOffset:g}});continue}let v=h&&typeof h=="object"&&!Array.isArray(h)?h:{value:h};f.push({type:
|
|
156
|
+
`,"utf8"),g=o+d;d+=k;let h;try{h=JSON.parse(m)}catch{f.push({type:"custom",sourceEventId:`transcript:${g}`,sourceSequence:g,data:{format:"raw-line",content:m},provenance:{source:"agy-transcript",sourcePath:e,sourceOffset:g}});continue}let v=h&&typeof h=="object"&&!Array.isArray(h)?h:{value:h};f.push({type:Hd(v),timestamp:Jd(v),role:typeof v.role=="string"?v.role:void 0,sourceEventId:`transcript:${g}`,sourceSequence:g,data:v,provenance:{source:"agy-transcript",sourcePath:e,sourceOffset:g}})}return{events:f,nextOffset:o+l,reset:r}}var Gd=[/^<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*$/],Ud=[/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],Yd=["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 Qd(e){let t=e.toLowerCase();return Yd.some(n=>t.includes(n))}function Xd(e){if(!e.trim())return!0;for(let t of Gd)if(t.test(e))return!0;return Qd(e),!1}function Zd(e){let t=e;for(let n of Ud)t=t.replace(n,r=>{let o=r.split(/[:\s=]+/);return o.length>1?`${o[0]}: [REDACTED]`:"[REDACTED]"});return t}function In(e){let t=e.trim();return t?Xd(t)?{content:"",filtered:!0,reason:"noise"}:{content:Zd(t),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function Rt(e){let t={};for(let[n,r]of Object.entries(e))if(typeof r=="string"){let o=In(r);o.filtered||(t[n]=o.content)}else r&&typeof r=="object"&&!Array.isArray(r)?t[n]=Rt(r):Array.isArray(r)?t[n]=r.map(o=>{if(typeof o=="string"){let s=In(o);return s.filtered?null:s.content}return o&&typeof o=="object"?Rt(o):o}).filter(o=>o!==null):t[n]=r;return t}function Os(e){let t=typeof e.type=="string"?e.type.toLowerCase():"";if(t.includes("system")||t.includes("ephemeral")||t==="tool_call"&&!e.result)return!0;if(e.data&&typeof e.data=="object"){let n=e.data,r=typeof n.content=="string"?n.content:"";if(r&&In(r).filtered)return!0}return!1}function nf(e){return e==="~"?Rs():e.startsWith("~/")?ef(Rs(),e.slice(2)):e}async function Ns(e){let t=e.conversationId.trim();if(!t)throw new Error("Agy conversationId is required");let n=tf(nf(e.transcriptPath)),r=new Ot({project:e.project,storage:e.storage,agent:"agy",nativeSessionId:t,metadata:{source:"antigravity-hook",transcriptPath:n,workspacePaths:e.workspacePaths??[],artifactDirectoryPath:e.artifactDirectoryPath,modelName:e.modelName},eventContext:{source:"agy",cwd:e.workspacePaths?.[0]??e.project.rootPath}}),o=r.status(),s=o.sourceCursors["agy.transcript.offset"],i=s?Number(s):0,a=Ts(n,{offset:Number.isFinite(i)?i:0}),c=[];o.lastSequence===0&&c.push({type:"session_start",sourceEventId:`agy:${t}:start`,data:{workspacePaths:e.workspacePaths??[],transcriptPath:n,modelName:e.modelName},provenance:{source:"antigravity-hook",sourcePath:n}}),a.reset&&c.push({type:"custom",sourceEventId:`agy:${t}:transcript-reset:${a.nextOffset}`,data:{event:"transcript_reset",transcriptPath:n},provenance:{source:"agy-transcript",sourcePath:n}});let u=a.events.filter(f=>!Os(f.data)).map(f=>({...f,data:Rt(f.data)}));c.push(...u),e.phase==="stop"&&(e.error&&c.push({type:"error",sourceEventId:["agy",t,"stop-error",e.terminationReason??"",a.nextOffset].join(":"),data:{error:e.error,terminationReason:e.terminationReason,fullyIdle:e.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),e.fullyIdle&&c.push({type:"session_idle",sourceEventId:["agy",t,"idle",a.nextOffset].join(":"),data:{terminationReason:e.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let p=r.recordMany(c);if(r.setSourceCursor("agy.transcript.offset",a.nextOffset),e.phase&&r.setSourceCursor("agy.last.phase",e.phase),u.length>0)try{let f=u.map(m=>JSON.stringify(m.data)),d=gt(f,t);r.setSourceCursor("agy.session.summary",d.summary),r.setSourceCursor("agy.session.facts_count",d.durableFacts.length),wo()&&(Ao()||r.setSourceCursor("agy.raw_transcript.archived","local"))}catch{}let l=await r.flush();return{conversationId:t,imported:p.length,eventCount:l.eventCount,chunkCount:l.chunkCount,status:l.status,transcriptOffset:a.nextOffset,reset:a.reset}}async function rf(){let e="";for await(let t of process.stdin)e+=t.toString();if(!e.trim())return{};try{return JSON.parse(e)}catch{return{}}}function qe(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}function of(e){let t=typeof e.common=="object"&&e.common!==null?e.common:{},n=typeof e.pre_invocation_hook_args=="object"&&e.pre_invocation_hook_args!==null?e.pre_invocation_hook_args:{},r=typeof e.post_invocation_hook_args=="object"&&e.post_invocation_hook_args!==null?e.post_invocation_hook_args:{},o=typeof e.stop_hook_args=="object"&&e.stop_hook_args!==null?e.stop_hook_args:{},s=(typeof e.conversationId=="string"?e.conversationId:"")||(typeof e.conversation_id=="string"?e.conversation_id:"")||(typeof t.conversation_id=="string"?t.conversation_id:""),i=(typeof e.transcriptPath=="string"?e.transcriptPath:"")||(typeof e.transcript_path=="string"?e.transcript_path:"")||(typeof t.transcript_path=="string"?t.transcript_path:""),a=qe(e.workspacePaths).length>0?qe(e.workspacePaths):qe(e.workspace_paths).length>0?qe(e.workspace_paths):qe(t.workspace_paths),c=typeof e.invocationNum=="number"?e.invocationNum:typeof n.invocation_num=="number"?n.invocation_num:typeof e.invocation_num=="number"?e.invocation_num:void 0,u=(typeof e.artifactDirectoryPath=="string"?e.artifactDirectoryPath:"")||(typeof t.artifact_directory_path=="string"?t.artifact_directory_path:"")||(typeof e.artifact_directory_path=="string"?e.artifact_directory_path:"")||void 0,p=(typeof e.modelName=="string"?e.modelName:"")||(typeof t.model_name=="string"?t.model_name:"")||(typeof e.model_name=="string"?e.model_name:"")||void 0,l=o.fully_idle===!0||e.fullyIdle===!0||e.fully_idle===!0,f=(typeof o.termination_reason=="string"?o.termination_reason:"")||(typeof e.terminationReason=="string"?e.terminationReason:"")||(typeof e.termination_reason=="string"?e.termination_reason:"")||void 0,d=(typeof o.error=="string"&&o.error?o.error:"")||(typeof e.error=="string"&&e.error?e.error:"")||void 0;return{conversationId:s,transcriptPath:i,workspacePaths:a,invocationNum:c,artifactDirectoryPath:u,modelName:p,fullyIdle:l,terminationReason:f,error:d}}function sf(e){let t=typeof e.toolCall=="object"&&e.toolCall!==null?e.toolCall:{},n=typeof t.args=="object"&&t.args!==null?t.args:{},r="";try{r=JSON.stringify(n).replace(/\\\\/g,"/").toLowerCase()}catch{r=""}return r.includes(".toolnet/journal")||r.includes(".toolnet/runtime/sources")||r.includes(".toolnet/sessions")?{decision:"deny",reason:"ToolNet continuity guard: do not replay raw .toolnet/journal, .toolnet/runtime/sources or legacy .toolnet/sessions history. Use the injected continuity handoff. If deeper history is required, invoke memory_agent_ask directly."}:{decision:"allow"}}async function af(){let e=process.argv[2]??"post",t=await rf();if(e==="pre-tool"){process.stdout.write(JSON.stringify(sf(t)));return}let n=of(t),r=n.conversationId,o=n.transcriptPath,s=n.workspacePaths,i=To(s);i&&(e==="pre"||e==="stop")&&rr(i.rootPath);let c={};if(i&&r)try{let u=Ve(),p=Zn(Qn({provider:u.storage.provider,huggingface:u.storage.huggingface,localRoot:u.storage.localRoot}),{attempts:2}),l=new Ze(p,i.id,i.name,i.remote??i.name);if(o)try{await Ns({project:i,storage:l,conversationId:r,transcriptPath:o,workspacePaths:s,artifactDirectoryPath:n.artifactDirectoryPath,modelName:n.modelName,phase:e,fullyIdle:n.fullyIdle,terminationReason:n.terminationReason,error:n.error})}catch{}if(e==="pre")try{c=await oo({project:i,storage:l,conversationId:r,invocationNum:n.invocationNum})}catch{c={}}if(e==="stop")try{await Ut(i,l,800)}catch{}}catch{}if(e==="stop"){process.stdout.write(JSON.stringify({decision:"stop"}));return}process.stdout.write(JSON.stringify(c))}af().catch(()=>{process.argv[2]==="stop"?process.stdout.write('{"decision":"stop"}'):process.argv[2]==="pre-tool"?process.stdout.write('{"decision":"allow"}'):process.stdout.write("{}"),process.exitCode=0});export{sf as buildAgyPreToolUseOutput,of as normalizeAgyInput};
|