toolnet-memory 0.3.14 → 0.3.16
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 +182 -6
- package/bin/toolnet-memory +5 -0
- package/bundle/agy-hook.js +71 -71
- package/bundle/agy.js +65 -65
- 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 +29 -28
- package/bundle/codex.js +77 -77
- package/bundle/context-runtime.js +44 -43
- package/bundle/context.js +15 -15
- package/bundle/continuity-certify.js +13 -13
- package/bundle/copilot-hook.js +88 -86
- package/bundle/copilot.js +4 -4
- package/bundle/cursor-hook.js +88 -86
- package/bundle/cursor.js +4 -4
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +21 -21
- 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 +64 -63
- package/bundle/grok.js +5 -5
- package/bundle/handoff-refresh.js +10 -10
- package/bundle/help-cli.js +3 -3
- package/bundle/impact.js +4 -4
- package/bundle/incremental.js +5 -4
- package/bundle/init.js +38 -37
- package/bundle/integration-status.js +4 -4
- package/bundle/kiro-hook.js +93 -92
- 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 +84 -84
- 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 +21 -3
- package/release-manifest.json +104 -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 f from"fs";import*as u from"path";import{existsSync as _,mkdirSync as te,readFileSync as O,renameSync as ne,writeFileSync as re}from"node:fs";import{dirname as oe,join as j}from"node:path";import{createHash as ee}from"node:crypto";function R(n){return ee("sha256").update(n).digest("hex")}function P(n){return j(n.rootPath,".toolnet","context","handoff.md")}function N(n){return j(n.rootPath,".toolnet","context","handoff.json")}function D(n,e){te(oe(n),{recursive:!0});let t=`${n}.tmp-${process.pid}-${Date.now()}`;re(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}),ne(t,n)}function ie(n,e){D(n,`${JSON.stringify(e,null,2)}
|
|
4
|
+
`)}function F(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:R(t),generatedAt:new Date().toISOString()};return D(P(n),t),ie(N(n),r),r}function $(n){let e=P(n);if(!_(e))return null;try{let t=O(e,"utf8").trim();if(!t)return null;let r=new Date(0).toISOString(),i=N(n);if(_(i))try{let o=JSON.parse(O(i,"utf8"));typeof o.generatedAt=="string"&&(r=o.generatedAt)}catch{}return{version:1,projectId:n.id,projectName:n.name,text:t,digest:R(t),generatedAt:r}}catch{return null}}function L(n){let e=u.resolve(n),t=u.parse(e).root;for(;e!==t;){let r=u.join(e,".toolnet");if(f.existsSync(r)&&f.statSync(r).isDirectory())return e;e=u.dirname(e)}return null}import{existsSync as le,readFileSync as fe}from"node:fs";import{join as pe}from"node:path";import{existsSync as se,mkdirSync as pt,readFileSync as ae,renameSync as mt,writeFileSync as gt}from"node:fs";import{dirname as ht,join as ce}from"node:path";function ue(n){return ce(n.rootPath,".toolnet","context","session-origin.json")}function de(n){let e=ue(n);if(!se(e))return null;try{let t=JSON.parse(ae(e,"utf8"));return t.version!==1||t.projectId!==n.id?null:t}catch{return null}}function K(n){let e=de(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 me(n){let e=pe(n.rootPath,".toolnet","current.md");if(!le(e))return null;try{return fe(e,"utf8").trim()}catch{return null}}function ge(n,e){let t=e.replace(/\r\n/g,`
|
|
7
|
+
`).trim(),r=2400,i=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=K(n);return["# ToolNet Fast Handoff","",`Project: ${n.name}`,"",...o?[o,""]:[],i,"","---","","Continuation rule:","- Continue unfinished work; do not redo completed steps.","- Query ToolNet Memory only when deeper history is needed."].join(`
|
|
10
|
+
`)}function z(n){let e=me(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=ge(n,e);return $(n)?.text.trim()===t.trim()?{updated:!1,reason:"unchanged",chars:t.length}:(F(n,t),{updated:!0,reason:"updated",chars:t.length})}import{existsSync as ye,readFileSync as he}from"node:fs";import{homedir as xe}from"node:os";import{join as Se}from"node:path";function be(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 ve(){let n=process.env.TOOLNET_GLOBAL_ENV??Se(xe(),".config","toolnet-memory",".env");if(!ye(n))return;let e=he(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 i=r.indexOf("=");if(i<=0)continue;let o=r.slice(0,i).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=be(r.slice(i+1)))}}ve();import{createHash as Ee}from"node:crypto";import{existsSync as b,mkdirSync as Te,readFileSync as Ie,renameSync as _e,writeFileSync as Oe}from"node:fs";import{basename as je,dirname as v,join as h,parse as U,resolve as l}from"node:path";import{createHash as H}from"node:crypto";import{spawnSync as we}from"node:child_process";var y="git-remote-v1",Me=new Set(["github.com","gitlab.com","bitbucket.org"]);function B(n,e){let t=e.replaceAll("\\","/").replace(/^\/+/u,"").replace(/\/+$/u,"").replace(/\.git$/iu,"").replace(/\/+/gu,"/");return!t||t==="."||t===".."||t.split("/").some(r=>!r||r==="."||r==="..")?null:(Me.has(n)&&(t=t.toLowerCase()),t)}function ke(n){let e;try{e=new URL(n)}catch{return null}if(!["https:","http:","ssh:","git:"].includes(e.protocol))return null;let t=e.hostname.trim().toLowerCase();if(!t)return null;let r=e.protocol==="https:"&&e.port==="443"||e.protocol==="http:"&&e.port==="80"||e.protocol==="ssh:"&&e.port==="22",i=e.port&&!r?`${t}:${e.port}`:t,o=B(t,e.pathname);return o?`${i}/${o}`:null}function Ae(n){let e=n.match(/^(?:[^@\s/:]+@)?([^:/\s]+):(.+)$/u);if(!e)return null;let t=e[1]?.trim().toLowerCase();if(!t||t.length===1)return null;let r=B(t,e[2]??"");return r?`${t}/${r}`:null}function V(n){let e=n.trim();return e?e.includes("://")?ke(e):Ae(e):null}function Re(n){return H("sha256").update(`${y}:${n}`).digest("hex")}function Y(n){return H("sha256").update(`toolnet-project:${y}:${n}`).digest("hex").slice(0,16)}function Ce(n){return n.split("/").filter(Boolean).at(-1)?.trim()||null}function C(n,e){let t=we("git",["-C",n,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function G(n,e){let t=Ce(n);return t?{scheme:y,canonicalRemote:n,fingerprint:Re(n),repositoryName:t,source:e}:null}function W(n){let e=C(n,["remote","get-url","origin"]);if(e){let i=V(e);if(i)return G(i,"origin")}let t=C(n,["remote"]);if(!t)return null;let r=new Set;for(let i of t.split(/\r?\n/u).map(o=>o.trim()).filter(Boolean)){let o=C(n,["remote","get-url",i]);if(!o)continue;let s=V(o);s&&r.add(s)}return r.size!==1?null:G([...r][0],"unique-remote")}var q=".toolnet",Pe="project.json";function Ne(n){return Ee("sha256").update(n).digest("hex").slice(0,16)}function p(n){return h(n,q,Pe)}function Z(n){return b(p(n))}function J(n,e){let t=l(n),r=U(t).root;for(;;){if(Z(t))return t;if(t===r||e&&t===l(e))break;let i=v(t);if(i===t)break;t=i}return null}function E(n){let e=l(n),t=U(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>b(h(e,o))))return e;if(e===t)break;let i=v(e);if(i===e)break;e=i}return l(n)}function x(n){let e;try{e=JSON.parse(Ie(n,"utf8"))}catch(i){throw new Error(`Invalid ToolNet project manifest: ${n}: ${i instanceof Error?i.message:String(i)}`)}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:v(v(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 S(n,e){let t=h(n,q);Te(t,{recursive:!0});let r=p(n),i=`${r}.tmp-${process.pid}`;Oe(i,JSON.stringify(e,null,2)+`
|
|
12
|
+
`,{encoding:"utf8",mode:384}),_e(i,r)}function d(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}}function T(n){return{version:1,scheme:y,canonicalRemote:n.canonicalRemote,fingerprint:n.fingerprint,repositoryName:n.repositoryName}}function De(n){let e=n.metadata?.toolnetIdentity;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return typeof t.fingerprint=="string"?t.fingerprint:null}var w=class{adopt(e,t){let r=E(l(e));if(!t.id.trim())throw new Error("PROJECT_ADOPTION_INVALID_ID");if(!t.name.trim())throw new Error("PROJECT_ADOPTION_INVALID_NAME");if(!t.remote.trim())throw new Error("PROJECT_ADOPTION_INVALID_REMOTE");if(Z(r)){let a=x(p(r));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return d(a,r)}let i=new Date().toISOString(),o={...t.metadata};t.gitIdentity&&(o.toolnetIdentity=T(t.gitIdentity));let s={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:r,createdAt:t.createdAt??i,updatedAt:i,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(o).length?o:void 0};return S(r,s),d(s,r)}recordGitIdentity(e,t,r={}){let i=this.requireExisting(e),o=p(i.rootPath),s=x(o),a=De(s);if(a&&a!==t.fingerprint&&!r.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${a}`,`current=${t.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let c=s.metadata?.toolnetIdentity;return c&&typeof c=="object"&&!Array.isArray(c)&&c.fingerprint===t.fingerprint||(s.metadata={...s.metadata,toolnetIdentity:T(t)},s.updatedAt=new Date().toISOString(),S(i.rootPath,s)),d(s,i.rootPath)}findExisting(e=process.cwd()){let t=l(e),r=E(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>b(h(r,c))),s=J(t,o?r:void 0);if(!s)return null;let a=x(p(s));return d(a,s)}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=l(e),r=E(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(A=>b(h(r,A))),s=J(t,o?r:void 0);if(s){let A=p(s),g=x(A);return g.rootPath!==s&&(g.rootPath=s,g.updatedAt=new Date().toISOString(),S(s,g)),d(g,s)}let a=new Date().toISOString(),c=je(r),m=W(r),I={version:1,id:m?Y(m.canonicalRemote):Ne(r),name:c,remote:m?.repositoryName??c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:m?{toolnetIdentity:T(m)}:void 0};return S(r,I),d(I,r)}};var Fe=[{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"}],$e=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function Q(n){return n.normalize("NFKC").trim().toLowerCase()}function Le(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 i=r/n.length;t-=i*Math.log2(i)}return t}function Ke(n){return/^[a-f0-9]{32}$/iu.test(n)||/^[a-f0-9]{40}$/iu.test(n)||/^[a-f0-9]{64}$/iu.test(n)}function ze(n,e,t){let r=n.slice(Math.max(0,e-48),e),i=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} ${i}`)}function Ve(n,e){return n.start<e.end&&e.start<n.end}function X(n){return n.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var M=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 Fe){let s=new RegExp(o.regex.source,o.regex.flags);for(let a of e.matchAll(s))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=X(t),i=[];for(let o of r)i.some(s=>Ve(s,o))||i.push(o);return X(i)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=Q(e);return $e.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let i of e.matchAll(r)){if(i.index===void 0||!i[0])continue;let o=i[0];this.allowed(o)||Ke(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||ze(e,i.index,i.index+o.length)&&(Le(o)<3.7||t.push({type:"high_entropy_secret",value:o,start:i.index,end:i.index+o.length,confidence:"heuristic"}))}return t}};var k=class{scanner;constructor(e={}){this.scanner=new M(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let r=e,i=[...t].sort((s,a)=>a.start-s.start),o=new Set;for(let s of i)o.add(s.type),r=r.slice(0,s.start)+`[REDACTED:${s.type}]`+r.slice(s.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,i]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(i)}return t}return e}};var Gt=new k;function Ge(){let n=process.cwd(),e=L(n);if(!e){console.error("Not in a ToolNet project."),process.exitCode=1;return}let t=new w().detect(e);if(!t){console.error("Unable to detect ToolNet project."),process.exitCode=1;return}let r=z(t);console.log(JSON.stringify({project:t.name,...r},null,2))}Ge();
|
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
|
|
1
|
+
import{readFileSync as A}from"node:fs";import{dirname as G,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 N(o,e){return f(o,m.dim,e)}function M(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?` ${N(`v${e}`,n)}`:"";return`${b(t.phaseDone,n)} ${o}${i}`}function a(o,e){return M(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] [--adopt-remote NAME] [--no-remote-identity] [--rebind-git-identity]",category:"core",examples:["toolnet-memory init","toolnet-memory init /path/to/project","toolnet-memory init --adopt-remote my-project"]},{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","Local Code Search \u2014 SQLite FTS5/BM25","Architecture Intelligence","Graph Analysis","3D Visualization Dataset"]},{name:"semantic",description:"Local code search \u2014 SQLite FTS5/BM25 (legacy command name)",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
3
|
`)}function S(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
|
|
4
|
+
`)}function v(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 L(){let o=G(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:L(),tty:!!process.stdout.isTTY};function E(o){let e=v(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=S(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 Ee,readFileSync as we}from"node:fs";import{homedir as ve}from"node:os";import{join as Re}from"node:path";function ke(n){let e=n.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 Pe(){let n=process.env.TOOLNET_GLOBAL_ENV??Re(ve(),".config","toolnet-memory",".env");if(!Ee(n))return;let e=we(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]=ke(r.slice(s+1)))}}Pe();function C(n,e){return n===void 0?e:["1","true","yes","on"].includes(n.toLowerCase())}function E(n,e){if(!n)return e;let t=Number(n);return Number.isFinite(t)?t:e}function q(){return{memory:{autoCapture:C(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:C(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:C(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:C(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:E(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:E(process.env.MEMORY_RERANK_TOP,10),finalContext:E(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:E(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:C(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:E(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Ne}from"node:crypto";import{existsSync as L,mkdirSync as _e,readFileSync as Oe,renameSync as Fe,writeFileSync as De}from"node:fs";import{basename as $e,dirname as N,join as v,parse as ne,resolve as b}from"node:path";import{createHash as Z}from"node:crypto";import{spawnSync as Ae}from"node:child_process";var w="git-remote-v1",Me=new Set(["github.com","gitlab.com","bitbucket.org"]);function X(n,e){let t=e.replaceAll("\\","/").replace(/^\/+/u,"").replace(/\/+$/u,"").replace(/\.git$/iu,"").replace(/\/+/gu,"/");return!t||t==="."||t===".."||t.split("/").some(r=>!r||r==="."||r==="..")?null:(Me.has(n)&&(t=t.toLowerCase()),t)}function Te(n){let e;try{e=new URL(n)}catch{return null}if(!["https:","http:","ssh:","git:"].includes(e.protocol))return null;let t=e.hostname.trim().toLowerCase();if(!t)return null;let r=e.protocol==="https:"&&e.port==="443"||e.protocol==="http:"&&e.port==="80"||e.protocol==="ssh:"&&e.port==="22",s=e.port&&!r?`${t}:${e.port}`:t,o=X(t,e.pathname);return o?`${s}/${o}`:null}function Ie(n){let e=n.match(/^(?:[^@\s/:]+@)?([^:/\s]+):(.+)$/u);if(!e)return null;let t=e[1]?.trim().toLowerCase();if(!t||t.length===1)return null;let r=X(t,e[2]??"");return r?`${t}/${r}`:null}function J(n){let e=n.trim();return e?e.includes("://")?Te(e):Ie(e):null}function je(n){return Z("sha256").update(`${w}:${n}`).digest("hex")}function ee(n){return Z("sha256").update(`toolnet-project:${w}:${n}`).digest("hex").slice(0,16)}function Le(n){return n.split("/").filter(Boolean).at(-1)?.trim()||null}function H(n,e){let t=Ae("git",["-C",n,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function Q(n,e){let t=Le(n);return t?{scheme:w,canonicalRemote:n,fingerprint:je(n),repositoryName:t,source:e}:null}function te(n){let e=H(n,["remote","get-url","origin"]);if(e){let s=J(e);if(s)return Q(s,"origin")}let t=H(n,["remote"]);if(!t)return null;let r=new Set;for(let s of t.split(/\r?\n/u).map(o=>o.trim()).filter(Boolean)){let o=H(n,["remote","get-url",s]);if(!o)continue;let i=J(o);i&&r.add(i)}return r.size!==1?null:Q([...r][0],"unique-remote")}var se=".toolnet",Ge="project.json";function Ke(n){return Ne("sha256").update(n).digest("hex").slice(0,16)}function x(n){return v(n,se,Ge)}function oe(n){return L(x(n))}function re(n,e){let t=b(n),r=ne(t).root;for(;;){if(oe(t))return t;if(t===r||e&&t===b(e))break;let s=N(t);if(s===t)break;t=s}return null}function W(n){let e=b(n),t=ne(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>L(v(e,o))))return e;if(e===t)break;let s=N(e);if(s===e)break;e=s}return b(n)}function I(n){let e;try{e=JSON.parse(Oe(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:N(N(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 j(n,e){let t=v(n,se);_e(t,{recursive:!0});let r=x(n),s=`${r}.tmp-${process.pid}`;De(s,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),Fe(s,r)}function S(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}}function U(n){return{version:1,scheme:w,canonicalRemote:n.canonicalRemote,fingerprint:n.fingerprint,repositoryName:n.repositoryName}}function ze(n){let e=n.metadata?.toolnetIdentity;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return typeof t.fingerprint=="string"?t.fingerprint:null}var _=class{adopt(e,t){let r=W(b(e));if(!t.id.trim())throw new Error("PROJECT_ADOPTION_INVALID_ID");if(!t.name.trim())throw new Error("PROJECT_ADOPTION_INVALID_NAME");if(!t.remote.trim())throw new Error("PROJECT_ADOPTION_INVALID_REMOTE");if(oe(r)){let a=I(x(r));if(a.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${a.id}`,`requested=${t.id}`].join(" "));return S(a,r)}let s=new Date().toISOString(),o={...t.metadata};t.gitIdentity&&(o.toolnetIdentity=U(t.gitIdentity));let i={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:r,createdAt:t.createdAt??s,updatedAt:s,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(o).length?o:void 0};return j(r,i),S(i,r)}recordGitIdentity(e,t,r={}){let s=this.requireExisting(e),o=x(s.rootPath),i=I(o),a=ze(i);if(a&&a!==t.fingerprint&&!r.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${a}`,`current=${t.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let c=i.metadata?.toolnetIdentity;return c&&typeof c=="object"&&!Array.isArray(c)&&c.fingerprint===t.fingerprint||(i.metadata={...i.metadata,toolnetIdentity:U(t)},i.updatedAt=new Date().toISOString(),j(s.rootPath,i)),S(i,s.rootPath)}findExisting(e=process.cwd()){let t=b(e),r=W(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>L(v(r,c))),i=re(t,o?r:void 0);if(!i)return null;let a=I(x(i));return S(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=b(e),r=W(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(g=>L(v(r,g))),i=re(t,o?r:void 0);if(i){let g=x(i),f=I(g);return f.rootPath!==i&&(f.rootPath=i,f.updatedAt=new Date().toISOString(),j(i,f)),S(f,i)}let a=new Date().toISOString(),c=$e(r),l=te(r),p={version:1,id:l?ee(l.canonicalRemote):Ke(r),name:c,remote:l?.repositoryName??c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0,metadata:l?{toolnetIdentity:U(l)}:void 0};return j(r,p),S(p,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"}],He=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function ie(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 Ue(n){return/^[a-f0-9]{32}$/iu.test(n)||/^[a-f0-9]{40}$/iu.test(n)||/^[a-f0-9]{64}$/iu.test(n)}function Ve(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 Ye(n,e){return n.start<e.end&&e.start<n.end}function ae(n){return n.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var O=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let r=ie(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=ae(t),s=[];for(let o of r)s.some(i=>Ye(i,o))||s.push(o);return ae(s)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=ie(e);return He.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)||Ue(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||Ve(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 R=class{scanner;constructor(e={}){this.scanner=new O(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 Xt=new R;import{homedir as yt}from"node:os";import{join as St}from"node:path";import{DeleteObjectCommand as qe,GetObjectCommand as Je,HeadObjectCommand as Qe,ListObjectsV2Command as Ze,PutObjectCommand as Xe,S3Client as et}from"@aws-sdk/client-s3";import{getSignedUrl as tt}from"@aws-sdk/s3-request-presigner";var F=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new et({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 s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Xe({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await tt(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(`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 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 qe({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new Ze({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};import{access as ce,mkdir as rt,readFile as nt,readdir as st,rm as ot,stat as le,writeFile as it}from"node:fs/promises";import{dirname as at,join as ct,relative as de,resolve as lt}from"node:path";var k=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return lt(this.root,t)}async put(e,t){let r=this.path(e);await rt(at(r),{recursive:!0}),await it(r,t)}async get(e){try{return await nt(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 ce(this.path(e)),!0}catch{return!1}}async delete(e){await ot(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await ce(t)}catch{return r}let s=async i=>{let a=await st(i,{withFileTypes:!0});for(let c of a){let l=ct(i,c.name);if(c.isDirectory()){await s(l);continue}let p=await le(l);r.push({key:de(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await le(t);return o.isDirectory()?await s(t):r.push({key:de(this.root,t),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as dt,GetObjectCommand as pt,HeadObjectCommand as ut,ListObjectsV2Command as mt,PutObjectCommand as ft,S3Client as gt}from"@aws-sdk/client-s3";import{getSignedUrl as ht}from"@aws-sdk/s3-request-presigner";var P=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new gt({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 s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new ft({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await ht(this.client,new pt({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 ut({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 dt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new mt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};function V(n,e){return console.warn(e),new k(n)}function pe(n){let e=n.localRoot??St(yt(),".toolnet-memory","storage");if(n.provider==="r2"){let t=n.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new P({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(n.provider==="s3"){let t=n.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new P({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] S3 credentials missing. Using local fallback.")}if(n.provider==="huggingface"){let t=n.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new F({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new k(e)}var A=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 bt(n){return new Promise(e=>setTimeout(e,n))}async function ue(n,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=t;i++)try{return await n()}catch(a){if(o=a,i>=t)break;let c=Math.min(s,r*2**(i-1)),l=Math.floor(Math.random()*Math.max(1,c*.2));await bt(c+l)}throw o}var xt=new Set(["put","get","getText","delete","list"]);function me(n,e={}){return new Proxy(n,{get(t,r){let s=Reflect.get(t,r,t);return typeof s!="function"?s:xt.has(r)?(...o)=>ue(()=>Promise.resolve(s.apply(t,o)),e):s.bind(t)}})}function fe(n){let e=n.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 ge(n){let e=n.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 s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var D=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=fe(s??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,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}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=ge(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 Hn=2*1024*1024;var M=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 vt(n,e){return e.ranges.length===0?!0:typeof n.startLine!="number"||typeof n.endLine!="number"?!1:e.ranges.some(t=>n.startLine<=t.endLine&&n.endLine>=t.startLine)}var $=class{constructor(e){this.graph=e}graph;map(e,t){let r=this.graph.allSymbols(e),s=[];for(let o of t){let i=r.filter(l=>l.filePath===o.filePath),c=i.filter(l=>l.type!=="file").filter(l=>vt(l,o));if(c.length===0){let l=i.find(p=>p.type==="file");l&&s.push({symbol:l,fileStatus:o.status,direct:!0});continue}for(let l of c)s.push({symbol:l,fileStatus:o.status,direct:!0})}return s}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var Rt={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function kt(n){return n>=30?"CRITICAL":n>=16?"HIGH":n>=6?"MEDIUM":"LOW"}function ye(n){let e=n.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var G=class{constructor(e){this.graph=e}graph;analyze(e,t,r=4){let s=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 g=new Set([p.symbol.id]),f=[{id:p.symbol.id,depth:0}];for(;f.length;){let z=f.shift();if(z.depth>=r)continue;let be=s.filter(h=>h.to===z.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(h.type));for(let h of be){if(g.has(h.from))continue;g.add(h.from);let T=this.graph.getSymbol(h.from);if(!T)continue;let B=z.depth+1,xe=`${p.symbol.id}:${T.id}`;o.set(xe,{symbol:T,relation:h.type,depth:B,sourceSymbolId:p.symbol.id});let Ce=Rt[h.type]??1;i+=Math.max(1,Ce-(B-1)),f.push({id:T.id,depth:B})}}}let a=[...o.values()].sort((p,g)=>p.depth-g.depth),c=[...new Set(a.map(p=>p.symbol.filePath))],l=c.filter(ye);return l.length===0&&l.push(...c.filter(p=>!ye(p)).slice(0,10)),{risk:kt(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:l}}};import{execFile as Pt}from"node:child_process";import{promisify as At}from"node:util";var Y=At(Pt);function Mt(n){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let r of n.matchAll(t)){let s=Number(r[1]),o=Number(r[2]??1);e.push({startLine:s,endLine:Math.max(s,s+o-1)})}return e}function Tt(n){return n.startsWith("A")?"added":n.startsWith("D")?"deleted":n.startsWith("R")?"renamed":"modified"}async function Se(n){let e="";try{e=(await Y("git",["diff","HEAD","--name-status","--no-renames"],{cwd:n,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let r of e.split(/\r?\n/).filter(Boolean)){let[s,...o]=r.split(" "),i=o.at(-1);if(!i)continue;let a="";try{a=(await Y("git",["diff","HEAD","--unified=0","--",i],{cwd:n,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:Tt(s),ranges:Mt(a)})}try{let r=await Y("git",["ls-files","--others","--exclude-standard"],{cwd:n});for(let s of r.stdout.split(/\r?\n/).filter(Boolean))t.some(o=>o.filePath===s)||t.push({filePath:s,status:"added",ranges:[]})}catch{}return t}var K=class{constructor(e){this.graph=e;this.mapper=new $(e),this.blast=new G(e)}graph;mapper;blast;async analyzeGitDiff(e,t,r={}){let s=await Se(t),o=this.mapper.map(e,s),i=this.blast.analyze(e,o,r.maxDepth??4);return{mode:"git_diff",changes:s,...i}}analyzeFile(e,t,r={}){let s=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,s,r.maxDepth??4)}}};import*as y from"typescript";import{DatabaseSync as to}from"node:sqlite";import*as m from"typescript";import*as d from"typescript";var To=new Set([d.SyntaxKind.EqualsToken,d.SyntaxKind.PlusEqualsToken,d.SyntaxKind.MinusEqualsToken,d.SyntaxKind.AsteriskEqualsToken,d.SyntaxKind.SlashEqualsToken,d.SyntaxKind.PercentEqualsToken,d.SyntaxKind.QuestionQuestionEqualsToken,d.SyntaxKind.AmpersandAmpersandEqualsToken,d.SyntaxKind.BarBarEqualsToken]);async function Lt(){let n=q(),e=new _().detect(),t=me(pe({provider:n.storage.provider,huggingface:n.storage.huggingface,localRoot:n.storage.localRoot}),{attempts:3}),r=new D(t,e.id,e.name,e.remote??e.name),s=await new A(r).load(e.id);if(!s)throw new Error("Code graph missing");let o=new M;o.import(s.symbols,s.edges);let i=new K(o),a=process.argv[2],c=a?i.analyzeFile(e.id,a):await i.analyzeGitDiff(e.id,e.rootPath);console.log({risk:c.risk,riskScore:c.riskScore,changedSymbols:c.changedSymbols.map(l=>({symbol:l.symbol.qualifiedName,file:l.symbol.filePath,type:l.symbol.type})),impactedFiles:c.impactedFiles,suggestedTests:c.suggestedTests,impactedCount:c.impacted.length})}Lt().catch(n=>{console.error(n),process.exit(1)});
|