toolnet-memory 0.3.11 → 0.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +432 -163
- package/bundle/agy-hook.js +38 -38
- package/bundle/agy.js +23 -23
- package/bundle/api.js +19 -16
- package/bundle/claude-hook.js +9 -9
- package/bundle/codex.js +28 -28
- package/bundle/context-runtime.js +4 -4
- package/bundle/context.js +12 -12
- package/bundle/continuity-certify.js +16 -13
- package/bundle/copilot-hook.js +13 -13
- package/bundle/cursor-hook.js +13 -13
- package/bundle/grok-hook.js +13 -13
- package/bundle/kiro-hook.js +14 -14
- package/bundle/mcp.js +21 -18
- package/bundle/opencode.js +27 -27
- package/package.json +1 -1
package/bundle/kiro-hook.js
CHANGED
|
@@ -90,7 +90,7 @@ Required order:
|
|
|
90
90
|
Current repository evidence overrides stale memory.
|
|
91
91
|
`.trim();return r?bn(`${r}
|
|
92
92
|
|
|
93
|
-
${s}`):s}function jn(t){let e=t.tool_input&&typeof t.tool_input=="object"?t.tool_input:{},n=[];return kt(e,n),n.find(oo)?{blocked:!0,reason:"ToolNet continuity guard: do not read or reconstruct previous work from raw ToolNet/agent session history. Use the injected continuity handoff first; if it is insufficient, invoke the MCP tool memory_agent_ask directly. Then inspect normal repository source/git evidence."}:{blocked:!1}}function An(t){return t==="PreToolUse"||t==="preToolUse"}function Cn(t){return t==="SessionStart"||t==="agentSpawn"}function Pn(t){return t==="UserPromptSubmit"||t==="userPromptSubmit"}import{existsSync as
|
|
93
|
+
${s}`):s}function jn(t){let e=t.tool_input&&typeof t.tool_input=="object"?t.tool_input:{},n=[];return kt(e,n),n.find(oo)?{blocked:!0,reason:"ToolNet continuity guard: do not read or reconstruct previous work from raw ToolNet/agent session history. Use the injected continuity handoff first; if it is insufficient, invoke the MCP tool memory_agent_ask directly. Then inspect normal repository source/git evidence."}:{blocked:!1}}function An(t){return t==="PreToolUse"||t==="preToolUse"}function Cn(t){return t==="SessionStart"||t==="agentSpawn"}function Pn(t){return t==="UserPromptSubmit"||t==="userPromptSubmit"}import{existsSync as Pu}from"node:fs";import{join as Iu}from"node:path";import{existsSync as ao,readFileSync as co}from"node:fs";import{homedir as uo}from"node:os";import{join as lo}from"node:path";function po(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
|
|
94
94
|
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function mo(){let t=process.env.TOOLNET_GLOBAL_ENV??lo(uo(),".config","toolnet-memory",".env");if(!ao(t))return;let e=co(t,"utf8");for(let n of e.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let o=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=po(r.slice(s+1)))}}mo();function ce(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function ue(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function Pe(){return{memory:{autoCapture:ce(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:ce(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:ce(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:ce(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:ue(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:ue(process.env.MEMORY_RERANK_TOP,10),finalContext:ue(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:ue(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:ce(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:ue(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as fo}from"node:crypto";import{existsSync as vt,mkdirSync as go,readFileSync as yo,renameSync as ho,writeFileSync as So}from"node:fs";import{basename as ko,dirname as Ie,join as Ee,parse as En,resolve as le}from"node:path";var Tn=".toolnet",wo="project.json";function vo(t){return fo("sha256").update(t).digest("hex").slice(0,16)}function bt(t){return Ee(t,Tn,wo)}function bo(t){return vt(bt(t))}function xo(t,e){let n=le(t),r=En(n).root;for(;;){if(bo(n))return n;if(n===r||e&&n===le(e))break;let s=Ie(n);if(s===n)break;n=s}return null}function jo(t){let e=le(t),n=En(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>vt(Ee(e,o))))return e;if(e===n)break;let s=Ie(e);if(s===e)break;e=s}return le(t)}function Ao(t){let e;try{e=JSON.parse(yo(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let n=e;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:Ie(Ie(t)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function In(t,e){let n=Ee(t,Tn);go(n,{recursive:!0});let r=bt(t),s=`${r}.tmp-${process.pid}`;So(s,JSON.stringify(e,null,2)+`
|
|
95
95
|
`,{encoding:"utf8",mode:384}),ho(s,r)}function Mn(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var Me=class{detect(e=process.cwd()){let n=le(e),r=jo(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>vt(Ee(r,m))),i=xo(n,o?r:void 0);if(i){let m=bt(i),p=Ao(m);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),In(i,p)),Mn(p,i)}let a=new Date().toISOString(),c=ko(r),u={version:1,id:vo(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return In(r,u),Mn(u,r)}};var Co=[{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}],Te=class{scan(e){let n=[];for(let r of Co){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var U=class{scanner=new Te;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as Uo}from"node:os";import{join as Yo}from"node:path";import{DeleteObjectCommand as Po,GetObjectCommand as Io,HeadObjectCommand as Mo,ListObjectsV2Command as Eo,PutObjectCommand as To,S3Client as Oo}from"@aws-sdk/client-s3";import{getSignedUrl as Ro}from"@aws-sdk/s3-request-presigner";var Oe=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Oo({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new To({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Ro(this.client,new Io({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Mo({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new Po({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Eo({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as On,mkdir as No,readFile as _o,readdir as Ko,rm as $o,stat as Rn,writeFile as Fo}from"node:fs/promises";import{dirname as Wo,join as Lo,relative as Nn,resolve as Do}from"node:path";var de=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Do(this.root,n)}async put(e,n){let r=this.path(e);await No(Wo(r),{recursive:!0}),await Fo(r,n)}async get(e){try{return await _o(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await On(this.path(e)),!0}catch{return!1}}async delete(e){await $o(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await On(n)}catch{return r}let s=async i=>{let a=await Ko(i,{withFileTypes:!0});for(let c of a){let u=Lo(i,c.name);if(c.isDirectory()){await s(u);continue}let m=await Rn(u);r.push({key:Nn(this.root,u),size:m.size,updatedAt:m.mtime.toISOString()})}},o=await Rn(n);return o.isDirectory()?await s(n):r.push({key:Nn(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as zo,GetObjectCommand as qo,HeadObjectCommand as Vo,ListObjectsV2Command as Bo,PutObjectCommand as Jo,S3Client as Ho}from"@aws-sdk/client-s3";import{getSignedUrl as Go}from"@aws-sdk/s3-request-presigner";var pe=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Ho({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Jo({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Go(this.client,new qo({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Vo({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new zo({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Bo({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function xt(t,e){return console.warn(e),new de(t)}function _n(t){let e=t.localRoot??Yo(Uo(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new pe({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xt(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new pe({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xt(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Oe({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xt(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new de(e)}function Xo(t){return new Promise(e=>setTimeout(e,t))}async function Kn(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(a){if(o=a,i>=n)break;let c=Math.min(s,r*2**(i-1)),u=Math.floor(Math.random()*Math.max(1,c*.2));await Xo(c+u)}throw o}var Qo=new Set(["put","get","getText","delete","list"]);function $n(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:Qo.has(r)?(...o)=>Kn(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Fn(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Wn(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var Re=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Fn(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
|
|
96
96
|
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Wn(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{existsSync as ci,readFileSync as ui}from"node:fs";import{join as li}from"node:path";import{existsSync as Zo,mkdirSync as ei,readFileSync as ti,renameSync as ni,writeFileSync as ri}from"node:fs";import{dirname as si,join as oi}from"node:path";function Ln(t){return oi(t.rootPath,".toolnet","context","session-origin.json")}function ii(t,e){ei(si(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;ri(n,`${JSON.stringify(e,null,2)}
|
|
@@ -101,9 +101,9 @@ ${s}`):s}function jn(t){let e=t.tool_input&&typeof t.tool_input=="object"?t.tool
|
|
|
101
101
|
[Current work truncated for fast handoff]`:n,o=zn(t);return["# ToolNet Fast Handoff","",`Project: ${t.name}`,"",...o?[o,""]:[],s,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
|
|
102
102
|
`)}function qn(t){let e=di(t);if(e===null)return{updated:!1,reason:"missing-current",chars:0};if(!e.trim())return{updated:!1,reason:"empty-current",chars:0};let n=pi(t,e);return gt(t)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(fn(t,n),{updated:!0,reason:"updated",chars:n.length})}import{join as mi}from"node:path";function Vn(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=w(n).slice(0,12);if(!r||r==="."||r==="..")return`${e}--${s}`;let o=r.slice(0,100);return o===n&&n.length<=100?o:`${o.slice(0,85)}--${s}`}function _e(t,e,n){let r=e.trim(),s=n.trim();if(!r)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=Vn(r.toLowerCase(),"agent"),i=Vn(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:r,nativeSessionId:s,sessionKey:`${r}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:mi(t.rootPath,".toolnet","sessions",o,i)}}function Bn(t){return String(t).padStart(12,"0")}var Ke=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
|
|
103
103
|
`,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let a=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!a)continue;let c=Number(a[1]),u=Number(a[2]);!Number.isFinite(c)||!Number.isFinite(u)||(s.push({key:i.key,start:c,end:u}),o=Math.max(o,u))}return s.sort((i,a)=>i.start-a.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
|
|
104
|
-
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),a=n.filter(y=>y.sequence>i.maxSequence),c=0;for(let y of this.split(a)){let S=y[0],k=y[y.length-1],
|
|
104
|
+
`,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),a=n.filter(y=>y.sequence>i.maxSequence),c=0;for(let y of this.split(a)){let S=y[0],k=y[y.length-1],I=y.map(E=>JSON.stringify(E)).join(`
|
|
105
105
|
`)+`
|
|
106
|
-
`,M=w(
|
|
106
|
+
`,M=w(I).slice(0,16),P=[e.remotePrefix,"events",`${Bn(S.sequence)}-${Bn(k.sequence)}-${M}.jsonl`].join("/");await this.storage.exists(P)||await this.storage.put(P,I,"application/x-ndjson"),c+=y.length}let u=await this.scan(e),m=n[n.length-1],p=o?.status??"active";m?.type==="session_end"||m?.type==="session_idle"?p="idle":m?.type==="error"?p="error":n.length>0&&(p="active");let d=new Date().toISOString(),l=n[0],g={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:p,createdAt:o?.createdAt??l?.timestamp??d,updatedAt:m?.timestamp??d,firstEventAt:o?.firstEventAt??l?.timestamp,lastEventAt:m?.timestamp??o?.lastEventAt,eventCount:u.maxSequence,chunkCount:u.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(g.title=s.title??o?.title);let h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:u.maxSequence,lastRemoteSequence:u.maxSequence,sourceCursors:r,updatedAt:d};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,g),{uploadedEvents:c,lastRemoteSequence:u.maxSequence,eventCount:g.eventCount,chunkCount:g.chunkCount,status:p}}};import{closeSync as At,existsSync as ki,fsyncSync as wi,mkdirSync as vi,openSync as Ct,readSync as bi,rmSync as Hn,statSync as Gn,writeSync as xi}from"node:fs";import{join as Pt}from"node:path";var fi=new Set(["thinking","reasoning","reasoningcontent","chainofthought","cot","analysistext","internalreasoning","modelthinking"]),gi=new Set(["reasoning","thinking","chain_of_thought","chain-of-thought","internal_reasoning","internal-reasoning"]);function yi(t){return t.toLowerCase().replace(/[^a-z0-9]+/gu,"")}function hi(t){for(let e of["type","kind"]){let n=t[e];if(typeof n=="string"){let r=n.toLowerCase();if(gi.has(r))return n}}return null}function jt(t,e=0){if(e>12)return"[ToolNet nested value omitted]";if(Array.isArray(t))return t.map(o=>jt(o,e+1));if(!t||typeof t!="object")return t;let n=t,r=hi(n);if(r)return{type:r,omitted:"[private reasoning omitted]"};let s={};for(let[o,i]of Object.entries(n))fi.has(yi(o))||(s[o]=jt(i,e+1));return s}function Si(t){if(!t)return new Date().toISOString();let e=new Date(t);return Number.isNaN(e.getTime())?new Date().toISOString():e.toISOString()}function Y(t){return t?.trim()||void 0}function Jn(t,e={}){let n={...t.provenance??{}},r=Y(t.source)??Y(e.source)??Y(n.source);return{...t,timestamp:Si(t.timestamp),source:r,turnId:Y(t.turnId)??Y(e.turnId),cwd:Y(t.cwd)??Y(e.cwd),data:jt(t.data??{}),provenance:n}}var ji=12e4,Ai=80,Ci=2e3;function Pi(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ne=class{constructor(e,n={}){this.identity=e;this.eventContext=n;vi(e.localDirectory,{recursive:!0}),this.eventsFile=Pt(e.localDirectory,"events.jsonl"),this.stateFile=Pt(e.localDirectory,"state.json"),this.lockFile=Pt(e.localDirectory,"journal.lock")}identity;eventContext;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return an(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){T(this.stateFile,e)}acquireLock(){for(let e=0;e<Ai;e+=1)try{return Ct(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-Gn(this.lockFile).mtimeMs>ji){Hn(this.lockFile,{force:!0});continue}}catch{}Pi(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{At(n),Hn(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let p of e){let d=Jn(p,this.eventContext),l=d.timestamp??new Date().toISOString(),g=d.data??{},h=d.provenance?.rawDigest??w(Ce(g)),y=d.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,d.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,d.type,l,h].join("|"),S=w(y).slice(0,32);if(r.has(S))continue;s+=1;let k={version:1,id:S,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,sessionId:this.identity.nativeSessionId,type:d.type,timestamp:l,source:d.source??d.provenance?.source??this.identity.agent,data:g,provenance:{...d.provenance,rawDigest:h}};d.role!==void 0&&(k.role=d.role),d.turnId!==void 0&&(k.turnId=d.turnId),d.cwd!==void 0&&(k.cwd=d.cwd),d.sourceEventId!==void 0&&(k.sourceEventId=d.sourceEventId),d.sourceSequence!==void 0&&(k.sourceSequence=d.sourceSequence),o.push(k),r.add(S)}if(o.length===0)return[];let i=o.map(p=>JSON.stringify(p)).join(`
|
|
107
107
|
`)+`
|
|
108
108
|
`,a=Ct(this.eventsFile,"a",384);try{xi(a,i,null,"utf8"),wi(a)}finally{At(a)}let c=o[o.length-1],u="active";c.type==="session_end"||c.type==="session_idle"?u="idle":c.type==="error"&&(u="error");let m=Array.from(r).slice(-Ci);return this.saveStateUnsafe({...n,status:u,updatedAt:c.timestamp,lastLocalEventAt:c.timestamp,lastSequence:c.sequence,recentEventIds:m}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!ki(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=Gn(this.eventsFile).size,r=Math.min(e.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let s=n-r,o=Buffer.alloc(s),i=Ct(this.eventsFile,"r");try{bi(i,o,0,s,r)}finally{At(i)}return{events:o.toString("utf8").split(`
|
|
109
109
|
`).filter(Boolean).map(u=>JSON.parse(u)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe(),s=new Date().toISOString();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),lastRemoteAt:s,updatedAt:s})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as Qa,existsSync as Za,openSync as ec,readSync as tc,statSync as nc}from"node:fs";function Un(t,e){let n=e.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var Zn=[/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],Ii=[/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],Mi=[/\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],Ei=[/\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],Ti=[/đã 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],Yn=[/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],Oi=[/\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],Ri=[/đườ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],Ni=[/\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],Xn=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),_i=new Set(["payload","data","content","message","messages","parts","summary"]);function R(t,e){return e.some(n=>n.test(t))}function er(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Ki(t){return er(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function $i(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function It(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||Xn.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))It(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(Xn.has(s)||_i.has(s))&&It(o,s,n,r+1)}}function Fi(t){let e=[];It(t.data,void 0,e);let n=[],r=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=er(o);if($i(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function Qn(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Wi(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&R(t,Zn)?{kind:"rule",confidence:.98}:r&&R(t,Ii)?{kind:"rule",confidence:.92}:R(t,Mi)?{kind:R(t,Yn)?"architecture":"decision",confidence:r?.93:.86}:r&&R(t,Ei)?{kind:"todo",confidence:.87}:R(t,Yn)&&R(t,Oi)?{kind:"architecture",confidence:r?.88:.82}:s&&R(t,Ti)?{kind:"fix",confidence:.8}:r&&R(t,Ri)&&R(t,Ni)?{kind:"context",confidence:.79}:null}function Li(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Di(t,e,n){return t==="rule"&&R(n,Zn)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":Un(e,n)}function tr(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,a=Qn(o);i&&a&&s.set(i,a)}for(let o of e){let i=Qn(o),a=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&a&&(i=s.get(a)??"");for(let c of Fi(o)){let u=Wi(c,i,o);if(!u||u.confidence<.75)continue;let m=Li(u.kind),p=Ki(c),d=w([t.projectId,u.kind,p].join("|"));if(r.has(d))continue;r.add(d);let l=o.provenance.sourcePath?[o.provenance.sourcePath]:[],g=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:d,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:u.kind,type:m,content:c,confidence:u.confidence,importance:Di(u.kind,m,c),tags:[m],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:g,sourcePaths:l,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}import{createHash as zi}from"node:crypto";var qi=["project-knowledge","implementation","continuation","session-context"],Vi={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function Mt(t){return zi("sha256").update(t).digest("hex")}function $e(t,e){return`${t}:${Mt(e).slice(0,24)}`}function Bi(t){try{return Mt(JSON.stringify(t))}catch{return Mt(String(t))}}function X(t){let e=new Set,n=[];for(let r of t){let s=r?.replace(/\s+/gu," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();e.has(o)||(e.add(o),n.push(s))}return n}function rr(t,e=420){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:`${n.slice(0,Math.max(0,e-1)).trimEnd()}\u2026`}function Ji(t){return t==="rule"||t==="architecture"?"project-knowledge":t==="decision"||t==="fix"?"implementation":t==="todo"?"continuation":"session-context"}function nr(t){return t.length===0?0:t.reduce((e,n)=>e+n,0)/t.length}function Hi(t){return t.slice().sort((e,n)=>n.importanceScore-e.importanceScore||n.confidence-e.confidence||e.id.localeCompare(n.id)).slice(0,5).map(e=>rr(e.content)).join(" | ")}function Gi(t){return t.slice().sort((e,n)=>n.importanceScore-e.importanceScore||n.confidence-e.confidence||e.id.localeCompare(n.id)).slice(0,6).map(e=>rr(e.content)).join(`
|
|
@@ -127,7 +127,7 @@ ${g.map(S=>`- \`${S}\``).join(`
|
|
|
127
127
|
`)}`);let y=h.join(`
|
|
128
128
|
|
|
129
129
|
`).slice(0,Rt);if(y.length<20)continue;n.push({sourceKey:`skill:${c}`,sourceType:"skill",title:m,summary:p,content:y,tags:["toolnet","auto","skill","sop"]})}catch{r+=1}return{candidates:n,failed:r}}function Ot(t){let e=new Date().toISOString();return{schema:Ir,version:1,projectId:t,entries:[],createdAt:e,updatedAt:e}}async function xa(t,e){let n=await t.getText(Pr);if(!n)return Ot(e);try{let r=JSON.parse(n);return r.schema!==Ir||r.version!==1||r.projectId!==e||!Array.isArray(r.entries)?Ot(e):r}catch{return Ot(e)}}async function ja(t,e){await t.put(Pr,JSON.stringify(e,null,2),"application/json")}function Aa(t){return`toolnet-auto-${he(t).slice(0,12)}`}function Ca(t){let e=Z(t.title).slice(0,72),n=he(t.sourceKey).slice(0,10);return Z(`auto-${t.sourceType}-${e}-${n}`)}function Pa(t){return[`> Auto-generated by ToolNet Knowledge Automation from ${t.sourceType==="skill"?"reusable Skill Memory":t.sourceType==="scene"?"semantic memory scene":"durable memory"}.`,"",t.content].join(`
|
|
130
|
-
`).slice(0,Rt)}function Ia(t){return he({sourceType:t.sourceType,title:t.title,summary:t.summary,content:t.content,tags:t.tags})}function Ma(t,e){return t.tags.includes(e)}async function Er(t){let e=wa(t.hierarchy),n=ba(t.project.rootPath),r=new Map;for(let l of[...e,...n.candidates])r.set(l.sourceKey,l);let s=[...r.values()].sort((l,g)=>l.sourceKey.localeCompare(g.sourceKey)),o={schema:"toolnet.wiki-automation-result.v1",scanned:e.length+n.candidates.length,eligible:s.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new We(new Le(t.storage,t.project));await i.initialize();let a=new ze(new De(t.storage,t.project));await a.initialize();let c=await xa(t.storage,t.project.id),u=await i.listPages(),m=new Map(u.map(l=>[l.slug,l])),p=new Map(c.entries.map(l=>[l.sourceKey,l]));for(let l of s)try{let g=Aa(l.sourceKey),h=Ia(l),y=p.get(l.sourceKey),S=y?.slug??Ca(l),k=m.get(S);if(k&&!Ma(k,g)){o.skipped+=1;continue}let
|
|
130
|
+
`).slice(0,Rt)}function Ia(t){return he({sourceType:t.sourceType,title:t.title,summary:t.summary,content:t.content,tags:t.tags})}function Ma(t,e){return t.tags.includes(e)}async function Er(t){let e=wa(t.hierarchy),n=ba(t.project.rootPath),r=new Map;for(let l of[...e,...n.candidates])r.set(l.sourceKey,l);let s=[...r.values()].sort((l,g)=>l.sourceKey.localeCompare(g.sourceKey)),o={schema:"toolnet.wiki-automation-result.v1",scanned:e.length+n.candidates.length,eligible:s.length,created:0,updated:0,unchanged:0,skipped:0,failed:n.failed,reviewPending:0,autoApproved:0,reviewApproved:0,pages:[]},i=new We(new Le(t.storage,t.project));await i.initialize();let a=new ze(new De(t.storage,t.project));await a.initialize();let c=await xa(t.storage,t.project.id),u=await i.listPages(),m=new Map(u.map(l=>[l.slug,l])),p=new Map(c.entries.map(l=>[l.sourceKey,l]));for(let l of s)try{let g=Aa(l.sourceKey),h=Ia(l),y=p.get(l.sourceKey),S=y?.slug??Ca(l),k=m.get(S);if(k&&!Ma(k,g)){o.skipped+=1;continue}let I=Se([...l.tags,g]),M=Pa(l),P=await a.gate({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:S,marker:g,digest:h,title:l.title,...l.summary?{summary:l.summary}:{},content:M,tags:I},[...m.values()]);if(!P.allowed){P.mode==="pending-review"?o.reviewPending+=1:o.skipped+=1;continue}P.mode==="auto-approved"?o.autoApproved+=1:P.mode==="review-approved"&&(o.reviewApproved+=1),k?y?.digest!==h?(k=await i.updatePage(S,{title:l.title,summary:l.summary??"",content:M,tags:I}),m.set(k.slug,k),o.updated+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"updated"})):(o.unchanged+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:S,action:"unchanged"})):(k=await i.createPage({slug:S,title:l.title,summary:l.summary,content:M,tags:I}),m.set(k.slug,k),o.created+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"created"}));let E=new Date().toISOString(),x={sourceKey:l.sourceKey,sourceType:l.sourceType,slug:S,digest:h,marker:g,updatedAt:E},v=c.entries.findIndex(D=>D.sourceKey===l.sourceKey);v>=0?c.entries[v]=x:c.entries.push(x),p.set(l.sourceKey,x),await a.markApplied(l.sourceKey,h)}catch(g){if(g instanceof j&&g.statusCode===409){o.skipped+=1;continue}o.failed+=1}let d=new Date().toISOString();return c.updatedAt=d,c.lastRunAt=d,c.entries.sort((l,g)=>l.sourceKey.localeCompare(g.sourceKey)),await ja(t.storage,c),o}import{createHash as Ea}from"node:crypto";import{chmodSync as Or,existsSync as Ta,mkdirSync as Oa,readFileSync as Yp,readdirSync as Xp,renameSync as Ra,statSync as Qp,writeFileSync as Na}from"node:fs";import{join as Rr}from"node:path";var _a="toolnet.skill-memory.v1",Tr=5,Ka=16,$a=24,Fa=32;function Wa(t){return Ea("sha256").update(t).digest("hex")}function we(t,e=Number.MAX_SAFE_INTEGER){let n=new Set,r=[];for(let s of t){let o=s.replace(/\s+/gu," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=e))break}return r}function Nt(t,e=360){let n=t.replace(/\s+/gu," ").trim();return n.length<=e?n:n.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function La(t){return t.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/giu,"Bearer [REDACTED]").replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu,"[REDACTED]").replace(/\b(api[_-]?key|token|password|passwd|secret)\b(\s*[:=]\s*)(["']?)[^\s"'`]+/giu,"$1$2[REDACTED]")}function q(t,e=360){return t&&Nt(La(t),e)||void 0}function ve(t,e){for(let n of e){let r=t[n];if(typeof r=="string"&&r.trim())return r}}function Nr(t,e){for(let n of e){let r=t[n];if(typeof r=="number"&&Number.isFinite(r))return r;if(typeof r=="string"&&r.trim()&&Number.isFinite(Number(r)))return Number(r)}}function _r(t,e){for(let n of e){let r=t[n];if(typeof r=="boolean")return r;if(typeof r=="string"){let s=r.trim().toLowerCase();if(["true","yes","pass","passed","success","succeeded","ok"].includes(s))return!0;if(["false","no","fail","failed","error"].includes(s))return!1}}}function Kr(t){let e=t.data??{};if(_r(e,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=Nr(e,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let s=ve(e,["status","result","outcome"]);return!!(s&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(s))}function ke(t){let e=t.data??{};if(Kr(t))return!1;if(_r(e,["passed","pass","success","succeeded","ok"])===!0||Nr(e,["exitCode","exit_code","code","statusCode"])===0)return!0;let s=ve(e,["status","result","outcome"]);return s&&/\b(pass(?:ed)?|success(?:ful)?|succeeded|ok|green|complete(?:d)?)\b/iu.test(s)?!0:t.type==="commit"||t.type==="deploy"}function $r(t){let e=t.data??{},n=ve(e,["path","file","filePath","filename","target"]);if(n)return q(n,260);let r=t.provenance?.files;return q(r?.[0],260)}function _t(t){return q(ve(t.data??{},["command","cmd","script"]),420)}function re(t){return q(ve(t.data??{},["name","test","suite","title","message","text","result","status"]),300)}function Da(t){let e=[];for(let n of[...t].sort((r,s)=>r.sequence-s.sequence))if(ke(n)){if(n.type==="test"){let r=re(n)??_t(n)??"Tests passed";e.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=re(n);e.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=re(n);e.push(r?`Deploy: ${r}`:"Deployment completed")}}return we(e,10)}function za(t,e){let n=[];for(let r of[...t].sort((s,o)=>s.sequence-o.sequence))switch(r.type){case"file_write":case"file_edit":{let s=$r(r);s&&n.push(`Update ${s}`);break}case"command":{if(Kr(r))break;let s=_t(r);s&&n.push(`Run: ${s}`);break}case"test":{if(!ke(r))break;let s=re(r)??_t(r)??"project tests";n.push(`Verify: ${s}`);break}case"commit":{if(!ke(r))break;let s=re(r);n.push(s?`Commit: ${s}`:"Commit verified changes");break}case"deploy":{if(!ke(r))break;let s=re(r);n.push(s?`Deploy: ${s}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of e.files.slice(0,8)){let s=q(r,260);s&&n.push(`Update ${s}`)}return we(n,Ka)}function qa(t,e){let n=[...e.files];for(let r of t){let s=$r(r);s&&n.push(s);for(let o of r.provenance?.files??[]){let i=q(o,260);i&&n.push(i)}}return we(n,$a)}function Va(t){return we(t.filter(e=>["file_write","file_edit","command","test","commit","deploy"].includes(e.type)).map(e=>e.id),Fa)}function Ba(t){return t.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function Fr(t,e,n){if(e.length===0)return[];let r=Da(e),s=we(n.completed.map(g=>q(g,280)??""),Tr);if(!(s.length>0||e.some(g=>["test","commit","deploy"].includes(g.type)&&ke(g))))return[];let i=q(n.task,280)??q(n.nextActions[0],280),a=s.length>0?s:i?[i]:[];if(a.length===0)return[];let c=za(e,n);if(c.length===0)return[];let u=qa(e,n),m=Va(e),p=Math.min(...e.map(g=>g.sequence)),d=Math.max(...e.map(g=>g.sequence)),l=Ba(e);return a.slice(0,Tr).map(g=>{let h=[`Reusable procedure learned from successful task: ${g}.`,u.length>0?`Files: ${u.slice(0,6).join(", ")}.`:"",r.length>0?`Verification: ${r.slice(0,4).join("; ")}.`:""].filter(Boolean),y=JSON.stringify({projectId:t.projectId,task:g,steps:c,verification:r,files:u}),S=Wa(y);return{schema:_a,version:1,id:`skill-${S.slice(0,24)}`,fingerprint:S,projectId:t.projectId,title:Nt(`SOP: ${g}`,180),task:g,summary:Nt(h.join(" "),900),steps:c,verification:r,files:u,source:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,firstSequence:p,lastSequence:d,eventIds:m},createdAt:l}})}function Ja(t){return Rr(t.rootPath,".toolnet","memory","skills")}function Ha(t){let e=Ja(t);return Oa(e,{recursive:!0,mode:448}),Or(e,448),e}function Wr(t,e){if(e.length===0)return{written:0,deduped:0,files:[]};let n=Ha(t),r=0,s=0,o=[];for(let i of e){if(i.projectId!==t.id)throw new Error(`Skill project mismatch: ${i.projectId} != ${t.id}`);let a=Rr(n,`${i.id}.json`);if(o.push(a),Ta(a)){s+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;Na(c,JSON.stringify(i,null,2)+`
|
|
131
131
|
`,{encoding:"utf8",mode:384}),Ra(c,a),Or(a,384),r+=1}return{written:r,deduped:s,files:o}}function Lr(t){return String(t).padStart(12,"0")}function Ga(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var Ve=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(m=>m.sequence)),o=Math.max(...n.map(m=>m.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},a=JSON.stringify(i,null,2)+`
|
|
132
132
|
`,c=w(r.map(m=>m.fingerprint).sort().join("|")).slice(0,16),u=[Ga(e),"batches",`${Lr(s)}-${Lr(o)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,a,"application/json"),u}};import{createHash as Ua}from"node:crypto";function Dr(t){return String(t).padStart(12,"0")}function Ya(t){return Ua("sha256").update(t).digest("hex")}function Xa(t){return t.remotePrefix.replace("/sessions/","/memory/hierarchy/")}var Be=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(n.length===0||r.facts.length===0)return null;let s=Math.min(...n.map(u=>u.sequence)),o=Math.max(...n.map(u=>u.sequence)),i={schema:"toolnet.memory-hierarchy-batch.v1",version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,hierarchy:r},a=Ya([...r.facts.map(u=>u.id),...r.knowledge.map(u=>u.id)].sort().join("|")).slice(0,16),c=[Xa(e),"batches",`${Dr(s)}-${Dr(o)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,`${JSON.stringify(i,null,2)}
|
|
133
133
|
`,"application/json"),c}};function rc(t,e){if(!Za(t))return{events:[],nextOffset:e};let n=nc(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=ec(t,"r");try{tc(i,o,0,s,r)}finally{Qa(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
@@ -135,14 +135,14 @@ ${g.map(S=>`- \`${S}\``).join(`
|
|
|
135
135
|
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Je=class{constructor(e){this.options=e;this.journal=new Ve(e.storage),this.hierarchyJournal=new Be(e.storage)}options;journal;hierarchyJournal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=rc(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Fe(this.options.identity,s.events),i=o.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,s.events,i));let c=!1;o.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,s.events,o.hierarchy));let u=Fr(this.options.identity,s.events,o.state),m=Wr(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",o.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",o.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",o.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",o.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",o.hierarchy.stats.knowledge),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.journal_written",c?1:0),this.options.wal.setSourceCursor("memory.skill.assets",u.length),this.options.wal.setSourceCursor("memory.skill.written",m.written),this.options.wal.setSourceCursor("memory.skill.deduped",m.deduped);try{let p=sn(this.options.project.rootPath,s.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 Er({project:this.options.project,storage:this.options.storage,hierarchy:o.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",s.nextOffset),{scannedEvents:s.events.length,candidates:i.length,journalWritten:a,nextOffset:s.nextOffset}}};import{closeSync as vc,existsSync as bc,openSync as xc,readSync as jc,statSync as Ac}from"node:fs";function zr(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function xe(t){return t.toLowerCase().replace(/[^a-z0-9]/gu,"")}function be(t,e,n=0){if(n>8)return;if(Array.isArray(t)){for(let s of t.slice(0,50))be(s,e,n+1);return}let r=zr(t);if(r)for(let[s,o]of Object.entries(r))e(s,o,r),be(o,e,n+1)}function se(t,e){let n=[];return be(t,(r,s)=>{e.has(xe(r))&&typeof s=="string"&&s.trim()&&n.push(s.trim())}),n}function sc(t){let e=t.trim();if(!e.startsWith("{"))return null;try{return zr(JSON.parse(e))}catch{return null}}function oc(t){let e=t.data;for(let r of["tool","toolName","tool_name"]){let s=e[r];if(typeof s=="string"&&s.trim())return s.trim().toLowerCase()}let n="";return be(e,(r,s,o)=>{if(n)return;let i=xe(r);if(["tool","toolname"].includes(i)&&typeof s=="string"){n=s.trim().toLowerCase();return}if(i!=="name"||typeof s!="string")return;let a=typeof o.type=="string"?o.type.toLowerCase():"";(a.includes("tool")||a.includes("function")||a.includes("command"))&&(n=s.trim().toLowerCase())}),n}function ic(t){let e=se(t.data,new Set(["command","cmd","script"])),n=se(t.data,new Set(["arguments","args"]));for(let r of n){let s=sc(r);if(s)for(let o of se(s,new Set(["command","cmd","script"])))e.push(o)}return Array.from(new Set(e.map(r=>r.trim()).filter(Boolean)))}function ac(t){let e=se(t.data,new Set(["filepath","file_path","filename","file","path","target"].map(xe)));return Array.from(new Set(e.map(n=>n.trim()).filter(n=>n.length>0&&n.length<1e3&&!n.includes(`
|
|
136
136
|
`))))}function cc(t,e){return t.type==="file_edit"||t.type==="file_write"?"modified":/\b(delete|remove|unlink)\b/iu.test(e)?"deleted":/\b(create|add[_-]?file|new[_-]?file)\b/iu.test(e)?"created":/\b(edit|write|patch|apply[_-]?patch|replace|update[_-]?file)\b/iu.test(e)?"modified":null}function uc(t){let e=se(t.data,new Set(["patch","diff","arguments","input"].map(xe))),n=[];for(let r of e){let s=[{regex:/^\*\*\* Update File:\s*(.+)$/gimu,action:"modified"},{regex:/^\*\*\* Add File:\s*(.+)$/gimu,action:"created"},{regex:/^\*\*\* Delete File:\s*(.+)$/gimu,action:"deleted"}];for(let o of s)for(let i of r.matchAll(o.regex)){let a=i[1]?.trim();a&&n.push({kind:"file",text:a,fileAction:o.action,confidence:.99})}}return n}function lc(t){let e=t.toLowerCase();return/\b(typecheck|type-check)\b/u.test(e)||/\btsc\b[\s\S]*--noemit\b/u.test(e)?"typecheck":/\b(eslint|lint)\b/u.test(e)?"lint":/\b(vitest|jest|pytest)\b/u.test(e)||/\bgo\s+test\b/u.test(e)||/\bcargo\s+test\b/u.test(e)||/\b(npm|pnpm|yarn)\s+(run\s+)?test\b/u.test(e)?"test":/\b(npm|pnpm|yarn)\s+(run\s+)?build\b/u.test(e)||/\bcargo\s+build\b/u.test(e)||/\bgo\s+build\b/u.test(e)||/\btsc\b/u.test(e)?"build":null}function dc(t){let e=null;return be(t,(n,r)=>{if(e===null&&["exitcode","code"].includes(xe(n))){if(typeof r=="number"&&Number.isFinite(r)){e=r;return}if(typeof r=="string"){let s=Number(r);Number.isFinite(s)&&(e=s)}}}),e}function pc(t){return se(t,new Set(["status","state","result","output","outputsummary","message","text"]))}function mc(t){let e=dc(t.data);if(e!==null)return e===0?"passed":"failed";let n=pc(t.data).join(`
|
|
137
137
|
`).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 fc(t){let e=[],n=new Set;for(let r of t){let s=[r.kind,r.fileAction??"",r.checkKind??"",r.checkStatus??"",r.text].join("|");n.has(s)||(n.add(s),e.push(r))}return e}function qr(t){let e=[],n=oc(t),r=cc(t,n);if(r)for(let s of ac(t))e.push({kind:"file",text:s,fileAction:r,confidence:t.type==="file_edit"||t.type==="file_write"?1:.96});e.push(...uc(t));for(let s of ic(t)){e.push({kind:"command",text:s,confidence:.98});let o=lc(s);o&&e.push({kind:"test",text:s,checkKind:o,checkStatus:mc(t),confidence:.98})}return fc(e)}var gc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function te(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Br(t){return te(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function ee(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))ee(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(gc.has(r)||["data","payload","parts","messages"].includes(r))&&ee(s,e,n+1)}}function He(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function Vr(t){let e=te(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function A(t,e,n,r,s={}){let o=te(r),i=s.key??Br(o);return{version:1,id:w([t.projectId,n,i,e.id,o,s.status??"",s.fileAction??"",s.checkKind??"",s.checkStatus??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,fileAction:s.fileAction,checkKind:s.checkKind,checkStatus:s.checkStatus,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function yc(t,e,n){let r=te(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(A(t,e,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&s.push(A(t,e,"plan",a[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,u;for(;!o&&(u=c.exec(r));){let d=Number(u[1]),l=te(u[2]??""),g=l&&!Vr(l)?`Phase ${d} - ${l}`:`Phase ${d}`;s.push(A(t,e,"phase",g,{key:`phase:${d}`,order:d,status:He(r),confidence:.93}))}let m=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);m?.[2]&&s.push(A(t,e,"task",m[2],{status:m[1].trim()?"completed":He(m[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,l=te(p[2]),g=Vr(l);s.push(A(t,e,"task",g&&d!==void 0?`TODO ${d}`:l,{key:d!==void 0?`task:${d}`:Br(l),order:d,status:He(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let 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&&s.push(A(t,e,"next_action",d,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(A(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(A(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(A(t,e,"decision",r,{confidence:.9})),r.length<=300&&/^(?:đang\s+(?:sửa|cập nhật|triển khai|xử lý|làm|refactor|fix)|(?:i(?:'m| am)\s+)?(?:working on|implementing|fixing|refactoring|updating|editing)\b)/iu.test(r)&&s.push(A(t,e,"activity",r,{confidence:.86})),s}function Ge(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="user_prompt"||i.role==="user"){let c=[];ee(i.data,c);let u=c.map(m=>te(m)).find(m=>m.length>=8&&m.length<=1200&&!/^\[?toolnet\b/iu.test(m));u&&s(A(t,i,"request",u,{confidence:.96}))}for(let c of qr(i))s(A(t,i,c.kind,c.text,{fileAction:c.fileAction,checkKind:c.checkKind,checkStatus:c.checkStatus,status:c.kind==="test"?c.checkStatus==="passed"?"completed":c.checkStatus==="failed"?"blocked":c.checkStatus==="running"?"in_progress":"pending":void 0,confidence:c.confidence}));if(i.type==="decision"){let c=[];ee(i.data,c);for(let u of c)s(A(t,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];ee(i.data,c);for(let u of c)s(A(t,i,"task",u,{status:He(u),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let u=i.data[c];typeof u=="string"&&u&&s(A(t,i,"file",u,{fileAction:"modified",confidence:1}))}if(i.type==="test"){let c=[];ee(i.data,c);for(let u of c)s(A(t,i,"test",u,{confidence:1}))}let a=[];ee(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let m of yc(t,i,u))s(m)}let o=e[e.length-1];return s(A(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function Jr(t){return String(t).padStart(12,"0")}var Ue=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.sequence)),s=Math.max(...n.map(u=>u.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
|
|
138
|
-
`,a=w(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Jr(r)}-${Jr(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Hr}from"node:path";import{mkdirSync as hc}from"node:fs";function Ur(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Ur(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Sc(t,e=20){let n=new Map;for(let r of t){let s=`${r.kind}|${Ur(r.command)}`;n.delete(s),n.set(s,r)}return Array.from(n.values()).slice(-e)}function kc(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function Gr(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&kc(e)?t.title:e.text;return{id:t?.id??w(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function wc(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}async function Ye(t,e){let r=(await wc(t,e)).flatMap(f=>f.observations).sort((f,b)=>{let V=f.occurredAt.localeCompare(b.occurredAt);if(V!==0)return V;let Ht=f.sequence-b.sequence;return Ht!==0?Ht:f.id.localeCompare(b.id)}),s=new Map,o=new Map,i,a,c,u,m,p=[],d=[],l=[],g=[],h=[],y=new Map,S=[],k=[],
|
|
138
|
+
`,a=w(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Jr(r)}-${Jr(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Hr}from"node:path";import{mkdirSync as hc}from"node:fs";function Ur(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Ur(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Sc(t,e=20){let n=new Map;for(let r of t){let s=`${r.kind}|${Ur(r.command)}`;n.delete(s),n.set(s,r)}return Array.from(n.values()).slice(-e)}function kc(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function Gr(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&kc(e)?t.title:e.text;return{id:t?.id??w(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function wc(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}async function Ye(t,e){let r=(await wc(t,e)).flatMap(f=>f.observations).sort((f,b)=>{let V=f.occurredAt.localeCompare(b.occurredAt);if(V!==0)return V;let Ht=f.sequence-b.sequence;return Ht!==0?Ht:f.id.localeCompare(b.id)}),s=new Map,o=new Map,i,a,c,u,m,p=[],d=[],l=[],g=[],h=[],y=new Map,S=[],k=[],I=[],M=[],P=[],E=[];for(let f of r)switch(f.kind){case"request":i=f.text;break;case"activity":a=f.text;break;case"goal":c=f.text;break;case"plan":u=f.text;break;case"phase":s.set(f.key,Gr(s.get(f.key),f));break;case"task":o.set(f.key,Gr(o.get(f.key),f));break;case"decision":p.push(f.text);break;case"blocker":d.push(f.text);break;case"warning":l.push(f.text);break;case"next_action":g.push(f.text);break;case"file":{h.push(f.text);let b=f.fileAction??"active";y.delete(f.text),y.set(f.text,b),b==="modified"?S.push(f.text):b==="created"?k.push(f.text):b==="deleted"&&I.push(f.text);break}case"command":M.push(f.text);break;case"test":P.push(f.text),f.checkKind&&E.push({kind:f.checkKind,command:f.text,status:f.checkStatus??"unknown",updatedAt:f.occurredAt,agent:f.agent,nativeSessionId:f.nativeSessionId});break;case"session":m={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let x=Array.from(s.values()).sort((f,b)=>(f.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),v=Array.from(o.values()).sort((f,b)=>(f.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),D=x.find(f=>f.status==="in_progress")??x.find(f=>f.status==="blocked")??x.find(f=>f.status==="pending"),z=v.find(f=>f.status==="in_progress")??v.find(f=>f.status==="blocked")??v.find(f=>f.status==="pending"),at=F([...g,...z?[z.title]:[],...!z&&D?[D.title]:[],...v.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),ct=F([...d,...x.filter(f=>f.status==="blocked").map(f=>f.title),...v.filter(f=>f.status==="blocked").map(f=>f.title)],20),ie={version:1,projectId:t.id,projectName:t.name,currentRequest:i,currentActivity:a,goal:c,plan:u,phases:x,tasks:v,decisions:F(p,20),blockers:ct,warnings:F(l,20),nextActions:at,filesTouched:F(h,30),activeFiles:Array.from(y.entries()).filter(([,f])=>f!=="deleted").map(([f])=>f).slice(-5),modifiedFiles:F(S,30),createdFiles:F(k,30),deletedFiles:F(I,30),commands:F(M,20),tests:F(P,20),checks:Sc(E,20),currentPhase:D,currentTask:z,progress:{phasesTotal:x.length,phasesCompleted:x.filter(f=>f.status==="completed").length,tasksTotal:v.length,tasksCompleted:v.filter(f=>f.status==="completed").length,blocked:x.filter(f=>f.status==="blocked").length+v.filter(f=>f.status==="blocked").length},lastSession:m,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},ae=Hr(t.rootPath,".toolnet","work");return hc(ae,{recursive:!0}),T(Hr(ae,"current.json"),ie),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(ie,null,2)+`
|
|
139
139
|
`,"application/json"),ie}async function Yr(t,e){let n=await e.getText(`projects/${t.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Cc(t,e){if(!bc(t))return{events:[],nextOffset:e};let n=Ac(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=xc(t,"r");try{jc(i,o,0,s,r)}finally{vc(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
140
140
|
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
141
|
-
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Xe=class{constructor(e){this.options=e;this.journal=new Ue(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Cc(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=Ge(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Ye(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as _c,existsSync as Kc,openSync as $c,readSync as Fc,statSync as Wc}from"node:fs";var Pc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function oe(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Kt(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))Kt(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Pc.has(r)||["data","payload","parts","messages"].includes(r))&&Kt(s,e,n+1)}}function N(t,e,n,r,s,o=.95){let i=oe(r);return{version:1,id:w([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function W(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return oe(t.slice(r.length+1))}return null}function Ic(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Mc(t){return oe(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function Xr(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Kt(o.data,i);for(let a of i){let c={type:"project"},u=null;for(let m of a.split(/\r?\n/u)){let p=oe(m);if(!p){u=null;continue}let d=p.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let v=Number(d[1]);c={type:"phase",key:`phase:${v}`,order:v,title:oe(d[2]??"")},u=null;continue}let l=p.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let v=Number(l[1]);c={type:"task",key:`task:${v}`,order:v,title:oe(l[2]??"")},u=null;continue}let g=W(p,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(g){s(N(t,o,"mission",g,{type:"project"},.99)),u=null;continue}let h=W(p,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(N(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),u=null;continue}let y=W(p,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(N(t,o,c.type==="phase"?"phase_why":"why",y,c,.98)),u=null;continue}let S=W(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(S){s(N(t,o,"desired_outcome",S,{type:"project"},.98)),u=null;continue}let k=W(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(k){s(N(t,o,"plan_rationale",k,{type:"project"},.98)),u=null;continue}let
|
|
141
|
+
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var Xe=class{constructor(e){this.options=e;this.journal=new Ue(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Cc(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=Ge(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Ye(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as _c,existsSync as Kc,openSync as $c,readSync as Fc,statSync as Wc}from"node:fs";var Pc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function oe(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Kt(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))Kt(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Pc.has(r)||["data","payload","parts","messages"].includes(r))&&Kt(s,e,n+1)}}function N(t,e,n,r,s,o=.95){let i=oe(r);return{version:1,id:w([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function W(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return oe(t.slice(r.length+1))}return null}function Ic(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Mc(t){return oe(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function Xr(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Kt(o.data,i);for(let a of i){let c={type:"project"},u=null;for(let m of a.split(/\r?\n/u)){let p=oe(m);if(!p){u=null;continue}let d=p.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let v=Number(d[1]);c={type:"phase",key:`phase:${v}`,order:v,title:oe(d[2]??"")},u=null;continue}let l=p.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let v=Number(l[1]);c={type:"task",key:`task:${v}`,order:v,title:oe(l[2]??"")},u=null;continue}let g=W(p,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(g){s(N(t,o,"mission",g,{type:"project"},.99)),u=null;continue}let h=W(p,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(N(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),u=null;continue}let y=W(p,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(N(t,o,c.type==="phase"?"phase_why":"why",y,c,.98)),u=null;continue}let S=W(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(S){s(N(t,o,"desired_outcome",S,{type:"project"},.98)),u=null;continue}let k=W(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(k){s(N(t,o,"plan_rationale",k,{type:"project"},.98)),u=null;continue}let I=W(p,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(I){s(N(t,o,"phase_deliverable",I,c,.97)),u=null;continue}let M=W(p,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(M){s(N(t,o,"acceptance_criterion",M,c,.98)),u="acceptance_criterion";continue}let P=W(p,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(P){s(N(t,o,"dependency",P,c,.97)),u="dependency";continue}let E=W(p,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(E){s(N(t,o,"open_question",E,c,.95)),u="open_question";continue}let x=W(p,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(x){s(N(t,o,"constraint",x,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(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&&Ic(m)){s(N(t,o,u,Mc(m),c,.96));continue}u=null}}}return n}function Qr(t){return String(t).padStart(12,"0")}var Qe=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.evidence.sequence)),s=Math.max(...n.map(c=>c.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=w(n.map(c=>c.id).sort().join("|")).slice(0,16),a=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${Qr(r)}-${Qr(s)}-${i}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,JSON.stringify(o,null,2)+`
|
|
142
142
|
`,"application/json"),a}};import{mkdirSync as Ec}from"node:fs";import{join as Zr}from"node:path";function Tc(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Oc(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function J(t,e){return Oc(e,t)?e:t}function H(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function Rc(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(o.key);if(i)try{let a=JSON.parse(i);a.version===1&&Array.isArray(a.observations)&&s.push(a)}catch{}}return s}function Nc(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function es(t,e){let r=(await Rc(t,e)).flatMap(h=>h.observations).sort((h,y)=>{let S=h.evidence.occurredAt.localeCompare(y.evidence.occurredAt);return S!==0?S:h.evidence.sessionKey===y.evidence.sessionKey?h.evidence.sequence-y.evidence.sequence:h.id.localeCompare(y.id)}),s,o,i,a,c,u=new Map,m=[],p=[],d=[];for(let h of r){let y=Tc(h);if(h.scope==="phase"&&h.scopeKey){let S=u.get(h.scopeKey)??Nc(h);switch(h.kind){case"phase_objective":S.objective=J(S.objective,y);break;case"phase_why":S.why=J(S.why,y);break;case"phase_deliverable":S.deliverable=J(S.deliverable,y);break;case"acceptance_criterion":S.acceptanceCriteria.push(y);break;case"dependency":S.dependencies.push(y);break;case"open_question":S.openQuestions.push(y);break;case"constraint":S.constraints.push(y);break;case"note":S.notes.push(y);break}u.set(S.key,S);continue}switch(h.kind){case"mission":s=J(s,y);break;case"objective":o=J(o,y);break;case"why":i=J(i,y);break;case"desired_outcome":a=J(a,y);break;case"plan_rationale":c=J(c,y);break;case"open_question":m.push(y);break;case"constraint":p.push(y);break;case"note":d.push(y);break}}for(let h of u.values())h.acceptanceCriteria=H(h.acceptanceCriteria,20),h.dependencies=H(h.dependencies,15),h.openQuestions=H(h.openQuestions,15),h.constraints=H(h.constraints,15),h.notes=H(h.notes,20);let l={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:a,planRationale:c,phases:Array.from(u.values()).sort((h,y)=>h.order-y.order),openQuestions:H(m,20),constraints:H(p,20),notes:H(d,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},g=Zr(t.rootPath,".toolnet","work");return Ec(g,{recursive:!0}),T(Zr(g,"semantic-current.json"),l),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
|
|
143
143
|
`,"application/json"),l}function Lc(t,e){if(!Kc(t))return{events:[],nextOffset:e};let n=Wc(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=$c(t,"r");try{Fc(o,s,0,s.length,r)}finally{_c(o)}let i=s.toString("utf8"),a=i.lastIndexOf(`
|
|
144
144
|
`);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
|
|
145
|
-
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var Ze=class{constructor(e){this.options=e;this.journal=new Qe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Lc(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=Xr(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await es(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{existsSync as
|
|
145
|
+
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var Ze=class{constructor(e){this.options=e;this.journal=new Qe(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Lc(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=Xr(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await es(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{existsSync as uu,mkdirSync as lu}from"node:fs";import{join as Ft}from"node:path";import{existsSync as rs,mkdirSync as Dc,readFileSync as zc,statSync as ts,writeFileSync as qc}from"node:fs";import{dirname as Vc,join as Bc}from"node:path";var ns=64*1024,Jc=`# ToolNet Project Operating Manual
|
|
146
146
|
|
|
147
147
|
This file contains persistent instructions for AI agents working on this project.
|
|
148
148
|
|
|
@@ -186,14 +186,14 @@ Things an AI agent should always remember.
|
|
|
186
186
|
- [advisory] Prefer small focused files.
|
|
187
187
|
-->
|
|
188
188
|
`;function ss(t){return Bc(t.rootPath,".toolnet","PROJECT.md")}function Hc(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function Gc(t){let e=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=r.exec(t);){let o=s[1].toLowerCase(),i=Hc(s[2]);if(!i)continue;let a=`${o}:${i.toLowerCase()}`;n.has(a)||(n.add(a),e.push({id:w(a).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function Uc(t){let e=ss(t);return rs(e)||(Dc(Vc(e),{recursive:!0}),qc(e,Jc,{encoding:"utf8",mode:384})),e}function os(t,e=!1){let n=e?Uc(t):ss(t);if(!rs(n))return null;if(ts(n).size>ns)throw new Error(`PROJECT.md exceeds ${ns} bytes`);let s=zc(n,"utf8");return{path:n,content:s,digest:w(s),rules:Gc(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(ts(n).mtimeMs).toISOString()}}import{existsSync as Yc,mkdirSync as Xc,readFileSync as Qc,renameSync as Zc,writeFileSync as eu}from"node:fs";import{dirname as tu,join as nu}from"node:path";function ru(t,e){Xc(tu(t),{recursive:!0});let n=`${t}.tmp-${process.pid}-${Date.now()}`;eu(n,`${JSON.stringify(e,null,2)}
|
|
189
|
-
`,{encoding:"utf8",mode:384}),Zc(n,t)}function ds(t){return nu(t.rootPath,".toolnet","work","current.json")}function $t(t){let e=ds(t);if(!Yc(e))return null;try{let n=JSON.parse(Qc(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function et(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function _(t,e,n){let r=[],s=new Set;for(let o of[...t,...e].reverse()){let i=et(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function su(t,e,n=20){let r=new Map;for(let s of[...t,...e]){let o=`${s.kind}|${et(s.command)}`;r.delete(o),r.set(o,s)}return Array.from(r.values()).slice(-n)}function ou(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function is(t,e){let n=e.status??t?.status??"pending",r=n;t?.status==="completed"&&n!=="completed"&&(r="completed"),t&&n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status);let s=t&&ou(e)?t.title:e.text;return{id:t?.id??e.id,title:s,status:r,order:e.order??t?.order,confidence:Math.max(t?.confidence??0,e.confidence),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}function as(t){let e=new Map;for(let n of t){let r=n.order!==void 0?`order:${n.order}`:et(n.title);e.set(r,n)}return e}function cs(t){return t.order!==void 0?`order:${t.order}`:et(t.key||t.text)}function us(t){return Array.from(t).sort((e,n)=>{let r=e.order??Number.MAX_SAFE_INTEGER,s=n.order??Number.MAX_SAFE_INTEGER;return r!==s?r-s:e.updatedAt.localeCompare(n.updatedAt)})}function ls(t){return t.find(e=>e.status==="in_progress")??t.find(e=>e.status==="blocked")??t.find(e=>e.status==="pending")}function ps(t,e){let n=$t(t),r=as(n?.phases??[]),s=as(n?.tasks??[]),o=n?.currentRequest,i=n?.currentActivity,a=n?.goal,c=n?.plan,u=n?.lastSession,m=[],p=[],d=[],l=[],g=[],h=[...n?.activeFiles??[]],y=[],S=[],k=[],
|
|
190
|
-
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function au(t){return w(JSON.stringify(t))}function fs(t){let{project:e,identity:n,state:r}=t,s=r.activeFiles?.at(-1)??r.filesTouched.at(-1),o=r.phases.filter(k=>k.status==="completed").map(k=>k.title),i=r.tasks.filter(k=>k.status==="completed").map(k=>k.title),a=r.phases.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),c=r.tasks.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),u=new Set(r.tasks.filter(k=>k.status==="completed").map(k=>k.title.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),m=
|
|
189
|
+
`,{encoding:"utf8",mode:384}),Zc(n,t)}function ds(t){return nu(t.rootPath,".toolnet","work","current.json")}function $t(t){let e=ds(t);if(!Yc(e))return null;try{let n=JSON.parse(Qc(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function et(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function _(t,e,n){let r=[],s=new Set;for(let o of[...t,...e].reverse()){let i=et(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function su(t,e,n=20){let r=new Map;for(let s of[...t,...e]){let o=`${s.kind}|${et(s.command)}`;r.delete(o),r.set(o,s)}return Array.from(r.values()).slice(-n)}function ou(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function is(t,e){let n=e.status??t?.status??"pending",r=n;t?.status==="completed"&&n!=="completed"&&(r="completed"),t&&n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status);let s=t&&ou(e)?t.title:e.text;return{id:t?.id??e.id,title:s,status:r,order:e.order??t?.order,confidence:Math.max(t?.confidence??0,e.confidence),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}function as(t){let e=new Map;for(let n of t){let r=n.order!==void 0?`order:${n.order}`:et(n.title);e.set(r,n)}return e}function cs(t){return t.order!==void 0?`order:${t.order}`:et(t.key||t.text)}function us(t){return Array.from(t).sort((e,n)=>{let r=e.order??Number.MAX_SAFE_INTEGER,s=n.order??Number.MAX_SAFE_INTEGER;return r!==s?r-s:e.updatedAt.localeCompare(n.updatedAt)})}function ls(t){return t.find(e=>e.status==="in_progress")??t.find(e=>e.status==="blocked")??t.find(e=>e.status==="pending")}function ps(t,e){let n=$t(t),r=as(n?.phases??[]),s=as(n?.tasks??[]),o=n?.currentRequest,i=n?.currentActivity,a=n?.goal,c=n?.plan,u=n?.lastSession,m=[],p=[],d=[],l=[],g=[],h=[...n?.activeFiles??[]],y=[],S=[],k=[],I=[],M=[],P=[],E=[...e].sort((f,b)=>{let V=f.occurredAt.localeCompare(b.occurredAt);return V!==0?V:f.sequence-b.sequence});for(let f of E)switch(f.kind){case"request":o=f.text;break;case"activity":i=f.text;break;case"goal":a=f.text;break;case"plan":c=f.text;break;case"phase":{let b=cs(f);r.set(b,is(r.get(b),f));break}case"task":{let b=cs(f);s.set(b,is(s.get(b),f));break}case"decision":m.push(f.text);break;case"blocker":p.push(f.text);break;case"warning":d.push(f.text);break;case"next_action":l.push(f.text);break;case"file":{g.push(f.text);let b=f.fileAction??"active",V=h.indexOf(f.text);V>=0&&h.splice(V,1),b!=="deleted"&&h.push(f.text),b==="modified"?y.push(f.text):b==="created"?S.push(f.text):b==="deleted"&&k.push(f.text);break}case"command":I.push(f.text);break;case"test":M.push(f.text),f.checkKind&&P.push({kind:f.checkKind,command:f.text,status:f.checkStatus??"unknown",updatedAt:f.occurredAt,agent:f.agent,nativeSessionId:f.nativeSessionId});break;case"session":u={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let x=us(r.values()),v=us(s.values()),D=ls(x),z=ls(v),at=_(n?.nextActions??[],[...l,...z?[z.title]:[],...!z&&D?[D.title]:[],...v.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),ct=_(n?.blockers??[],[...p,...x.filter(f=>f.status==="blocked").map(f=>f.title),...v.filter(f=>f.status==="blocked").map(f=>f.title)],20),ie=E.length>0?E[E.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),ae={version:1,projectId:t.id,projectName:t.name,currentRequest:o,currentActivity:i,goal:a,plan:c,phases:x,tasks:v,decisions:_(n?.decisions??[],m,20),blockers:ct,warnings:_(n?.warnings??[],d,20),nextActions:at,filesTouched:_(n?.filesTouched??[],g,30),activeFiles:_([],h,5),modifiedFiles:_(n?.modifiedFiles??[],y,30),createdFiles:_(n?.createdFiles??[],S,30),deletedFiles:_(n?.deletedFiles??[],k,30),commands:_(n?.commands??[],I,20),tests:_(n?.tests??[],M,20),checks:su(n?.checks??[],P,20),currentPhase:D,currentTask:z,progress:{phasesTotal:x.length,phasesCompleted:x.filter(f=>f.status==="completed").length,tasksTotal:v.length,tasksCompleted:v.filter(f=>f.status==="completed").length,blocked:x.filter(f=>f.status==="blocked").length+v.filter(f=>f.status==="blocked").length},lastSession:u,updatedAt:ie};return ru(ds(t),ae),ae}function C(t,e){let n=new Set,r=[];for(let s of t){let o=s.replace(/\s+/g," ").trim();if(!o)continue;let i=o.normalize("NFKC").toLowerCase();if(!n.has(i)&&(n.add(i),r.push(o),r.length>=e))break}return r}function ms(t){if(t)return{id:t.id,title:t.title,status:t.status}}function iu(t,e=[]){let n=e.slice(-10);if(n.some(s=>s.status==="failed"))return"failing";if(n.some(s=>s.status==="passed"))return"passing";let r=t.slice(-10).join(`
|
|
190
|
+
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function au(t){return w(JSON.stringify(t))}function cu(t){let e=[];for(let n of t){if(!n)continue;let r=n.match(/https?:\/\/[^\s<>"'`)\]}]+/giu)??[];for(let s of r){let o=s.replace(/[.,;:!?]+$/gu,"").trim();o&&e.push(o)}}return C(e,30)}function fs(t){let{project:e,identity:n,state:r}=t,s=r.activeFiles?.at(-1)??r.filesTouched.at(-1),o=r.phases.filter(k=>k.status==="completed").map(k=>k.title),i=r.tasks.filter(k=>k.status==="completed").map(k=>k.title),a=r.phases.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),c=r.tasks.filter(k=>k.status!=="completed"&&k.status!=="cancelled").map(k=>k.title),u=new Set(r.tasks.filter(k=>k.status==="completed").map(k=>k.title.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),m=C(r.nextActions.filter(k=>!u.has(k.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),10),p=C([...c,...m],15),d=C(r.tests.slice().reverse(),10),l=C([...(r.activeFiles??[]).slice().reverse(),...r.filesTouched.slice().reverse()],20),g={schema:"toolnet.handoff.v2",version:2,project:{id:e.id,name:e.name},source:{agent:n.agent,nativeSessionId:n.nativeSessionId,sessionKey:n.sessionKey,sequence:t.sequence,reason:t.reason},capturedAt:t.capturedAt??new Date().toISOString(),goal:r.goal,request:r.currentRequest,activity:r.currentActivity,current:{phase:ms(r.currentPhase),task:ms(r.currentTask),file:s},completed:{phases:C(o,20),tasks:C(i,30)},remaining:{phases:C(a,20),tasks:C(c,30),todos:p},nextAction:m[0],blockers:C(r.blockers.slice().reverse(),10),decisions:C(r.decisions.slice().reverse(),10),files:{current:s,recent:l,active:C(r.activeFiles??[],10),modified:C(r.modifiedFiles??[],20),created:C(r.createdFiles??[],20),deleted:C(r.deletedFiles??[],20)},tests:{status:iu(r.tests,r.checks),recent:d,checks:(r.checks??[]).slice(-10).map(k=>({kind:k.kind,status:k.status,command:k.command}))},evidence:{commands:C((r.commands??[]).slice().reverse(),20),references:cu([r.currentRequest,r.currentActivity,r.goal,r.plan,...r.decisions,...r.blockers,...r.warnings,...r.nextActions,...r.filesTouched,...r.commands??[],...r.tests,...(r.checks??[]).map(k=>k.command)])},attention:C(t.attention??[],20),progress:r.progress},{capturedAt:h,source:y,...S}=g;return{...g,stateDigest:au(S)}}function du(t){return!!(t.currentRequest||t.currentActivity||t.goal||t.plan||t.phases.length>0||t.tasks.length>0||t.nextActions.length>0||t.blockers.length>0||t.decisions.length>0||t.filesTouched.length>0)}function gs(t,e,n,r,s){if(!du(n))return null;let o=os(t,!1),a=[...o?o.rules.filter(p=>p.mode==="enforce").map(p=>p.text):[],...n.warnings].slice(0,20),c=fs({project:t,identity:e,state:n,reason:r,sequence:s,attention:a}),u=c.stateDigest;return{version:1,id:w([t.id,e.sessionKey,u].join("|")).slice(0,24),projectId:t.id,projectName:t.name,createdAt:new Date().toISOString(),reason:r,sourceSession:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,sequence:s},currentRequest:n.currentRequest,currentActivity:n.currentActivity,goal:n.goal,plan:n.plan,progress:n.progress,currentPhase:n.currentPhase,currentTask:n.currentTask,incompletePhases:n.phases.filter(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 ys(t,e){let n=Ft(t.rootPath,".toolnet","work","handoffs");lu(n,{recursive:!0});let r=Ft(n,`${e.id}.json`);uu(r)||T(r,e),T(Ft(t.rootPath,".toolnet","work","handoff-latest.json"),e)}function hs(t){let e=gs(t.project,t.identity,t.state,t.reason,t.sequence);return e?(ys(t.project,e),e):null}var tt=class{constructor(e){this.options=e}options;async capture(e,n){let r=$t(this.options.project);r||(r=await Yr(this.options.project,this.options.storage)),r||(r=await Ye(this.options.project,this.options.storage));let s=gs(this.options.project,this.options.identity,r,e,n);if(!s)return null;ys(this.options.project,s);let o=`projects/${this.options.project.id}/work/handoffs/${s.id}.json`;return await this.options.storage.exists(o)||await this.options.storage.put(o,JSON.stringify(s,null,2)+`
|
|
191
191
|
`,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(s,null,2)+`
|
|
192
|
-
`,"application/json"),s}};import{existsSync as
|
|
193
|
-
`)}function ws(t,e){let n=
|
|
192
|
+
`,"application/json"),s}};import{existsSync as pu,readFileSync as mu,writeFileSync as fu}from"node:fs";import{join as gu}from"node:path";var ks="<!-- TOOLNET:STABLE-WORK:BEGIN -->",Wt="<!-- TOOLNET:STABLE-WORK:END -->";function Lt(t){switch(t.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function L(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${n}`)]:[]}function Ss(t,e){return e.length?["",`${t}:`,...e.map(n=>`- ${Lt(n)} ${n.title}`)]:[]}function yu(t){let e=[ks,"# ToolNet Stable Work State","",`Updated: ${t.updatedAt}`];return t.lastSession&&e.push(`Last agent: ${t.lastSession.agent}`,`Last session: ${t.lastSession.nativeSessionId}`),t.currentRequest&&e.push("","Current request:",t.currentRequest),t.currentActivity&&e.push("","Current activity:",t.currentActivity),t.goal&&e.push("","Goal:",t.goal),t.plan&&e.push("","Plan:",t.plan),t.currentPhase&&e.push("","Current phase:",`${Lt(t.currentPhase)} ${t.currentPhase.title}`),t.currentTask&&e.push("","Current task:",`${Lt(t.currentTask)} ${t.currentTask.title}`),e.push(...Ss("Phases",t.phases)),e.push(...Ss("TODO / Tasks",t.tasks)),e.push(...L("Next actions",t.nextActions)),e.push(...L("Blockers",t.blockers)),e.push(...L("Important decisions",t.decisions)),e.push(...L("Active files",t.activeFiles??[])),e.push(...L("Modified files",t.modifiedFiles??[])),e.push(...L("Created files",t.createdFiles??[])),e.push(...L("Deleted files",t.deletedFiles??[])),e.push(...L("Files touched",t.filesTouched)),e.push(...L("Recent commands",t.commands??[])),e.push(...L("Checks",(t.checks??[]).map(n=>`[${n.status}] ${n.kind}: ${n.command}`))),e.push("","Progress:",`- Phases: ${t.progress.phasesCompleted}/${t.progress.phasesTotal}`,`- Tasks: ${t.progress.tasksCompleted}/${t.progress.tasksTotal}`,`- Blocked: ${t.progress.blocked}`,"","Continuation:","- Resume current unfinished task.","- Never redo completed TODO/Phase unless explicitly requested.","- Ask ToolNet Memory for deeper history only when necessary.",Wt),e.join(`
|
|
193
|
+
`)}function ws(t,e){let n=gu(t.rootPath,".toolnet","current.md"),r="";if(pu(n))try{r=mu(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let s=yu(e),o=r.indexOf(ks),i=r.indexOf(Wt),a;o>=0&&i>=o?a=[r.slice(0,o).trimEnd(),s,r.slice(i+Wt.length).trimStart()].filter(Boolean).join(`
|
|
194
194
|
|
|
195
195
|
`):a=r.trim()?`${r.trim()}
|
|
196
196
|
|
|
197
|
-
${s}`:s,
|
|
198
|
-
`,{encoding:"utf8",mode:384})}import{existsSync as vs,mkdirSync as yu,readFileSync as hu}from"node:fs";import{join as Dt}from"node:path";function bs(t){return Dt(t.rootPath,".toolnet","memory","checkpoints")}function xs(t){return Dt(bs(t),"latest.json")}function Su(t){let e=xs(t);if(!vs(e))return null;try{let n=JSON.parse(hu(e,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==t.id?null:n}catch{return null}}function ku(t){return["rule","architecture","decision","fix"].includes(t)}function wu(t,e){return e.length===0?[]:Fe(t,e).candidates.filter(r=>ku(r.kind)&&r.knowledgeClass!=="transient"&&r.importanceScore>=.65).map(r=>({fingerprint:r.fingerprint,kind:r.kind,content:r.content,knowledgeClass:r.knowledgeClass,importanceScore:r.importanceScore,confidence:r.confidence,createdAt:r.createdAt,agent:t.agent,nativeSessionId:t.nativeSessionId}))}function vu(t,e){let n=new Map;for(let r of[...t,...e]){let s=n.get(r.fingerprint);(!s||r.importanceScore>s.importanceScore)&&n.set(r.fingerprint,r)}return Array.from(n.values()).sort((r,s)=>s.importanceScore-r.importanceScore||s.createdAt.localeCompare(r.createdAt)).slice(0,80)}function bu(t){return{request:t.currentRequest,activity:t.currentActivity,goal:t.goal,phase:t.currentPhase?{title:t.currentPhase.title,status:t.currentPhase.status}:void 0,task:t.currentTask?{title:t.currentTask.title,status:t.currentTask.status}:void 0,phases:t.phases.map(e=>({title:e.title,status:e.status})),tasks:t.tasks.map(e=>({title:e.title,status:e.status})),activeFiles:t.activeFiles??[],modifiedFiles:t.modifiedFiles??[],createdFiles:t.createdFiles??[],deletedFiles:t.deletedFiles??[],checks:t.checks??[],blockers:t.blockers,decisions:t.decisions,nextActions:t.nextActions}}function js(t,e,n,r){let s=Su(t),o=vu(s?.durableFacts??[],wu(e,n)),i=n.at(-1)?.sequence??s?.source.sequence??0,a=r.phases.filter(y=>y.status==="completed").map(y=>y.title),c=r.tasks.filter(y=>y.status==="completed").map(y=>y.title),u=r.phases.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),m=r.tasks.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),p={work:bu(r),durableFacts:o.map(y=>y.fingerprint).sort()},d=w(JSON.stringify(p)).slice(0,32),l={schema:"toolnet.memory.checkpoint.v1",version:1,project:{id:t.id,name:t.name},source:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,sequence:i},capturedAt:new Date().toISOString(),request:r.currentRequest,activity:r.currentActivity,goal:r.goal,current:{phase:r.currentPhase,task:r.currentTask},completed:{phases:a,tasks:c},remaining:{phases:u,tasks:m},files:{active:r.activeFiles??[],modified:r.modifiedFiles??[],created:r.createdFiles??[],deleted:r.deletedFiles??[]},checks:r.checks??[],blockers:r.blockers.slice(-10),decisions:r.decisions.slice(-15),nextActions:r.nextActions.slice(0,10),durableFacts:o,stateDigest:d},g=bs(t);yu(g,{recursive:!0,mode:448});let h=Dt(g,`${d}.json`);return vs(h)||T(h,l),T(xs(t),l),l}function nt(t,e,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=Ge(e,n);if(r.length===0)return{updated:!1,observations:0};let s=ps(t,r);ws(t,s),Dn(t,{agent:e.agent,nativeSessionId:e.nativeSessionId,observations:r,workState:s});try{js(t,e,n,s)}catch{}try{hs({project:t,identity:e,state:s,reason:"continuous-checkpoint",sequence:n.at(-1)?.sequence??0})}catch{}return{updated:!0,observations:r.length}}var rt=class{identity;wal;remote;sanitizer=new U;learner;continuity;semantic;handoff;project;title;metadata;constructor(e){this.project=e.project,this.identity=_e(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new ne(this.identity,e.eventContext),this.remote=new Ke(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new Je({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new Xe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new Ze({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new tt({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}checkpointLocal(e){if(e.length!==0)try{nt(this.project,this.identity,e)}catch{}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){let n=this.wal.append([this.sanitizeEvent(e)]);return this.checkpointLocal(n),n[0]}recordMany(e){let n=this.wal.append(e.map(r=>this.sanitizeEvent(r)));return this.checkpointLocal(n),n}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};var st=4e3,zt=20,qt=30,As=4,Vt=20;function je(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function G(t){return typeof t=="string"&&t.trim()?t.trim():void 0}function ot(t,e=0){if(e>=As)return typeof t=="string"?t.length>st?`${t.slice(0,st)}\u2026`:t:Array.isArray(t)?`[array:${t.length}]`:je(t)?`[object:${Object.keys(t).length}]`:t;if(typeof t=="string")return t.length>st?`${t.slice(0,st)}\u2026`:t;if(Array.isArray(t)){let n=t.slice(0,zt).map(r=>ot(r,e+1));return t.length>zt&&n.push(`[+${t.length-zt} items]`),n}if(je(t)){let n={},r=Object.entries(t);for(let[s,o]of r.slice(0,qt))n[s]=ot(o,e+1);return r.length>qt&&(n.__truncatedKeys=r.length-qt),n}return t}function Jt(t,e,n=0){if(!(n>As||e.size>=Vt)){if(Array.isArray(t)){for(let r of t)if(Jt(r,e,n+1),e.size>=Vt)break;return}if(je(t))for(let[r,s]of Object.entries(t)){let o=r.toLowerCase().replace(/[^a-z]/g,"");if((o==="path"||o==="filepath"||o==="filename")&&typeof s=="string"&&s.trim()&&e.add(s.trim()),Jt(s,e,n+1),e.size>=Vt)break}}}function xu(t){let e=G(t);if(e)switch(e){case"agentSpawn":case"SessionStart":return"SessionStart";case"userPromptSubmit":case"UserPromptSubmit":return"UserPromptSubmit";case"postToolUse":case"PostToolUse":return"PostToolUse";case"preToolUse":case"PreToolUse":return"PreToolUse";case"stop":case"Stop":return"Stop";default:return e}}function Bt(t){try{return w(Ce(t)).slice(0,20)}catch{return w(String(t)).slice(0,20)}}function ju(t){let e=G(t.timestamp);if(e){let n=new Date(e);if(!Number.isNaN(n.getTime()))return n.toISOString()}return new Date().toISOString()}function Au(t,e){let n=(t??"").toLowerCase();return n==="read"||n==="fs_read"||n.includes("read_file")||n.includes("list_dir")||n.includes("grep")||n.includes("search")?null:e.length>0&&(n.includes("edit")||n.includes("patch")||n.includes("replace"))?"file_edit":e.length>0&&(n.includes("write")||n.includes("create")||n.includes("delete"))?"file_write":n.includes("bash")||n.includes("shell")||n.includes("command")||n.includes("execute")?"command":"tool_result"}function Cs(t,e){let n=xu(t.hook_event_name);if(!n)return[];let r=G(t.session_id)??"kiro",s=G(t.cwd)??e.rootPath,i={timestamp:ju(t),cwd:s,source:"kiro",provenance:{source:"kiro-hook"}};if(n==="SessionStart")return[{...i,type:"session_start",sourceEventId:`kiro:${r}:start`,data:{sessionId:r,cwd:s}}];if(n==="UserPromptSubmit"){let a=G(t.prompt)??G(process.env.USER_PROMPT)??"";return a?[{...i,type:"user_prompt",role:"user",sourceEventId:`kiro:${r}:prompt:${Bt(a)}`,data:{content:a}}]:[]}if(n==="PostToolUse"){let a=G(t.tool_name),c=je(t.tool_input)?t.tool_input:{},u=je(t.tool_response)?t.tool_response:{},m=new Set;Jt(c,m);let p=[...m],d=Au(a,p);if(!d)return[];let l=ot(c),g=ot(u),h=["kiro",r,"tool",Bt({toolName:a,input:l,response:g})].join(":");return[{...i,type:d,sourceEventId:h,data:{tool:a,input:l,response:g,files:p},provenance:{source:"kiro-hook",files:p.length>0?p:void 0}}]}if(n==="Stop"){let a=G(t.assistant_response),c=Bt({assistantResponse:a??"",sessionId:r}),u=[];return a&&u.push({...i,type:"assistant_message",role:"assistant",sourceEventId:`kiro:${r}:assistant:${c}`,data:{content:a}}),u.push({...i,type:"session_idle",sourceEventId:`kiro:${r}:idle:${c}`,data:{sessionId:r}}),u}return[]}function it(t){return typeof t=="string"&&t.trim()?t.trim():void 0}function Iu(t){switch(it(t)){case"agentSpawn":return"SessionStart";case"userPromptSubmit":return"UserPromptSubmit";case"postToolUse":return"PostToolUse";case"stop":return"Stop";default:return it(t)??""}}function Mu(t){let e=ht(t);if(!e||!Cu(Pu(e,".toolnet","project.json")))return null;try{return new Me().detect(e)}catch{return null}}function Eu(t,e,n,r){let s=Cs(r,t);if(s.length===0)return 0;let o=_e(t,"kiro",e),a=new ne(o,{source:"kiro",cwd:n}).append(s);return nt(t,o,a),a.length}async function Tu(t,e,n){let r=Pe(),s=$n(_n({provider:r.storage.provider,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),{attempts:2}),o=new Re(s,t.id,t.name,t.remote??t.name);await new rt({project:t,storage:o,agent:"kiro",nativeSessionId:e,metadata:{source:"kiro-hook"},eventContext:{source:"kiro",cwd:n}}).flush()}async function Ps(t,e={}){let n=it(t.cwd),r=it(t.session_id);if(!n||!r)return{active:!1,captured:0,flushed:!1};let s=Mu(n);if(!s)return{active:!1,captured:0,flushed:!1};let o=0;try{o=Eu(s,r,n,t)}catch(c){return{active:!0,projectRoot:s.rootPath,sessionId:r,captured:0,flushed:!1,error:c instanceof Error?c.message:String(c)}}let i=Iu(t.hook_event_name);if(i==="PostToolUse"||i==="Stop")try{qn(s)}catch{}if(i!=="Stop")return{active:!0,projectRoot:s.rootPath,sessionId:r,captured:o,flushed:!1};let a=e.flushSession??Tu;try{return await a(s,r,n),{active:!0,projectRoot:s.rootPath,sessionId:r,captured:o,flushed:!0}}catch(c){return{active:!0,projectRoot:s.rootPath,sessionId:r,captured:o,flushed:!1,error:c instanceof Error?c.message:String(c)}}}async function Ou(){let t="";for await(let e of process.stdin)t+=e.toString();if(!t.trim())return{};try{return JSON.parse(t)}catch{return{}}}async function Ru(){let t=await Ou(),e=t.hook_event_name;if(An(e)){let n=jn(t);if(n.blocked){process.stderr.write(`${n.reason??"ToolNet continuity guard blocked this tool."}
|
|
199
|
-
`),process.exitCode=2;return}return}if(await Ps(t),Cn(e)){let n=typeof t.cwd=="string"?t.cwd:"",r=wt(n);r&&process.stdout.write(r);return}if(Pn(e)){let n=xn(t);n&&process.stdout.write(n)}}
|
|
197
|
+
${s}`:s,fu(n,`${a.trim()}
|
|
198
|
+
`,{encoding:"utf8",mode:384})}import{existsSync as vs,mkdirSync as hu,readFileSync as Su}from"node:fs";import{join as Dt}from"node:path";function bs(t){return Dt(t.rootPath,".toolnet","memory","checkpoints")}function xs(t){return Dt(bs(t),"latest.json")}function ku(t){let e=xs(t);if(!vs(e))return null;try{let n=JSON.parse(Su(e,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==t.id?null:n}catch{return null}}function wu(t){return["rule","architecture","decision","fix"].includes(t)}function vu(t,e){return e.length===0?[]:Fe(t,e).candidates.filter(r=>wu(r.kind)&&r.knowledgeClass!=="transient"&&r.importanceScore>=.65).map(r=>({fingerprint:r.fingerprint,kind:r.kind,content:r.content,knowledgeClass:r.knowledgeClass,importanceScore:r.importanceScore,confidence:r.confidence,createdAt:r.createdAt,agent:t.agent,nativeSessionId:t.nativeSessionId}))}function bu(t,e){let n=new Map;for(let r of[...t,...e]){let s=n.get(r.fingerprint);(!s||r.importanceScore>s.importanceScore)&&n.set(r.fingerprint,r)}return Array.from(n.values()).sort((r,s)=>s.importanceScore-r.importanceScore||s.createdAt.localeCompare(r.createdAt)).slice(0,80)}function xu(t){return{request:t.currentRequest,activity:t.currentActivity,goal:t.goal,phase:t.currentPhase?{title:t.currentPhase.title,status:t.currentPhase.status}:void 0,task:t.currentTask?{title:t.currentTask.title,status:t.currentTask.status}:void 0,phases:t.phases.map(e=>({title:e.title,status:e.status})),tasks:t.tasks.map(e=>({title:e.title,status:e.status})),activeFiles:t.activeFiles??[],modifiedFiles:t.modifiedFiles??[],createdFiles:t.createdFiles??[],deletedFiles:t.deletedFiles??[],checks:t.checks??[],blockers:t.blockers,decisions:t.decisions,nextActions:t.nextActions}}function js(t,e,n,r){let s=ku(t),o=bu(s?.durableFacts??[],vu(e,n)),i=n.at(-1)?.sequence??s?.source.sequence??0,a=r.phases.filter(y=>y.status==="completed").map(y=>y.title),c=r.tasks.filter(y=>y.status==="completed").map(y=>y.title),u=r.phases.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),m=r.tasks.filter(y=>y.status!=="completed"&&y.status!=="cancelled").map(y=>y.title),p={work:xu(r),durableFacts:o.map(y=>y.fingerprint).sort()},d=w(JSON.stringify(p)).slice(0,32),l={schema:"toolnet.memory.checkpoint.v1",version:1,project:{id:t.id,name:t.name},source:{agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,sequence:i},capturedAt:new Date().toISOString(),request:r.currentRequest,activity:r.currentActivity,goal:r.goal,current:{phase:r.currentPhase,task:r.currentTask},completed:{phases:a,tasks:c},remaining:{phases:u,tasks:m},files:{active:r.activeFiles??[],modified:r.modifiedFiles??[],created:r.createdFiles??[],deleted:r.deletedFiles??[]},checks:r.checks??[],blockers:r.blockers.slice(-10),decisions:r.decisions.slice(-15),nextActions:r.nextActions.slice(0,10),durableFacts:o,stateDigest:d},g=bs(t);hu(g,{recursive:!0,mode:448});let h=Dt(g,`${d}.json`);return vs(h)||T(h,l),T(xs(t),l),l}function nt(t,e,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=Ge(e,n);if(r.length===0)return{updated:!1,observations:0};let s=ps(t,r);ws(t,s),Dn(t,{agent:e.agent,nativeSessionId:e.nativeSessionId,observations:r,workState:s});try{js(t,e,n,s)}catch{}try{hs({project:t,identity:e,state:s,reason:"continuous-checkpoint",sequence:n.at(-1)?.sequence??0})}catch{}return{updated:!0,observations:r.length}}var rt=class{identity;wal;remote;sanitizer=new U;learner;continuity;semantic;handoff;project;title;metadata;constructor(e){this.project=e.project,this.identity=_e(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new ne(this.identity,e.eventContext),this.remote=new Ke(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new Je({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new Xe({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new Ze({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new tt({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}checkpointLocal(e){if(e.length!==0)try{nt(this.project,this.identity,e)}catch{}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){let n=this.wal.append([this.sanitizeEvent(e)]);return this.checkpointLocal(n),n[0]}recordMany(e){let n=this.wal.append(e.map(r=>this.sanitizeEvent(r)));return this.checkpointLocal(n),n}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};var st=4e3,zt=20,qt=30,As=4,Vt=20;function je(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function G(t){return typeof t=="string"&&t.trim()?t.trim():void 0}function ot(t,e=0){if(e>=As)return typeof t=="string"?t.length>st?`${t.slice(0,st)}\u2026`:t:Array.isArray(t)?`[array:${t.length}]`:je(t)?`[object:${Object.keys(t).length}]`:t;if(typeof t=="string")return t.length>st?`${t.slice(0,st)}\u2026`:t;if(Array.isArray(t)){let n=t.slice(0,zt).map(r=>ot(r,e+1));return t.length>zt&&n.push(`[+${t.length-zt} items]`),n}if(je(t)){let n={},r=Object.entries(t);for(let[s,o]of r.slice(0,qt))n[s]=ot(o,e+1);return r.length>qt&&(n.__truncatedKeys=r.length-qt),n}return t}function Jt(t,e,n=0){if(!(n>As||e.size>=Vt)){if(Array.isArray(t)){for(let r of t)if(Jt(r,e,n+1),e.size>=Vt)break;return}if(je(t))for(let[r,s]of Object.entries(t)){let o=r.toLowerCase().replace(/[^a-z]/g,"");if((o==="path"||o==="filepath"||o==="filename")&&typeof s=="string"&&s.trim()&&e.add(s.trim()),Jt(s,e,n+1),e.size>=Vt)break}}}function ju(t){let e=G(t);if(e)switch(e){case"agentSpawn":case"SessionStart":return"SessionStart";case"userPromptSubmit":case"UserPromptSubmit":return"UserPromptSubmit";case"postToolUse":case"PostToolUse":return"PostToolUse";case"preToolUse":case"PreToolUse":return"PreToolUse";case"stop":case"Stop":return"Stop";default:return e}}function Bt(t){try{return w(Ce(t)).slice(0,20)}catch{return w(String(t)).slice(0,20)}}function Au(t){let e=G(t.timestamp);if(e){let n=new Date(e);if(!Number.isNaN(n.getTime()))return n.toISOString()}return new Date().toISOString()}function Cu(t,e){let n=(t??"").toLowerCase();return n==="read"||n==="fs_read"||n.includes("read_file")||n.includes("list_dir")||n.includes("grep")||n.includes("search")?null:e.length>0&&(n.includes("edit")||n.includes("patch")||n.includes("replace"))?"file_edit":e.length>0&&(n.includes("write")||n.includes("create")||n.includes("delete"))?"file_write":n.includes("bash")||n.includes("shell")||n.includes("command")||n.includes("execute")?"command":"tool_result"}function Cs(t,e){let n=ju(t.hook_event_name);if(!n)return[];let r=G(t.session_id)??"kiro",s=G(t.cwd)??e.rootPath,i={timestamp:Au(t),cwd:s,source:"kiro",provenance:{source:"kiro-hook"}};if(n==="SessionStart")return[{...i,type:"session_start",sourceEventId:`kiro:${r}:start`,data:{sessionId:r,cwd:s}}];if(n==="UserPromptSubmit"){let a=G(t.prompt)??G(process.env.USER_PROMPT)??"";return a?[{...i,type:"user_prompt",role:"user",sourceEventId:`kiro:${r}:prompt:${Bt(a)}`,data:{content:a}}]:[]}if(n==="PostToolUse"){let a=G(t.tool_name),c=je(t.tool_input)?t.tool_input:{},u=je(t.tool_response)?t.tool_response:{},m=new Set;Jt(c,m);let p=[...m],d=Cu(a,p);if(!d)return[];let l=ot(c),g=ot(u),h=["kiro",r,"tool",Bt({toolName:a,input:l,response:g})].join(":");return[{...i,type:d,sourceEventId:h,data:{tool:a,input:l,response:g,files:p},provenance:{source:"kiro-hook",files:p.length>0?p:void 0}}]}if(n==="Stop"){let a=G(t.assistant_response),c=Bt({assistantResponse:a??"",sessionId:r}),u=[];return a&&u.push({...i,type:"assistant_message",role:"assistant",sourceEventId:`kiro:${r}:assistant:${c}`,data:{content:a}}),u.push({...i,type:"session_idle",sourceEventId:`kiro:${r}:idle:${c}`,data:{sessionId:r}}),u}return[]}function it(t){return typeof t=="string"&&t.trim()?t.trim():void 0}function Mu(t){switch(it(t)){case"agentSpawn":return"SessionStart";case"userPromptSubmit":return"UserPromptSubmit";case"postToolUse":return"PostToolUse";case"stop":return"Stop";default:return it(t)??""}}function Eu(t){let e=ht(t);if(!e||!Pu(Iu(e,".toolnet","project.json")))return null;try{return new Me().detect(e)}catch{return null}}function Tu(t,e,n,r){let s=Cs(r,t);if(s.length===0)return 0;let o=_e(t,"kiro",e),a=new ne(o,{source:"kiro",cwd:n}).append(s);return nt(t,o,a),a.length}async function Ou(t,e,n){let r=Pe(),s=$n(_n({provider:r.storage.provider,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),{attempts:2}),o=new Re(s,t.id,t.name,t.remote??t.name);await new rt({project:t,storage:o,agent:"kiro",nativeSessionId:e,metadata:{source:"kiro-hook"},eventContext:{source:"kiro",cwd:n}}).flush()}async function Ps(t,e={}){let n=it(t.cwd),r=it(t.session_id);if(!n||!r)return{active:!1,captured:0,flushed:!1};let s=Eu(n);if(!s)return{active:!1,captured:0,flushed:!1};let o=0;try{o=Tu(s,r,n,t)}catch(c){return{active:!0,projectRoot:s.rootPath,sessionId:r,captured:0,flushed:!1,error:c instanceof Error?c.message:String(c)}}let i=Mu(t.hook_event_name);if(i==="PostToolUse"||i==="Stop")try{qn(s)}catch{}if(i!=="Stop")return{active:!0,projectRoot:s.rootPath,sessionId:r,captured:o,flushed:!1};let a=e.flushSession??Ou;try{return await a(s,r,n),{active:!0,projectRoot:s.rootPath,sessionId:r,captured:o,flushed:!0}}catch(c){return{active:!0,projectRoot:s.rootPath,sessionId:r,captured:o,flushed:!1,error:c instanceof Error?c.message:String(c)}}}async function Ru(){let t="";for await(let e of process.stdin)t+=e.toString();if(!t.trim())return{};try{return JSON.parse(t)}catch{return{}}}async function Nu(){let t=await Ru(),e=t.hook_event_name;if(An(e)){let n=jn(t);if(n.blocked){process.stderr.write(`${n.reason??"ToolNet continuity guard blocked this tool."}
|
|
199
|
+
`),process.exitCode=2;return}return}if(await Ps(t),Cn(e)){let n=typeof t.cwd=="string"?t.cwd:"",r=wt(n);r&&process.stdout.write(r);return}if(Pn(e)){let n=xn(t);n&&process.stdout.write(n)}}Nu().catch(()=>{process.exitCode=0});
|