toolnet-memory 0.3.14 → 0.3.15

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.
Files changed (48) hide show
  1. package/.env.example +0 -1
  2. package/.release-target +1 -1
  3. package/README.md +25 -1
  4. package/bin/toolnet-memory +5 -0
  5. package/bundle/agy-hook.js +67 -67
  6. package/bundle/agy.js +61 -61
  7. package/bundle/api.js +15 -15
  8. package/bundle/auto-integrate.js +28 -28
  9. package/bundle/background-refresh.js +7 -7
  10. package/bundle/claude-hook.js +51 -50
  11. package/bundle/codex-context.js +25 -24
  12. package/bundle/codex.js +71 -71
  13. package/bundle/context-runtime.js +45 -44
  14. package/bundle/context.js +15 -15
  15. package/bundle/continuity-certify.js +13 -13
  16. package/bundle/copilot-hook.js +87 -85
  17. package/bundle/copilot.js +4 -4
  18. package/bundle/cursor-hook.js +87 -85
  19. package/bundle/cursor.js +4 -4
  20. package/bundle/doctor.js +4 -4
  21. package/bundle/full-index.js +20 -20
  22. package/bundle/gc.js +3 -0
  23. package/bundle/graph-index.js +4 -4
  24. package/bundle/graph-ui.js +3 -3
  25. package/bundle/grok-hook.js +60 -59
  26. package/bundle/grok.js +5 -5
  27. package/bundle/handoff-refresh.js +10 -10
  28. package/bundle/help-cli.js +4 -4
  29. package/bundle/impact.js +4 -4
  30. package/bundle/incremental.js +5 -4
  31. package/bundle/init.js +37 -37
  32. package/bundle/integration-status.js +4 -4
  33. package/bundle/kiro-hook.js +82 -81
  34. package/bundle/learner.js +6 -6
  35. package/bundle/mcp.js +17 -17
  36. package/bundle/memory-agent.js +7 -7
  37. package/bundle/memory-query.js +7 -7
  38. package/bundle/opencode.js +80 -80
  39. package/bundle/project-manual.js +7 -7
  40. package/bundle/recovery-certify.js +15 -15
  41. package/bundle/runtime.js +13 -12
  42. package/bundle/semantic.js +5 -5
  43. package/bundle/snapshot.js +4 -4
  44. package/bundle/status-cli.js +4 -4
  45. package/bundle/toolnet-cli.js +60 -60
  46. package/bundle/work-continuity.js +7 -7
  47. package/package.json +9 -3
  48. package/release-manifest.json +54 -3
