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