@tosh99/navi-cli 0.1.0

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 (3) hide show
  1. package/README.md +15 -0
  2. package/dist/cli.js +5 -0
  3. package/package.json +37 -0
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # navi-cli
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ bun run index.ts
13
+ ```
14
+
15
+ This project was created using `bun init` in bun v1.3.11. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
package/dist/cli.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import{useState as I}from"react";import{Box as F,render as fJ,Text as U,useInput as o}from"ink";import AJ from"ink-text-input";import{readFileSync as t}from"fs";import{join as s}from"path";var e={providerId:"minimax",modelId:"MiniMax-M2.5"};function JJ(){try{let J=t(s(process.cwd(),"navi.json"),"utf-8");return JSON.parse(J)}catch{return{}}}var u=JJ(),QJ={openrouter:"OPENROUTER_API_KEY",zhipu:"ZHIPU_API_KEY",minimax:"MINIMAX_API_KEY"};for(let[J,X]of Object.entries(QJ)){let Q=u.apiKeys?.[J];if(Q)process.env[X]??=Q}function m(){let{providerId:J,modelId:X}=u.defaultModel??{};if(typeof J==="string"&&typeof X==="string")return{providerId:J,modelId:X};return e}import{stepCountIs as XJ,streamText as YJ,tool as $J}from"ai";import{openrouter as WJ}from"@openrouter/ai-sdk-provider";import{createZhipu as ZJ}from"zhipu-ai-provider";import{createMinimax as qJ}from"vercel-minimax-ai-provider";import{exec as GJ}from"child_process";import{promisify as HJ}from"util";import{z as d}from"zod";var KJ=HJ(GJ),UJ={bash:$J({description:"Run a bash/shell command and return stdout/stderr. Use for file operations, running scripts, checking system info, etc.",inputSchema:d.object({command:d.string().describe("The shell command to execute")}),execute:async({command:J})=>{try{let{stdout:X,stderr:Q}=await KJ(J,{timeout:30000});return(X||Q||"(no output)").slice(0,8000)}catch(X){return`Error: ${X.message}
3
+ ${X.stdout??""}
4
+ ${X.stderr??""}`.trim().slice(0,8000)}}})},E=[{id:"openrouter",label:"OpenRouter",models:[{id:"moonshotai/kimi-k2.5",label:"Kimi K2.5"},{id:"openai/gpt-4o-mini",label:"GPT-4o Mini"},{id:"anthropic/claude-3.5-haiku",label:"Claude 3.5 Haiku"}]},{id:"zhipu",label:"ZhipuAI",models:[{id:"glm-4.5",label:"GLM-4.5"},{id:"glm-4.5-flash",label:"GLM-4.5 Flash"},{id:"glm-z1-flash",label:"GLM Z1 Flash"}]},{id:"minimax",label:"MiniMax",models:[{id:"MiniMax-M2.7",label:"M2.7"},{id:"MiniMax-M2.5",label:"M2.5"}]}],_J=ZJ({baseURL:"https://api.z.ai/api/coding/paas/v4"}),NJ=qJ();function zJ(J,X){switch(J){case"openrouter":return WJ(X);case"zhipu":return _J(X,{thinking:{type:"enabled"}});case"minimax":return NJ(X);default:throw Error(`Unknown provider: ${J}`)}}function RJ(J){switch(J){case"openrouter":return{openrouter:{reasoning:{effort:"high"},provider:{order:["BaseTen","ModelRun"]}}};case"zhipu":return{zhipu:{thinking:{type:"enabled"}}};default:return{}}}function c(J,X){let Q=Date.now(),Y=YJ({model:zJ(X.providerId,X.modelId),messages:J,tools:UJ,stopWhen:XJ(10),providerOptions:RJ(X.providerId)}),Z=Promise.resolve(Y.usage).then((W)=>{let N=Date.now()-Q,z=W.outputTokens??0;return{elapsedMs:N,tokensPerSec:N>0?Math.round(z/N*1000):0,inputTokens:W.inputTokens??0,outputTokens:z}});async function*q(){for await(let W of Y.fullStream)if(W.type==="text-delta")yield{type:"text",delta:W.text};else if(W.type==="reasoning-delta")yield{type:"reasoning",delta:W.text};else if(W.type==="tool-call")yield{type:"tool-call",toolName:W.toolName,args:W.input};else if(W.type==="tool-result")yield{type:"tool-result",toolName:W.toolName,result:String(W.output)}}return{stream:q(),stats:Z}}import{Box as M,Text as f}from"ink";import{jsxDEV as K,Fragment as wJ}from"react/jsx-dev-runtime";function V(J){let X=[],Q=/(~~[^~]+~~|`[^`]+`|\*\*[^*]+\*\*|\*[^*\n]+\*|_[^_\n]+_)/g,Y=0;for(let Z of J.matchAll(Q)){if(Z.index>Y)X.push({t:J.slice(Y,Z.index)});let q=Z[0];if(q.startsWith("~~"))X.push({t:q.slice(2,-2),strike:!0});else if(q.startsWith("`"))X.push({t:q.slice(1,-1),code:!0});else if(q.startsWith("**"))X.push({t:q.slice(2,-2),bold:!0});else X.push({t:q.slice(1,-1),italic:!0});Y=Z.index+q.length}if(Y<J.length)X.push({t:J.slice(Y)});return X.filter((Z)=>Z.t)}var g=({segs:J,dim:X})=>K(wJ,{children:J.map((Q,Y)=>Q.code?K(f,{color:"#e8b86d",backgroundColor:"#2a2a2a",children:[" ",Q.t," "]},Y,!0,void 0,this):K(f,{bold:Q.bold,italic:Q.italic,strikethrough:Q.strike,dimColor:X,children:Q.t},Y,!1,void 0,this))},void 0,!1,void 0,this);function FJ(J){let X=J.split(`
5
+ `),Q=[],Y=0;while(Y<X.length){let Z=X[Y],q=Z.match(/^(`{3,}|~{3,})\s*(\S*)/);if(q){let _=q[1],b=q[2]??"",P=[];Y++;while(Y<X.length&&!X[Y].startsWith(_.slice(0,3)))P.push(X[Y]),Y++;Q.push({k:"code",lang:b,lines:P}),Y++;continue}let W=Z.match(/^(#{1,6})\s+(.+)/);if(W){Q.push({k:"h",level:W[1].length,segs:V(W[2])}),Y++;continue}if(/^[-*_]{3,}\s*$/.test(Z)){Q.push({k:"hr"}),Y++;continue}let N=Z.match(/^(\s*)[*\-+]\s+(.+)/);if(N){let _=Math.floor(N[1].length/2);Q.push({k:"li",ordered:!1,n:0,depth:_,segs:V(N[2])}),Y++;continue}let z=Z.match(/^(\s*)(\d+)\.\s+(.+)/);if(z){let _=Math.floor(z[1].length/2);Q.push({k:"li",ordered:!0,n:parseInt(z[2],10),depth:_,segs:V(z[3])}),Y++;continue}let h=Z.match(/^>\s?(.*)/);if(h){Q.push({k:"bq",segs:V(h[1])}),Y++;continue}if(Z.trim()===""){Y++;continue}let A=[];while(Y<X.length){let _=X[Y];if(_.trim()===""||/^#{1,6}\s/.test(_)||/^(`{3,}|~{3,})/.test(_)||/^[-*_]{3,}\s*$/.test(_)||/^\s*[*\-+]\s/.test(_)||/^\s*\d+\.\s/.test(_)||/^>\s/.test(_))break;A.push(_),Y++}if(A.length)Q.push({k:"p",segs:V(A.join(" "))})}return Q}var PJ=["#ffcc77","#ffb347","#e8a020","#cc8800","#aa6600","#886600"],OJ=({lang:J,lines:X})=>K(M,{flexDirection:"column",marginY:1,paddingX:1,borderStyle:"single",borderColor:"#3a3a3a",children:[J?K(f,{color:"#555555",dimColor:!0,children:J},void 0,!1,void 0,this):null,X.map((Q,Y)=>K(f,{color:"#d4c5a9",children:Q},Y,!1,void 0,this))]},void 0,!0,void 0,this),x=({content:J})=>{let X=FJ(J);return K(M,{flexDirection:"column",children:X.map((Q,Y)=>{let Z=X[Y+1],q=Q.k==="li"&&Z?.k!=="li";if(Q.k==="code")return K(OJ,{lang:Q.lang,lines:Q.lines},Y,!1,void 0,this);if(Q.k==="hr")return K(M,{marginBottom:1,children:K(f,{color:"#3a3a3a",children:"─".repeat(40)},void 0,!1,void 0,this)},Y,!1,void 0,this);if(Q.k==="h")return K(M,{marginBottom:1,children:K(f,{color:PJ[Q.level-1],bold:!0,children:K(g,{segs:Q.segs},void 0,!1,void 0,this)},void 0,!1,void 0,this)},Y,!1,void 0,this);if(Q.k==="li")return K(M,{marginBottom:q?1:0,children:[K(f,{color:"#555555",children:[" ".repeat(Q.depth),Q.ordered?`${Q.n}. `:"• "]},void 0,!0,void 0,this),K(M,{flexGrow:1,children:K(f,{color:"#aaaaaa",children:K(g,{segs:Q.segs},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},Y,!0,void 0,this);if(Q.k==="bq")return K(M,{marginBottom:1,borderStyle:"single",borderLeft:!0,borderRight:!1,borderTop:!1,borderBottom:!1,borderColor:"#555555",paddingLeft:1,children:K(f,{color:"#777777",italic:!0,children:K(g,{segs:Q.segs,dim:!0},void 0,!1,void 0,this)},void 0,!1,void 0,this)},Y,!1,void 0,this);return K(M,{marginBottom:1,children:K(f,{color:"#aaaaaa",wrap:"wrap",children:K(g,{segs:Q.segs},void 0,!1,void 0,this)},void 0,!1,void 0,this)},Y,!1,void 0,this)})},void 0,!1,void 0,this)};import{jsxDEV as $}from"react/jsx-dev-runtime";var G={border:"#3a3a3a",label:"#555555",text:"#aaaaaa",textDim:"#444444",amber:"#ffb347",amberGlow:"#ffcc77",amberDim:"#7a4f00",meta:"#3d3d3d"},l=[{cmd:"/models",description:"switch model"}],SJ=["███╗ ██╗ █████╗ ██╗ ██╗██╗","████╗ ██║██╔══██╗██║ ██║██║","██╔██╗ ██║███████║██║ ██║██║","██║╚██╗██║██╔══██║╚██╗ ██╔╝██║","██║ ╚████║██║ ██║ ╚████╔╝ ██║","╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═══╝ ╚═╝"],yJ=m();function BJ(J){let X=E.find((Y)=>Y.id===J.providerId),Q=X?.models.find((Y)=>Y.id===J.modelId);return Q?`${X.label} / ${Q.label}`:J.modelId}var LJ=({selectionLabel:J})=>$(F,{flexDirection:"column",marginBottom:1,children:[SJ.map((X,Q)=>{let Y=Q===0?G.amberGlow:Q<3?G.amber:Q<5?G.amberDim:G.meta;return $(U,{color:Y,children:X},Q,!1,void 0,this)}),$(U,{color:G.textDim,children:["v0.1.0 · ",$(U,{color:G.label,children:J},void 0,!1,void 0,this),$(U,{color:G.textDim,children:" · esc to quit"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),MJ=({content:J})=>$(F,{flexDirection:"column",marginBottom:1,children:$(U,{color:G.amber,children:J},void 0,!1,void 0,this)},void 0,!1,void 0,this),IJ=({stats:J})=>$(U,{color:G.meta,dimColor:!0,children:[(J.elapsedMs/1000).toFixed(1),"s · ",J.tokensPerSec," tok/s · ↑",J.inputTokens," ↓",J.outputTokens]},void 0,!0,void 0,this),hJ=({entry:J})=>$(F,{flexDirection:"column",marginBottom:1,children:[$(U,{color:G.amber,children:["⚙ ",$(U,{bold:!0,children:J.toolName},void 0,!1,void 0,this),$(U,{color:G.label,children:" "+JSON.stringify(J.args)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J.result!==void 0&&$(U,{color:G.textDim,dimColor:!0,children:J.result.slice(0,400)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),TJ=({content:J,reasoning:X,toolCalls:Q,isLast:Y,streaming:Z,stats:q})=>$(F,{flexDirection:"column",marginBottom:1,children:[X&&$(F,{marginBottom:1,children:$(U,{color:G.textDim,dimColor:!0,children:X?.trim()},void 0,!1,void 0,this)},void 0,!1,void 0,this),Q?.map((W,N)=>$(hJ,{entry:W},N,!1,void 0,this)),J?.trim()?Y&&Z?$(U,{color:G.text,children:[J.trim(),$(U,{color:G.amber,children:"▌"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):$(x,{content:J.trim()},void 0,!1,void 0,this):Y&&Z?$(U,{color:G.amber,children:"▌"},void 0,!1,void 0,this):null,!Z&&q&&$(IJ,{stats:q},void 0,!1,void 0,this)]},void 0,!0,void 0,this);function vJ(){let J=[];for(let X of E){J.push({providerId:X.id,providerLabel:X.label,modelId:"",modelLabel:"",isHeader:!0});for(let Q of X.models)J.push({providerId:X.id,providerLabel:X.label,modelId:Q.id,modelLabel:Q.label,isHeader:!1})}return J}var r=vJ(),v=r.filter((J)=>!J.isHeader),bJ=({current:J,onSelect:X})=>{let Q=v.findIndex((W)=>W.providerId===J.providerId&&W.modelId===J.modelId),[Y,Z]=I(Math.max(0,Q));o((W,N)=>{if(N.upArrow)Z((z)=>(z-1+v.length)%v.length);if(N.downArrow)Z((z)=>(z+1)%v.length);if(N.return){let z=v[Y];X({providerId:z.providerId,modelId:z.modelId})}});let q=v[Y];return $(F,{flexDirection:"column",marginBottom:1,children:r.map((W,N)=>W.isHeader?$(U,{color:G.label,children:" "+W.providerLabel},N,!1,void 0,this):$(F,{children:$(U,{color:W.providerId===q.providerId&&W.modelId===q.modelId?G.amber:G.textDim,children:[W.providerId===q.providerId&&W.modelId===q.modelId?" ❯ ":" ",W.modelLabel,W.providerId===J.providerId&&W.modelId===J.modelId?$(U,{color:G.label,children:" (active)"},void 0,!1,void 0,this):""]},void 0,!0,void 0,this)},N,!1,void 0,this))},void 0,!1,void 0,this)},kJ=()=>{let[J,X]=I(""),[Q,Y]=I([]),[Z,q]=I(!1),[W,N]=I(yJ),[z,h]=I(!1),[A,_]=I(0),b=J.startsWith("/"),P=b?l.filter((H)=>H.cmd.startsWith(J)):[],a=Math.max(...l.map((H)=>H.cmd.length));o((H,R)=>{if(R.escape){if(z){h(!1);return}process.exit(0)}if(P.length>0){if(R.upArrow){_((S)=>(S-1+P.length)%P.length);return}if(R.downArrow){_((S)=>(S+1)%P.length);return}if(R.return){let S=P[A]?.cmd;if(S)j(S);return}}});let j=(H)=>{if(X(""),_(0),H==="/models")h(!0)},n=async(H)=>{if(Z)return;if(P.length>0){let L=P[A]?.cmd;if(L)j(L);return}if(b){j(H.trim());return}if(!H.trim())return;X("");let R={role:"user",content:H},S=[...Q,R];Y([...S,{role:"assistant",content:""}]),q(!0);try{let{stream:L,stats:p}=c(S,W);for await(let O of L)Y((y)=>{let B=[...y],w=B[B.length-1];if(!w||w.role!=="assistant")return y;if(O.type==="text")return[...B.slice(0,-1),{...w,content:w.content+O.delta}];if(O.type==="reasoning")return[...B.slice(0,-1),{...w,reasoning:(w.reasoning??"")+O.delta}];if(O.type==="tool-call")return[...B.slice(0,-1),{...w,toolCalls:[...w.toolCalls??[],{toolName:O.toolName,args:O.args}]}];if(O.type==="tool-result"){let T=[...w.toolCalls??[]],D=-1;for(let C=T.length-1;C>=0;C--)if(T[C].toolName===O.toolName&&T[C].result===void 0){D=C;break}if(D>=0)T[D]={...T[D],result:O.result};return[...B.slice(0,-1),{...w,toolCalls:T}]}return y});let k=await p;Y((O)=>{let y=[...O],B=y[y.length-1];if(B?.role==="assistant")y[y.length-1]={...B,stats:k};return y})}catch(L){Y((p)=>{let k=[...p];return k[k.length-1]={role:"assistant",content:`ERR: ${L instanceof Error?L.message:String(L)}`},k})}finally{q(!1)}},i=(H)=>{X(H),_(0)};return $(F,{flexDirection:"column",paddingX:1,paddingTop:1,children:[$(LJ,{selectionLabel:BJ(W)},void 0,!1,void 0,this),Q.map((H,R)=>H.role==="user"?$(MJ,{content:H.content},R,!1,void 0,this):$(TJ,{content:H.content,reasoning:H.reasoning,toolCalls:H.toolCalls,isLast:R===Q.length-1,streaming:Z,stats:H.stats},R,!1,void 0,this)),z&&$(bJ,{current:W,onSelect:(H)=>{N(H),h(!1)}},void 0,!1,void 0,this),P.length>0&&$(F,{flexDirection:"column",marginBottom:1,children:P.map((H,R)=>$(F,{children:$(U,{color:R===A?G.amber:G.textDim,children:[R===A?" ❯ ":" ",$(U,{bold:R===A,children:H.cmd.padEnd(a)},void 0,!1,void 0,this)," ",$(U,{color:G.label,children:H.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},H.cmd,!1,void 0,this))},void 0,!1,void 0,this),$(F,{borderStyle:"single",borderTop:!0,borderBottom:!1,borderLeft:!1,borderRight:!1,borderColor:G.border},void 0,!1,void 0,this),$(F,{children:[$(U,{color:G.amber,children:"❯ "},void 0,!1,void 0,this),$(F,{flexGrow:1,children:$(U,{color:b?G.amber:void 0,children:$(AJ,{value:J,onChange:i,onSubmit:n,placeholder:z?"↑↓ navigate enter select esc cancel":Z?"waiting...":"type here..."},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$(F,{borderStyle:"single",borderTop:!0,borderBottom:!1,borderLeft:!1,borderRight:!1,borderColor:G.border},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};fJ($(kJ,{},void 0,!1,void 0,this));
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@tosh99/navi-cli",
3
+ "version": "0.1.0",
4
+ "description": "A terminal AI chat CLI with multi-provider support",
5
+ "author": "Anutosh Chaudhuri <anutosh.chaudhuri@gmail.com>",
6
+ "license": "MIT",
7
+ "module": "src/cli.tsx",
8
+ "type": "module",
9
+ "bin": {
10
+ "navi": "dist/cli.js"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "scripts": {
16
+ "build": "bun scripts/build.ts",
17
+ "prepublishOnly": "bun run build"
18
+ },
19
+ "devDependencies": {
20
+ "@types/bun": "latest",
21
+ "@types/react": "^19.2.14",
22
+ "prettier": "^3.8.1"
23
+ },
24
+ "peerDependencies": {
25
+ "typescript": "^5"
26
+ },
27
+ "dependencies": {
28
+ "@ai-sdk/openai": "^3.0.50",
29
+ "@openrouter/ai-sdk-provider": "^2.3.3",
30
+ "ai": "6",
31
+ "ink": "^6.8.0",
32
+ "ink-text-input": "^6.0.0",
33
+ "react": "^19.2.4",
34
+ "vercel-minimax-ai-provider": "^0.0.2",
35
+ "zhipu-ai-provider": "^0.3.0"
36
+ }
37
+ }