@@ -1,6 +1,6 @@
1
- import{existsSync as kt}from"node:fs";import{homedir as un}from"node:os";import{join as pn}from"node:path";import{spawnSync as gn}from"node:child_process";import{homedir as $o}from"node:os";import{join as v}from"node:path";function Ke(e={}){return v(e.home??$o(),".gemini")}function Be(e={}){return v(Ke(e),"antigravity-cli")}function Ue(e={}){return v(Ke(e),"config")}function L(e={}){return v(Ue(e),"mcp_config.json")}function K(e={}){let t=e.cwd??process.cwd();return v(t,".agents","mcp_config.json")}function B(e="toolnet-memory",t={}){return v(Be(t),"plugins",e)}function qe(e={}){return[Be(e),L(e),Ue(e),K(e)]}import{homedir as We}from"node:os";import{join as w}from"node:path";function S(e={}){let t=process.env.OPENCODE_CONFIG_DIR?.trim();if(t)return t;let o=e.xdgConfigHome??process.env.XDG_CONFIG_HOME?.trim();return o?w(o,"opencode"):w(e.home??We(),".config","opencode")}function le(e={}){let t=process.env.OPENCODE_CONFIG?.trim();if(t)return t;let o=e.home??We(),n=e.xdgConfigHome??process.env.XDG_CONFIG_HOME?.trim();return n?w(n,"opencode","opencode.json"):w(o,".config","opencode","opencode.json")}function ae(e={}){let t=e.cwd??process.cwd();return w(t,"opencode.json")}function Ye(e={}){return w(S(e),"plugins")}function Xe(e={}){return w(S(e),"AGENTS.md")}import{homedir as Ve}from"node:os";import{join as ue}from"node:path";function pe(e={}){return ue(e.home??Ve(),".claude")}function ze(e={}){return ue(pe(e),"settings.json")}function Qe(e={}){return ue(e.home??Ve(),".claude.json")}import{homedir as Jo}from"node:os";import{join as I}from"node:path";function ge(e={}){return e.kiroHome??process.env.KIRO_HOME??I(e.home??Jo(),".kiro")}function Go(e={}){return I(ge(e),"settings")}function U(e={}){return I(Go(e),"mcp.json")}function fe(e={}){let t=e.cwd??process.cwd();return I(t,".kiro","settings","mcp.json")}function Lo(e={}){return I(ge(e),"hooks")}function de(e={}){return I(Lo(e),"toolnet-memory.json")}function me(e={}){let t=e.cwd??process.cwd();return I(t,".kiro","hooks","toolnet-memory.json")}function Ze(e={}){return[ge(e),U(e)]}import{homedir as Ko}from"node:os";import{join as ye}from"node:path";function et(e={}){return ye(e.home??Ko(),".toolnetcli")}function Bo(e={}){return ye(et(e),"config.json")}function tt(e={}){let t=e.cwd??process.cwd();return ye(t,".toolnet","mcp.json")}function ot(e={}){let t=et(e),o=Bo(e);return[t,o]}import{homedir as Uo}from"node:os";import{join as he}from"node:path";function nt(e={}){if(e.kiloHome)return e.kiloHome;if(process.env.KILO_HOME)return process.env.KILO_HOME;let t=e.xdgConfigHome??process.env.XDG_CONFIG_HOME;return t?he(t,"kilo"):he(e.home??Uo(),".config","kilo")}function ke(e={}){return he(nt(e),"kilo.jsonc")}function rt(e={}){let t=nt(e),o=ke(e);return[t,o]}import{homedir as qo}from"node:os";import{join as h,resolve as Wo}from"node:path";function q(e={}){return e.cursorHome??h(e.home??qo(),".cursor")}function Yo(e={}){return e.cursorConfigDir??process.env.CURSOR_CONFIG_DIR??(e.xdgConfigHome??process.env.XDG_CONFIG_HOME?h(e.xdgConfigHome??process.env.XDG_CONFIG_HOME,"cursor"):void 0)??q(e)}function W(e={}){return h(q(e),"mcp.json")}function Y(e={}){return h(q(e),"hooks.json")}function be(e){return h(Wo(e),".cursor")}function it(e){return h(be(e),"mcp.json")}function st(e){return h(be(e),"hooks.json")}function Xo(e){return h(be(e),"rules")}function ct(e){return h(Xo(e),"toolnet-memory.mdc")}function lt(e={}){return Array.from(new Set([q(e),Yo(e)]))}import{homedir as Vo}from"node:os";import{join as y,resolve as zo}from"node:path";function Ce(e={}){return e.copilotHome??process.env.COPILOT_HOME??y(e.home??Vo(),".copilot")}function X(e={}){return y(Ce(e),"mcp-config.json")}function Qo(e={}){return y(Ce(e),"hooks")}function V(e={}){return y(Qo(e),"toolnet-memory.json")}function Oe(e){return y(zo(e),".github")}function at(e){return y(Oe(e),"mcp.json")}function Zo(e){return y(Oe(e),"hooks")}function ut(e){return y(Zo(e),"toolnet-memory.json")}function en(e){return y(Oe(e),"instructions")}function pt(e){return y(en(e),"toolnet-memory.instructions.md")}function gt(e={}){return[Ce(e)]}import{homedir as tn}from"node:os";import{join as m,resolve as on}from"node:path";function z(e={}){return e.grokHome??process.env.GROK_HOME??m(e.home??tn(),".grok")}function Q(e={}){return m(z(e),"config.toml")}function nn(e={}){return m(z(e),"hooks")}function Z(e={}){return m(nn(e),"toolnet-memory.json")}function rn(e={}){return m(z(e),"skills")}function sn(e={}){return m(rn(e),"toolnet-continuity")}function ee(e={}){return m(sn(e),"SKILL.md")}function je(e){return m(on(e),".grok")}function ft(e){return m(je(e),"config.toml")}function cn(e){return m(je(e),"hooks")}function dt(e){return m(cn(e),"toolnet-memory.json")}function ln(e){return m(je(e),"skills")}function an(e){return m(ln(e),"toolnet-continuity")}function mt(e){return m(an(e),"SKILL.md")}function yt(e={}){return[z(e)]}function fn(e){return gn("sh",["-lc",`command -v ${JSON.stringify(e)} >/dev/null 2>&1`],{stdio:"ignore"}).status===0}function O(e){let t=e.commandExists(e.command),o=e.configPaths.filter(s=>kt(s)),n=o.length>0,r=[];t&&r.push(`command:${e.command}`);for(let s of o)r.push(`config:${s}`);return{agent:e.agent,detected:t||n,commandDetected:t,configDetected:n,evidence:r}}function ht(e){let t=e.commands.filter(i=>e.commandExists(i)),o=e.configPaths.filter(i=>kt(i)),n=t.length>0,r=o.length>0,s=[...t.map(i=>`command:${i}`),...o.map(i=>`config:${i}`)];return{agent:e.agent,detected:n||r,commandDetected:n,configDetected:r,evidence:s}}function bt(e={}){let t=e.home??un(),o=e.commandExists??fn,n=e.codexHome??process.env.CODEX_HOME??pn(t,".codex");return[O({agent:"agy",command:"agy",commandExists:o,configPaths:qe({home:t})}),O({agent:"opencode",command:"opencode",commandExists:o,configPaths:[S({home:t,xdgConfigHome:e.xdgConfigHome})]}),O({agent:"claude",command:"claude",commandExists:o,configPaths:[pe({home:t})]}),O({agent:"kiro",command:"kiro-cli",commandExists:o,configPaths:Ze({home:t,kiroHome:e.kiroHome})}),ht({agent:"cursor",commands:["agent","cursor-agent"],commandExists:o,configPaths:lt({home:t,cursorHome:e.cursorHome,cursorConfigDir:e.cursorConfigDir,xdgConfigHome:e.xdgConfigHome})}),O({agent:"copilot",command:"copilot",commandExists:o,configPaths:gt({home:t,copilotHome:e.copilotHome})}),O({agent:"grok",command:"grok",commandExists:o,configPaths:yt({home:t,grokHome:e.grokHome})}),O({agent:"toolnet-cli",command:"toolnet",commandExists:o,configPaths:ot({home:t})}),ht({agent:"kilo",commands:["kilo","kilo-code"],commandExists:o,configPaths:rt({home:t,kiloHome:e.kiloHome})}),O({agent:"codex",command:"codex",commandExists:o,configPaths:[n]})]}import{existsSync as Tn,mkdirSync as vt,readFileSync as En,renameSync as Mn,writeFileSync as An}from"node:fs";import{dirname as Hn,join as oe}from"node:path";import{existsSync as dn,mkdirSync as mn,readFileSync as yn,renameSync as hn,rmSync as kn,writeFileSync as bn}from"node:fs";import{dirname as Cn,join as On}from"node:path";function jn(e){return`'${e.replace(/'/g,"'\\''")}'`}function wn(e){if(!dn(e))return{};let t;try{t=JSON.parse(yn(e,"utf8"))}catch{throw new Error(`Invalid existing Agy hooks.json at ${e}: parse error. Not overwriting.`)}if(typeof t!="object"||t===null||Array.isArray(t))throw new Error(`Invalid existing Agy hooks.json at ${e}: root must be a JSON object.`);return t}function In(e,t){mn(Cn(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{bn(o,`${JSON.stringify(t,null,2)}
2
- `,{encoding:"utf8",mode:384}),hn(o,e)}finally{kn(o,{force:!0})}}function Ct(e={}){let t=e.pluginName??"toolnet-memory",o=e.hooksFile??On(B(t),"hooks.json"),n=wn(o),r=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",s=`${jn(r)} session:agy-hook`;return n["toolnet-memory"]={enabled:!0,PreToolUse:[{matcher:"view_file|list_dir|find_by_name|grep_search|run_command",hooks:[{type:"command",command:`${s} pre-tool`,timeout:5}]}],PreInvocation:[{type:"command",command:`${s} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${s} post`,timeout:15}],Stop:[{type:"command",command:`${s} stop`,timeout:30}]},In(o,n),o}import{existsSync as vn,mkdirSync as Sn,readFileSync as xn,renameSync as Fn,writeFileSync as Rn}from"node:fs";import{dirname as Pn}from"node:path";function E(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Nn(e,t){Sn(Pn(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;Rn(o,`${JSON.stringify(t,null,2)}
3
- `,{encoding:"utf8",mode:384}),Fn(o,e)}function Ot(e){if(!vn(e))return{};let t=xn(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing Agy MCP config at ${e}: parse error. Not overwriting.`)}if(!E(o))throw new Error(`Invalid existing Agy MCP config at ${e}: root must be a JSON object. Not overwriting.`);return o}function jt(e,t){return E(e)?e.command===t&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp":!1}function te(e,t,o,n){let r=Ot(e),s=r.mcpServers;if(s!==void 0&&!E(s))throw new Error(`Invalid existing Agy MCP config: mcpServers must be an object in ${e}.`);let i=E(s)?{...s}:{},c=i[o];if(jt(c,t)&&!n)return{installed:!0,changed:!1};i[o]={command:t,args:["mcp"]};let l={...r,mcpServers:i};Nn(e,l);let u=Ot(e).mcpServers;if(!E(u)||!jt(u[o],t))throw new Error(`Agy MCP configuration was written but verification failed for ${e}.`);return{installed:!0,changed:!0}}function wt(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.serverName??"toolnet-memory",n=e.scope??"global";if(e.configFile)return{...te(e.configFile,t,o,e.force??!1),configFile:e.configFile,serverName:o,command:t,args:["mcp"]};if(n==="both"){let i=L(),c=K({cwd:e.cwd}),l=te(i,t,o,e.force??!1),a=te(c,t,o,e.force??!1);return{installed:!0,changed:l.changed||a.changed,configFile:i,serverName:o,command:t,args:["mcp"]}}let r=n==="workspace"?K({cwd:e.cwd}):L();return{...te(r,t,o,e.force??!1),configFile:r,serverName:o,command:t,args:["mcp"]}}var _n=`# ToolNet Memory Continuity
1
+ import{existsSync as kt}from"node:fs";import{homedir as un}from"node:os";import{join as pn}from"node:path";import{spawnSync as gn}from"node:child_process";import{homedir as Jo}from"node:os";import{join as v}from"node:path";function Ke(e={}){return v(e.home??Jo(),".gemini")}function Ue(e={}){return v(Ke(e),"antigravity-cli")}function Be(e={}){return v(Ke(e),"config")}function L(e={}){return v(Be(e),"mcp_config.json")}function K(e={}){let t=e.cwd??process.cwd();return v(t,".agents","mcp_config.json")}function U(e="toolnet-memory",t={}){return v(Ue(t),"plugins",e)}function qe(e={}){return[Ue(e),L(e),Be(e),K(e)]}import{homedir as We}from"node:os";import{join as O}from"node:path";function S(e={}){let t=process.env.OPENCODE_CONFIG_DIR?.trim();if(t)return t;let o=e.xdgConfigHome??process.env.XDG_CONFIG_HOME?.trim();return o?O(o,"opencode"):O(e.home??We(),".config","opencode")}function le(e={}){let t=process.env.OPENCODE_CONFIG?.trim();if(t)return t;let o=e.home??We(),n=e.xdgConfigHome??process.env.XDG_CONFIG_HOME?.trim();return n?O(n,"opencode","opencode.json"):O(o,".config","opencode","opencode.json")}function ae(e={}){let t=e.cwd??process.cwd();return O(t,"opencode.json")}function Ye(e={}){return O(S(e),"plugins")}function Ve(e={}){return O(S(e),"AGENTS.md")}import{homedir as Xe}from"node:os";import{join as ue}from"node:path";function pe(e={}){return ue(e.home??Xe(),".claude")}function ze(e={}){return ue(pe(e),"settings.json")}function Qe(e={}){return ue(e.home??Xe(),".claude.json")}import{homedir as $o}from"node:os";import{join as w}from"node:path";function ge(e={}){return e.kiroHome??process.env.KIRO_HOME??w(e.home??$o(),".kiro")}function Go(e={}){return w(ge(e),"settings")}function B(e={}){return w(Go(e),"mcp.json")}function fe(e={}){let t=e.cwd??process.cwd();return w(t,".kiro","settings","mcp.json")}function Lo(e={}){return w(ge(e),"hooks")}function de(e={}){return w(Lo(e),"toolnet-memory.json")}function me(e={}){let t=e.cwd??process.cwd();return w(t,".kiro","hooks","toolnet-memory.json")}function Ze(e={}){return[ge(e),B(e)]}import{homedir as Ko}from"node:os";import{join as ye}from"node:path";function et(e={}){return ye(e.home??Ko(),".toolnetcli")}function Uo(e={}){return ye(et(e),"config.json")}function tt(e={}){let t=e.cwd??process.cwd();return ye(t,".toolnet","mcp.json")}function ot(e={}){let t=et(e),o=Uo(e);return[t,o]}import{homedir as Bo}from"node:os";import{join as he}from"node:path";function nt(e={}){if(e.kiloHome)return e.kiloHome;if(process.env.KILO_HOME)return process.env.KILO_HOME;let t=e.xdgConfigHome??process.env.XDG_CONFIG_HOME;return t?he(t,"kilo"):he(e.home??Bo(),".config","kilo")}function ke(e={}){return he(nt(e),"kilo.jsonc")}function rt(e={}){let t=nt(e),o=ke(e);return[t,o]}import{homedir as qo}from"node:os";import{join as h,resolve as Wo}from"node:path";function q(e={}){return e.cursorHome??h(e.home??qo(),".cursor")}function Yo(e={}){return e.cursorConfigDir??process.env.CURSOR_CONFIG_DIR??(e.xdgConfigHome??process.env.XDG_CONFIG_HOME?h(e.xdgConfigHome??process.env.XDG_CONFIG_HOME,"cursor"):void 0)??q(e)}function W(e={}){return h(q(e),"mcp.json")}function Y(e={}){return h(q(e),"hooks.json")}function be(e){return h(Wo(e),".cursor")}function it(e){return h(be(e),"mcp.json")}function st(e){return h(be(e),"hooks.json")}function Vo(e){return h(be(e),"rules")}function ct(e){return h(Vo(e),"toolnet-memory.mdc")}function lt(e={}){return Array.from(new Set([q(e),Yo(e)]))}import{homedir as Xo}from"node:os";import{join as y,resolve as zo}from"node:path";function je(e={}){return e.copilotHome??process.env.COPILOT_HOME??y(e.home??Xo(),".copilot")}function V(e={}){return y(je(e),"mcp-config.json")}function Qo(e={}){return y(je(e),"hooks")}function X(e={}){return y(Qo(e),"toolnet-memory.json")}function Ie(e){return y(zo(e),".github")}function at(e){return y(Ie(e),"mcp.json")}function Zo(e){return y(Ie(e),"hooks")}function ut(e){return y(Zo(e),"toolnet-memory.json")}function en(e){return y(Ie(e),"instructions")}function pt(e){return y(en(e),"toolnet-memory.instructions.md")}function gt(e={}){return[je(e)]}import{homedir as tn}from"node:os";import{join as m,resolve as on}from"node:path";function z(e={}){return e.grokHome??process.env.GROK_HOME??m(e.home??tn(),".grok")}function Q(e={}){return m(z(e),"config.toml")}function nn(e={}){return m(z(e),"hooks")}function Z(e={}){return m(nn(e),"toolnet-memory.json")}function rn(e={}){return m(z(e),"skills")}function sn(e={}){return m(rn(e),"toolnet-continuity")}function ee(e={}){return m(sn(e),"SKILL.md")}function Ce(e){return m(on(e),".grok")}function ft(e){return m(Ce(e),"config.toml")}function cn(e){return m(Ce(e),"hooks")}function dt(e){return m(cn(e),"toolnet-memory.json")}function ln(e){return m(Ce(e),"skills")}function an(e){return m(ln(e),"toolnet-continuity")}function mt(e){return m(an(e),"SKILL.md")}function yt(e={}){return[z(e)]}function fn(e){return gn("sh",["-lc",`command -v ${JSON.stringify(e)} >/dev/null 2>&1`],{stdio:"ignore"}).status===0}function I(e){let t=e.commandExists(e.command),o=e.configPaths.filter(s=>kt(s)),n=o.length>0,r=[];t&&r.push(`command:${e.command}`);for(let s of o)r.push(`config:${s}`);return{agent:e.agent,detected:t||n,commandDetected:t,configDetected:n,evidence:r}}function ht(e){let t=e.commands.filter(i=>e.commandExists(i)),o=e.configPaths.filter(i=>kt(i)),n=t.length>0,r=o.length>0,s=[...t.map(i=>`command:${i}`),...o.map(i=>`config:${i}`)];return{agent:e.agent,detected:n||r,commandDetected:n,configDetected:r,evidence:s}}function bt(e={}){let t=e.home??un(),o=e.commandExists??fn,n=e.codexHome??process.env.CODEX_HOME??pn(t,".codex");return[I({agent:"agy",command:"agy",commandExists:o,configPaths:qe({home:t})}),I({agent:"opencode",command:"opencode",commandExists:o,configPaths:[S({home:t,xdgConfigHome:e.xdgConfigHome})]}),I({agent:"claude",command:"claude",commandExists:o,configPaths:[pe({home:t})]}),I({agent:"kiro",command:"kiro-cli",commandExists:o,configPaths:Ze({home:t,kiroHome:e.kiroHome})}),ht({agent:"cursor",commands:["agent","cursor-agent"],commandExists:o,configPaths:lt({home:t,cursorHome:e.cursorHome,cursorConfigDir:e.cursorConfigDir,xdgConfigHome:e.xdgConfigHome})}),I({agent:"copilot",command:"copilot",commandExists:o,configPaths:gt({home:t,copilotHome:e.copilotHome})}),I({agent:"grok",command:"grok",commandExists:o,configPaths:yt({home:t,grokHome:e.grokHome})}),I({agent:"toolnet-cli",command:"toolnet",commandExists:o,configPaths:ot({home:t})}),ht({agent:"kilo",commands:["kilo","kilo-code"],commandExists:o,configPaths:rt({home:t,kiloHome:e.kiloHome})}),I({agent:"codex",command:"codex",commandExists:o,configPaths:[n]})]}import{existsSync as En,mkdirSync as vt,readFileSync as Tn,renameSync as Mn,writeFileSync as An}from"node:fs";import{dirname as _n,join as oe}from"node:path";import{existsSync as dn,mkdirSync as mn,readFileSync as yn,renameSync as hn,rmSync as kn,writeFileSync as bn}from"node:fs";import{dirname as jn,join as In}from"node:path";function Cn(e){return`'${e.replace(/'/g,"'\\''")}'`}function On(e){if(!dn(e))return{};let t;try{t=JSON.parse(yn(e,"utf8"))}catch{throw new Error(`Invalid existing Agy hooks.json at ${e}: parse error. Not overwriting.`)}if(typeof t!="object"||t===null||Array.isArray(t))throw new Error(`Invalid existing Agy hooks.json at ${e}: root must be a JSON object.`);return t}function wn(e,t){mn(jn(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{bn(o,`${JSON.stringify(t,null,2)}
2
+ `,{encoding:"utf8",mode:384}),hn(o,e)}finally{kn(o,{force:!0})}}function jt(e={}){let t=e.pluginName??"toolnet-memory",o=e.hooksFile??In(U(t),"hooks.json"),n=On(o),r=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",s=`${Cn(r)} session:agy-hook`;return n["toolnet-memory"]={enabled:!0,PreToolUse:[{matcher:"view_file|list_dir|find_by_name|grep_search|run_command",hooks:[{type:"command",command:`${s} pre-tool`,timeout:5}]}],PreInvocation:[{type:"command",command:`${s} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${s} post`,timeout:15}],Stop:[{type:"command",command:`${s} stop`,timeout:30}]},wn(o,n),o}import{existsSync as vn,mkdirSync as Sn,readFileSync as xn,renameSync as Fn,writeFileSync as Rn}from"node:fs";import{dirname as Pn}from"node:path";function T(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Nn(e,t){Sn(Pn(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;Rn(o,`${JSON.stringify(t,null,2)}
3
+ `,{encoding:"utf8",mode:384}),Fn(o,e)}function It(e){if(!vn(e))return{};let t=xn(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing Agy MCP config at ${e}: parse error. Not overwriting.`)}if(!T(o))throw new Error(`Invalid existing Agy MCP config at ${e}: root must be a JSON object. Not overwriting.`);return o}function Ct(e,t){return T(e)?e.command===t&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp":!1}function te(e,t,o,n){let r=It(e),s=r.mcpServers;if(s!==void 0&&!T(s))throw new Error(`Invalid existing Agy MCP config: mcpServers must be an object in ${e}.`);let i=T(s)?{...s}:{},c=i[o];if(Ct(c,t)&&!n)return{installed:!0,changed:!1};i[o]={command:t,args:["mcp"]};let l={...r,mcpServers:i};Nn(e,l);let u=It(e).mcpServers;if(!T(u)||!Ct(u[o],t))throw new Error(`Agy MCP configuration was written but verification failed for ${e}.`);return{installed:!0,changed:!0}}function Ot(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.serverName??"toolnet-memory",n=e.scope??"global";if(e.configFile)return{...te(e.configFile,t,o,e.force??!1),configFile:e.configFile,serverName:o,command:t,args:["mcp"]};if(n==="both"){let i=L(),c=K({cwd:e.cwd}),l=te(i,t,o,e.force??!1),a=te(c,t,o,e.force??!1);return{installed:!0,changed:l.changed||a.changed,configFile:i,serverName:o,command:t,args:["mcp"]}}let r=n==="workspace"?K({cwd:e.cwd}):L();return{...te(r,t,o,e.force??!1),configFile:r,serverName:o,command:t,args:["mcp"]}}var Hn=`# ToolNet Memory Continuity
4
4
 
5
5
  ToolNet Memory is the authoritative continuity layer for previous project work.
6
6
 
@@ -39,13 +39,13 @@ Invoke the MCP tool directly.
39
39
  Current repository evidence overrides stale memory after ToolNet has restored the working context.
40
40
 
41
41
  Do not ask the user to repeat context already available through ToolNet Memory.
42
- `;function Dn(e,t){vt(Hn(e),{recursive:!0});let o=`${e}.tmp-${process.pid}-${Date.now()}`;An(o,t,{encoding:"utf8",mode:384}),Mn(o,e)}function It(e,t){Tn(e)&&En(e,"utf8")===t||Dn(e,t)}function St(e={}){let t=e.pluginName??"toolnet-memory",o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.pluginRoot??B(t),r=oe(n,"plugin.json"),s=oe(n,"mcp_config.json"),i=oe(n,"hooks.json"),c=oe(n,"rules","toolnet-memory-continuity.md");return vt(n,{recursive:!0,mode:448}),It(r,`${JSON.stringify({$schema:"https://antigravity.google/schemas/v1/plugin.json",name:t,description:"Persistent project continuity and memory for Antigravity coding sessions."},null,2)}
43
- `),wt({configFile:s,binary:o,serverName:"toolnet-memory",force:e.force}),Ct({hooksFile:i,binary:o,pluginName:t}),It(c,`${_n.trim()}
44
- `),{installed:!0,pluginRoot:n,files:[r,s,i,c]}}import{existsSync as Jn,mkdirSync as Pt,readFileSync as Gn,writeFileSync as Nt}from"node:fs";import{join as Ft}from"node:path";var $n="memory_agent_ask";function xt(){return`
42
+ `;function Dn(e,t){vt(_n(e),{recursive:!0});let o=`${e}.tmp-${process.pid}-${Date.now()}`;An(o,t,{encoding:"utf8",mode:384}),Mn(o,e)}function wt(e,t){En(e)&&Tn(e,"utf8")===t||Dn(e,t)}function St(e={}){let t=e.pluginName??"toolnet-memory",o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.pluginRoot??U(t),r=oe(n,"plugin.json"),s=oe(n,"mcp_config.json"),i=oe(n,"hooks.json"),c=oe(n,"rules","toolnet-memory-continuity.md");return vt(n,{recursive:!0,mode:448}),wt(r,`${JSON.stringify({$schema:"https://antigravity.google/schemas/v1/plugin.json",name:t,description:"Persistent project continuity and memory for Antigravity coding sessions."},null,2)}
43
+ `),Ot({configFile:s,binary:o,serverName:"toolnet-memory",force:e.force}),jt({hooksFile:i,binary:o,pluginName:t}),wt(c,`${Hn.trim()}
44
+ `),{installed:!0,pluginRoot:n,files:[r,s,i,c]}}import{existsSync as $n,mkdirSync as Pt,readFileSync as Gn,writeFileSync as Nt}from"node:fs";import{join as Ft}from"node:path";var Jn="memory_agent_ask";function xt(){return`
45
45
  [TOOLNET MEMORY AGENT]
46
46
 
47
47
  Tool available:
48
- - ${$n}
48
+ - ${Jn}
49
49
 
50
50
  Use it automatically BEFORE guessing when:
51
51
 
@@ -92,7 +92,7 @@ Rules:
92
92
  - After receiving the ToolNet answer, continue the task
93
93
  instead of asking the user to repeat known context.
94
94
  - If ToolNet says information is not recorded, say so.
95
- `.trim()}var Rt="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",we="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function Ln(e={}){let t=Xe();Pt(S(),{recursive:!0});let o=`${Rt}
95
+ `.trim()}var Rt="<!-- TOOLNET_MEMORY_BOOTSTRAP_START -->",Oe="<!-- TOOLNET_MEMORY_BOOTSTRAP_END -->";function Ln(e={}){let t=Ve();Pt(S(),{recursive:!0});let o=`${Rt}
96
96
  ## ToolNet Memory
97
97
 
98
98
  ToolNet Memory is available for projects that already contain a valid \`.toolnet/project.json\`.
@@ -111,10 +111,10 @@ Rules:
111
111
 
112
112
  ${xt()}
113
113
 
114
- ${we}`,n=Jn(t)?Gn(t,"utf8"):"",r=n.indexOf(Rt),s=n.indexOf(we);return r>=0&&s>=r?n=n.slice(0,r)+o+n.slice(s+we.length):(n=n.trimEnd(),n&&(n+=`
114
+ ${Oe}`,n=$n(t)?Gn(t,"utf8"):"",r=n.indexOf(Rt),s=n.indexOf(Oe);return r>=0&&s>=r?n=n.slice(0,r)+o+n.slice(s+Oe.length):(n=n.trimEnd(),n&&(n+=`
115
115
 
116
116
  `),n+=o),Nt(t,n.trimEnd()+`
117
- `,{encoding:"utf8",mode:384}),t}function Tt(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=[];o.push(Ln({cwd:e.cwd}));let n=e.scope??"global",r=[];if((n==="global"||n==="both")&&r.push(e.directory??Ye()),n==="project"||n==="both"){let s=e.cwd??process.cwd();r.push(Ft(s,".opencode","plugins"))}for(let s of r){Pt(s,{recursive:!0});let i=Ft(s,"toolnet-memory.js"),c=`
117
+ `,{encoding:"utf8",mode:384}),t}function Et(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=[];o.push(Ln({cwd:e.cwd}));let n=e.scope??"global",r=[];if((n==="global"||n==="both")&&r.push(e.directory??Ye()),n==="project"||n==="both"){let s=e.cwd??process.cwd();r.push(Ft(s,".opencode","plugins"))}for(let s of r){Pt(s,{recursive:!0});let i=Ft(s,"toolnet-memory.js"),c=`
118
118
  // Generated by ToolNet Memory.
119
119
  // OpenCode integration:
120
120
  // - project gated
@@ -1204,22 +1204,22 @@ export const ToolNetMemoryPlugin =
1204
1204
  },
1205
1205
  }
1206
1206
  }
1207
- `;Nt(i,c.trimStart(),{encoding:"utf8",mode:384}),o.push(i)}return o}import{existsSync as At,mkdirSync as Kn,readFileSync as Bn,renameSync as Un,writeFileSync as qn}from"node:fs";import{dirname as Ht,join as Wn}from"node:path";function M(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Yn(e,t){Kn(Ht(e),{recursive:!0});let o=`${e}.tmp-${process.pid}-${Date.now()}`;qn(o,`${JSON.stringify(t,null,2)}
1208
- `,{encoding:"utf8",mode:384}),Un(o,e)}function Et(e){if(!At(e))return{};let t=Bn(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing OpenCode config at ${e}: parse error. Not overwriting.`)}if(!M(o))throw new Error(`Invalid existing OpenCode config at ${e}: root must be a JSON object. Not overwriting.`);return o}function Mt(e,t){if(!M(e))return!1;let o=e.command;return e.type==="local"&&e.enabled!==!1&&Array.isArray(o)&&o.length===2&&o[0]===t&&o[1]==="mcp"}function ne(e,t,o,n){let r=Wn(Ht(e),"opencode.jsonc"),s=At(r)?r:void 0,i=Et(e),c=i.mcp;if(c!==void 0&&!M(c))throw new Error(`Invalid existing OpenCode config: mcp must be an object in ${e}.`);let l=M(c)?{...c}:{},a=l[o];if(Mt(a,t)&&!n)return{installed:!0,changed:!1,preservedJsonc:s};l[o]={type:"local",command:[t,"mcp"],enabled:!0};let u={...i,mcp:l};Yn(e,u);let p=Et(e);if(!M(p.mcp)||!Mt(p.mcp[o],t))throw new Error(`OpenCode MCP configuration was written but verification failed for ${e}.`);return{installed:!0,changed:!0,preservedJsonc:s}}function _t(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.serverName??"toolnet-memory",n=e.scope??"global";if(e.configFile)return{...ne(e.configFile,t,o,e.force??!1),configFile:e.configFile,serverName:o,command:[t,"mcp"]};if(n==="both"){let i=le(),c=ae({cwd:e.cwd}),l=ne(i,t,o,e.force??!1),a=ne(c,t,o,e.force??!1);return{installed:!0,changed:l.changed||a.changed,configFile:i,serverName:o,command:[t,"mcp"],preservedJsonc:l.preservedJsonc??a.preservedJsonc}}let r=n==="project"?ae({cwd:e.cwd}):le();return{...ne(r,t,o,e.force??!1),configFile:r,serverName:o,command:[t,"mcp"]}}import{existsSync as Xn,mkdirSync as Dt,readFileSync as Vn,writeFileSync as $t}from"node:fs";import{homedir as Jt}from"node:os";import{dirname as Gt,join as Ie}from"node:path";function zn(e){let t=[],o=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,n;for(;n=o.exec(e);){let r=n[1]??n[2]??"";try{t.push(n[1]!==void 0?JSON.parse(`"${r}"`):r)}catch{t.push(r)}}return t}function Lt(e={}){let t=e.configFile??Ie(process.env.CODEX_HOME??Ie(Jt(),".codex"),"config.toml"),o=e.previousFile??Ie(Jt(),".config","toolnet-memory","codex-notify-previous.json");Dt(Gt(t),{recursive:!0}),Dt(Gt(o),{recursive:!0});let n=Xn(t)?Vn(t,"utf8"):"",r=e.binary??"toolnet-memory",s=`notify = [${JSON.stringify(r)}, "session:codex-notify"]`,i=n.split(`
1207
+ `;Nt(i,c.trimStart(),{encoding:"utf8",mode:384}),o.push(i)}return o}import{existsSync as At,mkdirSync as Kn,readFileSync as Un,renameSync as Bn,writeFileSync as qn}from"node:fs";import{dirname as _t,join as Wn}from"node:path";function M(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Yn(e,t){Kn(_t(e),{recursive:!0});let o=`${e}.tmp-${process.pid}-${Date.now()}`;qn(o,`${JSON.stringify(t,null,2)}
1208
+ `,{encoding:"utf8",mode:384}),Bn(o,e)}function Tt(e){if(!At(e))return{};let t=Un(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing OpenCode config at ${e}: parse error. Not overwriting.`)}if(!M(o))throw new Error(`Invalid existing OpenCode config at ${e}: root must be a JSON object. Not overwriting.`);return o}function Mt(e,t){if(!M(e))return!1;let o=e.command;return e.type==="local"&&e.enabled!==!1&&Array.isArray(o)&&o.length===2&&o[0]===t&&o[1]==="mcp"}function ne(e,t,o,n){let r=Wn(_t(e),"opencode.jsonc"),s=At(r)?r:void 0,i=Tt(e),c=i.mcp;if(c!==void 0&&!M(c))throw new Error(`Invalid existing OpenCode config: mcp must be an object in ${e}.`);let l=M(c)?{...c}:{},a=l[o];if(Mt(a,t)&&!n)return{installed:!0,changed:!1,preservedJsonc:s};l[o]={type:"local",command:[t,"mcp"],enabled:!0};let u={...i,mcp:l};Yn(e,u);let p=Tt(e);if(!M(p.mcp)||!Mt(p.mcp[o],t))throw new Error(`OpenCode MCP configuration was written but verification failed for ${e}.`);return{installed:!0,changed:!0,preservedJsonc:s}}function Ht(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.serverName??"toolnet-memory",n=e.scope??"global";if(e.configFile)return{...ne(e.configFile,t,o,e.force??!1),configFile:e.configFile,serverName:o,command:[t,"mcp"]};if(n==="both"){let i=le(),c=ae({cwd:e.cwd}),l=ne(i,t,o,e.force??!1),a=ne(c,t,o,e.force??!1);return{installed:!0,changed:l.changed||a.changed,configFile:i,serverName:o,command:[t,"mcp"],preservedJsonc:l.preservedJsonc??a.preservedJsonc}}let r=n==="project"?ae({cwd:e.cwd}):le();return{...ne(r,t,o,e.force??!1),configFile:r,serverName:o,command:[t,"mcp"]}}import{existsSync as Vn,mkdirSync as Dt,readFileSync as Xn,writeFileSync as Jt}from"node:fs";import{homedir as $t}from"node:os";import{dirname as Gt,join as we}from"node:path";function zn(e){let t=[],o=/"((?:\\.|[^"\\])*)"|'([^']*)'/g,n;for(;n=o.exec(e);){let r=n[1]??n[2]??"";try{t.push(n[1]!==void 0?JSON.parse(`"${r}"`):r)}catch{t.push(r)}}return t}function Lt(e={}){let t=e.configFile??we(process.env.CODEX_HOME??we($t(),".codex"),"config.toml"),o=e.previousFile??we($t(),".config","toolnet-memory","codex-notify-previous.json");Dt(Gt(t),{recursive:!0}),Dt(Gt(o),{recursive:!0});let n=Vn(t)?Xn(t,"utf8"):"",r=e.binary??"toolnet-memory",s=`notify = [${JSON.stringify(r)}, "session:codex-notify"]`,i=n.split(`
1209
1209
  `),c=i.findIndex(g=>/^\s*\[/.test(g));c<0&&(c=i.length);let l=-1,a=-1;for(let g=0;g<c;g+=1)if(/^\s*notify\s*=/.test(i[g])){if(l=g,a=g,i[g].includes("[")&&!i[g].includes("]"))for(;a+1<c&&(a+=1,!i[a].includes("]")););break}let u=[];if(l>=0){let g=i.slice(l,a+1).join(`
1210
- `);u=zn(g),i.splice(l,a-l+1,s)}else c=i.findIndex(g=>/^\s*\[/.test(g)),c<0&&(c=i.length),i.splice(c,0,s);let p=u.length>=2&&u[u.length-1]==="session:codex-notify";return u.length>0&&!p&&$t(o,JSON.stringify(u,null,2)+`
1210
+ `);u=zn(g),i.splice(l,a-l+1,s)}else c=i.findIndex(g=>/^\s*\[/.test(g)),c<0&&(c=i.length),i.splice(c,0,s);let p=u.length>=2&&u[u.length-1]==="session:codex-notify";return u.length>0&&!p&&Jt(o,JSON.stringify(u,null,2)+`
1211
1211
  `,{encoding:"utf8",mode:384}),n=i.join(`
1212
1212
  `),n.endsWith(`
1213
1213
  `)||(n+=`
1214
- `),$t(t,n,{encoding:"utf8",mode:384}),{configFile:t,previousFile:o,preservedPrevious:u.length>0&&!p}}import{existsSync as Qn,mkdirSync as Zn,readFileSync as er,writeFileSync as tr}from"node:fs";import{homedir as or}from"node:os";import{dirname as nr,join as Kt}from"node:path";function rr(e){return`'${e.replace(/'/g,"'\\''")}'`}function Bt(e={}){let t=e.hooksFile??Kt(process.env.CODEX_HOME??Kt(or(),".codex"),"hooks.json");Zn(nr(t),{recursive:!0});let o={};if(Qn(t))try{o=JSON.parse(er(t,"utf8"))}catch(c){throw new Error(`Invalid existing Codex hooks.json: ${c instanceof Error?c.message:String(c)}`)}let n=o.hooks&&typeof o.hooks=="object"&&!Array.isArray(o.hooks)?o.hooks:{};o.hooks=n;let s=(Array.isArray(n.SessionStart)?n.SessionStart:[]).filter(c=>{try{return!JSON.stringify(c).includes("session:codex-context")}catch{return!0}}),i=e.binary??"toolnet-memory";return s.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${rr(i)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),n.SessionStart=s,tr(t,JSON.stringify(o,null,2)+`
1215
- `,{encoding:"utf8",mode:384}),t}import{spawnSync as ir}from"node:child_process";function ve(e,t){return ir(e,t,{encoding:"utf8",stdio:["ignore","pipe","pipe"]})}function Ut(e,t){let o=ve(e,["mcp","get",t,"--json"]);if(o.status!==0||!o.stdout)return null;try{return JSON.parse(o.stdout)}catch{return null}}function qt(e,t){return e.enabled!==!1&&e.transport?.type==="stdio"&&e.transport?.command===t&&Array.isArray(e.transport?.args)&&e.transport?.args.length===1&&e.transport.args[0]==="mcp"}function Wt(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.codexBinary??"codex",n=e.serverName??"toolnet-memory",r=Ut(o,n);if(r&&qt(r,t))return{installed:!0,changed:!1,serverName:n,command:t,args:["mcp"]};if(r){let c=ve(o,["mcp","remove",n]);if(c.status!==0)return{installed:!1,changed:!1,serverName:n,command:t,args:["mcp"],error:(c.stderr||c.stdout||"Unable to remove old ToolNet MCP configuration.").trim()}}let s=ve(o,["mcp","add",n,"--",t,"mcp"]);if(s.status!==0)return{installed:!1,changed:!1,serverName:n,command:t,args:["mcp"],error:(s.stderr||s.stdout||"Unable to register ToolNet MCP.").trim()};let i=Ut(o,n);return!i||!qt(i,t)?{installed:!1,changed:!0,serverName:n,command:t,args:["mcp"],error:"Codex accepted MCP registration but verification did not match expected ToolNet command."}:{installed:!0,changed:!0,serverName:n,command:t,args:["mcp"]}}import{existsSync as sr,mkdirSync as cr,readFileSync as lr,renameSync as ar,rmSync as ur,writeFileSync as pr}from"node:fs";import{dirname as gr}from"node:path";function A(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function fr(e){return/^[A-Za-z0-9_./:-]+$/u.test(e)?e:`'${e.replace(/'/gu,"'\\''")}'`}function dr(e){if(!sr(e))return{};let t;try{t=JSON.parse(lr(e,"utf8"))}catch(o){throw new Error(`Invalid existing Claude settings.json: ${o instanceof Error?o.message:String(o)}`)}if(!A(t))throw new Error("Invalid existing Claude settings.json: root must be a JSON object.");return t}function Se(e){if(e===void 0)return[];if(!Array.isArray(e))throw new Error("Invalid existing Claude settings.json: hook event must be an array.");let t=[];for(let o of e){if(!A(o)){t.push(o);continue}let n=o.hooks;if(!Array.isArray(n)){t.push(o);continue}let r=n.filter(s=>{if(!A(s))return!0;let i=s.command;return!(typeof i=="string"&&i.includes("session:claude-hook"))});r.length!==0&&t.push({...o,hooks:r})}return t}function xe(e){return{type:"command",command:e,timeout:10}}function mr(e,t){cr(gr(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{pr(o,JSON.stringify(t,null,2)+`
1216
- `,{encoding:"utf8",mode:384}),ar(o,e)}finally{ur(o,{force:!0})}}function Yt(e={}){let t=e.settingsFile??ze(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=dr(t),r=n.hooks;if(r!==void 0&&!A(r))throw new Error("Invalid existing Claude settings.json: hooks must be an object.");let s=A(r)?{...r}:{},i=`${fr(o)} session:claude-hook`,c=Se(s.SessionStart);c.push({matcher:"startup|resume|clear|compact",hooks:[xe(i)]}),s.SessionStart=c;let l=Se(s.PostToolUse);l.push({matcher:"Edit|Write",hooks:[xe(i)]}),s.PostToolUse=l;let a=Se(s.Stop);a.push({hooks:[xe(i)]}),s.Stop=a;let u={...n,hooks:s},p=JSON.stringify(n),g=JSON.stringify(u);return p===g?{settingsFile:t,changed:!1}:(mr(t,u),{settingsFile:t,changed:!0})}import{existsSync as yr,mkdirSync as hr,readFileSync as kr,renameSync as br,rmSync as Cr,writeFileSync as Or}from"node:fs";import{dirname as jr}from"node:path";function H(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Xt(e){if(!yr(e))return{};let t;try{t=JSON.parse(kr(e,"utf8"))}catch(o){throw new Error(`Invalid existing Claude Code config: ${o instanceof Error?o.message:String(o)}`)}if(!H(t))throw new Error("Invalid existing Claude Code config: root must be a JSON object.");return t}function Vt(e,t){if(!H(e))return!1;let o=e.args;return e.type==="stdio"&&e.command===t&&Array.isArray(o)&&o.length===1&&o[0]==="mcp"}function wr(e,t){hr(jr(e),{recursive:!0});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Or(o,JSON.stringify(t,null,2)+`
1217
- `,{encoding:"utf8",mode:384}),br(o,e)}finally{Cr(o,{force:!0})}}function zt(e={}){let t=e.stateFile??Qe(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=Xt(t),s=r.mcpServers;if(s!==void 0&&!H(s))throw new Error("Invalid existing Claude Code config: mcpServers must be an object.");let i=H(s)?{...s}:{},c=i[n];if(Vt(c,o))return{installed:!0,changed:!1,configFile:t,serverName:n,command:[o,"mcp"],repaired:!1};let l=c!==void 0;i[n]={type:"stdio",command:o,args:["mcp"]},wr(t,{...r,mcpServers:i});let u=Xt(t).mcpServers;if(!H(u)||!Vt(u[n],o))throw new Error("Claude Code MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:t,serverName:n,command:[o,"mcp"],repaired:l}}function Qt(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=Yt({binary:t,settingsFile:e.settingsFile}),n=zt({binary:t,stateFile:e.stateFile});return{hooks:o,mcp:n,files:[o.settingsFile,n.configFile]}}import{existsSync as Ir,mkdirSync as vr,readFileSync as Sr,renameSync as xr,rmSync as Fr,writeFileSync as Rr}from"node:fs";import{dirname as Pr}from"node:path";var x="ToolNet Memory - ";function to(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Nr(e){return/^[A-Za-z0-9_./:-]+$/u.test(e)?e:`'${e.replace(/'/gu,"'\\''")}'`}function Zt(e){if(!Ir(e))return{};let t=Sr(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing Kiro hooks file at ${e}: parse error. Not overwriting.`)}if(!to(o))throw new Error(`Invalid existing Kiro hooks file at ${e}: root must be a JSON object. Not overwriting.`);return o}function eo(e){return to(e)?typeof e.name=="string"&&e.name.startsWith(x):!1}function _(e){return{type:"command",command:e}}function Tr(e){return[{name:`${x}Session Start`,description:"Inject compact local ToolNet continuity and capture Kiro session activation.",trigger:"SessionStart",action:_(e),timeout:10,enabled:!0},{name:`${x}Prompt Continuity`,description:"Capture prompts and refresh ToolNet guidance only for resume/continue requests.",trigger:"UserPromptSubmit",action:_(e),timeout:10,enabled:!0},{name:`${x}Raw History Guard`,description:"Prevent Kiro from reconstructing continuity from raw ToolNet/agent session history.",trigger:"PreToolUse",matcher:"*",action:_(e),timeout:10,enabled:!0},{name:`${x}Tool Capture`,description:"Capture durable tool activity while filtering noisy read-only events.",trigger:"PostToolUse",matcher:"*",action:_(e),timeout:15,enabled:!0},{name:`${x}Final Flush`,description:"Flush pending Kiro WAL events when the assistant finishes a turn.",trigger:"Stop",action:_(e),timeout:30,enabled:!0}]}function Er(e,t){vr(Pr(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Rr(o,JSON.stringify(t,null,2)+`
1218
- `,{encoding:"utf8",mode:384}),xr(o,e)}finally{Fr(o,{force:!0})}}function re(e,t,o){let n=Zt(e);if(n.version!==void 0&&n.version!=="v1")throw new Error(`Unsupported existing Kiro hooks version: ${String(n.version)}`);let r=n.hooks;if(r!==void 0&&!Array.isArray(r))throw new Error("Invalid existing Kiro hooks file: hooks must be an array.");let s=Array.isArray(r)?r.filter(a=>!eo(a)):[],i=Tr(t),c={...n,version:"v1",hooks:[...s,...i]};if(!o&&JSON.stringify(n)===JSON.stringify(c))return{changed:!1,hookCount:i.length};Er(e,c);let l=Zt(e);if(l.version!=="v1"||!Array.isArray(l.hooks)||l.hooks.filter(eo).length!==i.length)throw new Error("Kiro hooks were written but verification failed.");return{changed:!0,hookCount:i.length}}function oo(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.scope??"global",n=`${Nr(t)} session:kiro-hook`;if(e.hooksFile){let i=re(e.hooksFile,n,e.force??!1);return{hooksFile:e.hooksFile,...i}}if(o==="both"){let i=de(),c=me({cwd:e.cwd}),l=re(i,n,e.force??!1),a=re(c,n,e.force??!1);return{hooksFile:i,changed:l.changed||a.changed,hookCount:l.hookCount}}let r=o==="project"?me({cwd:e.cwd}):de(),s=re(r,n,e.force??!1);return{hooksFile:r,...s}}import{existsSync as Mr,mkdirSync as Ar,readFileSync as Hr,renameSync as _r,rmSync as Dr,writeFileSync as $r}from"node:fs";import{dirname as Jr}from"node:path";function D(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function no(e){if(!Mr(e))return{};let t=Hr(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing Kiro MCP config at ${e}: parse error. Not overwriting.`)}if(!D(o))throw new Error(`Invalid existing Kiro MCP config at ${e}: root must be a JSON object. Not overwriting.`);return o}function ro(e,t){return D(e)?e.command===t&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp"&&e.disabled===!1:!1}function Gr(e,t){Ar(Jr(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{$r(o,`${JSON.stringify(t,null,2)}
1219
- `,{encoding:"utf8",mode:384}),_r(o,e)}finally{Dr(o,{force:!0})}}function ie(e,t,o,n){let r=no(e),s=r.mcpServers;if(s!==void 0&&!D(s))throw new Error(`Invalid existing Kiro MCP config: mcpServers must be an object in ${e}.`);let i=D(s)?{...s}:{},c=i[o];if(ro(c,t)&&!n)return{installed:!0,changed:!1};i[o]={command:t,args:["mcp"],disabled:!1};let l={...r,mcpServers:i};Gr(e,l);let u=no(e).mcpServers;if(!D(u)||!ro(u[o],t))throw new Error(`Kiro MCP configuration was written but verification failed for ${e}.`);return{installed:!0,changed:!0}}function io(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.serverName??"toolnet-memory",n=e.scope??"global";if(e.configFile)return{...ie(e.configFile,t,o,e.force??!1),configFile:e.configFile,serverName:o,command:t,args:["mcp"]};if(n==="both"){let i=U(),c=fe({cwd:e.cwd}),l=ie(i,t,o,e.force??!1),a=ie(c,t,o,e.force??!1);return{installed:!0,changed:l.changed||a.changed,configFile:i,serverName:o,command:t,args:["mcp"]}}let r=n==="project"?fe({cwd:e.cwd}):U();return{...ie(r,t,o,e.force??!1),configFile:r,serverName:o,command:t,args:["mcp"]}}function so(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=io({binary:t,configFile:e.configFile,scope:e.scope,cwd:e.cwd,force:e.force}),n=oo({binary:t,hooksFile:e.hooksFile,scope:e.scope,cwd:e.cwd,force:e.force});return{installed:o.installed,changed:o.changed||n.changed,mcp:o,hooks:n,files:[o.configFile,n.hooksFile]}}import{existsSync as Lr,mkdirSync as Kr,readFileSync as Br,renameSync as Ur,rmSync as qr,writeFileSync as Wr}from"node:fs";import{dirname as Yr}from"node:path";function Fe(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Xr(e){if(!Lr(e))return{};let t=Br(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing ToolNet CLI MCP config at ${e}: parse error. Not overwriting.`)}if(!Fe(o))throw new Error(`Invalid existing ToolNet CLI MCP config at ${e}: root must be a JSON object. Not overwriting.`);return o}function Vr(e,t){Kr(Yr(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{Wr(o,`${JSON.stringify(t,null,2)}
1220
- `,{encoding:"utf8",mode:384}),Ur(o,e)}finally{qr(o,{force:!0})}}function co(e={}){let t=e.binary??"toolnet-memory",o=e.configFile??tt({cwd:e.cwd}),n=Xr(o),r="toolnet-memory";if(Fe(n.mcpServers)&&n.mcpServers[r]!=null&&!e.force)return{installed:!0,changed:!1,configFile:o};let i=Fe(n.mcpServers)?{...n.mcpServers}:{};return i[r]={command:t,args:["mcp"]},n.mcpServers=i,Vr(o,n),{installed:!0,changed:!0,configFile:o}}function lo(e={}){let t=e.binary??"toolnet-memory",o=co({binary:t,configFile:e.configFile,force:e.force,cwd:e.cwd});return{installed:o.installed,changed:o.changed,mcp:{...o,configured:o.installed},files:[o.configFile]}}import{mkdirSync as ri,existsSync as ii}from"node:fs";import{dirname as si}from"node:path";import{existsSync as zr,mkdirSync as Qr,readFileSync as Zr,renameSync as ei,rmSync as ti,writeFileSync as oi}from"node:fs";import{dirname as ni}from"node:path";function d(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function j(e,t){if(!zr(e))return{};let o=Zr(e,"utf8").trim();if(!o)return{};let n;try{n=JSON.parse(o)}catch(r){throw new Error(`Invalid existing ${t} MCP config: ${r instanceof Error?r.message:String(r)}`)}if(!d(n))throw new Error(`Invalid existing ${t} MCP config: root must be a JSON object.`);return n}function F(e,t){Qr(ni(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{oi(o,`${JSON.stringify(t,null,2)}
1221
- `,{encoding:"utf8",mode:384}),ei(o,e)}finally{ti(o,{force:!0})}}function ao(e={}){let t=e.binary??"toolnet-memory",o=e.configFile??ke(),n=si(o);ii(n)||ri(n,{recursive:!0});let r=j(o,"Kilo"),s=r.mcp;if(s!==void 0&&!d(s))throw new Error("Invalid existing Kilo config: mcp must be an object.");let i=d(s)?{...s}:{},c="toolnet-memory";return d(i[c])&&!e.force?{installed:!0,changed:!1,configFile:o,configured:!0}:(i[c]={type:"local",command:[t,"mcp"],enabled:!0,timeout:1e4},F(o,{...r,mcp:i}),{installed:!0,changed:!0,configFile:o,configured:!0})}function uo(e={}){let t=e.binary??"toolnet-memory",o=ao({binary:t,configFile:e.configFile,force:e.force});return{installed:o.installed,changed:o.changed,mcp:o,files:[o.configFile]}}import{existsSync as ci,mkdirSync as li,readFileSync as ai,renameSync as ui,rmSync as pi,writeFileSync as gi}from"node:fs";import{dirname as fi}from"node:path";function f(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function k(e,t){if(!ci(e))return{};let o=ai(e,"utf8").trim();if(!o)return{};let n;try{n=JSON.parse(o)}catch(r){throw new Error(`Invalid existing ${t} hooks file: ${r instanceof Error?r.message:String(r)}`)}if(!f(n))throw new Error(`Invalid existing ${t} hooks file: root must be a JSON object.`);return n}function R(e,t){li(fi(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{gi(o,`${JSON.stringify(t,null,2)}
1222
- `,{encoding:"utf8",mode:384}),ui(o,e)}finally{pi(o,{force:!0})}}function Re(e){return/^[A-Za-z0-9_./:-]+$/u.test(e)?e:`'${e.replace(/'/gu,"'\\''")}'`}var $=[["sessionStart",10],["beforeSubmitPrompt",10],["preToolUse",10],["postToolUse",15],["afterAgentResponse",15],["stop",30]];function po(e){return f(e)&&typeof e.command=="string"&&e.command.includes("session:cursor-hook")}function di(e,t,o){let r={type:"command",command:`TOOLNET_HOOK_EVENT=${Re(e)} ${Re(t)} session:cursor-hook`,timeout:o};return e==="preToolUse"&&(r.matcher=".*"),r}function Pe(e={}){let t=e.hooksFile??Y(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=k(t,"Cursor");if(n.version!==void 0&&n.version!==1)throw new Error(`Unsupported existing Cursor hooks version: ${String(n.version)}`);let r=n.hooks;if(r!==void 0&&!f(r))throw new Error("Invalid existing Cursor hooks file: hooks must be an object.");let s=f(r)?{...r}:{};for(let[a,u]of $){let p=s[a];if(p!==void 0&&!Array.isArray(p))throw new Error(`Invalid existing Cursor hooks file: hooks.${a} must be an array.`);let g=Array.isArray(p)?p.filter(T=>!po(T)):[];s[a]=[...g,di(a,o,u)]}let i={...n,version:1,hooks:s};if(JSON.stringify(n)===JSON.stringify(i))return{hooksFile:t,changed:!1,hookCount:$.length};R(t,i);let c=k(t,"Cursor");if(c.version!==1||!f(c.hooks))throw new Error("Cursor hooks were written but verification failed.");let l=0;for(let[a]of $){let u=c.hooks[a];if(!Array.isArray(u))throw new Error("Cursor hooks were written but verification failed.");l+=u.filter(po).length}if(l!==$.length)throw new Error("Cursor hooks were written but verification failed.");return{hooksFile:t,changed:!0,hookCount:$.length}}function go(e,t){return d(e)?(e.type===void 0||e.type==="stdio")&&e.command===t&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp":!1}function Ne(e={}){let t=e.configFile??W(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=j(t,"Cursor"),s=r.mcpServers;if(s!==void 0&&!d(s))throw new Error("Invalid existing Cursor MCP config: mcpServers must be an object.");let i=d(s)?{...s}:{};if(go(i[n],o))return{installed:!0,changed:!1,configFile:t,serverName:n,command:o,args:["mcp"]};i[n]={type:"stdio",command:o,args:["mcp"]},F(t,{...r,mcpServers:i});let l=j(t,"Cursor").mcpServers;if(!d(l)||!go(l[n],o))throw new Error("Cursor MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:t,serverName:n,command:o,args:["mcp"]}}import{mkdirSync as mi,readFileSync as fo,renameSync as yi,rmSync as hi,writeFileSync as ki}from"node:fs";import{dirname as bi}from"node:path";var Te=`---
1214
+ `),Jt(t,n,{encoding:"utf8",mode:384}),{configFile:t,previousFile:o,preservedPrevious:u.length>0&&!p}}import{existsSync as Qn,mkdirSync as Zn,readFileSync as er,writeFileSync as tr}from"node:fs";import{homedir as or}from"node:os";import{dirname as nr,join as Kt}from"node:path";function rr(e){return`'${e.replace(/'/g,"'\\''")}'`}function Ut(e={}){let t=e.hooksFile??Kt(process.env.CODEX_HOME??Kt(or(),".codex"),"hooks.json");Zn(nr(t),{recursive:!0});let o={};if(Qn(t))try{o=JSON.parse(er(t,"utf8"))}catch(c){throw new Error(`Invalid existing Codex hooks.json: ${c instanceof Error?c.message:String(c)}`)}let n=o.hooks&&typeof o.hooks=="object"&&!Array.isArray(o.hooks)?o.hooks:{};o.hooks=n;let s=(Array.isArray(n.SessionStart)?n.SessionStart:[]).filter(c=>{try{return!JSON.stringify(c).includes("session:codex-context")}catch{return!0}}),i=e.binary??"toolnet-memory";return s.push({matcher:"startup|resume|clear|compact",hooks:[{type:"command",command:`${rr(i)} session:codex-context`,timeout:15,additionalContextLimit:1e3,statusMessage:"Loading ToolNet project continuity"}]}),n.SessionStart=s,tr(t,JSON.stringify(o,null,2)+`
1215
+ `,{encoding:"utf8",mode:384}),t}import{spawnSync as ir}from"node:child_process";function ve(e,t){return ir(e,t,{encoding:"utf8",stdio:["ignore","pipe","pipe"]})}function Bt(e,t){let o=ve(e,["mcp","get",t,"--json"]);if(o.status!==0||!o.stdout)return null;try{return JSON.parse(o.stdout)}catch{return null}}function qt(e,t){return e.enabled!==!1&&e.transport?.type==="stdio"&&e.transport?.command===t&&Array.isArray(e.transport?.args)&&e.transport?.args.length===1&&e.transport.args[0]==="mcp"}function Wt(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.codexBinary??"codex",n=e.serverName??"toolnet-memory",r=Bt(o,n);if(r&&qt(r,t))return{installed:!0,changed:!1,serverName:n,command:t,args:["mcp"]};if(r){let c=ve(o,["mcp","remove",n]);if(c.status!==0)return{installed:!1,changed:!1,serverName:n,command:t,args:["mcp"],error:(c.stderr||c.stdout||"Unable to remove old ToolNet MCP configuration.").trim()}}let s=ve(o,["mcp","add",n,"--",t,"mcp"]);if(s.status!==0)return{installed:!1,changed:!1,serverName:n,command:t,args:["mcp"],error:(s.stderr||s.stdout||"Unable to register ToolNet MCP.").trim()};let i=Bt(o,n);return!i||!qt(i,t)?{installed:!1,changed:!0,serverName:n,command:t,args:["mcp"],error:"Codex accepted MCP registration but verification did not match expected ToolNet command."}:{installed:!0,changed:!0,serverName:n,command:t,args:["mcp"]}}import{existsSync as sr,mkdirSync as cr,readFileSync as lr,renameSync as ar,rmSync as ur,writeFileSync as pr}from"node:fs";import{dirname as gr}from"node:path";function A(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function fr(e){return/^[A-Za-z0-9_./:-]+$/u.test(e)?e:`'${e.replace(/'/gu,"'\\''")}'`}function dr(e){if(!sr(e))return{};let t;try{t=JSON.parse(lr(e,"utf8"))}catch(o){throw new Error(`Invalid existing Claude settings.json: ${o instanceof Error?o.message:String(o)}`)}if(!A(t))throw new Error("Invalid existing Claude settings.json: root must be a JSON object.");return t}function Se(e){if(e===void 0)return[];if(!Array.isArray(e))throw new Error("Invalid existing Claude settings.json: hook event must be an array.");let t=[];for(let o of e){if(!A(o)){t.push(o);continue}let n=o.hooks;if(!Array.isArray(n)){t.push(o);continue}let r=n.filter(s=>{if(!A(s))return!0;let i=s.command;return!(typeof i=="string"&&i.includes("session:claude-hook"))});r.length!==0&&t.push({...o,hooks:r})}return t}function xe(e){return{type:"command",command:e,timeout:10}}function mr(e,t){cr(gr(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{pr(o,JSON.stringify(t,null,2)+`
1216
+ `,{encoding:"utf8",mode:384}),ar(o,e)}finally{ur(o,{force:!0})}}function Yt(e={}){let t=e.settingsFile??ze(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=dr(t),r=n.hooks;if(r!==void 0&&!A(r))throw new Error("Invalid existing Claude settings.json: hooks must be an object.");let s=A(r)?{...r}:{},i=`${fr(o)} session:claude-hook`,c=Se(s.SessionStart);c.push({matcher:"startup|resume|clear|compact",hooks:[xe(i)]}),s.SessionStart=c;let l=Se(s.PostToolUse);l.push({matcher:"Edit|Write",hooks:[xe(i)]}),s.PostToolUse=l;let a=Se(s.Stop);a.push({hooks:[xe(i)]}),s.Stop=a;let u={...n,hooks:s},p=JSON.stringify(n),g=JSON.stringify(u);return p===g?{settingsFile:t,changed:!1}:(mr(t,u),{settingsFile:t,changed:!0})}import{existsSync as yr,mkdirSync as hr,readFileSync as kr,renameSync as br,rmSync as jr,writeFileSync as Ir}from"node:fs";import{dirname as Cr}from"node:path";function _(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Vt(e){if(!yr(e))return{};let t;try{t=JSON.parse(kr(e,"utf8"))}catch(o){throw new Error(`Invalid existing Claude Code config: ${o instanceof Error?o.message:String(o)}`)}if(!_(t))throw new Error("Invalid existing Claude Code config: root must be a JSON object.");return t}function Xt(e,t){if(!_(e))return!1;let o=e.args;return e.type==="stdio"&&e.command===t&&Array.isArray(o)&&o.length===1&&o[0]==="mcp"}function Or(e,t){hr(Cr(e),{recursive:!0});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Ir(o,JSON.stringify(t,null,2)+`
1217
+ `,{encoding:"utf8",mode:384}),br(o,e)}finally{jr(o,{force:!0})}}function zt(e={}){let t=e.stateFile??Qe(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=Vt(t),s=r.mcpServers;if(s!==void 0&&!_(s))throw new Error("Invalid existing Claude Code config: mcpServers must be an object.");let i=_(s)?{...s}:{},c=i[n];if(Xt(c,o))return{installed:!0,changed:!1,configFile:t,serverName:n,command:[o,"mcp"],repaired:!1};let l=c!==void 0;i[n]={type:"stdio",command:o,args:["mcp"]},Or(t,{...r,mcpServers:i});let u=Vt(t).mcpServers;if(!_(u)||!Xt(u[n],o))throw new Error("Claude Code MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:t,serverName:n,command:[o,"mcp"],repaired:l}}function Qt(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=Yt({binary:t,settingsFile:e.settingsFile}),n=zt({binary:t,stateFile:e.stateFile});return{hooks:o,mcp:n,files:[o.settingsFile,n.configFile]}}import{existsSync as wr,mkdirSync as vr,readFileSync as Sr,renameSync as xr,rmSync as Fr,writeFileSync as Rr}from"node:fs";import{dirname as Pr}from"node:path";var x="ToolNet Memory - ";function to(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Nr(e){return/^[A-Za-z0-9_./:-]+$/u.test(e)?e:`'${e.replace(/'/gu,"'\\''")}'`}function Zt(e){if(!wr(e))return{};let t=Sr(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing Kiro hooks file at ${e}: parse error. Not overwriting.`)}if(!to(o))throw new Error(`Invalid existing Kiro hooks file at ${e}: root must be a JSON object. Not overwriting.`);return o}function eo(e){return to(e)?typeof e.name=="string"&&e.name.startsWith(x):!1}function H(e){return{type:"command",command:e}}function Er(e){return[{name:`${x}Session Start`,description:"Inject compact local ToolNet continuity and capture Kiro session activation.",trigger:"SessionStart",action:H(e),timeout:10,enabled:!0},{name:`${x}Prompt Continuity`,description:"Capture prompts and refresh ToolNet guidance only for resume/continue requests.",trigger:"UserPromptSubmit",action:H(e),timeout:10,enabled:!0},{name:`${x}Raw History Guard`,description:"Prevent Kiro from reconstructing continuity from raw ToolNet/agent session history.",trigger:"PreToolUse",matcher:"*",action:H(e),timeout:10,enabled:!0},{name:`${x}Tool Capture`,description:"Capture durable tool activity while filtering noisy read-only events.",trigger:"PostToolUse",matcher:"*",action:H(e),timeout:15,enabled:!0},{name:`${x}Final Flush`,description:"Flush pending Kiro WAL events when the assistant finishes a turn.",trigger:"Stop",action:H(e),timeout:30,enabled:!0}]}function Tr(e,t){vr(Pr(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Rr(o,JSON.stringify(t,null,2)+`
1218
+ `,{encoding:"utf8",mode:384}),xr(o,e)}finally{Fr(o,{force:!0})}}function re(e,t,o){let n=Zt(e);if(n.version!==void 0&&n.version!=="v1")throw new Error(`Unsupported existing Kiro hooks version: ${String(n.version)}`);let r=n.hooks;if(r!==void 0&&!Array.isArray(r))throw new Error("Invalid existing Kiro hooks file: hooks must be an array.");let s=Array.isArray(r)?r.filter(a=>!eo(a)):[],i=Er(t),c={...n,version:"v1",hooks:[...s,...i]};if(!o&&JSON.stringify(n)===JSON.stringify(c))return{changed:!1,hookCount:i.length};Tr(e,c);let l=Zt(e);if(l.version!=="v1"||!Array.isArray(l.hooks)||l.hooks.filter(eo).length!==i.length)throw new Error("Kiro hooks were written but verification failed.");return{changed:!0,hookCount:i.length}}function oo(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.scope??"global",n=`${Nr(t)} session:kiro-hook`;if(e.hooksFile){let i=re(e.hooksFile,n,e.force??!1);return{hooksFile:e.hooksFile,...i}}if(o==="both"){let i=de(),c=me({cwd:e.cwd}),l=re(i,n,e.force??!1),a=re(c,n,e.force??!1);return{hooksFile:i,changed:l.changed||a.changed,hookCount:l.hookCount}}let r=o==="project"?me({cwd:e.cwd}):de(),s=re(r,n,e.force??!1);return{hooksFile:r,...s}}import{existsSync as Mr,mkdirSync as Ar,readFileSync as _r,renameSync as Hr,rmSync as Dr,writeFileSync as Jr}from"node:fs";import{dirname as $r}from"node:path";function D(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function no(e){if(!Mr(e))return{};let t=_r(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing Kiro MCP config at ${e}: parse error. Not overwriting.`)}if(!D(o))throw new Error(`Invalid existing Kiro MCP config at ${e}: root must be a JSON object. Not overwriting.`);return o}function ro(e,t){return D(e)?e.command===t&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp"&&e.disabled===!1:!1}function Gr(e,t){Ar($r(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{Jr(o,`${JSON.stringify(t,null,2)}
1219
+ `,{encoding:"utf8",mode:384}),Hr(o,e)}finally{Dr(o,{force:!0})}}function ie(e,t,o,n){let r=no(e),s=r.mcpServers;if(s!==void 0&&!D(s))throw new Error(`Invalid existing Kiro MCP config: mcpServers must be an object in ${e}.`);let i=D(s)?{...s}:{},c=i[o];if(ro(c,t)&&!n)return{installed:!0,changed:!1};i[o]={command:t,args:["mcp"],disabled:!1};let l={...r,mcpServers:i};Gr(e,l);let u=no(e).mcpServers;if(!D(u)||!ro(u[o],t))throw new Error(`Kiro MCP configuration was written but verification failed for ${e}.`);return{installed:!0,changed:!0}}function io(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.serverName??"toolnet-memory",n=e.scope??"global";if(e.configFile)return{...ie(e.configFile,t,o,e.force??!1),configFile:e.configFile,serverName:o,command:t,args:["mcp"]};if(n==="both"){let i=B(),c=fe({cwd:e.cwd}),l=ie(i,t,o,e.force??!1),a=ie(c,t,o,e.force??!1);return{installed:!0,changed:l.changed||a.changed,configFile:i,serverName:o,command:t,args:["mcp"]}}let r=n==="project"?fe({cwd:e.cwd}):B();return{...ie(r,t,o,e.force??!1),configFile:r,serverName:o,command:t,args:["mcp"]}}function so(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=io({binary:t,configFile:e.configFile,scope:e.scope,cwd:e.cwd,force:e.force}),n=oo({binary:t,hooksFile:e.hooksFile,scope:e.scope,cwd:e.cwd,force:e.force});return{installed:o.installed,changed:o.changed||n.changed,mcp:o,hooks:n,files:[o.configFile,n.hooksFile]}}import{existsSync as Lr,mkdirSync as Kr,readFileSync as Ur,renameSync as Br,rmSync as qr,writeFileSync as Wr}from"node:fs";import{dirname as Yr}from"node:path";function Fe(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Vr(e){if(!Lr(e))return{};let t=Ur(e,"utf8").trim();if(!t)return{};let o;try{o=JSON.parse(t)}catch{throw new Error(`Invalid existing ToolNet CLI MCP config at ${e}: parse error. Not overwriting.`)}if(!Fe(o))throw new Error(`Invalid existing ToolNet CLI MCP config at ${e}: root must be a JSON object. Not overwriting.`);return o}function Xr(e,t){Kr(Yr(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{Wr(o,`${JSON.stringify(t,null,2)}
1220
+ `,{encoding:"utf8",mode:384}),Br(o,e)}finally{qr(o,{force:!0})}}function co(e={}){let t=e.binary??"toolnet-memory",o=e.configFile??tt({cwd:e.cwd}),n=Vr(o),r="toolnet-memory";if(Fe(n.mcpServers)&&n.mcpServers[r]!=null&&!e.force)return{installed:!0,changed:!1,configFile:o};let i=Fe(n.mcpServers)?{...n.mcpServers}:{};return i[r]={command:t,args:["mcp"]},n.mcpServers=i,Xr(o,n),{installed:!0,changed:!0,configFile:o}}function lo(e={}){let t=e.binary??"toolnet-memory",o=co({binary:t,configFile:e.configFile,force:e.force,cwd:e.cwd});return{installed:o.installed,changed:o.changed,mcp:{...o,configured:o.installed},files:[o.configFile]}}import{mkdirSync as ri,existsSync as ii}from"node:fs";import{dirname as si}from"node:path";import{existsSync as zr,mkdirSync as Qr,readFileSync as Zr,renameSync as ei,rmSync as ti,writeFileSync as oi}from"node:fs";import{dirname as ni}from"node:path";function d(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function C(e,t){if(!zr(e))return{};let o=Zr(e,"utf8").trim();if(!o)return{};let n;try{n=JSON.parse(o)}catch(r){throw new Error(`Invalid existing ${t} MCP config: ${r instanceof Error?r.message:String(r)}`)}if(!d(n))throw new Error(`Invalid existing ${t} MCP config: root must be a JSON object.`);return n}function F(e,t){Qr(ni(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{oi(o,`${JSON.stringify(t,null,2)}
1221
+ `,{encoding:"utf8",mode:384}),ei(o,e)}finally{ti(o,{force:!0})}}function ao(e={}){let t=e.binary??"toolnet-memory",o=e.configFile??ke(),n=si(o);ii(n)||ri(n,{recursive:!0});let r=C(o,"Kilo"),s=r.mcp;if(s!==void 0&&!d(s))throw new Error("Invalid existing Kilo config: mcp must be an object.");let i=d(s)?{...s}:{},c="toolnet-memory";return d(i[c])&&!e.force?{installed:!0,changed:!1,configFile:o,configured:!0}:(i[c]={type:"local",command:[t,"mcp"],enabled:!0,timeout:1e4},F(o,{...r,mcp:i}),{installed:!0,changed:!0,configFile:o,configured:!0})}function uo(e={}){let t=e.binary??"toolnet-memory",o=ao({binary:t,configFile:e.configFile,force:e.force});return{installed:o.installed,changed:o.changed,mcp:o,files:[o.configFile]}}import{existsSync as ci,mkdirSync as li,readFileSync as ai,renameSync as ui,rmSync as pi,writeFileSync as gi}from"node:fs";import{dirname as fi}from"node:path";function f(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function k(e,t){if(!ci(e))return{};let o=ai(e,"utf8").trim();if(!o)return{};let n;try{n=JSON.parse(o)}catch(r){throw new Error(`Invalid existing ${t} hooks file: ${r instanceof Error?r.message:String(r)}`)}if(!f(n))throw new Error(`Invalid existing ${t} hooks file: root must be a JSON object.`);return n}function R(e,t){li(fi(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{gi(o,`${JSON.stringify(t,null,2)}
1222
+ `,{encoding:"utf8",mode:384}),ui(o,e)}finally{pi(o,{force:!0})}}function Re(e){return/^[A-Za-z0-9_./:-]+$/u.test(e)?e:`'${e.replace(/'/gu,"'\\''")}'`}var J=[["sessionStart",10],["beforeSubmitPrompt",10],["preToolUse",10],["postToolUse",15],["afterAgentResponse",15],["stop",30]];function po(e){return f(e)&&typeof e.command=="string"&&e.command.includes("session:cursor-hook")}function di(e,t,o){let r={type:"command",command:`TOOLNET_HOOK_EVENT=${Re(e)} ${Re(t)} session:cursor-hook`,timeout:o};return e==="preToolUse"&&(r.matcher=".*"),r}function Pe(e={}){let t=e.hooksFile??Y(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=k(t,"Cursor");if(n.version!==void 0&&n.version!==1)throw new Error(`Unsupported existing Cursor hooks version: ${String(n.version)}`);let r=n.hooks;if(r!==void 0&&!f(r))throw new Error("Invalid existing Cursor hooks file: hooks must be an object.");let s=f(r)?{...r}:{};for(let[a,u]of J){let p=s[a];if(p!==void 0&&!Array.isArray(p))throw new Error(`Invalid existing Cursor hooks file: hooks.${a} must be an array.`);let g=Array.isArray(p)?p.filter(E=>!po(E)):[];s[a]=[...g,di(a,o,u)]}let i={...n,version:1,hooks:s};if(JSON.stringify(n)===JSON.stringify(i))return{hooksFile:t,changed:!1,hookCount:J.length};R(t,i);let c=k(t,"Cursor");if(c.version!==1||!f(c.hooks))throw new Error("Cursor hooks were written but verification failed.");let l=0;for(let[a]of J){let u=c.hooks[a];if(!Array.isArray(u))throw new Error("Cursor hooks were written but verification failed.");l+=u.filter(po).length}if(l!==J.length)throw new Error("Cursor hooks were written but verification failed.");return{hooksFile:t,changed:!0,hookCount:J.length}}function go(e,t){return d(e)?(e.type===void 0||e.type==="stdio")&&e.command===t&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp":!1}function Ne(e={}){let t=e.configFile??W(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=C(t,"Cursor"),s=r.mcpServers;if(s!==void 0&&!d(s))throw new Error("Invalid existing Cursor MCP config: mcpServers must be an object.");let i=d(s)?{...s}:{};if(go(i[n],o))return{installed:!0,changed:!1,configFile:t,serverName:n,command:o,args:["mcp"]};i[n]={type:"stdio",command:o,args:["mcp"]},F(t,{...r,mcpServers:i});let l=C(t,"Cursor").mcpServers;if(!d(l)||!go(l[n],o))throw new Error("Cursor MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:t,serverName:n,command:o,args:["mcp"]}}import{mkdirSync as mi,readFileSync as fo,renameSync as yi,rmSync as hi,writeFileSync as ki}from"node:fs";import{dirname as bi}from"node:path";var Ee=`---
1223
1223
  description: ToolNet Memory project continuity and safety rules
1224
1224
  alwaysApply: true
1225
1225
  ---
@@ -1246,7 +1246,7 @@ Use ToolNet Memory as the continuity source for this project.
1246
1246
  - Do not ask the user to repeat project context that ToolNet already provides.
1247
1247
 
1248
1248
  Current repository evidence overrides stale memory.
1249
- `;function Ci(e,t){mi(bi(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{ki(o,t,{encoding:"utf8",mode:384}),yi(o,e)}finally{hi(o,{force:!0})}}function mo(e){let t=e.ruleFile??ct(e.projectRoot);try{if(fo(t,"utf8")===Te)return{ruleFile:t,changed:!1}}catch{}if(Ci(t,Te),fo(t,"utf8")!==Te)throw new Error("Cursor ToolNet project rule was written but verification failed.");return{ruleFile:t,changed:!0}}import{spawnSync as Oi}from"node:child_process";import{existsSync as P,statSync as ji}from"node:fs";import{dirname as wi,join as Ii,parse as vi,resolve as Me}from"node:path";function yo(e){let t=Me(e);if(!P(t))throw new Error(`Project path does not exist: ${t}`);if(!ji(t).isDirectory())throw new Error(`Project path is not a directory: ${t}`);return t}function se(e){return Ii(e,".toolnet","project.json")}function Si(e){let t=Me(e),o=vi(t).root;for(;;){if(P(se(t)))return t;if(t===o)return;let n=wi(t);if(n===t)return;t=n}}function Ee(e){let t=Oi("git",["rev-parse","--show-toplevel"],{cwd:e,encoding:"utf8",timeout:5e3});if(t.status!==0)return;let o=t.stdout.trim();return o?Me(o):void 0}function b(e={}){let t=yo(e.cwd??process.cwd());if(e.project){let r=yo(e.project),s=se(r),i=Ee(r);return{root:r,source:"explicit",eligible:!0,toolnetProject:P(s),manifestFile:P(s)?s:void 0,gitRoot:i}}let o=Si(t);if(o){let r=se(o);return{root:o,source:"toolnet",eligible:!0,toolnetProject:!0,manifestFile:r,gitRoot:Ee(o)}}let n=Ee(t);if(n){let r=se(n);return{root:n,source:"git",eligible:!0,toolnetProject:P(r),manifestFile:P(r)?r:void 0,gitRoot:n}}return{root:t,source:"cwd",eligible:!1,toolnetProject:!1}}function Co(e,t={}){let o=[],n=e.indexOf("--scope");if(n>=0){let s=e[n+1];if(s!=="global"&&s!=="project"&&s!=="both")throw new Error(`Invalid --scope value: ${String(s)}`);o.push(s)}e.includes("--global")&&o.push("global"),e.includes("--both")&&o.push("both");let r=Array.from(new Set(o));if(r.length>1)throw new Error(`Conflicting integration scopes: ${r.join(", ")}`);return r[0]??t.defaultScope??"global"}function ho(e,t){return{install:e,effective:t}}function C(e,t){return{surface:e,global:ho(t.globalInstall,t.effective==="global"||t.effective==="both"),project:ho(t.projectInstall,t.effective==="project"||t.effective==="both"),effective:t.effective,risk:t.risk??"none",dedupeRequired:t.dedupeRequired??!1,trustRequired:t.trustRequired??t.projectInstall,note:t.note}}function xi(e){return{mcp:C("mcp",{globalInstall:!0,projectInstall:!1,effective:"global"}),hooks:C("hooks",{globalInstall:!0,projectInstall:!1,effective:"global"}),work:C("work",{globalInstall:e==="grok",projectInstall:!1,effective:e==="grok"?"global":"none",note:e==="grok"?"Grok supports a global ToolNet continuity skill.":"Cursor/Copilot work instructions remain project-scoped."})}}function ko(e){return{mcp:C("mcp",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),hooks:C("hooks",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),work:C("work",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!1,note:e==="cursor"?"Use .cursor/rules/toolnet-memory.mdc.":e==="copilot"?"Use .github/instructions/toolnet-memory.instructions.md.":"Use .grok/skills/toolnet-continuity/SKILL.md."})}}function bo(e){return{mcp:C("mcp",{globalInstall:!0,projectInstall:!0,effective:"project",risk:e==="cursor"?"precedence-unverified":"shadowed-global",trustRequired:!0,note:e==="cursor"?"Project ToolNet MCP is the intended effective definition; native same-name precedence must be E2E certified before release.":"Global remains useful outside the project; same-name project definition wins inside the project."}),hooks:C("hooks",{globalInstall:!0,projectInstall:!0,effective:"both",risk:"additive-duplicate",dedupeRequired:!0,trustRequired:!0,note:"Global and project hook sources can both execute for the same native event."}),work:C("work",{globalInstall:e==="grok",projectInstall:!0,effective:"project",risk:e==="grok"?"shadowed-global":"none",trustRequired:!1,note:e==="cursor"?"Project rule is authoritative.":e==="copilot"?"Project instruction is authoritative.":"Project skill shadows the same-name global skill inside the project."})}}function N(e){let{agent:t,scope:o,project:n}=e;return(o==="project"||o==="both")&&(!n||!n.eligible)?{agent:t,requestedScope:o,project:n,surfaces:o==="both"?bo(t):ko(t),canInstall:!1,reason:"Project scope requires an explicit project, existing ToolNet project, or Git repository root."}:{agent:t,requestedScope:o,project:n,surfaces:o==="global"?xi(t):o==="project"?ko(t):bo(t),canInstall:!0}}function Oo(e){return!!(e?.mcp?.changed||e?.hooks?.changed||e?.rule?.changed)}function jo(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.scope??"global",n=o==="global"?void 0:b({project:e.projectRoot}),r=N({agent:"cursor",scope:o,project:n});if(!r.canInstall)throw new Error(r.reason??"Cursor project integration scope cannot be resolved.");let s,i;if((r.surfaces.mcp.global.install||r.surfaces.hooks.global.install||r.surfaces.work.global.install)&&(s={},r.surfaces.mcp.global.install&&(s.mcp=Ne({binary:t,configFile:e.configFile??W()})),r.surfaces.hooks.global.install&&(s.hooks=Pe({binary:t,hooksFile:e.hooksFile??Y()}))),r.surfaces.mcp.project.install||r.surfaces.hooks.project.install||r.surfaces.work.project.install){if(!n?.eligible)throw new Error("Cursor project integration requires an eligible project root.");i={},r.surfaces.mcp.project.install&&(i.mcp=Ne({binary:t,configFile:e.projectConfigFile??it(n.root)})),r.surfaces.hooks.project.install&&(i.hooks=Pe({binary:t,hooksFile:e.projectHooksFile??st(n.root)})),r.surfaces.work.project.install&&(i.rule=mo({projectRoot:n.root,ruleFile:e.projectRuleFile}))}let c=i?.mcp??s?.mcp,l=i?.hooks??s?.hooks;if(!c||!l)throw new Error("Cursor integration did not produce an effective MCP/hooks installation.");let a=Array.from(new Set([s?.mcp?.configFile,s?.hooks?.hooksFile,s?.rule?.ruleFile,i?.mcp?.configFile,i?.hooks?.hooksFile,i?.rule?.ruleFile].filter(u=>typeof u=="string")));return{installed:!0,changed:Oo(s)||Oo(i),scope:o,plan:r,project:n,global:s,projectScope:i,mcp:c,hooks:l,rule:i?.rule,files:a}}var J=[["sessionStart",10],["userPromptSubmitted",10],["userPromptTransformed",10],["preToolUse",10],["postToolUse",15],["agentStop",30]];function Fi(e){if(typeof e.command=="string")return e.command;if(typeof e.bash=="string")return e.bash}function wo(e){return f(e)&&Fi(e)?.includes("session:copilot-hook")===!0}function Ri(e,t,o){let n={type:"command",command:`${t} session:copilot-hook`,env:{TOOLNET_HOOK_EVENT:e},timeoutSec:o};return e==="preToolUse"&&(n.matcher=".*"),n}function Ae(e={}){let t=e.hooksFile??V(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=k(t,"GitHub Copilot CLI");if(n.version!==void 0&&n.version!==1)throw new Error(`Unsupported existing GitHub Copilot CLI hooks version: ${String(n.version)}`);let r=n.hooks;if(r!==void 0&&!f(r))throw new Error("Invalid existing GitHub Copilot CLI hooks file: hooks must be an object.");let s=f(r)?{...r}:{};for(let[a,u]of J){let p=s[a];if(p!==void 0&&!Array.isArray(p))throw new Error(`Invalid existing GitHub Copilot CLI hooks file: hooks.${a} must be an array.`);let g=Array.isArray(p)?p.filter(T=>!wo(T)):[];s[a]=[...g,Ri(a,o,u)]}let i={...n,version:1,hooks:s};if(JSON.stringify(n)===JSON.stringify(i))return{hooksFile:t,changed:!1,hookCount:J.length};R(t,i);let c=k(t,"GitHub Copilot CLI");if(c.version!==1||!f(c.hooks))throw new Error("GitHub Copilot CLI hooks were written but verification failed.");let l=0;for(let[a]of J){let u=c.hooks[a];if(!Array.isArray(u))throw new Error("GitHub Copilot CLI hooks were written but verification failed.");l+=u.filter(wo).length}if(l!==J.length)throw new Error("GitHub Copilot CLI hooks were written but verification failed.");return{hooksFile:t,changed:!0,hookCount:J.length}}function Io(e,t){return d(e)?(e.type===void 0||e.type==="local"||e.type==="stdio")&&e.command===t&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp"&&Array.isArray(e.tools)&&e.tools.length===1&&e.tools[0]==="*":!1}function He(e={}){let t=e.configFile??X(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=j(t,"GitHub Copilot CLI"),s=r.mcpServers;if(s!==void 0&&!d(s))throw new Error("Invalid existing GitHub Copilot CLI MCP config: mcpServers must be an object.");let i=d(s)?{...s}:{};if(Io(i[n],o))return{installed:!0,changed:!1,configFile:t,serverName:n,command:o,args:["mcp"]};i[n]={type:"stdio",command:o,args:["mcp"],tools:["*"]},F(t,{...r,mcpServers:i});let l=j(t,"GitHub Copilot CLI").mcpServers;if(!d(l)||!Io(l[n],o))throw new Error("GitHub Copilot CLI MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:t,serverName:n,command:o,args:["mcp"]}}import{mkdirSync as Pi,readFileSync as vo,renameSync as Ni,rmSync as Ti,writeFileSync as Ei}from"node:fs";import{dirname as Mi}from"node:path";var _e=`---
1249
+ `;function ji(e,t){mi(bi(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{ki(o,t,{encoding:"utf8",mode:384}),yi(o,e)}finally{hi(o,{force:!0})}}function mo(e){let t=e.ruleFile??ct(e.projectRoot);try{if(fo(t,"utf8")===Ee)return{ruleFile:t,changed:!1}}catch{}if(ji(t,Ee),fo(t,"utf8")!==Ee)throw new Error("Cursor ToolNet project rule was written but verification failed.");return{ruleFile:t,changed:!0}}import{spawnSync as Ii}from"node:child_process";import{existsSync as P,statSync as Ci}from"node:fs";import{dirname as Oi,join as wi,parse as vi,resolve as Me}from"node:path";function yo(e){let t=Me(e);if(!P(t))throw new Error(`Project path does not exist: ${t}`);if(!Ci(t).isDirectory())throw new Error(`Project path is not a directory: ${t}`);return t}function se(e){return wi(e,".toolnet","project.json")}function Si(e){let t=Me(e),o=vi(t).root;for(;;){if(P(se(t)))return t;if(t===o)return;let n=Oi(t);if(n===t)return;t=n}}function Te(e){let t=Ii("git",["rev-parse","--show-toplevel"],{cwd:e,encoding:"utf8",timeout:5e3});if(t.status!==0)return;let o=t.stdout.trim();return o?Me(o):void 0}function b(e={}){let t=yo(e.cwd??process.cwd());if(e.project){let r=yo(e.project),s=se(r),i=Te(r);return{root:r,source:"explicit",eligible:!0,toolnetProject:P(s),manifestFile:P(s)?s:void 0,gitRoot:i}}let o=Si(t);if(o){let r=se(o);return{root:o,source:"toolnet",eligible:!0,toolnetProject:!0,manifestFile:r,gitRoot:Te(o)}}let n=Te(t);if(n){let r=se(n);return{root:n,source:"git",eligible:!0,toolnetProject:P(r),manifestFile:P(r)?r:void 0,gitRoot:n}}return{root:t,source:"cwd",eligible:!1,toolnetProject:!1}}function jo(e,t={}){let o=[],n=e.indexOf("--scope");if(n>=0){let s=e[n+1];if(s!=="global"&&s!=="project"&&s!=="both")throw new Error(`Invalid --scope value: ${String(s)}`);o.push(s)}e.includes("--global")&&o.push("global"),e.includes("--both")&&o.push("both");let r=Array.from(new Set(o));if(r.length>1)throw new Error(`Conflicting integration scopes: ${r.join(", ")}`);return r[0]??t.defaultScope??"global"}function ho(e,t){return{install:e,effective:t}}function j(e,t){return{surface:e,global:ho(t.globalInstall,t.effective==="global"||t.effective==="both"),project:ho(t.projectInstall,t.effective==="project"||t.effective==="both"),effective:t.effective,risk:t.risk??"none",dedupeRequired:t.dedupeRequired??!1,trustRequired:t.trustRequired??t.projectInstall,note:t.note}}function xi(e){return{mcp:j("mcp",{globalInstall:!0,projectInstall:!1,effective:"global"}),hooks:j("hooks",{globalInstall:!0,projectInstall:!1,effective:"global"}),work:j("work",{globalInstall:e==="grok",projectInstall:!1,effective:e==="grok"?"global":"none",note:e==="grok"?"Grok supports a global ToolNet continuity skill.":"Cursor/Copilot work instructions remain project-scoped."})}}function ko(e){return{mcp:j("mcp",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),hooks:j("hooks",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),work:j("work",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!1,note:e==="cursor"?"Use .cursor/rules/toolnet-memory.mdc.":e==="copilot"?"Use .github/instructions/toolnet-memory.instructions.md.":"Use .grok/skills/toolnet-continuity/SKILL.md."})}}function bo(e){return{mcp:j("mcp",{globalInstall:!0,projectInstall:!0,effective:"project",risk:e==="cursor"?"precedence-unverified":"shadowed-global",trustRequired:!0,note:e==="cursor"?"Project ToolNet MCP is the intended effective definition; native same-name precedence must be E2E certified before release.":"Global remains useful outside the project; same-name project definition wins inside the project."}),hooks:j("hooks",{globalInstall:!0,projectInstall:!0,effective:"both",risk:"additive-duplicate",dedupeRequired:!0,trustRequired:!0,note:"Global and project hook sources can both execute for the same native event."}),work:j("work",{globalInstall:e==="grok",projectInstall:!0,effective:"project",risk:e==="grok"?"shadowed-global":"none",trustRequired:!1,note:e==="cursor"?"Project rule is authoritative.":e==="copilot"?"Project instruction is authoritative.":"Project skill shadows the same-name global skill inside the project."})}}function N(e){let{agent:t,scope:o,project:n}=e;return(o==="project"||o==="both")&&(!n||!n.eligible)?{agent:t,requestedScope:o,project:n,surfaces:o==="both"?bo(t):ko(t),canInstall:!1,reason:"Project scope requires an explicit project, existing ToolNet project, or Git repository root."}:{agent:t,requestedScope:o,project:n,surfaces:o==="global"?xi(t):o==="project"?ko(t):bo(t),canInstall:!0}}function Io(e){return!!(e?.mcp?.changed||e?.hooks?.changed||e?.rule?.changed)}function Co(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.scope??"global",n=o==="global"?void 0:b({project:e.projectRoot}),r=N({agent:"cursor",scope:o,project:n});if(!r.canInstall)throw new Error(r.reason??"Cursor project integration scope cannot be resolved.");let s,i;if((r.surfaces.mcp.global.install||r.surfaces.hooks.global.install||r.surfaces.work.global.install)&&(s={},r.surfaces.mcp.global.install&&(s.mcp=Ne({binary:t,configFile:e.configFile??W()})),r.surfaces.hooks.global.install&&(s.hooks=Pe({binary:t,hooksFile:e.hooksFile??Y()}))),r.surfaces.mcp.project.install||r.surfaces.hooks.project.install||r.surfaces.work.project.install){if(!n?.eligible)throw new Error("Cursor project integration requires an eligible project root.");i={},r.surfaces.mcp.project.install&&(i.mcp=Ne({binary:t,configFile:e.projectConfigFile??it(n.root)})),r.surfaces.hooks.project.install&&(i.hooks=Pe({binary:t,hooksFile:e.projectHooksFile??st(n.root)})),r.surfaces.work.project.install&&(i.rule=mo({projectRoot:n.root,ruleFile:e.projectRuleFile}))}let c=i?.mcp??s?.mcp,l=i?.hooks??s?.hooks;if(!c||!l)throw new Error("Cursor integration did not produce an effective MCP/hooks installation.");let a=Array.from(new Set([s?.mcp?.configFile,s?.hooks?.hooksFile,s?.rule?.ruleFile,i?.mcp?.configFile,i?.hooks?.hooksFile,i?.rule?.ruleFile].filter(u=>typeof u=="string")));return{installed:!0,changed:Io(s)||Io(i),scope:o,plan:r,project:n,global:s,projectScope:i,mcp:c,hooks:l,rule:i?.rule,files:a}}var $=[["sessionStart",10],["userPromptSubmitted",10],["userPromptTransformed",10],["preToolUse",10],["postToolUse",15],["agentStop",30]];function Fi(e){if(typeof e.command=="string")return e.command;if(typeof e.bash=="string")return e.bash}function Oo(e){return f(e)&&Fi(e)?.includes("session:copilot-hook")===!0}function Ri(e,t,o){let n={type:"command",command:`${t} session:copilot-hook`,env:{TOOLNET_HOOK_EVENT:e},timeoutSec:o};return e==="preToolUse"&&(n.matcher=".*"),n}function Ae(e={}){let t=e.hooksFile??X(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=k(t,"GitHub Copilot CLI");if(n.version!==void 0&&n.version!==1)throw new Error(`Unsupported existing GitHub Copilot CLI hooks version: ${String(n.version)}`);let r=n.hooks;if(r!==void 0&&!f(r))throw new Error("Invalid existing GitHub Copilot CLI hooks file: hooks must be an object.");let s=f(r)?{...r}:{};for(let[a,u]of $){let p=s[a];if(p!==void 0&&!Array.isArray(p))throw new Error(`Invalid existing GitHub Copilot CLI hooks file: hooks.${a} must be an array.`);let g=Array.isArray(p)?p.filter(E=>!Oo(E)):[];s[a]=[...g,Ri(a,o,u)]}let i={...n,version:1,hooks:s};if(JSON.stringify(n)===JSON.stringify(i))return{hooksFile:t,changed:!1,hookCount:$.length};R(t,i);let c=k(t,"GitHub Copilot CLI");if(c.version!==1||!f(c.hooks))throw new Error("GitHub Copilot CLI hooks were written but verification failed.");let l=0;for(let[a]of $){let u=c.hooks[a];if(!Array.isArray(u))throw new Error("GitHub Copilot CLI hooks were written but verification failed.");l+=u.filter(Oo).length}if(l!==$.length)throw new Error("GitHub Copilot CLI hooks were written but verification failed.");return{hooksFile:t,changed:!0,hookCount:$.length}}function wo(e,t){return d(e)?(e.type===void 0||e.type==="local"||e.type==="stdio")&&e.command===t&&Array.isArray(e.args)&&e.args.length===1&&e.args[0]==="mcp"&&Array.isArray(e.tools)&&e.tools.length===1&&e.tools[0]==="*":!1}function _e(e={}){let t=e.configFile??V(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=C(t,"GitHub Copilot CLI"),s=r.mcpServers;if(s!==void 0&&!d(s))throw new Error("Invalid existing GitHub Copilot CLI MCP config: mcpServers must be an object.");let i=d(s)?{...s}:{};if(wo(i[n],o))return{installed:!0,changed:!1,configFile:t,serverName:n,command:o,args:["mcp"]};i[n]={type:"stdio",command:o,args:["mcp"],tools:["*"]},F(t,{...r,mcpServers:i});let l=C(t,"GitHub Copilot CLI").mcpServers;if(!d(l)||!wo(l[n],o))throw new Error("GitHub Copilot CLI MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:t,serverName:n,command:o,args:["mcp"]}}import{mkdirSync as Pi,readFileSync as vo,renameSync as Ni,rmSync as Ei,writeFileSync as Ti}from"node:fs";import{dirname as Mi}from"node:path";var He=`---
1250
1250
  applyTo: "**"
1251
1251
  ---
1252
1252
 
@@ -1272,7 +1272,7 @@ Use ToolNet Memory as the continuity source for this repository.
1272
1272
  - Do not ask the user to repeat context ToolNet already provides.
1273
1273
 
1274
1274
  Current repository evidence overrides stale memory.
1275
- `;function Ai(e,t){Pi(Mi(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Ei(o,t,{encoding:"utf8",mode:384}),Ni(o,e)}finally{Ti(o,{force:!0})}}function So(e){let t=e.instructionFile??pt(e.projectRoot);try{if(vo(t,"utf8")===_e)return{instructionFile:t,changed:!1}}catch{}if(Ai(t,_e),vo(t,"utf8")!==_e)throw new Error("Copilot ToolNet project instruction verification failed.");return{instructionFile:t,changed:!0}}function xo(e){return!!(e?.mcp?.changed||e?.hooks?.changed||e?.instruction?.changed)}function Fo(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.scope??"global",n=o==="global"?void 0:b({project:e.projectRoot}),r=N({agent:"copilot",scope:o,project:n});if(!r.canInstall)throw new Error(r.reason??"Copilot project integration scope cannot be resolved.");let s,i;if((r.surfaces.mcp.global.install||r.surfaces.hooks.global.install||r.surfaces.work.global.install)&&(s={},r.surfaces.mcp.global.install&&(s.mcp=He({binary:t,configFile:e.configFile??X()})),r.surfaces.hooks.global.install&&(s.hooks=Ae({binary:t,hooksFile:e.hooksFile??V()}))),r.surfaces.mcp.project.install||r.surfaces.hooks.project.install||r.surfaces.work.project.install){if(!n?.eligible)throw new Error("Copilot project integration requires an eligible project root.");i={},r.surfaces.mcp.project.install&&(i.mcp=He({binary:t,configFile:e.projectConfigFile??at(n.root)})),r.surfaces.hooks.project.install&&(i.hooks=Ae({binary:t,hooksFile:e.projectHooksFile??ut(n.root)})),r.surfaces.work.project.install&&(i.instruction=So({projectRoot:n.root,instructionFile:e.projectInstructionFile}))}let c=i?.mcp??s?.mcp,l=i?.hooks??s?.hooks;if(!c||!l)throw new Error("Copilot integration did not produce effective MCP/hooks.");let a=Array.from(new Set([s?.mcp?.configFile,s?.hooks?.hooksFile,s?.instruction?.instructionFile,i?.mcp?.configFile,i?.hooks?.hooksFile,i?.instruction?.instructionFile].filter(u=>typeof u=="string")));return{installed:!0,changed:xo(s)||xo(i),scope:o,plan:r,project:n,global:s,projectScope:i,mcp:c,hooks:l,instruction:i?.instruction,files:a}}import{existsSync as Hi,mkdirSync as _i,readFileSync as Ro,renameSync as Di,rmSync as $i,writeFileSync as Ji}from"node:fs";import{dirname as Gi}from"node:path";var De=`---
1275
+ `;function Ai(e,t){Pi(Mi(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Ti(o,t,{encoding:"utf8",mode:384}),Ni(o,e)}finally{Ei(o,{force:!0})}}function So(e){let t=e.instructionFile??pt(e.projectRoot);try{if(vo(t,"utf8")===He)return{instructionFile:t,changed:!1}}catch{}if(Ai(t,He),vo(t,"utf8")!==He)throw new Error("Copilot ToolNet project instruction verification failed.");return{instructionFile:t,changed:!0}}function xo(e){return!!(e?.mcp?.changed||e?.hooks?.changed||e?.instruction?.changed)}function Fo(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.scope??"global",n=o==="global"?void 0:b({project:e.projectRoot}),r=N({agent:"copilot",scope:o,project:n});if(!r.canInstall)throw new Error(r.reason??"Copilot project integration scope cannot be resolved.");let s,i;if((r.surfaces.mcp.global.install||r.surfaces.hooks.global.install||r.surfaces.work.global.install)&&(s={},r.surfaces.mcp.global.install&&(s.mcp=_e({binary:t,configFile:e.configFile??V()})),r.surfaces.hooks.global.install&&(s.hooks=Ae({binary:t,hooksFile:e.hooksFile??X()}))),r.surfaces.mcp.project.install||r.surfaces.hooks.project.install||r.surfaces.work.project.install){if(!n?.eligible)throw new Error("Copilot project integration requires an eligible project root.");i={},r.surfaces.mcp.project.install&&(i.mcp=_e({binary:t,configFile:e.projectConfigFile??at(n.root)})),r.surfaces.hooks.project.install&&(i.hooks=Ae({binary:t,hooksFile:e.projectHooksFile??ut(n.root)})),r.surfaces.work.project.install&&(i.instruction=So({projectRoot:n.root,instructionFile:e.projectInstructionFile}))}let c=i?.mcp??s?.mcp,l=i?.hooks??s?.hooks;if(!c||!l)throw new Error("Copilot integration did not produce effective MCP/hooks.");let a=Array.from(new Set([s?.mcp?.configFile,s?.hooks?.hooksFile,s?.instruction?.instructionFile,i?.mcp?.configFile,i?.hooks?.hooksFile,i?.instruction?.instructionFile].filter(u=>typeof u=="string")));return{installed:!0,changed:xo(s)||xo(i),scope:o,plan:r,project:n,global:s,projectScope:i,mcp:c,hooks:l,instruction:i?.instruction,files:a}}import{existsSync as _i,mkdirSync as Hi,readFileSync as Ro,renameSync as Di,rmSync as Ji,writeFileSync as $i}from"node:fs";import{dirname as Gi}from"node:path";var De=`---
1276
1276
  name: toolnet-continuity
1277
1277
  description: Restore previous ToolNet project work when the user asks to continue, resume, pick up, finish unfinished work, or asks where work stopped.
1278
1278
  when-to-use: continue, resume, pick up, carry on, ti\u1EBFp t\u1EE5c, l\xE0m ti\u1EBFp, l\xE0m n\u1ED1t, \u0111ang l\xE0m \u0111\u1EBFn \u0111\xE2u, d\u1EEBng \u1EDF \u0111\xE2u
@@ -1298,8 +1298,8 @@ When the user asks to continue or resume previous work:
1298
1298
  7. Do not ask the user to repeat context ToolNet already provides.
1299
1299
 
1300
1300
  Current repository evidence overrides stale memory.
1301
- `;function Li(e,t){_i(Gi(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Ji(o,t,{encoding:"utf8",mode:384}),Di(o,e)}finally{$i(o,{force:!0})}}function $e(e={}){let t=e.skillFile??ee();if(Hi(t)&&Ro(t,"utf8")===De)return{skillFile:t,changed:!1};if(Li(t,De),Ro(t,"utf8")!==De)throw new Error("Grok ToolNet continuity skill was written but verification failed.");return{skillFile:t,changed:!0}}var G=[["SessionStart",10],["UserPromptSubmit",10],["PreToolUse",10],["PostToolUse",15],["Stop",30]];function Po(e){return!f(e)||!Array.isArray(e.hooks)?!1:e.hooks.some(t=>f(t)&&typeof t.command=="string"&&t.command.includes("session:grok-hook"))}function Ki(e,t,o){let n={hooks:[{type:"command",command:`${t} session:grok-hook`,timeout:o,env:{TOOLNET_HOOK_EVENT:e}}]};return e==="PreToolUse"&&(n.matcher=".*"),n}function Je(e={}){let t=e.hooksFile??Z(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=k(t,"Grok Build"),r=n.hooks;if(r!==void 0&&!f(r))throw new Error("Invalid existing Grok Build hooks file: hooks must be an object.");let s=f(r)?{...r}:{};for(let[a,u]of G){let p=s[a];if(p!==void 0&&!Array.isArray(p))throw new Error(`Invalid existing Grok Build hooks file: hooks.${a} must be an array.`);let g=Array.isArray(p)?p.filter(T=>!Po(T)):[];s[a]=[...g,Ki(a,o,u)]}let i={...n,hooks:s};if(JSON.stringify(n)===JSON.stringify(i))return{hooksFile:t,changed:!1,hookCount:G.length};R(t,i);let c=k(t,"Grok Build");if(!f(c.hooks))throw new Error("Grok Build hooks were written but verification failed.");let l=0;for(let[a]of G){let u=c.hooks[a];if(!Array.isArray(u))throw new Error("Grok Build hooks were written but verification failed.");l+=u.filter(Po).length}if(l!==G.length)throw new Error("Grok Build hooks were written but verification failed.");return{hooksFile:t,changed:!0,hookCount:G.length}}import{existsSync as Bi,mkdirSync as Ui,readFileSync as qi,renameSync as Wi,rmSync as Yi,writeFileSync as Xi}from"node:fs";import{dirname as Vi}from"node:path";function No(e){return Bi(e)?qi(e,"utf8"):""}function zi(e,t){Ui(Vi(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{Xi(o,t,{encoding:"utf8",mode:384}),Wi(o,e)}finally{Yi(o,{force:!0})}}function Ge(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function Qi(e){return`[mcp_servers."${Ge(e)}"]`}function Zi(e,t){return[Qi(e),`command = "${Ge(t)}"`,'args = ["mcp"]',"enabled = true"].join(`
1302
- `)}function es(e){let t=e.trim();return t.startsWith("[")&&t.includes("]")}function ce(e){return e.trim().replace(/\s+/g,"")}function ts(e){return new Set([ce(`[mcp_servers.${e}]`),ce(`[mcp_servers."${e}"]`),ce(`[mcp_servers.'${e}']`)])}function Eo(e,t){let o=e.split(/\r?\n/),n=ts(t),r=-1;for(let u=0;u<o.length;u+=1){let p=ce(o[u].replace(/\s+#.*$/,""));if(n.has(p)){r=u;break}}if(r<0)return null;let s=o.length;for(let u=r+1;u<o.length;u+=1)if(es(o[u])){s=u;break}let i=[],c=0;for(let u of o)i.push(c),c+=u.length+1;let l=i[r]??0,a=s>=o.length?e.length:i[s]??e.length;return{start:l,end:a}}function os(e,t,o){let n=`${Zi(t,o)}
1303
- `,r=Eo(e,t);if(r){let s=e.slice(0,r.start),i=e.slice(r.end);return`${s}${n}${i.replace(/^\n+/,"")}`}return e.trim()?`${e.replace(/\s*$/,"")}
1301
+ `;function Li(e,t){Hi(Gi(e),{recursive:!0,mode:448});let o=`${e}.toolnet-${process.pid}-${Date.now()}.tmp`;try{$i(o,t,{encoding:"utf8",mode:384}),Di(o,e)}finally{Ji(o,{force:!0})}}function Je(e={}){let t=e.skillFile??ee();if(_i(t)&&Ro(t,"utf8")===De)return{skillFile:t,changed:!1};if(Li(t,De),Ro(t,"utf8")!==De)throw new Error("Grok ToolNet continuity skill was written but verification failed.");return{skillFile:t,changed:!0}}var G=[["SessionStart",10],["UserPromptSubmit",10],["PreToolUse",10],["PostToolUse",15],["Stop",30]];function Po(e){return!f(e)||!Array.isArray(e.hooks)?!1:e.hooks.some(t=>f(t)&&typeof t.command=="string"&&t.command.includes("session:grok-hook"))}function Ki(e,t,o){let n={hooks:[{type:"command",command:`${t} session:grok-hook`,timeout:o,env:{TOOLNET_HOOK_EVENT:e}}]};return e==="PreToolUse"&&(n.matcher=".*"),n}function $e(e={}){let t=e.hooksFile??Z(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=k(t,"Grok Build"),r=n.hooks;if(r!==void 0&&!f(r))throw new Error("Invalid existing Grok Build hooks file: hooks must be an object.");let s=f(r)?{...r}:{};for(let[a,u]of G){let p=s[a];if(p!==void 0&&!Array.isArray(p))throw new Error(`Invalid existing Grok Build hooks file: hooks.${a} must be an array.`);let g=Array.isArray(p)?p.filter(E=>!Po(E)):[];s[a]=[...g,Ki(a,o,u)]}let i={...n,hooks:s};if(JSON.stringify(n)===JSON.stringify(i))return{hooksFile:t,changed:!1,hookCount:G.length};R(t,i);let c=k(t,"Grok Build");if(!f(c.hooks))throw new Error("Grok Build hooks were written but verification failed.");let l=0;for(let[a]of G){let u=c.hooks[a];if(!Array.isArray(u))throw new Error("Grok Build hooks were written but verification failed.");l+=u.filter(Po).length}if(l!==G.length)throw new Error("Grok Build hooks were written but verification failed.");return{hooksFile:t,changed:!0,hookCount:G.length}}import{existsSync as Ui,mkdirSync as Bi,readFileSync as qi,renameSync as Wi,rmSync as Yi,writeFileSync as Vi}from"node:fs";import{dirname as Xi}from"node:path";function No(e){return Ui(e)?qi(e,"utf8"):""}function zi(e,t){Bi(Xi(e),{recursive:!0,mode:448});let o=`${e}.tmp-${process.pid}-${Date.now()}`;try{Vi(o,t,{encoding:"utf8",mode:384}),Wi(o,e)}finally{Yi(o,{force:!0})}}function Ge(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function Qi(e){return`[mcp_servers."${Ge(e)}"]`}function Zi(e,t){return[Qi(e),`command = "${Ge(t)}"`,'args = ["mcp"]',"enabled = true"].join(`
1302
+ `)}function es(e){let t=e.trim();return t.startsWith("[")&&t.includes("]")}function ce(e){return e.trim().replace(/\s+/g,"")}function ts(e){return new Set([ce(`[mcp_servers.${e}]`),ce(`[mcp_servers."${e}"]`),ce(`[mcp_servers.'${e}']`)])}function To(e,t){let o=e.split(/\r?\n/),n=ts(t),r=-1;for(let u=0;u<o.length;u+=1){let p=ce(o[u].replace(/\s+#.*$/,""));if(n.has(p)){r=u;break}}if(r<0)return null;let s=o.length;for(let u=r+1;u<o.length;u+=1)if(es(o[u])){s=u;break}let i=[],c=0;for(let u of o)i.push(c),c+=u.length+1;let l=i[r]??0,a=s>=o.length?e.length:i[s]??e.length;return{start:l,end:a}}function os(e,t,o){let n=`${Zi(t,o)}
1303
+ `,r=To(e,t);if(r){let s=e.slice(0,r.start),i=e.slice(r.end);return`${s}${n}${i.replace(/^\n+/,"")}`}return e.trim()?`${e.replace(/\s*$/,"")}
1304
1304
 
1305
- ${n}`:n}function To(e,t,o){let n=Eo(e,t);if(!n)return!1;let r=e.slice(n.start,n.end);return r.includes(`command = "${Ge(o)}"`)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(r)&&/enabled\s*=\s*true/.test(r)}function Le(e={}){let t=e.configFile??Q(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=No(t);if(To(r,n,o))return{installed:!0,changed:!1,configFile:t,serverName:n,command:o,args:["mcp"]};let s=os(r,n,o);zi(t,s);let i=No(t);if(!To(i,n,o))throw new Error("Grok Build MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:t,serverName:n,command:o,args:["mcp"]}}function Mo(e){return!!(e?.mcp?.changed||e?.hooks?.changed||e?.skill?.changed)}function Ao(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.scope??"global",n=o==="global"?void 0:b({project:e.projectRoot}),r=N({agent:"grok",scope:o,project:n});if(!r.canInstall)throw new Error(r.reason??"Grok project integration scope cannot be resolved.");let s,i;if((r.surfaces.mcp.global.install||r.surfaces.hooks.global.install||r.surfaces.work.global.install)&&(s={},r.surfaces.mcp.global.install&&(s.mcp=Le({binary:t,configFile:e.configFile??Q()})),r.surfaces.hooks.global.install&&(s.hooks=Je({binary:t,hooksFile:e.hooksFile??Z()})),r.surfaces.work.global.install&&(s.skill=$e({skillFile:e.skillFile??ee()}))),r.surfaces.mcp.project.install||r.surfaces.hooks.project.install||r.surfaces.work.project.install){if(!n?.eligible)throw new Error("Grok project integration requires an eligible project root.");i={},r.surfaces.mcp.project.install&&(i.mcp=Le({binary:t,configFile:e.projectConfigFile??ft(n.root)})),r.surfaces.hooks.project.install&&(i.hooks=Je({binary:t,hooksFile:e.projectHooksFile??dt(n.root)})),r.surfaces.work.project.install&&(i.skill=$e({skillFile:e.projectSkillFile??mt(n.root)}))}let c=i?.mcp??s?.mcp,l=i?.hooks??s?.hooks,a=i?.skill??s?.skill;if(!c||!l||!a)throw new Error("Grok integration did not produce effective MCP/hooks/skill.");let u=Array.from(new Set([s?.mcp?.configFile,s?.hooks?.hooksFile,s?.skill?.skillFile,i?.mcp?.configFile,i?.hooks?.hooksFile,i?.skill?.skillFile].filter(p=>typeof p=="string")));return{installed:!0,changed:Mo(s)||Mo(i),scope:o,plan:r,project:n,global:s,projectScope:i,mcp:c,hooks:l,skill:a,files:u}}function Ho(e={}){if(e.scope==="global")return{scope:"global",automatic:!1,reason:"explicit-global"};if(e.scope==="project"||e.scope==="both"){let o=b({cwd:e.cwd,project:e.projectRoot});if(!o.eligible)throw new Error(`Explicit ${e.scope} integration requires an explicit project, ToolNet project, or Git repository root.`);return{scope:e.scope,automatic:!1,project:o,reason:e.scope==="project"?"explicit-project":"explicit-both"}}let t=b({cwd:e.cwd,project:e.projectRoot});return t.toolnetProject?{scope:"both",automatic:!0,project:t,reason:"toolnet-project"}:{scope:"global",automatic:!0,reason:"no-toolnet-project"}}function _o(){return bt()}function ns(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=[],n=e.detections??_o(),r=new Map(n.map(i=>[i.agent,i.detected])),s=Ho({scope:e.scope,projectRoot:e.projectRoot,cwd:e.cwd});if(!(e.force===!0||r.get("agy")===!0))o.push({agent:"agy",detected:!1,installed:!1,targets:[]});else try{let c=St({binary:t});o.push({agent:"agy",detected:!0,installed:!0,targets:c.files})}catch(c){o.push({agent:"agy",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("opencode")===!0))o.push({agent:"opencode",detected:!1,installed:!1,targets:[]});else try{let c=Tt({binary:t}),l=_t({binary:t});o.push({agent:"opencode",detected:!0,installed:!0,targets:[...c,l.configFile,`mcp:${l.serverName}`]})}catch(c){o.push({agent:"opencode",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("claude")===!0))o.push({agent:"claude",detected:!1,installed:!1,targets:[]});else try{let c=Qt({binary:t});o.push({agent:"claude",detected:!0,installed:!0,targets:[c.hooks.settingsFile,c.mcp.configFile,`mcp:${c.mcp.serverName}`]})}catch(c){o.push({agent:"claude",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("kiro")===!0))o.push({agent:"kiro",detected:!1,installed:!1,targets:[]});else try{let c=so({...e.kiro??{},binary:t});o.push({agent:"kiro",detected:!0,installed:!0,targets:[c.mcp.configFile,`mcp:${c.mcp.serverName}`,c.hooks.hooksFile]})}catch(c){o.push({agent:"kiro",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("cursor")===!0))o.push({agent:"cursor",detected:!1,installed:!1,targets:[]});else try{let c=e.cursor??{},l=jo({...c,binary:t,scope:c.scope??s.scope,projectRoot:c.projectRoot??s.project?.root});o.push({agent:"cursor",detected:!0,installed:!0,scope:l.scope,projectRoot:l.project?.root,targets:[...l.files,`mcp:${l.mcp.serverName}`]})}catch(c){o.push({agent:"cursor",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("copilot")===!0))o.push({agent:"copilot",detected:!1,installed:!1,targets:[]});else try{let c=e.copilot??{},l=Fo({...c,binary:t,scope:c.scope??s.scope,projectRoot:c.projectRoot??s.project?.root});o.push({agent:"copilot",detected:!0,installed:!0,scope:l.scope,projectRoot:l.project?.root,targets:[...l.files,`mcp:${l.mcp.serverName}`]})}catch(c){o.push({agent:"copilot",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("grok")===!0))o.push({agent:"grok",detected:!1,installed:!1,targets:[]});else try{let c=e.grok??{},l=Ao({...c,binary:t,scope:c.scope??s.scope,projectRoot:c.projectRoot??s.project?.root});o.push({agent:"grok",detected:!0,installed:!0,scope:l.scope,projectRoot:l.project?.root,targets:[...l.files,`mcp:${l.mcp.serverName}`]})}catch(c){o.push({agent:"grok",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("toolnet-cli")===!0))o.push({agent:"toolnet-cli",detected:!1,installed:!1,targets:[]});else try{let c=e.toolnetCli??{},l=lo({...c,binary:t});o.push({agent:"toolnet-cli",detected:!0,installed:!0,targets:[l.mcp.configFile]})}catch(c){o.push({agent:"toolnet-cli",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("kilo")===!0))o.push({agent:"kilo",detected:!1,installed:!1,targets:[]});else try{let c=e.kilo??{},l=uo({...c,binary:t});o.push({agent:"kilo",detected:!0,installed:!0,targets:[l.mcp.configFile]})}catch(c){o.push({agent:"kilo",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("codex")===!0))o.push({agent:"codex",detected:!1,installed:!1,targets:[]});else try{let c=Lt({binary:t}),l=Bt({binary:t}),a=Wt({binary:t});if(!a.installed)throw new Error(a.error??"Codex MCP registration failed");let u=[c.configFile,l,`mcp:${a.serverName}`];c.preservedPrevious&&u.push(c.previousFile),o.push({agent:"codex",detected:!0,installed:!0,targets:u})}catch(c){o.push({agent:"codex",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}return o}function Do(e){switch(e){case"agy":return"Agy / Antigravity";case"opencode":return"OpenCode";case"claude":return"Claude Code";case"kiro":return"Kiro CLI";case"cursor":return"Cursor CLI";case"copilot":return"GitHub Copilot CLI";case"grok":return"Grok Build";case"toolnet-cli":return"ToolNet CLI";case"kilo":return"Kilo";case"codex":return"Codex";default:return e}}function rs(e){console.log(""),console.log("ToolNet Memory Integration Detection"),console.log("===================================="),console.log("");for(let t of e){let o=Do(t.agent);if(!t.detected){console.log(`\u25CB ${o}: not detected`);continue}console.log(`\u2713 ${o}: detected`);for(let n of t.evidence)console.log(` ${n}`)}console.log("")}function is(e){console.log(""),console.log("ToolNet Memory AI Integrations"),console.log("=============================="),console.log("");for(let t of e){let o=Do(t.agent);if(!t.detected){console.log(`- ${o}: not detected`);continue}if(t.installed){let n=t.scope?` [scope=${t.scope}]`:"";console.log(`\u2713 ${o}: automatic memory enabled${n}`),t.projectRoot&&console.log(` project: ${t.projectRoot}`);continue}console.log(`\u2717 ${o}: integration failed`),t.error&&console.log(` ${t.error}`)}console.log("")}function ss(e,t){let o=e.indexOf(t);return o>=0?e[o+1]:void 0}function cs(e){return e.includes("--scope")||e.includes("--global")||e.includes("--both")?Co(e):void 0}async function ls(){let e=process.argv.slice(2),t=e.includes("--all"),o=e.includes("--json"),n=e.includes("--detect-only"),r=cs(e),s=ss(e,"--project");if(n){let c=_o();if(o){console.log(JSON.stringify(c,null,2));return}rs(c);return}let i=ns({force:t,scope:r,projectRoot:s});if(o){console.log(JSON.stringify(i,null,2));return}is(i)}var as=process.argv[1]&&(process.argv[1].endsWith("auto-integrate.js")||process.argv[1].endsWith("auto-integrate.ts"));as&&ls().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});export{_o as detectAutoIntegrations,ns as installAutoIntegrations,Do as integrationDisplayName};
1305
+ ${n}`:n}function Eo(e,t,o){let n=To(e,t);if(!n)return!1;let r=e.slice(n.start,n.end);return r.includes(`command = "${Ge(o)}"`)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(r)&&/enabled\s*=\s*true/.test(r)}function Le(e={}){let t=e.configFile??Q(),o=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=e.serverName??"toolnet-memory",r=No(t);if(Eo(r,n,o))return{installed:!0,changed:!1,configFile:t,serverName:n,command:o,args:["mcp"]};let s=os(r,n,o);zi(t,s);let i=No(t);if(!Eo(i,n,o))throw new Error("Grok Build MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:t,serverName:n,command:o,args:["mcp"]}}function Mo(e){return!!(e?.mcp?.changed||e?.hooks?.changed||e?.skill?.changed)}function Ao(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=e.scope??"global",n=o==="global"?void 0:b({project:e.projectRoot}),r=N({agent:"grok",scope:o,project:n});if(!r.canInstall)throw new Error(r.reason??"Grok project integration scope cannot be resolved.");let s,i;if((r.surfaces.mcp.global.install||r.surfaces.hooks.global.install||r.surfaces.work.global.install)&&(s={},r.surfaces.mcp.global.install&&(s.mcp=Le({binary:t,configFile:e.configFile??Q()})),r.surfaces.hooks.global.install&&(s.hooks=$e({binary:t,hooksFile:e.hooksFile??Z()})),r.surfaces.work.global.install&&(s.skill=Je({skillFile:e.skillFile??ee()}))),r.surfaces.mcp.project.install||r.surfaces.hooks.project.install||r.surfaces.work.project.install){if(!n?.eligible)throw new Error("Grok project integration requires an eligible project root.");i={},r.surfaces.mcp.project.install&&(i.mcp=Le({binary:t,configFile:e.projectConfigFile??ft(n.root)})),r.surfaces.hooks.project.install&&(i.hooks=$e({binary:t,hooksFile:e.projectHooksFile??dt(n.root)})),r.surfaces.work.project.install&&(i.skill=Je({skillFile:e.projectSkillFile??mt(n.root)}))}let c=i?.mcp??s?.mcp,l=i?.hooks??s?.hooks,a=i?.skill??s?.skill;if(!c||!l||!a)throw new Error("Grok integration did not produce effective MCP/hooks/skill.");let u=Array.from(new Set([s?.mcp?.configFile,s?.hooks?.hooksFile,s?.skill?.skillFile,i?.mcp?.configFile,i?.hooks?.hooksFile,i?.skill?.skillFile].filter(p=>typeof p=="string")));return{installed:!0,changed:Mo(s)||Mo(i),scope:o,plan:r,project:n,global:s,projectScope:i,mcp:c,hooks:l,skill:a,files:u}}function _o(e={}){if(e.scope==="global")return{scope:"global",automatic:!1,reason:"explicit-global"};if(e.scope==="project"||e.scope==="both"){let o=b({cwd:e.cwd,project:e.projectRoot});if(!o.eligible)throw new Error(`Explicit ${e.scope} integration requires an explicit project, ToolNet project, or Git repository root.`);return{scope:e.scope,automatic:!1,project:o,reason:e.scope==="project"?"explicit-project":"explicit-both"}}let t=b({cwd:e.cwd,project:e.projectRoot});return t.toolnetProject?{scope:"both",automatic:!0,project:t,reason:"toolnet-project"}:{scope:"global",automatic:!0,reason:"no-toolnet-project"}}function Ho(){return bt()}function ns(e={}){let t=e.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",o=[],n=e.detections??Ho(),r=new Map(n.map(i=>[i.agent,i.detected])),s=_o({scope:e.scope,projectRoot:e.projectRoot,cwd:e.cwd});if(!(e.force===!0||r.get("agy")===!0))o.push({agent:"agy",detected:!1,installed:!1,targets:[]});else try{let c=St({binary:t});o.push({agent:"agy",detected:!0,installed:!0,targets:c.files})}catch(c){o.push({agent:"agy",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("opencode")===!0))o.push({agent:"opencode",detected:!1,installed:!1,targets:[]});else try{let c=Et({binary:t}),l=Ht({binary:t});o.push({agent:"opencode",detected:!0,installed:!0,targets:[...c,l.configFile,`mcp:${l.serverName}`]})}catch(c){o.push({agent:"opencode",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("claude")===!0))o.push({agent:"claude",detected:!1,installed:!1,targets:[]});else try{let c=Qt({binary:t});o.push({agent:"claude",detected:!0,installed:!0,targets:[c.hooks.settingsFile,c.mcp.configFile,`mcp:${c.mcp.serverName}`]})}catch(c){o.push({agent:"claude",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("kiro")===!0))o.push({agent:"kiro",detected:!1,installed:!1,targets:[]});else try{let c=so({...e.kiro??{},binary:t});o.push({agent:"kiro",detected:!0,installed:!0,targets:[c.mcp.configFile,`mcp:${c.mcp.serverName}`,c.hooks.hooksFile]})}catch(c){o.push({agent:"kiro",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("cursor")===!0))o.push({agent:"cursor",detected:!1,installed:!1,targets:[]});else try{let c=e.cursor??{},l=Co({...c,binary:t,scope:c.scope??s.scope,projectRoot:c.projectRoot??s.project?.root});o.push({agent:"cursor",detected:!0,installed:!0,scope:l.scope,projectRoot:l.project?.root,targets:[...l.files,`mcp:${l.mcp.serverName}`]})}catch(c){o.push({agent:"cursor",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("copilot")===!0))o.push({agent:"copilot",detected:!1,installed:!1,targets:[]});else try{let c=e.copilot??{},l=Fo({...c,binary:t,scope:c.scope??s.scope,projectRoot:c.projectRoot??s.project?.root});o.push({agent:"copilot",detected:!0,installed:!0,scope:l.scope,projectRoot:l.project?.root,targets:[...l.files,`mcp:${l.mcp.serverName}`]})}catch(c){o.push({agent:"copilot",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("grok")===!0))o.push({agent:"grok",detected:!1,installed:!1,targets:[]});else try{let c=e.grok??{},l=Ao({...c,binary:t,scope:c.scope??s.scope,projectRoot:c.projectRoot??s.project?.root});o.push({agent:"grok",detected:!0,installed:!0,scope:l.scope,projectRoot:l.project?.root,targets:[...l.files,`mcp:${l.mcp.serverName}`]})}catch(c){o.push({agent:"grok",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("toolnet-cli")===!0))o.push({agent:"toolnet-cli",detected:!1,installed:!1,targets:[]});else try{let c=e.toolnetCli??{},l=lo({...c,binary:t});o.push({agent:"toolnet-cli",detected:!0,installed:!0,targets:[l.mcp.configFile]})}catch(c){o.push({agent:"toolnet-cli",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("kilo")===!0))o.push({agent:"kilo",detected:!1,installed:!1,targets:[]});else try{let c=e.kilo??{},l=uo({...c,binary:t});o.push({agent:"kilo",detected:!0,installed:!0,targets:[l.mcp.configFile]})}catch(c){o.push({agent:"kilo",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}if(!(e.force===!0||r.get("codex")===!0))o.push({agent:"codex",detected:!1,installed:!1,targets:[]});else try{let c=Lt({binary:t}),l=Ut({binary:t}),a=Wt({binary:t});if(!a.installed)throw new Error(a.error??"Codex MCP registration failed");let u=[c.configFile,l,`mcp:${a.serverName}`];c.preservedPrevious&&u.push(c.previousFile),o.push({agent:"codex",detected:!0,installed:!0,targets:u})}catch(c){o.push({agent:"codex",detected:!0,installed:!1,targets:[],error:c instanceof Error?c.message:String(c)})}return o}function Do(e){switch(e){case"agy":return"Agy / Antigravity";case"opencode":return"OpenCode";case"claude":return"Claude Code";case"kiro":return"Kiro CLI";case"cursor":return"Cursor CLI";case"copilot":return"GitHub Copilot CLI";case"grok":return"Grok Build";case"toolnet-cli":return"ToolNet CLI";case"kilo":return"Kilo";case"codex":return"Codex";default:return e}}function rs(e){console.log(""),console.log("ToolNet Memory Integration Detection"),console.log("===================================="),console.log("");for(let t of e){let o=Do(t.agent);if(!t.detected){console.log(`\u25CB ${o}: not detected`);continue}console.log(`\u2713 ${o}: detected`);for(let n of t.evidence)console.log(` ${n}`)}console.log("")}function is(e){console.log(""),console.log("ToolNet Memory AI Integrations"),console.log("=============================="),console.log("");for(let t of e){let o=Do(t.agent);if(!t.detected){console.log(`- ${o}: not detected`);continue}if(t.installed){let n=t.scope?` [scope=${t.scope}]`:"";console.log(`\u2713 ${o}: automatic memory enabled${n}`),t.projectRoot&&console.log(` project: ${t.projectRoot}`);continue}console.log(`\u2717 ${o}: integration failed`),t.error&&console.log(` ${t.error}`)}console.log("")}function ss(e,t){let o=e.indexOf(t);return o>=0?e[o+1]:void 0}function cs(e){return e.includes("--scope")||e.includes("--global")||e.includes("--both")?jo(e):void 0}async function ls(){let e=process.argv.slice(2),t=e.includes("--all"),o=e.includes("--json"),n=e.includes("--detect-only"),r=cs(e),s=ss(e,"--project");if(n){let c=Ho();if(o){console.log(JSON.stringify(c,null,2));return}rs(c);return}let i=ns({force:t,scope:r,projectRoot:s});if(o){console.log(JSON.stringify(i,null,2));return}is(i)}var as=process.argv[1]&&(process.argv[1].endsWith("auto-integrate.js")||process.argv[1].endsWith("auto-integrate.ts"));as&&ls().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});export{Ho as detectAutoIntegrations,ns as installAutoIntegrations,Do as integrationDisplayName};
@@ -1,7 +1,7 @@
1
- import{existsSync as Ce,readFileSync as Oe}from"node:fs";import{homedir as Te}from"node:os";import{join as Ee}from"node:path";function _e(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
- `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function Ne(){let r=process.env.TOOLNET_GLOBAL_ENV??Ee(Te(),".config","toolnet-memory",".env");if(!Ce(r))return;let e=Oe(r,"utf8");for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let i=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=_e(o.slice(n+1)))}}Ne();function j(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function M(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function X(){return{memory:{autoCapture:j(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:j(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:j(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:j(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:M(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:M(process.env.MEMORY_RERANK_TOP,10),finalContext:M(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:M(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:j(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:M(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as $e}from"node:crypto";import{existsSync as H,mkdirSync as Ke,readFileSync as De,renameSync as ze,writeFileSync as He}from"node:fs";import{basename as Le,dirname as I,join as O,parse as re,resolve as x}from"node:path";var oe=".toolnet",Ve="project.json";function Be(r){return $e("sha256").update(r).digest("hex").slice(0,16)}function L(r){return O(r,oe,Ve)}function Fe(r){return H(L(r))}function We(r,e){let t=x(r),o=re(t).root;for(;;){if(Fe(t))return t;if(t===o||e&&t===x(e))break;let n=I(t);if(n===t)break;t=n}return null}function Je(r){let e=x(r),t=re(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(i=>H(O(e,i))))return e;if(e===t)break;let n=I(e);if(n===e)break;e=n}return x(r)}function Ue(r){let e;try{e=JSON.parse(De(r,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${r}: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let o=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:I(I(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:o,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:o,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function ee(r,e){let t=O(r,oe);Ke(t,{recursive:!0});let o=L(r),n=`${o}.tmp-${process.pid}`;He(n,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),ze(n,o)}function te(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var C=class{detect(e=process.cwd()){let t=x(e),o=Je(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>H(O(o,m))),a=We(t,i?o:void 0);if(a){let m=L(a),f=Ue(m);return f.rootPath!==a&&(f.rootPath=a,f.updatedAt=new Date().toISOString(),ee(a,f)),te(f,a)}let c=new Date().toISOString(),p=Le(o),d={version:1,id:Be(o),name:p,remote:p,rootPath:o,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return ee(o,d),te(d,o)}};import{homedir as yt}from"node:os";import{join as ht}from"node:path";import{DeleteObjectCommand as Ye,GetObjectCommand as Ge,HeadObjectCommand as qe,ListObjectsV2Command as Qe,PutObjectCommand as Ze,S3Client as Xe}from"@aws-sdk/client-s3";import{getSignedUrl as et}from"@aws-sdk/s3-request-presigner";var T=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Xe({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ze({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await et(this.client,new Ge({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new qe({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new Ye({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new Qe({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let i of n.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};import{access as ne,mkdir as tt,readFile as rt,readdir as ot,rm as nt,stat as se,writeFile as st}from"node:fs/promises";import{dirname as it,join as at,relative as ie,resolve as ct}from"node:path";var R=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return ct(this.root,t)}async put(e,t){let o=this.path(e);await tt(it(o),{recursive:!0}),await st(o,t)}async get(e){try{return await rt(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await ne(this.path(e)),!0}catch{return!1}}async delete(e){await nt(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await ne(t)}catch{return o}let n=async a=>{let c=await ot(a,{withFileTypes:!0});for(let p of c){let d=at(a,p.name);if(p.isDirectory()){await n(d);continue}let m=await se(d);o.push({key:ie(this.root,d),size:m.size,updatedAt:m.mtime.toISOString()})}},i=await se(t);return i.isDirectory()?await n(t):o.push({key:ie(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),o}};import{DeleteObjectCommand as ut,GetObjectCommand as dt,HeadObjectCommand as pt,ListObjectsV2Command as lt,PutObjectCommand as mt,S3Client as ft}from"@aws-sdk/client-s3";import{getSignedUrl as gt}from"@aws-sdk/s3-request-presigner";var A=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new ft({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new mt({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await gt(this.client,new dt({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`${this.name} download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new pt({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new ut({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new lt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let i of n.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};function V(r,e){return console.warn(e),new R(r)}function ae(r){let e=r.localRoot??ht(yt(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new A({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new A({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new T({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new R(e)}var E=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let o=JSON.parse(t);if(!Array.isArray(o))throw new Error("Invalid memory snapshot");return o}async save(e,t){let o=JSON.stringify(t,null,2);await this.storage.put(this.key(e),o,"application/json")}};function St(r){return new Promise(e=>setTimeout(e,r))}async function ce(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,i;for(let a=1;a<=t;a++)try{return await r()}catch(c){if(i=c,a>=t)break;let p=Math.min(n,o*2**(a-1)),d=Math.floor(Math.random()*Math.max(1,p*.2));await St(p+d)}throw i}var kt=new Set(["put","get","getText","delete","list"]);function ue(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:kt.has(o)?(...i)=>ce(()=>Promise.resolve(n.apply(t,i)),e):n.bind(t)}})}function de(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function pe(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(o)return`${o[1]}memory/records/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),o)return`${o[1]}memory/vectors/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),o)return`${o[1]}code/graph/${o[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var _=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=de(n??o),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),o=t,n=await this.provider.getText(e);if(n){let a;try{a=JSON.parse(n)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof a.id=="string"&&a.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${a.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof a.createdAt=="string"&&(o=a.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=pe(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,o){return await this.ensureRegistered(),this.provider.put(this.key(e),t,o)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{join as fe}from"node:path";import{mkdirSync as xt}from"node:fs";import{createHash as vt}from"node:crypto";import{dirname as wt}from"node:path";import{mkdirSync as bt,readFileSync as Wo,renameSync as jt,writeFileSync as Mt}from"node:fs";function le(r){return vt("sha256").update(r).digest("hex")}function me(r,e){bt(wt(r),{recursive:!0});let t=`${r}.${process.pid}.tmp`;Mt(t,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),jt(t,r)}function ye(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function y(r,e=20){let t=[],o=new Set;for(let n of r.slice().reverse()){let i=ye(n);if(!(!i||o.has(i))&&(o.add(i),t.push(n),t.length>=e))break}return t.reverse()}function Rt(r,e=20){let t=new Map;for(let o of r){let n=`${o.kind}|${ye(o.command)}`;t.delete(n),t.set(n,o)}return Array.from(t.values()).slice(-e)}function At(r){return r.kind==="phase"?/^Phase\s+\d+$/iu.test(r.text):r.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(r.text):!1}function ge(r,e){let t=e.status??r?.status??"pending",o=t;r&&(r.status==="completed"&&t!=="completed"?o="completed":t==="pending"&&(r.status==="in_progress"||r.status==="blocked")&&(o=r.status));let n=r&&At(e)?r.title:e.text;return{id:r?.id??le(e.key).slice(0,24),title:n,status:o,order:e.order??r?.order,confidence:Math.max(e.confidence,r?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function he(r,e){let t=`projects/${r.id}/work/observations/`,o=await e.list(t),n=[];for(let i of o.filter(a=>a.key.endsWith(".json")).sort((a,c)=>a.key.localeCompare(c.key))){let a=await e.getText(i.key);if(a)try{let c=JSON.parse(a);c.version===1&&Array.isArray(c.observations)&&n.push(c)}catch{}}return n}async function Pt(r,e){let o=(await he(r,e)).flatMap(s=>s.observations).sort((s,g)=>{let Q=s.occurredAt.localeCompare(g.occurredAt);if(Q!==0)return Q;let Z=s.sequence-g.sequence;return Z!==0?Z:s.id.localeCompare(g.id)}),n=new Map,i=new Map,a,c,p,d,m,f=[],u=[],l=[],S=[],w=[],b=new Map,F=[],W=[],J=[],U=[],Y=[],G=[];for(let s of o)switch(s.kind){case"request":a=s.text;break;case"activity":c=s.text;break;case"goal":p=s.text;break;case"plan":d=s.text;break;case"phase":n.set(s.key,ge(n.get(s.key),s));break;case"task":i.set(s.key,ge(i.get(s.key),s));break;case"decision":f.push(s.text);break;case"blocker":u.push(s.text);break;case"warning":l.push(s.text);break;case"next_action":S.push(s.text);break;case"file":{w.push(s.text);let g=s.fileAction??"active";b.delete(s.text),b.set(s.text,g),g==="modified"?F.push(s.text):g==="created"?W.push(s.text):g==="deleted"&&J.push(s.text);break}case"command":U.push(s.text);break;case"test":Y.push(s.text),s.checkKind&&G.push({kind:s.checkKind,command:s.text,status:s.checkStatus??"unknown",updatedAt:s.occurredAt,agent:s.agent,nativeSessionId:s.nativeSessionId});break;case"session":m={agent:s.agent,nativeSessionId:s.nativeSessionId,sessionKey:s.sessionKey,updatedAt:s.occurredAt};break}let k=Array.from(n.values()).sort((s,g)=>(s.order??Number.MAX_SAFE_INTEGER)-(g.order??Number.MAX_SAFE_INTEGER)),h=Array.from(i.values()).sort((s,g)=>(s.order??Number.MAX_SAFE_INTEGER)-(g.order??Number.MAX_SAFE_INTEGER)),D=k.find(s=>s.status==="in_progress")??k.find(s=>s.status==="blocked")??k.find(s=>s.status==="pending"),P=h.find(s=>s.status==="in_progress")??h.find(s=>s.status==="blocked")??h.find(s=>s.status==="pending"),Pe=y([...S,...P?[P.title]:[],...!P&&D?[D.title]:[],...h.filter(s=>s.status==="pending").slice(0,5).map(s=>s.title)],8),Ie=y([...u,...k.filter(s=>s.status==="blocked").map(s=>s.title),...h.filter(s=>s.status==="blocked").map(s=>s.title)],20),z={version:1,projectId:r.id,projectName:r.name,currentRequest:a,currentActivity:c,goal:p,plan:d,phases:k,tasks:h,decisions:y(f,20),blockers:Ie,warnings:y(l,20),nextActions:Pe,filesTouched:y(w,30),activeFiles:Array.from(b.entries()).filter(([,s])=>s!=="deleted").map(([s])=>s).slice(-5),modifiedFiles:y(F,30),createdFiles:y(W,30),deletedFiles:y(J,30),commands:y(U,20),tests:y(Y,20),checks:Rt(G,20),currentPhase:D,currentTask:P,progress:{phasesTotal:k.length,phasesCompleted:k.filter(s=>s.status==="completed").length,tasksTotal:h.length,tasksCompleted:h.filter(s=>s.status==="completed").length,blocked:k.filter(s=>s.status==="blocked").length+h.filter(s=>s.status==="blocked").length},lastSession:m,updatedAt:o.length?o[o.length-1].occurredAt:new Date().toISOString()},q=fe(r.rootPath,".toolnet","work");return xt(q,{recursive:!0}),me(fe(q,"current.json"),z),await e.put(`projects/${r.id}/work/current.json`,JSON.stringify(z,null,2)+`
6
- `,"application/json"),z}async function Se(r,e){if((await he(r,e)).length>0)return Pt(r,e);let o=await e.getText(`projects/${r.id}/work/current.json`);if(!o)return null;try{return JSON.parse(o)}catch{return null}}import{createHash as Nt}from"node:crypto";import{hostname as $t}from"node:os";import{createHash as It,randomUUID as Ct}from"node:crypto";function v(r,e){let t=r.trim();if(!t)throw new Error(`${e} is required`);return t}function N(r,e){return encodeURIComponent(v(r,e))}function Ot(r){let e=JSON.stringify(r);if(e===void 0)throw new Error("Multi-host operation payload must be JSON serializable");return e}function ve(r){return It("sha256").update(r).digest("hex")}function we(r){return ve(Ot(r))}function be(r){return Number.isFinite(Date.parse(r))}function Tt(r){return ve(JSON.stringify({version:r.version,operationId:r.operationId,projectId:r.projectId,scope:r.scope,hostId:r.hostId,occurredAt:r.occurredAt,payloadSha256:r.payloadSha256,payload:r.payload}))}function je(r){let e=v(r.projectId,"projectId"),t=v(r.scope,"scope"),o=v(r.hostId,"hostId"),n=v(r.operationId??Ct(),"operationId"),i=r.occurredAt??new Date().toISOString();if(!be(i))throw new Error(`Invalid operation timestamp: ${i}`);return{version:1,operationId:n,projectId:e,scope:t,hostId:o,occurredAt:i,payloadSha256:we(r.payload),payload:r.payload}}function Me(r,e){let t=["projects",N(r,"projectId"),"operations"];return e?`${[...t,N(e,"scope")].join("/")}/`:`${t.join("/")}/`}function Et(r){return[Me(r.projectId,r.scope).replace(/\/$/,""),N(r.hostId,"hostId"),`${N(r.operationId,"operationId")}-${r.payloadSha256}.json`].join("/")}async function xe(r,e){let t=Et(e);return await r.put(t,`${JSON.stringify(e,null,2)}
7
- `,"application/json"),t}function _t(r){let e;try{e=JSON.parse(r)}catch{return null}return e.version!==1||typeof e.operationId!="string"||typeof e.projectId!="string"||typeof e.scope!="string"||typeof e.hostId!="string"||typeof e.occurredAt!="string"||!be(e.occurredAt)||typeof e.payloadSha256!="string"||we(e.payload)!==e.payloadSha256?null:e}function ke(r,e){let t=r.occurredAt.localeCompare(e.occurredAt);if(t!==0)return t;let o=r.hostId.localeCompare(e.hostId);if(o!==0)return o;let n=r.operationId.localeCompare(e.operationId);return n!==0?n:r.payloadSha256.localeCompare(e.payloadSha256)}async function Re(r,e,t){let o=v(e,"projectId"),n=v(t,"scope"),i=Me(o,n),a=await r.list(i),c=[],p=[];for(let u of a){let l=await r.getText(u.key);if(!l){c.push(u.key);continue}let S=_t(l);if(!S){c.push(u.key);continue}if(S.projectId!==o){c.push(u.key);continue}if(S.scope!==n){c.push(u.key);continue}p.push(S)}let d=new Map;for(let u of p){let l=d.get(u.operationId);if(!l){d.set(u.operationId,[u]);continue}l.push(u)}let m=[],f=[];for(let[u,l]of d){if(new Set(l.map(b=>Tt(b))).size>1){f.push({operationId:u,variants:[...l].sort(ke)});continue}let w=l[0];w&&m.push(w)}return m.sort(ke),f.sort((u,l)=>u.operationId.localeCompare(l.operationId)),c.sort(),{operations:m,conflicts:f,invalidKeys:c}}function Kt(r){let t=(r??process.env.TOOLNET_HOST_ID??$t()).trim();return t||`pid-${process.pid}`}function Dt(r){let e=t=>{if(t===null||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>e(n));let o=t;return Object.fromEntries(Object.keys(o).sort().map(n=>[n,e(o[n])]))};return JSON.stringify(e(r))}function $(r){return Nt("sha256").update(Dt(r)).digest("hex")}function zt(r,e){let t=$(r).slice(0,12),o=$(e);return["memory",t,o].join("-")}function Ht(r,e){let t=r.updatedAt.localeCompare(e.updatedAt);if(t!==0)return t;let o=r.createdAt.localeCompare(e.createdAt);return o!==0?o:$(r).localeCompare($(e))}function Lt(r,e){return Ht(r,e)>=0?r:e}function B(r,e){let t=new Map;for(let o of r)t.set(o.id,o);for(let o of e){if(o.payload.kind!=="upsert")continue;let n=o.payload.memory,i=t.get(n.id);if(!i){t.set(n.id,n);continue}t.set(n.id,Lt(i,n))}return[...t.values()].sort((o,n)=>o.id.localeCompare(n.id))}var K=class{constructor(e,t={}){this.storage=e;this.legacy=new E(e),this.hostId=Kt(t.hostId)}storage;legacy;hostId;diagnostics={operationCount:0,conflicts:0,invalidKeys:0};getDiagnostics(){return{...this.diagnostics}}async operations(e){let t=await Re(this.storage,e,"memory");return this.diagnostics={operationCount:t.operations.length,conflicts:t.conflicts.length,invalidKeys:t.invalidKeys.length},t.operations}async load(e){let t=await this.legacy.load(e),o=await this.operations(e);return B(t,o)}async appendMemory(e,t){let o=je({projectId:e,scope:"memory",hostId:this.hostId,operationId:zt(this.hostId,t),occurredAt:t.updatedAt,payload:{kind:"upsert",memory:t}});await xe(this.storage,o)}async refreshProjection(e){let t=await this.legacy.load(e),o=await this.operations(e),n=B(t,o);return await this.legacy.save(e,n),n}async save(e,t){let o=[...t].sort((a,c)=>a.id.localeCompare(c.id));for(let a of o)await this.appendMemory(e,a);let n=await this.operations(e),i=B(t,n);await this.legacy.save(e,i)}};async function Ae(r,e){let t=new Date().toISOString(),n=await new K(e).refreshProjection(r.id),i=await Se(r,e);return{startedAt:t,finishedAt:new Date().toISOString(),memories:n.length,workAvailable:i!==null}}function Vt(r,e){let t=r.indexOf(e);if(!(t<0))return r[t+1]}function Bt(r){return{projectPath:Vt(r,"--project"),json:r.includes("--json"),quiet:r.includes("--quiet")}}async function Ft(r){let e=X(),t=ue(ae({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new _(t,r.id,r.name,r.remote??r.name)}async function Wt(){let r=Bt(process.argv.slice(2)),e=r.projectPath??process.cwd(),t=new C().detect(e);if(!t){r.quiet||console.error(`ToolNet project not found: ${e}`),process.exitCode=2;return}let o;try{o=await Ft(t)}catch(n){r.quiet||console.error(n instanceof Error?n.message:String(n)),process.exitCode=3;return}try{let n=await Ae(t,o);if(r.quiet)return;if(r.json){console.log(JSON.stringify(n));return}console.log(["ToolNet Memory refreshed",`memory=${n.memories}`,`work=${n.workAvailable?"yes":"no"}`].join(" "))}catch(n){r.quiet||console.error(n instanceof Error?n.message:String(n)),process.exitCode=4}}Wt().then(()=>{process.exit(process.exitCode??0)});
1
+ import{existsSync as $e,readFileSync as Ke}from"node:fs";import{homedir as ze}from"node:os";import{join as He}from"node:path";function Le(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function Ve(){let r=process.env.TOOLNET_GLOBAL_ENV??He(ze(),".config","toolnet-memory",".env");if(!$e(r))return;let e=Ke(r,"utf8");for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let s=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=Le(o.slice(n+1)))}}Ve();function j(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function M(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function re(){return{memory:{autoCapture:j(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:j(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:j(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:j(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:M(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:M(process.env.MEMORY_RERANK_TOP,10),finalContext:M(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:M(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:j(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:M(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Be}from"node:crypto";import{existsSync as C,mkdirSync as Fe,readFileSync as We,renameSync as Je,writeFileSync as Ue}from"node:fs";import{basename as Ye,dirname as O,join as A,parse as ae,resolve as w}from"node:path";var ce=".toolnet",Ge="project.json";function Ze(r){return Be("sha256").update(r).digest("hex").slice(0,16)}function T(r){return A(r,ce,Ge)}function qe(r){return C(T(r))}function oe(r,e){let t=w(r),o=ae(t).root;for(;;){if(qe(t))return t;if(t===o||e&&t===w(e))break;let n=O(t);if(n===t)break;t=n}return null}function ne(r){let e=w(r),t=ae(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(s=>C(A(e,s))))return e;if(e===t)break;let n=O(e);if(n===e)break;e=n}return w(r)}function se(r){let e;try{e=JSON.parse(We(r,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${r}: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let o=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:O(O(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:o,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:o,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function ie(r,e){let t=A(r,ce);Fe(t,{recursive:!0});let o=T(r),n=`${o}.tmp-${process.pid}`;Ue(n,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Je(n,o)}function F(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var E=class{findExisting(e=process.cwd()){let t=w(e),o=ne(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>C(A(o,d))),a=oe(t,s?o:void 0);if(!a)return null;let c=se(T(a));return F(c,a)}requireExisting(e=process.cwd()){let t=this.findExisting(e);if(!t)throw new Error("PROJECT_NOT_INITIALIZED");return t}detect(e=process.cwd()){let t=w(e),o=ne(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>C(A(o,m))),a=oe(t,s?o:void 0);if(a){let m=T(a),f=se(m);return f.rootPath!==a&&(f.rootPath=a,f.updatedAt=new Date().toISOString(),ie(a,f)),F(f,a)}let c=new Date().toISOString(),d=Ye(o),l={version:1,id:Ze(o),name:d,remote:d,rootPath:o,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return ie(o,l),F(l,o)}};var Qe=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_-]{20,}\b/g,confidence:"exact"},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g,confidence:"exact"},{type:"aws_access_key",regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,confidence:"exact"},{type:"github_token",regex:/\b(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{40,255})\b/g,confidence:"exact"},{type:"stripe_secret_key",regex:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,confidence:"exact"},{type:"google_api_key",regex:/\bAIza[A-Za-z0-9_-]{30,}\b/g,confidence:"exact"},{type:"slack_token",regex:/\bxox[baprs]-[A-Za-z0-9-]{16,}\b/g,confidence:"exact"},{type:"npm_token",regex:/\bnpm_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._~+/=-]{16,}\b/gi,confidence:"high"},{type:"jwt",regex:/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,confidence:"exact"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,confidence:"exact"},{type:"password_assignment",regex:/\b(?:password|passwd|pwd)\s*[:=]\s*["']?[^"' \t\r\n]{6,}["']?/gi,confidence:"high"},{type:"secret_assignment",regex:/\b(?:secret|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)\s*[:=]\s*["']?[^"' \t\r\n]{8,}["']?/gi,confidence:"high"},{type:"cookie",regex:/\b(?:cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi,confidence:"high"},{type:"url_credentials",regex:/\bhttps?:\/\/[^:/@\s]+:[^/@\s]{4,}@[^/\s]+/gi,confidence:"high"}],Xe=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function ue(r){return r.normalize("NFKC").trim().toLowerCase()}function et(r){if(r.length===0)return 0;let e=new Map;for(let o of r)e.set(o,(e.get(o)??0)+1);let t=0;for(let o of e.values()){let n=o/r.length;t-=n*Math.log2(n)}return t}function tt(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function rt(r,e,t){let o=r.slice(Math.max(0,e-48),e),n=r.slice(t,Math.min(r.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${o} ${n}`)}function ot(r,e){return r.start<e.end&&e.start<r.end}function de(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var _=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let o=ue(t);o&&this.allowValues.add(o)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let s of Qe){let a=new RegExp(s.regex.source,s.regex.flags);for(let c of e.matchAll(a))c.index===void 0||!c[0]||this.allowed(c[0])||t.push({type:s.type,value:c[0],start:c.index,end:c.index+c[0].length,confidence:s.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let o=de(t),n=[];for(let s of o)n.some(a=>ot(a,s))||n.push(s);return de(n)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=ue(e);return Xe.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],o=/[A-Za-z0-9_+/=-]{32,160}/g;for(let n of e.matchAll(o)){if(n.index===void 0||!n[0])continue;let s=n[0];this.allowed(s)||tt(s)||!/[A-Za-z]/u.test(s)||!/[0-9]/u.test(s)||rt(e,n.index,n.index+s.length)&&(et(s)<3.7||t.push({type:"high_entropy_secret",value:s,start:n.index,end:n.index+s.length,confidence:"heuristic"}))}return t}};var N=class{scanner;constructor(e={}){this.scanner=new _(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let o=e,n=[...t].sort((a,c)=>c.start-a.start),s=new Set;for(let a of n)s.add(a.type),o=o.slice(0,a.start)+`[REDACTED:${a.type}]`+o.slice(a.end);return{text:o,redacted:t.length,secretTypes:[...s].sort()}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[o,n]of Object.entries(e)){let s=o.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")){t[o]="[REDACTED]";continue}t[o]=this.sanitizeValue(n)}return t}return e}};var hr=new N;import{homedir as At}from"node:os";import{join as Rt}from"node:path";import{DeleteObjectCommand as nt,GetObjectCommand as st,HeadObjectCommand as it,ListObjectsV2Command as at,PutObjectCommand as ct,S3Client as ut}from"@aws-sdk/client-s3";import{getSignedUrl as dt}from"@aws-sdk/s3-request-presigner";var D=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new ut({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new ct({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await dt(this.client,new st({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new it({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new nt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new at({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};import{access as le,mkdir as lt,readFile as pt,readdir as mt,rm as ft,stat as pe,writeFile as gt}from"node:fs/promises";import{dirname as yt,join as ht,relative as me,resolve as St}from"node:path";var R=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return St(this.root,t)}async put(e,t){let o=this.path(e);await lt(yt(o),{recursive:!0}),await gt(o,t)}async get(e){try{return await pt(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await le(this.path(e)),!0}catch{return!1}}async delete(e){await ft(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await le(t)}catch{return o}let n=async a=>{let c=await mt(a,{withFileTypes:!0});for(let d of c){let l=ht(a,d.name);if(d.isDirectory()){await n(l);continue}let m=await pe(l);o.push({key:me(this.root,l),size:m.size,updatedAt:m.mtime.toISOString()})}},s=await pe(t);return s.isDirectory()?await n(t):o.push({key:me(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),o}};import{DeleteObjectCommand as kt,GetObjectCommand as bt,HeadObjectCommand as wt,ListObjectsV2Command as vt,PutObjectCommand as xt,S3Client as jt}from"@aws-sdk/client-s3";import{getSignedUrl as Mt}from"@aws-sdk/s3-request-presigner";var P=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new jt({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new xt({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await Mt(this.client,new bt({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`${this.name} download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new wt({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new kt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new vt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};function W(r,e){return console.warn(e),new R(r)}function fe(r){let e=r.localRoot??Rt(At(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new P({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):W(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new P({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):W(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new D({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):W(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new R(e)}var $=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let o=JSON.parse(t);if(!Array.isArray(o))throw new Error("Invalid memory snapshot");return o}async save(e,t){let o=JSON.stringify(t,null,2);await this.storage.put(this.key(e),o,"application/json")}};function Pt(r){return new Promise(e=>setTimeout(e,r))}async function ge(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,s;for(let a=1;a<=t;a++)try{return await r()}catch(c){if(s=c,a>=t)break;let d=Math.min(n,o*2**(a-1)),l=Math.floor(Math.random()*Math.max(1,d*.2));await Pt(d+l)}throw s}var It=new Set(["put","get","getText","delete","list"]);function ye(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:It.has(o)?(...s)=>ge(()=>Promise.resolve(n.apply(t,s)),e):n.bind(t)}})}function he(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Se(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(o)return`${o[1]}memory/records/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),o)return`${o[1]}memory/vectors/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),o)return`${o[1]}code/graph/${o[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var K=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=he(n??o),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),o=t,n=await this.provider.getText(e);if(n){let a;try{a=JSON.parse(n)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof a.id=="string"&&a.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${a.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof a.createdAt=="string"&&(o=a.createdAt)}let s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:t};await this.provider.put(e,JSON.stringify(s,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Se(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,o){return await this.ensureRegistered(),this.provider.put(this.key(e),t,o)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{join as we}from"node:path";import{mkdirSync as Nt}from"node:fs";import{createHash as Ct}from"node:crypto";import{dirname as Ot}from"node:path";import{mkdirSync as Tt,readFileSync as nn,renameSync as Et,writeFileSync as _t}from"node:fs";function ke(r){return Ct("sha256").update(r).digest("hex")}function be(r,e){Tt(Ot(r),{recursive:!0});let t=`${r}.${process.pid}.tmp`;_t(t,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Et(t,r)}function xe(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function y(r,e=20){let t=[],o=new Set;for(let n of r.slice().reverse()){let s=xe(n);if(!(!s||o.has(s))&&(o.add(s),t.push(n),t.length>=e))break}return t.reverse()}function Dt(r,e=20){let t=new Map;for(let o of r){let n=`${o.kind}|${xe(o.command)}`;t.delete(n),t.set(n,o)}return Array.from(t.values()).slice(-e)}function $t(r){return r.kind==="phase"?/^Phase\s+\d+$/iu.test(r.text):r.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(r.text):!1}function ve(r,e){let t=e.status??r?.status??"pending",o=t;r&&(r.status==="completed"&&t!=="completed"?o="completed":t==="pending"&&(r.status==="in_progress"||r.status==="blocked")&&(o=r.status));let n=r&&$t(e)?r.title:e.text;return{id:r?.id??ke(e.key).slice(0,24),title:n,status:o,order:e.order??r?.order,confidence:Math.max(e.confidence,r?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function je(r,e){let t=`projects/${r.id}/work/observations/`,o=await e.list(t),n=[];for(let s of o.filter(a=>a.key.endsWith(".json")).sort((a,c)=>a.key.localeCompare(c.key))){let a=await e.getText(s.key);if(a)try{let c=JSON.parse(a);c.version===1&&Array.isArray(c.observations)&&n.push(c)}catch{}}return n}async function Kt(r,e){let o=(await je(r,e)).flatMap(i=>i.observations).sort((i,g)=>{let ee=i.occurredAt.localeCompare(g.occurredAt);if(ee!==0)return ee;let te=i.sequence-g.sequence;return te!==0?te:i.id.localeCompare(g.id)}),n=new Map,s=new Map,a,c,d,l,m,f=[],u=[],p=[],S=[],v=[],x=new Map,U=[],Y=[],G=[],Z=[],q=[],Q=[];for(let i of o)switch(i.kind){case"request":a=i.text;break;case"activity":c=i.text;break;case"goal":d=i.text;break;case"plan":l=i.text;break;case"phase":n.set(i.key,ve(n.get(i.key),i));break;case"task":s.set(i.key,ve(s.get(i.key),i));break;case"decision":f.push(i.text);break;case"blocker":u.push(i.text);break;case"warning":p.push(i.text);break;case"next_action":S.push(i.text);break;case"file":{v.push(i.text);let g=i.fileAction??"active";x.delete(i.text),x.set(i.text,g),g==="modified"?U.push(i.text):g==="created"?Y.push(i.text):g==="deleted"&&G.push(i.text);break}case"command":Z.push(i.text);break;case"test":q.push(i.text),i.checkKind&&Q.push({kind:i.checkKind,command:i.text,status:i.checkStatus??"unknown",updatedAt:i.occurredAt,agent:i.agent,nativeSessionId:i.nativeSessionId});break;case"session":m={agent:i.agent,nativeSessionId:i.nativeSessionId,sessionKey:i.sessionKey,updatedAt:i.occurredAt};break}let k=Array.from(n.values()).sort((i,g)=>(i.order??Number.MAX_SAFE_INTEGER)-(g.order??Number.MAX_SAFE_INTEGER)),h=Array.from(s.values()).sort((i,g)=>(i.order??Number.MAX_SAFE_INTEGER)-(g.order??Number.MAX_SAFE_INTEGER)),V=k.find(i=>i.status==="in_progress")??k.find(i=>i.status==="blocked")??k.find(i=>i.status==="pending"),I=h.find(i=>i.status==="in_progress")??h.find(i=>i.status==="blocked")??h.find(i=>i.status==="pending"),Ne=y([...S,...I?[I.title]:[],...!I&&V?[V.title]:[],...h.filter(i=>i.status==="pending").slice(0,5).map(i=>i.title)],8),De=y([...u,...k.filter(i=>i.status==="blocked").map(i=>i.title),...h.filter(i=>i.status==="blocked").map(i=>i.title)],20),B={version:1,projectId:r.id,projectName:r.name,currentRequest:a,currentActivity:c,goal:d,plan:l,phases:k,tasks:h,decisions:y(f,20),blockers:De,warnings:y(p,20),nextActions:Ne,filesTouched:y(v,30),activeFiles:Array.from(x.entries()).filter(([,i])=>i!=="deleted").map(([i])=>i).slice(-5),modifiedFiles:y(U,30),createdFiles:y(Y,30),deletedFiles:y(G,30),commands:y(Z,20),tests:y(q,20),checks:Dt(Q,20),currentPhase:V,currentTask:I,progress:{phasesTotal:k.length,phasesCompleted:k.filter(i=>i.status==="completed").length,tasksTotal:h.length,tasksCompleted:h.filter(i=>i.status==="completed").length,blocked:k.filter(i=>i.status==="blocked").length+h.filter(i=>i.status==="blocked").length},lastSession:m,updatedAt:o.length?o[o.length-1].occurredAt:new Date().toISOString()},X=we(r.rootPath,".toolnet","work");return Nt(X,{recursive:!0}),be(we(X,"current.json"),B),await e.put(`projects/${r.id}/work/current.json`,JSON.stringify(B,null,2)+`
6
+ `,"application/json"),B}async function Me(r,e){if((await je(r,e)).length>0)return Kt(r,e);let o=await e.getText(`projects/${r.id}/work/current.json`);if(!o)return null;try{return JSON.parse(o)}catch{return null}}import{createHash as Wt}from"node:crypto";import{hostname as Jt}from"node:os";import{createHash as zt,randomUUID as Ht}from"node:crypto";function b(r,e){let t=r.trim();if(!t)throw new Error(`${e} is required`);return t}function z(r,e){return encodeURIComponent(b(r,e))}function Lt(r){let e=JSON.stringify(r);if(e===void 0)throw new Error("Multi-host operation payload must be JSON serializable");return e}function Re(r){return zt("sha256").update(r).digest("hex")}function Pe(r){return Re(Lt(r))}function Ie(r){return Number.isFinite(Date.parse(r))}function Vt(r){return Re(JSON.stringify({version:r.version,operationId:r.operationId,projectId:r.projectId,scope:r.scope,hostId:r.hostId,occurredAt:r.occurredAt,payloadSha256:r.payloadSha256,payload:r.payload}))}function Ce(r){let e=b(r.projectId,"projectId"),t=b(r.scope,"scope"),o=b(r.hostId,"hostId"),n=b(r.operationId??Ht(),"operationId"),s=r.occurredAt??new Date().toISOString();if(!Ie(s))throw new Error(`Invalid operation timestamp: ${s}`);return{version:1,operationId:n,projectId:e,scope:t,hostId:o,occurredAt:s,payloadSha256:Pe(r.payload),payload:r.payload}}function Oe(r,e){let t=["projects",z(r,"projectId"),"operations"];return e?`${[...t,z(e,"scope")].join("/")}/`:`${t.join("/")}/`}function Bt(r){return[Oe(r.projectId,r.scope).replace(/\/$/,""),z(r.hostId,"hostId"),`${z(r.operationId,"operationId")}-${r.payloadSha256}.json`].join("/")}async function Te(r,e){let t=Bt(e);return await r.put(t,`${JSON.stringify(e,null,2)}
7
+ `,"application/json"),t}function Ft(r){let e;try{e=JSON.parse(r)}catch{return null}return e.version!==1||typeof e.operationId!="string"||typeof e.projectId!="string"||typeof e.scope!="string"||typeof e.hostId!="string"||typeof e.occurredAt!="string"||!Ie(e.occurredAt)||typeof e.payloadSha256!="string"||Pe(e.payload)!==e.payloadSha256?null:e}function Ae(r,e){let t=r.occurredAt.localeCompare(e.occurredAt);if(t!==0)return t;let o=r.hostId.localeCompare(e.hostId);if(o!==0)return o;let n=r.operationId.localeCompare(e.operationId);return n!==0?n:r.payloadSha256.localeCompare(e.payloadSha256)}async function Ee(r,e,t){let o=b(e,"projectId"),n=b(t,"scope"),s=Oe(o,n),a=await r.list(s),c=[],d=[];for(let u of a){let p=await r.getText(u.key);if(!p){c.push(u.key);continue}let S=Ft(p);if(!S){c.push(u.key);continue}if(S.projectId!==o){c.push(u.key);continue}if(S.scope!==n){c.push(u.key);continue}d.push(S)}let l=new Map;for(let u of d){let p=l.get(u.operationId);if(!p){l.set(u.operationId,[u]);continue}p.push(u)}let m=[],f=[];for(let[u,p]of l){if(new Set(p.map(x=>Vt(x))).size>1){f.push({operationId:u,variants:[...p].sort(Ae)});continue}let v=p[0];v&&m.push(v)}return m.sort(Ae),f.sort((u,p)=>u.operationId.localeCompare(p.operationId)),c.sort(),{operations:m,conflicts:f,invalidKeys:c}}function Ut(r){let t=(r??process.env.TOOLNET_HOST_ID??Jt()).trim();return t||`pid-${process.pid}`}function Yt(r){let e=t=>{if(t===null||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>e(n));let o=t;return Object.fromEntries(Object.keys(o).sort().map(n=>[n,e(o[n])]))};return JSON.stringify(e(r))}function H(r){return Wt("sha256").update(Yt(r)).digest("hex")}function Gt(r,e){let t=H(r).slice(0,12),o=H(e);return["memory",t,o].join("-")}function Zt(r,e){let t=r.updatedAt.localeCompare(e.updatedAt);if(t!==0)return t;let o=r.createdAt.localeCompare(e.createdAt);return o!==0?o:H(r).localeCompare(H(e))}function qt(r,e){return Zt(r,e)>=0?r:e}function J(r,e){let t=new Map;for(let o of r)t.set(o.id,o);for(let o of e){if(o.payload.kind!=="upsert")continue;let n=o.payload.memory,s=t.get(n.id);if(!s){t.set(n.id,n);continue}t.set(n.id,qt(s,n))}return[...t.values()].sort((o,n)=>o.id.localeCompare(n.id))}var L=class{constructor(e,t={}){this.storage=e;this.legacy=new $(e),this.hostId=Ut(t.hostId)}storage;legacy;hostId;diagnostics={operationCount:0,conflicts:0,invalidKeys:0};getDiagnostics(){return{...this.diagnostics}}async operations(e){let t=await Ee(this.storage,e,"memory");return this.diagnostics={operationCount:t.operations.length,conflicts:t.conflicts.length,invalidKeys:t.invalidKeys.length},t.operations}async load(e){let t=await this.legacy.load(e),o=await this.operations(e);return J(t,o)}async appendMemory(e,t){let o=Ce({projectId:e,scope:"memory",hostId:this.hostId,operationId:Gt(this.hostId,t),occurredAt:t.updatedAt,payload:{kind:"upsert",memory:t}});await Te(this.storage,o)}async refreshProjection(e){let t=await this.legacy.load(e),o=await this.operations(e),n=J(t,o);return await this.legacy.save(e,n),n}async save(e,t){let o=[...t].sort((a,c)=>a.id.localeCompare(c.id));for(let a of o)await this.appendMemory(e,a);let n=await this.operations(e),s=J(t,n);await this.legacy.save(e,s)}};async function _e(r,e){let t=new Date().toISOString(),n=await new L(e).refreshProjection(r.id),s=await Me(r,e);return{startedAt:t,finishedAt:new Date().toISOString(),memories:n.length,workAvailable:s!==null}}function Qt(r,e){let t=r.indexOf(e);if(!(t<0))return r[t+1]}function Xt(r){return{projectPath:Qt(r,"--project"),json:r.includes("--json"),quiet:r.includes("--quiet")}}async function er(r){let e=re(),t=ye(fe({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new K(t,r.id,r.name,r.remote??r.name)}async function tr(){let r=Xt(process.argv.slice(2)),e=r.projectPath??process.cwd(),t=new E().detect(e);if(!t){r.quiet||console.error(`ToolNet project not found: ${e}`),process.exitCode=2;return}let o;try{o=await er(t)}catch(n){r.quiet||console.error(n instanceof Error?n.message:String(n)),process.exitCode=3;return}try{let n=await _e(t,o);if(r.quiet)return;if(r.json){console.log(JSON.stringify(n));return}console.log(["ToolNet Memory refreshed",`memory=${n.memories}`,`work=${n.workAvailable?"yes":"no"}`].join(" "))}catch(n){r.quiet||console.error(n instanceof Error?n.message:String(n)),process.exitCode=4}}tr().then(()=>{process.exit(process.exitCode??0)});