toolnet-memory 0.3.10 → 0.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +432 -163
- package/bin/toolnet-memory +5 -0
- package/bundle/agy-hook.js +38 -38
- package/bundle/agy.js +23 -23
- package/bundle/api.js +19 -16
- package/bundle/auto-integrate.js +84 -31
- package/bundle/claude-hook.js +9 -9
- package/bundle/codex.js +28 -28
- package/bundle/context-runtime.js +4 -4
- package/bundle/context.js +12 -12
- package/bundle/continuity-certify.js +16 -13
- package/bundle/copilot-hook.js +66 -66
- package/bundle/copilot.js +23 -27
- package/bundle/cursor-hook.js +66 -66
- package/bundle/cursor.js +24 -27
- package/bundle/grok-hook.js +46 -46
- package/bundle/grok.js +6 -7
- package/bundle/help-cli.js +4 -4
- package/bundle/init.js +92 -39
- package/bundle/integration-status.js +55 -0
- package/bundle/kiro-hook.js +14 -14
- package/bundle/mcp.js +21 -18
- package/bundle/opencode.js +27 -27
- package/bundle/setup.js +90 -37
- package/bundle/status-cli.js +4 -4
- package/package.json +12 -2
package/bundle/cursor-hook.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import*as
|
|
2
|
-
`),a=Math.max(o,i);return a>r*.7?s.slice(0,a+1):s}function
|
|
1
|
+
import*as F from"fs";import*as N from"path";function dt(e){return e?Math.ceil(e.length/3.5):0}function pt(e,t){if(!e)return"";if(dt(e)<=t)return e;let r=Math.floor(t*3.5),s=e.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
|
|
2
|
+
`),a=Math.max(o,i);return a>r*.7?s.slice(0,a+1):s}function Xt(e,t){if(!e)return"";let n=e.split(`
|
|
3
3
|
`).filter(o=>o.trim());if(n.length<=t)return e;let r=n.slice(0,t),s=n.length-t;return[...r,`... (${s} more items omitted)`].join(`
|
|
4
|
-
`)}function
|
|
4
|
+
`)}function Fs(e,t){let{maxTokens:n,trimMarker:r="[Context trimmed by ToolNet Memory token budget]"}=t;if(e.length===0)return"";let s=[...e].sort((c,u)=>u.priority-c.priority),o=[],i=0,a=!1;for(let c of s){let u=`# ${c.title}
|
|
5
5
|
|
|
6
|
-
`,m=
|
|
6
|
+
`,m=dt(u),p=dt(c.content),d=m+p;if(i+d<=n)o.push(u+c.content),i+=d;else{let l=n-i-m;if(l>50){let g=pt(c.content,l);o.push(u+g),i=n,a=!0}else a=!0;break}}return a&&o.push(`
|
|
7
7
|
${r}
|
|
8
8
|
`),o.join(`
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
`)}function
|
|
13
|
-
`)}function
|
|
14
|
-
`;
|
|
12
|
+
`)}function Qt(e,t){let n=[{title:"Profile",content:Xt(e,10),priority:100},{title:"Current Work",content:Xt(t,15),priority:90}];return Fs(n,{maxTokens:800})}import{createHash as Ws}from"node:crypto";import{chmodSync as en,existsSync as Ls,mkdirSync as Ds,readFileSync as zs,renameSync as qs,writeFileSync as tn}from"node:fs";import{dirname as nn,join as Ce}from"node:path";var gt="toolnet.context-offload.v1",Hs="toolnet.context-offload-asset.v1",Js=256,Vs=new Set(["tool_call","tool_result","file_read","file_write","file_edit","command","test","artifact"]);function rn(e){return Ce(e,".toolnet","offload")}function Bs(e){return Ce(rn(e),"assets")}function sn(e){return Ce(rn(e),"graph.json")}function on(e){Ds(e,{recursive:!0,mode:448});try{en(e,448)}catch{}}function Gs(e,t){on(nn(e));let n=`${e}.${process.pid}.${Date.now()}.tmp`;tn(n,t,{encoding:"utf8",mode:384}),qs(n,e);try{en(e,384)}catch{}}function ft(e){return Array.isArray(e)?e.map(ft):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,ft(n)])):e}function Us(e){return Ws("sha256").update(JSON.stringify(ft(e)),"utf8").digest("hex")}function mt(){return{schema:gt,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function an(e){let t=sn(e);if(!Ls(t))return mt();try{let n=JSON.parse(zs(t,"utf8"));return n.schema!==gt||n.version!==1||!Array.isArray(n.nodes)?mt():n}catch{return mt()}}function Ys(e,t){Gs(sn(e),JSON.stringify(t,null,2)+`
|
|
13
|
+
`)}function Xs(e,t=260){if(typeof e!="string")return null;let n=e.replace(/\s+/gu," ").trim();return n?n.slice(0,t):null}function Qs(e){let t=[...e.provenance.files??[],e.provenance.sourcePath],n=[];for(let r of t){let s=Xs(r);if(!(!s||n.includes(s))&&(n.push(s),n.length===3))break}return n}function Zs(e){return`${e.agent}:${e.sourceEventId??e.id}`.replace(/\s+/gu," ").trim().slice(0,120)}function eo(e,t){on(nn(e));try{return tn(e,t,{encoding:"utf8",flag:"wx",mode:384}),!0}catch(n){if(n.code==="EEXIST")return!1;throw n}}function to(e,t){let n=e.nodes.find(s=>s.id===t.id),r=n?{...n,kind:t.kind,bytes:t.bytes,sourceRefs:Array.from(new Set([...n.sourceRefs,...t.sourceRefs])).slice(-8),files:Array.from(new Set([...n.files,...t.files])).slice(0,6)}:t;return{schema:gt,version:1,updatedAt:new Date().toISOString(),nodes:[...e.nodes.filter(s=>s.id!==t.id),r].slice(-Js)}}function cn(e,t){let n=an(e),r=0,s=0,o=0,i=[];for(let a of t){if(!Vs.has(a.type))continue;r+=1;let c=Us({type:a.type,data:a.data}),u={schema:Hs,version:1,assetId:c,event:{type:a.type,agent:a.agent,nativeSessionId:a.nativeSessionId,timestamp:a.timestamp,sourceEventId:a.sourceEventId,provenance:a.provenance,data:a.data}},m=JSON.stringify(u,null,2)+`
|
|
14
|
+
`;eo(Ce(Bs(e),`${c}.json`),m)?s+=1:o+=1,i.push(c),n=to(n,{id:c,kind:a.type,bytes:Buffer.byteLength(m,"utf8"),createdAt:a.timestamp,sourceRefs:[Zs(a)],files:Qs(a)})}return r>0&&Ys(e,n),{eligible:r,written:s,deduped:o,graphNodes:n.nodes.length,assetIds:i}}function Zt(e,t){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:n.slice(0,t-1).trimEnd()+"\u2026"}function un(e,t={}){let n=an(e);if(n.nodes.length===0)return"";let r=Math.max(1,Math.min(12,t.maxAssets??6)),s=Math.max(320,Math.min(2400,t.maxChars??900)),o=["[TOOLNET CONTEXT OFFLOAD GRAPH]","Large tool/file payloads stay outside prompt context.","Read only a needed asset with MCP context_offload_read."];for(let i of n.nodes.slice(-r).reverse()){let a=Zt(i.sourceRefs.at(-1)??"unknown",72),c=i.files.length>0?` files=${Zt(i.files.join(","),120)}`:"",u=`event:${a} --offloads--> asset:${i.id.slice(0,12)} kind=${i.kind} bytes=${i.bytes}${c}`;if([...o,u].join(`
|
|
15
15
|
`).length>s)break;o.push(u)}return o.join(`
|
|
16
|
-
`)}import{existsSync as
|
|
17
|
-
`,{encoding:"utf8",mode:384}),
|
|
16
|
+
`)}import{existsSync as dn,mkdirSync as co,readFileSync as pn,renameSync as uo,writeFileSync as lo}from"node:fs";import{dirname as po,join as mn}from"node:path";import{createHash as no}from"node:crypto";import{dirname as ro}from"node:path";import{mkdirSync as so,readFileSync as oo,renameSync as io,writeFileSync as ao}from"node:fs";function w(e){return no("sha256").update(e).digest("hex")}function yt(e){if(Array.isArray(e))return e.map(yt);if(e&&typeof e=="object"){let t=e,n={};for(let r of Object.keys(t).sort())n[r]=yt(t[r]);return n}return e}function Pe(e){return JSON.stringify(yt(e))}function ln(e){try{return JSON.parse(oo(e,"utf8"))}catch{return null}}function R(e,t){so(ro(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;ao(n,JSON.stringify(t,null,2)+`
|
|
17
|
+
`,{encoding:"utf8",mode:384}),io(n,e)}function fn(e){return mn(e.rootPath,".toolnet","context","handoff.md")}function gn(e){return mn(e.rootPath,".toolnet","context","handoff.json")}function yn(e,t){co(po(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;lo(n,t.endsWith(`
|
|
18
18
|
`)?t:`${t}
|
|
19
|
-
`,{encoding:"utf8",mode:384}),
|
|
20
|
-
`)}function
|
|
21
|
-
`).trim();if(!n)return null;let r={version:1,projectId:e.id,projectName:e.name,text:n,digest:w(n),generatedAt:new Date().toISOString()};return
|
|
19
|
+
`,{encoding:"utf8",mode:384}),uo(n,e)}function mo(e,t){yn(e,`${JSON.stringify(t,null,2)}
|
|
20
|
+
`)}function hn(e,t){let n=t.replace(/\r\n/g,`
|
|
21
|
+
`).trim();if(!n)return null;let r={version:1,projectId:e.id,projectName:e.name,text:n,digest:w(n),generatedAt:new Date().toISOString()};return yn(fn(e),n),mo(gn(e),r),r}function ht(e){let t=fn(e);if(!dn(t))return null;try{let n=pn(t,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=gn(e);if(dn(s))try{let o=JSON.parse(pn(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:e.id,projectName:e.name,text:n,digest:w(n),generatedAt:r}}catch{return null}}function Sn(e,t=1800){let n=ht(e);if(!n?.text)return null;let r=n.text;return r.length>t&&(r=`${r.slice(0,t)}
|
|
22
22
|
|
|
23
23
|
[Fast handoff truncated]`),["[TOOLNET FAST HANDOFF]","",`Project: ${e.name}`,`Updated: ${n.generatedAt}`,"",r].join(`
|
|
24
|
-
`)}var
|
|
24
|
+
`)}var St="memory_agent_ask";function kn(){return`
|
|
25
25
|
[TOOLNET MEMORY AGENT]
|
|
26
26
|
|
|
27
27
|
Tool:
|
|
28
|
-
- ${
|
|
28
|
+
- ${St}
|
|
29
29
|
|
|
30
30
|
For resume/continue requests:
|
|
31
31
|
|
|
32
32
|
1. Use the injected ToolNet continuity handoff FIRST.
|
|
33
33
|
2. If the handoff is missing or ambiguous, invoke
|
|
34
|
-
${
|
|
34
|
+
${St} directly BEFORE repository/history exploration.
|
|
35
35
|
3. NEVER reconstruct prior work from:
|
|
36
36
|
- .toolnet/sessions/**
|
|
37
37
|
- state.json
|
|
38
38
|
- events.jsonl
|
|
39
39
|
- raw transcripts
|
|
40
40
|
4. NEVER search for the implementation/schema of
|
|
41
|
-
${
|
|
41
|
+
${St}; invoke the MCP tool directly.
|
|
42
42
|
5. Inspect git/source only AFTER continuity context is known.
|
|
43
43
|
|
|
44
44
|
Use:
|
|
@@ -46,31 +46,31 @@ Use:
|
|
|
46
46
|
- mode="ai" for ambiguous or combined continuity questions.
|
|
47
47
|
|
|
48
48
|
Current repository evidence overrides stale memory.
|
|
49
|
-
`.trim()}function
|
|
49
|
+
`.trim()}function kt(e){let t=N.resolve(e),n=N.parse(t).root;for(;t!==n;){let r=N.join(t,".toolnet");if(F.existsSync(r)&&F.statSync(r).isDirectory())return t;t=N.dirname(t)}return null}function wn(e){try{return F.existsSync(e)?F.readFileSync(e,"utf-8").trim():null}catch{return null}}function vn(e){return e.split(`
|
|
50
50
|
`).filter(r=>{let s=r.toUpperCase();return!(s.includes("SECRET")||s.includes("TOKEN")||s.includes("API_KEY")||s.includes("APIKEY")||s.includes("PASSWORD")||s.includes("PASS="))}).join(`
|
|
51
|
-
`)}function
|
|
51
|
+
`)}function bn(e={}){let t=e.projectPath||process.cwd(),n=kt(t);if(!n)return null;let r=N.join(n,".toolnet","project.json"),s="Unknown";try{if(F.existsSync(r)){let y=JSON.parse(F.readFileSync(r,"utf-8"));s=y.name||y.projectName||"Unknown"}}catch{}let o=N.join(n,".toolnet","profile.md"),i=N.join(n,".toolnet","current.md"),a=wn(o)||"",c=wn(i)||"";a=vn(a),c=vn(c);let u=`[TOOLNET PROJECT CONTEXT]
|
|
52
52
|
|
|
53
53
|
Project: ${s}
|
|
54
54
|
Root: ${n}
|
|
55
55
|
|
|
56
|
-
`,m=
|
|
56
|
+
`,m=Qt(a,c),p=Sn({id:"",name:s,rootPath:n},1600),d=p?`
|
|
57
57
|
|
|
58
58
|
${p}
|
|
59
|
-
`:"",l=
|
|
59
|
+
`:"",l=un(n,{maxAssets:6,maxChars:900}),g=l?`
|
|
60
60
|
|
|
61
61
|
${l}
|
|
62
62
|
`:"",S=`
|
|
63
63
|
|
|
64
|
-
${
|
|
64
|
+
${kn()}
|
|
65
65
|
|
|
66
66
|
Forbidden At Startup:
|
|
67
67
|
- Do not run session:agy-recover, handoff:latest, or brief automatically.
|
|
68
68
|
- Do not perform deep recovery merely because an agent starts.
|
|
69
69
|
- If the user asks to resume previous work and fast context is insufficient,
|
|
70
70
|
use memory_agent_ask before guessing.
|
|
71
|
-
`;return u+m+d+g+S}var
|
|
71
|
+
`;return u+m+d+g+S}var xn=6500,fo=[/\bcontinue\b/i,/\bresume\b/i,/\bpick\s+up\b/i,/\bcarry\s+on\b/i,/\bfinish\s+(?:the\s+)?(?:previous|last|unfinished|remaining)\b/i,/\bwhere\s+(?:did\s+we|were\s+we)\b/i,/\bwhat\s+was\s+(?:the\s+)?(?:last|previous)\b/i,/(?:^|[\s,.;:!?])tiếp\s+tục(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])làm\s+tiếp(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])làm\s+nốt(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])tiếp\s+phần(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])phần\s+đang\s+dở(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])đang\s+làm\s+(?:gì|đến\s+đâu)(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])dừng\s+(?:ở|tại)\s+đâu(?:$|[\s,.;:!?])/iu,/(?:^|[\s,.;:!?])task\s+(?:lúc\s+nãy|trước|đang\s+dở)(?:$|[\s,.;:!?])/iu];function In(e,t){return e.length<=xn?e:`${e.slice(0,xn)}
|
|
72
72
|
|
|
73
|
-
[ToolNet ${t} context truncated]`}function
|
|
73
|
+
[ToolNet ${t} context truncated]`}function jn(e){return e.replace(/\\/g,"/").toLowerCase()}function wt(e,t,n=0){if(!(n>6||t.length>=250)){if(typeof e=="string"){t.push(e);return}if(Array.isArray(e)){for(let r of e)if(wt(r,t,n+1),t.length>=250)break;return}if(e&&typeof e=="object"){for(let r of Object.values(e))if(wt(r,t,n+1),t.length>=250)break}}}function go(e){let t=jn(e);if(t.includes(".toolnet/sessions/")||t.endsWith(".toolnet/sessions")||t.includes(".gemini/antigravity-cli/brain/")||t.endsWith(".gemini/antigravity-cli/brain")||t.includes("/transcript.jsonl")||t.endsWith("transcript.jsonl")||t.includes(".toolnet/")&&(t.endsWith("/events.jsonl")||t.endsWith("/state.json")||t.includes("/sessions/")))return!0;let n=process.env.CURSOR_TRANSCRIPT_PATH;return!!(n&&jn(n)===t)}function yo(e){let t=e.trim();return t?fo.some(n=>n.test(t)):!1}function vt(e,t){if(!e.trim())return"";let n="";try{n=bn({projectPath:e})?.trim()??""}catch{n=""}let r=`
|
|
74
74
|
[TOOLNET CONTINUITY]
|
|
75
75
|
|
|
76
76
|
ToolNet Memory is the continuity source for this repository.
|
|
@@ -88,43 +88,43 @@ When the user asks to continue, resume, pick up, or finish previous work:
|
|
|
88
88
|
7. Do not ask the user to repeat context ToolNet already provides.
|
|
89
89
|
|
|
90
90
|
Current repository evidence overrides stale memory.
|
|
91
|
-
`.trim();return
|
|
91
|
+
`.trim();return In(n?`${n}
|
|
92
92
|
|
|
93
|
-
${r}`:r,t)}function
|
|
93
|
+
${r}`:r,t)}function An(e,t,n){if(!yo(e))return"";let r=vt(t,n),s=`
|
|
94
94
|
[TOOLNET RESUME REQUEST]
|
|
95
95
|
|
|
96
96
|
The current user message explicitly asks to continue previous work.
|
|
97
97
|
Use memory_agent_ask now if the fast handoff does not contain a clear,
|
|
98
98
|
current next action. Do not reconstruct continuity from raw session files.
|
|
99
|
-
`.trim();return
|
|
100
|
-
|
|
101
|
-
${s}`:s,n)}function
|
|
102
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function
|
|
103
|
-
`,{encoding:"utf8",mode:384}),wo(s,r)}function Tn(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 Ee=class{detect(t=process.cwd()){let n=le(t),r=Io(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>wt(Te(r,m))),i=Ao(n,o?r:void 0);if(i){let m=vt(i),p=Po(m);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),En(i,p)),Tn(p,i)}let a=new Date().toISOString(),c=bo(r),u={version:1,id:jo(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return En(r,u),Tn(u,r)}};var Mo=[{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}],Oe=class{scan(t){let n=[];for(let r of Mo){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 U=class{scanner=new Oe;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 Qo}from"node:os";import{join as Zo}from"node:path";import{DeleteObjectCommand as Eo,GetObjectCommand as To,HeadObjectCommand as Oo,ListObjectsV2Command as Ro,PutObjectCommand as No,S3Client as _o}from"@aws-sdk/client-s3";import{getSignedUrl as Ko}from"@aws-sdk/s3-request-presigner";var Re=class{name="huggingface";client;bucket;constructor(t){this.bucket=t.bucket,this.client=new _o({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 No({Bucket:this.bucket,Key:t,Body:s,ContentType:r}))}async get(t){let n=await Ko(this.client,new To({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 Oo({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 Eo({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let s=await this.client.send(new Ro({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 Nn,mkdir as $o,readFile as Wo,readdir as Fo,rm as Lo,stat as _n,writeFile as Do}from"node:fs/promises";import{dirname as zo,join as qo,relative as Kn,resolve as Ho}from"node:path";var de=class{constructor(t){this.root=t}root;name="local";path(t){let n=t.replace(/^\/+/,"");return Ho(this.root,n)}async put(t,n){let r=this.path(t);await $o(zo(r),{recursive:!0}),await Do(r,n)}async get(t){try{return await Wo(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 Nn(this.path(t)),!0}catch{return!1}}async delete(t){await Lo(this.path(t),{force:!0})}async list(t=""){let n=this.path(t),r=[];try{await Nn(n)}catch{return r}let s=async i=>{let a=await Fo(i,{withFileTypes:!0});for(let c of a){let u=qo(i,c.name);if(c.isDirectory()){await s(u);continue}let m=await _n(u);r.push({key:Kn(this.root,u),size:m.size,updatedAt:m.mtime.toISOString()})}},o=await _n(n);return o.isDirectory()?await s(n):r.push({key:Kn(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Jo,GetObjectCommand as Vo,HeadObjectCommand as Bo,ListObjectsV2Command as Go,PutObjectCommand as Uo,S3Client as Yo}from"@aws-sdk/client-s3";import{getSignedUrl as Xo}from"@aws-sdk/s3-request-presigner";var pe=class{name;client;bucket;constructor(t){this.name=t.name??"s3",this.bucket=t.bucket,this.client=new Yo({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 Uo({Bucket:this.bucket,Key:t,Body:s,ContentType:r}))}async get(t){let n=await Xo(this.client,new Vo({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 Bo({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 Jo({Bucket:this.bucket,Key:t}))}async list(t=""){let n=[],r;do{let s=await this.client.send(new Go({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 bt(e,t){return console.warn(t),new de(e)}function $n(e){let t=e.localRoot??Zo(Qo(),".toolnet-memory","storage");if(e.provider==="r2"){let n=e.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new pe({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):bt(t,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(e.provider==="s3"){let n=e.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new pe({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):bt(t,"[storage] S3 credentials missing. Using local fallback.")}if(e.provider==="huggingface"){let n=e.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Re({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):bt(t,"[storage] Hugging Face credentials missing. Using local fallback.")}return new de(t)}function ei(e){return new Promise(t=>setTimeout(t,e))}async function Wn(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 ei(c+u)}throw o}var ti=new Set(["put","get","getText","delete","list"]);function Fn(e,t={}){return new Proxy(e,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:ti.has(r)?(...o)=>Wn(()=>Promise.resolve(s.apply(n,o)),t):s.bind(n)}})}function Ln(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 Dn(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 Ne=class{constructor(t,n,r,s){this.provider=t;this.name=t.name,this.projectId=n,this.projectName=r,this.folder=Ln(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)+`
|
|
104
|
-
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(t){if(t=
|
|
105
|
-
`,{encoding:"utf8",mode:384}),
|
|
106
|
-
`)}function
|
|
99
|
+
`.trim();return In(r?`${r}
|
|
100
|
+
|
|
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 E(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Pn(e,t=process.env){return E(t.TOOLNET_HOOK_EVENT)??E(e.hook_event_name)??E(e.hookEventName)??""}function En(e,t=process.env){let n=E(e.session_id)??E(e.sessionId)??E(e.conversation_id)??E(t.TOOLNET_CURSOR_SESSION_ID)??"",r=E(e.cwd)??E(e.workspaceRoot)??E(t.CURSOR_PROJECT_DIR)??E(t.CLAUDE_PROJECT_DIR)??"",s=vt(r,"Cursor"),o={env:{TOOLNET_CURSOR_SESSION_ID:n}};return s&&(o.additional_context=s),o}function Mn(e,t=process.env){let n=E(e.prompt)??"",r=E(e.cwd)??E(e.workspaceRoot)??E(t.CURSOR_PROJECT_DIR)??E(t.CLAUDE_PROJECT_DIR)??"";return An(n,r,"Cursor")}function Tn(e){return Cn(e.tool_input??e.toolInput??e.updated_input??e)}function On(e){return{permission:"deny",user_message:e,agent_message: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,`
|
|
102
|
+
`).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 Ee(){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 Me,join as Oe,parse as _n,resolve as de}from"node:path";var Kn=".toolnet",Eo="project.json";function Mo(e){return xo("sha256").update(e).digest("hex").slice(0,16)}function xt(e){return Oe(e,Kn,Eo)}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=Me(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=Me(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:Me(Me(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)+`
|
|
103
|
+
`,{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:Mo(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)+`
|
|
104
|
+
`,"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)}
|
|
105
|
+
`,{encoding:"utf8",mode:384}),di(n,e)}function Ke(e,t){return[...e].filter(n=>n.kind===t).sort((n,r)=>{let s=n.occurredAt.localeCompare(r.occurredAt);return s!==0?s:n.sequence-r.sequence}).at(-1)}function Vn(e,t){let n=Ke(t.observations,"file"),r=Ke(t.observations,"next_action"),s=Ke(t.observations,"blocker"),o=Ke(t.observations,"decision"),i={version:1,projectId:e.id,agent:t.agent,nativeSessionId:t.nativeSessionId,updatedAt:t.workState.updatedAt,currentRequest:t.workState.currentRequest,currentActivity:t.workState.currentActivity,currentTask:t.workState.currentTask?.title,currentPhase:t.workState.currentPhase?.title,lastTouchedFile:n?.text??t.workState.activeFiles?.at(-1)??t.workState.filesTouched.at(-1),latestNextAction:r?.text??t.workState.nextActions.at(-1),latestBlocker:s?.text??t.workState.blockers.at(-1),latestDecision:o?.text??t.workState.decisions.at(-1)};return gi(Jn(e),i),i}function yi(e){let t=Jn(e);if(!ci(t))return null;try{let n=JSON.parse(li(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function Bn(e){let t=yi(e);if(!t)return null;let n=["Previous session:",`- Agent: ${t.agent}`,`- Session: ${t.nativeSessionId}`];return t.currentRequest&&n.push(`- Current request: ${t.currentRequest}`),t.currentActivity&&n.push(`- Current activity: ${t.currentActivity}`),t.currentPhase&&n.push(`- Current phase: ${t.currentPhase}`),t.currentTask&&n.push(`- Current task: ${t.currentTask}`),t.lastTouchedFile&&n.push(`- Last touched file: ${t.lastTouchedFile}`),t.latestBlocker&&n.push(`- Blocker: ${t.latestBlocker}`),t.latestNextAction&&n.push(`- Next action: ${t.latestNextAction}`),t.latestDecision&&n.push(`- Important decision: ${t.latestDecision}`),n.join(`
|
|
106
|
+
`)}function wi(e){let t=ki(e.rootPath,".toolnet","current.md");if(!hi(t))return null;try{return Si(t,"utf8").trim()}catch{return null}}function vi(e,t){let n=t.replace(/\r\n/g,`
|
|
107
107
|
`).trim(),r=2400,s=n.length>r?`${n.slice(0,r)}
|
|
108
108
|
|
|
109
|
-
[Current work truncated for fast handoff]`:n,o=
|
|
110
|
-
`)}function
|
|
109
|
+
[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(`
|
|
110
|
+
`)}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)+`
|
|
111
111
|
`,"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)+`
|
|
112
|
-
`,"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],
|
|
112
|
+
`,"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(O=>JSON.stringify(O)).join(`
|
|
113
113
|
`)+`
|
|
114
|
-
`,
|
|
114
|
+
`,T=w(M).slice(0,16),P=[t.remotePrefix,"events",`${Yn(h.sequence)}-${Yn(k.sequence)}-${T}.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 Ei,mkdirSync as Mi,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;Mi(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){R(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(`
|
|
115
115
|
`)+`
|
|
116
|
-
`,a=Ct(this.eventsFile,"a",384);try{
|
|
117
|
-
`).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
|
|
118
|
-
`)}function
|
|
119
|
-
`).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let m=u.toLowerCase().replace(/\s+/g," ");if(r.has(m))continue;r.add(m);let p="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(u)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(u)?p="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?p="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?p="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?p="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?p="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?p="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(p="file");let d=
|
|
116
|
+
`,a=Ct(this.eventsFile,"a",384);try{Oi(a,i,null,"utf8"),Ei(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(`
|
|
117
|
+
`).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 _(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 Et(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))Et(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))&&Et(o,s,n,r+1)}}function Bi(e){let t=[];Et(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&&_(e,sr)?{kind:"rule",confidence:.98}:r&&_(e,$i)?{kind:"rule",confidence:.92}:_(e,Fi)?{kind:_(e,tr)?"architecture":"decision",confidence:r?.93:.86}:r&&_(e,Wi)?{kind:"todo",confidence:.87}:_(e,tr)&&_(e,Di)?{kind:"architecture",confidence:r?.88:.82}:s&&_(e,Li)?{kind:"fix",confidence:.8}:r&&_(e,zi)&&_(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,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 Mt(e){return Xi("sha256").update(e).digest("hex")}function We(e,t){return`${e}:${Mt(t).slice(0,24)}`}function ea(e){try{return Mt(JSON.stringify(e))}catch{return Mt(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(`
|
|
118
|
+
`)}function ur(e,t){let n=e.slice().sort((d,l)=>d.sequence-l.sequence||d.timestamp.localeCompare(l.timestamp)||d.id.localeCompare(l.id)),r=n.map(d=>({id:We("raw",[d.projectId,d.agent,d.nativeSessionId,d.id,String(d.sequence)].join("|")),level:"raw",eventId:d.id,sourceEventId:d.sourceEventId,sequence:d.sequence,type:d.type,role:d.role,timestamp:d.timestamp,sourcePath:d.provenance.sourcePath,payloadDigest:ea(d.data)})),s=new Map,o=new Map;n.forEach((d,l)=>{let g=r[l];g&&(s.set(d.id,g.id),d.sourceEventId&&o.set(d.sourceEventId,g.id))});let i=t.map(d=>{let l=Q([...d.provenance.eventIds.map(g=>s.get(g)),...d.provenance.sourceEventIds.map(g=>o.get(g))]);return{id:We("fact",d.fingerprint),level:"fact",fingerprint:d.fingerprint,kind:d.kind,type:d.type,content:d.content,knowledgeClass:d.knowledgeClass,importanceScore:d.importanceScore,confidence:d.confidence,tags:Q([...d.tags,"level:fact",`class:${d.knowledgeClass}`,`kind:${d.kind}`]),rawIds:l,sourcePaths:Q(d.provenance.sourcePaths)}}),a=new Map;for(let d of i){let l=ta(d.kind),g=a.get(l)??[];g.push(d),a.set(l,g)}let c=[];for(let d of Qi){let l=a.get(d);if(!l?.length)continue;let g=l.slice().sort((y,h)=>h.importanceScore-y.importanceScore||h.confidence-y.confidence||y.id.localeCompare(h.id)),S=g.map(y=>y.id);c.push({id:We("scene",`${d}|${S.join("|")}`),level:"scene",kind:d,title:Zi[d],summary:na(g),factIds:S,importanceScore:Math.max(...g.map(y=>y.importanceScore)),confidence:ar(g.map(y=>y.confidence)),tags:Q(["level:scene",`scene:${d}`,...g.flatMap(y=>y.tags)]),sourcePaths:Q(g.flatMap(y=>y.sourcePaths))})}let u=new Map(i.map(d=>[d.id,d])),m=[];for(let d of c){let g=d.factIds.map(h=>u.get(h)).filter(h=>!!h).filter(h=>(h.knowledgeClass==="permanent"||h.knowledgeClass==="task")&&h.importanceScore>=.55);if(g.length===0)continue;let S=g.some(h=>h.knowledgeClass==="permanent")?"permanent":"task",y=ra(g);m.push({id:We("knowledge",`${d.id}|${S}|${g.map(h=>h.id).join("|")}`),level:"knowledge",knowledgeClass:S,title:d.title,content:y,sceneIds:[d.id],factIds:g.map(h=>h.id),importanceScore:Math.max(...g.map(h=>h.importanceScore)),confidence:ar(g.map(h=>h.confidence)),tags:Q(["level:knowledge",`class:${S}`,`scene:${d.kind}`,...g.flatMap(h=>h.tags)]),sourcePaths:Q(g.flatMap(h=>h.sourcePaths))})}let p=[];for(let d of i)for(let l of d.rawIds)p.push({from:l,to:d.id,type:"supports"});for(let d of c)for(let l of d.factIds)p.push({from:l,to:d.id,type:"belongs_to"});for(let d of m)for(let l of d.sceneIds)p.push({from:l,to:d.id,type:"promotes_to"});return{schema:"toolnet.memory-hierarchy.v1",version:1,raw:r,facts:i,scenes:c,knowledge:m,links:p,stats:{raw:r.length,facts:i.length,scenes:c.length,knowledge:m.length,links:p.length}}}function fe(){let e=Ee(),t=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||t==="archive"||t==="full",r=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",s=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),o=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),a=n,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||t==="full";return{sessionSave:t,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:a,archiveRemote:c}}function lr(e){return(e||fe()).durableMemoryMaxItemsPerSession}function dr(e){return(e||fe()).sessionSummaryMaxTokens}var pr=new Y;function mr(e){let t=e.trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{let r=JSON.parse(t);return JSON.stringify(pr.sanitizeValue(r))}catch{}let n=pr.sanitize(e).text;return n=n.replace(/("(?:api[_-]?key|token|secret|password|cookie|authorization)"\s*:\s*)"[^"]*"/gi,'$1"[REDACTED]"').replace(/('(?:api[_-]?key|token|secret|password|cookie|authorization)'\s*:\s*)'[^']*'/gi,"$1'[REDACTED]'").replace(/\b(api[_-]?key|token|secret|password|cookie|authorization)\b\s*[:=]\s*[^\s,;]+/gi,"$1=[REDACTED]").replace(/\bbearer\s+[A-Za-z0-9._~+/=-]+/gi,"Bearer [REDACTED]"),n}function sa(e,t){let n=e.toLowerCase(),r=.5,s=["nh\u1EDB","remember","quy t\u1EAFc","rule","t\u1EEB gi\u1EDD","from now","kh\xF4ng \u0111\u01B0\u1EE3c","must not","lu\xF4n lu\xF4n","always","never","critical","important","blocker","deploy","production","architecture"];for(let i of s)n.includes(i)&&(r+=.15);t==="rule"||t==="architecture"||t==="blocker"?r+=.2:t==="decision"||t==="deploy"?r+=.15:(t==="fix"||t==="next_action")&&(r+=.1),e.length<20?r-=.3:e.length>500&&(r-=.1);let o=[/npm (notice|warn|ERR)/i,/\d+ packages? in \d+/i,/found \d+ vulnerabilities/i,/up to date/i,/added \d+ packages/i,/^(ok|done|success|error|warning)$/i];for(let i of o)i.test(e)&&(r-=.4);return Math.max(0,Math.min(1,r))}function oa(e,t){let n=[],r=new Set;for(let i of e){let a=i.split(`
|
|
119
|
+
`).filter(c=>c.trim());for(let c of a){let u=c.trim();if(u.length<15)continue;let m=u.toLowerCase().replace(/\s+/g," ");if(r.has(m))continue;r.add(m);let p="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(u)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(u)?p="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(u)?p="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(u)?p="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(u)?p="next_action":/\b(deploy|release|publish|ship)\b/i.test(u)?p="deploy":/\b(architecture|design|structure|pattern)\b/i.test(u)?p="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(u)&&(p="file");let d=sa(u,p);if(d<.3)continue;let l=mr(u);n.push({category:p,text:l,importance:d,sourceSessionId:t})}}let s=fe(),o=lr(s);return n.sort((i,a)=>a.importance-i.importance).slice(0,o)}function ia(e){let t=fe(),n=dr(t),o=e.join(`
|
|
120
120
|
|
|
121
121
|
`).split(`
|
|
122
|
-
`).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).map(i=>
|
|
123
|
-
`);return
|
|
122
|
+
`).filter(i=>{let a=i.trim();return a.length>20&&!a.startsWith("npm")&&!a.startsWith("\u2713")&&!a.startsWith("Error:")}).slice(0,20).map(i=>mr(i)).join(`
|
|
123
|
+
`);return pt(o,n)}function fr(e,t){let r=(Array.isArray(e)?e:e.split(`
|
|
124
124
|
|
|
125
|
-
`).filter(l=>l.trim())).map(l=>typeof l=="string"?l:JSON.stringify(l)).filter(l=>l.trim()),s=Zi(r,t),o=s.filter(l=>l.category==="decision").map(l=>l.text),i=s.filter(l=>l.category==="rule").map(l=>l.text),a=s.filter(l=>l.category==="file").map(l=>l.text),c=s.filter(l=>l.category==="fix").map(l=>l.text),u=s.filter(l=>l.category==="blocker").map(l=>l.text),m=s.filter(l=>l.category==="next_action").map(l=>l.text),p=s.filter(l=>l.category==="deploy").map(l=>l.text);return{summary:ea(r),decisions:o,projectRules:i,filesChanged:a,bugsFixed:c,commands:p,blockers:u,nextActions:m,durableFacts:s}}function V(e){let t=new Set,n=[];for(let r of e){let s=r?.replace(/\s+/g," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();t.has(o)||(t.add(o),n.push(s))}return n}function ta(e){let t=new Map;for(let n of e){if(!n||!n.id||!Number.isFinite(n.sequence))continue;let r=n.sourceEventId?`${n.agent}:${n.sourceEventId}`:n.id,s=t.get(r);(!s||n.sequence>s.sequence)&&t.set(r,n)}return[...t.values()].sort((n,r)=>n.sequence-r.sequence||n.timestamp.localeCompare(r.timestamp))}function na(e){switch(e){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function ra(e){let t=na(e.importance);return Math.max(0,Math.min(1,t*.75+e.confidence*.25))}function sa(e){return e.importance==="temporary"||e.confidence<.78?"transient":e.kind==="rule"||e.kind==="architecture"?"permanent":e.kind==="decision"||e.kind==="todo"||e.kind==="fix"?"task":"session"}function oa(e){let t=e.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}_./:-]+/gu)??[],n=new Set;for(let r of t)if(!(r.length<2||/^\d+$/u.test(r))&&(n.add(r),n.size>=40))break;return[...n]}function ia(e){let t=sa(e),n=ra(e),r=oa(e.content);return{...e,knowledgeClass:t,importanceScore:n,retrievalTerms:r,tags:V([...e.tags,"level:fact",`class:${t}`,`kind:${e.kind}`])}}function aa(e){return e.map(t=>{try{return JSON.stringify({type:t.type,role:t.role,data:t.data,provenance:{sourcePath:t.provenance.sourcePath,files:t.provenance.files}})}catch{return""}}).filter(Boolean)}function ca(e,t,n){let r=dr(aa(t),e.nativeSessionId),s=n.filter(u=>u.kind==="todo").map(u=>u.content),o=n.flatMap(u=>u.provenance.sourcePaths),i=n.filter(u=>u.kind==="architecture").map(u=>u.content),a=V([...s,...r.nextActions]),c=V([...r.nextActions,...s]);return{summary:r.summary,state:{task:c[0]??a[0],decisions:V(r.decisions),files:V([...r.filesChanged,...o]),todos:a,completed:V(r.bugsFixed),blockers:V(r.blockers),nextActions:c,architecture:V(i)}}}function Fe(e,t){let n=ta(t),r=rr(e,n).map(ia),s=r.filter(m=>m.knowledgeClass!=="transient").sort((m,p)=>p.importanceScore-m.importanceScore),{summary:o,state:i}=ca(e,n,s),a=s.map(m=>({fingerprint:m.fingerprint,kind:m.kind,knowledgeClass:m.knowledgeClass,importanceScore:m.importanceScore,content:m.content,terms:m.retrievalTerms})),c=ir(n,s),u=m=>r.filter(p=>p.knowledgeClass===m).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:a,hierarchy:c,stats:{inputEvents:t.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:s.length,permanent:u("permanent"),task:u("task"),session:u("session"),transient:u("transient")}}}import{createHash as ya}from"node:crypto";import{existsSync as ha,readdirSync as Sa,readFileSync as ka}from"node:fs";import{basename as wa,join as Pr}from"node:path";import{randomUUID as fr}from"node:crypto";var j=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function fe(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 Z(e){let t=e.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!t)throw new j("Invalid Wiki slug",400);return t}function pr(e){let t=[];for(let n of e.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&t.push(Z(r))}return fe(t)}function ua(e){return e.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(t=>t.trim()).filter(t=>t.length>=2)}function mr(e){return{id:`revision-${fr()}`,pageId:e.id,slug:e.slug,revision:e.revision,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...e.tags],links:[...e.links],createdAt:e.updatedAt}}function Q(e){return structuredClone(e)}var Le=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(t){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=t(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let t=await this.ensureState(),n=new Set(t.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:t.projectId,pages:t.pages.length,revisions:t.revisions.length,tags:fe(t.pages.flatMap(r=>r.tags)).sort((r,s)=>r.localeCompare(s)),links:t.pages.reduce((r,s)=>r+s.links.length,0),orphanPages:t.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:t.pages.filter(r=>r.tags.some(s=>s.startsWith("toolnet-auto-"))).length,updatedAt:t.updatedAt}}async listPages(){let t=await this.ensureState();return Q([...t.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(t){let n=await this.ensureState(),r=Z(t),s=n.pages.find(o=>o.slug===r||o.id===t);if(!s)throw new j(`Wiki page not found: ${t}`,404);return Q(s)}async createPage(t){return this.mutate(n=>{let r=t.title.trim(),s=t.content.trim();if(!r)throw new j("Wiki title is required",400);let o=Z(t.slug??r);if(n.pages.some(c=>c.slug===o))throw new j(`Wiki page already exists: ${o}`,409);let i=new Date().toISOString(),a={id:`wiki-${fr()}`,slug:o,title:r,...t.summary?.trim()?{summary:t.summary.trim()}:{},content:s,tags:fe(t.tags??[]),links:pr(s),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(mr(a)),Q(a)})}async updatePage(t,n){return this.mutate(r=>{let s=Z(t),o=r.pages.find(i=>i.slug===s||i.id===t);if(!o)throw new j(`Wiki page not found: ${t}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new j("Wiki title is required",400);o.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?o.summary=i:delete o.summary}return n.content!==void 0&&(o.content=n.content.trim(),o.links=pr(o.content)),n.tags!==void 0&&(o.tags=fe(n.tags)),o.revision+=1,o.updatedAt=new Date().toISOString(),r.revisions.push(mr(o)),Q(o)})}async history(t){let n=await this.getPage(t),r=await this.ensureState();return Q(r.revisions.filter(s=>s.pageId===n.id).sort((s,o)=>o.revision-s.revision))}async backlinks(t){let n=await this.getPage(t),r=await this.ensureState();return Q(r.pages.filter(s=>s.links.includes(n.slug)).sort((s,o)=>s.title.localeCompare(o.title)))}async search(t,n=10){let r=await this.ensureState(),s=fe(ua(t));if(s.length===0)return[];let o=Math.max(1,Math.min(20,Math.floor(n))),i=[];for(let a of r.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),m=a.summary?.toLowerCase()??"",p=a.content.toLowerCase(),d=a.tags.map(g=>g.toLowerCase()),l=0;for(let g of s)u===g&&(l+=12),c===g&&(l+=10),c.includes(g)&&(l+=6),u.includes(g)&&(l+=5),d.some(S=>S===g)?l+=5:d.some(S=>S.includes(g))&&(l+=3),m.includes(g)&&(l+=2),p.includes(g)&&(l+=1);l>0&&i.push({page:Q(a),score:l})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,o)}};var gr="wiki/state.v1.json";function la(e){let t=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:e.id,pages:[],revisions:[],createdAt:t,updatedAt:t}}function da(e,t){let n=JSON.parse(e);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==t.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var De=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(gr);if(!t){let n=la(this.project);return await this.save(n),n}return da(t,this.project)}async save(t){await this.storage.put(gr,JSON.stringify(t,null,2),"application/json")}};import{createHash as pa,randomUUID as yr}from"node:crypto";var hr="wiki/governance.v1.json",vr="toolnet.knowledge-governance.v1",Sr=500,ge={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function ma(e,t=0,n=1){return Math.max(t,Math.min(n,e))}function Mt(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function kr(e){return pa("sha256").update(e.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function fa(e){let t=[e.title,e.summary??"",e.content.slice(0,2e3),...e.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(t)}function ga(e){let t=e.sourceType==="skill"?.96:e.sourceType==="memory"?.94:.88,n=e.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(t+=.03),e.content.length>=200&&(t+=.02),e.content.length<80&&(t-=.05),e.title.length<4&&(t-=.05),ma(t)}function wr(e){let t=new Date().toISOString();return{schema:vr,version:1,projectId:e,policy:{...ge},reviews:[],audit:[],createdAt:t,updatedAt:t}}function br(e){let t=e.autoApproveThreshold??ge.autoApproveThreshold,n=e.criticalApproveThreshold??ge.criticalApproveThreshold,r=e.staleAfterDays??ge.staleAfterDays;if(!Number.isFinite(t)||t<.5||t>1)throw new j("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new j("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new j("Invalid staleAfterDays",400);return{autoApproveThreshold:t,criticalApproveThreshold:n,staleAfterDays:r}}var ze=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(hr);if(!t){let n=wr(this.project.id);return await this.save(n),n}try{let n=JSON.parse(t);if(n.schema!==vr||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:br(n.policy??ge)}}catch{let n=wr(this.project.id);return await this.save(n),n}}async save(t){await this.storage.put(hr,JSON.stringify(t,null,2),"application/json")}},qe=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(t,n,r,s={}){t.audit.push({id:yr(),action:n,principal:r,...s.reviewId?{reviewId:s.reviewId}:{},...s.sourceKey?{sourceKey:s.sourceKey}:{},timestamp:new Date().toISOString(),...s.metadata?{metadata:s.metadata}:{}}),t.audit.length>Sr&&(t.audit=t.audit.slice(-Sr))}async mutate(t){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=await t(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(t,n){return this.mutate(r=>(r.policy=br({...r.policy,...t}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let t=await this.ensureState(),n=r=>t.reviews.filter(s=>s.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:t.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:t.audit.length,policy:{...t.policy},updatedAt:t.updatedAt}}async listReviews(t){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!t||r.status===t).sort((r,s)=>s.updatedAt.localeCompare(r.updatedAt)))}async auditLog(t=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(t)));return structuredClone(n.audit.slice(-r).reverse())}async assess(t,n){let r=await this.ensureState(),s=ga(t),o=Mt(t.title),i=n.filter(m=>m.slug!==t.slug&&Mt(m.title)===o&&kr(m.content)!==kr(t.content)).map(m=>m.slug),a=fa(t),c=[];s<r.policy.autoApproveThreshold&&c.push(`confidence:${s.toFixed(2)}`),a&&s<r.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:s,risk:u,requiresReview:i.length>0||s<r.policy.autoApproveThreshold||a&&s<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(t,n){let r=await this.assess(t,n);return this.mutate(s=>{let o=s.reviews.find(c=>c.sourceKey===t.sourceKey&&c.digest===t.digest);if(o?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(o)};if(o?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(o)};if(!r.requiresReview)return this.audit(s,"knowledge:auto-approved","system",{sourceKey:t.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(o?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(o)};let i=new Date().toISOString(),a={id:yr(),sourceKey:t.sourceKey,sourceType:t.sourceType,slug:t.slug,marker:t.marker,digest:t.digest,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...new Set([...t.tags,t.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};return s.reviews.push(a),this.audit(s,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(a)}})}async markApplied(t,n){await this.mutate(r=>{let s=r.reviews.find(o=>o.sourceKey===t&&o.digest===n&&o.status==="approved");s&&(s.appliedAt=new Date().toISOString(),s.updatedAt=s.appliedAt,this.audit(r,"knowledge:applied",s.reviewedBy??"system",{reviewId:s.id,sourceKey:t}))})}async decide(t,n,r){return this.mutate(async s=>{let o=s.reviews.find(u=>u.id===t);if(!o)throw new j(`Governance review not found: ${t}`,404);if(o.status!=="pending")throw new j("Governance review is already resolved",409);let i=new Date().toISOString();if(o.reviewedAt=i,o.reviewedBy=n.principal,o.updatedAt=i,n.note?.trim()&&(o.reviewNote=n.note.trim()),n.action==="reject")return o.status="rejected",this.audit(s,"knowledge:rejected",n.principal,{reviewId:t,sourceKey:o.sourceKey}),structuredClone(o);if(n.action==="supersede")return o.status="superseded",n.targetReviewId&&(o.supersededBy=n.targetReviewId),this.audit(s,"knowledge:superseded",n.principal,{reviewId:t,sourceKey:o.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(o);if(n.action==="merge"){if(!n.targetReviewId)throw new j("targetReviewId is required for merge",400);let u=s.reviews.find(m=>m.id===n.targetReviewId);if(!u)throw new j("Merge target review not found",404);return o.status="superseded",o.mergedInto=u.id,this.audit(s,"knowledge:merged",n.principal,{reviewId:t,sourceKey:o.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(o)}o.status="approved";let c=(await r.listPages()).find(u=>u.slug===o.slug);if(c&&!c.tags.includes(o.marker))throw new j(`Wiki page '${o.slug}' is manually managed`,409);return c?await r.updatePage(o.slug,{title:o.title,summary:o.summary??"",content:o.content,tags:o.tags}):await r.createPage({slug:o.slug,title:o.title,...o.summary?{summary:o.summary}:{},content:o.content,tags:o.tags}),o.appliedAt=i,this.audit(s,"knowledge:approved",n.principal,{reviewId:t,sourceKey:o.sourceKey}),structuredClone(o)})}async quality(t){let n=await this.ensureState(),r=await t.listPages(),s=Date.now(),o=n.policy.staleAfterDays*864e5,i=r.map(m=>{let p=s-Date.parse(m.updatedAt);return{slug:m.slug,title:m.title,updatedAt:m.updatedAt,ageDays:Math.max(0,Math.floor(p/864e5)),stale:Number.isFinite(p)&&p>o}}).filter(m=>m.stale).map(({stale:m,...p})=>p),a=new Map;for(let m of r){let p=Mt(m.title),d=a.get(p)??[];d.push(m),a.set(p,d)}let c=[...a.entries()].filter(([,m])=>m.length>1).map(([m,p])=>({title:m,pages:p.map(d=>d.slug)})),u=n.reviews.filter(m=>m.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(m=>m.tags.some(p=>p.startsWith("toolnet-auto-"))).length,manualPages:r.filter(m=>!m.tags.some(p=>p.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(m=>m.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(m=>m.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var Mr="wiki/automation.v1.json",Er="toolnet.wiki-automation.v1",Ot=8e3,xr=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function he(e){return ya("sha256").update(JSON.stringify(e)).digest("hex")}function ye(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function jr(e){return Array.isArray(e)?e:[]}function Tr(e){return typeof e!="string"?void 0:e.replace(/\s+/gu," ").trim()||void 0}function Et(e){return Array.isArray(e)?e.map(Tr).filter(t=>!!t):[]}function W(e,t){for(let n of t){let r=Tr(e[n]);if(r)return r}}function Se(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 He(e,t=0,n=""){if(t>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(xr.has(r))return[];if(typeof e=="string"){let i=e.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(e))return e.flatMap(i=>He(i,t+1,n));let s=ye(e);if(!s)return[];let o=[];for(let[i,a]of Object.entries(s)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();xr.has(c)||o.push(...He(a,t+1,i))}return o}function Cr(e){let n=Se(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(s=>He(e[s],0,s)));return(n.length>0?n:Se(He(e))).join(`
|
|
125
|
+
`).filter(l=>l.trim())).map(l=>typeof l=="string"?l:JSON.stringify(l)).filter(l=>l.trim()),s=oa(r,t),o=s.filter(l=>l.category==="decision").map(l=>l.text),i=s.filter(l=>l.category==="rule").map(l=>l.text),a=s.filter(l=>l.category==="file").map(l=>l.text),c=s.filter(l=>l.category==="fix").map(l=>l.text),u=s.filter(l=>l.category==="blocker").map(l=>l.text),m=s.filter(l=>l.category==="next_action").map(l=>l.text),p=s.filter(l=>l.category==="deploy").map(l=>l.text);return{summary:ia(r),decisions:o,projectRules:i,filesChanged:a,bugsFixed:c,commands:p,blockers:u,nextActions:m,durableFacts:s}}function B(e){let t=new Set,n=[];for(let r of e){let s=r?.replace(/\s+/g," ").trim();if(!s)continue;let o=s.normalize("NFKC").toLowerCase();t.has(o)||(t.add(o),n.push(s))}return n}function aa(e){let t=new Map;for(let n of e){if(!n||!n.id||!Number.isFinite(n.sequence))continue;let r=n.sourceEventId?`${n.agent}:${n.sourceEventId}`:n.id,s=t.get(r);(!s||n.sequence>s.sequence)&&t.set(r,n)}return[...t.values()].sort((n,r)=>n.sequence-r.sequence||n.timestamp.localeCompare(r.timestamp))}function ca(e){switch(e){case"critical":return 1;case"high":return .85;case"normal":return .6;case"temporary":return .25}}function ua(e){let t=ca(e.importance);return Math.max(0,Math.min(1,t*.75+e.confidence*.25))}function la(e){return e.importance==="temporary"||e.confidence<.78?"transient":e.kind==="rule"||e.kind==="architecture"?"permanent":e.kind==="decision"||e.kind==="todo"||e.kind==="fix"?"task":"session"}function da(e){let t=e.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}_./:-]+/gu)??[],n=new Set;for(let r of t)if(!(r.length<2||/^\d+$/u.test(r))&&(n.add(r),n.size>=40))break;return[...n]}function pa(e){let t=la(e),n=ua(e),r=da(e.content);return{...e,knowledgeClass:t,importanceScore:n,retrievalTerms:r,tags:B([...e.tags,"level:fact",`class:${t}`,`kind:${e.kind}`])}}function ma(e){return e.map(t=>{try{return JSON.stringify({type:t.type,role:t.role,data:t.data,provenance:{sourcePath:t.provenance.sourcePath,files:t.provenance.files}})}catch{return""}}).filter(Boolean)}function fa(e,t,n){let r=fr(ma(t),e.nativeSessionId),s=n.filter(u=>u.kind==="todo").map(u=>u.content),o=n.flatMap(u=>u.provenance.sourcePaths),i=n.filter(u=>u.kind==="architecture").map(u=>u.content),a=B([...s,...r.nextActions]),c=B([...r.nextActions,...s]);return{summary:r.summary,state:{task:c[0]??a[0],decisions:B(r.decisions),files:B([...r.filesChanged,...o]),todos:a,completed:B(r.bugsFixed),blockers:B(r.blockers),nextActions:c,architecture:B(i)}}}function Le(e,t){let n=aa(t),r=ir(e,n).map(pa),s=r.filter(m=>m.knowledgeClass!=="transient").sort((m,p)=>p.importanceScore-m.importanceScore),{summary:o,state:i}=fa(e,n,s),a=s.map(m=>({fingerprint:m.fingerprint,kind:m.kind,knowledgeClass:m.knowledgeClass,importanceScore:m.importanceScore,content:m.content,terms:m.retrievalTerms})),c=ur(n,s),u=m=>r.filter(p=>p.knowledgeClass===m).length;return{version:2,normalizedEvents:n,summary:o,state:i,candidates:s,retrievalIndex:a,hierarchy:c,stats:{inputEvents:t.length,normalizedEvents:n.length,extractedCandidates:r.length,persistedCandidates:s.length,permanent:u("permanent"),task:u("task"),session:u("session"),transient:u("transient")}}}import{createHash as ba}from"node:crypto";import{existsSync as xa,readdirSync as ja,readFileSync as Ia}from"node:fs";import{basename as Aa,join as Tr}from"node:path";import{randomUUID as hr}from"node:crypto";var j=class extends Error{constructor(n,r){super(n);this.statusCode=r}statusCode};function ge(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 ee(e){let t=e.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!t)throw new j("Invalid Wiki slug",400);return t}function gr(e){let t=[];for(let n of e.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let r=n[1]?.trim();r&&t.push(ee(r))}return ge(t)}function ga(e){return e.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(t=>t.trim()).filter(t=>t.length>=2)}function yr(e){return{id:`revision-${hr()}`,pageId:e.id,slug:e.slug,revision:e.revision,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...e.tags],links:[...e.links],createdAt:e.updatedAt}}function Z(e){return structuredClone(e)}var De=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(t){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=t(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async summary(){let t=await this.ensureState(),n=new Set(t.pages.flatMap(r=>r.links));return{schema:"toolnet.wiki-summary.v1",projectId:t.projectId,pages:t.pages.length,revisions:t.revisions.length,tags:ge(t.pages.flatMap(r=>r.tags)).sort((r,s)=>r.localeCompare(s)),links:t.pages.reduce((r,s)=>r+s.links.length,0),orphanPages:t.pages.filter(r=>r.links.length===0&&!n.has(r.slug)).length,automatedPages:t.pages.filter(r=>r.tags.some(s=>s.startsWith("toolnet-auto-"))).length,updatedAt:t.updatedAt}}async listPages(){let t=await this.ensureState();return Z([...t.pages].sort((n,r)=>n.title.localeCompare(r.title)))}async getPage(t){let n=await this.ensureState(),r=ee(t),s=n.pages.find(o=>o.slug===r||o.id===t);if(!s)throw new j(`Wiki page not found: ${t}`,404);return Z(s)}async createPage(t){return this.mutate(n=>{let r=t.title.trim(),s=t.content.trim();if(!r)throw new j("Wiki title is required",400);let o=ee(t.slug??r);if(n.pages.some(c=>c.slug===o))throw new j(`Wiki page already exists: ${o}`,409);let i=new Date().toISOString(),a={id:`wiki-${hr()}`,slug:o,title:r,...t.summary?.trim()?{summary:t.summary.trim()}:{},content:s,tags:ge(t.tags??[]),links:gr(s),revision:1,createdAt:i,updatedAt:i};return n.pages.push(a),n.revisions.push(yr(a)),Z(a)})}async updatePage(t,n){return this.mutate(r=>{let s=ee(t),o=r.pages.find(i=>i.slug===s||i.id===t);if(!o)throw new j(`Wiki page not found: ${t}`,404);if(n.title!==void 0){let i=n.title.trim();if(!i)throw new j("Wiki title is required",400);o.title=i}if(n.summary!==void 0){let i=n.summary.trim();i?o.summary=i:delete o.summary}return n.content!==void 0&&(o.content=n.content.trim(),o.links=gr(o.content)),n.tags!==void 0&&(o.tags=ge(n.tags)),o.revision+=1,o.updatedAt=new Date().toISOString(),r.revisions.push(yr(o)),Z(o)})}async history(t){let n=await this.getPage(t),r=await this.ensureState();return Z(r.revisions.filter(s=>s.pageId===n.id).sort((s,o)=>o.revision-s.revision))}async backlinks(t){let n=await this.getPage(t),r=await this.ensureState();return Z(r.pages.filter(s=>s.links.includes(n.slug)).sort((s,o)=>s.title.localeCompare(o.title)))}async search(t,n=10){let r=await this.ensureState(),s=ge(ga(t));if(s.length===0)return[];let o=Math.max(1,Math.min(20,Math.floor(n))),i=[];for(let a of r.pages){let c=a.title.toLowerCase(),u=a.slug.toLowerCase(),m=a.summary?.toLowerCase()??"",p=a.content.toLowerCase(),d=a.tags.map(g=>g.toLowerCase()),l=0;for(let g of s)u===g&&(l+=12),c===g&&(l+=10),c.includes(g)&&(l+=6),u.includes(g)&&(l+=5),d.some(S=>S===g)?l+=5:d.some(S=>S.includes(g))&&(l+=3),m.includes(g)&&(l+=2),p.includes(g)&&(l+=1);l>0&&i.push({page:Z(a),score:l})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,o)}};var Sr="wiki/state.v1.json";function ya(e){let t=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:e.id,pages:[],revisions:[],createdAt:t,updatedAt:t}}function ha(e,t){let n=JSON.parse(e);if(n.schema!=="toolnet.wiki.v1"||n.version!==1||n.projectId!==t.id||!Array.isArray(n.pages)||!Array.isArray(n.revisions))throw new Error("Invalid ToolNet Wiki state");return n}var ze=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(Sr);if(!t){let n=ya(this.project);return await this.save(n),n}return ha(t,this.project)}async save(t){await this.storage.put(Sr,JSON.stringify(t,null,2),"application/json")}};import{createHash as Sa,randomUUID as kr}from"node:crypto";var wr="wiki/governance.v1.json",jr="toolnet.knowledge-governance.v1",vr=500,ye={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function ka(e,t=0,n=1){return Math.max(t,Math.min(n,e))}function Tt(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function br(e){return Sa("sha256").update(e.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function wa(e){let t=[e.title,e.summary??"",e.content.slice(0,2e3),...e.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(t)}function va(e){let t=e.sourceType==="skill"?.96:e.sourceType==="memory"?.94:.88,n=e.tags.map(r=>r.toLowerCase());return(n.includes("permanent")||n.includes("task"))&&(t+=.03),e.content.length>=200&&(t+=.02),e.content.length<80&&(t-=.05),e.title.length<4&&(t-=.05),ka(t)}function xr(e){let t=new Date().toISOString();return{schema:jr,version:1,projectId:e,policy:{...ye},reviews:[],audit:[],createdAt:t,updatedAt:t}}function Ir(e){let t=e.autoApproveThreshold??ye.autoApproveThreshold,n=e.criticalApproveThreshold??ye.criticalApproveThreshold,r=e.staleAfterDays??ye.staleAfterDays;if(!Number.isFinite(t)||t<.5||t>1)throw new j("Invalid autoApproveThreshold",400);if(!Number.isFinite(n)||n<.5||n>1)throw new j("Invalid criticalApproveThreshold",400);if(!Number.isInteger(r)||r<1||r>3650)throw new j("Invalid staleAfterDays",400);return{autoApproveThreshold:t,criticalApproveThreshold:n,staleAfterDays:r}}var qe=class{constructor(t,n){this.storage=t;this.project=n}storage;project;async load(){let t=await this.storage.getText(wr);if(!t){let n=xr(this.project.id);return await this.save(n),n}try{let n=JSON.parse(t);if(n.schema!==jr||n.version!==1||n.projectId!==this.project.id||!Array.isArray(n.reviews)||!Array.isArray(n.audit))throw new Error("invalid");return{...n,policy:Ir(n.policy??ye)}}catch{let n=xr(this.project.id);return await this.save(n),n}}async save(t){await this.storage.put(wr,JSON.stringify(t,null,2),"application/json")}},He=class{constructor(t){this.store=t}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(t,n,r,s={}){t.audit.push({id:kr(),action:n,principal:r,...s.reviewId?{reviewId:s.reviewId}:{},...s.sourceKey?{sourceKey:s.sourceKey}:{},timestamp:new Date().toISOString(),...s.metadata?{metadata:s.metadata}:{}}),t.audit.length>vr&&(t.audit=t.audit.slice(-vr))}async mutate(t){let n,r=this.queue.then(async()=>{let s=await this.ensureState();n=await t(s),s.updatedAt=new Date().toISOString(),await this.store.save(s)});return this.queue=r.then(()=>{},()=>{}),await r,n}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(t,n){return this.mutate(r=>(r.policy=Ir({...r.policy,...t}),this.audit(r,"policy:update",n,{metadata:{...r.policy}}),{...r.policy}))}async summary(){let t=await this.ensureState(),n=r=>t.reviews.filter(s=>s.status===r).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:t.projectId,pending:n("pending"),approved:n("approved"),rejected:n("rejected"),superseded:n("superseded"),criticalPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="critical").length,conflictPending:t.reviews.filter(r=>r.status==="pending"&&r.risk==="conflict").length,auditEvents:t.audit.length,policy:{...t.policy},updatedAt:t.updatedAt}}async listReviews(t){let n=await this.ensureState();return structuredClone(n.reviews.filter(r=>!t||r.status===t).sort((r,s)=>s.updatedAt.localeCompare(r.updatedAt)))}async auditLog(t=100){let n=await this.ensureState(),r=Math.max(1,Math.min(500,Math.floor(t)));return structuredClone(n.audit.slice(-r).reverse())}async assess(t,n){let r=await this.ensureState(),s=va(t),o=Tt(t.title),i=n.filter(m=>m.slug!==t.slug&&Tt(m.title)===o&&br(m.content)!==br(t.content)).map(m=>m.slug),a=wa(t),c=[];s<r.policy.autoApproveThreshold&&c.push(`confidence:${s.toFixed(2)}`),a&&s<r.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let u=i.length>0?"conflict":a?"critical":"normal";return{confidence:s,risk:u,requiresReview:i.length>0||s<r.policy.autoApproveThreshold||a&&s<r.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(t,n){let r=await this.assess(t,n);return this.mutate(s=>{let o=s.reviews.find(c=>c.sourceKey===t.sourceKey&&c.digest===t.digest);if(o?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:r,review:structuredClone(o)};if(o?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:r,review:structuredClone(o)};if(!r.requiresReview)return this.audit(s,"knowledge:auto-approved","system",{sourceKey:t.sourceKey,metadata:{confidence:r.confidence,risk:r.risk}}),{allowed:!0,mode:"auto-approved",assessment:r};if(o?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(o)};let i=new Date().toISOString(),a={id:kr(),sourceKey:t.sourceKey,sourceType:t.sourceType,slug:t.slug,marker:t.marker,digest:t.digest,title:t.title,...t.summary?{summary:t.summary}:{},content:t.content,tags:[...new Set([...t.tags,t.marker])],confidence:r.confidence,risk:r.risk,reasons:[...r.reasons],conflicts:[...r.conflicts],status:"pending",createdAt:i,updatedAt:i};return s.reviews.push(a),this.audit(s,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:r,review:structuredClone(a)}})}async markApplied(t,n){await this.mutate(r=>{let s=r.reviews.find(o=>o.sourceKey===t&&o.digest===n&&o.status==="approved");s&&(s.appliedAt=new Date().toISOString(),s.updatedAt=s.appliedAt,this.audit(r,"knowledge:applied",s.reviewedBy??"system",{reviewId:s.id,sourceKey:t}))})}async decide(t,n,r){return this.mutate(async s=>{let o=s.reviews.find(u=>u.id===t);if(!o)throw new j(`Governance review not found: ${t}`,404);if(o.status!=="pending")throw new j("Governance review is already resolved",409);let i=new Date().toISOString();if(o.reviewedAt=i,o.reviewedBy=n.principal,o.updatedAt=i,n.note?.trim()&&(o.reviewNote=n.note.trim()),n.action==="reject")return o.status="rejected",this.audit(s,"knowledge:rejected",n.principal,{reviewId:t,sourceKey:o.sourceKey}),structuredClone(o);if(n.action==="supersede")return o.status="superseded",n.targetReviewId&&(o.supersededBy=n.targetReviewId),this.audit(s,"knowledge:superseded",n.principal,{reviewId:t,sourceKey:o.sourceKey,metadata:{targetReviewId:n.targetReviewId}}),structuredClone(o);if(n.action==="merge"){if(!n.targetReviewId)throw new j("targetReviewId is required for merge",400);let u=s.reviews.find(m=>m.id===n.targetReviewId);if(!u)throw new j("Merge target review not found",404);return o.status="superseded",o.mergedInto=u.id,this.audit(s,"knowledge:merged",n.principal,{reviewId:t,sourceKey:o.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(o)}o.status="approved";let c=(await r.listPages()).find(u=>u.slug===o.slug);if(c&&!c.tags.includes(o.marker))throw new j(`Wiki page '${o.slug}' is manually managed`,409);return c?await r.updatePage(o.slug,{title:o.title,summary:o.summary??"",content:o.content,tags:o.tags}):await r.createPage({slug:o.slug,title:o.title,...o.summary?{summary:o.summary}:{},content:o.content,tags:o.tags}),o.appliedAt=i,this.audit(s,"knowledge:approved",n.principal,{reviewId:t,sourceKey:o.sourceKey}),structuredClone(o)})}async quality(t){let n=await this.ensureState(),r=await t.listPages(),s=Date.now(),o=n.policy.staleAfterDays*864e5,i=r.map(m=>{let p=s-Date.parse(m.updatedAt);return{slug:m.slug,title:m.title,updatedAt:m.updatedAt,ageDays:Math.max(0,Math.floor(p/864e5)),stale:Number.isFinite(p)&&p>o}}).filter(m=>m.stale).map(({stale:m,...p})=>p),a=new Map;for(let m of r){let p=Tt(m.title),d=a.get(p)??[];d.push(m),a.set(p,d)}let c=[...a.entries()].filter(([,m])=>m.length>1).map(([m,p])=>({title:m,pages:p.map(d=>d.slug)})),u=n.reviews.filter(m=>m.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:r.length,automatedPages:r.filter(m=>m.tags.some(p=>p.startsWith("toolnet-auto-"))).length,manualPages:r.filter(m=>!m.tags.some(p=>p.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(m=>m.confidence<n.policy.autoApproveThreshold).length,conflicts:u.filter(m=>m.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var Or="wiki/automation.v1.json",Rr="toolnet.wiki-automation.v1",Nt=8e3,Ar=new Set(["raw","rawtext","raw_text","rawtranscript","raw_transcript","transcript","messages","message","payload","prompt","response","assistantmessage","assistant_message","userprompt","user_prompt"]);function Se(e){return ba("sha256").update(JSON.stringify(e)).digest("hex")}function he(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function Cr(e){return Array.isArray(e)?e:[]}function Nr(e){return typeof e!="string"?void 0:e.replace(/\s+/gu," ").trim()||void 0}function Ot(e){return Array.isArray(e)?e.map(Nr).filter(t=>!!t):[]}function W(e,t){for(let n of t){let r=Nr(e[n]);if(r)return r}}function ke(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 Je(e,t=0,n=""){if(t>3)return[];let r=n.replace(/[^a-z0-9]/giu,"").toLowerCase();if(Ar.has(r))return[];if(typeof e=="string"){let i=e.replace(/\s+/gu," ").trim();return i.length<8?[]:[i]}if(Array.isArray(e))return e.flatMap(i=>Je(i,t+1,n));let s=he(e);if(!s)return[];let o=[];for(let[i,a]of Object.entries(s)){let c=i.replace(/[^a-z0-9]/giu,"").toLowerCase();Ar.has(c)||o.push(...Je(a,t+1,i))}return o}function Pr(e){let n=ke(["content","summary","text","value","statement","description","decision","task","knowledge","context","outcome","reason","rationale"].flatMap(s=>Je(e[s],0,s)));return(n.length>0?n:ke(Je(e))).join(`
|
|
126
126
|
|
|
127
|
-
`).slice(0,
|
|
127
|
+
`).slice(0,Nt)}function Er(e,t){return W(e,["id","key","fingerprint","knowledgeId","sceneId"])??t}function Mr(e,t){return W(e,["title","name","topic","label","task","kind","type"])??t}function Ca(e){return(W(e,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function Pa(e){return(W(e,["kind","sceneKind","type"])??"").toLowerCase()}function Ea(e){let t=he(e);if(!t)return[];let n=[],r=Cr(t.knowledge);for(let[o,i]of r.entries()){let a=he(i);if(!a)continue;let c=Ca(a);if(c==="session"||c==="transient")continue;let u=Pr(a);if(u.length<20)continue;let m=Er(a,Se(a).slice(0,16)),p=Mr(a,`Durable Memory ${o+1}`);n.push({sourceKey:`memory:${m}`,sourceType:"memory",title:p,summary:W(a,["summary","description"]),content:u,tags:ke(["toolnet","auto","memory",...c?[c]:[]])})}let s=Cr(t.scenes);for(let[o,i]of s.entries()){let a=he(i);if(!a)continue;let c=Pa(a);if(c==="session-context")continue;let u=Pr(a);if(u.length<20)continue;let m=Er(a,Se(a).slice(0,16)),p=Mr(a,`Knowledge Scene ${o+1}`);n.push({sourceKey:`scene:${m}`,sourceType:"scene",title:p,summary:W(a,["summary","description"]),content:u,tags:ke(["toolnet","auto","scene",...c?[c]:[]])})}return n}function Ma(e){return Tr(e,".toolnet","memory","skills")}function Ta(e){let t=Ma(e);if(!xa(t))return{candidates:[],failed:0};let n=[],r=0,s=ja(t).filter(o=>o.endsWith(".json")).sort();for(let o of s)try{let i=JSON.parse(Ia(Tr(t,o),"utf8")),a=he(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let c=W(a,["id","fingerprint"])??Aa(o,".json"),u=W(a,["task"])??"",m=W(a,["title"])||u||`Reusable Skill ${c.slice(0,8)}`,p=W(a,["summary"])??void 0,d=Ot(a.steps),l=Ot(a.verification),g=Ot(a.files),S=[];u&&S.push(`## Task
|
|
128
128
|
${u}`),p&&S.push(`## Summary
|
|
129
129
|
${p}`),d.length>0&&S.push(`## Procedure
|
|
130
130
|
${d.map((h,k)=>`${k+1}. ${h}`).join(`
|
|
@@ -134,23 +134,23 @@ ${l.map(h=>`- ${h}`).join(`
|
|
|
134
134
|
${g.map(h=>`- \`${h}\``).join(`
|
|
135
135
|
`)}`);let y=S.join(`
|
|
136
136
|
|
|
137
|
-
`).slice(0,
|
|
138
|
-
`).slice(0,
|
|
139
|
-
`,{encoding:"utf8",mode:384}),
|
|
140
|
-
`,c=w(r.map(m=>m.fingerprint).sort().join("|")).slice(0,16),u=[
|
|
141
|
-
`,"application/json"),c}};function
|
|
137
|
+
`).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(`
|
|
138
|
+
`).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=Ea(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]),T=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:T,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:T,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:T,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 O=new Date().toISOString(),x={sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,digest:S,marker:g,updatedAt:O},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)+`
|
|
139
|
+
`,{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)+`
|
|
140
|
+
`,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)}
|
|
141
|
+
`,"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(`
|
|
142
142
|
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
143
|
-
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var
|
|
144
|
-
`))))}function
|
|
145
|
-
`).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
|
|
146
|
-
`,a=w(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${t.projectId}`,"work","observations",t.agent,t.nativeSessionId,`${
|
|
147
|
-
`,"application/json"),
|
|
143
|
+
`).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 Mc,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(`
|
|
144
|
+
`))))}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(`
|
|
145
|
+
`).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)+`
|
|
146
|
+
`,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 Ec(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 Ec(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=[],T=[],P=[],O=[];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":T.push(f.text);break;case"test":P.push(f.text),f.checkKind&&O.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(T,20),tests:L(P,20),checks:Cc(O,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}),R(Qr(ce,"current.json"),ae),await t.put(`projects/${e.id}/work/current.json`,JSON.stringify(ae,null,2)+`
|
|
147
|
+
`,"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{Mc(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
148
148
|
`);if(c<0)return{events:[],nextOffset:r};let u=a.slice(0,c+1);return{events:u.split(`
|
|
149
|
-
`).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var
|
|
150
|
-
`,"application/json"),a}};import{mkdirSync as
|
|
151
|
-
`,"application/json"),l}function
|
|
149
|
+
`).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 K(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(K(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(K(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(K(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(K(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(K(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(K(e,o,"phase_deliverable",M,c,.97)),u=null;continue}let T=D(p,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(T){s(K(e,o,"acceptance_criterion",T,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(K(e,o,"dependency",P,c,.97)),u="dependency";continue}let O=D(p,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(O){s(K(e,o,"open_question",O,c,.95)),u="open_question";continue}let x=D(p,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(x){s(K(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(K(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)+`
|
|
150
|
+
`,"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}),R(ss(g,"semantic-current.json"),l),await t.put(`projects/${e.id}/work/semantic/current.json`,JSON.stringify(l,null,2)+`
|
|
151
|
+
`,"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(`
|
|
152
152
|
`);if(a<0)return{events:[],nextOffset:r};let c=i.slice(0,a+1);return{events:c.split(`
|
|
153
|
-
`).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var
|
|
153
|
+
`).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
|
|
154
154
|
|
|
155
155
|
This file contains persistent instructions for AI agents working on this project.
|
|
156
156
|
|
|
@@ -193,14 +193,14 @@ Things an AI agent should always remember.
|
|
|
193
193
|
<!--
|
|
194
194
|
- [advisory] Prefer small focused files.
|
|
195
195
|
-->
|
|
196
|
-
`;function
|
|
197
|
-
`,{encoding:"utf8",mode:384}),
|
|
198
|
-
`).toLowerCase();return/(?:failed|failing|failure|error|✗|❌)/u.test(r)?"failing":/(?:passed|passing|green|success|✓|✅)/u.test(r)?"passing":"unknown"}function
|
|
196
|
+
`;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)}
|
|
197
|
+
`,{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 $(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=[],T=[],P=[],O=[...t].sort((f,b)=>{let V=f.occurredAt.localeCompare(b.occurredAt);return V!==0?V:f.sequence-b.sequence});for(let f of O)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":T.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=$(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=$(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=O.length>0?O[O.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:$(n?.decisions??[],m,20),blockers:lt,warnings:$(n?.warnings??[],d,20),nextActions:ut,filesTouched:$(n?.filesTouched??[],g,30),activeFiles:$([],S,5),modifiedFiles:$(n?.modifiedFiles??[],y,30),createdFiles:$(n?.createdFiles??[],h,30),deletedFiles:$(n?.deletedFiles??[],k,30),commands:$(n?.commands??[],M,20),tests:$(n?.tests??[],T,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(`
|
|
198
|
+
`).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)||R(r,t),R(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)+`
|
|
199
199
|
`,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(s,null,2)+`
|
|
200
|
-
`,"application/json"),s}};import{existsSync as
|
|
201
|
-
`)}function
|
|
200
|
+
`,"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(`
|
|
201
|
+
`)}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(`
|
|
202
202
|
|
|
203
203
|
`):a=r.trim()?`${r.trim()}
|
|
204
204
|
|
|
205
|
-
${s}`:s,
|
|
206
|
-
`,{encoding:"utf8",mode:384})}import{existsSync as xs,mkdirSync as ku,readFileSync as wu}from"node:fs";import{join as Lt}from"node:path";function js(e){return Lt(e.rootPath,".toolnet","memory","checkpoints")}function Cs(e){return Lt(js(e),"latest.json")}function vu(e){let t=Cs(e);if(!xs(t))return null;try{let n=JSON.parse(wu(t,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==e.id?null:n}catch{return null}}function bu(e){return["rule","architecture","decision","fix"].includes(e)}function xu(e,t){return t.length===0?[]:Fe(e,t).candidates.filter(r=>bu(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 ju(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 Cu(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 As(e,t,n,r){let s=vu(e),o=ju(s?.durableFacts??[],xu(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:Cu(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=js(e);ku(g,{recursive:!0,mode:448});let S=Lt(g,`${d}.json`);return xs(S)||O(S,l),O(Cs(e),l),l}function rt(e,t,n){if(process.env.TOOLNET_LOCAL_CHECKPOINT==="0"||n.length===0)return{updated:!1,observations:0};let r=Ue(t,n);if(r.length===0)return{updated:!1,observations:0};let s=fs(e,r);bs(e,s),qn(e,{agent:t.agent,nativeSessionId:t.nativeSessionId,observations:r,workState:s});try{As(e,t,n,s)}catch{}try{ks({project:e,identity:t,state:s,reason:"continuous-checkpoint",sequence:n.at(-1)?.sequence??0})}catch{}return{updated:!0,observations:r.length}}var st=class{identity;wal;remote;sanitizer=new U;learner;continuity;semantic;handoff;project;title;metadata;constructor(t){this.project=t.project,this.identity=Ke(t.project,t.agent,t.nativeSessionId),this.title=t.title,this.metadata=this.sanitizer.sanitizeValue(t.metadata??{}),this.wal=new ne(this.identity,t.eventContext),this.remote=new $e(t.storage,t.maxEventsPerChunk??100,t.maxChunkBytes??512*1024),this.learner=new Be({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.continuity=new Qe({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.semantic=new et({project:t.project,storage:t.storage,identity:this.identity,wal:this.wal}),this.handoff=new nt({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{rt(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 ot=4e3,Dt=20,zt=30,Is=4,qt=20;function Ht(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function it(e,t=0){if(t>=Is)return typeof e=="string"?e.length>ot?`${e.slice(0,ot)}\u2026`:e:Array.isArray(e)?`[array:${e.length}]`:Ht(e)?`[object:${Object.keys(e).length}]`:e;if(typeof e=="string")return e.length>ot?`${e.slice(0,ot)}\u2026`:e;if(Array.isArray(e)){let n=e.slice(0,Dt).map(r=>it(r,t+1));return e.length>Dt&&n.push(`[+${e.length-Dt} items]`),n}if(Ht(e)){let n={},r=Object.entries(e);for(let[s,o]of r.slice(0,zt))n[s]=it(o,t+1);return r.length>zt&&(n.__truncatedKeys=r.length-zt),n}return e}function Jt(e,t,n=0){if(!(n>Is||t.size>=qt)){if(Array.isArray(e)){for(let r of e)if(Jt(r,t,n+1),t.size>=qt)break;return}if(Ht(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()),Jt(s,t,n+1),t.size>=qt)break}}}function je(e){try{return w(Ie(e)).slice(0,20)}catch{return w(String(e)).slice(0,20)}}function Au(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 Iu(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 Vt(e,t){let r={timestamp:Au(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:`+je(s),data:{content:s}}]:[]}if(e.event==="PostToolUse"){let s=new Set;Jt(e.toolInput,s);let o=[...s],i=Iu(e.toolName,o);if(!i)return[];let a=it(e.toolInput),c=it(e.toolResponse);return[{...r,type:i,sourceEventId:[e.agent,e.sessionId,"tool",je({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:`+je(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:`+je(o),data:{content:o}}),s.push({...r,type:"session_idle",sourceEventId:`${e.agent}:${e.sessionId}:idle:`+je({sessionId:e.sessionId,response:o??""}),data:{sessionId:e.sessionId}}),s}return[]}function Eu(e){let t=ht(e);if(!t||!Pu(Mu(t,".toolnet","project.json")))return null;try{return new Ee().detect(t)}catch{return null}}function Tu(e,t){let n=Vt(t,e);if(n.length===0)return 0;let r=Ke(e,t.agent,t.sessionId),o=new ne(r,{source:t.agent,cwd:t.cwd}).append(n);return rt(e,r,o),o.length}async function Ou(e,t,n,r){let s=Pe(),o=Fn($n({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),{attempts:2}),i=new Ne(o,e.id,e.name,e.remote??e.name);await new st({project:e,storage:i,agent:t,nativeSessionId:n,metadata:{source:`${t}-hook`},eventContext:{source:t,cwd:r}}).flush()}async function Ps(e,t={}){if(!e.cwd||!e.sessionId)return{active:!1,captured:0,flushed:!1};let n=Eu(e.cwd);if(!n)return{active:!1,captured:0,flushed:!1};let r=0;try{r=Tu(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{Jn(n)}catch{}if(e.event!=="Stop")return{active:!0,projectRoot:n.rootPath,sessionId:e.sessionId,captured:r,flushed:!1};let s=t.flushSession??Ou;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 Ms(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Ce(...e){for(let t of e){let n=Ms(t);if(n)return n}}function Ru(e){switch(Ms(e)){case"sessionStart":case"SessionStart":return"SessionStart";case"beforeSubmitPrompt":case"UserPromptSubmit":case"userPromptSubmit":return"UserPromptSubmit";case"postToolUse":case"PostToolUse":return"PostToolUse";case"afterAgentResponse":return"AssistantMessage";case"stop":case"Stop":return"Stop";default:return null}}function Es(e,t=process.env){let n=Ru(t.TOOLNET_HOOK_EVENT??e.hook_event_name??e.hookEventName);if(!n)return null;let r=Ce(e.session_id,e.sessionId,e.conversation_id,t.TOOLNET_CURSOR_SESSION_ID),s=Ce(e.cwd,e.workspaceRoot,t.CURSOR_PROJECT_DIR,t.CLAUDE_PROJECT_DIR);return!r||!s?null:{agent:"cursor",event:n,sessionId:r,cwd:s,timestamp:typeof e.timestamp=="string"||typeof e.timestamp=="number"?e.timestamp:void 0,prompt:Ce(e.prompt),toolName:Ce(e.tool_name,e.toolName,e.tool),toolInput:e.tool_input??e.toolInput??e.tool_args??e.toolArgs??e.input,toolResponse:e.tool_response??e.tool_result??e.toolResult??e.result??e.output,assistantResponse:Ce(e.text,e.assistant_response,e.assistantResponse,e.last_assistant_message)}}async function Ts(e,t={},n=process.env){let r=Es(e,n);return r?Ps(r,t):{active:!1,captured:0,flushed:!1}}async function Nu(){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 _u(){let e=await Nu(),t=Cn(e);if(t==="preToolUse"||t==="PreToolUse"){let n=Pn(e);n.blocked&&(process.stdout.write(JSON.stringify(Mn(n.reason??"ToolNet continuity guard blocked this tool."))),process.exitCode=2);return}if(await Ts(e),t==="sessionStart"||t==="SessionStart"){process.stdout.write(JSON.stringify(An(e)));return}(t==="beforeSubmitPrompt"||t==="UserPromptSubmit")&&In(e)}_u().catch(()=>{process.exitCode=0});
|
|
205
|
+
${s}`:s,xu(n,`${a.trim()}
|
|
206
|
+
`,{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 Eu(e){return["rule","architecture","decision","fix"].includes(e)}function Mu(e,t){return t.length===0?[]:Le(e,t).candidates.filter(r=>Eu(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 Es(e,t,n,r){let s=Pu(e),o=Tu(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: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)||R(S,l),R(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{Es(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,Ms=4,Jt=20;function Vt(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function at(e,t=0){if(t>=Ms)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>Ms||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=Ee(),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"beforeSubmitPrompt":case"UserPromptSubmit":case"userPromptSubmit":return"UserPromptSubmit";case"postToolUse":case"PostToolUse":return"PostToolUse";case"afterAgentResponse":return"AssistantMessage";case"stop":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,e.conversation_id,t.TOOLNET_CURSOR_SESSION_ID),s=Ae(e.cwd,e.workspaceRoot,t.CURSOR_PROJECT_DIR,t.CLAUDE_PROJECT_DIR);return!r||!s?null:{agent:"cursor",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,e.tool),toolInput:e.tool_input??e.toolInput??e.tool_args??e.toolArgs??e.input,toolResponse:e.tool_response??e.tool_result??e.toolResult??e.result??e.output,assistantResponse:Ae(e.text,e.assistant_response,e.assistantResponse,e.last_assistant_message)}}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."))),process.exitCode=2);return}if(!(t&&$s({agent:"cursor",event:t,input:e,directory:process.env.TOOLNET_HOOK_DEDUPE_DIR}).duplicate)){if(await Ns(e),t==="sessionStart"||t==="SessionStart"){process.stdout.write(JSON.stringify(En(e)));return}(t==="beforeSubmitPrompt"||t==="UserPromptSubmit")&&Mn(e)}}sl().catch(()=>{process.exitCode=0});
|