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