ideawave 0.0.28 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +5 -5
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import{readFileSync as o1}from"node:fs";import{homedir as d1}from"node:os";import{join as z$}from"node:path";function n1(){let $=d1();switch(process.platform){case"win32":return process.env.APPDATA??z$($,"AppData","Roaming");case"darwin":return z$($,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??z$($,".config")}}function D0(){let $=process.env.IDEAWAVE_MCP_JSON_PATH;if($&&$.trim().length>0)return $;return z$(n1(),"ideawave","mcp.json")}var B0=null;function U0($){B0=$}var s1=86400000;function t1(){let $;try{$=o1(D0(),"utf8")}catch{return null}let Z;try{Z=JSON.parse($)}catch{return null}if(typeof Z.url!=="string")return null;if(typeof Z.startedAt==="string"){let X=Date.parse(Z.startedAt);if(!Number.isNaN(X)){if(Date.now()-X>s1)return null}}if(typeof Z.pid==="number"&&Z.pid>0)try{process.kill(Z.pid,0)}catch(X){if(X?.code!=="EPERM")return null}return{url:Z.url}}function H0($,Z={}){let X=[];if(Z.userId&&Z.userId.trim().length>0)X.push({name:"X-Ideawave-User-Id",value:Z.userId.trim()});if(Z.frontendSessionId&&Z.frontendSessionId.trim().length>0)X.push({name:"X-Ideawave-Frontend-Session-Id",value:Z.frontendSessionId.trim()});if(Z.toolSurface==="read")X.push({name:"X-Ideawave-Tool-Surface",value:"read"});if(Z.cardId&&Z.cardId.trim().length>0)X.push({name:"X-Ideawave-Card-Id",value:Z.cardId.trim()});if(Z.boardId&&Z.boardId.trim().length>0)X.push({name:"X-Ideawave-Board-Id",value:Z.boardId.trim()});if(Z.runFolder&&Z.runFolder.trim().length>0)X.push({name:"X-Ideawave-Run-Folder",value:Z.runFolder.trim()});return{type:"http",name:"ideawave-board",url:$,headers:X}}function T$($={}){let Z=B0;if(Z)return H0(Z.url,$);let X=t1();if(!X)return null;return H0(X.url,$)}import{spawn as J2}from"node:child_process";import{closeSync as Q2,existsSync as C0,mkdirSync as w0,openSync as V2,readFileSync as j2,renameSync as W2,rmSync as F0,statSync as K2,unlinkSync as M2,writeFileSync as Y2}from"node:fs";import q0 from"node:os";import d from"node:path";import{execFile as Z2}from"node:child_process";import{promisify as X2}from"node:util";import{execFile as r1}from"node:child_process";import{promisify as e1}from"node:util";var $2=e1(r1),b$=new Map,N0=5000;async function k0($,Z=$2){let X=b$.get($);if(X&&X.expiresAt>Date.now())return X.value;let J=process.platform==="win32"?"where":"which";try{let{stdout:Q}=await Z(J,[$],{timeout:2000}),V=Q.split(/\r?\n/).find((z)=>z.trim().length>0),W=V?V.trim():null;return b$.set($,{value:W,expiresAt:Date.now()+N0}),W}catch{return b$.set($,{value:null,expiresAt:Date.now()+N0}),null}}class J$ extends Error{code;constructor($,Z){super($);this.name="AcpError",this.code=Z}}class a extends J${constructor($="No ACP runtime configured"){super($,"RUNTIME_NOT_CONFIGURED");this.name="RuntimeNotConfiguredError"}}class F extends J${constructor($){super($,"RUNTIME_UNREACHABLE");this.name="RuntimeUnreachableError"}}class r extends J${authMethods;constructor($,Z){super($,"AUTH_REQUIRED");this.name="AuthRequiredError",this.authMethods=Z}}class i extends J${constructor($="ACP session timed out"){super($,"SESSION_TIMEOUT");this.name="SessionTimeoutError"}}var M6=X2(Z2);function A($,...Z){return k0($,...Z)}function b($){let Z={};for(let[X,J]of Object.entries(process.env))if(typeof J==="string")Z[X]=J;return{...Z,...$??{}}}var E$=[{adapterId:"claude-code",runtimeBinary:"claude",packageName:"@agentclientprotocol/claude-agent-acp",version:"0.39.0",warmupArgs:["--cli","--help"]},{adapterId:"codex",runtimeBinary:"codex",packageName:"@zed-industries/codex-acp",version:"0.15.0",warmupArgs:["--help"]}],G2=1800000,v$=new Map;function I$(){if(process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR)return process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR;if(process.platform==="win32"){let $=process.env.LOCALAPPDATA??d.join(q0.homedir(),"AppData","Local");return d.join($,"ideawave","acp-bridges")}return d.join(process.env.XDG_CACHE_HOME??d.join(q0.homedir(),".cache"),"ideawave","acp-bridges")}function x2($){return $.replace(/^@/,"").replace(/[/\\]/g,"-")}function D$(){return d.join(I$(),"install-state.json")}function g$($){return d.join(I$(),`${x2($.packageName)}@${$.version}.install.lock`)}function m$(){return process.platform==="win32"?"npx.cmd":"npx"}function h$($){return`${$.packageName}@${$.version}`}function L0(){let $=D$();if(!C0($))return{};try{return JSON.parse(j2($,"utf8"))}catch{return{}}}function y$($,Z){let X=I$();w0(X,{recursive:!0});let J=L0();J.bridges={...J.bridges??{},[$.adapterId]:Z},Y2(`${D$()}.tmp`,`${JSON.stringify(J,null,2)}
3
- `),W2(`${D$()}.tmp`,D$())}function O0($){return E$.find((Z)=>Z.packageName===$)??null}function y($,Z,X){return{adapterId:$.adapterId,packageName:$.packageName,version:$.version,status:Z,...X?{error:X}:{}}}function P0($,Z){return Z?.packageName===$.packageName&&Z.version===$.version}function A0($){try{return Date.now()-K2($).mtimeMs>G2}catch{return!1}}function z2($){let Z=g$($);if(!C0(Z))return!1;if(A0(Z))return F0(Z,{force:!0}),!1;return!0}function D2($){let Z=g$($);if(w0(d.dirname(Z),{recursive:!0}),A0(Z))F0(Z,{force:!0});try{let X=V2(Z,"wx");return Q2(X),!0}catch{return!1}}function H2($){M2(g$($))}function S$($){let Z=L0().bridges?.[$.adapterId];if(P0($,Z)&&Z.status==="ready")return y($,"ready");if(v$.has($.adapterId)||z2($))return y($,"installing");if(P0($,Z)&&Z.status==="failed")return y($,"failed",Z.error);return y($,"missing")}function B2($){let Z=S$($);if(Z.status==="ready"||Z.status==="installing")return Z;if(!D2($))return y($,"installing");let X=y($,"installing");y$($,X);let J=()=>{},Q=new Promise((K)=>{J=K});v$.set($.adapterId,Q);let V=!1,W=(K)=>{if(V)return;V=!0;try{H2($)}catch{}y$($,K),v$.delete($.adapterId),J(K)},z;try{z=J2(m$(),["-y",h$($),...$.warmupArgs],{stdio:"ignore",windowsHide:!0})}catch(K){let M=y($,"failed",K instanceof Error?K.message:String(K));return W(M),M}return z.on("error",(K)=>{W(y($,"failed",K.message))}),z.on("close",(K)=>{if(K===0){W(y($,"ready"));return}W(y($,"failed",`npx warmup exited ${K??"null"}`))}),z.unref(),X}function e($){let Z=O0($);return Z?S$(Z):null}async function _0(){let $=[];for(let Z of E$){if(!await A(Z.runtimeBinary)){$.push(y(Z,"not_needed"));continue}$.push(B2(Z))}return $.filter((Z)=>Z.status!=="not_needed")}function H$($){let Z=O0($);if(!Z)return null;if(S$(Z).status!=="ready")return null;return{command:m$(),args:["-y",h$(Z)],env:{}}}function c$($,Z){if($.command!==m$())return!1;let X=E$.find((J)=>$.args.includes(h$(J)));if(!X)return!1;return y$(X,y(X,"failed",Z)),!0}import{Readable as f2,Writable as R2}from"node:stream";import{ClientSideConnection as I0,ndJsonStream as g0}from"@agentclientprotocol/sdk";import c from"node:fs/promises";import T from"node:path";class V$ extends Error{constructor($){super($);this.name="PathTraversalError"}}class u$ extends Error{constructor($){super($);this.name="HiddenPathError"}}class p$ extends Error{constructor($){super($);this.name="RunFolderFileTooLargeError"}}class Q$ extends Error{constructor($){super($);this.name="RunFolderBinaryFileError"}}var U2=new Set([".bzr",".cache",".claude",".config",".env",".git",".hg",".idea",".obsidian",".svn",".vscode","node_modules"]),f0=1e6,N2=4096,k2=new TextDecoder("utf-8",{fatal:!0});function q2($){return $.split(/[\\/]+/).filter((Z)=>Z.length>0)}function B$($){if(T.isAbsolute($))throw new V$("Absolute paths are not allowed");for(let Z of q2($)){if(Z===".")continue;if(Z==="..")throw new V$("Parent-directory traversal is not allowed");if(Z.startsWith(".")||U2.has(Z))throw new u$(`Path segment "${Z}" is hidden or configuration data`)}}function P2($){B$($);let Z=T.normalize($||".");return Z==="."?"":Z}function C2($,Z,X){let J=T.relative($,Z);if(J===".."||J.startsWith(`..${T.sep}`)||T.isAbsolute(J))throw new V$(`Path "${X}" resolves outside the run folder`);if(J.length>0)B$(J);return J}async function l$($,Z){B$(Z);let X=T.resolve($,Z||"."),J;try{J=await c.realpath(X)}catch(Q){if(Q.code!=="ENOENT")throw Q;let V=T.dirname(X),W=[T.basename(X)];while(V!==$&&V!==T.dirname(V))try{V=await c.realpath(V);break}catch(z){if(z.code!=="ENOENT")throw z;W.unshift(T.basename(V)),V=T.dirname(V)}J=T.join(V,...W)}return C2($,J,Z),J}async function w2($,Z){let X=await c.realpath($);return l$(X,Z)}function F2($){let Z=$.subarray(0,Math.min($.length,N2));if(Z.length===0)return!1;let X=0;for(let J of Z){if(J===0)return!0;let Q=J===9||J===10||J===12||J===13;if(J<32&&!Q)X+=1}return X/Z.length>0.3}async function U$($,Z){let X=await w2($,Z),J=await c.stat(X);if(!J.isFile())throw new Q$(`Path "${Z}" is not a text file`);if(J.size>f0)throw new p$(`File "${Z}" is too large to read (${J.size} bytes, max ${f0} bytes)`);let Q=await c.readFile(X);if(F2(Q))throw new Q$(`File "${Z}" appears to be binary, not text`);try{return k2.decode(Q)}catch{throw new Q$(`File "${Z}" is not valid UTF-8 text`)}}function L2($){if($.isDirectory())return"directory";if($.isFile())return"file";if($.isSymbolicLink())return"symlink";return"other"}function R0($){return $.split(T.sep).join("/")}async function T0($,Z=""){let X=await c.realpath($),J=P2(Z),Q=await l$(X,J),V=await c.readdir(Q,{withFileTypes:!0}),W=[];for(let z of V){let K=J?T.join(J,z.name):z.name;try{B$(K);let M=await l$(X,K),j=await c.stat(M);W.push({name:z.name,path:R0(K),type:L2(z),size:z.isFile()?j.size:null})}catch{}}return W.sort((z,K)=>{if(z.type==="directory"&&K.type!=="directory")return-1;if(z.type!=="directory"&&K.type==="directory")return 1;return z.name.localeCompare(K.name)}),{path:R0(J),absolutePath:Q,entries:W}}var a$={fs:{readTextFile:!0,writeTextFile:!1},terminal:!1};function b0($){return{readTextFile:async(Z)=>{return{content:await U$($,Z.path)}}}}import{spawn as O2}from"node:child_process";function i$($){let Z=O2($.command,$.args,{cwd:$.cwd,env:$.env,stdio:["pipe","pipe","pipe"]});if(!Z.stdin||!Z.stdout||!Z.stderr)throw Error("Failed to allocate stdio streams for ACP subprocess");let{stdin:X,stdout:J,stderr:Q}=Z,V=4096,W=[],z=0;Q.on("data",(Y)=>{W.push(Y),z+=Y.length;while(z>V*2&&W.length>1){let N=W.shift();if(N)z-=N.length}});let K=()=>{let Y=Buffer.concat(W).toString("utf8");return Y.length>V?Y.slice(-V):Y},M=!1,j=!1,G,D,U=new Promise((Y)=>{G=Y}),B=new Promise((Y)=>{D=Y}),x=(Y)=>{if(j)return;if(j=!0,G(Y),!M)D(Y)};return Z.on("exit",(Y,N)=>{x({code:Y,signal:N,stderr:K()})}),Z.on("error",(Y)=>{let N=K(),w=Y?.message??String(Y);x({code:null,signal:null,stderr:N?`${w}
4
- ${N}`:w})}),{stdin:X,stdout:J,stderr:Q,kill:(Y="SIGTERM")=>{if(M)return;M=!0;try{Z.kill(Y)}catch{}},waitForExit:U,processCrashed:B}}function d$($){let Z=$?.toLowerCase();if(Z==="completed"||Z==="complete"||Z==="done"||Z==="success"||Z==="succeeded")return"completed";if(Z==="failed"||Z==="error"||Z==="errored")return"failed";return"running"}var A2={create_shape:"Create shape",update_shape:"Update shape",move_node:"Move card",resize_node:"Resize card",duplicate_node:"Duplicate card",delete_node:"Delete card",delete_nodes:"Delete cards",create_code_card:"Create code card",update_code_card:"Update code card",create_note_card:"Create note",update_note_card:"Update note",create_edge:"Create connection",update_edge:"Update connection",delete_edge:"Delete connection",create_flowchart:"Create flowchart",update_flowchart:"Update flowchart",create_agent_card:"Spawn sub-agent",spawn_child_agents:"Spawn sub-agents",list_nodes:"Read board",list_edges:"Read connections",read_file:"Read file"};function n$($){let Z=A2[$];if(Z)return Z;let X=$.replaceAll(/[_-]+/g," ").trim().split(/\s+/);if(X.length>1&&X[0].toLowerCase()==="mcp")X.shift();if(X.length===0)return $;return X.map((J,Q)=>Q===0?J.charAt(0).toUpperCase()+J.slice(1):J).join(" ")}var _2=33;function v0($){let{ctx:Z,appendText:X,appendToolActivity:J}=$,Q=$.flushIntervalMs??_2,V="",W=0,z=null,K={},M=new Map,j=(C)=>{if(M.set(C.toolCallId,C),!J)return;J({boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId,entry:C}).catch((H)=>{console.warn("[streamAdapter] appendToolActivity failed",H)})},G=(C)=>{for(let H of M.values()){if(H.status!=="running"||H.rawTitle.toLowerCase()!=="toolsearch")continue;j({...H,status:"completed",completedAt:H.completedAt??C})}},D="",U=0,B=null,x=null,Y=(C)=>{if(C===D)return;D=C,U=Date.now(),X({boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId,text:C}).catch((H)=>{console.warn("[streamAdapter] appendText failed",H)})},N=()=>{if(B!==null)clearTimeout(B),B=null;if(x!==null){let C=x;x=null,Y(C)}},w=(C)=>{let H=Date.now()-U;if(H>=Q&&B===null){Y(C);return}if(x=C,B===null){let O=Math.max(0,Q-H);B=setTimeout(()=>{B=null,N()},O)}};return{onSessionUpdate:async(C)=>{let H=C.update;switch(K[H.sessionUpdate]=(K[H.sessionUpdate]??0)+1,H.sessionUpdate){case"agent_message_chunk":{if(H.content.type==="text")V+=H.content.text,w(V);else{let O=`agent_message_chunk:${H.content.type}`;K[O]=(K[O]??0)+1}return}case"agent_thought_chunk":return;case"user_message_chunk":return;case"tool_call":{W+=1;let O=typeof H.title==="string"&&H.title.length>0?H.title:"tool",L=d$(H.status),k=new Date().toISOString();G(k),j({toolCallId:H.toolCallId,rawTitle:O,title:n$(O),kind:typeof H.kind==="string"?H.kind:null,status:L,startedAt:k,completedAt:L==="running"?null:k});return}case"tool_call_update":{let O=M.get(H.toolCallId);if(!O){let g=typeof H.title==="string"&&H.title.length>0?H.title:"tool",P=d$(H.status),R=new Date().toISOString();j({toolCallId:H.toolCallId,rawTitle:g,title:n$(g),kind:typeof H.kind==="string"?H.kind:null,status:P,startedAt:R,completedAt:P==="running"?null:R});return}let L=H.status===void 0||H.status===null?O.status:d$(H.status),k=typeof H.title==="string"&&H.title.length>0?H.title:O.rawTitle,_=L==="running"?O.completedAt:O.completedAt??new Date().toISOString();j({...O,rawTitle:k,title:n$(k),kind:typeof H.kind==="string"?H.kind:O.kind,status:L,completedAt:_});return}case"plan":z=H.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>V,getToolCallCount:()=>W,getLatestPlan:()=>z,getUpdateTypeCounts:()=>({...K}),flush:N}}var j$=1,y0=-32000;function E0($){if($.awaitingInput)return!1;return $.nowMs-$.lastUpdateMs>$.windowMs}function m0($){if(!$||typeof $!=="object")return!1;return $.code===y0}var T2=90000,b2=5000;function h0(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.28".trim()?"0.0.28":"dev"}}function S0($){if($===j$)return;throw new F(`Unsupported ACP protocol version ${$}; expected ${j$}`)}function c0($){return f2.toWeb($)}function l0($){return R2.toWeb($)}function u0($){let Z=$.configOptions?.find((J)=>J.type==="select"&&(J.category==="model"||J.id==="model"));if(Z&&Array.isArray(Z.options)){let J=[];for(let Q of Z.options)if(Q&&typeof Q==="object"&&"group"in Q){let V=Q.options;if(Array.isArray(V)){for(let W of V)if(W&&typeof W.value==="string"&&typeof W.name==="string")J.push({id:W.value,name:W.name,description:typeof W.description==="string"?W.description:null})}}else if(Q&&typeof Q.value==="string"&&typeof Q.name==="string")J.push({id:Q.value,name:Q.name,description:typeof Q.description==="string"?Q.description:null});if(J.length>0)return J}let X=$.models?.availableModels?.map((J)=>({id:J.modelId,name:J.name??null,description:J.description??null}));return X&&X.length>0?X:null}function v2($,Z){let X=[];if($.trim())X.push({type:"text",text:$});for(let J of Z)if(J.content.trim())X.push({type:"text",text:J.content});return X}async function o$($){let Z=i$($.spawn),X=[],J=0,Q=4096;Z.stderr.on("data",(P)=>{X.push(P),J+=P.length;while(J>Q*2&&X.length>1){let R=X.shift();if(R)J-=R.length}});let V=()=>{let P=Buffer.concat(X).toString("utf8");return P.length>Q?P.slice(-Q):P},W=b0($.spawn.cwd),z={current:null},K={at:Date.now()},M=l0(Z.stdin),j=c0(Z.stdout),G=g0(M,j),U=new I0((P)=>({requestPermission:async(R)=>{let v=R.options,s=v?.find((X$)=>X$.kind==="allow_once")??v?.find((X$)=>X$.kind==="allow_always");if(s)return{outcome:{outcome:"selected",optionId:s.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(R)=>{K.at=Date.now();let v=z.current;if(v)await v.onSessionUpdate(R)},readTextFile:W.readTextFile}),G),B=()=>Z.kill();if($.signal)$.signal.addEventListener("abort",B);let x=()=>{if($.signal)$.signal.removeEventListener("abort",B)},Y=async(P,R)=>{if(x(),Z.kill(),m0(P))throw new r(P.message??"Authentication required",R);if(P instanceof Error&&P.message==="ACP connection closed"){if($.signal?.aborted)throw new F("ACP session cancelled: abort signal received");let v=await Promise.race([Z.processCrashed,Z.waitForExit,new Promise((s)=>setTimeout(()=>s({stderr:""}),500))]);throw new F(`Runtime process exited before completion: ${v.stderr?.trim()??""}`)}throw P},N;try{N=await U.initialize({protocolVersion:j$,clientCapabilities:a$,clientInfo:h0()})}catch(P){throw await Y(P,[]),Error("unreachable")}try{S0(N.protocolVersion)}catch(P){throw x(),Z.kill(),P}let w=N.authMethods?.map((P)=>P.id)??[],C;try{C=await U.newSession({cwd:$.spawn.cwd,mcpServers:$.mcpServers??[]})}catch(P){throw await Y(P,w),Error("unreachable")}let H=C.sessionId,O=u0(C),L=$.modelId??C.models?.currentModelId??null;if(L)try{await U.unstable_setSessionModel({sessionId:H,modelId:L})}catch(P){console.warn(`[acp] setSessionModel(${L}) failed; using agent default.`,P instanceof Error?P.message:P)}x();let k=!1,_=async()=>{if(k)return;k=!0,Z.kill(),await Promise.race([Z.waitForExit,new Promise((P)=>setTimeout(P,2000))])},g=!1;return Z.processCrashed.then(()=>{g=!0}),{sessionId:H,availableModels:O,isAlive:()=>!k&&!g,dispose:_,prompt:(P)=>y2({proc:Z,conn:U,sessionId:H,activeAdapter:z,lastUpdate:K,collectStderrTail:V},P)}}async function y2($,Z){let{proc:X,conn:J,sessionId:Q,activeAdapter:V,lastUpdate:W}=$,z={boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId},K=v0({ctx:z,appendText:Z.appendText,appendToolActivity:Z.appendToolActivity});V.current=K,W.at=Date.now();let M=!1,j=null,G=()=>X.kill();Z.signal.addEventListener("abort",G);try{let D=async()=>{let Y=Z.heartbeatMs??T2,N=Math.min(b2,Math.max(50,Math.floor(Y/2)));j=setInterval(()=>{let C=Z.isAwaitingInput?.()??!1;if(C){W.at=Date.now();return}if(E0({nowMs:Date.now(),lastUpdateMs:W.at,windowMs:Y,awaitingInput:C}))M=!0,J.cancel({sessionId:Q}).catch(()=>{return}),X.kill()},N);let w=v2(Z.prompt.systemPrompt,Z.prompt.messages);await J.prompt({sessionId:Q,prompt:w}),K.flush()},U=X.waitForExit.then((Y)=>({kind:"exited",exit:Y})),B=D().then(()=>({kind:"ok"})).catch(async(Y)=>{if(Y instanceof Error&&Y.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([X.processCrashed,X.waitForExit])};throw Y}),x=await Promise.race([B,X.processCrashed.then((Y)=>({kind:"crashed",exit:Y})),U]);if(M)throw new i;if(x.kind==="crashed")throw new F(`Runtime process exited before completion: ${x.exit.stderr.trim()}`);if(x.kind==="exited"){if(Z.signal.aborted)throw new F("ACP session cancelled: abort signal received");if(M)throw new i;throw new F(`Runtime process exited unexpectedly: ${x.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:K.getFinalText(),toolCallsExecuted:K.getToolCallCount(),stderrTail:$.collectStderrTail(),updateTypeCounts:K.getUpdateTypeCounts()}}finally{if(j!==null)clearInterval(j);Z.signal.removeEventListener("abort",G),K.flush(),V.current=null}}var E2=30000;async function p0($){let Z=i$($.spawn),X=l0(Z.stdin),J=c0(Z.stdout),Q=g0(X,J),W=new I0((M)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),z=()=>Z.kill();if($.signal)$.signal.addEventListener("abort",z);let K=null;try{let M=(async()=>{let G=await W.initialize({protocolVersion:j$,clientCapabilities:a$,clientInfo:h0()});S0(G.protocolVersion);let D=G.authMethods?.map((Y)=>Y.id)??[],U;try{U=await W.newSession({cwd:$.spawn.cwd,mcpServers:[]})}catch(Y){if(m0(Y))throw new r(Y.message??"Authentication required",D);throw Y}let B=u0(U)??[],x=U.models?.currentModelId??null;return W.cancel({sessionId:U.sessionId}).catch(()=>{return}),{models:B,currentModelId:x}})(),j=new Promise((G,D)=>{K=setTimeout(()=>{D(new i)},E2)});return await Promise.race([M,j])}catch(M){if(M instanceof Error&&M.message==="ACP connection closed")throw new F("Runtime process exited during model discovery.");throw M}finally{if(K)clearTimeout(K);if($.signal)$.signal.removeEventListener("abort",z);Z.kill()}}var f=new Map,S=null;function N$($){$.then((Z)=>Z.dispose()).catch(()=>{return})}function I2(){if(S!==null)return;S=setInterval(()=>{let $=Date.now();for(let[Z,X]of f){if(X.inUse)continue;if($-X.lastUsed<600000)continue;f.delete(Z),N$(X.sessionPromise)}if(f.size===0&&S!==null)clearInterval(S),S=null},60000),S.unref?.()}function g2(){if(f.size<200)return;let $=null,Z=1/0;for(let[J,Q]of f){if(Q.inUse)continue;if(Q.lastUsed>=Z)continue;$=J,Z=Q.lastUsed}if(!$)return;let X=f.get($);if(!X)return;f.delete($),N$(X.sessionPromise)}function s$($,Z,X){return`${$}:${Z}:${X}`}async function t$($){let Z=f.get($.key);if(Z)if(Z.fingerprint===$.fingerprint){Z.inUse=!0,Z.lastUsed=Date.now();try{let J=await Z.sessionPromise;if(J.isAlive())return J}catch{}f.delete($.key)}else f.delete($.key),N$(Z.sessionPromise);let X=$.open();g2(),f.set($.key,{key:$.key,fingerprint:$.fingerprint,sessionPromise:X,lastUsed:Date.now(),inUse:!0}),I2();try{return await X}catch(J){throw f.delete($.key),J}}function r$($,Z=!1){let X=f.get($);if(!X)return;if(Z){f.delete($),N$(X.sessionPromise);return}X.inUse=!1,X.lastUsed=Date.now()}async function m2(){let $=Array.from(f.values());if(f.clear(),S!==null)clearInterval(S),S=null;await Promise.all($.map((Z)=>Z.sessionPromise.then((X)=>X.dispose()).catch(()=>{return})))}function e$($){return[$.adapterId,$.configId??"",$.modelId??"",$.mcpUrl??"",$.runFolder??"",$.toolSurface??"full"].join(" ")}var a0=!1;function h2(){if(a0)return;a0=!0;let $=()=>{m2()};process.once("beforeExit",$),process.once("SIGTERM",$),process.once("SIGINT",$)}h2();import W$ from"node:fs/promises";import u2 from"node:path";import{z as q}from"zod";var i0=q.object({id:q.string(),name:q.string().nullable().default(null),description:q.string().nullable().default(null)}),S2=q.discriminatedUnion("kind",[q.object({id:q.string(),kind:q.literal("registered"),adapterId:q.enum(["claude-code","opencode","codex","copilot"]),displayName:q.string(),runFolder:q.string().nullable(),defaultModelId:q.string().nullable().default(null),discoveredModels:q.array(i0).default([]),discoveredAt:q.string().nullable().default(null)}),q.object({id:q.string(),kind:q.literal("custom"),displayName:q.string(),command:q.string(),args:q.array(q.string()),env:q.record(q.string(),q.string()),runFolder:q.string().nullable(),defaultModelId:q.string().nullable().default(null),discoveredModels:q.array(i0).default([]),discoveredAt:q.string().nullable().default(null)})]),d0=q.object({runtimeConfigId:q.string(),runFolder:q.string().nullable(),modelId:q.string().nullable().default(null)}),k$=q.object({version:q.literal(1),globalDefaultConfigId:q.string().nullable(),runtimes:q.array(S2),boardOverrides:q.record(q.string(),d0).default({}),cardOverrides:q.record(q.string(),d0).default({})});import c2 from"node:os";import q$ from"node:path";function l2(){let $=c2.homedir();switch(process.platform){case"win32":return process.env.APPDATA??q$.join($,"AppData","Roaming");case"darwin":return q$.join($,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??q$.join($,".config")}}function P$(){let $=process.env.IDEAWAVE_RUNTIME_CONFIG_PATH;if($)return $;return q$.join(l2(),"ideawave","runtimes.json")}var p2={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},n0=new Map;function a2($){return n0.get($)??Promise.resolve()}function i2($,Z){n0.set($,Z)}async function E($){let Z=$??P$(),X;try{X=await W$.readFile(Z,"utf-8")}catch(Q){if(Q.code==="ENOENT")return structuredClone(p2);throw Q}return k$.parse(JSON.parse(X))}async function m($,Z){let X=Z??P$(),J=a2(X).then(async()=>{let Q=await E(X),V=structuredClone(Q),W=await $(V);return await d2(V,X),W});return i2(X,J.catch(()=>{return})),J}async function d2($,Z){let X=Z??P$(),J=u2.dirname(X);await W$.mkdir(J,{recursive:!0});let Q=`${X}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`,V=JSON.stringify($,null,2);await W$.writeFile(Q,V,"utf-8");try{await W$.rename(Q,X)}catch(W){throw await W$.unlink(Q).catch(()=>{return}),W}}import s2 from"node:fs/promises";import C$ from"node:os";var o0="claude",$0="@agentclientprotocol/claude-agent-acp",s0=["claude-agent-acp","claude-code-acp"],t0="Install Claude Code from https://github.com/anthropics/claude-code",r0={id:"claude-code",displayName:"Claude Code",kind:"registered",resolveSpawnConfig:async()=>{if(!await A(o0))throw new F(`Claude Code CLI not found. ${t0}`);let Z=H$($0);if(Z)return{command:Z.command,args:Z.args,env:b(Z.env)};let X=e($0),J=X?.status==="installing";for(let V of s0){let W=await A(V);if(W&&!J&&X?.status!=="failed")return{command:W,args:[],env:b()}}let Q=X?.status==="failed"?`Claude Code ACP bridge install failed. ${X.error??"Restart IdeaWave CLI so it can warm the pinned bridge again."}`:"Claude Code ACP bridge is not ready. Keep IdeaWave CLI running and retry in a moment.";throw new F(Q)},checkReadiness:async()=>{if(!await A(o0))return{status:"not_installed",detail:t0};let Z=e($0);if(Z?.status==="ready")return{status:"ready"};if(Z?.status==="installing")return{status:"not_running",detail:"Installing Claude Code ACP bridge..."};if(Z?.status==="failed")return{status:"not_running",detail:Z.error??"Claude Code ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};for(let X of s0)if(await A(X))return{status:"ready"};return{status:"not_running",detail:"Installing Claude Code ACP bridge..."}},authHint:"Run `claude login` (or set ANTHROPIC_API_KEY)."};var e0="codex",Z0="@zed-industries/codex-acp",$1="codex-acp",Z1="Install Codex CLI from https://developers.openai.com/codex/cli",X1={id:"codex",displayName:"Codex",kind:"registered",resolveSpawnConfig:async()=>{if(!await A(e0))throw new F(`Codex CLI not found. ${Z1}`);let Z=H$(Z0);if(Z)return{command:Z.command,args:Z.args,env:b(Z.env)};let X=e(Z0),J=X?.status==="installing",Q=await A($1);if(Q&&!J&&X?.status!=="failed")return{command:Q,args:[],env:b()};let V=X?.status==="failed"?`Codex ACP bridge install failed. ${X.error??"Restart IdeaWave CLI so it can warm the pinned bridge again."}`:"Codex ACP bridge is not ready. Keep IdeaWave CLI running and retry in a moment.";throw new F(V)},checkReadiness:async()=>{if(!await A(e0))return{status:"not_installed",detail:Z1};let Z=e(Z0);if(Z?.status==="ready")return{status:"ready"};if(Z?.status==="installing")return{status:"not_running",detail:"Installing Codex ACP bridge..."};if(Z?.status==="failed")return{status:"not_running",detail:Z.error??"Codex ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};if(await A($1))return{status:"ready"};return{status:"not_running",detail:"Installing Codex ACP bridge..."}},authHint:"Run `codex login` (or set OPENAI_API_KEY)."};var J1="copilot",Q1="copilot-acp",V1="npm i -g @github/copilot",j1={id:"copilot",displayName:"GitHub Copilot",kind:"registered",resolveSpawnConfig:async()=>{let $=await A(J1);if($)return{command:$,args:["--acp"],env:b()};let Z=await A(Q1);if(Z)return{command:Z,args:[],env:b()};throw new F(`Copilot not installed. Run: ${V1}`)},checkReadiness:async()=>{if(await A(J1))return{status:"ready"};if(await A(Q1))return{status:"ready"};return{status:"not_installed",detail:V1}},authHint:"Run `gh auth login` (or `copilot login`)."};import n2 from"node:fs/promises";function o2($){return $.startsWith("/")||/^[a-zA-Z]:[\\/]/.test($)}async function W1($){if(o2($))try{return await n2.access($),!0}catch{return!1}return await A($)!==null}var K1={id:"custom",displayName:"Custom ACP",kind:"custom",resolveSpawnConfig:async($)=>{if($.kind!=="custom")throw new F("customAdapter received non-custom entry");if(!await W1($.command))throw new F(`custom: command "${$.command}" not found`);return{command:$.command,args:$.args,env:b($.env)}},checkReadiness:async($)=>{if($.kind!=="custom")return{status:"unknown"};return await W1($.command)?{status:"ready"}:{status:"not_installed"}}};var M1="opencode",Y1="Install OpenCode from https://opencode.ai",G1={id:"opencode",displayName:"OpenCode",kind:"registered",resolveSpawnConfig:async()=>{let $=await A(M1);if(!$)throw new F(`OpenCode not installed. ${Y1}`);return{command:$,args:["acp"],env:b()}},checkReadiness:async()=>{if(!await A(M1))return{status:"not_installed",detail:Y1};return{status:"ready"}},authHint:"Run `opencode auth login <provider>` (or set the provider's API-key env var)."};var x1={"claude-code":r0,opencode:G1,codex:X1,copilot:j1};function h($){if($.kind==="custom")return K1;let Z=x1[$.adapterId];if(!Z)throw Error(`Unknown registered adapter: ${$.adapterId}`);return Z}function $$(){return Object.values(x1)}async function z1($){let Z={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},X;try{X=await s2.readFile($,"utf-8")}catch(J){if(J.code==="ENOENT")return structuredClone(Z);throw J}return k$.parse(JSON.parse(X))}async function n($){let Z=$.configPath?await z1($.configPath):await E(),X=$.cardId?Z.cardOverrides[$.cardId]:void 0;if(X?.runtimeConfigId){let Q=Z.runtimes.find((V)=>V.id===X.runtimeConfigId);if(Q)return{entry:Q,adapter:h(Q),runFolder:X.runFolder??Q.runFolder??C$.homedir(),modelId:X.modelId??Q.defaultModelId??null}}let J=Z.boardOverrides[$.boardId];if(J?.runtimeConfigId){let Q=Z.runtimes.find((V)=>V.id===J.runtimeConfigId);if(Q)return{entry:Q,adapter:h(Q),runFolder:J.runFolder??Q.runFolder??C$.homedir(),modelId:J.modelId??Q.defaultModelId??null}}if(Z.globalDefaultConfigId){let Q=Z.runtimes.find((V)=>V.id===Z.globalDefaultConfigId);if(Q)return{entry:Q,adapter:h(Q),runFolder:X?.runFolder??J?.runFolder??Q.runFolder??C$.homedir(),modelId:X?.modelId??J?.modelId??Q.defaultModelId??null}}throw new a}async function D1($,Z={}){let J=(Z.configPath?await z1(Z.configPath):await E()).runtimes.find((Q)=>Q.id===$);if(!J)return null;return{entry:J,adapter:h(J),runFolder:J.runFolder??C$.homedir(),modelId:Z.modelId??J.defaultModelId??null}}var o=new Map,X0=new Set;function J0($){o.get($)?.controller.abort()}function H1($){for(let[Z,X]of o){if(X.frontendSessionId!==$)continue;X.controller.abort(),o.delete(Z)}}function B1(){for(let $ of o.values())$.controller.abort();o.clear()}function U1($,Z){if(!Z.availableModels||Z.availableModels.length===0)return;m((X)=>{let J=X.runtimes.find((Q)=>Q.id===$);if(J)J.discoveredModels=Z.availableModels??[]}).catch(()=>{return})}function t2($,Z){return`${$}
2
+ import{readFileSync as o1}from"node:fs";import{homedir as d1}from"node:os";import{join as z$}from"node:path";function n1(){let $=d1();switch(process.platform){case"win32":return process.env.APPDATA??z$($,"AppData","Roaming");case"darwin":return z$($,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??z$($,".config")}}function D0(){let $=process.env.IDEAWAVE_MCP_JSON_PATH;if($&&$.trim().length>0)return $;return z$(n1(),"ideawave","mcp.json")}var B0=null;function U0($){B0=$}var s1=86400000;function t1(){let $;try{$=o1(D0(),"utf8")}catch{return null}let Z;try{Z=JSON.parse($)}catch{return null}if(typeof Z.url!=="string")return null;if(typeof Z.startedAt==="string"){let X=Date.parse(Z.startedAt);if(!Number.isNaN(X)){if(Date.now()-X>s1)return null}}if(typeof Z.pid==="number"&&Z.pid>0)try{process.kill(Z.pid,0)}catch(X){if(X?.code!=="EPERM")return null}return{url:Z.url}}function H0($,Z={}){let X=[];if(Z.userId&&Z.userId.trim().length>0)X.push({name:"X-Ideawave-User-Id",value:Z.userId.trim()});if(Z.frontendSessionId&&Z.frontendSessionId.trim().length>0)X.push({name:"X-Ideawave-Frontend-Session-Id",value:Z.frontendSessionId.trim()});if(Z.toolSurface==="read")X.push({name:"X-Ideawave-Tool-Surface",value:"read"});if(Z.cardId&&Z.cardId.trim().length>0)X.push({name:"X-Ideawave-Card-Id",value:Z.cardId.trim()});if(Z.boardId&&Z.boardId.trim().length>0)X.push({name:"X-Ideawave-Board-Id",value:Z.boardId.trim()});if(Z.runFolder&&Z.runFolder.trim().length>0)X.push({name:"X-Ideawave-Run-Folder",value:Z.runFolder.trim()});return{type:"http",name:"ideawave-board",url:$,headers:X}}function b$($={}){let Z=B0;if(Z)return H0(Z.url,$);let X=t1();if(!X)return null;return H0(X.url,$)}import{spawn as J2}from"node:child_process";import{closeSync as Q2,existsSync as C0,mkdirSync as w0,openSync as V2,readFileSync as j2,renameSync as K2,rmSync as F0,statSync as W2,unlinkSync as M2,writeFileSync as Y2}from"node:fs";import q0 from"node:os";import d from"node:path";import{execFile as Z2}from"node:child_process";import{promisify as X2}from"node:util";import{execFile as r1}from"node:child_process";import{promisify as e1}from"node:util";var $2=e1(r1),T$=new Map,N0=5000;async function k0($,Z=$2){let X=T$.get($);if(X&&X.expiresAt>Date.now())return X.value;let J=process.platform==="win32"?"where":"which";try{let{stdout:Q}=await Z(J,[$],{timeout:2000}),V=Q.split(/\r?\n/).find((z)=>z.trim().length>0),K=V?V.trim():null;return T$.set($,{value:K,expiresAt:Date.now()+N0}),K}catch{return T$.set($,{value:null,expiresAt:Date.now()+N0}),null}}class J$ extends Error{code;constructor($,Z){super($);this.name="AcpError",this.code=Z}}class a extends J${constructor($="No ACP runtime configured"){super($,"RUNTIME_NOT_CONFIGURED");this.name="RuntimeNotConfiguredError"}}class F extends J${constructor($){super($,"RUNTIME_UNREACHABLE");this.name="RuntimeUnreachableError"}}class r extends J${authMethods;constructor($,Z){super($,"AUTH_REQUIRED");this.name="AuthRequiredError",this.authMethods=Z}}class i extends J${constructor($="ACP session timed out"){super($,"SESSION_TIMEOUT");this.name="SessionTimeoutError"}}var z6=X2(Z2);function A($,...Z){return k0($,...Z)}function T($){let Z={};for(let[X,J]of Object.entries(process.env))if(typeof J==="string")Z[X]=J;return{...Z,...$??{}}}var E$=[{adapterId:"claude-code",runtimeBinary:"claude",packageName:"@agentclientprotocol/claude-agent-acp",version:"0.39.0",warmupArgs:["--cli","--help"]},{adapterId:"codex",runtimeBinary:"codex",packageName:"@zed-industries/codex-acp",version:"0.15.0",warmupArgs:["--help"]}],G2=1800000,v$=new Map;function I$(){if(process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR)return process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR;if(process.platform==="win32"){let $=process.env.LOCALAPPDATA??d.join(q0.homedir(),"AppData","Local");return d.join($,"ideawave","acp-bridges")}return d.join(process.env.XDG_CACHE_HOME??d.join(q0.homedir(),".cache"),"ideawave","acp-bridges")}function x2($){return $.replace(/^@/,"").replace(/[/\\]/g,"-")}function D$(){return d.join(I$(),"install-state.json")}function g$($){return d.join(I$(),`${x2($.packageName)}@${$.version}.install.lock`)}function h$(){return process.platform==="win32"?"npx.cmd":"npx"}function m$($){return`${$.packageName}@${$.version}`}function L0(){let $=D$();if(!C0($))return{};try{return JSON.parse(j2($,"utf8"))}catch{return{}}}function y$($,Z){let X=I$();w0(X,{recursive:!0});let J=L0();J.bridges={...J.bridges??{},[$.adapterId]:Z},Y2(`${D$()}.tmp`,`${JSON.stringify(J,null,2)}
3
+ `),K2(`${D$()}.tmp`,D$())}function O0($){return E$.find((Z)=>Z.packageName===$)??null}function y($,Z,X){return{adapterId:$.adapterId,packageName:$.packageName,version:$.version,status:Z,...X?{error:X}:{}}}function P0($,Z){return Z?.packageName===$.packageName&&Z.version===$.version}function A0($){try{return Date.now()-W2($).mtimeMs>G2}catch{return!1}}function z2($){let Z=g$($);if(!C0(Z))return!1;if(A0(Z))return F0(Z,{force:!0}),!1;return!0}function D2($){let Z=g$($);if(w0(d.dirname(Z),{recursive:!0}),A0(Z))F0(Z,{force:!0});try{let X=V2(Z,"wx");return Q2(X),!0}catch{return!1}}function H2($){M2(g$($))}function S$($){let Z=L0().bridges?.[$.adapterId];if(P0($,Z)&&Z.status==="ready")return y($,"ready");if(v$.has($.adapterId)||z2($))return y($,"installing");if(P0($,Z)&&Z.status==="failed")return y($,"failed",Z.error);return y($,"missing")}function B2($){let Z=S$($);if(Z.status==="ready"||Z.status==="installing")return Z;if(!D2($))return y($,"installing");let X=y($,"installing");y$($,X);let J=()=>{},Q=new Promise((W)=>{J=W});v$.set($.adapterId,Q);let V=!1,K=(W)=>{if(V)return;V=!0;try{H2($)}catch{}y$($,W),v$.delete($.adapterId),J(W)},z;try{z=J2(h$(),["-y",m$($),...$.warmupArgs],{stdio:"ignore",windowsHide:!0})}catch(W){let M=y($,"failed",W instanceof Error?W.message:String(W));return K(M),M}return z.on("error",(W)=>{K(y($,"failed",W.message))}),z.on("close",(W)=>{if(W===0){K(y($,"ready"));return}K(y($,"failed",`npx warmup exited ${W??"null"}`))}),z.unref(),X}function e($){let Z=O0($);return Z?S$(Z):null}async function _0(){let $=[];for(let Z of E$){if(!await A(Z.runtimeBinary)){$.push(y(Z,"not_needed"));continue}$.push(B2(Z))}return $.filter((Z)=>Z.status!=="not_needed")}function H$($){let Z=O0($);if(!Z)return null;if(S$(Z).status!=="ready")return null;return{command:h$(),args:["-y",m$(Z)],env:{}}}function c$($,Z){if($.command!==h$())return!1;let X=E$.find((J)=>$.args.includes(m$(J)));if(!X)return!1;return y$(X,y(X,"failed",Z)),!0}import{Readable as f2,Writable as R2}from"node:stream";import{ClientSideConnection as I0,ndJsonStream as g0}from"@agentclientprotocol/sdk";import c from"node:fs/promises";import b from"node:path";class V$ extends Error{constructor($){super($);this.name="PathTraversalError"}}class u$ extends Error{constructor($){super($);this.name="HiddenPathError"}}class p$ extends Error{constructor($){super($);this.name="RunFolderFileTooLargeError"}}class Q$ extends Error{constructor($){super($);this.name="RunFolderBinaryFileError"}}var U2=new Set([".bzr",".cache",".claude",".config",".env",".git",".hg",".idea",".obsidian",".svn",".vscode","node_modules"]),f0=1e6,N2=4096,k2=new TextDecoder("utf-8",{fatal:!0});function q2($){return $.split(/[\\/]+/).filter((Z)=>Z.length>0)}function B$($){if(b.isAbsolute($))throw new V$("Absolute paths are not allowed");for(let Z of q2($)){if(Z===".")continue;if(Z==="..")throw new V$("Parent-directory traversal is not allowed");if(Z.startsWith(".")||U2.has(Z))throw new u$(`Path segment "${Z}" is hidden or configuration data`)}}function P2($){B$($);let Z=b.normalize($||".");return Z==="."?"":Z}function C2($,Z,X){let J=b.relative($,Z);if(J===".."||J.startsWith(`..${b.sep}`)||b.isAbsolute(J))throw new V$(`Path "${X}" resolves outside the run folder`);if(J.length>0)B$(J);return J}async function l$($,Z){B$(Z);let X=b.resolve($,Z||"."),J;try{J=await c.realpath(X)}catch(Q){if(Q.code!=="ENOENT")throw Q;let V=b.dirname(X),K=[b.basename(X)];while(V!==$&&V!==b.dirname(V))try{V=await c.realpath(V);break}catch(z){if(z.code!=="ENOENT")throw z;K.unshift(b.basename(V)),V=b.dirname(V)}J=b.join(V,...K)}return C2($,J,Z),J}async function w2($,Z){let X=await c.realpath($);return l$(X,Z)}function F2($){let Z=$.subarray(0,Math.min($.length,N2));if(Z.length===0)return!1;let X=0;for(let J of Z){if(J===0)return!0;let Q=J===9||J===10||J===12||J===13;if(J<32&&!Q)X+=1}return X/Z.length>0.3}async function U$($,Z){let X=await w2($,Z),J=await c.stat(X);if(!J.isFile())throw new Q$(`Path "${Z}" is not a text file`);if(J.size>f0)throw new p$(`File "${Z}" is too large to read (${J.size} bytes, max ${f0} bytes)`);let Q=await c.readFile(X);if(F2(Q))throw new Q$(`File "${Z}" appears to be binary, not text`);try{return k2.decode(Q)}catch{throw new Q$(`File "${Z}" is not valid UTF-8 text`)}}function L2($){if($.isDirectory())return"directory";if($.isFile())return"file";if($.isSymbolicLink())return"symlink";return"other"}function R0($){return $.split(b.sep).join("/")}async function b0($,Z=""){let X=await c.realpath($),J=P2(Z),Q=await l$(X,J),V=await c.readdir(Q,{withFileTypes:!0}),K=[];for(let z of V){let W=J?b.join(J,z.name):z.name;try{B$(W);let M=await l$(X,W),j=await c.stat(M);K.push({name:z.name,path:R0(W),type:L2(z),size:z.isFile()?j.size:null})}catch{}}return K.sort((z,W)=>{if(z.type==="directory"&&W.type!=="directory")return-1;if(z.type!=="directory"&&W.type==="directory")return 1;return z.name.localeCompare(W.name)}),{path:R0(J),absolutePath:Q,entries:K}}var a$={fs:{readTextFile:!0,writeTextFile:!1},terminal:!1};function T0($){return{readTextFile:async(Z)=>{return{content:await U$($,Z.path)}}}}import{spawn as O2}from"node:child_process";function i$($){let Z=O2($.command,$.args,{cwd:$.cwd,env:$.env,stdio:["pipe","pipe","pipe"]});if(!Z.stdin||!Z.stdout||!Z.stderr)throw Error("Failed to allocate stdio streams for ACP subprocess");let{stdin:X,stdout:J,stderr:Q}=Z,V=4096,K=[],z=0;Q.on("data",(Y)=>{K.push(Y),z+=Y.length;while(z>V*2&&K.length>1){let N=K.shift();if(N)z-=N.length}});let W=()=>{let Y=Buffer.concat(K).toString("utf8");return Y.length>V?Y.slice(-V):Y},M=!1,j=!1,G,D,U=new Promise((Y)=>{G=Y}),B=new Promise((Y)=>{D=Y}),x=(Y)=>{if(j)return;if(j=!0,G(Y),!M)D(Y)};return Z.on("exit",(Y,N)=>{x({code:Y,signal:N,stderr:W()})}),Z.on("error",(Y)=>{let N=W(),w=Y?.message??String(Y);x({code:null,signal:null,stderr:N?`${w}
4
+ ${N}`:w})}),{stdin:X,stdout:J,stderr:Q,kill:(Y="SIGTERM")=>{if(M)return;M=!0;try{Z.kill(Y)}catch{}},waitForExit:U,processCrashed:B}}function d$($){let Z=$?.toLowerCase();if(Z==="completed"||Z==="complete"||Z==="done"||Z==="success"||Z==="succeeded")return"completed";if(Z==="failed"||Z==="error"||Z==="errored")return"failed";return"running"}var A2={create_shape:"Create shape",update_shape:"Update shape",move_node:"Move card",resize_node:"Resize card",duplicate_node:"Duplicate card",delete_node:"Delete card",delete_nodes:"Delete cards",create_code_card:"Create code card",update_code_card:"Update code card",create_note_card:"Create note",update_note_card:"Update note",create_edge:"Create connection",update_edge:"Update connection",delete_edge:"Delete connection",create_flowchart:"Create flowchart",update_flowchart:"Update flowchart",create_agent_card:"Spawn sub-agent",spawn_child_agents:"Spawn sub-agents",list_nodes:"Read board",list_edges:"Read connections",read_file:"Read file"};function n$($){let Z=A2[$];if(Z)return Z;let X=$.replaceAll(/[_-]+/g," ").trim().split(/\s+/);if(X.length>1&&X[0].toLowerCase()==="mcp")X.shift();if(X.length===0)return $;return X.map((J,Q)=>Q===0?J.charAt(0).toUpperCase()+J.slice(1):J).join(" ")}var _2=33;function v0($){let{ctx:Z,appendText:X,appendToolActivity:J}=$,Q=$.flushIntervalMs??_2,V="",K=0,z=null,W={},M=new Map,j=(C)=>{if(M.set(C.toolCallId,C),!J)return;J({boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId,entry:C}).catch((H)=>{console.warn("[streamAdapter] appendToolActivity failed",H)})},G=(C)=>{for(let H of M.values()){if(H.status!=="running"||H.rawTitle.toLowerCase()!=="toolsearch")continue;j({...H,status:"completed",completedAt:H.completedAt??C})}},D="",U=0,B=null,x=null,Y=(C)=>{if(C===D)return;D=C,U=Date.now(),X({boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId,text:C}).catch((H)=>{console.warn("[streamAdapter] appendText failed",H)})},N=()=>{if(B!==null)clearTimeout(B),B=null;if(x!==null){let C=x;x=null,Y(C)}},w=(C)=>{let H=Date.now()-U;if(H>=Q&&B===null){Y(C);return}if(x=C,B===null){let O=Math.max(0,Q-H);B=setTimeout(()=>{B=null,N()},O)}};return{onSessionUpdate:async(C)=>{let H=C.update;switch(W[H.sessionUpdate]=(W[H.sessionUpdate]??0)+1,H.sessionUpdate){case"agent_message_chunk":{if(H.content.type==="text")V+=H.content.text,w(V);else{let O=`agent_message_chunk:${H.content.type}`;W[O]=(W[O]??0)+1}return}case"agent_thought_chunk":return;case"user_message_chunk":return;case"tool_call":{K+=1;let O=typeof H.title==="string"&&H.title.length>0?H.title:"tool",L=d$(H.status),k=new Date().toISOString();G(k),j({toolCallId:H.toolCallId,rawTitle:O,title:n$(O),kind:typeof H.kind==="string"?H.kind:null,status:L,startedAt:k,completedAt:L==="running"?null:k});return}case"tool_call_update":{let O=M.get(H.toolCallId);if(!O){let g=typeof H.title==="string"&&H.title.length>0?H.title:"tool",P=d$(H.status),R=new Date().toISOString();j({toolCallId:H.toolCallId,rawTitle:g,title:n$(g),kind:typeof H.kind==="string"?H.kind:null,status:P,startedAt:R,completedAt:P==="running"?null:R});return}let L=H.status===void 0||H.status===null?O.status:d$(H.status),k=typeof H.title==="string"&&H.title.length>0?H.title:O.rawTitle,_=L==="running"?O.completedAt:O.completedAt??new Date().toISOString();j({...O,rawTitle:k,title:n$(k),kind:typeof H.kind==="string"?H.kind:O.kind,status:L,completedAt:_});return}case"plan":z=H.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>V,getToolCallCount:()=>K,getLatestPlan:()=>z,getUpdateTypeCounts:()=>({...W}),flush:N}}var j$=1,y0=-32000;function E0($){if($.awaitingInput)return!1;return $.nowMs-$.lastUpdateMs>$.windowMs}function h0($){if(!$||typeof $!=="object")return!1;return $.code===y0}var b2=90000,T2=5000;function m0(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.29".trim()?"0.0.29":"dev"}}function S0($){if($===j$)return;throw new F(`Unsupported ACP protocol version ${$}; expected ${j$}`)}function c0($){return f2.toWeb($)}function l0($){return R2.toWeb($)}function u0($){let Z=$.configOptions?.find((J)=>J.type==="select"&&(J.category==="model"||J.id==="model"));if(Z&&Array.isArray(Z.options)){let J=[];for(let Q of Z.options)if(Q&&typeof Q==="object"&&"group"in Q){let V=Q.options;if(Array.isArray(V)){for(let K of V)if(K&&typeof K.value==="string"&&typeof K.name==="string")J.push({id:K.value,name:K.name,description:typeof K.description==="string"?K.description:null})}}else if(Q&&typeof Q.value==="string"&&typeof Q.name==="string")J.push({id:Q.value,name:Q.name,description:typeof Q.description==="string"?Q.description:null});if(J.length>0)return J}let X=$.models?.availableModels?.map((J)=>({id:J.modelId,name:J.name??null,description:J.description??null}));return X&&X.length>0?X:null}function v2($,Z){let X=[];if($.trim())X.push({type:"text",text:$});for(let J of Z)if(J.content.trim())X.push({type:"text",text:J.content});return X}async function o$($){let Z=i$($.spawn),X=[],J=0,Q=4096;Z.stderr.on("data",(P)=>{X.push(P),J+=P.length;while(J>Q*2&&X.length>1){let R=X.shift();if(R)J-=R.length}});let V=()=>{let P=Buffer.concat(X).toString("utf8");return P.length>Q?P.slice(-Q):P},K=T0($.spawn.cwd),z={current:null},W={at:Date.now()},M=l0(Z.stdin),j=c0(Z.stdout),G=g0(M,j),U=new I0((P)=>({requestPermission:async(R)=>{let v=R.options,s=v?.find((X$)=>X$.kind==="allow_once")??v?.find((X$)=>X$.kind==="allow_always");if(s)return{outcome:{outcome:"selected",optionId:s.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(R)=>{W.at=Date.now();let v=z.current;if(v)await v.onSessionUpdate(R)},readTextFile:K.readTextFile}),G),B=()=>Z.kill();if($.signal)$.signal.addEventListener("abort",B);let x=()=>{if($.signal)$.signal.removeEventListener("abort",B)},Y=async(P,R)=>{if(x(),Z.kill(),h0(P))throw new r(P.message??"Authentication required",R);if(P instanceof Error&&P.message==="ACP connection closed"){if($.signal?.aborted)throw new F("ACP session cancelled: abort signal received");let v=await Promise.race([Z.processCrashed,Z.waitForExit,new Promise((s)=>setTimeout(()=>s({stderr:""}),500))]);throw new F(`Runtime process exited before completion: ${v.stderr?.trim()??""}`)}throw P},N;try{N=await U.initialize({protocolVersion:j$,clientCapabilities:a$,clientInfo:m0()})}catch(P){throw await Y(P,[]),Error("unreachable")}try{S0(N.protocolVersion)}catch(P){throw x(),Z.kill(),P}let w=N.authMethods?.map((P)=>P.id)??[],C;try{C=await U.newSession({cwd:$.spawn.cwd,mcpServers:$.mcpServers??[]})}catch(P){throw await Y(P,w),Error("unreachable")}let H=C.sessionId,O=u0(C),L=$.modelId??C.models?.currentModelId??null;if(L)try{await U.unstable_setSessionModel({sessionId:H,modelId:L})}catch(P){console.warn(`[acp] setSessionModel(${L}) failed; using agent default.`,P instanceof Error?P.message:P)}x();let k=!1,_=async()=>{if(k)return;k=!0,Z.kill(),await Promise.race([Z.waitForExit,new Promise((P)=>setTimeout(P,2000))])},g=!1;return Z.processCrashed.then(()=>{g=!0}),{sessionId:H,availableModels:O,isAlive:()=>!k&&!g,dispose:_,prompt:(P)=>y2({proc:Z,conn:U,sessionId:H,activeAdapter:z,lastUpdate:W,collectStderrTail:V},P)}}async function y2($,Z){let{proc:X,conn:J,sessionId:Q,activeAdapter:V,lastUpdate:K}=$,z={boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId},W=v0({ctx:z,appendText:Z.appendText,appendToolActivity:Z.appendToolActivity});V.current=W,K.at=Date.now();let M=!1,j=null,G=()=>X.kill();Z.signal.addEventListener("abort",G);try{let D=async()=>{let Y=Z.heartbeatMs??b2,N=Math.min(T2,Math.max(50,Math.floor(Y/2)));j=setInterval(()=>{let C=Z.isAwaitingInput?.()??!1;if(C){K.at=Date.now();return}if(E0({nowMs:Date.now(),lastUpdateMs:K.at,windowMs:Y,awaitingInput:C}))M=!0,J.cancel({sessionId:Q}).catch(()=>{return}),X.kill()},N);let w=v2(Z.prompt.systemPrompt,Z.prompt.messages);await J.prompt({sessionId:Q,prompt:w}),W.flush()},U=X.waitForExit.then((Y)=>({kind:"exited",exit:Y})),B=D().then(()=>({kind:"ok"})).catch(async(Y)=>{if(Y instanceof Error&&Y.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([X.processCrashed,X.waitForExit])};throw Y}),x=await Promise.race([B,X.processCrashed.then((Y)=>({kind:"crashed",exit:Y})),U]);if(M)throw new i;if(x.kind==="crashed")throw new F(`Runtime process exited before completion: ${x.exit.stderr.trim()}`);if(x.kind==="exited"){if(Z.signal.aborted)throw new F("ACP session cancelled: abort signal received");if(M)throw new i;throw new F(`Runtime process exited unexpectedly: ${x.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:W.getFinalText(),toolCallsExecuted:W.getToolCallCount(),stderrTail:$.collectStderrTail(),updateTypeCounts:W.getUpdateTypeCounts()}}finally{if(j!==null)clearInterval(j);Z.signal.removeEventListener("abort",G),W.flush(),V.current=null}}var E2=30000;async function p0($){let Z=i$($.spawn),X=l0(Z.stdin),J=c0(Z.stdout),Q=g0(X,J),K=new I0((M)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),z=()=>Z.kill();if($.signal)$.signal.addEventListener("abort",z);let W=null;try{let M=(async()=>{let G=await K.initialize({protocolVersion:j$,clientCapabilities:a$,clientInfo:m0()});S0(G.protocolVersion);let D=G.authMethods?.map((Y)=>Y.id)??[],U;try{U=await K.newSession({cwd:$.spawn.cwd,mcpServers:[]})}catch(Y){if(h0(Y))throw new r(Y.message??"Authentication required",D);throw Y}let B=u0(U)??[],x=U.models?.currentModelId??null;return K.cancel({sessionId:U.sessionId}).catch(()=>{return}),{models:B,currentModelId:x}})(),j=new Promise((G,D)=>{W=setTimeout(()=>{D(new i)},E2)});return await Promise.race([M,j])}catch(M){if(M instanceof Error&&M.message==="ACP connection closed")throw new F("Runtime process exited during model discovery.");throw M}finally{if(W)clearTimeout(W);if($.signal)$.signal.removeEventListener("abort",z);Z.kill()}}var f=new Map,S=null;function N$($){$.then((Z)=>Z.dispose()).catch(()=>{return})}function I2(){if(S!==null)return;S=setInterval(()=>{let $=Date.now();for(let[Z,X]of f){if(X.inUse)continue;if($-X.lastUsed<600000)continue;f.delete(Z),N$(X.sessionPromise)}if(f.size===0&&S!==null)clearInterval(S),S=null},60000),S.unref?.()}function g2(){if(f.size<200)return;let $=null,Z=1/0;for(let[J,Q]of f){if(Q.inUse)continue;if(Q.lastUsed>=Z)continue;$=J,Z=Q.lastUsed}if(!$)return;let X=f.get($);if(!X)return;f.delete($),N$(X.sessionPromise)}function s$($,Z,X){return`${$}:${Z}:${X}`}async function t$($){let Z=f.get($.key);if(Z)if(Z.fingerprint===$.fingerprint){Z.inUse=!0,Z.lastUsed=Date.now();try{let J=await Z.sessionPromise;if(J.isAlive())return J}catch{}f.delete($.key)}else f.delete($.key),N$(Z.sessionPromise);let X=$.open();g2(),f.set($.key,{key:$.key,fingerprint:$.fingerprint,sessionPromise:X,lastUsed:Date.now(),inUse:!0}),I2();try{return await X}catch(J){throw f.delete($.key),J}}function r$($,Z=!1){let X=f.get($);if(!X)return;if(Z){f.delete($),N$(X.sessionPromise);return}X.inUse=!1,X.lastUsed=Date.now()}async function h2(){let $=Array.from(f.values());if(f.clear(),S!==null)clearInterval(S),S=null;await Promise.all($.map((Z)=>Z.sessionPromise.then((X)=>X.dispose()).catch(()=>{return})))}function e$($){return[$.adapterId,$.configId??"",$.modelId??"",$.mcpUrl??"",$.runFolder??"",$.toolSurface??"full"].join(" ")}var a0=!1;function m2(){if(a0)return;a0=!0;let $=()=>{h2()};process.once("beforeExit",$),process.once("SIGTERM",$),process.once("SIGINT",$)}m2();import K$ from"node:fs/promises";import u2 from"node:path";import{z as q}from"zod";var i0=q.object({id:q.string(),name:q.string().nullable().default(null),description:q.string().nullable().default(null)}),S2=q.discriminatedUnion("kind",[q.object({id:q.string(),kind:q.literal("registered"),adapterId:q.enum(["claude-code","opencode","codex","copilot"]),displayName:q.string(),runFolder:q.string().nullable(),defaultModelId:q.string().nullable().default(null),discoveredModels:q.array(i0).default([]),discoveredAt:q.string().nullable().default(null)}),q.object({id:q.string(),kind:q.literal("custom"),displayName:q.string(),command:q.string(),args:q.array(q.string()),env:q.record(q.string(),q.string()),runFolder:q.string().nullable(),defaultModelId:q.string().nullable().default(null),discoveredModels:q.array(i0).default([]),discoveredAt:q.string().nullable().default(null)})]),d0=q.object({runtimeConfigId:q.string(),runFolder:q.string().nullable(),modelId:q.string().nullable().default(null)}),k$=q.object({version:q.literal(1),globalDefaultConfigId:q.string().nullable(),runtimes:q.array(S2),boardOverrides:q.record(q.string(),d0).default({}),cardOverrides:q.record(q.string(),d0).default({})});import c2 from"node:os";import q$ from"node:path";function l2(){let $=c2.homedir();switch(process.platform){case"win32":return process.env.APPDATA??q$.join($,"AppData","Roaming");case"darwin":return q$.join($,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??q$.join($,".config")}}function P$(){let $=process.env.IDEAWAVE_RUNTIME_CONFIG_PATH;if($)return $;return q$.join(l2(),"ideawave","runtimes.json")}var p2={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},n0=new Map;function a2($){return n0.get($)??Promise.resolve()}function i2($,Z){n0.set($,Z)}async function E($){let Z=$??P$(),X;try{X=await K$.readFile(Z,"utf-8")}catch(Q){if(Q.code==="ENOENT")return structuredClone(p2);throw Q}return k$.parse(JSON.parse(X))}async function h($,Z){let X=Z??P$(),J=a2(X).then(async()=>{let Q=await E(X),V=structuredClone(Q),K=await $(V);return await d2(V,X),K});return i2(X,J.catch(()=>{return})),J}async function d2($,Z){let X=Z??P$(),J=u2.dirname(X);await K$.mkdir(J,{recursive:!0});let Q=`${X}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`,V=JSON.stringify($,null,2);await K$.writeFile(Q,V,"utf-8");try{await K$.rename(Q,X)}catch(K){throw await K$.unlink(Q).catch(()=>{return}),K}}import s2 from"node:fs/promises";import C$ from"node:os";var o0="claude",$0="@agentclientprotocol/claude-agent-acp",s0=["claude-agent-acp","claude-code-acp"],t0="Install Claude Code from https://github.com/anthropics/claude-code",r0={id:"claude-code",displayName:"Claude Code",kind:"registered",resolveSpawnConfig:async()=>{if(!await A(o0))throw new F(`Claude Code CLI not found. ${t0}`);let Z=H$($0);if(Z)return{command:Z.command,args:Z.args,env:T(Z.env)};let X=e($0),J=X?.status==="installing";for(let V of s0){let K=await A(V);if(K&&!J&&X?.status!=="failed")return{command:K,args:[],env:T()}}let Q=X?.status==="failed"?`Claude Code ACP bridge install failed. ${X.error??"Restart IdeaWave CLI so it can warm the pinned bridge again."}`:"Claude Code ACP bridge is not ready. Keep IdeaWave CLI running and retry in a moment.";throw new F(Q)},checkReadiness:async()=>{if(!await A(o0))return{status:"not_installed",detail:t0};let Z=e($0);if(Z?.status==="ready")return{status:"ready"};if(Z?.status==="installing")return{status:"not_running",detail:"Installing Claude Code ACP bridge..."};if(Z?.status==="failed")return{status:"not_running",detail:Z.error??"Claude Code ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};for(let X of s0)if(await A(X))return{status:"ready"};return{status:"not_running",detail:"Installing Claude Code ACP bridge..."}},authHint:"Run `claude login` (or set ANTHROPIC_API_KEY)."};var e0="codex",Z0="@zed-industries/codex-acp",$1="codex-acp",Z1="Install Codex CLI from https://developers.openai.com/codex/cli",X1={id:"codex",displayName:"Codex",kind:"registered",resolveSpawnConfig:async()=>{if(!await A(e0))throw new F(`Codex CLI not found. ${Z1}`);let Z=H$(Z0);if(Z)return{command:Z.command,args:Z.args,env:T(Z.env)};let X=e(Z0),J=X?.status==="installing",Q=await A($1);if(Q&&!J&&X?.status!=="failed")return{command:Q,args:[],env:T()};let V=X?.status==="failed"?`Codex ACP bridge install failed. ${X.error??"Restart IdeaWave CLI so it can warm the pinned bridge again."}`:"Codex ACP bridge is not ready. Keep IdeaWave CLI running and retry in a moment.";throw new F(V)},checkReadiness:async()=>{if(!await A(e0))return{status:"not_installed",detail:Z1};let Z=e(Z0);if(Z?.status==="ready")return{status:"ready"};if(Z?.status==="installing")return{status:"not_running",detail:"Installing Codex ACP bridge..."};if(Z?.status==="failed")return{status:"not_running",detail:Z.error??"Codex ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};if(await A($1))return{status:"ready"};return{status:"not_running",detail:"Installing Codex ACP bridge..."}},authHint:"Run `codex login` (or set OPENAI_API_KEY)."};var J1="copilot",Q1="copilot-acp",V1="npm i -g @github/copilot",j1={id:"copilot",displayName:"GitHub Copilot",kind:"registered",resolveSpawnConfig:async()=>{let $=await A(J1);if($)return{command:$,args:["--acp"],env:T()};let Z=await A(Q1);if(Z)return{command:Z,args:[],env:T()};throw new F(`Copilot not installed. Run: ${V1}`)},checkReadiness:async()=>{if(await A(J1))return{status:"ready"};if(await A(Q1))return{status:"ready"};return{status:"not_installed",detail:V1}},authHint:"Run `gh auth login` (or `copilot login`)."};import n2 from"node:fs/promises";function o2($){return $.startsWith("/")||/^[a-zA-Z]:[\\/]/.test($)}async function K1($){if(o2($))try{return await n2.access($),!0}catch{return!1}return await A($)!==null}var W1={id:"custom",displayName:"Custom ACP",kind:"custom",resolveSpawnConfig:async($)=>{if($.kind!=="custom")throw new F("customAdapter received non-custom entry");if(!await K1($.command))throw new F(`custom: command "${$.command}" not found`);return{command:$.command,args:$.args,env:T($.env)}},checkReadiness:async($)=>{if($.kind!=="custom")return{status:"unknown"};return await K1($.command)?{status:"ready"}:{status:"not_installed"}}};var M1="opencode",Y1="Install OpenCode from https://opencode.ai",G1={id:"opencode",displayName:"OpenCode",kind:"registered",resolveSpawnConfig:async()=>{let $=await A(M1);if(!$)throw new F(`OpenCode not installed. ${Y1}`);return{command:$,args:["acp"],env:T()}},checkReadiness:async()=>{if(!await A(M1))return{status:"not_installed",detail:Y1};return{status:"ready"}},authHint:"Run `opencode auth login <provider>` (or set the provider's API-key env var)."};var x1={"claude-code":r0,opencode:G1,codex:X1,copilot:j1};function m($){if($.kind==="custom")return W1;let Z=x1[$.adapterId];if(!Z)throw Error(`Unknown registered adapter: ${$.adapterId}`);return Z}function $$(){return Object.values(x1)}async function z1($){let Z={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},X;try{X=await s2.readFile($,"utf-8")}catch(J){if(J.code==="ENOENT")return structuredClone(Z);throw J}return k$.parse(JSON.parse(X))}async function n($){let Z=$.configPath?await z1($.configPath):await E(),X=$.cardId?Z.cardOverrides[$.cardId]:void 0;if(X?.runtimeConfigId){let Q=Z.runtimes.find((V)=>V.id===X.runtimeConfigId);if(Q)return{entry:Q,adapter:m(Q),runFolder:X.runFolder??Q.runFolder??C$.homedir(),modelId:X.modelId??Q.defaultModelId??null}}let J=Z.boardOverrides[$.boardId];if(J?.runtimeConfigId){let Q=Z.runtimes.find((V)=>V.id===J.runtimeConfigId);if(Q)return{entry:Q,adapter:m(Q),runFolder:J.runFolder??Q.runFolder??C$.homedir(),modelId:J.modelId??Q.defaultModelId??null}}if(Z.globalDefaultConfigId){let Q=Z.runtimes.find((V)=>V.id===Z.globalDefaultConfigId);if(Q)return{entry:Q,adapter:m(Q),runFolder:X?.runFolder??J?.runFolder??Q.runFolder??C$.homedir(),modelId:X?.modelId??J?.modelId??Q.defaultModelId??null}}throw new a}async function D1($,Z={}){let J=(Z.configPath?await z1(Z.configPath):await E()).runtimes.find((Q)=>Q.id===$);if(!J)return null;return{entry:J,adapter:m(J),runFolder:J.runFolder??C$.homedir(),modelId:Z.modelId??J.defaultModelId??null}}var o=new Map,X0=new Set;function J0($){o.get($)?.controller.abort()}function H1($){for(let[Z,X]of o){if(X.frontendSessionId!==$)continue;X.controller.abort(),o.delete(Z)}}function B1(){for(let $ of o.values())$.controller.abort();o.clear()}function U1($,Z){if(!Z.availableModels||Z.availableModels.length===0)return;h((X)=>{let J=X.runtimes.find((Q)=>Q.id===$);if(J)J.discoveredModels=Z.availableModels??[]}).catch(()=>{return})}function t2($,Z){return`${$}
5
5
 
6
6
  Runtime run folder:
7
7
  - Effective run folder: ${Z}
8
8
  - When the user says "my folder", "current folder", or "run folder", they mean this selected runtime folder.
9
9
  - Use list_run_folder and read_run_folder_file for run-folder inspection. Do not use attached context-card tools for this unless the user asks about attached board context.
10
- - Filesystem access is read-only and limited to this folder. Hidden/config folders and outside-folder paths are unavailable.`}async function N1($,Z){let X=Date.now(),J=new AbortController;o.set($.runId,{controller:J,frontendSessionId:$.frontendSessionId}),X0.add($.cardId);let Q=s$($.userId,$.frontendSessionId,$.cardId),V=!1,W=null;try{let K=($.runtimeConfigIdHint?await D1($.runtimeConfigIdHint,{modelId:$.modelHint??null}):null)??await n({boardId:$.boardId,cardId:$.cardId}),M=await K.adapter.resolveSpawnConfig(K.entry),j=$.toolSurface??"full";W=M;let G=T$({userId:$.userId,frontendSessionId:$.frontendSessionId,boardId:$.boardId,toolSurface:j,cardId:$.cardId,runFolder:K.runFolder}),D=G?[G]:[],U=$.modelHint??K.modelId,B=e$({adapterId:K.adapter.id,configId:K.entry.id,modelId:U,mcpUrl:G?.url??null,runFolder:K.runFolder,toolSurface:j}),x=await t$({key:Q,fingerprint:B,open:()=>o$({spawn:{...M,cwd:K.runFolder},mcpServers:D,modelId:U,signal:J.signal})});U1(K.entry.id,x);let Y;try{Y=await x.prompt({runId:$.runId,boardId:$.boardId,cardId:$.cardId,prompt:{systemPrompt:t2($.systemPrompt,K.runFolder),messages:$.promptMessages.map((N)=>({role:N.role,content:N.content}))},signal:J.signal,appendText:async({text:N})=>{Z({type:"partial_text",runId:$.runId,cardId:$.cardId,text:N})},appendToolActivity:async({entry:N})=>{Z({type:"tool_activity",runId:$.runId,cardId:$.cardId,activity:N})}})}catch(N){if(!x.isAlive()||N instanceof F)V=!0;throw N}Z({type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:Y.finalText,model:Y.modelReported??null,latencyMs:Date.now()-X,errorText:null,partialText:null}})}catch(z){let K=z instanceof Error?z.message:"Agent run failed";if(z instanceof F&&W)c$(W,K);console.error(`[ideawave-cli] run ${$.runId} failed:`,K),Z({type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:"",model:null,latencyMs:Date.now()-X,errorText:K,partialText:null}})}finally{r$(Q,V),o.delete($.runId),X0.delete($.cardId)}}async function k1($){if(X0.has($.cardId))return{status:"skipped"};let Z=s$($.userId,$.frontendSessionId,$.cardId),X=null;try{let J=await n({boardId:$.boardId,cardId:$.cardId}),Q=await J.adapter.resolveSpawnConfig(J.entry);X=Q;let V=T$({userId:$.userId,frontendSessionId:$.frontendSessionId,boardId:$.boardId,cardId:$.cardId,runFolder:J.runFolder}),W=V?[V]:[],z=e$({adapterId:J.adapter.id,configId:J.entry.id,modelId:J.modelId,mcpUrl:V?.url??null,runFolder:J.runFolder}),K=new AbortController,M=await t$({key:Z,fingerprint:z,open:()=>o$({spawn:{...Q,cwd:J.runFolder},mcpServers:W,modelId:J.modelId,signal:K.signal})});return U1(J.entry.id,M),r$(Z,!1),console.log(`[ideawave-cli] warmed runtime for card ${$.cardId}`),{status:"ready"}}catch(J){if(J instanceof a)return{status:"skipped"};let Q=J instanceof Error?J.message:String(J);if(J instanceof F&&X)c$(X,Q);if(J instanceof F&&/(not ready|installing|warming|retry in a moment)/i.test(Q))return{status:"retryable",error:Q};return console.warn(`[ideawave-cli] warmup failed for card ${$.cardId}:`,Q),{status:"failed",error:Q}}}import{randomUUID as $3}from"node:crypto";import{createServer as Z3}from"node:http";import{WebSocket as L1,WebSocketServer as X3}from"ws";var Q0="/cli-bridge";function V0($=43275,Z=43277){let X=[];for(let J=$;J<=Z;J+=1)X.push(J);return X}function q1($=V0(),Z="127.0.0.1",X="/cli-bridge"){return $.map((J)=>`ws://${Z}:${J}${X}`)}var r2=new Set(["hello","frontend_hello","cli_status","browser_status","bridge_probe","bridge_probe_ack","bridge_ping","bridge_pong","tool_metadata","run_turn","cancel_run","tool_result","request_tool_metadata","tool_call","partial_text","tool_activity","run_settled","runtime_rpc","runtime_rpc_result","warmup_run","warmup_result"]);function w$($){try{let Z=JSON.parse($);if(Z&&typeof Z==="object"&&typeof Z.type==="string"&&r2.has(Z.type))return Z}catch{}return null}function F$($){return JSON.stringify($)}var e2=800;function P1({candidates:$,createWebSocket:Z,timeoutMs:X=e2,maxConcurrent:J=1,staggerMs:Q=0,setTimeoutFn:V=setTimeout,clearTimeoutFn:W=clearTimeout}){return new Promise((z,K)=>{let M=0,j=!1,G=null,D=new Map,U=Math.max(1,Math.floor(J)),B=()=>{if(G===null)return;W(G),G=null},x=(L)=>{let{socket:k,listeners:_,timer:g}=L;k.removeEventListener("open",_.open),k.removeEventListener("message",_.message),k.removeEventListener("error",_.error),k.removeEventListener("close",_.close),W(g),D.delete(k)},Y=(L)=>{B();for(let k of Array.from(D.values()))if(x(k),k.socket!==L)try{k.socket.close()}catch{}},N=()=>{if(j)return;if(M<$.length)return;if(D.size>0)return;if(G!==null)return;j=!0,K(Error("No IdeaWave CLI bridge is reachable"))},w=(L)=>{if(j)return;if(M>=$.length){N();return}if(D.size>=U)return;if(L<=0){B(),O();return}if(G!==null)return;G=V(()=>{G=null,O()},L)},C=()=>{if(j)return;if(D.size>=U)return;if(D.size===0||Q<=0||U===1){w(0);return}w(Q)},H=(L)=>{if(j)return;let k=D.get(L);if(!k)return;x(k);try{L.close()}catch{}C(),N()};function O(){if(j)return;if(D.size>=U)return;let L=$[M];if(M+=1,!L){N();return}let k;try{k=Z(L)}catch{C(),N();return}let _={open:()=>{if(j||!D.has(k))return;k.send(F$({type:"bridge_probe",protocolVersion:1}))},message:(P)=>{if(j||!D.has(k))return;if(w$(String(P?.data??""))?.type!=="bridge_probe_ack")return;j=!0,Y(k),z({url:L,socket:k})},error:()=>H(k),close:()=>H(k)};k.addEventListener("open",_.open),k.addEventListener("message",_.message),k.addEventListener("error",_.error),k.addEventListener("close",_.close);let g=V(()=>H(k),X);D.set(k,{url:L,socket:k,listeners:_,timer:g}),C()}O()})}var C1=10485760,J3=30000,Q3=15000,V3="http://127.0.0.1";async function O1($=q1(),Z=(X)=>new L1(X,{headers:{origin:V3}})){try{let{url:X,socket:J}=await P1({candidates:$,createWebSocket:Z});try{J.close()}catch{}return X}catch{return null}}function j3($){if(!$)return!1;let Z;try{Z=new URL($)}catch{return!1}if(Z.origin==="https://ideawave.app"||Z.origin==="https://ideawave-app-production.up.railway.app")return!0;if(Z.protocol!=="http:"&&Z.protocol!=="https:")return!1;return Z.hostname==="localhost"||Z.hostname==="127.0.0.1"||Z.hostname==="::1"}function Z$($,Z){if($.readyState!==L1.OPEN)return;try{$.send(F$(Z))}catch{}}function W3($){if(typeof $==="string")return $;if(Buffer.isBuffer($))return $.toString("utf8");if(Array.isArray($))return Buffer.concat($).toString("utf8");return Buffer.from($).toString("utf8")}function K3($){if(typeof $==="string")return $;if(Array.isArray($))return $[0]??null;return null}function w1($,Z,X){$.write(`HTTP/1.1 ${Z} ${X}\r
10
+ - Filesystem access is read-only and limited to this folder. Hidden/config folders and outside-folder paths are unavailable.`}async function N1($,Z){let X=Date.now(),J=new AbortController;o.set($.runId,{controller:J,frontendSessionId:$.frontendSessionId}),X0.add($.cardId);let Q=s$($.userId,$.frontendSessionId,$.cardId),V=!1,K=null;try{let W=($.runtimeConfigIdHint?await D1($.runtimeConfigIdHint,{modelId:$.modelHint??null}):null)??await n({boardId:$.boardId,cardId:$.cardId}),M=await W.adapter.resolveSpawnConfig(W.entry),j=$.toolSurface??"full";K=M;let G=b$({userId:$.userId,frontendSessionId:$.frontendSessionId,boardId:$.boardId,toolSurface:j,cardId:$.cardId,runFolder:W.runFolder}),D=G?[G]:[],U=$.modelHint??W.modelId,B=e$({adapterId:W.adapter.id,configId:W.entry.id,modelId:U,mcpUrl:G?.url??null,runFolder:W.runFolder,toolSurface:j}),x=await t$({key:Q,fingerprint:B,open:()=>o$({spawn:{...M,cwd:W.runFolder},mcpServers:D,modelId:U,signal:J.signal})});U1(W.entry.id,x);let Y;try{Y=await x.prompt({runId:$.runId,boardId:$.boardId,cardId:$.cardId,prompt:{systemPrompt:t2($.systemPrompt,W.runFolder),messages:$.promptMessages.map((N)=>({role:N.role,content:N.content}))},signal:J.signal,appendText:async({text:N})=>{Z({type:"partial_text",runId:$.runId,cardId:$.cardId,text:N})},appendToolActivity:async({entry:N})=>{Z({type:"tool_activity",runId:$.runId,cardId:$.cardId,activity:N})}})}catch(N){if(!x.isAlive()||N instanceof F)V=!0;throw N}Z({type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:Y.finalText,model:Y.modelReported??null,latencyMs:Date.now()-X,errorText:null,partialText:null}})}catch(z){let W=z instanceof Error?z.message:"Agent run failed";if(z instanceof F&&K)c$(K,W);console.error(`[ideawave-cli] run ${$.runId} failed:`,W),Z({type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:"",model:null,latencyMs:Date.now()-X,errorText:W,partialText:null}})}finally{r$(Q,V),o.delete($.runId),X0.delete($.cardId)}}async function k1($){if(X0.has($.cardId))return{status:"skipped"};let Z=s$($.userId,$.frontendSessionId,$.cardId),X=null;try{let J=await n({boardId:$.boardId,cardId:$.cardId}),Q=await J.adapter.resolveSpawnConfig(J.entry);X=Q;let V=b$({userId:$.userId,frontendSessionId:$.frontendSessionId,boardId:$.boardId,cardId:$.cardId,runFolder:J.runFolder}),K=V?[V]:[],z=e$({adapterId:J.adapter.id,configId:J.entry.id,modelId:J.modelId,mcpUrl:V?.url??null,runFolder:J.runFolder}),W=new AbortController,M=await t$({key:Z,fingerprint:z,open:()=>o$({spawn:{...Q,cwd:J.runFolder},mcpServers:K,modelId:J.modelId,signal:W.signal})});return U1(J.entry.id,M),r$(Z,!1),console.log(`[ideawave-cli] warmed runtime for card ${$.cardId}`),{status:"ready"}}catch(J){if(J instanceof a)return{status:"skipped"};let Q=J instanceof Error?J.message:String(J);if(J instanceof F&&X)c$(X,Q);if(J instanceof F&&/(not ready|installing|warming|retry in a moment)/i.test(Q))return{status:"retryable",error:Q};return console.warn(`[ideawave-cli] warmup failed for card ${$.cardId}:`,Q),{status:"failed",error:Q}}}import{randomUUID as $3}from"node:crypto";import{createServer as Z3}from"node:http";import{WebSocket as L1,WebSocketServer as X3}from"ws";var Q0="/cli-bridge";function V0($=43275,Z=43277){let X=[];for(let J=$;J<=Z;J+=1)X.push(J);return X}function q1($=V0(),Z="127.0.0.1",X="/cli-bridge"){return $.map((J)=>`ws://${Z}:${J}${X}`)}var r2=new Set(["hello","frontend_hello","cli_status","browser_status","bridge_probe","bridge_probe_ack","bridge_ping","bridge_pong","tool_metadata","run_turn","cancel_run","tool_result","request_tool_metadata","tool_call","partial_text","tool_activity","run_settled","runtime_rpc","runtime_rpc_result","warmup_run","warmup_result"]);function w$($){try{let Z=JSON.parse($);if(Z&&typeof Z==="object"&&typeof Z.type==="string"&&r2.has(Z.type))return Z}catch{}return null}function F$($){return JSON.stringify($)}var e2=800;function P1({candidates:$,createWebSocket:Z,timeoutMs:X=e2,maxConcurrent:J=1,staggerMs:Q=0,setTimeoutFn:V=setTimeout,clearTimeoutFn:K=clearTimeout}){return new Promise((z,W)=>{let M=0,j=!1,G=null,D=new Map,U=Math.max(1,Math.floor(J)),B=()=>{if(G===null)return;K(G),G=null},x=(L)=>{let{socket:k,listeners:_,timer:g}=L;k.removeEventListener("open",_.open),k.removeEventListener("message",_.message),k.removeEventListener("error",_.error),k.removeEventListener("close",_.close),K(g),D.delete(k)},Y=(L)=>{B();for(let k of Array.from(D.values()))if(x(k),k.socket!==L)try{k.socket.close()}catch{}},N=()=>{if(j)return;if(M<$.length)return;if(D.size>0)return;if(G!==null)return;j=!0,W(Error("No IdeaWave CLI bridge is reachable"))},w=(L)=>{if(j)return;if(M>=$.length){N();return}if(D.size>=U)return;if(L<=0){B(),O();return}if(G!==null)return;G=V(()=>{G=null,O()},L)},C=()=>{if(j)return;if(D.size>=U)return;if(D.size===0||Q<=0||U===1){w(0);return}w(Q)},H=(L)=>{if(j)return;let k=D.get(L);if(!k)return;x(k);try{L.close()}catch{}C(),N()};function O(){if(j)return;if(D.size>=U)return;let L=$[M];if(M+=1,!L){N();return}let k;try{k=Z(L)}catch{C(),N();return}let _={open:()=>{if(j||!D.has(k))return;k.send(F$({type:"bridge_probe",protocolVersion:1}))},message:(P)=>{if(j||!D.has(k))return;if(w$(String(P?.data??""))?.type!=="bridge_probe_ack")return;j=!0,Y(k),z({url:L,socket:k})},error:()=>H(k),close:()=>H(k)};k.addEventListener("open",_.open),k.addEventListener("message",_.message),k.addEventListener("error",_.error),k.addEventListener("close",_.close);let g=V(()=>H(k),X);D.set(k,{url:L,socket:k,listeners:_,timer:g}),C()}O()})}var C1=10485760,J3=30000,Q3=15000,V3="http://127.0.0.1";async function O1($=q1(),Z=(X)=>new L1(X,{headers:{origin:V3}})){try{let{url:X,socket:J}=await P1({candidates:$,createWebSocket:Z});try{J.close()}catch{}return X}catch{return null}}var j3=new Set(["https://ideawave-app-production.up.railway.app"]);function K3($){return $==="ideawave.app"||$.endsWith(".ideawave.app")}function W3(){let $=process.env.IDEAWAVE_CLI_ALLOWED_ORIGINS;if(!$)return M3;let Z=new Set;for(let X of $.split(",")){let J=X.trim();if(!J)continue;try{Z.add(new URL(J).origin)}catch{}}return Z}var M3=new Set;function Y3($){if(!$)return!1;let Z;try{Z=new URL($)}catch{return!1}if(j3.has(Z.origin))return!0;if(W3().has(Z.origin))return!0;if(Z.protocol==="https:"&&K3(Z.hostname))return!0;if(Z.protocol!=="http:"&&Z.protocol!=="https:")return!1;return Z.hostname==="localhost"||Z.hostname==="127.0.0.1"||Z.hostname==="::1"}function Z$($,Z){if($.readyState!==L1.OPEN)return;try{$.send(F$(Z))}catch{}}function G3($){if(typeof $==="string")return $;if(Buffer.isBuffer($))return $.toString("utf8");if(Array.isArray($))return Buffer.concat($).toString("utf8");return Buffer.from($).toString("utf8")}function x3($){if(typeof $==="string")return $;if(Array.isArray($))return $[0]??null;return null}function w1($,Z,X){$.write(`HTTP/1.1 ${Z} ${X}\r
11
11
  Connection: close\r
12
12
  Content-Length: ${Buffer.byteLength(X)}\r
13
13
  \r
14
- ${X}`),$.destroy()}function M3($,Z){return new Promise((X,J)=>{let Q=(W)=>{$.off("listening",V),J(W)},V=()=>{$.off("error",Q);let W=$.address();if(!W||typeof W==="string"){J(Error("Failed to read CLI bridge server address"));return}X(W.port)};$.once("error",Q),$.once("listening",V),$.listen(Z,"127.0.0.1")})}function F1($){return new Promise((Z,X)=>{$.close((J)=>{if(J)X(J);else Z()})})}async function A1($,Z=V0()){let X=new Map,J=new Map,Q=!1,V=(j)=>{let G=J.get(j);if(G)clearTimeout(G);J.delete(j)},W=(j)=>{J.delete(j);let{activeRunIds:G}=$.registry.disconnect(j);$.onDisconnect(j,G)},z=(j,G)=>{let D={type:"cli_status",connected:!0,runtime:$.runtime,mcpReady:$.mcpReady(),error:G};if(j){let U=X.get(j);if(U)Z$(U,D);return}for(let U of X.values())Z$(U,D)},K=(j,G)=>{let D=G.sessionId.trim(),U=G.userId.trim();if(!D||!U){Z$(j,{type:"cli_status",connected:!1,runtime:$.runtime,mcpReady:$.mcpReady(),error:"Missing frontend session or user id"}),j.close();return}V(D);let B=X.get(D);if(B&&B!==j)B.close();j.data.frontendSessionId=D,X.set(D,j),$.registry.register({frontendSessionId:D,userId:U,tools:G.tools,send:(x)=>Z$(j,x)}),z(D),$.onToolMetadata?.(D)},M=(j,G)=>{let D=$.registry.getUserId(j);if(!D)return;switch(G.type){case"bridge_ping":{let U=X.get(j);if(U)Z$(U,{type:"bridge_pong"});break}case"tool_metadata":$.registry.setMetadata(j,G.tools),$.onToolMetadata?.(j);break;case"tool_result":$.registry.handleToolResult(j,G);break;case"run_turn":$.registry.markRunActive(j,G.run.runId,G.run.cardId),$.onRunTurn(j,{...G.run,frontendSessionId:j,userId:D});break;case"cancel_run":if($.registry.ownsRun(j,G.runId))$.onCancelRun(j,G.runId);break;case"runtime_rpc":$.onRuntimeRpc(j,G);break;case"warmup_run":$.onWarmupRun(j,{...G,frontendSessionId:j},D);break;default:break}};for(let j of Z){let G=Z3((B,x)=>{x.writeHead(404,{"content-type":"text/plain"}),x.end("IdeaWave CLI bridge")}),D=new X3({noServer:!0,maxPayload:C1}),U=(B)=>{if(B.idleTimer)clearTimeout(B.idleTimer);B.idleTimer=setTimeout(()=>{B.close()},J3),B.idleTimer.unref?.()};D.on("connection",(B)=>{let x=B;x.data={id:$3(),frontendSessionId:null},x.idleTimer=null,U(x),x.on("ping",()=>U(x)),x.on("pong",()=>U(x)),x.on("message",(Y)=>{U(x);let N=W3(Y);if(N.length>C1)return;let w=w$(N);if(!w)return;let C=x.data.frontendSessionId;if(!C){if(w.type==="bridge_probe")Z$(x,{type:"bridge_probe_ack",protocolVersion:w.protocolVersion});else if(w.type==="frontend_hello")K(x,w);return}M(C,w)}),x.on("close",()=>{if(x.idleTimer)clearTimeout(x.idleTimer);let Y=x.data.frontendSessionId;if(!Y)return;if(X.get(Y)!==x)return;if(X.delete(Y),V(Y),Q)return;J.set(Y,setTimeout(()=>W(Y),Q3))})}),G.on("upgrade",(B,x,Y)=>{if(new URL(B.url??"/","http://127.0.0.1").pathname!==Q0){w1(x,404,"Not Found");return}if(!j3(K3(B.headers.origin))){w1(x,403,"Forbidden");return}D.handleUpgrade(B,x,Y,(w)=>{D.emit("connection",w,B)})});try{let B=await M3(G,j);return{url:`ws://127.0.0.1:${B}${Q0}`,port:B,sendStatus:z,close:async()=>{Q=!0;for(let x of J.values())clearTimeout(x);J.clear();for(let x of D.clients){let Y=x;if(Y.idleTimer)clearTimeout(Y.idleTimer);Y.close()}D.close(),await F1(G).catch(()=>{return})}}}catch(B){if(D.close(),await F1(G).catch(()=>{return}),B?.code==="EADDRINUSE")continue;throw B}}throw Error(`No free IdeaWave CLI bridge port found in ${Z[0]}-${Z.at(-1)}`)}import{Server as w3}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as F3,ListToolsRequestSchema as L3}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as G3}from"node:crypto";import{createServer as x3}from"node:http";import{StreamableHTTPServerTransport as z3}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as T1}from"@modelcontextprotocol/sdk/types.js";var _1=new Set(["127.0.0.1","localhost","[::1]","::1"]);function Y3($){let Z=$.trim();if(Z.length===0)return null;if(Z.startsWith("[")){let V=Z.indexOf("]");if(V===-1)return null;let W=Z.slice(0,V+1),z=Z.slice(V+1);if(z.length===0)return{host:W,port:null};if(!z.startsWith(":"))return null;let K=Number(z.slice(1));if(!Number.isInteger(K)||K<=0||K>65535)return null;return{host:W,port:K}}let X=Z.lastIndexOf(":");if(X===-1)return{host:Z,port:null};let J=Z.slice(X+1),Q=Number(J);if(!Number.isInteger(Q)||Q<=0||Q>65535)return{host:Z,port:null};return{host:Z.slice(0,X),port:Q}}function f1($){return _1.has($)||_1.has($.toLowerCase())}function R1($,Z){let X=$.headers.host;if(typeof X!=="string")return{ok:!1,status:403,reason:"missing-host"};let J=Y3(X);if(!J)return{ok:!1,status:403,reason:"bad-host"};if(!f1(J.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(J.port!==null&&J.port!==Z)return{ok:!1,status:403,reason:"host-port-mismatch"};let Q=$.headers.origin;if(typeof Q==="string"&&Q.length>0){if(Q!=="null"){let V;try{V=new URL(Q)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!f1(V.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var b1="/mcp",D3=43274,y1=16777216,H3=1800000,B3=300000,v1=200,U3=-32700,l=-32600,j0=-32603;function I($,Z,X,J,Q){$.statusCode=Z,$.setHeader("content-type","application/json"),$.end(JSON.stringify({jsonrpc:"2.0",error:{code:X,message:J,...Q?{data:Q}:{}},id:null}))}class W0 extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class K0 extends Error{constructor(){super(`body exceeds ${y1} bytes`);this.name="BodyTooLargeError"}}async function N3($){if($.method&&$.method!=="POST")return;let Z=$.headers["content-type"];if(typeof Z==="string"&&Z.trim().length>0){if(!Z.toLowerCase().includes("application/json"))throw new W0}let X=0,J=[];for await(let V of $){let W=typeof V==="string"?Buffer.from(V):V;if(X+=W.byteLength,X>y1)throw new K0;J.push(W)}if(J.length===0)return;let Q=Buffer.concat(J).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function k3($){if(Array.isArray($))return $.some(T1);return T1($)}function q3($){if(typeof $==="number")return $;let Z=process.env.IDEAWAVE_MCP_PORT;if(Z&&Z.trim().length>0){let X=Number(Z);if(Number.isInteger(X)&&X>=0&&X<65536)return X}return D3}async function P3($,Z){let X=(Q)=>new Promise((V,W)=>{let z=(M)=>{$.off("listening",K),W(M)},K=()=>{$.off("error",z),V()};$.once("error",z),$.once("listening",K),$.listen(Q,"127.0.0.1")});try{await X(Z)}catch(Q){if(Q.code!=="EADDRINUSE"||Z===0)throw Q;console.warn(`[mcp] port ${Z} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await X(0)}let J=$.address();if(J==null||typeof J==="string")throw Error("[mcp] failed to read bound address");return J.port}function C3($,Z){if(Z&&typeof Z==="object"&&!Array.isArray(Z)){let J=Z.params;if(J&&typeof J==="object"&&!Array.isArray(J)){let Q=J.clientInfo;if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let V=Q.name;if(typeof V==="string"&&V.trim().length>0)return V.trim()}}}let X=$.headers["user-agent"];if(typeof X==="string"&&X.trim().length>0)return X.trim();return null}async function E1($){let Z=new Map,X=0;function J(M){let j=Z.get(M);if(j)j.lastActivity=Date.now()}async function Q(M,j){Z.delete(M),await j.transport.close().catch(()=>{return})}async function V(){let M=null,j=1/0;for(let[G,D]of Z)if(D.lastActivity<j)j=D.lastActivity,M=G;if(M!==null){let G=Z.get(M);if(G)console.warn(`[mcp] session cap of ${v1} reached; evicting ${M}`),await Q(M,G)}}let W=setInterval(()=>{let M=Date.now()-H3;for(let[j,G]of Z)if(G.lastActivity<M)console.log(`[mcp] sweeping idle session ${j}`),Q(j,G)},B3);W.unref?.();let z=x3((M,j)=>{(async()=>{let G;try{G=new URL(M.url??"/","http://127.0.0.1").pathname}catch{I(j,400,l,"bad-url");return}if(G!==b1){I(j,404,l,"not-found");return}let D=M.method??"POST";if(D!=="POST"&&D!=="GET"&&D!=="DELETE"){j.setHeader("Allow","GET, POST, DELETE"),I(j,405,l,"method-not-allowed");return}let U=R1(M,X);if(!U.ok){I(j,U.status,l,"forbidden",{reason:U.reason});return}let B=M.headers["mcp-session-id"],x=typeof B==="string"?B:void 0;if(D==="GET"||D==="DELETE"){if(!x||!Z.has(x)){I(j,400,l,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let w=Z.get(x).transport;J(x);try{await w.handleRequest(M,j)}catch(C){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",C),!j.headersSent)I(j,500,j0,"internal")}return}let Y;try{Y=await N3(M)}catch(w){if(w instanceof W0){I(j,415,l,"expected-application-json");return}if(w instanceof K0){I(j,413,l,"body-too-large");return}I(j,400,U3,"invalid-json");return}let N;if(x&&Z.has(x))N=Z.get(x).transport,J(x);else if(!x&&Y!==void 0&&k3(Y)){let w=M.headers["x-ideawave-user-id"],C=typeof w==="string"&&w.trim().length>0?w.trim():null,H=M.headers["x-ideawave-frontend-session-id"],O=typeof H==="string"&&H.trim().length>0?H.trim():null,L=M.headers["x-ideawave-tool-surface"],k=typeof L==="string"&&L.trim()==="read"?"read":"full",_=M.headers["x-ideawave-card-id"],g=typeof _==="string"&&_.trim().length>0?_.trim():null,P=M.headers["x-ideawave-board-id"],R=typeof P==="string"&&P.trim().length>0?P.trim():null,v=M.headers["x-ideawave-run-folder"],s=typeof v==="string"&&v.trim().length>0?v.trim():null,X$=C3(M,Y);if(Z.size>=v1)await V();let R$=null,p=new z3({sessionIdGenerator:()=>G3(),onsessioninitialized:(t)=>{R$=t,Z.set(t,{transport:p,lastActivity:Date.now()})},onsessionclosed:(t)=>{Z.delete(t)}});p.onclose=()=>{if(p.sessionId)Z.delete(p.sessionId)};try{await $.buildServer({userId:C,frontendSessionId:O,boardId:R,toolSurface:k,cardId:g,runFolder:s,clientHint:X$}).connect(p)}catch(t){if(console.error("[mcp] buildServer/connect failed",t),R$)Z.delete(R$);await p.close().catch(()=>{return}),I(j,500,j0,"server-init-failed");return}N=p}else{I(j,400,l,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await N.handleRequest(M,j,Y)}catch(w){if(console.error("[mcp] transport.handleRequest threw",w),!j.headersSent)I(j,500,j0,"internal")}})().catch((G)=>{console.error("[mcp] unhandled request handler error:",G)})});return X=await P3(z,q3($.port)),{url:`http://127.0.0.1:${X}${b1}`,port:X,close:async()=>{clearInterval(W);for(let M of Z.values())await M.transport.close().catch(()=>{return});Z.clear(),await new Promise((M)=>z.close(()=>M()))}}}var O3={name:"ideawave-board",version:"1.0.0"},L$="list_run_folder",O$="read_run_folder_file",m1=new Set(["list_boards","get_board","list_nodes","list_edges","inspect_node","list_context_sources","read_context_card","read_context_file","list_context_folder","get_board_wiki","search_board","get_card_messages","list_agent_cards","inspect_neighbors",L$,O$]),A3=[{name:L$,description:"List visible files and folders under the selected runtime run folder. Hidden/config folders are omitted.",inputSchema:{type:"object",properties:{path:{type:"string",description:"Optional relative path inside the selected run folder. Defaults to the run-folder root."}},additionalProperties:!1}},{name:O$,description:"Read a text file inside the selected runtime run folder. Hidden/config paths and outside-folder paths are denied.",inputSchema:{type:"object",properties:{path:{type:"string",description:"Relative path to a text file inside the selected run folder."}},required:["path"],additionalProperties:!1}}];function M0($){return{content:[{type:"text",text:$}]}}function _3($){return M0(JSON.stringify($,null,2))}function I1($){return{...M0($),isError:!0}}function f3($,Z,X="full"){return $.getMetadata(Z).filter((J)=>X!=="read"||m1.has(J.name)).map((J)=>({name:J.name,description:J.description,inputSchema:J.inputSchema}))}function R3($,Z,X={}){let J=f3($,Z,X.toolSurface??"full");return X.includeRunFolderTools?[...J,...A3]:J}function g1($,Z){if(!$||typeof $!=="object"||Array.isArray($))return null;let X=$[Z];return typeof X==="string"?X:null}async function T3($,Z,X){if(X&&X.trim().length>0)return X.trim();if(!$||!Z)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await n({boardId:$,cardId:Z})).runFolder}async function b3($){let Z=await T3($.boardId,$.cardId,$.runFolder);if($.name===L$){let X=g1($.args,"path")??"",J=await T0(Z,X);return _3(J)}if($.name===O$){let X=g1($.args,"path");if(!X)return I1("read_run_folder_file requires a path.");return M0(await U$(Z,X))}return I1(`Unknown local tool "${$.name}"`)}function v3($,Z,X,J,Q,V="full"){let W=new w3(O3,{capabilities:{tools:{}}});return W.setRequestHandler(L3,async()=>({tools:R3($,Z,{includeRunFolderTools:Boolean(Q||X&&J),toolSurface:V})})),W.setRequestHandler(F3,async(z)=>{let{name:K,arguments:M}=z.params;try{if(K===L$||K===O$)return await b3({name:K,args:M,boardId:X,cardId:J,runFolder:Q});if(V==="read"&&!m1.has(K))throw Error(`Tool "${K}" is not available in read-only mode`);let j=await $.callTool(Z,K,M??{},void 0,J??void 0);if(j&&typeof j==="object"&&Array.isArray(j.content))return j;return{content:[{type:"text",text:typeof j==="string"?j:JSON.stringify(j)}]}}catch(j){return{content:[{type:"text",text:j instanceof Error?j.message:"Tool call failed"}],isError:!0}}}),W}function h1($,Z){return E1({buildServer:(X)=>v3($,X.frontendSessionId,X.boardId,X.cardId,X.runFolder,X.toolSurface),port:Z})}import _$ from"node:fs/promises";import G0 from"node:os";import f$ from"node:path";var S1=new Map,Y0=new Map,y3=30000;function A$($,Z){let X=S1.get($);if(X&&X.expiresAt>Date.now())return Promise.resolve(X.value);let J=Y0.get($);if(J)return J;let Q=Z().then((V)=>{return S1.set($,{value:V,expiresAt:Date.now()+y3}),V}).finally(()=>{Y0.delete($)});return Y0.set($,Q),Q}async function c1($){let Z=await Promise.all($$().map((V)=>A$(V.id,async()=>({adapterId:V.id,...await V.checkReadiness({id:"__probe__",kind:"registered",adapterId:V.id,displayName:V.displayName,runFolder:null,defaultModelId:null,discoveredModels:[],discoveredAt:null})})))),J=(await E($)).runtimes.filter((V)=>V.kind==="custom"),Q=await Promise.all(J.map((V)=>A$(`custom:${V.id}`,async()=>({adapterId:V.id,...await h(V).checkReadiness(V)}))));return[...Z,...Q]}async function l1($,Z){let X=$$().find((V)=>V.id===$);if(X)return A$(X.id,async()=>({adapterId:X.id,...await X.checkReadiness({id:"__probe__",kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,discoveredModels:[],discoveredAt:null})}));let Q=(await E(Z)).runtimes.find((V)=>V.id===$);if(!Q||Q.kind!=="custom")return null;return A$(`custom:${Q.id}`,async()=>({adapterId:Q.id,...await h(Q).checkReadiness(Q)}))}function u1(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function E3(){let[$,Z]=await Promise.all([E(),c1()]),X=$.globalDefaultConfigId?$.runtimes.find((J)=>J.id===$.globalDefaultConfigId)??null:null;return{runtimes:$.runtimes,globalDefaultConfigId:$.globalDefaultConfigId,globalDefaultEffective:X?{runFolder:X.runFolder??G0.homedir(),modelId:X.defaultModelId??null}:null,knownAdapters:$$().map((J)=>({id:J.id,displayName:J.displayName})),readiness:Z}}async function I3($){try{let Z=await n({boardId:$.boardId,cardId:$.cardId});return{resolved:{configId:Z.entry.id,adapterId:Z.entry.kind==="registered"?Z.entry.adapterId:null,displayName:Z.entry.displayName,runFolder:Z.runFolder,modelId:Z.modelId}}}catch(Z){if(Z instanceof a)return{resolved:null};throw Z}}async function g3($){return m((Z)=>{let X=Z.runtimes.find((V)=>V.kind==="registered"&&V.adapterId===$.adapterId);if(X)return X;let J=$$().find((V)=>V.id===$.adapterId);if(!J)throw Error(`Unknown adapterId: ${$.adapterId}`);let Q={id:u1(),kind:"registered",adapterId:$.adapterId,displayName:J.displayName,runFolder:null,defaultModelId:null,discoveredModels:[],discoveredAt:null};return Z.runtimes.push(Q),Q})}async function m3($){return m((Z)=>{let X={id:u1(),kind:"custom",displayName:$.displayName,command:$.command,args:$.args,env:$.env,runFolder:$.runFolder,defaultModelId:null,discoveredModels:[],discoveredAt:null};return Z.runtimes.push(X),X})}async function h3($){await m((Z)=>{if(Z.runtimes=Z.runtimes.filter((X)=>X.id!==$.runtimeConfigId),Z.globalDefaultConfigId===$.runtimeConfigId)Z.globalDefaultConfigId=null;for(let X of Object.keys(Z.boardOverrides))if(Z.boardOverrides[X].runtimeConfigId===$.runtimeConfigId)delete Z.boardOverrides[X];for(let X of Object.keys(Z.cardOverrides))if(Z.cardOverrides[X].runtimeConfigId===$.runtimeConfigId)delete Z.cardOverrides[X]})}async function S3($){await m((Z)=>{let X=Z.runtimes.find((J)=>J.id===$.runtimeConfigId);if(!X)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);if(Z.globalDefaultConfigId=$.runtimeConfigId,$.runFolder!==void 0)X.runFolder=$.runFolder;if($.modelId!==void 0)X.defaultModelId=$.modelId})}async function c3($){$.boardId,await m((Z)=>{if($.runtimeConfigId===null){delete Z.cardOverrides[$.cardId];return}if(!Z.runtimes.some((Q)=>Q.id===$.runtimeConfigId))throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=Z.cardOverrides[$.cardId];Z.cardOverrides[$.cardId]={runtimeConfigId:$.runtimeConfigId,runFolder:$.runFolder!==void 0?$.runFolder:J?.runFolder??null,modelId:$.modelId!==void 0?$.modelId:J?.modelId??null}})}async function l3($){let X=(await E()).runtimes.find((W)=>W.id===$.runtimeConfigId);if(!X)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=h(X),Q=await J.resolveSpawnConfig(X),V=X.runFolder??G0.homedir();try{let W=await p0({spawn:{...Q,cwd:V}}),z=new Date().toISOString();return await m((K)=>{let M=K.runtimes.find((j)=>j.id===$.runtimeConfigId);if(M)M.discoveredModels=W.models,M.discoveredAt=z}),{ok:!0,models:W.models,currentModelId:W.currentModelId}}catch(W){if(W instanceof r)throw Error(`${W.message}${J.authHint?` ${J.authHint}`:""}`);if(W instanceof F||W instanceof i)throw Error(W.message);throw W}}async function u3($){let Z=G0.homedir(),X=$.path?.trim()?$.path.trim():Z,J=f$.resolve(X),Q=!0;try{if(!(await _$.stat(J)).isDirectory())J=f$.dirname(J)}catch{Q=!1,J=Z}let V=[];try{V=(await _$.readdir(J,{withFileTypes:!0})).filter((K)=>K.isDirectory()&&!K.name.startsWith(".")).map((K)=>({name:K.name,path:f$.join(J,K.name)})).sort((K,M)=>K.name.localeCompare(M.name))}catch{V=[]}let W=f$.dirname(J);return{path:J,parent:W===J?null:W,home:Z,exists:Q,entries:V}}var p1={list:E3,getEffectiveForCard:I3,registerRegistered:g3,registerCustom:m3,unregister:h3,setUserDefault:S3,setCardOverride:c3,refreshModels:l3,browseFolder:u3};var p3=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function a3(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function a1(){try{let $=await E();if($.globalDefaultConfigId){if($.runtimes.some((X)=>X.id===$.globalDefaultConfigId))return $.globalDefaultConfigId}for(let Z of p3){if((await l1(Z.id))?.status!=="ready")continue;let J=null;if(await m((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((z)=>z.id===Q.globalDefaultConfigId)){J=Q.globalDefaultConfigId;return}}let V=Q.runtimes.find((W)=>W.kind==="registered"&&W.adapterId===Z.id);if(!V){let W={id:a3(),kind:"registered",adapterId:Z.id,displayName:Z.displayName,runFolder:null,defaultModelId:null,discoveredModels:[],discoveredAt:null};Q.runtimes.push(W),V=W}Q.globalDefaultConfigId=V.id,J=V.id}),J)return console.log(`[ideawave-cli] using agent runtime: ${Z.displayName}`),J}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch($){return console.warn("[ideawave-cli] runtime auto-seed failed",$),null}}function i3(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class x0{sessions=new Map;createCallId;toolCallTimeoutMs;constructor($={}){this.createCallId=$.createCallId??i3,this.toolCallTimeoutMs=$.toolCallTimeoutMs??120000}register($){let Z=this.sessions.get($.frontendSessionId);if(Z){if(Z.userId!==$.userId)this.rejectPending(Z,"frontend session user changed"),Z.activeRunIds.clear();this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:Z.pendingToolCalls,activeRunIds:Z.activeRunIds,activeRunCardIds:Z.activeRunCardIds});return}this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect($,Z="frontend session disconnected"){let X=this.sessions.get($);if(!X)return{activeRunIds:[]};return this.sessions.delete($),this.rejectPending(X,Z),{activeRunIds:Array.from(X.activeRunIds)}}sessionCount(){return this.sessions.size}has($){return this.sessions.has($)}getUserId($){return this.sessions.get($)?.userId??null}setMetadata($,Z){let X=this.sessions.get($);if(X)X.tools=Z}getMetadata($){if(!$)return[];return this.sessions.get($)?.tools??[]}sendToSession($,Z){let X=this.sessions.get($);if(!X)return!1;return X.send(Z),!0}callTool($,Z,X,J,Q){if(!$)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let V=this.sessions.get($);if(!V)return Promise.reject(Error(`Frontend session ${$} is not connected`));let W=this.createCallId();return new Promise((z,K)=>{let M=setTimeout(()=>{V.pendingToolCalls.delete(W),K(Error(`Tool "${Z}" timed out waiting for the frontend`))},this.toolCallTimeoutMs),j=J??(Q?this.getActiveRunIdForCard(V,Q):this.getSoleActiveRunId(V)),G=Q??(j?V.activeRunCardIds.get(j):void 0);V.pendingToolCalls.set(W,{resolve:z,reject:K,timer:M}),V.send({type:"tool_call",callId:W,name:Z,args:X,...j?{runId:j}:{},...G?{cardId:G}:{}})})}handleToolResult($,Z){let X=this.sessions.get($);if(!X)return;let J=X.pendingToolCalls.get(Z.callId);if(!J)return;if(X.pendingToolCalls.delete(Z.callId),clearTimeout(J.timer),Z.ok)J.resolve(Z.result);else J.reject(Error(Z.error??"Tool execution failed"))}markRunActive($,Z,X){let J=this.sessions.get($);if(!J)return;if(J.activeRunIds.add(Z),X)J.activeRunCardIds.set(Z,X)}markRunSettled($,Z){let X=this.sessions.get($);if(!X)return;X.activeRunIds.delete(Z),X.activeRunCardIds.delete(Z)}ownsRun($,Z){return this.sessions.get($)?.activeRunIds.has(Z)??!1}rejectPending($,Z){for(let X of $.pendingToolCalls.values())clearTimeout(X.timer),X.reject(Error(Z));$.pendingToolCalls.clear()}getSoleActiveRunId($){return $.activeRunIds.size===1?$.activeRunIds.values().next().value:void 0}getActiveRunIdForCard($,Z){let X=[...$.activeRunCardIds.entries()].filter(([J,Q])=>$.activeRunIds.has(J)&&Q===Z).map(([J])=>J);return X.length===1?X[0]:void 0}}function d3(){return"0.0.28".trim()?"0.0.28":"dev"}var u=process.argv[2];if(u==="--help"||u==="-h"||u==="help")console.log("ideawave — host the local bridge for a running ideawave.app session."),console.log(""),console.log("Usage:"),console.log(" ideawave Serve the browser bridge and MCP forwarder."),console.log(" ideawave --version Print the CLI version."),process.exit(0);if(u==="--version"||u==="-v"||u==="version")console.log(d3()),process.exit(0);if(u)console.error(`Unknown command: ${u}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var M$=new x0,x$=null;function Y$($,Z){M$.sendToSession($,Z)}async function n3($,Z){try{let X=p1[Z.method],J=await X(Z.params);Y$($,{type:"runtime_rpc_result",requestId:Z.requestId,ok:!0,result:J})}catch(X){Y$($,{type:"runtime_rpc_result",requestId:Z.requestId,ok:!1,error:X instanceof Error?X.message:String(X)})}}var G$=!1,K$=null;async function z0(){if(G$)return;if(K$)return K$;return K$=(async()=>{try{let $=await h1(M$);U0({...$,requestedPort:$.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${$.url}`);try{let Z=await _0();for(let X of Z)if(X.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${X.packageName}: ${X.error??"unknown error"}`)}catch(Z){console.warn("[ideawave-cli] ACP bridge setup skipped:",Z instanceof Error?Z.message:String(Z))}await a1(),G$=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),x$?.sendStatus()}catch($){console.error("[ideawave-cli] failed to start agent host:",$),x$?.sendStatus(void 0,$ instanceof Error?$.message:String($))}finally{K$=null}})(),K$}if(process.env.APP_ENV!=="development"){let $=await O1();if($)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${$}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}x$=await A1({registry:M$,runtime:null,mcpReady:()=>G$,onToolMetadata:($)=>{console.log(`[ideawave-cli] session ${$} advertised ${M$.getMetadata($).length} tools`),z0()},onRunTurn:($,Z)=>{console.log(`[ideawave-cli] running agent turn for card ${Z.cardId} (session ${$})`),(async()=>{if(await z0(),!G$){Y$($,{type:"run_settled",runId:Z.runId,cardId:Z.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await N1(Z,(X)=>Y$($,X))})().catch(()=>{return}).finally(()=>M$.markRunSettled($,Z.runId))},onCancelRun:($,Z)=>{J0(Z)},onRuntimeRpc:($,Z)=>{n3($,Z)},onWarmupRun:($,Z,X)=>{(async()=>{if(await z0(),!G$)return{status:"retryable",error:"agent host is not ready"};return k1({cardId:Z.cardId,boardId:Z.boardId,userId:X,frontendSessionId:$})})().then((J)=>{if(!Z.warmupId)return;Y$($,{type:"warmup_result",warmupId:Z.warmupId,cardId:Z.cardId,...J})})},onDisconnect:($,Z)=>{H1($);for(let X of Z)J0(X);console.log(`[ideawave-cli] browser session ${$} disconnected`)}});console.log(`[ideawave-cli] browser bridge listening on ${x$.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var i1=!1;for(let $ of["SIGINT","SIGTERM"])process.once($,()=>{if(i1)return;i1=!0,B1(),(async()=>{await x$?.close().catch(()=>{return}),process.exit(0)})()});
14
+ ${X}`),$.destroy()}function z3($,Z){return new Promise((X,J)=>{let Q=(K)=>{$.off("listening",V),J(K)},V=()=>{$.off("error",Q);let K=$.address();if(!K||typeof K==="string"){J(Error("Failed to read CLI bridge server address"));return}X(K.port)};$.once("error",Q),$.once("listening",V),$.listen(Z,"127.0.0.1")})}function F1($){return new Promise((Z,X)=>{$.close((J)=>{if(J)X(J);else Z()})})}async function A1($,Z=V0()){let X=new Map,J=new Map,Q=!1,V=(j)=>{let G=J.get(j);if(G)clearTimeout(G);J.delete(j)},K=(j)=>{J.delete(j);let{activeRunIds:G}=$.registry.disconnect(j);$.onDisconnect(j,G)},z=(j,G)=>{let D={type:"cli_status",connected:!0,runtime:$.runtime,mcpReady:$.mcpReady(),error:G};if(j){let U=X.get(j);if(U)Z$(U,D);return}for(let U of X.values())Z$(U,D)},W=(j,G)=>{let D=G.sessionId.trim(),U=G.userId.trim();if(!D||!U){Z$(j,{type:"cli_status",connected:!1,runtime:$.runtime,mcpReady:$.mcpReady(),error:"Missing frontend session or user id"}),j.close();return}V(D);let B=X.get(D);if(B&&B!==j)B.close();j.data.frontendSessionId=D,X.set(D,j),$.registry.register({frontendSessionId:D,userId:U,tools:G.tools,send:(x)=>Z$(j,x)}),z(D),$.onToolMetadata?.(D)},M=(j,G)=>{let D=$.registry.getUserId(j);if(!D)return;switch(G.type){case"bridge_ping":{let U=X.get(j);if(U)Z$(U,{type:"bridge_pong"});break}case"tool_metadata":$.registry.setMetadata(j,G.tools),$.onToolMetadata?.(j);break;case"tool_result":$.registry.handleToolResult(j,G);break;case"run_turn":$.registry.markRunActive(j,G.run.runId,G.run.cardId),$.onRunTurn(j,{...G.run,frontendSessionId:j,userId:D});break;case"cancel_run":if($.registry.ownsRun(j,G.runId))$.onCancelRun(j,G.runId);break;case"runtime_rpc":$.onRuntimeRpc(j,G);break;case"warmup_run":$.onWarmupRun(j,{...G,frontendSessionId:j},D);break;default:break}};for(let j of Z){let G=Z3((B,x)=>{x.writeHead(404,{"content-type":"text/plain"}),x.end("IdeaWave CLI bridge")}),D=new X3({noServer:!0,maxPayload:C1}),U=(B)=>{if(B.idleTimer)clearTimeout(B.idleTimer);B.idleTimer=setTimeout(()=>{B.close()},J3),B.idleTimer.unref?.()};D.on("connection",(B)=>{let x=B;x.data={id:$3(),frontendSessionId:null},x.idleTimer=null,U(x),x.on("ping",()=>U(x)),x.on("pong",()=>U(x)),x.on("message",(Y)=>{U(x);let N=G3(Y);if(N.length>C1)return;let w=w$(N);if(!w)return;let C=x.data.frontendSessionId;if(!C){if(w.type==="bridge_probe")Z$(x,{type:"bridge_probe_ack",protocolVersion:w.protocolVersion});else if(w.type==="frontend_hello")W(x,w);return}M(C,w)}),x.on("close",()=>{if(x.idleTimer)clearTimeout(x.idleTimer);let Y=x.data.frontendSessionId;if(!Y)return;if(X.get(Y)!==x)return;if(X.delete(Y),V(Y),Q)return;J.set(Y,setTimeout(()=>K(Y),Q3))})}),G.on("upgrade",(B,x,Y)=>{if(new URL(B.url??"/","http://127.0.0.1").pathname!==Q0){w1(x,404,"Not Found");return}if(!Y3(x3(B.headers.origin))){w1(x,403,"Forbidden");return}D.handleUpgrade(B,x,Y,(w)=>{D.emit("connection",w,B)})});try{let B=await z3(G,j);return{url:`ws://127.0.0.1:${B}${Q0}`,port:B,sendStatus:z,close:async()=>{Q=!0;for(let x of J.values())clearTimeout(x);J.clear();for(let x of D.clients){let Y=x;if(Y.idleTimer)clearTimeout(Y.idleTimer);Y.close()}D.close(),await F1(G).catch(()=>{return})}}}catch(B){if(D.close(),await F1(G).catch(()=>{return}),B?.code==="EADDRINUSE")continue;throw B}}throw Error(`No free IdeaWave CLI bridge port found in ${Z[0]}-${Z.at(-1)}`)}import{Server as A3}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as _3,ListToolsRequestSchema as f3}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as H3}from"node:crypto";import{createServer as B3}from"node:http";import{StreamableHTTPServerTransport as U3}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as b1}from"@modelcontextprotocol/sdk/types.js";var _1=new Set(["127.0.0.1","localhost","[::1]","::1"]);function D3($){let Z=$.trim();if(Z.length===0)return null;if(Z.startsWith("[")){let V=Z.indexOf("]");if(V===-1)return null;let K=Z.slice(0,V+1),z=Z.slice(V+1);if(z.length===0)return{host:K,port:null};if(!z.startsWith(":"))return null;let W=Number(z.slice(1));if(!Number.isInteger(W)||W<=0||W>65535)return null;return{host:K,port:W}}let X=Z.lastIndexOf(":");if(X===-1)return{host:Z,port:null};let J=Z.slice(X+1),Q=Number(J);if(!Number.isInteger(Q)||Q<=0||Q>65535)return{host:Z,port:null};return{host:Z.slice(0,X),port:Q}}function f1($){return _1.has($)||_1.has($.toLowerCase())}function R1($,Z){let X=$.headers.host;if(typeof X!=="string")return{ok:!1,status:403,reason:"missing-host"};let J=D3(X);if(!J)return{ok:!1,status:403,reason:"bad-host"};if(!f1(J.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(J.port!==null&&J.port!==Z)return{ok:!1,status:403,reason:"host-port-mismatch"};let Q=$.headers.origin;if(typeof Q==="string"&&Q.length>0){if(Q!=="null"){let V;try{V=new URL(Q)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!f1(V.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var T1="/mcp",N3=43274,y1=16777216,k3=1800000,q3=300000,v1=200,P3=-32700,l=-32600,j0=-32603;function I($,Z,X,J,Q){$.statusCode=Z,$.setHeader("content-type","application/json"),$.end(JSON.stringify({jsonrpc:"2.0",error:{code:X,message:J,...Q?{data:Q}:{}},id:null}))}class K0 extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class W0 extends Error{constructor(){super(`body exceeds ${y1} bytes`);this.name="BodyTooLargeError"}}async function C3($){if($.method&&$.method!=="POST")return;let Z=$.headers["content-type"];if(typeof Z==="string"&&Z.trim().length>0){if(!Z.toLowerCase().includes("application/json"))throw new K0}let X=0,J=[];for await(let V of $){let K=typeof V==="string"?Buffer.from(V):V;if(X+=K.byteLength,X>y1)throw new W0;J.push(K)}if(J.length===0)return;let Q=Buffer.concat(J).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function w3($){if(Array.isArray($))return $.some(b1);return b1($)}function F3($){if(typeof $==="number")return $;let Z=process.env.IDEAWAVE_MCP_PORT;if(Z&&Z.trim().length>0){let X=Number(Z);if(Number.isInteger(X)&&X>=0&&X<65536)return X}return N3}async function L3($,Z){let X=(Q)=>new Promise((V,K)=>{let z=(M)=>{$.off("listening",W),K(M)},W=()=>{$.off("error",z),V()};$.once("error",z),$.once("listening",W),$.listen(Q,"127.0.0.1")});try{await X(Z)}catch(Q){if(Q.code!=="EADDRINUSE"||Z===0)throw Q;console.warn(`[mcp] port ${Z} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await X(0)}let J=$.address();if(J==null||typeof J==="string")throw Error("[mcp] failed to read bound address");return J.port}function O3($,Z){if(Z&&typeof Z==="object"&&!Array.isArray(Z)){let J=Z.params;if(J&&typeof J==="object"&&!Array.isArray(J)){let Q=J.clientInfo;if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let V=Q.name;if(typeof V==="string"&&V.trim().length>0)return V.trim()}}}let X=$.headers["user-agent"];if(typeof X==="string"&&X.trim().length>0)return X.trim();return null}async function E1($){let Z=new Map,X=0;function J(M){let j=Z.get(M);if(j)j.lastActivity=Date.now()}async function Q(M,j){Z.delete(M),await j.transport.close().catch(()=>{return})}async function V(){let M=null,j=1/0;for(let[G,D]of Z)if(D.lastActivity<j)j=D.lastActivity,M=G;if(M!==null){let G=Z.get(M);if(G)console.warn(`[mcp] session cap of ${v1} reached; evicting ${M}`),await Q(M,G)}}let K=setInterval(()=>{let M=Date.now()-k3;for(let[j,G]of Z)if(G.lastActivity<M)console.log(`[mcp] sweeping idle session ${j}`),Q(j,G)},q3);K.unref?.();let z=B3((M,j)=>{(async()=>{let G;try{G=new URL(M.url??"/","http://127.0.0.1").pathname}catch{I(j,400,l,"bad-url");return}if(G!==T1){I(j,404,l,"not-found");return}let D=M.method??"POST";if(D!=="POST"&&D!=="GET"&&D!=="DELETE"){j.setHeader("Allow","GET, POST, DELETE"),I(j,405,l,"method-not-allowed");return}let U=R1(M,X);if(!U.ok){I(j,U.status,l,"forbidden",{reason:U.reason});return}let B=M.headers["mcp-session-id"],x=typeof B==="string"?B:void 0;if(D==="GET"||D==="DELETE"){if(!x||!Z.has(x)){I(j,400,l,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let w=Z.get(x).transport;J(x);try{await w.handleRequest(M,j)}catch(C){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",C),!j.headersSent)I(j,500,j0,"internal")}return}let Y;try{Y=await C3(M)}catch(w){if(w instanceof K0){I(j,415,l,"expected-application-json");return}if(w instanceof W0){I(j,413,l,"body-too-large");return}I(j,400,P3,"invalid-json");return}let N;if(x&&Z.has(x))N=Z.get(x).transport,J(x);else if(!x&&Y!==void 0&&w3(Y)){let w=M.headers["x-ideawave-user-id"],C=typeof w==="string"&&w.trim().length>0?w.trim():null,H=M.headers["x-ideawave-frontend-session-id"],O=typeof H==="string"&&H.trim().length>0?H.trim():null,L=M.headers["x-ideawave-tool-surface"],k=typeof L==="string"&&L.trim()==="read"?"read":"full",_=M.headers["x-ideawave-card-id"],g=typeof _==="string"&&_.trim().length>0?_.trim():null,P=M.headers["x-ideawave-board-id"],R=typeof P==="string"&&P.trim().length>0?P.trim():null,v=M.headers["x-ideawave-run-folder"],s=typeof v==="string"&&v.trim().length>0?v.trim():null,X$=O3(M,Y);if(Z.size>=v1)await V();let R$=null,p=new U3({sessionIdGenerator:()=>H3(),onsessioninitialized:(t)=>{R$=t,Z.set(t,{transport:p,lastActivity:Date.now()})},onsessionclosed:(t)=>{Z.delete(t)}});p.onclose=()=>{if(p.sessionId)Z.delete(p.sessionId)};try{await $.buildServer({userId:C,frontendSessionId:O,boardId:R,toolSurface:k,cardId:g,runFolder:s,clientHint:X$}).connect(p)}catch(t){if(console.error("[mcp] buildServer/connect failed",t),R$)Z.delete(R$);await p.close().catch(()=>{return}),I(j,500,j0,"server-init-failed");return}N=p}else{I(j,400,l,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await N.handleRequest(M,j,Y)}catch(w){if(console.error("[mcp] transport.handleRequest threw",w),!j.headersSent)I(j,500,j0,"internal")}})().catch((G)=>{console.error("[mcp] unhandled request handler error:",G)})});return X=await L3(z,F3($.port)),{url:`http://127.0.0.1:${X}${T1}`,port:X,close:async()=>{clearInterval(K);for(let M of Z.values())await M.transport.close().catch(()=>{return});Z.clear(),await new Promise((M)=>z.close(()=>M()))}}}var R3={name:"ideawave-board",version:"1.0.0"},L$="list_run_folder",O$="read_run_folder_file",h1=new Set(["list_boards","get_board","list_nodes","list_edges","inspect_node","list_context_sources","read_context_card","read_context_file","list_context_folder","get_board_wiki","search_board","get_card_messages","list_agent_cards","inspect_neighbors",L$,O$]),b3=[{name:L$,description:"List visible files and folders under the selected runtime run folder. Hidden/config folders are omitted.",inputSchema:{type:"object",properties:{path:{type:"string",description:"Optional relative path inside the selected run folder. Defaults to the run-folder root."}},additionalProperties:!1}},{name:O$,description:"Read a text file inside the selected runtime run folder. Hidden/config paths and outside-folder paths are denied.",inputSchema:{type:"object",properties:{path:{type:"string",description:"Relative path to a text file inside the selected run folder."}},required:["path"],additionalProperties:!1}}];function M0($){return{content:[{type:"text",text:$}]}}function T3($){return M0(JSON.stringify($,null,2))}function I1($){return{...M0($),isError:!0}}function v3($,Z,X="full"){return $.getMetadata(Z).filter((J)=>X!=="read"||h1.has(J.name)).map((J)=>({name:J.name,description:J.description,inputSchema:J.inputSchema}))}function y3($,Z,X={}){let J=v3($,Z,X.toolSurface??"full");return X.includeRunFolderTools?[...J,...b3]:J}function g1($,Z){if(!$||typeof $!=="object"||Array.isArray($))return null;let X=$[Z];return typeof X==="string"?X:null}async function E3($,Z,X){if(X&&X.trim().length>0)return X.trim();if(!$||!Z)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await n({boardId:$,cardId:Z})).runFolder}async function I3($){let Z=await E3($.boardId,$.cardId,$.runFolder);if($.name===L$){let X=g1($.args,"path")??"",J=await b0(Z,X);return T3(J)}if($.name===O$){let X=g1($.args,"path");if(!X)return I1("read_run_folder_file requires a path.");return M0(await U$(Z,X))}return I1(`Unknown local tool "${$.name}"`)}function g3($,Z,X,J,Q,V="full"){let K=new A3(R3,{capabilities:{tools:{}}});return K.setRequestHandler(f3,async()=>({tools:y3($,Z,{includeRunFolderTools:Boolean(Q||X&&J),toolSurface:V})})),K.setRequestHandler(_3,async(z)=>{let{name:W,arguments:M}=z.params;try{if(W===L$||W===O$)return await I3({name:W,args:M,boardId:X,cardId:J,runFolder:Q});if(V==="read"&&!h1.has(W))throw Error(`Tool "${W}" is not available in read-only mode`);let j=await $.callTool(Z,W,M??{},void 0,J??void 0);if(j&&typeof j==="object"&&Array.isArray(j.content))return j;return{content:[{type:"text",text:typeof j==="string"?j:JSON.stringify(j)}]}}catch(j){return{content:[{type:"text",text:j instanceof Error?j.message:"Tool call failed"}],isError:!0}}}),K}function m1($,Z){return E1({buildServer:(X)=>g3($,X.frontendSessionId,X.boardId,X.cardId,X.runFolder,X.toolSurface),port:Z})}import _$ from"node:fs/promises";import G0 from"node:os";import f$ from"node:path";var S1=new Map,Y0=new Map,h3=30000;function A$($,Z){let X=S1.get($);if(X&&X.expiresAt>Date.now())return Promise.resolve(X.value);let J=Y0.get($);if(J)return J;let Q=Z().then((V)=>{return S1.set($,{value:V,expiresAt:Date.now()+h3}),V}).finally(()=>{Y0.delete($)});return Y0.set($,Q),Q}async function c1($){let Z=await Promise.all($$().map((V)=>A$(V.id,async()=>({adapterId:V.id,...await V.checkReadiness({id:"__probe__",kind:"registered",adapterId:V.id,displayName:V.displayName,runFolder:null,defaultModelId:null,discoveredModels:[],discoveredAt:null})})))),J=(await E($)).runtimes.filter((V)=>V.kind==="custom"),Q=await Promise.all(J.map((V)=>A$(`custom:${V.id}`,async()=>({adapterId:V.id,...await m(V).checkReadiness(V)}))));return[...Z,...Q]}async function l1($,Z){let X=$$().find((V)=>V.id===$);if(X)return A$(X.id,async()=>({adapterId:X.id,...await X.checkReadiness({id:"__probe__",kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,discoveredModels:[],discoveredAt:null})}));let Q=(await E(Z)).runtimes.find((V)=>V.id===$);if(!Q||Q.kind!=="custom")return null;return A$(`custom:${Q.id}`,async()=>({adapterId:Q.id,...await m(Q).checkReadiness(Q)}))}function u1(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function m3(){let[$,Z]=await Promise.all([E(),c1()]),X=$.globalDefaultConfigId?$.runtimes.find((J)=>J.id===$.globalDefaultConfigId)??null:null;return{runtimes:$.runtimes,globalDefaultConfigId:$.globalDefaultConfigId,globalDefaultEffective:X?{runFolder:X.runFolder??G0.homedir(),modelId:X.defaultModelId??null}:null,knownAdapters:$$().map((J)=>({id:J.id,displayName:J.displayName})),readiness:Z}}async function S3($){try{let Z=await n({boardId:$.boardId,cardId:$.cardId});return{resolved:{configId:Z.entry.id,adapterId:Z.entry.kind==="registered"?Z.entry.adapterId:null,displayName:Z.entry.displayName,runFolder:Z.runFolder,modelId:Z.modelId}}}catch(Z){if(Z instanceof a)return{resolved:null};throw Z}}async function c3($){return h((Z)=>{let X=Z.runtimes.find((V)=>V.kind==="registered"&&V.adapterId===$.adapterId);if(X)return X;let J=$$().find((V)=>V.id===$.adapterId);if(!J)throw Error(`Unknown adapterId: ${$.adapterId}`);let Q={id:u1(),kind:"registered",adapterId:$.adapterId,displayName:J.displayName,runFolder:null,defaultModelId:null,discoveredModels:[],discoveredAt:null};return Z.runtimes.push(Q),Q})}async function l3($){return h((Z)=>{let X={id:u1(),kind:"custom",displayName:$.displayName,command:$.command,args:$.args,env:$.env,runFolder:$.runFolder,defaultModelId:null,discoveredModels:[],discoveredAt:null};return Z.runtimes.push(X),X})}async function u3($){await h((Z)=>{if(Z.runtimes=Z.runtimes.filter((X)=>X.id!==$.runtimeConfigId),Z.globalDefaultConfigId===$.runtimeConfigId)Z.globalDefaultConfigId=null;for(let X of Object.keys(Z.boardOverrides))if(Z.boardOverrides[X].runtimeConfigId===$.runtimeConfigId)delete Z.boardOverrides[X];for(let X of Object.keys(Z.cardOverrides))if(Z.cardOverrides[X].runtimeConfigId===$.runtimeConfigId)delete Z.cardOverrides[X]})}async function p3($){await h((Z)=>{let X=Z.runtimes.find((J)=>J.id===$.runtimeConfigId);if(!X)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);if(Z.globalDefaultConfigId=$.runtimeConfigId,$.runFolder!==void 0)X.runFolder=$.runFolder;if($.modelId!==void 0)X.defaultModelId=$.modelId})}async function a3($){$.boardId,await h((Z)=>{if($.runtimeConfigId===null){delete Z.cardOverrides[$.cardId];return}if(!Z.runtimes.some((Q)=>Q.id===$.runtimeConfigId))throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=Z.cardOverrides[$.cardId];Z.cardOverrides[$.cardId]={runtimeConfigId:$.runtimeConfigId,runFolder:$.runFolder!==void 0?$.runFolder:J?.runFolder??null,modelId:$.modelId!==void 0?$.modelId:J?.modelId??null}})}async function i3($){let X=(await E()).runtimes.find((K)=>K.id===$.runtimeConfigId);if(!X)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=m(X),Q=await J.resolveSpawnConfig(X),V=X.runFolder??G0.homedir();try{let K=await p0({spawn:{...Q,cwd:V}}),z=new Date().toISOString();return await h((W)=>{let M=W.runtimes.find((j)=>j.id===$.runtimeConfigId);if(M)M.discoveredModels=K.models,M.discoveredAt=z}),{ok:!0,models:K.models,currentModelId:K.currentModelId}}catch(K){if(K instanceof r)throw Error(`${K.message}${J.authHint?` ${J.authHint}`:""}`);if(K instanceof F||K instanceof i)throw Error(K.message);throw K}}async function d3($){let Z=G0.homedir(),X=$.path?.trim()?$.path.trim():Z,J=f$.resolve(X),Q=!0;try{if(!(await _$.stat(J)).isDirectory())J=f$.dirname(J)}catch{Q=!1,J=Z}let V=[];try{V=(await _$.readdir(J,{withFileTypes:!0})).filter((W)=>W.isDirectory()&&!W.name.startsWith(".")).map((W)=>({name:W.name,path:f$.join(J,W.name)})).sort((W,M)=>W.name.localeCompare(M.name))}catch{V=[]}let K=f$.dirname(J);return{path:J,parent:K===J?null:K,home:Z,exists:Q,entries:V}}var p1={list:m3,getEffectiveForCard:S3,registerRegistered:c3,registerCustom:l3,unregister:u3,setUserDefault:p3,setCardOverride:a3,refreshModels:i3,browseFolder:d3};var n3=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function o3(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function a1(){try{let $=await E();if($.globalDefaultConfigId){if($.runtimes.some((X)=>X.id===$.globalDefaultConfigId))return $.globalDefaultConfigId}for(let Z of n3){if((await l1(Z.id))?.status!=="ready")continue;let J=null;if(await h((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((z)=>z.id===Q.globalDefaultConfigId)){J=Q.globalDefaultConfigId;return}}let V=Q.runtimes.find((K)=>K.kind==="registered"&&K.adapterId===Z.id);if(!V){let K={id:o3(),kind:"registered",adapterId:Z.id,displayName:Z.displayName,runFolder:null,defaultModelId:null,discoveredModels:[],discoveredAt:null};Q.runtimes.push(K),V=K}Q.globalDefaultConfigId=V.id,J=V.id}),J)return console.log(`[ideawave-cli] using agent runtime: ${Z.displayName}`),J}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch($){return console.warn("[ideawave-cli] runtime auto-seed failed",$),null}}function s3(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class x0{sessions=new Map;createCallId;toolCallTimeoutMs;constructor($={}){this.createCallId=$.createCallId??s3,this.toolCallTimeoutMs=$.toolCallTimeoutMs??120000}register($){let Z=this.sessions.get($.frontendSessionId);if(Z){if(Z.userId!==$.userId)this.rejectPending(Z,"frontend session user changed"),Z.activeRunIds.clear();this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:Z.pendingToolCalls,activeRunIds:Z.activeRunIds,activeRunCardIds:Z.activeRunCardIds});return}this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect($,Z="frontend session disconnected"){let X=this.sessions.get($);if(!X)return{activeRunIds:[]};return this.sessions.delete($),this.rejectPending(X,Z),{activeRunIds:Array.from(X.activeRunIds)}}sessionCount(){return this.sessions.size}has($){return this.sessions.has($)}getUserId($){return this.sessions.get($)?.userId??null}setMetadata($,Z){let X=this.sessions.get($);if(X)X.tools=Z}getMetadata($){if(!$)return[];return this.sessions.get($)?.tools??[]}sendToSession($,Z){let X=this.sessions.get($);if(!X)return!1;return X.send(Z),!0}callTool($,Z,X,J,Q){if(!$)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let V=this.sessions.get($);if(!V)return Promise.reject(Error(`Frontend session ${$} is not connected`));let K=this.createCallId();return new Promise((z,W)=>{let M=setTimeout(()=>{V.pendingToolCalls.delete(K),W(Error(`Tool "${Z}" timed out waiting for the frontend`))},this.toolCallTimeoutMs),j=J??(Q?this.getActiveRunIdForCard(V,Q):this.getSoleActiveRunId(V)),G=Q??(j?V.activeRunCardIds.get(j):void 0);V.pendingToolCalls.set(K,{resolve:z,reject:W,timer:M}),V.send({type:"tool_call",callId:K,name:Z,args:X,...j?{runId:j}:{},...G?{cardId:G}:{}})})}handleToolResult($,Z){let X=this.sessions.get($);if(!X)return;let J=X.pendingToolCalls.get(Z.callId);if(!J)return;if(X.pendingToolCalls.delete(Z.callId),clearTimeout(J.timer),Z.ok)J.resolve(Z.result);else J.reject(Error(Z.error??"Tool execution failed"))}markRunActive($,Z,X){let J=this.sessions.get($);if(!J)return;if(J.activeRunIds.add(Z),X)J.activeRunCardIds.set(Z,X)}markRunSettled($,Z){let X=this.sessions.get($);if(!X)return;X.activeRunIds.delete(Z),X.activeRunCardIds.delete(Z)}ownsRun($,Z){return this.sessions.get($)?.activeRunIds.has(Z)??!1}rejectPending($,Z){for(let X of $.pendingToolCalls.values())clearTimeout(X.timer),X.reject(Error(Z));$.pendingToolCalls.clear()}getSoleActiveRunId($){return $.activeRunIds.size===1?$.activeRunIds.values().next().value:void 0}getActiveRunIdForCard($,Z){let X=[...$.activeRunCardIds.entries()].filter(([J,Q])=>$.activeRunIds.has(J)&&Q===Z).map(([J])=>J);return X.length===1?X[0]:void 0}}function t3(){return"0.0.29".trim()?"0.0.29":"dev"}var u=process.argv[2];if(u==="--help"||u==="-h"||u==="help")console.log("ideawave — host the local bridge for a running ideawave.app session."),console.log(""),console.log("Usage:"),console.log(" ideawave Serve the browser bridge and MCP forwarder."),console.log(" ideawave --version Print the CLI version."),process.exit(0);if(u==="--version"||u==="-v"||u==="version")console.log(t3()),process.exit(0);if(u)console.error(`Unknown command: ${u}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var M$=new x0,x$=null;function Y$($,Z){M$.sendToSession($,Z)}async function r3($,Z){try{let X=p1[Z.method],J=await X(Z.params);Y$($,{type:"runtime_rpc_result",requestId:Z.requestId,ok:!0,result:J})}catch(X){Y$($,{type:"runtime_rpc_result",requestId:Z.requestId,ok:!1,error:X instanceof Error?X.message:String(X)})}}var G$=!1,W$=null;async function z0(){if(G$)return;if(W$)return W$;return W$=(async()=>{try{let $=await m1(M$);U0({...$,requestedPort:$.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${$.url}`);try{let Z=await _0();for(let X of Z)if(X.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${X.packageName}: ${X.error??"unknown error"}`)}catch(Z){console.warn("[ideawave-cli] ACP bridge setup skipped:",Z instanceof Error?Z.message:String(Z))}await a1(),G$=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),x$?.sendStatus()}catch($){console.error("[ideawave-cli] failed to start agent host:",$),x$?.sendStatus(void 0,$ instanceof Error?$.message:String($))}finally{W$=null}})(),W$}if(process.env.APP_ENV!=="development"){let $=await O1();if($)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${$}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}x$=await A1({registry:M$,runtime:null,mcpReady:()=>G$,onToolMetadata:($)=>{console.log(`[ideawave-cli] session ${$} advertised ${M$.getMetadata($).length} tools`),z0()},onRunTurn:($,Z)=>{console.log(`[ideawave-cli] running agent turn for card ${Z.cardId} (session ${$})`),(async()=>{if(await z0(),!G$){Y$($,{type:"run_settled",runId:Z.runId,cardId:Z.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await N1(Z,(X)=>Y$($,X))})().catch(()=>{return}).finally(()=>M$.markRunSettled($,Z.runId))},onCancelRun:($,Z)=>{J0(Z)},onRuntimeRpc:($,Z)=>{r3($,Z)},onWarmupRun:($,Z,X)=>{(async()=>{if(await z0(),!G$)return{status:"retryable",error:"agent host is not ready"};return k1({cardId:Z.cardId,boardId:Z.boardId,userId:X,frontendSessionId:$})})().then((J)=>{if(!Z.warmupId)return;Y$($,{type:"warmup_result",warmupId:Z.warmupId,cardId:Z.cardId,...J})})},onDisconnect:($,Z)=>{H1($);for(let X of Z)J0(X);console.log(`[ideawave-cli] browser session ${$} disconnected`)}});console.log(`[ideawave-cli] browser bridge listening on ${x$.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var i1=!1;for(let $ of["SIGINT","SIGTERM"])process.once($,()=>{if(i1)return;i1=!0,B1(),(async()=>{await x$?.close().catch(()=>{return}),process.exit(0)})()});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideawave",
3
- "version": "0.0.28",
3
+ "version": "0.0.29",
4
4
  "description": "IdeaWave CLI",
5
5
  "type": "module",
6
6
  "bin": {