toolnet-memory 0.3.8 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
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 g=k(r,"Cursor");if(g.version!==1||!f(g.hooks))throw new Error("Cursor hooks were written but verification failed.");let u=0;for(let[l]of F){let c=g.hooks[l];if(!Array.isArray(c))throw new Error("Cursor hooks were written but verification failed.");u+=c.filter(K).length}if(u!==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 u=b(r,"Cursor").mcpServers;if(!d(u)||!z(u[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 g=k(r,"GitHub Copilot CLI");if(g.version!==1||!f(g.hooks))throw new Error("GitHub Copilot CLI hooks were written but verification failed.");let u=0;for(let[l]of S){let c=g.hooks[l];if(!Array.isArray(c))throw new Error("GitHub Copilot CLI hooks were written but verification failed.");u+=c.filter(oo).length}if(u!==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 u=b(r,"GitHub Copilot CLI").mcpServers;if(!d(u)||!no(u[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
7
+ ---
8
+
9
+ # ToolNet Continuity
10
+
11
+ When the user asks to continue or resume previous work:
12
+
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.
27
+
28
+ 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 g=k(r,"Grok Build");if(!f(g.hooks))throw new Error("Grok Build hooks were written but verification failed.");let u=0;for(let[l]of v){let c=g.hooks[l];if(!Array.isArray(c))throw new Error("Grok Build hooks were written but verification failed.");u+=c.filter(co).length}if(u!==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 uo(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=[],g=0;for(let c of n)i.push(g),g+=c.length+1;let u=i[e]??0,l=s>=n.length?o.length:i[s]??o.length;return{start:u,end:l}}function lr(o,r,n){let t=`${ir(r,n)}
31
+ `,e=uo(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 go(o,r,n){let t=uo(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(go(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(!go(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 gr(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),g=i.error?[]:ar(i.value,n),u=O(s)&&W(s,"utf8").includes("memory_agent_ask");return B({mcpConfigured:gr(t),configFile:t,hooksConfigured:n.every(l=>g.includes(l)),hooksFile:e,events:g,hookError:i.error,skill:{configured:u,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 g of i.errors)console.log(`Error : ${g}`);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("copilot")}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exitCode=1}