ideawave 0.0.72 → 0.0.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +4 -3
  2. package/dist/index.mjs +184 -90
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Run local coding agents from an IdeaWave board.
4
4
 
5
5
  ```bash
6
- npx ideawave
6
+ npx --yes ideawave@latest
7
7
  ```
8
8
 
9
9
  Then open [ideawave.app](https://ideawave.app), choose a board, and start an agent run.
@@ -22,7 +22,7 @@ Then open [ideawave.app](https://ideawave.app), choose a board, and start an age
22
22
  ## Commands
23
23
 
24
24
  ```bash
25
- npx ideawave --dev
25
+ npx --yes ideawave@latest --dev
26
26
  npx ideawave --help
27
27
  npx ideawave --version
28
28
  ```
@@ -33,7 +33,8 @@ If a runtime appears unavailable, confirm its command is on your `PATH` and that
33
33
 
34
34
  For supported runtimes, the CLI fetches small ACP bridge packages on first use. npm caches them, so later runs are fast. If npm's cache was cleared, keep the CLI running and retry after the bridge downloads again.
35
35
 
36
- The CLI advertises the `browser-proxy-v5` capability so browser cards can route
36
+ The CLI advertises the `browser-proxy-v6` capability so browser cards can share
37
+ one local browser profile while routing
37
38
  pages and subresources through the local browser-kit proxy. The normal command
38
39
  keeps screenshot capture available. `--dev` skips screenshot-engine setup and
39
40
  allows Railway PR previews for browser-card development. Existing saved browser
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.round(X*10)/10}function q(X,$={}){if(typeof process<"u"&&process.env.IDEAWAVE_AGENT_RUNTIME_TRACE==="0")return;let Z=Object.fromEntries(Object.entries($).filter(([,Q])=>Q!==void 0));console.info("[agent-runtime-trace]",JSON.stringify({event:X,epochMs:Date.now(),monotonicMs:f2(),...typeof document>"u"?{}:{visibility:document.visibilityState},...Z}))}var y2=600000,b2=60000,B1=200,E2=2,f=new Map,i=null;function T2(X){X.then(($)=>$.dispose()).catch(()=>{return})}function h0(X){for(let $ of X.idleWaiters)$();X.idleWaiters.clear()}function t(X,$){if(f.get(X)!==$)return;f.delete(X),h0($),T2($.sessionPromise)}function v2(){if(i!==null)return;i=setInterval(()=>{let X=Date.now();for(let[$,Z]of f){if(Z.inUse)continue;if(X-Z.lastUsed<y2)continue;t($,Z)}if(f.size===0&&i!==null)clearInterval(i),i=null},b2),i.unref?.()}function h2(){if(f.size<B1)return;let X=null,$=1/0;for(let[Q,W]of f){if(W.inUse)continue;if(W.lastUsed>=$)continue;X=Q,$=W.lastUsed}if(!X)return;let Z=f.get(X);if(!Z)return;t(X,Z)}function I2(){let X=0;while(f.size>B1){let $=null,Z=null;for(let[Q,W]of f){if(W.inUse)continue;if(Z&&W.lastUsed>=Z.lastUsed)continue;$=Q,Z=W}if(!$||!Z)break;t($,Z),X+=1}if(X>0)q("session_pool.global_idle_trimmed",{evictedSessions:X,poolEntries:f.size})}function S2(X){let $=Array.from(f.entries()).filter(([,Q])=>Q.frontendSessionId===X&&!Q.inUse).sort(([,Q],[,W])=>Q.lastUsed-W.lastUsed),Z=$.length-E2;if(Z<=0)return;for(let[Q,W]of $.slice(0,Z))t(Q,W);q("session_pool.frontend_idle_trimmed",{frontendSessionId:X,evictedSessions:Z,poolEntries:f.size})}function DX(X,$,Z){return`${X}:${$}:${Z}`}async function I0(X){let $=f.get(X.key);if($){if($.inUse)return q("session_pool.wait_for_idle",{frontendSessionId:$.frontendSessionId,poolEntries:f.size}),await new Promise((Q)=>$.idleWaiters.add(Q)),I0(X);if($.fingerprint===X.fingerprint){$.inUse=!0,$.lastUsed=Date.now();try{let Q=await $.sessionPromise;if(Q.isAlive()){if($.frontendSessionId)q("session_pool.reuse",{frontendSessionId:$.frontendSessionId,poolEntries:f.size});return Q}}catch{}t(X.key,$)}else t(X.key,$)}let Z=X.open();if(h2(),f.set(X.key,{key:X.key,frontendSessionId:X.frontendSessionId??null,fingerprint:X.fingerprint,sessionPromise:Z,lastUsed:Date.now(),inUse:!0,idleWaiters:new Set}),v2(),X.frontendSessionId)q("session_pool.open",{frontendSessionId:X.frontendSessionId,poolEntries:f.size});try{return await Z}catch(Q){let W=f.get(X.key);if(W?.sessionPromise===Z)t(X.key,W);throw Q}}function wX(X,$=!1){let Z=f.get(X);if(!Z)return;if($){t(X,Z);return}if(Z.inUse=!1,Z.lastUsed=Date.now(),Z.frontendSessionId)S2(Z.frontendSessionId),q("session_pool.release",{frontendSessionId:Z.frontendSessionId,poolEntries:f.size});if(I2(),f.get(X)===Z)h0(Z)}async function F1(X){let $=Array.from(f.entries()).filter(([,Z])=>Z.frontendSessionId===X);for(let[Z,Q]of $)f.delete(Z),h0(Q);return await Promise.all($.map(([,Z])=>Z.sessionPromise.then((Q)=>Q.dispose()).catch(()=>{return}))),q("session_pool.frontend_evicted",{frontendSessionId:X,evictedSessions:$.length,poolEntries:f.size}),$.length}async function g2(){let X=Array.from(f.values());f.clear();for(let $ of X)h0($);if(i!==null)clearInterval(i),i=null;await Promise.all(X.map(($)=>$.sessionPromise.then((Z)=>Z.dispose()).catch(()=>{return})))}function NX(X){let $=Object.entries(X.configValues??{}),Z=$.length>0?JSON.stringify(Object.fromEntries($.sort(([Q],[W])=>Q.localeCompare(W)))):"";return[X.adapterId,X.configId??"",X.modelId??"",Z,X.mcpUrl??"",X.runFolder??"",X.toolSurface??"full"].join(" ")}var P1=!1;function m2(){if(P1)return;P1=!0;let X=()=>{g2()};process.once("beforeExit",X),process.once("SIGTERM",X),process.once("SIGINT",X)}m2();import{readFileSync as p2}from"node:fs";import{homedir as c2}from"node:os";import{join as S0}from"node:path";function l2(){let X=c2();switch(process.platform){case"win32":return process.env.APPDATA??S0(X,"AppData","Roaming");case"darwin":return S0(X,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??S0(X,".config")}}function O1(){let X=process.env.IDEAWAVE_MCP_JSON_PATH;if(X&&X.trim().length>0)return X;return S0(l2(),"ideawave","mcp.json")}var q1=null;function _1(X){q1=X}var u2=86400000;function a2(){let X;try{X=p2(O1(),"utf8")}catch{return null}let $;try{$=JSON.parse(X)}catch{return null}if(typeof $.url!=="string")return null;if(typeof $.startedAt==="string"){let Z=Date.parse($.startedAt);if(!Number.isNaN(Z)){if(Date.now()-Z>u2)return null}}if(typeof $.pid==="number"&&$.pid>0)try{process.kill($.pid,0)}catch(Z){if(Z?.code!=="EPERM")return null}return{url:$.url}}function k1(X,$={}){let Z=[];if($.userId&&$.userId.trim().length>0)Z.push({name:"X-Ideawave-User-Id",value:$.userId.trim()});if($.frontendSessionId&&$.frontendSessionId.trim().length>0)Z.push({name:"X-Ideawave-Frontend-Session-Id",value:$.frontendSessionId.trim()});if($.toolSurface==="read")Z.push({name:"X-Ideawave-Tool-Surface",value:"read"});if($.imagesSupported)Z.push({name:"X-Ideawave-Images-Supported",value:"1"});if($.cardId&&$.cardId.trim().length>0)Z.push({name:"X-Ideawave-Card-Id",value:$.cardId.trim()});if($.boardId&&$.boardId.trim().length>0)Z.push({name:"X-Ideawave-Board-Id",value:$.boardId.trim()});if($.runFolder&&$.runFolder.trim().length>0)Z.push({name:"X-Ideawave-Run-Folder",value:$.runFolder.trim()});return{type:"http",name:"ideawave-board",url:X,headers:Z}}function MX(X={}){let $=q1;if($)return k1($.url,X);let Z=a2();if(!Z)return null;return k1(Z.url,X)}var A1="browser-proxy-v5";var d2=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","browser_rpc","browser_rpc_result","warmup_run","warmup_result"]);function g0(X){try{let $=JSON.parse(X);if($&&typeof $==="object"&&typeof $.type==="string"&&d2.has($.type))return $}catch{}return null}function m0(X){return JSON.stringify(X)}import F0 from"node:fs/promises";import r2 from"node:path";import{z as F}from"zod";var C1=F.object({id:F.string(),name:F.string().nullable().default(null),description:F.string().nullable().default(null)}),y1=F.union([F.string(),F.boolean()]),i2=F.object({value:F.string(),name:F.string(),description:F.string().nullable().default(null),group:F.string().nullable().default(null),groupName:F.string().nullable().default(null)}),R1=F.object({id:F.string(),name:F.string(),category:F.string().nullable().default(null),description:F.string().nullable().default(null),type:F.enum(["select","boolean"]),currentValue:y1.nullable().default(null),options:F.array(i2).default([])}),LX=F.record(F.string(),y1).default({}),o2=F.discriminatedUnion("kind",[F.object({id:F.string(),kind:F.literal("registered"),adapterId:F.enum(["claude-code","opencode","codex","copilot"]),displayName:F.string(),runFolder:F.string().nullable(),defaultModelId:F.string().nullable().default(null),defaultConfigValues:LX,discoveredModels:F.array(C1).default([]),discoveredConfigOptions:F.array(R1).default([]),discoveredAt:F.string().nullable().default(null)}),F.object({id:F.string(),kind:F.literal("custom"),displayName:F.string(),command:F.string(),args:F.array(F.string()),env:F.record(F.string(),F.string()),runFolder:F.string().nullable(),defaultModelId:F.string().nullable().default(null),defaultConfigValues:LX,discoveredModels:F.array(C1).default([]),discoveredConfigOptions:F.array(R1).default([]),discoveredAt:F.string().nullable().default(null)})]),f1=F.object({runtimeConfigId:F.string(),runFolder:F.string().nullable(),modelId:F.string().nullable().default(null),configValues:LX}),c0=F.object({version:F.literal(1),globalDefaultConfigId:F.string().nullable(),runtimes:F.array(o2),boardOverrides:F.record(F.string(),f1).default({}),cardOverrides:F.record(F.string(),f1).default({})});import n2 from"node:os";import l0 from"node:path";function t2(){let X=n2.homedir();switch(process.platform){case"win32":return process.env.APPDATA??l0.join(X,"AppData","Roaming");case"darwin":return l0.join(X,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??l0.join(X,".config")}}function p0(){let X=process.env.IDEAWAVE_RUNTIME_CONFIG_PATH;if(X)return X;return l0.join(t2(),"ideawave","runtimes.json")}var s2={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},b1=new Map;function e2(X){return b1.get(X)??Promise.resolve()}function X6(X,$){b1.set(X,$)}async function m(X){let $=X??p0(),Z;try{Z=await F0.readFile($,"utf-8")}catch(W){if(W.code==="ENOENT")return structuredClone(s2);throw W}return c0.parse(JSON.parse(Z))}async function p(X,$){let Z=$??p0(),Q=e2(Z).then(async()=>{let W=await m(Z),K=structuredClone(W),Y=await X(K);return await $6(K,Z),Y});return X6(Z,Q.catch(()=>{return})),Q}async function $6(X,$){let Z=$??p0(),Q=r2.dirname(Z);await F0.mkdir(Q,{recursive:!0});let W=`${Z}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`,K=JSON.stringify(X,null,2);await F0.writeFile(W,K,"utf-8");try{await F0.rename(W,Z)}catch(Y){throw await F0.unlink(W).catch(()=>{return}),Y}}import{spawn as z6}from"node:child_process";import{closeSync as U6,existsSync as I1,mkdirSync as S1,openSync as H6,readFileSync as x6,renameSync as D6,rmSync as g1,statSync as w6,unlinkSync as N6,writeFileSync as M6}from"node:fs";import v1 from"node:os";import J0 from"node:path";var Z6=/\.(?:cmd|bat)$/i;function Q6(X){return process.platform==="win32"&&Z6.test(X)}function u0(X){return Q6(X)?{shell:!0,windowsHide:!0}:{}}import{execFile as j6}from"node:child_process";import{promisify as G6}from"node:util";import{execFile as W6}from"node:child_process";import{promisify as K6}from"node:util";var Y6=K6(W6),PX=new Map,E1=5000,J6=/\.(?:cmd|bat|com|exe)$/i;function V6(X){let $=X.split(/\r?\n/).map((Z)=>Z.trim()).filter((Z)=>Z.length>0);if($.length===0)return null;if(process.platform!=="win32")return $[0]??null;return $.find((Z)=>J6.test(Z))??$[0]??null}async function T1(X,$=Y6){let Z=PX.get(X);if(Z&&Z.expiresAt>Date.now())return Z.value;let Q=process.platform==="win32"?"where":"which";try{let{stdout:W}=await $(Q,[X],{timeout:2000}),K=V6(W);return PX.set(X,{value:K,expiresAt:Date.now()+E1}),K}catch{return PX.set(X,{value:null,expiresAt:Date.now()+E1}),null}}class O0 extends Error{code;constructor(X,$){super(X);this.name="AcpError",this.code=$}}class Y0 extends O0{constructor(X="No ACP runtime configured"){super(X,"RUNTIME_NOT_CONFIGURED");this.name="RuntimeNotConfiguredError"}}class R extends O0{constructor(X){super(X,"RUNTIME_UNREACHABLE");this.name="RuntimeUnreachableError"}}class H0 extends O0{authMethods;constructor(X,$){super(X,"AUTH_REQUIRED");this.name="AuthRequiredError",this.authMethods=$}}class u extends O0{constructor(X="ACP session timed out"){super(X,"SESSION_TIMEOUT");this.name="SessionTimeoutError"}}var R4=G6(j6);function E(X,...$){return T1(X,...$)}function g(X){let $={};for(let[Z,Q]of Object.entries(process.env))if(typeof Q==="string")$[Z]=Q;return{...$,...X??{}}}var FX=[{adapterId:"claude-code",runtimeBinary:"claude",packageName:"@agentclientprotocol/claude-agent-acp",version:"0.61.0",warmupArgs:["--cli","--help"]},{adapterId:"codex",runtimeBinary:"codex",packageName:"@agentclientprotocol/codex-acp",version:"1.1.7",warmupArgs:["--version"]}],L6=1800000,a0=new Map;function OX(){if(process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR)return process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR;if(process.platform==="win32"){let X=process.env.LOCALAPPDATA??J0.join(v1.homedir(),"AppData","Local");return J0.join(X,"ideawave","acp-bridges")}return J0.join(process.env.XDG_CACHE_HOME??J0.join(v1.homedir(),".cache"),"ideawave","acp-bridges")}function P6(X){return X.replace(/^@/,"").replace(/[/\\]/g,"-")}function d0(){return J0.join(OX(),"install-state.json")}function kX(X){return J0.join(OX(),`${P6(X.packageName)}@${X.version}.install.lock`)}function qX(){return process.platform==="win32"?"npx.cmd":"npx"}function _X(X){return`${X.packageName}@${X.version}`}function m1(){let X=d0();if(!I1(X))return{};try{return JSON.parse(x6(X,"utf8"))}catch{return{}}}function BX(X,$){let Z=OX();S1(Z,{recursive:!0});let Q=m1();Q.bridges={...Q.bridges??{},[X.adapterId]:$},M6(`${d0()}.tmp`,`${JSON.stringify(Q,null,2)}
3
- `),D6(`${d0()}.tmp`,d0())}function c1(X){return FX.find(($)=>$.packageName===X)??null}function c(X,$,Z){return{adapterId:X.adapterId,packageName:X.packageName,version:X.version,status:$,...Z?{error:Z}:{}}}function h1(X,$){return $?.packageName===X.packageName&&$.version===X.version}function l1(X){try{return Date.now()-w6(X).mtimeMs>L6}catch{return!1}}function B6(X){let $=kX(X);if(!I1($))return!1;if(l1($))return g1($,{force:!0}),!1;return!0}function F6(X){let $=kX(X);if(S1(J0.dirname($),{recursive:!0}),l1($))g1($,{force:!0});try{let Z=H6($,"wx");return U6(Z),!0}catch{return!1}}function O6(X){N6(kX(X))}function AX(X){let $=m1().bridges?.[X.adapterId];if(h1(X,$)&&$.status==="ready")return c(X,"ready");if(a0.has(X.adapterId)||B6(X))return c(X,"installing");if(h1(X,$)&&$.status==="failed")return c(X,"failed",$.error);return c(X,"missing")}function k0(X,$){X?.onStatusChange?.($)}function k6(X,$){let Z=AX(X);if(Z.status==="ready")return k0($,Z),Z;if(Z.status==="installing"){let J=a0.get(X.adapterId);if(J&&$?.onStatusChange)J.then((G)=>k0($,G));return k0($,Z),Z}if(!F6(X))return c(X,"installing");let Q=c(X,"installing");BX(X,Q),k0($,Q);let W=()=>{},K=new Promise((J)=>{W=J});a0.set(X.adapterId,K);let Y=!1,V=(J)=>{if(Y)return;Y=!0;try{O6(X)}catch{}BX(X,J),k0($,J),a0.delete(X.adapterId),W(J)},z;try{let J=qX();z=z6(J,["-y",_X(X),...X.warmupArgs],{stdio:"ignore",windowsHide:!0,...u0(J)})}catch(J){let G=c(X,"failed",J instanceof Error?J.message:String(J));return V(G),G}return z.on("error",(J)=>{V(c(X,"failed",J.message))}),z.on("close",(J)=>{if(J===0){V(c(X,"ready"));return}V(c(X,"failed",`npx warmup exited ${J??"null"}`))}),z.unref(),Q}function x0(X){let $=c1(X);return $?AX($):null}async function p1(X){let $=[];for(let Z of FX){if(!await E(Z.runtimeBinary)){$.push(c(Z,"not_needed"));continue}$.push(k6(Z,X))}return $.filter((Z)=>Z.status!=="not_needed")}function i0(X){let $=c1(X);if(!$)return null;if(AX($).status!=="ready")return null;return{command:qX(),args:["-y",_X($)],env:{}}}function CX(X,$){if(X.command!==qX())return!1;let Z=FX.find((Q)=>X.args.includes(_X(Q)));if(!Z)return!1;return BX(Z,c(Z,"failed",$)),!0}var u1="claude",RX="@agentclientprotocol/claude-agent-acp",a1=["claude-agent-acp","claude-code-acp"],d1="Install Claude Code from https://github.com/anthropics/claude-code",i1={id:"claude-code",displayName:"Claude Code",kind:"registered",supportsImages:!0,resolveSpawnConfig:async()=>{if(!await E(u1))throw new R(`Claude Code CLI not found. ${d1}`);let $=i0(RX);if($)return{command:$.command,args:$.args,env:g($.env)};let Z=x0(RX),Q=Z?.status==="installing";for(let K of a1){let Y=await E(K);if(Y&&!Q&&Z?.status!=="failed")return{command:Y,args:[],env:g()}}let W=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 R(W)},checkReadiness:async()=>{if(!await E(u1))return{status:"not_installed",detail:d1};let $=x0(RX);if($?.status==="ready")return{status:"ready"};if($?.status==="installing")return{status:"not_running",detail:"Installing Claude Code ACP bridge..."};if($?.status==="failed")return{status:"not_running",detail:$.error??"Claude Code ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};for(let Z of a1)if(await E(Z))return{status:"ready"};return{status:"not_running",detail:"Installing Claude Code ACP bridge..."}},authHint:"Run `claude login` (or set ANTHROPIC_API_KEY)."};var o1="codex",fX="@agentclientprotocol/codex-acp",n1="codex-acp",t1="Install Codex CLI from https://developers.openai.com/codex/cli",r1={id:"codex",displayName:"Codex",kind:"registered",resolveSpawnConfig:async()=>{if(!await E(o1))throw new R(`Codex CLI not found. ${t1}`);let $=i0(fX);if($)return{command:$.command,args:$.args,env:g($.env)};let Z=x0(fX),Q=Z?.status==="installing",W=await E(n1);if(W&&!Q&&Z?.status!=="failed")return{command:W,args:[],env:g()};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 R(K)},checkReadiness:async()=>{if(!await E(o1))return{status:"not_installed",detail:t1};let $=x0(fX);if($?.status==="ready")return{status:"ready"};if($?.status==="installing")return{status:"not_running",detail:"Installing Codex ACP bridge..."};if($?.status==="failed")return{status:"not_running",detail:$.error??"Codex ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};if(await E(n1))return{status:"ready"};return{status:"not_running",detail:"Installing Codex ACP bridge..."}},authHint:"Run `codex login` (or set OPENAI_API_KEY)."};var s1="copilot",e1="copilot-acp",X$="npm i -g @github/copilot",$$={id:"copilot",displayName:"GitHub Copilot",kind:"registered",resolveSpawnConfig:async()=>{let X=await E(s1);if(X)return{command:X,args:["--acp"],env:g()};let $=await E(e1);if($)return{command:$,args:[],env:g()};throw new R(`Copilot not installed. Run: ${X$}`)},checkReadiness:async()=>{if(await E(s1))return{status:"ready"};if(await E(e1))return{status:"ready"};return{status:"not_installed",detail:X$}},authHint:"Run `gh auth login` (or `copilot login`)."};import q6 from"node:fs/promises";function _6(X){return X.startsWith("/")||/^[a-zA-Z]:[\\/]/.test(X)}async function Z$(X){if(_6(X))try{return await q6.access(X),!0}catch{return!1}return await E(X)!==null}var Q$={id:"custom",displayName:"Custom ACP",kind:"custom",resolveSpawnConfig:async(X)=>{if(X.kind!=="custom")throw new R("customAdapter received non-custom entry");if(!await Z$(X.command))throw new R(`custom: command "${X.command}" not found`);return{command:X.command,args:X.args,env:g(X.env)}},checkReadiness:async(X)=>{if(X.kind!=="custom")return{status:"unknown"};return await Z$(X.command)?{status:"ready"}:{status:"not_installed"}}};var W$="opencode",K$="Install OpenCode from https://opencode.ai",Y$={id:"opencode",displayName:"OpenCode",kind:"registered",resolveSpawnConfig:async()=>{let X=await E(W$);if(!X)throw new R(`OpenCode not installed. ${K$}`);return{command:X,args:["acp"],env:g()}},checkReadiness:async()=>{if(!await E(W$))return{status:"not_installed",detail:K$};return{status:"ready"}},authHint:"Run `opencode auth login <provider>` (or set the provider's API-key env var)."};var J$={"claude-code":i1,opencode:Y$,codex:r1,copilot:$$};function a(X){if(X.kind==="custom")return Q$;let $=J$[X.adapterId];if(!$)throw Error(`Unknown registered adapter: ${X.adapterId}`);return $}function D0(){return Object.values(J$)}var yX=new Map,o0=new Map,A6=30000;function n0(X,$){let Z=yX.get(X);if(Z&&Z.expiresAt>Date.now())return Promise.resolve(Z.value);let Q=o0.get(X);if(Q)return Q;let W=$().then((K)=>{return yX.set(X,{value:K,expiresAt:Date.now()+A6}),K}).finally(()=>{o0.delete(X)});return o0.set(X,W),W}async function V$(X){let $=await Promise.all(D0().map((K)=>n0(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(X)).runtimes.filter((K)=>K.kind==="custom"),W=await Promise.all(Q.map((K)=>n0(`custom:${K.id}`,async()=>({adapterId:K.id,...await a(K).checkReadiness(K)}))));return[...$,...W]}async function j$(X,$){let Z=D0().find((K)=>K.id===X);if(Z)return n0(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 W=(await m($)).runtimes.find((K)=>K.id===X);if(!W||W.kind!=="custom")return null;return n0(`custom:${W.id}`,async()=>({adapterId:W.id,...await a(W).checkReadiness(W)}))}function G$(){yX.clear(),o0.clear()}import{createHash as R6,randomBytes as f6,randomUUID as x$}from"node:crypto";import{WebSocket as t0,WebSocketServer as y6}from"ws";function r(X){return JSON.stringify(X).replace(/</g,"\\u003c")}function C6(X){try{let $=new URL(X);if($.protocol!=="https:"||$.hostname!=="www.google.com"||$.username||$.password||$.pathname!=="/"&&$.pathname!=="/webhp")return null;return"https://www.google.com/search"}catch{return null}}function z$(X){let $=r(C6(X.sourceUrl));return`(() => {
2
+ function T2(){let X=globalThis.performance?.now?.()??Date.now();return Math.round(X*10)/10}function _(X,$={}){if(typeof process<"u"&&process.env.IDEAWAVE_AGENT_RUNTIME_TRACE==="0")return;let Z=Object.fromEntries(Object.entries($).filter(([,W])=>W!==void 0));console.info("[agent-runtime-trace]",JSON.stringify({event:X,epochMs:Date.now(),monotonicMs:T2(),...typeof document>"u"?{}:{visibility:document.visibilityState},...Z}))}var f2=600000,v2=60000,k1=200,h2=2,y=new Map,i=null;function I2(X){X.then(($)=>$.dispose()).catch(()=>{return})}function h0(X){for(let $ of X.idleWaiters)$();X.idleWaiters.clear()}function t(X,$){if(y.get(X)!==$)return;y.delete(X),h0($),I2($.sessionPromise)}function S2(){if(i!==null)return;i=setInterval(()=>{let X=Date.now();for(let[$,Z]of y){if(Z.inUse)continue;if(X-Z.lastUsed<f2)continue;t($,Z)}if(y.size===0&&i!==null)clearInterval(i),i=null},v2),i.unref?.()}function g2(){if(y.size<k1)return;let X=null,$=1/0;for(let[W,Q]of y){if(Q.inUse)continue;if(Q.lastUsed>=$)continue;X=W,$=Q.lastUsed}if(!X)return;let Z=y.get(X);if(!Z)return;t(X,Z)}function m2(){let X=0;while(y.size>k1){let $=null,Z=null;for(let[W,Q]of y){if(Q.inUse)continue;if(Z&&Q.lastUsed>=Z.lastUsed)continue;$=W,Z=Q}if(!$||!Z)break;t($,Z),X+=1}if(X>0)_("session_pool.global_idle_trimmed",{evictedSessions:X,poolEntries:y.size})}function c2(X){let $=Array.from(y.entries()).filter(([,W])=>W.frontendSessionId===X&&!W.inUse).sort(([,W],[,Q])=>W.lastUsed-Q.lastUsed),Z=$.length-h2;if(Z<=0)return;for(let[W,Q]of $.slice(0,Z))t(W,Q);_("session_pool.frontend_idle_trimmed",{frontendSessionId:X,evictedSessions:Z,poolEntries:y.size})}function xX(X,$,Z){return`${X}:${$}:${Z}`}async function I0(X){let $=y.get(X.key);if($){if($.inUse)return _("session_pool.wait_for_idle",{frontendSessionId:$.frontendSessionId,poolEntries:y.size}),await new Promise((W)=>$.idleWaiters.add(W)),I0(X);if($.fingerprint===X.fingerprint){$.inUse=!0,$.lastUsed=Date.now();try{let W=await $.sessionPromise;if(W.isAlive()){if($.frontendSessionId)_("session_pool.reuse",{frontendSessionId:$.frontendSessionId,poolEntries:y.size});return W}}catch{}t(X.key,$)}else t(X.key,$)}let Z=X.open();if(g2(),y.set(X.key,{key:X.key,frontendSessionId:X.frontendSessionId??null,fingerprint:X.fingerprint,sessionPromise:Z,lastUsed:Date.now(),inUse:!0,idleWaiters:new Set}),S2(),X.frontendSessionId)_("session_pool.open",{frontendSessionId:X.frontendSessionId,poolEntries:y.size});try{return await Z}catch(W){let Q=y.get(X.key);if(Q?.sessionPromise===Z)t(X.key,Q);throw W}}function wX(X,$=!1){let Z=y.get(X);if(!Z)return;if($){t(X,Z);return}if(Z.inUse=!1,Z.lastUsed=Date.now(),Z.frontendSessionId)c2(Z.frontendSessionId),_("session_pool.release",{frontendSessionId:Z.frontendSessionId,poolEntries:y.size});if(m2(),y.get(X)===Z)h0(Z)}async function _1(X){let $=Array.from(y.entries()).filter(([,Z])=>Z.frontendSessionId===X);for(let[Z,W]of $)y.delete(Z),h0(W);return await Promise.all($.map(([,Z])=>Z.sessionPromise.then((W)=>W.dispose()).catch(()=>{return}))),_("session_pool.frontend_evicted",{frontendSessionId:X,evictedSessions:$.length,poolEntries:y.size}),$.length}async function l2(){let X=Array.from(y.values());y.clear();for(let $ of X)h0($);if(i!==null)clearInterval(i),i=null;await Promise.all(X.map(($)=>$.sessionPromise.then((Z)=>Z.dispose()).catch(()=>{return})))}function MX(X){let $=Object.entries(X.configValues??{}),Z=$.length>0?JSON.stringify(Object.fromEntries($.sort(([W],[Q])=>W.localeCompare(Q)))):"";return[X.adapterId,X.configId??"",X.modelId??"",Z,X.mcpUrl??"",X.runFolder??"",X.toolSurface??"full"].join(" ")}var O1=!1;function p2(){if(O1)return;O1=!0;let X=()=>{l2()};process.once("beforeExit",X),process.once("SIGTERM",X),process.once("SIGINT",X)}p2();import{readFileSync as d2}from"node:fs";import{homedir as u2}from"node:os";import{join as S0}from"node:path";function a2(){let X=u2();switch(process.platform){case"win32":return process.env.APPDATA??S0(X,"AppData","Roaming");case"darwin":return S0(X,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??S0(X,".config")}}function A1(){let X=process.env.IDEAWAVE_MCP_JSON_PATH;if(X&&X.trim().length>0)return X;return S0(a2(),"ideawave","mcp.json")}var C1=null;function R1(X){C1=X}var i2=86400000;function o2(){let X;try{X=d2(A1(),"utf8")}catch{return null}let $;try{$=JSON.parse(X)}catch{return null}if(typeof $.url!=="string")return null;if(typeof $.startedAt==="string"){let Z=Date.parse($.startedAt);if(!Number.isNaN(Z)){if(Date.now()-Z>i2)return null}}if(typeof $.pid==="number"&&$.pid>0)try{process.kill($.pid,0)}catch(Z){if(Z?.code!=="EPERM")return null}return{url:$.url}}function q1(X,$={}){let Z=[];if($.userId&&$.userId.trim().length>0)Z.push({name:"X-Ideawave-User-Id",value:$.userId.trim()});if($.frontendSessionId&&$.frontendSessionId.trim().length>0)Z.push({name:"X-Ideawave-Frontend-Session-Id",value:$.frontendSessionId.trim()});if($.toolSurface==="read")Z.push({name:"X-Ideawave-Tool-Surface",value:"read"});if($.imagesSupported)Z.push({name:"X-Ideawave-Images-Supported",value:"1"});if($.cardId&&$.cardId.trim().length>0)Z.push({name:"X-Ideawave-Card-Id",value:$.cardId.trim()});if($.boardId&&$.boardId.trim().length>0)Z.push({name:"X-Ideawave-Board-Id",value:$.boardId.trim()});if($.runFolder&&$.runFolder.trim().length>0)Z.push({name:"X-Ideawave-Run-Folder",value:$.runFolder.trim()});return{type:"http",name:"ideawave-board",url:X,headers:Z}}function FX(X={}){let $=C1;if($)return q1($.url,X);let Z=o2();if(!Z)return null;return q1(Z.url,X)}var y1="browser-proxy-v5",E1="browser-proxy-v6";var n2=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","browser_rpc","browser_rpc_result","warmup_run","warmup_result"]);function g0(X){try{let $=JSON.parse(X);if($&&typeof $==="object"&&typeof $.type==="string"&&n2.has($.type))return $}catch{}return null}function m0(X){return JSON.stringify(X)}import B0 from"node:fs/promises";import X6 from"node:path";import{z as B}from"zod";var b1=B.object({id:B.string(),name:B.string().nullable().default(null),description:B.string().nullable().default(null)}),v1=B.union([B.string(),B.boolean()]),t2=B.object({value:B.string(),name:B.string(),description:B.string().nullable().default(null),group:B.string().nullable().default(null),groupName:B.string().nullable().default(null)}),T1=B.object({id:B.string(),name:B.string(),category:B.string().nullable().default(null),description:B.string().nullable().default(null),type:B.enum(["select","boolean"]),currentValue:v1.nullable().default(null),options:B.array(t2).default([])}),LX=B.record(B.string(),v1).default({}),r2=B.discriminatedUnion("kind",[B.object({id:B.string(),kind:B.literal("registered"),adapterId:B.enum(["claude-code","opencode","codex","copilot"]),displayName:B.string(),runFolder:B.string().nullable(),defaultModelId:B.string().nullable().default(null),defaultConfigValues:LX,discoveredModels:B.array(b1).default([]),discoveredConfigOptions:B.array(T1).default([]),discoveredAt:B.string().nullable().default(null)}),B.object({id:B.string(),kind:B.literal("custom"),displayName:B.string(),command:B.string(),args:B.array(B.string()),env:B.record(B.string(),B.string()),runFolder:B.string().nullable(),defaultModelId:B.string().nullable().default(null),defaultConfigValues:LX,discoveredModels:B.array(b1).default([]),discoveredConfigOptions:B.array(T1).default([]),discoveredAt:B.string().nullable().default(null)})]),f1=B.object({runtimeConfigId:B.string(),runFolder:B.string().nullable(),modelId:B.string().nullable().default(null),configValues:LX}),c0=B.object({version:B.literal(1),globalDefaultConfigId:B.string().nullable(),runtimes:B.array(r2),boardOverrides:B.record(B.string(),f1).default({}),cardOverrides:B.record(B.string(),f1).default({})});import s2 from"node:os";import l0 from"node:path";function e2(){let X=s2.homedir();switch(process.platform){case"win32":return process.env.APPDATA??l0.join(X,"AppData","Roaming");case"darwin":return l0.join(X,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??l0.join(X,".config")}}function p0(){let X=process.env.IDEAWAVE_RUNTIME_CONFIG_PATH;if(X)return X;return l0.join(e2(),"ideawave","runtimes.json")}var $6={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},h1=new Map;function Z6(X){return h1.get(X)??Promise.resolve()}function W6(X,$){h1.set(X,$)}async function m(X){let $=X??p0(),Z;try{Z=await B0.readFile($,"utf-8")}catch(Q){if(Q.code==="ENOENT")return structuredClone($6);throw Q}return c0.parse(JSON.parse(Z))}async function p(X,$){let Z=$??p0(),W=Z6(Z).then(async()=>{let Q=await m(Z),K=structuredClone(Q),Y=await X(K);return await Q6(K,Z),Y});return W6(Z,W.catch(()=>{return})),W}async function Q6(X,$){let Z=$??p0(),W=X6.dirname(Z);await B0.mkdir(W,{recursive:!0});let Q=`${Z}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`,K=JSON.stringify(X,null,2);await B0.writeFile(Q,K,"utf-8");try{await B0.rename(Q,Z)}catch(Y){throw await B0.unlink(Q).catch(()=>{return}),Y}}import{spawn as D6}from"node:child_process";import{closeSync as N6,existsSync as c1,mkdirSync as l1,openSync as P6,readFileSync as x6,renameSync as w6,rmSync as p1,statSync as M6,unlinkSync as F6,writeFileSync as L6}from"node:fs";import g1 from"node:os";import Y0 from"node:path";var K6=/\.(?:cmd|bat)$/i;function J6(X){return process.platform==="win32"&&K6.test(X)}function u0(X){return J6(X)?{shell:!0,windowsHide:!0}:{}}import{execFile as H6}from"node:child_process";import{promisify as U6}from"node:util";import{execFile as Y6}from"node:child_process";import{promisify as V6}from"node:util";var j6=V6(Y6),BX=new Map,I1=5000,G6=/\.(?:cmd|bat|com|exe)$/i;function z6(X){let $=X.split(/\r?\n/).map((Z)=>Z.trim()).filter((Z)=>Z.length>0);if($.length===0)return null;if(process.platform!=="win32")return $[0]??null;return $.find((Z)=>G6.test(Z))??$[0]??null}async function S1(X,$=j6){let Z=BX.get(X);if(Z&&Z.expiresAt>Date.now())return Z.value;let W=process.platform==="win32"?"where":"which";try{let{stdout:Q}=await $(W,[X],{timeout:2000}),K=z6(Q);return BX.set(X,{value:K,expiresAt:Date.now()+I1}),K}catch{return BX.set(X,{value:null,expiresAt:Date.now()+I1}),null}}class O0 extends Error{code;constructor(X,$){super(X);this.name="AcpError",this.code=$}}class J0 extends O0{constructor(X="No ACP runtime configured"){super(X,"RUNTIME_NOT_CONFIGURED");this.name="RuntimeNotConfiguredError"}}class R extends O0{constructor(X){super(X,"RUNTIME_UNREACHABLE");this.name="RuntimeUnreachableError"}}class U0 extends O0{authMethods;constructor(X,$){super(X,"AUTH_REQUIRED");this.name="AuthRequiredError",this.authMethods=$}}class u extends O0{constructor(X="ACP session timed out"){super(X,"SESSION_TIMEOUT");this.name="SessionTimeoutError"}}var b4=U6(H6);function T(X,...$){return S1(X,...$)}function g(X){let $={};for(let[Z,W]of Object.entries(process.env))if(typeof W==="string")$[Z]=W;return{...$,...X??{}}}var kX=[{adapterId:"claude-code",runtimeBinary:"claude",packageName:"@agentclientprotocol/claude-agent-acp",version:"0.61.0",warmupArgs:["--cli","--help"]},{adapterId:"codex",runtimeBinary:"codex",packageName:"@agentclientprotocol/codex-acp",version:"1.1.7",warmupArgs:["--version"]}],B6=1800000,a0=new Map;function _X(){if(process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR)return process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR;if(process.platform==="win32"){let X=process.env.LOCALAPPDATA??Y0.join(g1.homedir(),"AppData","Local");return Y0.join(X,"ideawave","acp-bridges")}return Y0.join(process.env.XDG_CACHE_HOME??Y0.join(g1.homedir(),".cache"),"ideawave","acp-bridges")}function O6(X){return X.replace(/^@/,"").replace(/[/\\]/g,"-")}function d0(){return Y0.join(_X(),"install-state.json")}function AX(X){return Y0.join(_X(),`${O6(X.packageName)}@${X.version}.install.lock`)}function qX(){return process.platform==="win32"?"npx.cmd":"npx"}function CX(X){return`${X.packageName}@${X.version}`}function u1(){let X=d0();if(!c1(X))return{};try{return JSON.parse(x6(X,"utf8"))}catch{return{}}}function OX(X,$){let Z=_X();l1(Z,{recursive:!0});let W=u1();W.bridges={...W.bridges??{},[X.adapterId]:$},L6(`${d0()}.tmp`,`${JSON.stringify(W,null,2)}
3
+ `),w6(`${d0()}.tmp`,d0())}function a1(X){return kX.find(($)=>$.packageName===X)??null}function c(X,$,Z){return{adapterId:X.adapterId,packageName:X.packageName,version:X.version,status:$,...Z?{error:Z}:{}}}function m1(X,$){return $?.packageName===X.packageName&&$.version===X.version}function d1(X){try{return Date.now()-M6(X).mtimeMs>B6}catch{return!1}}function k6(X){let $=AX(X);if(!c1($))return!1;if(d1($))return p1($,{force:!0}),!1;return!0}function _6(X){let $=AX(X);if(l1(Y0.dirname($),{recursive:!0}),d1($))p1($,{force:!0});try{let Z=P6($,"wx");return N6(Z),!0}catch{return!1}}function A6(X){F6(AX(X))}function RX(X){let $=u1().bridges?.[X.adapterId];if(m1(X,$)&&$.status==="ready")return c(X,"ready");if(a0.has(X.adapterId)||k6(X))return c(X,"installing");if(m1(X,$)&&$.status==="failed")return c(X,"failed",$.error);return c(X,"missing")}function k0(X,$){X?.onStatusChange?.($)}function q6(X,$){let Z=RX(X);if(Z.status==="ready")return k0($,Z),Z;if(Z.status==="installing"){let J=a0.get(X.adapterId);if(J&&$?.onStatusChange)J.then((z)=>k0($,z));return k0($,Z),Z}if(!_6(X))return c(X,"installing");let W=c(X,"installing");OX(X,W),k0($,W);let Q=()=>{},K=new Promise((J)=>{Q=J});a0.set(X.adapterId,K);let Y=!1,V=(J)=>{if(Y)return;Y=!0;try{A6(X)}catch{}OX(X,J),k0($,J),a0.delete(X.adapterId),Q(J)},j;try{let J=qX();j=D6(J,["-y",CX(X),...X.warmupArgs],{stdio:"ignore",windowsHide:!0,...u0(J)})}catch(J){let z=c(X,"failed",J instanceof Error?J.message:String(J));return V(z),z}return j.on("error",(J)=>{V(c(X,"failed",J.message))}),j.on("close",(J)=>{if(J===0){V(c(X,"ready"));return}V(c(X,"failed",`npx warmup exited ${J??"null"}`))}),j.unref(),W}function D0(X){let $=a1(X);return $?RX($):null}async function i1(X){let $=[];for(let Z of kX){if(!await T(Z.runtimeBinary)){$.push(c(Z,"not_needed"));continue}$.push(q6(Z,X))}return $.filter((Z)=>Z.status!=="not_needed")}function i0(X){let $=a1(X);if(!$)return null;if(RX($).status!=="ready")return null;return{command:qX(),args:["-y",CX($)],env:{}}}function yX(X,$){if(X.command!==qX())return!1;let Z=kX.find((W)=>X.args.includes(CX(W)));if(!Z)return!1;return OX(Z,c(Z,"failed",$)),!0}var o1="claude",EX="@agentclientprotocol/claude-agent-acp",n1=["claude-agent-acp","claude-code-acp"],t1="Install Claude Code from https://github.com/anthropics/claude-code",r1={id:"claude-code",displayName:"Claude Code",kind:"registered",supportsImages:!0,resolveSpawnConfig:async()=>{if(!await T(o1))throw new R(`Claude Code CLI not found. ${t1}`);let $=i0(EX);if($)return{command:$.command,args:$.args,env:g($.env)};let Z=D0(EX),W=Z?.status==="installing";for(let K of n1){let Y=await T(K);if(Y&&!W&&Z?.status!=="failed")return{command:Y,args:[],env:g()}}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 R(Q)},checkReadiness:async()=>{if(!await T(o1))return{status:"not_installed",detail:t1};let $=D0(EX);if($?.status==="ready")return{status:"ready"};if($?.status==="installing")return{status:"not_running",detail:"Installing Claude Code ACP bridge..."};if($?.status==="failed")return{status:"not_running",detail:$.error??"Claude Code ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};for(let Z of n1)if(await T(Z))return{status:"ready"};return{status:"not_running",detail:"Installing Claude Code ACP bridge..."}},authHint:"Run `claude login` (or set ANTHROPIC_API_KEY)."};var s1="codex",bX="@agentclientprotocol/codex-acp",e1="codex-acp",X$="Install Codex CLI from https://developers.openai.com/codex/cli",$$={id:"codex",displayName:"Codex",kind:"registered",resolveSpawnConfig:async()=>{if(!await T(s1))throw new R(`Codex CLI not found. ${X$}`);let $=i0(bX);if($)return{command:$.command,args:$.args,env:g($.env)};let Z=D0(bX),W=Z?.status==="installing",Q=await T(e1);if(Q&&!W&&Z?.status!=="failed")return{command:Q,args:[],env:g()};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 R(K)},checkReadiness:async()=>{if(!await T(s1))return{status:"not_installed",detail:X$};let $=D0(bX);if($?.status==="ready")return{status:"ready"};if($?.status==="installing")return{status:"not_running",detail:"Installing Codex ACP bridge..."};if($?.status==="failed")return{status:"not_running",detail:$.error??"Codex ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};if(await T(e1))return{status:"ready"};return{status:"not_running",detail:"Installing Codex ACP bridge..."}},authHint:"Run `codex login` (or set OPENAI_API_KEY)."};var Z$="copilot",W$="copilot-acp",Q$="npm i -g @github/copilot",K$={id:"copilot",displayName:"GitHub Copilot",kind:"registered",resolveSpawnConfig:async()=>{let X=await T(Z$);if(X)return{command:X,args:["--acp"],env:g()};let $=await T(W$);if($)return{command:$,args:[],env:g()};throw new R(`Copilot not installed. Run: ${Q$}`)},checkReadiness:async()=>{if(await T(Z$))return{status:"ready"};if(await T(W$))return{status:"ready"};return{status:"not_installed",detail:Q$}},authHint:"Run `gh auth login` (or `copilot login`)."};import C6 from"node:fs/promises";function R6(X){return X.startsWith("/")||/^[a-zA-Z]:[\\/]/.test(X)}async function J$(X){if(R6(X))try{return await C6.access(X),!0}catch{return!1}return await T(X)!==null}var Y$={id:"custom",displayName:"Custom ACP",kind:"custom",resolveSpawnConfig:async(X)=>{if(X.kind!=="custom")throw new R("customAdapter received non-custom entry");if(!await J$(X.command))throw new R(`custom: command "${X.command}" not found`);return{command:X.command,args:X.args,env:g(X.env)}},checkReadiness:async(X)=>{if(X.kind!=="custom")return{status:"unknown"};return await J$(X.command)?{status:"ready"}:{status:"not_installed"}}};var V$="opencode",j$="Install OpenCode from https://opencode.ai",G$={id:"opencode",displayName:"OpenCode",kind:"registered",resolveSpawnConfig:async()=>{let X=await T(V$);if(!X)throw new R(`OpenCode not installed. ${j$}`);return{command:X,args:["acp"],env:g()}},checkReadiness:async()=>{if(!await T(V$))return{status:"not_installed",detail:j$};return{status:"ready"}},authHint:"Run `opencode auth login <provider>` (or set the provider's API-key env var)."};var z$={"claude-code":r1,opencode:G$,codex:$$,copilot:K$};function a(X){if(X.kind==="custom")return Y$;let $=z$[X.adapterId];if(!$)throw Error(`Unknown registered adapter: ${X.adapterId}`);return $}function N0(){return Object.values(z$)}var TX=new Map,o0=new Map,y6=30000;function n0(X,$){let Z=TX.get(X);if(Z&&Z.expiresAt>Date.now())return Promise.resolve(Z.value);let W=o0.get(X);if(W)return W;let Q=$().then((K)=>{return TX.set(X,{value:K,expiresAt:Date.now()+y6}),K}).finally(()=>{o0.delete(X)});return o0.set(X,Q),Q}async function H$(X){let $=await Promise.all(N0().map((K)=>n0(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})})))),W=(await m(X)).runtimes.filter((K)=>K.kind==="custom"),Q=await Promise.all(W.map((K)=>n0(`custom:${K.id}`,async()=>({adapterId:K.id,...await a(K).checkReadiness(K)}))));return[...$,...Q]}async function U$(X,$){let Z=N0().find((K)=>K.id===X);if(Z)return n0(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 m($)).runtimes.find((K)=>K.id===X);if(!Q||Q.kind!=="custom")return null;return n0(`custom:${Q.id}`,async()=>({adapterId:Q.id,...await a(Q).checkReadiness(Q)}))}function D$(){TX.clear(),o0.clear()}import{createHash as b6,randomBytes as T6,randomUUID as x$}from"node:crypto";import{WebSocket as r0,WebSocketServer as f6}from"ws";function r(X){return JSON.stringify(X).replace(/</g,"\\u003c")}function E6(X){try{let $=new URL(X);if($.protocol!=="https:"||$.hostname!=="www.google.com"||$.username||$.password||$.pathname!=="/"&&$.pathname!=="/webhp")return null;return"https://www.google.com/search"}catch{return null}}function N$(X){let $=r(E6(X.sourceUrl));return`(() => {
4
4
  "use strict";
5
5
  let TOKEN = ${r(X.token)};
6
6
  let SOURCE_URL = ${r(X.sourceUrl)};
@@ -396,20 +396,23 @@ function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.roun
396
396
  if (BRIDGE_SCRIPT) BRIDGE_SCRIPT.remove();
397
397
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", state, { once: true });
398
398
  else state();
399
- })();`}function U$(X){return JSON.stringify(X).replace(/</g,"\\u003c")}function bX(X){return`(() => {
399
+ })();`}function t0(X){return JSON.stringify(X).replace(/</g,"\\u003c")}function fX(X){return`(() => {
400
400
  "use strict";
401
401
  if (window.__browserKitHooked) return;
402
402
  window.__browserKitHooked = true;
403
- let REAL = ${U$(X.sourceUrl)};
404
- const PROXY_ORIGIN = ${U$(X.proxyOrigin)};
405
- const PREFIX = PROXY_ORIGIN + "/browser-kit/proxy/";
403
+ let REAL = ${t0(X.sourceUrl)};
404
+ const PROXY_ORIGIN = ${t0(X.proxyOrigin)};
405
+ const PREFIX = ${t0(X.proxyUrlPrefix)};
406
+ const PREFIX_PATH = new URL(PREFIX).pathname;
407
+ const SESSION_PATH = PREFIX_PATH.slice(0, -"/proxy/".length);
408
+ const SESSION_STORAGE_NAMESPACE = ${t0(X.sessionStorageNamespace??"default")};
406
409
 
407
410
  const currentRealUrl = () => {
408
411
  try {
409
412
  const locationUrl = new URL(location.href);
410
413
  if (locationUrl.origin === PROXY_ORIGIN) {
411
- if (locationUrl.pathname.startsWith("/browser-kit/proxy/")) {
412
- const proxied = locationUrl.pathname.slice("/browser-kit/proxy/".length) + locationUrl.search + locationUrl.hash;
414
+ if (locationUrl.pathname.startsWith(PREFIX_PATH)) {
415
+ const proxied = locationUrl.pathname.slice(PREFIX_PATH.length) + locationUrl.search + locationUrl.hash;
413
416
  if (/^https?:\\/\\//i.test(proxied)) return proxied;
414
417
  }
415
418
  return new URL(locationUrl.pathname + locationUrl.search + locationUrl.hash, REAL).href;
@@ -440,7 +443,7 @@ function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.roun
440
443
  try {
441
444
  if (value == null) return value;
442
445
  let raw = value instanceof URL ? value.href : String(value);
443
- if (!raw || raw.startsWith(PREFIX) || /^\\/browser-kit\\/proxy\\/https?:\\/\\//i.test(raw)) return raw;
446
+ if (!raw || raw.startsWith(PREFIX) || raw.startsWith(PREFIX_PATH)) return raw;
444
447
  if (/^(data|blob|javascript|about|mailto|tel):/i.test(raw) || raw.startsWith("#")) return raw;
445
448
  let absolute;
446
449
  if (/^[a-z][a-z0-9+.\\-]*:\\/\\//i.test(raw)) absolute = raw;
@@ -465,29 +468,65 @@ function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.roun
465
468
  else if (/^https?:\\/\\//i.test(raw)) absolute = raw.replace(/^http/i, "ws");
466
469
  else absolute = new URL(raw, currentRealUrl()).href.replace(/^http/i, "ws");
467
470
  const scheme = PROXY_ORIGIN.startsWith("https:") ? "wss://" : "ws://";
468
- return scheme + location.host + "/browser-kit/proxy/" + absolute;
471
+ return scheme + location.host + PREFIX_PATH + absolute;
469
472
  } catch {
470
473
  return value;
471
474
  }
472
475
  };
473
476
 
474
477
  try {
475
- if (location.pathname.startsWith("/browser-kit/proxy/")) {
478
+ if (location.pathname.startsWith(PREFIX_PATH)) {
476
479
  history.replaceState(history.state, "", virtualHistoryUrl(REAL));
477
480
  }
478
481
  } catch {}
479
482
  window.__browserKitRealUrl = currentRealUrl();
480
483
 
484
+ const bindServiceWorkerRoute = () => {
485
+ try {
486
+ navigator.serviceWorker?.controller?.postMessage({
487
+ type: "browser-kit-bind",
488
+ proxyPathPrefix: PREFIX_PATH,
489
+ realOrigin: realOrigin(),
490
+ });
491
+ } catch {}
492
+ };
493
+ bindServiceWorkerRoute();
494
+ try {
495
+ navigator.serviceWorker?.addEventListener(
496
+ "controllerchange",
497
+ bindServiceWorkerRoute,
498
+ );
499
+ } catch {}
500
+
481
501
  // Some applications canonicalize a non-production host by assigning the
482
- // current real URL to location. In the proxy that is a redundant navigation
483
- // which would escape the iframe, so cancel it before the request starts.
502
+ // current real URL to location. Route full document navigations through this
503
+ // card's explicit session path so a shared browser profile never has to guess
504
+ // which card initiated the request. SPA history changes remain untouched.
484
505
  try {
485
506
  if (window.navigation) {
486
507
  window.navigation.addEventListener("navigate", (event) => {
487
508
  if (!event.cancelable) return;
488
509
  try {
489
510
  const destination = new URL(event.destination.url);
490
- if (destination.href === currentRealUrl()) event.preventDefault();
511
+ if (destination.href === currentRealUrl()) {
512
+ event.preventDefault();
513
+ return;
514
+ }
515
+ if (event.destination.sameDocument) return;
516
+ if (
517
+ destination.origin === PROXY_ORIGIN &&
518
+ (
519
+ destination.pathname.startsWith(PREFIX_PATH) ||
520
+ destination.pathname === SESSION_PATH + "/navigate" ||
521
+ destination.pathname === SESSION_PATH + "/wrapper"
522
+ )
523
+ ) {
524
+ return;
525
+ }
526
+ const proxied = toProxy(destination.href);
527
+ if (!proxied || proxied === destination.href) return;
528
+ event.preventDefault();
529
+ window.setTimeout(() => location.assign(proxied), 0);
491
530
  } catch {}
492
531
  });
493
532
  }
@@ -500,9 +539,7 @@ function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.roun
500
539
  if (window.top !== window.self) {
501
540
  let parentProxied = true;
502
541
  try {
503
- parentProxied = window.parent.location.pathname.startsWith(
504
- "/browser-kit/proxy/",
505
- );
542
+ parentProxied = window.parent.location.pathname.startsWith(PREFIX_PATH);
506
543
  } catch {}
507
544
  if (!parentProxied) {
508
545
  Object.defineProperty(window, "top", {
@@ -572,8 +609,8 @@ function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.roun
572
609
  // wrapper below a hosted app. Third-party-cookie blocking therefore affects
573
610
  // the embedded build even though both versions proxy the page to localhost.
574
611
  // Keep client-written upstream cookies in partitioned localhost cookies. The
575
- // CLI decodes these on the next proxy request and adds them to the session's
576
- // server-side cookie jar.
612
+ // CLI decodes these on the next proxy request and adds them to the shared
613
+ // browser profile's server-side cookie jar.
577
614
  try {
578
615
  const cookieDescriptor =
579
616
  Object.getOwnPropertyDescriptor(Document.prototype, "cookie") ||
@@ -658,9 +695,9 @@ function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.roun
658
695
  }
659
696
  } catch {}
660
697
 
661
- const namespaceStorage = (storage) => {
698
+ const namespaceStorage = (storage, namespace) => {
662
699
  if (!storage) return storage;
663
- const prefix = "__browser_kit_" + realOrigin() + "::";
700
+ const prefix = "__browser_kit_" + namespace + realOrigin() + "::";
664
701
  const keys = () => {
665
702
  const result = [];
666
703
  for (let index = 0; index < storage.length; index += 1) {
@@ -703,8 +740,8 @@ function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.roun
703
740
  },
704
741
  });
705
742
  };
706
- try { Object.defineProperty(window, "localStorage", { value: namespaceStorage(window.localStorage), configurable: true }); } catch {}
707
- try { Object.defineProperty(window, "sessionStorage", { value: namespaceStorage(window.sessionStorage), configurable: true }); } catch {}
743
+ try { Object.defineProperty(window, "localStorage", { value: namespaceStorage(window.localStorage, ""), configurable: true }); } catch {}
744
+ try { Object.defineProperty(window, "sessionStorage", { value: namespaceStorage(window.sessionStorage, "session:" + SESSION_STORAGE_NAMESPACE + ":"), configurable: true }); } catch {}
708
745
 
709
746
  if (window.open) {
710
747
  window.open = new Proxy(window.open, {
@@ -785,52 +822,90 @@ function f2(){let X=globalThis.performance?.now?.()??Date.now();return Math.roun
785
822
  };
786
823
  addEventListener("popstate", notifyNavigation);
787
824
  addEventListener("hashchange", notifyNavigation);
788
- })();`}var H$=new Set(["content-security-policy","content-security-policy-report-only","x-frame-options","cross-origin-opener-policy","cross-origin-embedder-policy","cross-origin-resource-policy","content-encoding","content-length","transfer-encoding","set-cookie","strict-transport-security","report-to","nel","permissions-policy","x-content-type-options"]);function s(X,$,Z){if(!X)return X;let Q=X.trim();if(Q.startsWith(`${Z}/browser-kit/proxy/`)||Q.startsWith("/browser-kit/proxy/")||/^(data|blob|mailto|tel|javascript):/i.test(Q)||Q.startsWith("#"))return Q;try{let W=new URL(Q,$);if(W.protocol!=="http:"&&W.protocol!=="https:")return Q;return`${Z}/browser-kit/proxy/${W.href}`}catch{return Q}}function EX(X){let $=(Z)=>{let Q=Z.trim().replace(/^["']|["']$/g,"");if(!Q||Q.startsWith("data:"))return Z;return s(Q,X.baseUrl,X.proxyOrigin)};return X.css.replace(/url\(\s*([^)]+?)\s*\)/gi,(Z,Q)=>`url(${$(Q)})`).replace(/@import\s+(["'])([^"']+)\1/gi,(Z,Q,W)=>`@import ${Q}${$(W)}${Q}`)}function TX(X){let $=new URL(X.sourceUrl).origin,Z=X.html.replace(/<meta[^>]+http-equiv\s*=\s*["']?content-security-policy["']?[^>]*>/gi,"").replace(/\sintegrity\s*=\s*(["'])[^"']*\1/gi,"").replace(/(\b(?:href|src|action|poster)\s*=\s*["'])(https?:)\/\//gi,"$1/browser-kit/proxy/$2//").replace(/(\b(?:href|src|action|poster)\s*=\s*["'])\/\//gi,"$1/browser-kit/proxy/https://").replace(/(\b(?:href|action|poster)\s*=\s*["'])\/(?!\/|browser-kit\/proxy\/)/gi,`$1/browser-kit/proxy/${$}/`).replace(/(\bimport\s*\(\s*["'])\/(?!\/|browser-kit\/proxy\/)([^"']*)(["']\s*\))/g,`$1/browser-kit/proxy/${$}/$2$3`).replace(/(\bimport\s*\(\s*\\["'])\/(?!\/|browser-kit\/proxy\/)([^"'\\]*)(\\["']\s*\))/g,`$1/browser-kit/proxy/${$}/$2$3`);Z=Z.replace(/(<meta[^>]+http-equiv\s*=\s*["']?refresh["']?[^>]*content\s*=\s*["'][^"']*?url\s*=\s*)([^"'\s>]+)/gi,(Y,V,z)=>V+s(z,X.sourceUrl,X.proxyOrigin)),Z=Z.replace(/\bsrcset\s*=\s*["']([^"']*)["']/gi,(Y,V)=>{return`srcset="${V.split(",").map((J)=>{let G=J.trim().split(/\s+/),M=G.shift();if(!M)return"";return[/^https?:\/\//i.test(M)||M.startsWith("//")||M.startsWith("/")?s(M,X.sourceUrl,X.proxyOrigin):M,...G].join(" ")}).filter(Boolean).join(", ")}"`});let Q=bX({sourceUrl:X.sourceUrl,proxyOrigin:X.proxyOrigin}),W=z$({token:X.bridgeToken,sourceUrl:X.sourceUrl,revision:X.revision,navigateUrlPrefix:X.navigateUrlPrefix,parentOrigin:X.proxyOrigin}),K=`<base href="${X.proxyOrigin}/browser-kit/proxy/${X.sourceUrl}"><script data-browser-kit-runtime>${Q}</script><script data-ideawave-browser-bridge>${W}</script>`;if(/<head[^>]*>/i.test(Z))return Z.replace(/<head[^>]*>/i,(Y)=>Y+K);if(/<html[^>]*>/i.test(Z))return Z.replace(/<html[^>]*>/i,(Y)=>Y+K);return K+Z}function vX(){return`
825
+ })();`}var P$=new Set(["content-security-policy","content-security-policy-report-only","x-frame-options","cross-origin-opener-policy","cross-origin-embedder-policy","cross-origin-resource-policy","content-encoding","content-length","transfer-encoding","set-cookie","strict-transport-security","report-to","nel","permissions-policy","x-content-type-options"]);function s(X,$,Z){if(!X)return X;let W=X.trim(),Q=Z.endsWith("/")?Z:`${Z}/`,K=new URL(Q).pathname;if(W.startsWith(Q)||W.startsWith(K)||/^(data|blob|mailto|tel|javascript):/i.test(W)||W.startsWith("#"))return W;try{let Y=new URL(W,$);if(Y.protocol!=="http:"&&Y.protocol!=="https:")return W;return`${Q}${Y.href}`}catch{return W}}function vX(X){let $=(Z)=>{let W=Z.trim().replace(/^["']|["']$/g,"");if(!W||W.startsWith("data:"))return Z;return s(W,X.baseUrl,X.proxyUrlPrefix)};return X.css.replace(/url\(\s*([^)]+?)\s*\)/gi,(Z,W)=>`url(${$(W)})`).replace(/@import\s+(["'])([^"']+)\1/gi,(Z,W,Q)=>`@import ${W}${$(Q)}${W}`)}function hX(X){let $=new URL(X.sourceUrl).origin,Z=new URL(X.proxyUrlPrefix).pathname,W=X.html.replace(/<meta[^>]+http-equiv\s*=\s*["']?content-security-policy["']?[^>]*>/gi,"").replace(/\sintegrity\s*=\s*(["'])[^"']*\1/gi,"").replace(/(\b(?:href|src|action|poster)\s*=\s*["'])(https?:)\/\//gi,(V,j,J)=>`${j}${Z}${J}//`).replace(/(\b(?:href|src|action|poster)\s*=\s*["'])\/\//gi,(V,j)=>`${j}${Z}https://`).replace(/(\b(?:href|action|poster)\s*=\s*["'])\/(?!\/|browser-kit\/session\/)/gi,(V,j)=>`${j}${Z}${$}/`).replace(/(\bimport\s*\(\s*["'])\/(?!\/|browser-kit\/session\/)([^"']*)(["']\s*\))/g,(V,j,J,z)=>`${j}${Z}${$}/${J}${z}`).replace(/(\bimport\s*\(\s*\\["'])\/(?!\/|browser-kit\/session\/)([^"'\\]*)(\\["']\s*\))/g,(V,j,J,z)=>`${j}${Z}${$}/${J}${z}`);W=W.replace(/(<meta[^>]+http-equiv\s*=\s*["']?refresh["']?[^>]*content\s*=\s*["'][^"']*?url\s*=\s*)([^"'\s>]+)/gi,(V,j,J)=>j+s(J,X.sourceUrl,X.proxyUrlPrefix)),W=W.replace(/\bsrcset\s*=\s*["']([^"']*)["']/gi,(V,j)=>{return`srcset="${j.split(",").map((z)=>{let D=z.trim().split(/\s+/),N=D.shift();if(!N)return"";return[/^https?:\/\//i.test(N)||N.startsWith("//")||N.startsWith("/")?s(N,X.sourceUrl,X.proxyUrlPrefix):N,...D].join(" ")}).filter(Boolean).join(", ")}"`});let Q=fX({sourceUrl:X.sourceUrl,proxyOrigin:X.proxyOrigin,proxyUrlPrefix:X.proxyUrlPrefix,sessionStorageNamespace:X.sessionStorageNamespace}),K=N$({token:X.bridgeToken,sourceUrl:X.sourceUrl,revision:X.revision,navigateUrlPrefix:X.navigateUrlPrefix,parentOrigin:X.proxyOrigin}),Y=`<base href="${X.proxyUrlPrefix}${X.sourceUrl}"><script data-browser-kit-runtime>${Q}</script><script data-ideawave-browser-bridge>${K}</script>`;if(/<head[^>]*>/i.test(W))return W.replace(/<head[^>]*>/i,(V)=>V+Y);if(/<html[^>]*>/i.test(W))return W.replace(/<html[^>]*>/i,(V)=>V+Y);return Y+W}var IX="6";function SX(){return`
789
826
  self.addEventListener("install", (event) => event.waitUntil(self.skipWaiting()));
790
827
  self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim()));
791
828
 
792
- const PREFIX = "/browser-kit/proxy/";
793
- const clientOrigins = new Map();
794
- let lastOrigin = null;
829
+ const SESSION_PREFIX = "/browser-kit/session/";
830
+ const clientRoutes = new Map();
831
+
832
+ const routeFromProxyUrl = (value) => {
833
+ try {
834
+ const url = new URL(value, self.location.origin);
835
+ if (url.origin !== self.location.origin || !url.pathname.startsWith(SESSION_PREFIX)) return null;
836
+ const rest = url.pathname.slice(SESSION_PREFIX.length);
837
+ const separator = rest.indexOf("/");
838
+ if (separator <= 0) return null;
839
+ const sessionId = rest.slice(0, separator);
840
+ const proxyPathPrefix = SESSION_PREFIX + sessionId + "/proxy/";
841
+ if (!url.pathname.startsWith(proxyPathPrefix)) return null;
842
+ const realUrl = url.pathname.slice(proxyPathPrefix.length) + url.search + url.hash;
843
+ if (!/^https?:\\/\\//i.test(realUrl)) return null;
844
+ return {
845
+ sessionId,
846
+ proxyPathPrefix,
847
+ realOrigin: new URL(realUrl).origin,
848
+ };
849
+ } catch {
850
+ return null;
851
+ }
852
+ };
853
+
854
+ const routeFromBinding = (value, origin) => {
855
+ try {
856
+ if (
857
+ typeof value !== "string" ||
858
+ !value.startsWith(SESSION_PREFIX) ||
859
+ !value.endsWith("/proxy/")
860
+ ) return null;
861
+ const rest = value.slice(SESSION_PREFIX.length);
862
+ const separator = rest.indexOf("/");
863
+ if (separator <= 0 || rest.slice(separator) !== "/proxy/") return null;
864
+ const parsedOrigin = new URL(origin);
865
+ if (parsedOrigin.protocol !== "http:" && parsedOrigin.protocol !== "https:") return null;
866
+ return {
867
+ sessionId: rest.slice(0, separator),
868
+ proxyPathPrefix: value,
869
+ realOrigin: parsedOrigin.origin,
870
+ };
871
+ } catch {
872
+ return null;
873
+ }
874
+ };
795
875
 
796
- const realUrl = (value) => {
797
- const index = value.indexOf(PREFIX);
798
- if (index < 0) return null;
799
- const target = value.slice(index + PREFIX.length);
800
- return /^https?:\\/\\//i.test(target) ? target : null;
876
+ const remember = (id, route) => {
877
+ if (id && route) clientRoutes.set(id, route);
878
+ return route;
801
879
  };
802
880
 
803
- const baseOriginFor = async (event) => {
881
+ self.addEventListener("message", (event) => {
882
+ const message = event.data;
883
+ if (!message || message.type !== "browser-kit-bind") return;
884
+ const route = routeFromBinding(message.proxyPathPrefix, message.realOrigin);
885
+ if (route && event.source && event.source.id) remember(event.source.id, route);
886
+ });
887
+
888
+ const routeFor = async (event) => {
804
889
  const id = event.clientId || event.resultingClientId;
805
890
  if (id) {
806
891
  try {
807
892
  const client = await self.clients.get(id);
808
- if (client && client.url) {
809
- const target = realUrl(client.url);
810
- if (target) {
811
- lastOrigin = new URL(target).origin;
812
- clientOrigins.set(id, lastOrigin);
813
- return lastOrigin;
814
- }
815
- const remembered = clientOrigins.get(id);
816
- if (remembered) return remembered;
817
- return null;
818
- }
893
+ const direct = client && client.url ? routeFromProxyUrl(client.url) : null;
894
+ if (direct) return remember(id, direct);
819
895
  } catch {}
896
+ const remembered = clientRoutes.get(id);
897
+ if (remembered) return remembered;
820
898
  }
821
899
  if (event.request.referrer) {
822
- const target = realUrl(event.request.referrer);
823
- if (target) {
824
- lastOrigin = new URL(target).origin;
825
- return lastOrigin;
826
- }
900
+ const referrer = routeFromProxyUrl(event.request.referrer);
901
+ if (referrer) return referrer;
827
902
  }
828
- return event.request.mode === "navigate" ? lastOrigin : null;
903
+ return null;
829
904
  };
830
905
 
831
- const proxy = async (event, target) => {
906
+ const proxy = async (event, route, target) => {
832
907
  const request = event.request;
833
- const localUrl = self.location.origin + PREFIX + target;
908
+ const localUrl = self.location.origin + route.proxyPathPrefix + target;
834
909
  if (request.mode === "navigate") return Response.redirect(localUrl, 302);
835
910
  const init = {
836
911
  method: request.method,
@@ -845,35 +920,28 @@ const proxy = async (event, target) => {
845
920
  self.addEventListener("fetch", (event) => {
846
921
  const url = new URL(event.request.url);
847
922
  const sameOrigin = url.origin === self.location.origin;
923
+ if (sameOrigin && url.pathname === "/browser-kit/sw.js") return;
848
924
  if (
849
925
  sameOrigin &&
850
- (
851
- url.pathname === "/browser-kit/wrapper" ||
852
- url.pathname === "/browser-kit/sw.js" ||
853
- url.pathname === "/browser-kit/navigate"
854
- )
926
+ url.pathname.startsWith(SESSION_PREFIX) &&
927
+ (url.pathname.endsWith("/wrapper") || url.pathname.endsWith("/navigate"))
855
928
  ) return;
856
- if (sameOrigin && url.pathname.startsWith(PREFIX)) {
857
- const target = realUrl(url.href);
858
- if (target) {
859
- try {
860
- lastOrigin = new URL(target).origin;
861
- const id = event.resultingClientId || event.clientId;
862
- if (id) clientOrigins.set(id, lastOrigin);
863
- } catch {}
864
- }
929
+ const direct = sameOrigin ? routeFromProxyUrl(url.href) : null;
930
+ if (direct) {
931
+ const id = event.resultingClientId || event.clientId;
932
+ if (id) remember(id, direct);
865
933
  return;
866
934
  }
867
935
  event.respondWith((async () => {
868
- const base = await baseOriginFor(event);
936
+ const route = await routeFor(event);
937
+ if (!route) return sameOrigin ? fetch(event.request) : Response.error();
869
938
  if (sameOrigin) {
870
- if (!base) return fetch(event.request);
871
- return proxy(event, base + url.pathname + url.search);
939
+ return proxy(event, route, route.realOrigin + url.pathname + url.search);
872
940
  }
873
- return proxy(event, url.href);
941
+ return proxy(event, route, url.href);
874
942
  })());
875
943
  });
876
- `}var b6=1800000,w0="/browser-kit/proxy/",D$="__browser_kit_client_";function E6(X){let $=X??"";return $.startsWith("[")?$.slice(1,$.indexOf("]")):$.split(":")[0]??""}function w$(X){let $=new URL(X);if($.protocol!=="http:"&&$.protocol!=="https:")throw Error("Only HTTP(S) browser URLs are supported");return $.href}function T6(X){let $=new URL(X);if($.protocol!=="http:"&&$.protocol!=="https:")throw Error("Browser frontend origin is invalid");return $.origin}function hX(X){return JSON.stringify(X).replace(/</g,"\\u003c")}function v6(X,$){return R6("sha256").update(X).update("\x00").update($).digest("hex").slice(0,24)}function h6(X){let $=new Headers;for(let[Z,Q]of Object.entries(X.headers))if(typeof Q==="string")$.set(Z,Q);else if(Array.isArray(Q))$.set(Z,Q.join(", "));return $}async function I6(X){if(X.method==="GET"||X.method==="HEAD")return;let $=[];for await(let Z of X)$.push(Buffer.isBuffer(Z)?Z:Buffer.from(Z));return $.length>0?Buffer.concat($):void 0}function S6(X){let $={};return X.forEach((Z,Q)=>{$[Q]=Z}),$}function g6(X,$){return`<!doctype html>
944
+ `}var v6=1800000,s0="/browser-kit/session/",w$="__browser_kit_client_";function h6(X){let $=X??"";return $.startsWith("[")?$.slice(1,$.indexOf("]")):$.split(":")[0]??""}function M$(X){let $=new URL(X);if($.protocol!=="http:"&&$.protocol!=="https:")throw Error("Only HTTP(S) browser URLs are supported");return $.href}function I6(X){let $=new URL(X);if($.protocol!=="http:"&&$.protocol!=="https:")throw Error("Browser frontend origin is invalid");return $.origin}function P0(X){return JSON.stringify(X).replace(/</g,"\\u003c")}function S6(X){return b6("sha256").update(X).digest("hex").slice(0,24)}function gX(X){if(!X.startsWith(s0))return null;let $=X.slice(s0.length),Z=$.indexOf("/");if(Z<=0)return null;return{sessionId:$.slice(0,Z),route:$.slice(Z)}}function g6(X){let $=new Headers;for(let[Z,W]of Object.entries(X.headers))if(typeof W==="string")$.set(Z,W);else if(Array.isArray(W))$.set(Z,W.join(", "));return $}async function m6(X){if(X.method==="GET"||X.method==="HEAD")return;let $=[];for await(let Z of X)$.push(Buffer.isBuffer(Z)?Z:Buffer.from(Z));return $.length>0?Buffer.concat($):void 0}function c6(X){let $={};return X.forEach((Z,W)=>{$[W]=Z}),$}function l6(X,$){let W=`${`${s0}${encodeURIComponent(X.id)}`}/proxy/`;return`<!doctype html>
877
945
  <html>
878
946
  <head>
879
947
  <meta charset="utf-8">
@@ -890,9 +958,11 @@ html,body,#view{border:0;margin:0;width:100%;height:100%;overflow:hidden;backgro
890
958
  <div id="status" hidden></div>
891
959
  <script>
892
960
  (() => {
893
- const TOKEN = ${hX(X.bridgeToken)};
894
- const FRONTEND_ORIGIN = ${hX(X.frontendOrigin)};
895
- const INITIAL_URL = ${hX($)};
961
+ const TOKEN = ${P0(X.bridgeToken)};
962
+ const FRONTEND_ORIGIN = ${P0(X.frontendOrigin)};
963
+ const INITIAL_URL = ${P0($)};
964
+ const PROXY_PATH_PREFIX = ${P0(W)};
965
+ const SERVICE_WORKER_VERSION = ${P0(IX)};
896
966
  const frame = document.getElementById("view");
897
967
  const status = document.getElementById("status");
898
968
  const showError = (error) => {
@@ -909,38 +979,62 @@ html,body,#view{border:0;margin:0;width:100%;height:100%;overflow:hidden;backgro
909
979
  if (event.source !== frame.contentWindow || event.origin !== location.origin || !message || message.type !== "ideawave-browser-event" || message.token !== TOKEN) return;
910
980
  window.parent.postMessage(message, FRONTEND_ORIGIN);
911
981
  });
912
- navigator.serviceWorker.register("/browser-kit/sw.js", { scope: "/" })
913
- .then(() => navigator.serviceWorker.ready)
982
+ const currentWorkerControlsPage = () => {
983
+ const scriptUrl = navigator.serviceWorker.controller?.scriptURL;
984
+ if (!scriptUrl) return false;
985
+ return new URL(scriptUrl).searchParams.get("v") === SERVICE_WORKER_VERSION;
986
+ };
987
+ const waitForCurrentWorker = async (registration) => {
988
+ await navigator.serviceWorker.ready;
989
+ if (currentWorkerControlsPage()) return;
990
+ await registration.update();
991
+ if (currentWorkerControlsPage()) return;
992
+ await new Promise((resolve, reject) => {
993
+ const timer = window.setTimeout(() => {
994
+ navigator.serviceWorker.removeEventListener("controllerchange", changed);
995
+ reject(new Error("Browser proxy service worker did not update"));
996
+ }, 15_000);
997
+ const changed = () => {
998
+ if (!currentWorkerControlsPage()) return;
999
+ window.clearTimeout(timer);
1000
+ navigator.serviceWorker.removeEventListener("controllerchange", changed);
1001
+ resolve();
1002
+ };
1003
+ navigator.serviceWorker.addEventListener("controllerchange", changed);
1004
+ });
1005
+ };
1006
+ navigator.serviceWorker.register(${P0(`/browser-kit/sw.js?v=${IX}`)}, { scope: "/" })
1007
+ .then(waitForCurrentWorker)
914
1008
  .then(() => {
915
- frame.src = "/browser-kit/proxy/" + INITIAL_URL;
1009
+ frame.src = PROXY_PATH_PREFIX + INITIAL_URL;
916
1010
  })
917
1011
  .catch(showError);
918
1012
  })();
919
1013
  </script>
920
1014
  </body>
921
- </html>`}class r0{sessions=new Map;socketServer=new y6({noServer:!0});sweepTimer;port=null;constructor(){this.sweepTimer=setInterval(()=>this.sweep(),60000),this.sweepTimer.unref?.()}setPort(X){this.port=X}wrapperOrigin(X){if(!this.port)throw Error("Browser kit is not ready");return`http://${X.wrapperHost}.localhost:${this.port}`}result(X){let $=this.wrapperOrigin(X);return{proxySessionId:X.id,wrapperUrl:`${$}/browser-kit/wrapper?session=${encodeURIComponent(X.id)}`,bridgeToken:X.bridgeToken,navigateUrlPrefix:`${$}/browser-kit/navigate?session=${encodeURIComponent(X.id)}&url=`}}async handleRpc(X,$,Z){if(Z.method==="open_proxy_session"){let Q=Z.params;if(typeof Q.browserNodeId!=="string"||typeof Q.url!=="string")throw Error("Browser proxy session input is invalid");let W=w$(Q.url),K=T6($),Y=[...this.sessions.values()].find((z)=>z.frontendOrigin===K&&z.browserNodeId===Q.browserNodeId);if(Y)return Y.frontendSessionIds.add(X),Y.currentUrl=W,Y.lastUsedAt=Date.now(),this.result(Y);let V={id:x$(),frontendSessionIds:new Set([X]),frontendOrigin:K,browserNodeId:Q.browserNodeId,wrapperHost:`iw-browser-${v6(K,Q.browserNodeId)}`,bridgeToken:f6(24).toString("base64url"),currentUrl:W,lastUsedAt:Date.now(),cookies:new Map};return this.sessions.set(V.id,V),this.result(V)}if(Z.method==="close_proxy_session"){let Q=Z.params;if(typeof Q.proxySessionId!=="string")throw Error("Browser proxy session input is invalid");let W=this.sessions.get(Q.proxySessionId);if(W&&!W.frontendSessionIds.has(X))throw Error("Browser proxy session belongs to another frontend session");if(W)W.frontendSessionIds.delete(X),W.lastUsedAt=Date.now();return{closed:!0}}if(Z.method==="build_snapshot")throw Error("Browser-kit snapshots are not available yet");throw Error("Unsupported browser-kit RPC operation")}closeFrontendSession(X){for(let $ of this.sessions.values())if($.frontendSessionIds.delete(X))$.lastUsedAt=Date.now()}async close(){clearInterval(this.sweepTimer),this.sessions.clear(),this.socketServer.close()}sweep(){let X=Date.now()-b6;for(let $ of this.sessions.values())if($.frontendSessionIds.size===0&&$.lastUsedAt<X)this.sessions.delete($.id)}sessionForRequest(X){let $=E6(X.headers.host);return[...this.sessions.values()].find((Z)=>$===`${Z.wrapperHost}.localhost`)??null}storeCookies(X,$,Z){for(let Q of $){let[W="",...K]=Q.split(";"),Y=W.indexOf("=");if(Y<0)continue;let V=W.slice(0,Y).trim(),z=W.slice(Y+1).trim(),J=Z.toLowerCase();for(let M of K){let P=M.indexOf("="),x=(P<0?M:M.slice(0,P)).trim().toLowerCase(),U=P<0?"":M.slice(P+1).trim();if(x==="domain"&&U)J=U.replace(/^\./,"").toLowerCase()}if(!X.cookies.has(J))X.cookies.set(J,new Map);let G=X.cookies.get(J);if(!G)continue;if(z===""||/(^|;)\s*max-age=0/i.test(Q))G.delete(V);else G.set(V,z)}}storeClientCookies(X,$){if(!$)return;for(let Z of $.split(";")){let Q=Z.trim(),W=Q.indexOf("=");if(W<1)continue;let K=Q.slice(0,W);if(!K.startsWith(D$))continue;let Y=K.slice(D$.length).split(".");if(Y.length!==2)continue;try{let V=Buffer.from(Y[0]??"","base64url").toString(),z=Buffer.from(Y[1]??"","base64url").toString(),J=JSON.parse(decodeURIComponent(Q.slice(W+1))),G=new URL(V).hostname.toLowerCase();if(!z||J.name!==z||typeof J.value!=="string")continue;if(!X.cookies.has(G))X.cookies.set(G,new Map);let M=X.cookies.get(G);if(!M)continue;if(J.deleted===!0)M.delete(z);else M.set(z,J.value)}catch{}}}cookieHeader(X,$){let Z=$.toLowerCase(),Q=[];for(let[W,K]of X.cookies)if(Z===W||Z.endsWith(`.${W}`))for(let[Y,V]of K)Q.push(`${Y}=${V}`);return Q.join("; ")}async proxy(X,$,Z,Q){let W=Q.pathname.slice(w0.length)+Q.search+Q.hash;if(!/^https?:\/\//i.test(W)){$.writeHead(400,{"content-type":"text/plain"}),$.end(`Bad proxy target: ${W}`);return}let K=await I6(X),Y=X.method??"GET",V=W,z=K,J=null;this.storeClientCookies(Z,X.headers.cookie);for(let D=0;;D+=1){let w=new URL(V),H=h6(X);for(let j of["host","connection","origin","referer","cookie","accept-encoding"])H.delete(j);let B=this.cookieHeader(Z,w.hostname);if(B)H.set("cookie",B);H.set("referer",`${w.origin}/`);let N={method:Y,headers:H,redirect:"manual",...Y!=="GET"&&Y!=="HEAD"&&z?{body:z,duplex:"half"}:{}};try{J=await fetch(V,N)}catch(j){$.writeHead(502,{"content-type":"text/plain"}),$.end(`Proxy fetch error for ${V}: ${j instanceof Error?j.message:String(j)}`);return}let O=J.headers.getSetCookie,C=typeof O==="function"?O.call(J.headers):[];if(C.length>0)this.storeCookies(Z,C,w.hostname);let L=J.headers.get("location");if(J.status>=300&&J.status<400&&L&&D<15){if(V=new URL(L,V).href,J.status===303||Y==="POST"&&(J.status===301||J.status===302))Y="GET",z=void 0;continue}break}if(!J)throw Error("Browser proxy received no response");Z.lastUsedAt=Date.now();let G=new Headers;J.headers.forEach((D,w)=>{if(!H$.has(w.toLowerCase()))G.set(w,D)}),G.set("access-control-allow-origin","*"),G.set("access-control-allow-credentials","true");for(let D of["location","content-location"]){let w=G.get(D);if(w)G.set(D,s(w,V,this.wrapperOrigin(Z)))}let M=G.get("refresh");if(M){let D=M.toLowerCase().indexOf("url=");if(D>=0)G.set("refresh",M.slice(0,D+4)+s(M.slice(D+4).trim(),V,this.wrapperOrigin(Z)))}let P=G.get("link");if(P){let D=P.replace(/<([^>]+)>/g,(w,H)=>`<${s(H,V,this.wrapperOrigin(Z))}>`).replace(/;\s*integrity\s*=\s*(?:"[^"]*"|'[^']*'|[^;,\s]+)/gi,"");G.set("link",D)}let x=(J.headers.get("content-type")??"").toLowerCase(),U;if(x.includes("text/html")){let D=x$();U=TX({html:await J.text(),sourceUrl:V,proxyOrigin:this.wrapperOrigin(Z),bridgeToken:Z.bridgeToken,revision:D,navigateUrlPrefix:`${this.wrapperOrigin(Z)}/browser-kit/navigate?session=${encodeURIComponent(Z.id)}&url=`}),G.delete("etag"),G.delete("last-modified"),G.set("cache-control","no-store"),G.append("set-cookie",`__browser_kit_origin=${encodeURIComponent(new URL(V).origin)}; Path=/; SameSite=Lax`)}else if(x.includes("text/css"))U=EX({css:await J.text(),baseUrl:V,proxyOrigin:this.wrapperOrigin(Z)}),G.delete("etag"),G.delete("last-modified"),G.set("cache-control","no-store");else U=Buffer.from(await J.arrayBuffer());if($.writeHead(J.status,S6(G)),X.method==="HEAD")$.end();else $.end(U)}async handleHttpRequest(X,$){let Z=new URL(X.url??"/","http://localhost"),Q=Z.pathname.startsWith("/browser-kit/"),W=this.sessionForRequest(X);if(!W){if(!Q)return!1;return $.writeHead(404,{"content-type":"text/plain"}),$.end("Browser-kit session not found"),!0}if(W.lastUsedAt=Date.now(),!Q){let K=null,V=X.headers.referer?.match(/\/browser-kit\/proxy\/(https?:\/\/[^/?#]+)/i);if(V?.[1])K=V[1];if(!K){let J=X.headers.cookie?.match(/(?:^|;\s*)__browser_kit_origin=([^;]+)/);if(J?.[1])try{K=decodeURIComponent(J[1])}catch{}}if(!K)K=new URL(W.currentUrl).origin;let z=`${K}${Z.pathname}${Z.search}`;return $.writeHead(307,{location:`${this.wrapperOrigin(W)}${w0}${z}`,"cache-control":"no-store"}),$.end(),!0}if(Z.pathname==="/browser-kit/wrapper"){if(Z.searchParams.get("session")!==W.id||X.method!=="GET"&&X.method!=="HEAD")return $.writeHead(403),$.end(),!0;let K=g6(W,W.currentUrl);if($.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store","content-security-policy":`default-src 'self'; script-src 'self' 'unsafe-inline'; worker-src 'self'; style-src 'unsafe-inline'; frame-src 'self'; connect-src 'self'; frame-ancestors ${W.frontendOrigin}`,"access-control-allow-origin":W.frontendOrigin,vary:"Origin"}),X.method==="HEAD")$.end();else $.end(K);return!0}if(Z.pathname==="/browser-kit/sw.js")return $.writeHead(200,{"content-type":"text/javascript; charset=utf-8","service-worker-allowed":"/","cache-control":"no-store"}),$.end(vX()),!0;if(Z.pathname==="/browser-kit/navigate"){let K=Z.searchParams.get("url");if(!K)return $.writeHead(400),$.end(),!0;return W.currentUrl=w$(K),$.writeHead(307,{location:`${this.wrapperOrigin(W)}${w0}${W.currentUrl}`,"cache-control":"no-store"}),$.end(),!0}if(Z.pathname.startsWith(w0))return await this.proxy(X,$,W,Z),!0;return $.writeHead(404),$.end(),!0}handleUpgrade(X,$,Z){let Q=new URL(X.url??"/","http://localhost");if(!Q.pathname.startsWith(w0))return!1;let W=this.sessionForRequest(X);if(!W)return $.destroy(),!0;let K=Q.pathname.slice(w0.length)+Q.search+Q.hash;if(!/^wss?:\/\//i.test(K))return $.destroy(),!0;return this.socketServer.handleUpgrade(X,$,Z,(Y)=>{let V;try{let J=new URL(K),G={origin:J.origin},M=this.cookieHeader(W,J.hostname);if(M)G.cookie=M;V=new t0(K,{headers:G})}catch{Y.close(1011,"bad target");return}let z=[];V.binaryType="arraybuffer",V.on("open",()=>{for(let J of z)V.send(J);z.length=0}),Y.on("message",(J)=>{if(V.readyState===t0.OPEN)V.send(J);else z.push(J)}),V.on("message",(J)=>{if(Y.readyState===t0.OPEN)Y.send(J)}),Y.on("close",()=>V.close()),Y.on("error",()=>V.close()),V.on("close",(J,G)=>{if(Y.readyState===t0.OPEN)Y.close(J>=1000&&J<=4999?J:1000,G.toString())}),V.on("error",()=>Y.close(1011,"upstream error"))}),!0}}function m6(X){if(!X)return null;let $=X.indexOf("/");if($<=0)return null;return X.slice(0,$)}function s0(X){let $=[...X.models];if(X.adapterId!=="opencode"||$.length===0)return $;let Z=m6(X.currentModelId)??($.some((W)=>W.id.startsWith("opencode/"))?"opencode":null);if(!Z)return $;let Q=$.filter((W)=>W.id===X.currentModelId||W.id.startsWith(`${Z}/`));return Q.length>0?Q:$}import{Readable as Z3,Writable as Q3}from"node:stream";import{ClientSideConnection as A$,ndJsonStream as C$}from"@agentclientprotocol/sdk";import e from"node:fs/promises";import S from"node:path";class _0 extends Error{constructor(X){super(X);this.name="PathTraversalError"}}class SX extends Error{constructor(X){super(X);this.name="HiddenPathError"}}class gX extends Error{constructor(X){super(X);this.name="RunFolderFileTooLargeError"}}class q0 extends Error{constructor(X){super(X);this.name="RunFolderBinaryFileError"}}var c6=new Set([".bzr",".cache",".claude",".config",".env",".git",".hg",".idea",".obsidian",".svn",".vscode","node_modules"]),N$=1e6,l6=4096,p6=new TextDecoder("utf-8",{fatal:!0});function u6(X){return X.split(/[\\/]+/).filter(($)=>$.length>0)}function e0(X){if(S.isAbsolute(X))throw new _0("Absolute paths are not allowed");for(let $ of u6(X)){if($===".")continue;if($==="..")throw new _0("Parent-directory traversal is not allowed");if($.startsWith(".")||c6.has($))throw new SX(`Path segment "${$}" is hidden or configuration data`)}}function a6(X){e0(X);let $=S.normalize(X||".");return $==="."?"":$}function d6(X,$,Z){let Q=S.relative(X,$);if(Q===".."||Q.startsWith(`..${S.sep}`)||S.isAbsolute(Q))throw new _0(`Path "${Z}" resolves outside the run folder`);if(Q.length>0)e0(Q);return Q}async function IX(X,$){e0($);let Z=S.resolve(X,$||"."),Q;try{Q=await e.realpath(Z)}catch(W){if(W.code!=="ENOENT")throw W;let K=S.dirname(Z),Y=[S.basename(Z)];while(K!==X&&K!==S.dirname(K))try{K=await e.realpath(K);break}catch(V){if(V.code!=="ENOENT")throw V;Y.unshift(S.basename(K)),K=S.dirname(K)}Q=S.join(K,...Y)}return d6(X,Q,$),Q}async function i6(X,$){let Z=await e.realpath(X);return IX(Z,$)}function o6(X){let $=X.subarray(0,Math.min(X.length,l6));if($.length===0)return!1;let Z=0;for(let Q of $){if(Q===0)return!0;let W=Q===9||Q===10||Q===12||Q===13;if(Q<32&&!W)Z+=1}return Z/$.length>0.3}async function XX(X,$){let Z=await i6(X,$),Q=await e.stat(Z);if(!Q.isFile())throw new q0(`Path "${$}" is not a text file`);if(Q.size>N$)throw new gX(`File "${$}" is too large to read (${Q.size} bytes, max ${N$} bytes)`);let W=await e.readFile(Z);if(o6(W))throw new q0(`File "${$}" appears to be binary, not text`);try{return p6.decode(W)}catch{throw new q0(`File "${$}" is not valid UTF-8 text`)}}function n6(X){if(X.isDirectory())return"directory";if(X.isFile())return"file";if(X.isSymbolicLink())return"symlink";return"other"}function M$(X){return X.split(S.sep).join("/")}async function L$(X,$=""){let Z=await e.realpath(X),Q=a6($),W=await IX(Z,Q),K=await e.readdir(W,{withFileTypes:!0}),Y=[];for(let V of K){let z=Q?S.join(Q,V.name):V.name;try{e0(z);let J=await IX(Z,z),G=await e.stat(J);Y.push({name:V.name,path:M$(z),type:n6(V),size:V.isFile()?G.size:null})}catch{}}return Y.sort((V,z)=>{if(V.type==="directory"&&z.type!=="directory")return-1;if(V.type!=="directory"&&z.type==="directory")return 1;return V.name.localeCompare(z.name)}),{path:M$(Q),absolutePath:W,entries:Y}}var mX={fs:{readTextFile:!0,writeTextFile:!1},terminal:!1};function P$(X){return{readTextFile:async($)=>{return{content:await XX(X,$.path)}}}}import{spawn as t6}from"node:child_process";function cX(X){let $=t6(X.command,X.args,{cwd:X.cwd,env:X.env,stdio:["pipe","pipe","pipe"],...u0(X.command)});if(!$.stdin||!$.stdout||!$.stderr)throw Error("Failed to allocate stdio streams for ACP subprocess");let{stdin:Z,stdout:Q,stderr:W}=$,K=4096,Y=[],V=0;W.on("data",(w)=>{Y.push(w),V+=w.length;while(V>K*2&&Y.length>1){let H=Y.shift();if(H)V-=H.length}});let z=()=>{let w=Buffer.concat(Y).toString("utf8");return w.length>K?w.slice(-K):w},J=!1,G=!1,M,P,x=new Promise((w)=>{M=w}),U=new Promise((w)=>{P=w}),D=(w)=>{if(G)return;if(G=!0,M(w),!J)P(w)};return $.on("exit",(w,H)=>{D({code:w,signal:H,stderr:z()})}),$.on("error",(w)=>{let H=z(),B=w?.message??String(w);D({code:null,signal:null,stderr:H?`${B}
922
- ${H}`:B})}),{stdin:Z,stdout:Q,stderr:W,kill:(w="SIGTERM")=>{if(J)return;J=!0;try{$.kill(w)}catch{}},waitForExit:x,processCrashed:U}}var r6=["mcp_ideawave_board_","ideawave_board_","ideawave-board_","ideawave-board.","ideawave.board."];function s6(X){let $=X.toLowerCase();for(let Z of r6)if($.startsWith(Z))return X.slice(Z.length);if(/^mcp[-_.]/i.test(X))return X.slice(4);return X}function $X(X){return s6(X.trim())}function lX(X){let $=$X(X);if(!$)return"Tool";if(!/[-_.]/.test($))return $.charAt(0).toUpperCase()+$.slice(1);let Z=$.replace(/[-_.]+/g," ").replace(/\s+/g," ").trim();if(!Z)return"Tool";return Z.charAt(0).toUpperCase()+Z.slice(1)}function pX(X){let $=X?.toLowerCase();if($==="completed"||$==="complete"||$==="done"||$==="success"||$==="succeeded")return"completed";if($==="failed"||$==="error"||$==="errored")return"failed";return"running"}function uX(X){if(typeof X!=="string")return null;let $=X.trim();return $?$:null}function B$(X){if(typeof X!=="string")return"Tool";let $=X.trim();return $?$:"Tool"}function e6(X,$){if(!X||typeof X!=="object"||Array.isArray(X))return null;let Z=X;for(let Q of $){let W=Z[Q];if(typeof W==="string"&&W.trim())return W.trim()}return null}function aX(X,$){let Z=X.trim().toLowerCase();if(Z==="skill"||Z==="workflow"||Z==="tool"||Z==="invalid"){let Q=e6($,["skillName","workflowName","toolName","name","title"]);if(Q){let W=Z==="skill"?" skill":Z==="workflow"?" workflow":"";return`${lX(Q)}${W}`}}if(Z==="invalid")return"Tool call";return lX(X)}var X3=33,F$=1600;function V0(X){if(X.length<=F$)return X;return`${X.slice(0,F$-22)}
923
- ... truncated`}function QX(X){let $=X.replace(/\r\n?/g,`
924
- `),Z=$.trim();if(Z.startsWith('"')&&Z.endsWith('"')||Z.startsWith("'")&&Z.endsWith("'"))try{let W=JSON.parse(Z);if(typeof W==="string")return W.replace(/\r\n?/g,`
925
- `)}catch{return $}if(!$.includes("\\\""))return $;let Q=$.replace(/\\r\\n/g,`
1015
+ </html>`}class e0{sessions=new Map;profiles=new Map;socketServer=new f6({noServer:!0});sweepTimer;port=null;constructor(){this.sweepTimer=setInterval(()=>this.sweep(),60000),this.sweepTimer.unref?.()}setPort(X){this.port=X}profileForOrigin(X){let $=this.profiles.get(X);if($)return $;let Z={frontendOrigin:X,wrapperHost:`iw-browser-${S6(X)}`,cookies:new Map};return this.profiles.set(X,Z),Z}wrapperOrigin(X){if(!this.port)throw Error("Browser kit is not ready");return`http://${X.profile.wrapperHost}.localhost:${this.port}`}sessionPath(X){return`${s0}${encodeURIComponent(X.id)}`}proxyPathPrefix(X){return`${this.sessionPath(X)}/proxy/`}proxyUrlPrefix(X){return`${this.wrapperOrigin(X)}${this.proxyPathPrefix(X)}`}result(X){let $=this.wrapperOrigin(X),Z=this.sessionPath(X);return{proxySessionId:X.id,wrapperUrl:`${$}${Z}/wrapper`,bridgeToken:X.bridgeToken,navigateUrlPrefix:`${$}${Z}/navigate?url=`}}async handleRpc(X,$,Z){if(Z.method==="open_proxy_session"){let W=Z.params;if(typeof W.browserNodeId!=="string"||typeof W.url!=="string")throw Error("Browser proxy session input is invalid");let Q=M$(W.url),K=I6($),Y=this.profileForOrigin(K),V=[...this.sessions.values()].find((J)=>J.frontendOrigin===K&&J.browserNodeId===W.browserNodeId);if(V)return V.frontendSessionIds.add(X),V.currentUrl=Q,V.lastUsedAt=Date.now(),this.result(V);let j={id:x$(),frontendSessionIds:new Set([X]),frontendOrigin:K,browserNodeId:W.browserNodeId,profile:Y,bridgeToken:T6(24).toString("base64url"),currentUrl:Q,lastUsedAt:Date.now()};return this.sessions.set(j.id,j),this.result(j)}if(Z.method==="close_proxy_session"){let W=Z.params;if(typeof W.proxySessionId!=="string")throw Error("Browser proxy session input is invalid");let Q=this.sessions.get(W.proxySessionId);if(Q&&!Q.frontendSessionIds.has(X))throw Error("Browser proxy session belongs to another frontend session");if(Q)Q.frontendSessionIds.delete(X),Q.lastUsedAt=Date.now();return{closed:!0}}if(Z.method==="build_snapshot")throw Error("Browser-kit snapshots are not available yet");throw Error("Unsupported browser-kit RPC operation")}closeFrontendSession(X){for(let $ of this.sessions.values())if($.frontendSessionIds.delete(X))$.lastUsedAt=Date.now()}async close(){clearInterval(this.sweepTimer),this.sessions.clear(),this.profiles.clear(),this.socketServer.close()}sweep(){let X=Date.now()-v6;for(let $ of this.sessions.values())if($.frontendSessionIds.size===0&&$.lastUsedAt<X)this.sessions.delete($.id)}profileForRequest(X){let $=h6(X.headers.host);return[...this.profiles.values()].find((Z)=>$===`${Z.wrapperHost}.localhost`)??null}escapedSessionForProfile(X){let $=[...this.sessions.values()].filter((W)=>W.profile===X),Z=$.filter((W)=>W.frontendSessionIds.size>0);if(Z.length===1)return Z[0]??null;if(Z.length===0&&$.length===1)return $[0]??null;return null}storeCookies(X,$,Z){for(let W of $){let[Q="",...K]=W.split(";"),Y=Q.indexOf("=");if(Y<0)continue;let V=Q.slice(0,Y).trim(),j=Q.slice(Y+1).trim(),J=Z.toLowerCase();for(let D of K){let N=D.indexOf("="),U=(N<0?D:D.slice(0,N)).trim().toLowerCase(),H=N<0?"":D.slice(N+1).trim();if(U==="domain"&&H)J=H.replace(/^\./,"").toLowerCase()}if(!X.cookies.has(J))X.cookies.set(J,new Map);let z=X.cookies.get(J);if(!z)continue;if(j===""||/(^|;)\s*max-age=0/i.test(W))z.delete(V);else z.set(V,j)}}storeClientCookies(X,$){if(!$)return;for(let Z of $.split(";")){let W=Z.trim(),Q=W.indexOf("=");if(Q<1)continue;let K=W.slice(0,Q);if(!K.startsWith(w$))continue;let Y=K.slice(w$.length).split(".");if(Y.length!==2)continue;try{let V=Buffer.from(Y[0]??"","base64url").toString(),j=Buffer.from(Y[1]??"","base64url").toString(),J=JSON.parse(decodeURIComponent(W.slice(Q+1))),z=new URL(V).hostname.toLowerCase();if(!j||J.name!==j||typeof J.value!=="string")continue;if(!X.cookies.has(z))X.cookies.set(z,new Map);let D=X.cookies.get(z);if(!D)continue;if(J.deleted===!0)D.delete(j);else D.set(j,J.value)}catch{}}}cookieHeader(X,$){let Z=$.toLowerCase(),W=[];for(let[Q,K]of X.cookies)if(Z===Q||Z.endsWith(`.${Q}`))for(let[Y,V]of K)W.push(`${Y}=${V}`);return W.join("; ")}async proxy(X,$,Z,W){let Q=W.pathname.slice(this.proxyPathPrefix(Z).length)+W.search+W.hash;if(!/^https?:\/\//i.test(Q)){$.writeHead(400,{"content-type":"text/plain"}),$.end(`Bad proxy target: ${Q}`);return}let K=await m6(X),Y=X.method??"GET",V=Q,j=K,J=null;this.storeClientCookies(Z.profile,X.headers.cookie);for(let x=0;;x+=1){let w=new URL(V),P=g6(X);for(let G of["host","connection","origin","referer","cookie","accept-encoding"])P.delete(G);let L=this.cookieHeader(Z.profile,w.hostname);if(L)P.set("cookie",L);P.set("referer",`${w.origin}/`);let M={method:Y,headers:P,redirect:"manual",...Y!=="GET"&&Y!=="HEAD"&&j?{body:j,duplex:"half"}:{}};try{J=await fetch(V,M)}catch(G){$.writeHead(502,{"content-type":"text/plain"}),$.end(`Proxy fetch error for ${V}: ${G instanceof Error?G.message:String(G)}`);return}let O=J.headers.getSetCookie,C=typeof O==="function"?O.call(J.headers):[];if(C.length>0)this.storeCookies(Z.profile,C,w.hostname);let F=J.headers.get("location");if(J.status>=300&&J.status<400&&F&&x<15){if(V=new URL(F,V).href,J.status===303||Y==="POST"&&(J.status===301||J.status===302))Y="GET",j=void 0;continue}break}if(!J)throw Error("Browser proxy received no response");Z.lastUsedAt=Date.now();let z=new Headers;J.headers.forEach((x,w)=>{if(!P$.has(w.toLowerCase()))z.set(w,x)}),z.set("access-control-allow-origin","*"),z.set("access-control-allow-credentials","true");for(let x of["location","content-location"]){let w=z.get(x);if(w)z.set(x,s(w,V,this.proxyUrlPrefix(Z)))}let D=z.get("refresh");if(D){let x=D.toLowerCase().indexOf("url=");if(x>=0)z.set("refresh",D.slice(0,x+4)+s(D.slice(x+4).trim(),V,this.proxyUrlPrefix(Z)))}let N=z.get("link");if(N){let x=N.replace(/<([^>]+)>/g,(w,P)=>`<${s(P,V,this.proxyUrlPrefix(Z))}>`).replace(/;\s*integrity\s*=\s*(?:"[^"]*"|'[^']*'|[^;,\s]+)/gi,"");z.set("link",x)}let U=(J.headers.get("content-type")??"").toLowerCase(),H;if(U.includes("text/html")){let x=x$();H=hX({html:await J.text(),sourceUrl:V,proxyOrigin:this.wrapperOrigin(Z),proxyUrlPrefix:this.proxyUrlPrefix(Z),bridgeToken:Z.bridgeToken,revision:x,navigateUrlPrefix:`${this.wrapperOrigin(Z)}${this.sessionPath(Z)}/navigate?url=`,sessionStorageNamespace:Z.id}),z.delete("etag"),z.delete("last-modified"),z.set("cache-control","no-store"),z.append("set-cookie",`__browser_kit_origin_${Z.id}=${encodeURIComponent(new URL(V).origin)}; Path=/; SameSite=Lax`)}else if(U.includes("text/css"))H=vX({css:await J.text(),baseUrl:V,proxyUrlPrefix:this.proxyUrlPrefix(Z)}),z.delete("etag"),z.delete("last-modified"),z.set("cache-control","no-store");else H=Buffer.from(await J.arrayBuffer());if($.writeHead(J.status,c6(z)),X.method==="HEAD")$.end();else $.end(H)}async handleHttpRequest(X,$){let Z=new URL(X.url??"/","http://localhost"),W=Z.pathname.startsWith("/browser-kit/"),Q=this.profileForRequest(X);if(!Q){if(!W)return!1;return $.writeHead(404,{"content-type":"text/plain"}),$.end("Browser-kit profile not found"),!0}if(!W){let V=this.escapedSessionForProfile(Q);if(!V)return $.writeHead(409,{"content-type":"text/plain"}),$.end("Browser-kit request could not be assigned to one active card"),!0;let j=null,J=X.headers.referer;if(J)try{let D=new URL(J),N=gX(D.pathname);if(N?.sessionId===V.id&&N.route.startsWith("/proxy/"))j=new URL(N.route.slice(7)).origin}catch{}if(!j){let D=`__browser_kit_origin_${V.id}=`,N=X.headers.cookie?.split(";").map((U)=>U.trim()).find((U)=>U.startsWith(D));if(N)try{j=decodeURIComponent(N.slice(D.length))}catch{}}if(!j)j=new URL(V.currentUrl).origin;let z=`${j}${Z.pathname}${Z.search}`;return $.writeHead(307,{location:`${this.proxyUrlPrefix(V)}${z}`,"cache-control":"no-store"}),$.end(),!0}if(Z.pathname==="/browser-kit/sw.js"){if(X.method!=="GET"&&X.method!=="HEAD")return $.writeHead(405),$.end(),!0;if($.writeHead(200,{"content-type":"text/javascript; charset=utf-8","service-worker-allowed":"/","cache-control":"no-store"}),X.method==="HEAD")$.end();else $.end(SX());return!0}let K=gX(Z.pathname),Y=K?this.sessions.get(K.sessionId):void 0;if(!K||!Y||Y.profile!==Q)return $.writeHead(404,{"content-type":"text/plain"}),$.end("Browser-kit session not found"),!0;if(Y.lastUsedAt=Date.now(),K.route==="/wrapper"){if(X.method!=="GET"&&X.method!=="HEAD")return $.writeHead(405),$.end(),!0;let V=l6(Y,Y.currentUrl);if($.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store","content-security-policy":`default-src 'self'; script-src 'self' 'unsafe-inline'; worker-src 'self'; style-src 'unsafe-inline'; frame-src 'self'; connect-src 'self'; frame-ancestors ${Y.frontendOrigin}`,"access-control-allow-origin":Y.frontendOrigin,vary:"Origin"}),X.method==="HEAD")$.end();else $.end(V);return!0}if(K.route==="/navigate"){if(X.method!=="GET"&&X.method!=="HEAD")return $.writeHead(405),$.end(),!0;let V=Z.searchParams.get("url");if(!V)return $.writeHead(400),$.end(),!0;return Y.currentUrl=M$(V),$.writeHead(307,{location:`${this.proxyUrlPrefix(Y)}${Y.currentUrl}`,"cache-control":"no-store"}),$.end(),!0}if(K.route.startsWith("/proxy/"))return await this.proxy(X,$,Y,Z),!0;return $.writeHead(404),$.end(),!0}handleUpgrade(X,$,Z){let W=new URL(X.url??"/","http://localhost"),Q=gX(W.pathname);if(!Q?.route.startsWith("/proxy/"))return!1;let K=this.profileForRequest(X),Y=this.sessions.get(Q.sessionId);if(!K||!Y||Y.profile!==K)return $.destroy(),!0;let V=Q.route.slice(7)+W.search+W.hash;if(!/^wss?:\/\//i.test(V))return $.destroy(),!0;return this.socketServer.handleUpgrade(X,$,Z,(j)=>{let J;try{let D=new URL(V),N={origin:D.origin},U=this.cookieHeader(Y.profile,D.hostname);if(U)N.cookie=U;J=new r0(V,{headers:N})}catch{j.close(1011,"bad target");return}let z=[];J.binaryType="arraybuffer",J.on("open",()=>{for(let D of z)J.send(D);z.length=0}),j.on("message",(D)=>{if(J.readyState===r0.OPEN)J.send(D);else z.push(D)}),J.on("message",(D)=>{if(j.readyState===r0.OPEN)j.send(D)}),j.on("close",()=>J.close()),j.on("error",()=>J.close()),J.on("close",(D,N)=>{if(j.readyState===r0.OPEN)j.close(D>=1000&&D<=4999?D:1000,N.toString())}),J.on("error",()=>j.close(1011,"upstream error"))}),!0}}function p6(X){if(!X)return null;let $=X.indexOf("/");if($<=0)return null;return X.slice(0,$)}function XX(X){let $=[...X.models];if(X.adapterId!=="opencode"||$.length===0)return $;let Z=p6(X.currentModelId)??($.some((Q)=>Q.id.startsWith("opencode/"))?"opencode":null);if(!Z)return $;let W=$.filter((Q)=>Q.id===X.currentModelId||Q.id.startsWith(`${Z}/`));return W.length>0?W:$}import{Readable as K3,Writable as J3}from"node:stream";import{ClientSideConnection as y$,ndJsonStream as E$}from"@agentclientprotocol/sdk";import e from"node:fs/promises";import S from"node:path";class A0 extends Error{constructor(X){super(X);this.name="PathTraversalError"}}class cX extends Error{constructor(X){super(X);this.name="HiddenPathError"}}class lX extends Error{constructor(X){super(X);this.name="RunFolderFileTooLargeError"}}class _0 extends Error{constructor(X){super(X);this.name="RunFolderBinaryFileError"}}var u6=new Set([".bzr",".cache",".claude",".config",".env",".git",".hg",".idea",".obsidian",".svn",".vscode","node_modules"]),F$=1e6,a6=4096,d6=new TextDecoder("utf-8",{fatal:!0});function i6(X){return X.split(/[\\/]+/).filter(($)=>$.length>0)}function $X(X){if(S.isAbsolute(X))throw new A0("Absolute paths are not allowed");for(let $ of i6(X)){if($===".")continue;if($==="..")throw new A0("Parent-directory traversal is not allowed");if($.startsWith(".")||u6.has($))throw new cX(`Path segment "${$}" is hidden or configuration data`)}}function o6(X){$X(X);let $=S.normalize(X||".");return $==="."?"":$}function n6(X,$,Z){let W=S.relative(X,$);if(W===".."||W.startsWith(`..${S.sep}`)||S.isAbsolute(W))throw new A0(`Path "${Z}" resolves outside the run folder`);if(W.length>0)$X(W);return W}async function mX(X,$){$X($);let Z=S.resolve(X,$||"."),W;try{W=await e.realpath(Z)}catch(Q){if(Q.code!=="ENOENT")throw Q;let K=S.dirname(Z),Y=[S.basename(Z)];while(K!==X&&K!==S.dirname(K))try{K=await e.realpath(K);break}catch(V){if(V.code!=="ENOENT")throw V;Y.unshift(S.basename(K)),K=S.dirname(K)}W=S.join(K,...Y)}return n6(X,W,$),W}async function t6(X,$){let Z=await e.realpath(X);return mX(Z,$)}function r6(X){let $=X.subarray(0,Math.min(X.length,a6));if($.length===0)return!1;let Z=0;for(let W of $){if(W===0)return!0;let Q=W===9||W===10||W===12||W===13;if(W<32&&!Q)Z+=1}return Z/$.length>0.3}async function ZX(X,$){let Z=await t6(X,$),W=await e.stat(Z);if(!W.isFile())throw new _0(`Path "${$}" is not a text file`);if(W.size>F$)throw new lX(`File "${$}" is too large to read (${W.size} bytes, max ${F$} bytes)`);let Q=await e.readFile(Z);if(r6(Q))throw new _0(`File "${$}" appears to be binary, not text`);try{return d6.decode(Q)}catch{throw new _0(`File "${$}" is not valid UTF-8 text`)}}function s6(X){if(X.isDirectory())return"directory";if(X.isFile())return"file";if(X.isSymbolicLink())return"symlink";return"other"}function L$(X){return X.split(S.sep).join("/")}async function B$(X,$=""){let Z=await e.realpath(X),W=o6($),Q=await mX(Z,W),K=await e.readdir(Q,{withFileTypes:!0}),Y=[];for(let V of K){let j=W?S.join(W,V.name):V.name;try{$X(j);let J=await mX(Z,j),z=await e.stat(J);Y.push({name:V.name,path:L$(j),type:s6(V),size:V.isFile()?z.size:null})}catch{}}return Y.sort((V,j)=>{if(V.type==="directory"&&j.type!=="directory")return-1;if(V.type!=="directory"&&j.type==="directory")return 1;return V.name.localeCompare(j.name)}),{path:L$(W),absolutePath:Q,entries:Y}}var pX={fs:{readTextFile:!0,writeTextFile:!1},terminal:!1};function O$(X){return{readTextFile:async($)=>{return{content:await ZX(X,$.path)}}}}import{spawn as e6}from"node:child_process";function uX(X){let $=e6(X.command,X.args,{cwd:X.cwd,env:X.env,stdio:["pipe","pipe","pipe"],...u0(X.command)});if(!$.stdin||!$.stdout||!$.stderr)throw Error("Failed to allocate stdio streams for ACP subprocess");let{stdin:Z,stdout:W,stderr:Q}=$,K=4096,Y=[],V=0;Q.on("data",(w)=>{Y.push(w),V+=w.length;while(V>K*2&&Y.length>1){let P=Y.shift();if(P)V-=P.length}});let j=()=>{let w=Buffer.concat(Y).toString("utf8");return w.length>K?w.slice(-K):w},J=!1,z=!1,D,N,U=new Promise((w)=>{D=w}),H=new Promise((w)=>{N=w}),x=(w)=>{if(z)return;if(z=!0,D(w),!J)N(w)};return $.on("exit",(w,P)=>{x({code:w,signal:P,stderr:j()})}),$.on("error",(w)=>{let P=j(),L=w?.message??String(w);x({code:null,signal:null,stderr:P?`${L}
1016
+ ${P}`:L})}),{stdin:Z,stdout:W,stderr:Q,kill:(w="SIGTERM")=>{if(J)return;J=!0;try{$.kill(w)}catch{}},waitForExit:U,processCrashed:H}}var X3=["mcp_ideawave_board_","ideawave_board_","ideawave-board_","ideawave-board.","ideawave.board."];function $3(X){let $=X.toLowerCase();for(let Z of X3)if($.startsWith(Z))return X.slice(Z.length);if(/^mcp[-_.]/i.test(X))return X.slice(4);return X}function WX(X){return $3(X.trim())}function aX(X){let $=WX(X);if(!$)return"Tool";if(!/[-_.]/.test($))return $.charAt(0).toUpperCase()+$.slice(1);let Z=$.replace(/[-_.]+/g," ").replace(/\s+/g," ").trim();if(!Z)return"Tool";return Z.charAt(0).toUpperCase()+Z.slice(1)}function dX(X){let $=X?.toLowerCase();if($==="completed"||$==="complete"||$==="done"||$==="success"||$==="succeeded")return"completed";if($==="failed"||$==="error"||$==="errored")return"failed";return"running"}function iX(X){if(typeof X!=="string")return null;let $=X.trim();return $?$:null}function k$(X){if(typeof X!=="string")return"Tool";let $=X.trim();return $?$:"Tool"}function Z3(X,$){if(!X||typeof X!=="object"||Array.isArray(X))return null;let Z=X;for(let W of $){let Q=Z[W];if(typeof Q==="string"&&Q.trim())return Q.trim()}return null}function oX(X,$){let Z=X.trim().toLowerCase();if(Z==="skill"||Z==="workflow"||Z==="tool"||Z==="invalid"){let W=Z3($,["skillName","workflowName","toolName","name","title"]);if(W){let Q=Z==="skill"?" skill":Z==="workflow"?" workflow":"";return`${aX(W)}${Q}`}}if(Z==="invalid")return"Tool call";return aX(X)}var W3=33,_$=1600;function V0(X){if(X.length<=_$)return X;return`${X.slice(0,_$-22)}
1017
+ ... truncated`}function KX(X){let $=X.replace(/\r\n?/g,`
1018
+ `),Z=$.trim();if(Z.startsWith('"')&&Z.endsWith('"')||Z.startsWith("'")&&Z.endsWith("'"))try{let Q=JSON.parse(Z);if(typeof Q==="string")return Q.replace(/\r\n?/g,`
1019
+ `)}catch{return $}if(!$.includes("\\\""))return $;let W=$.replace(/\\r\\n/g,`
926
1020
  `).replace(/\\n/g,`
927
1021
  `).replace(/\\r/g,`
928
- `).replace(/\\t/g,"\t").replace(/\\"/g,'"');try{let W=JSON.parse(Q);if(W!==null&&typeof W==="object")return Q}catch{return $}return $}function o(X){if(X===void 0||X===null)return null;if(typeof X==="string"){let $=QX(X).trim();return $?V0($):null}if(typeof X==="number"||typeof X==="boolean"||typeof X==="bigint")return String(X);try{return V0(JSON.stringify(X,null,2))}catch{return V0(QX(String(X)))}}function $3(X){if(!X||typeof X!=="object")return null;let $=X;if($.type==="text"&&typeof $.text==="string")return QX($.text);if($.type==="image")return"[image]";if($.type==="resource")return"[resource]";if($.type==="content"){let Z=$.content;if(Z&&typeof Z==="object"){let Q=Z;if(Q.type==="text"&&typeof Q.text==="string")return QX(Q.text);if(Q.type==="image")return"[image]";if(Q.type==="resource")return"[resource]"}}if($.type==="diff")return`Diff: ${typeof $.path==="string"?$.path:"unknown file"}`;if($.type==="terminal")return`Terminal: ${typeof $.terminalId==="string"?$.terminalId:"terminal"}`;return o(X)}function ZX(X){if(!Array.isArray(X))return null;let $=X.map($3).filter((Z)=>Boolean(Z?.trim()));if($.length===0)return null;return V0($.join(`
1022
+ `).replace(/\\t/g,"\t").replace(/\\"/g,'"');try{let Q=JSON.parse(W);if(Q!==null&&typeof Q==="object")return W}catch{return $}return $}function o(X){if(X===void 0||X===null)return null;if(typeof X==="string"){let $=KX(X).trim();return $?V0($):null}if(typeof X==="number"||typeof X==="boolean"||typeof X==="bigint")return String(X);try{return V0(JSON.stringify(X,null,2))}catch{return V0(KX(String(X)))}}function Q3(X){if(!X||typeof X!=="object")return null;let $=X;if($.type==="text"&&typeof $.text==="string")return KX($.text);if($.type==="image")return"[image]";if($.type==="resource")return"[resource]";if($.type==="content"){let Z=$.content;if(Z&&typeof Z==="object"){let W=Z;if(W.type==="text"&&typeof W.text==="string")return KX(W.text);if(W.type==="image")return"[image]";if(W.type==="resource")return"[resource]"}}if($.type==="diff")return`Diff: ${typeof $.path==="string"?$.path:"unknown file"}`;if($.type==="terminal")return`Terminal: ${typeof $.terminalId==="string"?$.terminalId:"terminal"}`;return o(X)}function QX(X){if(!Array.isArray(X))return null;let $=X.map(Q3).filter((Z)=>Boolean(Z?.trim()));if($.length===0)return null;return V0($.join(`
929
1023
 
930
- `))}function dX(X){if(!X||typeof X!=="object"||Array.isArray(X))return o(X);let $=X,Z=ZX($.content);if(Z)return Z;for(let K of["output","result","text","message"]){let Y=o($[K]);if(Y)return Y}let Q=o($.stdout),W=o($.stderr);if(Q||W)return V0([Q?`stdout:
931
- ${Q}`:null,W?`stderr:
932
- ${W}`:null].filter(Boolean).join(`
1024
+ `))}function nX(X){if(!X||typeof X!=="object"||Array.isArray(X))return o(X);let $=X,Z=QX($.content);if(Z)return Z;for(let K of["output","result","text","message"]){let Y=o($[K]);if(Y)return Y}let W=o($.stdout),Q=o($.stderr);if(W||Q)return V0([W?`stdout:
1025
+ ${W}`:null,Q?`stderr:
1026
+ ${Q}`:null].filter(Boolean).join(`
933
1027
 
934
- `));return o(X)}function O$(X,$){if(!$)return X;if(!X)return $;if(X===$||X.endsWith($))return X;if($.startsWith(X))return $;return V0(`${X}
1028
+ `));return o(X)}function A$(X,$){if(!$)return X;if(!X)return $;if(X===$||X.endsWith($))return X;if($.startsWith(X))return $;return V0(`${X}
935
1029
 
936
- ${$}`)}function iX(X){if(!Array.isArray(X))return null;let $=X.flatMap((Z)=>{if(!Z||typeof Z!=="object")return[];let Q=Z;if(typeof Q.path!=="string"||!Q.path.trim())return[];let W=typeof Q.line==="number"?`:${Q.line}`:"";return[`${Q.path}${W}`]});return $.length>0?$.slice(0,5):null}function k$(X){let{ctx:$,appendText:Z,appendToolActivity:Q}=X,W=X.flushIntervalMs??X3,K="",Y="",V=0,z=null,J={},G=new Map,M=(L)=>{if(G.set(L.toolCallId,L),!Q)return;Q({boardId:$.boardId,cardId:$.cardId,runId:$.runId,entry:L}).catch((j)=>{console.warn("[streamAdapter] appendToolActivity failed",j)})},P=(L)=>{let j=`${$.runId}:thought`,k=G.get(j);if(!k||k.status!=="running")return;M({...k,status:"completed",completedAt:k.completedAt??L})},x=(L)=>{for(let j of G.values()){if(j.status!=="running"||j.rawTitle.toLowerCase()!=="toolsearch")continue;M({...j,status:"completed",completedAt:j.completedAt??L})}},U=(L)=>{for(let j of Array.from(G.values())){if(j.status!=="running")continue;if(j.kind==="thought"||j.rawTitle==="agent_thought")continue;M({...j,status:"completed",completedAt:j.completedAt??L})}},D="",w=0,H=null,B=null,N=(L)=>{if(L===D)return;D=L,w=Date.now(),Z({boardId:$.boardId,cardId:$.cardId,runId:$.runId,text:L}).catch((j)=>{console.warn("[streamAdapter] appendText failed",j)})},O=()=>{if(H!==null)clearTimeout(H),H=null;if(B!==null){let L=B;B=null,N(L)}},C=(L)=>{let j=Date.now()-w;if(j>=W&&H===null){N(L);return}if(B=L,H===null){let k=Math.max(0,W-j);H=setTimeout(()=>{H=null,O()},k)}};return{onSessionUpdate:async(L)=>{let j=L.update;switch(J[j.sessionUpdate]=(J[j.sessionUpdate]??0)+1,j.sessionUpdate){case"agent_message_chunk":{let k=new Date().toISOString();if(P(k),j.content.type==="text")K+=j.content.text,C(K);else{let _=`agent_message_chunk:${j.content.type}`;J[_]=(J[_]??0)+1}return}case"agent_thought_chunk":{if(j.content.type!=="text")return;Y+=j.content.text;let k=new Date().toISOString(),_=`${$.runId}:thought`,b=G.get(_);M({toolCallId:_,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:b?.startedAt??k,completedAt:null,contentPreview:V0(Y.trim())});return}case"user_message_chunk":return;case"tool_call":{V+=1;let k=B$(j.title),_=pX(j.status),b=new Date().toISOString();P(b),x(b),M({toolCallId:j.toolCallId,rawTitle:k,title:aX(k,j.rawInput),kind:uX(j.kind),status:_,startedAt:b,completedAt:_==="running"?null:b,inputPreview:o(j.rawInput),outputPreview:dX(j.rawOutput),contentPreview:ZX(j.content),locations:iX(j.locations)});return}case"tool_call_update":{let k=G.get(j.toolCallId);if(!k){let y=B$(j.title),I=pX(j.status),h=new Date().toISOString();M({toolCallId:j.toolCallId,rawTitle:y,title:aX(y,j.rawInput),kind:uX(j.kind),status:I,startedAt:h,completedAt:I==="running"?null:h,inputPreview:o(j.rawInput),outputPreview:dX(j.rawOutput),contentPreview:ZX(j.content),locations:iX(j.locations)});return}let _=j.status===void 0||j.status===null?k.status:pX(j.status),b=typeof j.title==="string"&&j.title.trim().length>0?j.title:k.rawTitle,d=typeof j.title==="string"&&j.title.trim().length>0,n=_==="running"?k.completedAt:k.completedAt??new Date().toISOString(),A=j.content===void 0?k.contentPreview:O$(k.contentPreview,ZX(j.content)),v=j.rawOutput===void 0?k.outputPreview:O$(k.outputPreview,dX(j.rawOutput));M({...k,rawTitle:b,title:d?aX(b,j.rawInput):k.title,kind:j.kind===void 0?k.kind:uX(j.kind),status:_,completedAt:n,inputPreview:j.rawInput===void 0?k.inputPreview:o(j.rawInput),outputPreview:v,contentPreview:A,locations:j.locations===void 0?k.locations:iX(j.locations)});return}case"plan":z=j.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>K,getToolCallCount:()=>V,getLatestPlan:()=>z,getUpdateTypeCounts:()=>({...J}),flush:(L)=>{let j=new Date().toISOString();if(P(j),L?.completeOpenToolCalls)U(j);O()}}}var A0=1,q$=-32000;function _$(X){if(X.awaitingInput)return!1;return X.nowMs-X.lastUpdateMs>=X.windowMs}function R$(X){if(!X||typeof X!=="object")return!1;return X.code===q$}var W3=60000,K3=W3,Y3=5000;function J3(X){let $=Math.max(1,Math.round(X/1000));return`Runtime has not responded for ${$} ${$===1?"second":"seconds"}. Retry the agent run.`}function f$(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.72".trim()?"0.0.72":"dev"}}function y$(X){if(X===A0)return;throw new R(`Unsupported ACP protocol version ${X}; expected ${A0}`)}function b$(X){return Z3.toWeb(X)}function E$(X){return Q3.toWeb(X)}function oX(X){return X!==null&&typeof X==="object"}function V3(X){if(!Array.isArray(X))return[];let $=[];for(let Z of X){if(!oX(Z))continue;if(typeof Z.group==="string"&&Array.isArray(Z.options)){let Q=typeof Z.name==="string"?Z.name:Z.group;for(let W of Z.options){if(!oX(W))continue;if(typeof W.value!=="string"||typeof W.name!=="string")continue;$.push({value:W.value,name:W.name,description:typeof W.description==="string"?W.description:null,group:Z.group,groupName:Q})}continue}if(typeof Z.value!=="string"||typeof Z.name!=="string")continue;$.push({value:Z.value,name:Z.name,description:typeof Z.description==="string"?Z.description:null,group:null,groupName:null})}return $}function j3(X){if(!oX(X))return null;if(typeof X.id!=="string"||typeof X.name!=="string")return null;let $=typeof X.category==="string"?X.category:null,Z=typeof X.description==="string"?X.description:null;if(X.type==="select"){let Q=typeof X.currentValue==="string"?X.currentValue:null;return{id:X.id,name:X.name,category:$,description:Z,type:"select",currentValue:Q,options:V3(X.options)}}if(X.type==="boolean"){let Q=typeof X.currentValue==="boolean"?X.currentValue:typeof X.value==="boolean"?X.value:null;return{id:X.id,name:X.name,category:$,description:Z,type:"boolean",currentValue:Q,options:[]}}return null}function nX(X){let $=(X.configOptions??[]).map(j3).filter((V)=>V!==null),Z=$.find((V)=>V.type==="select"&&V.category==="model")??$.find((V)=>V.type==="select"&&V.id==="model")??null,Q=Z?.options.map((V)=>({id:V.value,name:V.name,description:V.description??null})),W=G3(X.models),K=Q&&Q.length>0?Q:W&&W.length>0?W:null,Y=(typeof Z?.currentValue==="string"?Z.currentValue:null)??z3(X.models)??null;return{models:K,currentModelId:Y,configOptions:$,modelConfigId:Z?.id??null}}function G3(X){if(!X||!Array.isArray(X.availableModels))return null;let $=[];for(let Z of X.availableModels){if(typeof Z.modelId!=="string")continue;$.push({id:Z.modelId,name:typeof Z.name==="string"?Z.name:null,description:typeof Z.description==="string"?Z.description:null})}return $.length>0?$:null}function z3(X){return typeof X?.currentModelId==="string"?X.currentModelId:null}function U3(X,$){let Z=[];if(X.trim())Z.push({type:"text",text:X});for(let Q of $)if(Q.content.trim())Z.push({type:"text",text:Q.content});return Z}function H3(X){if(typeof X.value==="boolean")return{sessionId:X.sessionId,configId:X.configId,type:"boolean",value:X.value};return{sessionId:X.sessionId,configId:X.configId,value:X.value}}function x3(X,$){let Z=nX({configOptions:$.configOptions});return{models:Z.models??X.models,currentModelId:Z.currentModelId??X.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??X.modelConfigId}}function T$(X,$){if(X==="default")return null;if(!$||$.length===0)return X;let Z=$.find((J)=>J.id===X);if(Z)return Z.id;let Q=X.toLowerCase(),W=Q.includes("opus")?"opus":Q.includes("sonnet")?"sonnet":Q.includes("haiku")?"haiku":null;if(!W)return X;let K=(J)=>`${J.id} ${J.name??""} ${J.description??""}`.toLowerCase(),Y=$.filter((J)=>K(J).includes(W));if(Y.length===0)return X;let z=(Q.includes("1m")?Y.find((J)=>K(J).includes("1m")):void 0)??Y[0];return z?z.id:X}async function WX(X){try{let $=await X.conn.setSessionConfigOption(H3({sessionId:X.sessionId,configId:X.configId,value:X.value}));return x3(X.metadata,$)}catch($){return console.warn(`[acp] setSessionConfigOption(${X.label}) failed; using agent default.`,$ instanceof Error?$.message:$),X.metadata}}async function tX(X){let $=cX(X.spawn),Z=[],Q=0,W=4096;$.stderr.on("data",(A)=>{Z.push(A),Q+=A.length;while(Q>W*2&&Z.length>1){let v=Z.shift();if(v)Q-=v.length}});let K=()=>{let A=Buffer.concat(Z).toString("utf8");return A.length>W?A.slice(-W):A},Y=P$(X.spawn.cwd),V={current:null},z={current:null},J={at:Date.now()},G=null,M=E$($.stdin),P=b$($.stdout),x=C$(M,P),D=new A$((A)=>({requestPermission:async(v)=>{let y=v.options,I=y?.find((h)=>h.kind==="allow_once")??y?.find((h)=>h.kind==="allow_always");if(I)return{outcome:{outcome:"selected",optionId:I.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(v)=>{J.at=Date.now();let y=z.current;if(y){let h=v.update.sessionUpdate;if(y.updateCount+=1,y.updateCount===1||y.lastUpdateType!==h||h==="tool_call"||h==="tool_call_update")q("acp.session_update",{runId:y.runId,cardId:y.cardId,sessionId:G,updateType:h,updateCount:y.updateCount,elapsedMs:Date.now()-y.startedAt});y.lastUpdateType=h}let I=V.current;if(I)await I.onSessionUpdate(v)},readTextFile:Y.readTextFile}),x),w=()=>$.kill();if(X.signal)X.signal.addEventListener("abort",w);let H=()=>{if(X.signal)X.signal.removeEventListener("abort",w)},B=async(A,v)=>{if(H(),$.kill(),R$(A))throw new H0(A.message??"Authentication required",v);if(A instanceof Error&&A.message==="ACP connection closed"){if(X.signal?.aborted)throw new R("ACP session cancelled: abort signal received");let y=await Promise.race([$.processCrashed,$.waitForExit,new Promise((I)=>setTimeout(()=>I({stderr:""}),500))]);throw new R(`Runtime process exited before completion: ${y.stderr?.trim()??""}`)}throw A},N;try{N=await D.initialize({protocolVersion:A0,clientCapabilities:mX,clientInfo:f$()})}catch(A){throw await B(A,[]),Error("unreachable")}try{y$(N.protocolVersion)}catch(A){throw H(),$.kill(),A}let O=N.authMethods?.map((A)=>A.id)??[],C;try{C=await D.newSession({cwd:X.spawn.cwd,mcpServers:X.mcpServers??[]})}catch(A){throw await B(A,O),Error("unreachable")}let L=C.sessionId;G=L;let j=nX(C),k=X.modelId??null,_=k?T$(k,j.models):null;if(_&&_!==j.currentModelId)if(j.modelConfigId)j=await WX({conn:D,sessionId:L,configId:j.modelConfigId,value:_,metadata:j,label:`${j.modelConfigId}=${_}`});else console.warn(`[acp] runtime did not advertise a model config option for ${_}; using agent default.`);for(let[A,v]of Object.entries(X.configValues??{}).sort(([y],[I])=>y.localeCompare(I))){if(A===j.modelConfigId)continue;if(!j.configOptions.some((y)=>y.id===A))continue;j=await WX({conn:D,sessionId:L,configId:A,value:v,metadata:j,label:`${A}=${String(v)}`})}H();let b=!1,d=async()=>{if(b)return;b=!0,$.kill(),await Promise.race([$.waitForExit,new Promise((A)=>setTimeout(A,2000))])},n=!1;return $.processCrashed.then(()=>{n=!0}),{sessionId:L,availableModels:j.models,currentModelId:j.currentModelId,availableConfigOptions:j.configOptions,isAlive:()=>!b&&!n,dispose:d,prompt:(A)=>D3({proc:$,conn:D,sessionId:L,activeAdapter:V,activeTrace:z,lastUpdate:J,collectStderrTail:K},A)}}async function D3(X,$){let{proc:Z,conn:Q,sessionId:W,activeAdapter:K,activeTrace:Y,lastUpdate:V}=X,z=Date.now(),J=$.heartbeatMs??K3,G=J3(J),M={boardId:$.boardId,cardId:$.cardId,runId:$.runId},P=k$({ctx:M,appendText:$.appendText,appendToolActivity:$.appendToolActivity});K.current=P,Y.current={runId:$.runId,cardId:$.cardId,startedAt:z,updateCount:0,lastUpdateType:null},V.at=Date.now(),q("acp.prompt_started",{runId:$.runId,cardId:$.cardId,sessionId:W,heartbeatWindowMs:J});let x=!1,U=null,D=()=>Z.kill();$.signal.addEventListener("abort",D);try{let w=async()=>{let O=Math.min(Y3,Math.max(50,Math.floor(J/2)));U=setInterval(()=>{let L=$.isAwaitingInput?.()??!1;if(L){V.at=Date.now();return}if(_$({nowMs:Date.now(),lastUpdateMs:V.at,windowMs:J,awaitingInput:L}))x=!0,q("acp.inactivity_timeout",{runId:$.runId,cardId:$.cardId,sessionId:W,windowMs:J,silentForMs:Date.now()-V.at}),Q.cancel({sessionId:W}).catch(()=>{return}),Z.kill()},O);let C=U3($.prompt.systemPrompt,$.prompt.messages);await Q.prompt({sessionId:W,prompt:C}),q("acp.prompt_resolved",{runId:$.runId,cardId:$.cardId,sessionId:W,elapsedMs:Date.now()-z}),P.flush({completeOpenToolCalls:!0})},H=Z.waitForExit.then((O)=>({kind:"exited",exit:O})),B=w().then(()=>({kind:"ok"})).catch(async(O)=>{if(O instanceof Error&&O.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw O}),N;try{N=await Promise.race([B,Z.processCrashed.then((O)=>({kind:"crashed",exit:O})),H])}catch(O){if(x)throw new u(G);throw O}if(x)throw new u(G);if(N.kind==="crashed")throw new R(`Runtime process exited before completion: ${N.exit.stderr.trim()}`);if(N.kind==="exited"){if($.signal.aborted)throw new R("ACP session cancelled: abort signal received");if(x)throw new u(G);throw new R(`Runtime process exited unexpectedly: ${N.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:P.getFinalText(),toolCallsExecuted:P.getToolCallCount(),stderrTail:X.collectStderrTail(),updateTypeCounts:P.getUpdateTypeCounts()}}finally{if(q("acp.prompt_finished",{runId:$.runId,cardId:$.cardId,sessionId:W,elapsedMs:Date.now()-z,timedOut:x,updateCount:Y.current?.updateCount??0}),U!==null)clearInterval(U);$.signal.removeEventListener("abort",D),P.flush({completeOpenToolCalls:!0}),K.current=null,Y.current=null}}var w3=30000;async function v$(X){let $=cX(X.spawn),Z=E$($.stdin),Q=b$($.stdout),W=C$(Z,Q),Y=new A$((J)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),W),V=()=>$.kill();if(X.signal)X.signal.addEventListener("abort",V);let z=null;try{let J=(async()=>{let M=await Y.initialize({protocolVersion:A0,clientCapabilities:mX,clientInfo:f$()});y$(M.protocolVersion);let P=M.authMethods?.map((N)=>N.id)??[],x;try{x=await Y.newSession({cwd:X.spawn.cwd,mcpServers:[]})}catch(N){if(R$(N))throw new H0(N.message??"Authentication required",P);throw N}let U=nX(x),D=X.modelId??null,w=D?T$(D,U.models):null;if(w&&w!==U.currentModelId)if(U.modelConfigId)U=await WX({conn:Y,sessionId:x.sessionId,configId:U.modelConfigId,value:w,metadata:U,label:`${U.modelConfigId}=${w}`});else console.warn(`[acp] runtime did not advertise a model config option for ${w}; discovering agent default models.`);for(let[N,O]of Object.entries(X.configValues??{}).sort(([C],[L])=>C.localeCompare(L))){if(N===U.modelConfigId)continue;if(!U.configOptions.some((C)=>C.id===N))continue;U=await WX({conn:Y,sessionId:x.sessionId,configId:N,value:O,metadata:U,label:`${N}=${String(O)}`})}let H=U.models??[],B=U.currentModelId;return Y.cancel({sessionId:x.sessionId}).catch(()=>{return}),{models:H,configOptions:U.configOptions,currentModelId:B}})(),G=new Promise((M,P)=>{z=setTimeout(()=>{P(new u)},w3)});return await Promise.race([J,G])}catch(J){if(J instanceof Error&&J.message==="ACP connection closed"){if(X.signal?.aborted)throw new R("ACP model discovery cancelled: abort signal received");throw new R("Runtime process exited during model discovery.")}throw J}finally{if(z)clearTimeout(z);if(X.signal)X.signal.removeEventListener("abort",V);$.kill()}}import N3 from"node:fs/promises";import KX from"node:os";async function h$(X){let $={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await N3.readFile(X,"utf-8")}catch(Q){if(Q.code==="ENOENT")return structuredClone($);throw Q}return c0.parse(JSON.parse(Z))}function rX(X,$,Z){return{...X.defaultConfigValues??{},...$?.configValues??{},...Z?.configValues??{}}}async function X0(X){let $=X.configPath?await h$(X.configPath):await m(),Z=X.cardId?$.cardOverrides[X.cardId]:void 0;if(Z?.runtimeConfigId){let W=$.runtimes.find((K)=>K.id===Z.runtimeConfigId);if(W)return{entry:W,adapter:a(W),runFolder:Z.runFolder??W.runFolder??KX.homedir(),modelId:Z.modelId??W.defaultModelId??null,configValues:rX(W,void 0,Z)}}let Q=$.boardOverrides[X.boardId];if(Q?.runtimeConfigId){let W=$.runtimes.find((K)=>K.id===Q.runtimeConfigId);if(W)return{entry:W,adapter:a(W),runFolder:Q.runFolder??W.runFolder??KX.homedir(),modelId:Q.modelId??W.defaultModelId??null,configValues:rX(W,Q)}}if($.globalDefaultConfigId){let W=$.runtimes.find((K)=>K.id===$.globalDefaultConfigId);if(W)return{entry:W,adapter:a(W),runFolder:Z?.runFolder??Q?.runFolder??W.runFolder??KX.homedir(),modelId:Z?.modelId??Q?.modelId??W.defaultModelId??null,configValues:rX(W,Q,Z)}}throw new Y0}async function I$(X,$={}){let Q=($.configPath?await h$($.configPath):await m()).runtimes.find((W)=>W.id===X);if(!Q)return null;return{entry:Q,adapter:a(Q),runFolder:Q.runFolder??KX.homedir(),modelId:$.modelId??Q.defaultModelId??null,configValues:{...Q.defaultConfigValues??{},...$.configValues??{}}}}var S$=new Map;function sX(X,$){if(!X)return;S$.set(X,$)}function g$(X){if(!X)return!1;return S$.get(X)??!1}var j0=new Map,eX=new Set;function $1(X){j0.get(X)?.controller.abort()}function m$(X){for(let[$,Z]of j0){if(Z.frontendSessionId!==X)continue;Z.controller.abort(),j0.delete($)}}function c$(){for(let X of j0.values())X.controller.abort();j0.clear()}function X1(X,$){if($?.aborted)return!0;return X instanceof Error&&/abort signal received|session cancelled/i.test(X.message)}function l$(X,$,Z,Q){if((!$.availableModels||$.availableModels.length===0)&&$.availableConfigOptions.length===0)return;p((W)=>{let K=W.runtimes.find((Y)=>Y.id===X);if(K){if($.availableModels&&$.availableModels.length>0)K.discoveredModels=s0({adapterId:Z,models:$.availableModels,currentModelId:$.currentModelId??Q});if($.availableConfigOptions.length>0)K.discoveredConfigOptions=$.availableConfigOptions}}).catch(()=>{return})}function M3(X,$){return`${X}
1030
+ ${$}`)}function tX(X){if(!Array.isArray(X))return null;let $=X.flatMap((Z)=>{if(!Z||typeof Z!=="object")return[];let W=Z;if(typeof W.path!=="string"||!W.path.trim())return[];let Q=typeof W.line==="number"?`:${W.line}`:"";return[`${W.path}${Q}`]});return $.length>0?$.slice(0,5):null}function q$(X){let{ctx:$,appendText:Z,appendToolActivity:W}=X,Q=X.flushIntervalMs??W3,K="",Y="",V=0,j=null,J={},z=new Map,D=(F)=>{if(z.set(F.toolCallId,F),!W)return;W({boardId:$.boardId,cardId:$.cardId,runId:$.runId,entry:F}).catch((G)=>{console.warn("[streamAdapter] appendToolActivity failed",G)})},N=(F)=>{let G=`${$.runId}:thought`,k=z.get(G);if(!k||k.status!=="running")return;D({...k,status:"completed",completedAt:k.completedAt??F})},U=(F)=>{for(let G of z.values()){if(G.status!=="running"||G.rawTitle.toLowerCase()!=="toolsearch")continue;D({...G,status:"completed",completedAt:G.completedAt??F})}},H=(F)=>{for(let G of Array.from(z.values())){if(G.status!=="running")continue;if(G.kind==="thought"||G.rawTitle==="agent_thought")continue;D({...G,status:"completed",completedAt:G.completedAt??F})}},x="",w=0,P=null,L=null,M=(F)=>{if(F===x)return;x=F,w=Date.now(),Z({boardId:$.boardId,cardId:$.cardId,runId:$.runId,text:F}).catch((G)=>{console.warn("[streamAdapter] appendText failed",G)})},O=()=>{if(P!==null)clearTimeout(P),P=null;if(L!==null){let F=L;L=null,M(F)}},C=(F)=>{let G=Date.now()-w;if(G>=Q&&P===null){M(F);return}if(L=F,P===null){let k=Math.max(0,Q-G);P=setTimeout(()=>{P=null,O()},k)}};return{onSessionUpdate:async(F)=>{let G=F.update;switch(J[G.sessionUpdate]=(J[G.sessionUpdate]??0)+1,G.sessionUpdate){case"agent_message_chunk":{let k=new Date().toISOString();if(N(k),G.content.type==="text")K+=G.content.text,C(K);else{let A=`agent_message_chunk:${G.content.type}`;J[A]=(J[A]??0)+1}return}case"agent_thought_chunk":{if(G.content.type!=="text")return;Y+=G.content.text;let k=new Date().toISOString(),A=`${$.runId}:thought`,b=z.get(A);D({toolCallId:A,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:b?.startedAt??k,completedAt:null,contentPreview:V0(Y.trim())});return}case"user_message_chunk":return;case"tool_call":{V+=1;let k=k$(G.title),A=dX(G.status),b=new Date().toISOString();N(b),U(b),D({toolCallId:G.toolCallId,rawTitle:k,title:oX(k,G.rawInput),kind:iX(G.kind),status:A,startedAt:b,completedAt:A==="running"?null:b,inputPreview:o(G.rawInput),outputPreview:nX(G.rawOutput),contentPreview:QX(G.content),locations:tX(G.locations)});return}case"tool_call_update":{let k=z.get(G.toolCallId);if(!k){let E=k$(G.title),I=dX(G.status),h=new Date().toISOString();D({toolCallId:G.toolCallId,rawTitle:E,title:oX(E,G.rawInput),kind:iX(G.kind),status:I,startedAt:h,completedAt:I==="running"?null:h,inputPreview:o(G.rawInput),outputPreview:nX(G.rawOutput),contentPreview:QX(G.content),locations:tX(G.locations)});return}let A=G.status===void 0||G.status===null?k.status:dX(G.status),b=typeof G.title==="string"&&G.title.trim().length>0?G.title:k.rawTitle,d=typeof G.title==="string"&&G.title.trim().length>0,n=A==="running"?k.completedAt:k.completedAt??new Date().toISOString(),q=G.content===void 0?k.contentPreview:A$(k.contentPreview,QX(G.content)),v=G.rawOutput===void 0?k.outputPreview:A$(k.outputPreview,nX(G.rawOutput));D({...k,rawTitle:b,title:d?oX(b,G.rawInput):k.title,kind:G.kind===void 0?k.kind:iX(G.kind),status:A,completedAt:n,inputPreview:G.rawInput===void 0?k.inputPreview:o(G.rawInput),outputPreview:v,contentPreview:q,locations:G.locations===void 0?k.locations:tX(G.locations)});return}case"plan":j=G.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>K,getToolCallCount:()=>V,getLatestPlan:()=>j,getUpdateTypeCounts:()=>({...J}),flush:(F)=>{let G=new Date().toISOString();if(N(G),F?.completeOpenToolCalls)H(G);O()}}}var q0=1,C$=-32000;function R$(X){if(X.awaitingInput)return!1;return X.nowMs-X.lastUpdateMs>=X.windowMs}function b$(X){if(!X||typeof X!=="object")return!1;return X.code===C$}var Y3=60000,V3=Y3,j3=5000;function G3(X){let $=Math.max(1,Math.round(X/1000));return`Runtime has not responded for ${$} ${$===1?"second":"seconds"}. Retry the agent run.`}function T$(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.73".trim()?"0.0.73":"dev"}}function f$(X){if(X===q0)return;throw new R(`Unsupported ACP protocol version ${X}; expected ${q0}`)}function v$(X){return K3.toWeb(X)}function h$(X){return J3.toWeb(X)}function rX(X){return X!==null&&typeof X==="object"}function z3(X){if(!Array.isArray(X))return[];let $=[];for(let Z of X){if(!rX(Z))continue;if(typeof Z.group==="string"&&Array.isArray(Z.options)){let W=typeof Z.name==="string"?Z.name:Z.group;for(let Q of Z.options){if(!rX(Q))continue;if(typeof Q.value!=="string"||typeof Q.name!=="string")continue;$.push({value:Q.value,name:Q.name,description:typeof Q.description==="string"?Q.description:null,group:Z.group,groupName:W})}continue}if(typeof Z.value!=="string"||typeof Z.name!=="string")continue;$.push({value:Z.value,name:Z.name,description:typeof Z.description==="string"?Z.description:null,group:null,groupName:null})}return $}function H3(X){if(!rX(X))return null;if(typeof X.id!=="string"||typeof X.name!=="string")return null;let $=typeof X.category==="string"?X.category:null,Z=typeof X.description==="string"?X.description:null;if(X.type==="select"){let W=typeof X.currentValue==="string"?X.currentValue:null;return{id:X.id,name:X.name,category:$,description:Z,type:"select",currentValue:W,options:z3(X.options)}}if(X.type==="boolean"){let W=typeof X.currentValue==="boolean"?X.currentValue:typeof X.value==="boolean"?X.value:null;return{id:X.id,name:X.name,category:$,description:Z,type:"boolean",currentValue:W,options:[]}}return null}function sX(X){let $=(X.configOptions??[]).map(H3).filter((V)=>V!==null),Z=$.find((V)=>V.type==="select"&&V.category==="model")??$.find((V)=>V.type==="select"&&V.id==="model")??null,W=Z?.options.map((V)=>({id:V.value,name:V.name,description:V.description??null})),Q=U3(X.models),K=W&&W.length>0?W:Q&&Q.length>0?Q:null,Y=(typeof Z?.currentValue==="string"?Z.currentValue:null)??D3(X.models)??null;return{models:K,currentModelId:Y,configOptions:$,modelConfigId:Z?.id??null}}function U3(X){if(!X||!Array.isArray(X.availableModels))return null;let $=[];for(let Z of X.availableModels){if(typeof Z.modelId!=="string")continue;$.push({id:Z.modelId,name:typeof Z.name==="string"?Z.name:null,description:typeof Z.description==="string"?Z.description:null})}return $.length>0?$:null}function D3(X){return typeof X?.currentModelId==="string"?X.currentModelId:null}function N3(X,$){let Z=[];if(X.trim())Z.push({type:"text",text:X});for(let W of $)if(W.content.trim())Z.push({type:"text",text:W.content});return Z}function P3(X){if(typeof X.value==="boolean")return{sessionId:X.sessionId,configId:X.configId,type:"boolean",value:X.value};return{sessionId:X.sessionId,configId:X.configId,value:X.value}}function x3(X,$){let Z=sX({configOptions:$.configOptions});return{models:Z.models??X.models,currentModelId:Z.currentModelId??X.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??X.modelConfigId}}function I$(X,$){if(X==="default")return null;if(!$||$.length===0)return X;let Z=$.find((J)=>J.id===X);if(Z)return Z.id;let W=X.toLowerCase(),Q=W.includes("opus")?"opus":W.includes("sonnet")?"sonnet":W.includes("haiku")?"haiku":null;if(!Q)return X;let K=(J)=>`${J.id} ${J.name??""} ${J.description??""}`.toLowerCase(),Y=$.filter((J)=>K(J).includes(Q));if(Y.length===0)return X;let j=(W.includes("1m")?Y.find((J)=>K(J).includes("1m")):void 0)??Y[0];return j?j.id:X}async function JX(X){try{let $=await X.conn.setSessionConfigOption(P3({sessionId:X.sessionId,configId:X.configId,value:X.value}));return x3(X.metadata,$)}catch($){return console.warn(`[acp] setSessionConfigOption(${X.label}) failed; using agent default.`,$ instanceof Error?$.message:$),X.metadata}}async function eX(X){let $=uX(X.spawn),Z=[],W=0,Q=4096;$.stderr.on("data",(q)=>{Z.push(q),W+=q.length;while(W>Q*2&&Z.length>1){let v=Z.shift();if(v)W-=v.length}});let K=()=>{let q=Buffer.concat(Z).toString("utf8");return q.length>Q?q.slice(-Q):q},Y=O$(X.spawn.cwd),V={current:null},j={current:null},J={at:Date.now()},z=null,D=h$($.stdin),N=v$($.stdout),U=E$(D,N),x=new y$((q)=>({requestPermission:async(v)=>{let E=v.options,I=E?.find((h)=>h.kind==="allow_once")??E?.find((h)=>h.kind==="allow_always");if(I)return{outcome:{outcome:"selected",optionId:I.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(v)=>{J.at=Date.now();let E=j.current;if(E){let h=v.update.sessionUpdate;if(E.updateCount+=1,E.updateCount===1||E.lastUpdateType!==h||h==="tool_call"||h==="tool_call_update")_("acp.session_update",{runId:E.runId,cardId:E.cardId,sessionId:z,updateType:h,updateCount:E.updateCount,elapsedMs:Date.now()-E.startedAt});E.lastUpdateType=h}let I=V.current;if(I)await I.onSessionUpdate(v)},readTextFile:Y.readTextFile}),U),w=()=>$.kill();if(X.signal)X.signal.addEventListener("abort",w);let P=()=>{if(X.signal)X.signal.removeEventListener("abort",w)},L=async(q,v)=>{if(P(),$.kill(),b$(q))throw new U0(q.message??"Authentication required",v);if(q instanceof Error&&q.message==="ACP connection closed"){if(X.signal?.aborted)throw new R("ACP session cancelled: abort signal received");let E=await Promise.race([$.processCrashed,$.waitForExit,new Promise((I)=>setTimeout(()=>I({stderr:""}),500))]);throw new R(`Runtime process exited before completion: ${E.stderr?.trim()??""}`)}throw q},M;try{M=await x.initialize({protocolVersion:q0,clientCapabilities:pX,clientInfo:T$()})}catch(q){throw await L(q,[]),Error("unreachable")}try{f$(M.protocolVersion)}catch(q){throw P(),$.kill(),q}let O=M.authMethods?.map((q)=>q.id)??[],C;try{C=await x.newSession({cwd:X.spawn.cwd,mcpServers:X.mcpServers??[]})}catch(q){throw await L(q,O),Error("unreachable")}let F=C.sessionId;z=F;let G=sX(C),k=X.modelId??null,A=k?I$(k,G.models):null;if(A&&A!==G.currentModelId)if(G.modelConfigId)G=await JX({conn:x,sessionId:F,configId:G.modelConfigId,value:A,metadata:G,label:`${G.modelConfigId}=${A}`});else console.warn(`[acp] runtime did not advertise a model config option for ${A}; using agent default.`);for(let[q,v]of Object.entries(X.configValues??{}).sort(([E],[I])=>E.localeCompare(I))){if(q===G.modelConfigId)continue;if(!G.configOptions.some((E)=>E.id===q))continue;G=await JX({conn:x,sessionId:F,configId:q,value:v,metadata:G,label:`${q}=${String(v)}`})}P();let b=!1,d=async()=>{if(b)return;b=!0,$.kill(),await Promise.race([$.waitForExit,new Promise((q)=>setTimeout(q,2000))])},n=!1;return $.processCrashed.then(()=>{n=!0}),{sessionId:F,availableModels:G.models,currentModelId:G.currentModelId,availableConfigOptions:G.configOptions,isAlive:()=>!b&&!n,dispose:d,prompt:(q)=>w3({proc:$,conn:x,sessionId:F,activeAdapter:V,activeTrace:j,lastUpdate:J,collectStderrTail:K},q)}}async function w3(X,$){let{proc:Z,conn:W,sessionId:Q,activeAdapter:K,activeTrace:Y,lastUpdate:V}=X,j=Date.now(),J=$.heartbeatMs??V3,z=G3(J),D={boardId:$.boardId,cardId:$.cardId,runId:$.runId},N=q$({ctx:D,appendText:$.appendText,appendToolActivity:$.appendToolActivity});K.current=N,Y.current={runId:$.runId,cardId:$.cardId,startedAt:j,updateCount:0,lastUpdateType:null},V.at=Date.now(),_("acp.prompt_started",{runId:$.runId,cardId:$.cardId,sessionId:Q,heartbeatWindowMs:J});let U=!1,H=null,x=()=>Z.kill();$.signal.addEventListener("abort",x);try{let w=async()=>{let O=Math.min(j3,Math.max(50,Math.floor(J/2)));H=setInterval(()=>{let F=$.isAwaitingInput?.()??!1;if(F){V.at=Date.now();return}if(R$({nowMs:Date.now(),lastUpdateMs:V.at,windowMs:J,awaitingInput:F}))U=!0,_("acp.inactivity_timeout",{runId:$.runId,cardId:$.cardId,sessionId:Q,windowMs:J,silentForMs:Date.now()-V.at}),W.cancel({sessionId:Q}).catch(()=>{return}),Z.kill()},O);let C=N3($.prompt.systemPrompt,$.prompt.messages);await W.prompt({sessionId:Q,prompt:C}),_("acp.prompt_resolved",{runId:$.runId,cardId:$.cardId,sessionId:Q,elapsedMs:Date.now()-j}),N.flush({completeOpenToolCalls:!0})},P=Z.waitForExit.then((O)=>({kind:"exited",exit:O})),L=w().then(()=>({kind:"ok"})).catch(async(O)=>{if(O instanceof Error&&O.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw O}),M;try{M=await Promise.race([L,Z.processCrashed.then((O)=>({kind:"crashed",exit:O})),P])}catch(O){if(U)throw new u(z);throw O}if(U)throw new u(z);if(M.kind==="crashed")throw new R(`Runtime process exited before completion: ${M.exit.stderr.trim()}`);if(M.kind==="exited"){if($.signal.aborted)throw new R("ACP session cancelled: abort signal received");if(U)throw new u(z);throw new R(`Runtime process exited unexpectedly: ${M.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:N.getFinalText(),toolCallsExecuted:N.getToolCallCount(),stderrTail:X.collectStderrTail(),updateTypeCounts:N.getUpdateTypeCounts()}}finally{if(_("acp.prompt_finished",{runId:$.runId,cardId:$.cardId,sessionId:Q,elapsedMs:Date.now()-j,timedOut:U,updateCount:Y.current?.updateCount??0}),H!==null)clearInterval(H);$.signal.removeEventListener("abort",x),N.flush({completeOpenToolCalls:!0}),K.current=null,Y.current=null}}var M3=30000;async function S$(X){let $=uX(X.spawn),Z=h$($.stdin),W=v$($.stdout),Q=E$(Z,W),Y=new y$((J)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),V=()=>$.kill();if(X.signal)X.signal.addEventListener("abort",V);let j=null;try{let J=(async()=>{let D=await Y.initialize({protocolVersion:q0,clientCapabilities:pX,clientInfo:T$()});f$(D.protocolVersion);let N=D.authMethods?.map((M)=>M.id)??[],U;try{U=await Y.newSession({cwd:X.spawn.cwd,mcpServers:[]})}catch(M){if(b$(M))throw new U0(M.message??"Authentication required",N);throw M}let H=sX(U),x=X.modelId??null,w=x?I$(x,H.models):null;if(w&&w!==H.currentModelId)if(H.modelConfigId)H=await JX({conn:Y,sessionId:U.sessionId,configId:H.modelConfigId,value:w,metadata:H,label:`${H.modelConfigId}=${w}`});else console.warn(`[acp] runtime did not advertise a model config option for ${w}; discovering agent default models.`);for(let[M,O]of Object.entries(X.configValues??{}).sort(([C],[F])=>C.localeCompare(F))){if(M===H.modelConfigId)continue;if(!H.configOptions.some((C)=>C.id===M))continue;H=await JX({conn:Y,sessionId:U.sessionId,configId:M,value:O,metadata:H,label:`${M}=${String(O)}`})}let P=H.models??[],L=H.currentModelId;return Y.cancel({sessionId:U.sessionId}).catch(()=>{return}),{models:P,configOptions:H.configOptions,currentModelId:L}})(),z=new Promise((D,N)=>{j=setTimeout(()=>{N(new u)},M3)});return await Promise.race([J,z])}catch(J){if(J instanceof Error&&J.message==="ACP connection closed"){if(X.signal?.aborted)throw new R("ACP model discovery cancelled: abort signal received");throw new R("Runtime process exited during model discovery.")}throw J}finally{if(j)clearTimeout(j);if(X.signal)X.signal.removeEventListener("abort",V);$.kill()}}import F3 from"node:fs/promises";import YX from"node:os";async function g$(X){let $={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await F3.readFile(X,"utf-8")}catch(W){if(W.code==="ENOENT")return structuredClone($);throw W}return c0.parse(JSON.parse(Z))}function X1(X,$,Z){return{...X.defaultConfigValues??{},...$?.configValues??{},...Z?.configValues??{}}}async function X0(X){let $=X.configPath?await g$(X.configPath):await m(),Z=X.cardId?$.cardOverrides[X.cardId]:void 0;if(Z?.runtimeConfigId){let Q=$.runtimes.find((K)=>K.id===Z.runtimeConfigId);if(Q)return{entry:Q,adapter:a(Q),runFolder:Z.runFolder??Q.runFolder??YX.homedir(),modelId:Z.modelId??Q.defaultModelId??null,configValues:X1(Q,void 0,Z)}}let W=$.boardOverrides[X.boardId];if(W?.runtimeConfigId){let Q=$.runtimes.find((K)=>K.id===W.runtimeConfigId);if(Q)return{entry:Q,adapter:a(Q),runFolder:W.runFolder??Q.runFolder??YX.homedir(),modelId:W.modelId??Q.defaultModelId??null,configValues:X1(Q,W)}}if($.globalDefaultConfigId){let Q=$.runtimes.find((K)=>K.id===$.globalDefaultConfigId);if(Q)return{entry:Q,adapter:a(Q),runFolder:Z?.runFolder??W?.runFolder??Q.runFolder??YX.homedir(),modelId:Z?.modelId??W?.modelId??Q.defaultModelId??null,configValues:X1(Q,W,Z)}}throw new J0}async function m$(X,$={}){let W=($.configPath?await g$($.configPath):await m()).runtimes.find((Q)=>Q.id===X);if(!W)return null;return{entry:W,adapter:a(W),runFolder:W.runFolder??YX.homedir(),modelId:$.modelId??W.defaultModelId??null,configValues:{...W.defaultConfigValues??{},...$.configValues??{}}}}var c$=new Map;function $1(X,$){if(!X)return;c$.set(X,$)}function l$(X){if(!X)return!1;return c$.get(X)??!1}var j0=new Map,Z1=new Set;function Q1(X){j0.get(X)?.controller.abort()}function p$(X){for(let[$,Z]of j0){if(Z.frontendSessionId!==X)continue;Z.controller.abort(),j0.delete($)}}function u$(){for(let X of j0.values())X.controller.abort();j0.clear()}function W1(X,$){if($?.aborted)return!0;return X instanceof Error&&/abort signal received|session cancelled/i.test(X.message)}function a$(X,$,Z,W){if((!$.availableModels||$.availableModels.length===0)&&$.availableConfigOptions.length===0)return;p((Q)=>{let K=Q.runtimes.find((Y)=>Y.id===X);if(K){if($.availableModels&&$.availableModels.length>0)K.discoveredModels=XX({adapterId:Z,models:$.availableModels,currentModelId:$.currentModelId??W});if($.availableConfigOptions.length>0)K.discoveredConfigOptions=$.availableConfigOptions}}).catch(()=>{return})}function L3(X,$){return`${X}
937
1031
 
938
1032
  Runtime run folder:
939
1033
  - Effective run folder: ${$}
940
1034
  - When the user says "my folder", "current folder", or "run folder", they mean this selected runtime folder.
941
1035
  - 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.
942
- - Filesystem access is read-only and limited to this folder. Hidden/config folders and outside-folder paths are unavailable.`}async function p$(X,$){let Z=Date.now(),Q=new AbortController;j0.set(X.runId,{controller:Q,frontendSessionId:X.frontendSessionId}),eX.add(X.cardId),q("cli.run_started",{runId:X.runId,cardId:X.cardId,frontendSessionId:X.frontendSessionId});let W=DX(X.userId,X.frontendSessionId,X.cardId),K=!1,Y=null;try{let z=(X.runtimeConfigIdHint?await I$(X.runtimeConfigIdHint,{modelId:X.modelHint??null}):null)??await X0({boardId:X.boardId,cardId:X.cardId}),J=await z.adapter.resolveSpawnConfig(z.entry),G=X.toolSurface??"full",M=z.adapter.supportsImages===!0;Y=J;let P=MX({userId:X.userId,frontendSessionId:X.frontendSessionId,boardId:X.boardId,toolSurface:G,imagesSupported:M,cardId:X.cardId,runFolder:z.runFolder}),x=P?[P]:[];sX(X.cardId,M);let U=X.modelHint??z.modelId,D=NX({adapterId:z.adapter.id,configId:z.entry.id,modelId:U,configValues:z.configValues,mcpUrl:P?.url??null,runFolder:z.runFolder,toolSurface:G});q("cli.session_acquire_started",{runId:X.runId,cardId:X.cardId,frontendSessionId:X.frontendSessionId});let w=await I0({key:W,frontendSessionId:X.frontendSessionId,fingerprint:D,open:()=>tX({spawn:{...J,cwd:z.runFolder},mcpServers:x,modelId:U,configValues:z.configValues,signal:Q.signal})});q("cli.session_acquired",{runId:X.runId,cardId:X.cardId,frontendSessionId:X.frontendSessionId,elapsedMs:Date.now()-Z}),l$(z.entry.id,w,z.adapter.id,U);let H;try{let B=0,N="";q("cli.prompt_started",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z}),H=await w.prompt({runId:X.runId,boardId:X.boardId,cardId:X.cardId,prompt:{systemPrompt:M3(X.systemPrompt,z.runFolder),messages:X.promptMessages.map((O)=>({role:O.role,content:O.content}))},signal:Q.signal,appendText:async({text:O})=>{if(B+=1,B===1)q("cli.first_partial_text_forwarded",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z,textLength:O.length});$({type:"partial_text",runId:X.runId,cardId:X.cardId,text:O})},appendToolActivity:async({entry:O})=>{let C=`${O.toolCallId}:${O.status}`;if(C!==N)N=C,q("cli.tool_activity_forwarded",{runId:X.runId,cardId:X.cardId,toolCallId:O.toolCallId,toolStatus:O.status,elapsedMs:Date.now()-Z});$({type:"tool_activity",runId:X.runId,cardId:X.cardId,activity:O})}})}catch(B){if(!w.isAlive()||B instanceof R||B instanceof u)K=!0;throw B}$({type:"run_settled",runId:X.runId,cardId:X.cardId,result:{assistantContent:H.finalText,model:H.modelReported??null,latencyMs:Date.now()-Z,errorText:null,partialText:null}}),q("cli.run_settled",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z,hasError:!1})}catch(V){let z=V instanceof Error?V.message:"Agent run failed";if(V instanceof R&&Y&&!X1(V,Q.signal))CX(Y,z);if(!X1(V,Q.signal))console.error(`[ideawave-cli] run ${X.runId} failed:`,z);$({type:"run_settled",runId:X.runId,cardId:X.cardId,result:{assistantContent:"",model:null,latencyMs:Date.now()-Z,errorText:z,partialText:null}}),q("cli.run_settled",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z,hasError:!0,errorName:V instanceof Error?V.name:"unknown"})}finally{wX(W,K),j0.delete(X.runId),eX.delete(X.cardId),q("cli.run_released",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z,sessionDead:K})}}async function u$(X){if(eX.has(X.cardId))return{status:"skipped"};let $=DX(X.userId,X.frontendSessionId,X.cardId),Z=null;try{let Q=await X0({boardId:X.boardId,cardId:X.cardId}),W=await Q.adapter.resolveSpawnConfig(Q.entry);Z=W;let K=MX({userId:X.userId,frontendSessionId:X.frontendSessionId,boardId:X.boardId,cardId:X.cardId,runFolder:Q.runFolder}),Y=K?[K]:[];sX(X.cardId,Q.adapter.supportsImages===!0);let V=NX({adapterId:Q.adapter.id,configId:Q.entry.id,modelId:Q.modelId,configValues:Q.configValues,mcpUrl:K?.url??null,runFolder:Q.runFolder}),z=new AbortController,J=await I0({key:$,frontendSessionId:X.frontendSessionId,fingerprint:V,open:()=>tX({spawn:{...W,cwd:Q.runFolder},mcpServers:Y,modelId:Q.modelId,configValues:Q.configValues,signal:z.signal})});return l$(Q.entry.id,J,Q.adapter.id,Q.modelId),wX($,!1),console.log(`[ideawave-cli] warmed runtime for card ${X.cardId}`),{status:"ready"}}catch(Q){if(Q instanceof Y0)return{status:"skipped"};let W=Q instanceof Error?Q.message:String(Q);if(Q instanceof R&&Z&&!X1(Q))CX(Z,W);if(Q instanceof R&&/(not ready|installing|warming|retry in a moment)/i.test(W))return{status:"retryable",error:W};return console.warn(`[ideawave-cli] warmup failed for card ${X.cardId}:`,W),{status:"failed",error:W}}}import{chromium as b3}from"playwright-core";import{spawn as L3}from"node:child_process";import{existsSync as C0,readFileSync as P3}from"node:fs";import{createRequire as a$}from"node:module";import YX from"node:os";import T from"node:path";var $0={phase:"checking"},N0=null,Z1=0,B3=60000,F3=["install","--only-shell","chromium"];class R0 extends Error{constructor(){super("The lightweight screenshot engine is being installed in the background. Live browsing remains available; retry the screenshot shortly.");this.name="CaptureEngineInstallingError"}}class d$ extends Error{constructor(X){super(X?`The screenshot engine could not be installed: ${X}`:"The screenshot engine is unavailable. Retry after checking network access and disk space.");this.name="CaptureEngineUnavailableError"}}function O3(X){return X.phase==="failed"?new d$(X.error):new R0}function M0(){return{...$0}}function k3(X){let $=X.exists??C0;for(let[Z,Q]of[[X.override,"explicit"],[X.managedShell,"headless-shell"],[X.system,"system-chromium"]])if(Z&&$(Z))return{path:Z,engine:Q};return null}function i$(X,$){let Z=[],Q=$.IDEAWAVE_CAPTURE_EXECUTABLE_PATH??$.IDEAWAVE_CHROMIUM_PATH;if(Q)Z.push(Q);if(X==="win32"){let W=$.ProgramFiles??"C:\\Program Files",K=$["ProgramFiles(x86)"]??"C:\\Program Files (x86)";if(Z.push(T.win32.join(W,"Google\\Chrome\\Application\\chrome.exe"),T.win32.join(K,"Google\\Chrome\\Application\\chrome.exe")),$.LOCALAPPDATA)Z.push(T.win32.join($.LOCALAPPDATA,"Google\\Chrome\\Application\\chrome.exe"));Z.push(T.win32.join(K,"Microsoft\\Edge\\Application\\msedge.exe"),T.win32.join(W,"Microsoft\\Edge\\Application\\msedge.exe"))}else if(X==="darwin")Z.push("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Chromium.app/Contents/MacOS/Chromium","google-chrome","chromium");else Z.push("google-chrome","google-chrome-stable","chromium","chromium-browser","msedge");return Z}function q3(X){let $=(process.env.PATH??"").split(T.delimiter),Z=process.platform==="win32"?[".exe",".cmd",".bat",""]:[""];for(let Q of $){if(!Q)continue;for(let W of Z){let K=T.join(Q,`${X}${W}`);if(C0(K))return K}}return null}function _3(){let X=new Set([process.env.IDEAWAVE_CAPTURE_EXECUTABLE_PATH,process.env.IDEAWAVE_CHROMIUM_PATH]);for(let $ of i$(process.platform,process.env)){if(X.has($))continue;if(T.isAbsolute($)){if(C0($))return $}else{let Z=q3($);if(Z)return Z}}return null}function A3(){try{let X=a$(import.meta.url);return T.dirname(X.resolve("playwright-core/package.json"))}catch{return null}}function C3(X){let $=process.env.PLAYWRIGHT_BROWSERS_PATH?.trim();if($==="0")return T.join(X,".local-browsers");if($)return $.startsWith("~")?T.join(YX.homedir(),$.slice(1)):T.resolve($);if(process.platform==="win32")return T.join(process.env.LOCALAPPDATA??T.join(YX.homedir(),"AppData","Local"),"ms-playwright");if(process.platform==="darwin")return T.join(YX.homedir(),"Library","Caches","ms-playwright");return T.join(YX.homedir(),".cache","ms-playwright")}function R3(){if(process.platform==="win32")return"win64";if(process.platform==="darwin")return process.arch==="arm64"?"mac-arm64":"mac-x64";return process.arch==="arm64"?"linux-arm64":"linux64"}function Q1(){let X=A3();if(!X)return null;try{let Z=JSON.parse(P3(T.join(X,"browsers.json"),"utf8")).browsers?.find((V)=>V.name==="chromium-headless-shell");if(!Z?.revision)return null;let Q=R3(),W=Z.revisionOverrides?.[Q]??Z.revision,K=T.join(C3(X),`chromium_headless_shell-${W}`),Y=process.platform==="win32"?["chrome-headless-shell-win64/chrome-headless-shell.exe","chrome-headless-shell-win32/chrome-headless-shell.exe"]:process.platform==="darwin"?[`chrome-headless-shell-${Q}/chrome-headless-shell`,"chrome-headless-shell-mac-x64/chrome-headless-shell","chrome-headless-shell-mac-arm64/chrome-headless-shell"]:[`chrome-headless-shell-${Q}/chrome-headless-shell`,"chrome-headless-shell-linux64/chrome-headless-shell"];for(let V of Y){let z=T.join(K,...V.split("/"));if(C0(z))return z}}catch{return null}return null}function f3(){let X=process.env.IDEAWAVE_CAPTURE_EXECUTABLE_PATH??process.env.IDEAWAVE_CHROMIUM_PATH;return X&&C0(X)?X:null}function o$(){return k3({override:f3(),managedShell:Q1(),system:_3()})}function y3(){let $=a$(import.meta.url).resolve("playwright-core/package.json"),Z=T.join(T.dirname($),"cli.js");return new Promise((Q,W)=>{let K=L3(process.execPath,[Z,...F3],{stdio:"ignore",windowsHide:!0});K.once("error",W),K.once("exit",(Y)=>{if(Y===0)Q();else W(Error(`Playwright headless-shell installer exited with code ${Y}`))})})}function W1(X){let $=Q1();if($)return $0={phase:"ready",engine:"headless-shell",executablePath:$},Promise.resolve(M0());if(N0)return N0;if(Z1>0&&Date.now()-Z1<B3)return Promise.resolve(M0());return $0=X?{phase:"ready",engine:X.engine,executablePath:X.path,installingManagedShell:!0}:{phase:"installing",installingManagedShell:!0},N0=(async()=>{try{await y3();let Z=Q1();if(!Z)throw Error("Headless Shell finished installing but its executable was not found");$0={phase:"ready",engine:"headless-shell",executablePath:Z}}catch(Z){Z1=Date.now(),$0=X?{phase:"ready",engine:X.engine,executablePath:X.path,error:Z instanceof Error?Z.message:String(Z)}:{phase:"failed",error:Z instanceof Error?Z.message:String(Z)}}finally{N0=null}return M0()})(),N0}function n$(){let X=o$();if(X?.engine==="explicit"||X?.engine==="headless-shell")return $0={phase:"ready",engine:X.engine,executablePath:X.path},Promise.resolve(M0());return W1(X)}async function t$(){let X=o$();if(X){if($0={phase:"ready",engine:X.engine,executablePath:X.path,...X.engine==="system-chromium"&&N0?{installingManagedShell:!0}:{}},X.engine==="system-chromium")W1(X);return X.path}throw W1(null),O3($0)}var E3=60000,T3=16,G0=null,JX=null,L0=null,K1=Promise.resolve(),VX=0,Y1=0,v3=0;class jX extends Error{constructor(){super("The capture queue is busy; retry shortly.");this.name="CaptureQueueFullError"}}function J1(){if(L0)clearTimeout(L0);L0=null}async function V1(){J1();let X=G0;if(G0=null,JX=null,X)await X.close().catch(()=>{return})}function h3(X=E3){J1(),L0=setTimeout(()=>{if(L0=null,Y1===0&&VX===0)V1()},X),L0.unref?.()}async function I3(){let X=await t$();if(G0?.isConnected()&&JX===X)return G0;await V1();let $=await b3.launch({headless:!0,executablePath:X,handleSIGHUP:!1,handleSIGINT:!1,handleSIGTERM:!1});return v3+=1,G0=$,JX=X,$.on("disconnected",()=>{if(G0===$)G0=null,JX=null}),$}function r$(X,$){if(VX>=T3)return Promise.reject(new jX);VX+=1;let Z,Q,W=new Promise((K,Y)=>{Z=K,Q=Y});return K1=K1.then(async()=>{VX-=1,Y1+=1,J1();let K=null,Y;try{K=await(await I3()).newContext(X.context);let z=await K.newPage();Y={ok:!0,value:await $(z)}}catch(V){Y={ok:!1,error:V}}finally{if(K)await K.close().catch(()=>{return});Y1-=1,h3()}if(Y.ok)Z(Y.value);else Q(Y.error)}),W}async function s$(){await K1.catch(()=>{return}),await V1()}import{randomUUID as i3}from"node:crypto";import{createServer as o3}from"node:http";import{WebSocket as V2,WebSocketServer as n3}from"ws";var j1="/cli-bridge",e$="/ping";function G1(X=43275,$=43277){let Z=[];for(let Q=X;Q<=$;Q+=1)Z.push(Q);return Z}function X2(X=G1(),$="127.0.0.1",Z="/cli-bridge"){return X.map((Q)=>`ws://${$}:${Q}${Z}`)}var S3=800;function $2({candidates:X,createWebSocket:$,timeoutMs:Z=S3,maxConcurrent:Q=1,staggerMs:W=0,setTimeoutFn:K=setTimeout,clearTimeoutFn:Y=clearTimeout}){return new Promise((V,z)=>{let J=0,G=!1,M=null,P=new Map,x=Math.max(1,Math.floor(Q)),U=()=>{if(M===null)return;Y(M),M=null},D=(L)=>{let{socket:j,listeners:k,timer:_}=L;j.removeEventListener("open",k.open),j.removeEventListener("message",k.message),j.removeEventListener("error",k.error),j.removeEventListener("close",k.close),Y(_),P.delete(j)},w=(L)=>{U();for(let j of Array.from(P.values()))if(D(j),j.socket!==L)try{j.socket.close()}catch{}},H=()=>{if(G)return;if(J<X.length)return;if(P.size>0)return;if(M!==null)return;G=!0,z(Error("No IdeaWave CLI bridge is reachable"))},B=(L)=>{if(G)return;if(J>=X.length){H();return}if(P.size>=x)return;if(L<=0){U(),C();return}if(M!==null)return;M=K(()=>{M=null,C()},L)},N=()=>{if(G)return;if(P.size>=x)return;if(P.size===0||W<=0||x===1){B(0);return}B(W)},O=(L)=>{if(G)return;let j=P.get(L);if(!j)return;D(j);try{L.close()}catch{}N(),H()};function C(){if(G)return;if(P.size>=x)return;let L=X[J];if(J+=1,!L){H();return}let j;try{j=$(L)}catch{N(),H();return}let k={open:()=>{if(G||!P.has(j))return;j.send(m0({type:"bridge_probe",protocolVersion:1}))},message:(b)=>{if(G||!P.has(j))return;if(g0(String(b?.data??""))?.type!=="bridge_probe_ack")return;G=!0,w(j),V({url:L,socket:j})},error:()=>O(j),close:()=>O(j)};j.addEventListener("open",k.open),j.addEventListener("message",k.message),j.addEventListener("error",k.error),j.addEventListener("close",k.close);let _=K(()=>O(j),Z);P.set(j,{url:L,socket:j,listeners:k,timer:_}),N()}C()})}import{randomBytes as g3}from"node:crypto";import{mkdir as m3,writeFile as c3}from"node:fs/promises";import l3 from"node:os";import Z2 from"node:path";var p3=30000,u3=1024;function Q2(X){let $;try{$=new URL(X)}catch{return!1}if($.protocol!=="http:"&&$.protocol!=="https:")return!1;let Z=$.hostname.toLowerCase().replace(/^\[|\]$/g,"");if(Z==="localhost"||Z==="127.0.0.1"||Z==="::1")return!0;let W=Z==="ideawave.app"||Z.endsWith(".ideawave.app");return $.protocol==="https:"&&W&&$.pathname.startsWith("/static_boards/")}async function a3(X,$){let Z=Z2.join(l3.tmpdir(),"ideawave-screenshots");await m3(Z,{recursive:!0});let Q=Z2.join(Z,`board-${Date.now()}-${g3(4).toString("hex")}.png`);return await c3(Q,X),{path:Q,engine:$}}async function W2(X){let $=X.timeoutMs??p3;return r$({context:{viewport:{width:X.width,height:X.height},deviceScaleFactor:1}},async(Z)=>{Z.setDefaultTimeout($),Z.setDefaultNavigationTimeout($);let Q=await Z.goto(X.url,{waitUntil:"networkidle",timeout:$});if(!Q?.ok())throw Error(`Static board responded with HTTP ${Q?.status()??"unknown"}; request a fresh one-time token before retrying`);await Z.locator('[data-ideawave-static-board-ready="true"]').waitFor({state:"attached",timeout:$}),await Z.evaluate(async()=>{if(document.fonts?.ready)await document.fonts.ready});let W=await Z.screenshot({type:"png",animations:"disabled",caret:"hide",scale:"css"});if(W.byteLength<u3)throw Error("Headless Shell returned an empty screenshot");return a3(Buffer.from(W),M0().engine??"system-chromium")})}var f0="IDEAWAVE_CLI_ALLOW_RAILWAY_PR_PREVIEWS";function d3(X){return X==="1"||X?.toLowerCase()==="true"}function K2(X,$){let Q=X.includes("--dev")||d3($.IDEAWAVE_CLI_ALLOW_RAILWAY_PR_PREVIEWS),W=$.APP_ENV==="development"||Q;return{cliArgs:X.filter((K)=>K!=="--dev"),browserKitEnabled:!0,captureEngineEnabled:!W,allowRailwayPrPreviews:Q}}var t3=0,r3=30000,s3=15000,e3="/screenshot",XZ=65536,j2="http://127.0.0.1";async function G2(X=X2(),$=(Z)=>new V2(Z,{headers:{origin:j2}})){try{let{url:Z,socket:Q}=await $2({candidates:X,createWebSocket:$});try{Q.close()}catch{}return Z}catch{return null}}var $Z=new Set(["https://ideawave-app-production.up.railway.app"]);function ZZ(X){return X==="ideawave.app"||X.endsWith(".ideawave.app")}function QZ(X){return X==="1"||X?.toLowerCase()==="true"}function WZ(X){return/^ideawave-app-ideawave-app-pr-\d+\.up\.railway\.app$/i.test(X)}function KZ(){let X=process.env.IDEAWAVE_CLI_ALLOWED_ORIGINS;if(!X)return YZ;let $=new Set;for(let Z of X.split(",")){let Q=Z.trim();if(!Q)continue;try{$.add(new URL(Q).origin)}catch{}}return $}var YZ=new Set;function z1(X){if(!X)return!1;let $;try{$=new URL(X)}catch{return!1}if($Z.has($.origin))return!0;if(KZ().has($.origin))return!0;if($.protocol==="https:"&&QZ(process.env[f0])&&WZ($.hostname))return!0;if($.protocol==="https:"&&ZZ($.hostname))return!0;if($.protocol!=="http:"&&$.protocol!=="https:")return!1;return $.hostname==="localhost"||$.hostname==="127.0.0.1"||$.hostname==="::1"}function P0(X,$){if(X.readyState!==V2.OPEN)return;try{X.send(m0($))}catch{}}function JZ(X){if(typeof X==="string")return X;if(Buffer.isBuffer(X))return X.toString("utf8");if(Array.isArray(X))return Buffer.concat(X).toString("utf8");return Buffer.from(X).toString("utf8")}function GX(X){if(typeof X==="string")return X;if(Array.isArray(X))return X[0]??null;return null}function Y2(X,$,Z){X.write(`HTTP/1.1 ${$} ${Z}\r
1036
+ - Filesystem access is read-only and limited to this folder. Hidden/config folders and outside-folder paths are unavailable.`}async function d$(X,$){let Z=Date.now(),W=new AbortController;j0.set(X.runId,{controller:W,frontendSessionId:X.frontendSessionId}),Z1.add(X.cardId),_("cli.run_started",{runId:X.runId,cardId:X.cardId,frontendSessionId:X.frontendSessionId});let Q=xX(X.userId,X.frontendSessionId,X.cardId),K=!1,Y=null;try{let j=(X.runtimeConfigIdHint?await m$(X.runtimeConfigIdHint,{modelId:X.modelHint??null}):null)??await X0({boardId:X.boardId,cardId:X.cardId}),J=await j.adapter.resolveSpawnConfig(j.entry),z=X.toolSurface??"full",D=j.adapter.supportsImages===!0;Y=J;let N=FX({userId:X.userId,frontendSessionId:X.frontendSessionId,boardId:X.boardId,toolSurface:z,imagesSupported:D,cardId:X.cardId,runFolder:j.runFolder}),U=N?[N]:[];$1(X.cardId,D);let H=X.modelHint??j.modelId,x=MX({adapterId:j.adapter.id,configId:j.entry.id,modelId:H,configValues:j.configValues,mcpUrl:N?.url??null,runFolder:j.runFolder,toolSurface:z});_("cli.session_acquire_started",{runId:X.runId,cardId:X.cardId,frontendSessionId:X.frontendSessionId});let w=await I0({key:Q,frontendSessionId:X.frontendSessionId,fingerprint:x,open:()=>eX({spawn:{...J,cwd:j.runFolder},mcpServers:U,modelId:H,configValues:j.configValues,signal:W.signal})});_("cli.session_acquired",{runId:X.runId,cardId:X.cardId,frontendSessionId:X.frontendSessionId,elapsedMs:Date.now()-Z}),a$(j.entry.id,w,j.adapter.id,H);let P;try{let L=0,M="";_("cli.prompt_started",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z}),P=await w.prompt({runId:X.runId,boardId:X.boardId,cardId:X.cardId,prompt:{systemPrompt:L3(X.systemPrompt,j.runFolder),messages:X.promptMessages.map((O)=>({role:O.role,content:O.content}))},signal:W.signal,appendText:async({text:O})=>{if(L+=1,L===1)_("cli.first_partial_text_forwarded",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z,textLength:O.length});$({type:"partial_text",runId:X.runId,cardId:X.cardId,text:O})},appendToolActivity:async({entry:O})=>{let C=`${O.toolCallId}:${O.status}`;if(C!==M)M=C,_("cli.tool_activity_forwarded",{runId:X.runId,cardId:X.cardId,toolCallId:O.toolCallId,toolStatus:O.status,elapsedMs:Date.now()-Z});$({type:"tool_activity",runId:X.runId,cardId:X.cardId,activity:O})}})}catch(L){if(!w.isAlive()||L instanceof R||L instanceof u)K=!0;throw L}$({type:"run_settled",runId:X.runId,cardId:X.cardId,result:{assistantContent:P.finalText,model:P.modelReported??null,latencyMs:Date.now()-Z,errorText:null,partialText:null}}),_("cli.run_settled",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z,hasError:!1})}catch(V){let j=V instanceof Error?V.message:"Agent run failed";if(V instanceof R&&Y&&!W1(V,W.signal))yX(Y,j);if(!W1(V,W.signal))console.error(`[ideawave-cli] run ${X.runId} failed:`,j);$({type:"run_settled",runId:X.runId,cardId:X.cardId,result:{assistantContent:"",model:null,latencyMs:Date.now()-Z,errorText:j,partialText:null}}),_("cli.run_settled",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z,hasError:!0,errorName:V instanceof Error?V.name:"unknown"})}finally{wX(Q,K),j0.delete(X.runId),Z1.delete(X.cardId),_("cli.run_released",{runId:X.runId,cardId:X.cardId,elapsedMs:Date.now()-Z,sessionDead:K})}}async function i$(X){if(Z1.has(X.cardId))return{status:"skipped"};let $=xX(X.userId,X.frontendSessionId,X.cardId),Z=null;try{let W=await X0({boardId:X.boardId,cardId:X.cardId}),Q=await W.adapter.resolveSpawnConfig(W.entry);Z=Q;let K=FX({userId:X.userId,frontendSessionId:X.frontendSessionId,boardId:X.boardId,cardId:X.cardId,runFolder:W.runFolder}),Y=K?[K]:[];$1(X.cardId,W.adapter.supportsImages===!0);let V=MX({adapterId:W.adapter.id,configId:W.entry.id,modelId:W.modelId,configValues:W.configValues,mcpUrl:K?.url??null,runFolder:W.runFolder}),j=new AbortController,J=await I0({key:$,frontendSessionId:X.frontendSessionId,fingerprint:V,open:()=>eX({spawn:{...Q,cwd:W.runFolder},mcpServers:Y,modelId:W.modelId,configValues:W.configValues,signal:j.signal})});return a$(W.entry.id,J,W.adapter.id,W.modelId),wX($,!1),console.log(`[ideawave-cli] warmed runtime for card ${X.cardId}`),{status:"ready"}}catch(W){if(W instanceof J0)return{status:"skipped"};let Q=W instanceof Error?W.message:String(W);if(W instanceof R&&Z&&!W1(W))yX(Z,Q);if(W instanceof R&&/(not ready|installing|warming|retry in a moment)/i.test(Q))return{status:"retryable",error:Q};return console.warn(`[ideawave-cli] warmup failed for card ${X.cardId}:`,Q),{status:"failed",error:Q}}}import{chromium as v3}from"playwright-core";import{spawn as B3}from"node:child_process";import{existsSync as C0,readFileSync as O3}from"node:fs";import{createRequire as o$}from"node:module";import VX from"node:os";import f from"node:path";var $0={phase:"checking"},x0=null,K1=0,k3=60000,_3=["install","--only-shell","chromium"];class R0 extends Error{constructor(){super("The lightweight screenshot engine is being installed in the background. Live browsing remains available; retry the screenshot shortly.");this.name="CaptureEngineInstallingError"}}class n$ extends Error{constructor(X){super(X?`The screenshot engine could not be installed: ${X}`:"The screenshot engine is unavailable. Retry after checking network access and disk space.");this.name="CaptureEngineUnavailableError"}}function A3(X){return X.phase==="failed"?new n$(X.error):new R0}function w0(){return{...$0}}function q3(X){let $=X.exists??C0;for(let[Z,W]of[[X.override,"explicit"],[X.managedShell,"headless-shell"],[X.system,"system-chromium"]])if(Z&&$(Z))return{path:Z,engine:W};return null}function t$(X,$){let Z=[],W=$.IDEAWAVE_CAPTURE_EXECUTABLE_PATH??$.IDEAWAVE_CHROMIUM_PATH;if(W)Z.push(W);if(X==="win32"){let Q=$.ProgramFiles??"C:\\Program Files",K=$["ProgramFiles(x86)"]??"C:\\Program Files (x86)";if(Z.push(f.win32.join(Q,"Google\\Chrome\\Application\\chrome.exe"),f.win32.join(K,"Google\\Chrome\\Application\\chrome.exe")),$.LOCALAPPDATA)Z.push(f.win32.join($.LOCALAPPDATA,"Google\\Chrome\\Application\\chrome.exe"));Z.push(f.win32.join(K,"Microsoft\\Edge\\Application\\msedge.exe"),f.win32.join(Q,"Microsoft\\Edge\\Application\\msedge.exe"))}else if(X==="darwin")Z.push("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Chromium.app/Contents/MacOS/Chromium","google-chrome","chromium");else Z.push("google-chrome","google-chrome-stable","chromium","chromium-browser","msedge");return Z}function C3(X){let $=(process.env.PATH??"").split(f.delimiter),Z=process.platform==="win32"?[".exe",".cmd",".bat",""]:[""];for(let W of $){if(!W)continue;for(let Q of Z){let K=f.join(W,`${X}${Q}`);if(C0(K))return K}}return null}function R3(){let X=new Set([process.env.IDEAWAVE_CAPTURE_EXECUTABLE_PATH,process.env.IDEAWAVE_CHROMIUM_PATH]);for(let $ of t$(process.platform,process.env)){if(X.has($))continue;if(f.isAbsolute($)){if(C0($))return $}else{let Z=C3($);if(Z)return Z}}return null}function y3(){try{let X=o$(import.meta.url);return f.dirname(X.resolve("playwright-core/package.json"))}catch{return null}}function E3(X){let $=process.env.PLAYWRIGHT_BROWSERS_PATH?.trim();if($==="0")return f.join(X,".local-browsers");if($)return $.startsWith("~")?f.join(VX.homedir(),$.slice(1)):f.resolve($);if(process.platform==="win32")return f.join(process.env.LOCALAPPDATA??f.join(VX.homedir(),"AppData","Local"),"ms-playwright");if(process.platform==="darwin")return f.join(VX.homedir(),"Library","Caches","ms-playwright");return f.join(VX.homedir(),".cache","ms-playwright")}function b3(){if(process.platform==="win32")return"win64";if(process.platform==="darwin")return process.arch==="arm64"?"mac-arm64":"mac-x64";return process.arch==="arm64"?"linux-arm64":"linux64"}function J1(){let X=y3();if(!X)return null;try{let Z=JSON.parse(O3(f.join(X,"browsers.json"),"utf8")).browsers?.find((V)=>V.name==="chromium-headless-shell");if(!Z?.revision)return null;let W=b3(),Q=Z.revisionOverrides?.[W]??Z.revision,K=f.join(E3(X),`chromium_headless_shell-${Q}`),Y=process.platform==="win32"?["chrome-headless-shell-win64/chrome-headless-shell.exe","chrome-headless-shell-win32/chrome-headless-shell.exe"]:process.platform==="darwin"?[`chrome-headless-shell-${W}/chrome-headless-shell`,"chrome-headless-shell-mac-x64/chrome-headless-shell","chrome-headless-shell-mac-arm64/chrome-headless-shell"]:[`chrome-headless-shell-${W}/chrome-headless-shell`,"chrome-headless-shell-linux64/chrome-headless-shell"];for(let V of Y){let j=f.join(K,...V.split("/"));if(C0(j))return j}}catch{return null}return null}function T3(){let X=process.env.IDEAWAVE_CAPTURE_EXECUTABLE_PATH??process.env.IDEAWAVE_CHROMIUM_PATH;return X&&C0(X)?X:null}function r$(){return q3({override:T3(),managedShell:J1(),system:R3()})}function f3(){let $=o$(import.meta.url).resolve("playwright-core/package.json"),Z=f.join(f.dirname($),"cli.js");return new Promise((W,Q)=>{let K=B3(process.execPath,[Z,..._3],{stdio:"ignore",windowsHide:!0});K.once("error",Q),K.once("exit",(Y)=>{if(Y===0)W();else Q(Error(`Playwright headless-shell installer exited with code ${Y}`))})})}function Y1(X){let $=J1();if($)return $0={phase:"ready",engine:"headless-shell",executablePath:$},Promise.resolve(w0());if(x0)return x0;if(K1>0&&Date.now()-K1<k3)return Promise.resolve(w0());return $0=X?{phase:"ready",engine:X.engine,executablePath:X.path,installingManagedShell:!0}:{phase:"installing",installingManagedShell:!0},x0=(async()=>{try{await f3();let Z=J1();if(!Z)throw Error("Headless Shell finished installing but its executable was not found");$0={phase:"ready",engine:"headless-shell",executablePath:Z}}catch(Z){K1=Date.now(),$0=X?{phase:"ready",engine:X.engine,executablePath:X.path,error:Z instanceof Error?Z.message:String(Z)}:{phase:"failed",error:Z instanceof Error?Z.message:String(Z)}}finally{x0=null}return w0()})(),x0}function s$(){let X=r$();if(X?.engine==="explicit"||X?.engine==="headless-shell")return $0={phase:"ready",engine:X.engine,executablePath:X.path},Promise.resolve(w0());return Y1(X)}async function e$(){let X=r$();if(X){if($0={phase:"ready",engine:X.engine,executablePath:X.path,...X.engine==="system-chromium"&&x0?{installingManagedShell:!0}:{}},X.engine==="system-chromium")Y1(X);return X.path}throw Y1(null),A3($0)}var h3=60000,I3=16,G0=null,jX=null,M0=null,V1=Promise.resolve(),GX=0,j1=0,S3=0;class zX extends Error{constructor(){super("The capture queue is busy; retry shortly.");this.name="CaptureQueueFullError"}}function G1(){if(M0)clearTimeout(M0);M0=null}async function z1(){G1();let X=G0;if(G0=null,jX=null,X)await X.close().catch(()=>{return})}function g3(X=h3){G1(),M0=setTimeout(()=>{if(M0=null,j1===0&&GX===0)z1()},X),M0.unref?.()}async function m3(){let X=await e$();if(G0?.isConnected()&&jX===X)return G0;await z1();let $=await v3.launch({headless:!0,executablePath:X,handleSIGHUP:!1,handleSIGINT:!1,handleSIGTERM:!1});return S3+=1,G0=$,jX=X,$.on("disconnected",()=>{if(G0===$)G0=null,jX=null}),$}function X2(X,$){if(GX>=I3)return Promise.reject(new zX);GX+=1;let Z,W,Q=new Promise((K,Y)=>{Z=K,W=Y});return V1=V1.then(async()=>{GX-=1,j1+=1,G1();let K=null,Y;try{K=await(await m3()).newContext(X.context);let j=await K.newPage();Y={ok:!0,value:await $(j)}}catch(V){Y={ok:!1,error:V}}finally{if(K)await K.close().catch(()=>{return});j1-=1,g3()}if(Y.ok)Z(Y.value);else W(Y.error)}),Q}async function $2(){await V1.catch(()=>{return}),await z1()}import{randomUUID as t3}from"node:crypto";import{createServer as r3}from"node:http";import{WebSocket as z2,WebSocketServer as s3}from"ws";var H1="/cli-bridge",Z2="/ping";function U1(X=43275,$=43277){let Z=[];for(let W=X;W<=$;W+=1)Z.push(W);return Z}function W2(X=U1(),$="127.0.0.1",Z="/cli-bridge"){return X.map((W)=>`ws://${$}:${W}${Z}`)}var c3=800;function Q2({candidates:X,createWebSocket:$,timeoutMs:Z=c3,maxConcurrent:W=1,staggerMs:Q=0,setTimeoutFn:K=setTimeout,clearTimeoutFn:Y=clearTimeout}){return new Promise((V,j)=>{let J=0,z=!1,D=null,N=new Map,U=Math.max(1,Math.floor(W)),H=()=>{if(D===null)return;Y(D),D=null},x=(F)=>{let{socket:G,listeners:k,timer:A}=F;G.removeEventListener("open",k.open),G.removeEventListener("message",k.message),G.removeEventListener("error",k.error),G.removeEventListener("close",k.close),Y(A),N.delete(G)},w=(F)=>{H();for(let G of Array.from(N.values()))if(x(G),G.socket!==F)try{G.socket.close()}catch{}},P=()=>{if(z)return;if(J<X.length)return;if(N.size>0)return;if(D!==null)return;z=!0,j(Error("No IdeaWave CLI bridge is reachable"))},L=(F)=>{if(z)return;if(J>=X.length){P();return}if(N.size>=U)return;if(F<=0){H(),C();return}if(D!==null)return;D=K(()=>{D=null,C()},F)},M=()=>{if(z)return;if(N.size>=U)return;if(N.size===0||Q<=0||U===1){L(0);return}L(Q)},O=(F)=>{if(z)return;let G=N.get(F);if(!G)return;x(G);try{F.close()}catch{}M(),P()};function C(){if(z)return;if(N.size>=U)return;let F=X[J];if(J+=1,!F){P();return}let G;try{G=$(F)}catch{M(),P();return}let k={open:()=>{if(z||!N.has(G))return;G.send(m0({type:"bridge_probe",protocolVersion:1}))},message:(b)=>{if(z||!N.has(G))return;if(g0(String(b?.data??""))?.type!=="bridge_probe_ack")return;z=!0,w(G),V({url:F,socket:G})},error:()=>O(G),close:()=>O(G)};G.addEventListener("open",k.open),G.addEventListener("message",k.message),G.addEventListener("error",k.error),G.addEventListener("close",k.close);let A=K(()=>O(G),Z);N.set(G,{url:F,socket:G,listeners:k,timer:A}),M()}C()})}import{randomBytes as l3}from"node:crypto";import{mkdir as p3,writeFile as u3}from"node:fs/promises";import a3 from"node:os";import K2 from"node:path";var d3=30000,i3=1024;function J2(X){let $;try{$=new URL(X)}catch{return!1}if($.protocol!=="http:"&&$.protocol!=="https:")return!1;let Z=$.hostname.toLowerCase().replace(/^\[|\]$/g,"");if(Z==="localhost"||Z==="127.0.0.1"||Z==="::1")return!0;let Q=Z==="ideawave.app"||Z.endsWith(".ideawave.app");return $.protocol==="https:"&&Q&&$.pathname.startsWith("/static_boards/")}async function o3(X,$){let Z=K2.join(a3.tmpdir(),"ideawave-screenshots");await p3(Z,{recursive:!0});let W=K2.join(Z,`board-${Date.now()}-${l3(4).toString("hex")}.png`);return await u3(W,X),{path:W,engine:$}}async function Y2(X){let $=X.timeoutMs??d3;return X2({context:{viewport:{width:X.width,height:X.height},deviceScaleFactor:1}},async(Z)=>{Z.setDefaultTimeout($),Z.setDefaultNavigationTimeout($);let W=await Z.goto(X.url,{waitUntil:"networkidle",timeout:$});if(!W?.ok())throw Error(`Static board responded with HTTP ${W?.status()??"unknown"}; request a fresh one-time token before retrying`);await Z.locator('[data-ideawave-static-board-ready="true"]').waitFor({state:"attached",timeout:$}),await Z.evaluate(async()=>{if(document.fonts?.ready)await document.fonts.ready});let Q=await Z.screenshot({type:"png",animations:"disabled",caret:"hide",scale:"css"});if(Q.byteLength<i3)throw Error("Headless Shell returned an empty screenshot");return o3(Buffer.from(Q),w0().engine??"system-chromium")})}var y0="IDEAWAVE_CLI_ALLOW_RAILWAY_PR_PREVIEWS";function n3(X){return X==="1"||X?.toLowerCase()==="true"}function V2(X,$){let W=X.includes("--dev")||n3($.IDEAWAVE_CLI_ALLOW_RAILWAY_PR_PREVIEWS),Q=$.APP_ENV==="development"||W;return{cliArgs:X.filter((K)=>K!=="--dev"),browserKitEnabled:!0,captureEngineEnabled:!Q,allowRailwayPrPreviews:W}}var e3=0,XZ=30000,$Z=15000,ZZ="/screenshot",WZ=65536,H2="http://127.0.0.1";async function U2(X=W2(),$=(Z)=>new z2(Z,{headers:{origin:H2}})){try{let{url:Z,socket:W}=await Q2({candidates:X,createWebSocket:$});try{W.close()}catch{}return Z}catch{return null}}var QZ=new Set(["https://ideawave-app-production.up.railway.app"]);function KZ(X){return X==="ideawave.app"||X.endsWith(".ideawave.app")}function JZ(X){return X==="1"||X?.toLowerCase()==="true"}function YZ(X){return/^ideawave-app-ideawave-app-pr-\d+\.up\.railway\.app$/i.test(X)}function VZ(){let X=process.env.IDEAWAVE_CLI_ALLOWED_ORIGINS;if(!X)return jZ;let $=new Set;for(let Z of X.split(",")){let W=Z.trim();if(!W)continue;try{$.add(new URL(W).origin)}catch{}}return $}var jZ=new Set;function D1(X){if(!X)return!1;let $;try{$=new URL(X)}catch{return!1}if(QZ.has($.origin))return!0;if(VZ().has($.origin))return!0;if($.protocol==="https:"&&JZ(process.env[y0])&&YZ($.hostname))return!0;if($.protocol==="https:"&&KZ($.hostname))return!0;if($.protocol!=="http:"&&$.protocol!=="https:")return!1;return $.hostname==="localhost"||$.hostname==="127.0.0.1"||$.hostname==="::1"}function F0(X,$){if(X.readyState!==z2.OPEN)return;try{X.send(m0($))}catch{}}function GZ(X){if(typeof X==="string")return X;if(Buffer.isBuffer(X))return X.toString("utf8");if(Array.isArray(X))return Buffer.concat(X).toString("utf8");return Buffer.from(X).toString("utf8")}function HX(X){if(typeof X==="string")return X;if(Array.isArray(X))return X[0]??null;return null}function j2(X,$,Z){X.write(`HTTP/1.1 ${$} ${Z}\r
943
1037
  Connection: close\r
944
1038
  Content-Length: ${Buffer.byteLength(Z)}\r
945
1039
  \r
946
- ${Z}`),X.destroy()}function VZ(X,$){return new Promise((Z,Q)=>{let W=(Y)=>{X.off("listening",K),Q(Y)},K=()=>{X.off("error",W);let Y=X.address();if(!Y||typeof Y==="string"){Q(Error("Failed to read CLI bridge server address"));return}Z(Y.port)};X.once("error",W),X.once("listening",K),X.listen($,"127.0.0.1")})}function J2(X){return new Promise(($,Z)=>{X.close((Q)=>{if(Q)Z(Q);else $()})})}async function z2(X,$=G1()){let Z=new Map,Q=new Map,W=X.maxMessageSize??t3,K=!1,Y=(x)=>{let U=Q.get(x);if(U)clearTimeout(U);Q.delete(x)},V=(x)=>{Q.delete(x);let{activeRunIds:U}=X.registry.disconnect(x);X.onDisconnect(x,U)},z=(x,U)=>{let D={type:"cli_status",connected:!0,runtime:X.runtime,mcpReady:X.mcpReady(),error:U,capabilities:X.capabilities??[],cliVersion:X.cliVersion,browserRuntime:X.browserRuntimeStatus?.()};if(x){let w=Z.get(x);if(w)P0(w,D);return}for(let w of Z.values())P0(w,D)},J=(x,U)=>{let D=U.sessionId.trim(),w=U.userId.trim();if(!D||!w){P0(x,{type:"cli_status",connected:!1,runtime:X.runtime,mcpReady:X.mcpReady(),error:"Missing frontend session or user id"}),x.close();return}Y(D);let H=Z.get(D);if(H&&H!==x)H.close();x.data.frontendSessionId=D,Z.set(D,x),X.registry.register({frontendSessionId:D,userId:w,tools:U.tools,send:(B)=>P0(x,B)}),z(D),X.onToolMetadata?.(D)},G=(x,U)=>{let D=X.registry.getUserId(x);if(!D)return;switch(U.type){case"bridge_ping":{let w=Z.get(x);if(w)P0(w,{type:"bridge_pong"});break}case"tool_metadata":X.registry.setMetadata(x,U.tools),X.onToolMetadata?.(x);break;case"tool_result":X.registry.handleToolResult(x,U);break;case"run_turn":q("bridge.run_received",{runId:U.run.runId,cardId:U.run.cardId,frontendSessionId:x}),X.registry.markRunActive(x,U.run.runId,U.run.cardId),X.onRunTurn(x,{...U.run,frontendSessionId:x,userId:D});break;case"cancel_run":if(X.registry.ownsRun(x,U.runId))X.onCancelRun(x,U.runId);break;case"runtime_rpc":X.onRuntimeRpc(x,U);break;case"browser_rpc":X.onBrowserRpc?.(x,Z.get(x)?.data.frontendOrigin??"",U);break;case"warmup_run":X.onWarmupRun(x,{...U,frontendSessionId:x},D);break;default:break}},M=(x,U)=>{let D=GX(x.headers.origin),w=z1(D),H={Vary:"Origin"};if(w&&D)H["Access-Control-Allow-Origin"]=D,H["Access-Control-Allow-Private-Network"]="true";if(x.method==="OPTIONS"){U.writeHead(204,{...H,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),U.end();return}if(x.method!=="GET"){U.writeHead(405,H),U.end();return}U.writeHead(200,{...H,"content-type":"application/json","cache-control":"no-store"}),U.end(JSON.stringify({ideawave:!0,runtime:X.runtime,mcpReady:X.mcpReady(),capabilities:X.capabilities??[],cliVersion:X.cliVersion,browserRuntime:X.browserRuntimeStatus?.()}))},P=(x,U)=>{let D=GX(x.headers.origin),w=z1(D),H={Vary:"Origin"};if(w&&D)H["Access-Control-Allow-Origin"]=D,H["Access-Control-Allow-Private-Network"]="true";if(x.method==="OPTIONS"){U.writeHead(204,{...H,"Access-Control-Allow-Methods":"POST, OPTIONS","Access-Control-Allow-Headers":"content-type","Access-Control-Max-Age":"600"}),U.end();return}if(!w){U.writeHead(403,H),U.end();return}if(x.method!=="POST"){U.writeHead(405,H),U.end();return}let B={...H,"content-type":"application/json"},N=(L,j)=>{U.writeHead(L,B),U.end(JSON.stringify(j))},O="",C=!1;x.on("data",(L)=>{if(O+=L.toString("utf8"),O.length>XZ)C=!0,x.destroy()}),x.on("end",()=>{if(C){N(400,{ok:!1,error:"Request body too large"});return}let L;try{L=JSON.parse(O)}catch{N(400,{ok:!1,error:"Invalid JSON body"});return}let j=typeof L.url==="string"?L.url:"";if(!Q2(j)){N(400,{ok:!1,error:"url must be an http(s) loopback or /static_boards/ page URL"});return}let k=(_,b)=>{let d=typeof _==="number"?_:Number.NaN;if(!Number.isFinite(d))return b;return Math.min(4000,Math.max(200,Math.round(d)))};W2({url:j,width:k(L.width,1440),height:k(L.height,900)}).then((_)=>N(200,{ok:!0,path:_.path,engine:_.engine})).catch((_)=>{let b=_ instanceof R0?503:_ instanceof jX?429:500;N(b,{ok:!1,..._ instanceof R0?{installing:!0}:{},error:_ instanceof Error?_.message:String(_)})})})};for(let x of $){let U=o3((H,B)=>{(async()=>{let N=new URL(H.url??"/","http://127.0.0.1").pathname;if(N===e$){M(H,B);return}if(N===e3){P(H,B);return}if(await X.onHttpRequest?.(H,B))return;B.writeHead(404,{"content-type":"text/plain"}),B.end("IdeaWave CLI bridge")})().catch((N)=>{if(B.headersSent){B.destroy(N instanceof Error?N:void 0);return}B.writeHead(500,{"content-type":"text/plain"}),B.end("IdeaWave CLI bridge request failed")})}),D=new n3({noServer:!0,maxPayload:W}),w=(H)=>{if(H.idleTimer)clearTimeout(H.idleTimer);H.idleTimer=setTimeout(()=>{H.close()},r3),H.idleTimer.unref?.()};D.on("connection",(H,B)=>{let N=H;N.data={id:i3(),frontendSessionId:null,frontendOrigin:new URL(GX(B.headers.origin)??j2).origin},N.idleTimer=null,w(N),N.on("ping",()=>w(N)),N.on("pong",()=>w(N)),N.on("error",()=>{if(N.idleTimer)clearTimeout(N.idleTimer);N.close()}),N.on("message",(O)=>{w(N);let C=JZ(O);if(W>0&&C.length>W)return;let L=g0(C);if(!L)return;let j=N.data.frontendSessionId;if(!j){if(L.type==="bridge_probe")P0(N,{type:"bridge_probe_ack",protocolVersion:L.protocolVersion});else if(L.type==="frontend_hello")J(N,L);return}G(j,L)}),N.on("close",()=>{if(N.idleTimer)clearTimeout(N.idleTimer);let O=N.data.frontendSessionId;if(!O)return;if(Z.get(O)!==N)return;if(Z.delete(O),Y(O),K)return;Q.set(O,setTimeout(()=>V(O),s3))})}),U.on("upgrade",(H,B,N)=>{let O=new URL(H.url??"/","http://127.0.0.1").pathname;if(X.onHttpUpgrade?.(H,B,N))return;if(O!==j1){Y2(B,404,"Not Found");return}if(!z1(GX(H.headers.origin))){Y2(B,403,"Forbidden");return}D.handleUpgrade(H,B,N,(C)=>{D.emit("connection",C,H)})});try{let H=await VZ(U,x);return{url:`ws://127.0.0.1:${H}${j1}`,port:H,sendStatus:z,close:async()=>{K=!0;for(let B of Q.values())clearTimeout(B);Q.clear();for(let B of D.clients){let N=B;if(N.idleTimer)clearTimeout(N.idleTimer);N.close()}D.close(),await J2(U).catch(()=>{return})}}}catch(H){if(D.close(),await J2(U).catch(()=>{return}),H?.code==="EADDRINUSE")continue;throw H}}throw Error(`No free IdeaWave CLI bridge port found in ${$[0]}-${$.at(-1)}`)}import{lstat as FZ,readFile as OZ}from"node:fs/promises";import kZ from"node:os";import y0 from"node:path";import{Server as qZ}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as _Z,ListToolsRequestSchema as AZ}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as GZ}from"node:crypto";import{createServer as zZ}from"node:http";import{StreamableHTTPServerTransport as UZ}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as D2}from"@modelcontextprotocol/sdk/types.js";var U2=new Set(["127.0.0.1","localhost","[::1]","::1"]);function jZ(X){let $=X.trim();if($.length===0)return null;if($.startsWith("[")){let K=$.indexOf("]");if(K===-1)return null;let Y=$.slice(0,K+1),V=$.slice(K+1);if(V.length===0)return{host:Y,port:null};if(!V.startsWith(":"))return null;let z=Number(V.slice(1));if(!Number.isInteger(z)||z<=0||z>65535)return null;return{host:Y,port:z}}let Z=$.lastIndexOf(":");if(Z===-1)return{host:$,port:null};let Q=$.slice(Z+1),W=Number(Q);if(!Number.isInteger(W)||W<=0||W>65535)return{host:$,port:null};return{host:$.slice(0,Z),port:W}}function H2(X){return U2.has(X)||U2.has(X.toLowerCase())}function x2(X,$){let Z=X.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let Q=jZ(Z);if(!Q)return{ok:!1,status:403,reason:"bad-host"};if(!H2(Q.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(Q.port!==null&&Q.port!==$)return{ok:!1,status:403,reason:"host-port-mismatch"};let W=X.headers.origin;if(typeof W==="string"&&W.length>0){if(W!=="null"){let K;try{K=new URL(W)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!H2(K.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var w2="/mcp",HZ=43274,M2=16777216,xZ=1800000,DZ=300000,N2=200,wZ=-32700,Z0=-32600,U1=-32603;function l(X,$,Z,Q,W){X.statusCode=$,X.setHeader("content-type","application/json"),X.end(JSON.stringify({jsonrpc:"2.0",error:{code:Z,message:Q,...W?{data:W}:{}},id:null}))}class H1 extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class x1 extends Error{constructor(){super(`body exceeds ${M2} bytes`);this.name="BodyTooLargeError"}}async function NZ(X){if(X.method&&X.method!=="POST")return;let $=X.headers["content-type"];if(typeof $==="string"&&$.trim().length>0){if(!$.toLowerCase().includes("application/json"))throw new H1}let Z=0,Q=[];for await(let K of X){let Y=typeof K==="string"?Buffer.from(K):K;if(Z+=Y.byteLength,Z>M2)throw new x1;Q.push(Y)}if(Q.length===0)return;let W=Buffer.concat(Q).toString("utf8");if(W.length===0)return;return JSON.parse(W)}function MZ(X){if(Array.isArray(X))return X.some(D2);return D2(X)}function LZ(X){if(typeof X==="number")return X;let $=process.env.IDEAWAVE_MCP_PORT;if($&&$.trim().length>0){let Z=Number($);if(Number.isInteger(Z)&&Z>=0&&Z<65536)return Z}return HZ}async function PZ(X,$){let Z=(W)=>new Promise((K,Y)=>{let V=(J)=>{X.off("listening",z),Y(J)},z=()=>{X.off("error",V),K()};X.once("error",V),X.once("listening",z),X.listen(W,"127.0.0.1")});try{await Z($)}catch(W){if(W.code!=="EADDRINUSE"||$===0)throw W;console.warn(`[mcp] port ${$} 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 Q=X.address();if(Q==null||typeof Q==="string")throw Error("[mcp] failed to read bound address");return Q.port}function BZ(X,$){if($&&typeof $==="object"&&!Array.isArray($)){let Q=$.params;if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let W=Q.clientInfo;if(W&&typeof W==="object"&&!Array.isArray(W)){let K=W.name;if(typeof K==="string"&&K.trim().length>0)return K.trim()}}}let Z=X.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function L2(X){let $=new Map,Z=0;function Q(J){let G=$.get(J);if(G)G.lastActivity=Date.now()}async function W(J,G){$.delete(J),await G.transport.close().catch(()=>{return})}async function K(){let J=null,G=1/0;for(let[M,P]of $)if(P.lastActivity<G)G=P.lastActivity,J=M;if(J!==null){let M=$.get(J);if(M)console.warn(`[mcp] session cap of ${N2} reached; evicting ${J}`),await W(J,M)}}let Y=setInterval(()=>{let J=Date.now()-xZ;for(let[G,M]of $)if(M.lastActivity<J)console.log(`[mcp] sweeping idle session ${G}`),W(G,M)},DZ);Y.unref?.();let V=zZ((J,G)=>{(async()=>{let M;try{M=new URL(J.url??"/","http://127.0.0.1").pathname}catch{l(G,400,Z0,"bad-url");return}if(M!==w2){l(G,404,Z0,"not-found");return}let P=J.method??"POST";if(P!=="POST"&&P!=="GET"&&P!=="DELETE"){G.setHeader("Allow","GET, POST, DELETE"),l(G,405,Z0,"method-not-allowed");return}let x=x2(J,Z);if(!x.ok){l(G,x.status,Z0,"forbidden",{reason:x.reason});return}let U=J.headers["mcp-session-id"],D=typeof U==="string"?U:void 0;if(P==="GET"||P==="DELETE"){if(!D||!$.has(D)){l(G,400,Z0,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let B=$.get(D).transport;Q(D);try{await B.handleRequest(J,G)}catch(N){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",N),!G.headersSent)l(G,500,U1,"internal")}return}let w;try{w=await NZ(J)}catch(B){if(B instanceof H1){l(G,415,Z0,"expected-application-json");return}if(B instanceof x1){l(G,413,Z0,"body-too-large");return}l(G,400,wZ,"invalid-json");return}let H;if(D&&$.has(D))H=$.get(D).transport,Q(D);else if(!D&&w!==void 0&&MZ(w)){let B=J.headers["x-ideawave-user-id"],N=typeof B==="string"&&B.trim().length>0?B.trim():null,O=J.headers["x-ideawave-frontend-session-id"],C=typeof O==="string"&&O.trim().length>0?O.trim():null,L=J.headers["x-ideawave-tool-surface"],j=typeof L==="string"&&L.trim()==="read"?"read":"full",k=J.headers["x-ideawave-images-supported"],_=typeof k==="string"&&k.trim()==="1",b=J.headers["x-ideawave-card-id"],d=typeof b==="string"&&b.trim().length>0?b.trim():null,n=J.headers["x-ideawave-board-id"],A=typeof n==="string"&&n.trim().length>0?n.trim():null,v=J.headers["x-ideawave-run-folder"],y=typeof v==="string"&&v.trim().length>0?v.trim():null,I=BZ(J,w);if($.size>=N2)await K();let h=null,K0=new UZ({sessionIdGenerator:()=>GZ(),onsessioninitialized:(U0)=>{h=U0,$.set(U0,{transport:K0,lastActivity:Date.now()})},onsessionclosed:(U0)=>{$.delete(U0)}});K0.onclose=()=>{if(K0.sessionId)$.delete(K0.sessionId)};try{await X.buildServer({userId:N,frontendSessionId:C,boardId:A,toolSurface:j,imagesSupported:_,cardId:d,runFolder:y,clientHint:I}).connect(K0)}catch(U0){if(console.error("[mcp] buildServer/connect failed",U0),h)$.delete(h);await K0.close().catch(()=>{return}),l(G,500,U1,"server-init-failed");return}H=K0}else{l(G,400,Z0,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await H.handleRequest(J,G,w)}catch(B){if(console.error("[mcp] transport.handleRequest threw",B),!G.headersSent)l(G,500,U1,"internal")}})().catch((M)=>{console.error("[mcp] unhandled request handler error:",M)})});return Z=await PZ(V,LZ(X.port)),{url:`http://127.0.0.1:${Z}${w2}`,port:Z,close:async()=>{clearInterval(Y);for(let J of $.values())await J.transport.close().catch(()=>{return});$.clear(),await new Promise((J)=>V.close(()=>J()))}}}var CZ={name:"ideawave-board",version:"1.0.0"},zX="list_run_folder",UX="read_run_folder_file",F2=new Set(["list_boards","get_board","screenshot_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",zX,UX]),O2=new Set(["inspect_diagram"]),RZ=[{name:zX,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:UX,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 D1(X){return{content:[{type:"text",text:X}]}}function fZ(X){return D1(JSON.stringify(X,null,2))}function P2(X){return{...D1(X),isError:!0}}async function yZ(X,$){if(!$||X.isError)return X;let Z=X.content.find((K)=>K.type==="text");if(!Z)return X;let Q;try{let K=JSON.parse(Z.text);if(typeof K.path!=="string")return X;Q=y0.resolve(K.path)}catch{return X}let W=y0.resolve(y0.join(kZ.tmpdir(),"ideawave-screenshots"));if(y0.dirname(Q)!==W||!/^board-[a-z0-9-]+\.png$/i.test(y0.basename(Q)))return X;try{if(!(await FZ(Q)).isFile())return X;let Y=await OZ(Q);if(Y.byteLength<1024||Y.byteLength>26214400||!Y.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return X;return{...X,content:[...X.content,{type:"image",data:Y.toString("base64"),mimeType:"image/png"}]}}catch{return X}}function bZ(X,$,Z="full",Q=!1){return X.getMetadata($).filter((W)=>{let K=$X(W.name);if(Z==="read"&&!F2.has(K))return!1;if(!Q&&O2.has(K))return!1;return!0}).map((W)=>({name:W.name,description:W.description,inputSchema:W.inputSchema}))}function EZ(X,$,Z={}){let Q=bZ(X,$,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...Q,...RZ]:Q}function B2(X,$){if(!X||typeof X!=="object"||Array.isArray(X))return null;let Z=X[$];return typeof Z==="string"?Z:null}async function TZ(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 X0({boardId:X,cardId:$})).runFolder}async function vZ(X){let $=await TZ(X.boardId,X.cardId,X.runFolder);if(X.name===zX){let Z=B2(X.args,"path")??"",Q=await L$($,Z);return fZ(Q)}if(X.name===UX){let Z=B2(X.args,"path");if(!Z)return P2("read_run_folder_file requires a path.");return D1(await XX($,Z))}return P2(`Unknown local tool "${X.name}"`)}function hZ(X,$,Z,Q,W,K="full",Y=!1){let V=new qZ(CZ,{capabilities:{tools:{}}}),z=async()=>{if(Y)return!0;if(g$(Q))return!0;if(Z&&Q)try{return(await X0({boardId:Z,cardId:Q})).adapter.supportsImages===!0}catch{return!1}return!1};return V.setRequestHandler(AZ,async()=>({tools:EZ(X,$,{includeRunFolderTools:Boolean(W||Z&&Q),toolSurface:K,imagesSupported:await z()})})),V.setRequestHandler(_Z,async(J)=>{let{name:G,arguments:M}=J.params,P=$X(G),x=Date.now();q("mcp.tool_call_received",{frontendSessionId:$,cardId:Q,toolName:P});try{if(P===zX||P===UX)return await vZ({name:P,args:M,boardId:Z,cardId:Q,runFolder:W});if(K==="read"&&!F2.has(P))throw Error(`Tool "${G}" is not available in read-only mode`);if(O2.has(P)&&!await z())throw Error(`Tool "${G}" requires a runtime that supports image input`);let U=await X.callTool($,P,M??{},void 0,Q??void 0);if(q("mcp.tool_result_returned",{frontendSessionId:$,cardId:Q,toolName:P,elapsedMs:Date.now()-x}),U&&typeof U==="object"&&Array.isArray(U.content)){let D=U;return P==="screenshot_board"?await yZ(D,await z()):D}return{content:[{type:"text",text:typeof U==="string"?U:JSON.stringify(U)}]}}catch(U){return q("mcp.tool_result_returned",{frontendSessionId:$,cardId:Q,toolName:P,elapsedMs:Date.now()-x,hasError:!0}),{content:[{type:"text",text:U instanceof Error?U.message:"Tool call failed"}],isError:!0}}}),V}function k2(X,$){return L2({buildServer:(Z)=>hZ(X,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:$})}import HX from"node:fs/promises";import w1 from"node:os";import xX from"node:path";function q2(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function IZ(){let[X,$]=await Promise.all([m(),V$()]),Z=X.globalDefaultConfigId?X.runtimes.find((Q)=>Q.id===X.globalDefaultConfigId)??null:null;return{runtimes:X.runtimes,globalDefaultConfigId:X.globalDefaultConfigId,globalDefaultEffective:Z?{runFolder:Z.runFolder??w1.homedir(),modelId:Z.defaultModelId??null,configValues:Z.defaultConfigValues??{}}:null,knownAdapters:D0().map((Q)=>({id:Q.id,displayName:Q.displayName})),readiness:$}}async function SZ(X){try{let $=await X0({boardId:X.boardId,cardId:X.cardId});return{resolved:{configId:$.entry.id,adapterId:$.entry.kind==="registered"?$.entry.adapterId:null,displayName:$.entry.displayName,runFolder:$.runFolder,modelId:$.modelId,configValues:$.configValues}}}catch($){if($ instanceof Y0)return{resolved:null};throw $}}async function gZ(X){return p(($)=>{let Z=$.runtimes.find((K)=>K.kind==="registered"&&K.adapterId===X.adapterId);if(Z)return Z;let Q=D0().find((K)=>K.id===X.adapterId);if(!Q)throw Error(`Unknown adapterId: ${X.adapterId}`);let W={id:q2(),kind:"registered",adapterId:X.adapterId,displayName:Q.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return $.runtimes.push(W),W})}async function mZ(X){return p(($)=>{let Z={id:q2(),kind:"custom",displayName:X.displayName,command:X.command,args:X.args,env:X.env,runFolder:X.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return $.runtimes.push(Z),Z})}async function cZ(X){await p(($)=>{if($.runtimes=$.runtimes.filter((Z)=>Z.id!==X.runtimeConfigId),$.globalDefaultConfigId===X.runtimeConfigId)$.globalDefaultConfigId=null;for(let Z of Object.keys($.boardOverrides))if($.boardOverrides[Z].runtimeConfigId===X.runtimeConfigId)delete $.boardOverrides[Z];for(let Z of Object.keys($.cardOverrides))if($.cardOverrides[Z].runtimeConfigId===X.runtimeConfigId)delete $.cardOverrides[Z]})}async function lZ(X){await p(($)=>{let Z=$.runtimes.find((Q)=>Q.id===X.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);if($.globalDefaultConfigId=X.runtimeConfigId,X.runFolder!==void 0)Z.runFolder=X.runFolder;if(X.modelId!==void 0)Z.defaultModelId=X.modelId;if(X.configValues!==void 0)Z.defaultConfigValues=X.configValues})}async function pZ(X){X.boardId,await p(($)=>{if(X.runtimeConfigId===null){delete $.cardOverrides[X.cardId];return}if(!$.runtimes.some((W)=>W.id===X.runtimeConfigId))throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let Q=$.cardOverrides[X.cardId];$.cardOverrides[X.cardId]={runtimeConfigId:X.runtimeConfigId,runFolder:X.runFolder!==void 0?X.runFolder:Q?.runFolder??null,modelId:X.modelId!==void 0?X.modelId:Q?.modelId??null,configValues:X.configValues!==void 0?X.configValues:Q?.configValues??{}}})}async function uZ(X){let Z=(await m()).runtimes.find((Y)=>Y.id===X.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let Q=a(Z),W=await Q.resolveSpawnConfig(Z),K=Z.runFolder??w1.homedir();try{let Y=await v$({spawn:{...W,cwd:K},modelId:X.modelId??Z.defaultModelId??null,configValues:X.configValues??Z.defaultConfigValues??{}}),V=s0({adapterId:Q.id,models:Y.models,currentModelId:Y.currentModelId}),z=new Date().toISOString();return await p((J)=>{let G=J.runtimes.find((M)=>M.id===X.runtimeConfigId);if(G)G.discoveredModels=V,G.discoveredConfigOptions=Y.configOptions,G.discoveredAt=z}),{ok:!0,models:V,configOptions:Y.configOptions,currentModelId:Y.currentModelId}}catch(Y){if(Y instanceof H0)throw Error(`${Y.message}${Q.authHint?` ${Q.authHint}`:""}`);if(Y instanceof R||Y instanceof u)throw Error(Y.message);throw Y}}async function aZ(X){let $=w1.homedir(),Z=X.path?.trim()?X.path.trim():$,Q=xX.resolve(Z),W=!0;try{if(!(await HX.stat(Q)).isDirectory())Q=xX.dirname(Q)}catch{W=!1,Q=$}let K=[];try{K=(await HX.readdir(Q,{withFileTypes:!0})).filter((z)=>z.isDirectory()&&!z.name.startsWith(".")).map((z)=>({name:z.name,path:xX.join(Q,z.name)})).sort((z,J)=>z.name.localeCompare(J.name))}catch{K=[]}let Y=xX.dirname(Q);return{path:Q,parent:Y===Q?null:Y,home:$,exists:W,entries:K}}var _2={list:IZ,getEffectiveForCard:SZ,registerRegistered:gZ,registerCustom:mZ,unregister:cZ,setUserDefault:lZ,setCardOverride:pZ,refreshModels:uZ,browseFolder:aZ};var dZ=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function iZ(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function A2(){try{let X=await m();if(X.globalDefaultConfigId){if(X.runtimes.some((Z)=>Z.id===X.globalDefaultConfigId))return X.globalDefaultConfigId}for(let $ of dZ){if((await j$($.id))?.status!=="ready")continue;let Q=null;if(await p((W)=>{if(W.globalDefaultConfigId){if(W.runtimes.some((V)=>V.id===W.globalDefaultConfigId)){Q=W.globalDefaultConfigId;return}}let K=W.runtimes.find((Y)=>Y.kind==="registered"&&Y.adapterId===$.id);if(!K){let Y={id:iZ(),kind:"registered",adapterId:$.id,displayName:$.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};W.runtimes.push(Y),K=Y}W.globalDefaultConfigId=K.id,Q=K.id}),Q)return console.log(`[ideawave-cli] using agent runtime: ${$.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(X){return console.warn("[ideawave-cli] runtime auto-seed failed",X),null}}var oZ=120000;function nZ(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class N1{sessions=new Map;createCallId;toolCallTimeoutMs;constructor(X={}){this.createCallId=X.createCallId??nZ,this.toolCallTimeoutMs=X.toolCallTimeoutMs??oZ}register(X){let $=this.sessions.get(X.frontendSessionId);if($){if($.userId!==X.userId)this.rejectPending($,"frontend session user changed"),$.activeRunIds.clear();this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:$.pendingToolCalls,activeRunIds:$.activeRunIds,activeRunCardIds:$.activeRunCardIds});return}this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect(X,$="frontend session disconnected"){let Z=this.sessions.get(X);if(!Z)return{activeRunIds:[]};return this.sessions.delete(X),this.rejectPending(Z,$),{activeRunIds:Array.from(Z.activeRunIds)}}sessionCount(){return this.sessions.size}has(X){return this.sessions.has(X)}getUserId(X){return this.sessions.get(X)?.userId??null}setMetadata(X,$){let Z=this.sessions.get(X);if(Z)Z.tools=$}getMetadata(X){if(!X)return[];return this.sessions.get(X)?.tools??[]}sendToSession(X,$){let Z=this.sessions.get(X);if(!Z)return!1;return Z.send($),!0}callTool(X,$,Z,Q,W){if(!X)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let K=this.sessions.get(X);if(!K)return Promise.reject(Error(`Frontend session ${X} is not connected`));let Y=this.createCallId();return new Promise((V,z)=>{let J=Q??(W?this.getActiveRunIdForCard(K,W):this.getSoleActiveRunId(K)),G=W??(J?K.activeRunCardIds.get(J):void 0),M=Date.now(),P=setTimeout(()=>{K.pendingToolCalls.delete(Y),q("tool_queue.timeout",{frontendSessionId:X,runId:J,cardId:G,callId:Y,toolName:$,elapsedMs:Date.now()-M,queueDepth:K.pendingToolCalls.size}),z(Error(`Tool "${$}" timed out waiting for the frontend`))},this.toolCallTimeoutMs);K.pendingToolCalls.set(Y,{resolve:V,reject:z,timer:P,name:$,runId:J??null,cardId:G??null,startedAt:M}),q("tool_queue.forwarded_to_browser",{frontendSessionId:X,runId:J,cardId:G,callId:Y,toolName:$,queueDepth:K.pendingToolCalls.size}),K.send({type:"tool_call",callId:Y,name:$,args:Z,...J?{runId:J}:{},...G?{cardId:G}:{}})})}handleToolResult(X,$){let Z=this.sessions.get(X);if(!Z)return;let Q=Z.pendingToolCalls.get($.callId);if(!Q)return;if(Z.pendingToolCalls.delete($.callId),clearTimeout(Q.timer),q("tool_queue.result_received",{frontendSessionId:X,runId:Q.runId,cardId:Q.cardId,callId:$.callId,toolName:Q.name,elapsedMs:Date.now()-Q.startedAt,queueDepth:Z.pendingToolCalls.size,ok:$.ok}),$.ok){Q.resolve($.result);return}let W=$.result;if(W&&typeof W==="object"&&Array.isArray(W.content)){Q.resolve({...W,isError:!0});return}Q.reject(Error($.error??"Tool execution failed"))}markRunActive(X,$,Z){let Q=this.sessions.get(X);if(!Q)return;if(Q.activeRunIds.add($),Z)Q.activeRunCardIds.set($,Z)}markRunSettled(X,$){let Z=this.sessions.get(X);if(!Z)return;Z.activeRunIds.delete($),Z.activeRunCardIds.delete($)}ownsRun(X,$){return this.sessions.get(X)?.activeRunIds.has($)??!1}rejectPending(X,$){for(let Z of X.pendingToolCalls.values())clearTimeout(Z.timer),q("tool_queue.rejected",{frontendSessionId:X.frontendSessionId,runId:Z.runId,cardId:Z.cardId,toolName:Z.name,elapsedMs:Date.now()-Z.startedAt}),Z.reject(Error($));X.pendingToolCalls.clear()}getSoleActiveRunId(X){return X.activeRunIds.size===1?X.activeRunIds.values().next().value:void 0}getActiveRunIdForCard(X,$){let Z=[...X.activeRunCardIds.entries()].filter(([Q,W])=>X.activeRunIds.has(Q)&&W===$).map(([Q])=>Q);return Z.length===1?Z[0]:void 0}}function R2(){return"0.0.72".trim()?"0.0.72":"dev"}var tZ=process.argv.slice(2),L1=K2(tZ,process.env);if(L1.allowRailwayPrPreviews)process.env[f0]="1";var W0=L1.cliArgs[0],{browserKitEnabled:E0,captureEngineEnabled:rZ}=L1;if(W0==="--help"||W0==="-h"||W0==="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(W0==="--version"||W0==="-v"||W0==="version")console.log(R2()),process.exit(0);if(W0)console.error(`Unknown command: ${W0}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var T0=new N1,z0=null,sZ=E0?{phase:"ready",message:"Local browser-kit proxy is ready"}:{phase:"idle"},B0=new r0;function Q0(X,$){T0.sendToSession(X,$)}async function eZ(X,$){try{let Z=_2[$.method],Q=await Z($.params);Q0(X,{type:"runtime_rpc_result",requestId:$.requestId,ok:!0,result:Q})}catch(Z){Q0(X,{type:"runtime_rpc_result",requestId:$.requestId,ok:!1,error:Z instanceof Error?Z.message:String(Z)})}}var v0=!1,b0=null;async function M1(){if(v0)return;if(b0)return b0;return b0=(async()=>{try{let X=await k2(T0);_1({...X,requestedPort:X.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${X.url}`);try{await p1({onStatusChange:($)=>{if(G$(),z0?.sendStatus(),$.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${$.packageName}: ${$.error??"unknown error"}`)}})}catch($){console.warn("[ideawave-cli] ACP bridge setup skipped:",$ instanceof Error?$.message:String($))}await A2(),v0=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),z0?.sendStatus()}catch(X){console.error("[ideawave-cli] failed to start agent host:",X),z0?.sendStatus(void 0,X instanceof Error?X.message:String(X))}finally{b0=null}})(),b0}if(process.env.APP_ENV!=="development"){let X=await G2();if(X)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${X}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}if(rZ)n$().then((X)=>{if(X.phase==="ready")console.log("[ideawave-cli] screenshot engine ready");else if(X.phase==="failed")console.warn(`[ideawave-cli] screenshot engine setup failed: ${X.error??"unknown error"}`)});z0=await z2({registry:T0,runtime:null,mcpReady:()=>v0,capabilities:E0?[A1]:[],cliVersion:R2(),browserRuntimeStatus:()=>sZ,onToolMetadata:(X)=>{console.log(`[ideawave-cli] session ${X} advertised ${T0.getMetadata(X).length} tools`),M1()},onRunTurn:(X,$)=>{console.log(`[ideawave-cli] running agent turn for card ${$.cardId} (session ${X})`),(async()=>{if(await M1(),!v0){Q0(X,{type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await p$($,(Z)=>Q0(X,Z))})().catch(()=>{return}).finally(()=>T0.markRunSettled(X,$.runId))},onCancelRun:(X,$)=>{$1($)},onRuntimeRpc:(X,$)=>{eZ(X,$)},onBrowserRpc:(X,$,Z)=>{if(!E0){Q0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!1,error:"The development browser-kit proxy is not enabled"});return}B0.handleRpc(X,$,Z).then((Q)=>{Q0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!0,result:Q})},(Q)=>{Q0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!1,error:Q instanceof Error?Q.message:String(Q)})})},onHttpRequest:(X,$)=>E0?B0.handleHttpRequest(X,$):!1,onHttpUpgrade:(X,$,Z)=>E0?B0.handleUpgrade(X,$,Z):!1,onWarmupRun:(X,$,Z)=>{(async()=>{if(await M1(),!v0)return{status:"retryable",error:"agent host is not ready"};return u$({cardId:$.cardId,boardId:$.boardId,userId:Z,frontendSessionId:X})})().then((Q)=>{if(!$.warmupId)return;Q0(X,{type:"warmup_result",warmupId:$.warmupId,cardId:$.cardId,...Q})})},onDisconnect:(X,$)=>{B0.closeFrontendSession(X),m$(X);for(let Z of $)$1(Z);q("bridge.frontend_disconnected",{frontendSessionId:X,activeRuns:$.length}),F1(X).catch((Z)=>{console.warn(`[ideawave-cli] failed to evict sessions for ${X}:`,Z instanceof Error?Z.message:String(Z))}),console.log(`[ideawave-cli] browser session ${X} disconnected`)}});B0.setPort(z0.port);console.log(`[ideawave-cli] browser bridge listening on ${z0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var C2=!1;for(let X of["SIGINT","SIGTERM"])process.once(X,()=>{if(C2)return;C2=!0,c$(),(async()=>{await B0.close(),await s$(),await z0?.close().catch(()=>{return}),process.exit(0)})()});
1040
+ ${Z}`),X.destroy()}function zZ(X,$){return new Promise((Z,W)=>{let Q=(Y)=>{X.off("listening",K),W(Y)},K=()=>{X.off("error",Q);let Y=X.address();if(!Y||typeof Y==="string"){W(Error("Failed to read CLI bridge server address"));return}Z(Y.port)};X.once("error",Q),X.once("listening",K),X.listen($,"127.0.0.1")})}function G2(X){return new Promise(($,Z)=>{X.close((W)=>{if(W)Z(W);else $()})})}async function D2(X,$=U1()){let Z=new Map,W=new Map,Q=X.maxMessageSize??e3,K=!1,Y=(U)=>{let H=W.get(U);if(H)clearTimeout(H);W.delete(U)},V=(U)=>{W.delete(U);let{activeRunIds:H}=X.registry.disconnect(U);X.onDisconnect(U,H)},j=(U,H)=>{let x={type:"cli_status",connected:!0,runtime:X.runtime,mcpReady:X.mcpReady(),error:H,capabilities:X.capabilities??[],cliVersion:X.cliVersion,browserRuntime:X.browserRuntimeStatus?.()};if(U){let w=Z.get(U);if(w)F0(w,x);return}for(let w of Z.values())F0(w,x)},J=(U,H)=>{let x=H.sessionId.trim(),w=H.userId.trim();if(!x||!w){F0(U,{type:"cli_status",connected:!1,runtime:X.runtime,mcpReady:X.mcpReady(),error:"Missing frontend session or user id"}),U.close();return}Y(x);let P=Z.get(x);if(P&&P!==U)P.close();U.data.frontendSessionId=x,Z.set(x,U),X.registry.register({frontendSessionId:x,userId:w,tools:H.tools,send:(L)=>F0(U,L)}),j(x),X.onToolMetadata?.(x)},z=(U,H)=>{let x=X.registry.getUserId(U);if(!x)return;switch(H.type){case"bridge_ping":{let w=Z.get(U);if(w)F0(w,{type:"bridge_pong"});break}case"tool_metadata":X.registry.setMetadata(U,H.tools),X.onToolMetadata?.(U);break;case"tool_result":X.registry.handleToolResult(U,H);break;case"run_turn":_("bridge.run_received",{runId:H.run.runId,cardId:H.run.cardId,frontendSessionId:U}),X.registry.markRunActive(U,H.run.runId,H.run.cardId),X.onRunTurn(U,{...H.run,frontendSessionId:U,userId:x});break;case"cancel_run":if(X.registry.ownsRun(U,H.runId))X.onCancelRun(U,H.runId);break;case"runtime_rpc":X.onRuntimeRpc(U,H);break;case"browser_rpc":X.onBrowserRpc?.(U,Z.get(U)?.data.frontendOrigin??"",H);break;case"warmup_run":X.onWarmupRun(U,{...H,frontendSessionId:U},x);break;default:break}},D=(U,H)=>{let x=HX(U.headers.origin),w=D1(x),P={Vary:"Origin"};if(w&&x)P["Access-Control-Allow-Origin"]=x,P["Access-Control-Allow-Private-Network"]="true";if(U.method==="OPTIONS"){H.writeHead(204,{...P,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),H.end();return}if(U.method!=="GET"){H.writeHead(405,P),H.end();return}H.writeHead(200,{...P,"content-type":"application/json","cache-control":"no-store"}),H.end(JSON.stringify({ideawave:!0,runtime:X.runtime,mcpReady:X.mcpReady(),capabilities:X.capabilities??[],cliVersion:X.cliVersion,browserRuntime:X.browserRuntimeStatus?.()}))},N=(U,H)=>{let x=HX(U.headers.origin),w=D1(x),P={Vary:"Origin"};if(w&&x)P["Access-Control-Allow-Origin"]=x,P["Access-Control-Allow-Private-Network"]="true";if(U.method==="OPTIONS"){H.writeHead(204,{...P,"Access-Control-Allow-Methods":"POST, OPTIONS","Access-Control-Allow-Headers":"content-type","Access-Control-Max-Age":"600"}),H.end();return}if(!w){H.writeHead(403,P),H.end();return}if(U.method!=="POST"){H.writeHead(405,P),H.end();return}let L={...P,"content-type":"application/json"},M=(F,G)=>{H.writeHead(F,L),H.end(JSON.stringify(G))},O="",C=!1;U.on("data",(F)=>{if(O+=F.toString("utf8"),O.length>WZ)C=!0,U.destroy()}),U.on("end",()=>{if(C){M(400,{ok:!1,error:"Request body too large"});return}let F;try{F=JSON.parse(O)}catch{M(400,{ok:!1,error:"Invalid JSON body"});return}let G=typeof F.url==="string"?F.url:"";if(!J2(G)){M(400,{ok:!1,error:"url must be an http(s) loopback or /static_boards/ page URL"});return}let k=(A,b)=>{let d=typeof A==="number"?A:Number.NaN;if(!Number.isFinite(d))return b;return Math.min(4000,Math.max(200,Math.round(d)))};Y2({url:G,width:k(F.width,1440),height:k(F.height,900)}).then((A)=>M(200,{ok:!0,path:A.path,engine:A.engine})).catch((A)=>{let b=A instanceof R0?503:A instanceof zX?429:500;M(b,{ok:!1,...A instanceof R0?{installing:!0}:{},error:A instanceof Error?A.message:String(A)})})})};for(let U of $){let H=r3((P,L)=>{(async()=>{let M=new URL(P.url??"/","http://127.0.0.1").pathname;if(M===Z2){D(P,L);return}if(M===ZZ){N(P,L);return}if(await X.onHttpRequest?.(P,L))return;L.writeHead(404,{"content-type":"text/plain"}),L.end("IdeaWave CLI bridge")})().catch((M)=>{if(L.headersSent){L.destroy(M instanceof Error?M:void 0);return}L.writeHead(500,{"content-type":"text/plain"}),L.end("IdeaWave CLI bridge request failed")})}),x=new s3({noServer:!0,maxPayload:Q}),w=(P)=>{if(P.idleTimer)clearTimeout(P.idleTimer);P.idleTimer=setTimeout(()=>{P.close()},XZ),P.idleTimer.unref?.()};x.on("connection",(P,L)=>{let M=P;M.data={id:t3(),frontendSessionId:null,frontendOrigin:new URL(HX(L.headers.origin)??H2).origin},M.idleTimer=null,w(M),M.on("ping",()=>w(M)),M.on("pong",()=>w(M)),M.on("error",()=>{if(M.idleTimer)clearTimeout(M.idleTimer);M.close()}),M.on("message",(O)=>{w(M);let C=GZ(O);if(Q>0&&C.length>Q)return;let F=g0(C);if(!F)return;let G=M.data.frontendSessionId;if(!G){if(F.type==="bridge_probe")F0(M,{type:"bridge_probe_ack",protocolVersion:F.protocolVersion});else if(F.type==="frontend_hello")J(M,F);return}z(G,F)}),M.on("close",()=>{if(M.idleTimer)clearTimeout(M.idleTimer);let O=M.data.frontendSessionId;if(!O)return;if(Z.get(O)!==M)return;if(Z.delete(O),Y(O),K)return;W.set(O,setTimeout(()=>V(O),$Z))})}),H.on("upgrade",(P,L,M)=>{let O=new URL(P.url??"/","http://127.0.0.1").pathname;if(X.onHttpUpgrade?.(P,L,M))return;if(O!==H1){j2(L,404,"Not Found");return}if(!D1(HX(P.headers.origin))){j2(L,403,"Forbidden");return}x.handleUpgrade(P,L,M,(C)=>{x.emit("connection",C,P)})});try{let P=await zZ(H,U);return{url:`ws://127.0.0.1:${P}${H1}`,port:P,sendStatus:j,close:async()=>{K=!0;for(let L of W.values())clearTimeout(L);W.clear();for(let L of x.clients){let M=L;if(M.idleTimer)clearTimeout(M.idleTimer);M.close()}x.close(),await G2(H).catch(()=>{return})}}}catch(P){if(x.close(),await G2(H).catch(()=>{return}),P?.code==="EADDRINUSE")continue;throw P}}throw Error(`No free IdeaWave CLI bridge port found in ${$[0]}-${$.at(-1)}`)}import{lstat as _Z,readFile as AZ}from"node:fs/promises";import qZ from"node:os";import E0 from"node:path";import{Server as CZ}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as RZ,ListToolsRequestSchema as yZ}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as UZ}from"node:crypto";import{createServer as DZ}from"node:http";import{StreamableHTTPServerTransport as NZ}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as w2}from"@modelcontextprotocol/sdk/types.js";var N2=new Set(["127.0.0.1","localhost","[::1]","::1"]);function HZ(X){let $=X.trim();if($.length===0)return null;if($.startsWith("[")){let K=$.indexOf("]");if(K===-1)return null;let Y=$.slice(0,K+1),V=$.slice(K+1);if(V.length===0)return{host:Y,port:null};if(!V.startsWith(":"))return null;let j=Number(V.slice(1));if(!Number.isInteger(j)||j<=0||j>65535)return null;return{host:Y,port:j}}let Z=$.lastIndexOf(":");if(Z===-1)return{host:$,port:null};let W=$.slice(Z+1),Q=Number(W);if(!Number.isInteger(Q)||Q<=0||Q>65535)return{host:$,port:null};return{host:$.slice(0,Z),port:Q}}function P2(X){return N2.has(X)||N2.has(X.toLowerCase())}function x2(X,$){let Z=X.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let W=HZ(Z);if(!W)return{ok:!1,status:403,reason:"bad-host"};if(!P2(W.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(W.port!==null&&W.port!==$)return{ok:!1,status:403,reason:"host-port-mismatch"};let Q=X.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(!P2(K.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var M2="/mcp",PZ=43274,L2=16777216,xZ=1800000,wZ=300000,F2=200,MZ=-32700,Z0=-32600,N1=-32603;function l(X,$,Z,W,Q){X.statusCode=$,X.setHeader("content-type","application/json"),X.end(JSON.stringify({jsonrpc:"2.0",error:{code:Z,message:W,...Q?{data:Q}:{}},id:null}))}class P1 extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class x1 extends Error{constructor(){super(`body exceeds ${L2} bytes`);this.name="BodyTooLargeError"}}async function FZ(X){if(X.method&&X.method!=="POST")return;let $=X.headers["content-type"];if(typeof $==="string"&&$.trim().length>0){if(!$.toLowerCase().includes("application/json"))throw new P1}let Z=0,W=[];for await(let K of X){let Y=typeof K==="string"?Buffer.from(K):K;if(Z+=Y.byteLength,Z>L2)throw new x1;W.push(Y)}if(W.length===0)return;let Q=Buffer.concat(W).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function LZ(X){if(Array.isArray(X))return X.some(w2);return w2(X)}function BZ(X){if(typeof X==="number")return X;let $=process.env.IDEAWAVE_MCP_PORT;if($&&$.trim().length>0){let Z=Number($);if(Number.isInteger(Z)&&Z>=0&&Z<65536)return Z}return PZ}async function OZ(X,$){let Z=(Q)=>new Promise((K,Y)=>{let V=(J)=>{X.off("listening",j),Y(J)},j=()=>{X.off("error",V),K()};X.once("error",V),X.once("listening",j),X.listen(Q,"127.0.0.1")});try{await Z($)}catch(Q){if(Q.code!=="EADDRINUSE"||$===0)throw Q;console.warn(`[mcp] port ${$} 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 W=X.address();if(W==null||typeof W==="string")throw Error("[mcp] failed to read bound address");return W.port}function kZ(X,$){if($&&typeof $==="object"&&!Array.isArray($)){let W=$.params;if(W&&typeof W==="object"&&!Array.isArray(W)){let Q=W.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=X.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function B2(X){let $=new Map,Z=0;function W(J){let z=$.get(J);if(z)z.lastActivity=Date.now()}async function Q(J,z){$.delete(J),await z.transport.close().catch(()=>{return})}async function K(){let J=null,z=1/0;for(let[D,N]of $)if(N.lastActivity<z)z=N.lastActivity,J=D;if(J!==null){let D=$.get(J);if(D)console.warn(`[mcp] session cap of ${F2} reached; evicting ${J}`),await Q(J,D)}}let Y=setInterval(()=>{let J=Date.now()-xZ;for(let[z,D]of $)if(D.lastActivity<J)console.log(`[mcp] sweeping idle session ${z}`),Q(z,D)},wZ);Y.unref?.();let V=DZ((J,z)=>{(async()=>{let D;try{D=new URL(J.url??"/","http://127.0.0.1").pathname}catch{l(z,400,Z0,"bad-url");return}if(D!==M2){l(z,404,Z0,"not-found");return}let N=J.method??"POST";if(N!=="POST"&&N!=="GET"&&N!=="DELETE"){z.setHeader("Allow","GET, POST, DELETE"),l(z,405,Z0,"method-not-allowed");return}let U=x2(J,Z);if(!U.ok){l(z,U.status,Z0,"forbidden",{reason:U.reason});return}let H=J.headers["mcp-session-id"],x=typeof H==="string"?H:void 0;if(N==="GET"||N==="DELETE"){if(!x||!$.has(x)){l(z,400,Z0,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let L=$.get(x).transport;W(x);try{await L.handleRequest(J,z)}catch(M){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",M),!z.headersSent)l(z,500,N1,"internal")}return}let w;try{w=await FZ(J)}catch(L){if(L instanceof P1){l(z,415,Z0,"expected-application-json");return}if(L instanceof x1){l(z,413,Z0,"body-too-large");return}l(z,400,MZ,"invalid-json");return}let P;if(x&&$.has(x))P=$.get(x).transport,W(x);else if(!x&&w!==void 0&&LZ(w)){let L=J.headers["x-ideawave-user-id"],M=typeof L==="string"&&L.trim().length>0?L.trim():null,O=J.headers["x-ideawave-frontend-session-id"],C=typeof O==="string"&&O.trim().length>0?O.trim():null,F=J.headers["x-ideawave-tool-surface"],G=typeof F==="string"&&F.trim()==="read"?"read":"full",k=J.headers["x-ideawave-images-supported"],A=typeof k==="string"&&k.trim()==="1",b=J.headers["x-ideawave-card-id"],d=typeof b==="string"&&b.trim().length>0?b.trim():null,n=J.headers["x-ideawave-board-id"],q=typeof n==="string"&&n.trim().length>0?n.trim():null,v=J.headers["x-ideawave-run-folder"],E=typeof v==="string"&&v.trim().length>0?v.trim():null,I=kZ(J,w);if($.size>=F2)await K();let h=null,K0=new NZ({sessionIdGenerator:()=>UZ(),onsessioninitialized:(H0)=>{h=H0,$.set(H0,{transport:K0,lastActivity:Date.now()})},onsessionclosed:(H0)=>{$.delete(H0)}});K0.onclose=()=>{if(K0.sessionId)$.delete(K0.sessionId)};try{await X.buildServer({userId:M,frontendSessionId:C,boardId:q,toolSurface:G,imagesSupported:A,cardId:d,runFolder:E,clientHint:I}).connect(K0)}catch(H0){if(console.error("[mcp] buildServer/connect failed",H0),h)$.delete(h);await K0.close().catch(()=>{return}),l(z,500,N1,"server-init-failed");return}P=K0}else{l(z,400,Z0,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await P.handleRequest(J,z,w)}catch(L){if(console.error("[mcp] transport.handleRequest threw",L),!z.headersSent)l(z,500,N1,"internal")}})().catch((D)=>{console.error("[mcp] unhandled request handler error:",D)})});return Z=await OZ(V,BZ(X.port)),{url:`http://127.0.0.1:${Z}${M2}`,port:Z,close:async()=>{clearInterval(Y);for(let J of $.values())await J.transport.close().catch(()=>{return});$.clear(),await new Promise((J)=>V.close(()=>J()))}}}var EZ={name:"ideawave-board",version:"1.0.0"},UX="list_run_folder",DX="read_run_folder_file",_2=new Set(["list_boards","get_board","screenshot_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",UX,DX]),A2=new Set(["inspect_diagram"]),bZ=[{name:UX,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:DX,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 w1(X){return{content:[{type:"text",text:X}]}}function TZ(X){return w1(JSON.stringify(X,null,2))}function O2(X){return{...w1(X),isError:!0}}async function fZ(X,$){if(!$||X.isError)return X;let Z=X.content.find((K)=>K.type==="text");if(!Z)return X;let W;try{let K=JSON.parse(Z.text);if(typeof K.path!=="string")return X;W=E0.resolve(K.path)}catch{return X}let Q=E0.resolve(E0.join(qZ.tmpdir(),"ideawave-screenshots"));if(E0.dirname(W)!==Q||!/^board-[a-z0-9-]+\.png$/i.test(E0.basename(W)))return X;try{if(!(await _Z(W)).isFile())return X;let Y=await AZ(W);if(Y.byteLength<1024||Y.byteLength>26214400||!Y.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return X;return{...X,content:[...X.content,{type:"image",data:Y.toString("base64"),mimeType:"image/png"}]}}catch{return X}}function vZ(X,$,Z="full",W=!1){return X.getMetadata($).filter((Q)=>{let K=WX(Q.name);if(Z==="read"&&!_2.has(K))return!1;if(!W&&A2.has(K))return!1;return!0}).map((Q)=>({name:Q.name,description:Q.description,inputSchema:Q.inputSchema}))}function hZ(X,$,Z={}){let W=vZ(X,$,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...W,...bZ]:W}function k2(X,$){if(!X||typeof X!=="object"||Array.isArray(X))return null;let Z=X[$];return typeof Z==="string"?Z:null}async function IZ(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 X0({boardId:X,cardId:$})).runFolder}async function SZ(X){let $=await IZ(X.boardId,X.cardId,X.runFolder);if(X.name===UX){let Z=k2(X.args,"path")??"",W=await B$($,Z);return TZ(W)}if(X.name===DX){let Z=k2(X.args,"path");if(!Z)return O2("read_run_folder_file requires a path.");return w1(await ZX($,Z))}return O2(`Unknown local tool "${X.name}"`)}function gZ(X,$,Z,W,Q,K="full",Y=!1){let V=new CZ(EZ,{capabilities:{tools:{}}}),j=async()=>{if(Y)return!0;if(l$(W))return!0;if(Z&&W)try{return(await X0({boardId:Z,cardId:W})).adapter.supportsImages===!0}catch{return!1}return!1};return V.setRequestHandler(yZ,async()=>({tools:hZ(X,$,{includeRunFolderTools:Boolean(Q||Z&&W),toolSurface:K,imagesSupported:await j()})})),V.setRequestHandler(RZ,async(J)=>{let{name:z,arguments:D}=J.params,N=WX(z),U=Date.now();_("mcp.tool_call_received",{frontendSessionId:$,cardId:W,toolName:N});try{if(N===UX||N===DX)return await SZ({name:N,args:D,boardId:Z,cardId:W,runFolder:Q});if(K==="read"&&!_2.has(N))throw Error(`Tool "${z}" is not available in read-only mode`);if(A2.has(N)&&!await j())throw Error(`Tool "${z}" requires a runtime that supports image input`);let H=await X.callTool($,N,D??{},void 0,W??void 0);if(_("mcp.tool_result_returned",{frontendSessionId:$,cardId:W,toolName:N,elapsedMs:Date.now()-U}),H&&typeof H==="object"&&Array.isArray(H.content)){let x=H;return N==="screenshot_board"?await fZ(x,await j()):x}return{content:[{type:"text",text:typeof H==="string"?H:JSON.stringify(H)}]}}catch(H){return _("mcp.tool_result_returned",{frontendSessionId:$,cardId:W,toolName:N,elapsedMs:Date.now()-U,hasError:!0}),{content:[{type:"text",text:H instanceof Error?H.message:"Tool call failed"}],isError:!0}}}),V}function q2(X,$){return B2({buildServer:(Z)=>gZ(X,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:$})}import NX from"node:fs/promises";import M1 from"node:os";import PX from"node:path";function C2(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function mZ(){let[X,$]=await Promise.all([m(),H$()]),Z=X.globalDefaultConfigId?X.runtimes.find((W)=>W.id===X.globalDefaultConfigId)??null:null;return{runtimes:X.runtimes,globalDefaultConfigId:X.globalDefaultConfigId,globalDefaultEffective:Z?{runFolder:Z.runFolder??M1.homedir(),modelId:Z.defaultModelId??null,configValues:Z.defaultConfigValues??{}}:null,knownAdapters:N0().map((W)=>({id:W.id,displayName:W.displayName})),readiness:$}}async function cZ(X){try{let $=await X0({boardId:X.boardId,cardId:X.cardId});return{resolved:{configId:$.entry.id,adapterId:$.entry.kind==="registered"?$.entry.adapterId:null,displayName:$.entry.displayName,runFolder:$.runFolder,modelId:$.modelId,configValues:$.configValues}}}catch($){if($ instanceof J0)return{resolved:null};throw $}}async function lZ(X){return p(($)=>{let Z=$.runtimes.find((K)=>K.kind==="registered"&&K.adapterId===X.adapterId);if(Z)return Z;let W=N0().find((K)=>K.id===X.adapterId);if(!W)throw Error(`Unknown adapterId: ${X.adapterId}`);let Q={id:C2(),kind:"registered",adapterId:X.adapterId,displayName:W.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return $.runtimes.push(Q),Q})}async function pZ(X){return p(($)=>{let Z={id:C2(),kind:"custom",displayName:X.displayName,command:X.command,args:X.args,env:X.env,runFolder:X.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return $.runtimes.push(Z),Z})}async function uZ(X){await p(($)=>{if($.runtimes=$.runtimes.filter((Z)=>Z.id!==X.runtimeConfigId),$.globalDefaultConfigId===X.runtimeConfigId)$.globalDefaultConfigId=null;for(let Z of Object.keys($.boardOverrides))if($.boardOverrides[Z].runtimeConfigId===X.runtimeConfigId)delete $.boardOverrides[Z];for(let Z of Object.keys($.cardOverrides))if($.cardOverrides[Z].runtimeConfigId===X.runtimeConfigId)delete $.cardOverrides[Z]})}async function aZ(X){await p(($)=>{let Z=$.runtimes.find((W)=>W.id===X.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);if($.globalDefaultConfigId=X.runtimeConfigId,X.runFolder!==void 0)Z.runFolder=X.runFolder;if(X.modelId!==void 0)Z.defaultModelId=X.modelId;if(X.configValues!==void 0)Z.defaultConfigValues=X.configValues})}async function dZ(X){X.boardId,await p(($)=>{if(X.runtimeConfigId===null){delete $.cardOverrides[X.cardId];return}if(!$.runtimes.some((Q)=>Q.id===X.runtimeConfigId))throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let W=$.cardOverrides[X.cardId];$.cardOverrides[X.cardId]={runtimeConfigId:X.runtimeConfigId,runFolder:X.runFolder!==void 0?X.runFolder:W?.runFolder??null,modelId:X.modelId!==void 0?X.modelId:W?.modelId??null,configValues:X.configValues!==void 0?X.configValues:W?.configValues??{}}})}async function iZ(X){let Z=(await m()).runtimes.find((Y)=>Y.id===X.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let W=a(Z),Q=await W.resolveSpawnConfig(Z),K=Z.runFolder??M1.homedir();try{let Y=await S$({spawn:{...Q,cwd:K},modelId:X.modelId??Z.defaultModelId??null,configValues:X.configValues??Z.defaultConfigValues??{}}),V=XX({adapterId:W.id,models:Y.models,currentModelId:Y.currentModelId}),j=new Date().toISOString();return await p((J)=>{let z=J.runtimes.find((D)=>D.id===X.runtimeConfigId);if(z)z.discoveredModels=V,z.discoveredConfigOptions=Y.configOptions,z.discoveredAt=j}),{ok:!0,models:V,configOptions:Y.configOptions,currentModelId:Y.currentModelId}}catch(Y){if(Y instanceof U0)throw Error(`${Y.message}${W.authHint?` ${W.authHint}`:""}`);if(Y instanceof R||Y instanceof u)throw Error(Y.message);throw Y}}async function oZ(X){let $=M1.homedir(),Z=X.path?.trim()?X.path.trim():$,W=PX.resolve(Z),Q=!0;try{if(!(await NX.stat(W)).isDirectory())W=PX.dirname(W)}catch{Q=!1,W=$}let K=[];try{K=(await NX.readdir(W,{withFileTypes:!0})).filter((j)=>j.isDirectory()&&!j.name.startsWith(".")).map((j)=>({name:j.name,path:PX.join(W,j.name)})).sort((j,J)=>j.name.localeCompare(J.name))}catch{K=[]}let Y=PX.dirname(W);return{path:W,parent:Y===W?null:Y,home:$,exists:Q,entries:K}}var R2={list:mZ,getEffectiveForCard:cZ,registerRegistered:lZ,registerCustom:pZ,unregister:uZ,setUserDefault:aZ,setCardOverride:dZ,refreshModels:iZ,browseFolder:oZ};var nZ=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function tZ(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function y2(){try{let X=await m();if(X.globalDefaultConfigId){if(X.runtimes.some((Z)=>Z.id===X.globalDefaultConfigId))return X.globalDefaultConfigId}for(let $ of nZ){if((await U$($.id))?.status!=="ready")continue;let W=null;if(await p((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((V)=>V.id===Q.globalDefaultConfigId)){W=Q.globalDefaultConfigId;return}}let K=Q.runtimes.find((Y)=>Y.kind==="registered"&&Y.adapterId===$.id);if(!K){let Y={id:tZ(),kind:"registered",adapterId:$.id,displayName:$.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Q.runtimes.push(Y),K=Y}Q.globalDefaultConfigId=K.id,W=K.id}),W)return console.log(`[ideawave-cli] using agent runtime: ${$.displayName}`),W}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch(X){return console.warn("[ideawave-cli] runtime auto-seed failed",X),null}}var rZ=120000;function sZ(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class F1{sessions=new Map;createCallId;toolCallTimeoutMs;constructor(X={}){this.createCallId=X.createCallId??sZ,this.toolCallTimeoutMs=X.toolCallTimeoutMs??rZ}register(X){let $=this.sessions.get(X.frontendSessionId);if($){if($.userId!==X.userId)this.rejectPending($,"frontend session user changed"),$.activeRunIds.clear();this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:$.pendingToolCalls,activeRunIds:$.activeRunIds,activeRunCardIds:$.activeRunCardIds});return}this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect(X,$="frontend session disconnected"){let Z=this.sessions.get(X);if(!Z)return{activeRunIds:[]};return this.sessions.delete(X),this.rejectPending(Z,$),{activeRunIds:Array.from(Z.activeRunIds)}}sessionCount(){return this.sessions.size}has(X){return this.sessions.has(X)}getUserId(X){return this.sessions.get(X)?.userId??null}setMetadata(X,$){let Z=this.sessions.get(X);if(Z)Z.tools=$}getMetadata(X){if(!X)return[];return this.sessions.get(X)?.tools??[]}sendToSession(X,$){let Z=this.sessions.get(X);if(!Z)return!1;return Z.send($),!0}callTool(X,$,Z,W,Q){if(!X)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let K=this.sessions.get(X);if(!K)return Promise.reject(Error(`Frontend session ${X} is not connected`));let Y=this.createCallId();return new Promise((V,j)=>{let J=W??(Q?this.getActiveRunIdForCard(K,Q):this.getSoleActiveRunId(K)),z=Q??(J?K.activeRunCardIds.get(J):void 0),D=Date.now(),N=setTimeout(()=>{K.pendingToolCalls.delete(Y),_("tool_queue.timeout",{frontendSessionId:X,runId:J,cardId:z,callId:Y,toolName:$,elapsedMs:Date.now()-D,queueDepth:K.pendingToolCalls.size}),j(Error(`Tool "${$}" timed out waiting for the frontend`))},this.toolCallTimeoutMs);K.pendingToolCalls.set(Y,{resolve:V,reject:j,timer:N,name:$,runId:J??null,cardId:z??null,startedAt:D}),_("tool_queue.forwarded_to_browser",{frontendSessionId:X,runId:J,cardId:z,callId:Y,toolName:$,queueDepth:K.pendingToolCalls.size}),K.send({type:"tool_call",callId:Y,name:$,args:Z,...J?{runId:J}:{},...z?{cardId:z}:{}})})}handleToolResult(X,$){let Z=this.sessions.get(X);if(!Z)return;let W=Z.pendingToolCalls.get($.callId);if(!W)return;if(Z.pendingToolCalls.delete($.callId),clearTimeout(W.timer),_("tool_queue.result_received",{frontendSessionId:X,runId:W.runId,cardId:W.cardId,callId:$.callId,toolName:W.name,elapsedMs:Date.now()-W.startedAt,queueDepth:Z.pendingToolCalls.size,ok:$.ok}),$.ok){W.resolve($.result);return}let Q=$.result;if(Q&&typeof Q==="object"&&Array.isArray(Q.content)){W.resolve({...Q,isError:!0});return}W.reject(Error($.error??"Tool execution failed"))}markRunActive(X,$,Z){let W=this.sessions.get(X);if(!W)return;if(W.activeRunIds.add($),Z)W.activeRunCardIds.set($,Z)}markRunSettled(X,$){let Z=this.sessions.get(X);if(!Z)return;Z.activeRunIds.delete($),Z.activeRunCardIds.delete($)}ownsRun(X,$){return this.sessions.get(X)?.activeRunIds.has($)??!1}rejectPending(X,$){for(let Z of X.pendingToolCalls.values())clearTimeout(Z.timer),_("tool_queue.rejected",{frontendSessionId:X.frontendSessionId,runId:Z.runId,cardId:Z.cardId,toolName:Z.name,elapsedMs:Date.now()-Z.startedAt}),Z.reject(Error($));X.pendingToolCalls.clear()}getSoleActiveRunId(X){return X.activeRunIds.size===1?X.activeRunIds.values().next().value:void 0}getActiveRunIdForCard(X,$){let Z=[...X.activeRunCardIds.entries()].filter(([W,Q])=>X.activeRunIds.has(W)&&Q===$).map(([W])=>W);return Z.length===1?Z[0]:void 0}}function b2(){return"0.0.73".trim()?"0.0.73":"dev"}var eZ=process.argv.slice(2),B1=V2(eZ,process.env);if(B1.allowRailwayPrPreviews)process.env[y0]="1";var Q0=B1.cliArgs[0],{browserKitEnabled:T0,captureEngineEnabled:X4}=B1;if(Q0==="--help"||Q0==="-h"||Q0==="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(Q0==="--version"||Q0==="-v"||Q0==="version")console.log(b2()),process.exit(0);if(Q0)console.error(`Unknown command: ${Q0}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var f0=new F1,z0=null,$4=T0?{phase:"ready",message:"Local browser-kit proxy is ready"}:{phase:"idle"},L0=new e0;function W0(X,$){f0.sendToSession(X,$)}async function Z4(X,$){try{let Z=R2[$.method],W=await Z($.params);W0(X,{type:"runtime_rpc_result",requestId:$.requestId,ok:!0,result:W})}catch(Z){W0(X,{type:"runtime_rpc_result",requestId:$.requestId,ok:!1,error:Z instanceof Error?Z.message:String(Z)})}}var v0=!1,b0=null;async function L1(){if(v0)return;if(b0)return b0;return b0=(async()=>{try{let X=await q2(f0);R1({...X,requestedPort:X.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${X.url}`);try{await i1({onStatusChange:($)=>{if(D$(),z0?.sendStatus(),$.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${$.packageName}: ${$.error??"unknown error"}`)}})}catch($){console.warn("[ideawave-cli] ACP bridge setup skipped:",$ instanceof Error?$.message:String($))}await y2(),v0=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),z0?.sendStatus()}catch(X){console.error("[ideawave-cli] failed to start agent host:",X),z0?.sendStatus(void 0,X instanceof Error?X.message:String(X))}finally{b0=null}})(),b0}if(process.env.APP_ENV!=="development"){let X=await U2();if(X)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${X}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}if(X4)s$().then((X)=>{if(X.phase==="ready")console.log("[ideawave-cli] screenshot engine ready");else if(X.phase==="failed")console.warn(`[ideawave-cli] screenshot engine setup failed: ${X.error??"unknown error"}`)});z0=await D2({registry:f0,runtime:null,mcpReady:()=>v0,capabilities:T0?[y1,E1]:[],cliVersion:b2(),browserRuntimeStatus:()=>$4,onToolMetadata:(X)=>{console.log(`[ideawave-cli] session ${X} advertised ${f0.getMetadata(X).length} tools`),L1()},onRunTurn:(X,$)=>{console.log(`[ideawave-cli] running agent turn for card ${$.cardId} (session ${X})`),(async()=>{if(await L1(),!v0){W0(X,{type:"run_settled",runId:$.runId,cardId:$.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await d$($,(Z)=>W0(X,Z))})().catch(()=>{return}).finally(()=>f0.markRunSettled(X,$.runId))},onCancelRun:(X,$)=>{Q1($)},onRuntimeRpc:(X,$)=>{Z4(X,$)},onBrowserRpc:(X,$,Z)=>{if(!T0){W0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!1,error:"The development browser-kit proxy is not enabled"});return}L0.handleRpc(X,$,Z).then((W)=>{W0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!0,result:W})},(W)=>{W0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!1,error:W instanceof Error?W.message:String(W)})})},onHttpRequest:(X,$)=>T0?L0.handleHttpRequest(X,$):!1,onHttpUpgrade:(X,$,Z)=>T0?L0.handleUpgrade(X,$,Z):!1,onWarmupRun:(X,$,Z)=>{(async()=>{if(await L1(),!v0)return{status:"retryable",error:"agent host is not ready"};return i$({cardId:$.cardId,boardId:$.boardId,userId:Z,frontendSessionId:X})})().then((W)=>{if(!$.warmupId)return;W0(X,{type:"warmup_result",warmupId:$.warmupId,cardId:$.cardId,...W})})},onDisconnect:(X,$)=>{L0.closeFrontendSession(X),p$(X);for(let Z of $)Q1(Z);_("bridge.frontend_disconnected",{frontendSessionId:X,activeRuns:$.length}),_1(X).catch((Z)=>{console.warn(`[ideawave-cli] failed to evict sessions for ${X}:`,Z instanceof Error?Z.message:String(Z))}),console.log(`[ideawave-cli] browser session ${X} disconnected`)}});L0.setPort(z0.port);console.log(`[ideawave-cli] browser bridge listening on ${z0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var E2=!1;for(let X of["SIGINT","SIGTERM"])process.once(X,()=>{if(E2)return;E2=!0,u$(),(async()=>{await L0.close(),await $2(),await z0?.close().catch(()=>{return}),process.exit(0)})()});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideawave",
3
- "version": "0.0.72",
3
+ "version": "0.0.73",
4
4
  "description": "IdeaWave CLI",
5
5
  "type": "module",
6
6
  "bin": {