ideawave 0.0.61 → 0.0.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +3 -3
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{createRequire as a3}from"node:module";var i3=a3(import.meta.url);function p3(){let Z=globalThis.performance?.now?.()??Date.now();return Math.round(Z*10)/10}function m(Z,Q={}){if(typeof process<"u"&&process.env.IDEAWAVE_AGENT_RUNTIME_TRACE==="0")return;let X=Object.fromEntries(Object.entries(Q).filter(([,K])=>K!==void 0));console.info("[agent-runtime-trace]",JSON.stringify({event:Z,epochMs:Date.now(),monotonicMs:p3(),...typeof document>"u"?{}:{visibility:document.visibilityState},...X}))}var s3=600000,r3=60000,y6=200,o3=2,u=new Map,F0=null;function n3(Z){Z.then((Q)=>Q.dispose()).catch(()=>{return})}function L1(Z){for(let Q of Z.idleWaiters)Q();Z.idleWaiters.clear()}function x0(Z,Q){if(u.get(Z)!==Q)return;u.delete(Z),L1(Q),n3(Q.sessionPromise)}function t3(){if(F0!==null)return;F0=setInterval(()=>{let Z=Date.now();for(let[Q,X]of u){if(X.inUse)continue;if(Z-X.lastUsed<s3)continue;x0(Q,X)}if(u.size===0&&F0!==null)clearInterval(F0),F0=null},r3),F0.unref?.()}function e3(){if(u.size<y6)return;let Z=null,Q=1/0;for(let[K,Y]of u){if(Y.inUse)continue;if(Y.lastUsed>=Q)continue;Z=K,Q=Y.lastUsed}if(!Z)return;let X=u.get(Z);if(!X)return;x0(Z,X)}function Z7(){let Z=0;while(u.size>y6){let Q=null,X=null;for(let[K,Y]of u){if(Y.inUse)continue;if(X&&Y.lastUsed>=X.lastUsed)continue;Q=K,X=Y}if(!Q||!X)break;x0(Q,X),Z+=1}if(Z>0)m("session_pool.global_idle_trimmed",{evictedSessions:Z,poolEntries:u.size})}function Q7(Z){let Q=Array.from(u.entries()).filter(([,K])=>K.frontendSessionId===Z&&!K.inUse).sort(([,K],[,Y])=>K.lastUsed-Y.lastUsed),X=Q.length-o3;if(X<=0)return;for(let[K,Y]of Q.slice(0,X))x0(K,Y);m("session_pool.frontend_idle_trimmed",{frontendSessionId:Z,evictedSessions:X,poolEntries:u.size})}function Y4(Z,Q,X){return`${Z}:${Q}:${X}`}async function P1(Z){let Q=u.get(Z.key);if(Q){if(Q.inUse)return m("session_pool.wait_for_idle",{frontendSessionId:Q.frontendSessionId,poolEntries:u.size}),await new Promise((K)=>Q.idleWaiters.add(K)),P1(Z);if(Q.fingerprint===Z.fingerprint){Q.inUse=!0,Q.lastUsed=Date.now();try{let K=await Q.sessionPromise;if(K.isAlive()){if(Q.frontendSessionId)m("session_pool.reuse",{frontendSessionId:Q.frontendSessionId,poolEntries:u.size});return K}}catch{}x0(Z.key,Q)}else x0(Z.key,Q)}let X=Z.open();if(e3(),u.set(Z.key,{key:Z.key,frontendSessionId:Z.frontendSessionId??null,fingerprint:Z.fingerprint,sessionPromise:X,lastUsed:Date.now(),inUse:!0,idleWaiters:new Set}),t3(),Z.frontendSessionId)m("session_pool.open",{frontendSessionId:Z.frontendSessionId,poolEntries:u.size});try{return await X}catch(K){let Y=u.get(Z.key);if(Y?.sessionPromise===X)x0(Z.key,Y);throw K}}function W4(Z,Q=!1){let X=u.get(Z);if(!X)return;if(Q){x0(Z,X);return}if(X.inUse=!1,X.lastUsed=Date.now(),X.frontendSessionId)Q7(X.frontendSessionId),m("session_pool.release",{frontendSessionId:X.frontendSessionId,poolEntries:u.size});if(Z7(),u.get(Z)===X)L1(X)}async function f6(Z){let Q=Array.from(u.entries()).filter(([,X])=>X.frontendSessionId===Z);for(let[X,K]of Q)u.delete(X),L1(K);return await Promise.all(Q.map(([,X])=>X.sessionPromise.then((K)=>K.dispose()).catch(()=>{return}))),m("session_pool.frontend_evicted",{frontendSessionId:Z,evictedSessions:Q.length,poolEntries:u.size}),Q.length}async function X7(){let Z=Array.from(u.values());u.clear();for(let Q of Z)L1(Q);if(F0!==null)clearInterval(F0),F0=null;await Promise.all(Z.map((Q)=>Q.sessionPromise.then((X)=>X.dispose()).catch(()=>{return})))}function V4(Z){let Q=Object.entries(Z.configValues??{}),X=Q.length>0?JSON.stringify(Object.fromEntries(Q.sort(([K],[Y])=>K.localeCompare(Y)))):"";return[Z.adapterId,Z.configId??"",Z.modelId??"",X,Z.mcpUrl??"",Z.runFolder??"",Z.toolSurface??"full"].join(" ")}var R6=!1;function J7(){if(R6)return;R6=!0;let Z=()=>{X7()};process.once("beforeExit",Z),process.once("SIGTERM",Z),process.once("SIGINT",Z)}J7();import{readFileSync as W7}from"node:fs";import{homedir as K7}from"node:os";import{join as x1}from"node:path";function Y7(){let Z=K7();switch(process.platform){case"win32":return process.env.APPDATA??x1(Z,"AppData","Roaming");case"darwin":return x1(Z,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??x1(Z,".config")}}function h6(){let Z=process.env.IDEAWAVE_MCP_JSON_PATH;if(Z&&Z.trim().length>0)return Z;return x1(Y7(),"ideawave","mcp.json")}var N6=null;function D6(Z){N6=Z}var V7=86400000;function H7(){let Z;try{Z=W7(h6(),"utf8")}catch{return null}let Q;try{Q=JSON.parse(Z)}catch{return null}if(typeof Q.url!=="string")return null;if(typeof Q.startedAt==="string"){let X=Date.parse(Q.startedAt);if(!Number.isNaN(X)){if(Date.now()-X>V7)return null}}if(typeof Q.pid==="number"&&Q.pid>0)try{process.kill(Q.pid,0)}catch(X){if(X?.code!=="EPERM")return null}return{url:Q.url}}function M6(Z,Q={}){let X=[];if(Q.userId&&Q.userId.trim().length>0)X.push({name:"X-Ideawave-User-Id",value:Q.userId.trim()});if(Q.frontendSessionId&&Q.frontendSessionId.trim().length>0)X.push({name:"X-Ideawave-Frontend-Session-Id",value:Q.frontendSessionId.trim()});if(Q.toolSurface==="read")X.push({name:"X-Ideawave-Tool-Surface",value:"read"});if(Q.imagesSupported)X.push({name:"X-Ideawave-Images-Supported",value:"1"});if(Q.cardId&&Q.cardId.trim().length>0)X.push({name:"X-Ideawave-Card-Id",value:Q.cardId.trim()});if(Q.boardId&&Q.boardId.trim().length>0)X.push({name:"X-Ideawave-Board-Id",value:Q.boardId.trim()});if(Q.runFolder&&Q.runFolder.trim().length>0)X.push({name:"X-Ideawave-Run-Folder",value:Q.runFolder.trim()});return{type:"http",name:"ideawave-board",url:Z,headers:X}}function H4(Z={}){let Q=N6;if(Q)return M6(Q.url,Z);let X=H7();if(!X)return null;return M6(X.url,Z)}var $6="browser-proxy-v2",G6="browser-proxy-v3",j7=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 b1(Z){try{let Q=JSON.parse(Z);if(Q&&typeof Q==="object"&&typeof Q.type==="string"&&j7.has(Q.type))return Q}catch{}return null}function O1(Z){return JSON.stringify(Z)}import i0 from"node:fs/promises";import F7 from"node:path";import{z as h}from"zod";var g6=h.object({id:h.string(),name:h.string().nullable().default(null),description:h.string().nullable().default(null)}),k6=h.union([h.string(),h.boolean()]),z7=h.object({value:h.string(),name:h.string(),description:h.string().nullable().default(null),group:h.string().nullable().default(null),groupName:h.string().nullable().default(null)}),E6=h.object({id:h.string(),name:h.string(),category:h.string().nullable().default(null),description:h.string().nullable().default(null),type:h.enum(["select","boolean"]),currentValue:k6.nullable().default(null),options:h.array(z7).default([])}),j4=h.record(h.string(),k6).default({}),q7=h.discriminatedUnion("kind",[h.object({id:h.string(),kind:h.literal("registered"),adapterId:h.enum(["claude-code","opencode","codex","copilot"]),displayName:h.string(),runFolder:h.string().nullable(),defaultModelId:h.string().nullable().default(null),defaultConfigValues:j4,discoveredModels:h.array(g6).default([]),discoveredConfigOptions:h.array(E6).default([]),discoveredAt:h.string().nullable().default(null)}),h.object({id:h.string(),kind:h.literal("custom"),displayName:h.string(),command:h.string(),args:h.array(h.string()),env:h.record(h.string(),h.string()),runFolder:h.string().nullable(),defaultModelId:h.string().nullable().default(null),defaultConfigValues:j4,discoveredModels:h.array(g6).default([]),discoveredConfigOptions:h.array(E6).default([]),discoveredAt:h.string().nullable().default(null)})]),m6=h.object({runtimeConfigId:h.string(),runFolder:h.string().nullable(),modelId:h.string().nullable().default(null),configValues:j4}),C1=h.object({version:h.literal(1),globalDefaultConfigId:h.string().nullable(),runtimes:h.array(q7),boardOverrides:h.record(h.string(),m6).default({}),cardOverrides:h.record(h.string(),m6).default({})});import U7 from"node:os";import v1 from"node:path";function B7(){let Z=U7.homedir();switch(process.platform){case"win32":return process.env.APPDATA??v1.join(Z,"AppData","Roaming");case"darwin":return v1.join(Z,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??v1.join(Z,".config")}}function R1(){let Z=process.env.IDEAWAVE_RUNTIME_CONFIG_PATH;if(Z)return Z;return v1.join(B7(),"ideawave","runtimes.json")}var w7={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},_6=new Map;function L7(Z){return _6.get(Z)??Promise.resolve()}function P7(Z,Q){_6.set(Z,Q)}async function J0(Z){let Q=Z??R1(),X;try{X=await i0.readFile(Q,"utf-8")}catch(Y){if(Y.code==="ENOENT")return structuredClone(w7);throw Y}return C1.parse(JSON.parse(X))}async function V0(Z,Q){let X=Q??R1(),K=L7(X).then(async()=>{let Y=await J0(X),W=structuredClone(Y),z=await Z(W);return await x7(W,X),z});return P7(X,K.catch(()=>{return})),K}async function x7(Z,Q){let X=Q??R1(),K=F7.dirname(X);await i0.mkdir(K,{recursive:!0});let Y=`${X}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`,W=JSON.stringify(Z,null,2);await i0.writeFile(Y,W,"utf-8");try{await i0.rename(Y,X)}catch(z){throw await i0.unlink(Y).catch(()=>{return}),z}}import{spawn as N7}from"node:child_process";import{closeSync as D7,existsSync as A6,mkdirSync as l6,openSync as $7,readFileSync as G7,renameSync as g7,rmSync as c6,statSync as E7,unlinkSync as m7,writeFileSync as k7}from"node:fs";import u6 from"node:os";import $0 from"node:path";var b7=/\.(?:cmd|bat)$/i;function O7(Z){return process.platform==="win32"&&b7.test(Z)}function y1(Z){return O7(Z)?{shell:!0,windowsHide:!0}:{}}import{execFile as h7}from"node:child_process";import{promisify as M7}from"node:util";import{execFile as C7}from"node:child_process";import{promisify as v7}from"node:util";var R7=v7(C7),z4=new Map,S6=5000,y7=/\.(?:cmd|bat|com|exe)$/i;function f7(Z){let Q=Z.split(/\r?\n/).map((X)=>X.trim()).filter((X)=>X.length>0);if(Q.length===0)return null;if(process.platform!=="win32")return Q[0]??null;return Q.find((X)=>y7.test(X))??Q[0]??null}async function I6(Z,Q=R7){let X=z4.get(Z);if(X&&X.expiresAt>Date.now())return X.value;let K=process.platform==="win32"?"where":"which";try{let{stdout:Y}=await Q(K,[Z],{timeout:2000}),W=f7(Y);return z4.set(Z,{value:W,expiresAt:Date.now()+S6}),W}catch{return z4.set(Z,{value:null,expiresAt:Date.now()+S6}),null}}class p0 extends Error{code;constructor(Z,Q){super(Z);this.name="AcpError",this.code=Q}}class D0 extends p0{constructor(Z="No ACP runtime configured"){super(Z,"RUNTIME_NOT_CONFIGURED");this.name="RuntimeNotConfiguredError"}}class S extends p0{constructor(Z){super(Z,"RUNTIME_UNREACHABLE");this.name="RuntimeUnreachableError"}}class I0 extends p0{authMethods;constructor(Z,Q){super(Z,"AUTH_REQUIRED");this.name="AuthRequiredError",this.authMethods=Q}}class q0 extends p0{constructor(Z="ACP session timed out"){super(Z,"SESSION_TIMEOUT");this.name="SessionTimeoutError"}}var OJ=M7(h7);function d(Z,...Q){return I6(Z,...Q)}function X0(Z){let Q={};for(let[X,K]of Object.entries(process.env))if(typeof K==="string")Q[X]=K;return{...Q,...Z??{}}}var U4=[{adapterId:"claude-code",runtimeBinary:"claude",packageName:"@agentclientprotocol/claude-agent-acp",version:"0.50.0",warmupArgs:["--cli","--help"]},{adapterId:"codex",runtimeBinary:"codex",packageName:"@agentclientprotocol/codex-acp",version:"1.0.2",warmupArgs:["--version"]}],_7=1800000,f1=new Map;function B4(){if(process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR)return process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR;if(process.platform==="win32"){let Z=process.env.LOCALAPPDATA??$0.join(u6.homedir(),"AppData","Local");return $0.join(Z,"ideawave","acp-bridges")}return $0.join(process.env.XDG_CACHE_HOME??$0.join(u6.homedir(),".cache"),"ideawave","acp-bridges")}function S7(Z){return Z.replace(/^@/,"").replace(/[/\\]/g,"-")}function h1(){return $0.join(B4(),"install-state.json")}function F4(Z){return $0.join(B4(),`${S7(Z.packageName)}@${Z.version}.install.lock`)}function w4(){return process.platform==="win32"?"npx.cmd":"npx"}function L4(Z){return`${Z.packageName}@${Z.version}`}function d6(){let Z=h1();if(!A6(Z))return{};try{return JSON.parse(G7(Z,"utf8"))}catch{return{}}}function q4(Z,Q){let X=B4();l6(X,{recursive:!0});let K=d6();K.bridges={...K.bridges??{},[Z.adapterId]:Q},k7(`${h1()}.tmp`,`${JSON.stringify(K,null,2)}
2
+ import{createRequire as a3}from"node:module";var i3=a3(import.meta.url);function p3(){let Z=globalThis.performance?.now?.()??Date.now();return Math.round(Z*10)/10}function m(Z,Q={}){if(typeof process<"u"&&process.env.IDEAWAVE_AGENT_RUNTIME_TRACE==="0")return;let X=Object.fromEntries(Object.entries(Q).filter(([,K])=>K!==void 0));console.info("[agent-runtime-trace]",JSON.stringify({event:Z,epochMs:Date.now(),monotonicMs:p3(),...typeof document>"u"?{}:{visibility:document.visibilityState},...X}))}var s3=600000,r3=60000,y6=200,o3=2,u=new Map,F0=null;function n3(Z){Z.then((Q)=>Q.dispose()).catch(()=>{return})}function L1(Z){for(let Q of Z.idleWaiters)Q();Z.idleWaiters.clear()}function x0(Z,Q){if(u.get(Z)!==Q)return;u.delete(Z),L1(Q),n3(Q.sessionPromise)}function t3(){if(F0!==null)return;F0=setInterval(()=>{let Z=Date.now();for(let[Q,X]of u){if(X.inUse)continue;if(Z-X.lastUsed<s3)continue;x0(Q,X)}if(u.size===0&&F0!==null)clearInterval(F0),F0=null},r3),F0.unref?.()}function e3(){if(u.size<y6)return;let Z=null,Q=1/0;for(let[K,Y]of u){if(Y.inUse)continue;if(Y.lastUsed>=Q)continue;Z=K,Q=Y.lastUsed}if(!Z)return;let X=u.get(Z);if(!X)return;x0(Z,X)}function Z7(){let Z=0;while(u.size>y6){let Q=null,X=null;for(let[K,Y]of u){if(Y.inUse)continue;if(X&&Y.lastUsed>=X.lastUsed)continue;Q=K,X=Y}if(!Q||!X)break;x0(Q,X),Z+=1}if(Z>0)m("session_pool.global_idle_trimmed",{evictedSessions:Z,poolEntries:u.size})}function Q7(Z){let Q=Array.from(u.entries()).filter(([,K])=>K.frontendSessionId===Z&&!K.inUse).sort(([,K],[,Y])=>K.lastUsed-Y.lastUsed),X=Q.length-o3;if(X<=0)return;for(let[K,Y]of Q.slice(0,X))x0(K,Y);m("session_pool.frontend_idle_trimmed",{frontendSessionId:Z,evictedSessions:X,poolEntries:u.size})}function Y4(Z,Q,X){return`${Z}:${Q}:${X}`}async function P1(Z){let Q=u.get(Z.key);if(Q){if(Q.inUse)return m("session_pool.wait_for_idle",{frontendSessionId:Q.frontendSessionId,poolEntries:u.size}),await new Promise((K)=>Q.idleWaiters.add(K)),P1(Z);if(Q.fingerprint===Z.fingerprint){Q.inUse=!0,Q.lastUsed=Date.now();try{let K=await Q.sessionPromise;if(K.isAlive()){if(Q.frontendSessionId)m("session_pool.reuse",{frontendSessionId:Q.frontendSessionId,poolEntries:u.size});return K}}catch{}x0(Z.key,Q)}else x0(Z.key,Q)}let X=Z.open();if(e3(),u.set(Z.key,{key:Z.key,frontendSessionId:Z.frontendSessionId??null,fingerprint:Z.fingerprint,sessionPromise:X,lastUsed:Date.now(),inUse:!0,idleWaiters:new Set}),t3(),Z.frontendSessionId)m("session_pool.open",{frontendSessionId:Z.frontendSessionId,poolEntries:u.size});try{return await X}catch(K){let Y=u.get(Z.key);if(Y?.sessionPromise===X)x0(Z.key,Y);throw K}}function W4(Z,Q=!1){let X=u.get(Z);if(!X)return;if(Q){x0(Z,X);return}if(X.inUse=!1,X.lastUsed=Date.now(),X.frontendSessionId)Q7(X.frontendSessionId),m("session_pool.release",{frontendSessionId:X.frontendSessionId,poolEntries:u.size});if(Z7(),u.get(Z)===X)L1(X)}async function f6(Z){let Q=Array.from(u.entries()).filter(([,X])=>X.frontendSessionId===Z);for(let[X,K]of Q)u.delete(X),L1(K);return await Promise.all(Q.map(([,X])=>X.sessionPromise.then((K)=>K.dispose()).catch(()=>{return}))),m("session_pool.frontend_evicted",{frontendSessionId:Z,evictedSessions:Q.length,poolEntries:u.size}),Q.length}async function X7(){let Z=Array.from(u.values());u.clear();for(let Q of Z)L1(Q);if(F0!==null)clearInterval(F0),F0=null;await Promise.all(Z.map((Q)=>Q.sessionPromise.then((X)=>X.dispose()).catch(()=>{return})))}function V4(Z){let Q=Object.entries(Z.configValues??{}),X=Q.length>0?JSON.stringify(Object.fromEntries(Q.sort(([K],[Y])=>K.localeCompare(Y)))):"";return[Z.adapterId,Z.configId??"",Z.modelId??"",X,Z.mcpUrl??"",Z.runFolder??"",Z.toolSurface??"full"].join(" ")}var R6=!1;function J7(){if(R6)return;R6=!0;let Z=()=>{X7()};process.once("beforeExit",Z),process.once("SIGTERM",Z),process.once("SIGINT",Z)}J7();import{readFileSync as W7}from"node:fs";import{homedir as K7}from"node:os";import{join as x1}from"node:path";function Y7(){let Z=K7();switch(process.platform){case"win32":return process.env.APPDATA??x1(Z,"AppData","Roaming");case"darwin":return x1(Z,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??x1(Z,".config")}}function h6(){let Z=process.env.IDEAWAVE_MCP_JSON_PATH;if(Z&&Z.trim().length>0)return Z;return x1(Y7(),"ideawave","mcp.json")}var N6=null;function D6(Z){N6=Z}var V7=86400000;function H7(){let Z;try{Z=W7(h6(),"utf8")}catch{return null}let Q;try{Q=JSON.parse(Z)}catch{return null}if(typeof Q.url!=="string")return null;if(typeof Q.startedAt==="string"){let X=Date.parse(Q.startedAt);if(!Number.isNaN(X)){if(Date.now()-X>V7)return null}}if(typeof Q.pid==="number"&&Q.pid>0)try{process.kill(Q.pid,0)}catch(X){if(X?.code!=="EPERM")return null}return{url:Q.url}}function M6(Z,Q={}){let X=[];if(Q.userId&&Q.userId.trim().length>0)X.push({name:"X-Ideawave-User-Id",value:Q.userId.trim()});if(Q.frontendSessionId&&Q.frontendSessionId.trim().length>0)X.push({name:"X-Ideawave-Frontend-Session-Id",value:Q.frontendSessionId.trim()});if(Q.toolSurface==="read")X.push({name:"X-Ideawave-Tool-Surface",value:"read"});if(Q.imagesSupported)X.push({name:"X-Ideawave-Images-Supported",value:"1"});if(Q.cardId&&Q.cardId.trim().length>0)X.push({name:"X-Ideawave-Card-Id",value:Q.cardId.trim()});if(Q.boardId&&Q.boardId.trim().length>0)X.push({name:"X-Ideawave-Board-Id",value:Q.boardId.trim()});if(Q.runFolder&&Q.runFolder.trim().length>0)X.push({name:"X-Ideawave-Run-Folder",value:Q.runFolder.trim()});return{type:"http",name:"ideawave-board",url:Z,headers:X}}function H4(Z={}){let Q=N6;if(Q)return M6(Q.url,Z);let X=H7();if(!X)return null;return M6(X.url,Z)}var $6="browser-proxy-v2",G6="browser-proxy-v3",j7=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 b1(Z){try{let Q=JSON.parse(Z);if(Q&&typeof Q==="object"&&typeof Q.type==="string"&&j7.has(Q.type))return Q}catch{}return null}function O1(Z){return JSON.stringify(Z)}import i0 from"node:fs/promises";import F7 from"node:path";import{z as h}from"zod";var g6=h.object({id:h.string(),name:h.string().nullable().default(null),description:h.string().nullable().default(null)}),k6=h.union([h.string(),h.boolean()]),z7=h.object({value:h.string(),name:h.string(),description:h.string().nullable().default(null),group:h.string().nullable().default(null),groupName:h.string().nullable().default(null)}),E6=h.object({id:h.string(),name:h.string(),category:h.string().nullable().default(null),description:h.string().nullable().default(null),type:h.enum(["select","boolean"]),currentValue:k6.nullable().default(null),options:h.array(z7).default([])}),j4=h.record(h.string(),k6).default({}),q7=h.discriminatedUnion("kind",[h.object({id:h.string(),kind:h.literal("registered"),adapterId:h.enum(["claude-code","opencode","codex","copilot"]),displayName:h.string(),runFolder:h.string().nullable(),defaultModelId:h.string().nullable().default(null),defaultConfigValues:j4,discoveredModels:h.array(g6).default([]),discoveredConfigOptions:h.array(E6).default([]),discoveredAt:h.string().nullable().default(null)}),h.object({id:h.string(),kind:h.literal("custom"),displayName:h.string(),command:h.string(),args:h.array(h.string()),env:h.record(h.string(),h.string()),runFolder:h.string().nullable(),defaultModelId:h.string().nullable().default(null),defaultConfigValues:j4,discoveredModels:h.array(g6).default([]),discoveredConfigOptions:h.array(E6).default([]),discoveredAt:h.string().nullable().default(null)})]),m6=h.object({runtimeConfigId:h.string(),runFolder:h.string().nullable(),modelId:h.string().nullable().default(null),configValues:j4}),C1=h.object({version:h.literal(1),globalDefaultConfigId:h.string().nullable(),runtimes:h.array(q7),boardOverrides:h.record(h.string(),m6).default({}),cardOverrides:h.record(h.string(),m6).default({})});import U7 from"node:os";import v1 from"node:path";function B7(){let Z=U7.homedir();switch(process.platform){case"win32":return process.env.APPDATA??v1.join(Z,"AppData","Roaming");case"darwin":return v1.join(Z,"Library","Application Support");default:return process.env.XDG_CONFIG_HOME??v1.join(Z,".config")}}function R1(){let Z=process.env.IDEAWAVE_RUNTIME_CONFIG_PATH;if(Z)return Z;return v1.join(B7(),"ideawave","runtimes.json")}var w7={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},_6=new Map;function L7(Z){return _6.get(Z)??Promise.resolve()}function P7(Z,Q){_6.set(Z,Q)}async function J0(Z){let Q=Z??R1(),X;try{X=await i0.readFile(Q,"utf-8")}catch(Y){if(Y.code==="ENOENT")return structuredClone(w7);throw Y}return C1.parse(JSON.parse(X))}async function V0(Z,Q){let X=Q??R1(),K=L7(X).then(async()=>{let Y=await J0(X),W=structuredClone(Y),z=await Z(W);return await x7(W,X),z});return P7(X,K.catch(()=>{return})),K}async function x7(Z,Q){let X=Q??R1(),K=F7.dirname(X);await i0.mkdir(K,{recursive:!0});let Y=`${X}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`,W=JSON.stringify(Z,null,2);await i0.writeFile(Y,W,"utf-8");try{await i0.rename(Y,X)}catch(z){throw await i0.unlink(Y).catch(()=>{return}),z}}import{spawn as N7}from"node:child_process";import{closeSync as D7,existsSync as A6,mkdirSync as l6,openSync as $7,readFileSync as G7,renameSync as g7,rmSync as c6,statSync as E7,unlinkSync as m7,writeFileSync as k7}from"node:fs";import u6 from"node:os";import $0 from"node:path";var b7=/\.(?:cmd|bat)$/i;function O7(Z){return process.platform==="win32"&&b7.test(Z)}function y1(Z){return O7(Z)?{shell:!0,windowsHide:!0}:{}}import{execFile as h7}from"node:child_process";import{promisify as M7}from"node:util";import{execFile as C7}from"node:child_process";import{promisify as v7}from"node:util";var R7=v7(C7),z4=new Map,S6=5000,y7=/\.(?:cmd|bat|com|exe)$/i;function f7(Z){let Q=Z.split(/\r?\n/).map((X)=>X.trim()).filter((X)=>X.length>0);if(Q.length===0)return null;if(process.platform!=="win32")return Q[0]??null;return Q.find((X)=>y7.test(X))??Q[0]??null}async function I6(Z,Q=R7){let X=z4.get(Z);if(X&&X.expiresAt>Date.now())return X.value;let K=process.platform==="win32"?"where":"which";try{let{stdout:Y}=await Q(K,[Z],{timeout:2000}),W=f7(Y);return z4.set(Z,{value:W,expiresAt:Date.now()+S6}),W}catch{return z4.set(Z,{value:null,expiresAt:Date.now()+S6}),null}}class p0 extends Error{code;constructor(Z,Q){super(Z);this.name="AcpError",this.code=Q}}class D0 extends p0{constructor(Z="No ACP runtime configured"){super(Z,"RUNTIME_NOT_CONFIGURED");this.name="RuntimeNotConfiguredError"}}class S extends p0{constructor(Z){super(Z,"RUNTIME_UNREACHABLE");this.name="RuntimeUnreachableError"}}class I0 extends p0{authMethods;constructor(Z,Q){super(Z,"AUTH_REQUIRED");this.name="AuthRequiredError",this.authMethods=Q}}class q0 extends p0{constructor(Z="ACP session timed out"){super(Z,"SESSION_TIMEOUT");this.name="SessionTimeoutError"}}var OJ=M7(h7);function d(Z,...Q){return I6(Z,...Q)}function X0(Z){let Q={};for(let[X,K]of Object.entries(process.env))if(typeof K==="string")Q[X]=K;return{...Q,...Z??{}}}var U4=[{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"]}],_7=1800000,f1=new Map;function B4(){if(process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR)return process.env.IDEAWAVE_ACP_BRIDGE_CACHE_DIR;if(process.platform==="win32"){let Z=process.env.LOCALAPPDATA??$0.join(u6.homedir(),"AppData","Local");return $0.join(Z,"ideawave","acp-bridges")}return $0.join(process.env.XDG_CACHE_HOME??$0.join(u6.homedir(),".cache"),"ideawave","acp-bridges")}function S7(Z){return Z.replace(/^@/,"").replace(/[/\\]/g,"-")}function h1(){return $0.join(B4(),"install-state.json")}function F4(Z){return $0.join(B4(),`${S7(Z.packageName)}@${Z.version}.install.lock`)}function w4(){return process.platform==="win32"?"npx.cmd":"npx"}function L4(Z){return`${Z.packageName}@${Z.version}`}function d6(){let Z=h1();if(!A6(Z))return{};try{return JSON.parse(G7(Z,"utf8"))}catch{return{}}}function q4(Z,Q){let X=B4();l6(X,{recursive:!0});let K=d6();K.bridges={...K.bridges??{},[Z.adapterId]:Q},k7(`${h1()}.tmp`,`${JSON.stringify(K,null,2)}
3
3
  `),g7(`${h1()}.tmp`,h1())}function a6(Z){return U4.find((Q)=>Q.packageName===Z)??null}function K0(Z,Q,X){return{adapterId:Z.adapterId,packageName:Z.packageName,version:Z.version,status:Q,...X?{error:X}:{}}}function T6(Z,Q){return Q?.packageName===Z.packageName&&Q.version===Z.version}function i6(Z){try{return Date.now()-E7(Z).mtimeMs>_7}catch{return!1}}function I7(Z){let Q=F4(Z);if(!A6(Q))return!1;if(i6(Q))return c6(Q,{force:!0}),!1;return!0}function u7(Z){let Q=F4(Z);if(l6($0.dirname(Q),{recursive:!0}),i6(Q))c6(Q,{force:!0});try{let X=$7(Q,"wx");return D7(X),!0}catch{return!1}}function T7(Z){m7(F4(Z))}function P4(Z){let Q=d6().bridges?.[Z.adapterId];if(T6(Z,Q)&&Q.status==="ready")return K0(Z,"ready");if(f1.has(Z.adapterId)||I7(Z))return K0(Z,"installing");if(T6(Z,Q)&&Q.status==="failed")return K0(Z,"failed",Q.error);return K0(Z,"missing")}function s0(Z,Q){Z?.onStatusChange?.(Q)}function A7(Z,Q){let X=P4(Z);if(X.status==="ready")return s0(Q,X),X;if(X.status==="installing"){let q=f1.get(Z.adapterId);if(q&&Q?.onStatusChange)q.then((b)=>s0(Q,b));return s0(Q,X),X}if(!u7(Z))return K0(Z,"installing");let K=K0(Z,"installing");q4(Z,K),s0(Q,K);let Y=()=>{},W=new Promise((q)=>{Y=q});f1.set(Z.adapterId,W);let z=!1,B=(q)=>{if(z)return;z=!0;try{T7(Z)}catch{}q4(Z,q),s0(Q,q),f1.delete(Z.adapterId),Y(q)},w;try{let q=w4();w=N7(q,["-y",L4(Z),...Z.warmupArgs],{stdio:"ignore",windowsHide:!0,...y1(q)})}catch(q){let b=K0(Z,"failed",q instanceof Error?q.message:String(q));return B(b),b}return w.on("error",(q)=>{B(K0(Z,"failed",q.message))}),w.on("close",(q)=>{if(q===0){B(K0(Z,"ready"));return}B(K0(Z,"failed",`npx warmup exited ${q??"null"}`))}),w.unref(),K}function u0(Z){let Q=a6(Z);return Q?P4(Q):null}async function p6(Z){let Q=[];for(let X of U4){if(!await d(X.runtimeBinary)){Q.push(K0(X,"not_needed"));continue}Q.push(A7(X,Z))}return Q.filter((X)=>X.status!=="not_needed")}function M1(Z){let Q=a6(Z);if(!Q)return null;if(P4(Q).status!=="ready")return null;return{command:w4(),args:["-y",L4(Q)],env:{}}}function x4(Z,Q){if(Z.command!==w4())return!1;let X=U4.find((K)=>Z.args.includes(L4(K)));if(!X)return!1;return q4(X,K0(X,"failed",Q)),!0}var s6="claude",b4="@agentclientprotocol/claude-agent-acp",r6=["claude-agent-acp","claude-code-acp"],o6="Install Claude Code from https://github.com/anthropics/claude-code",n6={id:"claude-code",displayName:"Claude Code",kind:"registered",supportsImages:!0,resolveSpawnConfig:async()=>{if(!await d(s6))throw new S(`Claude Code CLI not found. ${o6}`);let Q=M1(b4);if(Q)return{command:Q.command,args:Q.args,env:X0(Q.env)};let X=u0(b4),K=X?.status==="installing";for(let W of r6){let z=await d(W);if(z&&!K&&X?.status!=="failed")return{command:z,args:[],env:X0()}}let Y=X?.status==="failed"?`Claude Code ACP bridge install failed. ${X.error??"Restart IdeaWave CLI so it can warm the pinned bridge again."}`:"Claude Code ACP bridge is not ready. Keep IdeaWave CLI running and retry in a moment.";throw new S(Y)},checkReadiness:async()=>{if(!await d(s6))return{status:"not_installed",detail:o6};let Q=u0(b4);if(Q?.status==="ready")return{status:"ready"};if(Q?.status==="installing")return{status:"not_running",detail:"Installing Claude Code ACP bridge..."};if(Q?.status==="failed")return{status:"not_running",detail:Q.error??"Claude Code ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};for(let X of r6)if(await d(X))return{status:"ready"};return{status:"not_running",detail:"Installing Claude Code ACP bridge..."}},authHint:"Run `claude login` (or set ANTHROPIC_API_KEY)."};var t6="codex",O4="@agentclientprotocol/codex-acp",e6="codex-acp",Z2="Install Codex CLI from https://developers.openai.com/codex/cli",Q2={id:"codex",displayName:"Codex",kind:"registered",resolveSpawnConfig:async()=>{if(!await d(t6))throw new S(`Codex CLI not found. ${Z2}`);let Q=M1(O4);if(Q)return{command:Q.command,args:Q.args,env:X0(Q.env)};let X=u0(O4),K=X?.status==="installing",Y=await d(e6);if(Y&&!K&&X?.status!=="failed")return{command:Y,args:[],env:X0()};let W=X?.status==="failed"?`Codex ACP bridge install failed. ${X.error??"Restart IdeaWave CLI so it can warm the pinned bridge again."}`:"Codex ACP bridge is not ready. Keep IdeaWave CLI running and retry in a moment.";throw new S(W)},checkReadiness:async()=>{if(!await d(t6))return{status:"not_installed",detail:Z2};let Q=u0(O4);if(Q?.status==="ready")return{status:"ready"};if(Q?.status==="installing")return{status:"not_running",detail:"Installing Codex ACP bridge..."};if(Q?.status==="failed")return{status:"not_running",detail:Q.error??"Codex ACP bridge install failed. Restart IdeaWave CLI so it can warm the pinned bridge again."};if(await d(e6))return{status:"ready"};return{status:"not_running",detail:"Installing Codex ACP bridge..."}},authHint:"Run `codex login` (or set OPENAI_API_KEY)."};var X2="copilot",J2="copilot-acp",K2="npm i -g @github/copilot",Y2={id:"copilot",displayName:"GitHub Copilot",kind:"registered",resolveSpawnConfig:async()=>{let Z=await d(X2);if(Z)return{command:Z,args:["--acp"],env:X0()};let Q=await d(J2);if(Q)return{command:Q,args:[],env:X0()};throw new S(`Copilot not installed. Run: ${K2}`)},checkReadiness:async()=>{if(await d(X2))return{status:"ready"};if(await d(J2))return{status:"ready"};return{status:"not_installed",detail:K2}},authHint:"Run `gh auth login` (or `copilot login`)."};import l7 from"node:fs/promises";function c7(Z){return Z.startsWith("/")||/^[a-zA-Z]:[\\/]/.test(Z)}async function W2(Z){if(c7(Z))try{return await l7.access(Z),!0}catch{return!1}return await d(Z)!==null}var V2={id:"custom",displayName:"Custom ACP",kind:"custom",resolveSpawnConfig:async(Z)=>{if(Z.kind!=="custom")throw new S("customAdapter received non-custom entry");if(!await W2(Z.command))throw new S(`custom: command "${Z.command}" not found`);return{command:Z.command,args:Z.args,env:X0(Z.env)}},checkReadiness:async(Z)=>{if(Z.kind!=="custom")return{status:"unknown"};return await W2(Z.command)?{status:"ready"}:{status:"not_installed"}}};var H2="opencode",j2="Install OpenCode from https://opencode.ai",z2={id:"opencode",displayName:"OpenCode",kind:"registered",resolveSpawnConfig:async()=>{let Z=await d(H2);if(!Z)throw new S(`OpenCode not installed. ${j2}`);return{command:Z,args:["acp"],env:X0()}},checkReadiness:async()=>{if(!await d(H2))return{status:"not_installed",detail:j2};return{status:"ready"}},authHint:"Run `opencode auth login <provider>` (or set the provider's API-key env var)."};var q2={"claude-code":n6,opencode:z2,codex:Q2,copilot:Y2};function U0(Z){if(Z.kind==="custom")return V2;let Q=q2[Z.adapterId];if(!Q)throw Error(`Unknown registered adapter: ${Z.adapterId}`);return Q}function T0(){return Object.values(q2)}var C4=new Map,N1=new Map,d7=30000;function D1(Z,Q){let X=C4.get(Z);if(X&&X.expiresAt>Date.now())return Promise.resolve(X.value);let K=N1.get(Z);if(K)return K;let Y=Q().then((W)=>{return C4.set(Z,{value:W,expiresAt:Date.now()+d7}),W}).finally(()=>{N1.delete(Z)});return N1.set(Z,Y),Y}async function U2(Z){let Q=await Promise.all(T0().map((W)=>D1(W.id,async()=>({adapterId:W.id,...await W.checkReadiness({id:"__probe__",kind:"registered",adapterId:W.id,displayName:W.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null})})))),K=(await J0(Z)).runtimes.filter((W)=>W.kind==="custom"),Y=await Promise.all(K.map((W)=>D1(`custom:${W.id}`,async()=>({adapterId:W.id,...await U0(W).checkReadiness(W)}))));return[...Q,...Y]}async function B2(Z,Q){let X=T0().find((W)=>W.id===Z);if(X)return D1(X.id,async()=>({adapterId:X.id,...await X.checkReadiness({id:"__probe__",kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null})}));let Y=(await J0(Q)).runtimes.find((W)=>W.id===Z);if(!Y||Y.kind!=="custom")return null;return D1(`custom:${Y.id}`,async()=>({adapterId:Y.id,...await U0(Y).checkReadiness(Y)}))}function F2(){C4.clear(),N1.clear()}function a7(Z){if(!Z)return null;let Q=Z.indexOf("/");if(Q<=0)return null;return Z.slice(0,Q)}function $1(Z){let Q=[...Z.models];if(Z.adapterId!=="opencode"||Q.length===0)return Q;let X=a7(Z.currentModelId)??(Q.some((Y)=>Y.id.startsWith("opencode/"))?"opencode":null);if(!X)return Q;let K=Q.filter((Y)=>Y.id===Z.currentModelId||Y.id.startsWith(`${X}/`));return K.length>0?K:Q}import{Readable as V9,Writable as H9}from"node:stream";import{ClientSideConnection as f2,ndJsonStream as h2}from"@agentclientprotocol/sdk";import b0 from"node:fs/promises";import Q0 from"node:path";class o0 extends Error{constructor(Z){super(Z);this.name="PathTraversalError"}}class R4 extends Error{constructor(Z){super(Z);this.name="HiddenPathError"}}class y4 extends Error{constructor(Z){super(Z);this.name="RunFolderFileTooLargeError"}}class r0 extends Error{constructor(Z){super(Z);this.name="RunFolderBinaryFileError"}}var i7=new Set([".bzr",".cache",".claude",".config",".env",".git",".hg",".idea",".obsidian",".svn",".vscode","node_modules"]),w2=1e6,p7=4096,s7=new TextDecoder("utf-8",{fatal:!0});function r7(Z){return Z.split(/[\\/]+/).filter((Q)=>Q.length>0)}function G1(Z){if(Q0.isAbsolute(Z))throw new o0("Absolute paths are not allowed");for(let Q of r7(Z)){if(Q===".")continue;if(Q==="..")throw new o0("Parent-directory traversal is not allowed");if(Q.startsWith(".")||i7.has(Q))throw new R4(`Path segment "${Q}" is hidden or configuration data`)}}function o7(Z){G1(Z);let Q=Q0.normalize(Z||".");return Q==="."?"":Q}function n7(Z,Q,X){let K=Q0.relative(Z,Q);if(K===".."||K.startsWith(`..${Q0.sep}`)||Q0.isAbsolute(K))throw new o0(`Path "${X}" resolves outside the run folder`);if(K.length>0)G1(K);return K}async function v4(Z,Q){G1(Q);let X=Q0.resolve(Z,Q||"."),K;try{K=await b0.realpath(X)}catch(Y){if(Y.code!=="ENOENT")throw Y;let W=Q0.dirname(X),z=[Q0.basename(X)];while(W!==Z&&W!==Q0.dirname(W))try{W=await b0.realpath(W);break}catch(B){if(B.code!=="ENOENT")throw B;z.unshift(Q0.basename(W)),W=Q0.dirname(W)}K=Q0.join(W,...z)}return n7(Z,K,Q),K}async function t7(Z,Q){let X=await b0.realpath(Z);return v4(X,Q)}function e7(Z){let Q=Z.subarray(0,Math.min(Z.length,p7));if(Q.length===0)return!1;let X=0;for(let K of Q){if(K===0)return!0;let Y=K===9||K===10||K===12||K===13;if(K<32&&!Y)X+=1}return X/Q.length>0.3}async function g1(Z,Q){let X=await t7(Z,Q),K=await b0.stat(X);if(!K.isFile())throw new r0(`Path "${Q}" is not a text file`);if(K.size>w2)throw new y4(`File "${Q}" is too large to read (${K.size} bytes, max ${w2} bytes)`);let Y=await b0.readFile(X);if(e7(Y))throw new r0(`File "${Q}" appears to be binary, not text`);try{return s7.decode(Y)}catch{throw new r0(`File "${Q}" is not valid UTF-8 text`)}}function Z9(Z){if(Z.isDirectory())return"directory";if(Z.isFile())return"file";if(Z.isSymbolicLink())return"symlink";return"other"}function L2(Z){return Z.split(Q0.sep).join("/")}async function P2(Z,Q=""){let X=await b0.realpath(Z),K=o7(Q),Y=await v4(X,K),W=await b0.readdir(Y,{withFileTypes:!0}),z=[];for(let B of W){let w=K?Q0.join(K,B.name):B.name;try{G1(w);let q=await v4(X,w),b=await b0.stat(q);z.push({name:B.name,path:L2(w),type:Z9(B),size:B.isFile()?b.size:null})}catch{}}return z.sort((B,w)=>{if(B.type==="directory"&&w.type!=="directory")return-1;if(B.type!=="directory"&&w.type==="directory")return 1;return B.name.localeCompare(w.name)}),{path:L2(K),absolutePath:Y,entries:z}}var f4={fs:{readTextFile:!0,writeTextFile:!1},terminal:!1};function x2(Z){return{readTextFile:async(Q)=>{return{content:await g1(Z,Q.path)}}}}import{spawn as Q9}from"node:child_process";function h4(Z){let Q=Q9(Z.command,Z.args,{cwd:Z.cwd,env:Z.env,stdio:["pipe","pipe","pipe"],...y1(Z.command)});if(!Q.stdin||!Q.stdout||!Q.stderr)throw Error("Failed to allocate stdio streams for ACP subprocess");let{stdin:X,stdout:K,stderr:Y}=Q,W=4096,z=[],B=0;Y.on("data",(C)=>{z.push(C),B+=C.length;while(B>W*2&&z.length>1){let N=z.shift();if(N)B-=N.length}});let w=()=>{let C=Buffer.concat(z).toString("utf8");return C.length>W?C.slice(-W):C},q=!1,b=!1,M,x,y=new Promise((C)=>{M=C}),v=new Promise((C)=>{x=C}),$=(C)=>{if(b)return;if(b=!0,M(C),!q)x(C)};return Q.on("exit",(C,N)=>{$({code:C,signal:N,stderr:w()})}),Q.on("error",(C)=>{let N=w(),f=C?.message??String(C);$({code:null,signal:null,stderr:N?`${f}
4
4
  ${N}`:f})}),{stdin:X,stdout:K,stderr:Y,kill:(C="SIGTERM")=>{if(q)return;q=!0;try{Q.kill(C)}catch{}},waitForExit:y,processCrashed:v}}var X9=["mcp_ideawave_board_","ideawave_board_","ideawave-board_","ideawave-board.","ideawave.board."];function J9(Z){let Q=Z.toLowerCase();for(let X of X9)if(Q.startsWith(X))return Z.slice(X.length);if(/^mcp[-_.]/i.test(Z))return Z.slice(4);return Z}function E1(Z){return J9(Z.trim())}function M4(Z){let Q=E1(Z);if(!Q)return"Tool";if(!/[-_.]/.test(Q))return Q.charAt(0).toUpperCase()+Q.slice(1);let X=Q.replace(/[-_.]+/g," ").replace(/\s+/g," ").trim();if(!X)return"Tool";return X.charAt(0).toUpperCase()+X.slice(1)}function N4(Z){let Q=Z?.toLowerCase();if(Q==="completed"||Q==="complete"||Q==="done"||Q==="success"||Q==="succeeded")return"completed";if(Q==="failed"||Q==="error"||Q==="errored")return"failed";return"running"}function D4(Z){if(typeof Z!=="string")return null;let Q=Z.trim();return Q?Q:null}function b2(Z){if(typeof Z!=="string")return"Tool";let Q=Z.trim();return Q?Q:"Tool"}function K9(Z,Q){if(!Z||typeof Z!=="object"||Array.isArray(Z))return null;let X=Z;for(let K of Q){let Y=X[K];if(typeof Y==="string"&&Y.trim())return Y.trim()}return null}function $4(Z,Q){let X=Z.trim().toLowerCase();if(X==="skill"||X==="workflow"||X==="tool"||X==="invalid"){let K=K9(Q,["skillName","workflowName","toolName","name","title"]);if(K){let Y=X==="skill"?" skill":X==="workflow"?" workflow":"";return`${M4(K)}${Y}`}}if(X==="invalid")return"Tool call";return M4(Z)}var Y9=33,O2=1600;function G0(Z){if(Z.length<=O2)return Z;return`${Z.slice(0,O2-22)}
5
5
  ... truncated`}function k1(Z){let Q=Z.replace(/\r\n?/g,`
@@ -15,7 +15,7 @@ ${Y}`:null].filter(Boolean).join(`
15
15
 
16
16
  `));return w0(Z)}function C2(Z,Q){if(!Q)return Z;if(!Z)return Q;if(Z===Q||Z.endsWith(Q))return Z;if(Q.startsWith(Z))return Q;return G0(`${Z}
17
17
 
18
- ${Q}`)}function g4(Z){if(!Array.isArray(Z))return null;let Q=Z.flatMap((X)=>{if(!X||typeof X!=="object")return[];let K=X;if(typeof K.path!=="string"||!K.path.trim())return[];let Y=typeof K.line==="number"?`:${K.line}`:"";return[`${K.path}${Y}`]});return Q.length>0?Q.slice(0,5):null}function v2(Z){let{ctx:Q,appendText:X,appendToolActivity:K}=Z,Y=Z.flushIntervalMs??Y9,W="",z="",B=0,w=null,q={},b=new Map,M=(D)=>{if(b.set(D.toolCallId,D),!K)return;K({boardId:Q.boardId,cardId:Q.cardId,runId:Q.runId,entry:D}).catch((L)=>{console.warn("[streamAdapter] appendToolActivity failed",L)})},x=(D)=>{let L=`${Q.runId}:thought`,g=b.get(L);if(!g||g.status!=="running")return;M({...g,status:"completed",completedAt:g.completedAt??D})},y=(D)=>{for(let L of b.values()){if(L.status!=="running"||L.rawTitle.toLowerCase()!=="toolsearch")continue;M({...L,status:"completed",completedAt:L.completedAt??D})}},v=(D)=>{for(let L of Array.from(b.values())){if(L.status!=="running")continue;if(L.kind==="thought"||L.rawTitle==="agent_thought")continue;M({...L,status:"completed",completedAt:L.completedAt??D})}},$="",C=0,N=null,f=null,E=(D)=>{if(D===$)return;$=D,C=Date.now(),X({boardId:Q.boardId,cardId:Q.cardId,runId:Q.runId,text:D}).catch((L)=>{console.warn("[streamAdapter] appendText failed",L)})},G=()=>{if(N!==null)clearTimeout(N),N=null;if(f!==null){let D=f;f=null,E(D)}},I=(D)=>{let L=Date.now()-C;if(L>=Y&&N===null){E(D);return}if(f=D,N===null){let g=Math.max(0,Y-L);N=setTimeout(()=>{N=null,G()},g)}};return{onSessionUpdate:async(D)=>{let L=D.update;switch(q[L.sessionUpdate]=(q[L.sessionUpdate]??0)+1,L.sessionUpdate){case"agent_message_chunk":{let g=new Date().toISOString();if(x(g),L.content.type==="text")W+=L.content.text,I(W);else{let l=`agent_message_chunk:${L.content.type}`;q[l]=(q[l]??0)+1}return}case"agent_thought_chunk":{if(L.content.type!=="text")return;z+=L.content.text;let g=new Date().toISOString(),l=`${Q.runId}:thought`,a=b.get(l);M({toolCallId:l,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:a?.startedAt??g,completedAt:null,contentPreview:G0(z.trim())});return}case"user_message_chunk":return;case"tool_call":{B+=1;let g=b2(L.title),l=N4(L.status),a=new Date().toISOString();x(a),y(a),M({toolCallId:L.toolCallId,rawTitle:g,title:$4(g,L.rawInput),kind:D4(L.kind),status:l,startedAt:a,completedAt:l==="running"?null:a,inputPreview:w0(L.rawInput),outputPreview:G4(L.rawOutput),contentPreview:m1(L.content),locations:g4(L.locations)});return}case"tool_call_update":{let g=b.get(L.toolCallId);if(!g){let A=b2(L.title),Z0=N4(L.status),s=new Date().toISOString();M({toolCallId:L.toolCallId,rawTitle:A,title:$4(A,L.rawInput),kind:D4(L.kind),status:Z0,startedAt:s,completedAt:Z0==="running"?null:s,inputPreview:w0(L.rawInput),outputPreview:G4(L.rawOutput),contentPreview:m1(L.content),locations:g4(L.locations)});return}let l=L.status===void 0||L.status===null?g.status:N4(L.status),a=typeof L.title==="string"&&L.title.trim().length>0?L.title:g.rawTitle,_0=typeof L.title==="string"&&L.title.trim().length>0,P0=l==="running"?g.completedAt:g.completedAt??new Date().toISOString(),_=L.content===void 0?g.contentPreview:C2(g.contentPreview,m1(L.content)),i=L.rawOutput===void 0?g.outputPreview:C2(g.outputPreview,G4(L.rawOutput));M({...g,rawTitle:a,title:_0?$4(a,L.rawInput):g.title,kind:L.kind===void 0?g.kind:D4(L.kind),status:l,completedAt:P0,inputPreview:L.rawInput===void 0?g.inputPreview:w0(L.rawInput),outputPreview:i,contentPreview:_,locations:L.locations===void 0?g.locations:g4(L.locations)});return}case"plan":w=L.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>W,getToolCallCount:()=>B,getLatestPlan:()=>w,getUpdateTypeCounts:()=>({...q}),flush:(D)=>{let L=new Date().toISOString();if(x(L),D?.completeOpenToolCalls)v(L);G()}}}var n0=1,R2=-32000;function y2(Z){if(Z.awaitingInput)return!1;return Z.nowMs-Z.lastUpdateMs>=Z.windowMs}function M2(Z){if(!Z||typeof Z!=="object")return!1;return Z.code===R2}var j9=60000,z9=j9,q9=5000;function U9(Z){let Q=Math.max(1,Math.round(Z/1000));return`Runtime has not responded for ${Q} ${Q===1?"second":"seconds"}. Retry the agent run.`}function N2(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.61".trim()?"0.0.61":"dev"}}function D2(Z){if(Z===n0)return;throw new S(`Unsupported ACP protocol version ${Z}; expected ${n0}`)}function $2(Z){return V9.toWeb(Z)}function G2(Z){return H9.toWeb(Z)}function E4(Z){return Z!==null&&typeof Z==="object"}function B9(Z){if(!Array.isArray(Z))return[];let Q=[];for(let X of Z){if(!E4(X))continue;if(typeof X.group==="string"&&Array.isArray(X.options)){let K=typeof X.name==="string"?X.name:X.group;for(let Y of X.options){if(!E4(Y))continue;if(typeof Y.value!=="string"||typeof Y.name!=="string")continue;Q.push({value:Y.value,name:Y.name,description:typeof Y.description==="string"?Y.description:null,group:X.group,groupName:K})}continue}if(typeof X.value!=="string"||typeof X.name!=="string")continue;Q.push({value:X.value,name:X.name,description:typeof X.description==="string"?X.description:null,group:null,groupName:null})}return Q}function F9(Z){if(!E4(Z))return null;if(typeof Z.id!=="string"||typeof Z.name!=="string")return null;let Q=typeof Z.category==="string"?Z.category:null,X=typeof Z.description==="string"?Z.description:null;if(Z.type==="select"){let K=typeof Z.currentValue==="string"?Z.currentValue:null;return{id:Z.id,name:Z.name,category:Q,description:X,type:"select",currentValue:K,options:B9(Z.options)}}if(Z.type==="boolean"){let K=typeof Z.currentValue==="boolean"?Z.currentValue:typeof Z.value==="boolean"?Z.value:null;return{id:Z.id,name:Z.name,category:Q,description:X,type:"boolean",currentValue:K,options:[]}}return null}function m4(Z){let Q=(Z.configOptions??[]).map(F9).filter((B)=>B!==null),X=Q.find((B)=>B.type==="select"&&B.category==="model")??Q.find((B)=>B.type==="select"&&B.id==="model")??null,K=X?.options.map((B)=>({id:B.value,name:B.name,description:B.description??null})),Y=w9(Z.models),W=K&&K.length>0?K:Y&&Y.length>0?Y:null,z=(typeof X?.currentValue==="string"?X.currentValue:null)??L9(Z.models)??null;return{models:W,currentModelId:z,configOptions:Q,modelConfigId:X?.id??null}}function w9(Z){if(!Z||!Array.isArray(Z.availableModels))return null;let Q=[];for(let X of Z.availableModels){if(typeof X.modelId!=="string")continue;Q.push({id:X.modelId,name:typeof X.name==="string"?X.name:null,description:typeof X.description==="string"?X.description:null})}return Q.length>0?Q:null}function L9(Z){return typeof Z?.currentModelId==="string"?Z.currentModelId:null}function P9(Z,Q){let X=[];if(Z.trim())X.push({type:"text",text:Z});for(let K of Q)if(K.content.trim())X.push({type:"text",text:K.content});return X}function x9(Z){if(typeof Z.value==="boolean")return{sessionId:Z.sessionId,configId:Z.configId,type:"boolean",value:Z.value};return{sessionId:Z.sessionId,configId:Z.configId,value:Z.value}}function b9(Z,Q){let X=m4({configOptions:Q.configOptions});return{models:X.models??Z.models,currentModelId:X.currentModelId??Z.currentModelId,configOptions:X.configOptions,modelConfigId:X.modelConfigId??Z.modelConfigId}}function g2(Z,Q){if(Z==="default")return null;if(!Q||Q.length===0)return Z;let X=Q.find((q)=>q.id===Z);if(X)return X.id;let K=Z.toLowerCase(),Y=K.includes("opus")?"opus":K.includes("sonnet")?"sonnet":K.includes("haiku")?"haiku":null;if(!Y)return Z;let W=(q)=>`${q.id} ${q.name??""} ${q.description??""}`.toLowerCase(),z=Q.filter((q)=>W(q).includes(Y));if(z.length===0)return Z;let w=(K.includes("1m")?z.find((q)=>W(q).includes("1m")):void 0)??z[0];return w?w.id:Z}async function _1(Z){try{let Q=await Z.conn.setSessionConfigOption(x9({sessionId:Z.sessionId,configId:Z.configId,value:Z.value}));return b9(Z.metadata,Q)}catch(Q){return console.warn(`[acp] setSessionConfigOption(${Z.label}) failed; using agent default.`,Q instanceof Error?Q.message:Q),Z.metadata}}async function k4(Z){let Q=h4(Z.spawn),X=[],K=0,Y=4096;Q.stderr.on("data",(_)=>{X.push(_),K+=_.length;while(K>Y*2&&X.length>1){let i=X.shift();if(i)K-=i.length}});let W=()=>{let _=Buffer.concat(X).toString("utf8");return _.length>Y?_.slice(-Y):_},z=x2(Z.spawn.cwd),B={current:null},w={current:null},q={at:Date.now()},b=null,M=G2(Q.stdin),x=$2(Q.stdout),y=h2(M,x),$=new f2((_)=>({requestPermission:async(i)=>{let A=i.options,Z0=A?.find((s)=>s.kind==="allow_once")??A?.find((s)=>s.kind==="allow_always");if(Z0)return{outcome:{outcome:"selected",optionId:Z0.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(i)=>{q.at=Date.now();let A=w.current;if(A){let s=i.update.sessionUpdate;if(A.updateCount+=1,A.updateCount===1||A.lastUpdateType!==s||s==="tool_call"||s==="tool_call_update")m("acp.session_update",{runId:A.runId,cardId:A.cardId,sessionId:b,updateType:s,updateCount:A.updateCount,elapsedMs:Date.now()-A.startedAt});A.lastUpdateType=s}let Z0=B.current;if(Z0)await Z0.onSessionUpdate(i)},readTextFile:z.readTextFile}),y),C=()=>Q.kill();if(Z.signal)Z.signal.addEventListener("abort",C);let N=()=>{if(Z.signal)Z.signal.removeEventListener("abort",C)},f=async(_,i)=>{if(N(),Q.kill(),M2(_))throw new I0(_.message??"Authentication required",i);if(_ instanceof Error&&_.message==="ACP connection closed"){if(Z.signal?.aborted)throw new S("ACP session cancelled: abort signal received");let A=await Promise.race([Q.processCrashed,Q.waitForExit,new Promise((Z0)=>setTimeout(()=>Z0({stderr:""}),500))]);throw new S(`Runtime process exited before completion: ${A.stderr?.trim()??""}`)}throw _},E;try{E=await $.initialize({protocolVersion:n0,clientCapabilities:f4,clientInfo:N2()})}catch(_){throw await f(_,[]),Error("unreachable")}try{D2(E.protocolVersion)}catch(_){throw N(),Q.kill(),_}let G=E.authMethods?.map((_)=>_.id)??[],I;try{I=await $.newSession({cwd:Z.spawn.cwd,mcpServers:Z.mcpServers??[]})}catch(_){throw await f(_,G),Error("unreachable")}let D=I.sessionId;b=D;let L=m4(I),g=Z.modelId??null,l=g?g2(g,L.models):null;if(l&&l!==L.currentModelId)if(L.modelConfigId)L=await _1({conn:$,sessionId:D,configId:L.modelConfigId,value:l,metadata:L,label:`${L.modelConfigId}=${l}`});else console.warn(`[acp] runtime did not advertise a model config option for ${l}; using agent default.`);for(let[_,i]of Object.entries(Z.configValues??{}).sort(([A],[Z0])=>A.localeCompare(Z0))){if(_===L.modelConfigId)continue;if(!L.configOptions.some((A)=>A.id===_))continue;L=await _1({conn:$,sessionId:D,configId:_,value:i,metadata:L,label:`${_}=${String(i)}`})}N();let a=!1,_0=async()=>{if(a)return;a=!0,Q.kill(),await Promise.race([Q.waitForExit,new Promise((_)=>setTimeout(_,2000))])},P0=!1;return Q.processCrashed.then(()=>{P0=!0}),{sessionId:D,availableModels:L.models,currentModelId:L.currentModelId,availableConfigOptions:L.configOptions,isAlive:()=>!a&&!P0,dispose:_0,prompt:(_)=>O9({proc:Q,conn:$,sessionId:D,activeAdapter:B,activeTrace:w,lastUpdate:q,collectStderrTail:W},_)}}async function O9(Z,Q){let{proc:X,conn:K,sessionId:Y,activeAdapter:W,activeTrace:z,lastUpdate:B}=Z,w=Date.now(),q=Q.heartbeatMs??z9,b=U9(q),M={boardId:Q.boardId,cardId:Q.cardId,runId:Q.runId},x=v2({ctx:M,appendText:Q.appendText,appendToolActivity:Q.appendToolActivity});W.current=x,z.current={runId:Q.runId,cardId:Q.cardId,startedAt:w,updateCount:0,lastUpdateType:null},B.at=Date.now(),m("acp.prompt_started",{runId:Q.runId,cardId:Q.cardId,sessionId:Y,heartbeatWindowMs:q});let y=!1,v=null,$=()=>X.kill();Q.signal.addEventListener("abort",$);try{let C=async()=>{let G=Math.min(q9,Math.max(50,Math.floor(q/2)));v=setInterval(()=>{let D=Q.isAwaitingInput?.()??!1;if(D){B.at=Date.now();return}if(y2({nowMs:Date.now(),lastUpdateMs:B.at,windowMs:q,awaitingInput:D}))y=!0,m("acp.inactivity_timeout",{runId:Q.runId,cardId:Q.cardId,sessionId:Y,windowMs:q,silentForMs:Date.now()-B.at}),K.cancel({sessionId:Y}).catch(()=>{return}),X.kill()},G);let I=P9(Q.prompt.systemPrompt,Q.prompt.messages);await K.prompt({sessionId:Y,prompt:I}),m("acp.prompt_resolved",{runId:Q.runId,cardId:Q.cardId,sessionId:Y,elapsedMs:Date.now()-w}),x.flush({completeOpenToolCalls:!0})},N=X.waitForExit.then((G)=>({kind:"exited",exit:G})),f=C().then(()=>({kind:"ok"})).catch(async(G)=>{if(G instanceof Error&&G.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([X.processCrashed,X.waitForExit])};throw G}),E;try{E=await Promise.race([f,X.processCrashed.then((G)=>({kind:"crashed",exit:G})),N])}catch(G){if(y)throw new q0(b);throw G}if(y)throw new q0(b);if(E.kind==="crashed")throw new S(`Runtime process exited before completion: ${E.exit.stderr.trim()}`);if(E.kind==="exited"){if(Q.signal.aborted)throw new S("ACP session cancelled: abort signal received");if(y)throw new q0(b);throw new S(`Runtime process exited unexpectedly: ${E.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:x.getFinalText(),toolCallsExecuted:x.getToolCallCount(),stderrTail:Z.collectStderrTail(),updateTypeCounts:x.getUpdateTypeCounts()}}finally{if(m("acp.prompt_finished",{runId:Q.runId,cardId:Q.cardId,sessionId:Y,elapsedMs:Date.now()-w,timedOut:y,updateCount:z.current?.updateCount??0}),v!==null)clearInterval(v);Q.signal.removeEventListener("abort",$),x.flush({completeOpenToolCalls:!0}),W.current=null,z.current=null}}var C9=30000;async function E2(Z){let Q=h4(Z.spawn),X=G2(Q.stdin),K=$2(Q.stdout),Y=h2(X,K),z=new f2((q)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Y),B=()=>Q.kill();if(Z.signal)Z.signal.addEventListener("abort",B);let w=null;try{let q=(async()=>{let M=await z.initialize({protocolVersion:n0,clientCapabilities:f4,clientInfo:N2()});D2(M.protocolVersion);let x=M.authMethods?.map((E)=>E.id)??[],y;try{y=await z.newSession({cwd:Z.spawn.cwd,mcpServers:[]})}catch(E){if(M2(E))throw new I0(E.message??"Authentication required",x);throw E}let v=m4(y),$=Z.modelId??null,C=$?g2($,v.models):null;if(C&&C!==v.currentModelId)if(v.modelConfigId)v=await _1({conn:z,sessionId:y.sessionId,configId:v.modelConfigId,value:C,metadata:v,label:`${v.modelConfigId}=${C}`});else console.warn(`[acp] runtime did not advertise a model config option for ${C}; discovering agent default models.`);for(let[E,G]of Object.entries(Z.configValues??{}).sort(([I],[D])=>I.localeCompare(D))){if(E===v.modelConfigId)continue;if(!v.configOptions.some((I)=>I.id===E))continue;v=await _1({conn:z,sessionId:y.sessionId,configId:E,value:G,metadata:v,label:`${E}=${String(G)}`})}let N=v.models??[],f=v.currentModelId;return z.cancel({sessionId:y.sessionId}).catch(()=>{return}),{models:N,configOptions:v.configOptions,currentModelId:f}})(),b=new Promise((M,x)=>{w=setTimeout(()=>{x(new q0)},C9)});return await Promise.race([q,b])}catch(q){if(q instanceof Error&&q.message==="ACP connection closed"){if(Z.signal?.aborted)throw new S("ACP model discovery cancelled: abort signal received");throw new S("Runtime process exited during model discovery.")}throw q}finally{if(w)clearTimeout(w);if(Z.signal)Z.signal.removeEventListener("abort",B);Q.kill()}}import v9 from"node:fs/promises";import S1 from"node:os";async function m2(Z){let Q={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},X;try{X=await v9.readFile(Z,"utf-8")}catch(K){if(K.code==="ENOENT")return structuredClone(Q);throw K}return C1.parse(JSON.parse(X))}function _4(Z,Q,X){return{...Z.defaultConfigValues??{},...Q?.configValues??{},...X?.configValues??{}}}async function O0(Z){let Q=Z.configPath?await m2(Z.configPath):await J0(),X=Z.cardId?Q.cardOverrides[Z.cardId]:void 0;if(X?.runtimeConfigId){let Y=Q.runtimes.find((W)=>W.id===X.runtimeConfigId);if(Y)return{entry:Y,adapter:U0(Y),runFolder:X.runFolder??Y.runFolder??S1.homedir(),modelId:X.modelId??Y.defaultModelId??null,configValues:_4(Y,void 0,X)}}let K=Q.boardOverrides[Z.boardId];if(K?.runtimeConfigId){let Y=Q.runtimes.find((W)=>W.id===K.runtimeConfigId);if(Y)return{entry:Y,adapter:U0(Y),runFolder:K.runFolder??Y.runFolder??S1.homedir(),modelId:K.modelId??Y.defaultModelId??null,configValues:_4(Y,K)}}if(Q.globalDefaultConfigId){let Y=Q.runtimes.find((W)=>W.id===Q.globalDefaultConfigId);if(Y)return{entry:Y,adapter:U0(Y),runFolder:X?.runFolder??K?.runFolder??Y.runFolder??S1.homedir(),modelId:X?.modelId??K?.modelId??Y.defaultModelId??null,configValues:_4(Y,K,X)}}throw new D0}async function k2(Z,Q={}){let K=(Q.configPath?await m2(Q.configPath):await J0()).runtimes.find((Y)=>Y.id===Z);if(!K)return null;return{entry:K,adapter:U0(K),runFolder:K.runFolder??S1.homedir(),modelId:Q.modelId??K.defaultModelId??null,configValues:{...K.defaultConfigValues??{},...Q.configValues??{}}}}var _2=new Map;function S4(Z,Q){if(!Z)return;_2.set(Z,Q)}function S2(Z){if(!Z)return!1;return _2.get(Z)??!1}var g0=new Map,I4=new Set;function T4(Z){g0.get(Z)?.controller.abort()}function I2(Z){for(let[Q,X]of g0){if(X.frontendSessionId!==Z)continue;X.controller.abort(),g0.delete(Q)}}function u2(){for(let Z of g0.values())Z.controller.abort();g0.clear()}function u4(Z,Q){if(Q?.aborted)return!0;return Z instanceof Error&&/abort signal received|session cancelled/i.test(Z.message)}function T2(Z,Q,X,K){if((!Q.availableModels||Q.availableModels.length===0)&&Q.availableConfigOptions.length===0)return;V0((Y)=>{let W=Y.runtimes.find((z)=>z.id===Z);if(W){if(Q.availableModels&&Q.availableModels.length>0)W.discoveredModels=$1({adapterId:X,models:Q.availableModels,currentModelId:Q.currentModelId??K});if(Q.availableConfigOptions.length>0)W.discoveredConfigOptions=Q.availableConfigOptions}}).catch(()=>{return})}function R9(Z,Q){return`${Z}
18
+ ${Q}`)}function g4(Z){if(!Array.isArray(Z))return null;let Q=Z.flatMap((X)=>{if(!X||typeof X!=="object")return[];let K=X;if(typeof K.path!=="string"||!K.path.trim())return[];let Y=typeof K.line==="number"?`:${K.line}`:"";return[`${K.path}${Y}`]});return Q.length>0?Q.slice(0,5):null}function v2(Z){let{ctx:Q,appendText:X,appendToolActivity:K}=Z,Y=Z.flushIntervalMs??Y9,W="",z="",B=0,w=null,q={},b=new Map,M=(D)=>{if(b.set(D.toolCallId,D),!K)return;K({boardId:Q.boardId,cardId:Q.cardId,runId:Q.runId,entry:D}).catch((L)=>{console.warn("[streamAdapter] appendToolActivity failed",L)})},x=(D)=>{let L=`${Q.runId}:thought`,g=b.get(L);if(!g||g.status!=="running")return;M({...g,status:"completed",completedAt:g.completedAt??D})},y=(D)=>{for(let L of b.values()){if(L.status!=="running"||L.rawTitle.toLowerCase()!=="toolsearch")continue;M({...L,status:"completed",completedAt:L.completedAt??D})}},v=(D)=>{for(let L of Array.from(b.values())){if(L.status!=="running")continue;if(L.kind==="thought"||L.rawTitle==="agent_thought")continue;M({...L,status:"completed",completedAt:L.completedAt??D})}},$="",C=0,N=null,f=null,E=(D)=>{if(D===$)return;$=D,C=Date.now(),X({boardId:Q.boardId,cardId:Q.cardId,runId:Q.runId,text:D}).catch((L)=>{console.warn("[streamAdapter] appendText failed",L)})},G=()=>{if(N!==null)clearTimeout(N),N=null;if(f!==null){let D=f;f=null,E(D)}},I=(D)=>{let L=Date.now()-C;if(L>=Y&&N===null){E(D);return}if(f=D,N===null){let g=Math.max(0,Y-L);N=setTimeout(()=>{N=null,G()},g)}};return{onSessionUpdate:async(D)=>{let L=D.update;switch(q[L.sessionUpdate]=(q[L.sessionUpdate]??0)+1,L.sessionUpdate){case"agent_message_chunk":{let g=new Date().toISOString();if(x(g),L.content.type==="text")W+=L.content.text,I(W);else{let l=`agent_message_chunk:${L.content.type}`;q[l]=(q[l]??0)+1}return}case"agent_thought_chunk":{if(L.content.type!=="text")return;z+=L.content.text;let g=new Date().toISOString(),l=`${Q.runId}:thought`,a=b.get(l);M({toolCallId:l,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:a?.startedAt??g,completedAt:null,contentPreview:G0(z.trim())});return}case"user_message_chunk":return;case"tool_call":{B+=1;let g=b2(L.title),l=N4(L.status),a=new Date().toISOString();x(a),y(a),M({toolCallId:L.toolCallId,rawTitle:g,title:$4(g,L.rawInput),kind:D4(L.kind),status:l,startedAt:a,completedAt:l==="running"?null:a,inputPreview:w0(L.rawInput),outputPreview:G4(L.rawOutput),contentPreview:m1(L.content),locations:g4(L.locations)});return}case"tool_call_update":{let g=b.get(L.toolCallId);if(!g){let A=b2(L.title),Z0=N4(L.status),s=new Date().toISOString();M({toolCallId:L.toolCallId,rawTitle:A,title:$4(A,L.rawInput),kind:D4(L.kind),status:Z0,startedAt:s,completedAt:Z0==="running"?null:s,inputPreview:w0(L.rawInput),outputPreview:G4(L.rawOutput),contentPreview:m1(L.content),locations:g4(L.locations)});return}let l=L.status===void 0||L.status===null?g.status:N4(L.status),a=typeof L.title==="string"&&L.title.trim().length>0?L.title:g.rawTitle,_0=typeof L.title==="string"&&L.title.trim().length>0,P0=l==="running"?g.completedAt:g.completedAt??new Date().toISOString(),_=L.content===void 0?g.contentPreview:C2(g.contentPreview,m1(L.content)),i=L.rawOutput===void 0?g.outputPreview:C2(g.outputPreview,G4(L.rawOutput));M({...g,rawTitle:a,title:_0?$4(a,L.rawInput):g.title,kind:L.kind===void 0?g.kind:D4(L.kind),status:l,completedAt:P0,inputPreview:L.rawInput===void 0?g.inputPreview:w0(L.rawInput),outputPreview:i,contentPreview:_,locations:L.locations===void 0?g.locations:g4(L.locations)});return}case"plan":w=L.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>W,getToolCallCount:()=>B,getLatestPlan:()=>w,getUpdateTypeCounts:()=>({...q}),flush:(D)=>{let L=new Date().toISOString();if(x(L),D?.completeOpenToolCalls)v(L);G()}}}var n0=1,R2=-32000;function y2(Z){if(Z.awaitingInput)return!1;return Z.nowMs-Z.lastUpdateMs>=Z.windowMs}function M2(Z){if(!Z||typeof Z!=="object")return!1;return Z.code===R2}var j9=60000,z9=j9,q9=5000;function U9(Z){let Q=Math.max(1,Math.round(Z/1000));return`Runtime has not responded for ${Q} ${Q===1?"second":"seconds"}. Retry the agent run.`}function N2(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.63".trim()?"0.0.63":"dev"}}function D2(Z){if(Z===n0)return;throw new S(`Unsupported ACP protocol version ${Z}; expected ${n0}`)}function $2(Z){return V9.toWeb(Z)}function G2(Z){return H9.toWeb(Z)}function E4(Z){return Z!==null&&typeof Z==="object"}function B9(Z){if(!Array.isArray(Z))return[];let Q=[];for(let X of Z){if(!E4(X))continue;if(typeof X.group==="string"&&Array.isArray(X.options)){let K=typeof X.name==="string"?X.name:X.group;for(let Y of X.options){if(!E4(Y))continue;if(typeof Y.value!=="string"||typeof Y.name!=="string")continue;Q.push({value:Y.value,name:Y.name,description:typeof Y.description==="string"?Y.description:null,group:X.group,groupName:K})}continue}if(typeof X.value!=="string"||typeof X.name!=="string")continue;Q.push({value:X.value,name:X.name,description:typeof X.description==="string"?X.description:null,group:null,groupName:null})}return Q}function F9(Z){if(!E4(Z))return null;if(typeof Z.id!=="string"||typeof Z.name!=="string")return null;let Q=typeof Z.category==="string"?Z.category:null,X=typeof Z.description==="string"?Z.description:null;if(Z.type==="select"){let K=typeof Z.currentValue==="string"?Z.currentValue:null;return{id:Z.id,name:Z.name,category:Q,description:X,type:"select",currentValue:K,options:B9(Z.options)}}if(Z.type==="boolean"){let K=typeof Z.currentValue==="boolean"?Z.currentValue:typeof Z.value==="boolean"?Z.value:null;return{id:Z.id,name:Z.name,category:Q,description:X,type:"boolean",currentValue:K,options:[]}}return null}function m4(Z){let Q=(Z.configOptions??[]).map(F9).filter((B)=>B!==null),X=Q.find((B)=>B.type==="select"&&B.category==="model")??Q.find((B)=>B.type==="select"&&B.id==="model")??null,K=X?.options.map((B)=>({id:B.value,name:B.name,description:B.description??null})),Y=w9(Z.models),W=K&&K.length>0?K:Y&&Y.length>0?Y:null,z=(typeof X?.currentValue==="string"?X.currentValue:null)??L9(Z.models)??null;return{models:W,currentModelId:z,configOptions:Q,modelConfigId:X?.id??null}}function w9(Z){if(!Z||!Array.isArray(Z.availableModels))return null;let Q=[];for(let X of Z.availableModels){if(typeof X.modelId!=="string")continue;Q.push({id:X.modelId,name:typeof X.name==="string"?X.name:null,description:typeof X.description==="string"?X.description:null})}return Q.length>0?Q:null}function L9(Z){return typeof Z?.currentModelId==="string"?Z.currentModelId:null}function P9(Z,Q){let X=[];if(Z.trim())X.push({type:"text",text:Z});for(let K of Q)if(K.content.trim())X.push({type:"text",text:K.content});return X}function x9(Z){if(typeof Z.value==="boolean")return{sessionId:Z.sessionId,configId:Z.configId,type:"boolean",value:Z.value};return{sessionId:Z.sessionId,configId:Z.configId,value:Z.value}}function b9(Z,Q){let X=m4({configOptions:Q.configOptions});return{models:X.models??Z.models,currentModelId:X.currentModelId??Z.currentModelId,configOptions:X.configOptions,modelConfigId:X.modelConfigId??Z.modelConfigId}}function g2(Z,Q){if(Z==="default")return null;if(!Q||Q.length===0)return Z;let X=Q.find((q)=>q.id===Z);if(X)return X.id;let K=Z.toLowerCase(),Y=K.includes("opus")?"opus":K.includes("sonnet")?"sonnet":K.includes("haiku")?"haiku":null;if(!Y)return Z;let W=(q)=>`${q.id} ${q.name??""} ${q.description??""}`.toLowerCase(),z=Q.filter((q)=>W(q).includes(Y));if(z.length===0)return Z;let w=(K.includes("1m")?z.find((q)=>W(q).includes("1m")):void 0)??z[0];return w?w.id:Z}async function _1(Z){try{let Q=await Z.conn.setSessionConfigOption(x9({sessionId:Z.sessionId,configId:Z.configId,value:Z.value}));return b9(Z.metadata,Q)}catch(Q){return console.warn(`[acp] setSessionConfigOption(${Z.label}) failed; using agent default.`,Q instanceof Error?Q.message:Q),Z.metadata}}async function k4(Z){let Q=h4(Z.spawn),X=[],K=0,Y=4096;Q.stderr.on("data",(_)=>{X.push(_),K+=_.length;while(K>Y*2&&X.length>1){let i=X.shift();if(i)K-=i.length}});let W=()=>{let _=Buffer.concat(X).toString("utf8");return _.length>Y?_.slice(-Y):_},z=x2(Z.spawn.cwd),B={current:null},w={current:null},q={at:Date.now()},b=null,M=G2(Q.stdin),x=$2(Q.stdout),y=h2(M,x),$=new f2((_)=>({requestPermission:async(i)=>{let A=i.options,Z0=A?.find((s)=>s.kind==="allow_once")??A?.find((s)=>s.kind==="allow_always");if(Z0)return{outcome:{outcome:"selected",optionId:Z0.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(i)=>{q.at=Date.now();let A=w.current;if(A){let s=i.update.sessionUpdate;if(A.updateCount+=1,A.updateCount===1||A.lastUpdateType!==s||s==="tool_call"||s==="tool_call_update")m("acp.session_update",{runId:A.runId,cardId:A.cardId,sessionId:b,updateType:s,updateCount:A.updateCount,elapsedMs:Date.now()-A.startedAt});A.lastUpdateType=s}let Z0=B.current;if(Z0)await Z0.onSessionUpdate(i)},readTextFile:z.readTextFile}),y),C=()=>Q.kill();if(Z.signal)Z.signal.addEventListener("abort",C);let N=()=>{if(Z.signal)Z.signal.removeEventListener("abort",C)},f=async(_,i)=>{if(N(),Q.kill(),M2(_))throw new I0(_.message??"Authentication required",i);if(_ instanceof Error&&_.message==="ACP connection closed"){if(Z.signal?.aborted)throw new S("ACP session cancelled: abort signal received");let A=await Promise.race([Q.processCrashed,Q.waitForExit,new Promise((Z0)=>setTimeout(()=>Z0({stderr:""}),500))]);throw new S(`Runtime process exited before completion: ${A.stderr?.trim()??""}`)}throw _},E;try{E=await $.initialize({protocolVersion:n0,clientCapabilities:f4,clientInfo:N2()})}catch(_){throw await f(_,[]),Error("unreachable")}try{D2(E.protocolVersion)}catch(_){throw N(),Q.kill(),_}let G=E.authMethods?.map((_)=>_.id)??[],I;try{I=await $.newSession({cwd:Z.spawn.cwd,mcpServers:Z.mcpServers??[]})}catch(_){throw await f(_,G),Error("unreachable")}let D=I.sessionId;b=D;let L=m4(I),g=Z.modelId??null,l=g?g2(g,L.models):null;if(l&&l!==L.currentModelId)if(L.modelConfigId)L=await _1({conn:$,sessionId:D,configId:L.modelConfigId,value:l,metadata:L,label:`${L.modelConfigId}=${l}`});else console.warn(`[acp] runtime did not advertise a model config option for ${l}; using agent default.`);for(let[_,i]of Object.entries(Z.configValues??{}).sort(([A],[Z0])=>A.localeCompare(Z0))){if(_===L.modelConfigId)continue;if(!L.configOptions.some((A)=>A.id===_))continue;L=await _1({conn:$,sessionId:D,configId:_,value:i,metadata:L,label:`${_}=${String(i)}`})}N();let a=!1,_0=async()=>{if(a)return;a=!0,Q.kill(),await Promise.race([Q.waitForExit,new Promise((_)=>setTimeout(_,2000))])},P0=!1;return Q.processCrashed.then(()=>{P0=!0}),{sessionId:D,availableModels:L.models,currentModelId:L.currentModelId,availableConfigOptions:L.configOptions,isAlive:()=>!a&&!P0,dispose:_0,prompt:(_)=>O9({proc:Q,conn:$,sessionId:D,activeAdapter:B,activeTrace:w,lastUpdate:q,collectStderrTail:W},_)}}async function O9(Z,Q){let{proc:X,conn:K,sessionId:Y,activeAdapter:W,activeTrace:z,lastUpdate:B}=Z,w=Date.now(),q=Q.heartbeatMs??z9,b=U9(q),M={boardId:Q.boardId,cardId:Q.cardId,runId:Q.runId},x=v2({ctx:M,appendText:Q.appendText,appendToolActivity:Q.appendToolActivity});W.current=x,z.current={runId:Q.runId,cardId:Q.cardId,startedAt:w,updateCount:0,lastUpdateType:null},B.at=Date.now(),m("acp.prompt_started",{runId:Q.runId,cardId:Q.cardId,sessionId:Y,heartbeatWindowMs:q});let y=!1,v=null,$=()=>X.kill();Q.signal.addEventListener("abort",$);try{let C=async()=>{let G=Math.min(q9,Math.max(50,Math.floor(q/2)));v=setInterval(()=>{let D=Q.isAwaitingInput?.()??!1;if(D){B.at=Date.now();return}if(y2({nowMs:Date.now(),lastUpdateMs:B.at,windowMs:q,awaitingInput:D}))y=!0,m("acp.inactivity_timeout",{runId:Q.runId,cardId:Q.cardId,sessionId:Y,windowMs:q,silentForMs:Date.now()-B.at}),K.cancel({sessionId:Y}).catch(()=>{return}),X.kill()},G);let I=P9(Q.prompt.systemPrompt,Q.prompt.messages);await K.prompt({sessionId:Y,prompt:I}),m("acp.prompt_resolved",{runId:Q.runId,cardId:Q.cardId,sessionId:Y,elapsedMs:Date.now()-w}),x.flush({completeOpenToolCalls:!0})},N=X.waitForExit.then((G)=>({kind:"exited",exit:G})),f=C().then(()=>({kind:"ok"})).catch(async(G)=>{if(G instanceof Error&&G.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([X.processCrashed,X.waitForExit])};throw G}),E;try{E=await Promise.race([f,X.processCrashed.then((G)=>({kind:"crashed",exit:G})),N])}catch(G){if(y)throw new q0(b);throw G}if(y)throw new q0(b);if(E.kind==="crashed")throw new S(`Runtime process exited before completion: ${E.exit.stderr.trim()}`);if(E.kind==="exited"){if(Q.signal.aborted)throw new S("ACP session cancelled: abort signal received");if(y)throw new q0(b);throw new S(`Runtime process exited unexpectedly: ${E.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:x.getFinalText(),toolCallsExecuted:x.getToolCallCount(),stderrTail:Z.collectStderrTail(),updateTypeCounts:x.getUpdateTypeCounts()}}finally{if(m("acp.prompt_finished",{runId:Q.runId,cardId:Q.cardId,sessionId:Y,elapsedMs:Date.now()-w,timedOut:y,updateCount:z.current?.updateCount??0}),v!==null)clearInterval(v);Q.signal.removeEventListener("abort",$),x.flush({completeOpenToolCalls:!0}),W.current=null,z.current=null}}var C9=30000;async function E2(Z){let Q=h4(Z.spawn),X=G2(Q.stdin),K=$2(Q.stdout),Y=h2(X,K),z=new f2((q)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Y),B=()=>Q.kill();if(Z.signal)Z.signal.addEventListener("abort",B);let w=null;try{let q=(async()=>{let M=await z.initialize({protocolVersion:n0,clientCapabilities:f4,clientInfo:N2()});D2(M.protocolVersion);let x=M.authMethods?.map((E)=>E.id)??[],y;try{y=await z.newSession({cwd:Z.spawn.cwd,mcpServers:[]})}catch(E){if(M2(E))throw new I0(E.message??"Authentication required",x);throw E}let v=m4(y),$=Z.modelId??null,C=$?g2($,v.models):null;if(C&&C!==v.currentModelId)if(v.modelConfigId)v=await _1({conn:z,sessionId:y.sessionId,configId:v.modelConfigId,value:C,metadata:v,label:`${v.modelConfigId}=${C}`});else console.warn(`[acp] runtime did not advertise a model config option for ${C}; discovering agent default models.`);for(let[E,G]of Object.entries(Z.configValues??{}).sort(([I],[D])=>I.localeCompare(D))){if(E===v.modelConfigId)continue;if(!v.configOptions.some((I)=>I.id===E))continue;v=await _1({conn:z,sessionId:y.sessionId,configId:E,value:G,metadata:v,label:`${E}=${String(G)}`})}let N=v.models??[],f=v.currentModelId;return z.cancel({sessionId:y.sessionId}).catch(()=>{return}),{models:N,configOptions:v.configOptions,currentModelId:f}})(),b=new Promise((M,x)=>{w=setTimeout(()=>{x(new q0)},C9)});return await Promise.race([q,b])}catch(q){if(q instanceof Error&&q.message==="ACP connection closed"){if(Z.signal?.aborted)throw new S("ACP model discovery cancelled: abort signal received");throw new S("Runtime process exited during model discovery.")}throw q}finally{if(w)clearTimeout(w);if(Z.signal)Z.signal.removeEventListener("abort",B);Q.kill()}}import v9 from"node:fs/promises";import S1 from"node:os";async function m2(Z){let Q={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},X;try{X=await v9.readFile(Z,"utf-8")}catch(K){if(K.code==="ENOENT")return structuredClone(Q);throw K}return C1.parse(JSON.parse(X))}function _4(Z,Q,X){return{...Z.defaultConfigValues??{},...Q?.configValues??{},...X?.configValues??{}}}async function O0(Z){let Q=Z.configPath?await m2(Z.configPath):await J0(),X=Z.cardId?Q.cardOverrides[Z.cardId]:void 0;if(X?.runtimeConfigId){let Y=Q.runtimes.find((W)=>W.id===X.runtimeConfigId);if(Y)return{entry:Y,adapter:U0(Y),runFolder:X.runFolder??Y.runFolder??S1.homedir(),modelId:X.modelId??Y.defaultModelId??null,configValues:_4(Y,void 0,X)}}let K=Q.boardOverrides[Z.boardId];if(K?.runtimeConfigId){let Y=Q.runtimes.find((W)=>W.id===K.runtimeConfigId);if(Y)return{entry:Y,adapter:U0(Y),runFolder:K.runFolder??Y.runFolder??S1.homedir(),modelId:K.modelId??Y.defaultModelId??null,configValues:_4(Y,K)}}if(Q.globalDefaultConfigId){let Y=Q.runtimes.find((W)=>W.id===Q.globalDefaultConfigId);if(Y)return{entry:Y,adapter:U0(Y),runFolder:X?.runFolder??K?.runFolder??Y.runFolder??S1.homedir(),modelId:X?.modelId??K?.modelId??Y.defaultModelId??null,configValues:_4(Y,K,X)}}throw new D0}async function k2(Z,Q={}){let K=(Q.configPath?await m2(Q.configPath):await J0()).runtimes.find((Y)=>Y.id===Z);if(!K)return null;return{entry:K,adapter:U0(K),runFolder:K.runFolder??S1.homedir(),modelId:Q.modelId??K.defaultModelId??null,configValues:{...K.defaultConfigValues??{},...Q.configValues??{}}}}var _2=new Map;function S4(Z,Q){if(!Z)return;_2.set(Z,Q)}function S2(Z){if(!Z)return!1;return _2.get(Z)??!1}var g0=new Map,I4=new Set;function T4(Z){g0.get(Z)?.controller.abort()}function I2(Z){for(let[Q,X]of g0){if(X.frontendSessionId!==Z)continue;X.controller.abort(),g0.delete(Q)}}function u2(){for(let Z of g0.values())Z.controller.abort();g0.clear()}function u4(Z,Q){if(Q?.aborted)return!0;return Z instanceof Error&&/abort signal received|session cancelled/i.test(Z.message)}function T2(Z,Q,X,K){if((!Q.availableModels||Q.availableModels.length===0)&&Q.availableConfigOptions.length===0)return;V0((Y)=>{let W=Y.runtimes.find((z)=>z.id===Z);if(W){if(Q.availableModels&&Q.availableModels.length>0)W.discoveredModels=$1({adapterId:X,models:Q.availableModels,currentModelId:Q.currentModelId??K});if(Q.availableConfigOptions.length>0)W.discoveredConfigOptions=Q.availableConfigOptions}}).catch(()=>{return})}function R9(Z,Q){return`${Z}
19
19
 
20
20
  Runtime run folder:
21
21
  - Effective run folder: ${Q}
@@ -45,4 +45,4 @@ Content-Length: ${W.byteLength}\r
45
45
  Connection: close\r
46
46
  Content-Length: ${Buffer.byteLength(X)}\r
47
47
  \r
48
- ${X}`),Z.destroy()}function JX(Z,Q){return new Promise((X,K)=>{let Y=(z)=>{Z.off("listening",W),K(z)},W=()=>{Z.off("error",Y);let z=Z.address();if(!z||typeof z==="string"){K(Error("Failed to read CLI bridge server address"));return}X(z.port)};Z.once("error",Y),Z.once("listening",W),Z.listen(Q,"127.0.0.1")})}function O3(Z){return new Promise((Q,X)=>{Z.close((K)=>{if(K)X(K);else Q()})})}async function y3(Z,Q=B6()){let X=new Map,K=new Map,Y=Z.maxMessageSize??pQ,W=!1,z=(x)=>{let y=K.get(x);if(y)clearTimeout(y);K.delete(x)},B=(x)=>{K.delete(x);let{activeRunIds:y}=Z.registry.disconnect(x);Z.onDisconnect(x,y)},w=(x,y)=>{let v={type:"cli_status",connected:!0,runtime:Z.runtime,mcpReady:Z.mcpReady(),error:y,capabilities:Z.capabilities??[],cliVersion:Z.cliVersion,browserRuntime:Z.browserRuntimeStatus?.()};if(x){let $=X.get(x);if($)a0($,v);return}for(let $ of X.values())a0($,v)},q=(x,y)=>{let v=y.sessionId.trim(),$=y.userId.trim();if(!v||!$){a0(x,{type:"cli_status",connected:!1,runtime:Z.runtime,mcpReady:Z.mcpReady(),error:"Missing frontend session or user id"}),x.close();return}z(v);let C=X.get(v);if(C&&C!==x)C.close();x.data.frontendSessionId=v,X.set(v,x),Z.registry.register({frontendSessionId:v,userId:$,tools:y.tools,send:(N)=>a0(x,N)}),w(v),Z.onToolMetadata?.(v)},b=(x,y)=>{let v=Z.registry.getUserId(x);if(!v)return;switch(y.type){case"bridge_ping":{let $=X.get(x);if($)a0($,{type:"bridge_pong"});break}case"tool_metadata":Z.registry.setMetadata(x,y.tools),Z.onToolMetadata?.(x);break;case"tool_result":Z.registry.handleToolResult(x,y);break;case"run_turn":m("bridge.run_received",{runId:y.run.runId,cardId:y.run.cardId,frontendSessionId:x}),Z.registry.markRunActive(x,y.run.runId,y.run.cardId),Z.onRunTurn(x,{...y.run,frontendSessionId:x,userId:v});break;case"cancel_run":if(Z.registry.ownsRun(x,y.runId))Z.onCancelRun(x,y.runId);break;case"runtime_rpc":Z.onRuntimeRpc(x,y);break;case"browser_rpc":Z.onBrowserRpc?.(x,X.get(x)?.data.frontendOrigin??"",y);break;case"warmup_run":Z.onWarmupRun(x,{...y,frontendSessionId:x},v);break;default:break}},M=(x,y)=>{let v=F6(x.headers.origin),$=x3(v),C={Vary:"Origin"};if($&&v)C["Access-Control-Allow-Origin"]=v,C["Access-Control-Allow-Private-Network"]="true";if(x.method==="OPTIONS"){y.writeHead(204,{...C,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),y.end();return}if(x.method!=="GET"){y.writeHead(405,C),y.end();return}y.writeHead(200,{...C,"content-type":"application/json","cache-control":"no-store"}),y.end(JSON.stringify({ideawave:!0,runtime:Z.runtime,mcpReady:Z.mcpReady(),capabilities:Z.capabilities??[],cliVersion:Z.cliVersion,browserRuntime:Z.browserRuntimeStatus?.()}))};for(let x of Q){let y=aQ((C,N)=>{(async()=>{if(new URL(C.url??"/","http://127.0.0.1").pathname===w3){M(C,N);return}if(await Z.onHttpRequest?.(C,N))return;N.writeHead(404,{"content-type":"text/plain"}),N.end("IdeaWave CLI bridge")})().catch((f)=>{if(N.headersSent){N.destroy(f instanceof Error?f:void 0);return}N.writeHead(500,{"content-type":"text/plain"}),N.end("IdeaWave CLI bridge request failed")})}),v=new iQ({noServer:!0,maxPayload:Y}),$=(C)=>{if(C.idleTimer)clearTimeout(C.idleTimer);C.idleTimer=setTimeout(()=>{C.close()},sQ),C.idleTimer.unref?.()};v.on("connection",(C,N)=>{let f=C;f.data={id:dQ(),frontendSessionId:null,frontendOrigin:new URL(F6(N.headers.origin)??v3).origin},f.idleTimer=null,$(f),f.on("ping",()=>$(f)),f.on("pong",()=>$(f)),f.on("error",()=>{if(f.idleTimer)clearTimeout(f.idleTimer);f.close()}),f.on("message",(E)=>{$(f);let G=XX(E);if(Y>0&&G.length>Y)return;let I=b1(G);if(!I)return;let D=f.data.frontendSessionId;if(!D){if(I.type==="bridge_probe")a0(f,{type:"bridge_probe_ack",protocolVersion:I.protocolVersion});else if(I.type==="frontend_hello")q(f,I);return}b(D,I)}),f.on("close",()=>{if(f.idleTimer)clearTimeout(f.idleTimer);let E=f.data.frontendSessionId;if(!E)return;if(X.get(E)!==f)return;if(X.delete(E),z(E),W)return;K.set(E,setTimeout(()=>B(E),rQ))})}),y.on("upgrade",(C,N,f)=>{if(new URL(C.url??"/","http://127.0.0.1").pathname!==U6){b3(N,404,"Not Found");return}if(!x3(F6(C.headers.origin))){b3(N,403,"Forbidden");return}v.handleUpgrade(C,N,f,(G)=>{v.emit("connection",G,C)})});try{let C=await JX(y,x);return{url:`ws://127.0.0.1:${C}${U6}`,port:C,sendStatus:w,close:async()=>{W=!0;for(let N of K.values())clearTimeout(N);K.clear();for(let N of v.clients){let f=N;if(f.idleTimer)clearTimeout(f.idleTimer);f.close()}v.close(),await O3(y).catch(()=>{return})}}}catch(C){if(v.close(),await O3(y).catch(()=>{return}),C?.code==="EADDRINUSE")continue;throw C}}throw Error(`No free IdeaWave CLI bridge port found in ${Q[0]}-${Q.at(-1)}`)}import{Server as PX}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as xX,ListToolsRequestSchema as bX}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as YX}from"node:crypto";import{createServer as WX}from"node:http";import{StreamableHTTPServerTransport as VX}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as N3}from"@modelcontextprotocol/sdk/types.js";var f3=new Set(["127.0.0.1","localhost","[::1]","::1"]);function KX(Z){let Q=Z.trim();if(Q.length===0)return null;if(Q.startsWith("[")){let W=Q.indexOf("]");if(W===-1)return null;let z=Q.slice(0,W+1),B=Q.slice(W+1);if(B.length===0)return{host:z,port:null};if(!B.startsWith(":"))return null;let w=Number(B.slice(1));if(!Number.isInteger(w)||w<=0||w>65535)return null;return{host:z,port:w}}let X=Q.lastIndexOf(":");if(X===-1)return{host:Q,port:null};let K=Q.slice(X+1),Y=Number(K);if(!Number.isInteger(Y)||Y<=0||Y>65535)return{host:Q,port:null};return{host:Q.slice(0,X),port:Y}}function h3(Z){return f3.has(Z)||f3.has(Z.toLowerCase())}function M3(Z,Q){let X=Z.headers.host;if(typeof X!=="string")return{ok:!1,status:403,reason:"missing-host"};let K=KX(X);if(!K)return{ok:!1,status:403,reason:"bad-host"};if(!h3(K.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(K.port!==null&&K.port!==Q)return{ok:!1,status:403,reason:"host-port-mismatch"};let Y=Z.headers.origin;if(typeof Y==="string"&&Y.length>0){if(Y!=="null"){let W;try{W=new URL(Y)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!h3(W.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var D3="/mcp",HX=43274,G3=16777216,jX=1800000,zX=300000,$3=200,qX=-32700,f0=-32600,L6=-32603;function W0(Z,Q,X,K,Y){Z.statusCode=Q,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify({jsonrpc:"2.0",error:{code:X,message:K,...Y?{data:Y}:{}},id:null}))}class P6 extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class x6 extends Error{constructor(){super(`body exceeds ${G3} bytes`);this.name="BodyTooLargeError"}}async function UX(Z){if(Z.method&&Z.method!=="POST")return;let Q=Z.headers["content-type"];if(typeof Q==="string"&&Q.trim().length>0){if(!Q.toLowerCase().includes("application/json"))throw new P6}let X=0,K=[];for await(let W of Z){let z=typeof W==="string"?Buffer.from(W):W;if(X+=z.byteLength,X>G3)throw new x6;K.push(z)}if(K.length===0)return;let Y=Buffer.concat(K).toString("utf8");if(Y.length===0)return;return JSON.parse(Y)}function BX(Z){if(Array.isArray(Z))return Z.some(N3);return N3(Z)}function FX(Z){if(typeof Z==="number")return Z;let Q=process.env.IDEAWAVE_MCP_PORT;if(Q&&Q.trim().length>0){let X=Number(Q);if(Number.isInteger(X)&&X>=0&&X<65536)return X}return HX}async function wX(Z,Q){let X=(Y)=>new Promise((W,z)=>{let B=(q)=>{Z.off("listening",w),z(q)},w=()=>{Z.off("error",B),W()};Z.once("error",B),Z.once("listening",w),Z.listen(Y,"127.0.0.1")});try{await X(Q)}catch(Y){if(Y.code!=="EADDRINUSE"||Q===0)throw Y;console.warn(`[mcp] port ${Q} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await X(0)}let K=Z.address();if(K==null||typeof K==="string")throw Error("[mcp] failed to read bound address");return K.port}function LX(Z,Q){if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let K=Q.params;if(K&&typeof K==="object"&&!Array.isArray(K)){let Y=K.clientInfo;if(Y&&typeof Y==="object"&&!Array.isArray(Y)){let W=Y.name;if(typeof W==="string"&&W.trim().length>0)return W.trim()}}}let X=Z.headers["user-agent"];if(typeof X==="string"&&X.trim().length>0)return X.trim();return null}async function g3(Z){let Q=new Map,X=0;function K(q){let b=Q.get(q);if(b)b.lastActivity=Date.now()}async function Y(q,b){Q.delete(q),await b.transport.close().catch(()=>{return})}async function W(){let q=null,b=1/0;for(let[M,x]of Q)if(x.lastActivity<b)b=x.lastActivity,q=M;if(q!==null){let M=Q.get(q);if(M)console.warn(`[mcp] session cap of ${$3} reached; evicting ${q}`),await Y(q,M)}}let z=setInterval(()=>{let q=Date.now()-jX;for(let[b,M]of Q)if(M.lastActivity<q)console.log(`[mcp] sweeping idle session ${b}`),Y(b,M)},zX);z.unref?.();let B=WX((q,b)=>{(async()=>{let M;try{M=new URL(q.url??"/","http://127.0.0.1").pathname}catch{W0(b,400,f0,"bad-url");return}if(M!==D3){W0(b,404,f0,"not-found");return}let x=q.method??"POST";if(x!=="POST"&&x!=="GET"&&x!=="DELETE"){b.setHeader("Allow","GET, POST, DELETE"),W0(b,405,f0,"method-not-allowed");return}let y=M3(q,X);if(!y.ok){W0(b,y.status,f0,"forbidden",{reason:y.reason});return}let v=q.headers["mcp-session-id"],$=typeof v==="string"?v:void 0;if(x==="GET"||x==="DELETE"){if(!$||!Q.has($)){W0(b,400,f0,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let f=Q.get($).transport;K($);try{await f.handleRequest(q,b)}catch(E){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",E),!b.headersSent)W0(b,500,L6,"internal")}return}let C;try{C=await UX(q)}catch(f){if(f instanceof P6){W0(b,415,f0,"expected-application-json");return}if(f instanceof x6){W0(b,413,f0,"body-too-large");return}W0(b,400,qX,"invalid-json");return}let N;if($&&Q.has($))N=Q.get($).transport,K($);else if(!$&&C!==void 0&&BX(C)){let f=q.headers["x-ideawave-user-id"],E=typeof f==="string"&&f.trim().length>0?f.trim():null,G=q.headers["x-ideawave-frontend-session-id"],I=typeof G==="string"&&G.trim().length>0?G.trim():null,D=q.headers["x-ideawave-tool-surface"],L=typeof D==="string"&&D.trim()==="read"?"read":"full",g=q.headers["x-ideawave-images-supported"],l=typeof g==="string"&&g.trim()==="1",a=q.headers["x-ideawave-card-id"],_0=typeof a==="string"&&a.trim().length>0?a.trim():null,P0=q.headers["x-ideawave-board-id"],_=typeof P0==="string"&&P0.trim().length>0?P0.trim():null,i=q.headers["x-ideawave-run-folder"],A=typeof i==="string"&&i.trim().length>0?i.trim():null,Z0=LX(q,C);if(Q.size>=$3)await W();let s=null,N0=new VX({sessionIdGenerator:()=>YX(),onsessioninitialized:(S0)=>{s=S0,Q.set(S0,{transport:N0,lastActivity:Date.now()})},onsessionclosed:(S0)=>{Q.delete(S0)}});N0.onclose=()=>{if(N0.sessionId)Q.delete(N0.sessionId)};try{await Z.buildServer({userId:E,frontendSessionId:I,boardId:_,toolSurface:L,imagesSupported:l,cardId:_0,runFolder:A,clientHint:Z0}).connect(N0)}catch(S0){if(console.error("[mcp] buildServer/connect failed",S0),s)Q.delete(s);await N0.close().catch(()=>{return}),W0(b,500,L6,"server-init-failed");return}N=N0}else{W0(b,400,f0,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await N.handleRequest(q,b,C)}catch(f){if(console.error("[mcp] transport.handleRequest threw",f),!b.headersSent)W0(b,500,L6,"internal")}})().catch((M)=>{console.error("[mcp] unhandled request handler error:",M)})});return X=await wX(B,FX(Z.port)),{url:`http://127.0.0.1:${X}${D3}`,port:X,close:async()=>{clearInterval(z);for(let q of Q.values())await q.transport.close().catch(()=>{return});Q.clear(),await new Promise((q)=>B.close(()=>q()))}}}var OX={name:"ideawave-board",version:"1.0.0"},Q4="list_run_folder",X4="read_run_folder_file",k3=new Set(["list_boards","get_board","list_nodes","list_edges","inspect_node","list_context_sources","read_context_card","read_context_file","read_context_image","list_context_folder","get_board_wiki","search_board","get_card_messages","list_agent_cards","inspect_neighbors",Q4,X4]),_3=new Set(["inspect_diagram"]),CX=[{name:Q4,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:X4,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 b6(Z){return{content:[{type:"text",text:Z}]}}function vX(Z){return b6(JSON.stringify(Z,null,2))}function E3(Z){return{...b6(Z),isError:!0}}function RX(Z,Q,X="full",K=!1){return Z.getMetadata(Q).filter((Y)=>{let W=E1(Y.name);if(X==="read"&&!k3.has(W))return!1;if(!K&&_3.has(W))return!1;return!0}).map((Y)=>({name:Y.name,description:Y.description,inputSchema:Y.inputSchema}))}function yX(Z,Q,X={}){let K=RX(Z,Q,X.toolSurface??"full",X.imagesSupported??!1);return X.includeRunFolderTools?[...K,...CX]:K}function m3(Z,Q){if(!Z||typeof Z!=="object"||Array.isArray(Z))return null;let X=Z[Q];return typeof X==="string"?X:null}async function fX(Z,Q,X){if(X&&X.trim().length>0)return X.trim();if(!Z||!Q)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await O0({boardId:Z,cardId:Q})).runFolder}async function hX(Z){let Q=await fX(Z.boardId,Z.cardId,Z.runFolder);if(Z.name===Q4){let X=m3(Z.args,"path")??"",K=await P2(Q,X);return vX(K)}if(Z.name===X4){let X=m3(Z.args,"path");if(!X)return E3("read_run_folder_file requires a path.");return b6(await g1(Q,X))}return E3(`Unknown local tool "${Z.name}"`)}function MX(Z,Q,X,K,Y,W="full",z=!1){let B=new PX(OX,{capabilities:{tools:{}}}),w=async()=>{if(z)return!0;if(S2(K))return!0;if(X&&K)try{return(await O0({boardId:X,cardId:K})).adapter.supportsImages===!0}catch{return!1}return!1};return B.setRequestHandler(bX,async()=>({tools:yX(Z,Q,{includeRunFolderTools:Boolean(Y||X&&K),toolSurface:W,imagesSupported:await w()})})),B.setRequestHandler(xX,async(q)=>{let{name:b,arguments:M}=q.params,x=E1(b),y=Date.now();m("mcp.tool_call_received",{frontendSessionId:Q,cardId:K,toolName:x});try{if(x===Q4||x===X4)return await hX({name:x,args:M,boardId:X,cardId:K,runFolder:Y});if(W==="read"&&!k3.has(x))throw Error(`Tool "${b}" is not available in read-only mode`);if(_3.has(x)&&!await w())throw Error(`Tool "${b}" requires a runtime that supports image input`);let v=await Z.callTool(Q,x,M??{},void 0,K??void 0);if(m("mcp.tool_result_returned",{frontendSessionId:Q,cardId:K,toolName:x,elapsedMs:Date.now()-y}),v&&typeof v==="object"&&Array.isArray(v.content))return v;return{content:[{type:"text",text:typeof v==="string"?v:JSON.stringify(v)}]}}catch(v){return m("mcp.tool_result_returned",{frontendSessionId:Q,cardId:K,toolName:x,elapsedMs:Date.now()-y,hasError:!0}),{content:[{type:"text",text:v instanceof Error?v.message:"Tool call failed"}],isError:!0}}}),B}function S3(Z,Q){return g3({buildServer:(X)=>MX(Z,X.frontendSessionId,X.boardId,X.cardId,X.runFolder,X.toolSurface,X.imagesSupported),port:Q})}import J4 from"node:fs/promises";import O6 from"node:os";import K4 from"node:path";function I3(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function NX(){let[Z,Q]=await Promise.all([J0(),U2()]),X=Z.globalDefaultConfigId?Z.runtimes.find((K)=>K.id===Z.globalDefaultConfigId)??null:null;return{runtimes:Z.runtimes,globalDefaultConfigId:Z.globalDefaultConfigId,globalDefaultEffective:X?{runFolder:X.runFolder??O6.homedir(),modelId:X.defaultModelId??null,configValues:X.defaultConfigValues??{}}:null,knownAdapters:T0().map((K)=>({id:K.id,displayName:K.displayName})),readiness:Q}}async function DX(Z){try{let Q=await O0({boardId:Z.boardId,cardId:Z.cardId});return{resolved:{configId:Q.entry.id,adapterId:Q.entry.kind==="registered"?Q.entry.adapterId:null,displayName:Q.entry.displayName,runFolder:Q.runFolder,modelId:Q.modelId,configValues:Q.configValues}}}catch(Q){if(Q instanceof D0)return{resolved:null};throw Q}}async function $X(Z){return V0((Q)=>{let X=Q.runtimes.find((W)=>W.kind==="registered"&&W.adapterId===Z.adapterId);if(X)return X;let K=T0().find((W)=>W.id===Z.adapterId);if(!K)throw Error(`Unknown adapterId: ${Z.adapterId}`);let Y={id:I3(),kind:"registered",adapterId:Z.adapterId,displayName:K.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return Q.runtimes.push(Y),Y})}async function GX(Z){return V0((Q)=>{let X={id:I3(),kind:"custom",displayName:Z.displayName,command:Z.command,args:Z.args,env:Z.env,runFolder:Z.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return Q.runtimes.push(X),X})}async function gX(Z){await V0((Q)=>{if(Q.runtimes=Q.runtimes.filter((X)=>X.id!==Z.runtimeConfigId),Q.globalDefaultConfigId===Z.runtimeConfigId)Q.globalDefaultConfigId=null;for(let X of Object.keys(Q.boardOverrides))if(Q.boardOverrides[X].runtimeConfigId===Z.runtimeConfigId)delete Q.boardOverrides[X];for(let X of Object.keys(Q.cardOverrides))if(Q.cardOverrides[X].runtimeConfigId===Z.runtimeConfigId)delete Q.cardOverrides[X]})}async function EX(Z){await V0((Q)=>{let X=Q.runtimes.find((K)=>K.id===Z.runtimeConfigId);if(!X)throw Error(`Runtime config not found: ${Z.runtimeConfigId}`);if(Q.globalDefaultConfigId=Z.runtimeConfigId,Z.runFolder!==void 0)X.runFolder=Z.runFolder;if(Z.modelId!==void 0)X.defaultModelId=Z.modelId;if(Z.configValues!==void 0)X.defaultConfigValues=Z.configValues})}async function mX(Z){Z.boardId,await V0((Q)=>{if(Z.runtimeConfigId===null){delete Q.cardOverrides[Z.cardId];return}if(!Q.runtimes.some((Y)=>Y.id===Z.runtimeConfigId))throw Error(`Runtime config not found: ${Z.runtimeConfigId}`);let K=Q.cardOverrides[Z.cardId];Q.cardOverrides[Z.cardId]={runtimeConfigId:Z.runtimeConfigId,runFolder:Z.runFolder!==void 0?Z.runFolder:K?.runFolder??null,modelId:Z.modelId!==void 0?Z.modelId:K?.modelId??null,configValues:Z.configValues!==void 0?Z.configValues:K?.configValues??{}}})}async function kX(Z){let X=(await J0()).runtimes.find((z)=>z.id===Z.runtimeConfigId);if(!X)throw Error(`Runtime config not found: ${Z.runtimeConfigId}`);let K=U0(X),Y=await K.resolveSpawnConfig(X),W=X.runFolder??O6.homedir();try{let z=await E2({spawn:{...Y,cwd:W},modelId:Z.modelId??X.defaultModelId??null,configValues:Z.configValues??X.defaultConfigValues??{}}),B=$1({adapterId:K.id,models:z.models,currentModelId:z.currentModelId}),w=new Date().toISOString();return await V0((q)=>{let b=q.runtimes.find((M)=>M.id===Z.runtimeConfigId);if(b)b.discoveredModels=B,b.discoveredConfigOptions=z.configOptions,b.discoveredAt=w}),{ok:!0,models:B,configOptions:z.configOptions,currentModelId:z.currentModelId}}catch(z){if(z instanceof I0)throw Error(`${z.message}${K.authHint?` ${K.authHint}`:""}`);if(z instanceof S||z instanceof q0)throw Error(z.message);throw z}}async function _X(Z){let Q=O6.homedir(),X=Z.path?.trim()?Z.path.trim():Q,K=K4.resolve(X),Y=!0;try{if(!(await J4.stat(K)).isDirectory())K=K4.dirname(K)}catch{Y=!1,K=Q}let W=[];try{W=(await J4.readdir(K,{withFileTypes:!0})).filter((w)=>w.isDirectory()&&!w.name.startsWith(".")).map((w)=>({name:w.name,path:K4.join(K,w.name)})).sort((w,q)=>w.name.localeCompare(q.name))}catch{W=[]}let z=K4.dirname(K);return{path:K,parent:z===K?null:z,home:Q,exists:Y,entries:W}}var u3={list:NX,getEffectiveForCard:DX,registerRegistered:$X,registerCustom:GX,unregister:gX,setUserDefault:EX,setCardOverride:mX,refreshModels:kX,browseFolder:_X};var SX=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function IX(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function T3(){try{let Z=await J0();if(Z.globalDefaultConfigId){if(Z.runtimes.some((X)=>X.id===Z.globalDefaultConfigId))return Z.globalDefaultConfigId}for(let Q of SX){if((await B2(Q.id))?.status!=="ready")continue;let K=null;if(await V0((Y)=>{if(Y.globalDefaultConfigId){if(Y.runtimes.some((B)=>B.id===Y.globalDefaultConfigId)){K=Y.globalDefaultConfigId;return}}let W=Y.runtimes.find((z)=>z.kind==="registered"&&z.adapterId===Q.id);if(!W){let z={id:IX(),kind:"registered",adapterId:Q.id,displayName:Q.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Y.runtimes.push(z),W=z}Y.globalDefaultConfigId=W.id,K=W.id}),K)return console.log(`[ideawave-cli] using agent runtime: ${Q.displayName}`),K}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch(Z){return console.warn("[ideawave-cli] runtime auto-seed failed",Z),null}}var uX=120000;function TX(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class C6{sessions=new Map;createCallId;toolCallTimeoutMs;constructor(Z={}){this.createCallId=Z.createCallId??TX,this.toolCallTimeoutMs=Z.toolCallTimeoutMs??uX}register(Z){let Q=this.sessions.get(Z.frontendSessionId);if(Q){if(Q.userId!==Z.userId)this.rejectPending(Q,"frontend session user changed"),Q.activeRunIds.clear();this.sessions.set(Z.frontendSessionId,{frontendSessionId:Z.frontendSessionId,userId:Z.userId,tools:Z.tools,send:Z.send,pendingToolCalls:Q.pendingToolCalls,activeRunIds:Q.activeRunIds,activeRunCardIds:Q.activeRunCardIds});return}this.sessions.set(Z.frontendSessionId,{frontendSessionId:Z.frontendSessionId,userId:Z.userId,tools:Z.tools,send:Z.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect(Z,Q="frontend session disconnected"){let X=this.sessions.get(Z);if(!X)return{activeRunIds:[]};return this.sessions.delete(Z),this.rejectPending(X,Q),{activeRunIds:Array.from(X.activeRunIds)}}sessionCount(){return this.sessions.size}has(Z){return this.sessions.has(Z)}getUserId(Z){return this.sessions.get(Z)?.userId??null}setMetadata(Z,Q){let X=this.sessions.get(Z);if(X)X.tools=Q}getMetadata(Z){if(!Z)return[];return this.sessions.get(Z)?.tools??[]}sendToSession(Z,Q){let X=this.sessions.get(Z);if(!X)return!1;return X.send(Q),!0}callTool(Z,Q,X,K,Y){if(!Z)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let W=this.sessions.get(Z);if(!W)return Promise.reject(Error(`Frontend session ${Z} is not connected`));let z=this.createCallId();return new Promise((B,w)=>{let q=K??(Y?this.getActiveRunIdForCard(W,Y):this.getSoleActiveRunId(W)),b=Y??(q?W.activeRunCardIds.get(q):void 0),M=Date.now(),x=setTimeout(()=>{W.pendingToolCalls.delete(z),m("tool_queue.timeout",{frontendSessionId:Z,runId:q,cardId:b,callId:z,toolName:Q,elapsedMs:Date.now()-M,queueDepth:W.pendingToolCalls.size}),w(Error(`Tool "${Q}" timed out waiting for the frontend`))},this.toolCallTimeoutMs);W.pendingToolCalls.set(z,{resolve:B,reject:w,timer:x,name:Q,runId:q??null,cardId:b??null,startedAt:M}),m("tool_queue.forwarded_to_browser",{frontendSessionId:Z,runId:q,cardId:b,callId:z,toolName:Q,queueDepth:W.pendingToolCalls.size}),W.send({type:"tool_call",callId:z,name:Q,args:X,...q?{runId:q}:{},...b?{cardId:b}:{}})})}handleToolResult(Z,Q){let X=this.sessions.get(Z);if(!X)return;let K=X.pendingToolCalls.get(Q.callId);if(!K)return;if(X.pendingToolCalls.delete(Q.callId),clearTimeout(K.timer),m("tool_queue.result_received",{frontendSessionId:Z,runId:K.runId,cardId:K.cardId,callId:Q.callId,toolName:K.name,elapsedMs:Date.now()-K.startedAt,queueDepth:X.pendingToolCalls.size,ok:Q.ok}),Q.ok){K.resolve(Q.result);return}let Y=Q.result;if(Y&&typeof Y==="object"&&Array.isArray(Y.content)){K.resolve({...Y,isError:!0});return}K.reject(Error(Q.error??"Tool execution failed"))}markRunActive(Z,Q,X){let K=this.sessions.get(Z);if(!K)return;if(K.activeRunIds.add(Q),X)K.activeRunCardIds.set(Q,X)}markRunSettled(Z,Q){let X=this.sessions.get(Z);if(!X)return;X.activeRunIds.delete(Q),X.activeRunCardIds.delete(Q)}ownsRun(Z,Q){return this.sessions.get(Z)?.activeRunIds.has(Q)??!1}rejectPending(Z,Q){for(let X of Z.pendingToolCalls.values())clearTimeout(X.timer),m("tool_queue.rejected",{frontendSessionId:Z.frontendSessionId,runId:X.runId,cardId:X.cardId,toolName:X.name,elapsedMs:Date.now()-X.startedAt}),X.reject(Error(Q));Z.pendingToolCalls.clear()}getSoleActiveRunId(Z){return Z.activeRunIds.size===1?Z.activeRunIds.values().next().value:void 0}getActiveRunIdForCard(Z,Q){let X=[...Z.activeRunCardIds.entries()].filter(([K,Y])=>Z.activeRunIds.has(K)&&Y===Q).map(([K])=>K);return X.length===1?X[0]:void 0}}function l3(){return"0.0.61".trim()?"0.0.61":"dev"}var AX=process.argv.slice(2),c3=[];for(let Z of AX){if(Z==="--dev"){process.env[w6]="1";continue}c3.push(Z)}var h0=c3[0];if(h0==="--help"||h0==="-h"||h0==="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(h0==="--version"||h0==="-v"||h0==="version")console.log(l3()),process.exit(0);if(h0)console.error(`Unknown command: ${h0}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var B1=new C6,M0=null,d3={phase:"idle"},F1=new q6(new t0((Z)=>{d3=Z,M0?.sendStatus()}));function k0(Z,Q){B1.sendToSession(Z,Q)}async function lX(Z,Q){try{let X=u3[Q.method],K=await X(Q.params);k0(Z,{type:"runtime_rpc_result",requestId:Q.requestId,ok:!0,result:K})}catch(X){k0(Z,{type:"runtime_rpc_result",requestId:Q.requestId,ok:!1,error:X instanceof Error?X.message:String(X)})}}var w1=!1,U1=null;async function v6(){if(w1)return;if(U1)return U1;return U1=(async()=>{try{let Z=await S3(B1);D6({...Z,requestedPort:Z.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${Z.url}`);try{await p6({onStatusChange:(Q)=>{if(F2(),M0?.sendStatus(),Q.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${Q.packageName}: ${Q.error??"unknown error"}`)}})}catch(Q){console.warn("[ideawave-cli] ACP bridge setup skipped:",Q instanceof Error?Q.message:String(Q))}await T3(),w1=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),M0?.sendStatus()}catch(Z){console.error("[ideawave-cli] failed to start agent host:",Z),M0?.sendStatus(void 0,Z instanceof Error?Z.message:String(Z))}finally{U1=null}})(),U1}if(process.env.APP_ENV!=="development"){let Z=await R3();if(Z)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${Z}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}M0=await y3({registry:B1,runtime:null,mcpReady:()=>w1,capabilities:["browser-proxy-v1",$6,G6],cliVersion:l3(),browserRuntimeStatus:()=>d3,onToolMetadata:(Z)=>{console.log(`[ideawave-cli] session ${Z} advertised ${B1.getMetadata(Z).length} tools`),v6()},onRunTurn:(Z,Q)=>{console.log(`[ideawave-cli] running agent turn for card ${Q.cardId} (session ${Z})`),(async()=>{if(await v6(),!w1){k0(Z,{type:"run_settled",runId:Q.runId,cardId:Q.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await A2(Q,(X)=>k0(Z,X))})().catch(()=>{return}).finally(()=>B1.markRunSettled(Z,Q.runId))},onCancelRun:(Z,Q)=>{T4(Q)},onRuntimeRpc:(Z,Q)=>{lX(Z,Q)},onBrowserRpc:(Z,Q,X)=>{F1.handleRpc(Z,Q,X).then((K)=>{k0(Z,{type:"browser_rpc_result",requestId:X.requestId,ok:!0,result:K})},(K)=>{k0(Z,{type:"browser_rpc_result",requestId:X.requestId,ok:!1,error:K instanceof Error?K.message:String(K)})})},onHttpRequest:(Z,Q)=>F1.handleHttpRequest(Z,Q),onWarmupRun:(Z,Q,X)=>{(async()=>{if(await v6(),!w1)return{status:"retryable",error:"agent host is not ready"};return l2({cardId:Q.cardId,boardId:Q.boardId,userId:X,frontendSessionId:Z})})().then((K)=>{if(!Q.warmupId)return;k0(Z,{type:"warmup_result",warmupId:Q.warmupId,cardId:Q.cardId,...K})})},onDisconnect:(Z,Q)=>{F1.closeFrontendSession(Z),I2(Z);for(let X of Q)T4(X);m("bridge.frontend_disconnected",{frontendSessionId:Z,activeRuns:Q.length}),f6(Z).catch((X)=>{console.warn(`[ideawave-cli] failed to evict sessions for ${Z}:`,X instanceof Error?X.message:String(X))}),console.log(`[ideawave-cli] browser session ${Z} disconnected`)}});F1.setPort(M0.port);console.log(`[ideawave-cli] browser bridge listening on ${M0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var A3=!1;for(let Z of["SIGINT","SIGTERM"])process.once(Z,()=>{if(A3)return;A3=!0,u2(),(async()=>{await F1.close(),await M0?.close().catch(()=>{return}),process.exit(0)})()});
48
+ ${X}`),Z.destroy()}function JX(Z,Q){return new Promise((X,K)=>{let Y=(z)=>{Z.off("listening",W),K(z)},W=()=>{Z.off("error",Y);let z=Z.address();if(!z||typeof z==="string"){K(Error("Failed to read CLI bridge server address"));return}X(z.port)};Z.once("error",Y),Z.once("listening",W),Z.listen(Q,"127.0.0.1")})}function O3(Z){return new Promise((Q,X)=>{Z.close((K)=>{if(K)X(K);else Q()})})}async function y3(Z,Q=B6()){let X=new Map,K=new Map,Y=Z.maxMessageSize??pQ,W=!1,z=(x)=>{let y=K.get(x);if(y)clearTimeout(y);K.delete(x)},B=(x)=>{K.delete(x);let{activeRunIds:y}=Z.registry.disconnect(x);Z.onDisconnect(x,y)},w=(x,y)=>{let v={type:"cli_status",connected:!0,runtime:Z.runtime,mcpReady:Z.mcpReady(),error:y,capabilities:Z.capabilities??[],cliVersion:Z.cliVersion,browserRuntime:Z.browserRuntimeStatus?.()};if(x){let $=X.get(x);if($)a0($,v);return}for(let $ of X.values())a0($,v)},q=(x,y)=>{let v=y.sessionId.trim(),$=y.userId.trim();if(!v||!$){a0(x,{type:"cli_status",connected:!1,runtime:Z.runtime,mcpReady:Z.mcpReady(),error:"Missing frontend session or user id"}),x.close();return}z(v);let C=X.get(v);if(C&&C!==x)C.close();x.data.frontendSessionId=v,X.set(v,x),Z.registry.register({frontendSessionId:v,userId:$,tools:y.tools,send:(N)=>a0(x,N)}),w(v),Z.onToolMetadata?.(v)},b=(x,y)=>{let v=Z.registry.getUserId(x);if(!v)return;switch(y.type){case"bridge_ping":{let $=X.get(x);if($)a0($,{type:"bridge_pong"});break}case"tool_metadata":Z.registry.setMetadata(x,y.tools),Z.onToolMetadata?.(x);break;case"tool_result":Z.registry.handleToolResult(x,y);break;case"run_turn":m("bridge.run_received",{runId:y.run.runId,cardId:y.run.cardId,frontendSessionId:x}),Z.registry.markRunActive(x,y.run.runId,y.run.cardId),Z.onRunTurn(x,{...y.run,frontendSessionId:x,userId:v});break;case"cancel_run":if(Z.registry.ownsRun(x,y.runId))Z.onCancelRun(x,y.runId);break;case"runtime_rpc":Z.onRuntimeRpc(x,y);break;case"browser_rpc":Z.onBrowserRpc?.(x,X.get(x)?.data.frontendOrigin??"",y);break;case"warmup_run":Z.onWarmupRun(x,{...y,frontendSessionId:x},v);break;default:break}},M=(x,y)=>{let v=F6(x.headers.origin),$=x3(v),C={Vary:"Origin"};if($&&v)C["Access-Control-Allow-Origin"]=v,C["Access-Control-Allow-Private-Network"]="true";if(x.method==="OPTIONS"){y.writeHead(204,{...C,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),y.end();return}if(x.method!=="GET"){y.writeHead(405,C),y.end();return}y.writeHead(200,{...C,"content-type":"application/json","cache-control":"no-store"}),y.end(JSON.stringify({ideawave:!0,runtime:Z.runtime,mcpReady:Z.mcpReady(),capabilities:Z.capabilities??[],cliVersion:Z.cliVersion,browserRuntime:Z.browserRuntimeStatus?.()}))};for(let x of Q){let y=aQ((C,N)=>{(async()=>{if(new URL(C.url??"/","http://127.0.0.1").pathname===w3){M(C,N);return}if(await Z.onHttpRequest?.(C,N))return;N.writeHead(404,{"content-type":"text/plain"}),N.end("IdeaWave CLI bridge")})().catch((f)=>{if(N.headersSent){N.destroy(f instanceof Error?f:void 0);return}N.writeHead(500,{"content-type":"text/plain"}),N.end("IdeaWave CLI bridge request failed")})}),v=new iQ({noServer:!0,maxPayload:Y}),$=(C)=>{if(C.idleTimer)clearTimeout(C.idleTimer);C.idleTimer=setTimeout(()=>{C.close()},sQ),C.idleTimer.unref?.()};v.on("connection",(C,N)=>{let f=C;f.data={id:dQ(),frontendSessionId:null,frontendOrigin:new URL(F6(N.headers.origin)??v3).origin},f.idleTimer=null,$(f),f.on("ping",()=>$(f)),f.on("pong",()=>$(f)),f.on("error",()=>{if(f.idleTimer)clearTimeout(f.idleTimer);f.close()}),f.on("message",(E)=>{$(f);let G=XX(E);if(Y>0&&G.length>Y)return;let I=b1(G);if(!I)return;let D=f.data.frontendSessionId;if(!D){if(I.type==="bridge_probe")a0(f,{type:"bridge_probe_ack",protocolVersion:I.protocolVersion});else if(I.type==="frontend_hello")q(f,I);return}b(D,I)}),f.on("close",()=>{if(f.idleTimer)clearTimeout(f.idleTimer);let E=f.data.frontendSessionId;if(!E)return;if(X.get(E)!==f)return;if(X.delete(E),z(E),W)return;K.set(E,setTimeout(()=>B(E),rQ))})}),y.on("upgrade",(C,N,f)=>{if(new URL(C.url??"/","http://127.0.0.1").pathname!==U6){b3(N,404,"Not Found");return}if(!x3(F6(C.headers.origin))){b3(N,403,"Forbidden");return}v.handleUpgrade(C,N,f,(G)=>{v.emit("connection",G,C)})});try{let C=await JX(y,x);return{url:`ws://127.0.0.1:${C}${U6}`,port:C,sendStatus:w,close:async()=>{W=!0;for(let N of K.values())clearTimeout(N);K.clear();for(let N of v.clients){let f=N;if(f.idleTimer)clearTimeout(f.idleTimer);f.close()}v.close(),await O3(y).catch(()=>{return})}}}catch(C){if(v.close(),await O3(y).catch(()=>{return}),C?.code==="EADDRINUSE")continue;throw C}}throw Error(`No free IdeaWave CLI bridge port found in ${Q[0]}-${Q.at(-1)}`)}import{Server as PX}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as xX,ListToolsRequestSchema as bX}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as YX}from"node:crypto";import{createServer as WX}from"node:http";import{StreamableHTTPServerTransport as VX}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as N3}from"@modelcontextprotocol/sdk/types.js";var f3=new Set(["127.0.0.1","localhost","[::1]","::1"]);function KX(Z){let Q=Z.trim();if(Q.length===0)return null;if(Q.startsWith("[")){let W=Q.indexOf("]");if(W===-1)return null;let z=Q.slice(0,W+1),B=Q.slice(W+1);if(B.length===0)return{host:z,port:null};if(!B.startsWith(":"))return null;let w=Number(B.slice(1));if(!Number.isInteger(w)||w<=0||w>65535)return null;return{host:z,port:w}}let X=Q.lastIndexOf(":");if(X===-1)return{host:Q,port:null};let K=Q.slice(X+1),Y=Number(K);if(!Number.isInteger(Y)||Y<=0||Y>65535)return{host:Q,port:null};return{host:Q.slice(0,X),port:Y}}function h3(Z){return f3.has(Z)||f3.has(Z.toLowerCase())}function M3(Z,Q){let X=Z.headers.host;if(typeof X!=="string")return{ok:!1,status:403,reason:"missing-host"};let K=KX(X);if(!K)return{ok:!1,status:403,reason:"bad-host"};if(!h3(K.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(K.port!==null&&K.port!==Q)return{ok:!1,status:403,reason:"host-port-mismatch"};let Y=Z.headers.origin;if(typeof Y==="string"&&Y.length>0){if(Y!=="null"){let W;try{W=new URL(Y)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!h3(W.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var D3="/mcp",HX=43274,G3=16777216,jX=1800000,zX=300000,$3=200,qX=-32700,f0=-32600,L6=-32603;function W0(Z,Q,X,K,Y){Z.statusCode=Q,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify({jsonrpc:"2.0",error:{code:X,message:K,...Y?{data:Y}:{}},id:null}))}class P6 extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class x6 extends Error{constructor(){super(`body exceeds ${G3} bytes`);this.name="BodyTooLargeError"}}async function UX(Z){if(Z.method&&Z.method!=="POST")return;let Q=Z.headers["content-type"];if(typeof Q==="string"&&Q.trim().length>0){if(!Q.toLowerCase().includes("application/json"))throw new P6}let X=0,K=[];for await(let W of Z){let z=typeof W==="string"?Buffer.from(W):W;if(X+=z.byteLength,X>G3)throw new x6;K.push(z)}if(K.length===0)return;let Y=Buffer.concat(K).toString("utf8");if(Y.length===0)return;return JSON.parse(Y)}function BX(Z){if(Array.isArray(Z))return Z.some(N3);return N3(Z)}function FX(Z){if(typeof Z==="number")return Z;let Q=process.env.IDEAWAVE_MCP_PORT;if(Q&&Q.trim().length>0){let X=Number(Q);if(Number.isInteger(X)&&X>=0&&X<65536)return X}return HX}async function wX(Z,Q){let X=(Y)=>new Promise((W,z)=>{let B=(q)=>{Z.off("listening",w),z(q)},w=()=>{Z.off("error",B),W()};Z.once("error",B),Z.once("listening",w),Z.listen(Y,"127.0.0.1")});try{await X(Q)}catch(Y){if(Y.code!=="EADDRINUSE"||Q===0)throw Y;console.warn(`[mcp] port ${Q} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await X(0)}let K=Z.address();if(K==null||typeof K==="string")throw Error("[mcp] failed to read bound address");return K.port}function LX(Z,Q){if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let K=Q.params;if(K&&typeof K==="object"&&!Array.isArray(K)){let Y=K.clientInfo;if(Y&&typeof Y==="object"&&!Array.isArray(Y)){let W=Y.name;if(typeof W==="string"&&W.trim().length>0)return W.trim()}}}let X=Z.headers["user-agent"];if(typeof X==="string"&&X.trim().length>0)return X.trim();return null}async function g3(Z){let Q=new Map,X=0;function K(q){let b=Q.get(q);if(b)b.lastActivity=Date.now()}async function Y(q,b){Q.delete(q),await b.transport.close().catch(()=>{return})}async function W(){let q=null,b=1/0;for(let[M,x]of Q)if(x.lastActivity<b)b=x.lastActivity,q=M;if(q!==null){let M=Q.get(q);if(M)console.warn(`[mcp] session cap of ${$3} reached; evicting ${q}`),await Y(q,M)}}let z=setInterval(()=>{let q=Date.now()-jX;for(let[b,M]of Q)if(M.lastActivity<q)console.log(`[mcp] sweeping idle session ${b}`),Y(b,M)},zX);z.unref?.();let B=WX((q,b)=>{(async()=>{let M;try{M=new URL(q.url??"/","http://127.0.0.1").pathname}catch{W0(b,400,f0,"bad-url");return}if(M!==D3){W0(b,404,f0,"not-found");return}let x=q.method??"POST";if(x!=="POST"&&x!=="GET"&&x!=="DELETE"){b.setHeader("Allow","GET, POST, DELETE"),W0(b,405,f0,"method-not-allowed");return}let y=M3(q,X);if(!y.ok){W0(b,y.status,f0,"forbidden",{reason:y.reason});return}let v=q.headers["mcp-session-id"],$=typeof v==="string"?v:void 0;if(x==="GET"||x==="DELETE"){if(!$||!Q.has($)){W0(b,400,f0,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let f=Q.get($).transport;K($);try{await f.handleRequest(q,b)}catch(E){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",E),!b.headersSent)W0(b,500,L6,"internal")}return}let C;try{C=await UX(q)}catch(f){if(f instanceof P6){W0(b,415,f0,"expected-application-json");return}if(f instanceof x6){W0(b,413,f0,"body-too-large");return}W0(b,400,qX,"invalid-json");return}let N;if($&&Q.has($))N=Q.get($).transport,K($);else if(!$&&C!==void 0&&BX(C)){let f=q.headers["x-ideawave-user-id"],E=typeof f==="string"&&f.trim().length>0?f.trim():null,G=q.headers["x-ideawave-frontend-session-id"],I=typeof G==="string"&&G.trim().length>0?G.trim():null,D=q.headers["x-ideawave-tool-surface"],L=typeof D==="string"&&D.trim()==="read"?"read":"full",g=q.headers["x-ideawave-images-supported"],l=typeof g==="string"&&g.trim()==="1",a=q.headers["x-ideawave-card-id"],_0=typeof a==="string"&&a.trim().length>0?a.trim():null,P0=q.headers["x-ideawave-board-id"],_=typeof P0==="string"&&P0.trim().length>0?P0.trim():null,i=q.headers["x-ideawave-run-folder"],A=typeof i==="string"&&i.trim().length>0?i.trim():null,Z0=LX(q,C);if(Q.size>=$3)await W();let s=null,N0=new VX({sessionIdGenerator:()=>YX(),onsessioninitialized:(S0)=>{s=S0,Q.set(S0,{transport:N0,lastActivity:Date.now()})},onsessionclosed:(S0)=>{Q.delete(S0)}});N0.onclose=()=>{if(N0.sessionId)Q.delete(N0.sessionId)};try{await Z.buildServer({userId:E,frontendSessionId:I,boardId:_,toolSurface:L,imagesSupported:l,cardId:_0,runFolder:A,clientHint:Z0}).connect(N0)}catch(S0){if(console.error("[mcp] buildServer/connect failed",S0),s)Q.delete(s);await N0.close().catch(()=>{return}),W0(b,500,L6,"server-init-failed");return}N=N0}else{W0(b,400,f0,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await N.handleRequest(q,b,C)}catch(f){if(console.error("[mcp] transport.handleRequest threw",f),!b.headersSent)W0(b,500,L6,"internal")}})().catch((M)=>{console.error("[mcp] unhandled request handler error:",M)})});return X=await wX(B,FX(Z.port)),{url:`http://127.0.0.1:${X}${D3}`,port:X,close:async()=>{clearInterval(z);for(let q of Q.values())await q.transport.close().catch(()=>{return});Q.clear(),await new Promise((q)=>B.close(()=>q()))}}}var OX={name:"ideawave-board",version:"1.0.0"},Q4="list_run_folder",X4="read_run_folder_file",k3=new Set(["list_boards","get_board","list_nodes","list_edges","inspect_node","list_context_sources","read_context_card","read_context_file","read_context_image","list_context_folder","get_board_wiki","search_board","get_card_messages","list_agent_cards","inspect_neighbors",Q4,X4]),_3=new Set(["inspect_diagram"]),CX=[{name:Q4,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:X4,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 b6(Z){return{content:[{type:"text",text:Z}]}}function vX(Z){return b6(JSON.stringify(Z,null,2))}function E3(Z){return{...b6(Z),isError:!0}}function RX(Z,Q,X="full",K=!1){return Z.getMetadata(Q).filter((Y)=>{let W=E1(Y.name);if(X==="read"&&!k3.has(W))return!1;if(!K&&_3.has(W))return!1;return!0}).map((Y)=>({name:Y.name,description:Y.description,inputSchema:Y.inputSchema}))}function yX(Z,Q,X={}){let K=RX(Z,Q,X.toolSurface??"full",X.imagesSupported??!1);return X.includeRunFolderTools?[...K,...CX]:K}function m3(Z,Q){if(!Z||typeof Z!=="object"||Array.isArray(Z))return null;let X=Z[Q];return typeof X==="string"?X:null}async function fX(Z,Q,X){if(X&&X.trim().length>0)return X.trim();if(!Z||!Q)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await O0({boardId:Z,cardId:Q})).runFolder}async function hX(Z){let Q=await fX(Z.boardId,Z.cardId,Z.runFolder);if(Z.name===Q4){let X=m3(Z.args,"path")??"",K=await P2(Q,X);return vX(K)}if(Z.name===X4){let X=m3(Z.args,"path");if(!X)return E3("read_run_folder_file requires a path.");return b6(await g1(Q,X))}return E3(`Unknown local tool "${Z.name}"`)}function MX(Z,Q,X,K,Y,W="full",z=!1){let B=new PX(OX,{capabilities:{tools:{}}}),w=async()=>{if(z)return!0;if(S2(K))return!0;if(X&&K)try{return(await O0({boardId:X,cardId:K})).adapter.supportsImages===!0}catch{return!1}return!1};return B.setRequestHandler(bX,async()=>({tools:yX(Z,Q,{includeRunFolderTools:Boolean(Y||X&&K),toolSurface:W,imagesSupported:await w()})})),B.setRequestHandler(xX,async(q)=>{let{name:b,arguments:M}=q.params,x=E1(b),y=Date.now();m("mcp.tool_call_received",{frontendSessionId:Q,cardId:K,toolName:x});try{if(x===Q4||x===X4)return await hX({name:x,args:M,boardId:X,cardId:K,runFolder:Y});if(W==="read"&&!k3.has(x))throw Error(`Tool "${b}" is not available in read-only mode`);if(_3.has(x)&&!await w())throw Error(`Tool "${b}" requires a runtime that supports image input`);let v=await Z.callTool(Q,x,M??{},void 0,K??void 0);if(m("mcp.tool_result_returned",{frontendSessionId:Q,cardId:K,toolName:x,elapsedMs:Date.now()-y}),v&&typeof v==="object"&&Array.isArray(v.content))return v;return{content:[{type:"text",text:typeof v==="string"?v:JSON.stringify(v)}]}}catch(v){return m("mcp.tool_result_returned",{frontendSessionId:Q,cardId:K,toolName:x,elapsedMs:Date.now()-y,hasError:!0}),{content:[{type:"text",text:v instanceof Error?v.message:"Tool call failed"}],isError:!0}}}),B}function S3(Z,Q){return g3({buildServer:(X)=>MX(Z,X.frontendSessionId,X.boardId,X.cardId,X.runFolder,X.toolSurface,X.imagesSupported),port:Q})}import J4 from"node:fs/promises";import O6 from"node:os";import K4 from"node:path";function I3(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function NX(){let[Z,Q]=await Promise.all([J0(),U2()]),X=Z.globalDefaultConfigId?Z.runtimes.find((K)=>K.id===Z.globalDefaultConfigId)??null:null;return{runtimes:Z.runtimes,globalDefaultConfigId:Z.globalDefaultConfigId,globalDefaultEffective:X?{runFolder:X.runFolder??O6.homedir(),modelId:X.defaultModelId??null,configValues:X.defaultConfigValues??{}}:null,knownAdapters:T0().map((K)=>({id:K.id,displayName:K.displayName})),readiness:Q}}async function DX(Z){try{let Q=await O0({boardId:Z.boardId,cardId:Z.cardId});return{resolved:{configId:Q.entry.id,adapterId:Q.entry.kind==="registered"?Q.entry.adapterId:null,displayName:Q.entry.displayName,runFolder:Q.runFolder,modelId:Q.modelId,configValues:Q.configValues}}}catch(Q){if(Q instanceof D0)return{resolved:null};throw Q}}async function $X(Z){return V0((Q)=>{let X=Q.runtimes.find((W)=>W.kind==="registered"&&W.adapterId===Z.adapterId);if(X)return X;let K=T0().find((W)=>W.id===Z.adapterId);if(!K)throw Error(`Unknown adapterId: ${Z.adapterId}`);let Y={id:I3(),kind:"registered",adapterId:Z.adapterId,displayName:K.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return Q.runtimes.push(Y),Y})}async function GX(Z){return V0((Q)=>{let X={id:I3(),kind:"custom",displayName:Z.displayName,command:Z.command,args:Z.args,env:Z.env,runFolder:Z.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return Q.runtimes.push(X),X})}async function gX(Z){await V0((Q)=>{if(Q.runtimes=Q.runtimes.filter((X)=>X.id!==Z.runtimeConfigId),Q.globalDefaultConfigId===Z.runtimeConfigId)Q.globalDefaultConfigId=null;for(let X of Object.keys(Q.boardOverrides))if(Q.boardOverrides[X].runtimeConfigId===Z.runtimeConfigId)delete Q.boardOverrides[X];for(let X of Object.keys(Q.cardOverrides))if(Q.cardOverrides[X].runtimeConfigId===Z.runtimeConfigId)delete Q.cardOverrides[X]})}async function EX(Z){await V0((Q)=>{let X=Q.runtimes.find((K)=>K.id===Z.runtimeConfigId);if(!X)throw Error(`Runtime config not found: ${Z.runtimeConfigId}`);if(Q.globalDefaultConfigId=Z.runtimeConfigId,Z.runFolder!==void 0)X.runFolder=Z.runFolder;if(Z.modelId!==void 0)X.defaultModelId=Z.modelId;if(Z.configValues!==void 0)X.defaultConfigValues=Z.configValues})}async function mX(Z){Z.boardId,await V0((Q)=>{if(Z.runtimeConfigId===null){delete Q.cardOverrides[Z.cardId];return}if(!Q.runtimes.some((Y)=>Y.id===Z.runtimeConfigId))throw Error(`Runtime config not found: ${Z.runtimeConfigId}`);let K=Q.cardOverrides[Z.cardId];Q.cardOverrides[Z.cardId]={runtimeConfigId:Z.runtimeConfigId,runFolder:Z.runFolder!==void 0?Z.runFolder:K?.runFolder??null,modelId:Z.modelId!==void 0?Z.modelId:K?.modelId??null,configValues:Z.configValues!==void 0?Z.configValues:K?.configValues??{}}})}async function kX(Z){let X=(await J0()).runtimes.find((z)=>z.id===Z.runtimeConfigId);if(!X)throw Error(`Runtime config not found: ${Z.runtimeConfigId}`);let K=U0(X),Y=await K.resolveSpawnConfig(X),W=X.runFolder??O6.homedir();try{let z=await E2({spawn:{...Y,cwd:W},modelId:Z.modelId??X.defaultModelId??null,configValues:Z.configValues??X.defaultConfigValues??{}}),B=$1({adapterId:K.id,models:z.models,currentModelId:z.currentModelId}),w=new Date().toISOString();return await V0((q)=>{let b=q.runtimes.find((M)=>M.id===Z.runtimeConfigId);if(b)b.discoveredModels=B,b.discoveredConfigOptions=z.configOptions,b.discoveredAt=w}),{ok:!0,models:B,configOptions:z.configOptions,currentModelId:z.currentModelId}}catch(z){if(z instanceof I0)throw Error(`${z.message}${K.authHint?` ${K.authHint}`:""}`);if(z instanceof S||z instanceof q0)throw Error(z.message);throw z}}async function _X(Z){let Q=O6.homedir(),X=Z.path?.trim()?Z.path.trim():Q,K=K4.resolve(X),Y=!0;try{if(!(await J4.stat(K)).isDirectory())K=K4.dirname(K)}catch{Y=!1,K=Q}let W=[];try{W=(await J4.readdir(K,{withFileTypes:!0})).filter((w)=>w.isDirectory()&&!w.name.startsWith(".")).map((w)=>({name:w.name,path:K4.join(K,w.name)})).sort((w,q)=>w.name.localeCompare(q.name))}catch{W=[]}let z=K4.dirname(K);return{path:K,parent:z===K?null:z,home:Q,exists:Y,entries:W}}var u3={list:NX,getEffectiveForCard:DX,registerRegistered:$X,registerCustom:GX,unregister:gX,setUserDefault:EX,setCardOverride:mX,refreshModels:kX,browseFolder:_X};var SX=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function IX(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function T3(){try{let Z=await J0();if(Z.globalDefaultConfigId){if(Z.runtimes.some((X)=>X.id===Z.globalDefaultConfigId))return Z.globalDefaultConfigId}for(let Q of SX){if((await B2(Q.id))?.status!=="ready")continue;let K=null;if(await V0((Y)=>{if(Y.globalDefaultConfigId){if(Y.runtimes.some((B)=>B.id===Y.globalDefaultConfigId)){K=Y.globalDefaultConfigId;return}}let W=Y.runtimes.find((z)=>z.kind==="registered"&&z.adapterId===Q.id);if(!W){let z={id:IX(),kind:"registered",adapterId:Q.id,displayName:Q.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Y.runtimes.push(z),W=z}Y.globalDefaultConfigId=W.id,K=W.id}),K)return console.log(`[ideawave-cli] using agent runtime: ${Q.displayName}`),K}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch(Z){return console.warn("[ideawave-cli] runtime auto-seed failed",Z),null}}var uX=120000;function TX(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class C6{sessions=new Map;createCallId;toolCallTimeoutMs;constructor(Z={}){this.createCallId=Z.createCallId??TX,this.toolCallTimeoutMs=Z.toolCallTimeoutMs??uX}register(Z){let Q=this.sessions.get(Z.frontendSessionId);if(Q){if(Q.userId!==Z.userId)this.rejectPending(Q,"frontend session user changed"),Q.activeRunIds.clear();this.sessions.set(Z.frontendSessionId,{frontendSessionId:Z.frontendSessionId,userId:Z.userId,tools:Z.tools,send:Z.send,pendingToolCalls:Q.pendingToolCalls,activeRunIds:Q.activeRunIds,activeRunCardIds:Q.activeRunCardIds});return}this.sessions.set(Z.frontendSessionId,{frontendSessionId:Z.frontendSessionId,userId:Z.userId,tools:Z.tools,send:Z.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect(Z,Q="frontend session disconnected"){let X=this.sessions.get(Z);if(!X)return{activeRunIds:[]};return this.sessions.delete(Z),this.rejectPending(X,Q),{activeRunIds:Array.from(X.activeRunIds)}}sessionCount(){return this.sessions.size}has(Z){return this.sessions.has(Z)}getUserId(Z){return this.sessions.get(Z)?.userId??null}setMetadata(Z,Q){let X=this.sessions.get(Z);if(X)X.tools=Q}getMetadata(Z){if(!Z)return[];return this.sessions.get(Z)?.tools??[]}sendToSession(Z,Q){let X=this.sessions.get(Z);if(!X)return!1;return X.send(Q),!0}callTool(Z,Q,X,K,Y){if(!Z)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let W=this.sessions.get(Z);if(!W)return Promise.reject(Error(`Frontend session ${Z} is not connected`));let z=this.createCallId();return new Promise((B,w)=>{let q=K??(Y?this.getActiveRunIdForCard(W,Y):this.getSoleActiveRunId(W)),b=Y??(q?W.activeRunCardIds.get(q):void 0),M=Date.now(),x=setTimeout(()=>{W.pendingToolCalls.delete(z),m("tool_queue.timeout",{frontendSessionId:Z,runId:q,cardId:b,callId:z,toolName:Q,elapsedMs:Date.now()-M,queueDepth:W.pendingToolCalls.size}),w(Error(`Tool "${Q}" timed out waiting for the frontend`))},this.toolCallTimeoutMs);W.pendingToolCalls.set(z,{resolve:B,reject:w,timer:x,name:Q,runId:q??null,cardId:b??null,startedAt:M}),m("tool_queue.forwarded_to_browser",{frontendSessionId:Z,runId:q,cardId:b,callId:z,toolName:Q,queueDepth:W.pendingToolCalls.size}),W.send({type:"tool_call",callId:z,name:Q,args:X,...q?{runId:q}:{},...b?{cardId:b}:{}})})}handleToolResult(Z,Q){let X=this.sessions.get(Z);if(!X)return;let K=X.pendingToolCalls.get(Q.callId);if(!K)return;if(X.pendingToolCalls.delete(Q.callId),clearTimeout(K.timer),m("tool_queue.result_received",{frontendSessionId:Z,runId:K.runId,cardId:K.cardId,callId:Q.callId,toolName:K.name,elapsedMs:Date.now()-K.startedAt,queueDepth:X.pendingToolCalls.size,ok:Q.ok}),Q.ok){K.resolve(Q.result);return}let Y=Q.result;if(Y&&typeof Y==="object"&&Array.isArray(Y.content)){K.resolve({...Y,isError:!0});return}K.reject(Error(Q.error??"Tool execution failed"))}markRunActive(Z,Q,X){let K=this.sessions.get(Z);if(!K)return;if(K.activeRunIds.add(Q),X)K.activeRunCardIds.set(Q,X)}markRunSettled(Z,Q){let X=this.sessions.get(Z);if(!X)return;X.activeRunIds.delete(Q),X.activeRunCardIds.delete(Q)}ownsRun(Z,Q){return this.sessions.get(Z)?.activeRunIds.has(Q)??!1}rejectPending(Z,Q){for(let X of Z.pendingToolCalls.values())clearTimeout(X.timer),m("tool_queue.rejected",{frontendSessionId:Z.frontendSessionId,runId:X.runId,cardId:X.cardId,toolName:X.name,elapsedMs:Date.now()-X.startedAt}),X.reject(Error(Q));Z.pendingToolCalls.clear()}getSoleActiveRunId(Z){return Z.activeRunIds.size===1?Z.activeRunIds.values().next().value:void 0}getActiveRunIdForCard(Z,Q){let X=[...Z.activeRunCardIds.entries()].filter(([K,Y])=>Z.activeRunIds.has(K)&&Y===Q).map(([K])=>K);return X.length===1?X[0]:void 0}}function l3(){return"0.0.63".trim()?"0.0.63":"dev"}var AX=process.argv.slice(2),c3=[];for(let Z of AX){if(Z==="--dev"){process.env[w6]="1";continue}c3.push(Z)}var h0=c3[0];if(h0==="--help"||h0==="-h"||h0==="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(h0==="--version"||h0==="-v"||h0==="version")console.log(l3()),process.exit(0);if(h0)console.error(`Unknown command: ${h0}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var B1=new C6,M0=null,d3={phase:"idle"},F1=new q6(new t0((Z)=>{d3=Z,M0?.sendStatus()}));function k0(Z,Q){B1.sendToSession(Z,Q)}async function lX(Z,Q){try{let X=u3[Q.method],K=await X(Q.params);k0(Z,{type:"runtime_rpc_result",requestId:Q.requestId,ok:!0,result:K})}catch(X){k0(Z,{type:"runtime_rpc_result",requestId:Q.requestId,ok:!1,error:X instanceof Error?X.message:String(X)})}}var w1=!1,U1=null;async function v6(){if(w1)return;if(U1)return U1;return U1=(async()=>{try{let Z=await S3(B1);D6({...Z,requestedPort:Z.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${Z.url}`);try{await p6({onStatusChange:(Q)=>{if(F2(),M0?.sendStatus(),Q.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${Q.packageName}: ${Q.error??"unknown error"}`)}})}catch(Q){console.warn("[ideawave-cli] ACP bridge setup skipped:",Q instanceof Error?Q.message:String(Q))}await T3(),w1=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),M0?.sendStatus()}catch(Z){console.error("[ideawave-cli] failed to start agent host:",Z),M0?.sendStatus(void 0,Z instanceof Error?Z.message:String(Z))}finally{U1=null}})(),U1}if(process.env.APP_ENV!=="development"){let Z=await R3();if(Z)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${Z}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}M0=await y3({registry:B1,runtime:null,mcpReady:()=>w1,capabilities:["browser-proxy-v1",$6,G6],cliVersion:l3(),browserRuntimeStatus:()=>d3,onToolMetadata:(Z)=>{console.log(`[ideawave-cli] session ${Z} advertised ${B1.getMetadata(Z).length} tools`),v6()},onRunTurn:(Z,Q)=>{console.log(`[ideawave-cli] running agent turn for card ${Q.cardId} (session ${Z})`),(async()=>{if(await v6(),!w1){k0(Z,{type:"run_settled",runId:Q.runId,cardId:Q.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await A2(Q,(X)=>k0(Z,X))})().catch(()=>{return}).finally(()=>B1.markRunSettled(Z,Q.runId))},onCancelRun:(Z,Q)=>{T4(Q)},onRuntimeRpc:(Z,Q)=>{lX(Z,Q)},onBrowserRpc:(Z,Q,X)=>{F1.handleRpc(Z,Q,X).then((K)=>{k0(Z,{type:"browser_rpc_result",requestId:X.requestId,ok:!0,result:K})},(K)=>{k0(Z,{type:"browser_rpc_result",requestId:X.requestId,ok:!1,error:K instanceof Error?K.message:String(K)})})},onHttpRequest:(Z,Q)=>F1.handleHttpRequest(Z,Q),onWarmupRun:(Z,Q,X)=>{(async()=>{if(await v6(),!w1)return{status:"retryable",error:"agent host is not ready"};return l2({cardId:Q.cardId,boardId:Q.boardId,userId:X,frontendSessionId:Z})})().then((K)=>{if(!Q.warmupId)return;k0(Z,{type:"warmup_result",warmupId:Q.warmupId,cardId:Q.cardId,...K})})},onDisconnect:(Z,Q)=>{F1.closeFrontendSession(Z),I2(Z);for(let X of Q)T4(X);m("bridge.frontend_disconnected",{frontendSessionId:Z,activeRuns:Q.length}),f6(Z).catch((X)=>{console.warn(`[ideawave-cli] failed to evict sessions for ${Z}:`,X instanceof Error?X.message:String(X))}),console.log(`[ideawave-cli] browser session ${Z} disconnected`)}});F1.setPort(M0.port);console.log(`[ideawave-cli] browser bridge listening on ${M0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var A3=!1;for(let Z of["SIGINT","SIGTERM"])process.once(Z,()=>{if(A3)return;A3=!0,u2(),(async()=>{await F1.close(),await M0?.close().catch(()=>{return}),process.exit(0)})()});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideawave",
3
- "version": "0.0.61",
3
+ "version": "0.0.63",
4
4
  "description": "IdeaWave CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "license": "UNLICENSED",
33
33
  "dependencies": {
34
- "@agentclientprotocol/sdk": "^0.25.1",
34
+ "@agentclientprotocol/sdk": "^1.3.0",
35
35
  "@modelcontextprotocol/sdk": "^1.29.0",
36
36
  "css-tree": "^3.2.1",
37
37
  "playwright-core": "1.60.0",