@mcplato/wandplus 2.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +46 -0
  2. package/dist/index.js +28 -0
  3. package/package.json +50 -0
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # @mcplato/wandplus
2
+
3
+ **WandPlus** — a terminal AI coding agent powered by the [MCPlato](https://wandplus.dev) monolith engine. Built with [Ink](https://github.com/vadimdemedes/ink) (React for the terminal).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm i -g @mcplato/wandplus
9
+ ```
10
+
11
+ This pulls in a small JS frontend plus a single platform-matched binary bundle
12
+ (`@mcplato/wandplus-<platform>`) containing the `monolith` engine and its tool
13
+ runtime. Only the bundle matching your OS/CPU is installed.
14
+
15
+ Supported platforms: macOS (arm64 / x64), Linux (x64), Windows (x64).
16
+
17
+ ## Configure (no login — just a base URL + token)
18
+
19
+ WandPlus reads credentials from environment variables or `~/.config/mcplato-tui/config.json`.
20
+ On first run it offers an interactive setup wizard.
21
+
22
+ ```bash
23
+ export WANDPLUS_AUTH_TOKEN=... # required — your token
24
+ # optional; defaults to the MCPlato gateway:
25
+ export WANDPLUS_BASE_URL=https://api.mcplato.com/api/v1/provider/anthropic
26
+ ```
27
+
28
+ ## Run
29
+
30
+ ```bash
31
+ wandplus --cwd /path/to/your/project
32
+ ```
33
+
34
+ Keys: `Enter` send · `Ctrl+J` newline · `Ctrl+C` interrupt · `↑/↓ + Enter` approve.
35
+ Slash commands: `/compact` `/clear` `/quit`.
36
+
37
+ ## Features
38
+
39
+ - Multi-turn streaming conversation
40
+ - Tools / MCP / Skills (executed by the monolith engine)
41
+ - Permission approval, plan-mode approval, and ask-user multi-choice prompts
42
+ - Todo list panel, automatic + manual context compaction (`/compact`)
43
+
44
+ ## License
45
+
46
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import{useEffect as Ro,useState as We}from"react";import{createRequire as bo}from"module";import{render as Ao,Text as en}from"ink";import{useEffect as An,useState as xt}from"react";import{Box as Pn,Static as Cn,Text as be,useApp as En}from"ink";import{useEffect as rn,useReducer as sn,useRef as an,useState as b}from"react";function st(t,e){let n=null,o=()=>{n&&(clearTimeout(n),n=null)};return{schedule(){n||(n=setTimeout(()=>{n=null,e()},t))},flushNow(){o(),e()},cancel(){o()}}}var ln=80;function at(t){let[e,n]=b([]),[o,r]=b("idle"),[i,s]=b([]),[a,c]=b({type:"none"}),[f,g]=b({}),[u,k]=b(!1),[h,m]=b(!1),[p,y]=b(null),_=an([]),[,L]=sn(E=>E+1,0);rn(()=>{let E=st(ln,L),nn=()=>E.schedule(),Ke=()=>E.flushNow(),He=d=>{let v=_.current.filter(on=>on.id!==d.id);_.current=[...v,d]},ze=d=>{He(d),Ke()},Fe=d=>{He(d),nn()},Ve=d=>{_.current=_.current.filter(v=>v.id!==d),Ke()},Ge=d=>n(v=>[...v,d]),Qe=d=>r(d),Xe=d=>s(d),Ye=d=>g(v=>({...v,...d})),Ze=d=>k(d),et=()=>m(!0),tt=d=>{m(!1),n(v=>[...v,{id:`compact-${v.length}-${Date.now()}`,type:"compact",timestamp:Date.now(),content:d,compactInfo:{status:"completed",summary:d}}])},nt=d=>c({type:"permission",req:d}),ot=d=>c({type:"plan",req:d}),rt=d=>c({type:"ask_user",req:d}),Y=()=>c({type:"none"}),it=d=>y(d.message);return t.on("live:start",ze),t.on("live:update",Fe),t.on("live:end",Ve),t.on("committed",Ge),t.on("status",Qe),t.on("todos",Xe),t.on("tokens",Ye),t.on("plan:mode",Ze),t.on("compact:start",et),t.on("compact:end",tt),t.on("permission",nt),t.on("permission:clear",Y),t.on("plan:approval",ot),t.on("ask:user",rt),t.on("ask:clear",Y),t.on("error",it),()=>{let d=t;d.off("live:start",ze),d.off("live:update",Fe),d.off("live:end",Ve),d.off("committed",Ge),d.off("status",Qe),d.off("todos",Xe),d.off("tokens",Ye),d.off("plan:mode",Ze),d.off("compact:start",et),d.off("compact:end",tt),d.off("permission",nt),d.off("permission:clear",Y),d.off("plan:approval",ot),d.off("ask:user",rt),d.off("ask:clear",Y),d.off("error",it),E.cancel()}},[t]);let K=()=>{_.current=[],n([]),s([])};return{committed:e,live:_.current,status:o,todos:i,overlay:a,tokens:f,planMode:u,compacting:h,error:p,clear:K}}import un from"react";import{Box as A,Text as I}from"ink";import{marked as dt}from"marked";import{markedTerminal as dn}from"marked-terminal";var lt=!1;function cn(){lt||(dt.use(dn({width:process.stdout.columns??80,reflowText:!0})),lt=!0)}function Z(t){if(!t)return"";cn();try{let e=dt.parse(t);return(typeof e=="string"?e:t).replace(/\n+$/,"")}catch{return t}}import{jsx as S,jsxs as N}from"react/jsx-runtime";function mn(t){let e=t.command??t.file_path??t.path??t.pattern??t.url??t.query;if(e!=null)return String(e);try{let n=JSON.stringify(t);return n.length>100?n.slice(0,100)+"\u2026":n}catch{return""}}function pn(t){return t.startsWith("mcp__")?t.split("__").slice(1).join(":"):t}var ct=un.memo(function({msg:e}){switch(e.type){case"user":return N(A,{flexDirection:"row",marginTop:1,children:[S(I,{color:"blue",bold:!0,children:"\u276F "}),S(I,{children:e.content})]});case"assistant":{if(e.thinking){let o=e.thinking.content.trim();return o?N(A,{flexDirection:"column",marginTop:1,children:[S(I,{color:"magenta",dimColor:!0,children:"\u273B thinking"}),S(I,{dimColor:!0,children:o})]}):null}let n=e.content?.trim();return n?S(A,{flexDirection:"column",marginTop:1,children:S(I,{children:Z(n)})}):null}case"tool_use":{let n=e.tool;return n?N(A,{flexDirection:"row",marginTop:1,children:[S(I,{color:"cyan",children:"\u2699 "}),S(I,{color:"cyan",bold:!0,children:pn(n.name)}),S(I,{dimColor:!0,children:" "+mn(n.input)})]}):null}case"tool_result":{let n=e.toolResult;if(!n)return null;let r=(n.output??"").trimEnd().split(`
3
+ `),i=12,s=r.slice(0,i),a=r.length>i;return N(A,{flexDirection:"column",marginLeft:2,children:[s.map((c,f)=>S(I,{color:n.isError?"red":"gray",children:c||" "},f)),a&&N(I,{dimColor:!0,children:["\u2026 ",r.length-i," more lines"]})]})}case"compact":return S(A,{marginTop:1,marginBottom:1,borderStyle:"round",borderColor:"cyan",paddingX:1,children:N(I,{color:"cyan",children:["\u27F2 ",e.content||"Context compacted"]})});case"error":return S(A,{marginTop:1,children:N(I,{color:"red",children:["\u2716 ",e.content]})});default:return e.content?S(A,{marginTop:1,children:S(I,{dimColor:!0,children:e.content})}):null}});import gn from"react";import{Box as te,Text as P}from"ink";import{jsx as M,jsxs as ee}from"react/jsx-runtime";function ut({live:t}){return t.length===0?null:M(te,{flexDirection:"column",children:t.map(e=>M(fn,{msg:e},e.id))})}var fn=gn.memo(function({msg:e}){if(e.thinking){let n=e.thinking.content;return ee(te,{flexDirection:"column",marginTop:1,children:[M(P,{color:"magenta",dimColor:!0,children:"\u273B thinking"}),ee(P,{dimColor:!0,children:[n,M(P,{color:"magenta",children:"\u258A"})]})]})}return e.type==="assistant"?M(te,{flexDirection:"column",marginTop:1,children:ee(P,{children:[e.content??"",M(P,{color:"blue",children:"\u258A"})]})}):e.type==="tool_use"&&e.tool?ee(te,{flexDirection:"row",marginTop:1,children:[M(P,{color:"cyan",children:"\u2699 "}),M(P,{color:"cyan",children:e.tool.name}),M(P,{color:"cyan",children:"\u258A"})]}):null});import{Box as Se,Text as H}from"ink";import mt from"ink-spinner";import{jsx as Ie,jsxs as B}from"react/jsx-runtime";var hn={idle:{text:"Ready",color:"green",spin:!1},thinking:{text:"Thinking",color:"yellow",spin:!0},tool_running:{text:"Running tools",color:"cyan",spin:!0},waiting_permission:{text:"Waiting for approval",color:"red",spin:!0},error:{text:"Error",color:"red",spin:!1}};function pt({status:t,tokens:e,planMode:n,compacting:o}){let r=hn[t],i=e.contextWindow&&e.totalTokens?Math.round(e.totalTokens/e.contextWindow*100):null,s=i==null?"gray":i>80?"red":i>60?"yellow":"gray";return B(Se,{flexDirection:"row",justifyContent:"space-between",marginTop:1,children:[B(Se,{flexDirection:"row",children:[o?B(H,{color:"cyan",children:[Ie(mt,{type:"dots"})," Compacting context\u2026"]}):B(H,{color:r.color,children:[r.spin?Ie(mt,{type:"dots"}):"\u25CF"," ",r.text]}),n&&Ie(H,{color:"blue",children:" \xB7 plan mode"})]}),B(Se,{flexDirection:"row",children:[e.model&&B(H,{dimColor:!0,children:[e.model," "]}),i!=null&&B(H,{color:s,children:[i,"% ctx"]})]})]})}import{Box as gt,Text as Te}from"ink";import{jsx as ft,jsxs as ve}from"react/jsx-runtime";var yn={pending:"\u25CB",in_progress:"\u25D0",completed:"\u2713"},_n={pending:"gray",in_progress:"yellow",completed:"green"};function ht({todos:t}){return t.length===0?null:ve(gt,{flexDirection:"column",borderStyle:"round",borderColor:"cyan",paddingX:1,marginTop:1,children:[ft(Te,{bold:!0,color:"cyan",children:"Tasks"}),t.map((e,n)=>ve(gt,{flexDirection:"row",children:[ve(Te,{color:_n[e.status],children:[yn[e.status]," "]}),ft(Te,{color:e.status==="completed"?"gray":void 0,strikethrough:e.status==="completed",children:e.status==="in_progress"&&e.activeForm||e.content})]},n))]})}import{useState as yt}from"react";import{Box as _t,Text as ne,useInput as kn}from"ink";import{jsx as xe,jsxs as Me}from"react/jsx-runtime";function kt({onSubmit:t,onInterrupt:e,isDisabled:n,hint:o}){let[r,i]=yt(""),[s,a]=yt(0),c=h=>{i(m=>m.slice(0,s)+h+m.slice(s)),a(m=>m+h.length)};kn((h,m)=>{if(m.ctrl&&h==="c"){e();return}if(!n){if(m.return&&m.meta||m.ctrl&&h==="j"){c(`
4
+ `);return}if(m.return){let p=r;if(p.trim().length===0)return;i(""),a(0),t(p);return}if(m.backspace||m.delete){s>0&&(i(p=>p.slice(0,s-1)+p.slice(s)),a(p=>Math.max(0,p-1)));return}if(m.leftArrow){a(p=>Math.max(0,p-1));return}if(m.rightArrow){a(p=>Math.min(r.length,p+1));return}if(m.ctrl&&h==="a"){a(0);return}if(m.ctrl&&h==="e"){a(r.length);return}m.ctrl||m.meta||m.escape||m.tab||m.upArrow||m.downArrow||h&&c(h)}});let f=r.slice(0,s),g=r[s]??" ",u=r.slice(s+1);return Me(_t,{flexDirection:"column",children:[Me(_t,{borderStyle:"round",borderColor:n?"gray":"blue",paddingX:1,children:[xe(ne,{color:n?"gray":"blue",children:"\u276F "}),Me(ne,{children:[f,xe(ne,{inverse:!0,children:g}),u]})]}),xe(ne,{dimColor:!0,children:o??"Enter send \xB7 Ctrl+J newline \xB7 Ctrl+C interrupt \xB7 /compact /clear /quit"})]})}import{useRef as wn,useState as Sn}from"react";import{Box as wt,Text as D,useInput as In}from"ink";import{jsx as z,jsxs as re}from"react/jsx-runtime";var oe=[{label:"Allow once",decision:"allow"},{label:"Allow for this session",decision:"allow_session"},{label:"Deny",decision:"deny"}];function Tn(t){return t.startsWith("mcp__")?t.split("__").slice(1).join(":"):t}function St(t){let e=t.command??t.file_path??t.path??t.pattern??t.url;if(e!=null)return String(e);try{return JSON.stringify(t).slice(0,120)}catch{return""}}function It({req:t,onRespond:e}){let[n,o]=Sn(0),r=wn(0),i=s=>{let a=(r.current+s+oe.length)%oe.length;r.current=a,o(a)};return In((s,a)=>{a.upArrow&&i(-1),a.downArrow&&i(1),a.return&&e(t.requestId,oe[r.current].decision)}),re(wt,{flexDirection:"column",borderStyle:"round",borderColor:"yellow",paddingX:1,marginTop:1,children:[z(D,{bold:!0,color:"yellow",children:"\u26A0 Permission request"}),re(D,{children:[z(D,{bold:!0,children:Tn(t.toolName)}),t.reason?re(D,{dimColor:!0,children:[" \u2014 ",t.reason]}):null]}),St(t.input)?z(D,{color:"gray",children:St(t.input)}):null,z(wt,{flexDirection:"column",marginTop:1,children:oe.map((s,a)=>re(D,{color:a===n?"white":"gray",bold:a===n,children:[a===n?"\u276F ":" ",s.label]},s.decision))}),z(D,{dimColor:!0,children:"\u2191/\u2193 select \xB7 Enter confirm"})]})}import{useRef as vn,useState as xn}from"react";import{Box as Re,Text as O,useInput as Mn}from"ink";import{jsx as F,jsxs as ie}from"react/jsx-runtime";function Tt({req:t,onRespond:e}){let[n,o]=xn("approve"),r=vn("approve"),i=s=>{r.current=s,o(s)};return Mn((s,a)=>{let c=s.toLowerCase();c==="a"&&i("approve"),c==="k"&&i("keep"),(a.leftArrow||a.rightArrow)&&i(r.current==="approve"?"keep":"approve"),a.return&&e(t.requestId,r.current==="approve")}),ie(Re,{flexDirection:"column",borderStyle:"double",borderColor:"blue",paddingX:1,marginTop:1,children:[F(O,{bold:!0,color:"blue",children:"\u25A4 Plan review"}),F(Re,{marginY:1,children:F(O,{children:Z(t.plan||"(empty plan)")})}),ie(Re,{flexDirection:"row",children:[ie(O,{color:n==="approve"?"green":"gray",bold:n==="approve",children:[n==="approve"?"\u276F ":" ","[A] Approve"]}),F(O,{children:" "}),ie(O,{color:n==="keep"?"yellow":"gray",bold:n==="keep",children:[n==="keep"?"\u276F ":" ","[K] Keep planning"]})]}),F(O,{dimColor:!0,children:"A/K or \u2190/\u2192 \xB7 Enter confirm"})]})}import{useRef as V,useState as Rn}from"react";import{Box as se,Text as C,useInput as bn}from"ink";import{jsx as G,jsxs as q}from"react/jsx-runtime";function vt({req:t,onSubmit:e}){let n=t.questions,[,o]=Rn(0),r=()=>o(m=>m+1),i=V(0),s=V(0),a=V(n.map(()=>[])),c=V(n.map(()=>"")),f=V(!1),g=()=>{let m={};return n.forEach((p,y)=>{if(c.current[y]){m[p.header]=c.current[y];return}let _=a.current[y].map(L=>p.options[L]?.label).filter(Boolean);m[p.header]=_.join(", ")}),m};bn((m,p)=>{let y=i.current,_=n[y];if(_){if(f.current){p.return?f.current=!1:p.backspace||p.delete?c.current[y]=c.current[y].slice(0,-1):m&&!p.ctrl&&!p.meta&&(c.current[y]=c.current[y]+m),r();return}if(m.toLowerCase()==="e"){f.current=!0,r();return}if(p.upArrow){s.current=(s.current-1+_.options.length)%_.options.length,r();return}if(p.downArrow){s.current=(s.current+1)%_.options.length,r();return}if(m===" "){let L=_.multiSelect===!0,K=a.current[y];L?a.current[y]=K.includes(s.current)?K.filter(E=>E!==s.current):[...K,s.current]:a.current[y]=[s.current],r();return}p.return&&(!(_.multiSelect===!0)&&a.current[y].length===0&&!c.current[y]&&(a.current[y]=[s.current]),y<n.length-1?(i.current=y+1,s.current=0,f.current=!1,r()):e(t.requestId,g()))}});let u=i.current,k=n[u];if(!k)return null;let h=k.multiSelect===!0;return q(se,{flexDirection:"column",borderStyle:"round",borderColor:"magenta",paddingX:1,marginTop:1,children:[q(C,{bold:!0,color:"magenta",children:["? ",k.header," ",n.length>1?`(${u+1}/${n.length})`:""]}),G(C,{children:k.question}),G(se,{flexDirection:"column",marginTop:1,children:k.options.map((m,p)=>{let y=a.current[u].includes(p),_=h?y?"[x]":"[ ]":y?"(\u2022)":"( )";return q(se,{flexDirection:"row",children:[q(C,{color:p===s.current?"white":"gray",bold:p===s.current,children:[p===s.current?"\u276F ":" ",_," ",m.label]}),m.description?q(C,{dimColor:!0,children:[" \u2014 ",m.description]}):null]},p)})}),(c.current[u]||f.current)&&q(se,{marginTop:1,children:[G(C,{color:"cyan",children:"custom: "}),q(C,{children:[c.current[u],f.current?G(C,{inverse:!0,children:" "}):null]})]}),G(C,{dimColor:!0,children:f.current?"type answer \xB7 Enter done":`\u2191/\u2193 move \xB7 ${h?"Space toggle \xB7 ":"Space pick \xB7 "}e custom \xB7 Enter ${u<n.length-1?"next":"submit"}`})]})}import{jsx as x,jsxs as Ae}from"react/jsx-runtime";function Mt({session:t}){let{exit:e}=En(),n=at(t),[o,r]=xt(!1),[i,s]=xt(null);An(()=>{let g=!1;return t.initialize().then(()=>{g||r(!0)}).catch(u=>{g||s(u.message)}),()=>{g=!0}},[t]);let a=g=>{let u=g.trim();if(u==="/quit"||u==="/exit"){t.dispose(),e();return}if(u==="/clear"){n.clear();return}if(u==="/compact"){t.compact();return}t.send(g)},c=()=>{n.status==="idle"?(t.dispose(),e()):t.interrupt()},f=n.overlay.type!=="none";return Ae(Pn,{flexDirection:"column",children:[x(Cn,{items:n.committed,children:g=>x(ct,{msg:g},g.id)}),x(ut,{live:n.live}),n.todos.length>0&&x(ht,{todos:n.todos}),n.overlay.type==="permission"&&x(It,{req:n.overlay.req,onRespond:(g,u)=>{t.respondPermission(g,u)}}),n.overlay.type==="plan"&&x(Tt,{req:n.overlay.req,onRespond:(g,u)=>{t.respondPlanApproval(g,u)}}),n.overlay.type==="ask_user"&&x(vt,{req:n.overlay.req,onSubmit:(g,u)=>{t.respondAskUser?.(g,u)}}),x(pt,{status:n.status,tokens:n.tokens,planMode:n.planMode,compacting:n.compacting}),i&&Ae(be,{color:"red",children:["init error: ",i]}),n.error&&Ae(be,{color:"red",children:["error: ",n.error]}),!o&&!i&&x(be,{color:"yellow",children:"Connecting to monolith\u2026"}),o&&!f&&x(kt,{onSubmit:a,onInterrupt:c,isDisabled:n.status!=="idle"})]})}import{useState as Pe}from"react";import{Box as de,Text as j}from"ink";import Ut from"ink-text-input";import{homedir as Nn}from"os";import{dirname as Rt,join as U}from"path";import{fileURLToPath as Bn}from"url";import{mkdirSync as bt,readFileSync as At,writeFileSync as Dn,existsSync as Pt}from"fs";var ae="https://api.mcplato.com/api/v1/provider/anthropic";function Q(){let t=process.env.XDG_CONFIG_HOME,e=t&&t.trim()?t:U(Nn(),".config");return U(e,"mcplato-tui")}function Ct(){return U(Q(),"config.json")}function Et(){return U(Q(),"monolith.db")}function le(){return U(Q(),"tui.log")}function qn(){let t=Ct();if(!Pt(t))return{};try{return JSON.parse(At(t,"utf8"))}catch{return{}}}function Un(){let t=[U(process.cwd(),".env")],e=Rt(Bn(import.meta.url));for(let n=0;n<4;n++){t.push(U(e,".env"));let o=Rt(e);if(o===e)break;e=o}return t}function Nt(){for(let t of Un()){if(!Pt(t))continue;let e;try{e=At(t,"utf8")}catch{continue}for(let n of e.split(`
5
+ `)){let o=n.trim();if(!o||o.startsWith("#"))continue;let r=o.indexOf("=");if(r<0)continue;let i=o.slice(0,r).trim();i.startsWith("export ")&&(i=i.slice(7).trim());let s=o.slice(r+1).trim();(s.startsWith('"')&&s.endsWith('"')||s.startsWith("'")&&s.endsWith("'"))&&(s=s.slice(1,-1)),i&&process.env[i]===void 0&&(process.env[i]=s)}}}function Ln(){return process.env.WANDPLUS_BASE_URL?.trim()||void 0}function On(){return process.env.WANDPLUS_AUTH_TOKEN?.trim()||void 0}function Bt(){let t=qn(),e=Ln()||t.baseUrl?.trim()||ae,n=On()||t.apiKey?.trim()||"";return n?{baseUrl:e,apiKey:n,workingDir:t.workingDir}:null}function Dt(t){bt(Q(),{recursive:!0}),Dn(Ct(),JSON.stringify(t,null,2),{mode:384})}function qt(){bt(Q(),{recursive:!0})}import{jsx as R,jsxs as Ce}from"react/jsx-runtime";function Lt({onDone:t}){let[e,n]=Pe("url"),[o,r]=Pe(ae),[i,s]=Pe("");return Ce(de,{flexDirection:"column",paddingX:1,children:[R(j,{bold:!0,color:"cyan",children:"MCPlato TUI \u2014 first-run setup"}),R(j,{dimColor:!0,children:"No login required. Configure your Anthropic-compatible endpoint."}),Ce(de,{marginTop:1,flexDirection:"row",children:[R(j,{color:e==="url"?"blue":"gray",children:"Base URL: "}),e==="url"?R(Ut,{value:o,onChange:r,onSubmit:()=>n("key")}):R(j,{children:o})]}),e==="key"&&Ce(de,{flexDirection:"row",children:[R(j,{color:"blue",children:"API Token: "}),R(Ut,{value:i,onChange:s,mask:"*",onSubmit:()=>{let a=i.trim();if(!a)return;let c={baseUrl:o.trim()||ae,apiKey:a};Dt(c),t(c)}})]}),R(de,{marginTop:1,children:R(j,{dimColor:!0,children:"Enter to continue \xB7 saved to ~/.config/mcplato-tui/config.json"})})]})}import{EventEmitter as zn}from"events";import{randomUUID as jt}from"crypto";function Ot(t,e){return $n({messageId:e?.messageId,nodeId:t.nodeId,logicalMessageId:t.logicalMessageId,segmentIndex:t.segmentIndex,revision:t.revision,kind:t.kind,turnId:t.turnId,payloadJson:t.payloadJson,timestamp:t.createdAtMs,isStreaming:e?.isStreaming??t.op!=="seal",engineMetadata:t.engineMetadata})}function jn(t){if(!t||t.length===0)return{};try{return JSON.parse(Buffer.from(t).toString("utf8"))}catch{return{}}}function $n(t){if(t.engineMetadata?.is_reminder_block==="true"||t.engineMetadata?.compaction_reinjection==="true")return null;let e=t.engineMetadata?.sequence_in_turn,n={nodeId:t.nodeId,logicalMessageId:t.logicalMessageId,segmentIndex:e!=null&&parseInt(e,10)||t.segmentIndex,revision:t.revision,turnId:t.turnId,kind:t.kind},o=t.messageId||t.nodeId,r=jn(t.payloadJson);switch(t.kind){case"root":return null;case"user":return{id:o,type:"user",timestamp:t.timestamp,content:X(r.blocks),engineMeta:n};case"assistant":return{id:o,type:"assistant",timestamp:t.timestamp,content:X(r.blocks),engineMeta:n,isStreaming:t.isStreaming};case"thinking":return{id:o,type:"assistant",timestamp:t.timestamp,content:"",engineMeta:n,thinking:{content:ce(r.text)||"",isCollapsed:!t.isStreaming,isStreaming:t.isStreaming}};case"tool_use":return{id:o,type:"tool_use",timestamp:t.timestamp,engineMeta:n,tool:{id:ce(r.tool_call_id)||t.nodeId,name:ce(r.tool_name)||"unknown",input:Hn(r.input_json),engineMetadata:t.engineMetadata}};case"tool_result":return{id:o,type:"tool_result",timestamp:t.timestamp,engineMeta:n,toolResult:{toolUseId:ce(r.tool_call_id)||"",output:X(r.blocks),isError:Kn(r.is_error)}};case"summary":{let i=X(r.blocks);return{id:o,type:"compact",timestamp:t.timestamp,content:i,engineMeta:n,compactInfo:{status:"completed",summary:i}}}default:return{id:o,type:"system",timestamp:t.timestamp,content:X(r.blocks)||t.kind,engineMeta:n}}}var Jn=/^\[Image: source: [^\n]+?\]$/;function Wn(t){let e=t.trim();if(!e.startsWith("[Image: source: "))return!1;let n=e.split(`
6
+ `).map(o=>o.trim()).filter(o=>o.length>0);return n.length>0&&n.every(o=>Jn.test(o))}function X(t){return Array.isArray(t)?t.map(e=>{let n=e&&typeof e=="object"?e:{};if(n.type!=="text")return"";let o=n.text||"";return Wn(o)?"":o}).join(""):""}function ce(t){if(typeof t=="string")return t;if(t!=null)return String(t)}function Kn(t){if(typeof t=="boolean")return t;if(t!=null){if(t==="true")return!0;if(t==="false")return!1}}function Hn(t){if(t&&typeof t=="object"&&!Array.isArray(t))return t;if(typeof t=="string")try{let e=JSON.parse(t);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{return{}}return{}}var Fn=new Set(["AskUserQuestion","EnterPlanMode"]);function Vn(t){return t==="AskUserQuestion"||t?.endsWith("__AskUserQuestion")===!0}function Gn(t){return t?Fn.has(t)?!0:Vn(t)||t.endsWith("__EnterPlanMode"):!1}function $t(t){return typeof t=="string"?t:t==null?"":String(t)}function $(...t){for(let e of t){let n=$t(e);if(n)return n}return""}var ue=class extends zn{constructor(n,o){super();this.client=n;this.opts=o}client;opts;engineSessionId="";leafNodeId="";status="idle";disposed=!1;hasPendingWork=!1;needsContinue=!1;wakeup=null;loopTask=null;filteredToolIds=new Set;autoAllowTools=new Set;requestToolName=new Map;planMode=!1;on(n,o){return super.on(n,o)}emit(n,...o){return super.emit(n,...o)}getStatus(){return this.status}getSessionId(){return this.engineSessionId}getLeafNodeId(){return this.leafNodeId}isPlanMode(){return this.planMode}async initialize(){await this.client.configureGateway({baseUrl:this.opts.baseUrl,apiKey:this.opts.apiKey,profiles:[{profileId:"default",provider:"anthropic",priority:1,enabled:!0}]});let n=await this.client.sessionCreate();this.engineSessionId=n.session_id,this.leafNodeId=n.node_id;let o=[...this.opts.mcpServers??[]];if(this.opts.askUser){let r=this.opts.askUser;o.push({name:"ask-user-question",type:"http",url:r.url(this.engineSessionId)}),r.onAsk(i=>{this.setStatus("waiting_permission"),this.emit("ask:user",{requestId:i.requestId,questions:i.questions})}),this.setAskUserResolver((i,s)=>r.resolve(i,s))}await this.client.setSessionRuntime({sessionId:this.engineSessionId,systemPrompt:this.opts.systemPrompt,workingDir:this.opts.workingDir,skillRoots:this.opts.skillRoots,mcpServers:o})}async send(n){if(!this.engineSessionId)throw new Error("session not initialized");let o=jt();await this.client.enqueue(this.engineSessionId,this.leafNodeId,n,{messageId:o}),this.hasPendingWork=!0,this.ensureLoop(),this.wake()}async respondPermission(n,o,r){if(o==="allow_session"){let s=this.requestToolName.get(n);s&&this.autoAllowTools.add(s)}let i=o==="deny"?"deny":"allow";await this.client.respondPermission(n,i,r),this.requestToolName.delete(n),this.emit("permission:clear",n),this.status==="waiting_permission"&&this.setStatus("thinking")}async respondPlanApproval(n,o,r){await this.client.respondPermission(n,o?"allow":"deny",r),this.requestToolName.delete(n),this.emit("permission:clear",n),this.status==="waiting_permission"&&this.setStatus("thinking")}askUserResolver=null;setAskUserResolver(n){this.askUserResolver=n}respondAskUser(n,o){this.askUserResolver?.(n,o),this.emit("ask:clear",n),this.status==="waiting_permission"&&this.setStatus("thinking")}async interrupt(){if(this.leafNodeId)try{await this.client.stopLoop(this.leafNodeId)}catch(n){this.emit("error",n)}}async compact(){if(this.leafNodeId){this.emit("compact:start");try{let n=await this.client.manualCompact(this.leafNodeId);n.nextLeafNodeId&&(this.leafNodeId=n.nextLeafNodeId);let o=`Context compacted (${n.preCompactTokens}\u2192${n.postCompactTokens} tokens)`;this.emit("compact:end",o)}catch(n){this.emit("compact:end","Compaction failed"),this.emit("error",n)}}}async estimateTokens(){return this.leafNodeId?this.client.estimateTokens(this.leafNodeId):{estimatedTokens:0,threshold:0}}dispose(){this.disposed=!0,this.wake();try{this.client.close()}catch{}this.emit("exit")}setStatus(n){this.status!==n&&(this.status=n,this.emit("status",n))}wake(){if(this.wakeup){let n=this.wakeup;this.wakeup=null,n()}}ensureLoop(){this.loopTask||(this.loopTask=this.runLoop().catch(n=>{this.emit("error",n)}))}async runLoop(){for(;!this.disposed;){if(!this.hasPendingWork){await new Promise(r=>{this.wakeup=r});continue}this.hasPendingWork=!1;let n=this.needsContinue;this.needsContinue=!0;let o=n?this.client.continueAgent(this.engineSessionId,this.leafNodeId,50):this.client.startAgent(this.engineSessionId,this.leafNodeId,{maxIterations:50});try{for await(let r of o){if(this.disposed)break;this.handleAgentEvent(r)}}catch(r){this.emit("error",r)}this.setStatus("idle")}}handleAgentEvent(n){n.system&&this.handleSystem(n.system),n.block&&this.handleBlock(n.block),n.result&&this.handleResult(n.result)}handleSystem(n){let o=n.payload??{};switch(n.type){case"turn_start":case"queue_dequeued":this.setStatus("thinking");break;case"tool_barrier_start":this.setStatus("tool_running");break;case"tool_barrier_end":this.setStatus("thinking");break;case"permission_request":this.handlePermissionRequest(o);break;case"mode_transition":{let r=$t(o.to),i=r==="plan"||r==="plan_mode";this.planMode=i,this.emit("plan:mode",i);break}case"compaction_start":this.emit("compact:start");break;case"compaction_end":{let r=$(o.summary,"Context compacted");this.emit("compact:end",r);break}default:break}}handlePermissionRequest(n){let o=$(n.request_id,n.requestId)||jt(),r=$(n.tool,n.tool_name,n.toolName),i=$(n.tool_call_id,n.toolCallId),s=n.input??{},a=$(n.reason);if(this.requestToolName.set(o,r),this.setStatus("waiting_permission"),r==="ExitPlanMode"){let c=$(s.plan,s.plan_markdown,n.plan);this.emit("plan:approval",{requestId:o,toolCallId:i,plan:c});return}if(Gn(r)||this.autoAllowTools.has(r)){this.client.respondPermission(o,"allow").catch(c=>this.emit("error",c)),this.requestToolName.delete(o),this.status==="waiting_permission"&&this.setStatus("thinking");return}this.emit("permission",{requestId:o,toolCallId:i,toolName:r,input:s,reason:a})}handleBlock(n){n.op==="append"&&(this.leafNodeId=n.nodeId);let o=n.op!=="seal",r=Ot(n,{isStreaming:o});if(r){if(r.type==="tool_use"&&r.tool&&r.tool.name.endsWith("EnterPlanMode")){this.filteredToolIds.add(r.tool.id);return}if(!(r.type==="tool_result"&&r.toolResult&&this.filteredToolIds.has(r.toolResult.toolUseId))){if(r.type==="tool_use"&&r.tool&&r.tool.name.endsWith("TodoWrite")){let i=r.tool.input?.todos??[];Array.isArray(i)&&this.emit("todos",i)}switch(n.op){case"append":this.emit("live:start",r);break;case"update":this.emit("live:update",r);break;case"seal":this.emit("live:end",r.id),this.emit("committed",{...r,isStreaming:!1});break;case"reset":this.emit("live:end",r.id);break;default:break}}}}handleResult(n){let o={promptTokens:n.promptTokens,completionTokens:n.completionTokens,totalTokens:n.totalTokens,model:n.model,contextWindow:n.contextWindow};if(this.emit("tokens",o),n.status==="failed"||n.errorMessage){let r=n.errorMessage||n.errorCode||"turn failed";this.emit("committed",{id:`error-${n.turnId}-${n.atMs}`,type:"error",timestamp:n.atMs||Date.now(),content:r})}}};import{spawn as uo}from"child_process";import{createWriteStream as mo,existsSync as po,mkdirSync as go}from"fs";import{dirname as ye,join as Oe}from"path";import{fileURLToPath as fo}from"url";import{createRequire as ho}from"module";import*as Jt from"readline";var J={ITEM:"$stream.item",END:"$stream.end",ERROR:"$stream.error"},Ee="$stream",me=class extends Error{code;data;constructor(e,n,o){super(e),this.name="JsonRpcCallError",this.code=n,this.data=o}},pe=class{input;output;nextId=0;pending=new Map;pendingMethods=new Map;streams=new Map;notificationHandlers=new Map;closed=!1;logger;constructor(e,n,o){this.input=e,this.output=n,this.logger=o;let r=Jt.createInterface({input:this.input});r.on("line",i=>this.handleLine(i)),r.on("close",()=>this.handleClose())}async call(e,n){let o=++this.nextId;return new Promise((r,i)=>{if(this.closed){i(new Error("jsonrpc client closed"));return}this.pending.set(o,{resolve:r,reject:i}),this.pendingMethods.set(o,e),this.logger?.out(e,o,n),this.send({jsonrpc:"2.0",id:o,method:e,params:n})})}async streamCall(e,n){let r=(await this.call(e,n))?.[Ee];if(!r)throw new Error(`jsonrpc stream: ack missing ${Ee} field`);let i=new Ne(r);return this.streams.set(r,i),i.onDone(()=>{this.streams.delete(r)}),i}notify(e,n){this.closed||(this.logger?.notificationOut?.(e,n),this.send({jsonrpc:"2.0",method:e,params:n}))}onNotification(e,n){let o=this.notificationHandlers.get(e)??new Set;return o.add(n),this.notificationHandlers.set(e,o),()=>{let r=this.notificationHandlers.get(e);r&&(r.delete(n),r.size===0&&this.notificationHandlers.delete(e))}}close(){this.handleClose()}send(e){this.output.write(JSON.stringify(e)+`
7
+ `)}handleLine(e){let n;try{n=JSON.parse(e)}catch{return}let o=n.method;if(o&&Qn(o)){this.handleStreamNotification(o,n.params);return}if(o){let i=n.id;i==null&&this.handleNotification(o,n.params);return}let r=n.id;if(r!=null){let i=this.pending.get(r);if(i){this.pending.delete(r);let s=this.pendingMethods.get(r)||"?";this.pendingMethods.delete(r);let a=n;a.error?(this.logger?.in(r,s,void 0,a.error),i.reject(new me(a.error.message,a.error.code,a.error.data))):(this.logger?.in(r,s,a.result),i.resolve(a.result))}}}handleStreamNotification(e,n){let o=n?.[Ee];if(!o)return;let r=this.streams.get(o);if(r)switch(e){case J.ITEM:this.logger?.streamItem(o,n.data),r.pushItem(n.data);break;case J.END:this.logger?.streamEnd(o),r.pushEnd();break;case J.ERROR:{let i=n;this.logger?.streamError(o,i.error),r.pushError(new me(i.error?.message??"stream error",i.error?.code??-32603,i.error?.data));break}}}handleNotification(e,n){this.logger?.notificationIn?.(e,n);let o=this.notificationHandlers.get(e);if(!(!o||o.size===0))for(let r of o)try{r(n)}catch(i){console.error(`[JsonRpcClient] notification handler failed for ${e}:`,i)}}handleClose(){if(this.closed)return;this.closed=!0;let e=new Error("jsonrpc client closed");for(let[,n]of this.pending)n.reject(e);this.pending.clear();for(let[,n]of this.streams)n.pushError(e);this.streams.clear()}};function Qn(t){return t===J.ITEM||t===J.END||t===J.ERROR}var Ne=class{buffer=[];waiting=null;ended=!1;doneCallbacks=[];constructor(e){}pushItem(e){this.ended||this.push({value:e})}pushEnd(){this.ended||(this.ended=!0,this.push({done:!0}),this.notifyDone())}pushError(e){this.ended||(this.ended=!0,this.push({error:e}),this.notifyDone())}onDone(e){this.ended?e():this.doneCallbacks.push(e)}close(){this.ended||(this.ended=!0,this.push({done:!0}),this.notifyDone())}async*[Symbol.asyncIterator](){try{for(;;){let e=await this.pull();if(e.error)throw e.error;if(e.done)return;yield e.value}}finally{this.close()}}push(e){if(this.waiting){let n=this.waiting;this.waiting=null,n(e)}else this.buffer.push(e)}pull(){return this.buffer.length>0?Promise.resolve(this.buffer.shift()):new Promise(e=>{this.waiting=e})}notifyDone(){for(let e of this.doneCallbacks)e();this.doneCallbacks=[]}};function T(t){let e=t&&typeof t=="object"?t:{};return{session_id:String(e.session_id??e.sessionId??""),parent_node_id:l(e.parent_node_id??e.parentNodeId),node_id:String(e.node_id??e.nodeId??e.NodeID??""),logical_message_id:String(e.logical_message_id??e.logicalMessageId??e.LogicalMessageID??""),segment_index:Number(e.segment_index??e.segmentIndex??e.SegmentIndex??0),status:l(e.status??e.Status),revision:Number(e.revision??e.Revision??0),provider_ref:zt(e.provider_ref??e.providerRef),node_type:String(e.node_type??e.nodeType??""),turn_id:l(e.turn_id??e.turnId),sequence_in_turn:Number(e.sequence_in_turn??e.sequenceInTurn??0),payload_json:Le(e.payload_json??e.payloadJson??e.PayloadJson),tool_call_id:l(e.tool_call_id??e.toolCallId),tool_result_index:w(e.tool_result_index??e.toolResultIndex),content:io(e.content??e.blocks),tool_name:l(e.tool_name??e.toolName),created_at_ms:Number(e.created_at_ms??e.createdAtMs??0),metadata:Ft(e.metadata)}}function Wt(t){if(!t||typeof t!="object")return null;let e=t,n=e.mount_roots??e.mountRoots,o=Array.isArray(n)?n.map(h=>h==null?"":String(h).trim()).filter(Boolean):void 0,r=e.skill_roots??e.skillRoots,i=Array.isArray(r)?r.map(h=>h==null?"":String(h).trim()).filter(Boolean):void 0,s=e.wand_roots??e.wandRoots,a=Array.isArray(s)?s.map(h=>h==null?"":String(h).trim()).filter(Boolean):void 0,c=Ft(e.env_vars??e.envVars),f=e.tool_policy??e.toolPolicy,g=f&&typeof f=="object"?{default_tool_timeout_ms:w(f.default_tool_timeout_ms??f.defaultToolTimeoutMs),permission_wait_timeout_ms:w(f.permission_wait_timeout_ms??f.permissionWaitTimeoutMs)}:void 0,u=e.skill_install_config??e.skillInstallConfig,k=u&&typeof u=="object"?{node_path:l(u.node_path??u.nodePath),npm_path:l(u.npm_path??u.npmPath),npm_cli_script_path:l(u.npm_cli_script_path??u.npmCliScriptPath),install_timeout_ms:w(u.install_timeout_ms??u.installTimeoutMs)}:void 0;return{session_id:String(e.session_id??e.sessionId??""),workspace_id:l(e.workspace_id??e.workspaceId),system_prompt:String(e.system_prompt??e.systemPrompt??""),preferred_profile:l(e.preferred_profile??e.preferredProfile),working_dir:l(e.working_dir??e.workingDir),mount_roots:o,skill_roots:i,wand_roots:a,env_vars:c,tool_policy:g,skill_install_config:k,updated_at_ms:Number(e.updated_at_ms??e.updatedAtMs??0)}}function Be(t){if(!t||typeof t!="object")return null;let e=t;return{trace_id:String(e.trace_id??e.traceId??""),request_id:String(e.request_id??e.requestId??""),turn_id:l(e.turn_id??e.turnId),session_id:l(e.session_id??e.sessionId),route_id:String(e.route_id??e.routeId??""),model_id:String(e.model_id??e.modelId??""),provider:String(e.provider??""),profile_id:String(e.profile_id??e.profileId??""),prompt_summary:String(e.prompt_summary??e.promptSummary??""),provider_request_summary:String(e.provider_request_summary??e.providerRequestSummary??""),provider_response_summary:String(e.provider_response_summary??e.providerResponseSummary??""),latency_ms:Number(e.latency_ms??e.latencyMs??0),prompt_tokens:Number(e.prompt_tokens??e.promptTokens??0),completion_tokens:Number(e.completion_tokens??e.completionTokens??0),created_at_ms:Number(e.created_at_ms??e.createdAtMs??0)}}function Kt(t){if(!t||typeof t!="object")return null;let e=t;return{receipt_id:String(e.receipt_id??e.receiptId??""),message_id:l(e.message_id??e.messageId),leaf_node_id:l(e.leaf_node_id??e.leafNodeId),status:String(e.status??""),reason:l(e.reason),turn_id:l(e.turn_id??e.turnId),updated_at_ms:w(e.updated_at_ms??e.updatedAtMs)}}function De(t){return{type:String(t?.type??t?.Type??""),sessionId:String(t?.session_id??t?.sessionId??t?.SessionID??""),turnId:l(t?.turn_id??t?.turnId??t?.TurnID),requestId:l(t?.request_id??t?.requestId??t?.RequestID),toolCallId:l(t?.tool_call_id??t?.toolCallId??t?.ToolCallID),promptReportId:l(t?.prompt_report_id??t?.promptReportId??t?.PromptReportID),receiptId:l(t?.receipt_id??t?.receiptId??t?.ReceiptID),messageId:l(t?.message_id??t?.messageId??t?.MessageID),inputNodeId:l(t?.input_node_id??t?.inputNodeId??t?.InputNodeID),assistantNodeId:l(t?.assistant_node_id??t?.assistantNodeId??t?.AssistantNodeID),queueStatus:Xn(t?.queue_status??t?.queueStatus??t?.QueueStatus),terminalReceiptStatus:Yn(t?.terminal_receipt_status??t?.terminalReceiptStatus??t?.TerminalReceiptStatus),thinkingId:l(t?.thinking_id??t?.thinkingId??t?.ThinkingID),thinkingState:Zn(t?.thinking_state??t?.thinkingState??t?.ThinkingState),thinkingDelta:l(t?.thinking_delta??t?.thinkingDelta??t?.ThinkingDelta),thinkingDigestSha256:l(t?.thinking_digest_sha256??t?.thinkingDigestSha256??t?.ThinkingDigestSha256),thinkingLen:eo(t?.thinking_len??t?.thinkingLen??t?.ThinkingLen),streamId:l(t?.stream_id??t?.streamId??t?.StreamID),seq:w(t?.seq??t?.Seq),layer:l(t?.layer??t?.Layer),phase:l(t?.phase??t?.Phase),payload:Ht(t?.payload_json??t?.payloadJson??t?.PayloadJson),createdAtMs:w(t?.created_at_ms??t?.createdAtMs??t?.CreatedAtMs)}}function qe(t){let e=t?.system??t?.System;if(e)return{system:oo(e)};let n=t?.block??t?.Block;if(n)return{block:to(n)};let o=t?.result??t?.Result;if(o)return{result:ro(o)};let r=t?.debug??t?.Debug;return r?{debug:De(r)}:{}}function Ue(t){return t instanceof Uint8Array||Buffer.isBuffer(t)?Buffer.from(t).toString("base64"):typeof t=="string"?Buffer.from(t,"utf8").toString("base64"):Buffer.from(JSON.stringify(t??{}),"utf8").toString("base64")}function Ht(t){if(t){try{if(typeof t=="string")try{return JSON.parse(t)}catch{return JSON.parse(Buffer.from(t,"base64").toString("utf8"))}if(t instanceof Uint8Array||Buffer.isBuffer(t))return JSON.parse(Buffer.from(t).toString("utf8"))}catch{return t}return t}}function Le(t){if(t!=null){if(t instanceof Uint8Array)return t;if(Buffer.isBuffer(t))return new Uint8Array(t);if(typeof t=="string"){try{let e=Buffer.from(t,"base64");if(e.toString("base64")===t&&t.length>0)return new Uint8Array(e)}catch{}return Buffer.from(t,"utf8")}if(typeof t=="object")return Buffer.from(JSON.stringify(t),"utf8")}}function l(t){if(t==null)return;let e=String(t);return e.length>0?e:void 0}function w(t){if(t==null||t==="")return;let e=Number(t);return Number.isFinite(e)?e:void 0}function Xn(t){let e=l(t);if(e==="dequeued"||e==="running"||e==="done")return e}function Yn(t){let e=l(t);if(e==="accepted"||e==="processing"||e==="completed"||e==="interrupted"||e==="failed"||e==="timeout")return e}function Zn(t){let e=l(t);if(e==="start"||e==="delta"||e==="end")return e}function eo(t){if(t==null||t==="")return;let e=Number(t);if(!(!Number.isFinite(e)||!Number.isSafeInteger(e)||e<0))return e}function zt(t){if(!t||typeof t!="object")return;let e=t,n=l(e.provider??e.Provider),o=l(e.provider_message_id??e.providerMessageId??e.ProviderMessageID),r=w(e.item_index??e.itemIndex??e.ItemIndex),i=l(e.item_kind??e.itemKind??e.ItemKind);if(!(!n||!o||r===void 0||!i))return{provider:n,provider_message_id:o,item_index:r,item_kind:i}}function to(t){let e=t&&typeof t=="object"?t:{},n=zt(e.provider_ref??e.providerRef??{provider:e.provider??e.Provider,provider_message_id:e.provider_message_id??e.providerMessageId??e.ProviderMessageID,item_index:e.provider_item_index??e.providerItemIndex??e.ProviderItemIndex,item_kind:e.provider_item_kind??e.providerItemKind??e.ProviderItemKind});return{nodeId:String(e.node_id??e.nodeId??e.NodeID??""),logicalMessageId:String(e.logical_message_id??e.logicalMessageId??e.LogicalMessageID??""),kind:String(e.kind??e.Kind??""),op:String(e.op??e.Op??""),revision:Number(e.revision??e.Revision??0),segmentIndex:Number(e.segment_index??e.segmentIndex??e.SegmentIndex??0),turnId:l(e.turn_id??e.turnId??e.TurnID),providerRef:n,payloadJson:Le(e.payload_json??e.payloadJson??e.PayloadJson)??new Uint8Array,createdAtMs:Number(e.created_at_ms??e.createdAtMs??e.CreatedAtMs??0),updatedAtMs:w(e.updated_at_ms??e.updatedAtMs??e.UpdatedAtMs),engineMetadata:no(e.engine_metadata??e.engineMetadata??e.EngineMetadata)}}function no(t){if(!t||typeof t!="object"||Array.isArray(t))return;let e={},n=0;for(let[o,r]of Object.entries(t))typeof r=="string"?(e[o]=r,n++):r!=null&&(e[o]=String(r),n++);return n>0?e:void 0}function oo(t){let e=t&&typeof t=="object"?t:{};return{type:String(e.type??e.Type??""),sessionId:String(e.session_id??e.sessionId??e.SessionID??""),turnId:l(e.turn_id??e.turnId??e.TurnID),messageId:l(e.message_id??e.messageId??e.MessageID),inputNodeId:l(e.input_node_id??e.inputNodeId??e.InputNodeID),receiptId:l(e.receipt_id??e.receiptId??e.ReceiptID),payload:Ht(e.payload_json??e.payloadJson??e.PayloadJson??e.payload??e.Payload),atMs:Number(e.at_ms??e.atMs??e.AtMs??0)}}function ro(t){let e=t&&typeof t=="object"?t:{};return{turnId:String(e.turn_id??e.turnId??e.TurnID??""),status:String(e.status??e.Status??""),numToolCalls:Number(e.num_tool_calls??e.numToolCalls??e.NumToolCalls??0),promptTokens:w(e.prompt_tokens??e.promptTokens??e.PromptTokens),completionTokens:w(e.completion_tokens??e.completionTokens??e.CompletionTokens),totalTokens:w(e.total_tokens??e.totalTokens??e.TotalTokens),cacheCreationInputTokens:w(e.cache_creation_input_tokens??e.cacheCreationInputTokens??e.CacheCreationInputTokens),cacheReadInputTokens:w(e.cache_read_input_tokens??e.cacheReadInputTokens??e.CacheReadInputTokens),model:l(e.model??e.Model),contextWindow:w(e.context_window??e.contextWindow??e.ContextWindow),durationMs:w(e.duration_ms??e.durationMs??e.DurationMs),errorCode:l(e.error_code??e.errorCode??e.ErrorCode),errorMessage:l(e.error_message??e.errorMessage??e.ErrorMessage),atMs:Number(e.at_ms??e.atMs??e.AtMs??0)}}function io(t){if(!Array.isArray(t))return;let e=t.map(n=>{let o=n&&typeof n=="object"?n:{};return{type:String(o.type??o.Type??""),text:l(o.text??o.Text),url:l(o.url??o.URL),data:Le(o.data??o.Data),mime_type:l(o.mime_type??o.mimeType??o.MimeType)}}).filter(n=>n.type.length>0);return e.length>0?e:void 0}function Ft(t){if(!t||typeof t!="object")return;let e={};for(let[n,o]of Object.entries(t))o!=null&&(e[n]=String(o));return Object.keys(e).length>0?e:void 0}var W="[Monolith:IPC]",so=7200*1e3,Vt=process.env.MCPLATO_VERBOSE_IPC==="true"||process.env.MCPLATO_VERBOSE_IPC==="1";function ge(t,e=4096){if(t==null)return"";let n;if(typeof t=="string")n=t;else try{n=JSON.stringify(t)}catch{n=String(t)}return n.length>e?n.slice(0,e)+"...":n}function fe(t){if(t===null||typeof t!="object")return t;if(Array.isArray(t))return t.map(fe);let e=t,n={};for(let[o,r]of Object.entries(e)){if(o==="payload_json"&&typeof r=="string"&&r.length>0)try{let i=Buffer.from(r,"base64").toString("utf-8");JSON.parse(i),n[o]=i;continue}catch{}n[o]=typeof r=="object"&&r!==null?fe(r):r}return n}var ao={out(t,e,n){console.log(`${W} OUT id=${e} method=${t} ${ge(n)}`)},in(t,e,n,o){console.log(o?`${W} IN id=${t} method=${e} ERROR code=${o.code} ${o.message}`:`${W} IN id=${t} method=${e} ${ge(Vt?fe(n):n)}`)},streamItem(t,e){Vt&&console.log(`${W} STREAM ${t} ${ge(fe(e))}`)},streamEnd(t){console.log(`${W} STREAM ${t} END`)},streamError(t,e){console.log(`${W} STREAM ${t} ERROR ${ge(e)}`)}},he=class{client;constructor(e,n,o){this.client=new pe(e,n,ao)}close(){this.client.close()}async listModels(){let e=await this.client.call("gateway.listModels");return Array.isArray(e?.routes)?e.routes:[]}async configureGateway(e){return await this.client.call("gateway.configure",{base_url:e.baseUrl,api_key:e.apiKey,timeout_ms:e.timeoutMs||so,profiles:e.profiles.map(o=>({profile_id:o.profileId,provider:o.provider,priority:o.priority,enabled:o.enabled}))})||{success:!1,profiles_count:0}}async sessionCreate(e={}){let n=await this.client.call("session.createSession",{metadata:e});return T(n)}async sessionCreateWithSummary(e){let n=await this.client.call("session.createWithSummary",{metadata:e.metadata??{},summary_blocks:e.summaryBlocks??[],summary_metadata:e.summaryMetadata??{}});return{sessionId:n.session_id,rootNodeId:n.root_node_id,leafNodeId:n.leaf_node_id,root:T(n.root),leaf:T(n.leaf)}}async sessionGetNode(e){let n=await this.client.call("session.getNode",{session_id:e});return T(n)}async sessionGetBlock(e){let n=await this.client.call("session.getSessionBlock",{node_id:e});return T(n)}async listSessionBlocks(e,n=200,o){let r=await this.client.call("session.listSessionBlocks",{leaf_node_id:e,limit:n,...o?{from_node_id:o}:{}});return Array.isArray(r?.blocks)?r.blocks.map(i=>T(i)):[]}async sessionAppendNode(e){let n=await this.client.call("session.appendNode",{parent_node_id:e.parentNodeId,node_type:e.nodeType,turn_id:e.turnId,sequence_in_turn:e.sequenceInTurn??0,payload_json:Ue(e.payloadJson),tool_call_id:e.toolCallId,tool_result_index:e.toolResultIndex,metadata:e.metadata??{}});return T(n)}async sessionAppendNodes(e,n){let o=await this.client.call("session.appendNodes",{parent_node_id:e,nodes:n.map(r=>({parent_node_id:r.parentNodeId,node_type:r.nodeType,turn_id:r.turnId,sequence_in_turn:r.sequenceInTurn??0,payload_json:Ue(r.payloadJson),tool_call_id:r.toolCallId,tool_result_index:r.toolResultIndex,metadata:r.metadata??{}}))});return Array.isArray(o?.nodes)?o.nodes.map(r=>T(r)):[]}async enqueue(e,n,o,r){let i=typeof o=="string"?[{type:"text",text:o}]:o;return await this.client.call("queue.enqueue",{session_id:e,mode:r?.mode??"async",message:{message_id:r?.messageId,leaf_node_id:n,queue_kind:r?.queueKind??"main",input_intent:r?.intent??"default",content:i,created_at_ms:Date.now()}})}async getReceipt(e,n){let o=await this.client.call("queue.getReceipt",{session_id:e,receipt_id:n});return Kt(o)}async stopLoop(e){await this.client.call("loop.stop",{leaf_node_id:e})}async markLoopDirty(e){await this.client.call("loop.markDirty",{leaf_node_id:e})}async*startLoop(e,n,o){let r=await this.client.streamCall("loop.start",{session_id:e,leaf_node_id:n,complexity:o?.complexity??6,required_capabilities:["tool_use"],max_iterations:o?.maxIterations??8,system_prompt_override:o?.systemPromptOverride});for await(let i of r)yield De(i)}async*startAgent(e,n,o){let r=await this.client.streamCall("agent.start",{session_id:e,leaf_node_id:n,complexity:o?.complexity??6,required_capabilities:["tool_use"],max_iterations:o?.maxIterations??8,system_prompt_override:o?.systemPromptOverride,initial_mode:o?.initialMode});for await(let i of r)yield qe(i)}async*continueAgent(e,n,o=8,r,i){let s=await this.client.streamCall("agent.continue",{session_id:e,leaf_node_id:n,max_iterations:o,system_prompt_override:r});for await(let a of s)yield qe(a)}async enterMode(e,n,o){await this.client.call("mode.enter",{session_id:e,mode:n,...o?{data:o}:{}})}async exitMode(e){await this.client.call("mode.exit",{session_id:e})}async updateModeData(e,n){await this.client.call("mode.updateData",{session_id:e,data:n})}async getMode(e){let n=await this.client.call("mode.current",{session_id:e});return{current:n.current??"",pending:n.pending??"",safeTurnsInMode:n.safe_turns_in_mode??0,humanTurnsInMode:n.human_turns_in_mode??0}}async respondPermission(e,n,o){await this.client.call("permission.respond",{request_id:e,decision:n,reason:o})}async upsertPermissionRule(e){let n=await this.client.call("permission.upsertRule",{scope_type:e.scopeType,scope_id:e.scopeId,tool_name:e.toolName,tool_pattern:e.toolPattern,decision:e.decision,expires_at_ms:e.expiresAtMs});if(!n?.rule)throw new Error("Monolith UpsertPermissionRule returned empty rule");return n.rule}async listPermissionRules(e,n){let o=await this.client.call("permission.listRules",{scope_type:e,scope_id:n});return Array.isArray(o?.rules)?o.rules:[]}async setSessionRuntime(e){let n=Array.isArray(e.mountRoots)?e.mountRoots.map(i=>String(i||"").trim()).filter(Boolean):void 0,o=Array.isArray(e.skillRoots)?e.skillRoots.map(i=>String(i||"").trim()).filter(Boolean):void 0,r=Array.isArray(e.wandRoots)?e.wandRoots.map(i=>String(i||"").trim()).filter(Boolean):void 0;await this.client.call("sessionRuntime.set",{session_id:e.sessionId,workspace_id:e.workspaceId,system_prompt:e.systemPrompt,preferred_profile:e.preferredProfile,working_dir:e.workingDir,mount_roots:n,skill_roots:o,wand_roots:r,env_vars:e.envVars,tool_policy:e.toolPolicy?{default_tool_timeout_ms:e.toolPolicy.defaultToolTimeoutMs,permission_wait_timeout_ms:e.toolPolicy.permissionWaitTimeoutMs}:void 0,skill_install_config:e.skillInstallConfig?{node_path:e.skillInstallConfig.nodePath,npm_path:e.skillInstallConfig.npmPath,npm_cli_script_path:e.skillInstallConfig.npmCliScriptPath,install_timeout_ms:e.skillInstallConfig.installTimeoutMs,python_path:e.skillInstallConfig.pythonPath,pip_install_timeout_ms:e.skillInstallConfig.pipInstallTimeoutMs}:void 0,mcp_servers:e.mcpServers?.map(i=>({name:i.name,type:i.type,command:i.command,args:i.args,env:i.env,url:i.url,headers:i.headers})),client_config:e.clientConfig,sprite_allowed_tools:e.spriteAllowedTools?[...e.spriteAllowedTools]:void 0})}async getSessionRuntime(e){let n=await this.client.call("sessionRuntime.get",{session_id:e});return Wt(n?.runtime||null)}async closeSession(e){await this.client.call("session.close",{session_id:e})}async getSessionTodos(e){let n=await this.client.call("todo.get",{session_id:e});return Array.isArray(n?.todos)?n.todos.map(o=>({content:String(o?.content||""),activeForm:String(o?.active_form||""),status:co(o?.status)})):[]}async getRequestTrace(e){let n=await this.client.call("trace.getRequestTrace",{request_id:e});return Be(n?.trace||null)}async listRequestTraces(e,n=20){let o=await this.client.call("trace.listRequestTraces",{session_id:e,limit:n});return Array.isArray(o?.traces)?o.traces.map(r=>Be(r)).filter(r=>!!r):[]}async manualCompact(e,n){let o=await this.client.call("memory.manualCompact",{leaf_node_id:e,custom_instructions:n}),r=o&&typeof o=="object"?o:{},i=r.SummaryNode?T(r.SummaryNode):null,s=r.ReinjectionNode?T(r.ReinjectionNode):null;return{summaryNode:i,reinjectionNode:s,nextLeafNodeId:lo(r.next_leaf_node_id??r.nextLeafNodeId??r.NextLeafNodeId,s?.node_id,i?.node_id)||null,preCompactTokens:Number(r.PreCompactTokens??0),postCompactTokens:Number(r.PostCompactTokens??0),mode:String(r.Mode??""),attempts:Number(r.Attempts??0)}}async estimateTokens(e){let n=await this.client.call("memory.estimateTokens",{leaf_node_id:e}),o=n&&typeof n=="object"?n:{};return{estimatedTokens:Number(o.estimated_tokens??0),threshold:Number(o.threshold??0)}}};function lo(...t){for(let e of t){if(typeof e!="string")continue;let n=e.trim();if(n)return n}return""}function co(t){let e=String(t||"").trim().toLowerCase();return e==="completed"?"completed":e==="in_progress"?"in_progress":"pending"}var je="@mcplato/wandplus",yo=ho(import.meta.url);function $e(){return`${process.platform==="win32"?"win":process.platform}-${process.arch}`}function Je(t){return process.platform==="win32"?`${t}.exe`:t}function _e(t){for(let e of t)if(e&&po(e))return e;return null}function _o(){return`${je}-${$e()}`}function Gt(t,e=yo.resolve){try{let n=ye(e(`${_o()}/package.json`));return _e([Oe(n,"vendor",Je(t))])}catch{return null}}function Qt(t,e){let n=ye(fo(import.meta.url));for(let o=0;o<8;o++){let r=_e([Oe(n,"packages",t,...e),Oe(n,t,...e)])??null;if(r)return r;let i=ye(n);if(i===n)break;n=i}return null}function ko(){let t=_e([process.env.MCPLATO_MONOLITH_BIN??""])??Gt("monolith")??Qt("monolith",["bin",Je("monolith")]);if(!t)throw new Error(`monolith binary not found.
8
+ \u2022 Installed via npm? The platform package ${je}-${$e()} is missing \u2014 reinstall with: npm i -g ${je}@latest
9
+ \u2022 Developing in the monorepo? Run \`make monolith-build\` or set MCPLATO_MONOLITH_BIN.`);return t}function wo(){return _e([process.env.MCPLATO_MONOLITH_RUNTIME_BIN??""])??Gt("monolith-runtime")??Qt("monolith-runtime",["dist",$e(),Je("monolith-runtime")])}function Xt(){qt();let t=ko(),e=wo(),n=["serve-stdio"];e&&n.push("--sandbox-provider","stdio","--sandbox-runtime-bin",e);let o=["--db-path",Et(),...n],r=le();go(ye(r),{recursive:!0});let i=mo(r,{flags:"a"}),s=uo(t,o,{stdio:["pipe","pipe","pipe"],detached:process.platform!=="win32",env:process.env});if(s.stderr?.pipe(i),!s.stdout||!s.stdin)throw new Error("failed to open monolith stdio pipes");let a=new he(s.stdout,s.stdin),c=new Promise(g=>{s.once("exit",u=>{i.end(),g(u)})});return{client:a,child:s,exited:c,dispose:()=>{try{a.close()}catch{}try{s.stdin?.end()}catch{}setTimeout(()=>{try{process.platform!=="win32"&&s.pid?process.kill(-s.pid,"SIGKILL"):s.kill("SIGKILL")}catch{}},3e3).unref?.();try{s.kill("SIGTERM")}catch{}}}}import{createServer as So}from"http";import{randomBytes as Yt}from"crypto";var Io={name:"AskUserQuestion",description:"Ask the user one to four multiple-choice questions during execution and wait for answers.",inputSchema:{type:"object",properties:{questions:{type:"array",minItems:1,maxItems:4,items:{type:"object",properties:{question:{type:"string"},header:{type:"string"},options:{type:"array",minItems:2,maxItems:4,items:{type:"object",properties:{label:{type:"string"},description:{type:"string"}},required:["label","description"]}},multiSelect:{type:"boolean"}},required:["question","header","options","multiSelect"]}}},required:["questions"]}},ke=class{server=null;port=0;key=Yt(16).toString("hex");pending=new Map;askCb=null;seq=0;async start(){this.server=So((e,n)=>this.handle(e,n)),await new Promise(e=>{this.server.listen(0,"127.0.0.1",()=>{let n=this.server.address();this.port=typeof n=="object"&&n?n.port:0,e()})})}url(e){return`http://127.0.0.1:${this.port}/mcp/ask-user?key=${this.key}&sessionId=${encodeURIComponent(e)}`}onAsk(e){this.askCb=e}resolve(e,n){let o=this.pending.get(e);o&&(this.pending.delete(e),o.resolve(n))}close(){for(let[,e]of this.pending)e.resolve({});this.pending.clear(),this.server?.close(),this.server=null}send(e,n,o){e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({jsonrpc:"2.0",id:n,result:o}))}handle(e,n){if(e.method==="OPTIONS"){n.writeHead(204),n.end();return}if(new URL(e.url??"",`http://127.0.0.1:${this.port}`).searchParams.get("key")!==this.key){n.writeHead(403),n.end("forbidden");return}let r="";e.on("data",i=>{r+=i}),e.on("end",()=>{this.dispatch(r,n).catch(()=>{n.writeHead(500),n.end("error")})})}async dispatch(e,n){let o;try{o=JSON.parse(e)}catch{n.writeHead(400),n.end("bad json");return}let{id:r,method:i,params:s}=o;switch(i){case"initialize":this.send(n,r,{protocolVersion:"2024-11-05",capabilities:{tools:{}},serverInfo:{name:"mcplato-tui-ask-user",version:"1.0.0"}});return;case"tools/list":this.send(n,r,{tools:[Io]});return;case"tools/call":{let a=await this.handleToolCall(s);this.send(n,r,a);return}default:n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify({jsonrpc:"2.0",id:r,error:{code:-32601,message:`Method not found: ${i}`}}))}}async handleToolCall(e){if(e?.name!=="AskUserQuestion")return{content:[{type:"text",text:`Unknown tool: ${e?.name}`}],isError:!0};let n=e.arguments??{},o=n.questions;if(!Array.isArray(o)||o.length===0)return{content:[{type:"text",text:"Error: questions is required"}],isError:!0};let r=typeof n._holoToolUseId=="string"?n._holoToolUseId:"",i=`ask_${++this.seq}_${Yt(4).toString("hex")}`,s=await new Promise(c=>{this.pending.set(i,{resolve:c}),this.askCb?.({requestId:i,toolUseId:r,questions:o})});return{content:[{type:"text",text:Object.entries(s).map(([c,f])=>`${c}: ${f}`).join(`
10
+ `)||"No answers provided"}]}}};import{createWriteStream as To,mkdirSync as vo}from"fs";import{dirname as xo}from"path";function Mo(t){if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return String(t)}}function Zt(){let t;try{let e=le();vo(xo(e),{recursive:!0});let n=To(e,{flags:"a"});t=(o,r)=>{let i=r.map(Mo).join(" ");n.write(`${new Date().toISOString()} [${o}] ${i}
11
+ `)}}catch{t=()=>{}}console.log=(...e)=>t("log",e),console.info=(...e)=>t("info",e),console.warn=(...e)=>t("warn",e),console.error=(...e)=>t("error",e),console.debug=(...e)=>t("debug",e)}import{jsx as we,jsxs as Do}from"react/jsx-runtime";var Po=["You are MCPlato, an AI coding assistant running in a terminal.","You operate inside the user's working directory and can use tools to read,","write, and run code. Be concise. Prefer doing the work over describing it."].join(" ");function Co({initialConfig:t,cwd:e}){let[n,o]=We(t),[r,i]=We(null),[s,a]=We(null);return Ro(()=>{if(!n)return;let c=null,f=null,g=new ke,u=!1;return g.start().then(()=>{u||(c=Xt(),f=new ue(c.client,{baseUrl:n.baseUrl,apiKey:n.apiKey,workingDir:n.workingDir??e,systemPrompt:Po,askUser:g}),i(f),c.exited.then(k=>{k&&k!==0&&a(`monolith exited with code ${k}`)}))}).catch(k=>{u||a(k.message)}),()=>{u=!0,f?.dispose(),c?.dispose(),g.close()}},[n]),s?Do(en,{color:"red",children:["Fatal: ",s]}):n?r?we(Mt,{session:r}):we(en,{color:"yellow",children:"Starting monolith\u2026"}):we(Lt,{onDone:o})}function Eo(t){let e=process.cwd(),n=!1,o=!1;for(let r=0;r<t.length;r++){let i=t[r];i==="--cwd"||i==="-C"?e=t[++r]??e:i==="--help"||i==="-h"?n=!0:(i==="--version"||i==="-v")&&(o=!0)}return{cwd:e,help:n,version:o}}function No(){try{return bo(import.meta.url)("../package.json").version??"0.0.0"}catch{return"0.0.0"}}var Bo=`wandplus \u2014 terminal AI coding agent (MCPlato)
12
+
13
+ Usage: wandplus [options]
14
+
15
+ Options:
16
+ -C, --cwd <dir> Working directory for the agent (default: cwd)
17
+ -h, --help Show this help
18
+ -v, --version Show version
19
+
20
+ Config (no login):
21
+ WANDPLUS_AUTH_TOKEN (required) and WANDPLUS_BASE_URL (optional; defaults to the
22
+ MCPlato gateway) env vars, or ~/.config/mcplato-tui/config.json (first-run
23
+ wizard writes it)
24
+
25
+ Binaries (dev): set MCPLATO_MONOLITH_BIN / MCPLATO_MONOLITH_RUNTIME_BIN
26
+ or run \`make monolith-build monolith-runtime-build\`.
27
+ `;function tn(){let t=Eo(process.argv.slice(2));if(t.help){process.stdout.write(Bo);return}if(t.version){process.stdout.write(`wandplus ${No()}
28
+ `);return}Nt();let e=Bt();Zt(),Ao(we(Co,{initialConfig:e,cwd:t.cwd}),{patchConsole:!1})}tn();
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@mcplato/wandplus",
3
+ "version": "2.2.6",
4
+ "description": "WandPlus — a terminal AI coding agent powered by the MCPlato monolith engine (Ink / React for terminal).",
5
+ "keywords": [
6
+ "ai",
7
+ "agent",
8
+ "cli",
9
+ "tui",
10
+ "terminal",
11
+ "coding-agent",
12
+ "mcplato",
13
+ "wandplus"
14
+ ],
15
+ "homepage": "https://wandplus.dev",
16
+ "bugs": {
17
+ "url": "https://wandplus.dev"
18
+ },
19
+ "license": "MIT",
20
+ "type": "module",
21
+ "bin": {
22
+ "wandplus": "./dist/index.js",
23
+ "mcplato-tui": "./dist/index.js"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md"
28
+ ],
29
+ "engines": {
30
+ "node": ">=20"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "registry": "https://registry.npmjs.org/"
35
+ },
36
+ "dependencies": {
37
+ "ink": "^5.1.0",
38
+ "ink-spinner": "^5.0.0",
39
+ "ink-text-input": "^6.0.0",
40
+ "marked": "^12.0.2",
41
+ "marked-terminal": "^7.1.0",
42
+ "react": "^18.3.1"
43
+ },
44
+ "optionalDependencies": {
45
+ "@mcplato/wandplus-darwin-arm64": "2.2.6",
46
+ "@mcplato/wandplus-darwin-x64": "2.2.6",
47
+ "@mcplato/wandplus-linux-x64": "2.2.6",
48
+ "@mcplato/wandplus-win-x64": "2.2.6"
49
+ }
50
+ }