toolnet-memory 0.3.10 → 0.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle/cursor.js CHANGED
@@ -1,33 +1,30 @@
1
- import{homedir as yo}from"node:os";import{join as _}from"node:path";function V(o={}){return o.cursorHome??_(o.home??yo(),".cursor")}function I(o={}){return _(V(o),"mcp.json")}function E(o={}){return _(V(o),"hooks.json")}import{existsSync as Co,mkdirSync as bo,readFileSync as Oo,renameSync as wo,rmSync as Fo,writeFileSync as So}from"node:fs";import{dirname as vo}from"node:path";function f(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function k(o,r){if(!Co(o))return{};let n=Oo(o,"utf8").trim();if(!n)return{};let t;try{t=JSON.parse(n)}catch(e){throw new Error(`Invalid existing ${r} hooks file: ${e instanceof Error?e.message:String(e)}`)}if(!f(t))throw new Error(`Invalid existing ${r} hooks file: root must be a JSON object.`);return t}function C(o,r){bo(vo(o),{recursive:!0,mode:448});let n=`${o}.toolnet-${process.pid}-${Date.now()}.tmp`;try{So(n,`${JSON.stringify(r,null,2)}
2
- `,{encoding:"utf8",mode:384}),wo(n,o)}finally{Fo(n,{force:!0})}}function R(o){return/^[A-Za-z0-9_./:-]+$/u.test(o)?o:`'${o.replace(/'/gu,"'\\''")}'`}var F=[["sessionStart",10],["beforeSubmitPrompt",10],["preToolUse",10],["postToolUse",15],["afterAgentResponse",15],["stop",30]];function K(o){return f(o)&&typeof o.command=="string"&&o.command.includes("session:cursor-hook")}function xo(o,r,n){let e={type:"command",command:`TOOLNET_HOOK_EVENT=${R(o)} ${R(r)} session:cursor-hook`,timeout:n};return o==="preToolUse"&&(e.matcher=".*"),e}function q(o={}){let r=o.hooksFile??E(),n=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=k(r,"Cursor");if(t.version!==void 0&&t.version!==1)throw new Error(`Unsupported existing Cursor hooks version: ${String(t.version)}`);let e=t.hooks;if(e!==void 0&&!f(e))throw new Error("Invalid existing Cursor hooks file: hooks must be an object.");let s=f(e)?{...e}:{};for(let[l,c]of F){let a=s[l];if(a!==void 0&&!Array.isArray(a))throw new Error(`Invalid existing Cursor hooks file: hooks.${l} must be an array.`);let m=Array.isArray(a)?a.filter(p=>!K(p)):[];s[l]=[...m,xo(l,n,c)]}let i={...t,version:1,hooks:s};if(JSON.stringify(t)===JSON.stringify(i))return{hooksFile:r,changed:!1,hookCount:F.length};C(r,i);let u=k(r,"Cursor");if(u.version!==1||!f(u.hooks))throw new Error("Cursor hooks were written but verification failed.");let g=0;for(let[l]of F){let c=u.hooks[l];if(!Array.isArray(c))throw new Error("Cursor hooks were written but verification failed.");g+=c.filter(K).length}if(g!==F.length)throw new Error("Cursor hooks were written but verification failed.");return{hooksFile:r,changed:!0,hookCount:F.length}}import{existsSync as Io,mkdirSync as Eo,readFileSync as Ho,renameSync as No,rmSync as jo,writeFileSync as To}from"node:fs";import{dirname as $o}from"node:path";function d(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function b(o,r){if(!Io(o))return{};let n=Ho(o,"utf8").trim();if(!n)return{};let t;try{t=JSON.parse(n)}catch(e){throw new Error(`Invalid existing ${r} MCP config: ${e instanceof Error?e.message:String(e)}`)}if(!d(t))throw new Error(`Invalid existing ${r} MCP config: root must be a JSON object.`);return t}function H(o,r){Eo($o(o),{recursive:!0,mode:448});let n=`${o}.tmp-${process.pid}-${Date.now()}`;try{To(n,`${JSON.stringify(r,null,2)}
3
- `,{encoding:"utf8",mode:384}),No(n,o)}finally{jo(n,{force:!0})}}function z(o,r){return d(o)?(o.type===void 0||o.type==="stdio")&&o.command===r&&Array.isArray(o.args)&&o.args.length===1&&o.args[0]==="mcp":!1}function Q(o={}){let r=o.configFile??I(),n=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=o.serverName??"toolnet-memory",e=b(r,"Cursor"),s=e.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(z(i[t],n))return{installed:!0,changed:!1,configFile:r,serverName:t,command:n,args:["mcp"]};i[t]={type:"stdio",command:n,args:["mcp"]},H(r,{...e,mcpServers:i});let g=b(r,"Cursor").mcpServers;if(!d(g)||!z(g[t],n))throw new Error("Cursor MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:r,serverName:t,command:n,args:["mcp"]}}function X(o={}){let r=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=Q({binary:r,configFile:o.configFile}),t=q({binary:r,hooksFile:o.hooksFile});return{installed:n.installed,changed:n.changed||t.changed,mcp:n,hooks:t,files:[n.configFile,t.hooksFile]}}import{homedir as Jo}from"node:os";import{join as N}from"node:path";function Z(o={}){return o.copilotHome??process.env.COPILOT_HOME??N(o.home??Jo(),".copilot")}function j(o={}){return N(Z(o),"mcp-config.json")}function Mo(o={}){return N(Z(o),"hooks")}function T(o={}){return N(Mo(o),"toolnet-memory.json")}var S=[["sessionStart",10],["userPromptSubmitted",10],["userPromptTransformed",10],["preToolUse",10],["postToolUse",15],["agentStop",30]];function Go(o){if(typeof o.command=="string")return o.command;if(typeof o.bash=="string")return o.bash}function oo(o){return f(o)&&Go(o)?.includes("session:copilot-hook")===!0}function Ao(o,r,n){let t={type:"command",command:`${r} session:copilot-hook`,env:{TOOLNET_HOOK_EVENT:o},timeoutSec:n};return o==="preToolUse"&&(t.matcher=".*"),t}function ro(o={}){let r=o.hooksFile??T(),n=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=k(r,"GitHub Copilot CLI");if(t.version!==void 0&&t.version!==1)throw new Error(`Unsupported existing GitHub Copilot CLI hooks version: ${String(t.version)}`);let e=t.hooks;if(e!==void 0&&!f(e))throw new Error("Invalid existing GitHub Copilot CLI hooks file: hooks must be an object.");let s=f(e)?{...e}:{};for(let[l,c]of S){let a=s[l];if(a!==void 0&&!Array.isArray(a))throw new Error(`Invalid existing GitHub Copilot CLI hooks file: hooks.${l} must be an array.`);let m=Array.isArray(a)?a.filter(p=>!oo(p)):[];s[l]=[...m,Ao(l,n,c)]}let i={...t,version:1,hooks:s};if(JSON.stringify(t)===JSON.stringify(i))return{hooksFile:r,changed:!1,hookCount:S.length};C(r,i);let u=k(r,"GitHub Copilot CLI");if(u.version!==1||!f(u.hooks))throw new Error("GitHub Copilot CLI hooks were written but verification failed.");let g=0;for(let[l]of S){let c=u.hooks[l];if(!Array.isArray(c))throw new Error("GitHub Copilot CLI hooks were written but verification failed.");g+=c.filter(oo).length}if(g!==S.length)throw new Error("GitHub Copilot CLI hooks were written but verification failed.");return{hooksFile:r,changed:!0,hookCount:S.length}}function no(o,r){return d(o)?(o.type===void 0||o.type==="local"||o.type==="stdio")&&o.command===r&&Array.isArray(o.args)&&o.args.length===1&&o.args[0]==="mcp"&&Array.isArray(o.tools)&&o.tools.length===1&&o.tools[0]==="*":!1}function to(o={}){let r=o.configFile??j(),n=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=o.serverName??"toolnet-memory",e=b(r,"GitHub Copilot CLI"),s=e.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(no(i[t],n))return{installed:!0,changed:!1,configFile:r,serverName:t,command:n,args:["mcp"]};i[t]={type:"stdio",command:n,args:["mcp"],tools:["*"]},H(r,{...e,mcpServers:i});let g=b(r,"GitHub Copilot CLI").mcpServers;if(!d(g)||!no(g[t],n))throw new Error("GitHub Copilot CLI MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:r,serverName:t,command:n,args:["mcp"]}}function eo(o={}){let r=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=to({binary:r,configFile:o.configFile}),t=ro({binary:r,hooksFile:o.hooksFile});return{installed:n.installed,changed:n.changed||t.changed,mcp:n,hooks:t,files:[n.configFile,t.hooksFile]}}import{existsSync as Do,mkdirSync as Uo,readFileSync as io,renameSync as Bo,rmSync as Wo,writeFileSync as Yo}from"node:fs";import{dirname as Vo}from"node:path";import{homedir as Po}from"node:os";import{join as y}from"node:path";function L(o={}){return o.grokHome??process.env.GROK_HOME??y(o.home??Po(),".grok")}function $(o={}){return y(L(o),"config.toml")}function _o(o={}){return y(L(o),"hooks")}function J(o={}){return y(_o(o),"toolnet-memory.json")}function Ro(o={}){return y(L(o),"skills")}function Lo(o={}){return y(Ro(o),"toolnet-continuity")}function M(o={}){return y(Lo(o),"SKILL.md")}var D=`---
4
- name: toolnet-continuity
5
- description: Restore previous ToolNet project work when the user asks to continue, resume, pick up, finish unfinished work, or asks where work stopped.
6
- 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
1
+ import{homedir as jo}from"node:os";import{join as m,resolve as bo}from"node:path";function z(o={}){return o.cursorHome??m(o.home??jo(),".cursor")}function k(o={}){return m(z(o),"mcp.json")}function h(o={}){return m(z(o),"hooks.json")}function J(o){return m(bo(o),".cursor")}function O(o){return m(J(o),"mcp.json")}function x(o){return m(J(o),"hooks.json")}function So(o){return m(J(o),"rules")}function E(o){return m(So(o),"toolnet-memory.mdc")}import{existsSync as Co,mkdirSync as Fo,readFileSync as Io,renameSync as vo,rmSync as wo,writeFileSync as Po}from"node:fs";import{dirname as Ro}from"node:path";function b(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function $(o,e){if(!Co(o))return{};let t=Io(o,"utf8").trim();if(!t)return{};let n;try{n=JSON.parse(t)}catch(r){throw new Error(`Invalid existing ${e} hooks file: ${r instanceof Error?r.message:String(r)}`)}if(!b(n))throw new Error(`Invalid existing ${e} hooks file: root must be a JSON object.`);return n}function Q(o,e){Fo(Ro(o),{recursive:!0,mode:448});let t=`${o}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Po(t,`${JSON.stringify(e,null,2)}
2
+ `,{encoding:"utf8",mode:384}),vo(t,o)}finally{wo(t,{force:!0})}}function D(o){return/^[A-Za-z0-9_./:-]+$/u.test(o)?o:`'${o.replace(/'/gu,"'\\''")}'`}var w=[["sessionStart",10],["beforeSubmitPrompt",10],["preToolUse",10],["postToolUse",15],["afterAgentResponse",15],["stop",30]];function V(o){return b(o)&&typeof o.command=="string"&&o.command.includes("session:cursor-hook")}function Oo(o,e,t){let r={type:"command",command:`TOOLNET_HOOK_EVENT=${D(o)} ${D(e)} session:cursor-hook`,timeout:t};return o==="preToolUse"&&(r.matcher=".*"),r}function _(o={}){let e=o.hooksFile??h(),t=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=$(e,"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&&!b(r))throw new Error("Invalid existing Cursor hooks file: hooks must be an object.");let s=b(r)?{...r}:{};for(let[c,a]of w){let g=s[c];if(g!==void 0&&!Array.isArray(g))throw new Error(`Invalid existing Cursor hooks file: hooks.${c} must be an array.`);let f=Array.isArray(g)?g.filter(p=>!V(p)):[];s[c]=[...f,Oo(c,t,a)]}let i={...n,version:1,hooks:s};if(JSON.stringify(n)===JSON.stringify(i))return{hooksFile:e,changed:!1,hookCount:w.length};Q(e,i);let u=$(e,"Cursor");if(u.version!==1||!b(u.hooks))throw new Error("Cursor hooks were written but verification failed.");let l=0;for(let[c]of w){let a=u.hooks[c];if(!Array.isArray(a))throw new Error("Cursor hooks were written but verification failed.");l+=a.filter(V).length}if(l!==w.length)throw new Error("Cursor hooks were written but verification failed.");return{hooksFile:e,changed:!0,hookCount:w.length}}import{existsSync as xo,mkdirSync as Eo,readFileSync as Ao,renameSync as Ho,rmSync as Mo,writeFileSync as No}from"node:fs";import{dirname as To}from"node:path";function S(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function q(o,e){if(!xo(o))return{};let t=Ao(o,"utf8").trim();if(!t)return{};let n;try{n=JSON.parse(t)}catch(r){throw new Error(`Invalid existing ${e} MCP config: ${r instanceof Error?r.message:String(r)}`)}if(!S(n))throw new Error(`Invalid existing ${e} MCP config: root must be a JSON object.`);return n}function Z(o,e){Eo(To(o),{recursive:!0,mode:448});let t=`${o}.tmp-${process.pid}-${Date.now()}`;try{No(t,`${JSON.stringify(e,null,2)}
3
+ `,{encoding:"utf8",mode:384}),Ho(t,o)}finally{Mo(t,{force:!0})}}function oo(o,e){return S(o)?(o.type===void 0||o.type==="stdio")&&o.command===e&&Array.isArray(o.args)&&o.args.length===1&&o.args[0]==="mcp":!1}function G(o={}){let e=o.configFile??k(),t=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=o.serverName??"toolnet-memory",r=q(e,"Cursor"),s=r.mcpServers;if(s!==void 0&&!S(s))throw new Error("Invalid existing Cursor MCP config: mcpServers must be an object.");let i=S(s)?{...s}:{};if(oo(i[n],t))return{installed:!0,changed:!1,configFile:e,serverName:n,command:t,args:["mcp"]};i[n]={type:"stdio",command:t,args:["mcp"]},Z(e,{...r,mcpServers:i});let l=q(e,"Cursor").mcpServers;if(!S(l)||!oo(l[n],t))throw new Error("Cursor MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:e,serverName:n,command:t,args:["mcp"]}}import{mkdirSync as Jo,readFileSync as eo,renameSync as $o,rmSync as Do,writeFileSync as _o}from"node:fs";import{dirname as qo}from"node:path";var P=`---
4
+ description: ToolNet Memory project continuity and safety rules
5
+ alwaysApply: true
7
6
  ---
8
7
 
9
- # ToolNet Continuity
8
+ # ToolNet Memory
10
9
 
11
- When the user asks to continue or resume previous work:
10
+ Use ToolNet Memory as the continuity source for this project.
12
11
 
13
- 1. Use the ToolNet Memory MCP server as the continuity source.
14
- 2. Invoke \`memory_agent_ask\` before exploring old history if the current
15
- ToolNet handoff is missing, stale, or ambiguous.
16
- 3. Prefer \`mode="local"\` for current task, last file, blocker, completed
17
- work, TODOs, and next action.
18
- 4. Use \`mode="ai"\` only when continuity requires synthesis.
19
- 5. Do not reconstruct previous work from:
20
- - \`.toolnet/sessions/**\`
21
- - ToolNet \`events.jsonl\` or \`state.json\`
22
- - raw transcripts
23
- - another coding agent's private session/history files
24
- 6. After ToolNet continuity is known, verify current git and repository
25
- source truth before changing code.
26
- 7. Do not ask the user to repeat context ToolNet already provides.
12
+ - When the user asks to continue, resume, pick up, finish unfinished work,
13
+ or asks where work stopped, use ToolNet continuity before reconstructing
14
+ context from old chat/session history.
15
+ - Use the ToolNet MCP server and \`memory_agent_ask\` when fast project context
16
+ is missing, stale, or ambiguous.
17
+ - Prefer \`mode="local"\` for current task, current file, blockers, TODOs,
18
+ completed work, and next action.
19
+ - Use \`mode="ai"\` only when synthesis is actually required.
20
+ - Do not reconstruct continuity by reading:
21
+ - \`.toolnet/sessions/**\`
22
+ - ToolNet raw \`events.jsonl\`
23
+ - ToolNet raw \`state.json\`
24
+ - another coding agent's private transcript/history files.
25
+ - After continuity is recovered, verify current repository source and git
26
+ state before changing code.
27
+ - Do not ask the user to repeat project context that ToolNet already provides.
27
28
 
28
29
  Current repository evidence overrides stale memory.
29
- `;function Ko(o,r){Uo(Vo(o),{recursive:!0,mode:448});let n=`${o}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Yo(n,r,{encoding:"utf8",mode:384}),Bo(n,o)}finally{Wo(n,{force:!0})}}function so(o={}){let r=o.skillFile??M();if(Do(r)&&io(r,"utf8")===D)return{skillFile:r,changed:!1};if(Ko(r,D),io(r,"utf8")!==D)throw new Error("Grok ToolNet continuity skill was written but verification failed.");return{skillFile:r,changed:!0}}var v=[["SessionStart",10],["UserPromptSubmit",10],["PreToolUse",10],["PostToolUse",15],["Stop",30]];function co(o){return!f(o)||!Array.isArray(o.hooks)?!1:o.hooks.some(r=>f(r)&&typeof r.command=="string"&&r.command.includes("session:grok-hook"))}function qo(o,r,n){let t={hooks:[{type:"command",command:`${r} session:grok-hook`,timeout:n,env:{TOOLNET_HOOK_EVENT:o}}]};return o==="PreToolUse"&&(t.matcher=".*"),t}function lo(o={}){let r=o.hooksFile??J(),n=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=k(r,"Grok Build"),e=t.hooks;if(e!==void 0&&!f(e))throw new Error("Invalid existing Grok Build hooks file: hooks must be an object.");let s=f(e)?{...e}:{};for(let[l,c]of v){let a=s[l];if(a!==void 0&&!Array.isArray(a))throw new Error(`Invalid existing Grok Build hooks file: hooks.${l} must be an array.`);let m=Array.isArray(a)?a.filter(p=>!co(p)):[];s[l]=[...m,qo(l,n,c)]}let i={...t,hooks:s};if(JSON.stringify(t)===JSON.stringify(i))return{hooksFile:r,changed:!1,hookCount:v.length};C(r,i);let u=k(r,"Grok Build");if(!f(u.hooks))throw new Error("Grok Build hooks were written but verification failed.");let g=0;for(let[l]of v){let c=u.hooks[l];if(!Array.isArray(c))throw new Error("Grok Build hooks were written but verification failed.");g+=c.filter(co).length}if(g!==v.length)throw new Error("Grok Build hooks were written but verification failed.");return{hooksFile:r,changed:!0,hookCount:v.length}}import{existsSync as zo,mkdirSync as Qo,readFileSync as Xo,renameSync as Zo,rmSync as or,writeFileSync as rr}from"node:fs";import{dirname as nr}from"node:path";function ao(o){return zo(o)?Xo(o,"utf8"):""}function tr(o,r){Qo(nr(o),{recursive:!0,mode:448});let n=`${o}.tmp-${process.pid}-${Date.now()}`;try{rr(n,r,{encoding:"utf8",mode:384}),Zo(n,o)}finally{or(n,{force:!0})}}function U(o){return o.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function er(o){return`[mcp_servers."${U(o)}"]`}function ir(o,r){return[er(o),`command = "${U(r)}"`,'args = ["mcp"]',"enabled = true"].join(`
30
- `)}function sr(o){let r=o.trim();return r.startsWith("[")&&r.includes("]")}function G(o){return o.trim().replace(/\s+/g,"")}function cr(o){return new Set([G(`[mcp_servers.${o}]`),G(`[mcp_servers."${o}"]`),G(`[mcp_servers.'${o}']`)])}function go(o,r){let n=o.split(/\r?\n/),t=cr(r),e=-1;for(let c=0;c<n.length;c+=1){let a=G(n[c].replace(/\s+#.*$/,""));if(t.has(a)){e=c;break}}if(e<0)return null;let s=n.length;for(let c=e+1;c<n.length;c+=1)if(sr(n[c])){s=c;break}let i=[],u=0;for(let c of n)i.push(u),u+=c.length+1;let g=i[e]??0,l=s>=n.length?o.length:i[s]??o.length;return{start:g,end:l}}function lr(o,r,n){let t=`${ir(r,n)}
31
- `,e=go(o,r);if(e){let s=o.slice(0,e.start),i=o.slice(e.end);return`${s}${t}${i.replace(/^\n+/,"")}`}return o.trim()?`${o.replace(/\s*$/,"")}
32
-
33
- ${t}`:t}function uo(o,r,n){let t=go(o,r);if(!t)return!1;let e=o.slice(t.start,t.end);return e.includes(`command = "${U(n)}"`)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(e)&&/enabled\s*=\s*true/.test(e)}function fo(o={}){let r=o.configFile??$(),n=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=o.serverName??"toolnet-memory",e=ao(r);if(uo(e,t,n))return{installed:!0,changed:!1,configFile:r,serverName:t,command:n,args:["mcp"]};let s=lr(e,t,n);tr(r,s);let i=ao(r);if(!uo(i,t,n))throw new Error("Grok Build MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:r,serverName:t,command:n,args:["mcp"]}}function mo(o={}){let r=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",n=fo({binary:r,configFile:o.configFile}),t=lo({binary:r,hooksFile:o.hooksFile}),e=so({skillFile:o.skillFile});return{installed:n.installed,changed:n.changed||t.changed||e.changed,mcp:n,hooks:t,skill:e,files:[n.configFile,t.hooksFile,e.skillFile]}}import{existsSync as O,readFileSync as W}from"node:fs";function h(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function x(o){if(!O(o))return{};try{let r=JSON.parse(W(o,"utf8"));return h(r)?{value:r}:{error:"root must be a JSON object"}}catch(r){return{error:r instanceof Error?r.message:String(r)}}}function po(o,r){if(!o||!h(o.mcpServers))return!1;let n=o.mcpServers["toolnet-memory"];return!h(n)||typeof n.command!="string"||!n.command.trim()||!Array.isArray(n.args)||n.args.length!==1||n.args[0]!=="mcp"?!1:!r||Array.isArray(n.tools)&&n.tools.includes("*")}function ko(o,r,n){if(!o||!h(o.hooks))return[];let t=o.hooks;return r.filter(e=>{let s=t[e];return Array.isArray(s)&&s.some(i=>h(i)&&(typeof i.command=="string"&&i.command.includes(n)||typeof i.bash=="string"&&i.bash.includes(n)))})}function ar(o,r){if(!o||!h(o.hooks))return[];let n=o.hooks;return r.filter(t=>{let e=n[t];return Array.isArray(e)&&e.some(s=>!h(s)||!Array.isArray(s.hooks)?!1:s.hooks.some(i=>h(i)&&typeof i.command=="string"&&i.command.includes("session:grok-hook")))})}function ur(o){if(!O(o))return!1;let r=W(o,"utf8"),n=/\[mcp_servers\.(?:"toolnet-memory"|'toolnet-memory'|toolnet-memory)\]/,t=r.search(n);if(t<0)return!1;let e=r.slice(t),s=e.slice(1).search(/\n\s*\[[^\]]+\]/),i=s>=0?e.slice(0,s+1):e;return/command\s*=\s*"[^"]+"/.test(i)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(i)&&!/enabled\s*=\s*false/.test(i)}function B(o){let r=[];o.mcpError&&r.push(`MCP config: ${o.mcpError}`),o.hookError&&r.push(`Hooks config: ${o.hookError}`);let n=o.mcpConfigured&&o.hooksConfigured&&(o.skill?.configured??!0),t=O(o.configFile)||O(o.hooksFile)||(o.skill?O(o.skill.skillFile):!1),e=r.length>0?"invalid":n?"ready":t?"partial":"not-installed";return{installed:n,state:e,mcp:{configured:o.mcpConfigured,configFile:o.configFile,error:o.mcpError},hooks:{configured:o.hooksConfigured,hooksFile:o.hooksFile,events:o.events,error:o.hookError},skill:o.skill,errors:r}}function Y(o,r={}){if(o==="cursor"){let l=["sessionStart","beforeSubmitPrompt","preToolUse","postToolUse","afterAgentResponse","stop"],c=r.configFile??I(),a=r.hooksFile??E(),m=x(c),p=x(a),w=p.error?[]:ko(p.value,l,"session:cursor-hook");return B({mcpConfigured:!m.error&&po(m.value,!1),configFile:c,mcpError:m.error,hooksConfigured:l.every(P=>w.includes(P)),hooksFile:a,events:w,hookError:p.error})}if(o==="copilot"){let l=["sessionStart","userPromptSubmitted","userPromptTransformed","preToolUse","postToolUse","agentStop"],c=r.configFile??j(),a=r.hooksFile??T(),m=x(c),p=x(a),w=p.error?[]:ko(p.value,l,"session:copilot-hook");return B({mcpConfigured:!m.error&&po(m.value,!0),configFile:c,mcpError:m.error,hooksConfigured:l.every(P=>w.includes(P)),hooksFile:a,events:w,hookError:p.error})}let n=["SessionStart","UserPromptSubmit","PreToolUse","PostToolUse","Stop"],t=r.configFile??$(),e=r.hooksFile??J(),s=r.skillFile??M(),i=x(e),u=i.error?[]:ar(i.value,n),g=O(s)&&W(s,"utf8").includes("memory_agent_ask");return B({mcpConfigured:ur(t),configFile:t,hooksConfigured:n.every(l=>u.includes(l)),hooksFile:e,events:u,hookError:i.error,skill:{configured:g,skillFile:s}})}var A={cursor:"Cursor CLI",copilot:"GitHub Copilot CLI",grok:"Grok Build"};function ho(o){let r=process.argv.slice(2),n=r.includes("--json");if(r.includes("--status")||r[0]==="status"){let i=Y(o);if(n)console.log(JSON.stringify(i,null,2));else{console.log(`${A[o]} Integration`),console.log("=".repeat(`${A[o]} Integration`.length)),console.log(""),console.log(`State : ${i.state}`),console.log(`MCP : ${i.mcp.configured?"ready":"missing"} \u2014 ${i.mcp.configFile}`),console.log(`Hooks : ${i.hooks.configured?"ready":"missing"} \u2014 ${i.hooks.hooksFile}`),i.skill&&console.log(`Skill : ${i.skill.configured?"ready":"missing"} \u2014 ${i.skill.skillFile}`),i.hooks.events.length>0&&console.log(`Events: ${i.hooks.events.join(", ")}`);for(let u of i.errors)console.log(`Error : ${u}`);console.log("")}i.installed||(process.exitCode=1);return}let e=o==="cursor"?X():o==="copilot"?eo():mo(),s=Y(o);if(!s.installed)throw new Error(`${A[o]} integration installation did not verify successfully (state=${s.state}).`);if(n){console.log(JSON.stringify({installed:!0,changed:e.changed,files:e.files,status:s},null,2));return}console.log(`\u2705 ${A[o]} integration installed`),console.log(`MCP: ${e.mcp.configFile}`),console.log(`Hooks: ${e.hooks.hooksFile}`),s.skill&&console.log(`Skill: ${s.skill.skillFile}`),console.log("Server: toolnet-memory")}try{ho("cursor")}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exitCode=1}
30
+ `;function Go(o,e){Jo(qo(o),{recursive:!0,mode:448});let t=`${o}.toolnet-${process.pid}-${Date.now()}.tmp`;try{_o(t,e,{encoding:"utf8",mode:384}),$o(t,o)}finally{Do(t,{force:!0})}}function to(o){let e=o.ruleFile??E(o.projectRoot);try{if(eo(e,"utf8")===P)return{ruleFile:e,changed:!1}}catch{}if(Go(e,P),eo(e,"utf8")!==P)throw new Error("Cursor ToolNet project rule was written but verification failed.");return{ruleFile:e,changed:!0}}import{spawnSync as Uo}from"node:child_process";import{existsSync as C,statSync as Lo}from"node:fs";import{dirname as Bo,join as Ko,parse as Wo,resolve as L}from"node:path";function ro(o){let e=L(o);if(!C(e))throw new Error(`Project path does not exist: ${e}`);if(!Lo(e).isDirectory())throw new Error(`Project path is not a directory: ${e}`);return e}function A(o){return Ko(o,".toolnet","project.json")}function Xo(o){let e=L(o),t=Wo(e).root;for(;;){if(C(A(e)))return e;if(e===t)return;let n=Bo(e);if(n===e)return;e=n}}function U(o){let e=Uo("git",["rev-parse","--show-toplevel"],{cwd:o,encoding:"utf8",timeout:5e3});if(e.status!==0)return;let t=e.stdout.trim();return t?L(t):void 0}function F(o={}){let e=ro(o.cwd??process.cwd());if(o.project){let r=ro(o.project),s=A(r),i=U(r);return{root:r,source:"explicit",eligible:!0,toolnetProject:C(s),manifestFile:C(s)?s:void 0,gitRoot:i}}let t=Xo(e);if(t){let r=A(t);return{root:t,source:"toolnet",eligible:!0,toolnetProject:!0,manifestFile:r,gitRoot:U(t)}}let n=U(e);if(n){let r=A(n);return{root:n,source:"git",eligible:!0,toolnetProject:C(r),manifestFile:C(r)?r:void 0,gitRoot:n}}return{root:e,source:"cwd",eligible:!1,toolnetProject:!1}}function co(o,e={}){let t=[],n=o.indexOf("--scope");if(n>=0){let s=o[n+1];if(s!=="global"&&s!=="project"&&s!=="both")throw new Error(`Invalid --scope value: ${String(s)}`);t.push(s)}o.includes("--global")&&t.push("global"),o.includes("--both")&&t.push("both");let r=Array.from(new Set(t));if(r.length>1)throw new Error(`Conflicting integration scopes: ${r.join(", ")}`);return r[0]??e.defaultScope??"global"}function no(o,e){return{install:o,effective:e}}function d(o,e){return{surface:o,global:no(e.globalInstall,e.effective==="global"||e.effective==="both"),project:no(e.projectInstall,e.effective==="project"||e.effective==="both"),effective:e.effective,risk:e.risk??"none",dedupeRequired:e.dedupeRequired??!1,trustRequired:e.trustRequired??e.projectInstall,note:e.note}}function Yo(o){return{mcp:d("mcp",{globalInstall:!0,projectInstall:!1,effective:"global"}),hooks:d("hooks",{globalInstall:!0,projectInstall:!1,effective:"global"}),work:d("work",{globalInstall:o==="grok",projectInstall:!1,effective:o==="grok"?"global":"none",note:o==="grok"?"Grok supports a global ToolNet continuity skill.":"Cursor/Copilot work instructions remain project-scoped."})}}function so(o){return{mcp:d("mcp",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),hooks:d("hooks",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),work:d("work",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!1,note:o==="cursor"?"Use .cursor/rules/toolnet-memory.mdc.":o==="copilot"?"Use .github/instructions/toolnet-memory.instructions.md.":"Use .grok/skills/toolnet-continuity/SKILL.md."})}}function io(o){return{mcp:d("mcp",{globalInstall:!0,projectInstall:!0,effective:"project",risk:o==="cursor"?"precedence-unverified":"shadowed-global",trustRequired:!0,note:o==="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:d("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:d("work",{globalInstall:o==="grok",projectInstall:!0,effective:"project",risk:o==="grok"?"shadowed-global":"none",trustRequired:!1,note:o==="cursor"?"Project rule is authoritative.":o==="copilot"?"Project instruction is authoritative.":"Project skill shadows the same-name global skill inside the project."})}}function H(o){let{agent:e,scope:t,project:n}=o;return(t==="project"||t==="both")&&(!n||!n.eligible)?{agent:e,requestedScope:t,project:n,surfaces:t==="both"?io(e):so(e),canInstall:!1,reason:"Project scope requires an explicit project, existing ToolNet project, or Git repository root."}:{agent:e,requestedScope:t,project:n,surfaces:t==="global"?Yo(e):t==="project"?so(e):io(e),canInstall:!0}}function lo(o){return!!(o?.mcp?.changed||o?.hooks?.changed||o?.rule?.changed)}function uo(o={}){let e=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=o.scope??"global",n=t==="global"?void 0:F({project:o.projectRoot}),r=H({agent:"cursor",scope:t,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=G({binary:e,configFile:o.configFile??k()})),r.surfaces.hooks.global.install&&(s.hooks=_({binary:e,hooksFile:o.hooksFile??h()}))),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=G({binary:e,configFile:o.projectConfigFile??O(n.root)})),r.surfaces.hooks.project.install&&(i.hooks=_({binary:e,hooksFile:o.projectHooksFile??x(n.root)})),r.surfaces.work.project.install&&(i.rule=to({projectRoot:n.root,ruleFile:o.projectRuleFile}))}let u=i?.mcp??s?.mcp,l=i?.hooks??s?.hooks;if(!u||!l)throw new Error("Cursor integration did not produce an effective MCP/hooks installation.");let c=Array.from(new Set([s?.mcp?.configFile,s?.hooks?.hooksFile,s?.rule?.ruleFile,i?.mcp?.configFile,i?.hooks?.hooksFile,i?.rule?.ruleFile].filter(a=>typeof a=="string")));return{installed:!0,changed:lo(s)||lo(i),scope:t,plan:r,project:n,global:s,projectScope:i,mcp:u,hooks:l,rule:i?.rule,files:c}}import{existsSync as Y,readFileSync as ne}from"node:fs";import{existsSync as I,readFileSync as W}from"node:fs";import{homedir as zo}from"node:os";import{join as M,resolve as Ye}from"node:path";function ao(o={}){return o.copilotHome??process.env.COPILOT_HOME??M(o.home??zo(),".copilot")}function go(o={}){return M(ao(o),"mcp-config.json")}function Qo(o={}){return M(ao(o),"hooks")}function fo(o={}){return M(Qo(o),"toolnet-memory.json")}import{homedir as Vo}from"node:os";import{join as j,resolve as Ze}from"node:path";function B(o={}){return o.grokHome??process.env.GROK_HOME??j(o.home??Vo(),".grok")}function po(o={}){return j(B(o),"config.toml")}function Zo(o={}){return j(B(o),"hooks")}function mo(o={}){return j(Zo(o),"toolnet-memory.json")}function oe(o={}){return j(B(o),"skills")}function ee(o={}){return j(oe(o),"toolnet-continuity")}function ko(o={}){return j(ee(o),"SKILL.md")}function y(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function R(o){if(!I(o))return{};try{let e=JSON.parse(W(o,"utf8"));return y(e)?{value:e}:{error:"root must be a JSON object"}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}function ho(o,e){if(!o||!y(o.mcpServers))return!1;let t=o.mcpServers["toolnet-memory"];return!y(t)||typeof t.command!="string"||!t.command.trim()||!Array.isArray(t.args)||t.args.length!==1||t.args[0]!=="mcp"?!1:!e||Array.isArray(t.tools)&&t.tools.includes("*")}function yo(o,e,t){if(!o||!y(o.hooks))return[];let n=o.hooks;return e.filter(r=>{let s=n[r];return Array.isArray(s)&&s.some(i=>y(i)&&(typeof i.command=="string"&&i.command.includes(t)||typeof i.bash=="string"&&i.bash.includes(t)))})}function te(o,e){if(!o||!y(o.hooks))return[];let t=o.hooks;return e.filter(n=>{let r=t[n];return Array.isArray(r)&&r.some(s=>!y(s)||!Array.isArray(s.hooks)?!1:s.hooks.some(i=>y(i)&&typeof i.command=="string"&&i.command.includes("session:grok-hook")))})}function re(o){if(!I(o))return!1;let e=W(o,"utf8"),t=/\[mcp_servers\.(?:"toolnet-memory"|'toolnet-memory'|toolnet-memory)\]/,n=e.search(t);if(n<0)return!1;let r=e.slice(n),s=r.slice(1).search(/\n\s*\[[^\]]+\]/),i=s>=0?r.slice(0,s+1):r;return/command\s*=\s*"[^"]+"/.test(i)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(i)&&!/enabled\s*=\s*false/.test(i)}function K(o){let e=[];o.mcpError&&e.push(`MCP config: ${o.mcpError}`),o.hookError&&e.push(`Hooks config: ${o.hookError}`);let t=o.mcpConfigured&&o.hooksConfigured&&(o.skill?.configured??!0),n=I(o.configFile)||I(o.hooksFile)||(o.skill?I(o.skill.skillFile):!1),r=e.length>0?"invalid":t?"ready":n?"partial":"not-installed";return{installed:t,state:r,mcp:{configured:o.mcpConfigured,configFile:o.configFile,error:o.mcpError},hooks:{configured:o.hooksConfigured,hooksFile:o.hooksFile,events:o.events,error:o.hookError},skill:o.skill,errors:e}}function X(o,e={}){if(o==="cursor"){let c=["sessionStart","beforeSubmitPrompt","preToolUse","postToolUse","afterAgentResponse","stop"],a=e.configFile??k(),g=e.hooksFile??h(),f=R(a),p=R(g),v=p.error?[]:yo(p.value,c,"session:cursor-hook");return K({mcpConfigured:!f.error&&ho(f.value,!1),configFile:a,mcpError:f.error,hooksConfigured:c.every(T=>v.includes(T)),hooksFile:g,events:v,hookError:p.error})}if(o==="copilot"){let c=["sessionStart","userPromptSubmitted","userPromptTransformed","preToolUse","postToolUse","agentStop"],a=e.configFile??go(),g=e.hooksFile??fo(),f=R(a),p=R(g),v=p.error?[]:yo(p.value,c,"session:copilot-hook");return K({mcpConfigured:!f.error&&ho(f.value,!0),configFile:a,mcpError:f.error,hooksConfigured:c.every(T=>v.includes(T)),hooksFile:g,events:v,hookError:p.error})}let t=["SessionStart","UserPromptSubmit","PreToolUse","PostToolUse","Stop"],n=e.configFile??po(),r=e.hooksFile??mo(),s=e.skillFile??ko(),i=R(r),u=i.error?[]:te(i.value,t),l=I(s)&&W(s,"utf8").includes("memory_agent_ask");return K({mcpConfigured:re(n),configFile:n,hooksConfigured:t.every(c=>u.includes(c)),hooksFile:r,events:u,hookError:i.error,skill:{configured:l,skillFile:s}})}function se(o){let e=!1;try{e=ne(o,"utf8")===P}catch{e=!1}return{configured:e,ruleFile:o}}function ie(o,e,t){return e.some(r=>r?.state==="invalid")?"invalid":o?"ready":e.some(r=>r&&(r.state==="partial"||r.state==="ready"||Y(r.mcp.configFile)||Y(r.hooks.hooksFile)))||!!(t&&Y(t.ruleFile))?"partial":"not-installed"}function N(o={}){let e=o.scope??"global",t=e==="global"?void 0:F({project:o.projectRoot}),n=H({agent:"cursor",scope:e,project:t}),r=e==="global"||e==="both"?X("cursor",{configFile:o.globalConfigFile??k(),hooksFile:o.globalHooksFile??h()}):void 0,s;if((e==="project"||e==="both")&&t?.eligible){let a=se(o.projectRuleFile??E(t.root));s={...X("cursor",{configFile:o.projectConfigFile??O(t.root),hooksFile:o.projectHooksFile??x(t.root)}),rule:a}}let i=e==="project"?!0:r?.installed===!0,u=e==="global"?!0:s?.installed===!0&&s.rule.configured===!0,l=n.canInstall&&i&&u,c=[];return!n.canInstall&&n.reason&&c.push(n.reason),e==="both"&&(c.push("Global + project Cursor hooks are additive; ToolNet runtime dedupe is required and enabled."),c.push("Cursor same-name global/project MCP precedence remains marked for native E2E certification.")),{installed:l,state:ie(l,[r,s],s?.rule),requestedScope:e,plan:n,project:t,global:r,projectScope:s,dedupeReady:!0,trustRequired:e==="project"||e==="both",warnings:c}}function ce(o,e){let t=o.indexOf(e);return t>=0?o[t+1]:void 0}function le(){let o=process.argv.slice(2);return o[0]==="install"?o.slice(1):o}function ue(o,e){let t=N({scope:o,projectRoot:e});console.log("Cursor CLI Integration"),console.log("======================"),console.log(""),console.log(`State : ${t.state}`),console.log(`Scope : ${t.requestedScope}`),t.global&&(console.log(""),console.log("Global"),console.log(` MCP : ${t.global.mcp.configured?"ready":"missing"} \u2014 ${t.global.mcp.configFile}`),console.log(` Hooks : ${t.global.hooks.configured?"ready":"missing"} \u2014 ${t.global.hooks.hooksFile}`)),t.projectScope&&(console.log(""),console.log("Project"),console.log(` Root : ${t.project?.root??"-"}`),console.log(` MCP : ${t.projectScope.mcp.configured?"ready":"missing"} \u2014 ${t.projectScope.mcp.configFile}`),console.log(` Hooks : ${t.projectScope.hooks.configured?"ready":"missing"} \u2014 ${t.projectScope.hooks.hooksFile}`),console.log(` Rule : ${t.projectScope.rule.configured?"ready":"missing"} \u2014 ${t.projectScope.rule.ruleFile}`),console.log(` Trust : ${t.trustRequired?"required":"n/a"}`)),console.log(""),console.log(`Dedupe: ${t.dedupeReady?"ready":"missing"}`);for(let n of t.warnings)console.log(`Note : ${n}`);console.log(""),t.installed||(process.exitCode=1)}function ae(){let o=le(),e=o.includes("--json"),t=o.includes("--status")||o[0]==="status",n=co(o),r=ce(o,"--project"),s=n==="global"?void 0:F({project:r});if(t){let l=N({scope:n,projectRoot:s?.root});if(e){console.log(JSON.stringify(l,null,2)),l.installed||(process.exitCode=1);return}ue(n,s?.root);return}let i=uo({scope:n,projectRoot:s?.root}),u=N({scope:n,projectRoot:s?.root});if(!u.installed)throw new Error(`Cursor integration installation did not verify successfully (state=${u.state}).`);if(e){console.log(JSON.stringify({installed:!0,changed:i.changed,scope:i.scope,files:i.files,status:u},null,2));return}console.log("\u2705 Cursor CLI integration installed"),console.log(`Scope: ${n}`);for(let l of i.files)console.log(`File: ${l}`);n==="both"&&(console.log("Hook dedupe: enabled"),console.log("Project trust: required by Cursor")),console.log("Server: toolnet-memory")}try{ae()}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exitCode=1}