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.
- package/.env.example +0 -1
- package/.release-target +1 -1
- package/README.md +25 -1
- package/bin/toolnet-memory +5 -0
- package/bundle/agy-hook.js +67 -67
- package/bundle/agy.js +61 -61
- package/bundle/api.js +15 -15
- package/bundle/auto-integrate.js +28 -28
- package/bundle/background-refresh.js +7 -7
- package/bundle/claude-hook.js +51 -50
- package/bundle/codex-context.js +25 -24
- package/bundle/codex.js +71 -71
- package/bundle/context-runtime.js +45 -44
- package/bundle/context.js +15 -15
- package/bundle/continuity-certify.js +13 -13
- package/bundle/copilot-hook.js +87 -85
- package/bundle/copilot.js +4 -4
- package/bundle/cursor-hook.js +87 -85
- package/bundle/cursor.js +4 -4
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +20 -20
- package/bundle/gc.js +3 -0
- package/bundle/graph-index.js +4 -4
- package/bundle/graph-ui.js +3 -3
- package/bundle/grok-hook.js +60 -59
- package/bundle/grok.js +5 -5
- package/bundle/handoff-refresh.js +10 -10
- package/bundle/help-cli.js +4 -4
- package/bundle/impact.js +4 -4
- package/bundle/incremental.js +5 -4
- package/bundle/init.js +37 -37
- package/bundle/integration-status.js +4 -4
- package/bundle/kiro-hook.js +82 -81
- package/bundle/learner.js +6 -6
- package/bundle/mcp.js +17 -17
- package/bundle/memory-agent.js +7 -7
- package/bundle/memory-query.js +7 -7
- package/bundle/opencode.js +80 -80
- package/bundle/project-manual.js +7 -7
- package/bundle/recovery-certify.js +15 -15
- package/bundle/runtime.js +13 -12
- package/bundle/semantic.js +5 -5
- package/bundle/snapshot.js +4 -4
- package/bundle/status-cli.js +4 -4
- package/bundle/toolnet-cli.js +60 -60
- package/bundle/work-continuity.js +7 -7
- package/package.json +9 -3
- package/release-manifest.json +54 -3
package/bundle/grok.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{homedir as
|
|
1
|
+
import{homedir as jo}from"node:os";import{join as p,resolve as bo}from"node:path";function _(o={}){return o.grokHome??process.env.GROK_HOME??p(o.home??jo(),".grok")}function m(o={}){return p(_(o),"config.toml")}function So(o={}){return p(_(o),"hooks")}function y(o={}){return p(So(o),"toolnet-memory.json")}function Io(o={}){return p(_(o),"skills")}function vo(o={}){return p(Io(o),"toolnet-continuity")}function h(o={}){return p(vo(o),"SKILL.md")}function T(o){return p(bo(o),".grok")}function x(o){return p(T(o),"config.toml")}function Fo(o){return p(T(o),"hooks")}function C(o){return p(Fo(o),"toolnet-memory.json")}function Po(o){return p(T(o),"skills")}function wo(o){return p(Po(o),"toolnet-continuity")}function R(o){return p(wo(o),"SKILL.md")}import{existsSync as xo,mkdirSync as Co,readFileSync as X,renameSync as Ro,rmSync as Oo,writeFileSync as Ao}from"node:fs";import{dirname as Eo}from"node:path";var M=`---
|
|
2
2
|
name: toolnet-continuity
|
|
3
3
|
description: Restore previous ToolNet project work when the user asks to continue, resume, pick up, finish unfinished work, or asks where work stopped.
|
|
4
4
|
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
|
|
@@ -24,9 +24,9 @@ When the user asks to continue or resume previous work:
|
|
|
24
24
|
7. Do not ask the user to repeat context ToolNet already provides.
|
|
25
25
|
|
|
26
26
|
Current repository evidence overrides stale memory.
|
|
27
|
-
`;function
|
|
28
|
-
`,{encoding:"utf8",mode:384}),
|
|
29
|
-
`)}function Qo(o){let e=o.trim();return e.startsWith("[")&&e.includes("]")}function
|
|
27
|
+
`;function Go(o,e){Co(Eo(o),{recursive:!0,mode:448});let t=`${o}.toolnet-${process.pid}-${Date.now()}.tmp`;try{Ao(t,e,{encoding:"utf8",mode:384}),Ro(t,o)}finally{Oo(t,{force:!0})}}function N(o={}){let e=o.skillFile??h();if(xo(e)&&X(e,"utf8")===M)return{skillFile:e,changed:!1};if(Go(e,M),X(e,"utf8")!==M)throw new Error("Grok ToolNet continuity skill was written but verification failed.");return{skillFile:e,changed:!0}}import{existsSync as Ho,mkdirSync as $o,readFileSync as _o,renameSync as To,rmSync as Mo,writeFileSync as No}from"node:fs";import{dirname as Do}from"node:path";function b(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function D(o,e){if(!Ho(o))return{};let t=_o(o,"utf8").trim();if(!t)return{};let r;try{r=JSON.parse(t)}catch(n){throw new Error(`Invalid existing ${e} hooks file: ${n instanceof Error?n.message:String(n)}`)}if(!b(r))throw new Error(`Invalid existing ${e} hooks file: root must be a JSON object.`);return r}function Q(o,e){$o(Do(o),{recursive:!0,mode:448});let t=`${o}.toolnet-${process.pid}-${Date.now()}.tmp`;try{No(t,`${JSON.stringify(e,null,2)}
|
|
28
|
+
`,{encoding:"utf8",mode:384}),To(t,o)}finally{Mo(t,{force:!0})}}var P=[["SessionStart",10],["UserPromptSubmit",10],["PreToolUse",10],["PostToolUse",15],["Stop",30]];function Z(o){return!b(o)||!Array.isArray(o.hooks)?!1:o.hooks.some(e=>b(e)&&typeof e.command=="string"&&e.command.includes("session:grok-hook"))}function Jo(o,e,t){let r={hooks:[{type:"command",command:`${e} session:grok-hook`,timeout:t,env:{TOOLNET_HOOK_EVENT:o}}]};return o==="PreToolUse"&&(r.matcher=".*"),r}function J(o={}){let e=o.hooksFile??y(),t=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=D(e,"Grok Build"),n=r.hooks;if(n!==void 0&&!b(n))throw new Error("Invalid existing Grok Build hooks file: hooks must be an object.");let i=b(n)?{...n}:{};for(let[c,l]of P){let g=i[c];if(g!==void 0&&!Array.isArray(g))throw new Error(`Invalid existing Grok Build hooks file: hooks.${c} must be an array.`);let f=Array.isArray(g)?g.filter(d=>!Z(d)):[];i[c]=[...f,Jo(c,t,l)]}let s={...r,hooks:i};if(JSON.stringify(r)===JSON.stringify(s))return{hooksFile:e,changed:!1,hookCount:P.length};Q(e,s);let a=D(e,"Grok Build");if(!b(a.hooks))throw new Error("Grok Build hooks were written but verification failed.");let u=0;for(let[c]of P){let l=a.hooks[c];if(!Array.isArray(l))throw new Error("Grok Build hooks were written but verification failed.");u+=l.filter(Z).length}if(u!==P.length)throw new Error("Grok Build hooks were written but verification failed.");return{hooksFile:e,changed:!0,hookCount:P.length}}import{existsSync as qo,mkdirSync as Lo,readFileSync as Uo,renameSync as Bo,rmSync as Ko,writeFileSync as Wo}from"node:fs";import{dirname as Vo}from"node:path";function oo(o){return qo(o)?Uo(o,"utf8"):""}function zo(o,e){Lo(Vo(o),{recursive:!0,mode:448});let t=`${o}.tmp-${process.pid}-${Date.now()}`;try{Wo(t,e,{encoding:"utf8",mode:384}),Bo(t,o)}finally{Ko(t,{force:!0})}}function q(o){return o.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function Yo(o){return`[mcp_servers."${q(o)}"]`}function Xo(o,e){return[Yo(o),`command = "${q(e)}"`,'args = ["mcp"]',"enabled = true"].join(`
|
|
29
|
+
`)}function Qo(o){let e=o.trim();return e.startsWith("[")&&e.includes("]")}function O(o){return o.trim().replace(/\s+/g,"")}function Zo(o){return new Set([O(`[mcp_servers.${o}]`),O(`[mcp_servers."${o}"]`),O(`[mcp_servers.'${o}']`)])}function to(o,e){let t=o.split(/\r?\n/),r=Zo(e),n=-1;for(let l=0;l<t.length;l+=1){let g=O(t[l].replace(/\s+#.*$/,""));if(r.has(g)){n=l;break}}if(n<0)return null;let i=t.length;for(let l=n+1;l<t.length;l+=1)if(Qo(t[l])){i=l;break}let s=[],a=0;for(let l of t)s.push(a),a+=l.length+1;let u=s[n]??0,c=i>=t.length?o.length:s[i]??o.length;return{start:u,end:c}}function oe(o,e,t){let r=`${Xo(e,t)}
|
|
30
30
|
`,n=to(o,e);if(n){let i=o.slice(0,n.start),s=o.slice(n.end);return`${i}${r}${s.replace(/^\n+/,"")}`}return o.trim()?`${o.replace(/\s*$/,"")}
|
|
31
31
|
|
|
32
|
-
${r}`:r}function eo(o,e,t){let r=to(o,e);if(!r)return!1;let n=o.slice(r.start,r.end);return n.includes(`command = "${q(t)}"`)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(n)&&/enabled\s*=\s*true/.test(n)}function B(o={}){let e=o.configFile??m(),t=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=o.serverName??"toolnet-memory",n=oo(e);if(eo(n,r,t))return{installed:!0,changed:!1,configFile:e,serverName:r,command:t,args:["mcp"]};let i=oe(n,r,t);Vo(e,i);let s=oo(e);if(!eo(s,r,t))throw new Error("Grok Build MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:e,serverName:r,command:t,args:["mcp"]}}import{spawnSync as ee}from"node:child_process";import{existsSync as S,statSync as te}from"node:fs";import{dirname as re,join as ne,parse as ie,resolve as L}from"node:path";function ro(o){let e=L(o);if(!S(e))throw new Error(`Project path does not exist: ${e}`);if(!te(e).isDirectory())throw new Error(`Project path is not a directory: ${e}`);return e}function G(o){return ne(o,".toolnet","project.json")}function se(o){let e=L(o),t=ie(e).root;for(;;){if(S(G(e)))return e;if(e===t)return;let r=re(e);if(r===e)return;e=r}}function U(o){let e=ee("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 v(o={}){let e=ro(o.cwd??process.cwd());if(o.project){let n=ro(o.project),i=G(n),s=U(n);return{root:n,source:"explicit",eligible:!0,toolnetProject:S(i),manifestFile:S(i)?i:void 0,gitRoot:s}}let t=se(e);if(t){let n=G(t);return{root:t,source:"toolnet",eligible:!0,toolnetProject:!0,manifestFile:n,gitRoot:U(t)}}let r=U(e);if(r){let n=G(r);return{root:r,source:"git",eligible:!0,toolnetProject:S(n),manifestFile:S(n)?n:void 0,gitRoot:r}}return{root:e,source:"cwd",eligible:!1,toolnetProject:!1}}function lo(o,e={}){let t=[],r=o.indexOf("--scope");if(r>=0){let i=o[r+1];if(i!=="global"&&i!=="project"&&i!=="both")throw new Error(`Invalid --scope value: ${String(i)}`);t.push(i)}o.includes("--global")&&t.push("global"),o.includes("--both")&&t.push("both");let n=Array.from(new Set(t));if(n.length>1)throw new Error(`Conflicting integration scopes: ${n.join(", ")}`);return n[0]??e.defaultScope??"global"}function no(o,e){return{install:o,effective:e}}function k(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 le(o){return{mcp:k("mcp",{globalInstall:!0,projectInstall:!1,effective:"global"}),hooks:k("hooks",{globalInstall:!0,projectInstall:!1,effective:"global"}),work:k("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 io(o){return{mcp:k("mcp",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),hooks:k("hooks",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),work:k("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 so(o){return{mcp:k("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:k("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:k("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:r}=o;return(t==="project"||t==="both")&&(!r||!r.eligible)?{agent:e,requestedScope:t,project:r,surfaces:t==="both"?so(e):io(e),canInstall:!1,reason:"Project scope requires an explicit project, existing ToolNet project, or Git repository root."}:{agent:e,requestedScope:t,project:r,surfaces:t==="global"?le(e):t==="project"?io(e):so(e),canInstall:!0}}function co(o){return!!(o?.mcp?.changed||o?.hooks?.changed||o?.skill?.changed)}function ao(o={}){let e=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=o.scope??"global",r=t==="global"?void 0:v({project:o.projectRoot}),n=H({agent:"grok",scope:t,project:r});if(!n.canInstall)throw new Error(n.reason??"Grok project integration scope cannot be resolved.");let i,s;if((n.surfaces.mcp.global.install||n.surfaces.hooks.global.install||n.surfaces.work.global.install)&&(i={},n.surfaces.mcp.global.install&&(i.mcp=B({binary:e,configFile:o.configFile??m()})),n.surfaces.hooks.global.install&&(i.hooks=J({binary:e,hooksFile:o.hooksFile??h()})),n.surfaces.work.global.install&&(i.skill=D({skillFile:o.skillFile??y()}))),n.surfaces.mcp.project.install||n.surfaces.hooks.project.install||n.surfaces.work.project.install){if(!r?.eligible)throw new Error("Grok project integration requires an eligible project root.");s={},n.surfaces.mcp.project.install&&(s.mcp=B({binary:e,configFile:o.projectConfigFile??P(r.root)})),n.surfaces.hooks.project.install&&(s.hooks=J({binary:e,hooksFile:o.projectHooksFile??x(r.root)})),n.surfaces.work.project.install&&(s.skill=D({skillFile:o.projectSkillFile??O(r.root)}))}let a=s?.mcp??i?.mcp,u=s?.hooks??i?.hooks,l=s?.skill??i?.skill;if(!a||!u||!l)throw new Error("Grok integration did not produce effective MCP/hooks/skill.");let c=Array.from(new Set([i?.mcp?.configFile,i?.hooks?.hooksFile,i?.skill?.skillFile,s?.mcp?.configFile,s?.hooks?.hooksFile,s?.skill?.skillFile].filter(g=>typeof g=="string")));return{installed:!0,changed:co(i)||co(s),scope:t,plan:n,project:r,global:i,projectScope:s,mcp:a,hooks:u,skill:l,files:c}}import{existsSync as X}from"node:fs";import{existsSync as F,readFileSync as z}from"node:fs";import{homedir as ce}from"node:os";import{join as K,resolve as ot}from"node:path";function uo(o={}){return o.cursorHome??K(o.home??ce(),".cursor")}function go(o={}){return K(uo(o),"mcp.json")}function fo(o={}){return K(uo(o),"hooks.json")}import{homedir as ae}from"node:os";import{join as A,resolve as nt}from"node:path";function po(o={}){return o.copilotHome??process.env.COPILOT_HOME??A(o.home??ae(),".copilot")}function ko(o={}){return A(po(o),"mcp-config.json")}function ue(o={}){return A(po(o),"hooks")}function mo(o={}){return A(ue(o),"toolnet-memory.json")}function b(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function C(o){if(!F(o))return{};try{let e=JSON.parse(z(o,"utf8"));return b(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||!b(o.mcpServers))return!1;let t=o.mcpServers["toolnet-memory"];return!b(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||!b(o.hooks))return[];let r=o.hooks;return e.filter(n=>{let i=r[n];return Array.isArray(i)&&i.some(s=>b(s)&&(typeof s.command=="string"&&s.command.includes(t)||typeof s.bash=="string"&&s.bash.includes(t)))})}function ge(o,e){if(!o||!b(o.hooks))return[];let t=o.hooks;return e.filter(r=>{let n=t[r];return Array.isArray(n)&&n.some(i=>!b(i)||!Array.isArray(i.hooks)?!1:i.hooks.some(s=>b(s)&&typeof s.command=="string"&&s.command.includes("session:grok-hook")))})}function fe(o){if(!F(o))return!1;let e=z(o,"utf8"),t=/\[mcp_servers\.(?:"toolnet-memory"|'toolnet-memory'|toolnet-memory)\]/,r=e.search(t);if(r<0)return!1;let n=e.slice(r),i=n.slice(1).search(/\n\s*\[[^\]]+\]/),s=i>=0?n.slice(0,i+1):n;return/command\s*=\s*"[^"]+"/.test(s)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(s)&&!/enabled\s*=\s*false/.test(s)}function W(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),r=F(o.configFile)||F(o.hooksFile)||(o.skill?F(o.skill.skillFile):!1),n=e.length>0?"invalid":t?"ready":r?"partial":"not-installed";return{installed:t,state:n,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 V(o,e={}){if(o==="cursor"){let l=["sessionStart","beforeSubmitPrompt","preToolUse","postToolUse","afterAgentResponse","stop"],c=e.configFile??go(),g=e.hooksFile??fo(),p=C(c),d=C(g),I=d.error?[]:yo(d.value,l,"session:cursor-hook");return W({mcpConfigured:!p.error&&ho(p.value,!1),configFile:c,mcpError:p.error,hooksConfigured:l.every($=>I.includes($)),hooksFile:g,events:I,hookError:d.error})}if(o==="copilot"){let l=["sessionStart","userPromptSubmitted","userPromptTransformed","preToolUse","postToolUse","agentStop"],c=e.configFile??ko(),g=e.hooksFile??mo(),p=C(c),d=C(g),I=d.error?[]:yo(d.value,l,"session:copilot-hook");return W({mcpConfigured:!p.error&&ho(p.value,!0),configFile:c,mcpError:p.error,hooksConfigured:l.every($=>I.includes($)),hooksFile:g,events:I,hookError:d.error})}let t=["SessionStart","UserPromptSubmit","PreToolUse","PostToolUse","Stop"],r=e.configFile??m(),n=e.hooksFile??h(),i=e.skillFile??y(),s=C(n),a=s.error?[]:ge(s.value,t),u=F(i)&&z(i,"utf8").includes("memory_agent_ask");return W({mcpConfigured:fe(r),configFile:r,hooksConfigured:t.every(l=>a.includes(l)),hooksFile:n,events:a,hookError:s.error,skill:{configured:u,skillFile:i}})}function pe(o,e){return e.some(r=>r?.state==="invalid")?"invalid":o?"ready":e.some(r=>r&&(r.state==="partial"||r.state==="ready"||X(r.mcp.configFile)||X(r.hooks.hooksFile)||!!(r.skill&&X(r.skill.skillFile))))?"partial":"not-installed"}function E(o={}){let e=o.scope??"global",t=e==="global"?void 0:v({project:o.projectRoot}),r=H({agent:"grok",scope:e,project:t}),n=e==="global"||e==="both"?V("grok",{configFile:o.globalConfigFile??m(),hooksFile:o.globalHooksFile??h(),skillFile:o.globalSkillFile??y()}):void 0,i=(e==="project"||e==="both")&&t?.eligible?V("grok",{configFile:o.projectConfigFile??P(t.root),hooksFile:o.projectHooksFile??x(t.root),skillFile:o.projectSkillFile??O(t.root)}):void 0,s=e==="project"?!0:n?.installed===!0,a=e==="global"?!0:i?.installed===!0,u=r.canInstall&&s&&a,l=[];return!r.canInstall&&r.reason&&l.push(r.reason),e==="both"&&(l.push("Global + project Grok hooks are layered; ToolNet cross-process dedupe is enabled."),l.push('Project [mcp_servers."toolnet-memory"] fully replaces the same-name global server inside this project.'),l.push("Project toolnet-continuity skill shadows the same-name global skill inside this project.")),{installed:u,state:pe(u,[n,i]),requestedScope:e,plan:r,project:t,global:n,projectScope:i,effective:{mcp:r.surfaces.mcp.effective==="project"?"project":r.surfaces.mcp.effective==="global"?"global":"none",hooks:r.surfaces.hooks.effective==="both"?"both":r.surfaces.hooks.effective==="project"?"project":r.surfaces.hooks.effective==="global"?"global":"none",skill:r.surfaces.work.effective==="project"?"project":r.surfaces.work.effective==="global"?"global":"none"},dedupeReady:!0,trustRequired:e==="project"||e==="both",warnings:l}}function de(o,e){let t=o.indexOf(e);return t>=0?o[t+1]:void 0}function ke(){let o=process.argv.slice(2);return o[0]==="install"?o.slice(1):o}function me(o,e){let t=E({scope:o,projectRoot:e});console.log("Grok Build 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}`),console.log(` Skill : ${t.global.skill?.configured?"ready":"missing"} \u2014 ${t.global.skill?.skillFile??"-"}`)),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(` Skill : ${t.projectScope.skill?.configured?"ready":"missing"} \u2014 ${t.projectScope.skill?.skillFile??"-"}`),console.log(` Trust : ${t.trustRequired?"required":"n/a"}`)),console.log(""),console.log(`Effective MCP : ${t.effective.mcp}`),console.log(`Effective Hooks : ${t.effective.hooks}`),console.log(`Effective Skill : ${t.effective.skill}`),console.log(`Dedupe : ${t.dedupeReady?"ready":"missing"}`);for(let r of t.warnings)console.log(`Note : ${r}`);console.log(""),t.installed||(process.exitCode=1)}function he(){let o=ke(),e=o.includes("--json"),t=o.includes("--status")||o[0]==="status",r=lo(o),n=de(o,"--project"),i=r==="global"?void 0:v({project:n});if(t){let u=E({scope:r,projectRoot:i?.root});if(e){console.log(JSON.stringify(u,null,2)),u.installed||(process.exitCode=1);return}me(r,i?.root);return}let s=ao({scope:r,projectRoot:i?.root}),a=E({scope:r,projectRoot:i?.root});if(!a.installed)throw new Error(`Grok Build integration installation did not verify successfully (state=${a.state}).`);if(e){console.log(JSON.stringify({installed:!0,changed:s.changed,scope:s.scope,files:s.files,status:a},null,2));return}console.log("\u2705 Grok Build integration installed"),console.log(`Scope: ${r}`);for(let u of s.files)console.log(`File: ${u}`);r==="both"&&(console.log("Hook dedupe: enabled"),console.log("Project MCP precedence: project fully replaces global same-name server"),console.log("Project skill precedence: project > global"),console.log("Project trust: required by Grok Build")),console.log("Server: toolnet-memory")}try{he()}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exitCode=1}
|
|
32
|
+
${r}`:r}function eo(o,e,t){let r=to(o,e);if(!r)return!1;let n=o.slice(r.start,r.end);return n.includes(`command = "${q(t)}"`)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(n)&&/enabled\s*=\s*true/.test(n)}function L(o={}){let e=o.configFile??m(),t=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",r=o.serverName??"toolnet-memory",n=oo(e);if(eo(n,r,t))return{installed:!0,changed:!1,configFile:e,serverName:r,command:t,args:["mcp"]};let i=oe(n,r,t);zo(e,i);let s=oo(e);if(!eo(s,r,t))throw new Error("Grok Build MCP configuration was written but verification failed.");return{installed:!0,changed:!0,configFile:e,serverName:r,command:t,args:["mcp"]}}import{spawnSync as ee}from"node:child_process";import{existsSync as S,statSync as te}from"node:fs";import{dirname as re,join as ne,parse as ie,resolve as B}from"node:path";function ro(o){let e=B(o);if(!S(e))throw new Error(`Project path does not exist: ${e}`);if(!te(e).isDirectory())throw new Error(`Project path is not a directory: ${e}`);return e}function A(o){return ne(o,".toolnet","project.json")}function se(o){let e=B(o),t=ie(e).root;for(;;){if(S(A(e)))return e;if(e===t)return;let r=re(e);if(r===e)return;e=r}}function U(o){let e=ee("git",["rev-parse","--show-toplevel"],{cwd:o,encoding:"utf8",timeout:5e3});if(e.status!==0)return;let t=e.stdout.trim();return t?B(t):void 0}function I(o={}){let e=ro(o.cwd??process.cwd());if(o.project){let n=ro(o.project),i=A(n),s=U(n);return{root:n,source:"explicit",eligible:!0,toolnetProject:S(i),manifestFile:S(i)?i:void 0,gitRoot:s}}let t=se(e);if(t){let n=A(t);return{root:t,source:"toolnet",eligible:!0,toolnetProject:!0,manifestFile:n,gitRoot:U(t)}}let r=U(e);if(r){let n=A(r);return{root:r,source:"git",eligible:!0,toolnetProject:S(n),manifestFile:S(n)?n:void 0,gitRoot:r}}return{root:e,source:"cwd",eligible:!1,toolnetProject:!1}}function co(o,e={}){let t=[],r=o.indexOf("--scope");if(r>=0){let i=o[r+1];if(i!=="global"&&i!=="project"&&i!=="both")throw new Error(`Invalid --scope value: ${String(i)}`);t.push(i)}o.includes("--global")&&t.push("global"),o.includes("--both")&&t.push("both");let n=Array.from(new Set(t));if(n.length>1)throw new Error(`Conflicting integration scopes: ${n.join(", ")}`);return n[0]??e.defaultScope??"global"}function no(o,e){return{install:o,effective:e}}function k(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 ce(o){return{mcp:k("mcp",{globalInstall:!0,projectInstall:!1,effective:"global"}),hooks:k("hooks",{globalInstall:!0,projectInstall:!1,effective:"global"}),work:k("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 io(o){return{mcp:k("mcp",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),hooks:k("hooks",{globalInstall:!1,projectInstall:!0,effective:"project",trustRequired:!0}),work:k("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 so(o){return{mcp:k("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:k("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:k("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 E(o){let{agent:e,scope:t,project:r}=o;return(t==="project"||t==="both")&&(!r||!r.eligible)?{agent:e,requestedScope:t,project:r,surfaces:t==="both"?so(e):io(e),canInstall:!1,reason:"Project scope requires an explicit project, existing ToolNet project, or Git repository root."}:{agent:e,requestedScope:t,project:r,surfaces:t==="global"?ce(e):t==="project"?io(e):so(e),canInstall:!0}}function lo(o){return!!(o?.mcp?.changed||o?.hooks?.changed||o?.skill?.changed)}function ao(o={}){let e=o.binary??process.env.TOOLNET_MEMORY_BIN??"toolnet-memory",t=o.scope??"global",r=t==="global"?void 0:I({project:o.projectRoot}),n=E({agent:"grok",scope:t,project:r});if(!n.canInstall)throw new Error(n.reason??"Grok project integration scope cannot be resolved.");let i,s;if((n.surfaces.mcp.global.install||n.surfaces.hooks.global.install||n.surfaces.work.global.install)&&(i={},n.surfaces.mcp.global.install&&(i.mcp=L({binary:e,configFile:o.configFile??m()})),n.surfaces.hooks.global.install&&(i.hooks=J({binary:e,hooksFile:o.hooksFile??y()})),n.surfaces.work.global.install&&(i.skill=N({skillFile:o.skillFile??h()}))),n.surfaces.mcp.project.install||n.surfaces.hooks.project.install||n.surfaces.work.project.install){if(!r?.eligible)throw new Error("Grok project integration requires an eligible project root.");s={},n.surfaces.mcp.project.install&&(s.mcp=L({binary:e,configFile:o.projectConfigFile??x(r.root)})),n.surfaces.hooks.project.install&&(s.hooks=J({binary:e,hooksFile:o.projectHooksFile??C(r.root)})),n.surfaces.work.project.install&&(s.skill=N({skillFile:o.projectSkillFile??R(r.root)}))}let a=s?.mcp??i?.mcp,u=s?.hooks??i?.hooks,c=s?.skill??i?.skill;if(!a||!u||!c)throw new Error("Grok integration did not produce effective MCP/hooks/skill.");let l=Array.from(new Set([i?.mcp?.configFile,i?.hooks?.hooksFile,i?.skill?.skillFile,s?.mcp?.configFile,s?.hooks?.hooksFile,s?.skill?.skillFile].filter(g=>typeof g=="string")));return{installed:!0,changed:lo(i)||lo(s),scope:t,plan:n,project:r,global:i,projectScope:s,mcp:a,hooks:u,skill:c,files:l}}import{existsSync as Y}from"node:fs";import{existsSync as v,readFileSync as V}from"node:fs";import{homedir as le}from"node:os";import{join as K,resolve as ot}from"node:path";function uo(o={}){return o.cursorHome??K(o.home??le(),".cursor")}function go(o={}){return K(uo(o),"mcp.json")}function po(o={}){return K(uo(o),"hooks.json")}import{homedir as ae}from"node:os";import{join as G,resolve as nt}from"node:path";function fo(o={}){return o.copilotHome??process.env.COPILOT_HOME??G(o.home??ae(),".copilot")}function ko(o={}){return G(fo(o),"mcp-config.json")}function ue(o={}){return G(fo(o),"hooks")}function mo(o={}){return G(ue(o),"toolnet-memory.json")}function j(o){return typeof o=="object"&&o!==null&&!Array.isArray(o)}function w(o){if(!v(o))return{};try{let e=JSON.parse(V(o,"utf8"));return j(e)?{value:e}:{error:"root must be a JSON object"}}catch(e){return{error:e instanceof Error?e.message:String(e)}}}function yo(o,e){if(!o||!j(o.mcpServers))return!1;let t=o.mcpServers["toolnet-memory"];return!j(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 ho(o,e,t){if(!o||!j(o.hooks))return[];let r=o.hooks;return e.filter(n=>{let i=r[n];return Array.isArray(i)&&i.some(s=>j(s)&&(typeof s.command=="string"&&s.command.includes(t)||typeof s.bash=="string"&&s.bash.includes(t)))})}function ge(o,e){if(!o||!j(o.hooks))return[];let t=o.hooks;return e.filter(r=>{let n=t[r];return Array.isArray(n)&&n.some(i=>!j(i)||!Array.isArray(i.hooks)?!1:i.hooks.some(s=>j(s)&&typeof s.command=="string"&&s.command.includes("session:grok-hook")))})}function pe(o){if(!v(o))return!1;let e=V(o,"utf8"),t=/\[mcp_servers\.(?:"toolnet-memory"|'toolnet-memory'|toolnet-memory)\]/,r=e.search(t);if(r<0)return!1;let n=e.slice(r),i=n.slice(1).search(/\n\s*\[[^\]]+\]/),s=i>=0?n.slice(0,i+1):n;return/command\s*=\s*"[^"]+"/.test(s)&&/args\s*=\s*\[\s*"mcp"\s*\]/.test(s)&&!/enabled\s*=\s*false/.test(s)}function W(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),r=v(o.configFile)||v(o.hooksFile)||(o.skill?v(o.skill.skillFile):!1),n=e.length>0?"invalid":t?"ready":r?"partial":"not-installed";return{installed:t,state:n,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 z(o,e={}){if(o==="cursor"){let c=["sessionStart","beforeSubmitPrompt","preToolUse","postToolUse","afterAgentResponse","stop"],l=e.configFile??go(),g=e.hooksFile??po(),f=w(l),d=w(g),F=d.error?[]:ho(d.value,c,"session:cursor-hook");return W({mcpConfigured:!f.error&&yo(f.value,!1),configFile:l,mcpError:f.error,hooksConfigured:c.every($=>F.includes($)),hooksFile:g,events:F,hookError:d.error})}if(o==="copilot"){let c=["sessionStart","userPromptSubmitted","userPromptTransformed","preToolUse","postToolUse","agentStop"],l=e.configFile??ko(),g=e.hooksFile??mo(),f=w(l),d=w(g),F=d.error?[]:ho(d.value,c,"session:copilot-hook");return W({mcpConfigured:!f.error&&yo(f.value,!0),configFile:l,mcpError:f.error,hooksConfigured:c.every($=>F.includes($)),hooksFile:g,events:F,hookError:d.error})}let t=["SessionStart","UserPromptSubmit","PreToolUse","PostToolUse","Stop"],r=e.configFile??m(),n=e.hooksFile??y(),i=e.skillFile??h(),s=w(n),a=s.error?[]:ge(s.value,t),u=v(i)&&V(i,"utf8").includes("memory_agent_ask");return W({mcpConfigured:pe(r),configFile:r,hooksConfigured:t.every(c=>a.includes(c)),hooksFile:n,events:a,hookError:s.error,skill:{configured:u,skillFile:i}})}function fe(o,e){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)||!!(r.skill&&Y(r.skill.skillFile))))?"partial":"not-installed"}function H(o={}){let e=o.scope??"global",t=e==="global"?void 0:I({project:o.projectRoot}),r=E({agent:"grok",scope:e,project:t}),n=e==="global"||e==="both"?z("grok",{configFile:o.globalConfigFile??m(),hooksFile:o.globalHooksFile??y(),skillFile:o.globalSkillFile??h()}):void 0,i=(e==="project"||e==="both")&&t?.eligible?z("grok",{configFile:o.projectConfigFile??x(t.root),hooksFile:o.projectHooksFile??C(t.root),skillFile:o.projectSkillFile??R(t.root)}):void 0,s=e==="project"?!0:n?.installed===!0,a=e==="global"?!0:i?.installed===!0,u=r.canInstall&&s&&a,c=[];return!r.canInstall&&r.reason&&c.push(r.reason),e==="both"&&(c.push("Global + project Grok hooks are layered; ToolNet cross-process dedupe is enabled."),c.push('Project [mcp_servers."toolnet-memory"] fully replaces the same-name global server inside this project.'),c.push("Project toolnet-continuity skill shadows the same-name global skill inside this project.")),{installed:u,state:fe(u,[n,i]),requestedScope:e,plan:r,project:t,global:n,projectScope:i,effective:{mcp:r.surfaces.mcp.effective==="project"?"project":r.surfaces.mcp.effective==="global"?"global":"none",hooks:r.surfaces.hooks.effective==="both"?"both":r.surfaces.hooks.effective==="project"?"project":r.surfaces.hooks.effective==="global"?"global":"none",skill:r.surfaces.work.effective==="project"?"project":r.surfaces.work.effective==="global"?"global":"none"},dedupeReady:!0,trustRequired:e==="project"||e==="both",warnings:c}}function de(o,e){let t=o.indexOf(e);return t>=0?o[t+1]:void 0}function ke(){let o=process.argv.slice(2);return o[0]==="install"?o.slice(1):o}function me(o,e){let t=H({scope:o,projectRoot:e});console.log("Grok Build 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}`),console.log(` Skill : ${t.global.skill?.configured?"ready":"missing"} \u2014 ${t.global.skill?.skillFile??"-"}`)),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(` Skill : ${t.projectScope.skill?.configured?"ready":"missing"} \u2014 ${t.projectScope.skill?.skillFile??"-"}`),console.log(` Trust : ${t.trustRequired?"required":"n/a"}`)),console.log(""),console.log(`Effective MCP : ${t.effective.mcp}`),console.log(`Effective Hooks : ${t.effective.hooks}`),console.log(`Effective Skill : ${t.effective.skill}`),console.log(`Dedupe : ${t.dedupeReady?"ready":"missing"}`);for(let r of t.warnings)console.log(`Note : ${r}`);console.log(""),t.installed||(process.exitCode=1)}function ye(){let o=ke(),e=o.includes("--json"),t=o.includes("--status")||o[0]==="status",r=co(o),n=de(o,"--project"),i=r==="global"?void 0:I({project:n});if(t){let u=H({scope:r,projectRoot:i?.root});if(e){console.log(JSON.stringify(u,null,2)),u.installed||(process.exitCode=1);return}me(r,i?.root);return}let s=ao({scope:r,projectRoot:i?.root}),a=H({scope:r,projectRoot:i?.root});if(!a.installed)throw new Error(`Grok Build integration installation did not verify successfully (state=${a.state}).`);if(e){console.log(JSON.stringify({installed:!0,changed:s.changed,scope:s.scope,files:s.files,status:a},null,2));return}console.log("\u2705 Grok Build integration installed"),console.log(`Scope: ${r}`);for(let u of s.files)console.log(`File: ${u}`);r==="both"&&(console.log("Hook dedupe: enabled"),console.log("Project MCP precedence: project fully replaces global same-name server"),console.log("Project skill precedence: project > global"),console.log("Project trust: required by Grok Build")),console.log("Server: toolnet-memory")}try{ye()}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exitCode=1}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as u from"fs";import*as c from"path";import{existsSync as A,mkdirSync as K,readFileSync as M,renameSync as G,writeFileSync as W}from"node:fs";import{dirname as Y,join as R}from"node:path";import{createHash as B}from"node:crypto";function k(n){return B("sha256").update(n).digest("hex")}function E(n){return R(n.rootPath,".toolnet","context","handoff.md")}function C(n){return R(n.rootPath,".toolnet","context","handoff.json")}function T(n,e){K(Y(n),{recursive:!0});let t=`${n}.tmp-${process.pid}-${Date.now()}`;W(t,e.endsWith(`
|
|
2
2
|
`)?e:`${e}
|
|
3
|
-
`,{encoding:"utf8",mode:384})
|
|
4
|
-
`)}function
|
|
5
|
-
`).trim();if(!t)return null;let r={version:1,projectId:n.id,projectName:n.name,text:t,digest:
|
|
6
|
-
`)}function
|
|
7
|
-
`).trim(),r=2400,
|
|
3
|
+
`,{encoding:"utf8",mode:384}),G(t,n)}function J(n,e){T(n,`${JSON.stringify(e,null,2)}
|
|
4
|
+
`)}function O(n,e){let t=e.replace(/\r\n/g,`
|
|
5
|
+
`).trim();if(!t)return null;let r={version:1,projectId:n.id,projectName:n.name,text:t,digest:k(t),generatedAt:new Date().toISOString()};return T(E(n),t),J(C(n),r),r}function _(n){let e=E(n);if(!A(e))return null;try{let t=M(e,"utf8").trim();if(!t)return null;let r=new Date(0).toISOString(),s=C(n);if(A(s))try{let o=JSON.parse(M(s,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:n.id,projectName:n.name,text:t,digest:k(t),generatedAt:r}}catch{return null}}function I(n){let e=c.resolve(n),t=c.parse(e).root;for(;e!==t;){let r=c.join(e,".toolnet");if(u.existsSync(r)&&u.statSync(r).isDirectory())return e;e=c.dirname(e)}return null}import{existsSync as ee,readFileSync as te}from"node:fs";import{join as ne}from"node:path";import{existsSync as U,mkdirSync as Ze,readFileSync as Z,renameSync as qe,writeFileSync as Qe}from"node:fs";import{dirname as et,join as q}from"node:path";function Q(n){return q(n.rootPath,".toolnet","context","session-origin.json")}function X(n){let e=Q(n);if(!U(e))return null;try{let t=JSON.parse(Z(e,"utf8"));return t.version!==1||t.projectId!==n.id?null:t}catch{return null}}function j(n){let e=X(n);if(!e)return null;let t=["Previous session:",`- Agent: ${e.agent}`,`- Session: ${e.nativeSessionId}`];return e.currentRequest&&t.push(`- Current request: ${e.currentRequest}`),e.currentActivity&&t.push(`- Current activity: ${e.currentActivity}`),e.currentPhase&&t.push(`- Current phase: ${e.currentPhase}`),e.currentTask&&t.push(`- Current task: ${e.currentTask}`),e.lastTouchedFile&&t.push(`- Last touched file: ${e.lastTouchedFile}`),e.latestBlocker&&t.push(`- Blocker: ${e.latestBlocker}`),e.latestNextAction&&t.push(`- Next action: ${e.latestNextAction}`),e.latestDecision&&t.push(`- Important decision: ${e.latestDecision}`),t.join(`
|
|
6
|
+
`)}function re(n){let e=ne(n.rootPath,".toolnet","current.md");if(!ee(e))return null;try{return te(e,"utf8").trim()}catch{return null}}function oe(n,e){let t=e.replace(/\r\n/g,`
|
|
7
|
+
`).trim(),r=2400,s=t.length>r?`${t.slice(0,r)}
|
|
8
8
|
|
|
9
|
-
[Current work truncated for fast handoff]`:t,
|
|
10
|
-
`)}function
|
|
11
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function
|
|
12
|
-
`,{encoding:"utf8",mode:384}),
|
|
9
|
+
[Current work truncated for fast handoff]`:t,o=j(n);return["# ToolNet Fast Handoff","",`Project: ${n.name}`,"",...o?[o,""]:[],s,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
|
|
10
|
+
`)}function N(n){let e=re(n);if(e===null)return{updated:!1,reason:"missing-current",chars:0};if(!e.trim())return{updated:!1,reason:"empty-current",chars:0};let t=oe(n,e);return _(n)?.text.trim()===t.trim()?{updated:!1,reason:"unchanged",chars:t.length}:(O(n,t),{updated:!0,reason:"updated",chars:t.length})}import{existsSync as se,readFileSync as ie}from"node:fs";import{homedir as ae}from"node:os";import{join as ce}from"node:path";function ue(n){let e=n.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
|
|
11
|
+
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function de(){let n=process.env.TOOLNET_GLOBAL_ENV??ce(ae(),".config","toolnet-memory",".env");if(!se(n))return;let e=ie(n,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let o=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=ue(r.slice(s+1)))}}de();import{createHash as le}from"node:crypto";import{existsSync as m,mkdirSync as fe,readFileSync as pe,renameSync as me,writeFileSync as ge}from"node:fs";import{basename as ye,dirname as g,join as f,parse as L,resolve as d}from"node:path";var z=".toolnet",he="project.json";function xe(n){return le("sha256").update(n).digest("hex").slice(0,16)}function y(n){return f(n,z,he)}function Se(n){return m(y(n))}function P(n,e){let t=d(n),r=L(t).root;for(;;){if(Se(t))return t;if(t===r||e&&t===d(e))break;let s=g(t);if(s===t)break;t=s}return null}function D(n){let e=d(n),t=L(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>m(f(e,o))))return e;if(e===t)break;let s=g(e);if(s===e)break;e=s}return d(n)}function F(n){let e;try{e=JSON.parse(pe(n,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${n}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${n}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${n}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${n}`);let r=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:g(g(n)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,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 $(n,e){let t=f(n,z);fe(t,{recursive:!0});let r=y(n),s=`${r}.tmp-${process.pid}`;ge(s,JSON.stringify(e,null,2)+`
|
|
12
|
+
`,{encoding:"utf8",mode:384}),me(s,r)}function w(n,e){return{id:n.id,name:n.name,remote:n.remote,rootPath:e,createdAt:n.createdAt,updatedAt:n.updatedAt,graphVersion:n.graphVersion,memoryVersion:n.memoryVersion,metadata:n.metadata}}var h=class{findExisting(e=process.cwd()){let t=d(e),r=D(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>m(f(r,p))),i=P(t,o?r:void 0);if(!i)return null;let a=F(y(i));return w(a,i)}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=d(e),r=D(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(b=>m(f(r,b))),i=P(t,o?r:void 0);if(i){let b=y(i),l=F(b);return l.rootPath!==i&&(l.rootPath=i,l.updatedAt=new Date().toISOString(),$(i,l)),w(l,i)}let a=new Date().toISOString(),p=ye(r),v={version:1,id:xe(r),name:p,remote:p,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return $(r,v),w(v,r)}};var be=[{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"}],ke=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function V(n){return n.normalize("NFKC").trim().toLowerCase()}function we(n){if(n.length===0)return 0;let e=new Map;for(let r of n)e.set(r,(e.get(r)??0)+1);let t=0;for(let r of e.values()){let s=r/n.length;t-=s*Math.log2(s)}return t}function ve(n){return/^[a-f0-9]{32}$/iu.test(n)||/^[a-f0-9]{40}$/iu.test(n)||/^[a-f0-9]{64}$/iu.test(n)}function Ae(n,e,t){let r=n.slice(Math.max(0,e-48),e),s=n.slice(t,Math.min(n.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${s}`)}function Me(n,e){return n.start<e.end&&e.start<n.end}function H(n){return n.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var x=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let r=V(t);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let o of be){let i=new RegExp(o.regex.source,o.regex.flags);for(let a of e.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:o.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:o.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let r=H(t),s=[];for(let o of r)s.some(i=>Me(i,o))||s.push(o);return H(s)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=V(e);return ke.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let s of e.matchAll(r)){if(s.index===void 0||!s[0])continue;let o=s[0];this.allowed(o)||ve(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||Ae(e,s.index,s.index+o.length)&&(we(o)<3.7||t.push({type:"high_entropy_secret",value:o,start:s.index,end:s.index+o.length,confidence:"heuristic"}))}return t}};var S=class{scanner;constructor(e={}){this.scanner=new x(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let r=e,s=[...t].sort((i,a)=>a.start-i.start),o=new Set;for(let i of s)o.add(i.type),r=r.slice(0,i.start)+`[REDACTED:${i.type}]`+r.slice(i.end);return{text:r,redacted:t.length,secretTypes:[...o].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[r,s]of Object.entries(e)){let o=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")){t[r]="[REDACTED]";continue}t[r]=this.sanitizeValue(s)}return t}return e}};var wt=new S;function Re(){let n=process.cwd(),e=I(n);if(!e){console.error("Not in a ToolNet project."),process.exitCode=1;return}let t=new h().detect(e);if(!t){console.error("Unable to detect ToolNet project."),process.exitCode=1;return}let r=N(t);console.log(JSON.stringify({project:t.name,...r},null,2))}Re();
|
package/bundle/help-cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readFileSync as A}from"node:fs";import{dirname as M,resolve as w}from"node:path";import{fileURLToPath as D}from"node:url";var I={spinner:["\xB7","\u2722","\u2733","\u2736","\u273B","\u273D"],barFilled:"\u2588",barEmpty:"\u2591",phaseDone:"\u25C6",phaseActive:"\u25C7",rail:"\u2502",branch:"\u251C",corner:"\u2514",dash:"\u2014"},R={spinner:[".","*","+","x","*","+"],barFilled:"#",barEmpty:"-",phaseDone:"[OK]",phaseActive:"[>>]",rail:"|",branch:"|",corner:"\\",dash:"-"};function U(){if(process.env.TOOLNET_ASCII==="1")return!1;if(process.env.TOOLNET_UNICODE==="1")return!0;if(process.platform==="win32"){let o=process.env.TERM_PROGRAM,e=process.env.WT_SESSION,n=process.env.VSCODE_PID,t=process.env.ConEmuPID;return!!(e||n||t||o==="vscode")}return process.env.TERM!=="linux"}var h;function k(){return h||(h=U()?I:R),h}var m={reset:"\x1B[0m",green:"\x1B[32m",cyan:"\x1B[36m",red:"\x1B[31m",yellow:"\x1B[33m",amber:"\x1B[38;5;214m",white:"\x1B[97m",dim:"\x1B[2m",bold:"\x1B[1m"};function T(o){return o.noColor||process.env.NO_COLOR?!1:o.tty??process.stdout.isTTY??!1}function f(o,e,n){return T(n)?`${e}${o}${m.reset}`:o}function G(o,e){return f(o,m.dim,e)}function N(o,e){return f(o,m.bold,e)}function b(o,e){return f(o,m.cyan,e)}function g(o,e,n){let t=k(),i=e?` ${G(`v${e}`,n)}`:"";return`${b(t.phaseDone,n)} ${o}${i}`}function a(o,e){return N(o,e)}function l(o,e,n,t){let i=" ".repeat(Math.max(0,n-o.length));return` ${b(o,t)}${i} ${e}`}var u=[{name:"init",description:"Initialize current project",usage:"toolnet-memory init [path]",category:"core"},{name:"doctor",description:"Check system health",category:"core"},{name:"ask",description:"Ask project memory",usage:"toolnet-memory ask <question>",category:"memory"},{name:"context",description:"Show current project context",category:"memory",aliases:["context:print"]},{name:"work",description:"Show current work state",category:"memory",aliases:["work:status"]},{name:"index",description:"Build code intelligence",category:"code",pipeline:["Scanning files","Parsing code","Type Resolution","Rich Graph","Semantic Code Index","Architecture Intelligence","Graph Analysis","3D Visualization Dataset"]},{name:"semantic",description:"Semantic code search",usage:"toolnet-memory semantic <query>",category:"code"},{name:"impact",description:"Analyze change impact",usage:"toolnet-memory impact <file>",category:"code"},{name:"graph",description:"Open code graph UI",category:"code"},{name:"graph:ui",description:"Open code graph UI",category:"code",hidden:!0},{name:"status",description:"Show ToolNet status",category:"system"},{name:"update",description:"Update ToolNet Memory",category:"system"},{name:"context:print",description:"Print fast project context",category:"context",hidden:!0},{name:"context:sync",description:"Show context hash/size",category:"context"},{name:"context:refresh",description:"Rebuild deep startup brief cache",category:"context"},{name:"brief",description:"Show full project brief",category:"context"},{name:"brief:json",description:"Show brief as JSON",category:"context"},{name:"profile:show",description:"Show .toolnet/profile.md",category:"context"},{name:"profile:sync",description:"Sync profile to agent files",category:"context"},{name:"work:status",description:"Show current work state",category:"work",hidden:!0},{name:"work:json",description:"Show work state as JSON",category:"work"},{name:"work:reconcile",description:"Reconcile work continuity",category:"work"},{name:"handoff:latest",description:"Show latest session handoff",category:"work"},{name:"handoff:refresh",description:"Refresh handoff data",category:"work"},{name:"index:graph",description:"Build graph index only",category:"code"},{name:"incremental",description:"Incremental code indexing",category:"code"},{name:"config",description:"Manage configuration",usage:"toolnet-memory config <get|set|list|open>",category:"system"},{name:"integrate:detect",description:"Detect agent integrations",category:"integration"},{name:"integrate:auto",description:"Auto-enable integrations with safe project scope policy",usage:"toolnet-memory integrate:auto [--all] [--scope global|project|both] [--project <path>] [--json]",category:"integration",examples:["toolnet-memory integrate:auto","toolnet-memory integrate:auto --project /path/to/toolnet-project","toolnet-memory integrate:auto --scope global","toolnet-memory integrate:auto --scope both --project /path/to/project"]},{name:"integrate:agy",description:"Install Agy hooks",category:"integration"},{name:"integrate:codex",description:"Install Codex integration",category:"integration"},{name:"integrate:opencode",description:"Install OpenCode plugin",category:"integration"},{name:"integrate:claude",description:"Install Claude Code integration",category:"integration"},{name:"integrate:kiro",description:"Install Kiro CLI integration",usage:"toolnet-memory integrate:kiro [--status] [--json]",category:"integration"},{name:"integrate:cursor",description:"Install Cursor CLI integration",usage:"toolnet-memory integrate:cursor [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:cursor --scope global","toolnet-memory integrate:cursor --scope project --project /path/to/project","toolnet-memory integrate:cursor --scope both --project /path/to/project"]},{name:"integrate:copilot",description:"Install GitHub Copilot CLI integration",usage:"toolnet-memory integrate:copilot [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:copilot --scope global","toolnet-memory integrate:copilot --scope project --project /path/to/project","toolnet-memory integrate:copilot --scope both --project /path/to/project"]},{name:"integrate:grok",description:"Install Grok Build integration",usage:"toolnet-memory integrate:grok [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:grok --scope global","toolnet-memory integrate:grok --scope project --project /path/to/project","toolnet-memory integrate:grok --scope both --project /path/to/project"]},{name:"integrate:toolnet-cli",description:"Install ToolNet CLI MCP integration",usage:"toolnet-memory integrate:toolnet-cli [--status] [--json] [--force]",category:"integration",examples:["toolnet-memory integrate:toolnet-cli","toolnet-memory integrate:toolnet-cli --status"]},{name:"integrate:kilo",description:"Install Kilo CLI MCP integration",usage:"toolnet-memory integrate:kilo [--status] [--json] [--force]",category:"integration",examples:["toolnet-memory integrate:kilo","toolnet-memory integrate:kilo --status"]},{name:"integrate:all",description:"Auto-enable all detected integrations",usage:"toolnet-memory integrate:all [--json]",category:"integration"},{name:"integrate:status",description:"Show unified Cursor/Copilot/Grok scoped integration status",usage:"toolnet-memory integrate:status [--scope global|project|both] [--project <path>] [--agent cursor|copilot|grok] [--json]",category:"integration",examples:["toolnet-memory integrate:status --scope global","toolnet-memory integrate:status --scope both --project /path/to/project","toolnet-memory integrate:status --scope both --project /path/to/project --agent cursor"]},{name:"session:agy-sync",description:"Sync Agy session",category:"session"},{name:"session:agy-recover",description:"Recover Agy sessions",category:"session"},{name:"session:agy-hook",description:"Agy session hook",category:"session",hidden:!0},{name:"session:codex-sync",description:"Sync Codex session",category:"session"},{name:"session:codex-recover",description:"Recover Codex sessions",category:"session"},{name:"session:codex-notify",description:"Codex notification hook",category:"session",hidden:!0},{name:"session:codex-context",description:"Codex context hook",category:"session",hidden:!0},{name:"session:opencode-sync",description:"Sync OpenCode session",category:"session"},{name:"session:opencode-recover",description:"Recover OpenCode sessions",category:"session"},{name:"session:claude-hook",description:"Claude session hook",category:"session",hidden:!0},{name:"session:kiro-hook",description:"Kiro lifecycle hook",category:"session",hidden:!0},{name:"session:cursor-hook",description:"Cursor lifecycle hook",category:"session",hidden:!0},{name:"session:copilot-hook",description:"Copilot lifecycle hook",category:"session",hidden:!0},{name:"session:grok-hook",description:"Grok lifecycle hook",category:"session",hidden:!0},{name:"memory:review",description:"Review memory entries",category:"session"},{name:"memory:reconcile",description:"Reconcile memory state",category:"session"},{name:"guard:check",description:"Check project rules",category:"guard"},{name:"guard:explain",description:"Show rules and evidence",category:"guard"},{name:"guard:json",description:"Output guard result as JSON",category:"guard",hidden:!0},{name:"project:manual-init",description:"Initialize project manual",category:"project"},{name:"project:manual-show",description:"Show project manual",category:"project"},{name:"project:manual-sync",description:"Sync project manual",category:"project"},{name:"snapshot:list",description:"List snapshots",category:"snapshot"},{name:"snapshot:create",description:"Create snapshot",category:"snapshot"},{name:"snapshot:restore",description:"Restore snapshot",category:"snapshot"},{name:"recover",description:"Recover latest snapshot",category:"snapshot"},{name:"service",description:"Run daemon in foreground",category:"service"},{name:"service:install",description:"Install/start daemon",category:"service"},{name:"service:start",description:"Start daemon",category:"service"},{name:"service:stop",description:"Stop daemon",category:"service"},{name:"service:restart",description:"Restart daemon",category:"service"},{name:"service:status",description:"Show daemon status",category:"service"},{name:"service:remove",description:"Remove daemon",category:"service"},{name:"mcp",description:"Run MCP server",category:"advanced"},{name:"api",description:"Run API server",category:"advanced"},{name:"run",description:"Run ToolNet runtime",category:"advanced",hidden:!0},{name:"production:certify",description:"Verify production runtime",category:"advanced"},{name:"certify:continuity",description:"Certify work continuity",category:"advanced"}];function x(o){return{tty:o.tty,noColor:o.noColor}}function O(o){let e=[],n=o.version??"0.0.0",t=x(o);e.push(""),e.push(g("ToolNet Memory",n,t)),e.push(" Persistent memory & code intelligence for AI coding agents"),e.push(""),e.push(a("USAGE",t)),e.push(" toolnet-memory <command> [options]"),e.push("");let i=[{key:"core",title:"GET STARTED"},{key:"memory",title:"MEMORY"},{key:"code",title:"CODE"},{key:"system",title:"SYSTEM"}];for(let{key:s,title:d}of i){let c=u.filter(r=>r.category===s&&!r.hidden);if(c.length===0)continue;e.push(a(d,t));let y=Math.max(...c.map(r=>r.name.length));for(let r of c)e.push(l(r.name,r.description,y,t));e.push("")}return e.push(a("MORE",t)),e.push(l("help --all","Show all advanced commands",15,t)),e.push(l("help <command>","Show command details",15,t)),e.push(""),e.join(`
|
|
2
|
-
`)}function
|
|
3
|
-
`)}function
|
|
4
|
-
`)}function
|
|
1
|
+
import{readFileSync as A}from"node:fs";import{dirname as M,resolve as w}from"node:path";import{fileURLToPath as D}from"node:url";var I={spinner:["\xB7","\u2722","\u2733","\u2736","\u273B","\u273D"],barFilled:"\u2588",barEmpty:"\u2591",phaseDone:"\u25C6",phaseActive:"\u25C7",rail:"\u2502",branch:"\u251C",corner:"\u2514",dash:"\u2014"},R={spinner:[".","*","+","x","*","+"],barFilled:"#",barEmpty:"-",phaseDone:"[OK]",phaseActive:"[>>]",rail:"|",branch:"|",corner:"\\",dash:"-"};function U(){if(process.env.TOOLNET_ASCII==="1")return!1;if(process.env.TOOLNET_UNICODE==="1")return!0;if(process.platform==="win32"){let o=process.env.TERM_PROGRAM,e=process.env.WT_SESSION,n=process.env.VSCODE_PID,t=process.env.ConEmuPID;return!!(e||n||t||o==="vscode")}return process.env.TERM!=="linux"}var h;function k(){return h||(h=U()?I:R),h}var m={reset:"\x1B[0m",green:"\x1B[32m",cyan:"\x1B[36m",red:"\x1B[31m",yellow:"\x1B[33m",amber:"\x1B[38;5;214m",white:"\x1B[97m",dim:"\x1B[2m",bold:"\x1B[1m"};function N(o){return o.noColor||process.env.NO_COLOR?!1:o.tty??process.stdout.isTTY??!1}function f(o,e,n){return N(n)?`${e}${o}${m.reset}`:o}function T(o,e){return f(o,m.dim,e)}function G(o,e){return f(o,m.bold,e)}function b(o,e){return f(o,m.cyan,e)}function g(o,e,n){let t=k(),i=e?` ${T(`v${e}`,n)}`:"";return`${b(t.phaseDone,n)} ${o}${i}`}function a(o,e){return G(o,e)}function l(o,e,n,t){let i=" ".repeat(Math.max(0,n-o.length));return` ${b(o,t)}${i} ${e}`}var u=[{name:"init",description:"Initialize current project",usage:"toolnet-memory init [path]",category:"core"},{name:"doctor",description:"Check system health",category:"core"},{name:"ask",description:"Ask project memory",usage:"toolnet-memory ask <question>",category:"memory"},{name:"context",description:"Show current project context",category:"memory",aliases:["context:print"]},{name:"work",description:"Show current work state",category:"memory",aliases:["work:status"]},{name:"index",description:"Build code intelligence",category:"code",pipeline:["Scanning files","Parsing code","Type Resolution","Rich Graph","Semantic Code Index","Architecture Intelligence","Graph Analysis","3D Visualization Dataset"]},{name:"semantic",description:"Semantic code search",usage:"toolnet-memory semantic <query>",category:"code"},{name:"impact",description:"Analyze change impact",usage:"toolnet-memory impact <file>",category:"code"},{name:"graph",description:"Open code graph UI",category:"code"},{name:"graph:ui",description:"Open code graph UI",category:"code",hidden:!0},{name:"status",description:"Show ToolNet status",category:"system"},{name:"gc",description:"Plan or apply safe retention cleanup",usage:"toolnet-memory gc [--dry-run|--apply] [--remote] [--keep-snapshots N] [--snapshot-days N] [--runtime-days N] [--stale-lock-minutes N] [--project PATH] [--json]",category:"system",examples:["toolnet-memory gc","toolnet-memory gc --remote --dry-run","toolnet-memory gc --apply","toolnet-memory gc --remote --apply --keep-snapshots 10"]},{name:"update",description:"Update ToolNet Memory",category:"system"},{name:"context:print",description:"Print fast project context",category:"context",hidden:!0},{name:"context:sync",description:"Show context hash/size",category:"context"},{name:"context:refresh",description:"Rebuild deep startup brief cache",category:"context"},{name:"brief",description:"Show full project brief",category:"context"},{name:"brief:json",description:"Show brief as JSON",category:"context"},{name:"profile:show",description:"Show .toolnet/profile.md",category:"context"},{name:"profile:sync",description:"Sync profile to agent files",category:"context"},{name:"work:status",description:"Show current work state",category:"work",hidden:!0},{name:"work:json",description:"Show work state as JSON",category:"work"},{name:"work:reconcile",description:"Reconcile work continuity",category:"work"},{name:"handoff:latest",description:"Show latest session handoff",category:"work"},{name:"handoff:refresh",description:"Refresh handoff data",category:"work"},{name:"index:graph",description:"Build graph index only",category:"code"},{name:"incremental",description:"Incremental code indexing",category:"code"},{name:"config",description:"Manage configuration",usage:"toolnet-memory config <get|set|list|open>",category:"system"},{name:"integrate:detect",description:"Detect agent integrations",category:"integration"},{name:"integrate:auto",description:"Auto-enable integrations with safe project scope policy",usage:"toolnet-memory integrate:auto [--all] [--scope global|project|both] [--project <path>] [--json]",category:"integration",examples:["toolnet-memory integrate:auto","toolnet-memory integrate:auto --project /path/to/toolnet-project","toolnet-memory integrate:auto --scope global","toolnet-memory integrate:auto --scope both --project /path/to/project"]},{name:"integrate:agy",description:"Install Agy hooks",category:"integration"},{name:"integrate:codex",description:"Install Codex integration",category:"integration"},{name:"integrate:opencode",description:"Install OpenCode plugin",category:"integration"},{name:"integrate:claude",description:"Install Claude Code integration",category:"integration"},{name:"integrate:kiro",description:"Install Kiro CLI integration",usage:"toolnet-memory integrate:kiro [--status] [--json]",category:"integration"},{name:"integrate:cursor",description:"Install Cursor CLI integration",usage:"toolnet-memory integrate:cursor [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:cursor --scope global","toolnet-memory integrate:cursor --scope project --project /path/to/project","toolnet-memory integrate:cursor --scope both --project /path/to/project"]},{name:"integrate:copilot",description:"Install GitHub Copilot CLI integration",usage:"toolnet-memory integrate:copilot [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:copilot --scope global","toolnet-memory integrate:copilot --scope project --project /path/to/project","toolnet-memory integrate:copilot --scope both --project /path/to/project"]},{name:"integrate:grok",description:"Install Grok Build integration",usage:"toolnet-memory integrate:grok [--scope global|project|both] [--project <path>] [--status] [--json]",category:"integration",examples:["toolnet-memory integrate:grok --scope global","toolnet-memory integrate:grok --scope project --project /path/to/project","toolnet-memory integrate:grok --scope both --project /path/to/project"]},{name:"integrate:toolnet-cli",description:"Install ToolNet CLI MCP integration",usage:"toolnet-memory integrate:toolnet-cli [--status] [--json] [--force]",category:"integration",examples:["toolnet-memory integrate:toolnet-cli","toolnet-memory integrate:toolnet-cli --status"]},{name:"integrate:kilo",description:"Install Kilo CLI MCP integration",usage:"toolnet-memory integrate:kilo [--status] [--json] [--force]",category:"integration",examples:["toolnet-memory integrate:kilo","toolnet-memory integrate:kilo --status"]},{name:"integrate:all",description:"Auto-enable all detected integrations",usage:"toolnet-memory integrate:all [--json]",category:"integration"},{name:"integrate:status",description:"Show unified Cursor/Copilot/Grok scoped integration status",usage:"toolnet-memory integrate:status [--scope global|project|both] [--project <path>] [--agent cursor|copilot|grok] [--json]",category:"integration",examples:["toolnet-memory integrate:status --scope global","toolnet-memory integrate:status --scope both --project /path/to/project","toolnet-memory integrate:status --scope both --project /path/to/project --agent cursor"]},{name:"session:agy-sync",description:"Sync Agy session",category:"session"},{name:"session:agy-recover",description:"Recover Agy sessions",category:"session"},{name:"session:agy-hook",description:"Agy session hook",category:"session",hidden:!0},{name:"session:codex-sync",description:"Sync Codex session",category:"session"},{name:"session:codex-recover",description:"Recover Codex sessions",category:"session"},{name:"session:codex-notify",description:"Codex notification hook",category:"session",hidden:!0},{name:"session:codex-context",description:"Codex context hook",category:"session",hidden:!0},{name:"session:opencode-sync",description:"Sync OpenCode session",category:"session"},{name:"session:opencode-recover",description:"Recover OpenCode sessions",category:"session"},{name:"session:claude-hook",description:"Claude session hook",category:"session",hidden:!0},{name:"session:kiro-hook",description:"Kiro lifecycle hook",category:"session",hidden:!0},{name:"session:cursor-hook",description:"Cursor lifecycle hook",category:"session",hidden:!0},{name:"session:copilot-hook",description:"Copilot lifecycle hook",category:"session",hidden:!0},{name:"session:grok-hook",description:"Grok lifecycle hook",category:"session",hidden:!0},{name:"memory:review",description:"Review memory entries",category:"session"},{name:"memory:reconcile",description:"Reconcile memory state",category:"session"},{name:"guard:check",description:"Check project rules",category:"guard"},{name:"guard:explain",description:"Show rules and evidence",category:"guard"},{name:"guard:json",description:"Output guard result as JSON",category:"guard",hidden:!0},{name:"project:manual-init",description:"Initialize project manual",category:"project"},{name:"project:manual-show",description:"Show project manual",category:"project"},{name:"project:manual-sync",description:"Sync project manual",category:"project"},{name:"snapshot:list",description:"List snapshots",category:"snapshot"},{name:"snapshot:create",description:"Create snapshot",category:"snapshot"},{name:"snapshot:restore",description:"Restore snapshot",category:"snapshot"},{name:"recover",description:"Recover latest snapshot",category:"snapshot"},{name:"service",description:"Run daemon in foreground",category:"service"},{name:"service:install",description:"Install/start daemon",category:"service"},{name:"service:start",description:"Start daemon",category:"service"},{name:"service:stop",description:"Stop daemon",category:"service"},{name:"service:restart",description:"Restart daemon",category:"service"},{name:"service:status",description:"Show daemon status",category:"service"},{name:"service:remove",description:"Remove daemon",category:"service"},{name:"mcp",description:"Run MCP server",category:"advanced"},{name:"api",description:"Run API server",category:"advanced"},{name:"run",description:"Run ToolNet runtime",category:"advanced",hidden:!0},{name:"production:certify",description:"Verify production runtime",category:"advanced"},{name:"certify:continuity",description:"Certify work continuity",category:"advanced"}];function x(o){return{tty:o.tty,noColor:o.noColor}}function O(o){let e=[],n=o.version??"0.0.0",t=x(o);e.push(""),e.push(g("ToolNet Memory",n,t)),e.push(" Persistent memory & code intelligence for AI coding agents"),e.push(""),e.push(a("USAGE",t)),e.push(" toolnet-memory <command> [options]"),e.push("");let i=[{key:"core",title:"GET STARTED"},{key:"memory",title:"MEMORY"},{key:"code",title:"CODE"},{key:"system",title:"SYSTEM"}];for(let{key:s,title:d}of i){let c=u.filter(r=>r.category===s&&!r.hidden);if(c.length===0)continue;e.push(a(d,t));let y=Math.max(...c.map(r=>r.name.length));for(let r of c)e.push(l(r.name,r.description,y,t));e.push("")}return e.push(a("MORE",t)),e.push(l("help --all","Show all advanced commands",15,t)),e.push(l("help <command>","Show command details",15,t)),e.push(""),e.join(`
|
|
2
|
+
`)}function j(o){let e=[],n=o.version??"0.0.0",t=x(o);e.push(""),e.push(g("ToolNet Memory",n,t)),e.push(" Persistent memory & code intelligence for AI coding agents"),e.push(""),e.push(a("USAGE",t)),e.push(" toolnet-memory <command> [options]"),e.push("");let i=[{key:"core",title:"PROJECT SETUP"},{key:"memory",title:"MEMORY"},{key:"code",title:"CODE INTELLIGENCE"},{key:"system",title:"SYSTEM"},{key:"context",title:"CONTEXT & MEMORY"},{key:"work",title:"WORK CONTINUITY"},{key:"integration",title:"AGENT INTEGRATIONS"},{key:"session",title:"SESSIONS"},{key:"guard",title:"GUARD"},{key:"project",title:"PROJECT MANUAL"},{key:"snapshot",title:"SNAPSHOTS & RECOVERY"},{key:"service",title:"BACKGROUND SERVICE"},{key:"advanced",title:"DEVELOPER / PRODUCTION"}];for(let{key:s,title:d}of i){let c=u.filter(r=>r.category===s&&!r.hidden);if(c.length===0)continue;e.push(a(d,t));let y=Math.max(...c.map(r=>r.name.length));for(let r of c)e.push(l(r.name,r.description,y,t));e.push("")}return e.join(`
|
|
3
|
+
`)}function v(o,e){let n=u.find(s=>s.name===o||s.aliases?.includes(o));if(!n)return null;let t=[],i=x(e);if(t.push(""),t.push(g(n.name,void 0,i)),t.push(""),t.push(n.description),t.push(""),n.usage&&(t.push(a("USAGE",i)),t.push(` ${n.usage}`),t.push("")),n.aliases&&n.aliases.length>0){t.push(a("ALIASES",i));for(let s of n.aliases)t.push(` ${s}`);t.push("")}if(n.pipeline&&n.pipeline.length>0){t.push(a("PIPELINE",i));for(let s of n.pipeline)t.push(` ${s}`);t.push("")}if(n.examples&&n.examples.length>0){t.push(a("EXAMPLES",i));for(let s of n.examples)t.push(` ${s}`);t.push("")}return t.join(`
|
|
4
|
+
`)}function S(o){return u.flatMap(t=>[t.name,...t.aliases??[]]).filter(t=>t===o?!1:!!(t.startsWith(o)||o.length>=3&&t.includes(o))).slice(0,3)}function P(){let o=M(D(import.meta.url)),e=[w(o,"../package.json"),w(o,"../../package.json")];for(let n of e)try{let t=JSON.parse(A(n,"utf8"));if(t.version)return t.version}catch{}return process.env.npm_package_version??"unknown"}var p=process.argv.slice(2),C={version:P(),tty:!!process.stdout.isTTY};function E(o){let e=S(o);if(console.error(""),console.error(`\u2715 Unknown command: ${o}`),e.length>0){console.error(""),console.error(" Did you mean:");for(let n of e)console.error(` ${n}`)}console.error(""),console.error(" Run `toolnet-memory help` to see available commands."),console.error("")}if(p[0]==="--unknown")E(p[1]??""),process.exitCode=1;else if(p[0]==="--all")console.log(j(C));else if(p[0]){let o=v(p[0],C);o?console.log(o):(E(p[0]),process.exitCode=1)}else console.log(O(C));
|
package/bundle/impact.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"dotenv/config";import{existsSync as
|
|
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
|
|
3
|
-
`,{encoding:"utf8",mode:384}),ue(o,r)}function K(s,e){return{id:s.id,name:s.name,remote:s.remote,rootPath:e,createdAt:s.createdAt,updatedAt:s.updatedAt,graphVersion:s.graphVersion,memoryVersion:s.memoryVersion,metadata:s.metadata}}var k=class{detect(e=process.cwd()){let t=b(e),r=be(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>O(P(r,d))),i=Se(t,n?r:void 0);if(i){let d=_(i),m=Ce(d);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),G(i,m)),K(m,i)}let p=new Date().toISOString(),l=me(r),c={version:1,id:he(r),name:l,remote:l,rootPath:r,createdAt:p,updatedAt:p,graphVersion:0,memoryVersion:0};return G(r,c),K(c,r)}};import{homedir as We}from"node:os";import{join as Ue}from"node:path";import{DeleteObjectCommand as Ee,GetObjectCommand as we,HeadObjectCommand as ve,ListObjectsV2Command as ke,PutObjectCommand as Pe,S3Client as Re}from"@aws-sdk/client-s3";import{getSignedUrl as Te}from"@aws-sdk/s3-request-presigner";var R=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Re({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,r="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Pe({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await Te(this.client,new we({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(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 ve({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 Ee({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new ke({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};import{access as W,mkdir as Me,readFile as Ae,readdir as je,rm as Le,stat as U,writeFile as Ne}from"node:fs/promises";import{dirname as Ie,join as Oe,relative as H,resolve as _e}from"node:path";var C=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return _e(this.root,t)}async put(e,t){let r=this.path(e);await Me(Ie(r),{recursive:!0}),await Ne(r,t)}async get(e){try{return await Ae(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 W(this.path(e)),!0}catch{return!1}}async delete(e){await Le(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await W(t)}catch{return r}let o=async i=>{let p=await je(i,{withFileTypes:!0});for(let l of p){let c=Oe(i,l.name);if(l.isDirectory()){await o(c);continue}let d=await U(c);r.push({key:H(this.root,c),size:d.size,updatedAt:d.mtime.toISOString()})}},n=await U(t);return n.isDirectory()?await o(t):r.push({key:H(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};import{DeleteObjectCommand as Fe,GetObjectCommand as De,HeadObjectCommand as $e,ListObjectsV2Command as Ge,PutObjectCommand as Ke,S3Client as ze}from"@aws-sdk/client-s3";import{getSignedUrl as Be}from"@aws-sdk/s3-request-presigner";var x=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new ze({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,r="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ke({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await Be(this.client,new De({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(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 $e({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 Fe({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new Ge({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};function F(s,e){return console.warn(e),new C(s)}function V(s){let e=s.localRoot??Ue(We(),".toolnet-memory","storage");if(s.provider==="r2"){let t=s.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new x({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):F(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(s.provider==="s3"){let t=s.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new x({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):F(e,"[storage] S3 credentials missing. Using local fallback.")}if(s.provider==="huggingface"){let t=s.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new R({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):F(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new C(e)}var E=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function He(s){return new Promise(e=>setTimeout(e,s))}async function Y(s,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,o=e.maxDelayMs??2e3,n;for(let i=1;i<=t;i++)try{return await s()}catch(p){if(n=p,i>=t)break;let l=Math.min(o,r*2**(i-1)),c=Math.floor(Math.random()*Math.max(1,l*.2));await He(l+c)}throw n}var Ve=new Set(["put","get","getText","delete","list"]);function J(s,e={}){return new Proxy(s,{get(t,r){let o=Reflect.get(t,r,t);return typeof o!="function"?o:Ve.has(r)?(...n)=>Y(()=>Promise.resolve(o.apply(t,n)),e):o.bind(t)}})}function q(s){let e=s.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 Q(s){let e=s.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 r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let o=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:e))}var T=class{constructor(e,t,r,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=q(o??r),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(),r=t,o=await this.provider.getText(e);if(o){let i;try{i=JSON.parse(o)}catch(p){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${p instanceof Error?p.message:String(p)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let n={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(n,null,2)+`
|
|
4
|
-
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=
|
|
1
|
+
import"dotenv/config";import{existsSync as ue,readFileSync as fe}from"node:fs";import{homedir as me}from"node:os";import{join as ge}from"node:path";function he(s){let e=s.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 ye(){let s=process.env.TOOLNET_GLOBAL_ENV??ge(me(),".config","toolnet-memory",".env");if(!ue(s))return;let e=fe(s,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let n=r.indexOf("=");if(n<=0)continue;let o=r.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=he(r.slice(n+1)))}}ye();function S(s,e){return s===void 0?e:["1","true","yes","on"].includes(s.toLowerCase())}function b(s,e){if(!s)return e;let t=Number(s);return Number.isFinite(t)?t:e}function B(){return{memory:{autoCapture:S(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:S(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:S(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:S(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:b(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:b(process.env.MEMORY_RERANK_TOP,10),finalContext:b(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:b(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:S(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:b(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Se}from"node:crypto";import{existsSync as R,mkdirSync as be,readFileSync as xe,renameSync as Ce,writeFileSync as Ee}from"node:fs";import{basename as we,dirname as T,join as x,parse as Y,resolve as y}from"node:path";var J=".toolnet",ve="project.json";function ke(s){return Se("sha256").update(s).digest("hex").slice(0,16)}function M(s){return x(s,J,ve)}function Pe(s){return R(M(s))}function W(s,e){let t=y(s),r=Y(t).root;for(;;){if(Pe(t))return t;if(t===r||e&&t===y(e))break;let n=T(t);if(n===t)break;t=n}return null}function U(s){let e=y(s),t=Y(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>R(x(e,o))))return e;if(e===t)break;let n=T(e);if(n===e)break;e=n}return y(s)}function H(s){let e;try{e=JSON.parse(xe(s,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${s}: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${s}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${s}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${s}`);let r=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:T(T(s)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,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 V(s,e){let t=x(s,J);be(t,{recursive:!0});let r=M(s),n=`${r}.tmp-${process.pid}`;Ee(n,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),Ce(n,r)}function G(s,e){return{id:s.id,name:s.name,remote:s.remote,rootPath:e,createdAt:s.createdAt,updatedAt:s.updatedAt,graphVersion:s.graphVersion,memoryVersion:s.memoryVersion,metadata:s.metadata}}var A=class{findExisting(e=process.cwd()){let t=y(e),r=U(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>R(x(r,d))),i=W(t,o?r:void 0);if(!i)return null;let a=H(M(i));return G(a,i)}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=y(e),r=U(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>R(x(r,p))),i=W(t,o?r:void 0);if(i){let p=M(i),m=H(p);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),V(i,m)),G(m,i)}let a=new Date().toISOString(),d=we(r),l={version:1,id:ke(r),name:d,remote:d,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return V(r,l),G(l,r)}};var Re=[{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"}],Te=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function q(s){return s.normalize("NFKC").trim().toLowerCase()}function Me(s){if(s.length===0)return 0;let e=new Map;for(let r of s)e.set(r,(e.get(r)??0)+1);let t=0;for(let r of e.values()){let n=r/s.length;t-=n*Math.log2(n)}return t}function Ae(s){return/^[a-f0-9]{32}$/iu.test(s)||/^[a-f0-9]{40}$/iu.test(s)||/^[a-f0-9]{64}$/iu.test(s)}function je(s,e,t){let r=s.slice(Math.max(0,e-48),e),n=s.slice(t,Math.min(s.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${n}`)}function Ie(s,e){return s.start<e.end&&e.start<s.end}function Z(s){return s.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var j=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let r=q(t);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let o of Re){let i=new RegExp(o.regex.source,o.regex.flags);for(let a of e.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:o.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:o.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let r=Z(t),n=[];for(let o of r)n.some(i=>Ie(i,o))||n.push(o);return Z(n)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=q(e);return Te.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let n of e.matchAll(r)){if(n.index===void 0||!n[0])continue;let o=n[0];this.allowed(o)||Ae(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||je(e,n.index,n.index+o.length)&&(Me(o)<3.7||t.push({type:"high_entropy_secret",value:o,start:n.index,end:n.index+o.length,confidence:"heuristic"}))}return t}};var C=class{scanner;constructor(e={}){this.scanner=new j(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let r=e,n=[...t].sort((i,a)=>a.start-i.start),o=new Set;for(let i of n)o.add(i.type),r=r.slice(0,i.start)+`[REDACTED:${i.type}]`+r.slice(i.end);return{text:r,redacted:t.length,secretTypes:[...o].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[r,n]of Object.entries(e)){let o=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")){t[r]="[REDACTED]";continue}t[r]=this.sanitizeValue(n)}return t}return e}};var Lt=new C;import{homedir as tt}from"node:os";import{join as rt}from"node:path";import{DeleteObjectCommand as Le,GetObjectCommand as Ne,HeadObjectCommand as Oe,ListObjectsV2Command as _e,PutObjectCommand as Fe,S3Client as De}from"@aws-sdk/client-s3";import{getSignedUrl as $e}from"@aws-sdk/s3-request-presigner";var I=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new De({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,r="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Fe({Bucket:this.bucket,Key:e,Body:n,ContentType:r}))}async get(e){let t=await $e(this.client,new Ne({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(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 Oe({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 Le({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let n=await this.client.send(new _e({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of n.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=n.IsTruncated?n.NextContinuationToken:void 0}while(r);return t}};import{access as Q,mkdir as Ge,readFile as ze,readdir as Ke,rm as Be,stat as X,writeFile as We}from"node:fs/promises";import{dirname as Ue,join as He,relative as ee,resolve as Ve}from"node:path";var E=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Ve(this.root,t)}async put(e,t){let r=this.path(e);await Ge(Ue(r),{recursive:!0}),await We(r,t)}async get(e){try{return await ze(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 Q(this.path(e)),!0}catch{return!1}}async delete(e){await Be(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await Q(t)}catch{return r}let n=async i=>{let a=await Ke(i,{withFileTypes:!0});for(let d of a){let l=He(i,d.name);if(d.isDirectory()){await n(l);continue}let p=await X(l);r.push({key:ee(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await X(t);return o.isDirectory()?await n(t):r.push({key:ee(this.root,t),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Ye,GetObjectCommand as Je,HeadObjectCommand as qe,ListObjectsV2Command as Ze,PutObjectCommand as Qe,S3Client as Xe}from"@aws-sdk/client-s3";import{getSignedUrl as et}from"@aws-sdk/s3-request-presigner";var w=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Xe({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,r="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Qe({Bucket:this.bucket,Key:e,Body:n,ContentType:r}))}async get(e){let t=await et(this.client,new Je({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(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=[],r;do{let n=await this.client.send(new Ze({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of n.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=n.IsTruncated?n.NextContinuationToken:void 0}while(r);return t}};function z(s,e){return console.warn(e),new E(s)}function te(s){let e=s.localRoot??rt(tt(),".toolnet-memory","storage");if(s.provider==="r2"){let t=s.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new w({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):z(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(s.provider==="s3"){let t=s.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new w({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):z(e,"[storage] S3 credentials missing. Using local fallback.")}if(s.provider==="huggingface"){let t=s.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new I({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):z(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new E(e)}var v=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function st(s){return new Promise(e=>setTimeout(e,s))}async function re(s,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,n=e.maxDelayMs??2e3,o;for(let i=1;i<=t;i++)try{return await s()}catch(a){if(o=a,i>=t)break;let d=Math.min(n,r*2**(i-1)),l=Math.floor(Math.random()*Math.max(1,d*.2));await st(d+l)}throw o}var nt=new Set(["put","get","getText","delete","list"]);function se(s,e={}){return new Proxy(s,{get(t,r){let n=Reflect.get(t,r,t);return typeof n!="function"?n:nt.has(r)?(...o)=>re(()=>Promise.resolve(n.apply(t,o)),e):n.bind(t)}})}function ne(s){let e=s.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 oe(s){let e=s.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 r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[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 L=class{constructor(e,t,r,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=ne(n??r),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(),r=t,n=await this.provider.getText(e);if(n){let i;try{i=JSON.parse(n)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(o,null,2)+`
|
|
4
|
+
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=oe(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,r){return await this.ensureRegistered(),this.provider.put(this.key(e),t,r)}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))}};var bs=2*1024*1024;var k=class{symbols=new Map;edges=new Map;addSymbol(e){this.symbols.set(e.id,e)}addEdge(e){this.edges.set(e.id,e)}getSymbol(e){return this.symbols.get(e)}findByName(e,t){return[...this.symbols.values()].filter(r=>r.projectId===e&&(r.name===t||r.qualifiedName===t))}allSymbols(e){return[...this.symbols.values()].filter(t=>t.projectId===e)}allEdges(e){return[...this.edges.values()].filter(t=>t.projectId===e)}import(e,t){for(let r of e)this.addSymbol(r);for(let r of t)this.addEdge(r)}clearProject(e){for(let[t,r]of this.symbols)r.projectId===e&&this.symbols.delete(t);for(let[t,r]of this.edges)r.projectId===e&&this.edges.delete(t)}};import*as u from"typescript";function ct(s,e){return e.ranges.length===0?!0:typeof s.startLine!="number"||typeof s.endLine!="number"?!1:e.ranges.some(t=>s.startLine<=t.endLine&&s.endLine>=t.startLine)}var N=class{constructor(e){this.graph=e}graph;map(e,t){let r=this.graph.allSymbols(e),n=[];for(let o of t){let i=r.filter(l=>l.filePath===o.filePath),d=i.filter(l=>l.type!=="file").filter(l=>ct(l,o));if(d.length===0){let l=i.find(p=>p.type==="file");l&&n.push({symbol:l,fileStatus:o.status,direct:!0});continue}for(let l of d)n.push({symbol:l,fileStatus:o.status,direct:!0})}return n}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var lt={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function dt(s){return s>=30?"CRITICAL":s>=16?"HIGH":s>=6?"MEDIUM":"LOW"}function ae(s){let e=s.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var O=class{constructor(e){this.graph=e}graph;analyze(e,t,r=4){let n=this.graph.allEdges(e),o=new Map,i=0;for(let p of t){p.fileStatus==="deleted"?i+=8:p.fileStatus==="renamed"?i+=5:i+=2,p.symbol.type==="interface"&&(i+=5),p.symbol.type==="class"&&(i+=3);let m=new Set([p.symbol.id]),F=[{id:p.symbol.id,depth:0}];for(;F.length;){let D=F.shift();if(D.depth>=r)continue;let le=n.filter(g=>g.to===D.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(g.type));for(let g of le){if(m.has(g.from))continue;m.add(g.from);let P=this.graph.getSymbol(g.from);if(!P)continue;let $=D.depth+1,de=`${p.symbol.id}:${P.id}`;o.set(de,{symbol:P,relation:g.type,depth:$,sourceSymbolId:p.symbol.id});let pe=lt[g.type]??1;i+=Math.max(1,pe-($-1)),F.push({id:P.id,depth:$})}}}let a=[...o.values()].sort((p,m)=>p.depth-m.depth),d=[...new Set(a.map(p=>p.symbol.filePath))],l=d.filter(ae);return l.length===0&&l.push(...d.filter(p=>!ae(p)).slice(0,10)),{risk:dt(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:d,suggestedTests:l}}};import{execFile as pt}from"node:child_process";import{promisify as ut}from"node:util";var K=ut(pt);function ft(s){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let r of s.matchAll(t)){let n=Number(r[1]),o=Number(r[2]??1);e.push({startLine:n,endLine:Math.max(n,n+o-1)})}return e}function mt(s){return s.startsWith("A")?"added":s.startsWith("D")?"deleted":s.startsWith("R")?"renamed":"modified"}async function ce(s){let e="";try{e=(await K("git",["diff","HEAD","--name-status","--no-renames"],{cwd:s,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let r of e.split(/\r?\n/).filter(Boolean)){let[n,...o]=r.split(" "),i=o.at(-1);if(!i)continue;let a="";try{a=(await K("git",["diff","HEAD","--unified=0","--",i],{cwd:s,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:mt(n),ranges:ft(a)})}try{let r=await K("git",["ls-files","--others","--exclude-standard"],{cwd:s});for(let n of r.stdout.split(/\r?\n/).filter(Boolean))t.some(o=>o.filePath===n)||t.push({filePath:n,status:"added",ranges:[]})}catch{}return t}var _=class{constructor(e){this.graph=e;this.mapper=new N(e),this.blast=new O(e)}graph;mapper;blast;async analyzeGitDiff(e,t,r={}){let n=await ce(t),o=this.mapper.map(e,n),i=this.blast.analyze(e,o,r.maxDepth??4);return{mode:"git_diff",changes:n,...i}}analyzeFile(e,t,r={}){let n=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,n,r.maxDepth??4)}}};import*as h from"typescript";import{DatabaseSync as jn}from"node:sqlite";import*as f from"typescript";import*as c from"typescript";var Xn=new Set([c.SyntaxKind.EqualsToken,c.SyntaxKind.PlusEqualsToken,c.SyntaxKind.MinusEqualsToken,c.SyntaxKind.AsteriskEqualsToken,c.SyntaxKind.SlashEqualsToken,c.SyntaxKind.PercentEqualsToken,c.SyntaxKind.QuestionQuestionEqualsToken,c.SyntaxKind.AmpersandAmpersandEqualsToken,c.SyntaxKind.BarBarEqualsToken]);async function yt(){let s=B(),e=new A().detect(),t=se(te({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),{attempts:3}),r=new L(t,e.id,e.name,e.remote??e.name),n=await new v(r).load(e.id);if(!n)throw new Error("Code graph missing");let o=new k;o.import(n.symbols,n.edges);let i=new _(o),a=process.argv[2],d=a?i.analyzeFile(e.id,a):await i.analyzeGitDiff(e.id,e.rootPath);console.log({risk:d.risk,riskScore:d.riskScore,changedSymbols:d.changedSymbols.map(l=>({symbol:l.symbol.qualifiedName,file:l.symbol.filePath,type:l.symbol.type})),impactedFiles:d.impactedFiles,suggestedTests:d.suggestedTests,impactedCount:d.impacted.length})}yt().catch(s=>{console.error(s),process.exit(1)});
|