ideawave 0.0.81 → 0.0.83

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 +2 -2
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1060,7 +1060,7 @@ ${J}`:null].filter(Boolean).join(`
1060
1060
 
1061
1061
  ${W}`)}function xX(X){if(!Array.isArray(X))return null;let W=X.flatMap((Z)=>{if(!Z||typeof Z!=="object")return[];let K=Z;if(typeof K.path!=="string"||!K.path.trim())return[];let J=typeof K.line==="number"?`:${K.line}`:"";return[`${K.path}${J}`]});return W.length>0?W.slice(0,5):null}function e3(X){let{ctx:W,appendText:Z,appendToolActivity:K}=X,J=X.flushIntervalMs??H5,V="",H="",U=0,F=null,w=!1,B={},b=new Map,v=(R)=>{if(b.set(R.toolCallId,R),!K)return;K({boardId:W.boardId,cardId:W.cardId,runId:W.runId,entry:R}).catch((O)=>{console.warn("[streamAdapter] appendToolActivity failed",O)})},y=(R)=>{let O=`${W.runId}:thought`,$=b.get(O);if(!$||$.status!=="running")return;v({...$,status:"completed",completedAt:$.completedAt??R})},x=(R)=>{for(let O of b.values()){if(O.status!=="running"||O.rawTitle.toLowerCase()!=="toolsearch")continue;v({...O,status:"completed",completedAt:O.completedAt??R})}},C=(R)=>{for(let O of Array.from(b.values())){if(O.status!=="running")continue;if(O.kind==="thought"||O.rawTitle==="agent_thought")continue;v({...O,status:"completed",completedAt:O.completedAt??R})}},M="",h=0,g=null,N=null,G=(R)=>{if(R===M)return;M=R,h=Date.now(),Z({boardId:W.boardId,cardId:W.cardId,runId:W.runId,text:R}).catch((O)=>{console.warn("[streamAdapter] appendText failed",O)})},u=()=>{if(g!==null)clearTimeout(g),g=null;if(N!==null){let R=N;N=null,G(R)}},D=(R)=>{let O=Date.now()-h;if(O>=J&&g===null){G(R);return}if(N=R,g===null){let $=Math.max(0,J-O);g=setTimeout(()=>{g=null,u()},$)}};return{onSessionUpdate:async(R)=>{X.onAnyUpdate?.();let O=R.update;switch(B[O.sessionUpdate]=(B[O.sessionUpdate]??0)+1,O.sessionUpdate){case"agent_message_chunk":{let $=new Date().toISOString();if(y($),O.content.type==="text"){if(O.content.text.length>0){if(w&&V.length>0&&!/\s$/.test(V)&&!/^\s/.test(O.content.text))V+=`
1062
1062
 
