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