@mimocode/cli 3.0.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/dist/cli.js ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ var pn=Object.defineProperty;var i=(t,e)=>pn(t,"name",{value:e,configurable:!0}),No=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,n)=>(typeof require<"u"?require:e)[n]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var fn=(t,e)=>()=>(t&&(e=t(t=0)),e);var mn=(t,e)=>{for(var n in e)pn(t,n,{get:e[n],enumerable:!0})};var Zt={};mn(Zt,{buildBackend:()=>St,cleanupBackend:()=>hs,clearDaemonInfo:()=>lo,findAvailablePorts:()=>Xt,findInstallDir:()=>qt,findJar:()=>ve,findJava:()=>Vt,findMvn:()=>ao,findRunningDaemon:()=>Qt,isDaemonAlive:()=>uo,killPort:()=>st,portInUse:()=>We,readDaemonInfo:()=>co,startBackend:()=>gs,startDaemon:()=>zt,waitForBackend:()=>Yt,writeDaemonInfo:()=>yt});import{spawn as so,spawnSync as us,execSync as Pe}from"node:child_process";import{existsSync as xe,readdirSync as Gt,statSync as ps}from"node:fs";import{join as oe,dirname as Ft}from"node:path";import{homedir as Kt}from"node:os";import{fileURLToPath as fs}from"node:url";import{mkdirSync as xs,writeFileSync as ws,readFileSync as Ts,unlinkSync as bs}from"node:fs";function qt(){let t=oe(Jt,"..","backend","jwcode-web.jar");if(xe(t))return oe(Jt,"..");let e=oe(Jt,"..","..");for(;e!==Ft(e);){if(xe(oe(e,"pom.xml")))return e;e=Ft(e)}return process.cwd()}function ve(t){let e=oe(t,"backend","jwcode-web.jar");if(xe(e))return e;let n=oe(t,"jwcode-web","target","jwcode-web.jar");if(xe(n))return n;let o=oe(t,"jwcode-web","target");if(xe(o))try{let s=Gt(o).filter(c=>c.startsWith("jwcode-web")&&c.endsWith(".jar")).map(c=>({name:c,mtime:ps(oe(o,c)).mtimeMs})).sort((c,d)=>d.mtime-c.mtime);if(s.length>0)return oe(o,s[0].name)}catch{}return null}function ao(){let t=process.env.PATH?.split(";")||[];for(let e of t)for(let n of["mvn.cmd","mvn.bat","mvn"]){let o=oe(e,n);if(xe(o))return o}for(let e of["C:\\Program Files",Kt()])try{for(let n of Gt(e,{withFileTypes:!0}))if(n.isDirectory()&&n.name.startsWith("apache-maven")){let o=oe(e,n.name,"bin","mvn.cmd");if(xe(o))return o}}catch{}return"mvn"}function Vt(t){if(t){let n=oe(t,"backend","jre","bin",process.platform==="win32"?"java.exe":"java");if(xe(n))return n}let e=process.env.PATH?.split(";")||[];for(let n of e)for(let o of["java.exe","java"]){let s=oe(n,o);if(xe(s))return s}for(let n of["C:\\Program Files\\Java","C:\\Program Files (x86)\\Java",Kt()])try{for(let o of Gt(n,{withFileTypes:!0}))if(o.isDirectory()&&(o.name.startsWith("jdk")||o.name.startsWith("openjdk"))){let s=oe(n,o.name,"bin","java.exe");if(xe(s))return s}}catch{}return"java"}function St(t){let n=`"${ao()}" package -pl jwcode-web -am -q -DskipTests`;console.log(`[launcher] Building: ${n}`);try{let o=us(n,[],{cwd:t,stdio:"pipe",shell:!0,windowsHide:!0});if(o.status!==0)throw new Error(o.stderr.toString()||o.stdout.toString())}catch(o){console.error("[launcher] Build failed:",String(o)),process.exit(1)}ve(t)||(console.error("[launcher] Build succeeded but jar not found"),process.exit(1))}function We(t){try{return process.platform==="win32"?Pe(`netstat -ano | findstr :${t} | findstr LISTENING`,{encoding:"utf-8"}).trim().length>0:(Pe(`lsof -ti:${t}`,{stdio:"ignore"}),!0)}catch{return!1}}function Xt(t=8080,e=20){for(let n=t;n<t+e;n++){if(!We(n)&&!We(n+1))return{httpPort:n,wsPort:n+1};We(n+1)&&n++}throw new Error(`No available port pair found in range ${t}-${t+e}`)}function st(t){try{if(process.platform==="win32"){let e=Pe(`netstat -ano | findstr :${t} | findstr LISTENING`,{encoding:"utf-8"});for(let n of e.trim().split(`
3
+ `)){let o=n.trim().split(/\s+/).pop();if(o)try{Pe(`taskkill /F /PID ${o}`,{stdio:"ignore"}),console.log(`[launcher] Killed process on port ${t} (PID ${o})`)}catch{}}}else Pe(`lsof -ti:${t} | xargs kill -9 2>/dev/null`,{stdio:"ignore"})}catch{}}function Yt(t,e=60){let n=Date.now(),o=`http://localhost:${t}/api/system/status`;return new Promise(s=>{function c(){if(Date.now()-n>e*1e3){console.log(`[launcher] WARNING: Backend not responding after ${e}s`),s();return}fetch(o,{signal:AbortSignal.timeout(2e3)}).then(async d=>{let f=await d.text();d.status===200&&(f.includes("running")||f.includes("status"))?(console.log(`[launcher] Backend ready on port ${t}`),s()):setTimeout(c,1e3)}).catch(()=>setTimeout(c,1e3))}i(c,"check"),c()})}function gs(t){let{installDir:e,workspaceDir:n,port:o,wsPort:s,forceKill:c}=t,d=Vt(e),f=ve(e);f||(console.error("[launcher] Backend JAR not found. Run with --build first, or ensure backend/jwcode-web.jar exists."),process.exit(1)),c&&(st(o),st(s)),console.log(`[launcher] Starting backend: ${d} -jar ${f}`),console.log(`[launcher] Workspace: ${n}`);let m=["-jar",f,String(o),String(s),n],g=so(d,m,{cwd:n,env:{...process.env,JWCODE_WS_PORT:String(s)},stdio:["ignore","pipe","pipe"],windowsHide:!0});return g.stdout?.on("data",()=>{}),g.stderr?.on("data",w=>{let T=w.toString("utf-8").trim();T&&(T.includes("Address already in use")||T.includes("BindException"))&&console.error(`[backend] ERROR: Port ${o} is in use.`)}),g.on("exit",w=>{w!==0&&w!==null&&console.error(`[launcher] Backend process exited with code ${w}`)}),g}function hs(t){if(t)if(console.log(`
4
+ [jwcode] Shutting down...`),process.platform==="win32")try{Pe(`taskkill /F /T /PID ${t.pid}`,{stdio:"ignore"})}catch{try{t.kill()}catch{}}else{try{process.kill(-t.pid,"SIGTERM")}catch{}t.kill("SIGTERM"),setTimeout(()=>{if(t&&!t.killed){try{process.kill(-t.pid,"SIGKILL")}catch{}t.kill("SIGKILL")}},5e3)}}function yt(t,e,n,o){try{xs(io,{recursive:!0})}catch{}let s={pid:t,httpPort:e,wsPort:n,workspaceDir:o,startedAt:new Date().toISOString(),lastActivity:new Date().toISOString()};ws(bt,JSON.stringify(s,null,2),"utf-8")}function co(){try{return xe(bt)?JSON.parse(Ts(bt,"utf-8")):null}catch{return null}}function lo(){try{bs(bt)}catch{}}function uo(t){try{return process.platform==="win32"?Pe(`tasklist /FI "PID eq ${t.pid}" /NH`,{encoding:"utf-8",timeout:3e3}).includes(String(t.pid)):(Pe(`kill -0 ${t.pid}`,{stdio:"ignore"}),!0)}catch{return!1}}function zt(t){let{installDir:e,workspaceDir:n,port:o,wsPort:s,forceKill:c}=t,d=Vt(e),f=ve(e);f||(console.error("[launcher] Backend JAR not found. Run: npm install -g @jwcode/cli"),process.exit(1)),c&&(st(o),st(s));let m=["-jar",f,String(o),String(s),n],g=t.idleTimeout??300,w=so(d,m,{cwd:n,env:{...process.env,JWCODE_WS_PORT:String(s),JWCODE_DAEMON_IDLE_TIMEOUT:String(g)},stdio:"ignore",detached:!0,windowsHide:!0});return w.unref(),yt(w.pid,o,s,n),console.log(`[daemon] Started JWCode daemon (PID ${w.pid}) on ports ${o}/${s}`),w}function Qt(t){let e=co();return e?uo(e)?t&&e.workspaceDir!==t?null:e:(lo(),null):null}var ms,Jt,io,bt,kt=fn(()=>{"use strict";ms=fs(import.meta.url),Jt=Ft(ms);i(qt,"findInstallDir");i(ve,"findJar");i(ao,"findMvn");i(Vt,"findJava");i(St,"buildBackend");i(We,"portInUse");i(Xt,"findAvailablePorts");i(st,"killPort");i(Yt,"waitForBackend");i(gs,"startBackend");i(hs,"cleanupBackend");io=oe(Kt(),".jwcode"),bt=oe(io,"daemon.json");i(yt,"writeDaemonInfo");i(co,"readDaemonInfo");i(lo,"clearDaemonInfo");i(uo,"isDaemonAlive");i(zt,"startDaemon");i(Qt,"findRunningDaemon")});var tn={};mn(tn,{checkDaemonHealth:()=>Bs,checkForUpdates:()=>Os,runNpmUpdate:()=>Ls});import{execSync as Ms}from"node:child_process";import{homedir as mo}from"node:os";import{join as go}from"node:path";import{existsSync as vs,readFileSync as As,writeFileSync as _s,mkdirSync as Rs}from"node:fs";function Ps(){try{return vs(en)?JSON.parse(As(en,"utf-8")):null}catch{return null}}function Is(t){try{Rs(go(mo(),".jwcode"),{recursive:!0}),_s(en,JSON.stringify({lastCheck:Date.now(),latestVersion:t}))}catch{}}async function Os(t){let e=Ps();if(e&&Date.now()-e.lastCheck<Es)return{latest:e.latestVersion,current:t,url:"",body:"",publishedAt:"",updateAvailable:e.latestVersion!==t};try{let n=await fetch(Ds,{headers:{Accept:"application/vnd.github+json","User-Agent":"JWCode-CLI"}});if(!n.ok)return null;let o=await n.json(),s=(o.tag_name||"").replace(/^v/,"");return Is(s),{latest:s,current:t,url:o.html_url||"",body:o.body||"",publishedAt:o.published_at||"",updateAvailable:s!==t}}catch{return null}}function Ls(){try{let t=process.platform==="win32"?"npm.cmd":"npm";return{ok:!0,message:Ms(`"${t}" install -g @jwcode/cli@latest`,{encoding:"utf-8",stdio:"pipe",timeout:12e4}).trim()}}catch(t){return{ok:!1,message:String(t.stderr||t.message||t)}}}async function Bs(t){try{let e=await fetch(`http://localhost:${t}/api/system/status`,{signal:AbortSignal.timeout(5e3)});if(e.status===200){let n=await e.json();return n?.status==="running"||n?.success===!0}return!1}catch{return!1}}var Ds,en,Es,nn=fn(()=>{"use strict";Ds="https://api.github.com/repos/jwcode/jwcode/releases/latest",en=go(mo(),".jwcode","last_update_check.json"),Es=360*60*1e3;i(Ps,"readCache");i(Is,"writeCache");i(Os,"checkForUpdates");i(Ls,"runNpmUpdate");i(Bs,"checkDaemonHealth")});import{render as on}from"ink";import{createElement as rn}from"react";import{useState as ie,useEffect as jt,useRef as ot,useCallback as te}from"react";import{Box as Q,Text as ae,useStdout as as}from"ink";import{useState as qo,useRef as Ue,useEffect as ct}from"react";import{Box as Rt,Text as Te,useInput as Vo}from"ink";var Ho=0,Wo=new Map;function $o(t){let e=++Ho;return Wo.set(e,t),e}i($o,"storePaste");function _t(t){let e=$o(t),n=(t.match(/\n/g)||[]).length+1,o=[`Pasted text #${e} +${t.length} chars`];return n>1&&o.push(`+${n} lines`),{id:e,label:`[${o.join(" ")}]`}}i(_t,"pasteSummary");var hn={bg:"",text:"#ffffff",muted:"#999999",border:"#505050",brand:"#d77757",primary:"#d77757",success:"#4eba65",warning:"#ffc107",error:"#ff6b80",info:"#b1b9f9",user:"#7ab4e8",assistant:"#ffffff",system:"#ff6b80",tool:"#b1b9f9",thinking:"#999999",plan:"#48968c",auto:"#ff7814",connected:"#4eba65",disconnected:"#ff6b80",diffAdded:"#38a660",diffRemoved:"#b3596b",diffAddedBg:"#225c2b",diffRemovedBg:"#7a2936",diffHeader:"#b1b9f9",diffFileHeader:"#d77757",diffPlaceholder:"#505050"},jo={...hn,text:"#1f2328",assistant:"#1f2328",muted:"#656d76",border:"#d0d7de",primary:"#cf5a2f",diffAdded:"#116329",diffRemoved:"#cf222e",diffAddedBg:"#dafbe1",diffRemovedBg:"#ffebe9",diffHeader:"#0550ae",diffFileHeader:"#cf5a2f",diffPlaceholder:"#6e7781"},Uo={dark:hn,light:jo};function Jo(){return process.env.JWCODE_THEME==="light"?"light":"dark"}i(Jo,"detectTheme");function Fo(){try{let t=process.env.JWCODE_THEME_COLORS;if(t)return JSON.parse(t)}catch{}return null}i(Fo,"loadCustomColors");var Go=Jo(),gn=Fo();function Ko(){let t=Uo[Go];return gn?{...t,...gn}:t}i(Ko,"getTheme");var u=Ko();import{jsx as Ie,jsxs as Je}from"react/jsx-runtime";function Xo(t){let e=0,n=0;for(let o of t)/[一-鿿㐀-䶿豈-﫿]/.test(o)?e++:n++;return Math.ceil(e/1.5+n/4)}i(Xo,"estimateTokens");function Ye({value:t,onChange:e,onSubmit:n,placeholder:o,disabled:s}){let c=Ue(t.length),[,d]=qo(0),f=Ue(t),m=Ue(e),g=Ue(n),w=Ue(s);ct(()=>{f.current=t}),ct(()=>{m.current=e}),ct(()=>{g.current=n}),ct(()=>{w.current=s}),c.current>t.length&&(c.current=t.length);let T=Ue({accumulating:!1,buf:""});Vo((M,a)=>{if(w.current)return;process.stderr.write(`[TextInput] input=${JSON.stringify(M.slice(0,20))} key.bs=${a.backspace} key.del=${a.delete} key.esc=${a.escape} key.ret=${a.return} key.ctrl=${a.ctrl} key.meta=${a.meta} key.tab=${a.tab} cursor=${c.current} val="${f.current.slice(0,20)}"
5
+ `);let r="[200~",p="[201~";if(M.includes(r)){if(T.current.accumulating=!0,T.current.buf=M.split(r).slice(1).join(r),T.current.buf.includes(p)){let l=T.current.buf.split(p);T.current.buf=l[0]||"",T.current.accumulating=!1;let{label:x}=_t(T.current.buf);m.current(f.current+x)}return}if(T.current.accumulating&&M.includes(p)){let l=M.split(p);T.current.buf+=l[0]||"",T.current.accumulating=!1;let{label:x}=_t(T.current.buf);m.current(f.current+x);return}if(T.current.accumulating){T.current.buf+=M;return}if(a.return){g.current(f.current);return}if(a.leftArrow){c.current=Math.max(0,c.current-1),d(l=>l+1);return}if(a.rightArrow){c.current=Math.min(f.current.length,c.current+1),d(l=>l+1);return}if(a.backspace){if(c.current>0){let l=c.current,x=f.current;m.current(x.slice(0,l-1)+x.slice(l)),c.current=l-1,d(b=>b+1)}return}if(a.delete&&c.current<f.current.length){let l=c.current,x=f.current;m.current(x.slice(0,l)+x.slice(l+1));return}if((M==="\x7F"||M==="\b"||M==="\x7F")&&!a.ctrl&&!a.meta){if(c.current>0){let l=c.current,x=f.current;m.current(x.slice(0,l-1)+x.slice(l)),c.current=l-1,d(b=>b+1)}return}if(M&&!a.ctrl&&!a.meta&&!a.tab&&!a.escape){let l=c.current,x=f.current;m.current(x.slice(0,l)+M+x.slice(l)),c.current=l+M.length,d(b=>b+1)}});let h=t||"",k=!h&&o,_=h?Xo(h):0,y=h.length,S=Math.min(c.current,t.length);return Je(Rt,{flexDirection:"column",children:[Ie(Rt,{children:h?Je(Te,{children:[Ie(Te,{children:t.slice(0,S)}),Ie(Te,{inverse:!0,children:t[S]||" "}),Ie(Te,{children:t.slice(S+1)})]}):Je(Te,{children:[Ie(Te,{dimColor:!0,children:o}),Ie(Te,{dimColor:!0,children:"\u25B6"})]})}),y>0&&Je(Rt,{children:[Je(Te,{dimColor:!0,children:[" ",y," chars ~ ",_," tokens"]}),Je(Te,{dimColor:!0,children:[" [",S+1,"/",y,"]"]}),_>1e5&&Ie(Te,{color:u.error,children:" WARN: Approaching context limit"})]})]})}i(Ye,"TextInput");import Dt from"ws";var Yo=3e4,zo=3e4,xn=50;function Et(t){try{process.stderr.write(t)}catch{}}i(Et,"stderr");function X(t,e){try{process.stderr.write("[dbg "+t+"] "+e+`
6
+ `)}catch{}}i(X,"debugLog");var lt=class{static{i(this,"JwCodeClient")}ws=null;handlers=new Map;_running=!1;_reconnecting=!1;_reconnectRetries=0;pingTimer=null;reconnectDelay=1e3;reconnectTimer=null;sessionId=null;backendUrl;wsUrl;token;constructor(e,n,o="default-token"){this.backendUrl=e,this.wsUrl=n,this.token=o}on(e,n){return this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(n),()=>this.handlers.get(e)?.delete(n)}async connect(){if(this._running=!0,this.ws){try{this.ws.close()}catch{}this.ws=null}return new Promise((e,n)=>{let o=!1,s=i((d,f)=>{o||(o=!0,d(f))},"settle");try{this.ws=new Dt(this.wsUrl)}catch(d){s(n,d);return}let c=this.ws._socket;c&&c.on("error",()=>{}),this.ws.on("message",d=>{let f;try{f=JSON.parse(d.toString())}catch{return}if(f.type==="auth_required"){this.ws.send(JSON.stringify({type:"auth",token:this.token}));return}if(f.type==="auth_success"){this._createSession().then(m=>{this.sessionId=m,this._startHeartbeat(),this._startReadLoop(),this._reconnecting=!1,this._reconnectRetries=0,this.reconnectDelay=1e3,s(e,m)}).catch(m=>s(n,m));return}if(f.type==="auth_failed"){s(n,new Error(`Auth failed: ${JSON.stringify(f)}`));return}}),this.ws.on("error",d=>{this.sessionId?this.dispatch({type:"error",data:`WebSocket error: ${d.message}`}):s(n,d)}),this.ws.on("close",()=>{this._stopHeartbeat(),!this.sessionId&&!this._reconnecting&&s(n,new Error("Connection closed before authentication")),this._running&&!this._reconnecting&&this._startReconnect()})})}async _createSession(){let n=await(await fetch(`${this.backendUrl}/api/sessions`,{method:"POST"})).json(),s=(n.data||{}).sessionId||n.sessionId||n.id||"default-session";return Et(`[ws] Session: ${s}
7
+ `),s}_startReadLoop(){this.ws&&this.ws.on("message",e=>{let n;try{n=JSON.parse(e.toString())}catch{return}n.type==="auth_required"||n.type==="auth_success"||n.type==="auth_failed"||this.dispatch(n)})}_startHeartbeat(){this._stopHeartbeat(),this.pingTimer=setInterval(()=>{if(this.ws?.readyState===Dt.OPEN)try{this.ws.send(JSON.stringify({type:"ping"}))}catch{}},Yo)}_stopHeartbeat(){this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null)}_startReconnect(){if(!(!this._running||this._reconnecting)){if(this._reconnectRetries>=xn){Et(`[ws] Max reconnect retries (${xn}) reached, giving up.
8
+ `),this.dispatch({type:"error",data:"Connection lost \u2014 max retries reached."});return}this._reconnecting=!0,this._reconnectRetries++,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.reconnectTimer=setTimeout(async()=>{try{Et(`[ws] Reconnecting (attempt ${this._reconnectRetries})...
9
+ `),this.dispatch({type:"notification",data:`Reconnecting (${this._reconnectRetries})...`}),await this.connect(),this.dispatch({type:"notification",data:"Reconnected."})}catch{this.reconnectDelay=Math.min(this.reconnectDelay*2,zo),this._reconnecting=!1,this._startReconnect()}},this.reconnectDelay)}}dispatch(e){let n=this.handlers.get(e.type);if(n)for(let o of n)try{o(e)}catch(s){console.error(`Handler error [${e.type}]:`,s)}}send(e,n,o){if(X("send",e+(n?" msg="+n.slice(0,40):"")+(o?" data="+JSON.stringify(o).slice(0,60):"")),!this.ws||this.ws.readyState!==Dt.OPEN){console.warn(`[ws] Not connected, dropping: ${e}`);return}let s={type:e,sessionId:this.sessionId};n!==void 0&&(s.message=n),o&&(s.data=JSON.stringify(o));try{this.ws.send(JSON.stringify(s))}catch(c){console.error(`[ws] send error [${e}]:`,c)}}chat(e,n=!1){this.send(n?"plan":"chat",e)}stop(){X("send","stop"),this.send("stop")}pause(){this.send("pause")}resume(){this.send("resume")}planConfirm(){this.send("plan_confirm")}updateDocs(){this.send("update_docs")}doctor(){this.send("doctor")}rewind(){this.send("rewind")}compact(){this.send("compact")}switchModel(e){this.send("model_change",void 0,{model:e})}approveHook(e){X("send","approveHook "+e),this.send("hook_allow",void 0,{approvalId:e})}denyHook(e){X("send","denyHook "+e),this.send("hook_deny",void 0,{approvalId:e})}exit(){this.send("exit")}init(){this.send("init")}effort(e){this.send("effort",void 0,{level:e})}branch(e){this.send("branch",void 0,{name:e})}mcp(e){this.send("mcp",void 0,{action:e})}skills(){this.send("skills")}agents(){this.send("agents")}config(e){this.send("config",void 0,{action:e})}plugin(e){this.send("plugin",void 0,{action:e})}async listFiles(e){try{let n=e?`${this.backendUrl}/api/files?path=${encodeURIComponent(e)}`:`${this.backendUrl}/api/files`,o=await fetch(n);if(!o.ok)return[];let s=await o.json(),c=[],d=i(f=>{for(let m of f)m.type==="file"&&c.push(m.path),m.children&&d(m.children)},"walk");return d(s?.data||s||[]),c}catch{return[]}}async readFileContent(e){try{let n=await fetch(`${this.backendUrl}/api/files/read?path=${encodeURIComponent(e)}`);if(!n.ok)return null;let o=await n.json();return o?.data||o}catch{return null}}async listSessions(){try{let n=await(await fetch(`${this.backendUrl}/api/sessions`)).json();return n?.data||n||[]}catch{return[]}}async deleteSession(e){try{return(await(await fetch(`${this.backendUrl}/api/sessions/${e}`,{method:"DELETE"})).json())?.success===!0}catch{return!1}}async getSessionMessages(e){try{return(await(await fetch(`${this.backendUrl}/api/sessions/${e}/messages`)).json())?.data||[]}catch{return[]}}async close(){this._running=!1,this._reconnecting=!1,this._stopHeartbeat(),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.ws&&(this.ws.close(),this.ws=null)}};import{memo as cr,useState as lr,useEffect as dr,useRef as ur}from"react";import{Box as ze,Text as R}from"ink";import{useSyncExternalStore as Qo,useRef as Zo}from"react";function wn(t,e){let n=t,o=new Set;return{getState:i(()=>n,"getState"),setState:i(s=>{let c=n,d=s(c);if(!Object.is(d,c)){n=d,e?.({newState:d,oldState:c});for(let f of o)f()}},"setState"),subscribe:i(s=>(o.add(s),()=>o.delete(s)),"subscribe")}}i(wn,"createStore");var er={messages:[],currentMessage:null,usage:{promptTokens:0,completionTokens:0,totalTokens:0,usageRatio:0},planMode:!1,autoMode:!1,planWaiting:!1,scrollOffset:0,modelName:"",connected:!1,statusText:"connecting...",tokenRate:0,toolCallsExpanded:!1,planTasks:[],pdcaPhase:"",degradation:{active:!1,retryCount:0,maxRetries:0,mode:"normal",message:""},compactionProgress:null,contentHeight:0},Pt=null;function be(){return Pt||(Pt=wn(er)),Pt}i(be,"getStore");var tr=i(t=>t.currentMessage!==null,"selIsGenerating");var nr=i(t=>t.planTasks,"selPlanTasks"),or=i(t=>t.pdcaPhase,"selPdcaPhase"),rr=i(t=>t.degradation,"selDegradation"),sr=i(t=>({messages:t.messages,currentMessage:t.currentMessage,scrollOffset:t.scrollOffset,contentHeight:t.contentHeight}),"selChatArea"),ar=i(t=>({usage:t.usage,modelName:t.modelName,planMode:t.planMode,autoMode:t.autoMode,connected:t.connected,statusText:t.statusText,messagesLen:t.messages.length,tokenRate:t.tokenRate,compactionProgress:t.compactionProgress}),"selStatusLine");function ir(t,e){if(Object.is(t,e))return!0;if(t===null||e===null||typeof t!="object"||typeof e!="object")return!1;let n=Object.keys(t),o=Object.keys(e);return n.length!==o.length?!1:n.every(s=>Object.is(t[s],e[s]))}i(ir,"shallowEqual");function re(t){let e=be(),n=Zo(null),o=i(()=>{let s=t(e.getState()),c=n.current;return c!==null&&ir(s,c.value)?c.value:(n.current={value:s},s)},"getSnapshot");return Qo(e.subscribe,o,o)}i(re,"useAppSlice");var Tn=i(()=>re(tr),"useAppIsGenerating"),bn=i(()=>re(sr),"useAppChatArea"),It=i(()=>re(ar),"useAppStatusLine");var Sn=i(()=>re(nr),"useAppPlanTasks"),yn=i(()=>re(or),"useAppPdcaPhase"),kn=i(()=>re(rr),"useAppDegradation");function A(t){be().setState(t)}i(A,"updateAppState");import{Fragment as _e,jsx as I,jsxs as Y}from"react/jsx-runtime";function dt(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${Math.round(t/1e3)}K`:String(t)}i(dt,"formatTokens");function pr(t){return t<=0?"":t>=100?`${Math.round(t)}t/s`:t>=10?`${t.toFixed(1)}t/s`:`${t.toFixed(1)}t/s`}i(pr,"formatRate");function fr(t){if(t<=0)return"";if(t>=60){let e=Math.floor(t/60),n=t%60;return`${e}m${n}s`}return`${t}s`}i(fr,"formatElapsed");var Cn=cr(i(function(){X("app","StatusLine mount planMode="+It().planMode);let{usage:e,modelName:n,planMode:o,autoMode:s,connected:c,statusText:d,messagesLen:f,tokenRate:m,compactionProgress:g}=It(),w=kn(),T=yn(),h=Sn(),k=f,_=Tn(),y=ur(0),[S,M]=lr(Date.now());dr(()=>{if(_){y.current===0&&(y.current=Date.now());let we=setInterval(()=>M(Date.now()),1e3);return()=>clearInterval(we)}else y.current=0},[_]);let a=_?Math.floor((S-y.current)/1e3):0,r=Math.min(100,Math.round(e.usageRatio*100)),p=Math.round(r/10),l="\u2588".repeat(p)+"\u2591".repeat(10-p),x=n||(c?"ready":"connecting..."),b=o?" Plan ":" Act ",P=o?u.plan:u.success,B=o?"mode-plan":"mode-act",K=c?"\u25CF":"\u25CB",v=c?u.connected:u.disconnected,D=d.startsWith("Error:"),H=r>90?u.error:r>70?u.warning:u.text,ce=pr(m),$e=fr(a),V=e.promptTokens,se=e.completionTokens;return Y(ze,{flexDirection:"column",width:"100%",paddingRight:1,children:[Y(ze,{height:1,children:[I(R,{bold:!0,color:u.primary,children:"jwcode"}),I(R,{children:" "}),Y(R,{backgroundColor:P,color:"black",children:[" ",b," "]},B),I(R,{children:" "}),s&&Y(_e,{children:[I(R,{backgroundColor:u.auto,color:"black",children:" AUTO "}),I(R,{children:" "})]}),T&&Y(_e,{children:[Y(R,{backgroundColor:u.warning,color:"black",children:[" ",T," "]}),I(R,{children:" "})]}),h.length>0&&Y(_e,{children:[I(R,{color:u.primary,children:h.filter(we=>we.status==="completed").length}),I(R,{dimColor:!0,children:"/"}),I(R,{color:u.text,children:h.length}),I(R,{dimColor:!0,children:" tasks"}),I(R,{children:" "})]}),Y(R,{color:v,children:[K," "]}),I(R,{color:u.success,children:x}),I(R,{children:" "}),Y(R,{dimColor:!0,children:[k,"msgs"]}),V>0||se>0?Y(_e,{children:[I(R,{children:" "}),I(R,{color:u.info,children:dt(V)}),I(R,{dimColor:!0,children:"+"}),I(R,{color:u.success,children:dt(se)}),I(R,{dimColor:!0,children:"="}),I(R,{color:u.warning,children:dt(e.totalTokens)})]}):Y(_e,{children:[I(R,{children:" t:"}),I(R,{color:u.warning,children:dt(e.totalTokens)})]}),I(R,{children:" "}),Y(R,{color:H,children:[l," ",r,"%"]}),_&&ce&&Y(_e,{children:[I(R,{children:" "}),I(R,{color:u.tool,children:ce})]}),_&&$e&&Y(_e,{children:[I(R,{children:" "}),I(R,{color:u.primary,children:$e})]})]}),I(ze,{height:1,children:w.active?Y(R,{color:u.warning,dimColor:!0,children:["[",w.mode.toUpperCase(),"] ",w.message,w.retryCount>0?` (${w.retryCount}/${w.maxRetries})`:""]}):I(R,{children:" "})}),I(ze,{height:1,children:g?Y(_e,{children:[Y(R,{color:g.percent>=100?u.success:u.primary,children:[g.percent>=100?"\u2713":"\u2699"," ",g.message]}),I(R,{children:" "}),Y(R,{color:u.warning,children:["\u2588".repeat(Math.round(g.percent/10)),"\u2591".repeat(10-Math.round(g.percent/10))]}),Y(R,{dimColor:!0,children:[" ",g.percent,"%"]})]}):I(R,{children:" "})}),I(ze,{height:1,children:d&&d!=="connecting..."?I(R,{color:D?u.error:u.muted,dimColor:!D,children:d.slice(0,100)}):I(R,{children:" "})})]})},"StatusLine"));import{Box as z,Text as $}from"ink";import{useState as Bt,useMemo as Cr,useRef as pt,useLayoutEffect as ft,memo as Ze,forwardRef as In}from"react";import{measureElement as Mr}from"ink";import{useEffect as ba,useRef as Sa}from"react";import{useStdin as ka}from"ink";var mr={topRow:0,trackHeight:0,contentHeight:0,viewportHeight:0,termCols:80};function Mn(t){mr=t}i(Mn,"setScrollGeometry");import{memo as _n,useState as gr,useMemo as ut}from"react";import{Box as Se,Text as ye}from"ink";import{jsx as ke,jsxs as fe}from"react/jsx-runtime";var hr=/^(---|\+\+\+) /,xr=/^@@ /,wr=/^\\(?!.*\\$)/;var vn=30;function Tr(t){let e=t.split(`
10
+ `),n=[];for(let o of e){let s="context";hr.test(o)?s="fileHeader":xr.test(o)?s="hunkHeader":o.startsWith("+")?s="addition":o.startsWith("-")?s="deletion":wr.test(o)&&(s="placeholder");let c=o;(s==="addition"||s==="deletion")&&(c=o.slice(1)),n.push({type:s,text:c,raw:o})}return n}i(Tr,"parseDiff");function An(t,e){return t.filter(n=>n.type===e).length}i(An,"countByType");var Ot=_n(i(function({content:e,terminalCols:n=120,startCollapsed:o}){let s=ut(()=>Tr(e),[e]),c=s.length,d=ut(()=>An(s,"addition"),[s]),f=ut(()=>An(s,"deletion"),[s]),m=o??c>vn,[g,w]=gr(m),T=i(()=>w(a=>!a),"toggle"),h=n-6,k=ut(()=>{let a=[];for(let r of s)if(r.type==="fileHeader"&&r.raw.startsWith("+++")){let p=r.raw.replace(/^\+\+\+ (a|b)\//,"").trim();p&&p!=="/dev/null"&&a.push(p)}return[...new Set(a)]},[s]),_=k.length>0?k.join(", ")+` \u2192 +${d}/-${f}`:`Diff \u2192 +${d}/-${f}`;if(c===0)return null;let y=vn,S=g?s.slice(0,y):s,M=c-y;return fe(Se,{flexDirection:"column",paddingLeft:1,children:[fe(Se,{children:[fe(ye,{color:u.primary,bold:!0,children:[" ","[",g?"+":"-","]"," "]}),ke(ye,{color:u.muted,children:_})]}),ke(Se,{flexDirection:"column",children:S.map((a,r)=>ke(Sr,{line:a,maxWidth:h},r))}),g&&M>0&&fe(Se,{children:[fe(ye,{color:u.info,dimColor:!0,children:[" \u2026 ",M," more lines"," "]}),ke(ye,{color:u.primary,dimColor:!0,underline:!0,children:"[click or press to expand]"})]})]})},"DiffDisplay"));function br(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}i(br,"truncateLine");var Sr=_n(i(function({line:e,maxWidth:n}){let o=br(e.text,n);switch(e.type){case"fileHeader":return ke(Se,{children:fe(ye,{color:u.diffFileHeader,bold:!0,dimColor:!1,children:[" ",e.raw.slice(0,n)]})});case"hunkHeader":return ke(Se,{children:fe(ye,{color:u.diffHeader,dimColor:!0,children:[" ",e.raw.slice(0,n)]})});case"addition":return ke(Se,{children:fe(ye,{color:u.diffAdded,backgroundColor:u.diffAddedBg,children:[" + ",o]})});case"deletion":return ke(Se,{children:fe(ye,{color:u.diffRemoved,backgroundColor:u.diffRemovedBg,children:[" - ",o]})});case"placeholder":return ke(Se,{children:fe(ye,{color:u.diffPlaceholder,dimColor:!0,children:[" ",e.raw.slice(0,n)]})});default:return ke(Se,{children:fe(ye,{color:u.muted,dimColor:!0,children:[" ",o]})})}},"RenderDiffLine"));import{Box as le,Text as ee}from"ink";import{memo as yr}from"react";import{jsx as F,jsxs as Fe}from"react/jsx-runtime";var Lt=null;function kr(){if(!Lt)try{Lt=No("marked")}catch{return null}return Lt}i(kr,"getMarked");function Rn(t,e){let n=[],o=0;for(let s of t){let c=s,d=e+"-"+o++;switch(c.type){case"strong":n.push(F(ee,{bold:!0,children:Qe(c.tokens||[])},d));break;case"em":n.push(F(ee,{italic:!0,children:Qe(c.tokens||[])},d));break;case"codespan":n.push(F(ee,{color:u.warning,backgroundColor:"#2d2d2d",children:c.text||""},d));break;case"link":{let f=Qe(c.tokens||[]),m=c.href||"";n.push(F(ee,{color:u.info,children:f+" ("+m+")"},d));break}default:n.push(F(ee,{children:c.text||c.raw||""},d));break}}return n}i(Rn,"renderInlineTokens");function Qe(t){return t.map(e=>e.text||e.raw||"").join("")}i(Qe,"renderPlainText");var Dn=yr(i(function({content:e,terminalCols:n}){let o=kr();if(!o||!e)return F(ee,{children:e});let s=[];try{s=new o.Lexer().lex(e)}catch{return F(ee,{children:e})}let c=[],d=0;for(let f of s){let m="md-"+d++,g=f;switch(g.type){case"heading":{let w=g.depth||1,T="#".repeat(w)+" ";c.push(F(le,{marginTop:w===1?1:0,children:Fe(ee,{bold:!0,color:w<=2?u.primary:u.muted,children:[T,Qe(g.tokens||[])]})},m));break}case"paragraph":c.push(F(le,{paddingLeft:0,children:F(ee,{children:Rn(g.tokens||[],m)})},m));break;case"code":{let w=g.lang||"",T=g.text||"",h=Math.min(n-4,100),k=T.split(`
11
+ `);c.push(Fe(le,{flexDirection:"column",marginY:0,children:[w&&F(le,{paddingLeft:1,children:Fe(ee,{dimColor:!0,children:["\u250C\u2500 ",w]})}),k.map((_,y)=>F(le,{paddingLeft:2,children:F(ee,{color:u.muted,dimColor:!0,children:_.slice(0,h)})},m+"-l"+y))]},m));break}case"blockquote":c.push(F(le,{flexDirection:"column",paddingLeft:2,children:(g.tokens||[]).map((w,T)=>Fe(le,{children:[Fe(ee,{dimColor:!0,children:["\u2502"," "]}),F(ee,{italic:!0,children:w.text||Qe(w.tokens||[])})]},m+"-b"+T))},m));break;case"list":{let w=g.items||[];c.push(F(le,{flexDirection:"column",children:w.map((T,h)=>{let k=g.ordered?(g.start||1)+h+". ":" \u2022 ";return Fe(le,{paddingLeft:1,children:[F(ee,{dimColor:!0,children:k}),F(le,{flexDirection:"column",children:(T.tokens||[]).map((_,y)=>_.type==="text"?F(ee,{children:Rn(_.tokens||[],m+"-it"+y)},m+"-it"+y):F(ee,{children:_.text||""},m+"-ip"+y))})]},m+"-i"+h)})},m));break}case"hr":c.push(F(le,{children:F(ee,{dimColor:!0,children:"\u2500".repeat(Math.min(n-2,60))})},m));break;case"space":break;default:g.raw&&c.push(F(ee,{children:g.raw.trimEnd()},m));break}}return F(le,{flexDirection:"column",children:c})},"MarkdownRenderer"));import{Fragment as Hn,jsx as E,jsxs as J}from"react/jsx-runtime";var En="-".repeat(60),gt=200,vr=6;function ht(t){if(t<=0)return"";if(t>=60){let e=Math.floor(t/60),n=t%60;return e+"m"+n+"s"}return t+"s"}i(ht,"formatDuration");function On(t){if(!t||t.length<20)return!1;let e=t.split(`
12
+ `),n=!1,o=!1,s=0;for(let c of e)/^--- .+\/|^\+\+\+ .+\//.test(c)&&(n=!0),/^@@ -\d+,\d+ +\d+,\d+ @@/.test(c)&&(o=!0),/^[+-]/.test(c)&&!/^[+-]{3}/.test(c)&&!/^[+-]{4}/.test(c)&&s++;return(n||o)&&s>=2}i(On,"isDiffContent");function Ln(t,e){let n=t[e];if(!n)return!0;if(n.status==="running")return!1;let o=-1;for(let s=t.length-1;s>=0;s--)if(t[s].status==="complete"||t[s].status==="error"){o=s;break}return e!==o}i(Ln,"shouldStartCollapsed");var Ar="\xB7",Pn="#",_r="^",Rr="v";function Dr({contentHeight:t,offset:e,viewportHeight:n}){let o=Math.max(2,n-2),s=Math.max(1,Math.floor(o*n/Math.max(t,1))),c=Math.max(0,t-n),d=c>0?Math.round((o-s)*e/c):0,f=[];for(let m=0;m<o;m++)m>=d&&m<d+s?f.push(Pn):f.push(Ar);return J(z,{flexDirection:"column",width:2,flexShrink:0,minWidth:2,children:[E($,{color:u.border,children:_r}),f.map((m,g)=>E($,{color:m===Pn?u.text:u.border,children:m},g)),E($,{color:u.border,children:Rr})]})}i(Dr,"Scrollbar");function Bn({content:t,terminalCols:e}){return On(t)?E(Ot,{content:t,terminalCols:e}):E(Dn,{content:t,terminalCols:e})}i(Bn,"MessageContent");function Er({result:t,terminalCols:e}){if(On(t)){let o=t.split(`
13
+ `),s=o.filter(g=>g.startsWith("+")&&!g.startsWith("+++")).length,c=o.filter(g=>g.startsWith("-")&&!g.startsWith("---")).length,d=`+${s}/-${c}`,m=t.length>2e3?t.slice(0,2e3)+`
14
+ ... (truncated)`:t;return J(z,{flexDirection:"column",paddingLeft:2,children:[J($,{dimColor:!0,children:["Diff: ",d]}),E(Ot,{content:m,terminalCols:e})]})}let n=t.length>500?t.slice(0,500)+"...":t;return E($,{color:u.muted,dimColor:!0,children:n})}i(Er,"ToolResult");var Pr=Ze(i(function({step:e}){let n=e.status==="success"?"[ok]":e.status==="error"?"[!!]":e.status==="running"?"[..]":"[--]",o=e.status==="success"?u.success:e.status==="error"?u.error:e.status==="running"?u.primary:u.primary,s=e.duration?ht(e.duration):e.status==="running"&&e.timestamp?ht(Math.floor((Date.now()-e.timestamp)/1e3)):"";return J(z,{flexDirection:"column",children:[J(z,{children:[J($,{color:o,children:[" ",n," "]}),E($,{bold:!0,color:o,children:e.title}),s&&J(Hn,{children:[E($,{dimColor:!0,children:" "}),E($,{color:u.muted,dimColor:!0,children:s})]})]}),e.thought&&J($,{color:u.info,dimColor:!0,children:[" ",Ge(e.thought,200)]}),e.action&&J($,{color:u.warning,children:[" ",Ge(e.action,200)]}),e.result&&J($,{color:u.success,children:[" ",Ge(e.result,300)]})]})},"StepDisplay")),Nn=Ze(i(function({tc:e,collapsed:n,onToggle:o,terminalCols:s}){let c=e.status==="complete"?"[ok]":e.status==="running"?"[..]":"[!!]",d=e.status==="complete"?u.success:e.status==="running"?u.warning:u.error,f=e.duration?ht(e.duration):e.status==="running"&&e.timestamp?ht(Math.floor((Date.now()-e.timestamp)/1e3)):"";return J(z,{flexDirection:"column",paddingLeft:1,children:[J(z,{children:[J($,{color:d,children:[" ",c," "]}),E($,{bold:!0,color:u.tool,children:e.name}),f&&J(Hn,{children:[E($,{dimColor:!0,children:" "}),E($,{color:u.muted,dimColor:!0,children:f})]}),E($,{dimColor:!0,children:" "}),J($,{color:u.info,dimColor:!0,children:["[",n?"+":"-","]"]})]}),!n&&e.args&&E(z,{paddingLeft:4,children:E($,{dimColor:!0,children:Ge(Br(e.args),200)})}),e.result&&E(z,{paddingLeft:2,flexDirection:"column",children:E(Er,{result:e.result,terminalCols:s})})]})},"ToolCallDisplay")),Ir=Ze(In(i(function({msg:e,expandedMessages:n,expandedTools:o,toolCallsExpanded:s,onToggleTool:c,onToggleMessage:d,terminalCols:f},m){return J(z,{flexDirection:"column",marginBottom:1,ref:m,children:[e.type==="user"&&J(z,{flexDirection:"column",children:[E($,{dimColor:!0,children:En}),J($,{color:u.user,bold:!0,children:[">"," ",e.content]})]}),e.type==="assistant"&&J(z,{flexDirection:"column",children:[E($,{children:" "}),e.steps.map((g,w)=>E(Pr,{step:g},g.id||w)),e.thinking&&J(z,{flexDirection:"column",children:[E($,{dimColor:!0,italic:!0,children:n.has(e.id)?e.thinking:Ge(e.thinking,gt)}),e.thinking.length>gt&&J($,{dimColor:!0,children:["[",e.thinking.length-gt," more chars]"," -> to expand"]})]}),e.toolCalls.map((g,w)=>{let T=g.id||g.name||"tool-"+e.id+"-"+w,h=Ln(e.toolCalls,w),k=o.has(T);return E(Nn,{tc:g,terminalCols:f,collapsed:s||k?!1:h,onToggle:()=>c(T)},T)}),e.content&&E(z,{paddingLeft:1,children:E(Bn,{content:e.content,terminalCols:f})}),E($,{dimColor:!0,children:En})]}),e.type==="system"&&E(z,{children:J($,{color:u.error,children:["Error: ",e.content]})})]})},"MessageItem")),(t,e)=>t.msg.id===e.msg.id&&t.msg.content===e.msg.content&&t.msg.thinking===e.msg.thinking&&t.msg.type===e.msg.type&&t.expandedMessages.has(t.msg.id)===e.expandedMessages.has(e.msg.id)&&t.toolCallsExpanded===e.toolCallsExpanded&&t.terminalCols===e.terminalCols),Or=Ze(In(i(function({msg:e,expandedTools:n,toolCallsExpanded:o,onToggleTool:s,terminalCols:c},d){return J(z,{flexDirection:"column",ref:d,children:[e.thinking&&E($,{dimColor:!0,italic:!0,children:Ge(e.thinking,gt)}),e.toolCalls.map((f,m)=>{let g=f.id||f.name||"tool-"+e.id+"-"+m,w=Ln(e.toolCalls,m),T=n.has(g);return E(Nn,{tc:f,terminalCols:c,collapsed:o||T?!1:w,onToggle:()=>s(g)},g)}),e.content&&E(z,{paddingLeft:1,children:E(Bn,{content:e.content,terminalCols:c})})]})},"StreamingMessage")));function mt(t,e){if(t.type==="user")return 3;let n=4;t.thinking&&(n+=Math.ceil(t.thinking.length/Math.max(1,e))+1),n+=t.steps.length;for(let o of t.toolCalls)n+=2,o.result&&(n+=Math.min(20,Math.ceil(o.result.length/Math.max(1,e))));return t.content&&(n+=Math.ceil(t.content.length/Math.max(1,e))),n}i(mt,"defaultMessageHeight");function Lr(t){let e=t,n=0;for(;e;){let o=e.yogaNode;if(!o||typeof o.getComputedTop!="function")break;n+=o.getComputedTop(),e=e.parentNode??null}return n}i(Lr,"getAbsoluteTopRow");var Nt=Ze(i(function({terminalCols:e,terminalRows:n}){let{messages:o,currentMessage:s,scrollOffset:c}=bn(),d=re(v=>v.toolCallsExpanded),[f,m]=Bt(new Set),[g,w]=Bt(new Set),[,T]=Bt(0),h=Math.max(3,n-vr),k=pt(new Map),_=pt(new Map),y=pt(0),S=pt(null),M=Cr(()=>s?o.filter(v=>v.id!==s.id):o,[o,s&&s.id]);ft(()=>{let v=0,D=k.current,H=_.current,ce=Math.max(10,e-4);for(let[V,se]of D)try{let{height:we}=Mr(se);we>0&&(H.set(V,we),v+=we)}catch{}for(let V of M)if(!D.has(V.id)){let se=H.get(V.id)??mt(V,ce);H.set(V.id,se),v+=se}if(s){let V=s,se=H.get(V.id)??mt(V,ce);H.set(V.id,se),v+=se}v+=1,v!==y.current&&(y.current=v,A(V=>V.contentHeight===v?V:{...V,contentHeight:v}));let $e=Lr(S.current)+1;Mn({topRow:$e,trackHeight:Math.max(2,h-2),contentHeight:v,viewportHeight:h,termCols:e})});let a=Math.min(c,Math.max(0,y.current-h)),r=M.length,p=0;if(a===0){let v=0;for(let D=r-1;D>=0;D--){let H=_.current.get(M[D].id)??mt(M[D],Math.max(10,e-4));if(v+=H,v>h){p=D+1;break}p=D}}else{let v=0,D=a+h;for(let H=r-1;H>=0;H--){let ce=_.current.get(M[H].id)??mt(M[H],Math.max(10,e-4));if(v+=ce,v>D){p=H;break}p=H}}p=Math.max(0,p);let l=M.slice(p);ft(()=>{let v=Math.max(0,y.current-h);c>v&&A(D=>({...D,scrollOffset:v}))},[c,h]),ft(()=>{let v=new Set(M.map(D=>D.id));s&&v.add(s.id);for(let D of _.current.keys())v.has(D)||(_.current.delete(D),k.current.delete(D))});let x=i(v=>{m(D=>{let H=new Set(D);return H.has(v)?H.delete(v):H.add(v),H})},"toggleExpandTool"),b=i(v=>{w(D=>{let H=new Set(D);return H.has(v)?H.delete(v):H.add(v),H})},"toggleExpandMessage"),P=y.current,B=P>h||c>0,K=i(v=>D=>{D?k.current.set(v,D):k.current.delete(v)},"registerMessageRef");return ft(()=>{T(v=>v+1)},[p,l.length,s&&s.id,f.size,g.size,d]),J(z,{flexDirection:"row",width:"100%",overflow:"hidden",ref:S,children:[J(z,{flexGrow:1,flexDirection:"column",overflow:"hidden",children:[E(z,{children:E($,{dimColor:!B,bold:B,children:B?`[${p+1}-${r} / ${r}]`:`[${r}]`})}),l.map(v=>E(Ir,{ref:K(v.id),msg:v,expandedMessages:g,expandedTools:f,terminalCols:e,toolCallsExpanded:d,onToggleTool:x,onToggleMessage:b},v.id)),s&&E(Or,{ref:K(s.id),msg:s,terminalCols:e,expandedTools:f,toolCallsExpanded:d,onToggleTool:x},s.id)]}),B&&E(Dr,{contentHeight:P,offset:a,viewportHeight:h})]})},"ChatArea"));function Br(t){if(typeof t!="string")return JSON.stringify(t,null,2);try{return JSON.stringify(JSON.parse(t),null,2)}catch{return t}}i(Br,"formatJson");function Ge(t,e){let n=typeof t=="string"?t:String(t??"");return n.length<=e?n:n.slice(0,e)+"..."}i(Ge,"truncate");import{useState as Wn,useMemo as Wr,useEffect as $n}from"react";import{Box as Tt,Text as Oe,useInput as $r,useStdout as jr}from"ink";var Nr=[{cmd:"/help",desc:"\u663E\u793A\u6240\u6709\u547D\u4EE4",via:"local",action:null},{cmd:"/plan",desc:"\u5207\u6362\u89C4\u5212\u6A21\u5F0F (\u5148\u89C4\u5212\u518D\u6267\u884C)",via:"local",action:"plan_mode"},{cmd:"/auto",desc:"\u5207\u6362\u81EA\u52A8\u6A21\u5F0F (\u81EA\u52A8\u6279\u51C6\u5DE5\u5177\u6267\u884C)",via:"local",action:"auto_mode"},{cmd:"/context",desc:"\u663E\u793A\u5F53\u524D\u4F1A\u8BDD\u72B6\u6001",via:"local",action:"show_context"},{cmd:"/exit",desc:"\u9000\u51FA JWCode",via:"local",action:"__exit__"}],Hr=[{cmd:"/confirm",desc:"\u786E\u8BA4\u5F53\u524D\u89C4\u5212\u5E76\u5F00\u59CB\u6267\u884C",via:"ws",action:"__confirm_plan"},{cmd:"/cancel",desc:"\u53D6\u6D88\u5F53\u524D\u89C4\u5212",via:"ws",action:"__cancel_plan"},{cmd:"/stop",desc:"\u505C\u6B62\u5F53\u524D AI \u751F\u6210",via:"ws",action:"stop"},{cmd:"/pause",desc:"\u6682\u505C\u5F53\u524D AI \u751F\u6210",via:"ws",action:"pause"},{cmd:"/resume",desc:"\u6062\u590D\u6682\u505C\u7684 AI \u751F\u6210",via:"ws",action:"resume"},{cmd:"/clear",desc:"\u6E05\u9664\u5F53\u524D\u4F1A\u8BDD\u6D88\u606F",via:"ws",action:"clear"},{cmd:"/doctor",desc:"\u8FD0\u884C\u7CFB\u7EDF\u81EA\u8BCA\u65AD",via:"ws",action:"doctor"},{cmd:"/rewind",desc:"\u56DE\u6EDA\u5230\u6700\u8FD1\u7684\u68C0\u67E5\u70B9",via:"ws",action:"rewind"},{cmd:"/compact",desc:"\u538B\u7F29\u4F1A\u8BDD\u4E0A\u4E0B\u6587 (\u91CA\u653E token)",via:"ws",action:"compact"},{cmd:"/model",desc:"\u5207\u6362 AI \u6A21\u578B (\u7528\u6CD5: /model <\u6A21\u578B\u540D> \u6216 /model \u6253\u5F00\u9009\u62E9\u5668)",via:"ws",action:"model_change"},{cmd:"/setup",desc:"\u914D\u7F6E AI \u63D0\u4F9B\u5546\u548C API Key",via:"local",action:"setup_wizard"},{cmd:"/init",desc:"\u5206\u6790\u9879\u76EE\u5E76\u751F\u6210 JWCODE.md \u9879\u76EE\u8BB0\u5FC6\u6587\u4EF6",via:"ws",action:"init"},{cmd:"/effort",desc:"\u8BBE\u7F6E\u4EFB\u52A1\u52AA\u529B\u7EA7\u522B (low/medium/high)",via:"ws",action:"effort"},{cmd:"/branch",desc:"\u521B\u5EFA\u5206\u652F\u4F1A\u8BDD (\u7528\u6CD5: /branch <\u540D\u79F0>)",via:"ws",action:"branch"},{cmd:"/mcp",desc:"MCP \u670D\u52A1\u5668\u7BA1\u7406 (list/add/remove)",via:"ws",action:"mcp"},{cmd:"/skills",desc:"\u67E5\u770B\u53EF\u7528 Skills \u5217\u8868",via:"ws",action:"skills"},{cmd:"/agents",desc:"\u5217\u51FA\u914D\u7F6E\u7684 Agent \u4EE3\u7406",via:"ws",action:"agents"},{cmd:"/config",desc:"\u7BA1\u7406\u914D\u7F6E (get/set/list)",via:"ws",action:"config"},{cmd:"/plugin",desc:"\u63D2\u4EF6\u7BA1\u7406 (install/list/remove)",via:"ws",action:"plugin"},{cmd:"/tokens",desc:"\u663E\u793A Token \u4F7F\u7528\u8BE6\u60C5",via:"ws",action:"tokens"},{cmd:"/memory",desc:"\u6D4F\u89C8\u9879\u76EE\u8BB0\u5FC6",via:"ws",action:"memory"},{cmd:"/export",desc:"\u5BFC\u51FA\u4F1A\u8BDD (\u7528\u6CD5: /export <\u8DEF\u5F84>)",via:"ws",action:"export"},{cmd:"/checkpoint",desc:"\u8BBE\u7F6E\u6216\u6062\u590D\u68C0\u67E5\u70B9",via:"ws",action:"checkpoint"},{cmd:"/test",desc:"\u8FD0\u884C\u5F53\u524D\u9879\u76EE\u6D4B\u8BD5",via:"ws",action:"test"},{cmd:"/lint",desc:"\u5BF9\u53D8\u66F4\u6587\u4EF6\u8FD0\u884C Linter",via:"ws",action:"lint"},{cmd:"/search",desc:"\u641C\u7D22\u4EE3\u7801\u5E93 (\u7528\u6CD5: /search <\u5173\u952E\u8BCD>)",via:"ws",action:"search"},{cmd:"/project",desc:"\u751F\u6210\u9879\u76EE\u6587\u6863",via:"ws",action:"project"}],Ht=[...Nr,...Hr],xt={"/help":null,"/plan":{action:"plan_mode"},"/auto":{action:"auto_mode"},"/context":{action:"show_context"},"/exit":{action:"__exit__"},"/quit":{action:"__exit__"},"/confirm":{action:"__confirm_plan"},"/cancel":{action:"__cancel_plan"},"/stop":{action:"stop"},"/pause":{action:"pause"},"/resume":{action:"resume"},"/clear":{action:"clear"},"/doctor":{action:"doctor"},"/rewind":{action:"rewind"},"/compact":{action:"compact"},"/model":{action:"model_change",needsArg:!1},"/setup":{action:"setup_wizard"},"/init":{action:"init"},"/effort":{action:"effort",needsArg:!0},"/branch":{action:"branch",needsArg:!0},"/mcp":{action:"mcp",needsArg:!0},"/skills":{action:"skills"},"/agents":{action:"agents"},"/config":{action:"config",needsArg:!0},"/plugin":{action:"plugin",needsArg:!0},"/tokens":{action:"tokens"},"/memory":{action:"memory"},"/export":{action:"export",needsArg:!0},"/checkpoint":{action:"checkpoint"},"/test":{action:"test"},"/lint":{action:"lint"},"/search":{action:"search",needsArg:!0},"/project":{action:"project"}},wt=`
15
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
16
+ \u2551 JWCode \u547D\u4EE4\u5E2E\u52A9 \u2551
17
+ \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
18
+ \u2551 \u672C\u5730\u547D\u4EE4: \u2551
19
+ \u2551 /help \u663E\u793A\u6B64\u5E2E\u52A9\u4FE1\u606F \u2551
20
+ \u2551 /plan \u5207\u6362\u89C4\u5212\u6A21\u5F0F \u2551
21
+ \u2551 /auto \u5207\u6362\u81EA\u52A8\u6A21\u5F0F \u2551
22
+ \u2551 /context \u663E\u793A\u5F53\u524D\u4F1A\u8BDD\u72B6\u6001 \u2551
23
+ \u2551 /exit \u9000\u51FA JWCode \u2551
24
+ \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
25
+ \u2551 \u540E\u7AEF\u547D\u4EE4: \u2551
26
+ \u2551 /confirm \u786E\u8BA4\u6267\u884C\u5F53\u524D\u89C4\u5212 \u2551
27
+ \u2551 /cancel \u53D6\u6D88\u5F53\u524D\u89C4\u5212 \u2551
28
+ \u2551 /stop \u505C\u6B62\u5F53\u524D AI \u751F\u6210 \u2551
29
+ \u2551 /pause \u6682\u505C\u5F53\u524D AI \u751F\u6210 \u2551
30
+ \u2551 /resume \u6062\u590D\u6682\u505C\u7684\u751F\u6210 \u2551
31
+ \u2551 /clear \u6E05\u9664\u5F53\u524D\u4F1A\u8BDD\u6D88\u606F \u2551
32
+ \u2551 /model [\u540D] \u5207\u6362/\u9009\u62E9 AI \u6A21\u578B \u2551
33
+ \u2551 /setup \u914D\u7F6E AI \u63D0\u4F9B\u5546\u548C API Key \u2551
34
+ \u2551 /compact \u538B\u7F29\u4F1A\u8BDD\u4E0A\u4E0B\u6587 \u2551
35
+ \u2551 /doctor \u7CFB\u7EDF\u81EA\u8BCA\u65AD \u2551
36
+ \u2551 /rewind \u56DE\u6EDA\u5230\u6700\u8FD1\u68C0\u67E5\u70B9 \u2551
37
+ \u2551 /init \u751F\u6210\u9879\u76EE JWCODE.md \u2551
38
+ \u2551 /effort <\u7EA7> \u8BBE\u7F6E\u52AA\u529B\u7EA7\u522B low/med/high \u2551
39
+ \u2551 /branch <\u540D> \u521B\u5EFA\u5206\u652F\u4F1A\u8BDD \u2551
40
+ \u2551 /mcp <\u64CD\u4F5C> MCP \u670D\u52A1\u5668\u7BA1\u7406 \u2551
41
+ \u2551 /skills \u67E5\u770B Skills \u5217\u8868 \u2551
42
+ \u2551 /agents \u5217\u51FA Agent \u4EE3\u7406 \u2551
43
+ \u2551 /config <\u64CD> \u7BA1\u7406\u914D\u7F6E (get/set/list) \u2551
44
+ \u2551 /plugin <\u64CD> \u63D2\u4EF6\u7BA1\u7406 \u2551
45
+ \u2551 /tokens \u663E\u793A Token \u4F7F\u7528\u8BE6\u60C5 \u2551
46
+ \u2551 /memory \u6D4F\u89C8\u9879\u76EE\u8BB0\u5FC6 \u2551
47
+ \u2551 /export <\u8DEF> \u5BFC\u51FA\u4F1A\u8BDD\u5230\u6587\u4EF6 \u2551
48
+ \u2551 /checkpoint \u8BBE\u7F6E\u6216\u6062\u590D\u68C0\u67E5\u70B9 \u2551
49
+ \u2551 /test \u8FD0\u884C\u5F53\u524D\u9879\u76EE\u6D4B\u8BD5 \u2551
50
+ \u2551 /lint \u5BF9\u53D8\u66F4\u6587\u4EF6\u8FD0\u884C Linter \u2551
51
+ \u2551 /search <\u8BCD> \u641C\u7D22\u4EE3\u7801\u5E93 \u2551
52
+ \u2551 /project \u751F\u6210\u9879\u76EE\u6587\u6863 \u2551
53
+ \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
54
+ \u2551 \u5FEB\u6377\u952E: \u2551
55
+ \u2551 \u2191\u2193 \u6D4F\u89C8\u8F93\u5165\u5386\u53F2 (\u6700\u8FD130\u6761) \u2551
56
+ \u2551 PgUp/PgDn \u7FFB\u9875\u6D4F\u89C8\u6D88\u606F \u2551
57
+ \u2551 Home/End \u8DF3\u5230\u6700\u65E9/\u6700\u65B0\u6D88\u606F \u2551
58
+ \u2551 Tab \u5207\u6362 Plan/Act \u6A21\u5F0F \u2551
59
+ \u2551 / \u6253\u5F00\u547D\u4EE4\u9762\u677F (\u53EF\u7FFB\u9875) \u2551
60
+ \u2551 Esc \u5173\u95ED\u9762\u677F/\u53D6\u6D88\u5BA1\u6279 \u2551
61
+ \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
62
+ \u2551 \u666E\u901A\u8F93\u5165\u5373\u53D1\u9001\u804A\u5929\u6D88\u606F \u2551
63
+ \u2551 \u8F93\u5165\u6846\u663E\u793A\u5B57\u7B26\u6570+token\u4F30\u7B97 \u2551
64
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D`;import{jsx as et,jsxs as Ke}from"react/jsx-runtime";function jn({filter:t,onSelect:e}){let[n,o]=Wn(0),[s,c]=Wn(0),{stdout:d}=jr(),f=d?.rows||24,m=Wr(()=>{let T=t.replace(/^\//,"").toLowerCase();return T?Ht.filter(h=>h.cmd.toLowerCase().includes(T)||h.desc.includes(T)):Ht},[t]);$n(()=>{o(0),c(0)},[t]);let g=Math.max(5,Math.min(f-13,10));$n(()=>{c(T=>n<T?n:n>=T+g?n-g+1:T)},[n,g]);let w=m.slice(s,s+g);return $r((T,h)=>{if(h.escape){e(null);return}if(h.downArrow){o(k=>Math.min(k+1,m.length-1));return}if(h.upArrow){o(k=>Math.max(k-1,0));return}if(h.pageDown){o(k=>Math.min(k+g,m.length-1));return}if(h.pageUp){o(k=>Math.max(k-g,0));return}if(h.home){o(0);return}if(h.end){o(m.length-1);return}h.return&&m.length>0&&n>=0&&n<m.length&&e(m[n].cmd)}),Ke(Tt,{flexDirection:"column",borderStyle:"single",borderColor:u.primary,paddingX:1,width:52,children:[Ke(Tt,{children:[et(Oe,{bold:!0,color:u.primary,children:"\u547D\u4EE4\u5217\u8868"}),et(Oe,{dimColor:!0,children:" \u2191\u2193\u9009\u62E9 / PgUp/PgDn\u7FFB\u9875 / \u56DE\u8F66\u786E\u8BA4 / Esc\u53D6\u6D88"})]}),w.map((T,h)=>{let k=s+h;return Ke(Tt,{paddingLeft:1,children:[et(Oe,{color:k===n?u.primary:void 0,bold:k===n,children:k===n?"> ":" "}),et(Oe,{color:u.success,children:T.cmd}),Ke(Oe,{dimColor:!0,children:[" ",T.desc]}),Ke(Oe,{color:T.via==="ws"?u.warning:u.info,dimColor:k!==n,children:["(",T.via==="ws"?"\u540E\u7AEF":"\u672C\u5730",")"]})]},T.cmd)}),m.length>g&&et(Tt,{children:Ke(Oe,{dimColor:!0,children:[" ",s+1,"-",Math.min(s+g,m.length)," / ",m.length]})})]})}i(jn,"CommandPalette");import{useState as Un,useMemo as Ur,useEffect as Jn}from"react";import{Box as tt,Text as Re,useInput as Jr,useStdout as Fr}from"ink";import{jsx as De,jsxs as nt}from"react/jsx-runtime";var Fn=60;function Gr(t){let e=t.replace(/\\/g,"/").split("/");return e[e.length-1]||t}i(Gr,"basename");function Kr(t){let e=t.replace(/\\/g,"/").split("/");return e.pop(),e.join("/")||"."}i(Kr,"dirname");function Gn({query:t,files:e,onSelect:n}){let[o,s]=Un(0),[c,d]=Un(0),{stdout:f}=Fr(),m=f?.rows||24,g=Ur(()=>{if(!t)return e;let h=t.toLowerCase().replace(/\\/g,"/");return e.filter(k=>k.toLowerCase().replace(/\\/g,"/").includes(h))},[e,t]);Jn(()=>{s(0),d(0)},[t]);let w=Math.max(4,Math.min(m-13,8));Jn(()=>{d(h=>o<h?o:o>=h+w?o-w+1:h)},[o,w]);let T=g.slice(c,c+w);return Jr((h,k)=>{if(k.escape){n(null);return}if(k.downArrow){s(_=>Math.min(_+1,g.length-1));return}if(k.upArrow){s(_=>Math.max(_-1,0));return}if(k.pageDown){s(_=>Math.min(_+w,g.length-1));return}if(k.pageUp){s(_=>Math.max(_-w,0));return}k.return&&g.length>0&&o>=0&&o<g.length&&n(g[o])}),nt(tt,{flexDirection:"column",borderStyle:"single",borderColor:u.warning,paddingX:1,width:64,children:[nt(tt,{children:[De(Re,{bold:!0,color:u.warning,children:"@ \u641C\u7D22: "}),De(Re,{color:u.success,children:t||"(\u8F93\u5165\u6587\u4EF6\u540D)"}),De(Re,{dimColor:!0,children:" \u2191\u2193 \u9009\u62E9 \xB7 Enter \u63D2\u5165 \xB7 Esc \u5173\u95ED"})]}),g.length===0&&De(tt,{paddingLeft:1,children:De(Re,{dimColor:!0,children:" \u672A\u627E\u5230\u5339\u914D\u6587\u4EF6"})}),T.map((h,k)=>{let _=c+k,y=Gr(h),S=Kr(h),M=h.length>Fn?"..."+h.slice(-(Fn-3)):h;return nt(tt,{paddingLeft:1,children:[De(Re,{color:_===o?u.warning:void 0,bold:_===o,children:_===o?"\u276F ":" "}),De(Re,{color:u.success,children:y}),nt(Re,{dimColor:!0,children:[" \u2014 ",S]})]},h)}),g.length>w&&De(tt,{children:nt(Re,{dimColor:!0,children:[" ",c+1,"-",Math.min(c+w,g.length)," / ",g.length]})})]})}i(Gn,"FilePalette");import{useState as Wt,useMemo as qr,useEffect as Kn}from"react";import{Box as qe,Text as me,useInput as Vr,useStdout as Xr}from"ink";import{jsx as Me,jsxs as Ee}from"react/jsx-runtime";function qn({sessions:t,onSelect:e,onDelete:n}){let[o,s]=Wt(0),[c,d]=Wt(0),[f,m]=Wt(""),{stdout:g}=Xr(),w=g?.rows||24,T=qr(()=>{let y=f.toLowerCase();return y?t.filter(S=>S.title.toLowerCase().includes(y)||S.id.toLowerCase().includes(y)):t},[t,f]);Kn(()=>{s(0),d(0)},[f]);let h=Math.max(5,Math.min(w-12,10));Kn(()=>{d(y=>o<y?o:o>=y+h?o-h+1:y)},[o,h]);let k=T.slice(c,c+h);Vr((y,S)=>{if(S.escape){e(null);return}if(S.downArrow){s(M=>Math.min(M+1,T.length-1));return}if(S.upArrow){s(M=>Math.max(M-1,0));return}if(S.pageDown){s(M=>Math.min(M+h,T.length-1));return}if(S.pageUp){s(M=>Math.max(M-h,0));return}S.return&&T.length>0&&o>=0&&o<T.length&&e(T[o]),S.delete&&n&&T.length>0&&o>=0&&o<T.length&&n(T[o].id),!S.ctrl&&!S.meta&&y&&y.length===1&&!S.return&&!S.escape&&m(M=>M+y),(S.backspace||S.delete)&&m(M=>M.slice(0,-1))});let _=i(y=>{try{let S=new Date(y);return S.toLocaleDateString()+" "+S.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}catch{return y}},"formatDate");return Ee(qe,{flexDirection:"column",borderStyle:"single",borderColor:u.primary,paddingX:1,width:66,children:[Ee(qe,{children:[Me(me,{bold:!0,color:u.primary,children:"Session History"}),Me(me,{dimColor:!0,children:" type to filter / Enter resume / Del delete / Esc close"})]}),f&&Ee(qe,{paddingLeft:1,children:[Me(me,{dimColor:!0,children:"Filter: "}),Me(me,{color:u.warning,children:f})]}),k.length===0&&Me(qe,{paddingLeft:2,children:Me(me,{dimColor:!0,children:"No sessions found."})}),k.map((y,S)=>{let M=c+S;return Ee(qe,{paddingLeft:1,children:[Me(me,{color:M===o?u.primary:void 0,bold:M===o,children:M===o?"> ":" "}),Me(me,{color:u.success,children:y.id}),Ee(me,{dimColor:!0,children:[" ",y.title.slice(0,30)]}),Ee(me,{color:u.muted,children:[" [",y.messageCount," msgs]"]}),Ee(me,{dimColor:!0,children:[" ",_(y.updatedAt||y.createdAt)]})]},y.id)}),T.length>h&&Me(qe,{children:Ee(me,{dimColor:!0,children:[" ",c+1,"-",Math.min(c+h,T.length)," / ",T.length]})})]})}i(qn,"SessionPicker");import{useState as Vn,useEffect as Xn,useRef as Yr}from"react";import{Box as de,Text as ge,useInput as zr}from"ink";import{jsx as ue,jsxs as he}from"react/jsx-runtime";var Yn=15;function Qr(t,e){let n=t.toLowerCase();return/\b(rm|del|delete|drop|truncate|format|mkfs)\b/.test(n)?{level:"CRITICAL",reason:"Destructive - may delete data"}:/\b(bash|shell|exec|cmd|powershell|terminal)\b/.test(n)?/\b(rm\s+-rf|sudo|chmod\s+777|curl.*\|\s*(ba)?sh|wget.*-O|>\/dev\/|mkfs)\b/i.test(e)?{level:"CRITICAL",reason:"High-risk command - system-level operation"}:{level:"HIGH",reason:"Shell command execution"}:/\b(write|edit|save|upload|deploy|publish)\b/i.test(n)?{level:"HIGH",reason:"File write operation"}:/\b(install|uninstall|npm|pip|cargo|gem|apt|brew)\b/i.test(n)?{level:"HIGH",reason:"Package manager operation"}:/\b(git)\b/.test(n)&&/\b(push|force|hard\s*reset|rebase)\b/i.test(e)?{level:"HIGH",reason:"Git destructive operation"}:/\b(http|fetch|curl|wget|api|request|download)\b/i.test(n)?{level:"MEDIUM",reason:"Network request"}:/\b(read|open|list|ls|dir|cat|view|search|find|grep|glob)\b/i.test(n)?{level:"LOW",reason:"Read-only operation"}:{level:"MEDIUM",reason:"Tool invocation"}}i(Qr,"classifyRisk");var Zr={CRITICAL:u.error,HIGH:u.warning,MEDIUM:u.warning,LOW:u.info},es={CRITICAL:"!",HIGH:"!",MEDIUM:"*",LOW:"~"};function ts(t,e){if(/\b(bash|shell|exec|cmd|powershell|terminal)\b/i.test(t))return e.slice(0,200);if(/\b(write|edit|save|create)\b/i.test(t)){let n=e.match(/(?:file_path|path|file)["\s:=]+([^\s",}]+)/i);if(n)return"File: "+n[1]+`
65
+ `+e.slice(0,160)}return e.length>200?e.slice(0,200)+"...":e}i(ts,"extractPreview");function zn({toolName:t,payload:e,onAllow:n,onDeny:o,onAllowSession:s,onAutoMode:c,queuePosition:d}){let[f,m]=Vn(0),[g,w]=Vn(Yn),T=Yr(null),{level:h,reason:k}=Qr(t,e),_=Zr[h],y=ts(t,e);Xn(()=>(w(Yn),T.current=setInterval(()=>{w(p=>p<=1?(T.current&&clearInterval(T.current),0):p-1)},1e3),()=>{T.current&&clearInterval(T.current)}),[t,e]),Xn(()=>{g===0&&n()},[g,n]);let S=g<=5,M=[{label:"Allow \u2014 execute this command",hint:"Press Enter or y to confirm",action:n},{label:"Deny \u2014 cancel this operation",hint:"Press Esc or n to cancel",action:o},{label:"Allow always this session",hint:"Don't ask again for "+t,action:s},{label:"Auto mode \u2014 allow all hooks",hint:"All future hooks will be auto-approved",action:c}],a=i(()=>M[f].action(),"execSelected");zr((p,l)=>{if(l.escape){o();return}if(l.upArrow){m(x=>x===0?3:x-1);return}if(l.downArrow){m(x=>x===3?0:x+1);return}if(l.return){a();return}if(p==="1"){n();return}if(p==="2"){o();return}if(p==="3"){s();return}if(p==="4"){c();return}if(p==="y"||p==="Y"){n();return}if(p==="n"||p==="N"){o();return}});let r=h==="CRITICAL"?u.error:u.warning;return he(de,{flexDirection:"column",borderStyle:"round",borderColor:r,marginTop:1,children:[he(de,{paddingLeft:1,paddingRight:1,justifyContent:"space-between",children:[he(de,{gap:1,children:[ue(ge,{bold:!0,children:"Permission Required"}),he(ge,{dimColor:!0,children:["\xB7 ",t]}),d&&d.total>1&&he(ge,{dimColor:!0,children:["(",d.current,"/",d.total,")"]})]}),he(ge,{color:S?u.error:u.muted,children:["Auto ",g,"s"]})]}),he(de,{paddingLeft:1,paddingRight:1,children:[he(ge,{color:_,bold:h==="CRITICAL",children:[es[h]," ",h]}),he(ge,{dimColor:!0,children:[" \u2014 ",k]})]}),y?ue(de,{flexDirection:"column",paddingLeft:1,paddingRight:1,marginTop:1,children:ue(de,{marginLeft:2,children:ue(ge,{color:u.tool,children:y})})}):null,h==="CRITICAL"&&ue(de,{paddingLeft:1,paddingRight:1,marginTop:1,children:ue(ge,{color:u.error,children:"This may cause irreversible changes \u2014 verify carefully"})}),ue(de,{flexDirection:"column",marginTop:1,children:M.map((p,l)=>he(de,{flexDirection:"column",paddingLeft:1,paddingRight:1,children:[ue(de,{children:he(ge,{color:f===l?u.brand:u.muted,children:[f===l?"\u276F":" "," ",l+1,". ",p.label]})}),ue(de,{marginLeft:4,children:ue(ge,{dimColor:!0,children:p.hint})})]},l))}),ue(de,{paddingLeft:1,paddingRight:1,marginTop:1,children:ue(ge,{dimColor:!0,children:"1/2/3/4 to select \xB7 \u2191\u2193 to navigate \xB7 Enter to confirm \xB7 Esc to deny"})})]})}i(zn,"ApprovalModal");function Le(t){if(typeof t.data=="string")try{return JSON.parse(t.data)}catch{return{}}return t.data||{}}i(Le,"parseData");function Be(t,e=""){return{id:`msg-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,type:t,content:e,thinking:"",steps:[],toolCalls:[],timestamp:Date.now()}}i(Be,"createMessage");import{useCallback as ns}from"react";var Qn=200;function $t(t,e){let n=[...t.messages,e];return n.length>Qn?n.slice(n.length-Qn):n}i($t,"appendMessage");function Zn(t){let e=typeof t=="string"?t:JSON.stringify(t);for(let n=0;n<10;n++)try{let o=JSON.parse(e);if(o&&typeof o=="object"&&!Array.isArray(o)){if(typeof o.command=="string")return o.command;if(typeof o.command=="object"){e=JSON.stringify(o.command);continue}return JSON.stringify(o,null,2)}return e}catch{return e}return e}i(Zn,"cleanArgs");function eo(t,e){return ns(n=>{let o="",s="",c=[],d=[],f=null,m=!1;function g(){m=!1;let a=o;o="";let r=s;s="";let p=c;c=[];let l=d;d=[],!(!a&&!r&&p.length===0&&l.length===0)&&A(x=>{if(!x.currentMessage)return x;let b=x.currentMessage;a&&(b={...b,content:b.content+a}),r&&(b={...b,thinking:b.thinking+r});for(let P of p)b=P(b);for(let P of l)b=P(b);return{...x,currentMessage:b}})}i(g,"doStreamFlush");function w(){m||(m=!0,f=setTimeout(g,32))}i(w,"scheduleStreamFlush");function T(){f&&(clearTimeout(f),f=null),m=!1,g()}i(T,"flushNow");let h=0,k=0,_=!0,y=null,S=!1;function M(){S=!1;let a=y;if(!a)return;y=null;let r=Number(a.promptTokens)||0,p=Number(a.completionTokens)||0,l=Number(a.totalTokens)||0,x=Number(a.usageRatio)||0;if(l<=0)return;let b=Date.now(),P=0;if(k>0&&h>0&&b>k&&l>h){let B=l-h,K=(b-k)/1e3,v=B/K,D=be().getState().tokenRate;P=D>0?D*.6+v*.4:v}h=l,k=b,A(B=>({...B,usage:{promptTokens:r,completionTokens:p,totalTokens:l,usageRatio:x},modelName:a.model||B.modelName,tokenRate:P}))}i(M,"flushToken"),n.on("start",()=>{X("evt",">> STREAM START"),T();let a=Be("assistant");A(r=>({...r,currentMessage:a,messages:$t(r,a),scrollOffset:0}))}),n.on("content",a=>{let r=typeof a.data=="string"?a.data:a.data?String(a.data):"";o+=r,w()}),n.on("thinking",a=>{s+=typeof a.data=="string"?a.data:"",w()}),n.on("tool_call",a=>{let r=Le(a);X("evt","tool_call: "+(r.name||"?")+(r.complete?" complete":" running")),c.push(p=>{let l=r.id?p.toolCalls.findIndex(b=>b.id===r.id):-1;l<0&&r.name&&(l=p.toolCalls.findIndex(b=>b.name===r.name&&b.status==="running"));let x=[...p.toolCalls];if(l>=0){let b={...x[l]};r.args&&(b.args=Zn(r.args)),r.complete&&(b.status="complete"),r.result&&(b.result=r.result),x[l]=b}else x.push({id:r.id||(r.name?`${r.name}-${Date.now()}`:""),name:r.name||"",args:r.args?Zn(r.args):void 0,status:r.complete?"complete":"running",complete:!!r.complete,timestamp:Date.now()});return{...p,toolCalls:x}}),w()}),n.on("tool_result",a=>{let r=Le(a);c.push(p=>{let l=[...p.toolCalls];for(let x=l.length-1;x>=0;x--)if(l[x].name===r.toolName&&!l[x].result){let b=l[x],P=b.timestamp?Math.floor((Date.now()-b.timestamp)/1e3):void 0;l[x]={...b,result:r.result||"",status:"complete",duration:P};break}return{...p,toolCalls:l}}),w()}),n.on("complete",()=>{X("evt",">> STREAM COMPLETE"),T(),A(a=>{if(!a.currentMessage)return a;let r=[...a.messages],p=a.currentMessage;for(let l=r.length-1;l>=0;l--)if(r[l].type==="assistant"&&r[l].id===p.id){r[l]=p;break}return{...a,currentMessage:null,messages:r}})}),n.on("error",a=>{let r=String(a.data||"Error");X("evt","error: "+r.slice(0,80)),A(p=>({...p,statusText:"Error: "+r.slice(0,120)}))}),n.on("step_start",a=>{let r={};if(typeof a.data=="string")try{r=JSON.parse(a.data)}catch{}else a.data&&typeof a.data=="object"&&(r=a.data);d.push(p=>{let l={id:r.id||"step-"+Date.now(),title:r.title||r.description||"",thought:r.thought,action:r.action,status:"running",tools:[],timestamp:Date.now()};return{...p,steps:[...p.steps,l]}}),w()}),n.on("step_thinking",a=>{let r={};if(typeof a.data=="string")try{r=JSON.parse(a.data)}catch{}else a.data&&typeof a.data=="object"&&(r=a.data);d.push(p=>{let l=[...p.steps],x=r.id?l.findIndex(b=>b.id===r.id):l.length-1;return x>=0&&(l[x]={...l[x],status:"thinking",thought:r.thought||l[x].thought}),{...p,steps:l}}),w()}),n.on("step_action",a=>{let r={};if(typeof a.data=="string")try{r=JSON.parse(a.data)}catch{}else a.data&&typeof a.data=="object"&&(r=a.data);d.push(p=>{let l=[...p.steps],x=r.id?l.findIndex(b=>b.id===r.id):l.length-1;return x>=0&&(l[x]={...l[x],status:"action",action:r.action||l[x].action}),{...p,steps:l}}),w()}),n.on("step_complete",a=>{let r={};if(typeof a.data=="string")try{r=JSON.parse(a.data)}catch{}else a.data&&typeof a.data=="object"&&(r=a.data);d.push(p=>{let l=[...p.steps],x=r.id?l.findIndex(b=>b.id===r.id):l.length-1;if(x>=0){let b=r.duration?Number(r.duration):l[x].timestamp?Math.floor((Date.now()-l[x].timestamp)/1e3):void 0;l[x]={...l[x],status:r.status==="error"?"error":"success",result:r.result,duration:b}}return{...p,steps:l}}),w()}),n.on("plan_start",()=>{X("evt",">> PLAN START"),T();let a=Be("assistant");A(r=>({...r,planWaiting:!1,currentMessage:a,messages:$t(r,a),scrollOffset:0}))}),n.on("plan_thinking",a=>{let r=typeof a.data=="string"?a.data:a.data?String(a.data):"";s+=r+`
66
+ `,w()}),n.on("plan_tasks",()=>{o+=`
67
+ Task list generated
68
+ `,w()}),n.on("plan_error",a=>{let r=String(a.data||"Plan failed");A(p=>({...p,planWaiting:!1,statusText:"Plan error: "+r.slice(0,120)}))}),n.on("plan_mode_enter",()=>{X("evt","plan_mode_enter"),A(a=>({...a,planMode:!0,statusText:"Entered plan mode"}))}),n.on("plan_mode_exit",()=>{X("evt","plan_mode_exit"),A(a=>({...a,planMode:!1,statusText:"Exited plan mode"}))}),n.on("plan_task_start",a=>{let r=Le(a);A(p=>{let l=[...p.planTasks],x=l.findIndex(b=>b.id===r.id);return x>=0?l[x]={...l[x],...r,status:"running",timestamp:Date.now()}:l.push({...r,status:"running",timestamp:Date.now()}),{...p,planTasks:l,pdcaPhase:p.pdcaPhase||"Do"}})}),n.on("plan_task_update",a=>{let r=Le(a);A(p=>{let l=[...p.planTasks],x=l.findIndex(b=>b.id===r.id);return x>=0&&(l[x]={...l[x],...r}),{...p,planTasks:l}})}),n.on("plan_task_result",a=>{let r=Le(a);A(p=>{let l=[...p.planTasks],x=l.findIndex(b=>b.id===r.id);if(x>=0){let b=l[x].timestamp?Math.floor((Date.now()-l[x].timestamp)/1e3):void 0;l[x]={...l[x],...r,status:r.status||"completed",duration:b}}else l.push({...r});return{...p,planTasks:l}})}),n.on("plan_complete",a=>{T();let r=a.status;X("evt",">> PLAN COMPLETE status="+(r||"none"));let p=typeof a.data=="string"?a.data:"";A(l=>{if(!l.currentMessage)return l;let x=[...l.messages],b=l.currentMessage;for(let P=x.length-1;P>=0;P--)if(x[P].type==="assistant"&&x[P].id===b.id){x[P]={...b,content:p||"Plan complete."};break}return{...l,currentMessage:null,messages:x,planWaiting:r==="waiting_confirm"}})}),n.on("token_update",a=>{let r={};if(typeof a.data=="string")try{r=JSON.parse(a.data)}catch{}else a.data&&typeof a.data=="object"&&(r=a.data);_=!1,(Number(r.totalTokens)||0)>0&&(y=r,S||(S=!0,setTimeout(M,100)))}),n.on("compaction_progress",a=>{let r={};if(typeof a.data=="string")try{r=JSON.parse(a.data)}catch{}else a.data&&typeof a.data=="object"&&(r=a.data);A(p=>({...p,compactionProgress:{stage:String(r.stage||""),percent:Number(r.percent)||0,message:String(r.message||"")}}))}),n.on("context_compressed",a=>{let r={};if(typeof a.data=="string")try{r=JSON.parse(a.data)}catch{}else a.data&&typeof a.data=="object"&&(r=a.data);let p=Number(r.originalCount)||0,l=Number(r.compressedCount)||0,x=Number(r.tokensSaved)||0,b=x>=1e3?(x/1e3).toFixed(1)+"K":String(x);A(P=>({...P,statusText:"Context compressed "+p+" to "+l+" messages, freed "+b+" tokens",usage:{...P.usage,usageRatio:Math.max(0,P.usage.usageRatio-.15)},compactionProgress:null}))}),n.on("hook_ask",a=>{let r=Le(a),p=r.toolName||"";X("evt","hook_ask: "+p+" autoMode="+String(be().getState().autoMode));let l=r.approvalId||"",x=r.toolName||"";if(be().getState().autoMode||e.current.has(x)){n.approveHook(l);return}t(b=>b.some(P=>P.approvalId===l)?b:[...b,{approvalId:l,toolName:r.toolName||"",payload:r.askPayload||r.payload||JSON.stringify(r)}])}),n.on("doctor_result",a=>{let r=String(a.data||""),p=r.length>300?r.slice(0,300)+"...":r,l=Be("assistant",p);A(x=>({...x,messages:$t(x,l),statusText:"Doctor diagnosis complete"}))}),n.on("degradation_update",a=>{let r={};if(typeof a.data=="string")try{r=JSON.parse(a.data)}catch{}else a.data&&typeof a.data=="object"&&(r=a.data);A(p=>({...p,degradation:{active:r.active||!1,retryCount:Number(r.retryCount)||0,maxRetries:Number(r.maxRetries)||0,mode:r.mode||"normal",message:r.message||""}}))}),n.on("todo_update",a=>{let r=String(a.data||"");A(p=>({...p,statusText:"TODO: "+r.slice(0,100)}))}),n.on("todo_item_done",a=>{let r=String(a.data||"");A(p=>({...p,statusText:"Done: "+r.slice(0,100)}))}),n.on("todo_progress",a=>{let r=String(a.data||"");A(p=>({...p,statusText:r.slice(0,100)}))}),n.on("workspace_changed",a=>{let r=String(a.data||"Workspace changed");A(p=>({...p,statusText:r.slice(0,100)}))}),n.on("generation_paused",()=>{A(a=>({...a,statusText:"Generation paused -- press ESC to resume or ESC ESC to stop"}))}),n.on("generation_resumed",()=>{A(a=>({...a,statusText:""}))}),n.on("notification",a=>{let r=String(a.data||"");A(p=>({...p,statusText:r,connected:r==="Reconnected."?!0:p.connected}))})},[t])}i(eo,"useStreamHandlers");import{useRef as os}from"react";import{useInput as rs}from"ink";function to(t){let{showApproval:e,showHelp:n,isGenerating:o,terminalRows:s,viewportHeight:c,paletteOpen:d,clientRef:f,onDenyApproval:m,onCloseHelp:g,setHelpScroll:w,onToggleHelp:T,onNewSession:h,onSessionHistory:k}=t,_=os(0);rs((y,S)=>{if(S.f1||S.ctrl&&y==="h"){T?T():n&&g();return}if(S.ctrl&&y==="n"&&!e&&!o){h?.();return}if(S.ctrl&&y==="r"&&!e&&!o){k?.();return}if(S.escape){if(e)return;if(n){g();return}if(o){let r=Date.now(),p=_.current;_.current=r,p>0&&r-p<500?(f.current?.stop(),A(l=>({...l,statusText:"Stopped (ESC\xD72)"}))):(f.current?.pause(),A(l=>({...l,statusText:"Paused \u2014 press ESC again to stop"})));return}}if(S.ctrl&&y==="s"&&!e){o&&(f.current?.pause(),A(r=>({...r,statusText:"Paused (Ctrl+S). Press again to resume."})));return}if(S.ctrl&&y==="l"&&!e&&!o){A(r=>({...r,messages:[],currentMessage:null,scrollOffset:0,contentHeight:0,statusText:"Screen cleared"}));return}if(S.ctrl&&y==="o"){A(r=>({...r,toolCallsExpanded:!r.toolCallsExpanded}));return}if(S.ctrl&&y==="e"){A(r=>({...r,toolCallsExpanded:!r.toolCallsExpanded}));return}if(n){let r=wt.split(`
69
+ `),p=Math.max(5,s-12);if(S.pageUp||S.upArrow){w(l=>Math.min(l+(S.pageUp?p:1),r.length-1));return}if(S.pageDown||S.downArrow){w(l=>Math.max(0,l-(S.pageDown?p:1)));return}if(S.home){w(()=>r.length-1);return}if(S.end){w(()=>0);return}}let M=i(()=>{let{contentHeight:r}=be().getState();return Math.max(0,r-c)},"maxOffsetLive"),a=Math.max(1,c-2);if(S.pageUp){A(r=>({...r,scrollOffset:Math.min(M(),r.scrollOffset+a)}));return}if(S.upArrow&&!e&&!d){A(r=>({...r,scrollOffset:Math.min(M(),r.scrollOffset+1)}));return}if(S.pageDown){A(r=>({...r,scrollOffset:Math.max(0,r.scrollOffset-a)}));return}if(S.downArrow&&!e&&!d){A(r=>({...r,scrollOffset:Math.max(0,r.scrollOffset-1)}));return}if(S.home){A(r=>({...r,scrollOffset:M()}));return}if(S.end){A(r=>({...r,scrollOffset:0}));return}if(S.tab){A(r=>({...r,planMode:!r.planMode,planWaiting:!1}));return}})}i(to,"useKeyboardInput");var ss=null;function no(t){ss=t}i(no,"setClient");import{jsx as O,jsxs as Ce}from"react/jsx-runtime";function oo(t){for(let e=t.length-1;e>=0;e--)if(t[e]==="@"){if(e>0&&/\w/.test(t[e-1]))continue;return e}return-1}i(oo,"findAtTrigger");function Ut({backendUrl:t,wsUrl:e,onExit:n}){let[o,s]=ie(""),[c,d]=ie(!1),[f,m]=ie(!1),[g,w]=ie(""),[T,h]=ie([]),k=ot(null),_=ot([]),[y,S]=ie(!1),[M,a]=ie(0),[r,p]=ie([]),l=r.length>0?r[0]:null,x=ot(new Set),b=ot(null),{stdout:P}=as(),[B,K]=ie(P?.rows||24),[v,D]=ie(P?.columns||80);jt(()=>{let C=i(()=>{K(P?.rows||24),D(P?.columns||80)},"onResize");return P?.on?.("resize",C),()=>{P?.off?.("resize",C)}},[P]);let H=6,ce=re(C=>C.connected),$e=re(C=>C.planWaiting),V=re(C=>C.currentMessage!==null),se=re(C=>C.messages.length),we=re(C=>C.modelName),Mt=re(C=>C.planMode),[sn,an]=ie(!1),[bo,cn]=ie([]),[So,yo]=ie(0),vt=ot("");jt(()=>{let C=Mt+"-"+ce+"-"+(se===0);vt.current&&vt.current!==C&&yo(W=>W+1),vt.current=C},[Mt,ce,se]);let ln=eo(p,x);jt(()=>{let C=new lt(t,e);return b.current=C,no(C),ln(C),C.connect().then(async()=>{try{let j=(await(await fetch(t+"/api/models")).json()).data?.models?.[0]?.name||"";A(Ae=>({...Ae,connected:!0,modelName:j}))}catch{A(W=>({...W,connected:!0}))}}).catch(W=>{A(N=>({...N,statusText:"Connection failed: "+W.message}))}),()=>{C.close()}},[t,e,ln]);let dn=te(C=>{let W=C.trim();if(!W||!b.current)return;s(""),S(!1),d(!1);let N=W.startsWith("/")?W.split(/\s+/):[],q=N[0]||null,j=N.slice(1).join(" ");if(q&&q in xt){let Ae=xt[q];if(Ae===null){S(!0),a(0);return}let{action:pe,needsArg:it}=Ae,U=b.current;switch(pe){case"__exit__":n();return;case"__confirm_plan":A(Z=>Z.planWaiting?(U?.planConfirm(),{...Z,planWaiting:!1}):Z);return;case"__cancel_plan":A(Z=>({...Z,planWaiting:!1}));return;case"plan_mode":A(Z=>({...Z,planMode:!Z.planMode}));return;case"auto_mode":X("app","auto_mode toggle"),A(Z=>({...Z,autoMode:!Z.autoMode}));return;case"clear":A(Z=>({...Z,messages:[],currentMessage:null,contentHeight:0,scrollOffset:0}));return;case"model_change":it&&j&&U?.switchModel(j);return;case"show_context":A(Z=>({...Z,statusText:"Messages: "+Z.messages.length+" | Plan: "+(Z.planMode?"On":"Off")+" | Model: "+(Z.modelName||"N/A")}));return;case"stop":U?.stop();return;case"pause":U?.pause();return;case"resume":U?.resume();return;case"doctor":U?.doctor();return;case"rewind":U?.rewind();return;case"compact":U?.compact();return;case"init":U?.init();return;case"effort":j&&U?.effort(j);return;case"branch":j&&U?.branch(j);return;case"mcp":j&&U?.mcp(j);return;case"skills":U?.skills();return;case"agents":U?.agents();return;case"config":j&&U?.config(j);return;case"plugin":j&&U?.plugin(j);return;case"tokens":U?.send("tokens");return;case"memory":U?.send("memory");return;case"export":j&&U?.send("export",void 0,{path:j});return;case"checkpoint":U?.send("checkpoint");return;case"test":U?.send("test");return;case"lint":U?.send("lint");return;case"search":j&&U?.send("search",void 0,{query:j});return;case"project":U?.send("project");return}return}W.startsWith("/")&&!(q&&q in xt)||ko(W)},[n]),ko=te(async C=>{let W=b.current;if(!W)return;let N=C,q=_.current;_.current=[];let j=[];for(let pe of q)try{let it=await W.readFileContent(pe);if(it){N=N.replace(pe,"").trim();let U=pe.split(".").pop()||"";j.push(`<context ref="${pe}">
70
+ \`\`\`${U}
71
+ ${it}
72
+ \`\`\`
73
+ </context>`)}}catch{}j.length>0&&(N=j.join(`
74
+
75
+ `)+`
76
+
77
+ `+N.trim(),N=N.trim());let Ae=Be("user",N);A(pe=>({...pe,messages:[...pe.messages,Ae]})),W.chat(N,be().getState().planMode)},[]),Co=te(C=>{c||f||dn(C)},[dn,c,f]),Mo=te(C=>{s(C),d(C.startsWith("/"));let W=oo(C);if(W>=0){let N=C.slice(W+1);if(/^[\w.\-\\\/\s]*$/.test(N)&&N.length<200){w(N),m(!0),k.current&&clearTimeout(k.current),k.current=setTimeout(async()=>{let q=b.current;if(q){let j=await q.listFiles(N.trim()||void 0);h(j)}},150);return}}m(!1),w("")},[]),vo=te(C=>{if(C){let W=oo(o);if(W>=0){let N=o.slice(0,W)+C+" ";s(N),_.current.push(C)}}m(!1),w(""),h([])},[o]),Ao=te(C=>{C?(s(C),d(!1)):(d(!1),s(""))},[]),at=te(()=>{p(C=>C.length>1?C.slice(1):[])},[]),je=te(C=>{b.current?.approveHook(C),at()},[at]),At=te(C=>{b.current?.denyHook(C),at()},[at]),un=c||f||sn,_o=te(()=>{A(C=>({...C,messages:[],currentMessage:null,scrollOffset:0,contentHeight:0,statusText:"New session started"})),b.current&&b.current.send("create_session")},[]),Ro=te(async()=>{if(b.current){let C=await b.current.listSessions();cn(C),an(!0)}},[]),Do=te(async C=>{if(an(!1),!C||!b.current)return;let N=(await b.current.getSessionMessages(C.id)).map(q=>Be(q.type==="chat"||q.type==="plan"?"user":"assistant",q.data||q.message||JSON.stringify(q)));A(q=>({...q,messages:N.length>0?N:q.messages,scrollOffset:0,contentHeight:0,statusText:`Loaded session: ${C.id} (${N.length} msgs)`}))},[]),Eo=te(async C=>{if(b.current){await b.current.deleteSession(C);let W=await b.current.listSessions();cn(W)}},[]),Po=i(()=>{y?S(!1):(S(!0),a(0))},"handleToggleHelp");to({showApproval:l!==null,showHelp:y,isGenerating:V,terminalRows:B,viewportHeight:Math.max(3,B-H),paletteOpen:un,clientRef:b,onDenyApproval:i(()=>{l&&At(l.approvalId)},"onDenyApproval"),onCloseHelp:i(()=>S(!1),"onCloseHelp"),setHelpScroll:a,onToggleHelp:Po,onNewSession:_o,onSessionHistory:Ro});let Io=te(()=>{l&&je(l.approvalId)},[l,je]),Oo=te(()=>{l&&At(l.approvalId)},[l,At]),Lo=te(()=>{l&&(x.current.add(l.toolName),je(l.approvalId))},[l,je]),Bo=te(()=>{X("app","autoMode button pressed"),A(C=>({...C,autoMode:!0})),l&&je(l.approvalId)},[l,je]);return Ce(Q,{flexDirection:"column",width:"100%",children:[ce?Ce(Q,{flexDirection:"column",children:[se===0&&!V&&!!we&&Ce(Q,{flexDirection:"column",flexShrink:0,marginBottom:1,children:[Ce(Q,{flexDirection:"column",paddingX:1,children:[O(Q,{children:O(ae,{color:u.primary,bold:!0,children:">_ JWCode v3.0.0"})}),Ce(Q,{children:[O(ae,{dimColor:!0,children:"model: "}),O(ae,{color:u.success,children:we||"connecting..."}),O(ae,{dimColor:!0,children:" /model to change"})]}),Ce(Q,{children:[O(ae,{dimColor:!0,children:"directory: "}),O(ae,{color:u.warning,children:process.cwd()})]})]}),O(Q,{paddingLeft:3,children:O(ae,{dimColor:!0,children:"Tip: Type / for commands, @ to reference files"})}),O(Q,{paddingLeft:3,children:O(ae,{dimColor:!0,children:"TUI shortcuts: F1 help | Ctrl+L clear | Ctrl+S pause | Ctrl+N new | Ctrl+R history | Tab mode | PgUp/PgDn scroll"})})]},"welcome"),O(Q,{flexGrow:un?0:1,flexDirection:"column",children:O(Nt,{terminalCols:v,terminalRows:B})}),Ce(Q,{flexDirection:"row",borderStyle:"single",borderColor:u.primary,paddingLeft:1,children:[O(ae,{color:u.success,bold:!0,children:"> "}),O(Ye,{value:o,onChange:Mo,onSubmit:Co,placeholder:"Type a message or / for commands...",disabled:l!==null})]}),Ce(Q,{flexDirection:"column",children:[c&&O(jn,{filter:o,onSelect:Ao},"command-palette"),f&&O(Gn,{query:g,files:T,onSelect:vo},"file-palette"),sn&&O(qn,{sessions:bo,onSelect:Do,onDelete:Eo},"session-picker"),y&&(()=>{let C=wt.split("\\n"),W=Math.max(5,Math.min(B-12,10)),N=Math.max(0,C.length-M),q=Math.max(0,N-W),j=C.slice(q,N);return Ce(Q,{flexDirection:"column",borderStyle:"single",borderColor:u.primary,paddingX:1,children:[C.length>W&&O(Q,{children:O(ae,{dimColor:!0,children:" "+(q+1)+"-"+N+" / "+C.length+" PgUp/PgDn scroll / Esc close"})}),j.map((Ae,pe)=>O(ae,{color:u.primary,children:Ae},pe))]},"help-box")})(),l&&O(zn,{toolName:l.toolName,payload:l.payload,onAllow:Io,onDeny:Oo,onAllowSession:Lo,onAutoMode:Bo,queuePosition:{current:1,total:r.length}},"approval-modal")]})]}):Ce(Q,{flexDirection:"column",children:[O(Q,{flexGrow:1,flexDirection:"column",children:O(Nt,{terminalCols:v,terminalRows:B})}),O(Q,{paddingLeft:1,children:O(ae,{dimColor:!0,children:"Connecting..."})})]}),O(Cn,{},Mt?"status-plan":"status-act"),!ce&&O(Q,{height:1,children:O(ae,{color:u.error,children:"Backend not connected -- WebSocket reconnecting."})}),$e&&O(Q,{height:1,children:O(ae,{color:u.warning,bold:!0,children:"Plan ready -- /confirm to execute, /cancel to discard."})})]},So)}i(Ut,"App");import{useState as Ne,useCallback as is,useEffect as cs}from"react";import{Box as He,Text as L,useInput as ls}from"ink";import{Fragment as ds,jsx as G,jsxs as ne}from"react/jsx-runtime";var Ve={openai:{name:"OpenAI",baseUrl:"https://api.openai.com/v1",apiType:"openai-completions",defaultModel:"gpt-4o"},anthropic:{name:"Anthropic",baseUrl:"https://api.anthropic.com/v1",apiType:"anthropic-messages",defaultModel:"claude-sonnet-4-6"},deepseek:{name:"DeepSeek",baseUrl:"https://api.deepseek.com/v1",apiType:"openai-completions",defaultModel:"deepseek-chat"},moonshot:{name:"Moonshot / Kimi",baseUrl:"https://api.moonshot.cn/v1",apiType:"openai-completions",defaultModel:"moonshot-v1-8k"},qwen:{name:"\u901A\u4E49\u5343\u95EE (Qwen)",baseUrl:"https://dashscope.aliyuncs.com/compatible-mode/v1",apiType:"openai-completions",defaultModel:"qwen-plus"},zhipu:{name:"\u667A\u8C31 (GLM)",baseUrl:"https://open.bigmodel.cn/api/paas/v4",apiType:"openai-completions",defaultModel:"glm-4-plus"},baichuan:{name:"\u767E\u5DDD (Baichuan)",baseUrl:"https://api.baichuan-ai.com/v1",apiType:"openai-completions",defaultModel:"Baichuan4"},minimax:{name:"MiniMax / \u6D77\u87BA",baseUrl:"https://api.minimax.chat/v1",apiType:"openai-completions",defaultModel:"abab6.5s-chat"},doubao:{name:"\u8C46\u5305 (Doubao)",baseUrl:"https://ark.cn-beijing.volces.com/api/v3",apiType:"openai-completions",defaultModel:"doubao-pro-32k"},hunyuan:{name:"\u817E\u8BAF\u6DF7\u5143 (Hunyuan)",baseUrl:"https://api.hunyuan.cloud.tencent.com/v1",apiType:"openai-completions",defaultModel:"hunyuan-pro"},spark:{name:"\u8BAF\u98DE\u661F\u706B (Spark)",baseUrl:"https://spark-api-open.xf-yun.com/v1",apiType:"openai-completions",defaultModel:"generalv3.5"},custom:{name:"Custom (\u81EA\u5B9A\u4E49)",baseUrl:"",apiType:"openai-completions",defaultModel:""}},rt=Object.keys(Ve),ro=i(({backendUrl:t,onComplete:e,onCancel:n,mode:o="fullscreen"})=>{let[s,c]=Ne("select_provider"),[d,f]=Ne(0),[m,g]=Ne(""),[w,T]=Ne(""),[h,k]=Ne(""),[_,y]=Ne(""),[S,M]=Ne(""),a=o==="modal",r=is(async()=>{c("saving");try{let B=Ve[m],K=h||B.baseUrl,v=await fetch(`${t}/api/config/provider`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:m,baseUrl:K,apiType:B.apiType,apiKey:w,setDefault:!0,models:[{id:_,name:_,enabled:!0,priority:10}]})});if(!v.ok){let D=await v.text();throw new Error(D||`HTTP ${v.status}`)}c("done"),setTimeout(e,1200)}catch(B){M(String(B)),c("error")}},[t,m,h,w,_,e]);cs(()=>{if(s==="done")return;i(async()=>{try{(await(await fetch(`${t}/api/config/provider`)).json())?.data?.configured&&e()}catch{}},"check")()},[s,t,e]),ls((B,K)=>{if(K.escape&&a&&n){n();return}if(s==="select_provider"){if(K.upArrow||B==="k")f(v=>(v-1+rt.length)%rt.length);else if(K.downArrow||B==="j")f(v=>(v+1)%rt.length);else if(K.return){let v=rt[d];g(v);let D=Ve[v];k(D.baseUrl),y(D.defaultModel),c("enter_key")}return}if(s==="error"){if(K.escape&&a&&n){n();return}K.return&&(c("enter_key"),M(""))}});let p=i(()=>{if(w.trim().length<10){M("API key too short (min 10 characters).");return}M(""),m==="custom"?c("enter_model"):r()},"handleKeySubmit"),l=i(()=>{if(_.trim().length===0){M("Model name is required.");return}r()},"handleModelSubmit");if(s==="done")return ne(He,{flexDirection:"column",padding:1,children:[G(L,{color:u.success,children:"\u2713 Configuration saved!"}),o==="fullscreen"&&G(L,{dimColor:!0,children:"Starting JWCode..."})]});let x=a?"single":"round",b=a?u.warning:u.primary,P=a?"Add Provider":"JWCode \u2014 First Run Setup";return ne(He,{flexDirection:"column",padding:1,borderStyle:x,borderColor:b,children:[G(He,{marginBottom:1,children:G(L,{bold:!0,color:u.primary,children:P})}),o==="fullscreen"&&ne(ds,{children:[G(L,{children:"Configure your AI provider to get started."}),G(L,{children:" "})]}),a&&n&&G(L,{dimColor:!0,children:"Esc to close"}),s==="select_provider"&&ne(He,{flexDirection:"column",children:[G(L,{children:"Select provider (\u2191\u2193 to navigate, Enter to confirm):"}),rt.map((B,K)=>ne(L,{children:[K===d?"\u276F ":" ",G(L,{color:K===d?"green":void 0,bold:K===d,children:Ve[B].name}),K===d?" \u25C0":""]},B))]}),s==="enter_key"&&ne(He,{flexDirection:"column",children:[ne(L,{children:["Provider: ",G(L,{color:u.success,children:Ve[m].name})]}),ne(L,{children:["Base URL: ",G(L,{color:u.info,children:h})]}),G(L,{children:" "}),G(L,{children:"Enter API Key:"}),G(Ye,{value:w,onChange:T,onSubmit:p,placeholder:"sk-..."}),G(L,{dimColor:!0,children:"Press Enter to confirm"}),S&&ne(L,{color:u.error,children:["Error: ",S]})]}),s==="enter_model"&&ne(He,{flexDirection:"column",children:[ne(L,{children:["Provider: ",G(L,{color:u.success,children:Ve[m].name})]}),ne(L,{children:["API Key: ",G(L,{color:u.success,children:"configured"})]}),G(L,{children:" "}),ne(L,{children:["Base URL: ",G(L,{color:u.info,children:h})]}),G(L,{children:" "}),G(L,{children:"Model ID:"}),G(Ye,{value:_,onChange:y,onSubmit:l,placeholder:"model-name"}),G(L,{dimColor:!0,children:"Press Enter to confirm, type to edit model name"}),S&&ne(L,{color:u.error,children:["Error: ",S]})]}),s==="saving"&&G(L,{color:u.warning,children:"Saving configuration to ~/.jwcode/config.yaml..."}),s==="error"&&ne(He,{flexDirection:"column",children:[ne(L,{color:u.error,children:["Failed to save: ",S]}),ne(L,{children:["Press Enter to retry",a?", Esc to cancel":"","."]})]})]})},"SetupWizard");kt();import{existsSync as ho}from"node:fs";import{join as xo}from"node:path";import{readFileSync as Ss,existsSync as ys}from"node:fs";import{join as po}from"node:path";import{homedir as ks}from"node:os";var Xe={backend_url:"http://localhost:8080",ws_url:"ws://localhost:8081/ws",ws_auth_token:"default-token",workspace_dir:""};function Cs(t){let e={};for(let n of t.split(`
78
+ `)){let o=n.trim();if(!o||o.startsWith("#"))continue;let s=o.indexOf(":");if(s===-1)continue;let c=o.slice(0,s).trim(),d=o.slice(s+1).trim();if(typeof d=="string")if(d==="true"||d==="false")d=d==="true";else if(/^\d+$/.test(d))d=parseInt(d);else{let f=d.match(/^["'](.*)["']$/);f&&(d=f[1])}e[c]=d}return e}i(Cs,"parseYaml");function fo(){let t=po(ks(),".jwcode"),e=po(t,"config.yaml");if(!ys(e))return{...Xe};try{let n=Ss(e,"utf-8"),o=Cs(n);return{backend_url:o.backend_url||Xe.backend_url,ws_url:o.ws_url||Xe.ws_url,ws_auth_token:o.ws_auth_token||Xe.ws_auth_token,workspace_dir:o.workspace_dir||Xe.workspace_dir}}catch{return{...Xe}}}i(fo,"loadConfig");["stdout","stderr"].forEach(t=>{let e=process[t];e&&e.on("error",n=>{n.code==="EPIPE"||n.code})});process.on("uncaughtException",t=>{t.code==="EPIPE"||t.code==="ECONNRESET"||(console.error("Fatal error:",t),process.exit(1))});var Ct="3.0.0";function wo(){console.log(`JWCode CLI v${Ct}`),console.log(""),console.log("Usage:"),console.log(" jwcode [options] Start backend + interactive terminal (default)"),console.log(" jwcode start [options] Start backend + interactive terminal"),console.log(" jwcode run [options] Connect to existing backend"),console.log(" jwcode stop Stop running daemon"),console.log(" jwcode update Check for updates / update CLI"),console.log(" jwcode version Print version"),console.log(""),console.log("Options:"),console.log(" -p, --port <port> HTTP port (default: auto, first available from 8080)"),console.log(" -w, --workspace <dir> Workspace directory (default: current directory)"),console.log(" -F, --force Kill existing process on target port before starting"),console.log(" -B, --build Force rebuild backend (dev mode only)"),console.log(" -b, --backend <url> Backend URL (run mode, WS auto-derived)"),console.log(" --ws <url> Override WebSocket URL"),console.log(""),console.log("Environment:"),console.log(" JWCODE_THEME=dark|light Color theme (default: dark)"),console.log(""),console.log("Keyboard shortcuts (in TUI):"),console.log(" / Open command palette"),console.log(" Tab Toggle Plan/Act mode"),console.log(" F1 Toggle help panel"),console.log(" Ctrl+N New session"),console.log(" Ctrl+R Session history picker"),console.log(" Ctrl+L Clear screen"),console.log(" Ctrl+S Pause/resume generation"),console.log(" Ctrl+E Toggle expand all tool calls"),console.log(" Up/Down Browse input history (last 30)"),console.log(" PgUp/PgDn Scroll message history"),console.log(" Home/End Jump to oldest/newest message"),console.log(" Esc Close palette / pause gen. / deny approval")}i(wo,"printUsage");function Ns(){let t={},e=process.argv.slice(2);for(let n=0;n<e.length;n++){let o=e[n];o==="--build"||o==="-B"?t.build=!0:o==="--force"||o==="-F"?t.force=!0:o==="--port"||o==="-p"?t.port=e[++n]:o==="--workspace"||o==="-w"?t.workspace=e[++n]:o==="--backend"||o==="-b"?t.backend=e[++n]:o==="--ws"?t.ws=e[++n]:o.startsWith("-")||(t._cmd=o)}return t}i(Ns,"parseArgs");async function Hs(t){let e=!!t.force,n=!!t.build,o=String(t.workspace||process.cwd()),s=qt(),c=Qt(o);if(c){let h=c.httpPort,k=c.wsPort;console.log("[daemon] Reusing existing daemon (PID "+c.pid+") on ports "+h+"/"+k),yt(c.pid,h,k,o),await To(h,k,o,s);return}let d,f;if(t.port)d=parseInt(String(t.port),10),f=d+1,!e&&(We(d)||We(f))&&(console.error(`[launcher] Port ${d} or ${f} is already in use.`),console.error("[launcher] Use --force to replace the existing process, or omit -p for auto port selection."),process.exit(1));else{let h=Xt(8080);d=h.httpPort,f=h.wsPort}console.log("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.log("\u2551 JWCode \u2014 Java AI Coding Tool \u2551"),console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),console.log(` Workspace: ${o}`),console.log(` HTTP API: http://localhost:${d}`),console.log(` WebSocket: ws://localhost:${f}/ws`),(n||!ve(s))&&(ho(xo(s,"pom.xml"))?St(s):ve(s)||(console.error("[launcher] Backend JAR not found and no pom.xml for build."),console.error("[launcher] Install via: npm install -g @jwcode/cli"),process.exit(1))),(n||!ve(s))&&(ho(xo(s,"pom.xml"))?St(s):ve(s)||(console.error("[launcher] Backend JAR not found. Run: npm install -g @jwcode/cli"),process.exit(1)));let m=zt({installDir:s,workspaceDir:o,port:d,wsPort:f,forceKill:e,idleTimeout:300}),g=!1,w=i(()=>{g||(g=!0,process.stdout.write("\x1B[?1049l"),console.log(`
79
+ [jwcode] Closing. Daemon continues running in background.`),console.log("[daemon] Stop it with: jwcode stop"))},"cleanup");process.on("SIGINT",()=>{w(),process.exit(0)}),process.on("SIGTERM",()=>{w(),process.exit(0)}),process.on("exit",w),await Yt(d),Promise.resolve().then(()=>(nn(),tn)).then(({checkForUpdates:h})=>{h(Ct).then(k=>{k?.updateAvailable&&(console.log(`
80
+ Update available: v${k.current} \u2192 v${k.latest}`),console.log(` Run 'jwcode update' (or '${k.url}') to upgrade.
81
+ `))}).catch(()=>{})});let T=setInterval(()=>{Promise.resolve().then(()=>(kt(),Zt)).then(({readDaemonInfo:h,isDaemonAlive:k,startDaemon:_,writeDaemonInfo:y})=>{let S=h();if(S&&!k(S)){console.error(`
82
+ [daemon] Daemon process died. Attempting auto-restart...`);try{let M=_({installDir:s,workspaceDir:o,port:d,wsPort:f,forceKill:!0,idleTimeout:300});y(M.pid,d,f,o),console.error("[daemon] Daemon restarted successfully.")}catch(M){console.error("[daemon] Auto-restart failed:",String(M))}}}).catch(()=>{})},3e4);await To(d,f,o,s),clearInterval(T)}i(Hs,"cmdStart");async function To(t,e,n,o){let s=`http://localhost:${t}`,c=`ws://localhost:${e}/ws`;process.stdout.write("\x1B[?1049h"),process.stdout.write("\x1B[2J\x1B[H");let d=!1;try{d=(await(await fetch(`${s}/api/config/provider`)).json())?.data?.configured===!0}catch{}d||await new Promise(m=>{let{unmount:g}=on(rn(ro,{backendUrl:s,onComplete:i(()=>{g(),m()},"onComplete")}))});let{unmount:f}=on(rn(Ut,{backendUrl:s,wsUrl:c,onExit:i(()=>{process.stdout.write("\x1B[?1049l"),process.exit(0)},"onExit")}));await new Promise(m=>{process.on("SIGINT",()=>m()),process.on("SIGTERM",()=>m())}),process.stdout.write("\x1B[?1049l")}i(To,"startTUI");async function Ws(t){process.stdin.isTTY||(console.error("Error: jwcode requires a real terminal (TTY)."),console.error("Please run from a terminal emulator like Windows Terminal, CMD, or PowerShell."),process.exit(1)),process.env.JWCODE_NO_BRACKETED_PASTE!=="1"&&process.stdout.write("\x1B[?2004h");let e=fo(),n=String(t.backend||e.backend_url),o=String(t.ws||n.replace(/^http/,"ws").replace(/:(\d+)/,(d,f)=>":"+(parseInt(f)+1))+"/ws"||e.ws_url);process.stdout.write("\x1B[?1049h"),process.stdout.write("\x1B[2J\x1B[H");let{unmount:s,waitUntilExit:c}=on(rn(Ut,{backendUrl:n,wsUrl:o,onExit:i(()=>{process.stdout.write("\x1B[?1049l"),process.exit(0)},"onExit")}));await c(),process.stdout.write("\x1B[?1049l")}i(Ws,"cmdRun");async function $s(){let{execSync:t}=await import("node:child_process"),{readDaemonInfo:e,clearDaemonInfo:n,isDaemonAlive:o}=await Promise.resolve().then(()=>(kt(),Zt)),s=e();if(!s){console.log("No daemon is running.");return}if(!o(s)){console.log("Daemon process is already dead. Cleaning up."),n();return}console.log("Stopping JWCode daemon (PID "+s.pid+")...");try{process.platform==="win32"?t("taskkill /F /T /PID "+s.pid,{stdio:"ignore"}):process.kill(s.pid,"SIGTERM"),n(),console.log("Daemon stopped.")}catch(c){console.error("Failed to stop daemon:",String(c))}}i($s,"cmdStop");async function js(){let{checkForUpdates:t,runNpmUpdate:e}=await Promise.resolve().then(()=>(nn(),tn));console.log("Checking for updates...");let n=await t(Ct);if(!n){console.log("Could not check for updates. Try again later or install manually:"),console.log(" npm install -g @jwcode/cli@latest");return}if(!n.updateAvailable){console.log(`JWCode CLI is up to date (v${n.current}).`);return}if(console.log(`Update available: v${n.current} \u2192 v${n.latest}`),console.log(""),n.body){let c=n.body.split(`
83
+ `).filter(d=>d.trim()).slice(0,3);for(let d of c)console.log(" "+d);console.log("")}let s=(await import("node:readline")).createInterface({input:process.stdin,output:process.stdout});s.question("Update now? [Y/n] ",c=>{if(s.close(),c.toLowerCase()==="n"||c.toLowerCase()==="no"){console.log('Skipped. Run "jwcode update" later or: npm install -g @jwcode/cli@latest'),process.exit(0);return}console.log("Updating...");let d=e();d.ok?console.log("Updated successfully. Restart jwcode to use the new version."):(console.error("Update failed:",d.message),console.log("Try manually: npm install -g @jwcode/cli@latest")),process.exit(d.ok?0:1)})}i(js,"cmdUpdate");async function Us(){if(process.argv.includes("--help")||process.argv.includes("-h")||process.argv.includes("help")){wo();return}if(process.argv.includes("--version")||process.argv.includes("-v")||process.argv.includes("version")){console.log(`JWCode CLI v${Ct}`);return}let t=Ns(),e=t._cmd||"start";switch(e){case"start":await Hs(t);break;case"run":await Ws(t);break;case"stop":await $s();break;case"update":await js();break;default:console.error(`Unknown command: ${e}`),wo(),process.exit(1)}}i(Us,"main");Us().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Command definitions — Chinese descriptions.
3
+ * Local commands handled by TUI; WS commands sent to backend.
4
+ */
5
+ export interface CmdEntry {
6
+ cmd: string;
7
+ desc: string;
8
+ via: 'local' | 'ws';
9
+ action: string | null;
10
+ }
11
+ export declare const LOCAL_COMMANDS: CmdEntry[];
12
+ export declare const WS_COMMANDS: CmdEntry[];
13
+ export declare const ALL_COMMANDS: CmdEntry[];
14
+ export declare const SLASH_COMMANDS: Record<string, {
15
+ action: string;
16
+ needsArg?: boolean;
17
+ } | null>;
18
+ export declare const HELP_TEXT = "\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 JWCode \u547D\u4EE4\u5E2E\u52A9 \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 \u672C\u5730\u547D\u4EE4: \u2551\n\u2551 /help \u663E\u793A\u6B64\u5E2E\u52A9\u4FE1\u606F \u2551\n\u2551 /plan \u5207\u6362\u89C4\u5212\u6A21\u5F0F \u2551\n\u2551 /auto \u5207\u6362\u81EA\u52A8\u6A21\u5F0F \u2551\n\u2551 /context \u663E\u793A\u5F53\u524D\u4F1A\u8BDD\u72B6\u6001 \u2551\n\u2551 /exit \u9000\u51FA JWCode \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 \u540E\u7AEF\u547D\u4EE4: \u2551\n\u2551 /confirm \u786E\u8BA4\u6267\u884C\u5F53\u524D\u89C4\u5212 \u2551\n\u2551 /cancel \u53D6\u6D88\u5F53\u524D\u89C4\u5212 \u2551\n\u2551 /stop \u505C\u6B62\u5F53\u524D AI \u751F\u6210 \u2551\n\u2551 /pause \u6682\u505C\u5F53\u524D AI \u751F\u6210 \u2551\n\u2551 /resume \u6062\u590D\u6682\u505C\u7684\u751F\u6210 \u2551\n\u2551 /clear \u6E05\u9664\u5F53\u524D\u4F1A\u8BDD\u6D88\u606F \u2551\n\u2551 /model <\u540D> \u5207\u6362 AI \u6A21\u578B \u2551\n\u2551 /compact \u538B\u7F29\u4F1A\u8BDD\u4E0A\u4E0B\u6587 \u2551\n\u2551 /doctor \u7CFB\u7EDF\u81EA\u8BCA\u65AD \u2551\n\u2551 /rewind \u56DE\u6EDA\u5230\u6700\u8FD1\u68C0\u67E5\u70B9 \u2551\n\u2551 /init \u751F\u6210\u9879\u76EE JWCODE.md \u2551\n\u2551 /effort <\u7EA7> \u8BBE\u7F6E\u52AA\u529B\u7EA7\u522B low/med/high \u2551\n\u2551 /branch <\u540D> \u521B\u5EFA\u5206\u652F\u4F1A\u8BDD \u2551\n\u2551 /mcp <\u64CD\u4F5C> MCP \u670D\u52A1\u5668\u7BA1\u7406 \u2551\n\u2551 /skills \u67E5\u770B Skills \u5217\u8868 \u2551\n\u2551 /agents \u5217\u51FA Agent \u4EE3\u7406 \u2551\n\u2551 /config <\u64CD> \u7BA1\u7406\u914D\u7F6E (get/set/list) \u2551\n\u2551 /plugin <\u64CD> \u63D2\u4EF6\u7BA1\u7406 \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 \u5FEB\u6377\u952E: \u2551\n\u2551 \u2191\u2193 \u6D4F\u89C8\u8F93\u5165\u5386\u53F2 (\u6700\u8FD130\u6761) \u2551\n\u2551 PgUp/PgDn \u7FFB\u9875\u6D4F\u89C8\u6D88\u606F \u2551\n\u2551 Home/End \u8DF3\u5230\u6700\u65E9/\u6700\u65B0\u6D88\u606F \u2551\n\u2551 Tab \u5207\u6362 Plan/Act \u6A21\u5F0F \u2551\n\u2551 / \u6253\u5F00\u547D\u4EE4\u9762\u677F (\u53EF\u7FFB\u9875) \u2551\n\u2551 Esc \u5173\u95ED\u9762\u677F/\u53D6\u6D88\u5BA1\u6279 \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 \u666E\u901A\u8F93\u5165\u5373\u53D1\u9001\u804A\u5929\u6D88\u606F \u2551\n\u2551 \u8F93\u5165\u6846\u663E\u793A\u5B57\u7B26\u6570+token\u4F30\u7B97 \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D";
@@ -0,0 +1,99 @@
1
+ // Local TUI commands
2
+ export const LOCAL_COMMANDS = [
3
+ { cmd: '/help', desc: '显示所有命令', via: 'local', action: null },
4
+ { cmd: '/plan', desc: '切换规划模式 (先规划再执行)', via: 'local', action: 'plan_mode' },
5
+ { cmd: '/auto', desc: '切换自动模式 (自动批准工具执行)', via: 'local', action: 'auto_mode' },
6
+ { cmd: '/context', desc: '显示当前会话状态', via: 'local', action: 'show_context' },
7
+ { cmd: '/exit', desc: '退出 JWCode', via: 'local', action: '__exit__' },
8
+ ];
9
+ // WebSocket commands sent to backend
10
+ export const WS_COMMANDS = [
11
+ { cmd: '/confirm', desc: '确认当前规划并开始执行', via: 'ws', action: '__confirm_plan' },
12
+ { cmd: '/cancel', desc: '取消当前规划', via: 'ws', action: '__cancel_plan' },
13
+ { cmd: '/stop', desc: '停止当前 AI 生成', via: 'ws', action: 'stop' },
14
+ { cmd: '/pause', desc: '暂停当前 AI 生成', via: 'ws', action: 'pause' },
15
+ { cmd: '/resume', desc: '恢复暂停的 AI 生成', via: 'ws', action: 'resume' },
16
+ { cmd: '/clear', desc: '清除当前会话消息', via: 'ws', action: 'clear' },
17
+ { cmd: '/doctor', desc: '运行系统自诊断', via: 'ws', action: 'doctor' },
18
+ { cmd: '/rewind', desc: '回滚到最近的检查点', via: 'ws', action: 'rewind' },
19
+ { cmd: '/compact', desc: '压缩会话上下文 (释放 token)', via: 'ws', action: 'compact' },
20
+ { cmd: '/model', desc: '切换 AI 模型 (用法: /model <模型名>)', via: 'ws', action: 'model_change' },
21
+ { cmd: '/init', desc: '分析项目并生成 JWCODE.md 项目记忆文件', via: 'ws', action: 'init' },
22
+ { cmd: '/effort', desc: '设置任务努力级别 (low/medium/high)', via: 'ws', action: 'effort' },
23
+ { cmd: '/branch', desc: '创建分支会话 (用法: /branch <名称>)', via: 'ws', action: 'branch' },
24
+ { cmd: '/mcp', desc: 'MCP 服务器管理 (list/add/remove)', via: 'ws', action: 'mcp' },
25
+ { cmd: '/skills', desc: '查看可用 Skills 列表', via: 'ws', action: 'skills' },
26
+ { cmd: '/agents', desc: '列出配置的 Agent 代理', via: 'ws', action: 'agents' },
27
+ { cmd: '/config', desc: '管理配置 (get/set/list)', via: 'ws', action: 'config' },
28
+ { cmd: '/plugin', desc: '插件管理 (install/list/remove)', via: 'ws', action: 'plugin' },
29
+ ];
30
+ export const ALL_COMMANDS = [...LOCAL_COMMANDS, ...WS_COMMANDS];
31
+ // Action map: slash command -> { action, needsArg? }
32
+ export const SLASH_COMMANDS = {
33
+ '/help': null,
34
+ '/plan': { action: 'plan_mode' },
35
+ '/auto': { action: 'auto_mode' },
36
+ '/context': { action: 'show_context' },
37
+ '/exit': { action: '__exit__' },
38
+ '/quit': { action: '__exit__' },
39
+ '/confirm': { action: '__confirm_plan' },
40
+ '/cancel': { action: '__cancel_plan' },
41
+ '/stop': { action: 'stop' },
42
+ '/pause': { action: 'pause' },
43
+ '/resume': { action: 'resume' },
44
+ '/clear': { action: 'clear' },
45
+ '/doctor': { action: 'doctor' },
46
+ '/rewind': { action: 'rewind' },
47
+ '/compact': { action: 'compact' },
48
+ '/model': { action: 'model_change', needsArg: true },
49
+ '/init': { action: 'init' },
50
+ '/effort': { action: 'effort', needsArg: true },
51
+ '/branch': { action: 'branch', needsArg: true },
52
+ '/mcp': { action: 'mcp', needsArg: true },
53
+ '/skills': { action: 'skills' },
54
+ '/agents': { action: 'agents' },
55
+ '/config': { action: 'config', needsArg: true },
56
+ '/plugin': { action: 'plugin', needsArg: true },
57
+ };
58
+ export const HELP_TEXT = `
59
+ ╔══════════════════════════════════════════╗
60
+ ║ JWCode 命令帮助 ║
61
+ ╠══════════════════════════════════════════╣
62
+ ║ 本地命令: ║
63
+ ║ /help 显示此帮助信息 ║
64
+ ║ /plan 切换规划模式 ║
65
+ ║ /auto 切换自动模式 ║
66
+ ║ /context 显示当前会话状态 ║
67
+ ║ /exit 退出 JWCode ║
68
+ ╠══════════════════════════════════════════╣
69
+ ║ 后端命令: ║
70
+ ║ /confirm 确认执行当前规划 ║
71
+ ║ /cancel 取消当前规划 ║
72
+ ║ /stop 停止当前 AI 生成 ║
73
+ ║ /pause 暂停当前 AI 生成 ║
74
+ ║ /resume 恢复暂停的生成 ║
75
+ ║ /clear 清除当前会话消息 ║
76
+ ║ /model <名> 切换 AI 模型 ║
77
+ ║ /compact 压缩会话上下文 ║
78
+ ║ /doctor 系统自诊断 ║
79
+ ║ /rewind 回滚到最近检查点 ║
80
+ ║ /init 生成项目 JWCODE.md ║
81
+ ║ /effort <级> 设置努力级别 low/med/high ║
82
+ ║ /branch <名> 创建分支会话 ║
83
+ ║ /mcp <操作> MCP 服务器管理 ║
84
+ ║ /skills 查看 Skills 列表 ║
85
+ ║ /agents 列出 Agent 代理 ║
86
+ ║ /config <操> 管理配置 (get/set/list) ║
87
+ ║ /plugin <操> 插件管理 ║
88
+ ╠══════════════════════════════════════════╣
89
+ ║ 快捷键: ║
90
+ ║ ↑↓ 浏览输入历史 (最近30条) ║
91
+ ║ PgUp/PgDn 翻页浏览消息 ║
92
+ ║ Home/End 跳到最早/最新消息 ║
93
+ ║ Tab 切换 Plan/Act 模式 ║
94
+ ║ / 打开命令面板 (可翻页) ║
95
+ ║ Esc 关闭面板/取消审批 ║
96
+ ╠══════════════════════════════════════════╣
97
+ ║ 普通输入即发送聊天消息 ║
98
+ ║ 输入框显示字符数+token估算 ║
99
+ ╚══════════════════════════════════════════╝`;
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ toolName: string;
3
+ payload: string;
4
+ onAllow: () => void;
5
+ onDeny: () => void;
6
+ }
7
+ export declare function ApprovalModal({ toolName, payload, onAllow, onDeny }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ApprovalModal — permission prompt in Claude Code style.
4
+ * Arrow keys to select, Enter to confirm, Esc to cancel.
5
+ */
6
+ import { useState } from 'react';
7
+ import { Box, Text, useInput } from 'ink';
8
+ export function ApprovalModal({ toolName, payload, onAllow, onDeny }) {
9
+ const [selected, setSelected] = useState(0); // 0=allow, 1=deny
10
+ useInput((_input, key) => {
11
+ if (key.escape || key.tab) {
12
+ onDeny();
13
+ return;
14
+ }
15
+ if (key.upArrow || key.downArrow) {
16
+ setSelected(prev => prev === 0 ? 1 : 0);
17
+ return;
18
+ }
19
+ if (key.return) {
20
+ if (selected === 0)
21
+ onAllow();
22
+ else
23
+ onDeny();
24
+ return;
25
+ }
26
+ if (_input === '1') {
27
+ onAllow();
28
+ return;
29
+ }
30
+ if (_input === '2') {
31
+ onDeny();
32
+ return;
33
+ }
34
+ if (_input === 'y' || _input === 'Y') {
35
+ onAllow();
36
+ return;
37
+ }
38
+ if (_input === 'n' || _input === 'N') {
39
+ onDeny();
40
+ return;
41
+ }
42
+ });
43
+ const desc = payload
44
+ ? (payload.length > 200 ? payload.slice(0, 200) + '...' : payload)
45
+ : '';
46
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Do you want to proceed?" }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 2, marginBottom: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: selected === 0 ? 'green' : undefined, children: [selected === 0 ? ' ❯' : ' ', " 1. Allow"] }) }), _jsx(Box, { children: _jsxs(Text, { color: selected === 1 ? 'red' : undefined, children: [selected === 1 ? ' ❯' : ' ', " 2. Deny"] }) })] }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { dimColor: true, children: "Tool: " }), _jsx(Text, { color: "cyan", children: toolName }), desc ? _jsxs(Text, { dimColor: true, children: [" ", desc] }) : null] }), _jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: " Esc to cancel \u00B7 " }), _jsx(Text, { dimColor: true, children: "\u2191\u2193 to select \u00B7 " }), _jsx(Text, { dimColor: true, children: "Enter to confirm" })] })] }));
47
+ }
@@ -0,0 +1,10 @@
1
+ import { type Message } from '../protocol.js';
2
+ interface Props {
3
+ messages: Message[];
4
+ currentMessage: Message | null;
5
+ scrollOffset: number;
6
+ terminalRows: number;
7
+ reservedRows: number;
8
+ }
9
+ export declare function ChatArea({ messages, currentMessage, scrollOffset, terminalRows, reservedRows }: Props): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,49 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * ChatArea — renders message list with markdown, tool calls, steps, thinking.
4
+ * Shows newest messages at the bottom; uses scrollOffset to page through history.
5
+ */
6
+ import { Box, Text } from 'ink';
7
+ const SEP = '─'.repeat(60);
8
+ export function ChatArea({ messages, currentMessage, scrollOffset, terminalRows, reservedRows }) {
9
+ const allMessages = currentMessage
10
+ ? [...messages.filter(m => m.id !== currentMessage.id)]
11
+ : messages;
12
+ const availableRows = Math.max(10, terminalRows - reservedRows);
13
+ const maxVisible = Math.max(5, Math.floor(availableRows / 4));
14
+ const total = allMessages.length;
15
+ // scrollOffset = how many messages scrolled above the bottom
16
+ // 0 = at bottom (show newest), N = N messages scrolled up
17
+ const clampedOffset = Math.min(scrollOffset, total - 1);
18
+ const end = total - clampedOffset;
19
+ const start = Math.max(0, end - maxVisible);
20
+ const visibleMessages = allMessages.slice(start, end);
21
+ const isScrolledUp = clampedOffset > 0;
22
+ const hiddenAbove = start;
23
+ const hiddenBelow = clampedOffset;
24
+ return (_jsxs(Box, { flexDirection: "column", width: "100%", children: [isScrolledUp && (_jsx(Box, { children: _jsxs(Text, { color: "yellow", dimColor: true, children: ["\u25B2 [", start + 1, "-", end, "/", total, "] \u4E0A\u7FFB\u4E2D (PgUp/PgDn \u7FFB\u9875, Home \u5F00\u5934, End \u6700\u65B0)"] }) })), !isScrolledUp && total > maxVisible && (_jsx(Box, { children: _jsxs(Text, { color: "grey", dimColor: true, children: ["[", start + 1, "-", end, "/", total, "] \u2191/PgUp \u67E5\u770B\u66F4\u65E9\u6D88\u606F"] }) })), visibleMessages.map(msg => (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [msg.type === 'user' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: SEP }), _jsxs(Text, { color: "green", bold: true, children: ["> ", msg.content] })] })), msg.type === 'assistant' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: ' ' }), msg.steps.map((step, i) => (_jsx(StepDisplay, { step: step }, step.id || i))), msg.thinking && (_jsx(Text, { dimColor: true, italic: true, children: truncate(msg.thinking, 200) })), msg.toolCalls.map((tc, i) => (_jsx(ToolCallDisplay, { tc: tc }, tc.id || i))), msg.content && _jsx(Text, { children: msg.content }), _jsx(Text, { dimColor: true, children: SEP })] })), msg.type === 'system' && (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", msg.content] }) }))] }, msg.id))), currentMessage && (_jsxs(Box, { flexDirection: "column", children: [currentMessage.thinking && (_jsx(Text, { dimColor: true, italic: true, children: truncate(currentMessage.thinking, 200) })), currentMessage.toolCalls.map((tc, i) => (_jsx(ToolCallDisplay, { tc: tc }, tc.id || i))), currentMessage.content && _jsx(Text, { children: currentMessage.content })] }, currentMessage.id))] }));
25
+ }
26
+ function StepDisplay({ step }) {
27
+ const icon = step.status === 'success' ? '✓' : step.status === 'error' ? '✗' : '▶';
28
+ const color = step.status === 'success' ? 'green' : step.status === 'error' ? 'red' : 'cyan';
29
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: color, children: [" ", icon, " ", step.title] }), step.thought && _jsxs(Text, { color: "blue", dimColor: true, children: [" ", truncate(step.thought, 200)] }), step.action && _jsxs(Text, { color: "yellow", children: [" ", truncate(step.action, 200)] }), step.result && _jsxs(Text, { color: "green", children: [" ", truncate(step.result, 300)] })] }));
30
+ }
31
+ function ToolCallDisplay({ tc }) {
32
+ const argsStr = tc.args ? truncate(formatJson(tc.args), 200) : '';
33
+ const statusIcon = tc.status === 'complete' ? '✓' : tc.status === 'running' ? '◷' : '✗';
34
+ const statusColor = tc.status === 'complete' ? 'green' : tc.status === 'running' ? 'yellow' : 'red';
35
+ return (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { color: statusColor, children: [" ", statusIcon, " "] }), _jsx(Text, { bold: true, color: "magenta", children: tc.name }), argsStr && _jsxs(Text, { dimColor: true, children: [" ", argsStr] })] }), tc.result && (_jsx(Box, { paddingLeft: 4, children: _jsx(Text, { color: "green", dimColor: true, children: truncate(tc.result, 200) }) }))] }));
36
+ }
37
+ function formatJson(s) {
38
+ try {
39
+ return JSON.stringify(JSON.parse(s), null, 2);
40
+ }
41
+ catch {
42
+ return s;
43
+ }
44
+ }
45
+ function truncate(s, max) {
46
+ if (s.length <= max)
47
+ return s;
48
+ return s.slice(0, max) + '...';
49
+ }
@@ -0,0 +1,6 @@
1
+ interface Props {
2
+ filter: string;
3
+ onSelect: (cmd: string | null) => void;
4
+ }
5
+ export declare function CommandPalette({ filter, onSelect }: Props): import("react/jsx-runtime").JSX.Element;
6
+ export {};