toolnet-memory 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/toolnet-memory +44 -0
- package/bundle/agy-hook.js +39 -88
- package/bundle/agy.js +38 -104
- package/bundle/auto-integrate.js +131 -707
- package/bundle/codex-context.js +44 -54
- package/bundle/codex.js +47 -83
- package/bundle/context-runtime.js +29 -124
- package/bundle/context.js +14 -15
- package/bundle/doctor.js +3 -6
- package/bundle/full-index.js +8 -18
- package/bundle/graph-index.js +4 -4
- package/bundle/impact.js +3 -3
- package/bundle/incremental.js +4 -4
- package/bundle/learner.js +5 -5
- package/bundle/mcp.js +7 -54
- package/bundle/opencode.js +168 -717
- package/bundle/project-manual.js +6 -6
- package/bundle/runtime.js +11 -11
- package/bundle/semantic.js +6 -6
- package/bundle/setup.js +187 -716
- package/bundle/snapshot.js +4 -4
- package/bundle/update.js +1 -4
- package/bundle/work-continuity.js +6 -6
- package/package.json +1 -1
- package/bundle/api.js +0 -52
- package/bundle/claude-hook.js +0 -78
- package/bundle/claude.js +0 -3
- package/bundle/continuity-certify.js +0 -49
- package/bundle/handoff-refresh.js +0 -12
- package/bundle/init.js +0 -763
- package/bundle/memory-agent.js +0 -48
- package/bundle/memory-query.js +0 -7
- package/bundle/production-certify.js +0 -5
- package/bundle/provider.js +0 -3
- package/bundle/recovery-certify.js +0 -55
package/bundle/codex.js
CHANGED
|
@@ -1,52 +1,26 @@
|
|
|
1
|
-
import{existsSync as
|
|
2
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function
|
|
3
|
-
`,{encoding:"utf8",mode:384}),is(s,r)}function Mt(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var q=class{detect(e=process.cwd()){let n=Z(e),r=fs(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>Qe(ge(r,f))),i=ps(n,o?r:void 0);if(i){let f=Ze(i),d=ms(f);return d.rootPath!==i&&(d.rootPath=i,d.updatedAt=new Date().toISOString(),At(i,d)),Mt(d,i)}let a=new Date().toISOString(),c=cs(r),u={version:1,id:ls(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return At(r,u),Mt(u,r)}};var gs=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],ye=class{scan(e){let n=[];for(let r of gs){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var ee=class{scanner=new ye;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as Ws}from"node:os";import{join as Ls}from"node:path";import{DeleteObjectCommand as ys,GetObjectCommand as hs,HeadObjectCommand as Ss,ListObjectsV2Command as ks,PutObjectCommand as ws,S3Client as vs}from"@aws-sdk/client-s3";import{getSignedUrl as bs}from"@aws-sdk/s3-request-presigner";var he=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new vs({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new ws({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await bs(this.client,new hs({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Ss({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new ys({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new ks({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as Ot,mkdir as xs,readFile as js,readdir as Is,rm as Ps,stat as Rt,writeFile as Cs}from"node:fs/promises";import{dirname as As,join as Ms,relative as Nt,resolve as Es}from"node:path";var te=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Es(this.root,n)}async put(e,n){let r=this.path(e);await xs(As(r),{recursive:!0}),await Cs(r,n)}async get(e){try{return await js(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await Ot(this.path(e)),!0}catch{return!1}}async delete(e){await Ps(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ot(n)}catch{return r}let s=async i=>{let a=await Is(i,{withFileTypes:!0});for(let c of a){let u=Ms(i,c.name);if(c.isDirectory()){await s(u);continue}let f=await Rt(u);r.push({key:Nt(this.root,u),size:f.size,updatedAt:f.mtime.toISOString()})}},o=await Rt(n);return o.isDirectory()?await s(n):r.push({key:Nt(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Ts,GetObjectCommand as Os,HeadObjectCommand as Rs,ListObjectsV2Command as Ns,PutObjectCommand as _s,S3Client as $s}from"@aws-sdk/client-s3";import{getSignedUrl as Ks}from"@aws-sdk/s3-request-presigner";var ne=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new $s({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new _s({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Ks(this.client,new Os({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Rs({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new Ts({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Ns({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function et(t,e){return console.warn(e),new te(t)}function _t(t){let e=t.localRoot??Ls(Ws(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new ne({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):et(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new ne({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):et(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new he({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):et(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new te(e)}function Fs(t){return new Promise(e=>setTimeout(e,t))}async function $t(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(a){if(o=a,i>=n)break;let c=Math.min(s,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await Fs(c+u)}throw o}var Ds=new Set(["put","get","getText","delete","list"]);function Kt(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:Ds.has(r)?(...o)=>$t(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Wt(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Lt(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var Se=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Wt(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
|
|
4
|
-
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=
|
|
5
|
-
`,{encoding:"utf8",mode:384}),
|
|
6
|
-
`,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let
|
|
7
|
-
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),
|
|
1
|
+
import{existsSync as no,readFileSync as ro}from"node:fs";import{spawn as so}from"node:child_process";import{homedir as oo}from"node:os";import{join as io}from"node:path";import{existsSync as Xt,readFileSync as Qt}from"node:fs";import{homedir as Zt}from"node:os";import{join as en}from"node:path";function tn(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
|
|
2
|
+
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function nn(){let t=process.env.TOOLNET_GLOBAL_ENV??en(Zt(),".config","toolnet-memory",".env");if(!Xt(t))return;let e=Qt(t,"utf8");for(let n of e.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let o=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=tn(r.slice(s+1)))}}nn();function W(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function D(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function H(){return{memory:{autoCapture:W(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:W(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:W(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:W(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:D(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:D(process.env.MEMORY_RERANK_TOP,10),finalContext:D(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:D(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:W(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:D(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as rn}from"node:crypto";import{existsSync as xe,mkdirSync as sn,readFileSync as on,renameSync as an,writeFileSync as cn}from"node:fs";import{basename as un,dirname as Y,join as G,parse as De,resolve as B}from"node:path";var Be=".toolnet",ln="project.json";function dn(t){return rn("sha256").update(t).digest("hex").slice(0,16)}function ke(t){return G(t,Be,ln)}function pn(t){return xe(ke(t))}function fn(t,e){let n=B(t),r=De(n).root;for(;;){if(pn(n))return n;if(n===r||e&&n===B(e))break;let s=Y(n);if(s===n)break;n=s}return null}function mn(t){let e=B(t),n=De(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>xe(G(e,o))))return e;if(e===n)break;let s=Y(e);if(s===e)break;e=s}return B(t)}function gn(t){let e;try{e=JSON.parse(on(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let n=e;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:Y(Y(t)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function Ke(t,e){let n=G(t,Be);sn(n,{recursive:!0});let r=ke(t),s=`${r}.tmp-${process.pid}`;cn(s,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),an(s,r)}function We(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var _=class{detect(e=process.cwd()){let n=B(e),r=mn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>xe(G(r,f))),i=fn(n,o?r:void 0);if(i){let f=ke(i),l=gn(f);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),Ke(i,l)),We(l,i)}let u=new Date().toISOString(),c=un(r),a={version:1,id:dn(r),name:c,remote:c,rootPath:r,createdAt:u,updatedAt:u,graphVersion:0,memoryVersion:0};return Ke(r,a),We(a,r)}};var hn=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],X=class{scan(e){let n=[];for(let r of hn){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var z=class{scanner=new X;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as Kn}from"node:os";import{join as Wn}from"node:path";import{DeleteObjectCommand as yn,GetObjectCommand as Sn,HeadObjectCommand as vn,ListObjectsV2Command as bn,PutObjectCommand as xn,S3Client as kn}from"@aws-sdk/client-s3";import{getSignedUrl as wn}from"@aws-sdk/s3-request-presigner";var Q=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new kn({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new xn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await wn(this.client,new Sn({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new vn({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new yn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new bn({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as ze,mkdir as jn,readFile as In,readdir as Pn,rm as En,stat as Je,writeFile as On}from"node:fs/promises";import{dirname as Cn,join as Tn,relative as qe,resolve as Mn}from"node:path";var J=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Mn(this.root,n)}async put(e,n){let r=this.path(e);await jn(Cn(r),{recursive:!0}),await On(r,n)}async get(e){try{return await In(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await ze(this.path(e)),!0}catch{return!1}}async delete(e){await En(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await ze(n)}catch{return r}let s=async i=>{let u=await Pn(i,{withFileTypes:!0});for(let c of u){let a=Tn(i,c.name);if(c.isDirectory()){await s(a);continue}let f=await Je(a);r.push({key:qe(this.root,a),size:f.size,updatedAt:f.mtime.toISOString()})}},o=await Je(n);return o.isDirectory()?await s(n):r.push({key:qe(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as An,GetObjectCommand as Rn,HeadObjectCommand as Nn,ListObjectsV2Command as _n,PutObjectCommand as $n,S3Client as Ln}from"@aws-sdk/client-s3";import{getSignedUrl as Fn}from"@aws-sdk/s3-request-presigner";var q=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Ln({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new $n({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Fn(this.client,new Rn({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Nn({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new An({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new _n({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function we(t,e){return console.warn(e),new J(t)}function Ve(t){let e=t.localRoot??Wn(Kn(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new q({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):we(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new q({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):we(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Q({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):we(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new J(e)}function Dn(t){return new Promise(e=>setTimeout(e,t))}async function Ue(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(u){if(o=u,i>=n)break;let c=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,c*.2));await Dn(c+a)}throw o}var Bn=new Set(["put","get","getText","delete","list"]);function He(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:Bn.has(r)?(...o)=>Ue(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Ye(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Ge(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var Z=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Ye(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(u){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${u instanceof Error?u.message:String(u)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
|
|
4
|
+
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Ge(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{join as Yn}from"node:path";import{createHash as zn}from"node:crypto";import{dirname as Jn}from"node:path";import{mkdirSync as qn,readFileSync as Vn,renameSync as Un,writeFileSync as Hn}from"node:fs";function v(t){return zn("sha256").update(t).digest("hex")}function je(t){if(Array.isArray(t))return t.map(je);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=je(e[r]);return n}return t}function Xe(t){return JSON.stringify(je(t))}function Qe(t){try{return JSON.parse(Vn(t,"utf8"))}catch{return null}}function j(t,e){qn(Jn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;Hn(n,JSON.stringify(e,null,2)+`
|
|
5
|
+
`,{encoding:"utf8",mode:384}),Un(n,t)}function Ze(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=v(n).slice(0,12);if(!r||r==="."||r==="..")return`${e}--${s}`;let o=r.slice(0,100);return o===n&&n.length<=100?o:`${o.slice(0,85)}--${s}`}function et(t,e,n){let r=e.trim(),s=n.trim();if(!r)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=Ze(r.toLowerCase(),"agent"),i=Ze(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:r,nativeSessionId:s,sessionKey:`${r}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:Yn(t.rootPath,".toolnet","sessions",o,i)}}function tt(t){return String(t).padStart(12,"0")}var ee=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
|
|
6
|
+
`,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let u=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!u)continue;let c=Number(u[1]),a=Number(u[2]);!Number.isFinite(c)||!Number.isFinite(a)||(s.push({key:i.key,start:c,end:a}),o=Math.max(o,a))}return s.sort((i,u)=>i.start-u.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
|
|
7
|
+
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),u=n.filter(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(u)){let S=g[0],w=g[g.length-1],M=g.map(A=>JSON.stringify(A)).join(`
|
|
8
8
|
`)+`
|
|
9
|
-
`,
|
|
9
|
+
`,N=v(M).slice(0,16),O=[e.remotePrefix,"events",`${tt(S.sequence)}-${tt(w.sequence)}-${N}.jsonl`].join("/");await this.storage.exists(O)||await this.storage.put(O,M,"application/x-ndjson"),c+=g.length}let a=await this.scan(e),f=n[n.length-1],l=o?.status??"active";f?.type==="session_end"||f?.type==="session_idle"?l="idle":f?.type==="error"?l="error":n.length>0&&(l="active");let p=new Date().toISOString(),d=n[0],y={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:l,createdAt:o?.createdAt??d?.timestamp??p,updatedAt:f?.timestamp??p,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:f?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(y.title=s.title??o?.title);let h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:p};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,y),{uploadedEvents:c,lastRemoteSequence:a.maxSequence,eventCount:y.eventCount,chunkCount:y.chunkCount,status:l}}};import{closeSync as Ie,existsSync as Gn,fsyncSync as Xn,mkdirSync as Qn,openSync as Pe,readSync as Zn,rmSync as nt,statSync as rt,writeSync as er}from"node:fs";import{join as Ee}from"node:path";var tr=12e4,nr=80,rr=2e3;function sr(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var te=class{constructor(e){this.identity=e;Qn(e.localDirectory,{recursive:!0}),this.eventsFile=Ee(e.localDirectory,"events.jsonl"),this.stateFile=Ee(e.localDirectory,"state.json"),this.lockFile=Ee(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return Qe(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){j(this.stateFile,e)}acquireLock(){for(let e=0;e<nr;e+=1)try{return Pe(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-rt(this.lockFile).mtimeMs>tr){nt(this.lockFile,{force:!0});continue}}catch{}sr(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{Ie(n),nt(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let l of e){let p=l.timestamp??new Date().toISOString(),d=l.data??{},y=l.provenance?.rawDigest??v(Xe(d)),h=l.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,l.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,l.type,p,y].join("|"),g=v(h).slice(0,32);if(r.has(g))continue;s+=1;let S={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:l.type,timestamp:p,data:d,provenance:{...l.provenance,rawDigest:y}};l.role!==void 0&&(S.role=l.role),l.sourceEventId!==void 0&&(S.sourceEventId=l.sourceEventId),l.sourceSequence!==void 0&&(S.sourceSequence=l.sourceSequence),o.push(S),r.add(g)}if(o.length===0)return[];let i=o.map(l=>JSON.stringify(l)).join(`
|
|
10
10
|
`)+`
|
|
11
|
-
`,
|
|
12
|
-
`).filter(Boolean).map(
|
|
13
|
-
|
|
14
|
-
`)
|
|
15
|
-
`).filter(
|
|
16
|
-
|
|
17
|
-
`).
|
|
18
|
-
`)
|
|
19
|
-
`);return
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`)
|
|
23
|
-
`;ei(Ie(Ho(t),`${c}.json`),f)?s+=1:o+=1,i.push(c),n=ti(n,{id:c,kind:a.type,bytes:Buffer.byteLength(f,"utf8"),createdAt:a.timestamp,sourceRefs:[Zo(a)],files:Qo(a)})}return r>0&&Yo(t,n),{eligible:r,written:s,deduped:o,graphNodes:n.nodes.length,assetIds:i}}import{createHash as ui}from"node:crypto";import{existsSync as li,readdirSync as di,readFileSync as pi}from"node:fs";import{basename as fi,join as On}from"node:path";import{randomUUID as Sn}from"node:crypto";var x=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function re(t){let e=new Set,n=[];for(let r of t){let s=r.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function B(t){let e=t.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!e)throw new x("Invalid Wiki slug",400);return e}function yn(t){let e=[];for(let n of t.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&e.push(B(r))}return re(e)}function ni(t){return t.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function hn(t){return{id:`revision-${Sn()}`,pageId:t.id,slug:t.slug,revision:t.revision,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...t.tags],links:[...t.links],createdAt:t.updatedAt}}function z(t){return structuredClone(t)}var Pe=class{constructor(e){this.store=e}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(e){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=e(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let e=await this.ensureState(),n=new Set(e.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:e.projectId,pages:e.pages.length,revisions:e.revisions.length,tags:re(e.pages.flatMap(r=>r.tags)).sort((r,s)=>r.localeCompare(s)),links:e.pages.reduce((r,s)=>r+s.links.length,0),orphanPages:e.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:e.pages.filter(r=>r.tags.some(s=>s.startsWith("toolnet-auto-"))).length,updatedAt:e.updatedAt}}async listPages(){let e=await this.ensureState();return z([...e.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(e){let n=await this.ensureState(),r=B(e),s=n.pages.find(o=>o.slug===r||o.id===e);if(!s)throw new x(`Wiki page not found: ${e}`,404);return z(s)}async createPage(e){return this.mutate(n=>{let r=e.title.trim(),s=e.content.trim();if(!r)throw new x("Wiki title is required",400);let o=B(e.slug??r);if(n.pages.some(c=>c.slug===o))throw new x(`Wiki page already exists: ${o}`,409);let i=new Date().toISOString(),a={id:`wiki-${Sn()}`,slug:o,title:r,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:s,tags:re(e.tags??[]),links:yn(s),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(hn(a)),z(a)})}async updatePage(e,n){return this.mutate(r=>{let s=B(e),o=r.pages.find(i=>i.slug===s||i.id===e);if(!o)throw new x(`Wiki page not found: ${e}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new x("Wiki title is required",400);o.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?o.summary=i:delete o.summary}return n.content!==void 0&&(o.content=n.content.trim(),o.links=yn(o.content)),n.tags!==void 0&&(o.tags=re(n.tags)),o.revision+=1,o.updatedAt=new Date().toISOString(),r.revisions.push(hn(o)),z(o)})}async history(e){let n=await this.getPage(e),r=await this.ensureState();return z(r.revisions.filter(s=>s.pageId===n.id).sort((s,o)=>o.revision-s.revision))}async backlinks(e){let n=await this.getPage(e),r=await this.ensureState();return z(r.pages.filter(s=>s.links.includes(n.slug)).sort((s,o)=>s.title.localeCompare(o.title)))}async search(e,n=10){let r=await this.ensureState(),s=re(ni(e));if(s.length===0)return[];let o=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(),f=a.summary?.toLowerCase()??"",d=a.content.toLowerCase(),p=a.tags.map(m=>m.toLowerCase()),l=0;for(let m of s)u===m&&(l+=12),c===m&&(l+=10),c.includes(m)&&(l+=6),u.includes(m)&&(l+=5),p.some(S=>S===m)?l+=5:p.some(S=>S.includes(m))&&(l+=3),f.includes(m)&&(l+=2),d.includes(m)&&(l+=1);l>0&&i.push({page:z(a),score:l})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,o)}};var kn="wiki/state.v1.json";function ri(t){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:t.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function si(t,e){let n=JSON.parse(t);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==e.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var Ce=class{constructor(e,n){this.storage=e;this.project=n}storage;project;async load(){let e=await this.storage.getText(kn);if(!e){let n=ri(this.project);return await this.save(n),n}return si(e,this.project)}async save(e){await this.storage.put(kn,JSON.stringify(e,null,2),"application/json")}};import{createHash as oi,randomUUID as wn}from"node:crypto";var vn="wiki/governance.v1.json",In="toolnet.knowledge-governance.v1",bn=500,se={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function ii(t,e=0,n=1){return Math.max(e,Math.min(n,t))}function lt(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function xn(t){return oi("sha256").update(t.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function ai(t){let e=[t.title,t.summary??"",t.content.slice(0,2e3),...t.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(e)}function ci(t){let e=t.sourceType==="skill"?.96:t.sourceType==="memory"?.94:.88,n=t.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(e+=.03),t.content.length>=200&&(e+=.02),t.content.length<80&&(e-=.05),t.title.length<4&&(e-=.05),ii(e)}function jn(t){let e=new Date().toISOString();return{schema:In,version:1,projectId:t,policy:{...se},reviews:[],audit:[],createdAt:e,updatedAt:e}}function Pn(t){let e=t.autoApproveThreshold??se.autoApproveThreshold,n=t.criticalApproveThreshold??se.criticalApproveThreshold,r=t.staleAfterDays??se.staleAfterDays;if(!Number.isFinite(e)||e<.5||e>1)throw new x("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new x("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new x("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:n,staleAfterDays:r}}var Ae=class{constructor(e,n){this.storage=e;this.project=n}storage;project;async load(){let e=await this.storage.getText(vn);if(!e){let n=jn(this.project.id);return await this.save(n),n}try{let n=JSON.parse(e);if(n.schema!==In||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:Pn(n.policy??se)}}catch{let n=jn(this.project.id);return await this.save(n),n}}async save(e){await this.storage.put(vn,JSON.stringify(e,null,2),"application/json")}},Me=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(e,n,r,s={}){e.audit.push({id:wn(),action:n,principal:r,...s.reviewId?{reviewId:s.reviewId}:{},...s.sourceKey?{sourceKey:s.sourceKey}:{},timestamp:new Date().toISOString(),...s.metadata?{metadata:s.metadata}:{}}),e.audit.length>bn&&(e.audit=e.audit.slice(-bn))}async mutate(e){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=await e(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(e,n){return this.mutate(r=>(r.policy=Pn({...r.policy,...e}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let e=await this.ensureState(),n=r=>e.reviews.filter(s=>s.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:e.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:e.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:e.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:e.audit.length,policy:{...e.policy},updatedAt:e.updatedAt}}async listReviews(e){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!e||r.status===e).sort((r,s)=>s.updatedAt.localeCompare(r.updatedAt)))}async auditLog(e=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(e)));return structuredClone(n.audit.slice(-r).reverse())}async assess(e,n){let r=await this.ensureState(),s=ci(e),o=lt(e.title),i=n.filter(f=>f.slug!==e.slug&<(f.title)===o&&xn(f.content)!==xn(e.content)).map(f=>f.slug),a=ai(e),c=[];s<r.policy.autoApproveThreshold&&c.push(`confidence:${s.toFixed(2)}`),a&&s<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:s,risk:u,requiresReview:i.length>0||s<r.policy.autoApproveThreshold||a&&s<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(e,n){let r=await this.assess(e,n);return this.mutate(s=>{let o=s.reviews.find(c=>c.sourceKey===e.sourceKey&&c.digest===e.digest);if(o?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(o)};if(o?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(o)};if(!r.requiresReview)return this.audit(s,"knowledge:auto-approved","system",{sourceKey:e.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(o?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(o)};let i=new Date().toISOString(),a={id:wn(),sourceKey:e.sourceKey,sourceType:e.sourceType,slug:e.slug,marker:e.marker,digest:e.digest,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...new Set([...e.tags,e.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};return s.reviews.push(a),this.audit(s,"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(e,n){await this.mutate(r=>{let s=r.reviews.find(o=>o.sourceKey===e&&o.digest===n&&o.status==="approved");s&&(s.appliedAt=new Date().toISOString(),s.updatedAt=s.appliedAt,this.audit(r,"knowledge:applied",s.reviewedBy??"system",{reviewId:s.id,sourceKey:e}))})}async decide(e,n,r){return this.mutate(async s=>{let o=s.reviews.find(u=>u.id===e);if(!o)throw new x(`Governance review not found: ${e}`,404);if(o.status!=="pending")throw new x("Governance review is already resolved",409);let i=new Date().toISOString();if(o.reviewedAt=i,o.reviewedBy=n.principal,o.updatedAt=i,n.note?.trim()&&(o.reviewNote=n.note.trim()),n.action==="reject")return o.status="rejected",this.audit(s,"knowledge:rejected",n.principal,{reviewId:e,sourceKey:o.sourceKey}),structuredClone(o);if(n.action==="supersede")return o.status="superseded",n.targetReviewId&&(o.supersededBy=n.targetReviewId),this.audit(s,"knowledge:superseded",n.principal,{reviewId:e,sourceKey:o.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(o);if(n.action==="merge"){if(!n.targetReviewId)throw new x("targetReviewId is required for merge",400);let u=s.reviews.find(f=>f.id===n.targetReviewId);if(!u)throw new x("Merge target review not found",404);return o.status="superseded",o.mergedInto=u.id,this.audit(s,"knowledge:merged",n.principal,{reviewId:e,sourceKey:o.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(o)}o.status="approved";let c=(await r.listPages()).find(u=>u.slug===o.slug);if(c&&!c.tags.includes(o.marker))throw new x(`Wiki page '${o.slug}' is manually managed`,409);return c?await r.updatePage(o.slug,{title:o.title,summary:o.summary??"",content:o.content,tags:o.tags}):await r.createPage({slug:o.slug,title:o.title,...o.summary?{summary:o.summary}:{},content:o.content,tags:o.tags}),o.appliedAt=i,this.audit(s,"knowledge:approved",n.principal,{reviewId:e,sourceKey:o.sourceKey}),structuredClone(o)})}async quality(e){let n=await this.ensureState(),r=await e.listPages(),s=Date.now(),o=n.policy.staleAfterDays*864e5,i=r.map(f=>{let d=s-Date.parse(f.updatedAt);return{slug:f.slug,title:f.title,updatedAt:f.updatedAt,ageDays:Math.max(0,Math.floor(d/864e5)),stale:Number.isFinite(d)&&d>o}}).filter(f=>f.stale).map(({stale:f,...d})=>d),a=new Map;for(let f of r){let d=lt(f.title),p=a.get(d)??[];p.push(f),a.set(d,p)}let c=[...a.entries()].filter(([,f])=>f.length>1).map(([f,d])=>({title:f,pages:d.map(p=>p.slug)})),u=n.reviews.filter(f=>f.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(f=>f.tags.some(d=>d.startsWith("toolnet-auto-"))).length,manualPages:r.filter(f=>!f.tags.some(d=>d.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(f=>f.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(f=>f.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var Rn="wiki/automation.v1.json",Nn="toolnet.wiki-automation.v1",ft=8e3,Cn=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function ie(t){return ui("sha256").update(JSON.stringify(t)).digest("hex")}function oe(t){if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function An(t){return Array.isArray(t)?t:[]}function _n(t){return typeof t!="string"?void 0:t.replace(/\s+/gu," ").trim()||void 0}function dt(t){return Array.isArray(t)?t.map(_n).filter(e=>!!e):[]}function R(t,e){for(let n of e){let r=_n(t[n]);if(r)return r}}function ae(t){let e=new Set,n=[];for(let r of t){let s=r.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function Ee(t,e=0,n=""){if(e>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(Cn.has(r))return[];if(typeof t=="string"){let i=t.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(t))return t.flatMap(i=>Ee(i,e+1,n));let s=oe(t);if(!s)return[];let o=[];for(let[i,a]of Object.entries(s)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();Cn.has(c)||o.push(...Ee(a,e+1,i))}return o}function Mn(t){let n=ae(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(s=>Ee(t[s],0,s)));return(n.length>0?n:ae(Ee(t))).join(`
|
|
24
|
-
|
|
25
|
-
`).slice(0,ft)}function En(t,e){return R(t,["id","key","fingerprint","knowledgeId","sceneId"])??e}function Tn(t,e){return R(t,["title","name","topic","label","task","kind","type"])??e}function mi(t){return(R(t,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function gi(t){return(R(t,["kind","sceneKind","type"])??"").toLowerCase()}function yi(t){let e=oe(t);if(!e)return[];let n=[],r=An(e.knowledge);for(let[o,i]of r.entries()){let a=oe(i);if(!a)continue;let c=mi(a);if(c==="session"||c==="transient")continue;let u=Mn(a);if(u.length<20)continue;let f=En(a,ie(a).slice(0,16)),d=Tn(a,`Durable Memory ${o+1}`);n.push({sourceKey:`memory:${f}`,sourceType:"memory",title:d,summary:R(a,["summary","description"]),content:u,tags:ae(["toolnet","auto","memory",...c?[c]:[]])})}let s=An(e.scenes);for(let[o,i]of s.entries()){let a=oe(i);if(!a)continue;let c=gi(a);if(c==="session-context")continue;let u=Mn(a);if(u.length<20)continue;let f=En(a,ie(a).slice(0,16)),d=Tn(a,`Knowledge Scene ${o+1}`);n.push({sourceKey:`scene:${f}`,sourceType:"scene",title:d,summary:R(a,["summary","description"]),content:u,tags:ae(["toolnet","auto","scene",...c?[c]:[]])})}return n}function hi(t){return On(t,".toolnet","memory","skills")}function Si(t){let e=hi(t);if(!li(e))return{candidates:[],failed:0};let n=[],r=0,s=di(e).filter(o=>o.endsWith(".json")).sort();for(let o of s)try{let i=JSON.parse(pi(On(e,o),"utf8")),a=oe(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let c=R(a,["id","fingerprint"])??fi(o,".json"),u=R(a,["task"])??"",f=R(a,["title"])||u||`Reusable Skill ${c.slice(0,8)}`,d=R(a,["summary"])??void 0,p=dt(a.steps),l=dt(a.verification),m=dt(a.files),S=[];u&&S.push(`## Task
|
|
26
|
-
${u}`),d&&S.push(`## Summary
|
|
27
|
-
${d}`),p.length>0&&S.push(`## Procedure
|
|
28
|
-
${p.map((y,k)=>`${k+1}. ${y}`).join(`
|
|
29
|
-
`)}`),l.length>0&&S.push(`## Verification
|
|
30
|
-
${l.map(y=>`- ${y}`).join(`
|
|
31
|
-
`)}`),m.length>0&&S.push(`## Relevant Files
|
|
32
|
-
${m.map(y=>`- \`${y}\``).join(`
|
|
33
|
-
`)}`);let h=S.join(`
|
|
34
|
-
|
|
35
|
-
`).slice(0,ft);if(h.length<20)continue;n.push({sourceKey:`skill:${c}`,sourceType:"skill",title:f,summary:d,content:h,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function pt(t){let e=new Date().toISOString();return{schema:Nn,version:1,projectId:t,entries:[],createdAt:e,updatedAt:e}}async function ki(t,e){let n=await t.getText(Rn);if(!n)return pt(e);try{let r=JSON.parse(n);return r.schema!==Nn||r.version!==1||r.projectId!==e||!Array.isArray(r.entries)?pt(e):r}catch{return pt(e)}}async function wi(t,e){await t.put(Rn,JSON.stringify(e,null,2),"application/json")}function vi(t){return`toolnet-auto-${ie(t).slice(0,12)}`}function bi(t){let e=B(t.title).slice(0,72),n=ie(t.sourceKey).slice(0,10);return B(`auto-${t.sourceType}-${e}-${n}`)}function xi(t){return[`> Auto-generated by ToolNet Knowledge Automation from ${t.sourceType==="skill"?"reusable Skill Memory":t.sourceType==="scene"?"semantic memory scene":"durable memory"}.`,"",t.content].join(`
|
|
36
|
-
`).slice(0,ft)}function ji(t){return ie({sourceType:t.sourceType,title:t.title,summary:t.summary,content:t.content,tags:t.tags})}function Ii(t,e){return t.tags.includes(e)}async function $n(t){let e=yi(t.hierarchy),n=Si(t.project.rootPath),r=new Map;for(let l of[...e,...n.candidates])r.set(l.sourceKey,l);let s=[...r.values()].sort((l,m)=>l.sourceKey.localeCompare(m.sourceKey)),o={schema:"toolnet.wiki-automation-result.v1",scanned:e.length+n.candidates.length,eligible:s.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new Pe(new Ce(t.storage,t.project));await i.initialize();let a=new Me(new Ae(t.storage,t.project));await a.initialize();let c=await ki(t.storage,t.project.id),u=await i.listPages(),f=new Map(u.map(l=>[l.slug,l])),d=new Map(c.entries.map(l=>[l.sourceKey,l]));for(let l of s)try{let m=vi(l.sourceKey),S=ji(l),h=d.get(l.sourceKey),y=h?.slug??bi(l),k=f.get(y);if(k&&!Ii(k,m)){o.skipped+=1;continue}let P=ae([...l.tags,m]),C=xi(l),j=await a.gate({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:y,marker:m,digest:S,title:l.title,...l.summary?{summary:l.summary}:{},content:C,tags:P},[...f.values()]);if(!j.allowed){j.mode==="pending-review"?o.reviewPending+=1:o.skipped+=1;continue}j.mode==="auto-approved"?o.autoApproved+=1:j.mode==="review-approved"&&(o.reviewApproved+=1),k?h?.digest!==S?(k=await i.updatePage(y,{title:l.title,summary:l.summary??"",content:C,tags:P}),f.set(k.slug,k),o.updated+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"updated"})):(o.unchanged+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:y,action:"unchanged"})):(k=await i.createPage({slug:y,title:l.title,summary:l.summary,content:C,tags:P}),f.set(k.slug,k),o.created+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"created"}));let A=new Date().toISOString(),g={sourceKey:l.sourceKey,sourceType:l.sourceType,slug:y,digest:S,marker:m,updatedAt:A},v=c.entries.findIndex(L=>L.sourceKey===l.sourceKey);v>=0?c.entries[v]=g:c.entries.push(g),d.set(l.sourceKey,g),await a.markApplied(l.sourceKey,S)}catch(m){if(m instanceof x&&m.statusCode===409){o.skipped+=1;continue}o.failed+=1}let p=new Date().toISOString();return c.updatedAt=p,c.lastRunAt=p,c.entries.sort((l,m)=>l.sourceKey.localeCompare(m.sourceKey)),await wi(t.storage,c),o}import{createHash as Pi}from"node:crypto";import{chmodSync as Wn,existsSync as Ci,mkdirSync as Ai,readFileSync as ap,readdirSync as cp,renameSync as Mi,statSync as up,writeFileSync as Ei}from"node:fs";import{join as Ln}from"node:path";var Ti="toolnet.skill-memory.v1",Kn=5,Oi=16,Ri=24,Ni=32;function _i(t){return Pi("sha256").update(t).digest("hex")}function ue(t,e=Number.MAX_SAFE_INTEGER){let n=new Set,r=[];for(let s of t){let o=s.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=e))break}return r}function mt(t,e=360){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function $i(t){return t.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/giu,"Bearer [REDACTED]").replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu,"[REDACTED]").replace(/\b(api[_-]?key|token|password|passwd|secret)\b(\s*[:=]\s*)(["']?)[^\s"'`]+/giu,"$1$2[REDACTED]")}function _(t,e=360){return t&&mt($i(t),e)||void 0}function le(t,e){for(let n of e){let r=t[n];if(typeof r=="string"&&r.trim())return r}}function Fn(t,e){for(let n of e){let r=t[n];if(typeof r=="number"&&Number.isFinite(r))return r;if(typeof r=="string"&&r.trim()&&Number.isFinite(Number(r)))return Number(r)}}function Dn(t,e){for(let n of e){let r=t[n];if(typeof r=="boolean")return r;if(typeof r=="string"){let s=r.trim().toLowerCase();if(["true","yes","pass","passed","success","succeeded","ok"].includes(s))return!0;if(["false","no","fail","failed","error"].includes(s))return!1}}}function zn(t){let e=t.data??{};if(Dn(e,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=Fn(e,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let s=le(e,["status","result","outcome"]);return!!(s&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(s))}function ce(t){let e=t.data??{};if(zn(t))return!1;if(Dn(e,["passed","pass","success","succeeded","ok"])===!0||Fn(e,["exitCode","exit_code","code","statusCode"])===0)return!0;let s=le(e,["status","result","outcome"]);return s&&/\b(pass(?:ed)?|success(?:ful)?|succeeded|ok|green|complete(?:d)?)\b/iu.test(s)?!0:t.type==="commit"||t.type==="deploy"}function Bn(t){let e=t.data??{},n=le(e,["path","file","filePath","filename","target"]);if(n)return _(n,260);let r=t.provenance?.files;return _(r?.[0],260)}function gt(t){return _(le(t.data??{},["command","cmd","script"]),420)}function V(t){return _(le(t.data??{},["name","test","suite","title","message","text","result","status"]),300)}function Ki(t){let e=[];for(let n of[...t].sort((r,s)=>r.sequence-s.sequence))if(ce(n)){if(n.type==="test"){let r=V(n)??gt(n)??"Tests passed";e.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=V(n);e.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=V(n);e.push(r?`Deploy: ${r}`:"Deployment completed")}}return ue(e,10)}function Wi(t,e){let n=[];for(let r of[...t].sort((s,o)=>s.sequence-o.sequence))switch(r.type){case"file_write":case"file_edit":{let s=Bn(r);s&&n.push(`Update ${s}`);break}case"command":{if(zn(r))break;let s=gt(r);s&&n.push(`Run: ${s}`);break}case"test":{if(!ce(r))break;let s=V(r)??gt(r)??"project tests";n.push(`Verify: ${s}`);break}case"commit":{if(!ce(r))break;let s=V(r);n.push(s?`Commit: ${s}`:"Commit verified changes");break}case"deploy":{if(!ce(r))break;let s=V(r);n.push(s?`Deploy: ${s}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of e.files.slice(0,8)){let s=_(r,260);s&&n.push(`Update ${s}`)}return ue(n,Oi)}function Li(t,e){let n=[...e.files];for(let r of t){let s=Bn(r);s&&n.push(s);for(let o of r.provenance?.files??[]){let i=_(o,260);i&&n.push(i)}}return ue(n,Ri)}function Fi(t){return ue(t.filter(e=>["file_write","file_edit","command","test","commit","deploy"].includes(e.type)).map(e=>e.id),Ni)}function Di(t){return t.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function qn(t,e,n){if(e.length===0)return[];let r=Ki(e),s=ue(n.completed.map(m=>_(m,280)??""),Kn);if(!(s.length>0||e.some(m=>["test","commit","deploy"].includes(m.type)&&ce(m))))return[];let i=_(n.task,280)??_(n.nextActions[0],280),a=s.length>0?s:i?[i]:[];if(a.length===0)return[];let c=Wi(e,n);if(c.length===0)return[];let u=Li(e,n),f=Fi(e),d=Math.min(...e.map(m=>m.sequence)),p=Math.max(...e.map(m=>m.sequence)),l=Di(e);return a.slice(0,Kn).map(m=>{let S=[`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),h=JSON.stringify({projectId:t.projectId,task:m,steps:c,verification:r,files:u}),y=_i(h);return{schema:Ti,version:1,id:`skill-${y.slice(0,24)}`,fingerprint:y,projectId:t.projectId,title:mt(`SOP: ${m}`,180),task:m,summary:mt(S.join(" "),900),steps:c,verification:r,files:u,source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:d,lastSequence:p,eventIds:f},createdAt:l}})}function zi(t){return Ln(t.rootPath,".toolnet","memory","skills")}function Bi(t){let e=zi(t);return Ai(e,{recursive:!0,mode:448}),Wn(e,448),e}function Vn(t,e){if(e.length===0)return{written:0,deduped:0,files:[]};let n=Bi(t),r=0,s=0,o=[];for(let i of e){if(i.projectId!==t.id)throw new Error(`Skill project mismatch: ${i.projectId} != ${t.id}`);let a=Ln(n,`${i.id}.json`);if(o.push(a),Ci(a)){s+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;Ei(c,JSON.stringify(i,null,2)+`
|
|
37
|
-
`,{encoding:"utf8",mode:384}),Mi(c,a),Wn(a,384),r+=1}return{written:r,deduped:s,files:o}}function Hn(t){return String(t).padStart(12,"0")}function qi(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var Te=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(f=>f.sequence)),o=Math.max(...n.map(f=>f.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},a=JSON.stringify(i,null,2)+`
|
|
38
|
-
`,c=w(r.map(f=>f.fingerprint).sort().join("|")).slice(0,16),u=[qi(e),"batches",`${Hn(s)}-${Hn(o)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,a,"application/json"),u}};import{createHash as Vi}from"node:crypto";function Jn(t){return String(t).padStart(12,"0")}function Hi(t){return Vi("sha256").update(t).digest("hex")}function Ji(t){return t.remotePrefix.replace("/sessions/","/memory/hierarchy/")}var Oe=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(n.length===0||r.facts.length===0)return null;let s=Math.min(...n.map(u=>u.sequence)),o=Math.max(...n.map(u=>u.sequence)),i={schema:"toolnet.memory-hierarchy-batch.v1",version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,hierarchy:r},a=Hi([...r.facts.map(u=>u.id),...r.knowledge.map(u=>u.id)].sort().join("|")).slice(0,16),c=[Ji(e),"batches",`${Jn(s)}-${Jn(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,`${JSON.stringify(i,null,2)}
|
|
39
|
-
`,"application/json"),c}};function Zi(t,e){if(!Ui(t))return{events:[],nextOffset:e};let n=Qi(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=Yi(t,"r");try{Xi(i,o,0,s,r)}finally{Gi(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
40
|
-
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
41
|
-
`).filter(Boolean).flatMap(d=>{try{return[JSON.parse(d)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Re=class{constructor(e){this.options=e;this.journal=new Te(e.storage),this.hierarchyJournal=new Oe(e.storage)}options;journal;hierarchyJournal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Zi(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=cn(this.options.identity,s.events),i=o.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,s.events,i));let c=!1;o.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,s.events,o.hierarchy));let u=qn(this.options.identity,s.events,o.state),f=Vn(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",o.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",o.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",o.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",o.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",o.hierarchy.stats.knowledge),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.journal_written",c?1:0),this.options.wal.setSourceCursor("memory.skill.assets",u.length),this.options.wal.setSourceCursor("memory.skill.written",f.written),this.options.wal.setSourceCursor("memory.skill.deduped",f.deduped);try{let d=gn(this.options.project.rootPath,s.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",d.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",d.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",d.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",d.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let d=await $n({project:this.options.project,storage:this.options.storage,hierarchy:o.hierarchy});this.options.wal.setSourceCursor("memory.wiki_automation.scanned",d.scanned),this.options.wal.setSourceCursor("memory.wiki_automation.eligible",d.eligible),this.options.wal.setSourceCursor("memory.wiki_automation.created",d.created),this.options.wal.setSourceCursor("memory.wiki_automation.updated",d.updated),this.options.wal.setSourceCursor("memory.wiki_automation.unchanged",d.unchanged),this.options.wal.setSourceCursor("memory.wiki_automation.skipped",d.skipped),this.options.wal.setSourceCursor("memory.wiki_automation.failed",d.failed),this.options.wal.setSourceCursor("memory.wiki_automation.review_pending",d.reviewPending),this.options.wal.setSourceCursor("memory.wiki_automation.auto_approved",d.autoApproved),this.options.wal.setSourceCursor("memory.wiki_automation.review_approved",d.reviewApproved)}catch{this.options.wal.setSourceCursor("memory.wiki_automation.failed",1)}return this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:i.length,journalWritten:a,nextOffset:s.nextOffset}}};import{closeSync as ia,existsSync as aa,openSync as ca,readSync as ua,statSync as la}from"node:fs";var ea=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function J(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Un(t){return J(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function H(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))H(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(ea.has(r)||["data","payload","parts","messages"].includes(r))&&H(s,e,n+1)}}function Ne(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function Gn(t){let e=J(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function I(t,e,n,r,s={}){let o=J(r),i=s.key??Un(o);return{version:1,id:w([t.projectId,n,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function ta(t,e,n){let r=J(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(I(t,e,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&s.push(I(t,e,"plan",a[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,u;for(;!o&&(u=c.exec(r));){let p=Number(u[1]),l=J(u[2]??""),m=l&&!Gn(l)?`Phase ${p} - ${l}`:`Phase ${p}`;s.push(I(t,e,"phase",m,{key:`phase:${p}`,order:p,status:Ne(r),confidence:.93}))}let f=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);f?.[2]&&s.push(I(t,e,"task",f[2],{status:f[1].trim()?"completed":Ne(f[2]),confidence:.96}));let d=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(d?.[2]){let p=d[1]?Number(d[1]):void 0,l=J(d[2]),m=Gn(l);s.push(I(t,e,"task",m&&p!==void 0?`TODO ${p}`:l,{key:p!==void 0?`task:${p}`:Un(l),order:p,status:Ne(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let p=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");p&&s.push(I(t,e,"next_action",p,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(I(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(I(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(I(t,e,"decision",r,{confidence:.9})),s}function _e(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let c=[];H(i.data,c);for(let u of c)s(I(t,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];H(i.data,c);for(let u of c)s(I(t,i,"task",u,{status:Ne(u),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let u=i.data[c];typeof u=="string"&&u&&s(I(t,i,"file",u,{confidence:1}))}if(i.type==="test"){let c=[];H(i.data,c);for(let u of c)s(I(t,i,"test",u,{confidence:1}))}let a=[];H(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let f of ta(t,i,u))s(f)}let o=e[e.length-1];return s(I(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function Yn(t){return String(t).padStart(12,"0")}var $e=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.sequence)),s=Math.max(...n.map(u=>u.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
|
|
42
|
-
`,a=w(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Yn(r)}-${Yn(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Xn}from"node:path";import{mkdirSync as na}from"node:fs";function ra(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function G(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=ra(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function sa(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function Qn(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&sa(e)?t.title:e.text;return{id:t?.id??w(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function oa(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}async function Ke(t,e){let r=(await oa(t,e)).flatMap(g=>g.observations).sort((g,v)=>{let L=g.occurredAt.localeCompare(v.occurredAt);if(L!==0)return L;let Ct=g.sequence-v.sequence;return Ct!==0?Ct:g.id.localeCompare(v.id)}),s=new Map,o=new Map,i,a,c,u=[],f=[],d=[],p=[],l=[],m=[];for(let g of r)switch(g.kind){case"goal":i=g.text;break;case"plan":a=g.text;break;case"phase":s.set(g.key,Qn(s.get(g.key),g));break;case"task":o.set(g.key,Qn(o.get(g.key),g));break;case"decision":u.push(g.text);break;case"blocker":f.push(g.text);break;case"warning":d.push(g.text);break;case"next_action":p.push(g.text);break;case"file":l.push(g.text);break;case"test":m.push(g.text);break;case"session":c={agent:g.agent,nativeSessionId:g.nativeSessionId,sessionKey:g.sessionKey,updatedAt:g.occurredAt};break}let S=Array.from(s.values()).sort((g,v)=>(g.order??Number.MAX_SAFE_INTEGER)-(v.order??Number.MAX_SAFE_INTEGER)),h=Array.from(o.values()).sort((g,v)=>(g.order??Number.MAX_SAFE_INTEGER)-(v.order??Number.MAX_SAFE_INTEGER)),y=S.find(g=>g.status==="in_progress")??S.find(g=>g.status==="blocked")??S.find(g=>g.status==="pending"),k=h.find(g=>g.status==="in_progress")??h.find(g=>g.status==="blocked")??h.find(g=>g.status==="pending"),P=G([...p,...k?[k.title]:[],...!k&&y?[y.title]:[],...h.filter(g=>g.status==="pending").slice(0,5).map(g=>g.title)],8),C=G([...f,...S.filter(g=>g.status==="blocked").map(g=>g.title),...h.filter(g=>g.status==="blocked").map(g=>g.title)],20),j={version:1,projectId:t.id,projectName:t.name,goal:i,plan:a,phases:S,tasks:h,decisions:G(u,20),blockers:C,warnings:G(d,20),nextActions:P,filesTouched:G(l,30),tests:G(m,20),currentPhase:y,currentTask:k,progress:{phasesTotal:S.length,phasesCompleted:S.filter(g=>g.status==="completed").length,tasksTotal:h.length,tasksCompleted:h.filter(g=>g.status==="completed").length,blocked:S.filter(g=>g.status==="blocked").length+h.filter(g=>g.status==="blocked").length},lastSession:c,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},A=Xn(t.rootPath,".toolnet","work");return na(A,{recursive:!0}),M(Xn(A,"current.json"),j),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(j,null,2)+`
|
|
43
|
-
`,"application/json"),j}async function We(t,e){let n=await e.getText(`projects/${t.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function da(t,e){if(!aa(t))return{events:[],nextOffset:e};let n=la(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=ca(t,"r");try{ua(i,o,0,s,r)}finally{ia(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
44
|
-
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
45
|
-
`).filter(Boolean).flatMap(d=>{try{return[JSON.parse(d)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Le=class{constructor(e){this.options=e;this.journal=new $e(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=da(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=_e(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Ke(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as wa,existsSync as va,openSync as ba,readSync as xa,statSync as ja}from"node:fs";var pa=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function U(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function yt(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))yt(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(pa.has(r)||["data","payload","parts","messages"].includes(r))&&yt(s,e,n+1)}}function T(t,e,n,r,s,o=.95){let i=U(r);return{version:1,id:w([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function N(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return U(t.slice(r.length+1))}return null}function fa(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function ma(t){return U(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function Zn(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];yt(o.data,i);for(let a of i){let c={type:"project"},u=null;for(let f of a.split(/\r?\n/u)){let d=U(f);if(!d){u=null;continue}let p=d.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(p){let v=Number(p[1]);c={type:"phase",key:`phase:${v}`,order:v,title:U(p[2]??"")},u=null;continue}let l=d.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let v=Number(l[1]);c={type:"task",key:`task:${v}`,order:v,title:U(l[2]??"")},u=null;continue}let m=N(d,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(m){s(T(t,o,"mission",m,{type:"project"},.99)),u=null;continue}let S=N(d,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(S){s(T(t,o,c.type==="phase"?"phase_objective":"objective",S,c,.98)),u=null;continue}let h=N(d,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(h){s(T(t,o,c.type==="phase"?"phase_why":"why",h,c,.98)),u=null;continue}let y=N(d,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(y){s(T(t,o,"desired_outcome",y,{type:"project"},.98)),u=null;continue}let k=N(d,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(k){s(T(t,o,"plan_rationale",k,{type:"project"},.98)),u=null;continue}let P=N(d,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(P){s(T(t,o,"phase_deliverable",P,c,.97)),u=null;continue}let C=N(d,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(C){s(T(t,o,"acceptance_criterion",C,c,.98)),u="acceptance_criterion";continue}let j=N(d,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(j){s(T(t,o,"dependency",j,c,.97)),u="dependency";continue}let A=N(d,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(A){s(T(t,o,"open_question",A,c,.95)),u="open_question";continue}let g=N(d,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(g){s(T(t,o,"constraint",g,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(d)){u="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(d)){u="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(d)){u="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(d)){u="constraint";continue}if(u&&fa(f)){s(T(t,o,u,ma(f),c,.96));continue}u=null}}}return n}function er(t){return String(t).padStart(12,"0")}var Fe=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.evidence.sequence)),s=Math.max(...n.map(c=>c.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=w(n.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${er(r)}-${er(s)}-${i}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,JSON.stringify(o,null,2)+`
|
|
46
|
-
`,"application/json"),a}};import{mkdirSync as ga}from"node:fs";import{join as tr}from"node:path";function ya(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function ha(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function K(t,e){return ha(e,t)?e:t}function W(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function Sa(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}function ka(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function nr(t,e){let r=(await Sa(t,e)).flatMap(S=>S.observations).sort((S,h)=>{let y=S.evidence.occurredAt.localeCompare(h.evidence.occurredAt);return y!==0?y:S.evidence.sessionKey===h.evidence.sessionKey?S.evidence.sequence-h.evidence.sequence:S.id.localeCompare(h.id)}),s,o,i,a,c,u=new Map,f=[],d=[],p=[];for(let S of r){let h=ya(S);if(S.scope==="phase"&&S.scopeKey){let y=u.get(S.scopeKey)??ka(S);switch(S.kind){case"phase_objective":y.objective=K(y.objective,h);break;case"phase_why":y.why=K(y.why,h);break;case"phase_deliverable":y.deliverable=K(y.deliverable,h);break;case"acceptance_criterion":y.acceptanceCriteria.push(h);break;case"dependency":y.dependencies.push(h);break;case"open_question":y.openQuestions.push(h);break;case"constraint":y.constraints.push(h);break;case"note":y.notes.push(h);break}u.set(y.key,y);continue}switch(S.kind){case"mission":s=K(s,h);break;case"objective":o=K(o,h);break;case"why":i=K(i,h);break;case"desired_outcome":a=K(a,h);break;case"plan_rationale":c=K(c,h);break;case"open_question":f.push(h);break;case"constraint":d.push(h);break;case"note":p.push(h);break}}for(let S of u.values())S.acceptanceCriteria=W(S.acceptanceCriteria,20),S.dependencies=W(S.dependencies,15),S.openQuestions=W(S.openQuestions,15),S.constraints=W(S.constraints,15),S.notes=W(S.notes,20);let l={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:a,planRationale:c,phases:Array.from(u.values()).sort((S,h)=>S.order-h.order),openQuestions:W(f,20),constraints:W(d,20),notes:W(p,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},m=tr(t.rootPath,".toolnet","work");return ga(m,{recursive:!0}),M(tr(m,"semantic-current.json"),l),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
|
|
47
|
-
`,"application/json"),l}async function rr(t,e){let n=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Ia(t,e){if(!va(t))return{events:[],nextOffset:e};let n=ja(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=ba(t,"r");try{xa(o,s,0,s.length,r)}finally{wa(o)}let i=s.toString("utf8"),a=i.lastIndexOf(`
|
|
48
|
-
`);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
|
|
49
|
-
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var De=class{constructor(e){this.options=e;this.journal=new Fe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Ia(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=Zn(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await nr(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as Ka}from"node:fs";import{join as ht}from"node:path";import{existsSync as ir,mkdirSync as Pa,readFileSync as Ca,statSync as sr,writeFileSync as Aa}from"node:fs";import{dirname as Ma,join as Ea}from"node:path";var or=64*1024,Ta=`# ToolNet Project Operating Manual
|
|
11
|
+
`,u=Pe(this.eventsFile,"a",384);try{er(u,i,null,"utf8"),Xn(u)}finally{Ie(u)}let c=o[o.length-1],a="active";c.type==="session_end"||c.type==="session_idle"?a="idle":c.type==="error"&&(a="error");let f=Array.from(r).slice(-rr);return this.saveStateUnsafe({...n,status:a,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:f}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Gn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=rt(this.eventsFile).size,r=Math.min(e.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let s=n-r,o=Buffer.alloc(s),i=Pe(this.eventsFile,"r");try{Zn(i,o,0,s,r)}finally{Ie(i)}return{events:o.toString("utf8").split(`
|
|
12
|
+
`).filter(Boolean).map(a=>JSON.parse(a)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as br,existsSync as xr,openSync as kr,readSync as wr,statSync as jr}from"node:fs";function st(t,e){let n=e.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var ct=[/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],or=[/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],ir=[/\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],ar=[/\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],cr=[/đã 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],ot=[/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],ur=[/\bdùng\b/iu,/\btách\b/iu,/\bthay\b/iu,/\bchuyển\b/iu,/\blưu\b/iu,/\bmap\b/iu,/\buse\b/iu,/\bsplit\b/iu,/\bstore\b/iu,/\breplace\b/iu,/\bmove\b/iu],lr=[/đường dẫn/iu,/\bpath\b/iu,/\bport\b/iu,/\bendpoint\b/iu,/\bdomain\b/iu,/\bbucket\b/iu,/\brepository\b/iu,/\brepo\b/iu,/\bbranch\b/iu,/\/[A-Za-z0-9._/-]{4,}/u],dr=[/\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],it=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),pr=new Set(["payload","data","content","message","messages","parts","summary"]);function I(t,e){return e.some(n=>n.test(t))}function ut(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function fr(t){return ut(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function mr(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function Oe(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||it.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Oe(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(it.has(s)||pr.has(s))&&Oe(o,s,n,r+1)}}function gr(t){let e=[];Oe(t.data,void 0,e);let n=[],r=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=ut(o);if(mr(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function at(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function hr(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&I(t,ct)?{kind:"rule",confidence:.98}:r&&I(t,or)?{kind:"rule",confidence:.92}:I(t,ir)?{kind:I(t,ot)?"architecture":"decision",confidence:r?.93:.86}:r&&I(t,ar)?{kind:"todo",confidence:.87}:I(t,ot)&&I(t,ur)?{kind:"architecture",confidence:r?.88:.82}:s&&I(t,cr)?{kind:"fix",confidence:.8}:r&&I(t,lr)&&I(t,dr)?{kind:"context",confidence:.79}:null}function yr(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Sr(t,e,n){return t==="rule"&&I(n,ct)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":st(e,n)}function lt(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,u=at(o);i&&u&&s.set(i,u)}for(let o of e){let i=at(o),u=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&u&&(i=s.get(u)??"");for(let c of gr(o)){let a=hr(c,i,o);if(!a||a.confidence<.75)continue;let f=yr(a.kind),l=fr(c),p=v([t.projectId,a.kind,l].join("|"));if(r.has(p))continue;r.add(p);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],y=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:p,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:f,content:c,confidence:a.confidence,importance:Sr(a.kind,f,c),tags:[f],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:y,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function dt(t){return String(t).padStart(12,"0")}function vr(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var ne=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(f=>f.sequence)),o=Math.max(...n.map(f=>f.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},u=JSON.stringify(i,null,2)+`
|
|
13
|
+
`,c=v(r.map(f=>f.fingerprint).sort().join("|")).slice(0,16),a=[vr(e),"batches",`${dt(s)}-${dt(o)}-${c}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,u,"application/json"),a}};function Ir(t,e){if(!xr(t))return{events:[],nextOffset:e};let n=jr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=kr(t,"r");try{wr(i,o,0,s,r)}finally{br(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
|
|
14
|
+
`);if(c<0)return{events:[],nextOffset:r};let a=u.slice(0,c+1);return{events:a.split(`
|
|
15
|
+
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var re=class{constructor(e){this.options=e;this.journal=new ne(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Ir(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=lt(this.options.identity,s.events),i=!1;return o.length>0&&(i=!!await this.journal.write(this.options.identity,s.events,o)),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:o.length,journalWritten:i,nextOffset:s.nextOffset}}};import{closeSync as Ar,existsSync as Rr,openSync as Nr,readSync as _r,statSync as $r}from"node:fs";var Pr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function L(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function ft(t){return L(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function $(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))$(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Pr.has(r)||["data","payload","parts","messages"].includes(r))&&$(s,e,n+1)}}function se(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function pt(t){let e=L(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function x(t,e,n,r,s={}){let o=L(r),i=s.key??ft(o);return{version:1,id:v([t.projectId,n,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function Er(t,e,n){let r=L(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(x(t,e,"goal",i[1],{confidence:.97}));let u=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);u?.[1]&&s.push(x(t,e,"plan",u[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=c.exec(r));){let p=Number(a[1]),d=L(a[2]??""),y=d&&!pt(d)?`Phase ${p} - ${d}`:`Phase ${p}`;s.push(x(t,e,"phase",y,{key:`phase:${p}`,order:p,status:se(r),confidence:.93}))}let f=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);f?.[2]&&s.push(x(t,e,"task",f[2],{status:f[1].trim()?"completed":se(f[2]),confidence:.96}));let l=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(l?.[2]){let p=l[1]?Number(l[1]):void 0,d=L(l[2]),y=pt(d);s.push(x(t,e,"task",y&&p!==void 0?`TODO ${p}`:d,{key:p!==void 0?`task:${p}`:ft(d),order:p,status:se(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let p=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");p&&s.push(x(t,e,"next_action",p,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(x(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(x(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(x(t,e,"decision",r,{confidence:.9})),s}function mt(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let c=[];$(i.data,c);for(let a of c)s(x(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let c=[];$(i.data,c);for(let a of c)s(x(t,i,"task",a,{status:se(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let a=i.data[c];typeof a=="string"&&a&&s(x(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let c=[];$(i.data,c);for(let a of c)s(x(t,i,"test",a,{confidence:1}))}let u=[];$(i.data,u);for(let c of u)for(let a of c.split(/\n+/u))for(let f of Er(t,i,a))s(f)}let o=e[e.length-1];return s(x(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function gt(t){return String(t).padStart(12,"0")}var oe=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
|
|
16
|
+
`,u=v(n.map(a=>a.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${gt(r)}-${gt(s)}-${u}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as ht}from"node:path";import{mkdirSync as Or}from"node:fs";function Cr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Cr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Tr(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function yt(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&Tr(e)?t.title:e.text;return{id:t?.id??v(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function Mr(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,u)=>i.key.localeCompare(u.key))){let i=await e.getText(o.key);if(i)try{let u=JSON.parse(i);u.version===1&&Array.isArray(u.observations)&&s.push(u)}catch{}}return s}async function ie(t,e){let r=(await Mr(t,e)).flatMap(m=>m.observations).sort((m,k)=>{let Le=m.occurredAt.localeCompare(k.occurredAt);if(Le!==0)return Le;let Fe=m.sequence-k.sequence;return Fe!==0?Fe:m.id.localeCompare(k.id)}),s=new Map,o=new Map,i,u,c,a=[],f=[],l=[],p=[],d=[],y=[];for(let m of r)switch(m.kind){case"goal":i=m.text;break;case"plan":u=m.text;break;case"phase":s.set(m.key,yt(s.get(m.key),m));break;case"task":o.set(m.key,yt(o.get(m.key),m));break;case"decision":a.push(m.text);break;case"blocker":f.push(m.text);break;case"warning":l.push(m.text);break;case"next_action":p.push(m.text);break;case"file":d.push(m.text);break;case"test":y.push(m.text);break;case"session":c={agent:m.agent,nativeSessionId:m.nativeSessionId,sessionKey:m.sessionKey,updatedAt:m.occurredAt};break}let h=Array.from(s.values()).sort((m,k)=>(m.order??Number.MAX_SAFE_INTEGER)-(k.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((m,k)=>(m.order??Number.MAX_SAFE_INTEGER)-(k.order??Number.MAX_SAFE_INTEGER)),S=h.find(m=>m.status==="in_progress")??h.find(m=>m.status==="blocked")??h.find(m=>m.status==="pending"),w=g.find(m=>m.status==="in_progress")??g.find(m=>m.status==="blocked")??g.find(m=>m.status==="pending"),M=F([...p,...w?[w.title]:[],...!w&&S?[S.title]:[],...g.filter(m=>m.status==="pending").slice(0,5).map(m=>m.title)],8),N=F([...f,...h.filter(m=>m.status==="blocked").map(m=>m.title),...g.filter(m=>m.status==="blocked").map(m=>m.title)],20),O={version:1,projectId:t.id,projectName:t.name,goal:i,plan:u,phases:h,tasks:g,decisions:F(a,20),blockers:N,warnings:F(l,20),nextActions:M,filesTouched:F(d,30),tests:F(y,20),currentPhase:S,currentTask:w,progress:{phasesTotal:h.length,phasesCompleted:h.filter(m=>m.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(m=>m.status==="completed").length,blocked:h.filter(m=>m.status==="blocked").length+g.filter(m=>m.status==="blocked").length},lastSession:c,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},A=ht(t.rootPath,".toolnet","work");return Or(A,{recursive:!0}),j(ht(A,"current.json"),O),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(O,null,2)+`
|
|
17
|
+
`,"application/json"),O}async function ae(t,e){let n=await e.getText(`projects/${t.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Lr(t,e){if(!Rr(t))return{events:[],nextOffset:e};let n=$r(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=Nr(t,"r");try{_r(i,o,0,s,r)}finally{Ar(i)}let u=o.toString("utf8"),c=u.lastIndexOf(`
|
|
18
|
+
`);if(c<0)return{events:[],nextOffset:r};let a=u.slice(0,c+1);return{events:a.split(`
|
|
19
|
+
`).filter(Boolean).flatMap(l=>{try{return[JSON.parse(l)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var ce=class{constructor(e){this.options=e;this.journal=new oe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Lr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=mt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ie(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as Vr,existsSync as Ur,openSync as Hr,readSync as Yr,statSync as Gr}from"node:fs";var Fr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function K(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ce(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))Ce(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Fr.has(r)||["data","payload","parts","messages"].includes(r))&&Ce(s,e,n+1)}}function P(t,e,n,r,s,o=.95){let i=K(r);return{version:1,id:v([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function E(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return K(t.slice(r.length+1))}return null}function Kr(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Wr(t){return K(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function St(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Ce(o.data,i);for(let u of i){let c={type:"project"},a=null;for(let f of u.split(/\r?\n/u)){let l=K(f);if(!l){a=null;continue}let p=l.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(p){let k=Number(p[1]);c={type:"phase",key:`phase:${k}`,order:k,title:K(p[2]??"")},a=null;continue}let d=l.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let k=Number(d[1]);c={type:"task",key:`task:${k}`,order:k,title:K(d[2]??"")},a=null;continue}let y=E(l,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(y){s(P(t,o,"mission",y,{type:"project"},.99)),a=null;continue}let h=E(l,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(P(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),a=null;continue}let g=E(l,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(P(t,o,c.type==="phase"?"phase_why":"why",g,c,.98)),a=null;continue}let S=E(l,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(S){s(P(t,o,"desired_outcome",S,{type:"project"},.98)),a=null;continue}let w=E(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(w){s(P(t,o,"plan_rationale",w,{type:"project"},.98)),a=null;continue}let M=E(l,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(M){s(P(t,o,"phase_deliverable",M,c,.97)),a=null;continue}let N=E(l,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(N){s(P(t,o,"acceptance_criterion",N,c,.98)),a="acceptance_criterion";continue}let O=E(l,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(O){s(P(t,o,"dependency",O,c,.97)),a="dependency";continue}let A=E(l,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(A){s(P(t,o,"open_question",A,c,.95)),a="open_question";continue}let m=E(l,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(m){s(P(t,o,"constraint",m,c,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(l)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(l)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(l)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(l)){a="constraint";continue}if(a&&Kr(f)){s(P(t,o,a,Wr(f),c,.96));continue}a=null}}}return n}function vt(t){return String(t).padStart(12,"0")}var ue=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.evidence.sequence)),s=Math.max(...n.map(c=>c.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=v(n.map(c=>c.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${vt(r)}-${vt(s)}-${i}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,JSON.stringify(o,null,2)+`
|
|
20
|
+
`,"application/json"),u}};import{mkdirSync as Dr}from"node:fs";import{join as bt}from"node:path";function Br(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function zr(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function C(t,e){return zr(e,t)?e:t}function T(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function Jr(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,u)=>i.key.localeCompare(u.key))){let i=await e.getText(o.key);if(i)try{let u=JSON.parse(i);u.version===1&&Array.isArray(u.observations)&&s.push(u)}catch{}}return s}function qr(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function xt(t,e){let r=(await Jr(t,e)).flatMap(h=>h.observations).sort((h,g)=>{let S=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return S!==0?S:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),s,o,i,u,c,a=new Map,f=[],l=[],p=[];for(let h of r){let g=Br(h);if(h.scope==="phase"&&h.scopeKey){let S=a.get(h.scopeKey)??qr(h);switch(h.kind){case"phase_objective":S.objective=C(S.objective,g);break;case"phase_why":S.why=C(S.why,g);break;case"phase_deliverable":S.deliverable=C(S.deliverable,g);break;case"acceptance_criterion":S.acceptanceCriteria.push(g);break;case"dependency":S.dependencies.push(g);break;case"open_question":S.openQuestions.push(g);break;case"constraint":S.constraints.push(g);break;case"note":S.notes.push(g);break}a.set(S.key,S);continue}switch(h.kind){case"mission":s=C(s,g);break;case"objective":o=C(o,g);break;case"why":i=C(i,g);break;case"desired_outcome":u=C(u,g);break;case"plan_rationale":c=C(c,g);break;case"open_question":f.push(g);break;case"constraint":l.push(g);break;case"note":p.push(g);break}}for(let h of a.values())h.acceptanceCriteria=T(h.acceptanceCriteria,20),h.dependencies=T(h.dependencies,15),h.openQuestions=T(h.openQuestions,15),h.constraints=T(h.constraints,15),h.notes=T(h.notes,20);let d={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:u,planRationale:c,phases:Array.from(a.values()).sort((h,g)=>h.order-g.order),openQuestions:T(f,20),constraints:T(l,20),notes:T(p,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},y=bt(t.rootPath,".toolnet","work");return Dr(y,{recursive:!0}),j(bt(y,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
|
|
21
|
+
`,"application/json"),d}async function kt(t,e){let n=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Xr(t,e){if(!Ur(t))return{events:[],nextOffset:e};let n=Gr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=Hr(t,"r");try{Yr(o,s,0,s.length,r)}finally{Vr(o)}let i=s.toString("utf8"),u=i.lastIndexOf(`
|
|
22
|
+
`);if(u<0)return{events:[],nextOffset:r};let c=i.slice(0,u+1);return{events:c.split(`
|
|
23
|
+
`).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var le=class{constructor(e){this.options=e;this.journal=new ue(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Xr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=St(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await xt(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as as}from"node:fs";import{join as Te}from"node:path";import{existsSync as It,mkdirSync as Qr,readFileSync as Zr,statSync as wt,writeFileSync as es}from"node:fs";import{dirname as ts,join as ns}from"node:path";var jt=64*1024,rs=`# ToolNet Project Operating Manual
|
|
50
24
|
|
|
51
25
|
This file contains persistent instructions for AI agents working on this project.
|
|
52
26
|
|
|
@@ -89,51 +63,41 @@ Things an AI agent should always remember.
|
|
|
89
63
|
<!--
|
|
90
64
|
- [advisory] Prefer small focused files.
|
|
91
65
|
-->
|
|
92
|
-
`;function
|
|
93
|
-
|
|
94
|
-
`,"application/json")
|
|
95
|
-
|
|
96
|
-
`)
|
|
97
|
-
`)
|
|
98
|
-
`)){if(!
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
`)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
`)
|
|
109
|
-
`),a=i.findIndex(p=>/^\s*\[/.test(p));a<0&&(a=i.length);let c=-1,u=-1;for(let p=0;p<a;p+=1)if(/^\s*notify\s*=/.test(i[p])){if(c=p,u=p,i[p].includes("[")&&!i[p].includes("]"))for(;u+1<a&&(u+=1,!i[u].includes("]")););break}let f=[];if(c>=0){let p=i.slice(c,u+1).join(`
|
|
110
|
-
`);f=Nc(p),i.splice(c,u-c+1,o)}else a=i.findIndex(p=>/^\s*\[/.test(p)),a<0&&(a=i.length),i.splice(a,0,o);let d=f.length>=2&&f[f.length-1]==="session:codex-notify";return f.length>0&&!d&&Or(n,JSON.stringify(f,null,2)+`
|
|
66
|
+
`;function de(t){return ns(t.rootPath,".toolnet","PROJECT.md")}function ss(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function os(t){let e=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=r.exec(t);){let o=s[1].toLowerCase(),i=ss(s[2]);if(!i)continue;let u=`${o}:${i.toLowerCase()}`;n.has(u)||(n.add(u),e.push({id:v(u).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function is(t){let e=de(t);return It(e)||(Qr(ts(e),{recursive:!0}),es(e,rs,{encoding:"utf8",mode:384})),e}function pe(t,e=!1){let n=e?is(t):de(t);if(!It(n))return null;if(wt(n).size>jt)throw new Error(`PROJECT.md exceeds ${jt} bytes`);let s=Zr(n,"utf8");return{path:n,content:s,digest:v(s),rules:os(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(wt(n).mtimeMs).toISOString()}}function cs(t){return{goal:t.goal,plan:t.plan,phases:t.phases.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),tasks:t.tasks.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),decisions:t.decisions,blockers:t.blockers,warnings:t.warnings,nextActions:t.nextActions,filesTouched:t.filesTouched,tests:t.tests}}function us(t){return t.phases.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.tasks.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.nextActions.length>0||t.blockers.length>0}var fe=class{constructor(e){this.options=e}options;async capture(e,n){let r=await ae(this.options.project,this.options.storage);if(r||(r=await ie(this.options.project,this.options.storage)),!us(r))return null;let s=pe(this.options.project,!1),o=s?s.rules.filter(p=>p.mode==="enforce").map(p=>p.text):[],i=v(JSON.stringify(cs(r))),u=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),c=new Date().toISOString(),a={version:1,id:u,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:c,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(p=>p.status!=="completed"&&p.status!=="cancelled"),incompleteTasks:r.tasks.filter(p=>p.status!=="completed"&&p.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:[...o,...r.warnings].slice(0,20),filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:i},f=`projects/${this.options.project.id}/work/handoffs/${u}.json`;await this.options.storage.exists(f)||await this.options.storage.put(f,JSON.stringify(a,null,2)+`
|
|
67
|
+
`,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(a,null,2)+`
|
|
68
|
+
`,"application/json");let l=Te(this.options.project.rootPath,".toolnet","work","handoffs");return as(l,{recursive:!0}),j(Te(l,`${u}.json`),a),j(Te(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};async function Pt(t,e){let n=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}var me=class{identity;wal;remote;sanitizer=new z;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=et(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new te(this.identity),this.remote=new ee(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new re({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ce({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new le({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new fe({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as ls,readFileSync as ds,readdirSync as ps,statSync as Et}from"node:fs";import{homedir as fs}from"node:os";import{join as ge,resolve as Ot}from"node:path";function Ct(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function ms(){return process.env.CODEX_HOME??ge(fs(),".codex")}function V(t){let e="";try{e=ds(t,"utf8").slice(0,128*1024)}catch{return{raw:{}}}for(let n of e.split(`
|
|
69
|
+
`))if(n)try{let r=Ct(JSON.parse(n));if(r.type!=="session_meta")continue;let s=Ct(r.payload),o=[s.id,s.thread_id,s.threadId,s.session_id,s.sessionId].find(u=>typeof u=="string"),i=typeof s.cwd=="string"?s.cwd:void 0;return{threadId:o,cwd:i,raw:s}}catch{}return{raw:{}}}function Me(t,e){if(!ls(t))return;let n;try{n=ps(t,{withFileTypes:!0})}catch{return}for(let r of n){let s=ge(t,r.name);if(r.isDirectory()){Me(s,e);continue}r.isFile()&&r.name.endsWith(".jsonl")&&e.push(s)}}function Ae(){let t=ms(),e=[];return Me(ge(t,"sessions"),e),Me(ge(t,"archived_sessions"),e),e.sort((n,r)=>{try{return Et(r).mtimeMs-Et(n).mtimeMs}catch{return 0}})}function Re(t){let e=Ae(),n=e.find(r=>r.includes(t));if(n)return n;for(let r of e)if(V(r).threadId===t)return r;return null}function he(t,e){let n=Ot(t),r=Ot(e);return r===n||r.startsWith(n+"/")||n.startsWith(r+"/")}import{closeSync as gs,existsSync as hs,openSync as ys,readSync as Ss,statSync as vs}from"node:fs";function Tt(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function bs(t){let e=t.timestamp;if(typeof e=="string"){let n=new Date(e);if(!Number.isNaN(n.getTime()))return n.toISOString()}return new Date().toISOString()}function xs(t){let e=typeof t.type=="string"?t.type.toLowerCase():"",n=Tt(t.payload),r=typeof n.type=="string"?n.type.toLowerCase():"",s=typeof n.role=="string"?n.role.toLowerCase():void 0;return e==="session_meta"?{type:"custom"}:s==="user"||r==="user_message"?{type:"user_prompt",role:"user"}:s==="assistant"||r==="agent_message"||r==="assistant_message"?{type:"assistant_message",role:"assistant"}:r.includes("function_call")||r.includes("tool_call")||r.includes("exec_command_begin")||r.includes("exec_command_start")?{type:"tool_call"}:r.includes("function_call_output")||r.includes("tool_result")||r.includes("exec_command_end")||r.includes("exec_command_complete")?{type:"tool_result"}:r.includes("error")?{type:"error"}:e.includes("compacted")||r.includes("compacted")?{type:"session_compact"}:{type:"custom",role:s}}function Mt(t,e=0){if(!hs(t))return{events:[],nextOffset:e,reset:!1};let n=vs(t).size,r=e>n,s=r?0:e;if(s>=n)return{events:[],nextOffset:n,reset:r};let o=n-s,i=Buffer.alloc(o),u=ys(t,"r");try{Ss(u,i,0,o,s)}finally{gs(u)}let c=i.toString("utf8"),a=c.lastIndexOf(`
|
|
70
|
+
`);if(a<0)return{events:[],nextOffset:s,reset:r};let f=c.slice(0,a+1),l=0,p=[];for(let d of f.split(`
|
|
71
|
+
`)){if(!d)continue;let y=Buffer.byteLength(d+`
|
|
72
|
+
`,"utf8"),h=s+l;l+=y;let g;try{g=JSON.parse(d)}catch{continue}let S=Tt(g),w=xs(S);p.push({type:w.type,timestamp:bs(S),role:w.role,sourceEventId:`rollout:${h}`,sourceSequence:h,data:S,provenance:{source:"codex-rollout",sourcePath:t,sourceOffset:h}})}return{events:p,nextOffset:s+Buffer.byteLength(f,"utf8"),reset:r}}var ks=[/^<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*$/],ws=[/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],js=["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 Is(t){let e=t.toLowerCase();return js.some(n=>e.includes(n))}function Ps(t){if(!t.trim())return!0;for(let e of ks)if(e.test(t))return!0;return Is(t),!1}function Es(t){let e=t;for(let n of ws)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Ne(t){let e=t.trim();return e?Ps(e)?{content:"",filtered:!0,reason:"noise"}:{content:Es(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function ye(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=Ne(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=ye(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=Ne(s);return o.filtered?null:o.content}return s&&typeof s=="object"?ye(s):s}).filter(s=>s!==null):e[n]=r;return e}function At(t){let e=typeof t.type=="string"?t.type.toLowerCase():"";if(e.includes("system")||e.includes("ephemeral")||e==="tool_call"&&!t.result)return!0;if(t.data&&typeof t.data=="object"){let n=t.data,r=typeof n.content=="string"?n.content:"";if(r&&Ne(r).filtered)return!0}return!1}function Se(t){return t?Math.ceil(t.length/3.5):0}function ve(t,e){if(!t)return"";if(Se(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
|
|
73
|
+
`),u=Math.max(o,i);return u>r*.7?s.slice(0,u+1):s}function R(){let t=H(),e=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||e==="archive"||e==="full",r=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",s=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),o=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),u=n,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:u,archiveRemote:c}}function Rt(t){return(t||R()).rawTranscript}function Nt(t){return(t||R()).durableMemoryMaxItemsPerSession}function _t(t){return(t||R()).sessionSummaryMaxTokens}function $t(t){return(t||R()).archiveRemote}function Os(t){return t.replace(/\b[A-Za-z0-9_-]{20,}\b/g,"[REDACTED]").replace(/api[_-]?key[:\s=]+[^\s]+/gi,"api_key=[REDACTED]").replace(/token[:\s=]+[^\s]+/gi,"token=[REDACTED]").replace(/secret[:\s=]+[^\s]+/gi,"secret=[REDACTED]").replace(/password[:\s=]+[^\s]+/gi,"password=[REDACTED]")}function Cs(t,e){let n=t.toLowerCase(),r=.5,s=["nh\u1EDB","remember","quy t\u1EAFc","rule","t\u1EEB gi\u1EDD","from now","kh\xF4ng \u0111\u01B0\u1EE3c","must not","lu\xF4n lu\xF4n","always","never","critical","important","blocker","deploy","production","architecture"];for(let i of s)n.includes(i)&&(r+=.15);e==="rule"||e==="architecture"||e==="blocker"?r+=.2:e==="decision"||e==="deploy"?r+=.15:(e==="fix"||e==="next_action")&&(r+=.1),t.length<20?r-=.3:t.length>500&&(r-=.1);let o=[/npm (notice|warn|ERR)/i,/\d+ packages? in \d+/i,/found \d+ vulnerabilities/i,/up to date/i,/added \d+ packages/i,/^(ok|done|success|error|warning)$/i];for(let i of o)i.test(t)&&(r-=.4);return Math.max(0,Math.min(1,r))}function Ts(t,e){let n=[],r=new Set;for(let i of t){let u=i.split(`
|
|
74
|
+
`).filter(c=>c.trim());for(let c of u){let a=c.trim();if(a.length<15)continue;let f=a.toLowerCase().replace(/\s+/g," ");if(r.has(f))continue;r.add(f);let l="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(a)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(a)?l="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(a)?l="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(a)?l="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(a)?l="next_action":/\b(deploy|release|publish|ship)\b/i.test(a)?l="deploy":/\b(architecture|design|structure|pattern)\b/i.test(a)?l="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(a)&&(l="file");let p=Cs(a,l);if(p<.3)continue;let d=Os(a);n.push({category:l,text:d,importance:p,sourceSessionId:e})}}let s=R(),o=Nt(s);return n.sort((i,u)=>u.importance-i.importance).slice(0,o)}function Ms(t){let e=R(),n=_t(e),o=t.join(`
|
|
75
|
+
|
|
76
|
+
`).split(`
|
|
77
|
+
`).filter(i=>{let u=i.trim();return u.length>20&&!u.startsWith("npm")&&!u.startsWith("\u2713")&&!u.startsWith("Error:")}).slice(0,20).join(`
|
|
78
|
+
`);return ve(o,n)}function Lt(t,e){let r=(Array.isArray(t)?t:t.split(`
|
|
79
|
+
|
|
80
|
+
`).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=Ts(r,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),u=s.filter(d=>d.category==="file").map(d=>d.text),c=s.filter(d=>d.category==="fix").map(d=>d.text),a=s.filter(d=>d.category==="blocker").map(d=>d.text),f=s.filter(d=>d.category==="next_action").map(d=>d.text),l=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:Ms(r),decisions:o,projectRules:i,filesChanged:u,bugsFixed:c,commands:l,blockers:a,nextActions:f,durableFacts:s}}async function U(t){let e=t.threadId.trim();if(!e)throw new Error("Codex thread ID is required");let n=V(t.rolloutPath),r=t.cwd??n.cwd;if(r&&!he(t.project.rootPath,r))throw new Error(`Codex thread does not belong to project: ${r}`);if(n.threadId&&n.threadId!==e)throw new Error(`Codex rollout thread mismatch: expected ${e}, got ${n.threadId}`);let s=new me({project:t.project,storage:t.storage,agent:"codex",nativeSessionId:e,metadata:{source:"codex-rollout",rolloutPath:t.rolloutPath,cwd:r,client:t.client}}),o=s.status(),i=o.sourceCursors["codex.rollout.path"],u=Number(o.sourceCursors["codex.rollout.offset"]??0);i&&i!==t.rolloutPath&&(u=0),(!Number.isFinite(u)||u<0)&&(u=0);let c=Mt(t.rolloutPath,u),a=[];o.lastSequence===0&&a.push({type:"session_start",sourceEventId:`codex:${e}:start`,data:{threadId:e,cwd:r,rolloutPath:t.rolloutPath,sessionMeta:n.raw},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}}),i&&i!==t.rolloutPath&&a.push({type:"custom",sourceEventId:`codex:${e}:rollout-rotation:${t.rolloutPath}`,data:{event:"rollout_rotation",previousPath:i,rolloutPath:t.rolloutPath},provenance:{source:"codex-rollout"}}),c.reset&&a.push({type:"custom",sourceEventId:`codex:${e}:rollout-reset:${c.nextOffset}`,data:{event:"rollout_reset"},provenance:{source:"codex-rollout",sourcePath:t.rolloutPath}});let f=c.events.filter(d=>!At(d.data)).map(d=>({...d,data:ye(d.data)}));a.push(...f),t.idle&&t.turnId&&a.push({type:"session_idle",sourceEventId:`codex:${e}:turn:${t.turnId}:idle`,data:{turnId:t.turnId,client:t.client},provenance:{source:"codex-notify"}});let l=s.recordMany(a);if(s.setSourceCursor("codex.rollout.path",t.rolloutPath),s.setSourceCursor("codex.rollout.offset",c.nextOffset),t.turnId&&s.setSourceCursor("codex.last.turn",t.turnId),t.idle&&f.length>0)try{let d=f.map(h=>JSON.stringify(h.data)),y=Lt(d,e);s.setSourceCursor("codex.session.summary",y.summary),s.setSourceCursor("codex.session.facts_count",y.durableFacts.length),Rt()&&!$t()&&s.setSourceCursor("codex.raw_transcript.archived","local")}catch{}let p=await s.flush();return{threadId:e,imported:l.length,rolloutEvents:c.events.length,eventCount:p.eventCount,chunkCount:p.chunkCount,status:p.status,rolloutOffset:c.nextOffset,reset:c.reset}}import{existsSync as As}from"node:fs";import{dirname as Rs,join as Ns,parse as _s,resolve as $s}from"node:path";function Ft(t){let e=$s(t),n=_s(e).root;for(;;){if(As(Ns(e,".toolnet","project.json")))return new _().detect(e);if(e===n)break;let r=Rs(e);if(r===e)break;e=r}return null}async function Kt(t,e,n=100){let r=[];for(let s of Ae()){let o=V(s);if(!(!o.threadId||!o.cwd)&&he(t.rootPath,o.cwd)&&(r.push(await U({project:t,storage:e,threadId:o.threadId,rolloutPath:s,cwd:o.cwd})),r.length>=n))break}return r}import{existsSync as Ls,mkdirSync as Wt,readFileSync as Fs,writeFileSync as Dt}from"node:fs";import{homedir as Bt}from"node:os";import{dirname as zt,join as _e}from"node:path";function Ks(t){let e=[],n=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,r;for(;r=n.exec(t);){let s=r[1]??r[2]??"";try{e.push(r[1]!==void 0?JSON.parse(`"${s}"`):s)}catch{e.push(s)}}return e}function Jt(t={}){let e=t.configFile??_e(process.env.CODEX_HOME??_e(Bt(),".codex"),"config.toml"),n=t.previousFile??_e(Bt(),".config","toolnet-memory","codex-notify-previous.json");Wt(zt(e),{recursive:!0}),Wt(zt(n),{recursive:!0});let r=Ls(e)?Fs(e,"utf8"):"",s=t.binary??"toolnet-memory",o=`notify = [${JSON.stringify(s)}, "session:codex-notify"]`,i=r.split(`
|
|
81
|
+
`),u=i.findIndex(p=>/^\s*\[/.test(p));u<0&&(u=i.length);let c=-1,a=-1;for(let p=0;p<u;p+=1)if(/^\s*notify\s*=/.test(i[p])){if(c=p,a=p,i[p].includes("[")&&!i[p].includes("]"))for(;a+1<u&&(a+=1,!i[a].includes("]")););break}let f=[];if(c>=0){let p=i.slice(c,a+1).join(`
|
|
82
|
+
`);f=Ks(p),i.splice(c,a-c+1,o)}else u=i.findIndex(p=>/^\s*\[/.test(p)),u<0&&(u=i.length),i.splice(u,0,o);let l=f.length>=2&&f[f.length-1]==="session:codex-notify";return f.length>0&&!l&&Dt(n,JSON.stringify(f,null,2)+`
|
|
111
83
|
`,{encoding:"utf8",mode:384}),r=i.join(`
|
|
112
84
|
`),r.endsWith(`
|
|
113
85
|
`)||(r+=`
|
|
114
|
-
`),
|
|
115
|
-
`,{encoding:"utf8",mode:384}),e}import{existsSync as
|
|
116
|
-
`);if(
|
|
117
|
-
`)),i=Math.max(0,e-o);if(i>=16){let
|
|
118
|
-
`).trim()}async function
|
|
86
|
+
`),Dt(e,r,{encoding:"utf8",mode:384}),{configFile:e,previousFile:n,preservedPrevious:f.length>0&&!l}}import{existsSync as Ws,mkdirSync as Ds,readFileSync as Bs,writeFileSync as zs}from"node:fs";import{homedir as Js}from"node:os";import{dirname as qs,join as qt}from"node:path";function Vs(t){return`'${t.replace(/'/g,"'\\''")}'`}function Vt(t={}){let e=t.hooksFile??qt(process.env.CODEX_HOME??qt(Js(),".codex"),"hooks.json");Ds(qs(e),{recursive:!0});let n={};if(Ws(e))try{n=JSON.parse(Bs(e,"utf8"))}catch(u){throw new Error(`Invalid existing Codex hooks.json: ${u instanceof Error?u.message:String(u)}`)}let r=n.hooks&&typeof n.hooks=="object"&&!Array.isArray(n.hooks)?n.hooks:{};n.hooks=r;let o=(Array.isArray(r.SessionStart)?r.SessionStart:[]).filter(u=>{try{return!JSON.stringify(u).includes("session:codex-context")}catch{return!0}}),i=t.binary??"toolnet-memory";return o.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${Vs(i)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),r.SessionStart=o,zs(e,JSON.stringify(n,null,2)+`
|
|
87
|
+
`,{encoding:"utf8",mode:384}),e}import{existsSync as cu,mkdirSync as Gs,readFileSync as uu,writeFileSync as Xs}from"node:fs";import{dirname as Qs,join as Ht}from"node:path";function $e(t){if(!t)return 0;let e=Array.from(t).length,n=t.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,n*1.3))}function b(t,e){let n=t.replace(/\s+/g," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function Us(t){let e=[],n=!1;for(let r of t.split(/\r?\n/u)){let s=r.trim();if(s.includes("<!--")&&(n=!0),n){s.includes("-->")&&(n=!1);continue}let o=s.toLowerCase();if(!(!s||s.startsWith("#")||s==="```"||o.startsWith("- [enforce]")||o.startsWith("* [enforce]")||o.startsWith("- [advisory]")||o.startsWith("* [advisory]"))&&(s=s.replace(/^[-*]\s+/u,""),s&&e.push(b(s,280)),e.length>=16))break}return e}function Hs(t){let e=[],n=[];for(let r of t.split(/\\r?\\n/u)){let s=r.trim(),o=s.toLowerCase(),u=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(a=>o.startsWith(a));if(!u)continue;let c=s.slice(u.length).trim();c&&(u.includes("enforce")?e.push(c):n.push(c))}return{enforce:e,advisory:n}}function Ys(t,e){let n=[];for(let r of t){let s=[...n,r].join(`
|
|
88
|
+
`);if($e(s)<=e){n.push(r);continue}let o=$e(n.join(`
|
|
89
|
+
`)),i=Math.max(0,e-o);if(i>=16){let u=Math.floor(i*3.2),c=b(r,u);c&&n.push(c)}break}return n.join(`
|
|
90
|
+
`).trim()}async function Ut(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=pe(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=Hs(r),o=n?n.rules.filter(d=>d.mode==="enforce").map(d=>d.text):s.enforce,i=n?n.rules.filter(d=>d.mode==="advisory").map(d=>d.text):s.advisory,u=r?Us(r):[],c=await ae(t.project,t.storage),a=await kt(t.project,t.storage),f=await Pt(t.project,t.storage),l=[];if(l.push("[TOOLNET PROJECT CONTEXT]"),l.push(`Project: ${t.project.name}`),l.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),r&&l.push(`Full operating manual: ${de(t.project)}`),o.length){l.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of o.slice(0,24))l.push(`- [ENFORCE] ${b(d,240)}`)}if(i.length){l.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))l.push(`- ${b(d,220)}`)}if(a&&(a.mission&&l.push("","MISSION",b(a.mission.value,420)),a.activeObjective&&l.push("","CURRENT OBJECTIVE",b(a.activeObjective.value,420)),a.why&&l.push("","WHY THIS WORK MATTERS",b(a.why.value,420)),a.desiredOutcome&&l.push("","DESIRED OUTCOME",b(a.desiredOutcome.value,420)),a.planRationale&&l.push("","WHY THIS APPROACH",b(a.planRationale.value,420))),c){if(l.push("","ACTIVE WORK"),c.goal&&l.push(`Goal: ${b(c.goal,320)}`),c.plan&&l.push(`Plan: ${b(c.plan,320)}`),l.push(`Progress: phases ${c.progress.phasesCompleted}/${c.progress.phasesTotal}; tasks ${c.progress.tasksCompleted}/${c.progress.tasksTotal}; blocked ${c.progress.blocked}`),c.currentPhase&&l.push(`Current phase: ${c.currentPhase.title} [${c.currentPhase.status}]`),c.currentPhase&&a){let d=a.phases.find(y=>y.order===c.currentPhase?.order);d&&(d.objective&&l.push(`Phase objective: ${b(d.objective.value,340)}`),d.why?l.push(`Why this phase: ${b(d.why.value,340)}`):l.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&l.push(`Deliverable: ${b(d.deliverable.value,340)}`),d.dependencies.length&&l.push(`Depends on: ${d.dependencies.slice(0,4).map(y=>b(y.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(l.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(y=>{l.push(`- ${b(y.value,260)}`)})),d.openQuestions.length&&(l.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(y=>{l.push(`- ${b(y.value,260)}`)})))}c.currentTask&&l.push(`Current task: ${c.currentTask.title} [${c.currentTask.status}]`),c.nextActions.length&&(l.push("","NEXT ACTIONS"),c.nextActions.slice(0,6).forEach((d,y)=>{l.push(`${y+1}. ${b(d,260)}`)})),c.blockers.length&&(l.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(d=>{l.push(`- ${b(d,260)}`)})),c.warnings.length&&(l.push("","ATTENTION"),c.warnings.slice(-5).forEach(d=>{l.push(`- ${b(d,260)}`)})),c.decisions.length&&(l.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(d=>{l.push(`- ${b(d,260)}`)})),c.lastSession&&l.push("",`Last work session: ${c.lastSession.agent} / ${c.lastSession.nativeSessionId}`)}if(a&&a.openQuestions.length&&(l.push("","UNRESOLVED QUESTIONS"),a.openQuestions.slice(0,5).forEach(d=>{l.push(`- ${b(d.value,260)}`)})),f&&l.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),u.length){l.push("","OPERATING NOTES");for(let d of u)l.push(`- ${d}`)}l.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let p=Ys(l,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:p,estimatedTokens:$e(p),maxTokens:e,hasManual:!!r,hasWorkState:!!c,hasHandoff:!!f,generatedAt:new Date().toISOString()}}function Zs(t){return Ht(t.rootPath,".toolnet","context","startup.md")}function eo(t){return Ht(t.rootPath,".toolnet","context","startup.json")}function to(t,e){let n=Zs(t);Gs(Qs(n),{recursive:!0}),Xs(n,e.text.endsWith(`
|
|
119
91
|
`)?e.text:e.text+`
|
|
120
|
-
`,{encoding:"utf8",mode:384}),
|
|
92
|
+
`,{encoding:"utf8",mode:384}),j(eo(t),e)}async function Yt(t,e,n=800){let s=(await Ut({project:t,storage:e,maxTokens:n})).text;Se(s)>n&&(s=ve(s,n),s+=`
|
|
121
93
|
|
|
122
94
|
[Context trimmed by ToolNet Memory token budget]
|
|
123
|
-
`);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:
|
|
95
|
+
`);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:v(s),estimatedTokens:Se(s),generatedAt:new Date().toISOString()};return to(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
|
|
124
96
|
`,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
|
|
125
|
-
`,"application/json"),i}
|
|
126
|
-
`)?e:`${e}
|
|
127
|
-
`,{encoding:"utf8",mode:384}),Qc(n,t)}function tu(t,e){Hr(t,`${JSON.stringify(e,null,2)}
|
|
128
|
-
`)}function Jr(t,e){let n=e.replace(/\r\n/g,`
|
|
129
|
-
`).trim();if(!n)return null;let r={version:1,projectId:t.id,projectName:t.name,text:n,digest:w(n),generatedAt:new Date().toISOString()};return Hr(qr(t),n),tu(Vr(t),r),r}function Gr(t){let e=qr(t);if(!Dr(e))return null;try{let n=zr(e,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=Vr(t);if(Dr(s))try{let o=JSON.parse(zr(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:t.id,projectName:t.name,text:n,digest:w(n),generatedAt:r}}catch{return null}}function ou(t){let e=su(t.rootPath,".toolnet","current.md");if(!nu(e))return null;try{return ru(e,"utf8").trim()}catch{return null}}function iu(t,e){let n=e.replace(/\r\n/g,`
|
|
130
|
-
`).trim(),r=2400,s=n.length>r?`${n.slice(0,r)}
|
|
131
|
-
|
|
132
|
-
[Current work truncated for fast handoff]`:n,o=Ar(t);return["# ToolNet Fast Handoff","",`Project: ${t.name}`,"",...o?[o,""]:[],s,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
|
|
133
|
-
`)}function Ur(t){let e=ou(t);if(e===null)return{updated:!1,reason:"missing-current",chars:0};if(!e.trim())return{updated:!1,reason:"empty-current",chars:0};let n=iu(t,e);return Gr(t)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(Jr(t,n),{updated:!0,reason:"updated",chars:n.length})}function Xe(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function Yr(t){let e=fe(),n=Kt(_t({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new Se(n,t.id,t.name,t.remote??t.name)}async function pu(t){for(let e=0;e<10;e+=1){let n=wt(t);if(n)return n;await new Promise(r=>setTimeout(r,150))}return null}function fu(t){let e=du(lu(),".config","toolnet-memory","codex-notify-previous.json");if(au(e))try{let n=JSON.parse(cu(e,"utf8"));if(!Array.isArray(n)||n.length===0||!n.every(s=>typeof s=="string"))return;uu(n[0],[...n.slice(1),t],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function mu(t){let e;try{e=JSON.parse(t)}catch{return}if(e.type!=="agent-turn-complete")return;let r=typeof e["thread-id"]=="string"?e["thread-id"]:"",s=typeof e["turn-id"]=="string"?e["turn-id"]:"",o=typeof e.cwd=="string"?e.cwd:"",i=typeof e.client=="string"?e.client:void 0;if(!r||!o)return;let a=Mr(o);if(!a)return;let c=await pu(r);if(!c)return;let u=Yr(a);await pe({project:a,storage:u,threadId:r,rolloutPath:c,cwd:o,turnId:s,client:i,idle:!0});try{await Fr(a,u,800)}catch{}try{Ur(a)}catch{}}async function gu(){let[t="help",...e]=process.argv.slice(2);if(t==="install-notify"){let o=Xe(e,"--bin"),i=_r({binary:o}),a=Kr({binary:o});console.log(`\u2705 Codex notify installed: ${i.configFile}`),i.preservedPrevious&&console.log(`\u2705 Previous notify preserved: ${i.previousFile}`),console.log(`\u2705 Codex SessionStart context hook: ${a}`);return}if(t==="notify"){let o=e[e.length-1]??"";try{await mu(o)}finally{fu(o)}return}let n=Xe(e,"--project")??process.cwd(),r=new q().detect(n),s=Yr(r);if(t==="sync"){let o=e[0];if(!o)throw new Error("Usage: sync <thread-id>");let i=Xe(e,"--rollout")??wt(o);if(!i)throw new Error(`Codex rollout not found for ${o}`);let a=await pe({project:r,storage:s,threadId:o,rolloutPath:i,idle:e.includes("--idle")});console.log(JSON.stringify(a,null,2));return}if(t==="recover"){let o=Number(Xe(e,"--limit")??100),i=await Er(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((a,c)=>a+c.imported,0)},null,2));return}console.log(`Codex Session Adapter
|
|
97
|
+
`,"application/json"),i}function be(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function Gt(t){let e=H(),n=He(Ve({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new Z(n,t.id,t.name,t.remote??t.name)}async function ao(t){for(let e=0;e<10;e+=1){let n=Re(t);if(n)return n;await new Promise(r=>setTimeout(r,150))}return null}function co(t){let e=io(oo(),".config","toolnet-memory","codex-notify-previous.json");if(no(e))try{let n=JSON.parse(ro(e,"utf8"));if(!Array.isArray(n)||n.length===0||!n.every(s=>typeof s=="string"))return;so(n[0],[...n.slice(1),t],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function uo(t){let e;try{e=JSON.parse(t)}catch{return}if(e.type!=="agent-turn-complete")return;let r=typeof e["thread-id"]=="string"?e["thread-id"]:"",s=typeof e["turn-id"]=="string"?e["turn-id"]:"",o=typeof e.cwd=="string"?e.cwd:"",i=typeof e.client=="string"?e.client:void 0;if(!r||!o)return;let u=Ft(o);if(!u)return;let c=await ao(r);if(!c)return;let a=Gt(u);await U({project:u,storage:a,threadId:r,rolloutPath:c,cwd:o,turnId:s,client:i,idle:!0});try{await Yt(u,a,800)}catch{}}async function lo(){let[t="help",...e]=process.argv.slice(2);if(t==="install-notify"){let o=be(e,"--bin"),i=Jt({binary:o}),u=Vt({binary:o});console.log(`\u2705 Codex notify installed: ${i.configFile}`),i.preservedPrevious&&console.log(`\u2705 Previous notify preserved: ${i.previousFile}`),console.log(`\u2705 Codex SessionStart context hook: ${u}`);return}if(t==="notify"){let o=e[e.length-1]??"";try{await uo(o)}finally{co(o)}return}let n=be(e,"--project")??process.cwd(),r=new _().detect(n),s=Gt(r);if(t==="sync"){let o=e[0];if(!o)throw new Error("Usage: sync <thread-id>");let i=be(e,"--rollout")??Re(o);if(!i)throw new Error(`Codex rollout not found for ${o}`);let u=await U({project:r,storage:s,threadId:o,rolloutPath:i,idle:e.includes("--idle")});console.log(JSON.stringify(u,null,2));return}if(t==="recover"){let o=Number(be(e,"--limit")??100),i=await Kt(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((u,c)=>u+c.imported,0)},null,2));return}console.log(`Codex Session Adapter
|
|
134
98
|
|
|
135
99
|
Commands:
|
|
136
100
|
install-notify
|
|
137
101
|
sync <thread-id> [--project PATH]
|
|
138
102
|
recover [--project PATH] [--limit N]
|
|
139
|
-
`)}
|
|
103
|
+
`)}lo().catch(t=>{process.argv[2]==="notify"&&process.exit(0),console.error(t instanceof Error?t.message:t),process.exit(1)});
|