toolnet-memory 0.3.9 → 0.3.10
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 +8 -1
- package/bin/toolnet-memory +48 -0
- package/bundle/auto-integrate.js +60 -28
- package/bundle/continuity-certify.js +1 -1
- package/bundle/copilot-hook.js +208 -0
- package/bundle/copilot.js +33 -0
- package/bundle/cursor-hook.js +206 -0
- package/bundle/cursor.js +33 -0
- package/bundle/grok-hook.js +114 -0
- package/bundle/grok.js +33 -0
- package/bundle/help-cli.js +4 -4
- package/bundle/init.js +65 -33
- package/bundle/kiro-hook.js +1 -1
- package/bundle/production-certify.js +5 -5
- package/bundle/setup.js +61 -29
- package/bundle/status-cli.js +4 -4
- package/bundle/update.js +5 -4
- package/package.json +16 -3
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import*as $ from"fs";import*as R from"path";function ut(e){return e?Math.ceil(e.length/3.5):0}function lt(e,t){if(!e)return"";if(ut(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 Gt(e,t){if(!e)return"";let n=e.split(`
|
|
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 Os(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
|
+
|
|
6
|
+
`,m=ut(u),p=ut(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=lt(c.content,l);o.push(u+g),i=n,a=!0}else a=!0;break}}return a&&o.push(`
|
|
7
|
+
${r}
|
|
8
|
+
`),o.join(`
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
`)}function Ut(e,t){let n=[{title:"Profile",content:Gt(e,10),priority:100},{title:"Current Work",content:Gt(t,15),priority:90}];return Os(n,{maxTokens:800})}import{createHash as Rs}from"node:crypto";import{chmodSync as Xt,existsSync as Ns,mkdirSync as _s,readFileSync as Ks,renameSync as $s,writeFileSync as Qt}from"node:fs";import{dirname as Zt,join as Ae}from"node:path";var mt="toolnet.context-offload.v1",Ws="toolnet.context-offload-asset.v1",Fs=256,Ls=new Set(["tool_call","tool_result","file_read","file_write","file_edit","command","test","artifact"]);function en(e){return Ae(e,".toolnet","offload")}function Ds(e){return Ae(en(e),"assets")}function tn(e){return Ae(en(e),"graph.json")}function nn(e){_s(e,{recursive:!0,mode:448});try{Xt(e,448)}catch{}}function zs(e,t){nn(Zt(e));let n=`${e}.${process.pid}.${Date.now()}.tmp`;Qt(n,t,{encoding:"utf8",mode:384}),$s(n,e);try{Xt(e,384)}catch{}}function pt(e){return Array.isArray(e)?e.map(pt):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,pt(n)])):e}function qs(e){return Rs("sha256").update(JSON.stringify(pt(e)),"utf8").digest("hex")}function dt(){return{schema:mt,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function rn(e){let t=tn(e);if(!Ns(t))return dt();try{let n=JSON.parse(Ks(t,"utf8"));return n.schema!==mt||n.version!==1||!Array.isArray(n.nodes)?dt():n}catch{return dt()}}function Hs(e,t){zs(tn(e),JSON.stringify(t,null,2)+`
|
|
13
|
+
`)}function Js(e,t=260){if(typeof e!="string")return null;let n=e.replace(/\s+/gu," ").trim();return n?n.slice(0,t):null}function Vs(e){let t=[...e.provenance.files??[],e.provenance.sourcePath],n=[];for(let r of t){let s=Js(r);if(!(!s||n.includes(s))&&(n.push(s),n.length===3))break}return n}function Bs(e){return`${e.agent}:${e.sourceEventId??e.id}`.replace(/\s+/gu," ").trim().slice(0,120)}function Gs(e,t){nn(Zt(e));try{return Qt(e,t,{encoding:"utf8",flag:"wx",mode:384}),!0}catch(n){if(n.code==="EEXIST")return!1;throw n}}function Us(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:mt,version:1,updatedAt:new Date().toISOString(),nodes:[...e.nodes.filter(s=>s.id!==t.id),r].slice(-Fs)}}function sn(e,t){let n=rn(e),r=0,s=0,o=0,i=[];for(let a of t){if(!Ls.has(a.type))continue;r+=1;let c=qs({type:a.type,data:a.data}),u={schema:Ws,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
|
+
`;Gs(Ae(Ds(e),`${c}.json`),m)?s+=1:o+=1,i.push(c),n=Us(n,{id:c,kind:a.type,bytes:Buffer.byteLength(m,"utf8"),createdAt:a.timestamp,sourceRefs:[Bs(a)],files:Vs(a)})}return r>0&&Hs(e,n),{eligible:r,written:s,deduped:o,graphNodes:n.nodes.length,assetIds:i}}function Yt(e,t){let n=e.replace(/\s+/gu," ").trim();return n.length<=t?n:n.slice(0,t-1).trimEnd()+"\u2026"}function on(e,t={}){let n=rn(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=Yt(i.sourceRefs.at(-1)??"unknown",72),c=i.files.length>0?` files=${Yt(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
|
+
`).length>s)break;o.push(u)}return o.join(`
|
|
16
|
+
`)}import{existsSync as cn,mkdirSync as no,readFileSync as un,renameSync as ro,writeFileSync as so}from"node:fs";import{dirname as oo,join as ln}from"node:path";import{createHash as Ys}from"node:crypto";import{dirname as Xs}from"node:path";import{mkdirSync as Qs,readFileSync as Zs,renameSync as eo,writeFileSync as to}from"node:fs";function w(e){return Ys("sha256").update(e).digest("hex")}function ft(e){if(Array.isArray(e))return e.map(ft);if(e&&typeof e=="object"){let t=e,n={};for(let r of Object.keys(t).sort())n[r]=ft(t[r]);return n}return e}function Ie(e){return JSON.stringify(ft(e))}function an(e){try{return JSON.parse(Zs(e,"utf8"))}catch{return null}}function O(e,t){Qs(Xs(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;to(n,JSON.stringify(t,null,2)+`
|
|
17
|
+
`,{encoding:"utf8",mode:384}),eo(n,e)}function dn(e){return ln(e.rootPath,".toolnet","context","handoff.md")}function pn(e){return ln(e.rootPath,".toolnet","context","handoff.json")}function mn(e,t){no(oo(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;so(n,t.endsWith(`
|
|
18
|
+
`)?t:`${t}
|
|
19
|
+
`,{encoding:"utf8",mode:384}),ro(n,e)}function io(e,t){mn(e,`${JSON.stringify(t,null,2)}
|
|
20
|
+
`)}function fn(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 mn(dn(e),n),io(pn(e),r),r}function gt(e){let t=dn(e);if(!cn(t))return null;try{let n=un(t,"utf8").trim();if(!n)return null;let r=new Date(0).toISOString(),s=pn(e);if(cn(s))try{let o=JSON.parse(un(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 gn(e,t=1800){let n=gt(e);if(!n?.text)return null;let r=n.text;return r.length>t&&(r=`${r.slice(0,t)}
|
|
22
|
+
|
|
23
|
+
[Fast handoff truncated]`),["[TOOLNET FAST HANDOFF]","",`Project: ${e.name}`,`Updated: ${n.generatedAt}`,"",r].join(`
|
|
24
|
+
`)}var yt="memory_agent_ask";function yn(){return`
|
|
25
|
+
[TOOLNET MEMORY AGENT]
|
|
26
|
+
|
|
27
|
+
Tool:
|
|
28
|
+
- ${yt}
|
|
29
|
+
|
|
30
|
+
For resume/continue requests:
|
|
31
|
+
|
|
32
|
+
1. Use the injected ToolNet continuity handoff FIRST.
|
|
33
|
+
2. If the handoff is missing or ambiguous, invoke
|
|
34
|
+
${yt} directly BEFORE repository/history exploration.
|
|
35
|
+
3. NEVER reconstruct prior work from:
|
|
36
|
+
- .toolnet/sessions/**
|
|
37
|
+
- state.json
|
|
38
|
+
- events.jsonl
|
|
39
|
+
- raw transcripts
|
|
40
|
+
4. NEVER search for the implementation/schema of
|
|
41
|
+
${yt}; invoke the MCP tool directly.
|
|
42
|
+
5. Inspect git/source only AFTER continuity context is known.
|
|
43
|
+
|
|
44
|
+
Use:
|
|
45
|
+
- mode="local" for current task, last file, blocker or next action.
|
|
46
|
+
- mode="ai" for ambiguous or combined continuity questions.
|
|
47
|
+
|
|
48
|
+
Current repository evidence overrides stale memory.
|
|
49
|
+
`.trim()}function ht(e){let t=R.resolve(e),n=R.parse(t).root;for(;t!==n;){let r=R.join(t,".toolnet");if($.existsSync(r)&&$.statSync(r).isDirectory())return t;t=R.dirname(t)}return null}function hn(e){try{return $.existsSync(e)?$.readFileSync(e,"utf-8").trim():null}catch{return null}}function Sn(e){return e.split(`
|
|
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 kn(e={}){let t=e.projectPath||process.cwd(),n=ht(t);if(!n)return null;let r=R.join(n,".toolnet","project.json"),s="Unknown";try{if($.existsSync(r)){let y=JSON.parse($.readFileSync(r,"utf-8"));s=y.name||y.projectName||"Unknown"}}catch{}let o=R.join(n,".toolnet","profile.md"),i=R.join(n,".toolnet","current.md"),a=hn(o)||"",c=hn(i)||"";a=Sn(a),c=Sn(c);let u=`[TOOLNET PROJECT CONTEXT]
|
|
52
|
+
|
|
53
|
+
Project: ${s}
|
|
54
|
+
Root: ${n}
|
|
55
|
+
|
|
56
|
+
`,m=Ut(a,c),p=gn({id:"",name:s,rootPath:n},1600),d=p?`
|
|
57
|
+
|
|
58
|
+
${p}
|
|
59
|
+
`:"",l=on(n,{maxAssets:6,maxChars:900}),g=l?`
|
|
60
|
+
|
|
61
|
+
${l}
|
|
62
|
+
`:"",S=`
|
|
63
|
+
|
|
64
|
+
${yn()}
|
|
65
|
+
|
|
66
|
+
Forbidden At Startup:
|
|
67
|
+
- Do not run session:agy-recover, handoff:latest, or brief automatically.
|
|
68
|
+
- Do not perform deep recovery merely because an agent starts.
|
|
69
|
+
- If the user asks to resume previous work and fast context is insufficient,
|
|
70
|
+
use memory_agent_ask before guessing.
|
|
71
|
+
`;return u+m+d+g+S}var wn=6500,ao=[/\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 bn(e,t){return e.length<=wn?e:`${e.slice(0,wn)}
|
|
72
|
+
|
|
73
|
+
[ToolNet ${t} context truncated]`}function vn(e){return e.replace(/\\/g,"/").toLowerCase()}function St(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(St(r,t,n+1),t.length>=250)break;return}if(e&&typeof e=="object"){for(let r of Object.values(e))if(St(r,t,n+1),t.length>=250)break}}}function co(e){let t=vn(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&&vn(n)===t)}function uo(e){let t=e.trim();return t?ao.some(n=>n.test(t)):!1}function kt(e,t){if(!e.trim())return"";let n="";try{n=kn({projectPath:e})?.trim()??""}catch{n=""}let r=`
|
|
74
|
+
[TOOLNET CONTINUITY]
|
|
75
|
+
|
|
76
|
+
ToolNet Memory is the continuity source for this repository.
|
|
77
|
+
|
|
78
|
+
When the user asks to continue, resume, pick up, or finish previous work:
|
|
79
|
+
1. Use this injected ToolNet fast handoff first.
|
|
80
|
+
2. If the handoff is missing, stale, or ambiguous, invoke the MCP tool
|
|
81
|
+
memory_agent_ask before exploring prior history.
|
|
82
|
+
3. Prefer mode="local" for current task, last file, blocker, completed work,
|
|
83
|
+
TODOs, and next action.
|
|
84
|
+
4. Use mode="ai" only when continuity requires synthesis.
|
|
85
|
+
5. Never reconstruct prior work from .toolnet/sessions/**, events.jsonl,
|
|
86
|
+
state.json, raw transcripts, or another agent's private history.
|
|
87
|
+
6. After continuity is known, verify current git/source truth and continue.
|
|
88
|
+
7. Do not ask the user to repeat context ToolNet already provides.
|
|
89
|
+
|
|
90
|
+
Current repository evidence overrides stale memory.
|
|
91
|
+
`.trim();return bn(n?`${n}
|
|
92
|
+
|
|
93
|
+
${r}`:r,t)}function xn(e,t,n){if(!uo(e))return"";let r=kt(t,n),s=`
|
|
94
|
+
[TOOLNET RESUME REQUEST]
|
|
95
|
+
|
|
96
|
+
The current user message explicitly asks to continue previous work.
|
|
97
|
+
Use memory_agent_ask now if the fast handoff does not contain a clear,
|
|
98
|
+
current next action. Do not reconstruct continuity from raw session files.
|
|
99
|
+
`.trim();return bn(r?`${r}
|
|
100
|
+
|
|
101
|
+
${s}`:s,n)}function jn(e){let t=[];return St(e,t),t.find(co)?{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 I(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function Cn(e,t=process.env){return I(t.TOOLNET_HOOK_EVENT)??I(e.hook_event_name)??I(e.hookEventName)??""}function An(e,t=process.env){let n=I(e.session_id)??I(e.sessionId)??I(e.conversation_id)??I(t.TOOLNET_CURSOR_SESSION_ID)??"",r=I(e.cwd)??I(e.workspaceRoot)??I(t.CURSOR_PROJECT_DIR)??I(t.CLAUDE_PROJECT_DIR)??"",s=kt(r,"Cursor"),o={env:{TOOLNET_CURSOR_SESSION_ID:n}};return s&&(o.additional_context=s),o}function In(e,t=process.env){let n=I(e.prompt)??"",r=I(e.cwd)??I(e.workspaceRoot)??I(t.CURSOR_PROJECT_DIR)??I(t.CLAUDE_PROJECT_DIR)??"";return xn(n,r,"Cursor")}function Pn(e){return jn(e.tool_input??e.toolInput??e.updated_input??e)}function Mn(e){return{permission:"deny",user_message:e,agent_message:e}}import{existsSync as Pu}from"node:fs";import{join as Mu}from"node:path";import{existsSync as lo,readFileSync as po}from"node:fs";import{homedir as mo}from"node:os";import{join as fo}from"node:path";function go(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 yo(){let e=process.env.TOOLNET_GLOBAL_ENV??fo(mo(),".config","toolnet-memory",".env");if(!lo(e))return;let t=po(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]=go(r.slice(s+1)))}}yo();function ce(e,t){return e===void 0?t:["1","true","yes","on"].includes(e.toLowerCase())}function ue(e,t){if(!e)return t;let n=Number(e);return Number.isFinite(n)?n:t}function Pe(){return{memory:{autoCapture:ce(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:ce(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:ce(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:ce(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:ue(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:ue(process.env.MEMORY_RERANK_TOP,10),finalContext:ue(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:ue(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:ce(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:ue(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ho}from"node:crypto";import{existsSync as wt,mkdirSync as So,readFileSync as ko,renameSync as wo,writeFileSync as vo}from"node:fs";import{basename as bo,dirname as Me,join as Te,parse as On,resolve as le}from"node:path";var Rn=".toolnet",xo="project.json";function jo(e){return ho("sha256").update(e).digest("hex").slice(0,16)}function vt(e){return Te(e,Rn,xo)}function Co(e){return wt(vt(e))}function Ao(e,t){let n=le(e),r=On(n).root;for(;;){if(Co(n))return n;if(n===r||t&&n===le(t))break;let s=Me(n);if(s===n)break;n=s}return null}function Io(e){let t=le(e),n=On(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>wt(Te(t,o))))return t;if(t===n)break;let s=Me(t);if(s===t)break;t=s}return le(e)}function Po(e){let t;try{t=JSON.parse(ko(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 En(e,t){let n=Te(e,Rn);So(n,{recursive:!0});let r=vt(e),s=`${r}.tmp-${process.pid}`;vo(s,JSON.stringify(t,null,2)+`
|
|
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=Dn(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 di,readFileSync as pi}from"node:fs";import{join as mi}from"node:path";import{existsSync as ni,mkdirSync as ri,readFileSync as si,renameSync as oi,writeFileSync as ii}from"node:fs";import{dirname as ai,join as ci}from"node:path";function zn(e){return ci(e.rootPath,".toolnet","context","session-origin.json")}function ui(e,t){ri(ai(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;ii(n,`${JSON.stringify(t,null,2)}
|
|
105
|
+
`,{encoding:"utf8",mode:384}),oi(n,e)}function _e(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 qn(e,t){let n=_e(t.observations,"file"),r=_e(t.observations,"next_action"),s=_e(t.observations,"blocker"),o=_e(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 ui(zn(e),i),i}function li(e){let t=zn(e);if(!ni(t))return null;try{let n=JSON.parse(si(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function Hn(e){let t=li(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 fi(e){let t=mi(e.rootPath,".toolnet","current.md");if(!di(t))return null;try{return pi(t,"utf8").trim()}catch{return null}}function gi(e,t){let n=t.replace(/\r\n/g,`
|
|
107
|
+
`).trim(),r=2400,s=n.length>r?`${n.slice(0,r)}
|
|
108
|
+
|
|
109
|
+
[Current work truncated for fast handoff]`:n,o=Hn(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 Jn(e){let t=fi(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=gi(e,t);return gt(e)?.text.trim()===n.trim()?{updated:!1,reason:"unchanged",chars:n.length}:(fn(e,n),{updated:!0,reason:"updated",chars:n.length})}import{join as yi}from"node:path";function Vn(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 Ke(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=Vn(r.toLowerCase(),"agent"),i=Vn(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:yi(e.rootPath,".toolnet","sessions",o,i)}}function Bn(e){return String(e).padStart(12,"0")}var $e=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
|
+
`,"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],P=y.map(T=>JSON.stringify(T)).join(`
|
|
113
|
+
`)+`
|
|
114
|
+
`,E=w(P).slice(0,16),A=[t.remotePrefix,"events",`${Bn(h.sequence)}-${Bn(k.sequence)}-${E}.jsonl`].join("/");await this.storage.exists(A)||await this.storage.put(A,P,"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 jt,existsSync as bi,fsyncSync as xi,mkdirSync as ji,openSync as Ct,readSync as Ci,rmSync as Un,statSync as Yn,writeSync as Ai}from"node:fs";import{join as At}from"node:path";var hi=new Set(["thinking","reasoning","reasoningcontent","chainofthought","cot","analysistext","internalreasoning","modelthinking"]),Si=new Set(["reasoning","thinking","chain_of_thought","chain-of-thought","internal_reasoning","internal-reasoning"]);function ki(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,"")}function wi(e){for(let t of["type","kind"]){let n=e[t];if(typeof n=="string"){let r=n.toLowerCase();if(Si.has(r))return n}}return null}function xt(e,t=0){if(t>12)return"[ToolNet nested value omitted]";if(Array.isArray(e))return e.map(o=>xt(o,t+1));if(!e||typeof e!="object")return e;let n=e,r=wi(n);if(r)return{type:r,omitted:"[private reasoning omitted]"};let s={};for(let[o,i]of Object.entries(n))hi.has(ki(o))||(s[o]=xt(i,t+1));return s}function vi(e){if(!e)return new Date().toISOString();let t=new Date(e);return Number.isNaN(t.getTime())?new Date().toISOString():t.toISOString()}function Y(e){return e?.trim()||void 0}function Gn(e,t={}){let n={...e.provenance??{}},r=Y(e.source)??Y(t.source)??Y(n.source);return{...e,timestamp:vi(e.timestamp),source:r,turnId:Y(e.turnId)??Y(t.turnId),cwd:Y(e.cwd)??Y(t.cwd),data:xt(e.data??{}),provenance:n}}var Ii=12e4,Pi=80,Mi=2e3;function Ei(e){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}var ne=class{constructor(t,n={}){this.identity=t;this.eventContext=n;ji(t.localDirectory,{recursive:!0}),this.eventsFile=At(t.localDirectory,"events.jsonl"),this.stateFile=At(t.localDirectory,"state.json"),this.lockFile=At(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 an(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(t){O(this.stateFile,t)}acquireLock(){for(let t=0;t<Pi;t+=1)try{return Ct(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-Yn(this.lockFile).mtimeMs>Ii){Un(this.lockFile,{force:!0});continue}}catch{}Ei(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(t){let n=this.acquireLock();try{return t()}finally{jt(n),Un(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=Gn(p,this.eventContext),l=d.timestamp??new Date().toISOString(),g=d.data??{},S=d.provenance?.rawDigest??w(Ie(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
|
+
`)+`
|
|
116
|
+
`,a=Ct(this.eventsFile,"a",384);try{Ai(a,i,null,"utf8"),xi(a)}finally{jt(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(-Mi);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(!bi(this.eventsFile))return{events:[],startOffset:t.remoteByteOffset,endOffset:t.remoteByteOffset};let n=Yn(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{Ci(i,o,0,s,r)}finally{jt(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 tc,existsSync as nc,openSync as rc,readSync as sc,statSync as oc}from"node:fs";function Xn(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 tr=[/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],Ti=[/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],Oi=[/\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],Ri=[/\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],Ni=[/đã 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],Qn=[/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],_i=[/\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],Ki=[/đườ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],$i=[/\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],Zn=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Wi=new Set(["payload","data","content","message","messages","parts","summary"]);function N(e,t){return t.some(n=>n.test(e))}function nr(e){return e.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function Fi(e){return nr(e).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function Li(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 It(e,t,n,r=0){if(!(r>6)){if(typeof e=="string"){(!t||Zn.has(t))&&n.push(e);return}if(Array.isArray(e)){for(let s of e.slice(0,50))It(s,t,n,r+1);return}if(!(!e||typeof e!="object"))for(let[s,o]of Object.entries(e))(Zn.has(s)||Wi.has(s))&&It(o,s,n,r+1)}}function Di(e){let t=[];It(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=nr(o);if(Li(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function er(e){return(e.role??(typeof e.data.role=="string"?e.data.role:"")).toLowerCase()}function zi(e,t,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=t==="user"||n.type==="user_prompt",s=t==="assistant"||n.type==="assistant_message";return r&&N(e,tr)?{kind:"rule",confidence:.98}:r&&N(e,Ti)?{kind:"rule",confidence:.92}:N(e,Oi)?{kind:N(e,Qn)?"architecture":"decision",confidence:r?.93:.86}:r&&N(e,Ri)?{kind:"todo",confidence:.87}:N(e,Qn)&&N(e,_i)?{kind:"architecture",confidence:r?.88:.82}:s&&N(e,Ni)?{kind:"fix",confidence:.8}:r&&N(e,Ki)&&N(e,$i)?{kind:"context",confidence:.79}:null}function qi(e){switch(e){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Hi(e,t,n){return e==="rule"&&N(n,tr)?"critical":e==="architecture"||e==="decision"||e==="rule"?"high":e==="fix"||e==="context"?"normal":Xn(t,n)}function rr(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=er(o);i&&a&&s.set(i,a)}for(let o of t){let i=er(o),a=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&a&&(i=s.get(a)??"");for(let c of Di(o)){let u=zi(c,i,o);if(!u||u.confidence<.75)continue;let m=qi(u.kind),p=Fi(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:Hi(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 Ji}from"node:crypto";var Vi=["project-knowledge","implementation","continuation","session-context"],Bi={"project-knowledge":"Project knowledge",implementation:"Implementation state",continuation:"Work continuation","session-context":"Session context"};function Pt(e){return Ji("sha256").update(e).digest("hex")}function We(e,t){return`${e}:${Pt(t).slice(0,24)}`}function Gi(e){try{return Pt(JSON.stringify(e))}catch{return Pt(String(e))}}function X(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 or(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 Ui(e){return e==="rule"||e==="architecture"?"project-knowledge":e==="decision"||e==="fix"?"implementation":e==="todo"?"continuation":"session-context"}function sr(e){return e.length===0?0:e.reduce((t,n)=>t+n,0)/e.length}function Yi(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=>or(t.content)).join(" | ")}function Xi(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=>or(t.content)).join(`
|
|
118
|
+
`)}function ir(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:Gi(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=X([...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:X([...d.tags,"level:fact",`class:${d.knowledgeClass}`,`kind:${d.kind}`]),rawIds:l,sourcePaths:X(d.provenance.sourcePaths)}}),a=new Map;for(let d of i){let l=Ui(d.kind),g=a.get(l)??[];g.push(d),a.set(l,g)}let c=[];for(let d of Vi){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:Bi[d],summary:Yi(g),factIds:S,importanceScore:Math.max(...g.map(y=>y.importanceScore)),confidence:sr(g.map(y=>y.confidence)),tags:X(["level:scene",`scene:${d}`,...g.flatMap(y=>y.tags)]),sourcePaths:X(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=Xi(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:sr(g.map(h=>h.confidence)),tags:X(["level:knowledge",`class:${S}`,`scene:${d.kind}`,...g.flatMap(h=>h.tags)]),sourcePaths:X(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 me(){let e=Pe(),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 ar(e){return(e||me()).durableMemoryMaxItemsPerSession}function cr(e){return(e||me()).sessionSummaryMaxTokens}var ur=new U;function lr(e){let t=e.trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{let r=JSON.parse(t);return JSON.stringify(ur.sanitizeValue(r))}catch{}let n=ur.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 Qi(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 Zi(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=Qi(u,p);if(d<.3)continue;let l=lr(u);n.push({category:p,text:l,importance:d,sourceSessionId:t})}}let s=me(),o=ar(s);return n.sort((i,a)=>a.importance-i.importance).slice(0,o)}function ea(e){let t=me(),n=cr(t),o=e.join(`
|
|
120
|
+
|
|
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=>lr(i)).join(`
|
|
123
|
+
`);return lt(o,n)}function dr(e,t){let r=(Array.isArray(e)?e:e.split(`
|
|
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(`
|
|
126
|
+
|
|
127
|
+
`).slice(0,Ot)}function Ar(e,t){return W(e,["id","key","fingerprint","knowledgeId","sceneId"])??t}function Ir(e,t){return W(e,["title","name","topic","label","task","kind","type"])??t}function va(e){return(W(e,["knowledgeClass","class","classification","scope"])??"").toLowerCase()}function ba(e){return(W(e,["kind","sceneKind","type"])??"").toLowerCase()}function xa(e){let t=ye(e);if(!t)return[];let n=[],r=jr(t.knowledge);for(let[o,i]of r.entries()){let a=ye(i);if(!a)continue;let c=va(a);if(c==="session"||c==="transient")continue;let u=Cr(a);if(u.length<20)continue;let m=Ar(a,he(a).slice(0,16)),p=Ir(a,`Durable Memory ${o+1}`);n.push({sourceKey:`memory:${m}`,sourceType:"memory",title:p,summary:W(a,["summary","description"]),content:u,tags:Se(["toolnet","auto","memory",...c?[c]:[]])})}let s=jr(t.scenes);for(let[o,i]of s.entries()){let a=ye(i);if(!a)continue;let c=ba(a);if(c==="session-context")continue;let u=Cr(a);if(u.length<20)continue;let m=Ar(a,he(a).slice(0,16)),p=Ir(a,`Knowledge Scene ${o+1}`);n.push({sourceKey:`scene:${m}`,sourceType:"scene",title:p,summary:W(a,["summary","description"]),content:u,tags:Se(["toolnet","auto","scene",...c?[c]:[]])})}return n}function ja(e){return Pr(e,".toolnet","memory","skills")}function Ca(e){let t=ja(e);if(!ha(t))return{candidates:[],failed:0};let n=[],r=0,s=Sa(t).filter(o=>o.endsWith(".json")).sort();for(let o of s)try{let i=JSON.parse(ka(Pr(t,o),"utf8")),a=ye(i);if(!a||a.schema!=="toolnet.skill-memory.v1")continue;let c=W(a,["id","fingerprint"])??wa(o,".json"),u=W(a,["task"])??"",m=W(a,["title"])||u||`Reusable Skill ${c.slice(0,8)}`,p=W(a,["summary"])??void 0,d=Et(a.steps),l=Et(a.verification),g=Et(a.files),S=[];u&&S.push(`## Task
|
|
128
|
+
${u}`),p&&S.push(`## Summary
|
|
129
|
+
${p}`),d.length>0&&S.push(`## Procedure
|
|
130
|
+
${d.map((h,k)=>`${k+1}. ${h}`).join(`
|
|
131
|
+
`)}`),l.length>0&&S.push(`## Verification
|
|
132
|
+
${l.map(h=>`- ${h}`).join(`
|
|
133
|
+
`)}`),g.length>0&&S.push(`## Relevant Files
|
|
134
|
+
${g.map(h=>`- \`${h}\``).join(`
|
|
135
|
+
`)}`);let y=S.join(`
|
|
136
|
+
|
|
137
|
+
`).slice(0,Ot);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 Tt(e){let t=new Date().toISOString();return{schema:Er,version:1,projectId:e,entries:[],createdAt:t,updatedAt:t}}async function Aa(e,t){let n=await e.getText(Mr);if(!n)return Tt(t);try{let r=JSON.parse(n);return r.schema!==Er||r.version!==1||r.projectId!==t||!Array.isArray(r.entries)?Tt(t):r}catch{return Tt(t)}}async function Ia(e,t){await e.put(Mr,JSON.stringify(t,null,2),"application/json")}function Pa(e){return`toolnet-auto-${he(e).slice(0,12)}`}function Ma(e){let t=Z(e.title).slice(0,72),n=he(e.sourceKey).slice(0,10);return Z(`auto-${e.sourceType}-${t}-${n}`)}function Ea(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,Ot)}function Ta(e){return he({sourceType:e.sourceType,title:e.title,summary:e.summary,content:e.content,tags:e.tags})}function Oa(e,t){return e.tags.includes(t)}async function Or(e){let t=xa(e.hierarchy),n=Ca(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 Le(new De(e.storage,e.project));await i.initialize();let a=new qe(new ze(e.storage,e.project));await a.initialize();let c=await Aa(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=Pa(l.sourceKey),S=Ta(l),y=p.get(l.sourceKey),h=y?.slug??Ma(l),k=m.get(h);if(k&&!Oa(k,g)){o.skipped+=1;continue}let P=Se([...l.tags,g]),E=Ea(l),A=await a.gate({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,marker:g,digest:S,title:l.title,...l.summary?{summary:l.summary}:{},content:E,tags:P},[...m.values()]);if(!A.allowed){A.mode==="pending-review"?o.reviewPending+=1:o.skipped+=1;continue}A.mode==="auto-approved"?o.autoApproved+=1:A.mode==="review-approved"&&(o.reviewApproved+=1),k?y?.digest!==S?(k=await i.updatePage(h,{title:l.title,summary:l.summary??"",content:E,tags:P}),m.set(k.slug,k),o.updated+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"updated"})):(o.unchanged+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,action:"unchanged"})):(k=await i.createPage({slug:h,title:l.title,summary:l.summary,content:E,tags:P}),m.set(k.slug,k),o.created+=1,o.pages.push({sourceKey:l.sourceKey,sourceType:l.sourceType,slug:k.slug,action:"created"}));let T=new Date().toISOString(),x={sourceKey:l.sourceKey,sourceType:l.sourceType,slug:h,digest:S,marker:g,updatedAt:T},v=c.entries.findIndex(z=>z.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 Ia(e.storage,c),o}import{createHash as Ra}from"node:crypto";import{chmodSync as Nr,existsSync as Na,mkdirSync as _a,readFileSync as Zp,readdirSync as em,renameSync as Ka,statSync as tm,writeFileSync as $a}from"node:fs";import{join as _r}from"node:path";var Wa="toolnet.skill-memory.v1",Rr=5,Fa=16,La=24,Da=32;function za(e){return Ra("sha256").update(e).digest("hex")}function we(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 Rt(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 qa(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 H(e,t=360){return e&&Rt(qa(e),t)||void 0}function ve(e,t){for(let n of t){let r=e[n];if(typeof r=="string"&&r.trim())return r}}function Kr(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 $r(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 Wr(e){let t=e.data??{};if($r(t,["passed","pass","success","succeeded","ok"])===!1)return!0;let r=Kr(t,["exitCode","exit_code","code","statusCode"]);if(r!==void 0&&r!==0)return!0;let s=ve(t,["status","result","outcome"]);return!!(s&&/\b(fail(?:ed)?|error|broken|cancelled)\b/iu.test(s))}function ke(e){let t=e.data??{};if(Wr(e))return!1;if($r(t,["passed","pass","success","succeeded","ok"])===!0||Kr(t,["exitCode","exit_code","code","statusCode"])===0)return!0;let s=ve(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 Fr(e){let t=e.data??{},n=ve(t,["path","file","filePath","filename","target"]);if(n)return H(n,260);let r=e.provenance?.files;return H(r?.[0],260)}function Nt(e){return H(ve(e.data??{},["command","cmd","script"]),420)}function re(e){return H(ve(e.data??{},["name","test","suite","title","message","text","result","status"]),300)}function Ha(e){let t=[];for(let n of[...e].sort((r,s)=>r.sequence-s.sequence))if(ke(n)){if(n.type==="test"){let r=re(n)??Nt(n)??"Tests passed";t.push(`Test passed: ${r}`);continue}if(n.type==="commit"){let r=re(n);t.push(r?`Commit: ${r}`:"Commit completed");continue}if(n.type==="deploy"){let r=re(n);t.push(r?`Deploy: ${r}`:"Deployment completed")}}return we(t,10)}function Ja(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=Fr(r);s&&n.push(`Update ${s}`);break}case"command":{if(Wr(r))break;let s=Nt(r);s&&n.push(`Run: ${s}`);break}case"test":{if(!ke(r))break;let s=re(r)??Nt(r)??"project tests";n.push(`Verify: ${s}`);break}case"commit":{if(!ke(r))break;let s=re(r);n.push(s?`Commit: ${s}`:"Commit verified changes");break}case"deploy":{if(!ke(r))break;let s=re(r);n.push(s?`Deploy: ${s}`:"Deploy verified build");break}default:break}if(n.length===0)for(let r of t.files.slice(0,8)){let s=H(r,260);s&&n.push(`Update ${s}`)}return we(n,Fa)}function Va(e,t){let n=[...t.files];for(let r of e){let s=Fr(r);s&&n.push(s);for(let o of r.provenance?.files??[]){let i=H(o,260);i&&n.push(i)}}return we(n,La)}function Ba(e){return we(e.filter(t=>["file_write","file_edit","command","test","commit","deploy"].includes(t.type)).map(t=>t.id),Da)}function Ga(e){return e.map(n=>n.timestamp).filter(Boolean).sort().at(-1)??new Date(0).toISOString()}function Lr(e,t,n){if(t.length===0)return[];let r=Ha(t),s=we(n.completed.map(g=>H(g,280)??""),Rr);if(!(s.length>0||t.some(g=>["test","commit","deploy"].includes(g.type)&&ke(g))))return[];let i=H(n.task,280)??H(n.nextActions[0],280),a=s.length>0?s:i?[i]:[];if(a.length===0)return[];let c=Ja(t,n);if(c.length===0)return[];let u=Va(t,n),m=Ba(t),p=Math.min(...t.map(g=>g.sequence)),d=Math.max(...t.map(g=>g.sequence)),l=Ga(t);return a.slice(0,Rr).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=za(y);return{schema:Wa,version:1,id:`skill-${h.slice(0,24)}`,fingerprint:h,projectId:e.projectId,title:Rt(`SOP: ${g}`,180),task:g,summary:Rt(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 Ua(e){return _r(e.rootPath,".toolnet","memory","skills")}function Ya(e){let t=Ua(e);return _a(t,{recursive:!0,mode:448}),Nr(t,448),t}function Dr(e,t){if(t.length===0)return{written:0,deduped:0,files:[]};let n=Ya(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=_r(n,`${i.id}.json`);if(o.push(a),Na(a)){s+=1;continue}let c=`${a}.${process.pid}.${Date.now()}.tmp`;$a(c,JSON.stringify(i,null,2)+`
|
|
139
|
+
`,{encoding:"utf8",mode:384}),Ka(c,a),Nr(a,384),r+=1}return{written:r,deduped:s,files:o}}function zr(e){return String(e).padStart(12,"0")}function Xa(e){return e.remotePrefix.replace("/sessions/","/memory/learned/")}var Je=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=[Xa(t),"batches",`${zr(s)}-${zr(o)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,a,"application/json"),u}};import{createHash as Qa}from"node:crypto";function qr(e){return String(e).padStart(12,"0")}function Za(e){return Qa("sha256").update(e).digest("hex")}function ec(e){return e.remotePrefix.replace("/sessions/","/memory/hierarchy/")}var Ve=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=Za([...r.facts.map(u=>u.id),...r.knowledge.map(u=>u.id)].sort().join("|")).slice(0,16),c=[ec(t),"batches",`${qr(s)}-${qr(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 ic(e,t){if(!nc(e))return{events:[],nextOffset:t};let n=oc(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=rc(e,"r");try{sc(i,o,0,s,r)}finally{tc(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
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 Be=class{constructor(t){this.options=t;this.journal=new Je(t.storage),this.hierarchyJournal=new Ve(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=ic(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Fe(this.options.identity,s.events),i=o.candidates,a=!1;i.length>0&&(a=!!await this.journal.write(this.options.identity,s.events,i));let c=!1;o.hierarchy.facts.length>0&&(c=!!await this.hierarchyJournal.write(this.options.identity,s.events,o.hierarchy));let u=Lr(this.options.identity,s.events,o.state),m=Dr(this.options.project,u);this.options.wal.setSourceCursor("memory.pipeline.version",2),this.options.wal.setSourceCursor("memory.pipeline.normalized_events",o.stats.normalizedEvents),this.options.wal.setSourceCursor("memory.pipeline.persisted",o.stats.persistedCandidates),this.options.wal.setSourceCursor("memory.pipeline.permanent",o.stats.permanent),this.options.wal.setSourceCursor("memory.pipeline.task",o.stats.task),this.options.wal.setSourceCursor("memory.pipeline.session",o.stats.session),this.options.wal.setSourceCursor("memory.pipeline.transient",o.stats.transient),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.version",o.hierarchy.version),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.raw",o.hierarchy.stats.raw),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.facts",o.hierarchy.stats.facts),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.scenes",o.hierarchy.stats.scenes),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.knowledge",o.hierarchy.stats.knowledge),this.options.wal.setSourceCursor("memory.pipeline.hierarchy.journal_written",c?1:0),this.options.wal.setSourceCursor("memory.skill.assets",u.length),this.options.wal.setSourceCursor("memory.skill.written",m.written),this.options.wal.setSourceCursor("memory.skill.deduped",m.deduped);try{let p=sn(this.options.project.rootPath,s.events);this.options.wal.setSourceCursor("memory.context_offload.eligible",p.eligible),this.options.wal.setSourceCursor("memory.context_offload.written",p.written),this.options.wal.setSourceCursor("memory.context_offload.deduped",p.deduped),this.options.wal.setSourceCursor("memory.context_offload.graph_nodes",p.graphNodes),this.options.wal.setSourceCursor("memory.context_offload.failed",0)}catch{this.options.wal.setSourceCursor("memory.context_offload.failed",1)}try{let p=await Or({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 jc,existsSync as Cc,openSync as Ac,readSync as Ic,statSync as Pc}from"node:fs";function Hr(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function xe(e){return e.toLowerCase().replace(/[^a-z0-9]/gu,"")}function be(e,t,n=0){if(n>8)return;if(Array.isArray(e)){for(let s of e.slice(0,50))be(s,t,n+1);return}let r=Hr(e);if(r)for(let[s,o]of Object.entries(r))t(s,o,r),be(o,t,n+1)}function se(e,t){let n=[];return be(e,(r,s)=>{t.has(xe(r))&&typeof s=="string"&&s.trim()&&n.push(s.trim())}),n}function ac(e){let t=e.trim();if(!t.startsWith("{"))return null;try{return Hr(JSON.parse(t))}catch{return null}}function cc(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 be(t,(r,s,o)=>{if(n)return;let i=xe(r);if(["tool","toolname"].includes(i)&&typeof s=="string"){n=s.trim().toLowerCase();return}if(i!=="name"||typeof s!="string")return;let a=typeof o.type=="string"?o.type.toLowerCase():"";(a.includes("tool")||a.includes("function")||a.includes("command"))&&(n=s.trim().toLowerCase())}),n}function uc(e){let t=se(e.data,new Set(["command","cmd","script"])),n=se(e.data,new Set(["arguments","args"]));for(let r of n){let s=ac(r);if(s)for(let o of se(s,new Set(["command","cmd","script"])))t.push(o)}return Array.from(new Set(t.map(r=>r.trim()).filter(Boolean)))}function lc(e){let t=se(e.data,new Set(["filepath","file_path","filename","file","path","target"].map(xe)));return Array.from(new Set(t.map(n=>n.trim()).filter(n=>n.length>0&&n.length<1e3&&!n.includes(`
|
|
144
|
+
`))))}function dc(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 pc(e){let t=se(e.data,new Set(["patch","diff","arguments","input"].map(xe))),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 mc(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 fc(e){let t=null;return be(e,(n,r)=>{if(t===null&&["exitcode","code"].includes(xe(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 gc(e){return se(e,new Set(["status","state","result","output","outputsummary","message","text"]))}function yc(e){let t=fc(e.data);if(t!==null)return t===0?"passed":"failed";let n=gc(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 hc(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 Jr(e){let t=[],n=cc(e),r=dc(e,n);if(r)for(let s of lc(e))t.push({kind:"file",text:s,fileAction:r,confidence:e.type==="file_edit"||e.type==="file_write"?1:.96});t.push(...pc(e));for(let s of uc(e)){t.push({kind:"command",text:s,confidence:.98});let o=mc(s);o&&t.push({kind:"test",text:s,checkKind:o,checkStatus:yc(e),confidence:.98})}return hc(t)}var Sc=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function te(e){return e.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Br(e){return te(e).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function ee(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))ee(r,t,n+1);return}if(!(!e||typeof e!="object"))for(let[r,s]of Object.entries(e))(Sc.has(r)||["data","payload","parts","messages"].includes(r))&&ee(s,t,n+1)}}function Ge(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 Vr(e){let t=te(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 C(e,t,n,r,s={}){let o=te(r),i=s.key??Br(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 kc(e,t,n){let r=te(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(C(e,t,"goal",i[1],{confidence:.97}));let a=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);a?.[1]&&s.push(C(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=te(u[2]??""),g=l&&!Vr(l)?`Phase ${d} - ${l}`:`Phase ${d}`;s.push(C(e,t,"phase",g,{key:`phase:${d}`,order:d,status:Ge(r),confidence:.93}))}let m=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);m?.[2]&&s.push(C(e,t,"task",m[2],{status:m[1].trim()?"completed":Ge(m[2]),confidence:.96}));let p=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(p?.[2]){let d=p[1]?Number(p[1]):void 0,l=te(p[2]),g=Vr(l);s.push(C(e,t,"task",g&&d!==void 0?`TODO ${d}`:l,{key:d!==void 0?`task:${d}`:Br(l),order:d,status:Ge(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(C(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(C(e,t,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(C(e,t,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(C(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(C(e,t,"activity",r,{confidence:.86})),s}function Ue(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=[];ee(i.data,c);let u=c.map(m=>te(m)).find(m=>m.length>=8&&m.length<=1200&&!/^\[?toolnet\b/iu.test(m));u&&s(C(e,i,"request",u,{confidence:.96}))}for(let c of Jr(i))s(C(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=[];ee(i.data,c);for(let u of c)s(C(e,i,"decision",u,{confidence:1}))}if(i.type==="todo"){let c=[];ee(i.data,c);for(let u of c)s(C(e,i,"task",u,{status:Ge(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(C(e,i,"file",u,{fileAction:"modified",confidence:1}))}if(i.type==="test"){let c=[];ee(i.data,c);for(let u of c)s(C(e,i,"test",u,{confidence:1}))}let a=[];ee(i.data,a);for(let c of a)for(let u of c.split(/\n+/u))for(let m of kc(e,i,u))s(m)}let o=t[t.length-1];return s(C(e,o,"session",`${e.agent}:${e.nativeSessionId}`,{key:e.sessionKey,confidence:1})),n}function Gr(e){return String(e).padStart(12,"0")}var Ye=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,`${Gr(r)}-${Gr(s)}-${a}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as Ur}from"node:path";import{mkdirSync as wc}from"node:fs";function Xr(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(e,t=20){let n=[],r=new Set;for(let s of e.slice().reverse()){let o=Xr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=t))break}return n.reverse()}function vc(e,t=20){let n=new Map;for(let r of e){let s=`${r.kind}|${Xr(r.command)}`;n.delete(s),n.set(s,r)}return Array.from(n.values()).slice(-t)}function bc(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 Yr(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&&bc(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 xc(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 Xe(e,t){let r=(await xc(e,t)).flatMap(f=>f.observations).sort((f,b)=>{let J=f.occurredAt.localeCompare(b.occurredAt);if(J!==0)return J;let Bt=f.sequence-b.sequence;return Bt!==0?Bt: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=[],P=[],E=[],A=[],T=[];for(let f of r)switch(f.kind){case"request":i=f.text;break;case"activity":a=f.text;break;case"goal":c=f.text;break;case"plan":u=f.text;break;case"phase":s.set(f.key,Yr(s.get(f.key),f));break;case"task":o.set(f.key,Yr(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"&&P.push(f.text);break}case"command":E.push(f.text);break;case"test":A.push(f.text),f.checkKind&&T.push({kind:f.checkKind,command:f.text,status:f.checkStatus??"unknown",updatedAt:f.occurredAt,agent:f.agent,nativeSessionId:f.nativeSessionId});break;case"session":m={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let x=Array.from(s.values()).sort((f,b)=>(f.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),v=Array.from(o.values()).sort((f,b)=>(f.order??Number.MAX_SAFE_INTEGER)-(b.order??Number.MAX_SAFE_INTEGER)),z=x.find(f=>f.status==="in_progress")??x.find(f=>f.status==="blocked")??x.find(f=>f.status==="pending"),q=v.find(f=>f.status==="in_progress")??v.find(f=>f.status==="blocked")??v.find(f=>f.status==="pending"),at=F([...g,...q?[q.title]:[],...!q&&z?[z.title]:[],...v.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),ct=F([...d,...x.filter(f=>f.status==="blocked").map(f=>f.title),...v.filter(f=>f.status==="blocked").map(f=>f.title)],20),ie={version:1,projectId:e.id,projectName:e.name,currentRequest:i,currentActivity:a,goal:c,plan:u,phases:x,tasks:v,decisions:F(p,20),blockers:ct,warnings:F(l,20),nextActions:at,filesTouched:F(S,30),activeFiles:Array.from(y.entries()).filter(([,f])=>f!=="deleted").map(([f])=>f).slice(-5),modifiedFiles:F(h,30),createdFiles:F(k,30),deletedFiles:F(P,30),commands:F(E,20),tests:F(A,20),checks:vc(T,20),currentPhase:z,currentTask:q,progress:{phasesTotal:x.length,phasesCompleted:x.filter(f=>f.status==="completed").length,tasksTotal:v.length,tasksCompleted:v.filter(f=>f.status==="completed").length,blocked:x.filter(f=>f.status==="blocked").length+v.filter(f=>f.status==="blocked").length},lastSession:m,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},ae=Ur(e.rootPath,".toolnet","work");return wc(ae,{recursive:!0}),O(Ur(ae,"current.json"),ie),await t.put(`projects/${e.id}/work/current.json`,JSON.stringify(ie,null,2)+`
|
|
147
|
+
`,"application/json"),ie}async function Qr(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 Mc(e,t){if(!Cc(e))return{events:[],nextOffset:t};let n=Pc(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=Ac(e,"r");try{Ic(i,o,0,s,r)}finally{jc(i)}let a=o.toString("utf8"),c=a.lastIndexOf(`
|
|
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 Qe=class{constructor(t){this.options=t;this.journal=new Ye(t.storage)}options;journal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["work.continuity.offset"]??0),r=Mc(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=Ue(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await Xe(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 Wc,existsSync as Fc,openSync as Lc,readSync as Dc,statSync as zc}from"node:fs";var Ec=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function oe(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))(Ec.has(r)||["data","payload","parts","messages"].includes(r))&&_t(s,t,n+1)}}function _(e,t,n,r,s,o=.95){let i=oe(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 L(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 oe(e.slice(r.length+1))}return null}function Tc(e){let t=e.trimStart();return t.startsWith("- ")||t.startsWith("* ")||/^\d+[.)]\s+/u.test(t)}function Oc(e){return oe(e.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function Zr(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=oe(m);if(!p){u=null;continue}let d=p.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let v=Number(d[1]);c={type:"phase",key:`phase:${v}`,order:v,title:oe(d[2]??"")},u=null;continue}let l=p.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(l){let v=Number(l[1]);c={type:"task",key:`task:${v}`,order:v,title:oe(l[2]??"")},u=null;continue}let g=L(p,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(g){s(_(e,o,"mission",g,{type:"project"},.99)),u=null;continue}let S=L(p,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(S){s(_(e,o,c.type==="phase"?"phase_objective":"objective",S,c,.98)),u=null;continue}let y=L(p,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(y){s(_(e,o,c.type==="phase"?"phase_why":"why",y,c,.98)),u=null;continue}let h=L(p,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){s(_(e,o,"desired_outcome",h,{type:"project"},.98)),u=null;continue}let k=L(p,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(k){s(_(e,o,"plan_rationale",k,{type:"project"},.98)),u=null;continue}let P=L(p,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(P){s(_(e,o,"phase_deliverable",P,c,.97)),u=null;continue}let E=L(p,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(E){s(_(e,o,"acceptance_criterion",E,c,.98)),u="acceptance_criterion";continue}let A=L(p,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(A){s(_(e,o,"dependency",A,c,.97)),u="dependency";continue}let T=L(p,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(T){s(_(e,o,"open_question",T,c,.95)),u="open_question";continue}let x=L(p,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(x){s(_(e,o,"constraint",x,c,.97)),u="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(p)){u="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(p)){u="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(p)){u="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(p)){u="constraint";continue}if(u&&Tc(m)){s(_(e,o,u,Oc(m),c,.96));continue}u=null}}}return n}function es(e){return String(e).padStart(12,"0")}var Ze=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,`${es(r)}-${es(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 Rc}from"node:fs";import{join as ts}from"node:path";function Nc(e){return{value:e.value,confidence:e.confidence,evidence:e.evidence}}function _c(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 B(e,t){return _c(t,e)?t:e}function G(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 Kc(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 $c(e){return{key:e.scopeKey??`phase:${e.scopeOrder??0}`,order:e.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function ns(e,t){let r=(await Kc(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=Nc(S);if(S.scope==="phase"&&S.scopeKey){let h=u.get(S.scopeKey)??$c(S);switch(S.kind){case"phase_objective":h.objective=B(h.objective,y);break;case"phase_why":h.why=B(h.why,y);break;case"phase_deliverable":h.deliverable=B(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=B(s,y);break;case"objective":o=B(o,y);break;case"why":i=B(i,y);break;case"desired_outcome":a=B(a,y);break;case"plan_rationale":c=B(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=G(S.acceptanceCriteria,20),S.dependencies=G(S.dependencies,15),S.openQuestions=G(S.openQuestions,15),S.constraints=G(S.constraints,15),S.notes=G(S.notes,20);let 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:G(m,20),constraints:G(p,20),notes:G(d,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},g=ts(e.rootPath,".toolnet","work");return Rc(g,{recursive:!0}),O(ts(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 qc(e,t){if(!Fc(e))return{events:[],nextOffset:t};let n=zc(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=Lc(e,"r");try{Dc(o,s,0,s.length,r)}finally{Wc(o)}let i=s.toString("utf8"),a=i.lastIndexOf(`
|
|
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 et=class{constructor(t){this.options=t;this.journal=new Ze(t.storage)}options;journal;async learnNew(){let t=this.options.wal.loadState(),n=Number(t.sourceCursors["work.semantic.offset"]??0),r=qc(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=Zr(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ns(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 du,mkdirSync as pu}from"node:fs";import{join as $t}from"node:path";import{existsSync as os,mkdirSync as Hc,readFileSync as Jc,statSync as rs,writeFileSync as Vc}from"node:fs";import{dirname as Bc,join as Gc}from"node:path";var ss=64*1024,Uc=`# ToolNet Project Operating Manual
|
|
154
|
+
|
|
155
|
+
This file contains persistent instructions for AI agents working on this project.
|
|
156
|
+
|
|
157
|
+
## Critical Rules
|
|
158
|
+
|
|
159
|
+
<!--
|
|
160
|
+
Examples:
|
|
161
|
+
|
|
162
|
+
- [enforce] Never edit production files directly.
|
|
163
|
+
- [enforce] Edit source only in /path/to/source.
|
|
164
|
+
- [enforce] Deploy only with ./deploy.sh --apply
|
|
165
|
+
-->
|
|
166
|
+
|
|
167
|
+
## Workflow
|
|
168
|
+
|
|
169
|
+
<!--
|
|
170
|
+
Describe the correct working process.
|
|
171
|
+
-->
|
|
172
|
+
|
|
173
|
+
## Architecture
|
|
174
|
+
|
|
175
|
+
<!--
|
|
176
|
+
Important architecture conventions.
|
|
177
|
+
-->
|
|
178
|
+
|
|
179
|
+
## Verification
|
|
180
|
+
|
|
181
|
+
<!--
|
|
182
|
+
Tests / QA required after changes.
|
|
183
|
+
-->
|
|
184
|
+
|
|
185
|
+
## Known Gotchas
|
|
186
|
+
|
|
187
|
+
<!--
|
|
188
|
+
Things an AI agent should always remember.
|
|
189
|
+
-->
|
|
190
|
+
|
|
191
|
+
## Preferences
|
|
192
|
+
|
|
193
|
+
<!--
|
|
194
|
+
- [advisory] Prefer small focused files.
|
|
195
|
+
-->
|
|
196
|
+
`;function is(e){return Gc(e.rootPath,".toolnet","PROJECT.md")}function Yc(e){return e.normalize("NFKC").replace(/\s+/g," ").trim()}function Xc(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=Yc(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 Qc(e){let t=is(e);return os(t)||(Hc(Bc(t),{recursive:!0}),Vc(t,Uc,{encoding:"utf8",mode:384})),t}function as(e,t=!1){let n=t?Qc(e):is(e);if(!os(n))return null;if(rs(n).size>ss)throw new Error(`PROJECT.md exceeds ${ss} bytes`);let s=Jc(n,"utf8");return{path:n,content:s,digest:w(s),rules:Xc(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(rs(n).mtimeMs).toISOString()}}import{existsSync as Zc,mkdirSync as eu,readFileSync as tu,renameSync as nu,writeFileSync as ru}from"node:fs";import{dirname as su,join as ou}from"node:path";function iu(e,t){eu(su(e),{recursive:!0});let n=`${e}.tmp-${process.pid}-${Date.now()}`;ru(n,`${JSON.stringify(t,null,2)}
|
|
197
|
+
`,{encoding:"utf8",mode:384}),nu(n,e)}function ms(e){return ou(e.rootPath,".toolnet","work","current.json")}function Kt(e){let t=ms(e);if(!Zc(t))return null;try{let n=JSON.parse(tu(t,"utf8"));return n.version!==1||n.projectId!==e.id?null:n}catch{return null}}function tt(e){return e.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function K(e,t,n){let r=[],s=new Set;for(let o of[...e,...t].reverse()){let i=tt(o);if(!(!i||s.has(i))&&(s.add(i),r.push(o),r.length>=n))break}return r.reverse()}function au(e,t,n=20){let r=new Map;for(let s of[...e,...t]){let o=`${s.kind}|${tt(s.command)}`;r.delete(o),r.set(o,s)}return Array.from(r.values()).slice(-n)}function cu(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 cs(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&&cu(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 us(e){let t=new Map;for(let n of e){let r=n.order!==void 0?`order:${n.order}`:tt(n.title);t.set(r,n)}return t}function ls(e){return e.order!==void 0?`order:${e.order}`:tt(e.key||e.text)}function ds(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 ps(e){return e.find(t=>t.status==="in_progress")??e.find(t=>t.status==="blocked")??e.find(t=>t.status==="pending")}function fs(e,t){let n=Kt(e),r=us(n?.phases??[]),s=us(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=[],P=[],E=[],A=[],T=[...t].sort((f,b)=>{let J=f.occurredAt.localeCompare(b.occurredAt);return J!==0?J:f.sequence-b.sequence});for(let f of T)switch(f.kind){case"request":o=f.text;break;case"activity":i=f.text;break;case"goal":a=f.text;break;case"plan":c=f.text;break;case"phase":{let b=ls(f);r.set(b,cs(r.get(b),f));break}case"task":{let b=ls(f);s.set(b,cs(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",J=S.indexOf(f.text);J>=0&&S.splice(J,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":P.push(f.text);break;case"test":E.push(f.text),f.checkKind&&A.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=ds(r.values()),v=ds(s.values()),z=ps(x),q=ps(v),at=K(n?.nextActions??[],[...l,...q?[q.title]:[],...!q&&z?[z.title]:[],...v.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),ct=K(n?.blockers??[],[...p,...x.filter(f=>f.status==="blocked").map(f=>f.title),...v.filter(f=>f.status==="blocked").map(f=>f.title)],20),ie=T.length>0?T[T.length-1].occurredAt:n?.updatedAt??new Date().toISOString(),ae={version:1,projectId:e.id,projectName:e.name,currentRequest:o,currentActivity:i,goal:a,plan:c,phases:x,tasks:v,decisions:K(n?.decisions??[],m,20),blockers:ct,warnings:K(n?.warnings??[],d,20),nextActions:at,filesTouched:K(n?.filesTouched??[],g,30),activeFiles:K([],S,5),modifiedFiles:K(n?.modifiedFiles??[],y,30),createdFiles:K(n?.createdFiles??[],h,30),deletedFiles:K(n?.deletedFiles??[],k,30),commands:K(n?.commands??[],P,20),tests:K(n?.tests??[],E,20),checks:au(n?.checks??[],A,20),currentPhase:z,currentTask:q,progress:{phasesTotal:x.length,phasesCompleted:x.filter(f=>f.status==="completed").length,tasksTotal:v.length,tasksCompleted:v.filter(f=>f.status==="completed").length,blocked:x.filter(f=>f.status==="blocked").length+v.filter(f=>f.status==="blocked").length},lastSession:u,updatedAt:ie};return iu(ms(e),ae),ae}function M(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 gs(e){if(e)return{id:e.id,title:e.title,status:e.status}}function uu(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 lu(e){return w(JSON.stringify(e))}function ys(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=M(r.nextActions.filter(k=>!u.has(k.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim())),10),p=M([...c,...m],15),d=M(r.tests.slice().reverse(),10),l=M([...(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:gs(r.currentPhase),task:gs(r.currentTask),file:s},completed:{phases:M(o,20),tasks:M(i,30)},remaining:{phases:M(a,20),tasks:M(c,30),todos:p},nextAction:m[0],blockers:M(r.blockers.slice().reverse(),10),decisions:M(r.decisions.slice().reverse(),10),files:{current:s,recent:l,active:M(r.activeFiles??[],10),modified:M(r.modifiedFiles??[],20),created:M(r.createdFiles??[],20),deleted:M(r.deletedFiles??[],20)},tests:{status:uu(r.tests,r.checks),recent:d,checks:(r.checks??[]).slice(-10).map(k=>({kind:k.kind,status:k.status,command:k.command}))},attention:M(e.attention??[],20),progress:r.progress},{capturedAt:S,source:y,...h}=g;return{...g,stateDigest:lu(h)}}function mu(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 hs(e,t,n,r,s){if(!mu(n))return null;let o=as(e,!1),a=[...o?o.rules.filter(p=>p.mode==="enforce").map(p=>p.text):[],...n.warnings].slice(0,20),c=ys({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 Ss(e,t){let n=$t(e.rootPath,".toolnet","work","handoffs");pu(n,{recursive:!0});let r=$t(n,`${t.id}.json`);du(r)||O(r,t),O($t(e.rootPath,".toolnet","work","handoff-latest.json"),t)}function ks(e){let t=hs(e.project,e.identity,e.state,e.reason,e.sequence);return t?(Ss(e.project,t),t):null}var nt=class{constructor(t){this.options=t}options;async capture(t,n){let r=Kt(this.options.project);r||(r=await Qr(this.options.project,this.options.storage)),r||(r=await Xe(this.options.project,this.options.storage));let s=hs(this.options.project,this.options.identity,r,t,n);if(!s)return null;Ss(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
|
+
`,"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 fu,readFileSync as gu,writeFileSync as yu}from"node:fs";import{join as hu}from"node:path";var vs="<!-- TOOLNET:STABLE-WORK:BEGIN -->",Wt="<!-- TOOLNET:STABLE-WORK:END -->";function Ft(e){switch(e.status){case"completed":return"[x]";case"in_progress":return"[~]";case"blocked":return"[!]";case"cancelled":return"[-]";default:return"[ ]"}}function D(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${n}`)]:[]}function ws(e,t){return t.length?["",`${e}:`,...t.map(n=>`- ${Ft(n)} ${n.title}`)]:[]}function Su(e){let t=[vs,"# 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:",`${Ft(e.currentPhase)} ${e.currentPhase.title}`),e.currentTask&&t.push("","Current task:",`${Ft(e.currentTask)} ${e.currentTask.title}`),t.push(...ws("Phases",e.phases)),t.push(...ws("TODO / Tasks",e.tasks)),t.push(...D("Next actions",e.nextActions)),t.push(...D("Blockers",e.blockers)),t.push(...D("Important decisions",e.decisions)),t.push(...D("Active files",e.activeFiles??[])),t.push(...D("Modified files",e.modifiedFiles??[])),t.push(...D("Created files",e.createdFiles??[])),t.push(...D("Deleted files",e.deletedFiles??[])),t.push(...D("Files touched",e.filesTouched)),t.push(...D("Recent commands",e.commands??[])),t.push(...D("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.",Wt),t.join(`
|
|
201
|
+
`)}function bs(e,t){let n=hu(e.rootPath,".toolnet","current.md"),r="";if(fu(n))try{r=gu(n,"utf8")}catch{r=""}r=r.replace(/<!-- TOOLNET:AUTO-CURRENT:BEGIN -->[\s\S]*?<!-- TOOLNET:AUTO-CURRENT:END -->/gu,"");let s=Su(t),o=r.indexOf(vs),i=r.indexOf(Wt),a;o>=0&&i>=o?a=[r.slice(0,o).trimEnd(),s,r.slice(i+Wt.length).trimStart()].filter(Boolean).join(`
|
|
202
|
+
|
|
203
|
+
`):a=r.trim()?`${r.trim()}
|
|
204
|
+
|
|
205
|
+
${s}`:s,yu(n,`${a.trim()}
|
|
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});
|