nex-code 0.4.14 → 0.4.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/nex-code.js +12 -12
  2. package/package.json +1 -1
package/dist/nex-code.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var G=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Mn=G((jk,Hm)=>{Hm.exports={name:"nex-code",version:"0.4.14",description:"The open-source agentic coding CLI. Free with Ollama Cloud \u2014 switch to OpenAI, Anthropic or Gemini anytime. Alternative to Claude Code & Gemini CLI.",bin:{"nex-code":"./dist/nex-code.js"},files:["dist/","README.md","LICENSE"],engines:{node:">=18.0.0"},scripts:{start:"node dist/nex-code.js",build:"esbuild bin/nex-code.js --bundle --platform=node --target=node18 --outfile=dist/nex-code.js --minify --external:axios --external:dotenv --external:playwright",test:"jest --forceExit","test:orchestrator":"jest tests/orchestrator.test.js --forceExit",coverage:"jest --coverage --forceExit","test:watch":"jest --watch",format:"prettier --write .","install-hooks":"ln -sf ../../hooks/pre-push .git/hooks/pre-push && chmod +x .git/hooks/pre-push && ln -sf ../../hooks/post-merge .git/hooks/post-merge && chmod +x .git/hooks/post-merge && echo 'Hooks installed (pre-push, post-merge).'",prepublishOnly:"npm run build && npm test","merge-to-main":"bash scripts/merge-to-main.sh",release:"npm version patch && git push --follow-tags && npm publish"},keywords:["ai","cli","coding","agent","ollama","ollama-cloud","openai","anthropic","claude","gemini","llm","gpt","agentic","terminal","coding-assistant","claude-code-alternative","gemini-cli-alternative","open-source","free","qwen3","devstral","kimi-k2","deepseek","local-llm","mcp","model-context-protocol","multi-provider"],repository:{type:"git",url:"https://github.com/hybridpicker/nex-code.git"},bugs:{url:"https://github.com/hybridpicker/nex-code/issues"},homepage:"https://github.com/hybridpicker/nex-code#readme",license:"MIT",dependencies:{axios:"^1.7.0",dotenv:"^16.4.0"},devDependencies:{esbuild:"^0.27.3",jest:"^29.7.0",prettier:"^3.8.1"},jest:{coverageThreshold:{global:{lines:45,functions:30,branches:35},"./cli/sub-agent.js":{lines:70,functions:60,branches:55}}}}});var pn=G((qk,Cc)=>{"use strict";var kc="\x1B[0m",vc="\x1B[1m",Pn="\x1B[2m";function q(t,e,n){return`\x1B[38;2;${t};${e};${n}m`}function Gm(){if(!process.stdout.isTTY)return null;try{let{execFileSync:t}=require("child_process"),e=["import sys,os,tty,termios,select","f=open('/dev/tty','r+b',buffering=0)","fd=f.fileno()","s=termios.tcgetattr(fd)","try:"," tty.setraw(fd)"," f.write(bytes([0x1b,0x5d,0x31,0x31,0x3b,0x3f,0x1b,0x5c]))"," r=select.select([fd],[],[],0.1)[0]"," d=b''"," if r:"," while True:"," r2=select.select([fd],[],[],0.05)[0]"," if not r2:break"," c=os.read(fd,1)"," d+=c"," if d[-1:]==bytes([0x07]) or d[-2:]==bytes([0x1b,0x5c]):break"," sys.stdout.buffer.write(d)","finally:"," termios.tcsetattr(fd,termios.TCSADRAIN,s)"," f.close()"].join(`
2
+ var G=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Mn=G((jk,Hm)=>{Hm.exports={name:"nex-code",version:"0.4.15",description:"The open-source agentic coding CLI. Free with Ollama Cloud \u2014 switch to OpenAI, Anthropic or Gemini anytime. Alternative to Claude Code & Gemini CLI.",bin:{"nex-code":"./dist/nex-code.js"},files:["dist/","README.md","LICENSE"],engines:{node:">=18.0.0"},scripts:{start:"node dist/nex-code.js",build:"esbuild bin/nex-code.js --bundle --platform=node --target=node18 --outfile=dist/nex-code.js --minify --external:axios --external:dotenv --external:playwright",test:"jest --forceExit","test:orchestrator":"jest tests/orchestrator.test.js --forceExit",coverage:"jest --coverage --forceExit","test:watch":"jest --watch",format:"prettier --write .","install-hooks":"ln -sf ../../hooks/pre-push .git/hooks/pre-push && chmod +x .git/hooks/pre-push && ln -sf ../../hooks/post-merge .git/hooks/post-merge && chmod +x .git/hooks/post-merge && echo 'Hooks installed (pre-push, post-merge).'",prepublishOnly:"npm run build && npm test","merge-to-main":"bash scripts/merge-to-main.sh",release:"npm version patch && git push --follow-tags && npm publish"},keywords:["ai","cli","coding","agent","ollama","ollama-cloud","openai","anthropic","claude","gemini","llm","gpt","agentic","terminal","coding-assistant","claude-code-alternative","gemini-cli-alternative","open-source","free","qwen3","devstral","kimi-k2","deepseek","local-llm","mcp","model-context-protocol","multi-provider"],repository:{type:"git",url:"https://github.com/hybridpicker/nex-code.git"},bugs:{url:"https://github.com/hybridpicker/nex-code/issues"},homepage:"https://github.com/hybridpicker/nex-code#readme",license:"MIT",dependencies:{axios:"^1.7.0",dotenv:"^16.4.0"},devDependencies:{esbuild:"^0.27.3",jest:"^29.7.0",prettier:"^3.8.1"},jest:{coverageThreshold:{global:{lines:45,functions:30,branches:35},"./cli/sub-agent.js":{lines:70,functions:60,branches:55}}}}});var pn=G((qk,Cc)=>{"use strict";var kc="\x1B[0m",vc="\x1B[1m",Pn="\x1B[2m";function q(t,e,n){return`\x1B[38;2;${t};${e};${n}m`}function Gm(){if(!process.stdout.isTTY)return null;try{let{execFileSync:t}=require("child_process"),e=["import sys,os,tty,termios,select","f=open('/dev/tty','r+b',buffering=0)","fd=f.fileno()","s=termios.tcgetattr(fd)","try:"," tty.setraw(fd)"," f.write(bytes([0x1b,0x5d,0x31,0x31,0x3b,0x3f,0x1b,0x5c]))"," r=select.select([fd],[],[],0.1)[0]"," d=b''"," if r:"," while True:"," r2=select.select([fd],[],[],0.05)[0]"," if not r2:break"," c=os.read(fd,1)"," d+=c"," if d[-1:]==bytes([0x07]) or d[-2:]==bytes([0x1b,0x5c]):break"," sys.stdout.buffer.write(d)","finally:"," termios.tcsetattr(fd,termios.TCSADRAIN,s)"," f.close()"].join(`
3
3
  `),s=t("python3",["-c",e],{encoding:"buffer",timeout:400,stdio:["ignore","pipe","ignore"]}).toString("utf8").match(/rgb:([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)/);if(s){let r=parseInt(s[1].slice(0,2),16),i=parseInt(s[2].slice(0,2),16),c=parseInt(s[3].slice(0,2),16);return .299*r+.587*i+.114*c<128}}catch{}return null}function Sc(){let t=require("os");return require("path").join(t.homedir(),".nex-code",".theme_cache.json")}function Km(t){try{let n=require("fs").readFileSync(Sc(),"utf8"),o=JSON.parse(n);if(o&&typeof o[t]=="boolean")return o[t]}catch{}return null}function Ym(t,e){try{let n=require("fs"),o=require("path"),s=Sc(),r=o.dirname(s),i={};try{i=JSON.parse(n.readFileSync(s,"utf8"))}catch{}i[t]=e;let c=Object.keys(i);c.length>50&&c.slice(0,c.length-50).forEach(l=>delete i[l]),n.existsSync(r)||n.mkdirSync(r,{recursive:!0}),n.writeFileSync(s,JSON.stringify(i),"utf8")}catch{}}function zm(){let t=(process.env.NEX_THEME||"").toLowerCase();if(t==="light")return!1;if(t==="dark")return!0;let e=process.env.COLORFGBG;if(e){let i=e.split(";"),c=parseInt(i[i.length-1],10);if(!isNaN(c))return c<8}let n=process.env.TERM_SESSION_ID||"default",o=Km(n);if(o!==null)return o;let s=Gm(),r=s!==null?s:!0;return Ym(n,r),r}var Ec=zm(),Tc={reset:kc,bold:vc,dim:Pn,primary:q(80,190,255),secondary:q(60,170,190),success:q(80,210,120),warning:q(245,175,50),error:q(230,80,80),muted:Pn,subtle:q(130,130,145),tool_read:q(80,190,255),tool_write:q(245,165,55),tool_exec:q(185,100,235),tool_search:q(70,185,190),tool_git:q(90,210,100),tool_web:q(100,215,250),tool_sysadmin:q(225,150,75),tool_default:q(100,205,115),syn_keyword:q(185,100,235),syn_string:q(90,210,120),syn_number:q(245,175,50),syn_comment:Pn,syn_key:q(80,190,255),diff_add:q(80,210,120),diff_rem:q(230,80,80),banner_logo:q(80,200,255),banner_name:q(80,200,255),banner_version:Pn,banner_model:Pn,banner_yolo:q(245,175,50),footer_sep:Pn,footer_model:q(80,175,235),footer_branch:q(80,210,100),footer_project:q(130,130,145),footer_divider:q(80,80,95),footer_mode:q(210,150,50),white:"\x1B[37m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",gray:"\x1B[90m",bgRed:"\x1B[41m",bgGreen:"\x1B[42m",diff_add_bg:"\x1B[48;2;10;46;20m",diff_rem_bg:"\x1B[48;2;58;16;16m",brightCyan:"\x1B[96m",brightMagenta:"\x1B[95m",brightBlue:"\x1B[94m"},Rc={reset:kc,bold:vc,dim:q(110,110,120),primary:q(0,110,190),secondary:q(0,125,148),success:q(0,148,62),warning:q(168,92,0),error:q(188,32,32),muted:q(110,110,120),subtle:q(155,155,165),tool_read:q(0,110,190),tool_write:q(168,92,0),tool_exec:q(128,42,188),tool_search:q(0,122,148),tool_git:q(0,138,62),tool_web:q(0,112,178),tool_sysadmin:q(168,82,0),tool_default:q(0,138,62),syn_keyword:q(128,42,188),syn_string:q(0,138,62),syn_number:q(168,92,0),syn_comment:q(135,135,148),syn_key:q(0,110,190),diff_add:q(0,148,62),diff_rem:q(188,32,32),banner_logo:q(0,122,205),banner_name:q(0,122,205),banner_version:q(100,100,118),banner_model:q(100,100,118),banner_yolo:q(168,62,0),footer_sep:q(168,168,178),footer_model:q(0,102,175),footer_branch:q(0,138,62),footer_project:q(135,135,148),footer_divider:q(168,168,178),footer_mode:q(148,88,0),white:q(40,40,52),red:q(188,32,32),green:q(0,148,62),yellow:q(168,92,0),blue:q(0,110,190),magenta:q(128,42,188),cyan:q(0,125,148),gray:q(132,132,142),bgRed:"\x1B[41m",bgGreen:"\x1B[42m",diff_add_bg:"\x1B[48;2;215;245;220m",diff_rem_bg:"\x1B[48;2;255;215;215m",brightCyan:q(0,158,182),brightMagenta:q(158,52,208),brightBlue:q(0,112,208)},Xm=Ec?Tc:Rc;Cc.exports={T:Xm,isDark:Ec,DARK:Tc,LIGHT:Rc}});var Ln=G((Fk,Oc)=>{var{T:B}=pn(),mo=5,In=(()=>{let t=[];for(let e=0;e<mo;e++)t.push(e);for(let e=mo-2;e>=1;e--)t.push(e);return t})(),Ac=["\u273D","\u2726","\u2727","\u2726"],zr=class{constructor(e="Thinking..."){this.text=e,this.frame=0,this.interval=null,this.startTime=null}_render(){if(this._stopped)return;let e=In[this.frame%In.length],n="";for(let s=0;s<mo;s++)n+=s===e?`${B.cyan}\u25CF${B.reset}`:" ";let o="";if(this.startTime){let s=Math.floor((Date.now()-this.startTime)/1e3);if(s>=60){let r=Math.floor(s/60),i=s%60;o=` ${B.dim}${r}m ${String(i).padStart(2,"0")}s${B.reset}`}else s>=1&&(o=` ${B.dim}${s}s${B.reset}`)}process.stderr.write(`\x1B[2K\r${n} ${B.dim}${this.text}${B.reset}${o}`),this.frame++}start(){this._stopped=!1,this.startTime=Date.now(),process.stderr.isTTY&&(process.stderr.write("\x1B[?25l"),this._render(),this.interval=setInterval(()=>this._render(),100))}update(e){this.text=e}stop(){this._stopped=!0,this.interval&&(clearInterval(this.interval),this.interval=null),process.stderr.isTTY&&process.stderr.write("\x1B[2K\r\x1B[?25h"),this.startTime=null}},Xr=class{constructor(e){this.labels=e,this.statuses=e.map(()=>"running"),this.frame=0,this.interval=null,this.startTime=null,this.lineCount=e.length}_formatElapsed(){if(!this.startTime)return"";let e=Math.floor((Date.now()-this.startTime)/1e3);if(e<1)return"";let n=Math.floor(e/60),o=e%60;return n>0?`${n}m ${String(o).padStart(2,"0")}s`:`${o}s`}_render(){if(this._stopped)return;let e=In[this.frame%In.length],n=`${B.cyan}\u25CF${B.reset}`,o=`${B.dim}\u25CB${B.reset}`,s=this._formatElapsed(),r=s?` ${B.dim}${s}${B.reset}`:"",i="";for(let c=0;c<this.labels.length;c++){let l,u;switch(this.statuses[c]){case"done":l=`${B.green}\u2713${B.reset}`,u=B.dim;break;case"error":l=`${B.red}\u2717${B.reset}`,u=B.dim;break;case"retry":l=`${B.yellow}\u21BB${B.reset}`,u=B.yellow;break;default:l=c===e?n:" ",u=""}let d=c===this.labels.length-1?r:"";i+=`\x1B[2K ${l} ${u}${this.labels[c]}${B.reset}${d}
4
4
  `}this.lineCount>0&&(i+=`\x1B[${this.lineCount}A`),process.stderr.write(i),this.frame++}start(){this._stopped=!1,this.startTime=Date.now();let e="\x1B[?25l";for(let n=0;n<this.lineCount;n++)e+=`
5
5
  `;this.lineCount>0&&(e+=`\x1B[${this.lineCount}A`),process.stderr.write(e),this._render(),this.interval=setInterval(()=>this._render(),100)}update(e,n){e>=0&&e<this.statuses.length&&(this.statuses[e]=n)}stop(e={}){if(this._stopped=!0,this.interval&&(clearInterval(this.interval),this.interval=null),!e.silent)this._renderFinal();else{let n="";for(let o=0;o<this.lineCount;o++)n+=`\x1B[2K
@@ -116,7 +116,7 @@ ${o}`)}return e.join(`
116
116
  ${e.instructions}`);return t.length===0?"":`SKILL INSTRUCTIONS:
117
117
  ${t.join(`
118
118
 
119
- `)}`}function b$(){let t=[];for(let e of at)if(e.enabled)for(let n of e.commands)t.push({cmd:n.cmd,desc:n.desc||`[skill: ${e.name}]`});return t}function _$(){let t=[];for(let e of at)if(e.enabled)for(let n of e.tools)t.push({type:"function",function:{name:`skill_${n.function.name}`,description:`[Skill:${e.name}] ${n.function.description}`,parameters:n.function.parameters}});return t}async function x$(t,e){if(!t.startsWith("skill_"))return null;let n=t.substring(6);for(let o of at)if(o.enabled){for(let s of o.tools)if(s.function.name===n&&s.execute)try{let r=await s.execute(e);return typeof r=="string"?r:JSON.stringify(r)}catch(r){return`ERROR: Skill tool '${n}' failed: ${r.message}`}}return`ERROR: Skill tool '${n}' not found`}function k$(t){let[e,...n]=t.split(/\s+/),o=n.join(" ").trim();for(let s of at)if(s.enabled){for(let r of s.commands)if(r.cmd===e&&r.handler){try{r.handler(o)}catch(i){console.error(`Skill command error (${e}): ${i.message}`)}return!0}}return!1}function v$(){return at.map(t=>({name:t.name,type:t.type,enabled:t.enabled,description:t.description||"",commands:t.commands.length,tools:t.tools.length,filePath:t.filePath}))}function S$(t){let e=at.find(o=>o.name===t);if(!e)return!1;e.enabled=!0;let n=vi().filter(o=>o!==t);return Vl(n),!0}function E$(t){let e=at.find(o=>o.name===t);if(!e)return!1;e.enabled=!1;let n=vi();return n.includes(t)||(n.push(t),Vl(n)),!0}function T$(){return at}async function R$(t,e={}){let{execSync:n}=require("child_process"),o=Jl(),s=t;/^[\w-]+\/[\w.-]+$/.test(t)&&(s=`https://github.com/${t}.git`);let r=e.name||it.basename(s,".git").replace(/^nex-skill-/,""),i=it.join(o,r);if(Re.existsSync(i))return{ok:!1,name:r,error:`Skill "${r}" is already installed at ${i}. Remove it first to reinstall.`};try{n(`git clone --depth 1 ${s} ${i}`,{timeout:3e4,stdio:"pipe"})}catch(d){return{ok:!1,name:r,error:`Git clone failed: ${d.stderr?.toString().trim()||d.message}`}}let c=it.join(i,"skill.json"),l=Re.existsSync(c),u=Re.readdirSync(i).some(d=>(d.endsWith(".md")||d.endsWith(".js"))&&!d.startsWith("."));if(!l&&!u){try{Re.rmSync(i,{recursive:!0,force:!0})}catch{}return{ok:!1,name:r,error:"No skill.json manifest or .md/.js skill file found in repository"}}if(l)try{let d=JSON.parse(Re.readFileSync(c,"utf-8"));d.name||(d.name=r)}catch{try{Re.rmSync(i,{recursive:!0,force:!0})}catch{}return{ok:!1,name:r,error:"Invalid skill.json \u2014 not valid JSON"}}return Si(),{ok:!0,name:r}}async function C$(t){let e=require("axios");try{let n=encodeURIComponent(`nex-skill ${t} OR nex-code-skill ${t}`);return((await e.get(`https://api.github.com/search/repositories?q=${n}&sort=stars&per_page=10`,{timeout:1e4,headers:{Accept:"application/vnd.github.v3+json"}})).data.items||[]).map(s=>({name:s.name.replace(/^nex-skill-/,""),description:s.description||"(no description)",url:s.clone_url,stars:s.stargazers_count,owner:s.owner.login}))}catch(n){return[{name:"error",description:`Search failed: ${n.message}`,url:"",stars:0,owner:""}]}}function A$(t){let e=it.join(gs(),t);if(!Re.existsSync(e))return{ok:!1,error:`Skill "${t}" not found in ${gs()}`};try{return Re.rmSync(e,{recursive:!0,force:!0}),Si(),{ok:!0}}catch(n){return{ok:!1,error:n.message}}}Zl.exports={initSkillsDir:Jl,loadAllSkills:Si,getSkillInstructions:w$,getSkillCommands:b$,getSkillToolDefinitions:_$,routeSkillCall:x$,handleSkillCommand:k$,listSkills:v$,enableSkill:S$,disableSkill:E$,getLoadedSkills:T$,installSkill:R$,searchSkills:C$,removeSkill:A$,_getSkillsDir:gs,_validateScriptSkill:Ql,_loadMarkdownSkill:xi,_loadScriptSkill:ki}});var Ao=G((fv,ru)=>{var{spawn:O$}=require("child_process"),N$=require("path"),eu=require("fs"),Bt=new Map;function M$(){return N$.join(process.cwd(),".nex","config.json")}function Ei(){let t=M$();if(!eu.existsSync(t))return{};try{return JSON.parse(eu.readFileSync(t,"utf-8")).mcpServers||{}}catch{return{}}}function Co(t,e,n={},o=1e4){return new Promise((s,r)=>{let i=`${Date.now()}-${Math.random().toString(36).slice(2,6)}`,c=JSON.stringify({jsonrpc:"2.0",id:i,method:e,params:n})+`
119
+ `)}`}function b$(){let t=[];for(let e of at)if(e.enabled)for(let n of e.commands)t.push({cmd:n.cmd,desc:n.desc||`[skill: ${e.name}]`});return t}function _$(){let t=[];for(let e of at)if(e.enabled)for(let n of e.tools)t.push({type:"function",function:{name:`skill_${n.function.name}`,description:`[Skill:${e.name}] ${n.function.description}`,parameters:n.function.parameters}});return t}async function x$(t,e){if(!t.startsWith("skill_"))return null;let n=t.substring(6);for(let o of at)if(o.enabled){for(let s of o.tools)if(s.function.name===n&&s.execute)try{let r=await s.execute(e);return typeof r=="string"?r:JSON.stringify(r)}catch(r){return`ERROR: Skill tool '${n}' failed: ${r.message}`}}return`ERROR: Skill tool '${n}' not found`}function k$(t){let[e,...n]=t.split(/\s+/),o=n.join(" ").trim();for(let s of at)if(s.enabled){for(let r of s.commands)if(r.cmd===e&&r.handler){try{r.handler(o)}catch(i){console.error(`Skill command error (${e}): ${i.message}`)}return!0}}return!1}function v$(){return at.map(t=>({name:t.name,type:t.type,enabled:t.enabled,description:t.description||"",commands:t.commands.length,tools:t.tools.length,filePath:t.filePath}))}function S$(t){let e=at.find(o=>o.name===t);if(!e)return!1;e.enabled=!0;let n=vi().filter(o=>o!==t);return Vl(n),!0}function E$(t){let e=at.find(o=>o.name===t);if(!e)return!1;e.enabled=!1;let n=vi();return n.includes(t)||(n.push(t),Vl(n)),!0}function T$(){return at}async function R$(t,e={}){let{execSync:n}=require("child_process"),o=Jl(),s=t;/^[\w-]+\/[\w.-]+$/.test(t)&&(s=`https://github.com/${t}.git`);let r=e.name||it.basename(s,".git").replace(/^nex-skill-/,""),i=it.join(o,r);if(Re.existsSync(i))return{ok:!1,name:r,error:`Skill "${r}" is already installed at ${i}. Remove it first to reinstall.`};try{if(!/^https?:\/\/[a-zA-Z0-9._\-/:@#?=&%+~]+$/.test(s))throw new Error(`Invalid git URL: ${s}`);let d=i.replace(/'/g,"'\\''");n(`git clone --depth 1 '${s}' '${d}'`,{timeout:3e4,stdio:"pipe"})}catch(d){return{ok:!1,name:r,error:`Git clone failed: ${d.stderr?.toString().trim()||d.message}`}}let c=it.join(i,"skill.json"),l=Re.existsSync(c),u=Re.readdirSync(i).some(d=>(d.endsWith(".md")||d.endsWith(".js"))&&!d.startsWith("."));if(!l&&!u){try{Re.rmSync(i,{recursive:!0,force:!0})}catch{}return{ok:!1,name:r,error:"No skill.json manifest or .md/.js skill file found in repository"}}if(l)try{let d=JSON.parse(Re.readFileSync(c,"utf-8"));d.name||(d.name=r)}catch{try{Re.rmSync(i,{recursive:!0,force:!0})}catch{}return{ok:!1,name:r,error:"Invalid skill.json \u2014 not valid JSON"}}return Si(),{ok:!0,name:r}}async function C$(t){let e=require("axios");try{let n=encodeURIComponent(`nex-skill ${t} OR nex-code-skill ${t}`);return((await e.get(`https://api.github.com/search/repositories?q=${n}&sort=stars&per_page=10`,{timeout:1e4,headers:{Accept:"application/vnd.github.v3+json"}})).data.items||[]).map(s=>({name:s.name.replace(/^nex-skill-/,""),description:s.description||"(no description)",url:s.clone_url,stars:s.stargazers_count,owner:s.owner.login}))}catch(n){return[{name:"error",description:`Search failed: ${n.message}`,url:"",stars:0,owner:""}]}}function A$(t){let e=it.join(gs(),t);if(!Re.existsSync(e))return{ok:!1,error:`Skill "${t}" not found in ${gs()}`};try{return Re.rmSync(e,{recursive:!0,force:!0}),Si(),{ok:!0}}catch(n){return{ok:!1,error:n.message}}}Zl.exports={initSkillsDir:Jl,loadAllSkills:Si,getSkillInstructions:w$,getSkillCommands:b$,getSkillToolDefinitions:_$,routeSkillCall:x$,handleSkillCommand:k$,listSkills:v$,enableSkill:S$,disableSkill:E$,getLoadedSkills:T$,installSkill:R$,searchSkills:C$,removeSkill:A$,_getSkillsDir:gs,_validateScriptSkill:Ql,_loadMarkdownSkill:xi,_loadScriptSkill:ki}});var Ao=G((fv,ru)=>{var{spawn:O$}=require("child_process"),N$=require("path"),eu=require("fs"),Bt=new Map;function M$(){return N$.join(process.cwd(),".nex","config.json")}function Ei(){let t=M$();if(!eu.existsSync(t))return{};try{return JSON.parse(eu.readFileSync(t,"utf-8")).mcpServers||{}}catch{return{}}}function Co(t,e,n={},o=1e4){return new Promise((s,r)=>{let i=`${Date.now()}-${Math.random().toString(36).slice(2,6)}`,c=JSON.stringify({jsonrpc:"2.0",id:i,method:e,params:n})+`
120
120
  `,l="",u=setTimeout(()=>{f(),r(new Error(`MCP request timeout: ${e}`))},o);function d(m){l+=m.toString();let h=l.split(`
121
121
  `);for(let p of h)if(p.trim())try{let g=JSON.parse(p);if(g.id===i){f(),g.error?r(new Error(`MCP error: ${g.error.message||JSON.stringify(g.error)}`)):s(g.result);return}}catch{}l=h[h.length-1]||""}function f(){clearTimeout(u),t.stdout.removeListener("data",d)}t.stdout.on("data",d);try{t.stdin.write(c)}catch(m){f(),r(new Error(`MCP write failed: ${m.message}`))}})}async function tu(t,e){if(Bt.has(t))return Bt.get(t);let n=["PATH","HOME","USER","SHELL","LANG","TERM","NODE_ENV"],o={};for(let i of n)process.env[i]&&(o[i]=process.env[i]);let s=O$(e.command,e.args||[],{stdio:["pipe","pipe","pipe"],env:{...o,...e.env||{}}}),r={name:t,proc:s,tools:[],config:e};try{await Co(s,"initialize",{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"nex-code",version:"0.2.0"}});let i=await Co(s,"tools/list",{});return r.tools=i&&i.tools||[],Bt.set(t,r),r}catch(i){throw s.kill(),new Error(`Failed to connect MCP server '${t}': ${i.message}`)}}function nu(t){let e=Bt.get(t);if(!e)return!1;try{e.proc.kill()}catch{}return Bt.delete(t),!0}function P$(){for(let[t]of Bt)nu(t)}async function su(t,e,n={}){let o=Bt.get(t);if(!o)throw new Error(`MCP server not connected: ${t}`);let s=await Co(o.proc,"tools/call",{name:e,arguments:n});return s&&Array.isArray(s.content)?s.content.filter(r=>r.type==="text").map(r=>r.text).join(`
122
122
  `):JSON.stringify(s)}function ou(){let t=[];for(let[e,n]of Bt)for(let o of n.tools)t.push({server:e,name:o.name,description:o.description||"",inputSchema:o.inputSchema||{type:"object",properties:{}}});return t}function I$(){return ou().map(t=>({type:"function",function:{name:`mcp_${t.server}_${t.name}`,description:`[MCP:${t.server}] ${t.description}`,parameters:t.inputSchema}}))}async function L$(t,e){if(!t.startsWith("mcp_"))return null;let n=t.substring(4).split("_");if(n.length<2)return null;let o=n[0],s=n.slice(1).join("_");return su(o,s,e)}function D$(){let t=Ei();return Object.entries(t).map(([e,n])=>{let o=Bt.get(e);return{name:e,command:n.command,connected:!!o,toolCount:o?o.tools.length:0}})}async function j$(){let t=Ei(),e=[];for(let[n,o]of Object.entries(t))try{let s=await tu(n,o);e.push({name:n,tools:s.tools.length})}catch(s){e.push({name:n,tools:0,error:s.message})}return e}ru.exports={loadMCPConfig:Ei,sendRequest:Co,connectServer:tu,disconnectServer:nu,disconnectAll:P$,callTool:su,getAllTools:ou,getMCPToolDefinitions:I$,routeMCPCall:L$,listServers:D$,connectAll:j$}});var No=G((pv,lu)=>{var iu=require("fs"),Ti=require("path"),Oo=[],$s=[],yn={},ys=["onToolResult","onModelResponse","onSessionStart","onSessionEnd","onFileChange","beforeToolExec","afterToolExec"];function au(t,e){if(!t||!t.function||!t.function.name)return{ok:!1,error:"Tool definition must have function.name"};if(typeof e!="function")return{ok:!1,error:"Handler must be a function"};let n=t.function.name;return $s.some(o=>o.definition.function.name===n)?{ok:!1,error:`Tool "${n}" is already registered`}:($s.push({definition:{type:"function",...t},handler:e}),{ok:!0})}function cu(t,e){return ys.includes(t)?typeof e!="function"?{ok:!1,error:"Handler must be a function"}:(yn[t]||(yn[t]=[]),yn[t].push(e),{ok:!0}):{ok:!1,error:`Unknown event "${t}". Available: ${ys.join(", ")}`}}async function Ri(t,e){let n=yn[t]||[],o=e;for(let s of n)try{let r=await s(o);r!==void 0&&(o=r)}catch(r){process.env.NEX_DEBUG&&console.error(`[plugin] Hook error on ${t}: ${r.message}`)}return o}function q$(){let t=Ti.join(process.cwd(),".nex","plugins"),e=[];if(!iu.existsSync(t))return{loaded:0,errors:[]};let n=iu.readdirSync(t).filter(s=>s.endsWith(".js")),o={registerTool:au,registerHook:cu,EVENTS:ys};for(let s of n){let r=Ti.join(t,s);try{let i=require(r);if(typeof i=="function")i(o);else if(typeof i.setup=="function")i.setup(o);else{e.push(`${s}: Plugin must export a function or { setup: function }`);continue}Oo.push({name:i.name||Ti.basename(s,".js"),filePath:r})}catch(i){e.push(`${s}: ${i.message}`)}}return{loaded:Oo.length,errors:e}}function F$(){return $s.map(t=>t.definition)}async function U$(t,e,n={}){let o=$s.find(c=>c.definition.function.name===t);if(!o)return null;let s=await Ri("beforeToolExec",{name:t,args:e,options:n}),r=await o.handler(s.args||e,n);return(await Ri("afterToolExec",{name:t,args:e,result:r})).result||r}function W$(){return[...Oo]}function B$(){let t={};for(let e of ys)t[e]=(yn[e]||[]).length;return t}function H$(){Oo.length=0,$s.length=0;for(let t of Object.keys(yn))delete yn[t]}lu.exports={registerTool:au,registerHook:cu,emit:Ri,loadPlugins:q$,getPluginToolDefinitions:F$,executePluginTool:U$,getLoadedPlugins:W$,getHookCounts:B$,clearPlugins:H$,EVENTS:ys}});var Ci=G((mv,pu)=>{var{getSkillToolDefinitions:G$}=nn(),{getMCPToolDefinitions:K$}=Ao(),{getPluginToolDefinitions:Y$}=No(),Mo=new Map;function uu(){let{TOOL_DEFINITIONS:t}=Et();return[...t,...G$(),...K$(),...Y$()]}function du(t){if(Mo.has(t))return Mo.get(t);let n=uu().find(s=>s.function.name===t);if(!n)return null;let o=n.function.parameters;return Mo.set(t,o),o}function z$(){Mo.clear()}function Po(t,e){if(!t||e.length===0)return null;let n=null,o=1/0;for(let s of e){let r=fu(t.toLowerCase(),s.toLowerCase());r<o&&(o=r,n=s)}return o<=Math.ceil(t.length/2)?n:null}function fu(t,e){let n=t.length,o=e.length,s=Array.from({length:n+1},()=>Array(o+1).fill(0));for(let r=0;r<=n;r++)s[r][0]=r;for(let r=0;r<=o;r++)s[0][r]=r;for(let r=1;r<=n;r++)for(let i=1;i<=o;i++)s[r][i]=t[r-1]===e[i-1]?s[r-1][i-1]:1+Math.min(s[r-1][i],s[r][i-1],s[r-1][i-1]);return s[n][o]}function X$(t,e){let n=du(t);if(n===null){let d=uu().map(m=>m.function.name),f=Po(t,d);return{valid:!1,error:`Unknown tool "${t}".${f?` Did you mean "${f}"?`:""}
@@ -310,21 +310,21 @@ ${(m.stderr||m.message||"").toString().trim()}`}let i;try{i=kt(e.server)}catch(m
310
310
  ${d||f}`:f||"(no containers)"}case"container_logs":{if(!e.container)return"ERROR: container is required";let o=!e.server||e.server==="local"||e.server==="localhost",s=e.lines||50,r=e.since?`--since "${e.since}"`:"",i=`docker logs --tail ${s} ${r} ${e.container} 2>&1`.trim().replace(/\s+/g," ");if(o)try{let{stdout:h,stderr:p}=await Se(i,{timeout:15e3});return(h||p||"(no log output)").trim()}catch(h){return`EXIT ${h.code||1}
311
311
  ${(h.stderr||h.message||"").toString().trim()}`}let c;try{c=kt(e.server)}catch(h){return`ERROR: ${h.message}`}let{stdout:l,stderr:u,exitCode:d,error:f}=await ct(c,i,{timeout:2e4}),m=[l,u].filter(Boolean).join(`
312
312
  `).trim();return d!==0?`EXIT ${d}
313
- ${f||m}`:m||"(no log output)"}case"container_exec":{if(!e.container)return"ERROR: container is required";if(!e.command)return"ERROR: command is required";let o=!e.server||e.server==="local"||e.server==="localhost",s=/^(cat|ls|echo|env|printenv|df|du|ps|id|whoami|uname|hostname|date|pwd|which|find\s|head\s|tail\s|grep\s|curl\s+-[A-Za-z]*G|curl\s+https?:\/\/[^\s]+$)/;if(!n.autoConfirm&&!s.test(e.command.trim())){let h=o?"local":e.server;if(console.log(`
314
- ${ne.yellow} \u26A0 docker exec in ${e.container} on ${h}: ${e.command}${ne.reset}`),!await Tt(" Execute?"))return"CANCELLED: User declined."}let i=`docker exec ${e.container} sh -c ${JSON.stringify(e.command)}`;if(o)try{let{stdout:h,stderr:p}=await Se(i,{timeout:3e4});return(h||p||"(no output)").trim()}catch(h){return`EXIT ${h.code||1}
315
- ${(h.stderr||h.message||"").toString().trim()}`}let c;try{c=kt(e.server)}catch(h){return`ERROR: ${h.message}`}let{stdout:l,stderr:u,exitCode:d,error:f}=await ct(c,i,{timeout:35e3}),m=[l,u].filter(Boolean).join(`
316
- `).trim();return d!==0?`EXIT ${d}
317
- ${f||m}`:m||"(no output)"}case"container_manage":{if(!e.container)return"ERROR: container is required";if(!e.action)return"ERROR: action is required";let o=["start","stop","restart","remove","inspect"];if(!o.includes(e.action))return`ERROR: invalid action "${e.action}". Valid: ${o.join(", ")}`;let s=!e.server||e.server==="local"||e.server==="localhost";if(!(e.action==="inspect")&&!n.autoConfirm){let p=s?"local":e.server;if(console.log(`
313
+ ${f||m}`:m||"(no log output)"}case"container_exec":{if(!e.container)return"ERROR: container is required";if(!e.command)return"ERROR: command is required";let o=!e.server||e.server==="local"||e.server==="localhost",s=/^(cat|ls|echo|env|printenv|df|du|ps|id|whoami|uname|hostname|date|pwd|which|find\s|head\s|tail\s|grep\s|curl\s+-[A-Za-z]*G|curl\s+https?:\/\/[^\s]+$)/;if(!n.autoConfirm&&!s.test(e.command.trim())){let p=o?"local":e.server;if(console.log(`
314
+ ${ne.yellow} \u26A0 docker exec in ${e.container} on ${p}: ${e.command}${ne.reset}`),!await Tt(" Execute?"))return"CANCELLED: User declined."}let i=(e.container||"").replace(/[^a-zA-Z0-9._\/-]/g,"");if(!i)return"ERROR: Invalid container name";let c=`docker exec ${i} sh -c ${JSON.stringify(e.command)}`;if(o)try{let{stdout:p,stderr:g}=await Se(c,{timeout:3e4});return(p||g||"(no output)").trim()}catch(p){return`EXIT ${p.code||1}
315
+ ${(p.stderr||p.message||"").toString().trim()}`}let l;try{l=kt(e.server)}catch(p){return`ERROR: ${p.message}`}let{stdout:u,stderr:d,exitCode:f,error:m}=await ct(l,c,{timeout:35e3}),h=[u,d].filter(Boolean).join(`
316
+ `).trim();return f!==0?`EXIT ${f}
317
+ ${m||h}`:h||"(no output)"}case"container_manage":{if(!e.container)return"ERROR: container is required";if(!e.action)return"ERROR: action is required";let o=["start","stop","restart","remove","inspect"];if(!o.includes(e.action))return`ERROR: invalid action "${e.action}". Valid: ${o.join(", ")}`;let s=!e.server||e.server==="local"||e.server==="localhost";if(!(e.action==="inspect")&&!n.autoConfirm){let p=s?"local":e.server;if(console.log(`
318
318
  ${ne.yellow} \u26A0 docker ${e.action} ${e.container} on ${p}${ne.reset}`),!await Tt(" Execute?"))return"CANCELLED: User declined."}let i=e.action==="remove"?"rm":e.action,c=e.action==="inspect"?`docker inspect ${e.container}`:`docker ${i} ${e.container}`;if(s)try{let{stdout:p,stderr:g}=await Se(c,{timeout:3e4});return(p||g||`docker ${e.action} ${e.container}: OK`).trim()}catch(p){return`EXIT ${p.code||1}
319
319
  ${(p.stderr||p.message||"").toString().trim()}`}let l;try{l=kt(e.server)}catch(p){return`ERROR: ${p.message}`}let{stdout:u,stderr:d,exitCode:f,error:m}=await ct(l,c,{timeout:35e3}),h=[u,d].filter(Boolean).join(`
320
320
  `).trim();return f!==0?`EXIT ${f}
321
321
  ${m||h}`:h||`docker ${e.action} ${e.container}: OK`}case"deploy":{if(e.config)try{e={...Iw(e.config),...e},delete e.config,delete e._name}catch(d){return`ERROR: ${d.message}`}if(!e.server)return'ERROR: server is required (or use config: "<name>")';if(!e.remote_path)return"ERROR: remote_path is required";let o=e.method||"rsync";if(o==="rsync"&&!e.local_path)return"ERROR: local_path is required for rsync method";let s;try{s=kt(e.server)}catch(d){return`ERROR: ${d.message}`}let r=s.user?`${s.user}@${s.host}`:s.host;if(!e.dry_run&&!n.autoConfirm){if(o==="git"){let f=e.branch?` (branch: ${e.branch})`:"";console.log(`
322
322
  ${ne.yellow} \u26A0 Deploy [git pull]: ${r}:${e.remote_path}${f}${ne.reset}`)}else{let f=e.local_path.endsWith("/")?e.local_path:`${e.local_path}/`;console.log(`
323
- ${ne.yellow} \u26A0 Deploy [rsync]: ${f} \u2192 ${r}:${e.remote_path}${ne.reset}`)}if(e.deploy_script&&console.log(`${ne.yellow} Then run: ${e.deploy_script}${ne.reset}`),e.health_check&&console.log(`${ne.yellow} Health check: ${e.health_check}${ne.reset}`),!await Tt(" Proceed with deployment?"))return"CANCELLED: User declined."}let i="";if(o==="git"){let d=e.branch?`cd ${e.remote_path} && git fetch origin && git checkout ${e.branch} && git pull origin ${e.branch}`:`cd ${e.remote_path} && git pull`;if(e.dry_run)return`DRY RUN [git]: would run on ${r}:
324
- ${d}${e.deploy_script?`
325
- ${e.deploy_script}`:""}`;let{stdout:f,stderr:m,exitCode:h,error:p}=await ct(s,d,{timeout:12e4});if(i=[f,m].filter(Boolean).join(`
326
- `).trim(),h!==0)return`ERROR (git pull, exit ${h}):
327
- ${p||i}`}else{let d=s.key?`-e "ssh -i ${s.key.replace(/^~/,require("os").homedir())}${s.port&&Number(s.port)!==22?` -p ${s.port}`:""}"`:s.port&&Number(s.port)!==22?`-e "ssh -p ${s.port}"`:"",f=(e.exclude||[]).map(g=>`--exclude="${g}"`).join(" "),m=e.dry_run?"--dry-run":"",h=e.local_path.endsWith("/")?e.local_path:`${e.local_path}/`,p=`rsync -avz --delete ${m} ${f} ${d} ${h} ${r}:${e.remote_path}`.trim().replace(/\s+/g," ");try{let{stdout:g,stderr:y}=await Se(p,{timeout:12e4});i=(g||y||"").trim()}catch(g){return`ERROR (rsync): ${(g.stderr||g.message||"").toString().trim()}`}if(e.dry_run)return`DRY RUN [rsync]:
323
+ ${ne.yellow} \u26A0 Deploy [rsync]: ${f} \u2192 ${r}:${e.remote_path}${ne.reset}`)}if(e.deploy_script&&console.log(`${ne.yellow} Then run: ${e.deploy_script}${ne.reset}`),e.health_check&&console.log(`${ne.yellow} Health check: ${e.health_check}${ne.reset}`),!await Tt(" Proceed with deployment?"))return"CANCELLED: User declined."}let i="";if(o==="git"){let d=(e.branch||"").replace(/[^a-zA-Z0-9._\/-]/g,"");if(e.branch&&d!==e.branch)return`ERROR: Invalid branch name: ${e.branch}`;let f=(e.remote_path||"").replace(/'/g,"'\\''"),m=d?`cd '${f}' && git fetch origin && git checkout '${d}' && git pull origin '${d}'`:`cd '${f}' && git pull`;if(e.dry_run)return`DRY RUN [git]: would run on ${r}:
324
+ ${m}${e.deploy_script?`
325
+ ${e.deploy_script}`:""}`;let{stdout:h,stderr:p,exitCode:g,error:y}=await ct(s,m,{timeout:12e4});if(i=[h,p].filter(Boolean).join(`
326
+ `).trim(),g!==0)return`ERROR (git pull, exit ${g}):
327
+ ${y||i}`}else{let d=s.key?`-e "ssh -i ${s.key.replace(/^~/,require("os").homedir())}${s.port&&Number(s.port)!==22?` -p ${s.port}`:""}"`:s.port&&Number(s.port)!==22?`-e "ssh -p ${s.port}"`:"",f=(e.exclude||[]).map(g=>`--exclude="${g}"`).join(" "),m=e.dry_run?"--dry-run":"",h=e.local_path.endsWith("/")?e.local_path:`${e.local_path}/`,p=`rsync -avz --delete ${m} ${f} ${d} ${h} ${r}:${e.remote_path}`.trim().replace(/\s+/g," ");try{let{stdout:g,stderr:y}=await Se(p,{timeout:12e4});i=(g||y||"").trim()}catch(g){return`ERROR (rsync): ${(g.stderr||g.message||"").toString().trim()}`}if(e.dry_run)return`DRY RUN [rsync]:
328
328
  ${i||"(nothing to sync)"}`}let c="";if(e.deploy_script){let{stdout:d,stderr:f,exitCode:m,error:h}=await ct(s,e.deploy_script,{timeout:12e4}),p=[d,f].filter(Boolean).join(`
329
329
  `).trim();if(m!==0)return`${o==="git"?"git pull":"rsync"} OK
330
330
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nex-code",
3
- "version": "0.4.14",
3
+ "version": "0.4.15",
4
4
  "description": "The open-source agentic coding CLI. Free with Ollama Cloud — switch to OpenAI, Anthropic or Gemini anytime. Alternative to Claude Code & Gemini CLI.",
5
5
  "bin": {
6
6
  "nex-code": "./dist/nex-code.js"