1063
- `;V+=O.content.text,w=!1,D(V)}}else{let A=`agent_message_chunk:${O.content.type}`;B[A]=(B[A]??0)+1}return}case"agent_thought_chunk":{if(O.content.type!=="text")return;H+=O.content.text;let $=new Date().toISOString(),A=`${W.runId}:thought`,r=b.get(A);v({toolCallId:A,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:r?.startedAt??$,completedAt:null,contentPreview:_0(H.trim())});return}case"user_message_chunk":return;case"tool_call":{U+=1,w=V.length>0;let $=o3(O.title),A=qX(O.status),r=new Date().toISOString();y(r),x(r),v({toolCallId:O.toolCallId,rawTitle:$,title:LX($,O.rawInput),kind:BX(O.kind),status:A,startedAt:r,completedAt:A==="running"?null:r,inputPreview:x0(O.rawInput),outputPreview:PX(O.rawOutput),contentPreview:w2(O.content),locations:xX(O.locations)});return}case"tool_call_update":{let $=b.get(O.toolCallId);if(!$){let W0=o3(O.title),s=qX(O.status),w0=new Date().toISOString();v({toolCallId:O.toolCallId,rawTitle:W0,title:LX(W0,O.rawInput),kind:BX(O.kind),status:s,startedAt:w0,completedAt:s==="running"?null:w0,inputPreview:x0(O.rawInput),outputPreview:PX(O.rawOutput),contentPreview:w2(O.content),locations:xX(O.locations)});return}let A=O.status===void 0||O.status===null?$.status:qX(O.status),r=typeof O.title==="string"&&O.title.trim().length>0?O.title:$.rawTitle,b0=typeof O.title==="string"&&O.title.trim().length>0,k=A==="running"?$.completedAt:$.completedAt??new Date().toISOString(),d=O.content===void 0?$.contentPreview:t3($.contentPreview,w2(O.content)),T=O.rawOutput===void 0?$.outputPreview:t3($.outputPreview,PX(O.rawOutput));v({...$,rawTitle:r,title:b0?LX(r,O.rawInput):$.title,kind:O.kind===void 0?$.kind:BX(O.kind),status:A,completedAt:k,inputPreview:O.rawInput===void 0?$.inputPreview:x0(O.rawInput),outputPreview:T,contentPreview:d,locations:O.locations===void 0?$.locations:xX(O.locations)});return}case"plan":F=O.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>V,getToolCallCount:()=>U,getLatestPlan:()=>F,getUpdateTypeCounts:()=>({...B}),flush:(R)=>{let O=new Date().toISOString();if(y(O),R?.completeOpenToolCalls)C(O);u()}}}var P1=1,X4=-32000;function W4(X){if(X.awaitingInput)return!1;return X.nowMs-X.lastUpdateMs>=X.windowMs}function K4(X){if(!X||typeof X!=="object")return!1;return X.code===X4}var q5=300000,B5=q5,L5=5000;function P5(X){let W=Math.max(1,Math.round(X/1000));return`Runtime has not responded for ${W} ${W===1?"second":"seconds"}. Retry the agent run.`}function J4(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.81".trim()?"0.0.81":"dev"}}function V4(X){if(X===P1)return;throw new I(`Unsupported ACP protocol version ${X}; expected ${P1}`)}function Y4(X){return U5.toWeb(X)}function z4(X){return F5.toWeb(X)}function bX(X){return X!==null&&typeof X==="object"}function x5(X){if(!Array.isArray(X))return[];let W=[];for(let Z of X){if(!bX(Z))continue;if(typeof Z.group==="string"&&Array.isArray(Z.options)){let K=typeof Z.name==="string"?Z.name:Z.group;for(let J of Z.options){if(!bX(J))continue;if(typeof J.value!=="string"||typeof J.name!=="string")continue;W.push({value:J.value,name:J.name,description:typeof J.description==="string"?J.description:null,group:Z.group,groupName:K})}continue}if(typeof Z.value!=="string"||typeof Z.name!=="string")continue;W.push({value:Z.value,name:Z.name,description:typeof Z.description==="string"?Z.description:null,group:null,groupName:null})}return W}function b5(X){if(!bX(X))return null;if(typeof X.id!=="string"||typeof X.name!=="string")return null;let W=typeof X.category==="string"?X.category:null,Z=typeof X.description==="string"?X.description:null;if(X.type==="select"){let K=typeof X.currentValue==="string"?X.currentValue:null;return{id:X.id,name:X.name,category:W,description:Z,type:"select",currentValue:K,options:x5(X.options)}}if(X.type==="boolean"){let K=typeof X.currentValue==="boolean"?X.currentValue:typeof X.value==="boolean"?X.value:null;return{id:X.id,name:X.name,category:W,description:Z,type:"boolean",currentValue:K,options:[]}}return null}function vX(X){let W=(X.configOptions??[]).map(b5).filter((U)=>U!==null),Z=W.find((U)=>U.type==="select"&&U.category==="model")??W.find((U)=>U.type==="select"&&U.id==="model")??null,K=Z?.options.map((U)=>({id:U.value,name:U.name,description:U.description??null})),J=v5(X.models),V=K&&K.length>0?K:J&&J.length>0?J:null,H=(typeof Z?.currentValue==="string"?Z.currentValue:null)??y5(X.models)??null;return{models:V,currentModelId:H,configOptions:W,modelConfigId:Z?.id??null}}function v5(X){if(!X||!Array.isArray(X.availableModels))return null;let W=[];for(let Z of X.availableModels){if(typeof Z.modelId!=="string")continue;W.push({id:Z.modelId,name:typeof Z.name==="string"?Z.name:null,description:typeof Z.description==="string"?Z.description:null})}return W.length>0?W:null}function y5(X){return typeof X?.currentModelId==="string"?X.currentModelId:null}function f5(X,W){let Z=[];if(X.trim())Z.push({type:"text",text:X});for(let K of W)if(K.content.trim())Z.push({type:"text",text:K.content});return Z}function O5(X){if(typeof X.value==="boolean")return{sessionId:X.sessionId,configId:X.configId,type:"boolean",value:X.value};return{sessionId:X.sessionId,configId:X.configId,value:X.value}}function R5(X,W){let Z=vX({configOptions:W.configOptions});return{models:Z.models??X.models,currentModelId:Z.currentModelId??X.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??X.modelConfigId}}function j4(X,W){if(X==="default")return null;if(!W||W.length===0)return X;let Z=W.find((w)=>w.id===X);if(Z)return Z.id;let K=X.toLowerCase(),J=K.includes("opus")?"opus":K.includes("sonnet")?"sonnet":K.includes("haiku")?"haiku":null;if(!J)return X;let V=(w)=>`${w.id} ${w.name??""} ${w.description??""}`.toLowerCase(),H=W.filter((w)=>V(w).includes(J));if(H.length===0)return X;let F=(K.includes("1m")?H.find((w)=>V(w).includes("1m")):void 0)??H[0];return F?F.id:X}async function F2(X){try{let W=await X.conn.setSessionConfigOption(O5({sessionId:X.sessionId,configId:X.configId,value:X.value}));return R5(X.metadata,W)}catch(W){return console.warn(`[acp] setSessionConfigOption(${X.label}) failed; using agent default.`,W instanceof Error?W.message:W),X.metadata}}async function yX(X){let W=UX(X.spawn),Z=[],K=0,J=4096;W.stderr.on("data",(k)=>{Z.push(k),K+=k.length;while(K>J*2&&Z.length>1){let d=Z.shift();if(d)K-=d.length}});let V=()=>{let k=Buffer.concat(Z).toString("utf8");return k.length>J?k.slice(-J):k},H=s3(X.spawn.cwd),U={current:null},F={current:null},w={at:Date.now()},B=null,b=z4(W.stdin),v=Y4(W.stdout),y=Q4(b,v),C=new Z4((k)=>({requestPermission:async(d)=>{let T=d.options,W0=T?.find((s)=>s.kind==="allow_once")??T?.find((s)=>s.kind==="allow_always");if(W0)return{outcome:{outcome:"selected",optionId:W0.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(d)=>{w.at=Date.now();let T=F.current;if(T){let s=d.update.sessionUpdate;if(T.updateCount+=1,T.updateCount===1||T.lastUpdateType!==s||s==="tool_call"||s==="tool_call_update")E("acp.session_update",{runId:T.runId,cardId:T.cardId,sessionId:B,updateType:s,updateCount:T.updateCount,elapsedMs:Date.now()-T.startedAt});T.lastUpdateType=s}let W0=U.current;if(W0)await W0.onSessionUpdate(d)},readTextFile:H.readTextFile}),y),M=()=>W.kill();if(X.signal)X.signal.addEventListener("abort",M);let h=()=>{if(X.signal)X.signal.removeEventListener("abort",M)},g=async(k,d)=>{if(h(),W.kill(),K4(k))throw new l0(k.message??"Authentication required",d);if(k instanceof Error&&k.message==="ACP connection closed"){if(X.signal?.aborted)throw new I("ACP session cancelled: abort signal received");let T=await Promise.race([W.processCrashed,W.waitForExit,new Promise((W0)=>setTimeout(()=>W0({stderr:""}),500))]);throw new I(`Runtime process exited before completion: ${T.stderr?.trim()??""}`)}throw k},N;try{N=await C.initialize({protocolVersion:P1,clientCapabilities:wX,clientInfo:J4()})}catch(k){throw await g(k,[]),Error("unreachable")}try{V4(N.protocolVersion)}catch(k){throw h(),W.kill(),k}let G=N.authMethods?.map((k)=>k.id)??[],u;try{u=await C.newSession({cwd:X.spawn.cwd,mcpServers:X.mcpServers??[]})}catch(k){throw await g(k,G),Error("unreachable")}let D=u.sessionId;B=D;let R=vX(u),O=X.modelId??null,$=O?j4(O,R.models):null;if($&&$!==R.currentModelId)if(R.modelConfigId)R=await F2({conn:C,sessionId:D,configId:R.modelConfigId,value:$,metadata:R,label:`${R.modelConfigId}=${$}`});else console.warn(`[acp] runtime did not advertise a model config option for ${$}; using agent default.`);for(let[k,d]of Object.entries(X.configValues??{}).sort(([T],[W0])=>T.localeCompare(W0))){if(k===R.modelConfigId)continue;if(!R.configOptions.some((T)=>T.id===k))continue;R=await F2({conn:C,sessionId:D,configId:k,value:d,metadata:R,label:`${k}=${String(d)}`})}h();let A=!1,r=async()=>{if(A)return;A=!0,W.kill(),await Promise.race([W.waitForExit,new Promise((k)=>setTimeout(k,2000))])},b0=!1;return W.processCrashed.then(()=>{b0=!0}),{sessionId:D,availableModels:R.models,currentModelId:R.currentModelId,availableConfigOptions:R.configOptions,isAlive:()=>!A&&!b0,dispose:r,prompt:(k)=>C5({proc:W,conn:C,sessionId:D,activeAdapter:U,activeTrace:F,lastUpdate:w,collectStderrTail:V},k)}}async function C5(X,W){let{proc:Z,conn:K,sessionId:J,activeAdapter:V,activeTrace:H,lastUpdate:U}=X,F=Date.now(),w=W.heartbeatMs??B5,B=P5(w),b={boardId:W.boardId,cardId:W.cardId,runId:W.runId},v=e3({ctx:b,appendText:W.appendText,appendToolActivity:W.appendToolActivity,onAnyUpdate:W.onAnyUpdate});V.current=v,H.current={runId:W.runId,cardId:W.cardId,startedAt:F,updateCount:0,lastUpdateType:null},U.at=Date.now(),E("acp.prompt_started",{runId:W.runId,cardId:W.cardId,sessionId:J,heartbeatWindowMs:w});let y=!1,x=null,C=()=>Z.kill();W.signal.addEventListener("abort",C);try{let M=async()=>{let G=Math.min(L5,Math.max(50,Math.floor(w/2)));x=setInterval(()=>{let D=W.isAwaitingInput?.()??!1;if(D){U.at=Date.now();return}if(W4({nowMs:Date.now(),lastUpdateMs:U.at,windowMs:w,awaitingInput:D}))y=!0,E("acp.inactivity_timeout",{runId:W.runId,cardId:W.cardId,sessionId:J,windowMs:w,silentForMs:Date.now()-U.at}),K.cancel({sessionId:J}).catch(()=>{return}),Z.kill()},G);let u=f5(W.prompt.systemPrompt,W.prompt.messages);await K.prompt({sessionId:J,prompt:u}),E("acp.prompt_resolved",{runId:W.runId,cardId:W.cardId,sessionId:J,elapsedMs:Date.now()-F}),v.flush({completeOpenToolCalls:!0})},h=Z.waitForExit.then((G)=>({kind:"exited",exit:G})),g=M().then(()=>({kind:"ok"})).catch(async(G)=>{if(G instanceof Error&&G.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw G}),N;try{N=await Promise.race([g,Z.processCrashed.then((G)=>({kind:"crashed",exit:G})),h])}catch(G){if(y)throw new U0(B);throw G}if(y)throw new U0(B);if(N.kind==="crashed")throw new I(`Runtime process exited before completion: ${N.exit.stderr.trim()}`);if(N.kind==="exited"){if(W.signal.aborted)throw new I("ACP session cancelled: abort signal received");if(y)throw new U0(B);throw new I(`Runtime process exited unexpectedly: ${N.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:v.getFinalText(),toolCallsExecuted:v.getToolCallCount(),stderrTail:X.collectStderrTail(),updateTypeCounts:v.getUpdateTypeCounts()}}finally{if(E("acp.prompt_finished",{runId:W.runId,cardId:W.cardId,sessionId:J,elapsedMs:Date.now()-F,timedOut:y,updateCount:H.current?.updateCount??0}),x!==null)clearInterval(x);W.signal.removeEventListener("abort",C),v.flush({completeOpenToolCalls:!0}),V.current=null,H.current=null}}var h5=30000;async function H4(X){let W=UX(X.spawn),Z=z4(W.stdin),K=Y4(W.stdout),J=Q4(Z,K),H=new Z4((w)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),J),U=()=>W.kill();if(X.signal)X.signal.addEventListener("abort",U);let F=null;try{let w=(async()=>{let b=await H.initialize({protocolVersion:P1,clientCapabilities:wX,clientInfo:J4()});V4(b.protocolVersion);let v=b.authMethods?.map((N)=>N.id)??[],y;try{y=await H.newSession({cwd:X.spawn.cwd,mcpServers:[]})}catch(N){if(K4(N))throw new l0(N.message??"Authentication required",v);throw N}let x=vX(y),C=X.modelId??null,M=C?j4(C,x.models):null;if(M&&M!==x.currentModelId)if(x.modelConfigId)x=await F2({conn:H,sessionId:y.sessionId,configId:x.modelConfigId,value:M,metadata:x,label:`${x.modelConfigId}=${M}`});else console.warn(`[acp] runtime did not advertise a model config option for ${M}; discovering agent default models.`);for(let[N,G]of Object.entries(X.configValues??{}).sort(([u],[D])=>u.localeCompare(D))){if(N===x.modelConfigId)continue;if(!x.configOptions.some((u)=>u.id===N))continue;x=await F2({conn:H,sessionId:y.sessionId,configId:N,value:G,metadata:x,label:`${N}=${String(G)}`})}let h=x.models??[],g=x.currentModelId;return H.cancel({sessionId:y.sessionId}).catch(()=>{return}),{models:h,configOptions:x.configOptions,currentModelId:g}})(),B=new Promise((b,v)=>{F=setTimeout(()=>{v(new U0)},h5)});return await Promise.race([w,B])}catch(w){if(w instanceof Error&&w.message==="ACP connection closed"){if(X.signal?.aborted)throw new I("ACP model discovery cancelled: abort signal received");throw new I("Runtime process exited during model discovery.")}throw w}finally{if(F)clearTimeout(F);if(X.signal)X.signal.removeEventListener("abort",U);W.kill()}}import N5 from"node:fs/promises";import q2 from"node:os";async function w4(X){let W={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await N5.readFile(X,"utf-8")}catch(K){if(K.code==="ENOENT")return structuredClone(W);throw K}return D1.parse(JSON.parse(Z))}function fX(X,W,Z){return{...X.defaultConfigValues??{},...W?.configValues??{},...Z?.configValues??{}}}async function C0(X){let W=X.configPath?await w4(X.configPath):await K0(),Z=X.cardId?W.cardOverrides[X.cardId]:void 0;if(Z?.runtimeConfigId){let J=W.runtimes.find((V)=>V.id===Z.runtimeConfigId);if(J)return{entry:J,adapter:F0(J),runFolder:Z.runFolder??J.runFolder??q2.homedir(),modelId:Z.modelId??J.defaultModelId??null,configValues:fX(J,void 0,Z)}}let K=W.boardOverrides[X.boardId];if(K?.runtimeConfigId){let J=W.runtimes.find((V)=>V.id===K.runtimeConfigId);if(J)return{entry:J,adapter:F0(J),runFolder:K.runFolder??J.runFolder??q2.homedir(),modelId:K.modelId??J.defaultModelId??null,configValues:fX(J,K)}}if(W.globalDefaultConfigId){let J=W.runtimes.find((V)=>V.id===W.globalDefaultConfigId);if(J)return{entry:J,adapter:F0(J),runFolder:Z?.runFolder??K?.runFolder??J.runFolder??q2.homedir(),modelId:Z?.modelId??K?.modelId??J.defaultModelId??null,configValues:fX(J,K,Z)}}throw new D0}async function U4(X,W={}){let K=(W.configPath?await w4(W.configPath):await K0()).runtimes.find((J)=>J.id===X);if(!K)return null;return{entry:K,adapter:F0(K),runFolder:K.runFolder??q2.homedir(),modelId:W.modelId??K.defaultModelId??null,configValues:{...K.defaultConfigValues??{},...W.configValues??{}}}}var F4=new Map;function OX(X,W){if(!X)return;F4.set(X,W)}function q4(X){if(!X)return!1;return F4.get(X)??!1}var k0=new Map,RX=new Set;function CX(X){k0.get(X)?.controller.abort()}function B4(X){for(let[W,Z]of k0){if(Z.frontendSessionId!==X)continue;Z.controller.abort(),k0.delete(W)}}function L4(){for(let X of k0.values())X.controller.abort();k0.clear()}function P4(X,W){if(W?.aborted)return!0;return X instanceof Error&&/abort signal received|session cancelled/i.test(X.message)}function x4(X,W,Z,K){if((!W.availableModels||W.availableModels.length===0)&&W.availableConfigOptions.length===0)return;z0((J)=>{let V=J.runtimes.find((H)=>H.id===X);if(V){if(W.availableModels&&W.availableModels.length>0)V.discoveredModels=Y2({adapterId:Z,models:W.availableModels,currentModelId:W.currentModelId??K});if(W.availableConfigOptions.length>0)V.discoveredConfigOptions=W.availableConfigOptions}}).catch(()=>{return})}function M5(X,W){return`${X}
1063
+ `;V+=O.content.text,w=!1,D(V)}}else{let A=`agent_message_chunk:${O.content.type}`;B[A]=(B[A]??0)+1}return}case"agent_thought_chunk":{if(O.content.type!=="text")return;H+=O.content.text;let $=new Date().toISOString(),A=`${W.runId}:thought`,r=b.get(A);v({toolCallId:A,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:r?.startedAt??$,completedAt:null,contentPreview:_0(H.trim())});return}case"user_message_chunk":return;case"tool_call":{U+=1,w=V.length>0;let $=o3(O.title),A=qX(O.status),r=new Date().toISOString();y(r),x(r),v({toolCallId:O.toolCallId,rawTitle:$,title:LX($,O.rawInput),kind:BX(O.kind),status:A,startedAt:r,completedAt:A==="running"?null:r,inputPreview:x0(O.rawInput),outputPreview:PX(O.rawOutput),contentPreview:w2(O.content),locations:xX(O.locations)});return}case"tool_call_update":{let $=b.get(O.toolCallId);if(!$){let W0=o3(O.title),s=qX(O.status),w0=new Date().toISOString();v({toolCallId:O.toolCallId,rawTitle:W0,title:LX(W0,O.rawInput),kind:BX(O.kind),status:s,startedAt:w0,completedAt:s==="running"?null:w0,inputPreview:x0(O.rawInput),outputPreview:PX(O.rawOutput),contentPreview:w2(O.content),locations:xX(O.locations)});return}let A=O.status===void 0||O.status===null?$.status:qX(O.status),r=typeof O.title==="string"&&O.title.trim().length>0?O.title:$.rawTitle,b0=typeof O.title==="string"&&O.title.trim().length>0,k=A==="running"?$.completedAt:$.completedAt??new Date().toISOString(),d=O.content===void 0?$.contentPreview:t3($.contentPreview,w2(O.content)),T=O.rawOutput===void 0?$.outputPreview:t3($.outputPreview,PX(O.rawOutput));v({...$,rawTitle:r,title:b0?LX(r,O.rawInput):$.title,kind:O.kind===void 0?$.kind:BX(O.kind),status:A,completedAt:k,inputPreview:O.rawInput===void 0?$.inputPreview:x0(O.rawInput),outputPreview:T,contentPreview:d,locations:O.locations===void 0?$.locations:xX(O.locations)});return}case"plan":F=O.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>V,getToolCallCount:()=>U,getLatestPlan:()=>F,getUpdateTypeCounts:()=>({...B}),flush:(R)=>{let O=new Date().toISOString();if(y(O),R?.completeOpenToolCalls)C(O);u()}}}var P1=1,X4=-32000;function W4(X){if(X.awaitingInput)return!1;return X.nowMs-X.lastUpdateMs>=X.windowMs}function K4(X){if(!X||typeof X!=="object")return!1;return X.code===X4}var q5=300000,B5=q5,L5=5000;function P5(X){let W=Math.max(1,Math.round(X/1000));return`Runtime has not responded for ${W} ${W===1?"second":"seconds"}. Retry the agent run.`}function J4(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.83".trim()?"0.0.83":"dev"}}function V4(X){if(X===P1)return;throw new I(`Unsupported ACP protocol version ${X}; expected ${P1}`)}function Y4(X){return U5.toWeb(X)}function z4(X){return F5.toWeb(X)}function bX(X){return X!==null&&typeof X==="object"}function x5(X){if(!Array.isArray(X))return[];let W=[];for(let Z of X){if(!bX(Z))continue;if(typeof Z.group==="string"&&Array.isArray(Z.options)){let K=typeof Z.name==="string"?Z.name:Z.group;for(let J of Z.options){if(!bX(J))continue;if(typeof J.value!=="string"||typeof J.name!=="string")continue;W.push({value:J.value,name:J.name,description:typeof J.description==="string"?J.description:null,group:Z.group,groupName:K})}continue}if(typeof Z.value!=="string"||typeof Z.name!=="string")continue;W.push({value:Z.value,name:Z.name,description:typeof Z.description==="string"?Z.description:null,group:null,groupName:null})}return W}function b5(X){if(!bX(X))return null;if(typeof X.id!=="string"||typeof X.name!=="string")return null;let W=typeof X.category==="string"?X.category:null,Z=typeof X.description==="string"?X.description:null;if(X.type==="select"){let K=typeof X.currentValue==="string"?X.currentValue:null;return{id:X.id,name:X.name,category:W,description:Z,type:"select",currentValue:K,options:x5(X.options)}}if(X.type==="boolean"){let K=typeof X.currentValue==="boolean"?X.currentValue:typeof X.value==="boolean"?X.value:null;return{id:X.id,name:X.name,category:W,description:Z,type:"boolean",currentValue:K,options:[]}}return null}function vX(X){let W=(X.configOptions??[]).map(b5).filter((U)=>U!==null),Z=W.find((U)=>U.type==="select"&&U.category==="model")??W.find((U)=>U.type==="select"&&U.id==="model")??null,K=Z?.options.map((U)=>({id:U.value,name:U.name,description:U.description??null})),J=v5(X.models),V=K&&K.length>0?K:J&&J.length>0?J:null,H=(typeof Z?.currentValue==="string"?Z.currentValue:null)??y5(X.models)??null;return{models:V,currentModelId:H,configOptions:W,modelConfigId:Z?.id??null}}function v5(X){if(!X||!Array.isArray(X.availableModels))return null;let W=[];for(let Z of X.availableModels){if(typeof Z.modelId!=="string")continue;W.push({id:Z.modelId,name:typeof Z.name==="string"?Z.name:null,description:typeof Z.description==="string"?Z.description:null})}return W.length>0?W:null}function y5(X){return typeof X?.currentModelId==="string"?X.currentModelId:null}function f5(X,W){let Z=[];if(X.trim())Z.push({type:"text",text:X});for(let K of W)if(K.content.trim())Z.push({type:"text",text:K.content});return Z}function O5(X){if(typeof X.value==="boolean")return{sessionId:X.sessionId,configId:X.configId,type:"boolean",value:X.value};return{sessionId:X.sessionId,configId:X.configId,value:X.value}}function R5(X,W){let Z=vX({configOptions:W.configOptions});return{models:Z.models??X.models,currentModelId:Z.currentModelId??X.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??X.modelConfigId}}function j4(X,W){if(X==="default")return null;if(!W||W.length===0)return X;let Z=W.find((w)=>w.id===X);if(Z)return Z.id;let K=X.toLowerCase(),J=K.includes("opus")?"opus":K.includes("sonnet")?"sonnet":K.includes("haiku")?"haiku":null;if(!J)return X;let V=(w)=>`${w.id} ${w.name??""} ${w.description??""}`.toLowerCase(),H=W.filter((w)=>V(w).includes(J));if(H.length===0)return X;let F=(K.includes("1m")?H.find((w)=>V(w).includes("1m")):void 0)??H[0];return F?F.id:X}async function F2(X){try{let W=await X.conn.setSessionConfigOption(O5({sessionId:X.sessionId,configId:X.configId,value:X.value}));return R5(X.metadata,W)}catch(W){return console.warn(`[acp] setSessionConfigOption(${X.label}) failed; using agent default.`,W instanceof Error?W.message:W),X.metadata}}async function yX(X){let W=UX(X.spawn),Z=[],K=0,J=4096;W.stderr.on("data",(k)=>{Z.push(k),K+=k.length;while(K>J*2&&Z.length>1){let d=Z.shift();if(d)K-=d.length}});let V=()=>{let k=Buffer.concat(Z).toString("utf8");return k.length>J?k.slice(-J):k},H=s3(X.spawn.cwd),U={current:null},F={current:null},w={at:Date.now()},B=null,b=z4(W.stdin),v=Y4(W.stdout),y=Q4(b,v),C=new Z4((k)=>({requestPermission:async(d)=>{let T=d.options,W0=T?.find((s)=>s.kind==="allow_once")??T?.find((s)=>s.kind==="allow_always");if(W0)return{outcome:{outcome:"selected",optionId:W0.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(d)=>{w.at=Date.now();let T=F.current;if(T){let s=d.update.sessionUpdate;if(T.updateCount+=1,T.updateCount===1||T.lastUpdateType!==s||s==="tool_call"||s==="tool_call_update")E("acp.session_update",{runId:T.runId,cardId:T.cardId,sessionId:B,updateType:s,updateCount:T.updateCount,elapsedMs:Date.now()-T.startedAt});T.lastUpdateType=s}let W0=U.current;if(W0)await W0.onSessionUpdate(d)},readTextFile:H.readTextFile}),y),M=()=>W.kill();if(X.signal)X.signal.addEventListener("abort",M);let h=()=>{if(X.signal)X.signal.removeEventListener("abort",M)},g=async(k,d)=>{if(h(),W.kill(),K4(k))throw new l0(k.message??"Authentication required",d);if(k instanceof Error&&k.message==="ACP connection closed"){if(X.signal?.aborted)throw new I("ACP session cancelled: abort signal received");let T=await Promise.race([W.processCrashed,W.waitForExit,new Promise((W0)=>setTimeout(()=>W0({stderr:""}),500))]);throw new I(`Runtime process exited before completion: ${T.stderr?.trim()??""}`)}throw k},N;try{N=await C.initialize({protocolVersion:P1,clientCapabilities:wX,clientInfo:J4()})}catch(k){throw await g(k,[]),Error("unreachable")}try{V4(N.protocolVersion)}catch(k){throw h(),W.kill(),k}let G=N.authMethods?.map((k)=>k.id)??[],u;try{u=await C.newSession({cwd:X.spawn.cwd,mcpServers:X.mcpServers??[]})}catch(k){throw await g(k,G),Error("unreachable")}let D=u.sessionId;B=D;let R=vX(u),O=X.modelId??null,$=O?j4(O,R.models):null;if($&&$!==R.currentModelId)if(R.modelConfigId)R=await F2({conn:C,sessionId:D,configId:R.modelConfigId,value:$,metadata:R,label:`${R.modelConfigId}=${$}`});else console.warn(`[acp] runtime did not advertise a model config option for ${$}; using agent default.`);for(let[k,d]of Object.entries(X.configValues??{}).sort(([T],[W0])=>T.localeCompare(W0))){if(k===R.modelConfigId)continue;if(!R.configOptions.some((T)=>T.id===k))continue;R=await F2({conn:C,sessionId:D,configId:k,value:d,metadata:R,label:`${k}=${String(d)}`})}h();let A=!1,r=async()=>{if(A)return;A=!0,W.kill(),await Promise.race([W.waitForExit,new Promise((k)=>setTimeout(k,2000))])},b0=!1;return W.processCrashed.then(()=>{b0=!0}),{sessionId:D,availableModels:R.models,currentModelId:R.currentModelId,availableConfigOptions:R.configOptions,isAlive:()=>!A&&!b0,dispose:r,prompt:(k)=>C5({proc:W,conn:C,sessionId:D,activeAdapter:U,activeTrace:F,lastUpdate:w,collectStderrTail:V},k)}}async function C5(X,W){let{proc:Z,conn:K,sessionId:J,activeAdapter:V,activeTrace:H,lastUpdate:U}=X,F=Date.now(),w=W.heartbeatMs??B5,B=P5(w),b={boardId:W.boardId,cardId:W.cardId,runId:W.runId},v=e3({ctx:b,appendText:W.appendText,appendToolActivity:W.appendToolActivity,onAnyUpdate:W.onAnyUpdate});V.current=v,H.current={runId:W.runId,cardId:W.cardId,startedAt:F,updateCount:0,lastUpdateType:null},U.at=Date.now(),E("acp.prompt_started",{runId:W.runId,cardId:W.cardId,sessionId:J,heartbeatWindowMs:w});let y=!1,x=null,C=()=>Z.kill();W.signal.addEventListener("abort",C);try{let M=async()=>{let G=Math.min(L5,Math.max(50,Math.floor(w/2)));x=setInterval(()=>{let D=W.isAwaitingInput?.()??!1;if(D){U.at=Date.now();return}if(W4({nowMs:Date.now(),lastUpdateMs:U.at,windowMs:w,awaitingInput:D}))y=!0,E("acp.inactivity_timeout",{runId:W.runId,cardId:W.cardId,sessionId:J,windowMs:w,silentForMs:Date.now()-U.at}),K.cancel({sessionId:J}).catch(()=>{return}),Z.kill()},G);let u=f5(W.prompt.systemPrompt,W.prompt.messages);await K.prompt({sessionId:J,prompt:u}),E("acp.prompt_resolved",{runId:W.runId,cardId:W.cardId,sessionId:J,elapsedMs:Date.now()-F}),v.flush({completeOpenToolCalls:!0})},h=Z.waitForExit.then((G)=>({kind:"exited",exit:G})),g=M().then(()=>({kind:"ok"})).catch(async(G)=>{if(G instanceof Error&&G.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw G}),N;try{N=await Promise.race([g,Z.processCrashed.then((G)=>({kind:"crashed",exit:G})),h])}catch(G){if(y)throw new U0(B);throw G}if(y)throw new U0(B);if(N.kind==="crashed")throw new I(`Runtime process exited before completion: ${N.exit.stderr.trim()}`);if(N.kind==="exited"){if(W.signal.aborted)throw new I("ACP session cancelled: abort signal received");if(y)throw new U0(B);throw new I(`Runtime process exited unexpectedly: ${N.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:v.getFinalText(),toolCallsExecuted:v.getToolCallCount(),stderrTail:X.collectStderrTail(),updateTypeCounts:v.getUpdateTypeCounts()}}finally{if(E("acp.prompt_finished",{runId:W.runId,cardId:W.cardId,sessionId:J,elapsedMs:Date.now()-F,timedOut:y,updateCount:H.current?.updateCount??0}),x!==null)clearInterval(x);W.signal.removeEventListener("abort",C),v.flush({completeOpenToolCalls:!0}),V.current=null,H.current=null}}var h5=30000;async function H4(X){let W=UX(X.spawn),Z=z4(W.stdin),K=Y4(W.stdout),J=Q4(Z,K),H=new Z4((w)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),J),U=()=>W.kill();if(X.signal)X.signal.addEventListener("abort",U);let F=null;try{let w=(async()=>{let b=await H.initialize({protocolVersion:P1,clientCapabilities:wX,clientInfo:J4()});V4(b.protocolVersion);let v=b.authMethods?.map((N)=>N.id)??[],y;try{y=await H.newSession({cwd:X.spawn.cwd,mcpServers:[]})}catch(N){if(K4(N))throw new l0(N.message??"Authentication required",v);throw N}let x=vX(y),C=X.modelId??null,M=C?j4(C,x.models):null;if(M&&M!==x.currentModelId)if(x.modelConfigId)x=await F2({conn:H,sessionId:y.sessionId,configId:x.modelConfigId,value:M,metadata:x,label:`${x.modelConfigId}=${M}`});else console.warn(`[acp] runtime did not advertise a model config option for ${M}; discovering agent default models.`);for(let[N,G]of Object.entries(X.configValues??{}).sort(([u],[D])=>u.localeCompare(D))){if(N===x.modelConfigId)continue;if(!x.configOptions.some((u)=>u.id===N))continue;x=await F2({conn:H,sessionId:y.sessionId,configId:N,value:G,metadata:x,label:`${N}=${String(G)}`})}let h=x.models??[],g=x.currentModelId;return H.cancel({sessionId:y.sessionId}).catch(()=>{return}),{models:h,configOptions:x.configOptions,currentModelId:g}})(),B=new Promise((b,v)=>{F=setTimeout(()=>{v(new U0)},h5)});return await Promise.race([w,B])}catch(w){if(w instanceof Error&&w.message==="ACP connection closed"){if(X.signal?.aborted)throw new I("ACP model discovery cancelled: abort signal received");throw new I("Runtime process exited during model discovery.")}throw w}finally{if(F)clearTimeout(F);if(X.signal)X.signal.removeEventListener("abort",U);W.kill()}}import N5 from"node:fs/promises";import q2 from"node:os";async function w4(X){let W={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await N5.readFile(X,"utf-8")}catch(K){if(K.code==="ENOENT")return structuredClone(W);throw K}return D1.parse(JSON.parse(Z))}function fX(X,W,Z){return{...X.defaultConfigValues??{},...W?.configValues??{},...Z?.configValues??{}}}async function C0(X){let W=X.configPath?await w4(X.configPath):await K0(),Z=X.cardId?W.cardOverrides[X.cardId]:void 0;if(Z?.runtimeConfigId){let J=W.runtimes.find((V)=>V.id===Z.runtimeConfigId);if(J)return{entry:J,adapter:F0(J),runFolder:Z.runFolder??J.runFolder??q2.homedir(),modelId:Z.modelId??J.defaultModelId??null,configValues:fX(J,void 0,Z)}}let K=W.boardOverrides[X.boardId];if(K?.runtimeConfigId){let J=W.runtimes.find((V)=>V.id===K.runtimeConfigId);if(J)return{entry:J,adapter:F0(J),runFolder:K.runFolder??J.runFolder??q2.homedir(),modelId:K.modelId??J.defaultModelId??null,configValues:fX(J,K)}}if(W.globalDefaultConfigId){let J=W.runtimes.find((V)=>V.id===W.globalDefaultConfigId);if(J)return{entry:J,adapter:F0(J),runFolder:Z?.runFolder??K?.runFolder??J.runFolder??q2.homedir(),modelId:Z?.modelId??K?.modelId??J.defaultModelId??null,configValues:fX(J,K,Z)}}throw new D0}async function U4(X,W={}){let K=(W.configPath?await w4(W.configPath):await K0()).runtimes.find((J)=>J.id===X);if(!K)return null;return{entry:K,adapter:F0(K),runFolder:K.runFolder??q2.homedir(),modelId:W.modelId??K.defaultModelId??null,configValues:{...K.defaultConfigValues??{},...W.configValues??{}}}}var F4=new Map;function OX(X,W){if(!X)return;F4.set(X,W)}function q4(X){if(!X)return!1;return F4.get(X)??!1}var k0=new Map,RX=new Set;function CX(X){k0.get(X)?.controller.abort()}function B4(X){for(let[W,Z]of k0){if(Z.frontendSessionId!==X)continue;Z.controller.abort(),k0.delete(W)}}function L4(){for(let X of k0.values())X.controller.abort();k0.clear()}function P4(X,W){if(W?.aborted)return!0;return X instanceof Error&&/abort signal received|session cancelled/i.test(X.message)}function x4(X,W,Z,K){if((!W.availableModels||W.availableModels.length===0)&&W.availableConfigOptions.length===0)return;z0((J)=>{let V=J.runtimes.find((H)=>H.id===X);if(V){if(W.availableModels&&W.availableModels.length>0)V.discoveredModels=Y2({adapterId:Z,models:W.availableModels,currentModelId:W.currentModelId??K});if(W.availableConfigOptions.length>0)V.discoveredConfigOptions=W.availableConfigOptions}}).catch(()=>{return})}function M5(X,W){return`${X}
1064
1064
 
1065
1065
  Runtime run folder:
1066
1066
  - Effective run folder: ${W}
@@ -1070,4 +1070,4 @@ Runtime run folder:
1070
1070
  Connection: close\r
1071
1071
  Content-Length: ${Buffer.byteLength(Z)}\r
1072
1072
  \r
1073
- ${Z}`),X.destroy()}function x7(X,W){return new Promise((Z,K)=>{let J=(H)=>{X.off("listening",V),K(H)},V=()=>{X.off("error",J);let H=X.address();if(!H||typeof H==="string"){K(Error("Failed to read CLI bridge server address"));return}Z(H.port)};X.once("error",J),X.once("listening",V),X.listen(W,"127.0.0.1")})}function u4(X){return new Promise((W,Z)=>{X.close((K)=>{if(K)Z(K);else W()})})}async function A4(X,W=EX()){let Z=new Map,K=new Map,J=X.maxMessageSize??V7,V=!1,H=(y)=>{let x=K.get(y);if(x)clearTimeout(x);K.delete(y)},U=(y)=>{K.delete(y);let{activeRunIds:x}=X.registry.disconnect(y);X.onDisconnect(y,x)},F=(y,x)=>{let C={type:"cli_status",connected:!0,runtime:X.runtime,mcpReady:X.mcpReady(),error:x,capabilities:X.capabilities??[],cliVersion:X.cliVersion,browserRuntime:X.browserRuntimeStatus?.()};if(y){let M=Z.get(y);if(M)o0(M,C);return}for(let M of Z.values())o0(M,C)},w=(y,x)=>{let C=x.sessionId.trim(),M=x.userId.trim();if(!C||!M){o0(y,{type:"cli_status",connected:!1,runtime:X.runtime,mcpReady:X.mcpReady(),error:"Missing frontend session or user id"}),y.close();return}H(C);let h=Z.get(C);if(h&&h!==y)h.close();y.data.frontendSessionId=C,Z.set(C,y),X.registry.register({frontendSessionId:C,userId:M,tools:x.tools,send:(g)=>o0(y,g)}),F(C),X.onToolMetadata?.(C)},B=(y,x)=>{let C=X.registry.getUserId(y);if(!C)return;switch(x.type){case"bridge_ping":{let M=Z.get(y);if(M)o0(M,{type:"bridge_pong"});break}case"tool_metadata":X.registry.setMetadata(y,x.tools),X.onToolMetadata?.(y);break;case"tool_result":X.registry.handleToolResult(y,x);break;case"run_turn":E("bridge.run_received",{runId:x.run.runId,cardId:x.run.cardId,frontendSessionId:y}),X.registry.markRunActive(y,x.run.runId,x.run.cardId),X.onRunTurn(y,{...x.run,frontendSessionId:y,userId:C});break;case"cancel_run":if(X.registry.ownsRun(y,x.runId))X.onCancelRun(y,x.runId);break;case"runtime_rpc":X.onRuntimeRpc(y,x);break;case"browser_rpc":X.onBrowserRpc?.(y,Z.get(y)?.data.frontendOrigin??"",x);break;case"warmup_run":X.onWarmupRun(y,{...x,frontendSessionId:y},C);break;default:break}},b=(y,x)=>{let C=b2(y.headers.origin),M=_X(C),h={Vary:"Origin"};if(M&&C)h["Access-Control-Allow-Origin"]=C,h["Access-Control-Allow-Private-Network"]="true";if(y.method==="OPTIONS"){x.writeHead(204,{...h,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),x.end();return}if(y.method!=="GET"){x.writeHead(405,h),x.end();return}x.writeHead(200,{...h,"content-type":"application/json","cache-control":"no-store"}),x.end(JSON.stringify({ideawave:!0,runtime:X.runtime,mcpReady:X.mcpReady(),capabilities:X.capabilities??[],cliVersion:X.cliVersion,browserRuntime:X.browserRuntimeStatus?.()}))},v=(y,x)=>{let C=b2(y.headers.origin),M=_X(C),h={Vary:"Origin"};if(M&&C)h["Access-Control-Allow-Origin"]=C,h["Access-Control-Allow-Private-Network"]="true";if(y.method==="OPTIONS"){x.writeHead(204,{...h,"Access-Control-Allow-Methods":"POST, OPTIONS","Access-Control-Allow-Headers":"content-type","Access-Control-Max-Age":"600"}),x.end();return}if(!M){x.writeHead(403,h),x.end();return}if(y.method!=="POST"){x.writeHead(405,h),x.end();return}let g={...h,"content-type":"application/json"},N=(D,R)=>{x.writeHead(D,g),x.end(JSON.stringify(R))},G="",u=!1;y.on("data",(D)=>{if(G+=D.toString("utf8"),G.length>H7)u=!0,y.destroy()}),y.on("end",()=>{if(u){N(400,{ok:!1,error:"Request body too large"});return}let D;try{D=JSON.parse(G)}catch{N(400,{ok:!1,error:"Invalid JSON body"});return}let R=typeof D.url==="string"?D.url:"";if(!G4(R)){N(400,{ok:!1,error:"url must be an http(s) loopback or /static_boards/ page URL"});return}let O=($,A)=>{let r=typeof $==="number"?$:Number.NaN;if(!Number.isFinite(r))return A;return Math.min(4000,Math.max(200,Math.round(r)))};E4({url:R,width:O(D.width,1440),height:O(D.height,900)}).then(($)=>N(200,{ok:!0,path:$.path,engine:$.engine})).catch(($)=>{let A=$ instanceof b1?503:$ instanceof x2?429:500;N(A,{ok:!1,...$ instanceof b1?{installing:!0}:{},error:$ instanceof Error?$.message:String($)})})})};for(let y of W){let x=K7((h,g)=>{(async()=>{let N=new URL(h.url??"/","http://127.0.0.1").pathname;if(N===g4){b(h,g);return}if(N===j7){v(h,g);return}if(await X.onHttpRequest?.(h,g))return;g.writeHead(404,{"content-type":"text/plain"}),g.end("IdeaWave CLI bridge")})().catch((N)=>{if(g.headersSent){g.destroy(N instanceof Error?N:void 0);return}g.writeHead(500,{"content-type":"text/plain"}),g.end("IdeaWave CLI bridge request failed")})}),C=new J7({noServer:!0,maxPayload:J}),M=(h)=>{if(h.idleTimer)clearTimeout(h.idleTimer);h.idleTimer=setTimeout(()=>{h.close()},Y7),h.idleTimer.unref?.()};C.on("connection",(h,g)=>{let N=h;N.data={id:Q7(),frontendSessionId:null,frontendOrigin:new URL(b2(g.headers.origin)??S4).origin},N.idleTimer=null,M(N),N.on("ping",()=>M(N)),N.on("pong",()=>M(N)),N.on("error",()=>{if(N.idleTimer)clearTimeout(N.idleTimer);N.close()}),N.on("message",(G)=>{M(N);let u=P7(G);if(J>0&&u.length>J)return;let D=M1(u);if(!D)return;let R=N.data.frontendSessionId;if(!R){if(D.type==="bridge_probe")o0(N,{type:"bridge_probe_ack",protocolVersion:D.protocolVersion});else if(D.type==="frontend_hello")w(N,D);return}B(R,D)}),N.on("close",()=>{if(N.idleTimer)clearTimeout(N.idleTimer);let G=N.data.frontendSessionId;if(!G)return;if(Z.get(G)!==N)return;if(Z.delete(G),H(G),V)return;K.set(G,setTimeout(()=>U(G),z7))})}),x.on("upgrade",(h,g,N)=>{let G=new URL(h.url??"/","http://127.0.0.1").pathname;if(X.onHttpUpgrade?.(h,g,N))return;if(G!==GX){k4(g,404,"Not Found");return}if(!_X(b2(h.headers.origin))){k4(g,403,"Forbidden");return}C.handleUpgrade(h,g,N,(u)=>{C.emit("connection",u,h)})});try{let h=await x7(x,y);return{url:`ws://127.0.0.1:${h}${GX}`,port:h,sendStatus:F,close:async()=>{V=!0;for(let g of K.values())clearTimeout(g);K.clear();for(let g of C.clients){let N=g;if(N.idleTimer)clearTimeout(N.idleTimer);N.close()}C.close(),await u4(x).catch(()=>{return})}}}catch(h){if(C.close(),await u4(x).catch(()=>{return}),h?.code==="EADDRINUSE")continue;throw h}}throw Error(`No free IdeaWave CLI bridge port found in ${W[0]}-${W.at(-1)}`)}import{lstat as E7,readFile as _7}from"node:fs/promises";import k7 from"node:os";import y1 from"node:path";import{Server as u7}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as I7,ListToolsRequestSchema as S7}from"@modelcontextprotocol/sdk/types.js";var kX=new Set(["list_boards","get_board","screenshot_board","list_nodes","list_edges","inspect_node","list_context_sources","read_context_card","read_context_file","read_context_image","list_context_folder","get_board_wiki","search_board","get_card_messages","list_agent_cards","inspect_neighbors"]),b7=["screenshot_board","inspect_diagram","ask_user_question","create_agent_card","append_user_message","spawn_child_agents"],v7=new Set(b7),QY=new Set([...kX].filter((X)=>!v7.has(X)));import{randomUUID as f7}from"node:crypto";import{createServer as O7}from"node:http";import{StreamableHTTPServerTransport as R7}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as i4}from"@modelcontextprotocol/sdk/types.js";var T4=new Set(["127.0.0.1","localhost","[::1]","::1"]);function y7(X){let W=X.trim();if(W.length===0)return null;if(W.startsWith("[")){let V=W.indexOf("]");if(V===-1)return null;let H=W.slice(0,V+1),U=W.slice(V+1);if(U.length===0)return{host:H,port:null};if(!U.startsWith(":"))return null;let F=Number(U.slice(1));if(!Number.isInteger(F)||F<=0||F>65535)return null;return{host:H,port:F}}let Z=W.lastIndexOf(":");if(Z===-1)return{host:W,port:null};let K=W.slice(Z+1),J=Number(K);if(!Number.isInteger(J)||J<=0||J>65535)return{host:W,port:null};return{host:W.slice(0,Z),port:J}}function c4(X){return T4.has(X)||T4.has(X.toLowerCase())}function a4(X,W){let Z=X.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let K=y7(Z);if(!K)return{ok:!1,status:403,reason:"bad-host"};if(!c4(K.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(K.port!==null&&K.port!==W)return{ok:!1,status:403,reason:"host-port-mismatch"};let J=X.headers.origin;if(typeof J==="string"&&J.length>0){if(J!=="null"){let V;try{V=new URL(J)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!c4(V.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var d4="/mcp",C7=43274,r4=16777216,h7=1800000,N7=300000,p4=200,M7=-32700,N0=-32600,uX=-32603;function Y0(X,W,Z,K,J){X.statusCode=W,X.setHeader("content-type","application/json"),X.end(JSON.stringify({jsonrpc:"2.0",error:{code:Z,message:K,...J?{data:J}:{}},id:null}))}class IX extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class SX extends Error{constructor(){super(`body exceeds ${r4} bytes`);this.name="BodyTooLargeError"}}async function g7(X){if(X.method&&X.method!=="POST")return;let W=X.headers["content-type"];if(typeof W==="string"&&W.trim().length>0){if(!W.toLowerCase().includes("application/json"))throw new IX}let Z=0,K=[];for await(let V of X){let H=typeof V==="string"?Buffer.from(V):V;if(Z+=H.byteLength,Z>r4)throw new SX;K.push(H)}if(K.length===0)return;let J=Buffer.concat(K).toString("utf8");if(J.length===0)return;return JSON.parse(J)}function D7(X){if(Array.isArray(X))return X.some(i4);return i4(X)}function m7(X){if(typeof X==="number")return X;let W=process.env.IDEAWAVE_MCP_PORT;if(W&&W.trim().length>0){let Z=Number(W);if(Number.isInteger(Z)&&Z>=0&&Z<65536)return Z}return C7}async function $7(X,W){let Z=(J)=>new Promise((V,H)=>{let U=(w)=>{X.off("listening",F),H(w)},F=()=>{X.off("error",U),V()};X.once("error",U),X.once("listening",F),X.listen(J,"127.0.0.1")});try{await Z(W)}catch(J){if(J.code!=="EADDRINUSE"||W===0)throw J;console.warn(`[mcp] port ${W} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await Z(0)}let K=X.address();if(K==null||typeof K==="string")throw Error("[mcp] failed to read bound address");return K.port}function G7(X,W){if(W&&typeof W==="object"&&!Array.isArray(W)){let K=W.params;if(K&&typeof K==="object"&&!Array.isArray(K)){let J=K.clientInfo;if(J&&typeof J==="object"&&!Array.isArray(J)){let V=J.name;if(typeof V==="string"&&V.trim().length>0)return V.trim()}}}let Z=X.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function s4(X){let W=new Map,Z=0;function K(w){let B=W.get(w);if(B)B.lastActivity=Date.now()}async function J(w,B){W.delete(w),await B.transport.close().catch(()=>{return})}async function V(){let w=null,B=1/0;for(let[b,v]of W)if(v.lastActivity<B)B=v.lastActivity,w=b;if(w!==null){let b=W.get(w);if(b)console.warn(`[mcp] session cap of ${p4} reached; evicting ${w}`),await J(w,b)}}let H=setInterval(()=>{let w=Date.now()-h7;for(let[B,b]of W)if(b.lastActivity<w)console.log(`[mcp] sweeping idle session ${B}`),J(B,b)},N7);H.unref?.();let U=O7((w,B)=>{(async()=>{let b;try{b=new URL(w.url??"/","http://127.0.0.1").pathname}catch{Y0(B,400,N0,"bad-url");return}if(b!==d4){Y0(B,404,N0,"not-found");return}let v=w.method??"POST";if(v!=="POST"&&v!=="GET"&&v!=="DELETE"){B.setHeader("Allow","GET, POST, DELETE"),Y0(B,405,N0,"method-not-allowed");return}let y=a4(w,Z);if(!y.ok){Y0(B,y.status,N0,"forbidden",{reason:y.reason});return}let x=w.headers["mcp-session-id"],C=typeof x==="string"?x:void 0;if(v==="GET"||v==="DELETE"){if(!C||!W.has(C)){Y0(B,400,N0,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let g=W.get(C).transport;K(C);try{await g.handleRequest(w,B)}catch(N){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",N),!B.headersSent)Y0(B,500,uX,"internal")}return}let M;try{M=await g7(w)}catch(g){if(g instanceof IX){Y0(B,415,N0,"expected-application-json");return}if(g instanceof SX){Y0(B,413,N0,"body-too-large");return}Y0(B,400,M7,"invalid-json");return}let h;if(C&&W.has(C))h=W.get(C).transport,K(C);else if(!C&&M!==void 0&&D7(M)){let g=w.headers["x-ideawave-user-id"],N=typeof g==="string"&&g.trim().length>0?g.trim():null,G=w.headers["x-ideawave-frontend-session-id"],u=typeof G==="string"&&G.trim().length>0?G.trim():null,D=w.headers["x-ideawave-tool-surface"],R=typeof D==="string"&&D.trim()==="read"?"read":"full",O=w.headers["x-ideawave-images-supported"],$=typeof O==="string"&&O.trim()==="1",A=w.headers["x-ideawave-card-id"],r=typeof A==="string"&&A.trim().length>0?A.trim():null,b0=w.headers["x-ideawave-board-id"],k=typeof b0==="string"&&b0.trim().length>0?b0.trim():null,d=w.headers["x-ideawave-run-folder"],T=typeof d==="string"&&d.trim().length>0?d.trim():null,W0=G7(w,M);if(W.size>=p4)await V();let s=null,w0=new R7({sessionIdGenerator:()=>f7(),onsessioninitialized:(S0)=>{s=S0,W.set(S0,{transport:w0,lastActivity:Date.now()})},onsessionclosed:(S0)=>{W.delete(S0)}});w0.onclose=()=>{if(w0.sessionId)W.delete(w0.sessionId)};try{await X.buildServer({userId:N,frontendSessionId:u,boardId:k,toolSurface:R,imagesSupported:$,cardId:r,runFolder:T,clientHint:W0}).connect(w0)}catch(S0){if(console.error("[mcp] buildServer/connect failed",S0),s)W.delete(s);await w0.close().catch(()=>{return}),Y0(B,500,uX,"server-init-failed");return}h=w0}else{Y0(B,400,N0,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await h.handleRequest(w,B,M)}catch(g){if(console.error("[mcp] transport.handleRequest threw",g),!B.headersSent)Y0(B,500,uX,"internal")}})().catch((b)=>{console.error("[mcp] unhandled request handler error:",b)})});return Z=await $7(U,m7(X.port)),{url:`http://127.0.0.1:${Z}${d4}`,port:Z,close:async()=>{clearInterval(H);for(let w of W.values())await w.transport.close().catch(()=>{return});W.clear(),await new Promise((w)=>U.close(()=>w()))}}}var l7={name:"ideawave-board",version:"1.0.0"},v2="list_run_folder",y2="read_run_folder_file",t4=new Set([...kX,v2,y2]),e4=new Set(["inspect_diagram"]),A7=[{name:v2,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:y2,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 lX(X){return{content:[{type:"text",text:X}]}}function T7(X){return lX(JSON.stringify(X,null,2))}function o4(X){return{...lX(X),isError:!0}}async function c7(X,W){if(!W||X.isError)return X;let Z=X.content.find((V)=>V.type==="text");if(!Z)return X;let K;try{let V=JSON.parse(Z.text);if(typeof V.path!=="string")return X;K=y1.resolve(V.path)}catch{return X}let J=y1.resolve(y1.join(k7.tmpdir(),"ideawave-screenshots"));if(y1.dirname(K)!==J||!/^board-[a-z0-9-]+\.png$/i.test(y1.basename(K)))return X;try{if(!(await E7(K)).isFile())return X;let H=await _7(K);if(H.byteLength<1024||H.byteLength>26214400||!H.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return X;return{...X,content:[...X.content,{type:"image",data:H.toString("base64"),mimeType:"image/png"}]}}catch{return X}}function a7(X,W,Z="full",K=!1){return X.getMetadata(W).filter((J)=>{let V=H2(J.name);if(Z==="read"&&!t4.has(V))return!1;if(!K&&e4.has(V))return!1;return!0}).map((J)=>({name:J.name,description:J.description,inputSchema:J.inputSchema}))}function i7(X,W,Z={}){let K=a7(X,W,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...K,...A7]:K}function n4(X,W){if(!X||typeof X!=="object"||Array.isArray(X))return null;let Z=X[W];return typeof Z==="string"?Z:null}async function d7(X,W,Z){if(Z&&Z.trim().length>0)return Z.trim();if(!X||!W)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await C0({boardId:X,cardId:W})).runFolder}async function p7(X){let W=await d7(X.boardId,X.cardId,X.runFolder);if(X.name===v2){let Z=n4(X.args,"path")??"",K=await r3(W,Z);return T7(K)}if(X.name===y2){let Z=n4(X.args,"path");if(!Z)return o4("read_run_folder_file requires a path.");return lX(await j2(W,Z))}return o4(`Unknown local tool "${X.name}"`)}function r7(X,W,Z,K,J,V="full",H=!1){let U=new u7(l7,{capabilities:{tools:{}}}),F=async()=>{if(H)return!0;if(q4(K))return!0;if(Z&&K)try{return(await C0({boardId:Z,cardId:K})).adapter.supportsImages===!0}catch{return!1}return!1};return U.setRequestHandler(S7,async()=>({tools:i7(X,W,{includeRunFolderTools:Boolean(J||Z&&K),toolSurface:V,imagesSupported:await F()})})),U.setRequestHandler(I7,async(w)=>{let{name:B,arguments:b}=w.params,v=H2(B),y=Date.now();E("mcp.tool_call_received",{frontendSessionId:W,cardId:K,toolName:v});try{if(v===v2||v===y2)return await p7({name:v,args:b,boardId:Z,cardId:K,runFolder:J});if(V==="read"&&!t4.has(v))throw Error(`Tool "${B}" is not available in read-only mode`);if(e4.has(v)&&!await F())throw Error(`Tool "${B}" requires a runtime that supports image input`);let x=await X.callTool(W,v,b??{},void 0,K??void 0);if(E("mcp.tool_result_returned",{frontendSessionId:W,cardId:K,toolName:v,elapsedMs:Date.now()-y}),x&&typeof x==="object"&&Array.isArray(x.content)){let C=x;return v==="screenshot_board"?await c7(C,await F()):C}return{content:[{type:"text",text:typeof x==="string"?x:JSON.stringify(x)}]}}catch(x){return E("mcp.tool_result_returned",{frontendSessionId:W,cardId:K,toolName:v,elapsedMs:Date.now()-y,hasError:!0}),{content:[{type:"text",text:x instanceof Error?x.message:"Tool call failed"}],isError:!0}}}),U}function X8(X,W){return s4({buildServer:(Z)=>r7(X,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:W})}import f2 from"node:fs/promises";import AX from"node:os";import O2 from"node:path";function W8(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function s7(){let[X,W]=await Promise.all([K0(),k6()]),Z=X.globalDefaultConfigId?X.runtimes.find((K)=>K.id===X.globalDefaultConfigId)??null:null;return{runtimes:X.runtimes,globalDefaultConfigId:X.globalDefaultConfigId,globalDefaultEffective:Z?{runFolder:Z.runFolder??AX.homedir(),modelId:Z.defaultModelId??null,configValues:Z.defaultConfigValues??{}}:null,knownAdapters:T0().map((K)=>({id:K.id,displayName:K.displayName})),readiness:W}}async function o7(X){try{let W=await C0({boardId:X.boardId,cardId:X.cardId});return{resolved:{configId:W.entry.id,adapterId:W.entry.kind==="registered"?W.entry.adapterId:null,displayName:W.entry.displayName,runFolder:W.runFolder,modelId:W.modelId,configValues:W.configValues}}}catch(W){if(W instanceof D0)return{resolved:null};throw W}}async function n7(X){return z0((W)=>{let Z=W.runtimes.find((V)=>V.kind==="registered"&&V.adapterId===X.adapterId);if(Z)return Z;let K=T0().find((V)=>V.id===X.adapterId);if(!K)throw Error(`Unknown adapterId: ${X.adapterId}`);let J={id:W8(),kind:"registered",adapterId:X.adapterId,displayName:K.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return W.runtimes.push(J),J})}async function t7(X){return z0((W)=>{let Z={id:W8(),kind:"custom",displayName:X.displayName,command:X.command,args:X.args,env:X.env,runFolder:X.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return W.runtimes.push(Z),Z})}async function e7(X){await z0((W)=>{if(W.runtimes=W.runtimes.filter((Z)=>Z.id!==X.runtimeConfigId),W.globalDefaultConfigId===X.runtimeConfigId)W.globalDefaultConfigId=null;for(let Z of Object.keys(W.boardOverrides))if(W.boardOverrides[Z].runtimeConfigId===X.runtimeConfigId)delete W.boardOverrides[Z];for(let Z of Object.keys(W.cardOverrides))if(W.cardOverrides[Z].runtimeConfigId===X.runtimeConfigId)delete W.cardOverrides[Z]})}async function XQ(X){await z0((W)=>{let Z=W.runtimes.find((K)=>K.id===X.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);if(W.globalDefaultConfigId=X.runtimeConfigId,X.runFolder!==void 0)Z.runFolder=X.runFolder;if(X.modelId!==void 0)Z.defaultModelId=X.modelId;if(X.configValues!==void 0)Z.defaultConfigValues=X.configValues})}async function WQ(X){X.boardId,await z0((W)=>{if(X.runtimeConfigId===null){delete W.cardOverrides[X.cardId];return}if(!W.runtimes.some((J)=>J.id===X.runtimeConfigId))throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let K=W.cardOverrides[X.cardId];W.cardOverrides[X.cardId]={runtimeConfigId:X.runtimeConfigId,runFolder:X.runFolder!==void 0?X.runFolder:K?.runFolder??null,modelId:X.modelId!==void 0?X.modelId:K?.modelId??null,configValues:X.configValues!==void 0?X.configValues:K?.configValues??{}}})}async function ZQ(X){let Z=(await K0()).runtimes.find((H)=>H.id===X.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let K=F0(Z),J=await K.resolveSpawnConfig(Z),V=Z.runFolder??AX.homedir();try{let H=await H4({spawn:{...J,cwd:V},modelId:X.modelId??Z.defaultModelId??null,configValues:X.configValues??Z.defaultConfigValues??{}}),U=Y2({adapterId:K.id,models:H.models,currentModelId:H.currentModelId}),F=new Date().toISOString();return await z0((w)=>{let B=w.runtimes.find((b)=>b.id===X.runtimeConfigId);if(B)B.discoveredModels=U,B.discoveredConfigOptions=H.configOptions,B.discoveredAt=F}),{ok:!0,models:U,configOptions:H.configOptions,currentModelId:H.currentModelId}}catch(H){if(H instanceof l0)throw Error(`${H.message}${K.authHint?` ${K.authHint}`:""}`);if(H instanceof I||H instanceof U0)throw Error(H.message);throw H}}async function QQ(X){let W=AX.homedir(),Z=X.path?.trim()?X.path.trim():W,K=O2.resolve(Z),J=!0;try{if(!(await f2.stat(K)).isDirectory())K=O2.dirname(K)}catch{J=!1,K=W}let V=[];try{V=(await f2.readdir(K,{withFileTypes:!0})).filter((F)=>F.isDirectory()&&!F.name.startsWith(".")).map((F)=>({name:F.name,path:O2.join(K,F.name)})).sort((F,w)=>F.name.localeCompare(w.name))}catch{V=[]}let H=O2.dirname(K);return{path:K,parent:H===K?null:H,home:W,exists:J,entries:V}}var Z8={list:s7,getEffectiveForCard:o7,registerRegistered:n7,registerCustom:t7,unregister:e7,setUserDefault:XQ,setCardOverride:WQ,refreshModels:ZQ,browseFolder:QQ};var KQ=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function JQ(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function Q8(){try{let X=await K0();if(X.globalDefaultConfigId){if(X.runtimes.some((Z)=>Z.id===X.globalDefaultConfigId))return X.globalDefaultConfigId}for(let W of KQ){if((await u6(W.id))?.status!=="ready")continue;let K=null;if(await z0((J)=>{if(J.globalDefaultConfigId){if(J.runtimes.some((U)=>U.id===J.globalDefaultConfigId)){K=J.globalDefaultConfigId;return}}let V=J.runtimes.find((H)=>H.kind==="registered"&&H.adapterId===W.id);if(!V){let H={id:JQ(),kind:"registered",adapterId:W.id,displayName:W.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};J.runtimes.push(H),V=H}J.globalDefaultConfigId=V.id,K=V.id}),K)return console.log(`[ideawave-cli] using agent runtime: ${W.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(X){return console.warn("[ideawave-cli] runtime auto-seed failed",X),null}}var VQ=120000;function YQ(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class TX{sessions=new Map;createCallId;toolCallTimeoutMs;constructor(X={}){this.createCallId=X.createCallId??YQ,this.toolCallTimeoutMs=X.toolCallTimeoutMs??VQ}register(X){let W=this.sessions.get(X.frontendSessionId);if(W){if(W.userId!==X.userId)this.rejectPending(W,"frontend session user changed"),W.activeRunIds.clear();this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:W.pendingToolCalls,activeRunIds:W.activeRunIds,activeRunCardIds:W.activeRunCardIds});return}this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect(X,W="frontend session disconnected"){let Z=this.sessions.get(X);if(!Z)return{activeRunIds:[]};return this.sessions.delete(X),this.rejectPending(Z,W),{activeRunIds:Array.from(Z.activeRunIds)}}sessionCount(){return this.sessions.size}has(X){return this.sessions.has(X)}getUserId(X){return this.sessions.get(X)?.userId??null}setMetadata(X,W){let Z=this.sessions.get(X);if(Z)Z.tools=W}getMetadata(X){if(!X)return[];return this.sessions.get(X)?.tools??[]}sendToSession(X,W){let Z=this.sessions.get(X);if(!Z)return!1;return Z.send(W),!0}callTool(X,W,Z,K,J){if(!X)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let V=this.sessions.get(X);if(!V)return Promise.reject(Error(`Frontend session ${X} is not connected`));let H=this.createCallId();return new Promise((U,F)=>{let w=K??(J?this.getActiveRunIdForCard(V,J):this.getSoleActiveRunId(V)),B=J??(w?V.activeRunCardIds.get(w):void 0),b=Date.now(),v=setTimeout(()=>{V.pendingToolCalls.delete(H),E("tool_queue.timeout",{frontendSessionId:X,runId:w,cardId:B,callId:H,toolName:W,elapsedMs:Date.now()-b,queueDepth:V.pendingToolCalls.size}),F(Error(`Tool "${W}" timed out waiting for the frontend`))},this.toolCallTimeoutMs);V.pendingToolCalls.set(H,{resolve:U,reject:F,timer:v,name:W,runId:w??null,cardId:B??null,startedAt:b}),E("tool_queue.forwarded_to_browser",{frontendSessionId:X,runId:w,cardId:B,callId:H,toolName:W,queueDepth:V.pendingToolCalls.size}),V.send({type:"tool_call",callId:H,name:W,args:Z,...w?{runId:w}:{},...B?{cardId:B}:{}})})}handleToolResult(X,W){let Z=this.sessions.get(X);if(!Z)return;let K=Z.pendingToolCalls.get(W.callId);if(!K)return;if(Z.pendingToolCalls.delete(W.callId),clearTimeout(K.timer),E("tool_queue.result_received",{frontendSessionId:X,runId:K.runId,cardId:K.cardId,callId:W.callId,toolName:K.name,elapsedMs:Date.now()-K.startedAt,queueDepth:Z.pendingToolCalls.size,ok:W.ok}),W.ok){K.resolve(W.result);return}let J=W.result;if(J&&typeof J==="object"&&Array.isArray(J.content)){K.resolve({...J,isError:!0});return}K.reject(Error(W.error??"Tool execution failed"))}markRunActive(X,W,Z){let K=this.sessions.get(X);if(!K)return;if(K.activeRunIds.add(W),Z)K.activeRunCardIds.set(W,Z)}markRunSettled(X,W){let Z=this.sessions.get(X);if(!Z)return;Z.activeRunIds.delete(W),Z.activeRunCardIds.delete(W)}ownsRun(X,W){return this.sessions.get(X)?.activeRunIds.has(W)??!1}rejectPending(X,W){for(let Z of X.pendingToolCalls.values())clearTimeout(Z.timer),E("tool_queue.rejected",{frontendSessionId:X.frontendSessionId,runId:Z.runId,cardId:Z.cardId,toolName:Z.name,elapsedMs:Date.now()-Z.startedAt}),Z.reject(Error(W));X.pendingToolCalls.clear()}getSoleActiveRunId(X){return X.activeRunIds.size===1?X.activeRunIds.values().next().value:void 0}getActiveRunIdForCard(X,W){let Z=[...X.activeRunCardIds.entries()].filter(([K,J])=>X.activeRunIds.has(K)&&J===W).map(([K])=>K);return Z.length===1?Z[0]:void 0}}function J8(){return"0.0.81".trim()?"0.0.81":"dev"}var zQ=process.argv.slice(2),aX=_4(zQ,process.env);if(aX.allowRailwayPrPreviews)process.env[v1]="1";var g0=aX.cliArgs[0],{browserKitEnabled:O1,captureEngineEnabled:jQ}=aX;if(g0==="--help"||g0==="-h"||g0==="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(g0==="--version"||g0==="-v"||g0==="version")console.log(J8()),process.exit(0);if(g0)console.error(`Unknown command: ${g0}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var R1=new TX,I0=null,HQ=O1?{phase:"ready",message:"Local browser-kit proxy is ready"}:{phase:"idle"},n0=new V2;function M0(X,W){R1.sendToSession(X,W)}async function wQ(X,W){try{let Z=Z8[W.method],K=await Z(W.params);M0(X,{type:"runtime_rpc_result",requestId:W.requestId,ok:!0,result:K})}catch(Z){M0(X,{type:"runtime_rpc_result",requestId:W.requestId,ok:!1,error:Z instanceof Error?Z.message:String(Z)})}}var C1=!1,f1=null;async function cX(){if(C1)return;if(f1)return f1;return f1=(async()=>{try{let X=await X8(R1);tX({...X,requestedPort:X.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${X.url}`);try{await P6({onStatusChange:(W)=>{if(I6(),I0?.sendStatus(),W.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${W.packageName}: ${W.error??"unknown error"}`)}})}catch(W){console.warn("[ideawave-cli] ACP bridge setup skipped:",W instanceof Error?W.message:String(W))}await Q8(),C1=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),I0?.sendStatus()}catch(X){console.error("[ideawave-cli] failed to start agent host:",X),I0?.sendStatus(void 0,X instanceof Error?X.message:String(X))}finally{f1=null}})(),f1}if(process.env.APP_ENV!=="development"){let X=await l4();if(X)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${X}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}if(jQ)C4().then((X)=>{if(X.phase==="ready")console.log("[ideawave-cli] screenshot engine ready");else if(X.phase==="failed")console.warn(`[ideawave-cli] screenshot engine setup failed: ${X.error??"unknown error"}`)});I0=await A4({registry:R1,runtime:null,mcpReady:()=>C1,capabilities:O1?[eX,X6,W6]:[],cliVersion:J8(),browserRuntimeStatus:()=>HQ,onToolMetadata:(X)=>{console.log(`[ideawave-cli] session ${X} advertised ${R1.getMetadata(X).length} tools`),cX()},onRunTurn:(X,W)=>{console.log(`[ideawave-cli] running agent turn for card ${W.cardId} (session ${X})`),(async()=>{if(await cX(),!C1){M0(X,{type:"run_settled",runId:W.runId,cardId:W.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await b4(W,(Z)=>M0(X,Z))})().catch(()=>{return}).finally(()=>R1.markRunSettled(X,W.runId))},onCancelRun:(X,W)=>{CX(W)},onRuntimeRpc:(X,W)=>{wQ(X,W)},onBrowserRpc:(X,W,Z)=>{if(!O1){M0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!1,error:"The development browser-kit proxy is not enabled"});return}n0.handleRpc(X,W,Z).then((K)=>{M0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!0,result:K})},(K)=>{M0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!1,error:K instanceof Error?K.message:String(K)})})},onHttpRequest:(X,W)=>O1?n0.handleHttpRequest(X,W):!1,onHttpUpgrade:(X,W,Z)=>O1?n0.handleUpgrade(X,W,Z):!1,onWarmupRun:(X,W,Z)=>{(async()=>{if(await cX(),!C1)return{status:"retryable",error:"agent host is not ready"};return v4({cardId:W.cardId,boardId:W.boardId,userId:Z,frontendSessionId:X})})().then((K)=>{if(!W.warmupId)return;M0(X,{type:"warmup_result",warmupId:W.warmupId,cardId:W.cardId,...K})})},onDisconnect:(X,W)=>{n0.closeFrontendSession(X),B4(X);for(let Z of W)CX(Z);E("bridge.frontend_disconnected",{frontendSessionId:X,activeRuns:W.length}),pX(X).catch((Z)=>{console.warn(`[ideawave-cli] failed to evict sessions for ${X}:`,Z instanceof Error?Z.message:String(Z))}),console.log(`[ideawave-cli] browser session ${X} disconnected`)}});n0.setPort(I0.port);console.log(`[ideawave-cli] browser bridge listening on ${I0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var K8=!1;for(let X of["SIGINT","SIGTERM"])process.once(X,()=>{if(K8)return;K8=!0,L4(),(async()=>{await n0.close(),await M4(),await I0?.close().catch(()=>{return}),process.exit(0)})()});
1073
+ ${Z}`),X.destroy()}function x7(X,W){return new Promise((Z,K)=>{let J=(H)=>{X.off("listening",V),K(H)},V=()=>{X.off("error",J);let H=X.address();if(!H||typeof H==="string"){K(Error("Failed to read CLI bridge server address"));return}Z(H.port)};X.once("error",J),X.once("listening",V),X.listen(W,"127.0.0.1")})}function u4(X){return new Promise((W,Z)=>{X.close((K)=>{if(K)Z(K);else W()})})}async function A4(X,W=EX()){let Z=new Map,K=new Map,J=X.maxMessageSize??V7,V=!1,H=(y)=>{let x=K.get(y);if(x)clearTimeout(x);K.delete(y)},U=(y)=>{K.delete(y);let{activeRunIds:x}=X.registry.disconnect(y);X.onDisconnect(y,x)},F=(y,x)=>{let C={type:"cli_status",connected:!0,runtime:X.runtime,mcpReady:X.mcpReady(),error:x,capabilities:X.capabilities??[],cliVersion:X.cliVersion,browserRuntime:X.browserRuntimeStatus?.()};if(y){let M=Z.get(y);if(M)o0(M,C);return}for(let M of Z.values())o0(M,C)},w=(y,x)=>{let C=x.sessionId.trim(),M=x.userId.trim();if(!C||!M){o0(y,{type:"cli_status",connected:!1,runtime:X.runtime,mcpReady:X.mcpReady(),error:"Missing frontend session or user id"}),y.close();return}H(C);let h=Z.get(C);if(h&&h!==y)h.close();y.data.frontendSessionId=C,Z.set(C,y),X.registry.register({frontendSessionId:C,userId:M,tools:x.tools,send:(g)=>o0(y,g)}),F(C),X.onToolMetadata?.(C)},B=(y,x)=>{let C=X.registry.getUserId(y);if(!C)return;switch(x.type){case"bridge_ping":{let M=Z.get(y);if(M)o0(M,{type:"bridge_pong"});break}case"tool_metadata":X.registry.setMetadata(y,x.tools),X.onToolMetadata?.(y);break;case"tool_result":X.registry.handleToolResult(y,x);break;case"run_turn":E("bridge.run_received",{runId:x.run.runId,cardId:x.run.cardId,frontendSessionId:y}),X.registry.markRunActive(y,x.run.runId,x.run.cardId),X.onRunTurn(y,{...x.run,frontendSessionId:y,userId:C});break;case"cancel_run":if(X.registry.ownsRun(y,x.runId))X.onCancelRun(y,x.runId);break;case"runtime_rpc":X.onRuntimeRpc(y,x);break;case"browser_rpc":X.onBrowserRpc?.(y,Z.get(y)?.data.frontendOrigin??"",x);break;case"warmup_run":X.onWarmupRun(y,{...x,frontendSessionId:y},C);break;default:break}},b=(y,x)=>{let C=b2(y.headers.origin),M=_X(C),h={Vary:"Origin"};if(M&&C)h["Access-Control-Allow-Origin"]=C,h["Access-Control-Allow-Private-Network"]="true";if(y.method==="OPTIONS"){x.writeHead(204,{...h,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),x.end();return}if(y.method!=="GET"){x.writeHead(405,h),x.end();return}x.writeHead(200,{...h,"content-type":"application/json","cache-control":"no-store"}),x.end(JSON.stringify({ideawave:!0,runtime:X.runtime,mcpReady:X.mcpReady(),capabilities:X.capabilities??[],cliVersion:X.cliVersion,browserRuntime:X.browserRuntimeStatus?.()}))},v=(y,x)=>{let C=b2(y.headers.origin),M=_X(C),h={Vary:"Origin"};if(M&&C)h["Access-Control-Allow-Origin"]=C,h["Access-Control-Allow-Private-Network"]="true";if(y.method==="OPTIONS"){x.writeHead(204,{...h,"Access-Control-Allow-Methods":"POST, OPTIONS","Access-Control-Allow-Headers":"content-type","Access-Control-Max-Age":"600"}),x.end();return}if(!M){x.writeHead(403,h),x.end();return}if(y.method!=="POST"){x.writeHead(405,h),x.end();return}let g={...h,"content-type":"application/json"},N=(D,R)=>{x.writeHead(D,g),x.end(JSON.stringify(R))},G="",u=!1;y.on("data",(D)=>{if(G+=D.toString("utf8"),G.length>H7)u=!0,y.destroy()}),y.on("end",()=>{if(u){N(400,{ok:!1,error:"Request body too large"});return}let D;try{D=JSON.parse(G)}catch{N(400,{ok:!1,error:"Invalid JSON body"});return}let R=typeof D.url==="string"?D.url:"";if(!G4(R)){N(400,{ok:!1,error:"url must be an http(s) loopback or /static_boards/ page URL"});return}let O=($,A)=>{let r=typeof $==="number"?$:Number.NaN;if(!Number.isFinite(r))return A;return Math.min(4000,Math.max(200,Math.round(r)))};E4({url:R,width:O(D.width,1440),height:O(D.height,900)}).then(($)=>N(200,{ok:!0,path:$.path,engine:$.engine})).catch(($)=>{let A=$ instanceof b1?503:$ instanceof x2?429:500;N(A,{ok:!1,...$ instanceof b1?{installing:!0}:{},error:$ instanceof Error?$.message:String($)})})})};for(let y of W){let x=K7((h,g)=>{(async()=>{let N=new URL(h.url??"/","http://127.0.0.1").pathname;if(N===g4){b(h,g);return}if(N===j7){v(h,g);return}if(await X.onHttpRequest?.(h,g))return;g.writeHead(404,{"content-type":"text/plain"}),g.end("IdeaWave CLI bridge")})().catch((N)=>{if(g.headersSent){g.destroy(N instanceof Error?N:void 0);return}g.writeHead(500,{"content-type":"text/plain"}),g.end("IdeaWave CLI bridge request failed")})}),C=new J7({noServer:!0,maxPayload:J}),M=(h)=>{if(h.idleTimer)clearTimeout(h.idleTimer);h.idleTimer=setTimeout(()=>{h.close()},Y7),h.idleTimer.unref?.()};C.on("connection",(h,g)=>{let N=h;N.data={id:Q7(),frontendSessionId:null,frontendOrigin:new URL(b2(g.headers.origin)??S4).origin},N.idleTimer=null,M(N),N.on("ping",()=>M(N)),N.on("pong",()=>M(N)),N.on("error",()=>{if(N.idleTimer)clearTimeout(N.idleTimer);N.close()}),N.on("message",(G)=>{M(N);let u=P7(G);if(J>0&&u.length>J)return;let D=M1(u);if(!D)return;let R=N.data.frontendSessionId;if(!R){if(D.type==="bridge_probe")o0(N,{type:"bridge_probe_ack",protocolVersion:D.protocolVersion});else if(D.type==="frontend_hello")w(N,D);return}B(R,D)}),N.on("close",()=>{if(N.idleTimer)clearTimeout(N.idleTimer);let G=N.data.frontendSessionId;if(!G)return;if(Z.get(G)!==N)return;if(Z.delete(G),H(G),V)return;K.set(G,setTimeout(()=>U(G),z7))})}),x.on("upgrade",(h,g,N)=>{let G=new URL(h.url??"/","http://127.0.0.1").pathname;if(X.onHttpUpgrade?.(h,g,N))return;if(G!==GX){k4(g,404,"Not Found");return}if(!_X(b2(h.headers.origin))){k4(g,403,"Forbidden");return}C.handleUpgrade(h,g,N,(u)=>{C.emit("connection",u,h)})});try{let h=await x7(x,y);return{url:`ws://127.0.0.1:${h}${GX}`,port:h,sendStatus:F,close:async()=>{V=!0;for(let g of K.values())clearTimeout(g);K.clear();for(let g of C.clients){let N=g;if(N.idleTimer)clearTimeout(N.idleTimer);N.close()}C.close(),await u4(x).catch(()=>{return})}}}catch(h){if(C.close(),await u4(x).catch(()=>{return}),h?.code==="EADDRINUSE")continue;throw h}}throw Error(`No free IdeaWave CLI bridge port found in ${W[0]}-${W.at(-1)}`)}import{lstat as E7,readFile as _7}from"node:fs/promises";import k7 from"node:os";import y1 from"node:path";import{Server as u7}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as I7,ListToolsRequestSchema as S7}from"@modelcontextprotocol/sdk/types.js";var kX=new Set(["list_boards","get_board","screenshot_board","list_nodes","list_edges","inspect_node","list_context_sources","read_context_card","read_context_file","read_context_image","list_context_folder","get_board_wiki","search_board","get_card_messages","list_agent_cards","inspect_neighbors"]),b7=["screenshot_board","inspect_diagram","ask_user_question","create_agent_card","append_user_message","spawn_child_agents"],v7=new Set(b7),QY=new Set([...kX].filter((X)=>!v7.has(X)));import{randomUUID as f7}from"node:crypto";import{createServer as O7}from"node:http";import{StreamableHTTPServerTransport as R7}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as i4}from"@modelcontextprotocol/sdk/types.js";var T4=new Set(["127.0.0.1","localhost","[::1]","::1"]);function y7(X){let W=X.trim();if(W.length===0)return null;if(W.startsWith("[")){let V=W.indexOf("]");if(V===-1)return null;let H=W.slice(0,V+1),U=W.slice(V+1);if(U.length===0)return{host:H,port:null};if(!U.startsWith(":"))return null;let F=Number(U.slice(1));if(!Number.isInteger(F)||F<=0||F>65535)return null;return{host:H,port:F}}let Z=W.lastIndexOf(":");if(Z===-1)return{host:W,port:null};let K=W.slice(Z+1),J=Number(K);if(!Number.isInteger(J)||J<=0||J>65535)return{host:W,port:null};return{host:W.slice(0,Z),port:J}}function c4(X){return T4.has(X)||T4.has(X.toLowerCase())}function a4(X,W){let Z=X.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let K=y7(Z);if(!K)return{ok:!1,status:403,reason:"bad-host"};if(!c4(K.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(K.port!==null&&K.port!==W)return{ok:!1,status:403,reason:"host-port-mismatch"};let J=X.headers.origin;if(typeof J==="string"&&J.length>0){if(J!=="null"){let V;try{V=new URL(J)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!c4(V.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var d4="/mcp",C7=43274,r4=16777216,h7=1800000,N7=300000,p4=200,M7=-32700,N0=-32600,uX=-32603;function Y0(X,W,Z,K,J){X.statusCode=W,X.setHeader("content-type","application/json"),X.end(JSON.stringify({jsonrpc:"2.0",error:{code:Z,message:K,...J?{data:J}:{}},id:null}))}class IX extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class SX extends Error{constructor(){super(`body exceeds ${r4} bytes`);this.name="BodyTooLargeError"}}async function g7(X){if(X.method&&X.method!=="POST")return;let W=X.headers["content-type"];if(typeof W==="string"&&W.trim().length>0){if(!W.toLowerCase().includes("application/json"))throw new IX}let Z=0,K=[];for await(let V of X){let H=typeof V==="string"?Buffer.from(V):V;if(Z+=H.byteLength,Z>r4)throw new SX;K.push(H)}if(K.length===0)return;let J=Buffer.concat(K).toString("utf8");if(J.length===0)return;return JSON.parse(J)}function D7(X){if(Array.isArray(X))return X.some(i4);return i4(X)}function m7(X){if(typeof X==="number")return X;let W=process.env.IDEAWAVE_MCP_PORT;if(W&&W.trim().length>0){let Z=Number(W);if(Number.isInteger(Z)&&Z>=0&&Z<65536)return Z}return C7}async function $7(X,W){let Z=(J)=>new Promise((V,H)=>{let U=(w)=>{X.off("listening",F),H(w)},F=()=>{X.off("error",U),V()};X.once("error",U),X.once("listening",F),X.listen(J,"127.0.0.1")});try{await Z(W)}catch(J){if(J.code!=="EADDRINUSE"||W===0)throw J;console.warn(`[mcp] port ${W} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await Z(0)}let K=X.address();if(K==null||typeof K==="string")throw Error("[mcp] failed to read bound address");return K.port}function G7(X,W){if(W&&typeof W==="object"&&!Array.isArray(W)){let K=W.params;if(K&&typeof K==="object"&&!Array.isArray(K)){let J=K.clientInfo;if(J&&typeof J==="object"&&!Array.isArray(J)){let V=J.name;if(typeof V==="string"&&V.trim().length>0)return V.trim()}}}let Z=X.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function s4(X){let W=new Map,Z=0;function K(w){let B=W.get(w);if(B)B.lastActivity=Date.now()}async function J(w,B){W.delete(w),await B.transport.close().catch(()=>{return})}async function V(){let w=null,B=1/0;for(let[b,v]of W)if(v.lastActivity<B)B=v.lastActivity,w=b;if(w!==null){let b=W.get(w);if(b)console.warn(`[mcp] session cap of ${p4} reached; evicting ${w}`),await J(w,b)}}let H=setInterval(()=>{let w=Date.now()-h7;for(let[B,b]of W)if(b.lastActivity<w)console.log(`[mcp] sweeping idle session ${B}`),J(B,b)},N7);H.unref?.();let U=O7((w,B)=>{(async()=>{let b;try{b=new URL(w.url??"/","http://127.0.0.1").pathname}catch{Y0(B,400,N0,"bad-url");return}if(b!==d4){Y0(B,404,N0,"not-found");return}let v=w.method??"POST";if(v!=="POST"&&v!=="GET"&&v!=="DELETE"){B.setHeader("Allow","GET, POST, DELETE"),Y0(B,405,N0,"method-not-allowed");return}let y=a4(w,Z);if(!y.ok){Y0(B,y.status,N0,"forbidden",{reason:y.reason});return}let x=w.headers["mcp-session-id"],C=typeof x==="string"?x:void 0;if(v==="GET"||v==="DELETE"){if(!C||!W.has(C)){Y0(B,400,N0,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let g=W.get(C).transport;K(C);try{await g.handleRequest(w,B)}catch(N){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",N),!B.headersSent)Y0(B,500,uX,"internal")}return}let M;try{M=await g7(w)}catch(g){if(g instanceof IX){Y0(B,415,N0,"expected-application-json");return}if(g instanceof SX){Y0(B,413,N0,"body-too-large");return}Y0(B,400,M7,"invalid-json");return}let h;if(C&&W.has(C))h=W.get(C).transport,K(C);else if(!C&&M!==void 0&&D7(M)){let g=w.headers["x-ideawave-user-id"],N=typeof g==="string"&&g.trim().length>0?g.trim():null,G=w.headers["x-ideawave-frontend-session-id"],u=typeof G==="string"&&G.trim().length>0?G.trim():null,D=w.headers["x-ideawave-tool-surface"],R=typeof D==="string"&&D.trim()==="read"?"read":"full",O=w.headers["x-ideawave-images-supported"],$=typeof O==="string"&&O.trim()==="1",A=w.headers["x-ideawave-card-id"],r=typeof A==="string"&&A.trim().length>0?A.trim():null,b0=w.headers["x-ideawave-board-id"],k=typeof b0==="string"&&b0.trim().length>0?b0.trim():null,d=w.headers["x-ideawave-run-folder"],T=typeof d==="string"&&d.trim().length>0?d.trim():null,W0=G7(w,M);if(W.size>=p4)await V();let s=null,w0=new R7({sessionIdGenerator:()=>f7(),onsessioninitialized:(S0)=>{s=S0,W.set(S0,{transport:w0,lastActivity:Date.now()})},onsessionclosed:(S0)=>{W.delete(S0)}});w0.onclose=()=>{if(w0.sessionId)W.delete(w0.sessionId)};try{await X.buildServer({userId:N,frontendSessionId:u,boardId:k,toolSurface:R,imagesSupported:$,cardId:r,runFolder:T,clientHint:W0}).connect(w0)}catch(S0){if(console.error("[mcp] buildServer/connect failed",S0),s)W.delete(s);await w0.close().catch(()=>{return}),Y0(B,500,uX,"server-init-failed");return}h=w0}else{Y0(B,400,N0,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await h.handleRequest(w,B,M)}catch(g){if(console.error("[mcp] transport.handleRequest threw",g),!B.headersSent)Y0(B,500,uX,"internal")}})().catch((b)=>{console.error("[mcp] unhandled request handler error:",b)})});return Z=await $7(U,m7(X.port)),{url:`http://127.0.0.1:${Z}${d4}`,port:Z,close:async()=>{clearInterval(H);for(let w of W.values())await w.transport.close().catch(()=>{return});W.clear(),await new Promise((w)=>U.close(()=>w()))}}}var l7={name:"ideawave-board",version:"1.0.0"},v2="list_run_folder",y2="read_run_folder_file",t4=new Set([...kX,v2,y2]),e4=new Set(["inspect_diagram"]),A7=[{name:v2,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:y2,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 lX(X){return{content:[{type:"text",text:X}]}}function T7(X){return lX(JSON.stringify(X,null,2))}function o4(X){return{...lX(X),isError:!0}}async function c7(X,W){if(!W||X.isError)return X;let Z=X.content.find((V)=>V.type==="text");if(!Z)return X;let K;try{let V=JSON.parse(Z.text);if(typeof V.path!=="string")return X;K=y1.resolve(V.path)}catch{return X}let J=y1.resolve(y1.join(k7.tmpdir(),"ideawave-screenshots"));if(y1.dirname(K)!==J||!/^board-[a-z0-9-]+\.png$/i.test(y1.basename(K)))return X;try{if(!(await E7(K)).isFile())return X;let H=await _7(K);if(H.byteLength<1024||H.byteLength>26214400||!H.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return X;return{...X,content:[...X.content,{type:"image",data:H.toString("base64"),mimeType:"image/png"}]}}catch{return X}}function a7(X,W,Z="full",K=!1){return X.getMetadata(W).filter((J)=>{let V=H2(J.name);if(Z==="read"&&!t4.has(V))return!1;if(!K&&e4.has(V))return!1;return!0}).map((J)=>({name:J.name,description:J.description,inputSchema:J.inputSchema}))}function i7(X,W,Z={}){let K=a7(X,W,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...K,...A7]:K}function n4(X,W){if(!X||typeof X!=="object"||Array.isArray(X))return null;let Z=X[W];return typeof Z==="string"?Z:null}async function d7(X,W,Z){if(Z&&Z.trim().length>0)return Z.trim();if(!X||!W)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await C0({boardId:X,cardId:W})).runFolder}async function p7(X){let W=await d7(X.boardId,X.cardId,X.runFolder);if(X.name===v2){let Z=n4(X.args,"path")??"",K=await r3(W,Z);return T7(K)}if(X.name===y2){let Z=n4(X.args,"path");if(!Z)return o4("read_run_folder_file requires a path.");return lX(await j2(W,Z))}return o4(`Unknown local tool "${X.name}"`)}function r7(X,W,Z,K,J,V="full",H=!1){let U=new u7(l7,{capabilities:{tools:{}}}),F=async()=>{if(H)return!0;if(q4(K))return!0;if(Z&&K)try{return(await C0({boardId:Z,cardId:K})).adapter.supportsImages===!0}catch{return!1}return!1};return U.setRequestHandler(S7,async()=>({tools:i7(X,W,{includeRunFolderTools:Boolean(J||Z&&K),toolSurface:V,imagesSupported:await F()})})),U.setRequestHandler(I7,async(w)=>{let{name:B,arguments:b}=w.params,v=H2(B),y=Date.now();E("mcp.tool_call_received",{frontendSessionId:W,cardId:K,toolName:v});try{if(v===v2||v===y2)return await p7({name:v,args:b,boardId:Z,cardId:K,runFolder:J});if(V==="read"&&!t4.has(v))throw Error(`Tool "${B}" is not available in read-only mode`);if(e4.has(v)&&!await F())throw Error(`Tool "${B}" requires a runtime that supports image input`);let x=await X.callTool(W,v,b??{},void 0,K??void 0);if(E("mcp.tool_result_returned",{frontendSessionId:W,cardId:K,toolName:v,elapsedMs:Date.now()-y}),x&&typeof x==="object"&&Array.isArray(x.content)){let C=x;return v==="screenshot_board"?await c7(C,await F()):C}return{content:[{type:"text",text:typeof x==="string"?x:JSON.stringify(x)}]}}catch(x){return E("mcp.tool_result_returned",{frontendSessionId:W,cardId:K,toolName:v,elapsedMs:Date.now()-y,hasError:!0}),{content:[{type:"text",text:x instanceof Error?x.message:"Tool call failed"}],isError:!0}}}),U}function X8(X,W){return s4({buildServer:(Z)=>r7(X,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:W})}import f2 from"node:fs/promises";import AX from"node:os";import O2 from"node:path";function W8(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function s7(){let[X,W]=await Promise.all([K0(),k6()]),Z=X.globalDefaultConfigId?X.runtimes.find((K)=>K.id===X.globalDefaultConfigId)??null:null;return{runtimes:X.runtimes,globalDefaultConfigId:X.globalDefaultConfigId,globalDefaultEffective:Z?{runFolder:Z.runFolder??AX.homedir(),modelId:Z.defaultModelId??null,configValues:Z.defaultConfigValues??{}}:null,knownAdapters:T0().map((K)=>({id:K.id,displayName:K.displayName})),readiness:W}}async function o7(X){try{let W=await C0({boardId:X.boardId,cardId:X.cardId});return{resolved:{configId:W.entry.id,adapterId:W.entry.kind==="registered"?W.entry.adapterId:null,displayName:W.entry.displayName,runFolder:W.runFolder,modelId:W.modelId,configValues:W.configValues}}}catch(W){if(W instanceof D0)return{resolved:null};throw W}}async function n7(X){return z0((W)=>{let Z=W.runtimes.find((V)=>V.kind==="registered"&&V.adapterId===X.adapterId);if(Z)return Z;let K=T0().find((V)=>V.id===X.adapterId);if(!K)throw Error(`Unknown adapterId: ${X.adapterId}`);let J={id:W8(),kind:"registered",adapterId:X.adapterId,displayName:K.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return W.runtimes.push(J),J})}async function t7(X){return z0((W)=>{let Z={id:W8(),kind:"custom",displayName:X.displayName,command:X.command,args:X.args,env:X.env,runFolder:X.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return W.runtimes.push(Z),Z})}async function e7(X){await z0((W)=>{if(W.runtimes=W.runtimes.filter((Z)=>Z.id!==X.runtimeConfigId),W.globalDefaultConfigId===X.runtimeConfigId)W.globalDefaultConfigId=null;for(let Z of Object.keys(W.boardOverrides))if(W.boardOverrides[Z].runtimeConfigId===X.runtimeConfigId)delete W.boardOverrides[Z];for(let Z of Object.keys(W.cardOverrides))if(W.cardOverrides[Z].runtimeConfigId===X.runtimeConfigId)delete W.cardOverrides[Z]})}async function XQ(X){await z0((W)=>{let Z=W.runtimes.find((K)=>K.id===X.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);if(W.globalDefaultConfigId=X.runtimeConfigId,X.runFolder!==void 0)Z.runFolder=X.runFolder;if(X.modelId!==void 0)Z.defaultModelId=X.modelId;if(X.configValues!==void 0)Z.defaultConfigValues=X.configValues})}async function WQ(X){X.boardId,await z0((W)=>{if(X.runtimeConfigId===null){delete W.cardOverrides[X.cardId];return}if(!W.runtimes.some((J)=>J.id===X.runtimeConfigId))throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let K=W.cardOverrides[X.cardId];W.cardOverrides[X.cardId]={runtimeConfigId:X.runtimeConfigId,runFolder:X.runFolder!==void 0?X.runFolder:K?.runFolder??null,modelId:X.modelId!==void 0?X.modelId:K?.modelId??null,configValues:X.configValues!==void 0?X.configValues:K?.configValues??{}}})}async function ZQ(X){let Z=(await K0()).runtimes.find((H)=>H.id===X.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let K=F0(Z),J=await K.resolveSpawnConfig(Z),V=Z.runFolder??AX.homedir();try{let H=await H4({spawn:{...J,cwd:V},modelId:X.modelId??Z.defaultModelId??null,configValues:X.configValues??Z.defaultConfigValues??{}}),U=Y2({adapterId:K.id,models:H.models,currentModelId:H.currentModelId}),F=new Date().toISOString();return await z0((w)=>{let B=w.runtimes.find((b)=>b.id===X.runtimeConfigId);if(B)B.discoveredModels=U,B.discoveredConfigOptions=H.configOptions,B.discoveredAt=F}),{ok:!0,models:U,configOptions:H.configOptions,currentModelId:H.currentModelId}}catch(H){if(H instanceof l0)throw Error(`${H.message}${K.authHint?` ${K.authHint}`:""}`);if(H instanceof I||H instanceof U0)throw Error(H.message);throw H}}async function QQ(X){let W=AX.homedir(),Z=X.path?.trim()?X.path.trim():W,K=O2.resolve(Z),J=!0;try{if(!(await f2.stat(K)).isDirectory())K=O2.dirname(K)}catch{J=!1,K=W}let V=[];try{V=(await f2.readdir(K,{withFileTypes:!0})).filter((F)=>F.isDirectory()&&!F.name.startsWith(".")).map((F)=>({name:F.name,path:O2.join(K,F.name)})).sort((F,w)=>F.name.localeCompare(w.name))}catch{V=[]}let H=O2.dirname(K);return{path:K,parent:H===K?null:H,home:W,exists:J,entries:V}}var Z8={list:s7,getEffectiveForCard:o7,registerRegistered:n7,registerCustom:t7,unregister:e7,setUserDefault:XQ,setCardOverride:WQ,refreshModels:ZQ,browseFolder:QQ};var KQ=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function JQ(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function Q8(){try{let X=await K0();if(X.globalDefaultConfigId){if(X.runtimes.some((Z)=>Z.id===X.globalDefaultConfigId))return X.globalDefaultConfigId}for(let W of KQ){if((await u6(W.id))?.status!=="ready")continue;let K=null;if(await z0((J)=>{if(J.globalDefaultConfigId){if(J.runtimes.some((U)=>U.id===J.globalDefaultConfigId)){K=J.globalDefaultConfigId;return}}let V=J.runtimes.find((H)=>H.kind==="registered"&&H.adapterId===W.id);if(!V){let H={id:JQ(),kind:"registered",adapterId:W.id,displayName:W.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};J.runtimes.push(H),V=H}J.globalDefaultConfigId=V.id,K=V.id}),K)return console.log(`[ideawave-cli] using agent runtime: ${W.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(X){return console.warn("[ideawave-cli] runtime auto-seed failed",X),null}}var VQ=120000;function YQ(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class TX{sessions=new Map;createCallId;toolCallTimeoutMs;constructor(X={}){this.createCallId=X.createCallId??YQ,this.toolCallTimeoutMs=X.toolCallTimeoutMs??VQ}register(X){let W=this.sessions.get(X.frontendSessionId);if(W){if(W.userId!==X.userId)this.rejectPending(W,"frontend session user changed"),W.activeRunIds.clear();this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:W.pendingToolCalls,activeRunIds:W.activeRunIds,activeRunCardIds:W.activeRunCardIds});return}this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect(X,W="frontend session disconnected"){let Z=this.sessions.get(X);if(!Z)return{activeRunIds:[]};return this.sessions.delete(X),this.rejectPending(Z,W),{activeRunIds:Array.from(Z.activeRunIds)}}sessionCount(){return this.sessions.size}has(X){return this.sessions.has(X)}getUserId(X){return this.sessions.get(X)?.userId??null}setMetadata(X,W){let Z=this.sessions.get(X);if(Z)Z.tools=W}getMetadata(X){if(!X)return[];return this.sessions.get(X)?.tools??[]}sendToSession(X,W){let Z=this.sessions.get(X);if(!Z)return!1;return Z.send(W),!0}callTool(X,W,Z,K,J){if(!X)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let V=this.sessions.get(X);if(!V)return Promise.reject(Error(`Frontend session ${X} is not connected`));let H=this.createCallId();return new Promise((U,F)=>{let w=K??(J?this.getActiveRunIdForCard(V,J):this.getSoleActiveRunId(V)),B=J??(w?V.activeRunCardIds.get(w):void 0),b=Date.now(),v=setTimeout(()=>{V.pendingToolCalls.delete(H),E("tool_queue.timeout",{frontendSessionId:X,runId:w,cardId:B,callId:H,toolName:W,elapsedMs:Date.now()-b,queueDepth:V.pendingToolCalls.size}),F(Error(`Tool "${W}" timed out waiting for the frontend`))},this.toolCallTimeoutMs);V.pendingToolCalls.set(H,{resolve:U,reject:F,timer:v,name:W,runId:w??null,cardId:B??null,startedAt:b}),E("tool_queue.forwarded_to_browser",{frontendSessionId:X,runId:w,cardId:B,callId:H,toolName:W,queueDepth:V.pendingToolCalls.size}),V.send({type:"tool_call",callId:H,name:W,args:Z,...w?{runId:w}:{},...B?{cardId:B}:{}})})}handleToolResult(X,W){let Z=this.sessions.get(X);if(!Z)return;let K=Z.pendingToolCalls.get(W.callId);if(!K)return;if(Z.pendingToolCalls.delete(W.callId),clearTimeout(K.timer),E("tool_queue.result_received",{frontendSessionId:X,runId:K.runId,cardId:K.cardId,callId:W.callId,toolName:K.name,elapsedMs:Date.now()-K.startedAt,queueDepth:Z.pendingToolCalls.size,ok:W.ok}),W.ok){K.resolve(W.result);return}let J=W.result;if(J&&typeof J==="object"&&Array.isArray(J.content)){K.resolve({...J,isError:!0});return}K.reject(Error(W.error??"Tool execution failed"))}markRunActive(X,W,Z){let K=this.sessions.get(X);if(!K)return;if(K.activeRunIds.add(W),Z)K.activeRunCardIds.set(W,Z)}markRunSettled(X,W){let Z=this.sessions.get(X);if(!Z)return;Z.activeRunIds.delete(W),Z.activeRunCardIds.delete(W)}ownsRun(X,W){return this.sessions.get(X)?.activeRunIds.has(W)??!1}rejectPending(X,W){for(let Z of X.pendingToolCalls.values())clearTimeout(Z.timer),E("tool_queue.rejected",{frontendSessionId:X.frontendSessionId,runId:Z.runId,cardId:Z.cardId,toolName:Z.name,elapsedMs:Date.now()-Z.startedAt}),Z.reject(Error(W));X.pendingToolCalls.clear()}getSoleActiveRunId(X){return X.activeRunIds.size===1?X.activeRunIds.values().next().value:void 0}getActiveRunIdForCard(X,W){let Z=[...X.activeRunCardIds.entries()].filter(([K,J])=>X.activeRunIds.has(K)&&J===W).map(([K])=>K);return Z.length===1?Z[0]:void 0}}function J8(){return"0.0.83".trim()?"0.0.83":"dev"}var zQ=process.argv.slice(2),aX=_4(zQ,process.env);if(aX.allowRailwayPrPreviews)process.env[v1]="1";var g0=aX.cliArgs[0],{browserKitEnabled:O1,captureEngineEnabled:jQ}=aX;if(g0==="--help"||g0==="-h"||g0==="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(g0==="--version"||g0==="-v"||g0==="version")console.log(J8()),process.exit(0);if(g0)console.error(`Unknown command: ${g0}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var R1=new TX,I0=null,HQ=O1?{phase:"ready",message:"Local browser-kit proxy is ready"}:{phase:"idle"},n0=new V2;function M0(X,W){R1.sendToSession(X,W)}async function wQ(X,W){try{let Z=Z8[W.method],K=await Z(W.params);M0(X,{type:"runtime_rpc_result",requestId:W.requestId,ok:!0,result:K})}catch(Z){M0(X,{type:"runtime_rpc_result",requestId:W.requestId,ok:!1,error:Z instanceof Error?Z.message:String(Z)})}}var C1=!1,f1=null;async function cX(){if(C1)return;if(f1)return f1;return f1=(async()=>{try{let X=await X8(R1);tX({...X,requestedPort:X.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${X.url}`);try{await P6({onStatusChange:(W)=>{if(I6(),I0?.sendStatus(),W.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${W.packageName}: ${W.error??"unknown error"}`)}})}catch(W){console.warn("[ideawave-cli] ACP bridge setup skipped:",W instanceof Error?W.message:String(W))}await Q8(),C1=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),I0?.sendStatus()}catch(X){console.error("[ideawave-cli] failed to start agent host:",X),I0?.sendStatus(void 0,X instanceof Error?X.message:String(X))}finally{f1=null}})(),f1}if(process.env.APP_ENV!=="development"){let X=await l4();if(X)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${X}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}if(jQ)C4().then((X)=>{if(X.phase==="ready")console.log("[ideawave-cli] screenshot engine ready");else if(X.phase==="failed")console.warn(`[ideawave-cli] screenshot engine setup failed: ${X.error??"unknown error"}`)});I0=await A4({registry:R1,runtime:null,mcpReady:()=>C1,capabilities:O1?[eX,X6,W6]:[],cliVersion:J8(),browserRuntimeStatus:()=>HQ,onToolMetadata:(X)=>{console.log(`[ideawave-cli] session ${X} advertised ${R1.getMetadata(X).length} tools`),cX()},onRunTurn:(X,W)=>{console.log(`[ideawave-cli] running agent turn for card ${W.cardId} (session ${X})`),(async()=>{if(await cX(),!C1){M0(X,{type:"run_settled",runId:W.runId,cardId:W.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await b4(W,(Z)=>M0(X,Z))})().catch(()=>{return}).finally(()=>R1.markRunSettled(X,W.runId))},onCancelRun:(X,W)=>{CX(W)},onRuntimeRpc:(X,W)=>{wQ(X,W)},onBrowserRpc:(X,W,Z)=>{if(!O1){M0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!1,error:"The development browser-kit proxy is not enabled"});return}n0.handleRpc(X,W,Z).then((K)=>{M0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!0,result:K})},(K)=>{M0(X,{type:"browser_rpc_result",requestId:Z.requestId,ok:!1,error:K instanceof Error?K.message:String(K)})})},onHttpRequest:(X,W)=>O1?n0.handleHttpRequest(X,W):!1,onHttpUpgrade:(X,W,Z)=>O1?n0.handleUpgrade(X,W,Z):!1,onWarmupRun:(X,W,Z)=>{(async()=>{if(await cX(),!C1)return{status:"retryable",error:"agent host is not ready"};return v4({cardId:W.cardId,boardId:W.boardId,userId:Z,frontendSessionId:X})})().then((K)=>{if(!W.warmupId)return;M0(X,{type:"warmup_result",warmupId:W.warmupId,cardId:W.cardId,...K})})},onDisconnect:(X,W)=>{n0.closeFrontendSession(X),B4(X);for(let Z of W)CX(Z);E("bridge.frontend_disconnected",{frontendSessionId:X,activeRuns:W.length}),pX(X).catch((Z)=>{console.warn(`[ideawave-cli] failed to evict sessions for ${X}:`,Z instanceof Error?Z.message:String(Z))}),console.log(`[ideawave-cli] browser session ${X} disconnected`)}});n0.setPort(I0.port);console.log(`[ideawave-cli] browser bridge listening on ${I0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var K8=!1;for(let X of["SIGINT","SIGTERM"])process.once(X,()=>{if(K8)return;K8=!0,L4(),(async()=>{await n0.close(),await M4(),await I0?.close().catch(()=>{return}),process.exit(0)})()});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideawave",
3
- "version": "0.0.81",
3
+ "version": "0.0.83",
4
4
  "description": "IdeaWave CLI",
5
5
  "type": "module",
6
6
  "bin": {