ideawave 0.0.47 → 0.0.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +10 -10
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1,28 +1,28 @@
1
1
  #!/usr/bin/env node
2
- import{readFileSync as w2}from"node:fs";import{homedir as _2}from"node:os";import{join as x0}from"node:path";function A2(){let $=_2();switch(process.platform){case"win32":return process.env.APPDATA??x0($,"AppData","Roaming");case"darwin":return x0($,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??x0($,".config")}}function v$(){let $=process.env.IDEAWAVE_MCP_JSON_PATH;if($&&$.trim().length>0)return $;return x0(A2(),"ideawave","mcp.json")}var h$=null;function S$($){h$=$}var T2=86400000;function f2(){let $;try{$=w2(v$(),"utf8")}catch{return null}let X;try{X=JSON.parse($)}catch{return null}if(typeof X.url!=="string")return null;if(typeof X.startedAt==="string"){let Z=Date.parse(X.startedAt);if(!Number.isNaN(Z)){if(Date.now()-Z>T2)return null}}if(typeof X.pid==="number"&&X.pid>0)try{process.kill(X.pid,0)}catch(Z){if(Z?.code!=="EPERM")return null}return{url:X.url}}function I$($,X={}){let Z=[];if(X.userId&&X.userId.trim().length>0)Z.push({name:"X-Ideawave-User-Id",value:X.userId.trim()});if(X.frontendSessionId&&X.frontendSessionId.trim().length>0)Z.push({name:"X-Ideawave-Frontend-Session-Id",value:X.frontendSessionId.trim()});if(X.toolSurface==="read")Z.push({name:"X-Ideawave-Tool-Surface",value:"read"});if(X.imagesSupported)Z.push({name:"X-Ideawave-Images-Supported",value:"1"});if(X.cardId&&X.cardId.trim().length>0)Z.push({name:"X-Ideawave-Card-Id",value:X.cardId.trim()});if(X.boardId&&X.boardId.trim().length>0)Z.push({name:"X-Ideawave-Board-Id",value:X.boardId.trim()});if(X.runFolder&&X.runFolder.trim().length>0)Z.push({name:"X-Ideawave-Run-Folder",value:X.runFolder.trim()});return{type:"http",name:"ideawave-board",url:$,headers:Z}}function u0($={}){let X=h$;if(X)return I$(X.url,$);let Z=f2();if(!Z)return null;return I$(Z.url,$)}import Y0 from"node:fs/promises";import v2 from"node:path";import{z as q}from"zod";var m$=q.object({id:q.string(),name:q.string().nullable().default(null),description:q.string().nullable().default(null)}),l$=q.union([q.string(),q.boolean()]),R2=q.object({value:q.string(),name:q.string(),description:q.string().nullable().default(null),group:q.string().nullable().default(null),groupName:q.string().nullable().default(null)}),g$=q.object({id:q.string(),name:q.string(),category:q.string().nullable().default(null),description:q.string().nullable().default(null),type:q.enum(["select","boolean"]),currentValue:l$.nullable().default(null),options:q.array(R2).default([])}),p0=q.record(q.string(),l$).default({}),E2=q.discriminatedUnion("kind",[q.object({id:q.string(),kind:q.literal("registered"),adapterId:q.enum(["claude-code","opencode","codex","copilot"]),displayName:q.string(),runFolder:q.string().nullable(),defaultModelId:q.string().nullable().default(null),defaultConfigValues:p0,discoveredModels:q.array(m$).default([]),discoveredConfigOptions:q.array(g$).default([]),discoveredAt:q.string().nullable().default(null)}),q.object({id:q.string(),kind:q.literal("custom"),displayName:q.string(),command:q.string(),args:q.array(q.string()),env:q.record(q.string(),q.string()),runFolder:q.string().nullable(),defaultModelId:q.string().nullable().default(null),defaultConfigValues:p0,discoveredModels:q.array(m$).default([]),discoveredConfigOptions:q.array(g$).default([]),discoveredAt:q.string().nullable().default(null)})]),c$=q.object({runtimeConfigId:q.string(),runFolder:q.string().nullable(),modelId:q.string().nullable().default(null),configValues:p0}),F0=q.object({version:q.literal(1),globalDefaultConfigId:q.string().nullable(),runtimes:q.array(E2),boardOverrides:q.record(q.string(),c$).default({}),cardOverrides:q.record(q.string(),c$).default({})});import y2 from"node:os";import C0 from"node:path";function b2(){let $=y2.homedir();switch(process.platform){case"win32":return process.env.APPDATA??C0.join($,"AppData","Roaming");case"darwin":return C0.join($,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??C0.join($,".config")}}function P0(){let $=process.env.IDEAWAVE_RUNTIME_CONFIG_PATH;if($)return $;return C0.join(b2(),"ideawave","runtimes.json")}var I2={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},u$=new Map;function h2($){return u$.get($)??Promise.resolve()}function S2($,X){u$.set($,X)}async function h($){let X=$??P0(),Z;try{Z=await Y0.readFile(X,"utf-8")}catch(Q){if(Q.code==="ENOENT")return structuredClone(I2);throw Q}return F0.parse(JSON.parse(Z))}async function g($,X){let Z=X??P0(),J=h2(Z).then(async()=>{let Q=await h(Z),j=structuredClone(Q),K=await $(j);return await m2(j,Z),K});return S2(Z,J.catch(()=>{return})),J}async function m2($,X){let Z=X??P0(),J=v2.dirname(Z);await Y0.mkdir(J,{recursive:!0});let Q=`${Z}.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,Z)}catch(K){throw await Y0.unlink(Q).catch(()=>{return}),K}}import{spawn as d2}from"node:child_process";import{closeSync as a2,existsSync as n$,mkdirSync as o$,openSync as i2,readFileSync as n2,renameSync as o2,rmSync as s$,statSync as s2,unlinkSync as t2,writeFileSync as r2}from"node:fs";import a$ from"node:os";import r from"node:path";import{execFile as u2}from"node:child_process";import{promisify as p2}from"node:util";import{execFile as g2}from"node:child_process";import{promisify as c2}from"node:util";var l2=c2(g2),d0=new Map,p$=5000;async function d$($,X=l2){let Z=d0.get($);if(Z&&Z.expiresAt>Date.now())return Z.value;let J=process.platform==="win32"?"where":"which";try{let{stdout:Q}=await X(J,[$],{timeout:2000}),j=Q.split(/\r?\n/).find((G)=>G.trim().length>0),K=j?j.trim():null;return d0.set($,{value:K,expiresAt:Date.now()+p$}),K}catch{return d0.set($,{value:null,expiresAt:Date.now()+p$}),null}}class V0 extends Error{code;constructor($,X){super($);this.name="AcpError",this.code=X}}class t extends V0{constructor($="No ACP runtime configured"){super($,"RUNTIME_NOT_CONFIGURED");this.name="RuntimeNotConfiguredError"}}class O extends V0{constructor($){super($,"RUNTIME_UNREACHABLE");this.name="RuntimeUnreachableError"}}class J0 extends V0{authMethods;constructor($,X){super($,"AUTH_REQUIRED");this.name="AuthRequiredError",this.authMethods=X}}class d extends V0{constructor($="ACP session timed out"){super($,"SESSION_TIMEOUT");this.name="SessionTimeoutError"}}var MZ=p2(u2);function w($,...X){return d$($,...X)}function v($){let X={};for(let[Z,J]of Object.entries(process.env))if(typeof J==="string")X[Z]=J;return{...X,...$??{}}}var i0=[{adapterId:"claude-code",runtimeBinary:"claude",packageName:"@agentclientprotocol/claude-agent-acp",version:"0.50.0",warmupArgs:["--cli","--help"]},{adapterId:"codex",runtimeBinary:"codex",packageName:"@agentclientprotocol/codex-acp",version:"1.0.0",warmupArgs:["--version"]}],e2=1800000,L0=new Map;function n0(){if(process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR)return process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR;if(process.platform==="win32"){let $=process.env.LOCALAPPDATA??r.join(a$.homedir(),"AppData","Local");return r.join($,"ideawave","acp-bridges")}return r.join(process.env.XDG_CACHE_HOME??r.join(a$.homedir(),".cache"),"ideawave","acp-bridges")}function $6($){return $.replace(/^@/,"").replace(/[/\\]/g,"-")}function k0(){return r.join(n0(),"install-state.json")}function o0($){return r.join(n0(),`${$6($.packageName)}@${$.version}.install.lock`)}function s0(){return process.platform==="win32"?"npx.cmd":"npx"}function t0($){return`${$.packageName}@${$.version}`}function t$(){let $=k0();if(!n$($))return{};try{return JSON.parse(n2($,"utf8"))}catch{return{}}}function a0($,X){let Z=n0();o$(Z,{recursive:!0});let J=t$();J.bridges={...J.bridges??{},[$.adapterId]:X},r2(`${k0()}.tmp`,`${JSON.stringify(J,null,2)}
3
- `),o2(`${k0()}.tmp`,k0())}function r$($){return i0.find((X)=>X.packageName===$)??null}function S($,X,Z){return{adapterId:$.adapterId,packageName:$.packageName,version:$.version,status:X,...Z?{error:Z}:{}}}function i$($,X){return X?.packageName===$.packageName&&X.version===$.version}function e$($){try{return Date.now()-s2($).mtimeMs>e2}catch{return!1}}function X6($){let X=o0($);if(!n$(X))return!1;if(e$(X))return s$(X,{force:!0}),!1;return!0}function Z6($){let X=o0($);if(o$(r.dirname(X),{recursive:!0}),e$(X))s$(X,{force:!0});try{let Z=i2(X,"wx");return a2(Z),!0}catch{return!1}}function J6($){t2(o0($))}function r0($){let X=t$().bridges?.[$.adapterId];if(i$($,X)&&X.status==="ready")return S($,"ready");if(L0.has($.adapterId)||X6($))return S($,"installing");if(i$($,X)&&X.status==="failed")return S($,"failed",X.error);return S($,"missing")}function z0($,X){$?.onStatusChange?.(X)}function Q6($,X){let Z=r0($);if(Z.status==="ready")return z0(X,Z),Z;if(Z.status==="installing"){let W=L0.get($.adapterId);if(W&&X?.onStatusChange)W.then((H)=>z0(X,H));return z0(X,Z),Z}if(!Z6($))return S($,"installing");let J=S($,"installing");a0($,J),z0(X,J);let Q=()=>{},j=new Promise((W)=>{Q=W});L0.set($.adapterId,j);let K=!1,G=(W)=>{if(K)return;K=!0;try{J6($)}catch{}a0($,W),z0(X,W),L0.delete($.adapterId),Q(W)},z;try{z=d2(s0(),["-y",t0($),...$.warmupArgs],{stdio:"ignore",windowsHide:!0})}catch(W){let H=S($,"failed",W instanceof Error?W.message:String(W));return G(H),H}return z.on("error",(W)=>{G(S($,"failed",W.message))}),z.on("close",(W)=>{if(W===0){G(S($,"ready"));return}G(S($,"failed",`npx warmup exited ${W??"null"}`))}),z.unref(),J}function Q0($){let X=r$($);return X?r0(X):null}async function $1($){let X=[];for(let Z of i0){if(!await w(Z.runtimeBinary)){X.push(S(Z,"not_needed"));continue}X.push(Q6(Z,$))}return X.filter((Z)=>Z.status!=="not_needed")}function O0($){let X=r$($);if(!X)return null;if(r0(X).status!=="ready")return null;return{command:s0(),args:["-y",t0(X)],env:{}}}function e0($,X){if($.command!==s0())return!1;let Z=i0.find((J)=>$.args.includes(t0(J)));if(!Z)return!1;return a0(Z,S(Z,"failed",X)),!0}var X1="claude",$$="@agentclientprotocol/claude-agent-acp",Z1=["claude-agent-acp","claude-code-acp"],J1="Install Claude Code from https://github.com/anthropics/claude-code",Q1={id:"claude-code",displayName:"Claude Code",kind:"registered",supportsImages:!0,resolveSpawnConfig:async()=>{if(!await w(X1))throw new O(`Claude Code CLI not found. ${J1}`);let X=O0($$);if(X)return{command:X.command,args:X.args,env:v(X.env)};let Z=Q0($$),J=Z?.status==="installing";for(let j of Z1){let K=await w(j);if(K&&!J&&Z?.status!=="failed")return{command:K,args:[],env:v()}}let Q=Z?.status==="failed"?`Claude Code ACP bridge install failed. ${Z.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 O(Q)},checkReadiness:async()=>{if(!await w(X1))return{status:"not_installed",detail:J1};let X=Q0($$);if(X?.status==="ready")return{status:"ready"};if(X?.status==="installing")return{status:"not_running",detail:"Installing Claude Code ACP bridge..."};if(X?.status==="failed")return{status:"not_running",detail:X.error??"Claude Code ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};for(let Z of Z1)if(await w(Z))return{status:"ready"};return{status:"not_running",detail:"Installing Claude Code ACP bridge..."}},authHint:"Run `claude login` (or set ANTHROPIC_API_KEY)."};var j1="codex",X$="@agentclientprotocol/codex-acp",K1="codex-acp",W1="Install Codex CLI from https://developers.openai.com/codex/cli",Y1={id:"codex",displayName:"Codex",kind:"registered",resolveSpawnConfig:async()=>{if(!await w(j1))throw new O(`Codex CLI not found. ${W1}`);let X=O0(X$);if(X)return{command:X.command,args:X.args,env:v(X.env)};let Z=Q0(X$),J=Z?.status==="installing",Q=await w(K1);if(Q&&!J&&Z?.status!=="failed")return{command:Q,args:[],env:v()};let j=Z?.status==="failed"?`Codex ACP bridge install failed. ${Z.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 O(j)},checkReadiness:async()=>{if(!await w(j1))return{status:"not_installed",detail:W1};let X=Q0(X$);if(X?.status==="ready")return{status:"ready"};if(X?.status==="installing")return{status:"not_running",detail:"Installing Codex ACP bridge..."};if(X?.status==="failed")return{status:"not_running",detail:X.error??"Codex ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};if(await w(K1))return{status:"ready"};return{status:"not_running",detail:"Installing Codex ACP bridge..."}},authHint:"Run `codex login` (or set OPENAI_API_KEY)."};var V1="copilot",z1="copilot-acp",G1="npm i -g @github/copilot",H1={id:"copilot",displayName:"GitHub Copilot",kind:"registered",resolveSpawnConfig:async()=>{let $=await w(V1);if($)return{command:$,args:["--acp"],env:v()};let X=await w(z1);if(X)return{command:X,args:[],env:v()};throw new O(`Copilot not installed. Run: ${G1}`)},checkReadiness:async()=>{if(await w(V1))return{status:"ready"};if(await w(z1))return{status:"ready"};return{status:"not_installed",detail:G1}},authHint:"Run `gh auth login` (or `copilot login`)."};import j6 from"node:fs/promises";function K6($){return $.startsWith("/")||/^[a-zA-Z]:[\\/]/.test($)}async function U1($){if(K6($))try{return await j6.access($),!0}catch{return!1}return await w($)!==null}var D1={id:"custom",displayName:"Custom ACP",kind:"custom",resolveSpawnConfig:async($)=>{if($.kind!=="custom")throw new O("customAdapter received non-custom entry");if(!await U1($.command))throw new O(`custom: command "${$.command}" not found`);return{command:$.command,args:$.args,env:v($.env)}},checkReadiness:async($)=>{if($.kind!=="custom")return{status:"unknown"};return await U1($.command)?{status:"ready"}:{status:"not_installed"}}};var M1="opencode",N1="Install OpenCode from https://opencode.ai",q1={id:"opencode",displayName:"OpenCode",kind:"registered",resolveSpawnConfig:async()=>{let $=await w(M1);if(!$)throw new O(`OpenCode not installed. ${N1}`);return{command:$,args:["acp"],env:v()}},checkReadiness:async()=>{if(!await w(M1))return{status:"not_installed",detail:N1};return{status:"ready"}},authHint:"Run `opencode auth login <provider>` (or set the provider's API-key env var)."};var B1={"claude-code":Q1,opencode:q1,codex:Y1,copilot:H1};function c($){if($.kind==="custom")return D1;let X=B1[$.adapterId];if(!X)throw Error(`Unknown registered adapter: ${$.adapterId}`);return X}function j0(){return Object.values(B1)}var Z$=new Map,_0=new Map,W6=30000;function A0($,X){let Z=Z$.get($);if(Z&&Z.expiresAt>Date.now())return Promise.resolve(Z.value);let J=_0.get($);if(J)return J;let Q=X().then((j)=>{return Z$.set($,{value:j,expiresAt:Date.now()+W6}),j}).finally(()=>{_0.delete($)});return _0.set($,Q),Q}async function x1($){let X=await Promise.all(j0().map((j)=>A0(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 h($)).runtimes.filter((j)=>j.kind==="custom"),Q=await Promise.all(J.map((j)=>A0(`custom:${j.id}`,async()=>({adapterId:j.id,...await c(j).checkReadiness(j)}))));return[...X,...Q]}async function F1($,X){let Z=j0().find((j)=>j.id===$);if(Z)return A0(Z.id,async()=>({adapterId:Z.id,...await Z.checkReadiness({id:"__probe__",kind:"registered",adapterId:Z.id,displayName:Z.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null})}));let Q=(await h(X)).runtimes.find((j)=>j.id===$);if(!Q||Q.kind!=="custom")return null;return A0(`custom:${Q.id}`,async()=>({adapterId:Q.id,...await c(Q).checkReadiness(Q)}))}function C1(){Z$.clear(),_0.clear()}function Y6($){if(!$)return null;let X=$.indexOf("/");if(X<=0)return null;return $.slice(0,X)}function w0($){let X=[...$.models];if($.adapterId!=="opencode"||X.length===0)return X;let Z=Y6($.currentModelId)??(X.some((Q)=>Q.id.startsWith("opencode/"))?"opencode":null);if(!Z)return X;let J=X.filter((Q)=>Q.id===$.currentModelId||Q.id.startsWith(`${Z}/`));return J.length>0?J:X}import{Readable as k6,Writable as O6}from"node:stream";import{ClientSideConnection as E1,ndJsonStream as y1}from"@agentclientprotocol/sdk";import a from"node:fs/promises";import b from"node:path";class H0 extends Error{constructor($){super($);this.name="PathTraversalError"}}class Q$ extends Error{constructor($){super($);this.name="HiddenPathError"}}class j$ extends Error{constructor($){super($);this.name="RunFolderFileTooLargeError"}}class G0 extends Error{constructor($){super($);this.name="RunFolderBinaryFileError"}}var V6=new Set([".bzr",".cache",".claude",".config",".env",".git",".hg",".idea",".obsidian",".svn",".vscode","node_modules"]),P1=1e6,z6=4096,G6=new TextDecoder("utf-8",{fatal:!0});function H6($){return $.split(/[\\/]+/).filter((X)=>X.length>0)}function T0($){if(b.isAbsolute($))throw new H0("Absolute paths are not allowed");for(let X of H6($)){if(X===".")continue;if(X==="..")throw new H0("Parent-directory traversal is not allowed");if(X.startsWith(".")||V6.has(X))throw new Q$(`Path segment "${X}" is hidden or configuration data`)}}function U6($){T0($);let X=b.normalize($||".");return X==="."?"":X}function D6($,X,Z){let J=b.relative($,X);if(J===".."||J.startsWith(`..${b.sep}`)||b.isAbsolute(J))throw new H0(`Path "${Z}" resolves outside the run folder`);if(J.length>0)T0(J);return J}async function J$($,X){T0(X);let Z=b.resolve($,X||"."),J;try{J=await a.realpath(Z)}catch(Q){if(Q.code!=="ENOENT")throw Q;let j=b.dirname(Z),K=[b.basename(Z)];while(j!==$&&j!==b.dirname(j))try{j=await a.realpath(j);break}catch(G){if(G.code!=="ENOENT")throw G;K.unshift(b.basename(j)),j=b.dirname(j)}J=b.join(j,...K)}return D6($,J,X),J}async function M6($,X){let Z=await a.realpath($);return J$(Z,X)}function N6($){let X=$.subarray(0,Math.min($.length,z6));if(X.length===0)return!1;let Z=0;for(let J of X){if(J===0)return!0;let Q=J===9||J===10||J===12||J===13;if(J<32&&!Q)Z+=1}return Z/X.length>0.3}async function f0($,X){let Z=await M6($,X),J=await a.stat(Z);if(!J.isFile())throw new G0(`Path "${X}" is not a text file`);if(J.size>P1)throw new j$(`File "${X}" is too large to read (${J.size} bytes, max ${P1} bytes)`);let Q=await a.readFile(Z);if(N6(Q))throw new G0(`File "${X}" appears to be binary, not text`);try{return G6.decode(Q)}catch{throw new G0(`File "${X}" is not valid UTF-8 text`)}}function q6($){if($.isDirectory())return"directory";if($.isFile())return"file";if($.isSymbolicLink())return"symlink";return"other"}function L1($){return $.split(b.sep).join("/")}async function k1($,X=""){let Z=await a.realpath($),J=U6(X),Q=await J$(Z,J),j=await a.readdir(Q,{withFileTypes:!0}),K=[];for(let G of j){let z=J?b.join(J,G.name):G.name;try{T0(z);let W=await J$(Z,z),H=await a.stat(W);K.push({name:G.name,path:L1(z),type:q6(G),size:G.isFile()?H.size:null})}catch{}}return K.sort((G,z)=>{if(G.type==="directory"&&z.type!=="directory")return-1;if(G.type!=="directory"&&z.type==="directory")return 1;return G.name.localeCompare(z.name)}),{path:L1(J),absolutePath:Q,entries:K}}var K$={fs:{readTextFile:!0,writeTextFile:!1},terminal:!1};function O1($){return{readTextFile:async(X)=>{return{content:await f0($,X.path)}}}}import{spawn as B6}from"node:child_process";function W$($){let X=B6($.command,$.args,{cwd:$.cwd,env:$.env,stdio:["pipe","pipe","pipe"]});if(!X.stdin||!X.stdout||!X.stderr)throw Error("Failed to allocate stdio streams for ACP subprocess");let{stdin:Z,stdout:J,stderr:Q}=X,j=4096,K=[],G=0;Q.on("data",(V)=>{K.push(V),G+=V.length;while(G>j*2&&K.length>1){let D=K.shift();if(D)G-=D.length}});let z=()=>{let V=Buffer.concat(K).toString("utf8");return V.length>j?V.slice(-j):V},W=!1,H=!1,B,U,M=new Promise((V)=>{B=V}),N=new Promise((V)=>{U=V}),F=(V)=>{if(H)return;if(H=!0,B(V),!W)U(V)};return X.on("exit",(V,D)=>{F({code:V,signal:D,stderr:z()})}),X.on("error",(V)=>{let D=z(),x=V?.message??String(V);F({code:null,signal:null,stderr:D?`${x}
4
- ${D}`:x})}),{stdin:Z,stdout:J,stderr:Q,kill:(V="SIGTERM")=>{if(W)return;W=!0;try{X.kill(V)}catch{}},waitForExit:M,processCrashed:N}}var x6=["mcp_ideawave_board_","ideawave_board_","ideawave-board_","ideawave-board.","ideawave.board."];function F6($){let X=$.toLowerCase();for(let Z of x6)if(X.startsWith(Z))return $.slice(Z.length);if(/^mcp[-_.]/i.test($))return $.slice(4);return $}function R0($){return F6($.trim())}function Y$($){let X=R0($);if(!X)return"Tool";if(!/[-_.]/.test(X))return X.charAt(0).toUpperCase()+X.slice(1);let Z=X.replace(/[-_.]+/g," ").replace(/\s+/g," ").trim();if(!Z)return"Tool";return Z.charAt(0).toUpperCase()+Z.slice(1)}function V$($){let X=$?.toLowerCase();if(X==="completed"||X==="complete"||X==="done"||X==="success"||X==="succeeded")return"completed";if(X==="failed"||X==="error"||X==="errored")return"failed";return"running"}function z$($){if(typeof $!=="string")return null;let X=$.trim();return X?X:null}function _1($){if(typeof $!=="string")return"Tool";let X=$.trim();return X?X:"Tool"}function C6($,X){if(!$||typeof $!=="object"||Array.isArray($))return null;let Z=$;for(let J of X){let Q=Z[J];if(typeof Q==="string"&&Q.trim())return Q.trim()}return null}function G$($,X){let Z=$.trim().toLowerCase();if(Z==="skill"||Z==="workflow"||Z==="tool"||Z==="invalid"){let J=C6(X,["skillName","workflowName","toolName","name","title"]);if(J){let Q=Z==="skill"?" skill":Z==="workflow"?" workflow":"";return`${Y$(J)}${Q}`}}if(Z==="invalid")return"Tool call";return Y$($)}var P6=33,A1=1600;function e($){if($.length<=A1)return $;return`${$.slice(0,A1-22)}
5
- ... truncated`}function y0($){let X=$.replace(/\r\n?/g,`
2
+ import{readFileSync as T6}from"node:fs";import{homedir as A6}from"node:os";import{join as x0}from"node:path";function w6(){let $=A6();switch(process.platform){case"win32":return process.env.APPDATA??x0($,"AppData","Roaming");case"darwin":return x0($,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??x0($,".config")}}function I$(){let $=process.env.IDEAWAVE_MCP_JSON_PATH;if($&&$.trim().length>0)return $;return x0(w6(),"ideawave","mcp.json")}var S$=null;function m$($){S$=$}var f6=86400000;function R6(){let $;try{$=T6(I$(),"utf8")}catch{return null}let X;try{X=JSON.parse($)}catch{return null}if(typeof X.url!=="string")return null;if(typeof X.startedAt==="string"){let Z=Date.parse(X.startedAt);if(!Number.isNaN(Z)){if(Date.now()-Z>f6)return null}}if(typeof X.pid==="number"&&X.pid>0)try{process.kill(X.pid,0)}catch(Z){if(Z?.code!=="EPERM")return null}return{url:X.url}}function h$($,X={}){let Z=[];if(X.userId&&X.userId.trim().length>0)Z.push({name:"X-Ideawave-User-Id",value:X.userId.trim()});if(X.frontendSessionId&&X.frontendSessionId.trim().length>0)Z.push({name:"X-Ideawave-Frontend-Session-Id",value:X.frontendSessionId.trim()});if(X.toolSurface==="read")Z.push({name:"X-Ideawave-Tool-Surface",value:"read"});if(X.imagesSupported)Z.push({name:"X-Ideawave-Images-Supported",value:"1"});if(X.cardId&&X.cardId.trim().length>0)Z.push({name:"X-Ideawave-Card-Id",value:X.cardId.trim()});if(X.boardId&&X.boardId.trim().length>0)Z.push({name:"X-Ideawave-Board-Id",value:X.boardId.trim()});if(X.runFolder&&X.runFolder.trim().length>0)Z.push({name:"X-Ideawave-Run-Folder",value:X.runFolder.trim()});return{type:"http",name:"ideawave-board",url:$,headers:Z}}function p0($={}){let X=S$;if(X)return h$(X.url,$);let Z=R6();if(!Z)return null;return h$(Z.url,$)}import W0 from"node:fs/promises";import I6 from"node:path";import{z as q}from"zod";var g$=q.object({id:q.string(),name:q.string().nullable().default(null),description:q.string().nullable().default(null)}),u$=q.union([q.string(),q.boolean()]),E6=q.object({value:q.string(),name:q.string(),description:q.string().nullable().default(null),group:q.string().nullable().default(null),groupName:q.string().nullable().default(null)}),c$=q.object({id:q.string(),name:q.string(),category:q.string().nullable().default(null),description:q.string().nullable().default(null),type:q.enum(["select","boolean"]),currentValue:u$.nullable().default(null),options:q.array(E6).default([])}),d0=q.record(q.string(),u$).default({}),y6=q.discriminatedUnion("kind",[q.object({id:q.string(),kind:q.literal("registered"),adapterId:q.enum(["claude-code","opencode","codex","copilot"]),displayName:q.string(),runFolder:q.string().nullable(),defaultModelId:q.string().nullable().default(null),defaultConfigValues:d0,discoveredModels:q.array(g$).default([]),discoveredConfigOptions:q.array(c$).default([]),discoveredAt:q.string().nullable().default(null)}),q.object({id:q.string(),kind:q.literal("custom"),displayName:q.string(),command:q.string(),args:q.array(q.string()),env:q.record(q.string(),q.string()),runFolder:q.string().nullable(),defaultModelId:q.string().nullable().default(null),defaultConfigValues:d0,discoveredModels:q.array(g$).default([]),discoveredConfigOptions:q.array(c$).default([]),discoveredAt:q.string().nullable().default(null)})]),l$=q.object({runtimeConfigId:q.string(),runFolder:q.string().nullable(),modelId:q.string().nullable().default(null),configValues:d0}),F0=q.object({version:q.literal(1),globalDefaultConfigId:q.string().nullable(),runtimes:q.array(y6),boardOverrides:q.record(q.string(),l$).default({}),cardOverrides:q.record(q.string(),l$).default({})});import b6 from"node:os";import C0 from"node:path";function v6(){let $=b6.homedir();switch(process.platform){case"win32":return process.env.APPDATA??C0.join($,"AppData","Roaming");case"darwin":return C0.join($,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??C0.join($,".config")}}function P0(){let $=process.env.IDEAWAVE_RUNTIME_CONFIG_PATH;if($)return $;return C0.join(v6(),"ideawave","runtimes.json")}var h6={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},p$=new Map;function S6($){return p$.get($)??Promise.resolve()}function m6($,X){p$.set($,X)}async function h($){let X=$??P0(),Z;try{Z=await W0.readFile(X,"utf-8")}catch(Q){if(Q.code==="ENOENT")return structuredClone(h6);throw Q}return F0.parse(JSON.parse(Z))}async function g($,X){let Z=X??P0(),J=S6(Z).then(async()=>{let Q=await h(Z),j=structuredClone(Q),Y=await $(j);return await g6(j,Z),Y});return m6(Z,J.catch(()=>{return})),J}async function g6($,X){let Z=X??P0(),J=I6.dirname(Z);await W0.mkdir(J,{recursive:!0});let Q=`${Z}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`,j=JSON.stringify($,null,2);await W0.writeFile(Q,j,"utf-8");try{await W0.rename(Q,Z)}catch(Y){throw await W0.unlink(Q).catch(()=>{return}),Y}}import{spawn as n6}from"node:child_process";import{closeSync as o6,existsSync as o$,mkdirSync as s$,openSync as s6,readFileSync as t6,renameSync as r6,rmSync as t$,statSync as e6,unlinkSync as $X,writeFileSync as XX}from"node:fs";import i$ from"node:os";import r from"node:path";var c6=/\.(?:cmd|bat)$/i;function l6($){return process.platform==="win32"&&c6.test($)}function L0($){return l6($)?{shell:!0,windowsHide:!0}:{}}import{execFile as a6}from"node:child_process";import{promisify as i6}from"node:util";import{execFile as u6}from"node:child_process";import{promisify as p6}from"node:util";var d6=p6(u6),a0=new Map,d$=5000;async function a$($,X=d6){let Z=a0.get($);if(Z&&Z.expiresAt>Date.now())return Z.value;let J=process.platform==="win32"?"where":"which";try{let{stdout:Q}=await X(J,[$],{timeout:2000}),j=Q.split(/\r?\n/).find((G)=>G.trim().length>0),Y=j?j.trim():null;return a0.set($,{value:Y,expiresAt:Date.now()+d$}),Y}catch{return a0.set($,{value:null,expiresAt:Date.now()+d$}),null}}class V0 extends Error{code;constructor($,X){super($);this.name="AcpError",this.code=X}}class t extends V0{constructor($="No ACP runtime configured"){super($,"RUNTIME_NOT_CONFIGURED");this.name="RuntimeNotConfiguredError"}}class O extends V0{constructor($){super($,"RUNTIME_UNREACHABLE");this.name="RuntimeUnreachableError"}}class J0 extends V0{authMethods;constructor($,X){super($,"AUTH_REQUIRED");this.name="AuthRequiredError",this.authMethods=X}}class d extends V0{constructor($="ACP session timed out"){super($,"SESSION_TIMEOUT");this.name="SessionTimeoutError"}}var x3=i6(a6);function w($,...X){return a$($,...X)}function v($){let X={};for(let[Z,J]of Object.entries(process.env))if(typeof J==="string")X[Z]=J;return{...X,...$??{}}}var n0=[{adapterId:"claude-code",runtimeBinary:"claude",packageName:"@agentclientprotocol/claude-agent-acp",version:"0.50.0",warmupArgs:["--cli","--help"]},{adapterId:"codex",runtimeBinary:"codex",packageName:"@agentclientprotocol/codex-acp",version:"1.0.0",warmupArgs:["--version"]}],ZX=1800000,k0=new Map;function o0(){if(process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR)return process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR;if(process.platform==="win32"){let $=process.env.LOCALAPPDATA??r.join(i$.homedir(),"AppData","Local");return r.join($,"ideawave","acp-bridges")}return r.join(process.env.XDG_CACHE_HOME??r.join(i$.homedir(),".cache"),"ideawave","acp-bridges")}function JX($){return $.replace(/^@/,"").replace(/[/\\]/g,"-")}function O0(){return r.join(o0(),"install-state.json")}function s0($){return r.join(o0(),`${JX($.packageName)}@${$.version}.install.lock`)}function t0(){return process.platform==="win32"?"npx.cmd":"npx"}function r0($){return`${$.packageName}@${$.version}`}function r$(){let $=O0();if(!o$($))return{};try{return JSON.parse(t6($,"utf8"))}catch{return{}}}function i0($,X){let Z=o0();s$(Z,{recursive:!0});let J=r$();J.bridges={...J.bridges??{},[$.adapterId]:X},XX(`${O0()}.tmp`,`${JSON.stringify(J,null,2)}
3
+ `),r6(`${O0()}.tmp`,O0())}function e$($){return n0.find((X)=>X.packageName===$)??null}function S($,X,Z){return{adapterId:$.adapterId,packageName:$.packageName,version:$.version,status:X,...Z?{error:Z}:{}}}function n$($,X){return X?.packageName===$.packageName&&X.version===$.version}function $1($){try{return Date.now()-e6($).mtimeMs>ZX}catch{return!1}}function QX($){let X=s0($);if(!o$(X))return!1;if($1(X))return t$(X,{force:!0}),!1;return!0}function jX($){let X=s0($);if(s$(r.dirname(X),{recursive:!0}),$1(X))t$(X,{force:!0});try{let Z=s6(X,"wx");return o6(Z),!0}catch{return!1}}function KX($){$X(s0($))}function e0($){let X=r$().bridges?.[$.adapterId];if(n$($,X)&&X.status==="ready")return S($,"ready");if(k0.has($.adapterId)||QX($))return S($,"installing");if(n$($,X)&&X.status==="failed")return S($,"failed",X.error);return S($,"missing")}function z0($,X){$?.onStatusChange?.(X)}function YX($,X){let Z=e0($);if(Z.status==="ready")return z0(X,Z),Z;if(Z.status==="installing"){let K=k0.get($.adapterId);if(K&&X?.onStatusChange)K.then((H)=>z0(X,H));return z0(X,Z),Z}if(!jX($))return S($,"installing");let J=S($,"installing");i0($,J),z0(X,J);let Q=()=>{},j=new Promise((K)=>{Q=K});k0.set($.adapterId,j);let Y=!1,G=(K)=>{if(Y)return;Y=!0;try{KX($)}catch{}i0($,K),z0(X,K),k0.delete($.adapterId),Q(K)},z;try{let K=t0();z=n6(K,["-y",r0($),...$.warmupArgs],{stdio:"ignore",windowsHide:!0,...L0(K)})}catch(K){let H=S($,"failed",K instanceof Error?K.message:String(K));return G(H),H}return z.on("error",(K)=>{G(S($,"failed",K.message))}),z.on("close",(K)=>{if(K===0){G(S($,"ready"));return}G(S($,"failed",`npx warmup exited ${K??"null"}`))}),z.unref(),J}function Q0($){let X=e$($);return X?e0(X):null}async function X1($){let X=[];for(let Z of n0){if(!await w(Z.runtimeBinary)){X.push(S(Z,"not_needed"));continue}X.push(YX(Z,$))}return X.filter((Z)=>Z.status!=="not_needed")}function _0($){let X=e$($);if(!X)return null;if(e0(X).status!=="ready")return null;return{command:t0(),args:["-y",r0(X)],env:{}}}function $$($,X){if($.command!==t0())return!1;let Z=n0.find((J)=>$.args.includes(r0(J)));if(!Z)return!1;return i0(Z,S(Z,"failed",X)),!0}var Z1="claude",X$="@agentclientprotocol/claude-agent-acp",J1=["claude-agent-acp","claude-code-acp"],Q1="Install Claude Code from https://github.com/anthropics/claude-code",j1={id:"claude-code",displayName:"Claude Code",kind:"registered",supportsImages:!0,resolveSpawnConfig:async()=>{if(!await w(Z1))throw new O(`Claude Code CLI not found. ${Q1}`);let X=_0(X$);if(X)return{command:X.command,args:X.args,env:v(X.env)};let Z=Q0(X$),J=Z?.status==="installing";for(let j of J1){let Y=await w(j);if(Y&&!J&&Z?.status!=="failed")return{command:Y,args:[],env:v()}}let Q=Z?.status==="failed"?`Claude Code ACP bridge install failed. ${Z.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 O(Q)},checkReadiness:async()=>{if(!await w(Z1))return{status:"not_installed",detail:Q1};let X=Q0(X$);if(X?.status==="ready")return{status:"ready"};if(X?.status==="installing")return{status:"not_running",detail:"Installing Claude Code ACP bridge..."};if(X?.status==="failed")return{status:"not_running",detail:X.error??"Claude Code ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};for(let Z of J1)if(await w(Z))return{status:"ready"};return{status:"not_running",detail:"Installing Claude Code ACP bridge..."}},authHint:"Run `claude login` (or set ANTHROPIC_API_KEY)."};var K1="codex",Z$="@agentclientprotocol/codex-acp",Y1="codex-acp",W1="Install Codex CLI from https://developers.openai.com/codex/cli",V1={id:"codex",displayName:"Codex",kind:"registered",resolveSpawnConfig:async()=>{if(!await w(K1))throw new O(`Codex CLI not found. ${W1}`);let X=_0(Z$);if(X)return{command:X.command,args:X.args,env:v(X.env)};let Z=Q0(Z$),J=Z?.status==="installing",Q=await w(Y1);if(Q&&!J&&Z?.status!=="failed")return{command:Q,args:[],env:v()};let j=Z?.status==="failed"?`Codex ACP bridge install failed. ${Z.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 O(j)},checkReadiness:async()=>{if(!await w(K1))return{status:"not_installed",detail:W1};let X=Q0(Z$);if(X?.status==="ready")return{status:"ready"};if(X?.status==="installing")return{status:"not_running",detail:"Installing Codex ACP bridge..."};if(X?.status==="failed")return{status:"not_running",detail:X.error??"Codex ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};if(await w(Y1))return{status:"ready"};return{status:"not_running",detail:"Installing Codex ACP bridge..."}},authHint:"Run `codex login` (or set OPENAI_API_KEY)."};var z1="copilot",G1="copilot-acp",H1="npm i -g @github/copilot",U1={id:"copilot",displayName:"GitHub Copilot",kind:"registered",resolveSpawnConfig:async()=>{let $=await w(z1);if($)return{command:$,args:["--acp"],env:v()};let X=await w(G1);if(X)return{command:X,args:[],env:v()};throw new O(`Copilot not installed. Run: ${H1}`)},checkReadiness:async()=>{if(await w(z1))return{status:"ready"};if(await w(G1))return{status:"ready"};return{status:"not_installed",detail:H1}},authHint:"Run `gh auth login` (or `copilot login`)."};import WX from"node:fs/promises";function VX($){return $.startsWith("/")||/^[a-zA-Z]:[\\/]/.test($)}async function D1($){if(VX($))try{return await WX.access($),!0}catch{return!1}return await w($)!==null}var M1={id:"custom",displayName:"Custom ACP",kind:"custom",resolveSpawnConfig:async($)=>{if($.kind!=="custom")throw new O("customAdapter received non-custom entry");if(!await D1($.command))throw new O(`custom: command "${$.command}" not found`);return{command:$.command,args:$.args,env:v($.env)}},checkReadiness:async($)=>{if($.kind!=="custom")return{status:"unknown"};return await D1($.command)?{status:"ready"}:{status:"not_installed"}}};var N1="opencode",q1="Install OpenCode from https://opencode.ai",B1={id:"opencode",displayName:"OpenCode",kind:"registered",resolveSpawnConfig:async()=>{let $=await w(N1);if(!$)throw new O(`OpenCode not installed. ${q1}`);return{command:$,args:["acp"],env:v()}},checkReadiness:async()=>{if(!await w(N1))return{status:"not_installed",detail:q1};return{status:"ready"}},authHint:"Run `opencode auth login <provider>` (or set the provider's API-key env var)."};var x1={"claude-code":j1,opencode:B1,codex:V1,copilot:U1};function c($){if($.kind==="custom")return M1;let X=x1[$.adapterId];if(!X)throw Error(`Unknown registered adapter: ${$.adapterId}`);return X}function j0(){return Object.values(x1)}var J$=new Map,A0=new Map,zX=30000;function w0($,X){let Z=J$.get($);if(Z&&Z.expiresAt>Date.now())return Promise.resolve(Z.value);let J=A0.get($);if(J)return J;let Q=X().then((j)=>{return J$.set($,{value:j,expiresAt:Date.now()+zX}),j}).finally(()=>{A0.delete($)});return A0.set($,Q),Q}async function F1($){let X=await Promise.all(j0().map((j)=>w0(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 h($)).runtimes.filter((j)=>j.kind==="custom"),Q=await Promise.all(J.map((j)=>w0(`custom:${j.id}`,async()=>({adapterId:j.id,...await c(j).checkReadiness(j)}))));return[...X,...Q]}async function C1($,X){let Z=j0().find((j)=>j.id===$);if(Z)return w0(Z.id,async()=>({adapterId:Z.id,...await Z.checkReadiness({id:"__probe__",kind:"registered",adapterId:Z.id,displayName:Z.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null})}));let Q=(await h(X)).runtimes.find((j)=>j.id===$);if(!Q||Q.kind!=="custom")return null;return w0(`custom:${Q.id}`,async()=>({adapterId:Q.id,...await c(Q).checkReadiness(Q)}))}function P1(){J$.clear(),A0.clear()}function GX($){if(!$)return null;let X=$.indexOf("/");if(X<=0)return null;return $.slice(0,X)}function T0($){let X=[...$.models];if($.adapterId!=="opencode"||X.length===0)return X;let Z=GX($.currentModelId)??(X.some((Q)=>Q.id.startsWith("opencode/"))?"opencode":null);if(!Z)return X;let J=X.filter((Q)=>Q.id===$.currentModelId||Q.id.startsWith(`${Z}/`));return J.length>0?J:X}import{Readable as AX,Writable as wX}from"node:stream";import{ClientSideConnection as y1,ndJsonStream as b1}from"@agentclientprotocol/sdk";import a from"node:fs/promises";import b from"node:path";class H0 extends Error{constructor($){super($);this.name="PathTraversalError"}}class j$ extends Error{constructor($){super($);this.name="HiddenPathError"}}class K$ extends Error{constructor($){super($);this.name="RunFolderFileTooLargeError"}}class G0 extends Error{constructor($){super($);this.name="RunFolderBinaryFileError"}}var HX=new Set([".bzr",".cache",".claude",".config",".env",".git",".hg",".idea",".obsidian",".svn",".vscode","node_modules"]),L1=1e6,UX=4096,DX=new TextDecoder("utf-8",{fatal:!0});function MX($){return $.split(/[\\/]+/).filter((X)=>X.length>0)}function f0($){if(b.isAbsolute($))throw new H0("Absolute paths are not allowed");for(let X of MX($)){if(X===".")continue;if(X==="..")throw new H0("Parent-directory traversal is not allowed");if(X.startsWith(".")||HX.has(X))throw new j$(`Path segment "${X}" is hidden or configuration data`)}}function NX($){f0($);let X=b.normalize($||".");return X==="."?"":X}function qX($,X,Z){let J=b.relative($,X);if(J===".."||J.startsWith(`..${b.sep}`)||b.isAbsolute(J))throw new H0(`Path "${Z}" resolves outside the run folder`);if(J.length>0)f0(J);return J}async function Q$($,X){f0(X);let Z=b.resolve($,X||"."),J;try{J=await a.realpath(Z)}catch(Q){if(Q.code!=="ENOENT")throw Q;let j=b.dirname(Z),Y=[b.basename(Z)];while(j!==$&&j!==b.dirname(j))try{j=await a.realpath(j);break}catch(G){if(G.code!=="ENOENT")throw G;Y.unshift(b.basename(j)),j=b.dirname(j)}J=b.join(j,...Y)}return qX($,J,X),J}async function BX($,X){let Z=await a.realpath($);return Q$(Z,X)}function xX($){let X=$.subarray(0,Math.min($.length,UX));if(X.length===0)return!1;let Z=0;for(let J of X){if(J===0)return!0;let Q=J===9||J===10||J===12||J===13;if(J<32&&!Q)Z+=1}return Z/X.length>0.3}async function R0($,X){let Z=await BX($,X),J=await a.stat(Z);if(!J.isFile())throw new G0(`Path "${X}" is not a text file`);if(J.size>L1)throw new K$(`File "${X}" is too large to read (${J.size} bytes, max ${L1} bytes)`);let Q=await a.readFile(Z);if(xX(Q))throw new G0(`File "${X}" appears to be binary, not text`);try{return DX.decode(Q)}catch{throw new G0(`File "${X}" is not valid UTF-8 text`)}}function FX($){if($.isDirectory())return"directory";if($.isFile())return"file";if($.isSymbolicLink())return"symlink";return"other"}function k1($){return $.split(b.sep).join("/")}async function O1($,X=""){let Z=await a.realpath($),J=NX(X),Q=await Q$(Z,J),j=await a.readdir(Q,{withFileTypes:!0}),Y=[];for(let G of j){let z=J?b.join(J,G.name):G.name;try{f0(z);let K=await Q$(Z,z),H=await a.stat(K);Y.push({name:G.name,path:k1(z),type:FX(G),size:G.isFile()?H.size:null})}catch{}}return Y.sort((G,z)=>{if(G.type==="directory"&&z.type!=="directory")return-1;if(G.type!=="directory"&&z.type==="directory")return 1;return G.name.localeCompare(z.name)}),{path:k1(J),absolutePath:Q,entries:Y}}var Y$={fs:{readTextFile:!0,writeTextFile:!1},terminal:!1};function _1($){return{readTextFile:async(X)=>{return{content:await R0($,X.path)}}}}import{spawn as CX}from"node:child_process";function W$($){let X=CX($.command,$.args,{cwd:$.cwd,env:$.env,stdio:["pipe","pipe","pipe"],...L0($.command)});if(!X.stdin||!X.stdout||!X.stderr)throw Error("Failed to allocate stdio streams for ACP subprocess");let{stdin:Z,stdout:J,stderr:Q}=X,j=4096,Y=[],G=0;Q.on("data",(V)=>{Y.push(V),G+=V.length;while(G>j*2&&Y.length>1){let D=Y.shift();if(D)G-=D.length}});let z=()=>{let V=Buffer.concat(Y).toString("utf8");return V.length>j?V.slice(-j):V},K=!1,H=!1,B,U,M=new Promise((V)=>{B=V}),N=new Promise((V)=>{U=V}),F=(V)=>{if(H)return;if(H=!0,B(V),!K)U(V)};return X.on("exit",(V,D)=>{F({code:V,signal:D,stderr:z()})}),X.on("error",(V)=>{let D=z(),x=V?.message??String(V);F({code:null,signal:null,stderr:D?`${x}
4
+ ${D}`:x})}),{stdin:Z,stdout:J,stderr:Q,kill:(V="SIGTERM")=>{if(K)return;K=!0;try{X.kill(V)}catch{}},waitForExit:M,processCrashed:N}}var PX=["mcp_ideawave_board_","ideawave_board_","ideawave-board_","ideawave-board.","ideawave.board."];function LX($){let X=$.toLowerCase();for(let Z of PX)if(X.startsWith(Z))return $.slice(Z.length);if(/^mcp[-_.]/i.test($))return $.slice(4);return $}function E0($){return LX($.trim())}function V$($){let X=E0($);if(!X)return"Tool";if(!/[-_.]/.test(X))return X.charAt(0).toUpperCase()+X.slice(1);let Z=X.replace(/[-_.]+/g," ").replace(/\s+/g," ").trim();if(!Z)return"Tool";return Z.charAt(0).toUpperCase()+Z.slice(1)}function z$($){let X=$?.toLowerCase();if(X==="completed"||X==="complete"||X==="done"||X==="success"||X==="succeeded")return"completed";if(X==="failed"||X==="error"||X==="errored")return"failed";return"running"}function G$($){if(typeof $!=="string")return null;let X=$.trim();return X?X:null}function A1($){if(typeof $!=="string")return"Tool";let X=$.trim();return X?X:"Tool"}function kX($,X){if(!$||typeof $!=="object"||Array.isArray($))return null;let Z=$;for(let J of X){let Q=Z[J];if(typeof Q==="string"&&Q.trim())return Q.trim()}return null}function H$($,X){let Z=$.trim().toLowerCase();if(Z==="skill"||Z==="workflow"||Z==="tool"||Z==="invalid"){let J=kX(X,["skillName","workflowName","toolName","name","title"]);if(J){let Q=Z==="skill"?" skill":Z==="workflow"?" workflow":"";return`${V$(J)}${Q}`}}if(Z==="invalid")return"Tool call";return V$($)}var OX=33,w1=1600;function e($){if($.length<=w1)return $;return`${$.slice(0,w1-22)}
5
+ ... truncated`}function b0($){let X=$.replace(/\r\n?/g,`
6
6
  `),Z=X.trim();if(Z.startsWith('"')&&Z.endsWith('"')||Z.startsWith("'")&&Z.endsWith("'"))try{let Q=JSON.parse(Z);if(typeof Q==="string")return Q.replace(/\r\n?/g,`
7
7
  `)}catch{return X}if(!X.includes("\\\""))return X;let J=X.replace(/\\r\\n/g,`
8
8
  `).replace(/\\n/g,`
9
9
  `).replace(/\\r/g,`
10
- `).replace(/\\t/g,"\t").replace(/\\"/g,'"');try{let Q=JSON.parse(J);if(Q!==null&&typeof Q==="object")return J}catch{return X}return X}function l($){if($===void 0||$===null)return null;if(typeof $==="string"){let X=y0($).trim();return X?e(X):null}if(typeof $==="number"||typeof $==="boolean"||typeof $==="bigint")return String($);try{return e(JSON.stringify($,null,2))}catch{return e(y0(String($)))}}function L6($){if(!$||typeof $!=="object")return null;let X=$;if(X.type==="text"&&typeof X.text==="string")return y0(X.text);if(X.type==="image")return"[image]";if(X.type==="resource")return"[resource]";if(X.type==="content"){let Z=X.content;if(Z&&typeof Z==="object"){let J=Z;if(J.type==="text"&&typeof J.text==="string")return y0(J.text);if(J.type==="image")return"[image]";if(J.type==="resource")return"[resource]"}}if(X.type==="diff")return`Diff: ${typeof X.path==="string"?X.path:"unknown file"}`;if(X.type==="terminal")return`Terminal: ${typeof X.terminalId==="string"?X.terminalId:"terminal"}`;return l($)}function E0($){if(!Array.isArray($))return null;let X=$.map(L6).filter((Z)=>Boolean(Z?.trim()));if(X.length===0)return null;return e(X.join(`
10
+ `).replace(/\\t/g,"\t").replace(/\\"/g,'"');try{let Q=JSON.parse(J);if(Q!==null&&typeof Q==="object")return J}catch{return X}return X}function l($){if($===void 0||$===null)return null;if(typeof $==="string"){let X=b0($).trim();return X?e(X):null}if(typeof $==="number"||typeof $==="boolean"||typeof $==="bigint")return String($);try{return e(JSON.stringify($,null,2))}catch{return e(b0(String($)))}}function _X($){if(!$||typeof $!=="object")return null;let X=$;if(X.type==="text"&&typeof X.text==="string")return b0(X.text);if(X.type==="image")return"[image]";if(X.type==="resource")return"[resource]";if(X.type==="content"){let Z=X.content;if(Z&&typeof Z==="object"){let J=Z;if(J.type==="text"&&typeof J.text==="string")return b0(J.text);if(J.type==="image")return"[image]";if(J.type==="resource")return"[resource]"}}if(X.type==="diff")return`Diff: ${typeof X.path==="string"?X.path:"unknown file"}`;if(X.type==="terminal")return`Terminal: ${typeof X.terminalId==="string"?X.terminalId:"terminal"}`;return l($)}function y0($){if(!Array.isArray($))return null;let X=$.map(_X).filter((Z)=>Boolean(Z?.trim()));if(X.length===0)return null;return e(X.join(`
11
11
 
12
- `))}function H$($){if(!$||typeof $!=="object"||Array.isArray($))return l($);let X=$,Z=E0(X.content);if(Z)return Z;for(let j of["output","result","text","message"]){let K=l(X[j]);if(K)return K}let J=l(X.stdout),Q=l(X.stderr);if(J||Q)return e([J?`stdout:
12
+ `))}function U$($){if(!$||typeof $!=="object"||Array.isArray($))return l($);let X=$,Z=y0(X.content);if(Z)return Z;for(let j of["output","result","text","message"]){let Y=l(X[j]);if(Y)return Y}let J=l(X.stdout),Q=l(X.stderr);if(J||Q)return e([J?`stdout:
13
13
  ${J}`:null,Q?`stderr:
14
14
  ${Q}`:null].filter(Boolean).join(`
15
15
 
16
- `));return l($)}function w1($,X){if(!X)return $;if(!$)return X;if($===X||$.endsWith(X))return $;if(X.startsWith($))return X;return e(`${$}
16
+ `));return l($)}function T1($,X){if(!X)return $;if(!$)return X;if($===X||$.endsWith(X))return $;if(X.startsWith($))return X;return e(`${$}
17
17
 
18
- ${X}`)}function U$($){if(!Array.isArray($))return null;let X=$.flatMap((Z)=>{if(!Z||typeof Z!=="object")return[];let J=Z;if(typeof J.path!=="string"||!J.path.trim())return[];let Q=typeof J.line==="number"?`:${J.line}`:"";return[`${J.path}${Q}`]});return X.length>0?X.slice(0,5):null}function T1($){let{ctx:X,appendText:Z,appendToolActivity:J}=$,Q=$.flushIntervalMs??P6,j="",K="",G=0,z=null,W={},H=new Map,B=(P)=>{if(H.set(P.toolCallId,P),!J)return;J({boardId:X.boardId,cardId:X.cardId,runId:X.runId,entry:P}).catch((Y)=>{console.warn("[streamAdapter] appendToolActivity failed",Y)})},U=(P)=>{let Y=`${X.runId}:thought`,C=H.get(Y);if(!C||C.status!=="running")return;B({...C,status:"completed",completedAt:C.completedAt??P})},M=(P)=>{for(let Y of H.values()){if(Y.status!=="running"||Y.rawTitle.toLowerCase()!=="toolsearch")continue;B({...Y,status:"completed",completedAt:Y.completedAt??P})}},N=(P)=>{for(let Y of Array.from(H.values())){if(Y.status!=="running")continue;if(Y.kind==="thought"||Y.rawTitle==="agent_thought")continue;B({...Y,status:"completed",completedAt:Y.completedAt??P})}},F="",V=0,D=null,x=null,k=(P)=>{if(P===F)return;F=P,V=Date.now(),Z({boardId:X.boardId,cardId:X.cardId,runId:X.runId,text:P}).catch((Y)=>{console.warn("[streamAdapter] appendText failed",Y)})},A=()=>{if(D!==null)clearTimeout(D),D=null;if(x!==null){let P=x;x=null,k(P)}},_=(P)=>{let Y=Date.now()-V;if(Y>=Q&&D===null){k(P);return}if(x=P,D===null){let C=Math.max(0,Q-Y);D=setTimeout(()=>{D=null,A()},C)}};return{onSessionUpdate:async(P)=>{let Y=P.update;switch(W[Y.sessionUpdate]=(W[Y.sessionUpdate]??0)+1,Y.sessionUpdate){case"agent_message_chunk":{let C=new Date().toISOString();if(U(C),Y.content.type==="text")j+=Y.content.text,_(j);else{let T=`agent_message_chunk:${Y.content.type}`;W[T]=(W[T]??0)+1}return}case"agent_thought_chunk":{if(Y.content.type!=="text")return;K+=Y.content.text;let C=new Date().toISOString(),T=`${X.runId}:thought`,f=H.get(T);B({toolCallId:T,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:f?.startedAt??C,completedAt:null,contentPreview:e(K.trim())});return}case"user_message_chunk":return;case"tool_call":{G+=1;let C=_1(Y.title),T=V$(Y.status),f=new Date().toISOString();U(f),M(f),B({toolCallId:Y.toolCallId,rawTitle:C,title:G$(C,Y.rawInput),kind:z$(Y.kind),status:T,startedAt:f,completedAt:T==="running"?null:f,inputPreview:l(Y.rawInput),outputPreview:H$(Y.rawOutput),contentPreview:E0(Y.content),locations:U$(Y.locations)});return}case"tool_call_update":{let C=H.get(Y.toolCallId);if(!C){let p=_1(Y.title),B0=V$(Y.status),X0=new Date().toISOString();B({toolCallId:Y.toolCallId,rawTitle:p,title:G$(p,Y.rawInput),kind:z$(Y.kind),status:B0,startedAt:X0,completedAt:B0==="running"?null:X0,inputPreview:l(Y.rawInput),outputPreview:H$(Y.rawOutput),contentPreview:E0(Y.content),locations:U$(Y.locations)});return}let T=Y.status===void 0||Y.status===null?C.status:V$(Y.status),f=typeof Y.title==="string"&&Y.title.trim().length>0?Y.title:C.rawTitle,L=typeof Y.title==="string"&&Y.title.trim().length>0,R=T==="running"?C.completedAt:C.completedAt??new Date().toISOString(),E=Y.content===void 0?C.contentPreview:w1(C.contentPreview,E0(Y.content)),I=Y.rawOutput===void 0?C.outputPreview:w1(C.outputPreview,H$(Y.rawOutput));B({...C,rawTitle:f,title:L?G$(f,Y.rawInput):C.title,kind:Y.kind===void 0?C.kind:z$(Y.kind),status:T,completedAt:R,inputPreview:Y.rawInput===void 0?C.inputPreview:l(Y.rawInput),outputPreview:I,contentPreview:E,locations:Y.locations===void 0?C.locations:U$(Y.locations)});return}case"plan":z=Y.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>j,getToolCallCount:()=>G,getLatestPlan:()=>z,getUpdateTypeCounts:()=>({...W}),flush:(P)=>{let Y=new Date().toISOString();if(U(Y),P?.completeOpenToolCalls)N(Y);A()}}}var U0=1,f1=-32000;function R1($){if($.awaitingInput)return!1;return $.nowMs-$.lastUpdateMs>$.windowMs}function b1($){if(!$||typeof $!=="object")return!1;return $.code===f1}var _6=300000,A6=5000;function v1(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.47".trim()?"0.0.47":"dev"}}function I1($){if($===U0)return;throw new O(`Unsupported ACP protocol version ${$}; expected ${U0}`)}function h1($){return k6.toWeb($)}function S1($){return O6.toWeb($)}function D$($){return $!==null&&typeof $==="object"}function w6($){if(!Array.isArray($))return[];let X=[];for(let Z of $){if(!D$(Z))continue;if(typeof Z.group==="string"&&Array.isArray(Z.options)){let J=typeof Z.name==="string"?Z.name:Z.group;for(let Q of Z.options){if(!D$(Q))continue;if(typeof Q.value!=="string"||typeof Q.name!=="string")continue;X.push({value:Q.value,name:Q.name,description:typeof Q.description==="string"?Q.description:null,group:Z.group,groupName:J})}continue}if(typeof Z.value!=="string"||typeof Z.name!=="string")continue;X.push({value:Z.value,name:Z.name,description:typeof Z.description==="string"?Z.description:null,group:null,groupName:null})}return X}function T6($){if(!D$($))return null;if(typeof $.id!=="string"||typeof $.name!=="string")return null;let X=typeof $.category==="string"?$.category:null,Z=typeof $.description==="string"?$.description:null;if($.type==="select"){let J=typeof $.currentValue==="string"?$.currentValue:null;return{id:$.id,name:$.name,category:X,description:Z,type:"select",currentValue:J,options:w6($.options)}}if($.type==="boolean"){let J=typeof $.currentValue==="boolean"?$.currentValue:typeof $.value==="boolean"?$.value:null;return{id:$.id,name:$.name,category:X,description:Z,type:"boolean",currentValue:J,options:[]}}return null}function M$($){let X=($.configOptions??[]).map(T6).filter((G)=>G!==null),Z=X.find((G)=>G.type==="select"&&G.category==="model")??X.find((G)=>G.type==="select"&&G.id==="model")??null,J=Z?.options.map((G)=>({id:G.value,name:G.name,description:G.description??null})),Q=f6($.models),j=J&&J.length>0?J:Q&&Q.length>0?Q:null,K=(typeof Z?.currentValue==="string"?Z.currentValue:null)??R6($.models)??null;return{models:j,currentModelId:K,configOptions:X,modelConfigId:Z?.id??null}}function f6($){if(!$||!Array.isArray($.availableModels))return null;let X=[];for(let Z of $.availableModels){if(typeof Z.modelId!=="string")continue;X.push({id:Z.modelId,name:typeof Z.name==="string"?Z.name:null,description:typeof Z.description==="string"?Z.description:null})}return X.length>0?X:null}function R6($){return typeof $?.currentModelId==="string"?$.currentModelId:null}function E6($,X){let Z=[];if($.trim())Z.push({type:"text",text:$});for(let J of X)if(J.content.trim())Z.push({type:"text",text:J.content});return Z}function y6($){if(typeof $.value==="boolean")return{sessionId:$.sessionId,configId:$.configId,type:"boolean",value:$.value};return{sessionId:$.sessionId,configId:$.configId,value:$.value}}function b6($,X){let Z=M$({configOptions:X.configOptions});return{models:Z.models??$.models,currentModelId:Z.currentModelId??$.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??$.modelConfigId}}function m1($,X){if($==="default")return null;if(!X||X.length===0)return $;let Z=X.find((W)=>W.id===$);if(Z)return Z.id;let J=$.toLowerCase(),Q=J.includes("opus")?"opus":J.includes("sonnet")?"sonnet":J.includes("haiku")?"haiku":null;if(!Q)return $;let j=(W)=>`${W.id} ${W.name??""} ${W.description??""}`.toLowerCase(),K=X.filter((W)=>j(W).includes(Q));if(K.length===0)return $;let z=(J.includes("1m")?K.find((W)=>j(W).includes("1m")):void 0)??K[0];return z?z.id:$}async function b0($){try{let X=await $.conn.setSessionConfigOption(y6({sessionId:$.sessionId,configId:$.configId,value:$.value}));return b6($.metadata,X)}catch(X){return console.warn(`[acp] setSessionConfigOption(${$.label}) failed; using agent default.`,X instanceof Error?X.message:X),$.metadata}}async function N$($){let X=W$($.spawn),Z=[],J=0,Q=4096;X.stderr.on("data",(L)=>{Z.push(L),J+=L.length;while(J>Q*2&&Z.length>1){let R=Z.shift();if(R)J-=R.length}});let j=()=>{let L=Buffer.concat(Z).toString("utf8");return L.length>Q?L.slice(-Q):L},K=O1($.spawn.cwd),G={current:null},z={at:Date.now()},W=S1(X.stdin),H=h1(X.stdout),B=y1(W,H),M=new E1((L)=>({requestPermission:async(R)=>{let E=R.options,I=E?.find((p)=>p.kind==="allow_once")??E?.find((p)=>p.kind==="allow_always");if(I)return{outcome:{outcome:"selected",optionId:I.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(R)=>{z.at=Date.now();let E=G.current;if(E)await E.onSessionUpdate(R)},readTextFile:K.readTextFile}),B),N=()=>X.kill();if($.signal)$.signal.addEventListener("abort",N);let F=()=>{if($.signal)$.signal.removeEventListener("abort",N)},V=async(L,R)=>{if(F(),X.kill(),b1(L))throw new J0(L.message??"Authentication required",R);if(L instanceof Error&&L.message==="ACP connection closed"){if($.signal?.aborted)throw new O("ACP session cancelled: abort signal received");let E=await Promise.race([X.processCrashed,X.waitForExit,new Promise((I)=>setTimeout(()=>I({stderr:""}),500))]);throw new O(`Runtime process exited before completion: ${E.stderr?.trim()??""}`)}throw L},D;try{D=await M.initialize({protocolVersion:U0,clientCapabilities:K$,clientInfo:v1()})}catch(L){throw await V(L,[]),Error("unreachable")}try{I1(D.protocolVersion)}catch(L){throw F(),X.kill(),L}let x=D.authMethods?.map((L)=>L.id)??[],k;try{k=await M.newSession({cwd:$.spawn.cwd,mcpServers:$.mcpServers??[]})}catch(L){throw await V(L,x),Error("unreachable")}let A=k.sessionId,_=M$(k),P=$.modelId??null,Y=P?m1(P,_.models):null;if(Y&&Y!==_.currentModelId)if(_.modelConfigId)_=await b0({conn:M,sessionId:A,configId:_.modelConfigId,value:Y,metadata:_,label:`${_.modelConfigId}=${Y}`});else console.warn(`[acp] runtime did not advertise a model config option for ${Y}; using agent default.`);for(let[L,R]of Object.entries($.configValues??{}).sort(([E],[I])=>E.localeCompare(I))){if(L===_.modelConfigId)continue;if(!_.configOptions.some((E)=>E.id===L))continue;_=await b0({conn:M,sessionId:A,configId:L,value:R,metadata:_,label:`${L}=${String(R)}`})}F();let C=!1,T=async()=>{if(C)return;C=!0,X.kill(),await Promise.race([X.waitForExit,new Promise((L)=>setTimeout(L,2000))])},f=!1;return X.processCrashed.then(()=>{f=!0}),{sessionId:A,availableModels:_.models,currentModelId:_.currentModelId,availableConfigOptions:_.configOptions,isAlive:()=>!C&&!f,dispose:T,prompt:(L)=>v6({proc:X,conn:M,sessionId:A,activeAdapter:G,lastUpdate:z,collectStderrTail:j},L)}}async function v6($,X){let{proc:Z,conn:J,sessionId:Q,activeAdapter:j,lastUpdate:K}=$,G={boardId:X.boardId,cardId:X.cardId,runId:X.runId},z=T1({ctx:G,appendText:X.appendText,appendToolActivity:X.appendToolActivity});j.current=z,K.at=Date.now();let W=!1,H=null,B=()=>Z.kill();X.signal.addEventListener("abort",B);try{let U=async()=>{let V=X.heartbeatMs??_6,D=Math.min(A6,Math.max(50,Math.floor(V/2)));H=setInterval(()=>{let k=X.isAwaitingInput?.()??!1;if(k){K.at=Date.now();return}if(R1({nowMs:Date.now(),lastUpdateMs:K.at,windowMs:V,awaitingInput:k}))W=!0,J.cancel({sessionId:Q}).catch(()=>{return}),Z.kill()},D);let x=E6(X.prompt.systemPrompt,X.prompt.messages);await J.prompt({sessionId:Q,prompt:x}),z.flush({completeOpenToolCalls:!0})},M=Z.waitForExit.then((V)=>({kind:"exited",exit:V})),N=U().then(()=>({kind:"ok"})).catch(async(V)=>{if(V instanceof Error&&V.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw V}),F;try{F=await Promise.race([N,Z.processCrashed.then((V)=>({kind:"crashed",exit:V})),M])}catch(V){if(W)throw new d;throw V}if(W)throw new d;if(F.kind==="crashed")throw new O(`Runtime process exited before completion: ${F.exit.stderr.trim()}`);if(F.kind==="exited"){if(X.signal.aborted)throw new O("ACP session cancelled: abort signal received");if(W)throw new d;throw new O(`Runtime process exited unexpectedly: ${F.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:z.getFinalText(),toolCallsExecuted:z.getToolCallCount(),stderrTail:$.collectStderrTail(),updateTypeCounts:z.getUpdateTypeCounts()}}finally{if(H!==null)clearInterval(H);X.signal.removeEventListener("abort",B),z.flush({completeOpenToolCalls:!0}),j.current=null}}var I6=30000;async function g1($){let X=W$($.spawn),Z=S1(X.stdin),J=h1(X.stdout),Q=y1(Z,J),K=new E1((W)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),G=()=>X.kill();if($.signal)$.signal.addEventListener("abort",G);let z=null;try{let W=(async()=>{let B=await K.initialize({protocolVersion:U0,clientCapabilities:K$,clientInfo:v1()});I1(B.protocolVersion);let U=B.authMethods?.map((k)=>k.id)??[],M;try{M=await K.newSession({cwd:$.spawn.cwd,mcpServers:[]})}catch(k){if(b1(k))throw new J0(k.message??"Authentication required",U);throw k}let N=M$(M),F=$.modelId??null,V=F?m1(F,N.models):null;if(V&&V!==N.currentModelId)if(N.modelConfigId)N=await b0({conn:K,sessionId:M.sessionId,configId:N.modelConfigId,value:V,metadata:N,label:`${N.modelConfigId}=${V}`});else console.warn(`[acp] runtime did not advertise a model config option for ${V}; discovering agent default models.`);for(let[k,A]of Object.entries($.configValues??{}).sort(([_],[P])=>_.localeCompare(P))){if(k===N.modelConfigId)continue;if(!N.configOptions.some((_)=>_.id===k))continue;N=await b0({conn:K,sessionId:M.sessionId,configId:k,value:A,metadata:N,label:`${k}=${String(A)}`})}let D=N.models??[],x=N.currentModelId;return K.cancel({sessionId:M.sessionId}).catch(()=>{return}),{models:D,configOptions:N.configOptions,currentModelId:x}})(),H=new Promise((B,U)=>{z=setTimeout(()=>{U(new d)},I6)});return await Promise.race([W,H])}catch(W){if(W instanceof Error&&W.message==="ACP connection closed"){if($.signal?.aborted)throw new O("ACP model discovery cancelled: abort signal received");throw new O("Runtime process exited during model discovery.")}throw W}finally{if(z)clearTimeout(z);if($.signal)$.signal.removeEventListener("abort",G);X.kill()}}var y=new Map,u=null;function v0($){$.then((X)=>X.dispose()).catch(()=>{return})}function h6(){if(u!==null)return;u=setInterval(()=>{let $=Date.now();for(let[X,Z]of y){if(Z.inUse)continue;if($-Z.lastUsed<600000)continue;y.delete(X),v0(Z.sessionPromise)}if(y.size===0&&u!==null)clearInterval(u),u=null},60000),u.unref?.()}function S6(){if(y.size<200)return;let $=null,X=1/0;for(let[J,Q]of y){if(Q.inUse)continue;if(Q.lastUsed>=X)continue;$=J,X=Q.lastUsed}if(!$)return;let Z=y.get($);if(!Z)return;y.delete($),v0(Z.sessionPromise)}function q$($,X,Z){return`${$}:${X}:${Z}`}async function B$($){let X=y.get($.key);if(X)if(X.fingerprint===$.fingerprint){X.inUse=!0,X.lastUsed=Date.now();try{let J=await X.sessionPromise;if(J.isAlive())return J}catch{}y.delete($.key)}else y.delete($.key),v0(X.sessionPromise);let Z=$.open();S6(),y.set($.key,{key:$.key,fingerprint:$.fingerprint,sessionPromise:Z,lastUsed:Date.now(),inUse:!0}),h6();try{return await Z}catch(J){throw y.delete($.key),J}}function x$($,X=!1){let Z=y.get($);if(!Z)return;if(X){y.delete($),v0(Z.sessionPromise);return}Z.inUse=!1,Z.lastUsed=Date.now()}async function m6(){let $=Array.from(y.values());if(y.clear(),u!==null)clearInterval(u),u=null;await Promise.all($.map((X)=>X.sessionPromise.then((Z)=>Z.dispose()).catch(()=>{return})))}function F$($){let X=Object.entries($.configValues??{}),Z=X.length>0?JSON.stringify(Object.fromEntries(X.sort(([J],[Q])=>J.localeCompare(Q)))):"";return[$.adapterId,$.configId??"",$.modelId??"",Z,$.mcpUrl??"",$.runFolder??"",$.toolSurface??"full"].join(" ")}var c1=!1;function g6(){if(c1)return;c1=!0;let $=()=>{m6()};process.once("beforeExit",$),process.once("SIGTERM",$),process.once("SIGINT",$)}g6();import c6 from"node:fs/promises";import I0 from"node:os";async function l1($){let X={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await c6.readFile($,"utf-8")}catch(J){if(J.code==="ENOENT")return structuredClone(X);throw J}return F0.parse(JSON.parse(Z))}function C$($,X,Z){return{...$.defaultConfigValues??{},...X?.configValues??{},...Z?.configValues??{}}}async function i($){let X=$.configPath?await l1($.configPath):await h(),Z=$.cardId?X.cardOverrides[$.cardId]:void 0;if(Z?.runtimeConfigId){let Q=X.runtimes.find((j)=>j.id===Z.runtimeConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:Z.runFolder??Q.runFolder??I0.homedir(),modelId:Z.modelId??Q.defaultModelId??null,configValues:C$(Q,void 0,Z)}}let J=X.boardOverrides[$.boardId];if(J?.runtimeConfigId){let Q=X.runtimes.find((j)=>j.id===J.runtimeConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:J.runFolder??Q.runFolder??I0.homedir(),modelId:J.modelId??Q.defaultModelId??null,configValues:C$(Q,J)}}if(X.globalDefaultConfigId){let Q=X.runtimes.find((j)=>j.id===X.globalDefaultConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:Z?.runFolder??J?.runFolder??Q.runFolder??I0.homedir(),modelId:Z?.modelId??J?.modelId??Q.defaultModelId??null,configValues:C$(Q,J,Z)}}throw new t}async function u1($,X={}){let J=(X.configPath?await l1(X.configPath):await h()).runtimes.find((Q)=>Q.id===$);if(!J)return null;return{entry:J,adapter:c(J),runFolder:J.runFolder??I0.homedir(),modelId:X.modelId??J.defaultModelId??null,configValues:{...J.defaultConfigValues??{},...X.configValues??{}}}}var p1=new Map;function P$($,X){if(!$)return;p1.set($,X)}function d1($){if(!$)return!1;return p1.get($)??!1}var $0=new Map,L$=new Set;function k$($){$0.get($)?.controller.abort()}function a1($){for(let[X,Z]of $0){if(Z.frontendSessionId!==$)continue;Z.controller.abort(),$0.delete(X)}}function i1(){for(let $ of $0.values())$.controller.abort();$0.clear()}function n1($,X){if(X?.aborted)return!0;return $ instanceof Error&&/abort signal received|session cancelled/i.test($.message)}function o1($,X,Z,J){if((!X.availableModels||X.availableModels.length===0)&&X.availableConfigOptions.length===0)return;g((Q)=>{let j=Q.runtimes.find((K)=>K.id===$);if(j){if(X.availableModels&&X.availableModels.length>0)j.discoveredModels=w0({adapterId:Z,models:X.availableModels,currentModelId:X.currentModelId??J});if(X.availableConfigOptions.length>0)j.discoveredConfigOptions=X.availableConfigOptions}}).catch(()=>{return})}function l6($,X){return`${$}
18
+ ${X}`)}function D$($){if(!Array.isArray($))return null;let X=$.flatMap((Z)=>{if(!Z||typeof Z!=="object")return[];let J=Z;if(typeof J.path!=="string"||!J.path.trim())return[];let Q=typeof J.line==="number"?`:${J.line}`:"";return[`${J.path}${Q}`]});return X.length>0?X.slice(0,5):null}function f1($){let{ctx:X,appendText:Z,appendToolActivity:J}=$,Q=$.flushIntervalMs??OX,j="",Y="",G=0,z=null,K={},H=new Map,B=(P)=>{if(H.set(P.toolCallId,P),!J)return;J({boardId:X.boardId,cardId:X.cardId,runId:X.runId,entry:P}).catch((W)=>{console.warn("[streamAdapter] appendToolActivity failed",W)})},U=(P)=>{let W=`${X.runId}:thought`,C=H.get(W);if(!C||C.status!=="running")return;B({...C,status:"completed",completedAt:C.completedAt??P})},M=(P)=>{for(let W of H.values()){if(W.status!=="running"||W.rawTitle.toLowerCase()!=="toolsearch")continue;B({...W,status:"completed",completedAt:W.completedAt??P})}},N=(P)=>{for(let W of Array.from(H.values())){if(W.status!=="running")continue;if(W.kind==="thought"||W.rawTitle==="agent_thought")continue;B({...W,status:"completed",completedAt:W.completedAt??P})}},F="",V=0,D=null,x=null,k=(P)=>{if(P===F)return;F=P,V=Date.now(),Z({boardId:X.boardId,cardId:X.cardId,runId:X.runId,text:P}).catch((W)=>{console.warn("[streamAdapter] appendText failed",W)})},A=()=>{if(D!==null)clearTimeout(D),D=null;if(x!==null){let P=x;x=null,k(P)}},_=(P)=>{let W=Date.now()-V;if(W>=Q&&D===null){k(P);return}if(x=P,D===null){let C=Math.max(0,Q-W);D=setTimeout(()=>{D=null,A()},C)}};return{onSessionUpdate:async(P)=>{let W=P.update;switch(K[W.sessionUpdate]=(K[W.sessionUpdate]??0)+1,W.sessionUpdate){case"agent_message_chunk":{let C=new Date().toISOString();if(U(C),W.content.type==="text")j+=W.content.text,_(j);else{let T=`agent_message_chunk:${W.content.type}`;K[T]=(K[T]??0)+1}return}case"agent_thought_chunk":{if(W.content.type!=="text")return;Y+=W.content.text;let C=new Date().toISOString(),T=`${X.runId}:thought`,f=H.get(T);B({toolCallId:T,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:f?.startedAt??C,completedAt:null,contentPreview:e(Y.trim())});return}case"user_message_chunk":return;case"tool_call":{G+=1;let C=A1(W.title),T=z$(W.status),f=new Date().toISOString();U(f),M(f),B({toolCallId:W.toolCallId,rawTitle:C,title:H$(C,W.rawInput),kind:G$(W.kind),status:T,startedAt:f,completedAt:T==="running"?null:f,inputPreview:l(W.rawInput),outputPreview:U$(W.rawOutput),contentPreview:y0(W.content),locations:D$(W.locations)});return}case"tool_call_update":{let C=H.get(W.toolCallId);if(!C){let p=A1(W.title),B0=z$(W.status),X0=new Date().toISOString();B({toolCallId:W.toolCallId,rawTitle:p,title:H$(p,W.rawInput),kind:G$(W.kind),status:B0,startedAt:X0,completedAt:B0==="running"?null:X0,inputPreview:l(W.rawInput),outputPreview:U$(W.rawOutput),contentPreview:y0(W.content),locations:D$(W.locations)});return}let T=W.status===void 0||W.status===null?C.status:z$(W.status),f=typeof W.title==="string"&&W.title.trim().length>0?W.title:C.rawTitle,L=typeof W.title==="string"&&W.title.trim().length>0,R=T==="running"?C.completedAt:C.completedAt??new Date().toISOString(),E=W.content===void 0?C.contentPreview:T1(C.contentPreview,y0(W.content)),I=W.rawOutput===void 0?C.outputPreview:T1(C.outputPreview,U$(W.rawOutput));B({...C,rawTitle:f,title:L?H$(f,W.rawInput):C.title,kind:W.kind===void 0?C.kind:G$(W.kind),status:T,completedAt:R,inputPreview:W.rawInput===void 0?C.inputPreview:l(W.rawInput),outputPreview:I,contentPreview:E,locations:W.locations===void 0?C.locations:D$(W.locations)});return}case"plan":z=W.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>j,getToolCallCount:()=>G,getLatestPlan:()=>z,getUpdateTypeCounts:()=>({...K}),flush:(P)=>{let W=new Date().toISOString();if(U(W),P?.completeOpenToolCalls)N(W);A()}}}var U0=1,R1=-32000;function E1($){if($.awaitingInput)return!1;return $.nowMs-$.lastUpdateMs>$.windowMs}function v1($){if(!$||typeof $!=="object")return!1;return $.code===R1}var TX=300000,fX=5000;function I1(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.49".trim()?"0.0.49":"dev"}}function h1($){if($===U0)return;throw new O(`Unsupported ACP protocol version ${$}; expected ${U0}`)}function S1($){return AX.toWeb($)}function m1($){return wX.toWeb($)}function M$($){return $!==null&&typeof $==="object"}function RX($){if(!Array.isArray($))return[];let X=[];for(let Z of $){if(!M$(Z))continue;if(typeof Z.group==="string"&&Array.isArray(Z.options)){let J=typeof Z.name==="string"?Z.name:Z.group;for(let Q of Z.options){if(!M$(Q))continue;if(typeof Q.value!=="string"||typeof Q.name!=="string")continue;X.push({value:Q.value,name:Q.name,description:typeof Q.description==="string"?Q.description:null,group:Z.group,groupName:J})}continue}if(typeof Z.value!=="string"||typeof Z.name!=="string")continue;X.push({value:Z.value,name:Z.name,description:typeof Z.description==="string"?Z.description:null,group:null,groupName:null})}return X}function EX($){if(!M$($))return null;if(typeof $.id!=="string"||typeof $.name!=="string")return null;let X=typeof $.category==="string"?$.category:null,Z=typeof $.description==="string"?$.description:null;if($.type==="select"){let J=typeof $.currentValue==="string"?$.currentValue:null;return{id:$.id,name:$.name,category:X,description:Z,type:"select",currentValue:J,options:RX($.options)}}if($.type==="boolean"){let J=typeof $.currentValue==="boolean"?$.currentValue:typeof $.value==="boolean"?$.value:null;return{id:$.id,name:$.name,category:X,description:Z,type:"boolean",currentValue:J,options:[]}}return null}function N$($){let X=($.configOptions??[]).map(EX).filter((G)=>G!==null),Z=X.find((G)=>G.type==="select"&&G.category==="model")??X.find((G)=>G.type==="select"&&G.id==="model")??null,J=Z?.options.map((G)=>({id:G.value,name:G.name,description:G.description??null})),Q=yX($.models),j=J&&J.length>0?J:Q&&Q.length>0?Q:null,Y=(typeof Z?.currentValue==="string"?Z.currentValue:null)??bX($.models)??null;return{models:j,currentModelId:Y,configOptions:X,modelConfigId:Z?.id??null}}function yX($){if(!$||!Array.isArray($.availableModels))return null;let X=[];for(let Z of $.availableModels){if(typeof Z.modelId!=="string")continue;X.push({id:Z.modelId,name:typeof Z.name==="string"?Z.name:null,description:typeof Z.description==="string"?Z.description:null})}return X.length>0?X:null}function bX($){return typeof $?.currentModelId==="string"?$.currentModelId:null}function vX($,X){let Z=[];if($.trim())Z.push({type:"text",text:$});for(let J of X)if(J.content.trim())Z.push({type:"text",text:J.content});return Z}function IX($){if(typeof $.value==="boolean")return{sessionId:$.sessionId,configId:$.configId,type:"boolean",value:$.value};return{sessionId:$.sessionId,configId:$.configId,value:$.value}}function hX($,X){let Z=N$({configOptions:X.configOptions});return{models:Z.models??$.models,currentModelId:Z.currentModelId??$.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??$.modelConfigId}}function g1($,X){if($==="default")return null;if(!X||X.length===0)return $;let Z=X.find((K)=>K.id===$);if(Z)return Z.id;let J=$.toLowerCase(),Q=J.includes("opus")?"opus":J.includes("sonnet")?"sonnet":J.includes("haiku")?"haiku":null;if(!Q)return $;let j=(K)=>`${K.id} ${K.name??""} ${K.description??""}`.toLowerCase(),Y=X.filter((K)=>j(K).includes(Q));if(Y.length===0)return $;let z=(J.includes("1m")?Y.find((K)=>j(K).includes("1m")):void 0)??Y[0];return z?z.id:$}async function v0($){try{let X=await $.conn.setSessionConfigOption(IX({sessionId:$.sessionId,configId:$.configId,value:$.value}));return hX($.metadata,X)}catch(X){return console.warn(`[acp] setSessionConfigOption(${$.label}) failed; using agent default.`,X instanceof Error?X.message:X),$.metadata}}async function q$($){let X=W$($.spawn),Z=[],J=0,Q=4096;X.stderr.on("data",(L)=>{Z.push(L),J+=L.length;while(J>Q*2&&Z.length>1){let R=Z.shift();if(R)J-=R.length}});let j=()=>{let L=Buffer.concat(Z).toString("utf8");return L.length>Q?L.slice(-Q):L},Y=_1($.spawn.cwd),G={current:null},z={at:Date.now()},K=m1(X.stdin),H=S1(X.stdout),B=b1(K,H),M=new y1((L)=>({requestPermission:async(R)=>{let E=R.options,I=E?.find((p)=>p.kind==="allow_once")??E?.find((p)=>p.kind==="allow_always");if(I)return{outcome:{outcome:"selected",optionId:I.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(R)=>{z.at=Date.now();let E=G.current;if(E)await E.onSessionUpdate(R)},readTextFile:Y.readTextFile}),B),N=()=>X.kill();if($.signal)$.signal.addEventListener("abort",N);let F=()=>{if($.signal)$.signal.removeEventListener("abort",N)},V=async(L,R)=>{if(F(),X.kill(),v1(L))throw new J0(L.message??"Authentication required",R);if(L instanceof Error&&L.message==="ACP connection closed"){if($.signal?.aborted)throw new O("ACP session cancelled: abort signal received");let E=await Promise.race([X.processCrashed,X.waitForExit,new Promise((I)=>setTimeout(()=>I({stderr:""}),500))]);throw new O(`Runtime process exited before completion: ${E.stderr?.trim()??""}`)}throw L},D;try{D=await M.initialize({protocolVersion:U0,clientCapabilities:Y$,clientInfo:I1()})}catch(L){throw await V(L,[]),Error("unreachable")}try{h1(D.protocolVersion)}catch(L){throw F(),X.kill(),L}let x=D.authMethods?.map((L)=>L.id)??[],k;try{k=await M.newSession({cwd:$.spawn.cwd,mcpServers:$.mcpServers??[]})}catch(L){throw await V(L,x),Error("unreachable")}let A=k.sessionId,_=N$(k),P=$.modelId??null,W=P?g1(P,_.models):null;if(W&&W!==_.currentModelId)if(_.modelConfigId)_=await v0({conn:M,sessionId:A,configId:_.modelConfigId,value:W,metadata:_,label:`${_.modelConfigId}=${W}`});else console.warn(`[acp] runtime did not advertise a model config option for ${W}; using agent default.`);for(let[L,R]of Object.entries($.configValues??{}).sort(([E],[I])=>E.localeCompare(I))){if(L===_.modelConfigId)continue;if(!_.configOptions.some((E)=>E.id===L))continue;_=await v0({conn:M,sessionId:A,configId:L,value:R,metadata:_,label:`${L}=${String(R)}`})}F();let C=!1,T=async()=>{if(C)return;C=!0,X.kill(),await Promise.race([X.waitForExit,new Promise((L)=>setTimeout(L,2000))])},f=!1;return X.processCrashed.then(()=>{f=!0}),{sessionId:A,availableModels:_.models,currentModelId:_.currentModelId,availableConfigOptions:_.configOptions,isAlive:()=>!C&&!f,dispose:T,prompt:(L)=>SX({proc:X,conn:M,sessionId:A,activeAdapter:G,lastUpdate:z,collectStderrTail:j},L)}}async function SX($,X){let{proc:Z,conn:J,sessionId:Q,activeAdapter:j,lastUpdate:Y}=$,G={boardId:X.boardId,cardId:X.cardId,runId:X.runId},z=f1({ctx:G,appendText:X.appendText,appendToolActivity:X.appendToolActivity});j.current=z,Y.at=Date.now();let K=!1,H=null,B=()=>Z.kill();X.signal.addEventListener("abort",B);try{let U=async()=>{let V=X.heartbeatMs??TX,D=Math.min(fX,Math.max(50,Math.floor(V/2)));H=setInterval(()=>{let k=X.isAwaitingInput?.()??!1;if(k){Y.at=Date.now();return}if(E1({nowMs:Date.now(),lastUpdateMs:Y.at,windowMs:V,awaitingInput:k}))K=!0,J.cancel({sessionId:Q}).catch(()=>{return}),Z.kill()},D);let x=vX(X.prompt.systemPrompt,X.prompt.messages);await J.prompt({sessionId:Q,prompt:x}),z.flush({completeOpenToolCalls:!0})},M=Z.waitForExit.then((V)=>({kind:"exited",exit:V})),N=U().then(()=>({kind:"ok"})).catch(async(V)=>{if(V instanceof Error&&V.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw V}),F;try{F=await Promise.race([N,Z.processCrashed.then((V)=>({kind:"crashed",exit:V})),M])}catch(V){if(K)throw new d;throw V}if(K)throw new d;if(F.kind==="crashed")throw new O(`Runtime process exited before completion: ${F.exit.stderr.trim()}`);if(F.kind==="exited"){if(X.signal.aborted)throw new O("ACP session cancelled: abort signal received");if(K)throw new d;throw new O(`Runtime process exited unexpectedly: ${F.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:z.getFinalText(),toolCallsExecuted:z.getToolCallCount(),stderrTail:$.collectStderrTail(),updateTypeCounts:z.getUpdateTypeCounts()}}finally{if(H!==null)clearInterval(H);X.signal.removeEventListener("abort",B),z.flush({completeOpenToolCalls:!0}),j.current=null}}var mX=30000;async function c1($){let X=W$($.spawn),Z=m1(X.stdin),J=S1(X.stdout),Q=b1(Z,J),Y=new y1((K)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),G=()=>X.kill();if($.signal)$.signal.addEventListener("abort",G);let z=null;try{let K=(async()=>{let B=await Y.initialize({protocolVersion:U0,clientCapabilities:Y$,clientInfo:I1()});h1(B.protocolVersion);let U=B.authMethods?.map((k)=>k.id)??[],M;try{M=await Y.newSession({cwd:$.spawn.cwd,mcpServers:[]})}catch(k){if(v1(k))throw new J0(k.message??"Authentication required",U);throw k}let N=N$(M),F=$.modelId??null,V=F?g1(F,N.models):null;if(V&&V!==N.currentModelId)if(N.modelConfigId)N=await v0({conn:Y,sessionId:M.sessionId,configId:N.modelConfigId,value:V,metadata:N,label:`${N.modelConfigId}=${V}`});else console.warn(`[acp] runtime did not advertise a model config option for ${V}; discovering agent default models.`);for(let[k,A]of Object.entries($.configValues??{}).sort(([_],[P])=>_.localeCompare(P))){if(k===N.modelConfigId)continue;if(!N.configOptions.some((_)=>_.id===k))continue;N=await v0({conn:Y,sessionId:M.sessionId,configId:k,value:A,metadata:N,label:`${k}=${String(A)}`})}let D=N.models??[],x=N.currentModelId;return Y.cancel({sessionId:M.sessionId}).catch(()=>{return}),{models:D,configOptions:N.configOptions,currentModelId:x}})(),H=new Promise((B,U)=>{z=setTimeout(()=>{U(new d)},mX)});return await Promise.race([K,H])}catch(K){if(K instanceof Error&&K.message==="ACP connection closed"){if($.signal?.aborted)throw new O("ACP model discovery cancelled: abort signal received");throw new O("Runtime process exited during model discovery.")}throw K}finally{if(z)clearTimeout(z);if($.signal)$.signal.removeEventListener("abort",G);X.kill()}}var y=new Map,u=null;function I0($){$.then((X)=>X.dispose()).catch(()=>{return})}function gX(){if(u!==null)return;u=setInterval(()=>{let $=Date.now();for(let[X,Z]of y){if(Z.inUse)continue;if($-Z.lastUsed<600000)continue;y.delete(X),I0(Z.sessionPromise)}if(y.size===0&&u!==null)clearInterval(u),u=null},60000),u.unref?.()}function cX(){if(y.size<200)return;let $=null,X=1/0;for(let[J,Q]of y){if(Q.inUse)continue;if(Q.lastUsed>=X)continue;$=J,X=Q.lastUsed}if(!$)return;let Z=y.get($);if(!Z)return;y.delete($),I0(Z.sessionPromise)}function B$($,X,Z){return`${$}:${X}:${Z}`}async function x$($){let X=y.get($.key);if(X)if(X.fingerprint===$.fingerprint){X.inUse=!0,X.lastUsed=Date.now();try{let J=await X.sessionPromise;if(J.isAlive())return J}catch{}y.delete($.key)}else y.delete($.key),I0(X.sessionPromise);let Z=$.open();cX(),y.set($.key,{key:$.key,fingerprint:$.fingerprint,sessionPromise:Z,lastUsed:Date.now(),inUse:!0}),gX();try{return await Z}catch(J){throw y.delete($.key),J}}function F$($,X=!1){let Z=y.get($);if(!Z)return;if(X){y.delete($),I0(Z.sessionPromise);return}Z.inUse=!1,Z.lastUsed=Date.now()}async function lX(){let $=Array.from(y.values());if(y.clear(),u!==null)clearInterval(u),u=null;await Promise.all($.map((X)=>X.sessionPromise.then((Z)=>Z.dispose()).catch(()=>{return})))}function C$($){let X=Object.entries($.configValues??{}),Z=X.length>0?JSON.stringify(Object.fromEntries(X.sort(([J],[Q])=>J.localeCompare(Q)))):"";return[$.adapterId,$.configId??"",$.modelId??"",Z,$.mcpUrl??"",$.runFolder??"",$.toolSurface??"full"].join(" ")}var l1=!1;function uX(){if(l1)return;l1=!0;let $=()=>{lX()};process.once("beforeExit",$),process.once("SIGTERM",$),process.once("SIGINT",$)}uX();import pX from"node:fs/promises";import h0 from"node:os";async function u1($){let X={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await pX.readFile($,"utf-8")}catch(J){if(J.code==="ENOENT")return structuredClone(X);throw J}return F0.parse(JSON.parse(Z))}function P$($,X,Z){return{...$.defaultConfigValues??{},...X?.configValues??{},...Z?.configValues??{}}}async function i($){let X=$.configPath?await u1($.configPath):await h(),Z=$.cardId?X.cardOverrides[$.cardId]:void 0;if(Z?.runtimeConfigId){let Q=X.runtimes.find((j)=>j.id===Z.runtimeConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:Z.runFolder??Q.runFolder??h0.homedir(),modelId:Z.modelId??Q.defaultModelId??null,configValues:P$(Q,void 0,Z)}}let J=X.boardOverrides[$.boardId];if(J?.runtimeConfigId){let Q=X.runtimes.find((j)=>j.id===J.runtimeConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:J.runFolder??Q.runFolder??h0.homedir(),modelId:J.modelId??Q.defaultModelId??null,configValues:P$(Q,J)}}if(X.globalDefaultConfigId){let Q=X.runtimes.find((j)=>j.id===X.globalDefaultConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:Z?.runFolder??J?.runFolder??Q.runFolder??h0.homedir(),modelId:Z?.modelId??J?.modelId??Q.defaultModelId??null,configValues:P$(Q,J,Z)}}throw new t}async function p1($,X={}){let J=(X.configPath?await u1(X.configPath):await h()).runtimes.find((Q)=>Q.id===$);if(!J)return null;return{entry:J,adapter:c(J),runFolder:J.runFolder??h0.homedir(),modelId:X.modelId??J.defaultModelId??null,configValues:{...J.defaultConfigValues??{},...X.configValues??{}}}}var d1=new Map;function L$($,X){if(!$)return;d1.set($,X)}function a1($){if(!$)return!1;return d1.get($)??!1}var $0=new Map,k$=new Set;function O$($){$0.get($)?.controller.abort()}function i1($){for(let[X,Z]of $0){if(Z.frontendSessionId!==$)continue;Z.controller.abort(),$0.delete(X)}}function n1(){for(let $ of $0.values())$.controller.abort();$0.clear()}function o1($,X){if(X?.aborted)return!0;return $ instanceof Error&&/abort signal received|session cancelled/i.test($.message)}function s1($,X,Z,J){if((!X.availableModels||X.availableModels.length===0)&&X.availableConfigOptions.length===0)return;g((Q)=>{let j=Q.runtimes.find((Y)=>Y.id===$);if(j){if(X.availableModels&&X.availableModels.length>0)j.discoveredModels=T0({adapterId:Z,models:X.availableModels,currentModelId:X.currentModelId??J});if(X.availableConfigOptions.length>0)j.discoveredConfigOptions=X.availableConfigOptions}}).catch(()=>{return})}function dX($,X){return`${$}
19
19
 
20
20
  Runtime run folder:
21
21
  - Effective run folder: ${X}
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 s1($,X){let Z=Date.now(),J=new AbortController;$0.set($.runId,{controller:J,frontendSessionId:$.frontendSessionId}),L$.add($.cardId);let Q=q$($.userId,$.frontendSessionId,$.cardId),j=!1,K=null;try{let z=($.runtimeConfigIdHint?await u1($.runtimeConfigIdHint,{modelId:$.modelHint??null}):null)??await i({boardId:$.boardId,cardId:$.cardId}),W=await z.adapter.resolveSpawnConfig(z.entry),H=$.toolSurface??"full",B=z.adapter.supportsImages===!0;K=W;let U=u0({userId:$.userId,frontendSessionId:$.frontendSessionId,boardId:$.boardId,toolSurface:H,imagesSupported:B,cardId:$.cardId,runFolder:z.runFolder}),M=U?[U]:[];P$($.cardId,B);let N=$.modelHint??z.modelId,F=F$({adapterId:z.adapter.id,configId:z.entry.id,modelId:N,configValues:z.configValues,mcpUrl:U?.url??null,runFolder:z.runFolder,toolSurface:H}),V=await B$({key:Q,fingerprint:F,open:()=>N$({spawn:{...W,cwd:z.runFolder},mcpServers:M,modelId:N,configValues:z.configValues,signal:J.signal})});o1(z.entry.id,V,z.adapter.id,N);let D;try{D=await V.prompt({runId:$.runId,boardId:$.boardId,cardId:$.cardId,prompt:{systemPrompt:l6($.systemPrompt,z.runFolder),messages:$.promptMessages.map((x)=>({role:x.role,content:x.content}))},signal:J.signal,appendText:async({text:x})=>{X({type:"partial_text",runId:$.runId,cardId:$.cardId,text:x})},appendToolActivity:async({entry:x})=>{X({type:"tool_activity",runId:$.runId,cardId:$.cardId,activity:x})}})}catch(x){if(!V.isAlive()||x instanceof O)j=!0;throw x}X({type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:D.finalText,model:D.modelReported??null,latencyMs:Date.now()-Z,errorText:null,partialText:null}})}catch(G){let z=G instanceof Error?G.message:"Agent run failed";if(G instanceof O&&K&&!n1(G,J.signal))e0(K,z);console.error(`[ideawave-cli] run ${$.runId} failed:`,z),X({type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:"",model:null,latencyMs:Date.now()-Z,errorText:z,partialText:null}})}finally{x$(Q,j),$0.delete($.runId),L$.delete($.cardId)}}async function t1($){if(L$.has($.cardId))return{status:"skipped"};let X=q$($.userId,$.frontendSessionId,$.cardId),Z=null;try{let J=await i({boardId:$.boardId,cardId:$.cardId}),Q=await J.adapter.resolveSpawnConfig(J.entry);Z=Q;let j=u0({userId:$.userId,frontendSessionId:$.frontendSessionId,boardId:$.boardId,cardId:$.cardId,runFolder:J.runFolder}),K=j?[j]:[];P$($.cardId,J.adapter.supportsImages===!0);let G=F$({adapterId:J.adapter.id,configId:J.entry.id,modelId:J.modelId,configValues:J.configValues,mcpUrl:j?.url??null,runFolder:J.runFolder}),z=new AbortController,W=await B$({key:X,fingerprint:G,open:()=>N$({spawn:{...Q,cwd:J.runFolder},mcpServers:K,modelId:J.modelId,configValues:J.configValues,signal:z.signal})});return o1(J.entry.id,W,J.adapter.id,J.modelId),x$(X,!1),console.log(`[ideawave-cli] warmed runtime for card ${$.cardId}`),{status:"ready"}}catch(J){if(J instanceof t)return{status:"skipped"};let Q=J instanceof Error?J.message:String(J);if(J instanceof O&&Z&&!n1(J))e0(Z,Q);if(J instanceof O&&/(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 d6}from"node:crypto";import{createServer as a6}from"node:http";import{WebSocket as j2,WebSocketServer as i6}from"ws";var O$="/cli-bridge",r1="/ping";function _$($=43275,X=43277){let Z=[];for(let J=$;J<=X;J+=1)Z.push(J);return Z}function e1($=_$(),X="127.0.0.1",Z="/cli-bridge"){return $.map((J)=>`ws://${X}:${J}${Z}`)}var u6=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 h0($){try{let X=JSON.parse($);if(X&&typeof X==="object"&&typeof X.type==="string"&&u6.has(X.type))return X}catch{}return null}function S0($){return JSON.stringify($)}var p6=800;function $2({candidates:$,createWebSocket:X,timeoutMs:Z=p6,maxConcurrent:J=1,staggerMs:Q=0,setTimeoutFn:j=setTimeout,clearTimeoutFn:K=clearTimeout}){return new Promise((G,z)=>{let W=0,H=!1,B=null,U=new Map,M=Math.max(1,Math.floor(J)),N=()=>{if(B===null)return;K(B),B=null},F=(P)=>{let{socket:Y,listeners:C,timer:T}=P;Y.removeEventListener("open",C.open),Y.removeEventListener("message",C.message),Y.removeEventListener("error",C.error),Y.removeEventListener("close",C.close),K(T),U.delete(Y)},V=(P)=>{N();for(let Y of Array.from(U.values()))if(F(Y),Y.socket!==P)try{Y.socket.close()}catch{}},D=()=>{if(H)return;if(W<$.length)return;if(U.size>0)return;if(B!==null)return;H=!0,z(Error("No IdeaWave CLI bridge is reachable"))},x=(P)=>{if(H)return;if(W>=$.length){D();return}if(U.size>=M)return;if(P<=0){N(),_();return}if(B!==null)return;B=j(()=>{B=null,_()},P)},k=()=>{if(H)return;if(U.size>=M)return;if(U.size===0||Q<=0||M===1){x(0);return}x(Q)},A=(P)=>{if(H)return;let Y=U.get(P);if(!Y)return;F(Y);try{P.close()}catch{}k(),D()};function _(){if(H)return;if(U.size>=M)return;let P=$[W];if(W+=1,!P){D();return}let Y;try{Y=X(P)}catch{k(),D();return}let C={open:()=>{if(H||!U.has(Y))return;Y.send(S0({type:"bridge_probe",protocolVersion:1}))},message:(f)=>{if(H||!U.has(Y))return;if(h0(String(f?.data??""))?.type!=="bridge_probe_ack")return;H=!0,V(Y),G({url:P,socket:Y})},error:()=>A(Y),close:()=>A(Y)};Y.addEventListener("open",C.open),Y.addEventListener("message",C.message),Y.addEventListener("error",C.error),Y.addEventListener("close",C.close);let T=j(()=>A(Y),Z);U.set(Y,{url:P,socket:Y,listeners:C,timer:T}),k()}_()})}var n6=0,o6=30000,s6=15000,t6="http://127.0.0.1",A$="IDEAWAVE_CLI_ALLOW_RAILWAY_PR_PREVIEWS";async function K2($=e1(),X=(Z)=>new j2(Z,{headers:{origin:t6}})){try{let{url:Z,socket:J}=await $2({candidates:$,createWebSocket:X});try{J.close()}catch{}return Z}catch{return null}}var r6=new Set(["https://ideawave-app-production.up.railway.app"]);function e6($){return $==="ideawave.app"||$.endsWith(".ideawave.app")}function $X($){return $==="1"||$?.toLowerCase()==="true"}function XX($){return/^ideawave-app-ideawave-app-pr-\d+\.up\.railway\.app$/i.test($)}function ZX(){let $=process.env.IDEAWAVE_CLI_ALLOWED_ORIGINS;if(!$)return JX;let X=new Set;for(let Z of $.split(",")){let J=Z.trim();if(!J)continue;try{X.add(new URL(J).origin)}catch{}}return X}var JX=new Set;function X2($){if(!$)return!1;let X;try{X=new URL($)}catch{return!1}if(r6.has(X.origin))return!0;if(ZX().has(X.origin))return!0;if(X.protocol==="https:"&&$X(process.env[A$])&&XX(X.hostname))return!0;if(X.protocol==="https:"&&e6(X.hostname))return!0;if(X.protocol!=="http:"&&X.protocol!=="https:")return!1;return X.hostname==="localhost"||X.hostname==="127.0.0.1"||X.hostname==="::1"}function K0($,X){if($.readyState!==j2.OPEN)return;try{$.send(S0(X))}catch{}}function QX($){if(typeof $==="string")return $;if(Buffer.isBuffer($))return $.toString("utf8");if(Array.isArray($))return Buffer.concat($).toString("utf8");return Buffer.from($).toString("utf8")}function Z2($){if(typeof $==="string")return $;if(Array.isArray($))return $[0]??null;return null}function J2($,X,Z){$.write(`HTTP/1.1 ${X} ${Z}\r
24
+ - Filesystem access is read-only and limited to this folder. Hidden/config folders and outside-folder paths are unavailable.`}async function t1($,X){let Z=Date.now(),J=new AbortController;$0.set($.runId,{controller:J,frontendSessionId:$.frontendSessionId}),k$.add($.cardId);let Q=B$($.userId,$.frontendSessionId,$.cardId),j=!1,Y=null;try{let z=($.runtimeConfigIdHint?await p1($.runtimeConfigIdHint,{modelId:$.modelHint??null}):null)??await i({boardId:$.boardId,cardId:$.cardId}),K=await z.adapter.resolveSpawnConfig(z.entry),H=$.toolSurface??"full",B=z.adapter.supportsImages===!0;Y=K;let U=p0({userId:$.userId,frontendSessionId:$.frontendSessionId,boardId:$.boardId,toolSurface:H,imagesSupported:B,cardId:$.cardId,runFolder:z.runFolder}),M=U?[U]:[];L$($.cardId,B);let N=$.modelHint??z.modelId,F=C$({adapterId:z.adapter.id,configId:z.entry.id,modelId:N,configValues:z.configValues,mcpUrl:U?.url??null,runFolder:z.runFolder,toolSurface:H}),V=await x$({key:Q,fingerprint:F,open:()=>q$({spawn:{...K,cwd:z.runFolder},mcpServers:M,modelId:N,configValues:z.configValues,signal:J.signal})});s1(z.entry.id,V,z.adapter.id,N);let D;try{D=await V.prompt({runId:$.runId,boardId:$.boardId,cardId:$.cardId,prompt:{systemPrompt:dX($.systemPrompt,z.runFolder),messages:$.promptMessages.map((x)=>({role:x.role,content:x.content}))},signal:J.signal,appendText:async({text:x})=>{X({type:"partial_text",runId:$.runId,cardId:$.cardId,text:x})},appendToolActivity:async({entry:x})=>{X({type:"tool_activity",runId:$.runId,cardId:$.cardId,activity:x})}})}catch(x){if(!V.isAlive()||x instanceof O)j=!0;throw x}X({type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:D.finalText,model:D.modelReported??null,latencyMs:Date.now()-Z,errorText:null,partialText:null}})}catch(G){let z=G instanceof Error?G.message:"Agent run failed";if(G instanceof O&&Y&&!o1(G,J.signal))$$(Y,z);console.error(`[ideawave-cli] run ${$.runId} failed:`,z),X({type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:"",model:null,latencyMs:Date.now()-Z,errorText:z,partialText:null}})}finally{F$(Q,j),$0.delete($.runId),k$.delete($.cardId)}}async function r1($){if(k$.has($.cardId))return{status:"skipped"};let X=B$($.userId,$.frontendSessionId,$.cardId),Z=null;try{let J=await i({boardId:$.boardId,cardId:$.cardId}),Q=await J.adapter.resolveSpawnConfig(J.entry);Z=Q;let j=p0({userId:$.userId,frontendSessionId:$.frontendSessionId,boardId:$.boardId,cardId:$.cardId,runFolder:J.runFolder}),Y=j?[j]:[];L$($.cardId,J.adapter.supportsImages===!0);let G=C$({adapterId:J.adapter.id,configId:J.entry.id,modelId:J.modelId,configValues:J.configValues,mcpUrl:j?.url??null,runFolder:J.runFolder}),z=new AbortController,K=await x$({key:X,fingerprint:G,open:()=>q$({spawn:{...Q,cwd:J.runFolder},mcpServers:Y,modelId:J.modelId,configValues:J.configValues,signal:z.signal})});return s1(J.entry.id,K,J.adapter.id,J.modelId),F$(X,!1),console.log(`[ideawave-cli] warmed runtime for card ${$.cardId}`),{status:"ready"}}catch(J){if(J instanceof t)return{status:"skipped"};let Q=J instanceof Error?J.message:String(J);if(J instanceof O&&Z&&!o1(J))$$(Z,Q);if(J instanceof O&&/(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 nX}from"node:crypto";import{createServer as oX}from"node:http";import{WebSocket as K6,WebSocketServer as sX}from"ws";var _$="/cli-bridge",e1="/ping";function A$($=43275,X=43277){let Z=[];for(let J=$;J<=X;J+=1)Z.push(J);return Z}function $6($=A$(),X="127.0.0.1",Z="/cli-bridge"){return $.map((J)=>`ws://${X}:${J}${Z}`)}var aX=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 S0($){try{let X=JSON.parse($);if(X&&typeof X==="object"&&typeof X.type==="string"&&aX.has(X.type))return X}catch{}return null}function m0($){return JSON.stringify($)}var iX=800;function X6({candidates:$,createWebSocket:X,timeoutMs:Z=iX,maxConcurrent:J=1,staggerMs:Q=0,setTimeoutFn:j=setTimeout,clearTimeoutFn:Y=clearTimeout}){return new Promise((G,z)=>{let K=0,H=!1,B=null,U=new Map,M=Math.max(1,Math.floor(J)),N=()=>{if(B===null)return;Y(B),B=null},F=(P)=>{let{socket:W,listeners:C,timer:T}=P;W.removeEventListener("open",C.open),W.removeEventListener("message",C.message),W.removeEventListener("error",C.error),W.removeEventListener("close",C.close),Y(T),U.delete(W)},V=(P)=>{N();for(let W of Array.from(U.values()))if(F(W),W.socket!==P)try{W.socket.close()}catch{}},D=()=>{if(H)return;if(K<$.length)return;if(U.size>0)return;if(B!==null)return;H=!0,z(Error("No IdeaWave CLI bridge is reachable"))},x=(P)=>{if(H)return;if(K>=$.length){D();return}if(U.size>=M)return;if(P<=0){N(),_();return}if(B!==null)return;B=j(()=>{B=null,_()},P)},k=()=>{if(H)return;if(U.size>=M)return;if(U.size===0||Q<=0||M===1){x(0);return}x(Q)},A=(P)=>{if(H)return;let W=U.get(P);if(!W)return;F(W);try{P.close()}catch{}k(),D()};function _(){if(H)return;if(U.size>=M)return;let P=$[K];if(K+=1,!P){D();return}let W;try{W=X(P)}catch{k(),D();return}let C={open:()=>{if(H||!U.has(W))return;W.send(m0({type:"bridge_probe",protocolVersion:1}))},message:(f)=>{if(H||!U.has(W))return;if(S0(String(f?.data??""))?.type!=="bridge_probe_ack")return;H=!0,V(W),G({url:P,socket:W})},error:()=>A(W),close:()=>A(W)};W.addEventListener("open",C.open),W.addEventListener("message",C.message),W.addEventListener("error",C.error),W.addEventListener("close",C.close);let T=j(()=>A(W),Z);U.set(W,{url:P,socket:W,listeners:C,timer:T}),k()}_()})}var tX=0,rX=30000,eX=15000,$Z="http://127.0.0.1",w$="IDEAWAVE_CLI_ALLOW_RAILWAY_PR_PREVIEWS";async function Y6($=$6(),X=(Z)=>new K6(Z,{headers:{origin:$Z}})){try{let{url:Z,socket:J}=await X6({candidates:$,createWebSocket:X});try{J.close()}catch{}return Z}catch{return null}}var XZ=new Set(["https://ideawave-app-production.up.railway.app"]);function ZZ($){return $==="ideawave.app"||$.endsWith(".ideawave.app")}function JZ($){return $==="1"||$?.toLowerCase()==="true"}function QZ($){return/^ideawave-app-ideawave-app-pr-\d+\.up\.railway\.app$/i.test($)}function jZ(){let $=process.env.IDEAWAVE_CLI_ALLOWED_ORIGINS;if(!$)return KZ;let X=new Set;for(let Z of $.split(",")){let J=Z.trim();if(!J)continue;try{X.add(new URL(J).origin)}catch{}}return X}var KZ=new Set;function Z6($){if(!$)return!1;let X;try{X=new URL($)}catch{return!1}if(XZ.has(X.origin))return!0;if(jZ().has(X.origin))return!0;if(X.protocol==="https:"&&JZ(process.env[w$])&&QZ(X.hostname))return!0;if(X.protocol==="https:"&&ZZ(X.hostname))return!0;if(X.protocol!=="http:"&&X.protocol!=="https:")return!1;return X.hostname==="localhost"||X.hostname==="127.0.0.1"||X.hostname==="::1"}function K0($,X){if($.readyState!==K6.OPEN)return;try{$.send(m0(X))}catch{}}function YZ($){if(typeof $==="string")return $;if(Buffer.isBuffer($))return $.toString("utf8");if(Array.isArray($))return Buffer.concat($).toString("utf8");return Buffer.from($).toString("utf8")}function J6($){if(typeof $==="string")return $;if(Array.isArray($))return $[0]??null;return null}function Q6($,X,Z){$.write(`HTTP/1.1 ${X} ${Z}\r
25
25
  Connection: close\r
26
26
  Content-Length: ${Buffer.byteLength(Z)}\r
27
27
  \r
28
- ${Z}`),$.destroy()}function jX($,X){return new Promise((Z,J)=>{let Q=(K)=>{$.off("listening",j),J(K)},j=()=>{$.off("error",Q);let K=$.address();if(!K||typeof K==="string"){J(Error("Failed to read CLI bridge server address"));return}Z(K.port)};$.once("error",Q),$.once("listening",j),$.listen(X,"127.0.0.1")})}function Q2($){return new Promise((X,Z)=>{$.close((J)=>{if(J)Z(J);else X()})})}async function W2($,X=_$()){let Z=new Map,J=new Map,Q=$.maxMessageSize??n6,j=!1,K=(U)=>{let M=J.get(U);if(M)clearTimeout(M);J.delete(U)},G=(U)=>{J.delete(U);let{activeRunIds:M}=$.registry.disconnect(U);$.onDisconnect(U,M)},z=(U,M)=>{let N={type:"cli_status",connected:!0,runtime:$.runtime,mcpReady:$.mcpReady(),error:M};if(U){let F=Z.get(U);if(F)K0(F,N);return}for(let F of Z.values())K0(F,N)},W=(U,M)=>{let N=M.sessionId.trim(),F=M.userId.trim();if(!N||!F){K0(U,{type:"cli_status",connected:!1,runtime:$.runtime,mcpReady:$.mcpReady(),error:"Missing frontend session or user id"}),U.close();return}K(N);let V=Z.get(N);if(V&&V!==U)V.close();U.data.frontendSessionId=N,Z.set(N,U),$.registry.register({frontendSessionId:N,userId:F,tools:M.tools,send:(D)=>K0(U,D)}),z(N),$.onToolMetadata?.(N)},H=(U,M)=>{let N=$.registry.getUserId(U);if(!N)return;switch(M.type){case"bridge_ping":{let F=Z.get(U);if(F)K0(F,{type:"bridge_pong"});break}case"tool_metadata":$.registry.setMetadata(U,M.tools),$.onToolMetadata?.(U);break;case"tool_result":$.registry.handleToolResult(U,M);break;case"run_turn":$.registry.markRunActive(U,M.run.runId,M.run.cardId),$.onRunTurn(U,{...M.run,frontendSessionId:U,userId:N});break;case"cancel_run":if($.registry.ownsRun(U,M.runId))$.onCancelRun(U,M.runId);break;case"runtime_rpc":$.onRuntimeRpc(U,M);break;case"warmup_run":$.onWarmupRun(U,{...M,frontendSessionId:U},N);break;default:break}},B=(U,M)=>{let N=Z2(U.headers.origin),F=X2(N),V={Vary:"Origin"};if(F&&N)V["Access-Control-Allow-Origin"]=N,V["Access-Control-Allow-Private-Network"]="true";if(U.method==="OPTIONS"){M.writeHead(204,{...V,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),M.end();return}if(U.method!=="GET"){M.writeHead(405,V),M.end();return}M.writeHead(200,{...V,"content-type":"application/json","cache-control":"no-store"}),M.end(JSON.stringify({ideawave:!0,runtime:$.runtime,mcpReady:$.mcpReady()}))};for(let U of X){let M=a6((V,D)=>{if(new URL(V.url??"/","http://127.0.0.1").pathname===r1){B(V,D);return}D.writeHead(404,{"content-type":"text/plain"}),D.end("IdeaWave CLI bridge")}),N=new i6({noServer:!0,maxPayload:Q}),F=(V)=>{if(V.idleTimer)clearTimeout(V.idleTimer);V.idleTimer=setTimeout(()=>{V.close()},o6),V.idleTimer.unref?.()};N.on("connection",(V)=>{let D=V;D.data={id:d6(),frontendSessionId:null},D.idleTimer=null,F(D),D.on("ping",()=>F(D)),D.on("pong",()=>F(D)),D.on("error",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);D.close()}),D.on("message",(x)=>{F(D);let k=QX(x);if(Q>0&&k.length>Q)return;let A=h0(k);if(!A)return;let _=D.data.frontendSessionId;if(!_){if(A.type==="bridge_probe")K0(D,{type:"bridge_probe_ack",protocolVersion:A.protocolVersion});else if(A.type==="frontend_hello")W(D,A);return}H(_,A)}),D.on("close",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);let x=D.data.frontendSessionId;if(!x)return;if(Z.get(x)!==D)return;if(Z.delete(x),K(x),j)return;J.set(x,setTimeout(()=>G(x),s6))})}),M.on("upgrade",(V,D,x)=>{if(new URL(V.url??"/","http://127.0.0.1").pathname!==O$){J2(D,404,"Not Found");return}if(!X2(Z2(V.headers.origin))){J2(D,403,"Forbidden");return}N.handleUpgrade(V,D,x,(A)=>{N.emit("connection",A,V)})});try{let V=await jX(M,U);return{url:`ws://127.0.0.1:${V}${O$}`,port:V,sendStatus:z,close:async()=>{j=!0;for(let D of J.values())clearTimeout(D);J.clear();for(let D of N.clients){let x=D;if(x.idleTimer)clearTimeout(x.idleTimer);x.close()}N.close(),await Q2(M).catch(()=>{return})}}}catch(V){if(N.close(),await Q2(M).catch(()=>{return}),V?.code==="EADDRINUSE")continue;throw V}}throw Error(`No free IdeaWave CLI bridge port found in ${X[0]}-${X.at(-1)}`)}import{Server as xX}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as FX,ListToolsRequestSchema as CX}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as WX}from"node:crypto";import{createServer as YX}from"node:http";import{StreamableHTTPServerTransport as VX}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as G2}from"@modelcontextprotocol/sdk/types.js";var Y2=new Set(["127.0.0.1","localhost","[::1]","::1"]);function KX($){let X=$.trim();if(X.length===0)return null;if(X.startsWith("[")){let j=X.indexOf("]");if(j===-1)return null;let K=X.slice(0,j+1),G=X.slice(j+1);if(G.length===0)return{host:K,port:null};if(!G.startsWith(":"))return null;let z=Number(G.slice(1));if(!Number.isInteger(z)||z<=0||z>65535)return null;return{host:K,port:z}}let Z=X.lastIndexOf(":");if(Z===-1)return{host:X,port:null};let J=X.slice(Z+1),Q=Number(J);if(!Number.isInteger(Q)||Q<=0||Q>65535)return{host:X,port:null};return{host:X.slice(0,Z),port:Q}}function V2($){return Y2.has($)||Y2.has($.toLowerCase())}function z2($,X){let Z=$.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let J=KX(Z);if(!J)return{ok:!1,status:403,reason:"bad-host"};if(!V2(J.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(J.port!==null&&J.port!==X)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(!V2(j.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var H2="/mcp",zX=43274,D2=16777216,GX=1800000,HX=300000,U2=200,UX=-32700,n=-32600,w$=-32603;function m($,X,Z,J,Q){$.statusCode=X,$.setHeader("content-type","application/json"),$.end(JSON.stringify({jsonrpc:"2.0",error:{code:Z,message:J,...Q?{data:Q}:{}},id:null}))}class T$ extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class f$ extends Error{constructor(){super(`body exceeds ${D2} bytes`);this.name="BodyTooLargeError"}}async function DX($){if($.method&&$.method!=="POST")return;let X=$.headers["content-type"];if(typeof X==="string"&&X.trim().length>0){if(!X.toLowerCase().includes("application/json"))throw new T$}let Z=0,J=[];for await(let j of $){let K=typeof j==="string"?Buffer.from(j):j;if(Z+=K.byteLength,Z>D2)throw new f$;J.push(K)}if(J.length===0)return;let Q=Buffer.concat(J).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function MX($){if(Array.isArray($))return $.some(G2);return G2($)}function NX($){if(typeof $==="number")return $;let X=process.env.IDEAWAVE_MCP_PORT;if(X&&X.trim().length>0){let Z=Number(X);if(Number.isInteger(Z)&&Z>=0&&Z<65536)return Z}return zX}async function qX($,X){let Z=(Q)=>new Promise((j,K)=>{let G=(W)=>{$.off("listening",z),K(W)},z=()=>{$.off("error",G),j()};$.once("error",G),$.once("listening",z),$.listen(Q,"127.0.0.1")});try{await Z(X)}catch(Q){if(Q.code!=="EADDRINUSE"||X===0)throw Q;console.warn(`[mcp] port ${X} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await Z(0)}let J=$.address();if(J==null||typeof J==="string")throw Error("[mcp] failed to read bound address");return J.port}function BX($,X){if(X&&typeof X==="object"&&!Array.isArray(X)){let J=X.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 Z=$.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function M2($){let X=new Map,Z=0;function J(W){let H=X.get(W);if(H)H.lastActivity=Date.now()}async function Q(W,H){X.delete(W),await H.transport.close().catch(()=>{return})}async function j(){let W=null,H=1/0;for(let[B,U]of X)if(U.lastActivity<H)H=U.lastActivity,W=B;if(W!==null){let B=X.get(W);if(B)console.warn(`[mcp] session cap of ${U2} reached; evicting ${W}`),await Q(W,B)}}let K=setInterval(()=>{let W=Date.now()-GX;for(let[H,B]of X)if(B.lastActivity<W)console.log(`[mcp] sweeping idle session ${H}`),Q(H,B)},HX);K.unref?.();let G=YX((W,H)=>{(async()=>{let B;try{B=new URL(W.url??"/","http://127.0.0.1").pathname}catch{m(H,400,n,"bad-url");return}if(B!==H2){m(H,404,n,"not-found");return}let U=W.method??"POST";if(U!=="POST"&&U!=="GET"&&U!=="DELETE"){H.setHeader("Allow","GET, POST, DELETE"),m(H,405,n,"method-not-allowed");return}let M=z2(W,Z);if(!M.ok){m(H,M.status,n,"forbidden",{reason:M.reason});return}let N=W.headers["mcp-session-id"],F=typeof N==="string"?N:void 0;if(U==="GET"||U==="DELETE"){if(!F||!X.has(F)){m(H,400,n,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let x=X.get(F).transport;J(F);try{await x.handleRequest(W,H)}catch(k){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",k),!H.headersSent)m(H,500,w$,"internal")}return}let V;try{V=await DX(W)}catch(x){if(x instanceof T$){m(H,415,n,"expected-application-json");return}if(x instanceof f$){m(H,413,n,"body-too-large");return}m(H,400,UX,"invalid-json");return}let D;if(F&&X.has(F))D=X.get(F).transport,J(F);else if(!F&&V!==void 0&&MX(V)){let x=W.headers["x-ideawave-user-id"],k=typeof x==="string"&&x.trim().length>0?x.trim():null,A=W.headers["x-ideawave-frontend-session-id"],_=typeof A==="string"&&A.trim().length>0?A.trim():null,P=W.headers["x-ideawave-tool-surface"],Y=typeof P==="string"&&P.trim()==="read"?"read":"full",C=W.headers["x-ideawave-images-supported"],T=typeof C==="string"&&C.trim()==="1",f=W.headers["x-ideawave-card-id"],L=typeof f==="string"&&f.trim().length>0?f.trim():null,R=W.headers["x-ideawave-board-id"],E=typeof R==="string"&&R.trim().length>0?R.trim():null,I=W.headers["x-ideawave-run-folder"],p=typeof I==="string"&&I.trim().length>0?I.trim():null,B0=BX(W,V);if(X.size>=U2)await j();let X0=null,s=new VX({sessionIdGenerator:()=>WX(),onsessioninitialized:(Z0)=>{X0=Z0,X.set(Z0,{transport:s,lastActivity:Date.now()})},onsessionclosed:(Z0)=>{X.delete(Z0)}});s.onclose=()=>{if(s.sessionId)X.delete(s.sessionId)};try{await $.buildServer({userId:k,frontendSessionId:_,boardId:E,toolSurface:Y,imagesSupported:T,cardId:L,runFolder:p,clientHint:B0}).connect(s)}catch(Z0){if(console.error("[mcp] buildServer/connect failed",Z0),X0)X.delete(X0);await s.close().catch(()=>{return}),m(H,500,w$,"server-init-failed");return}D=s}else{m(H,400,n,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await D.handleRequest(W,H,V)}catch(x){if(console.error("[mcp] transport.handleRequest threw",x),!H.headersSent)m(H,500,w$,"internal")}})().catch((B)=>{console.error("[mcp] unhandled request handler error:",B)})});return Z=await qX(G,NX($.port)),{url:`http://127.0.0.1:${Z}${H2}`,port:Z,close:async()=>{clearInterval(K);for(let W of X.values())await W.transport.close().catch(()=>{return});X.clear(),await new Promise((W)=>G.close(()=>W()))}}}var PX={name:"ideawave-board",version:"1.0.0"},m0="list_run_folder",g0="read_run_folder_file",B2=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",m0,g0]),x2=new Set(["inspect_diagram"]),LX=[{name:m0,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:g0,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 R$($){return{content:[{type:"text",text:$}]}}function kX($){return R$(JSON.stringify($,null,2))}function N2($){return{...R$($),isError:!0}}function OX($,X,Z="full",J=!1){return $.getMetadata(X).filter((Q)=>{let j=R0(Q.name);if(Z==="read"&&!B2.has(j))return!1;if(!J&&x2.has(j))return!1;return!0}).map((Q)=>({name:Q.name,description:Q.description,inputSchema:Q.inputSchema}))}function _X($,X,Z={}){let J=OX($,X,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...J,...LX]:J}function q2($,X){if(!$||typeof $!=="object"||Array.isArray($))return null;let Z=$[X];return typeof Z==="string"?Z:null}async function AX($,X,Z){if(Z&&Z.trim().length>0)return Z.trim();if(!$||!X)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await i({boardId:$,cardId:X})).runFolder}async function wX($){let X=await AX($.boardId,$.cardId,$.runFolder);if($.name===m0){let Z=q2($.args,"path")??"",J=await k1(X,Z);return kX(J)}if($.name===g0){let Z=q2($.args,"path");if(!Z)return N2("read_run_folder_file requires a path.");return R$(await f0(X,Z))}return N2(`Unknown local tool "${$.name}"`)}function TX($,X,Z,J,Q,j="full",K=!1){let G=new xX(PX,{capabilities:{tools:{}}}),z=async()=>{if(K)return!0;if(d1(J))return!0;if(Z&&J)try{return(await i({boardId:Z,cardId:J})).adapter.supportsImages===!0}catch{return!1}return!1};return G.setRequestHandler(CX,async()=>({tools:_X($,X,{includeRunFolderTools:Boolean(Q||Z&&J),toolSurface:j,imagesSupported:await z()})})),G.setRequestHandler(FX,async(W)=>{let{name:H,arguments:B}=W.params,U=R0(H);try{if(U===m0||U===g0)return await wX({name:U,args:B,boardId:Z,cardId:J,runFolder:Q});if(j==="read"&&!B2.has(U))throw Error(`Tool "${H}" is not available in read-only mode`);if(x2.has(U)&&!await z())throw Error(`Tool "${H}" requires a runtime that supports image input`);let M=await $.callTool(X,U,B??{},void 0,J??void 0);if(M&&typeof M==="object"&&Array.isArray(M.content))return M;return{content:[{type:"text",text:typeof M==="string"?M:JSON.stringify(M)}]}}catch(M){return{content:[{type:"text",text:M instanceof Error?M.message:"Tool call failed"}],isError:!0}}}),G}function F2($,X){return M2({buildServer:(Z)=>TX($,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:X})}import c0 from"node:fs/promises";import E$ from"node:os";import l0 from"node:path";function C2(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function fX(){let[$,X]=await Promise.all([h(),x1()]),Z=$.globalDefaultConfigId?$.runtimes.find((J)=>J.id===$.globalDefaultConfigId)??null:null;return{runtimes:$.runtimes,globalDefaultConfigId:$.globalDefaultConfigId,globalDefaultEffective:Z?{runFolder:Z.runFolder??E$.homedir(),modelId:Z.defaultModelId??null,configValues:Z.defaultConfigValues??{}}:null,knownAdapters:j0().map((J)=>({id:J.id,displayName:J.displayName})),readiness:X}}async function RX($){try{let X=await i({boardId:$.boardId,cardId:$.cardId});return{resolved:{configId:X.entry.id,adapterId:X.entry.kind==="registered"?X.entry.adapterId:null,displayName:X.entry.displayName,runFolder:X.runFolder,modelId:X.modelId,configValues:X.configValues}}}catch(X){if(X instanceof t)return{resolved:null};throw X}}async function EX($){return g((X)=>{let Z=X.runtimes.find((j)=>j.kind==="registered"&&j.adapterId===$.adapterId);if(Z)return Z;let J=j0().find((j)=>j.id===$.adapterId);if(!J)throw Error(`Unknown adapterId: ${$.adapterId}`);let Q={id:C2(),kind:"registered",adapterId:$.adapterId,displayName:J.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Q),Q})}async function yX($){return g((X)=>{let Z={id:C2(),kind:"custom",displayName:$.displayName,command:$.command,args:$.args,env:$.env,runFolder:$.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Z),Z})}async function bX($){await g((X)=>{if(X.runtimes=X.runtimes.filter((Z)=>Z.id!==$.runtimeConfigId),X.globalDefaultConfigId===$.runtimeConfigId)X.globalDefaultConfigId=null;for(let Z of Object.keys(X.boardOverrides))if(X.boardOverrides[Z].runtimeConfigId===$.runtimeConfigId)delete X.boardOverrides[Z];for(let Z of Object.keys(X.cardOverrides))if(X.cardOverrides[Z].runtimeConfigId===$.runtimeConfigId)delete X.cardOverrides[Z]})}async function vX($){await g((X)=>{let Z=X.runtimes.find((J)=>J.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);if(X.globalDefaultConfigId=$.runtimeConfigId,$.runFolder!==void 0)Z.runFolder=$.runFolder;if($.modelId!==void 0)Z.defaultModelId=$.modelId;if($.configValues!==void 0)Z.defaultConfigValues=$.configValues})}async function IX($){$.boardId,await g((X)=>{if($.runtimeConfigId===null){delete X.cardOverrides[$.cardId];return}if(!X.runtimes.some((Q)=>Q.id===$.runtimeConfigId))throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=X.cardOverrides[$.cardId];X.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 hX($){let Z=(await h()).runtimes.find((K)=>K.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=c(Z),Q=await J.resolveSpawnConfig(Z),j=Z.runFolder??E$.homedir();try{let K=await g1({spawn:{...Q,cwd:j},modelId:$.modelId??Z.defaultModelId??null,configValues:$.configValues??Z.defaultConfigValues??{}}),G=w0({adapterId:J.id,models:K.models,currentModelId:K.currentModelId}),z=new Date().toISOString();return await g((W)=>{let H=W.runtimes.find((B)=>B.id===$.runtimeConfigId);if(H)H.discoveredModels=G,H.discoveredConfigOptions=K.configOptions,H.discoveredAt=z}),{ok:!0,models:G,configOptions:K.configOptions,currentModelId:K.currentModelId}}catch(K){if(K instanceof J0)throw Error(`${K.message}${J.authHint?` ${J.authHint}`:""}`);if(K instanceof O||K instanceof d)throw Error(K.message);throw K}}async function SX($){let X=E$.homedir(),Z=$.path?.trim()?$.path.trim():X,J=l0.resolve(Z),Q=!0;try{if(!(await c0.stat(J)).isDirectory())J=l0.dirname(J)}catch{Q=!1,J=X}let j=[];try{j=(await c0.readdir(J,{withFileTypes:!0})).filter((z)=>z.isDirectory()&&!z.name.startsWith(".")).map((z)=>({name:z.name,path:l0.join(J,z.name)})).sort((z,W)=>z.name.localeCompare(W.name))}catch{j=[]}let K=l0.dirname(J);return{path:J,parent:K===J?null:K,home:X,exists:Q,entries:j}}var P2={list:fX,getEffectiveForCard:RX,registerRegistered:EX,registerCustom:yX,unregister:bX,setUserDefault:vX,setCardOverride:IX,refreshModels:hX,browseFolder:SX};var mX=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function gX(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function L2(){try{let $=await h();if($.globalDefaultConfigId){if($.runtimes.some((Z)=>Z.id===$.globalDefaultConfigId))return $.globalDefaultConfigId}for(let X of mX){if((await F1(X.id))?.status!=="ready")continue;let J=null;if(await g((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((G)=>G.id===Q.globalDefaultConfigId)){J=Q.globalDefaultConfigId;return}}let j=Q.runtimes.find((K)=>K.kind==="registered"&&K.adapterId===X.id);if(!j){let K={id:gX(),kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Q.runtimes.push(K),j=K}Q.globalDefaultConfigId=j.id,J=j.id}),J)return console.log(`[ideawave-cli] using agent runtime: ${X.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 cX(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class y${sessions=new Map;createCallId;toolCallTimeoutMs;constructor($={}){this.createCallId=$.createCallId??cX,this.toolCallTimeoutMs=$.toolCallTimeoutMs??120000}register($){let X=this.sessions.get($.frontendSessionId);if(X){if(X.userId!==$.userId)this.rejectPending(X,"frontend session user changed"),X.activeRunIds.clear();this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:X.pendingToolCalls,activeRunIds:X.activeRunIds,activeRunCardIds:X.activeRunCardIds});return}this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect($,X="frontend session disconnected"){let Z=this.sessions.get($);if(!Z)return{activeRunIds:[]};return this.sessions.delete($),this.rejectPending(Z,X),{activeRunIds:Array.from(Z.activeRunIds)}}sessionCount(){return this.sessions.size}has($){return this.sessions.has($)}getUserId($){return this.sessions.get($)?.userId??null}setMetadata($,X){let Z=this.sessions.get($);if(Z)Z.tools=X}getMetadata($){if(!$)return[];return this.sessions.get($)?.tools??[]}sendToSession($,X){let Z=this.sessions.get($);if(!Z)return!1;return Z.send(X),!0}callTool($,X,Z,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 K=this.createCallId();return new Promise((G,z)=>{let W=setTimeout(()=>{j.pendingToolCalls.delete(K),z(Error(`Tool "${X}" timed out waiting for the frontend`))},this.toolCallTimeoutMs),H=J??(Q?this.getActiveRunIdForCard(j,Q):this.getSoleActiveRunId(j)),B=Q??(H?j.activeRunCardIds.get(H):void 0);j.pendingToolCalls.set(K,{resolve:G,reject:z,timer:W}),j.send({type:"tool_call",callId:K,name:X,args:Z,...H?{runId:H}:{},...B?{cardId:B}:{}})})}handleToolResult($,X){let Z=this.sessions.get($);if(!Z)return;let J=Z.pendingToolCalls.get(X.callId);if(!J)return;if(Z.pendingToolCalls.delete(X.callId),clearTimeout(J.timer),X.ok)J.resolve(X.result);else J.reject(Error(X.error??"Tool execution failed"))}markRunActive($,X,Z){let J=this.sessions.get($);if(!J)return;if(J.activeRunIds.add(X),Z)J.activeRunCardIds.set(X,Z)}markRunSettled($,X){let Z=this.sessions.get($);if(!Z)return;Z.activeRunIds.delete(X),Z.activeRunCardIds.delete(X)}ownsRun($,X){return this.sessions.get($)?.activeRunIds.has(X)??!1}rejectPending($,X){for(let Z of $.pendingToolCalls.values())clearTimeout(Z.timer),Z.reject(Error(X));$.pendingToolCalls.clear()}getSoleActiveRunId($){return $.activeRunIds.size===1?$.activeRunIds.values().next().value:void 0}getActiveRunIdForCard($,X){let Z=[...$.activeRunCardIds.entries()].filter(([J,Q])=>$.activeRunIds.has(J)&&Q===X).map(([J])=>J);return Z.length===1?Z[0]:void 0}}function lX(){return"0.0.47".trim()?"0.0.47":"dev"}var uX=process.argv.slice(2),O2=[];for(let $ of uX){if($==="--dev"){process.env[A$]="1";continue}O2.push($)}var o=O2[0];if(o==="--help"||o==="-h"||o==="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(o==="--version"||o==="-v"||o==="version")console.log(lX()),process.exit(0);if(o)console.error(`Unknown command: ${o}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var M0=new y$,W0=null;function N0($,X){M0.sendToSession($,X)}async function pX($,X){try{let Z=P2[X.method],J=await Z(X.params);N0($,{type:"runtime_rpc_result",requestId:X.requestId,ok:!0,result:J})}catch(Z){N0($,{type:"runtime_rpc_result",requestId:X.requestId,ok:!1,error:Z instanceof Error?Z.message:String(Z)})}}var q0=!1,D0=null;async function b$(){if(q0)return;if(D0)return D0;return D0=(async()=>{try{let $=await F2(M0);S$({...$,requestedPort:$.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${$.url}`);try{await $1({onStatusChange:(X)=>{if(C1(),W0?.sendStatus(),X.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${X.packageName}: ${X.error??"unknown error"}`)}})}catch(X){console.warn("[ideawave-cli] ACP bridge setup skipped:",X instanceof Error?X.message:String(X))}await L2(),q0=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),W0?.sendStatus()}catch($){console.error("[ideawave-cli] failed to start agent host:",$),W0?.sendStatus(void 0,$ instanceof Error?$.message:String($))}finally{D0=null}})(),D0}if(process.env.APP_ENV!=="development"){let $=await K2();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)}W0=await W2({registry:M0,runtime:null,mcpReady:()=>q0,onToolMetadata:($)=>{console.log(`[ideawave-cli] session ${$} advertised ${M0.getMetadata($).length} tools`),b$()},onRunTurn:($,X)=>{console.log(`[ideawave-cli] running agent turn for card ${X.cardId} (session ${$})`),(async()=>{if(await b$(),!q0){N0($,{type:"run_settled",runId:X.runId,cardId:X.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await s1(X,(Z)=>N0($,Z))})().catch(()=>{return}).finally(()=>M0.markRunSettled($,X.runId))},onCancelRun:($,X)=>{k$(X)},onRuntimeRpc:($,X)=>{pX($,X)},onWarmupRun:($,X,Z)=>{(async()=>{if(await b$(),!q0)return{status:"retryable",error:"agent host is not ready"};return t1({cardId:X.cardId,boardId:X.boardId,userId:Z,frontendSessionId:$})})().then((J)=>{if(!X.warmupId)return;N0($,{type:"warmup_result",warmupId:X.warmupId,cardId:X.cardId,...J})})},onDisconnect:($,X)=>{a1($);for(let Z of X)k$(Z);console.log(`[ideawave-cli] browser session ${$} disconnected`)}});console.log(`[ideawave-cli] browser bridge listening on ${W0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var k2=!1;for(let $ of["SIGINT","SIGTERM"])process.once($,()=>{if(k2)return;k2=!0,i1(),(async()=>{await W0?.close().catch(()=>{return}),process.exit(0)})()});
28
+ ${Z}`),$.destroy()}function WZ($,X){return new Promise((Z,J)=>{let Q=(Y)=>{$.off("listening",j),J(Y)},j=()=>{$.off("error",Q);let Y=$.address();if(!Y||typeof Y==="string"){J(Error("Failed to read CLI bridge server address"));return}Z(Y.port)};$.once("error",Q),$.once("listening",j),$.listen(X,"127.0.0.1")})}function j6($){return new Promise((X,Z)=>{$.close((J)=>{if(J)Z(J);else X()})})}async function W6($,X=A$()){let Z=new Map,J=new Map,Q=$.maxMessageSize??tX,j=!1,Y=(U)=>{let M=J.get(U);if(M)clearTimeout(M);J.delete(U)},G=(U)=>{J.delete(U);let{activeRunIds:M}=$.registry.disconnect(U);$.onDisconnect(U,M)},z=(U,M)=>{let N={type:"cli_status",connected:!0,runtime:$.runtime,mcpReady:$.mcpReady(),error:M};if(U){let F=Z.get(U);if(F)K0(F,N);return}for(let F of Z.values())K0(F,N)},K=(U,M)=>{let N=M.sessionId.trim(),F=M.userId.trim();if(!N||!F){K0(U,{type:"cli_status",connected:!1,runtime:$.runtime,mcpReady:$.mcpReady(),error:"Missing frontend session or user id"}),U.close();return}Y(N);let V=Z.get(N);if(V&&V!==U)V.close();U.data.frontendSessionId=N,Z.set(N,U),$.registry.register({frontendSessionId:N,userId:F,tools:M.tools,send:(D)=>K0(U,D)}),z(N),$.onToolMetadata?.(N)},H=(U,M)=>{let N=$.registry.getUserId(U);if(!N)return;switch(M.type){case"bridge_ping":{let F=Z.get(U);if(F)K0(F,{type:"bridge_pong"});break}case"tool_metadata":$.registry.setMetadata(U,M.tools),$.onToolMetadata?.(U);break;case"tool_result":$.registry.handleToolResult(U,M);break;case"run_turn":$.registry.markRunActive(U,M.run.runId,M.run.cardId),$.onRunTurn(U,{...M.run,frontendSessionId:U,userId:N});break;case"cancel_run":if($.registry.ownsRun(U,M.runId))$.onCancelRun(U,M.runId);break;case"runtime_rpc":$.onRuntimeRpc(U,M);break;case"warmup_run":$.onWarmupRun(U,{...M,frontendSessionId:U},N);break;default:break}},B=(U,M)=>{let N=J6(U.headers.origin),F=Z6(N),V={Vary:"Origin"};if(F&&N)V["Access-Control-Allow-Origin"]=N,V["Access-Control-Allow-Private-Network"]="true";if(U.method==="OPTIONS"){M.writeHead(204,{...V,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),M.end();return}if(U.method!=="GET"){M.writeHead(405,V),M.end();return}M.writeHead(200,{...V,"content-type":"application/json","cache-control":"no-store"}),M.end(JSON.stringify({ideawave:!0,runtime:$.runtime,mcpReady:$.mcpReady()}))};for(let U of X){let M=oX((V,D)=>{if(new URL(V.url??"/","http://127.0.0.1").pathname===e1){B(V,D);return}D.writeHead(404,{"content-type":"text/plain"}),D.end("IdeaWave CLI bridge")}),N=new sX({noServer:!0,maxPayload:Q}),F=(V)=>{if(V.idleTimer)clearTimeout(V.idleTimer);V.idleTimer=setTimeout(()=>{V.close()},rX),V.idleTimer.unref?.()};N.on("connection",(V)=>{let D=V;D.data={id:nX(),frontendSessionId:null},D.idleTimer=null,F(D),D.on("ping",()=>F(D)),D.on("pong",()=>F(D)),D.on("error",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);D.close()}),D.on("message",(x)=>{F(D);let k=YZ(x);if(Q>0&&k.length>Q)return;let A=S0(k);if(!A)return;let _=D.data.frontendSessionId;if(!_){if(A.type==="bridge_probe")K0(D,{type:"bridge_probe_ack",protocolVersion:A.protocolVersion});else if(A.type==="frontend_hello")K(D,A);return}H(_,A)}),D.on("close",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);let x=D.data.frontendSessionId;if(!x)return;if(Z.get(x)!==D)return;if(Z.delete(x),Y(x),j)return;J.set(x,setTimeout(()=>G(x),eX))})}),M.on("upgrade",(V,D,x)=>{if(new URL(V.url??"/","http://127.0.0.1").pathname!==_$){Q6(D,404,"Not Found");return}if(!Z6(J6(V.headers.origin))){Q6(D,403,"Forbidden");return}N.handleUpgrade(V,D,x,(A)=>{N.emit("connection",A,V)})});try{let V=await WZ(M,U);return{url:`ws://127.0.0.1:${V}${_$}`,port:V,sendStatus:z,close:async()=>{j=!0;for(let D of J.values())clearTimeout(D);J.clear();for(let D of N.clients){let x=D;if(x.idleTimer)clearTimeout(x.idleTimer);x.close()}N.close(),await j6(M).catch(()=>{return})}}}catch(V){if(N.close(),await j6(M).catch(()=>{return}),V?.code==="EADDRINUSE")continue;throw V}}throw Error(`No free IdeaWave CLI bridge port found in ${X[0]}-${X.at(-1)}`)}import{Server as PZ}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as LZ,ListToolsRequestSchema as kZ}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as zZ}from"node:crypto";import{createServer as GZ}from"node:http";import{StreamableHTTPServerTransport as HZ}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as H6}from"@modelcontextprotocol/sdk/types.js";var V6=new Set(["127.0.0.1","localhost","[::1]","::1"]);function VZ($){let X=$.trim();if(X.length===0)return null;if(X.startsWith("[")){let j=X.indexOf("]");if(j===-1)return null;let Y=X.slice(0,j+1),G=X.slice(j+1);if(G.length===0)return{host:Y,port:null};if(!G.startsWith(":"))return null;let z=Number(G.slice(1));if(!Number.isInteger(z)||z<=0||z>65535)return null;return{host:Y,port:z}}let Z=X.lastIndexOf(":");if(Z===-1)return{host:X,port:null};let J=X.slice(Z+1),Q=Number(J);if(!Number.isInteger(Q)||Q<=0||Q>65535)return{host:X,port:null};return{host:X.slice(0,Z),port:Q}}function z6($){return V6.has($)||V6.has($.toLowerCase())}function G6($,X){let Z=$.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let J=VZ(Z);if(!J)return{ok:!1,status:403,reason:"bad-host"};if(!z6(J.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(J.port!==null&&J.port!==X)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(!z6(j.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var U6="/mcp",UZ=43274,M6=16777216,DZ=1800000,MZ=300000,D6=200,NZ=-32700,n=-32600,T$=-32603;function m($,X,Z,J,Q){$.statusCode=X,$.setHeader("content-type","application/json"),$.end(JSON.stringify({jsonrpc:"2.0",error:{code:Z,message:J,...Q?{data:Q}:{}},id:null}))}class f$ extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class R$ extends Error{constructor(){super(`body exceeds ${M6} bytes`);this.name="BodyTooLargeError"}}async function qZ($){if($.method&&$.method!=="POST")return;let X=$.headers["content-type"];if(typeof X==="string"&&X.trim().length>0){if(!X.toLowerCase().includes("application/json"))throw new f$}let Z=0,J=[];for await(let j of $){let Y=typeof j==="string"?Buffer.from(j):j;if(Z+=Y.byteLength,Z>M6)throw new R$;J.push(Y)}if(J.length===0)return;let Q=Buffer.concat(J).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function BZ($){if(Array.isArray($))return $.some(H6);return H6($)}function xZ($){if(typeof $==="number")return $;let X=process.env.IDEAWAVE_MCP_PORT;if(X&&X.trim().length>0){let Z=Number(X);if(Number.isInteger(Z)&&Z>=0&&Z<65536)return Z}return UZ}async function FZ($,X){let Z=(Q)=>new Promise((j,Y)=>{let G=(K)=>{$.off("listening",z),Y(K)},z=()=>{$.off("error",G),j()};$.once("error",G),$.once("listening",z),$.listen(Q,"127.0.0.1")});try{await Z(X)}catch(Q){if(Q.code!=="EADDRINUSE"||X===0)throw Q;console.warn(`[mcp] port ${X} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await Z(0)}let J=$.address();if(J==null||typeof J==="string")throw Error("[mcp] failed to read bound address");return J.port}function CZ($,X){if(X&&typeof X==="object"&&!Array.isArray(X)){let J=X.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 Z=$.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function N6($){let X=new Map,Z=0;function J(K){let H=X.get(K);if(H)H.lastActivity=Date.now()}async function Q(K,H){X.delete(K),await H.transport.close().catch(()=>{return})}async function j(){let K=null,H=1/0;for(let[B,U]of X)if(U.lastActivity<H)H=U.lastActivity,K=B;if(K!==null){let B=X.get(K);if(B)console.warn(`[mcp] session cap of ${D6} reached; evicting ${K}`),await Q(K,B)}}let Y=setInterval(()=>{let K=Date.now()-DZ;for(let[H,B]of X)if(B.lastActivity<K)console.log(`[mcp] sweeping idle session ${H}`),Q(H,B)},MZ);Y.unref?.();let G=GZ((K,H)=>{(async()=>{let B;try{B=new URL(K.url??"/","http://127.0.0.1").pathname}catch{m(H,400,n,"bad-url");return}if(B!==U6){m(H,404,n,"not-found");return}let U=K.method??"POST";if(U!=="POST"&&U!=="GET"&&U!=="DELETE"){H.setHeader("Allow","GET, POST, DELETE"),m(H,405,n,"method-not-allowed");return}let M=G6(K,Z);if(!M.ok){m(H,M.status,n,"forbidden",{reason:M.reason});return}let N=K.headers["mcp-session-id"],F=typeof N==="string"?N:void 0;if(U==="GET"||U==="DELETE"){if(!F||!X.has(F)){m(H,400,n,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let x=X.get(F).transport;J(F);try{await x.handleRequest(K,H)}catch(k){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",k),!H.headersSent)m(H,500,T$,"internal")}return}let V;try{V=await qZ(K)}catch(x){if(x instanceof f$){m(H,415,n,"expected-application-json");return}if(x instanceof R$){m(H,413,n,"body-too-large");return}m(H,400,NZ,"invalid-json");return}let D;if(F&&X.has(F))D=X.get(F).transport,J(F);else if(!F&&V!==void 0&&BZ(V)){let x=K.headers["x-ideawave-user-id"],k=typeof x==="string"&&x.trim().length>0?x.trim():null,A=K.headers["x-ideawave-frontend-session-id"],_=typeof A==="string"&&A.trim().length>0?A.trim():null,P=K.headers["x-ideawave-tool-surface"],W=typeof P==="string"&&P.trim()==="read"?"read":"full",C=K.headers["x-ideawave-images-supported"],T=typeof C==="string"&&C.trim()==="1",f=K.headers["x-ideawave-card-id"],L=typeof f==="string"&&f.trim().length>0?f.trim():null,R=K.headers["x-ideawave-board-id"],E=typeof R==="string"&&R.trim().length>0?R.trim():null,I=K.headers["x-ideawave-run-folder"],p=typeof I==="string"&&I.trim().length>0?I.trim():null,B0=CZ(K,V);if(X.size>=D6)await j();let X0=null,s=new HZ({sessionIdGenerator:()=>zZ(),onsessioninitialized:(Z0)=>{X0=Z0,X.set(Z0,{transport:s,lastActivity:Date.now()})},onsessionclosed:(Z0)=>{X.delete(Z0)}});s.onclose=()=>{if(s.sessionId)X.delete(s.sessionId)};try{await $.buildServer({userId:k,frontendSessionId:_,boardId:E,toolSurface:W,imagesSupported:T,cardId:L,runFolder:p,clientHint:B0}).connect(s)}catch(Z0){if(console.error("[mcp] buildServer/connect failed",Z0),X0)X.delete(X0);await s.close().catch(()=>{return}),m(H,500,T$,"server-init-failed");return}D=s}else{m(H,400,n,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await D.handleRequest(K,H,V)}catch(x){if(console.error("[mcp] transport.handleRequest threw",x),!H.headersSent)m(H,500,T$,"internal")}})().catch((B)=>{console.error("[mcp] unhandled request handler error:",B)})});return Z=await FZ(G,xZ($.port)),{url:`http://127.0.0.1:${Z}${U6}`,port:Z,close:async()=>{clearInterval(Y);for(let K of X.values())await K.transport.close().catch(()=>{return});X.clear(),await new Promise((K)=>G.close(()=>K()))}}}var OZ={name:"ideawave-board",version:"1.0.0"},g0="list_run_folder",c0="read_run_folder_file",x6=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",g0,c0]),F6=new Set(["inspect_diagram"]),_Z=[{name:g0,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:c0,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 E$($){return{content:[{type:"text",text:$}]}}function AZ($){return E$(JSON.stringify($,null,2))}function q6($){return{...E$($),isError:!0}}function wZ($,X,Z="full",J=!1){return $.getMetadata(X).filter((Q)=>{let j=E0(Q.name);if(Z==="read"&&!x6.has(j))return!1;if(!J&&F6.has(j))return!1;return!0}).map((Q)=>({name:Q.name,description:Q.description,inputSchema:Q.inputSchema}))}function TZ($,X,Z={}){let J=wZ($,X,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...J,..._Z]:J}function B6($,X){if(!$||typeof $!=="object"||Array.isArray($))return null;let Z=$[X];return typeof Z==="string"?Z:null}async function fZ($,X,Z){if(Z&&Z.trim().length>0)return Z.trim();if(!$||!X)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await i({boardId:$,cardId:X})).runFolder}async function RZ($){let X=await fZ($.boardId,$.cardId,$.runFolder);if($.name===g0){let Z=B6($.args,"path")??"",J=await O1(X,Z);return AZ(J)}if($.name===c0){let Z=B6($.args,"path");if(!Z)return q6("read_run_folder_file requires a path.");return E$(await R0(X,Z))}return q6(`Unknown local tool "${$.name}"`)}function EZ($,X,Z,J,Q,j="full",Y=!1){let G=new PZ(OZ,{capabilities:{tools:{}}}),z=async()=>{if(Y)return!0;if(a1(J))return!0;if(Z&&J)try{return(await i({boardId:Z,cardId:J})).adapter.supportsImages===!0}catch{return!1}return!1};return G.setRequestHandler(kZ,async()=>({tools:TZ($,X,{includeRunFolderTools:Boolean(Q||Z&&J),toolSurface:j,imagesSupported:await z()})})),G.setRequestHandler(LZ,async(K)=>{let{name:H,arguments:B}=K.params,U=E0(H);try{if(U===g0||U===c0)return await RZ({name:U,args:B,boardId:Z,cardId:J,runFolder:Q});if(j==="read"&&!x6.has(U))throw Error(`Tool "${H}" is not available in read-only mode`);if(F6.has(U)&&!await z())throw Error(`Tool "${H}" requires a runtime that supports image input`);let M=await $.callTool(X,U,B??{},void 0,J??void 0);if(M&&typeof M==="object"&&Array.isArray(M.content))return M;return{content:[{type:"text",text:typeof M==="string"?M:JSON.stringify(M)}]}}catch(M){return{content:[{type:"text",text:M instanceof Error?M.message:"Tool call failed"}],isError:!0}}}),G}function C6($,X){return N6({buildServer:(Z)=>EZ($,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:X})}import l0 from"node:fs/promises";import y$ from"node:os";import u0 from"node:path";function P6(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function yZ(){let[$,X]=await Promise.all([h(),F1()]),Z=$.globalDefaultConfigId?$.runtimes.find((J)=>J.id===$.globalDefaultConfigId)??null:null;return{runtimes:$.runtimes,globalDefaultConfigId:$.globalDefaultConfigId,globalDefaultEffective:Z?{runFolder:Z.runFolder??y$.homedir(),modelId:Z.defaultModelId??null,configValues:Z.defaultConfigValues??{}}:null,knownAdapters:j0().map((J)=>({id:J.id,displayName:J.displayName})),readiness:X}}async function bZ($){try{let X=await i({boardId:$.boardId,cardId:$.cardId});return{resolved:{configId:X.entry.id,adapterId:X.entry.kind==="registered"?X.entry.adapterId:null,displayName:X.entry.displayName,runFolder:X.runFolder,modelId:X.modelId,configValues:X.configValues}}}catch(X){if(X instanceof t)return{resolved:null};throw X}}async function vZ($){return g((X)=>{let Z=X.runtimes.find((j)=>j.kind==="registered"&&j.adapterId===$.adapterId);if(Z)return Z;let J=j0().find((j)=>j.id===$.adapterId);if(!J)throw Error(`Unknown adapterId: ${$.adapterId}`);let Q={id:P6(),kind:"registered",adapterId:$.adapterId,displayName:J.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Q),Q})}async function IZ($){return g((X)=>{let Z={id:P6(),kind:"custom",displayName:$.displayName,command:$.command,args:$.args,env:$.env,runFolder:$.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Z),Z})}async function hZ($){await g((X)=>{if(X.runtimes=X.runtimes.filter((Z)=>Z.id!==$.runtimeConfigId),X.globalDefaultConfigId===$.runtimeConfigId)X.globalDefaultConfigId=null;for(let Z of Object.keys(X.boardOverrides))if(X.boardOverrides[Z].runtimeConfigId===$.runtimeConfigId)delete X.boardOverrides[Z];for(let Z of Object.keys(X.cardOverrides))if(X.cardOverrides[Z].runtimeConfigId===$.runtimeConfigId)delete X.cardOverrides[Z]})}async function SZ($){await g((X)=>{let Z=X.runtimes.find((J)=>J.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);if(X.globalDefaultConfigId=$.runtimeConfigId,$.runFolder!==void 0)Z.runFolder=$.runFolder;if($.modelId!==void 0)Z.defaultModelId=$.modelId;if($.configValues!==void 0)Z.defaultConfigValues=$.configValues})}async function mZ($){$.boardId,await g((X)=>{if($.runtimeConfigId===null){delete X.cardOverrides[$.cardId];return}if(!X.runtimes.some((Q)=>Q.id===$.runtimeConfigId))throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=X.cardOverrides[$.cardId];X.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 gZ($){let Z=(await h()).runtimes.find((Y)=>Y.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=c(Z),Q=await J.resolveSpawnConfig(Z),j=Z.runFolder??y$.homedir();try{let Y=await c1({spawn:{...Q,cwd:j},modelId:$.modelId??Z.defaultModelId??null,configValues:$.configValues??Z.defaultConfigValues??{}}),G=T0({adapterId:J.id,models:Y.models,currentModelId:Y.currentModelId}),z=new Date().toISOString();return await g((K)=>{let H=K.runtimes.find((B)=>B.id===$.runtimeConfigId);if(H)H.discoveredModels=G,H.discoveredConfigOptions=Y.configOptions,H.discoveredAt=z}),{ok:!0,models:G,configOptions:Y.configOptions,currentModelId:Y.currentModelId}}catch(Y){if(Y instanceof J0)throw Error(`${Y.message}${J.authHint?` ${J.authHint}`:""}`);if(Y instanceof O||Y instanceof d)throw Error(Y.message);throw Y}}async function cZ($){let X=y$.homedir(),Z=$.path?.trim()?$.path.trim():X,J=u0.resolve(Z),Q=!0;try{if(!(await l0.stat(J)).isDirectory())J=u0.dirname(J)}catch{Q=!1,J=X}let j=[];try{j=(await l0.readdir(J,{withFileTypes:!0})).filter((z)=>z.isDirectory()&&!z.name.startsWith(".")).map((z)=>({name:z.name,path:u0.join(J,z.name)})).sort((z,K)=>z.name.localeCompare(K.name))}catch{j=[]}let Y=u0.dirname(J);return{path:J,parent:Y===J?null:Y,home:X,exists:Q,entries:j}}var L6={list:yZ,getEffectiveForCard:bZ,registerRegistered:vZ,registerCustom:IZ,unregister:hZ,setUserDefault:SZ,setCardOverride:mZ,refreshModels:gZ,browseFolder:cZ};var lZ=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function uZ(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function k6(){try{let $=await h();if($.globalDefaultConfigId){if($.runtimes.some((Z)=>Z.id===$.globalDefaultConfigId))return $.globalDefaultConfigId}for(let X of lZ){if((await C1(X.id))?.status!=="ready")continue;let J=null;if(await g((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((G)=>G.id===Q.globalDefaultConfigId)){J=Q.globalDefaultConfigId;return}}let j=Q.runtimes.find((Y)=>Y.kind==="registered"&&Y.adapterId===X.id);if(!j){let Y={id:uZ(),kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Q.runtimes.push(Y),j=Y}Q.globalDefaultConfigId=j.id,J=j.id}),J)return console.log(`[ideawave-cli] using agent runtime: ${X.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 pZ(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class b${sessions=new Map;createCallId;toolCallTimeoutMs;constructor($={}){this.createCallId=$.createCallId??pZ,this.toolCallTimeoutMs=$.toolCallTimeoutMs??120000}register($){let X=this.sessions.get($.frontendSessionId);if(X){if(X.userId!==$.userId)this.rejectPending(X,"frontend session user changed"),X.activeRunIds.clear();this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:X.pendingToolCalls,activeRunIds:X.activeRunIds,activeRunCardIds:X.activeRunCardIds});return}this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect($,X="frontend session disconnected"){let Z=this.sessions.get($);if(!Z)return{activeRunIds:[]};return this.sessions.delete($),this.rejectPending(Z,X),{activeRunIds:Array.from(Z.activeRunIds)}}sessionCount(){return this.sessions.size}has($){return this.sessions.has($)}getUserId($){return this.sessions.get($)?.userId??null}setMetadata($,X){let Z=this.sessions.get($);if(Z)Z.tools=X}getMetadata($){if(!$)return[];return this.sessions.get($)?.tools??[]}sendToSession($,X){let Z=this.sessions.get($);if(!Z)return!1;return Z.send(X),!0}callTool($,X,Z,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 Y=this.createCallId();return new Promise((G,z)=>{let K=setTimeout(()=>{j.pendingToolCalls.delete(Y),z(Error(`Tool "${X}" timed out waiting for the frontend`))},this.toolCallTimeoutMs),H=J??(Q?this.getActiveRunIdForCard(j,Q):this.getSoleActiveRunId(j)),B=Q??(H?j.activeRunCardIds.get(H):void 0);j.pendingToolCalls.set(Y,{resolve:G,reject:z,timer:K}),j.send({type:"tool_call",callId:Y,name:X,args:Z,...H?{runId:H}:{},...B?{cardId:B}:{}})})}handleToolResult($,X){let Z=this.sessions.get($);if(!Z)return;let J=Z.pendingToolCalls.get(X.callId);if(!J)return;if(Z.pendingToolCalls.delete(X.callId),clearTimeout(J.timer),X.ok)J.resolve(X.result);else J.reject(Error(X.error??"Tool execution failed"))}markRunActive($,X,Z){let J=this.sessions.get($);if(!J)return;if(J.activeRunIds.add(X),Z)J.activeRunCardIds.set(X,Z)}markRunSettled($,X){let Z=this.sessions.get($);if(!Z)return;Z.activeRunIds.delete(X),Z.activeRunCardIds.delete(X)}ownsRun($,X){return this.sessions.get($)?.activeRunIds.has(X)??!1}rejectPending($,X){for(let Z of $.pendingToolCalls.values())clearTimeout(Z.timer),Z.reject(Error(X));$.pendingToolCalls.clear()}getSoleActiveRunId($){return $.activeRunIds.size===1?$.activeRunIds.values().next().value:void 0}getActiveRunIdForCard($,X){let Z=[...$.activeRunCardIds.entries()].filter(([J,Q])=>$.activeRunIds.has(J)&&Q===X).map(([J])=>J);return Z.length===1?Z[0]:void 0}}function dZ(){return"0.0.49".trim()?"0.0.49":"dev"}var aZ=process.argv.slice(2),_6=[];for(let $ of aZ){if($==="--dev"){process.env[w$]="1";continue}_6.push($)}var o=_6[0];if(o==="--help"||o==="-h"||o==="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(o==="--version"||o==="-v"||o==="version")console.log(dZ()),process.exit(0);if(o)console.error(`Unknown command: ${o}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var M0=new b$,Y0=null;function N0($,X){M0.sendToSession($,X)}async function iZ($,X){try{let Z=L6[X.method],J=await Z(X.params);N0($,{type:"runtime_rpc_result",requestId:X.requestId,ok:!0,result:J})}catch(Z){N0($,{type:"runtime_rpc_result",requestId:X.requestId,ok:!1,error:Z instanceof Error?Z.message:String(Z)})}}var q0=!1,D0=null;async function v$(){if(q0)return;if(D0)return D0;return D0=(async()=>{try{let $=await C6(M0);m$({...$,requestedPort:$.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${$.url}`);try{await X1({onStatusChange:(X)=>{if(P1(),Y0?.sendStatus(),X.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${X.packageName}: ${X.error??"unknown error"}`)}})}catch(X){console.warn("[ideawave-cli] ACP bridge setup skipped:",X instanceof Error?X.message:String(X))}await k6(),q0=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),Y0?.sendStatus()}catch($){console.error("[ideawave-cli] failed to start agent host:",$),Y0?.sendStatus(void 0,$ instanceof Error?$.message:String($))}finally{D0=null}})(),D0}if(process.env.APP_ENV!=="development"){let $=await Y6();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)}Y0=await W6({registry:M0,runtime:null,mcpReady:()=>q0,onToolMetadata:($)=>{console.log(`[ideawave-cli] session ${$} advertised ${M0.getMetadata($).length} tools`),v$()},onRunTurn:($,X)=>{console.log(`[ideawave-cli] running agent turn for card ${X.cardId} (session ${$})`),(async()=>{if(await v$(),!q0){N0($,{type:"run_settled",runId:X.runId,cardId:X.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await t1(X,(Z)=>N0($,Z))})().catch(()=>{return}).finally(()=>M0.markRunSettled($,X.runId))},onCancelRun:($,X)=>{O$(X)},onRuntimeRpc:($,X)=>{iZ($,X)},onWarmupRun:($,X,Z)=>{(async()=>{if(await v$(),!q0)return{status:"retryable",error:"agent host is not ready"};return r1({cardId:X.cardId,boardId:X.boardId,userId:Z,frontendSessionId:$})})().then((J)=>{if(!X.warmupId)return;N0($,{type:"warmup_result",warmupId:X.warmupId,cardId:X.cardId,...J})})},onDisconnect:($,X)=>{i1($);for(let Z of X)O$(Z);console.log(`[ideawave-cli] browser session ${$} disconnected`)}});console.log(`[ideawave-cli] browser bridge listening on ${Y0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var O6=!1;for(let $ of["SIGINT","SIGTERM"])process.once($,()=>{if(O6)return;O6=!0,n1(),(async()=>{await Y0?.close().catch(()=>{return}),process.exit(0)})()});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideawave",
3
- "version": "0.0.47",
3
+ "version": "0.0.49",
4
4
  "description": "IdeaWave CLI",
5
5
  "type": "module",
6
6
  "bin": {