@tosh99/navi-cli 0.1.0 → 0.1.2
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/README.md +52 -5
- package/dist/cli.js +13 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,15 +1,62 @@
|
|
|
1
1
|
# navi-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A terminal AI chat CLI with multi-provider support. Ask questions, work with files, run code, and switch between AI models — all from your terminal.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
[Bun](https://bun.sh) (v1.3.11 or higher)
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -g @tosh99/navi-cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
Create a `navi.jsonc` file in your project directory:
|
|
18
|
+
|
|
19
|
+
```jsonc
|
|
20
|
+
{
|
|
21
|
+
"DEFAULT_MODEL_PROVIDER": "minimax",
|
|
22
|
+
"DEFAULT_MODEL": "MiniMax-M2.5",
|
|
23
|
+
"API_KEY_MINIMAX": "your-api-key"
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Available Providers
|
|
28
|
+
|
|
29
|
+
| Provider | Models |
|
|
30
|
+
|----------------|------------------------------------------|
|
|
31
|
+
| **OpenRouter** | Kimi K2.5, GPT-4o Mini, Claude 3.5 Haiku |
|
|
32
|
+
| **ZhipuAI** | GLM-4.5, GLM-4.5 Flash, GLM Z1 Flash |
|
|
33
|
+
| **MiniMax** | M2.7, M2.5 |
|
|
34
|
+
|
|
35
|
+
### Environment Variables
|
|
36
|
+
|
|
37
|
+
You can also set API keys via environment variables instead of the config file:
|
|
4
38
|
|
|
5
39
|
```bash
|
|
6
|
-
|
|
40
|
+
export OPENROUTER_API_KEY="your-key"
|
|
41
|
+
export ZHIPU_API_KEY="your-key"
|
|
42
|
+
export MINIMAX_API_KEY="your-key"
|
|
7
43
|
```
|
|
8
44
|
|
|
9
|
-
|
|
45
|
+
## Usage
|
|
10
46
|
|
|
11
47
|
```bash
|
|
12
|
-
|
|
48
|
+
navi
|
|
13
49
|
```
|
|
14
50
|
|
|
15
|
-
|
|
51
|
+
- Type your message and press **Enter** to send
|
|
52
|
+
- Type `/models` to switch AI models
|
|
53
|
+
- Use **↑/↓** arrows to navigate suggestions
|
|
54
|
+
- Press **Esc** to quit
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install -g @tosh99/navi-cli
|
|
60
|
+
echo '{"DEFAULT_MODEL_PROVIDER": "minimax", "DEFAULT_MODEL": "MiniMax-M2.5", "API_KEY_MINIMAX": "your-key"}' > navi.jsonc
|
|
61
|
+
navi
|
|
62
|
+
```
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{useState as
|
|
3
|
-
${
|
|
4
|
-
${
|
|
5
|
-
`)
|
|
2
|
+
import{useEffect as iJ,useRef as JJ,useState as h}from"react";import{Box as L,render as tJ,Text as A,useInput as FJ}from"ink";import sJ from"ink-text-input";import{readFileSync as PJ}from"fs";import{join as BJ}from"path";var MJ={providerId:"minimax",modelId:"MiniMax-M2.5"};function LJ(X){return X.replace(/("(?:[^"\\]|\\.)*")|\/\/[^\n]*/g,(Y,$)=>$??"").replace(/("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g,(Y,$)=>$??"")}function yJ(){for(let X of["navi.jsonc","navi.json"])try{let Y=PJ(BJ(process.cwd(),X),"utf-8");return JSON.parse(LJ(Y))}catch{}return{}}var wJ=yJ();function n(X){return wJ[X]||process.env[X]||void 0}var IJ=[["API_KEY_OPENROUTER","OPENROUTER_API_KEY"],["API_KEY_ZHIPU","ZHIPU_API_KEY"],["API_KEY_MINIMAX","MINIMAX_API_KEY"]];for(let[X,Y]of IJ){let $=n(X);if($)process.env[Y]??=$}function YJ(){let X=n("DEFAULT_MODEL_PROVIDER"),Y=n("DEFAULT_MODEL");if(X&&Y)return{providerId:X,modelId:Y};return MJ}import{stepCountIs as SJ,streamText as fJ,tool as V}from"ai";import{openrouter as vJ}from"@openrouter/ai-sdk-provider";import{createZhipu as kJ}from"zhipu-ai-provider";import{createMinimax as TJ}from"vercel-minimax-ai-provider";import{exec as CJ}from"child_process";import{mkdirSync as i,renameSync as VJ,rmSync as DJ}from"fs";import{dirname as t,join as hJ,resolve as D}from"path";import{promisify as bJ}from"util";import{z as F}from"zod";var jJ=bJ(CJ),gJ={bash:V({description:"Run a bash/shell command and return stdout/stderr. Use for file operations, running scripts, checking system info, etc.",inputSchema:F.object({command:F.string().describe("The shell command to execute")}),execute:async({command:X})=>{try{let{stdout:Y,stderr:$}=await jJ(X,{timeout:30000});return(Y||$||"(no output)").slice(0,8000)}catch(Y){return`Error: ${Y.message}
|
|
3
|
+
${Y.stdout??""}
|
|
4
|
+
${Y.stderr??""}`.trim().slice(0,8000)}}}),glob:V({description:"Find files matching a glob pattern. Returns matching file paths.",inputSchema:F.object({pattern:F.string().describe("Glob pattern, e.g. 'src/**/*.ts'"),cwd:F.string().optional().describe("Base directory to search from (defaults to current working directory)")}),execute:async({pattern:X,cwd:Y})=>{try{let $=Y?D(Y):process.cwd(),J=new Bun.Glob(X),U=[];for await(let K of J.scan({cwd:$,onlyFiles:!0}))U.push(K);if(U.length===0)return"No files found.";return U.join(`
|
|
5
|
+
`).slice(0,8000)}catch($){return`Error: ${$.message}`}}}),grep:V({description:"Search file contents for a regex pattern. Returns matching lines with file:line format.",inputSchema:F.object({pattern:F.string().describe("Regex pattern to search for"),path:F.string().optional().describe("Directory or file to search in (defaults to cwd)"),fileGlob:F.string().optional().describe("Glob to filter files, e.g. '**/*.ts' (defaults to all files)")}),execute:async({pattern:X,path:Y,fileGlob:$})=>{try{let J=Y?D(Y):process.cwd(),U=new Bun.Glob($??"**/*"),K=new RegExp(X),H=[];for await(let O of U.scan({cwd:J,onlyFiles:!0})){let _=hJ(J,O);try{let w=(await Bun.file(_).text()).split(`
|
|
6
|
+
`);for(let Q=0;Q<w.length;Q++)if(K.test(w[Q])){if(H.push(`${O}:${Q+1}: ${w[Q]}`),H.join(`
|
|
7
|
+
`).length>7800)return H.push("... (truncated)"),H.join(`
|
|
8
|
+
`)}}catch{}}return H.length?H.join(`
|
|
9
|
+
`):"No matches found."}catch(J){return`Error: ${J.message}`}}}),read_file:V({description:"Read the contents of a file. Optionally limit to a range of lines.",inputSchema:F.object({path:F.string().describe("Path to the file"),offset:F.number().int().optional().describe("Line number to start reading from (1-based)"),limit:F.number().int().optional().describe("Maximum number of lines to read")}),execute:async({path:X,offset:Y,limit:$})=>{try{let J=D(X),U=(await Bun.file(J).text()).split(`
|
|
10
|
+
`),K=Y?Y-1:0;return($!==void 0?U.slice(K,K+$):U.slice(K)).map((O,_)=>`${K+_+1} ${O}`).join(`
|
|
11
|
+
`).slice(0,8000)}catch(J){return`Error: ${J.message}`}}}),sync_file:V({description:"Write, append to, or delete a file. Creates missing parent directories as needed.",inputSchema:F.object({path:F.string().describe("Path to the file"),content:F.string().optional().describe("Content to write or append (not required for delete)"),mode:F.enum(["replace","append","delete"]).optional().describe("'replace' (default) overwrites, 'append' adds to end, 'delete' removes the file")}),execute:async({path:X,content:Y="",mode:$="replace"})=>{try{let J=D(X);if($==="delete")return DJ(J,{force:!0}),`Deleted ${X}`;if(i(t(J),{recursive:!0}),$==="append"){let U=await Bun.file(J).exists()?await Bun.file(J).text():"";return await Bun.write(J,U+Y),`Appended ${Y.length} chars to ${X}`}return await Bun.write(J,Y),`Written ${Y.length} chars to ${X}`}catch(J){return`Error: ${J.message}`}}}),copy_file:V({description:"Copy a file from source to destination, creating missing parent directories.",inputSchema:F.object({src:F.string().describe("Source file path"),dest:F.string().describe("Destination file path")}),execute:async({src:X,dest:Y})=>{try{let $=D(Y);return i(t($),{recursive:!0}),await Bun.write($,Bun.file(D(X))),`Copied ${X} → ${Y}`}catch($){return`Error: ${$.message}`}}}),move_file:V({description:"Move (rename) a file, creating missing parent directories at the destination.",inputSchema:F.object({src:F.string().describe("Source file path"),dest:F.string().describe("Destination file path")}),execute:async({src:X,dest:Y})=>{try{let $=D(Y);return i(t($),{recursive:!0}),VJ(D(X),$),`Moved ${X} → ${Y}`}catch($){return`Error: ${$.message}`}}}),patch_file:V({description:"Replace an exact string in a file with new content. Fails if old_str is not found or appears more than once.",inputSchema:F.object({path:F.string().describe("Path to the file"),old_str:F.string().describe("Exact string to find and replace (must be unique in the file)"),new_str:F.string().describe("Replacement string")}),execute:async({path:X,old_str:Y,new_str:$})=>{try{let J=D(X),U=await Bun.file(J).text(),K=U.split(Y).length-1;if(K===0)return`Error: old_str not found in ${X}`;if(K>1)return`Error: old_str found ${K} times — provide more context to make it unique`;return await Bun.write(J,U.replace(Y,$)),`Patched ${X}`}catch(J){return`Error: ${J.message}`}}}),ask_user_question:V({description:"Ask the user a clarifying question. The stream will end and the user will type their answer as the next message.",inputSchema:F.object({question:F.string().describe("The question to ask the user")}),execute:async({question:X})=>X})},s=[{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"}]}],EJ=kJ({baseURL:"https://api.z.ai/api/coding/paas/v4"}),mJ=TJ();function uJ(X,Y){switch(X){case"openrouter":return vJ(Y);case"zhipu":return EJ(Y,{thinking:{type:"enabled"}});case"minimax":return mJ(Y);default:throw Error(`Unknown provider: ${X}`)}}function pJ(X){switch(X){case"openrouter":return{openrouter:{reasoning:{effort:"high"},provider:{order:["BaseTen","ModelRun"]}}};case"zhipu":return{zhipu:{thinking:{type:"enabled"}}};default:return{}}}function $J(X,Y){let $=Date.now(),J=fJ({model:uJ(Y.providerId,Y.modelId),messages:X,tools:gJ,stopWhen:SJ(50),providerOptions:pJ(Y.providerId)}),U=Promise.resolve(J.usage).then((H)=>{let O=Date.now()-$,_=H.outputTokens??0;return{elapsedMs:O,tokensPerSec:O>0?Math.round(_/O*1000):0,inputTokens:H.inputTokens??0,outputTokens:_}});async function*K(){for await(let H of J.fullStream)if(H.type==="text-delta")yield{type:"text",delta:H.text};else if(H.type==="reasoning-delta")yield{type:"reasoning",delta:H.text};else if(H.type==="tool-call")yield{type:"tool-call",toolName:H.toolName,args:H.input};else if(H.type==="tool-result"){if(H.toolName==="ask_user_question"){yield{type:"ask-user",question:String(H.output)};return}yield{type:"tool-result",toolName:H.toolName,result:String(H.output)}}}return{stream:K(),stats:U}}import HJ from"react";import{Box as S,Text as z}from"ink";import{jsxDEV as q,Fragment as rJ}from"react/jsx-dev-runtime";function g(X){let Y=[],$=/(~~[^~]+~~|`[^`]+`|\*\*[^*]+\*\*|\*[^*\n]+\*|_[^_\n]+_)/g,J=0;for(let U of X.matchAll($)){if(U.index>J)Y.push({t:X.slice(J,U.index)});let K=U[0];if(K.startsWith("~~"))Y.push({t:K.slice(2,-2),strike:!0});else if(K.startsWith("`"))Y.push({t:K.slice(1,-1),code:!0});else if(K.startsWith("**"))Y.push({t:K.slice(2,-2),bold:!0});else Y.push({t:K.slice(1,-1),italic:!0});J=U.index+K.length}if(J<X.length)Y.push({t:X.slice(J)});return Y.filter((U)=>U.t)}var x=({segs:X,dim:Y})=>q(rJ,{children:X.map(($,J)=>$.code?q(z,{color:"#e8b86d",backgroundColor:"#2a2a2a",children:[" ",$.t," "]},J,!0,void 0,this):q(z,{bold:$.bold,italic:$.italic,strikethrough:$.strike,dimColor:Y,children:$.t},J,!1,void 0,this))},void 0,!1,void 0,this);function c(X){return X.map((Y)=>Y.t).join("")}function e(X){let Y=0;for(let $ of X){let J=$.codePointAt(0)??0;if(J>=4352&&J<=4447||J>=9001&&J<=9002||J>=9728&&J<=10175||J>=11904&&J<=13311||J>=13312&&J<=19903||J>=19968&&J<=40959||J>=40960&&J<=42191||J>=44032&&J<=55215||J>=63744&&J<=64255||J>=65040&&J<=65135||J>=65280&&J<=65376||J>=65504&&J<=65510||J>=126980&&J<=129791||J>=131072&&J<=262141)Y+=2;else Y+=1}return Y}function UJ(X){return X.split("|").slice(1,-1).map((Y)=>g(Y.trim()))}function dJ(X){return X.split("|").slice(1,-1).map((Y)=>{let $=Y.trim();if($.startsWith(":")&&$.endsWith(":"))return"center";if($.endsWith(":"))return"right";if($.startsWith(":"))return"left";return null})}function xJ(X){let Y=X.split(`
|
|
12
|
+
`),$=[],J=0;while(J<Y.length){let U=Y[J],K=U.match(/^(`{3,}|~{3,})\s*(\S*)/);if(K){let G=K[1],P=K[2]??"",R=[];J++;while(J<Y.length&&!Y[J].startsWith(G.slice(0,3)))R.push(Y[J]),J++;$.push({k:"code",lang:P,lines:R}),J++;continue}let H=U.match(/^(#{1,6})\s+(.+)/);if(H){$.push({k:"h",level:H[1].length,segs:g(H[2])}),J++;continue}if(/^[-*_]{3,}\s*$/.test(U)){$.push({k:"hr"}),J++;continue}if(U.startsWith("|")){let G=[];while(J<Y.length&&Y[J].trimEnd().startsWith("|"))G.push(Y[J]),J++;let P=G.findIndex((R)=>/^\|[\s|:\-]+\|?\s*$/.test(R));if(P>=1&&G[0]){let R=UJ(G[0]),k=dJ(G[P]),j=G.slice(P+1).map(UJ);$.push({k:"table",headers:R,rows:j,aligns:k})}else for(let R of G)$.push({k:"p",segs:g(R)});continue}let O=U.match(/^(\s*)[*\-+]\s+(.+)/);if(O){let G=Math.floor(O[1].length/2);$.push({k:"li",ordered:!1,n:0,depth:G,segs:g(O[2])}),J++;continue}let _=U.match(/^(\s*)(\d+)\.\s+(.+)/);if(_){let G=Math.floor(_[1].length/2);$.push({k:"li",ordered:!0,n:parseInt(_[2],10),depth:G,segs:g(_[3])}),J++;continue}let w=U.match(/^>\s?(.*)/);if(w){$.push({k:"bq",segs:g(w[1])}),J++;continue}if(U.trim()===""){J++;continue}let Q=[];while(J<Y.length){let G=Y[J];if(G.trim()===""||/^#{1,6}\s/.test(G)||/^(`{3,}|~{3,})/.test(G)||/^[-*_]{3,}\s*$/.test(G)||/^\s*[*\-+]\s/.test(G)||/^\s*\d+\.\s/.test(G)||/^>\s/.test(G)||G.startsWith("|"))break;Q.push(G),J++}if(Q.length)$.push({k:"p",segs:g(Q.join(" "))})}return $}var cJ=["#ffcc77","#ffb347","#e8a020","#cc8800","#aa6600","#886600"],lJ=({lang:X,lines:Y})=>q(S,{flexDirection:"column",marginY:1,paddingX:1,borderStyle:"single",borderColor:"#3a3a3a",children:[X?q(z,{color:"#555555",dimColor:!0,children:X},void 0,!1,void 0,this):null,Y.map(($,J)=>q(z,{color:"#d4c5a9",children:$},J,!1,void 0,this))]},void 0,!0,void 0,this),oJ=({headers:X,rows:Y,aligns:$})=>{let J=X.length,U=Array.from({length:J},(Q,G)=>{let P=e(c(X[G]??[])),R=Y.reduce((k,j)=>Math.max(k,e(c(j[G]??[]))),0);return Math.max(P,R,3)});function K(Q,G,P){let R=G-e(Q);if(P==="right")return" "+" ".repeat(R)+Q+" ";if(P==="center"){let k=Math.floor(R/2),j=R-k;return" "+" ".repeat(k)+Q+" ".repeat(j)+" "}return" "+Q+" ".repeat(R)+" "}let H="#3a3a3a",O="┌"+U.map((Q)=>"─".repeat(Q+2)).join("┬")+"┐",_="├"+U.map((Q)=>"─".repeat(Q+2)).join("┼")+"┤",w="└"+U.map((Q)=>"─".repeat(Q+2)).join("┴")+"┘";return q(S,{flexDirection:"column",marginY:1,children:[q(z,{color:H,children:O},void 0,!1,void 0,this),q(S,{children:[q(z,{color:H,children:"│"},void 0,!1,void 0,this),U.map((Q,G)=>q(HJ.Fragment,{children:[q(z,{bold:!0,color:"#ffb347",children:K(c(X[G]??[]),Q,$[G]??null)},void 0,!1,void 0,this),q(z,{color:H,children:"│"},void 0,!1,void 0,this)]},G,!0,void 0,this))]},void 0,!0,void 0,this),q(z,{color:H,children:_},void 0,!1,void 0,this),Y.map((Q,G)=>q(S,{children:[q(z,{color:H,children:"│"},void 0,!1,void 0,this),U.map((P,R)=>q(HJ.Fragment,{children:[q(z,{color:"#aaaaaa",children:K(c(Q[R]??[]),P,$[R]??null)},void 0,!1,void 0,this),q(z,{color:H,children:"│"},void 0,!1,void 0,this)]},R,!0,void 0,this))]},G,!0,void 0,this)),q(z,{color:H,children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},ZJ=({content:X})=>{let Y=xJ(X);return q(S,{flexDirection:"column",children:Y.map(($,J)=>{let U=Y[J+1],K=$.k==="li"&&U?.k!=="li";if($.k==="code")return q(lJ,{lang:$.lang,lines:$.lines},J,!1,void 0,this);if($.k==="table")return q(oJ,{headers:$.headers,rows:$.rows,aligns:$.aligns},J,!1,void 0,this);if($.k==="hr")return q(S,{marginBottom:1,children:q(z,{color:"#3a3a3a",children:"─".repeat(40)},void 0,!1,void 0,this)},J,!1,void 0,this);if($.k==="h")return q(S,{marginBottom:1,children:q(z,{color:cJ[$.level-1],bold:!0,children:q(x,{segs:$.segs},void 0,!1,void 0,this)},void 0,!1,void 0,this)},J,!1,void 0,this);if($.k==="li")return q(S,{marginBottom:K?1:0,children:[q(z,{color:"#555555",children:[" ".repeat($.depth),$.ordered?`${$.n}. `:"• "]},void 0,!0,void 0,this),q(S,{flexGrow:1,children:q(z,{color:"#aaaaaa",children:q(x,{segs:$.segs},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},J,!0,void 0,this);if($.k==="bq")return q(S,{marginBottom:1,borderStyle:"single",borderLeft:!0,borderRight:!1,borderTop:!1,borderBottom:!1,borderColor:"#555555",paddingLeft:1,children:q(z,{color:"#777777",italic:!0,children:q(x,{segs:$.segs,dim:!0},void 0,!1,void 0,this)},void 0,!1,void 0,this)},J,!1,void 0,this);return q(S,{marginBottom:1,children:q(z,{color:"#aaaaaa",wrap:"wrap",children:q(x,{segs:$.segs},void 0,!1,void 0,this)},void 0,!1,void 0,this)},J,!1,void 0,this)})},void 0,!1,void 0,this)};import{mkdirSync as aJ,writeFileSync as nJ}from"fs";import{join as GJ}from"path";var KJ=GJ(process.cwd(),".navi","sessions");function qJ(){let X=new Date().toISOString();return{id:X.replace(/:/g,"-").replace(/\./g,"-"),createdAt:X}}function QJ(X){aJ(KJ,{recursive:!0});let Y=GJ(KJ,`${X.id}.json`);nJ(Y,JSON.stringify(X,null,2))}import{jsxDEV as Z}from"react/jsx-dev-runtime";var W={border:"#3a3a3a",label:"#555555",text:"#aaaaaa",textDim:"#444444",amber:"#ffb347",amberGlow:"#ffcc77",amberDim:"#7a4f00",meta:"#3d3d3d"},WJ=[{cmd:"/models",description:"switch model"}],eJ=["███╗ ██╗ █████╗ ██╗ ██╗██╗","████╗ ██║██╔══██╗██║ ██║██║","██╔██╗ ██║███████║██║ ██║██║","██║╚██╗██║██╔══██║╚██╗ ██╔╝██║","██║ ╚████║██║ ██║ ╚████╔╝ ██║","╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═══╝ ╚═╝"],JX=YJ();function XX(X){let Y=s.find((J)=>J.id===X.providerId),$=Y?.models.find((J)=>J.id===X.modelId);return $?`${Y.label} / ${$.label}`:X.modelId}var YX=({selectionLabel:X})=>Z(L,{flexDirection:"column",marginBottom:1,children:[eJ.map((Y,$)=>{let J=$===0?W.amberGlow:$<3?W.amber:$<5?W.amberDim:W.meta;return Z(A,{color:J,children:Y},$,!1,void 0,this)}),Z(A,{color:W.textDim,children:["v0.1.0 · ",Z(A,{color:W.label,children:X},void 0,!1,void 0,this),Z(A,{color:W.textDim,children:" · esc to quit"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),$X=({content:X})=>Z(L,{flexDirection:"column",marginBottom:1,children:Z(A,{color:W.amber,children:X},void 0,!1,void 0,this)},void 0,!1,void 0,this),HX=({stats:X})=>Z(A,{color:W.meta,dimColor:!0,children:[(X.elapsedMs/1000).toFixed(1),"s · ",X.tokensPerSec," tok/s · ↑",X.inputTokens," ↓",X.outputTokens]},void 0,!0,void 0,this),UX=({entry:X})=>Z(L,{flexDirection:"column",marginBottom:1,children:[Z(A,{color:W.amber,children:["⚙ ",Z(A,{bold:!0,children:X.toolName},void 0,!1,void 0,this),Z(A,{color:W.label,children:" "+JSON.stringify(X.args)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X.result!==void 0&&Z(A,{color:W.textDim,dimColor:!0,children:X.result.slice(0,400)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),ZX=({content:X,reasoning:Y,toolCalls:$,isLast:J,streaming:U,stats:K})=>Z(L,{flexDirection:"column",marginBottom:1,children:[Y&&Z(L,{marginBottom:1,children:Z(A,{color:W.textDim,dimColor:!0,children:Y?.trim()},void 0,!1,void 0,this)},void 0,!1,void 0,this),$?.map((H,O)=>Z(UX,{entry:H},O,!1,void 0,this)),X?.trim()?J&&U?Z(A,{color:W.text,children:[X.trim(),Z(A,{color:W.amber,children:"▌"},void 0,!1,void 0,this)]},void 0,!0,void 0,this):Z(ZJ,{content:X.trim()},void 0,!1,void 0,this):J&&U?Z(A,{color:W.amber,children:"▌"},void 0,!1,void 0,this):null,!U&&K&&Z(HX,{stats:K},void 0,!1,void 0,this)]},void 0,!0,void 0,this),NJ=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function KX(){let X=[];for(let Y of s){X.push({providerId:Y.id,providerLabel:Y.label,modelId:"",modelLabel:"",isHeader:!0});for(let $ of Y.models)X.push({providerId:Y.id,providerLabel:Y.label,modelId:$.id,modelLabel:$.label,isHeader:!1})}return X}var OJ=KX(),m=OJ.filter((X)=>!X.isHeader),GX=({current:X,onSelect:Y})=>{let $=m.findIndex((H)=>H.providerId===X.providerId&&H.modelId===X.modelId),[J,U]=h(Math.max(0,$));FJ((H,O)=>{if(O.upArrow)U((_)=>(_-1+m.length)%m.length);if(O.downArrow)U((_)=>(_+1)%m.length);if(O.return){let _=m[J];Y({providerId:_.providerId,modelId:_.modelId})}});let K=m[J];return Z(L,{flexDirection:"column",marginBottom:1,children:OJ.map((H,O)=>H.isHeader?Z(A,{color:W.label,children:" "+H.providerLabel},O,!1,void 0,this):Z(L,{children:Z(A,{color:H.providerId===K.providerId&&H.modelId===K.modelId?W.amber:W.textDim,children:[H.providerId===K.providerId&&H.modelId===K.modelId?" ❯ ":" ",H.modelLabel,H.providerId===X.providerId&&H.modelId===X.modelId?Z(A,{color:W.label,children:" (active)"},void 0,!1,void 0,this):""]},void 0,!0,void 0,this)},O,!1,void 0,this))},void 0,!1,void 0,this)},qX=()=>{let[X,Y]=h(""),[$,J]=h([]),[U,K]=h(!1),[H,O]=h(JX),[_,w]=h(!1),[Q,G]=h(0),[P,R]=h(null),k=JJ(null),[j,_J]=h(0);iJ(()=>{if(!U)return;let N=setInterval(()=>_J((B)=>(B+1)%NJ.length),80);return()=>clearInterval(N)},[U]);let l=JJ(null),XJ=JJ([]),d=(N)=>{J((B)=>{let I=N(B);return XJ.current=I,I})},o=X.startsWith("/"),T=o?WJ.filter((N)=>N.cmd.startsWith(X)):[],AJ=Math.max(...WJ.map((N)=>N.cmd.length));FJ((N,B)=>{if(B.escape){if(_){w(!1);return}process.exit(0)}if(T.length>0){if(B.upArrow){G((I)=>(I-1+T.length)%T.length);return}if(B.downArrow){G((I)=>(I+1)%T.length);return}if(B.return){let I=T[Q]?.cmd;if(I)r(I);return}}});let r=(N)=>{if(Y(""),G(0),N==="/models")w(!0)},RJ=async(N)=>{if(U)return;if(P!==null)R(null),k.current=null;if(T.length>0){let b=T[Q]?.cmd;if(b)r(b);return}if(o){r(N.trim());return}if(!N.trim())return;if(Y(""),!l.current)l.current=qJ();let B={role:"user",content:N},I=[...$,B];d(()=>[...I,{role:"assistant",content:""}]),K(!0);try{let{stream:b,stats:a}=$J(I,H);for await(let M of b)if(d((C)=>{let f=[...C],y=f[f.length-1];if(!y||y.role!=="assistant")return C;if(M.type==="text")return[...f.slice(0,-1),{...y,content:y.content+M.delta}];if(M.type==="reasoning")return[...f.slice(0,-1),{...y,reasoning:(y.reasoning??"")+M.delta}];if(M.type==="tool-call")return[...f.slice(0,-1),{...y,toolCalls:[...y.toolCalls??[],{toolName:M.toolName,args:M.args}]}];if(M.type==="tool-result"){let v=[...y.toolCalls??[]],E=-1;for(let p=v.length-1;p>=0;p--)if(v[p].toolName===M.toolName&&v[p].result===void 0){E=p;break}if(E>=0)v[E]={...v[E],result:M.result};return[...f.slice(0,-1),{...y,toolCalls:v}]}if(M.type==="ask-user"){let v=M.question;k.current=v,R(v);let E={...y,content:y.content+(y.content.trim()?`
|
|
13
|
+
|
|
14
|
+
`:"")+v};return[...f.slice(0,-1),E]}return C}),M.type==="ask-user")break;let u=await a;d((M)=>{let C=[...M],f=C[C.length-1];if(f?.role==="assistant")C[C.length-1]={...f,stats:u};return C})}catch(b){d((a)=>{let u=[...a];return u[u.length-1]={role:"assistant",content:`ERR: ${b instanceof Error?b.message:String(b)}`},u})}finally{K(!1),QJ({...l.current,model:H,messages:XJ.current})}},zJ=(N)=>{Y(N),G(0)};return Z(L,{flexDirection:"column",paddingX:1,paddingTop:1,children:[Z(YX,{selectionLabel:XX(H)},void 0,!1,void 0,this),$.map((N,B)=>N.role==="user"?Z($X,{content:N.content},B,!1,void 0,this):Z(ZX,{content:N.content,reasoning:N.reasoning,toolCalls:N.toolCalls,isLast:B===$.length-1,streaming:U,stats:N.stats},B,!1,void 0,this)),_&&Z(GX,{current:H,onSelect:(N)=>{O(N),w(!1)}},void 0,!1,void 0,this),T.length>0&&Z(L,{flexDirection:"column",marginBottom:1,children:T.map((N,B)=>Z(L,{children:Z(A,{color:B===Q?W.amber:W.textDim,children:[B===Q?" ❯ ":" ",Z(A,{bold:B===Q,children:N.cmd.padEnd(AJ)},void 0,!1,void 0,this)," ",Z(A,{color:W.label,children:N.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},N.cmd,!1,void 0,this))},void 0,!1,void 0,this),Z(L,{borderStyle:"single",borderTop:!0,borderBottom:!1,borderLeft:!1,borderRight:!1,borderColor:W.border},void 0,!1,void 0,this),P!==null&&Z(L,{marginBottom:1,children:[Z(A,{color:W.amber,children:"? "},void 0,!1,void 0,this),Z(A,{color:W.amberGlow,children:P},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z(L,{children:[Z(A,{color:P!==null?W.amberGlow:W.amber,children:"❯ "},void 0,!1,void 0,this),Z(L,{flexGrow:1,children:Z(A,{color:o?W.amber:void 0,children:Z(sJ,{value:X,onChange:zJ,onSubmit:RJ,placeholder:_?"↑↓ navigate enter select esc cancel":U?NJ[j]??"⠋":P!==null?"type your answer...":"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),Z(L,{borderStyle:"single",borderTop:!0,borderBottom:!1,borderLeft:!1,borderRight:!1,borderColor:W.border},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};tJ(Z(qX,{},void 0,!1,void 0,this));
|