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