ideawave 0.0.98 → 0.0.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +3 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1140,8 +1140,8 @@ ${J}`:null].filter(Boolean).join(`
|
|
|
1140
1140
|
|
|
1141
1141
|
${Z}`)}function aX(X){if(!Array.isArray(X))return null;let Z=X.flatMap((W)=>{if(!W||typeof W!=="object")return[];let Q=W;if(typeof Q.path!=="string"||!Q.path.trim())return[];let J=typeof Q.line==="number"?`:${Q.line}`:"";return[`${Q.path}${J}`]});return Z.length>0?Z.slice(0,5):null}function _4(X){let{ctx:Z,appendText:W,appendToolActivity:Q}=X,J=X.flushIntervalMs??xW,z="",H="",F=0,L=null,U=!1,w={},b=new Map,C=(P)=>{if(b.set(P.toolCallId,P),!Q)return;Q({boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId,entry:P}).catch((O)=>{console.warn("[streamAdapter] appendToolActivity failed",O)})},M=(P)=>{let O=`${Z.runId}:thought`,f=b.get(O);if(!f||f.status!=="running")return;C({...f,status:"completed",completedAt:f.completedAt??P})},G=(P)=>{for(let O of b.values()){if(O.status!=="running"||O.rawTitle.toLowerCase()!=="toolsearch")continue;C({...O,status:"completed",completedAt:O.completedAt??P})}},g=(P)=>{for(let O of Array.from(b.values())){if(O.status!=="running")continue;if(O.kind==="thought"||O.rawTitle==="agent_thought")continue;C({...O,status:"completed",completedAt:O.completedAt??P})}},N="",R=0,v=null,h=null,m=(P)=>{if(P===N)return;N=P,R=Date.now(),W({boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId,text:P}).catch((O)=>{console.warn("[streamAdapter] appendText failed",O)})},$=()=>{if(v!==null)clearTimeout(v),v=null;if(h!==null){let P=h;h=null,m(P)}},k=(P)=>{let O=Date.now()-R;if(O>=J&&v===null){m(P);return}if(h=P,v===null){let f=Math.max(0,J-O);v=setTimeout(()=>{v=null,$()},f)}};return{onSessionUpdate:async(P)=>{X.onAnyUpdate?.();let O=P.update;switch(w[O.sessionUpdate]=(w[O.sessionUpdate]??0)+1,O.sessionUpdate){case"agent_message_chunk":{let f=new Date().toISOString();if(M(f),O.content.type==="text"){if(O.content.text.length>0){if(U&&z.length>0&&!/\s$/.test(z)&&!/^\s/.test(O.content.text))z+=`
|
|
1142
1142
|
|
|
1143
|
-
`;z+=O.content.text,U=!1,k(z)}}else{let S=`agent_message_chunk:${O.content.type}`;w[S]=(w[S]??0)+1}return}case"agent_thought_chunk":{if(O.content.type!=="text")return;H+=O.content.text;let f=new Date().toISOString(),S=`${Z.runId}:thought`,T=b.get(S);C({toolCallId:S,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:T?.startedAt??f,completedAt:null,contentPreview:u0(H.trim())});return}case"user_message_chunk":return;case"tool_call":{F+=1,U=z.length>0;let f=g4(O.title),S=uX(O.status),T=new Date().toISOString();M(T),G(T),C({toolCallId:O.toolCallId,rawTitle:f,title:cX(f,O.rawInput),kind:lX(O.kind),status:S,startedAt:T,completedAt:S==="running"?null:T,inputPreview:y0(O.rawInput),outputPreview:dX(O.rawOutput),contentPreview:N2(O.content),locations:aX(O.locations)});return}case"tool_call_update":{let f=b.get(O.toolCallId);if(!f){let W0=g4(O.title),d=uX(O.status),m0=new Date().toISOString();C({toolCallId:O.toolCallId,rawTitle:W0,title:cX(W0,O.rawInput),kind:lX(O.kind),status:d,startedAt:m0,completedAt:d==="running"?null:m0,inputPreview:y0(O.rawInput),outputPreview:dX(O.rawOutput),contentPreview:N2(O.content),locations:aX(O.locations)});return}let S=O.status===void 0||O.status===null?f.status:uX(O.status),T=typeof O.title==="string"&&O.title.trim().length>0?O.title:f.rawTitle,o=typeof O.title==="string"&&O.title.trim().length>0,D=S==="running"?f.completedAt:f.completedAt??new Date().toISOString(),l=O.content===void 0?f.contentPreview:m4(f.contentPreview,N2(O.content)),u=O.rawOutput===void 0?f.outputPreview:m4(f.outputPreview,dX(O.rawOutput));C({...f,rawTitle:T,title:o?cX(T,O.rawInput):f.title,kind:O.kind===void 0?f.kind:lX(O.kind),status:S,completedAt:D,inputPreview:O.rawInput===void 0?f.inputPreview:y0(O.rawInput),outputPreview:u,contentPreview:l,locations:O.locations===void 0?f.locations:aX(O.locations)});return}case"plan":L=O.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>z,getToolCallCount:()=>F,getLatestPlan:()=>L,getUpdateTypeCounts:()=>({...w}),flush:(P)=>{let O=new Date().toISOString();if(M(O),P?.completeOpenToolCalls)g(O);$()}}}var RW=new Set(["ECONNRESET","EPIPE"]);function $2(X){if(!X||typeof X!=="object")return!1;if(X instanceof Error&&X.message==="ACP connection closed")return!0;let Z="code"in X?X.code:void 0;return typeof Z==="string"&&RW.has(Z)}var E1=1,k4=-32000;function S4(X){if(X.awaitingInput)return!1;return X.nowMs-X.lastUpdateMs>=X.windowMs}function T4(X){if(!X||typeof X!=="object")return!1;return X.code===k4}var fW=300000,hW=fW,MW=5000;function NW(X){let Z=Math.max(1,Math.round(X/1000));return`Runtime has not responded for ${Z} ${Z===1?"second":"seconds"}. Retry the agent run.`}function u4(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.98".trim()?"0.0.98":"dev"}}function l4(X){if(X===E1)return;throw new I(`Unsupported ACP protocol version ${X}; expected ${E1}`)}function c4(X){return CW.toWeb(X)}function d4(X){return yW.toWeb(X)}function iX(X){return X!==null&&typeof X==="object"}function DW(X){if(!Array.isArray(X))return[];let Z=[];for(let W of X){if(!iX(W))continue;if(typeof W.group==="string"&&Array.isArray(W.options)){let Q=typeof W.name==="string"?W.name:W.group;for(let J of W.options){if(!iX(J))continue;if(typeof J.value!=="string"||typeof J.name!=="string")continue;Z.push({value:J.value,name:J.name,description:typeof J.description==="string"?J.description:null,group:W.group,groupName:Q})}continue}if(typeof W.value!=="string"||typeof W.name!=="string")continue;Z.push({value:W.value,name:W.name,description:typeof W.description==="string"?W.description:null,group:null,groupName:null})}return Z}function $W(X){if(!iX(X))return null;if(typeof X.id!=="string"||typeof X.name!=="string")return null;let Z=typeof X.category==="string"?X.category:null,W=typeof X.description==="string"?X.description:null;if(X.type==="select"){let Q=typeof X.currentValue==="string"?X.currentValue:null;return{id:X.id,name:X.name,category:Z,description:W,type:"select",currentValue:Q,options:DW(X.options)}}if(X.type==="boolean"){let Q=typeof X.currentValue==="boolean"?X.currentValue:typeof X.value==="boolean"?X.value:null;return{id:X.id,name:X.name,category:Z,description:W,type:"boolean",currentValue:Q,options:[]}}return null}function pX(X){let Z=(X.configOptions??[]).map($W).filter((F)=>F!==null),W=Z.find((F)=>F.type==="select"&&F.category==="model")??Z.find((F)=>F.type==="select"&&F.id==="model")??null,Q=W?.options.map((F)=>({id:F.value,name:F.name,description:F.description??null})),J=GW(X.models),z=Q&&Q.length>0?Q:J&&J.length>0?J:null,H=(typeof W?.currentValue==="string"?W.currentValue:null)??gW(X.models)??null;return{models:z,currentModelId:H,configOptions:Z,modelConfigId:W?.id??null}}function GW(X){if(!X||!Array.isArray(X.availableModels))return null;let Z=[];for(let W of X.availableModels){if(typeof W.modelId!=="string")continue;Z.push({id:W.modelId,name:typeof W.name==="string"?W.name:null,description:typeof W.description==="string"?W.description:null})}return Z.length>0?Z:null}function gW(X){return typeof X?.currentModelId==="string"?X.currentModelId:null}function EW(X,Z){let W=[];if(X.trim())W.push({type:"text",text:X});for(let Q of Z)if(Q.content.trim())W.push({type:"text",text:Q.content});return W}var mW=500;function a4(X){return new Promise((Z)=>{let W=setTimeout(()=>Z({code:null,signal:null,stderr:""}),mW);X.then((Q)=>{clearTimeout(W),Z(Q)})})}function _W(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 kW(X,Z){let W=pX({configOptions:Z.configOptions});return{models:W.models??X.models,currentModelId:W.currentModelId??X.currentModelId,configOptions:W.configOptions,modelConfigId:W.modelConfigId??X.modelConfigId}}function i4(X,Z){if(X==="default")return null;if(!Z||Z.length===0)return X;let W=Z.find((U)=>U.id===X);if(W)return W.id;let Q=X.toLowerCase(),J=Q.includes("opus")?"opus":Q.includes("sonnet")?"sonnet":Q.includes("haiku")?"haiku":null;if(!J)return X;let z=(U)=>`${U.id} ${U.name??""} ${U.description??""}`.toLowerCase(),H=Z.filter((U)=>z(U).includes(J));if(H.length===0)return X;let L=(Q.includes("1m")?H.find((U)=>z(U).includes("1m")):void 0)??H[0];return L?L.id:X}async function G2(X){try{let Z=await X.conn.setSessionConfigOption(_W({sessionId:X.sessionId,configId:X.configId,value:X.value}));return kW(X.metadata,Z)}catch(Z){return console.warn(`[acp] setSessionConfigOption(${X.label}) failed; using agent default.`,Z instanceof Error?Z.message:Z),X.metadata}}async function g2(X){let Z=AX(X.spawn),W=[],Q=0,J=4096;Z.stderr.on("data",(D)=>{W.push(D),Q+=D.length;while(Q>J*2&&W.length>1){let l=W.shift();if(l)Q-=l.length}});let z=()=>{let D=Buffer.concat(W).toString("utf8");return D.length>J?D.slice(-J):D},H=G4(X.spawn.cwd),F={current:null},L={current:null},U={at:Date.now()},w=null,b=d4(Z.stdin),C=c4(Z.stdout),M=A4(b,C),g=new I4((D)=>({requestPermission:async(l)=>{let u=l.options,W0=u?.find((d)=>d.kind==="allow_once")??u?.find((d)=>d.kind==="allow_always");if(W0)return{outcome:{outcome:"selected",optionId:W0.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(l)=>{U.at=Date.now();let u=L.current;if(u){let d=l.update.sessionUpdate;if(u.updateCount+=1,u.updateCount===1||u.lastUpdateType!==d||d==="tool_call"||d==="tool_call_update")_("acp.session_update",{runId:u.runId,cardId:u.cardId,sessionId:w,updateType:d,updateCount:u.updateCount,elapsedMs:Date.now()-u.startedAt});u.lastUpdateType=d}let W0=F.current;if(W0)await W0.onSessionUpdate(l)},readTextFile:H.readTextFile}),M),N=()=>Z.kill();if(X.signal)X.signal.addEventListener("abort",N);let R=()=>{if(X.signal)X.signal.removeEventListener("abort",N)},v=async(D,l)=>{if(R(),Z.kill(),T4(D))throw new s0(D.message??"Authentication required",l);if($2(D)){if(X.signal?.aborted)throw new I("ACP session cancelled: abort signal received");let u=await a4(Z.waitForExit);throw new I(`Runtime process exited before completion: ${u.stderr?.trim()??""}`)}throw D},h;try{h=await g.initialize({protocolVersion:E1,clientCapabilities:IX,clientInfo:u4()})}catch(D){throw await v(D,[]),Error("unreachable")}try{l4(h.protocolVersion)}catch(D){throw R(),Z.kill(),D}let m=h.authMethods?.map((D)=>D.id)??[],$;try{$=await g.newSession({cwd:X.spawn.cwd,mcpServers:X.mcpServers??[],...X.isolateAmbientToolSources?{_meta:{claudeCode:{options:{settingSources:[]}}}}:{}})}catch(D){throw await v(D,m),Error("unreachable")}let k=$.sessionId;w=k;let P=pX($),O=X.modelId??null,f=O?i4(O,P.models):null;if(f&&f!==P.currentModelId)if(P.modelConfigId)P=await G2({conn:g,sessionId:k,configId:P.modelConfigId,value:f,metadata:P,label:`${P.modelConfigId}=${f}`});else console.warn(`[acp] runtime did not advertise a model config option for ${f}; using agent default.`);for(let[D,l]of Object.entries(X.configValues??{}).sort(([u],[W0])=>u.localeCompare(W0))){if(D===P.modelConfigId)continue;if(!P.configOptions.some((u)=>u.id===D))continue;P=await G2({conn:g,sessionId:k,configId:D,value:l,metadata:P,label:`${D}=${String(l)}`})}R();let S=!1,T=async()=>{if(S)return;S=!0,Z.kill(),await Promise.race([Z.waitForExit,new Promise((D)=>setTimeout(D,2000))])},o=!1;return Z.processCrashed.then(()=>{o=!0}),{sessionId:k,availableModels:P.models,currentModelId:P.currentModelId,availableConfigOptions:P.configOptions,isAlive:()=>!S&&!o,dispose:T,prompt:(D)=>SW({proc:Z,conn:g,sessionId:k,activeAdapter:F,activeTrace:L,lastUpdate:U,collectStderrTail:z},D)}}async function SW(X,Z){let{proc:W,conn:Q,sessionId:J,activeAdapter:z,activeTrace:H,lastUpdate:F}=X,L=Date.now(),U=Z.heartbeatMs??hW,w=NW(U),b={boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId},C=_4({ctx:b,appendText:Z.appendText,appendToolActivity:Z.appendToolActivity,onAnyUpdate:Z.onAnyUpdate});z.current=C,H.current={runId:Z.runId,cardId:Z.cardId,startedAt:L,updateCount:0,lastUpdateType:null},F.at=Date.now(),_("acp.prompt_started",{runId:Z.runId,cardId:Z.cardId,sessionId:J,heartbeatWindowMs:U});let M=!1,G=null,g=()=>W.kill();Z.signal.addEventListener("abort",g);try{let N=async()=>{let m=Math.min(MW,Math.max(50,Math.floor(U/2)));G=setInterval(()=>{let k=Z.isAwaitingInput?.()??!1;if(k){F.at=Date.now();return}if(S4({nowMs:Date.now(),lastUpdateMs:F.at,windowMs:U,awaitingInput:k}))M=!0,_("acp.inactivity_timeout",{runId:Z.runId,cardId:Z.cardId,sessionId:J,windowMs:U,silentForMs:Date.now()-F.at}),Q.cancel({sessionId:J}).catch(()=>{return}),W.kill()},m);let $=EW(Z.prompt.systemPrompt,Z.prompt.messages);await Q.prompt({sessionId:J,prompt:$}),_("acp.prompt_resolved",{runId:Z.runId,cardId:Z.cardId,sessionId:J,elapsedMs:Date.now()-L}),C.flush({completeOpenToolCalls:!0})},R=W.waitForExit.then((m)=>({kind:"exited",exit:m})),v=N().then(()=>({kind:"ok"})).catch(async(m)=>{if($2(m))return W.kill(),{kind:"crashed",exit:await a4(W.waitForExit)};throw m}),h;try{h=await Promise.race([v,W.processCrashed.then((m)=>({kind:"crashed",exit:m})),R])}catch(m){if(M)throw new w0(w);throw m}if(M)throw new w0(w);if(h.kind!=="ok"&&Z.signal.aborted)throw new I("ACP session cancelled: abort signal received");if(h.kind==="crashed")throw new I(`Runtime process exited before completion: ${h.exit.stderr.trim()}`);if(h.kind==="exited"){if(M)throw new w0(w);throw new I(`Runtime process exited unexpectedly: ${h.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:C.getFinalText(),toolCallsExecuted:C.getToolCallCount(),stderrTail:X.collectStderrTail(),updateTypeCounts:C.getUpdateTypeCounts()}}finally{if(_("acp.prompt_finished",{runId:Z.runId,cardId:Z.cardId,sessionId:J,elapsedMs:Date.now()-L,timedOut:M,updateCount:H.current?.updateCount??0}),G!==null)clearInterval(G);Z.signal.removeEventListener("abort",g),C.flush({completeOpenToolCalls:!0}),z.current=null,H.current=null}}var IW=30000;async function p4(X){let Z=AX(X.spawn),W=d4(Z.stdin),Q=c4(Z.stdout),J=A4(W,Q),H=new I4((U)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),J),F=()=>Z.kill();if(X.signal)X.signal.addEventListener("abort",F);let L=null;try{let U=(async()=>{let b=await H.initialize({protocolVersion:E1,clientCapabilities:IX,clientInfo:u4()});l4(b.protocolVersion);let C=b.authMethods?.map((h)=>h.id)??[],M;try{M=await H.newSession({cwd:X.spawn.cwd,mcpServers:[]})}catch(h){if(T4(h))throw new s0(h.message??"Authentication required",C);throw h}let G=pX(M),g=X.modelId??null,N=g?i4(g,G.models):null;if(N&&N!==G.currentModelId)if(G.modelConfigId)G=await G2({conn:H,sessionId:M.sessionId,configId:G.modelConfigId,value:N,metadata:G,label:`${G.modelConfigId}=${N}`});else console.warn(`[acp] runtime did not advertise a model config option for ${N}; discovering agent default models.`);for(let[h,m]of Object.entries(X.configValues??{}).sort(([$],[k])=>$.localeCompare(k))){if(h===G.modelConfigId)continue;if(!G.configOptions.some(($)=>$.id===h))continue;G=await G2({conn:H,sessionId:M.sessionId,configId:h,value:m,metadata:G,label:`${h}=${String(m)}`})}let R=G.models??[],v=G.currentModelId;return H.cancel({sessionId:M.sessionId}).catch(()=>{return}),{models:R,configOptions:G.configOptions,currentModelId:v}})(),w=new Promise((b,C)=>{L=setTimeout(()=>{C(new w0)},IW)});return await Promise.race([U,w])}catch(U){if($2(U)){if(X.signal?.aborted)throw new I("ACP model discovery cancelled: abort signal received");throw new I("Runtime process exited during model discovery.")}throw U}finally{if(L)clearTimeout(L);if(X.signal)X.signal.removeEventListener("abort",F);Z.kill()}}import AW from"node:fs/promises";import E2 from"node:os";async function r4(X){let Z={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},W;try{W=await AW.readFile(X,"utf-8")}catch(Q){if(Q.code==="ENOENT")return structuredClone(Z);throw Q}return r1.parse(JSON.parse(W))}function rX(X,Z,W){return{...X.defaultConfigValues??{},...Z?.configValues??{},...W?.configValues??{}}}async function D0(X){let Z=X.configPath?await r4(X.configPath):await j0(),W=X.cardId?Z.cardOverrides[X.cardId]:void 0;if(W?.runtimeConfigId){let J=Z.runtimes.find((z)=>z.id===W.runtimeConfigId);if(J)return{entry:J,adapter:q0(J),runFolder:W.runFolder??J.runFolder??E2.homedir(),modelId:W.modelId??J.defaultModelId??null,configValues:rX(J,void 0,W)}}let Q=Z.boardOverrides[X.boardId];if(Q?.runtimeConfigId){let J=Z.runtimes.find((z)=>z.id===Q.runtimeConfigId);if(J)return{entry:J,adapter:q0(J),runFolder:Q.runFolder??J.runFolder??E2.homedir(),modelId:Q.modelId??J.defaultModelId??null,configValues:rX(J,Q)}}if(Z.globalDefaultConfigId){let J=Z.runtimes.find((z)=>z.id===Z.globalDefaultConfigId);if(J)return{entry:J,adapter:q0(J),runFolder:W?.runFolder??Q?.runFolder??J.runFolder??E2.homedir(),modelId:W?.modelId??Q?.modelId??J.defaultModelId??null,configValues:rX(J,Q,W)}}throw new v0}async function sX(X,Z={}){let Q=(Z.configPath?await r4(Z.configPath):await j0()).runtimes.find((J)=>J.id===X);if(!Q)return null;return{entry:Q,adapter:q0(Q),runFolder:Q.runFolder??E2.homedir(),modelId:Z.modelId??Q.defaultModelId??null,configValues:{...Q.defaultConfigValues??{},...Z.configValues??{}}}}var oX=new Map;function nX(X,Z){oX.set(X,Z)}function tX(X){oX.delete(X)}function s4(X){if(!X)return null;return oX.get(X)??null}import{lstat as YQ,readFile as JQ}from"node:fs/promises";import zQ from"node:os";import _1 from"node:path";import{Server as VQ}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as jQ,ListToolsRequestSchema as HQ}from"@modelcontextprotocol/sdk/types.js";import{z as a}from"zod";var z0={maxSteps:12,maxParticipants:4,maxChannels:2,maxHandoffsPerChannel:12,maxTotalDispatches:24},m1=["ideate_create_note","ideate_create_code","ideate_create_shape","ideate_create_browser","ideate_create_image_context_card","ideate_add_browser_note","ideate_add_board_callout","ideate_create_diagram","ideate_create_edge","ideate_update_note","ideate_update_code","ideate_update_shape","ideate_update_diagram","ideate_update_edge","ideate_delete_node","ideate_delete_edge"],TW=`
|
|
1144
|
-
<!-- ideawave:mutation-tool=`,uW=" -->",uV=new RegExp(`${TW.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(?<tool>${m1.join("|")})${uW.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}$`);var l0=a.string().trim().min(1).max(80),o4=a.string().trim().min(1).max(240).regex(/^(node|edge|diagram|browser|browser-annotation|comment|spatial-group|create):/),n4={type:"string",minLength:1,maxLength:240,pattern:"^(node|edge|diagram|browser|browser-annotation|comment|spatial-group|create):",description:"Exact lease key. A new artifact uses create:<runId>:<clientKey>, where clientKey exactly matches this step. An existing artifact uses its frozen UUID-backed node:, edge:, browser:, or diagram: key. External-only research declares no invented resource key."},lV={type:"object",description:`A bounded acyclic Ideate plan with at most ${z0.maxSteps} total steps. Each new visible artifact gets one step and one exact create lease.`,properties:{summary:{type:"string",minLength:1,maxLength:1500},semanticAnchorId:{type:"string",minLength:1,maxLength:160},participants:{type:"array",maxItems:z0.maxParticipants,items:{type:"object",properties:{clientKey:{type:"string",minLength:1,maxLength:80},label:{type:"string",minLength:1,maxLength:40},responsibility:{type:"string",minLength:1,maxLength:1000}},required:["clientKey","label","responsibility"],additionalProperties:!1}},collaborationChannels:{type:"array",maxItems:z0.maxChannels,items:{type:"object",properties:{clientKey:{type:"string",minLength:1,maxLength:80},protocol:{type:"string",enum:["handoff","turn-taking","request-response","barrier"]},participantKeys:{type:"array",minItems:2,maxItems:4,items:{type:"string",minLength:1,maxLength:80}},resourceScope:{type:"array",maxItems:40,items:n4},maxHandoffs:{type:"integer",minimum:1,maximum:z0.maxHandoffsPerChannel},maxDurationMs:{type:"integer",minimum:1000,maximum:1800000},completion:{type:"string",enum:["all-done","accepted","coordinator-decides"]}},required:["clientKey","protocol","participantKeys","resourceScope","maxHandoffs","maxDurationMs","completion"],additionalProperties:!1}},steps:{type:"array",minItems:1,maxItems:z0.maxSteps,description:`HARD LIMIT: 1-${z0.maxSteps} total steps. Count plan.steps before submitting. If a draft is larger, combine related work and retry the same plan tool immediately; never silently truncate required outcomes.`,items:{type:"object",properties:{clientKey:{type:"string",minLength:1,maxLength:80,description:"Stable step key. For a create step, this exact value is the final segment of its create lease and the worker create call clientKey."},participantKey:{type:"string",minLength:1,maxLength:80},channelKeys:{type:"array",maxItems:2,items:{type:"string",minLength:1,maxLength:80}},label:{type:"string",minLength:1,maxLength:80},kind:{type:"string",enum:["read","browser","write","synthesis"]},prompt:{type:"string",minLength:1,maxLength:4000},mutationTool:{type:"string",enum:m1,description:"Required exactly once for each fresh write step. This is the one fenced mutation capability its worker receives."},dependsOn:{type:"array",maxItems:z0.maxSteps,items:{type:"string",minLength:1,maxLength:80}},resources:{type:"array",maxItems:40,items:{type:"object",properties:{key:n4,mode:{type:"string",enum:["read","write"]}},required:["key","mode"],additionalProperties:!1}}},required:["clientKey","label","kind","prompt","dependsOn","resources"],additionalProperties:!1}}},required:["summary","steps"],additionalProperties:!1};var cV=a.object({summary:a.string().trim().min(1).max(1500),semanticAnchorId:a.string().trim().min(1).max(160).optional(),participants:a.array(a.object({clientKey:l0,label:a.string().trim().min(1).max(40),responsibility:a.string().trim().min(1).max(1000)}).strict()).max(z0.maxParticipants).optional(),collaborationChannels:a.array(a.object({clientKey:l0,protocol:a.enum(["handoff","turn-taking","request-response","barrier"]),participantKeys:a.array(l0).min(2).max(4),resourceScope:a.array(o4).max(40),maxHandoffs:a.number().int().min(1).max(z0.maxHandoffsPerChannel),maxDurationMs:a.number().int().min(1000).max(1800000),completion:a.enum(["all-done","accepted","coordinator-decides"])}).strict()).max(z0.maxChannels).optional(),steps:a.array(a.object({clientKey:l0,participantKey:l0.optional(),channelKeys:a.array(l0).max(2).optional(),label:a.string().trim().min(1).max(80),kind:a.enum(["read","browser","write","synthesis"]),prompt:a.string().trim().min(1).max(4000),mutationTool:a.enum(m1).optional(),dependsOn:a.array(l0).max(z0.maxSteps),resources:a.array(a.object({key:o4,mode:a.enum(["read","write"])}).strict()).max(40)}).strict()).min(1).max(z0.maxSteps,{error:`Plan exceeds the hard ${z0.maxSteps}-step limit. Combine related work into ${z0.maxSteps} or fewer steps and retry the same plan tool immediately; do not drop required outcomes.`})}).strict();var t4=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"]),lW=["screenshot_board","inspect_diagram","ask_user_question","create_agent_card","append_user_message","spawn_child_agents"],cW=new Set(lW),iV=new Set([...t4].filter((X)=>!cW.has(X)));var eX={coordinator:["inspect_ideate_context","get_ideate_run_status","screenshot_ideate_context","submit_ideate_plan","revise_ideate_plan","ask_ideate_question","complete_ideate_run","start_board_walkthrough"],worker:["inspect_ideate_context","get_ideate_run_status","get_ideate_worker_context","screenshot_ideate_context","get_board","list_nodes","list_edges","inspect_node","inspect_board_region","inspect_diagram","list_context_sources","read_context_card","read_context_file","read_context_image","list_context_folder","get_board_wiki","search_board","inspect_neighbors","read_diagram_guide","inspect_browser","list_browser_images","locate_browser_element","list_agent_cards","get_card_messages","inspect_table","get_table_schema","read_table","query_table","export_table_csv","start_board_walkthrough",...m1]},e4=new Set(eX.coordinator),m2=new Set(eX.worker);var pV=eX.worker.filter((X)=>X.startsWith("ideate_"));var dW=new Set([...e4,...m2,"set_ideate_placement"].filter((X)=>X.startsWith("ideate_")||X.includes("ideate_")));function X8(X,Z,W){if(Z==="full")return!dW.has(X);if(Z==="read")return t4.has(X);if(Z==="ideate-coordinator")return e4.has(X);return m2.has(X)&&(!W||W.includes(X))}import{randomUUID as iW}from"node:crypto";import{createServer as pW}from"node:http";import{StreamableHTTPServerTransport as rW}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as Y8}from"@modelcontextprotocol/sdk/types.js";var Z8=new Set(["127.0.0.1","localhost","[::1]","::1"]);function aW(X){let Z=X.trim();if(Z.length===0)return null;if(Z.startsWith("[")){let z=Z.indexOf("]");if(z===-1)return null;let H=Z.slice(0,z+1),F=Z.slice(z+1);if(F.length===0)return{host:H,port:null};if(!F.startsWith(":"))return null;let L=Number(F.slice(1));if(!Number.isInteger(L)||L<=0||L>65535)return null;return{host:H,port:L}}let W=Z.lastIndexOf(":");if(W===-1)return{host:Z,port:null};let Q=Z.slice(W+1),J=Number(Q);if(!Number.isInteger(J)||J<=0||J>65535)return{host:Z,port:null};return{host:Z.slice(0,W),port:J}}function W8(X){return Z8.has(X)||Z8.has(X.toLowerCase())}function Q8(X,Z){let W=X.headers.host;if(typeof W!=="string")return{ok:!1,status:403,reason:"missing-host"};let Q=aW(W);if(!Q)return{ok:!1,status:403,reason:"bad-host"};if(!W8(Q.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(Q.port!==null&&Q.port!==Z)return{ok:!1,status:403,reason:"host-port-mismatch"};let J=X.headers.origin;if(typeof J==="string"&&J.length>0){if(J!=="null"){let z;try{z=new URL(J)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!W8(z.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var J8="/mcp",sW=43274,V8=16777216,oW=1800000,nW=300000,z8=200,tW=-32700,$0=-32600,X3=-32603;function U0(X,Z,W,Q,J){X.statusCode=Z,X.setHeader("content-type","application/json"),X.end(JSON.stringify({jsonrpc:"2.0",error:{code:W,message:Q,...J?{data:J}:{}},id:null}))}class Z3 extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class W3 extends Error{constructor(){super(`body exceeds ${V8} bytes`);this.name="BodyTooLargeError"}}async function eW(X){if(X.method&&X.method!=="POST")return;let Z=X.headers["content-type"];if(typeof Z==="string"&&Z.trim().length>0){if(!Z.toLowerCase().includes("application/json"))throw new Z3}let W=0,Q=[];for await(let z of X){let H=typeof z==="string"?Buffer.from(z):z;if(W+=H.byteLength,W>V8)throw new W3;Q.push(H)}if(Q.length===0)return;let J=Buffer.concat(Q).toString("utf8");if(J.length===0)return;return JSON.parse(J)}function XQ(X){if(Array.isArray(X))return X.some(Y8);return Y8(X)}function ZQ(X){if(typeof X==="number")return X;let Z=process.env.IDEAWAVE_MCP_PORT;if(Z&&Z.trim().length>0){let W=Number(Z);if(Number.isInteger(W)&&W>=0&&W<65536)return W}return sW}async function WQ(X,Z){let W=(J)=>new Promise((z,H)=>{let F=(U)=>{X.off("listening",L),H(U)},L=()=>{X.off("error",F),z()};X.once("error",F),X.once("listening",L),X.listen(J,"127.0.0.1")});try{await W(Z)}catch(J){if(J.code!=="EADDRINUSE"||Z===0)throw J;console.warn(`[mcp] port ${Z} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await W(0)}let Q=X.address();if(Q==null||typeof Q==="string")throw Error("[mcp] failed to read bound address");return Q.port}function QQ(X,Z){if(Z&&typeof Z==="object"&&!Array.isArray(Z)){let Q=Z.params;if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let J=Q.clientInfo;if(J&&typeof J==="object"&&!Array.isArray(J)){let z=J.name;if(typeof z==="string"&&z.trim().length>0)return z.trim()}}}let W=X.headers["user-agent"];if(typeof W==="string"&&W.trim().length>0)return W.trim();return null}async function j8(X){let Z=new Map,W=0;function Q(U){let w=Z.get(U);if(w)w.lastActivity=Date.now()}async function J(U,w){Z.delete(U),await w.transport.close().catch(()=>{return})}async function z(){let U=null,w=1/0;for(let[b,C]of Z)if(C.lastActivity<w)w=C.lastActivity,U=b;if(U!==null){let b=Z.get(U);if(b)console.warn(`[mcp] session cap of ${z8} reached; evicting ${U}`),await J(U,b)}}let H=setInterval(()=>{let U=Date.now()-oW;for(let[w,b]of Z)if(b.lastActivity<U)console.log(`[mcp] sweeping idle session ${w}`),J(w,b)},nW);H.unref?.();let F=pW((U,w)=>{(async()=>{let b;try{b=new URL(U.url??"/","http://127.0.0.1").pathname}catch{U0(w,400,$0,"bad-url");return}if(b!==J8){U0(w,404,$0,"not-found");return}let C=U.method??"POST";if(C!=="POST"&&C!=="GET"&&C!=="DELETE"){w.setHeader("Allow","GET, POST, DELETE"),U0(w,405,$0,"method-not-allowed");return}let M=Q8(U,W);if(!M.ok){U0(w,M.status,$0,"forbidden",{reason:M.reason});return}let G=U.headers["mcp-session-id"],g=typeof G==="string"?G:void 0;if(C==="GET"||C==="DELETE"){if(!g||!Z.has(g)){U0(w,400,$0,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let v=Z.get(g).transport;Q(g);try{await v.handleRequest(U,w)}catch(h){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",h),!w.headersSent)U0(w,500,X3,"internal")}return}let N;try{N=await eW(U)}catch(v){if(v instanceof Z3){U0(w,415,$0,"expected-application-json");return}if(v instanceof W3){U0(w,413,$0,"body-too-large");return}U0(w,400,tW,"invalid-json");return}let R;if(g&&Z.has(g))R=Z.get(g).transport,Q(g);else if(!g&&N!==void 0&&XQ(N)){let v=U.headers["x-ideawave-user-id"],h=typeof v==="string"&&v.trim().length>0?v.trim():null,m=U.headers["x-ideawave-frontend-session-id"],$=typeof m==="string"&&m.trim().length>0?m.trim():null,k=U.headers["x-ideawave-tool-surface"],P=typeof k==="string"?k.trim():"full",O=P==="read"||P==="ideate-coordinator"||P==="ideate-worker"?P:"full",f=U.headers["x-ideawave-images-supported"],S=typeof f==="string"&&f.trim()==="1",T=U.headers["x-ideawave-card-id"],o=typeof T==="string"&&T.trim().length>0?T.trim():null,D=U.headers["x-ideawave-execution-kind"],l=U.headers["x-ideawave-execution-id"],u=typeof D==="string"?D.trim():"",W0=typeof l==="string"?l.trim():"",m0=W0&&new Set(["agent-card","ideate-coordinator","ideate-step","ideate-participant","board-insight","board-auto-title"]).has(u)?{kind:u,id:W0}:null,p2=U.headers["x-ideawave-ideate-claims"],r2=null;if(typeof p2==="string"&&p2.length>0)try{r2=JSON.parse(p2)}catch{r2=null}let s2=U.headers["x-ideawave-board-id"],z9=typeof s2==="string"&&s2.trim().length>0?s2.trim():null,o2=U.headers["x-ideawave-run-folder"],V9=typeof o2==="string"&&o2.trim().length>0?o2.trim():null,n2=U.headers["x-ideawave-pool-session-id"],j9=typeof n2==="string"&&n2.trim().length>0?n2.trim():null,H9=QQ(U,N);if(Z.size>=z8)await z();let t2=null,_0=new rW({sessionIdGenerator:()=>iW(),onsessioninitialized:(r0)=>{t2=r0,Z.set(r0,{transport:_0,lastActivity:Date.now()})},onsessionclosed:(r0)=>{Z.delete(r0)}});_0.onclose=()=>{if(_0.sessionId)Z.delete(_0.sessionId)};try{await X.buildServer({userId:h,frontendSessionId:$,boardId:z9,toolSurface:O,imagesSupported:S,cardId:o,executionTarget:m0,ideateClaims:r2,runFolder:V9,poolSessionId:j9,clientHint:H9}).connect(_0)}catch(r0){if(console.error("[mcp] buildServer/connect failed",r0),t2)Z.delete(t2);await _0.close().catch(()=>{return}),U0(w,500,X3,"server-init-failed");return}R=_0}else{U0(w,400,$0,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await R.handleRequest(U,w,N)}catch(v){if(console.error("[mcp] transport.handleRequest threw",v),!w.headersSent)U0(w,500,X3,"internal")}})().catch((b)=>{console.error("[mcp] unhandled request handler error:",b)})});return W=await WQ(F,ZQ(X.port)),{url:`http://127.0.0.1:${W}${J8}`,port:W,close:async()=>{clearInterval(H);for(let U of Z.values())await U.transport.close().catch(()=>{return});Z.clear(),await new Promise((U)=>F.close(()=>U()))}}}var H8=new Map;function Q3(X,Z){if(!X)return;H8.set(X,Z)}function K8(X){if(!X)return!1;return H8.get(X)??!1}var KQ={name:"ideawave-board",version:"1.0.0"},_2="list_run_folder",k2="read_run_folder_file",L8=new Set(["inspect_diagram"]),k1=new Map;function UQ(X,Z){let W=new Set(X.map(({name:J})=>Y1(J)).filter((J)=>m2.has(J))),Q=new Set(Z.map((J)=>Y1(J)));return W.size===Q.size&&[...W].every((J)=>Q.has(J))}function FQ(X,Z){if(!X)return;let W=k1.get(X);if(!W)return;for(let Q of W.waiters){if(!UQ(Z,Q.expectedWorkerTools))continue;W.waiters.delete(Q),Q.resolve(!0)}}async function B8(X){let Z=k1.get(X.poolSessionId);if(!Z)return!1;let W=X.timeoutMs??750;return new Promise((Q)=>{let J=!1,z=(L)=>{if(J)return;J=!0,clearTimeout(F),Z.waiters.delete(H),Q(L)},H={expectedWorkerTools:X.expectedWorkerTools,resolve:z},F=setTimeout(()=>z(!1),W);F.unref?.(),Z.waiters.add(H),Z.server.sendToolListChanged().catch(()=>z(!1))})}function Y3(X,Z,W){if(X===_2||X===k2)return Z==="full"||Z==="read";return X8(X,Z,W)}var LQ=[{name:_2,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:k2,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 J3(X){return{content:[{type:"text",text:X}]}}function BQ(X){return J3(JSON.stringify(X,null,2))}function U8(X){return{...J3(X),isError:!0}}async function wQ(X,Z){if(!Z||X.isError)return X;let W=X.content.find((z)=>z.type==="text");if(!W)return X;let Q;try{let z=JSON.parse(W.text);if(typeof z.path!=="string")return X;Q=_1.resolve(z.path)}catch{return X}let J=_1.resolve(_1.join(zQ.tmpdir(),"ideawave-screenshots"));if(_1.dirname(Q)!==J||!/^board-[a-z0-9-]+\.png$/i.test(_1.basename(Q)))return X;try{if(!(await YQ(Q)).isFile())return X;let H=await JQ(Q);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 qQ(X,Z,W="full",Q=!1,J){return X.getMetadata(Z).filter((z)=>{let H=Y1(z.name);if(!Y3(H,W,J))return!1;if(!Q&&L8.has(H))return!1;return!0}).map((z)=>({name:z.name,description:z.description,inputSchema:z.inputSchema}))}function PQ(X,Z,W={}){let Q=qQ(X,Z,W.toolSurface??"full",W.imagesSupported??!1,W.workerToolNames);if(!W.includeRunFolderTools)return Q;let J=W.toolSurface??"full",z=LQ.filter((H)=>Y3(H.name,J,W.workerToolNames));return[...Q,...z]}function F8(X,Z){if(!X||typeof X!=="object"||Array.isArray(X))return null;let W=X[Z];return typeof W==="string"?W:null}async function bQ(X,Z,W){if(W&&W.trim().length>0)return W.trim();if(!X||!Z)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await D0({boardId:X,cardId:Z})).runFolder}async function OQ(X){let Z=await bQ(X.boardId,X.cardId,X.runFolder);if(X.name===_2){let W=F8(X.args,"path")??"",Q=await $4(Z,W);return BQ(Q)}if(X.name===k2){let W=F8(X.args,"path");if(!W)return U8("read_run_folder_file requires a path.");return J3(await M2(Z,W))}return U8(`Unknown local tool "${X.name}"`)}function xQ(X,Z,W,Q,J,z="full",H=!1,F=null,L=null,U=null){let w=new VQ(KQ,{capabilities:{tools:{listChanged:!0}}});if(U){let M={server:w,waiters:new Set};k1.set(U,M),w.onclose=()=>{if(k1.get(U)!==M)return;k1.delete(U);for(let G of M.waiters)G.resolve(!1);M.waiters.clear()}}let b=()=>{let M=s4(U);return{cardId:M?.cardId??Q,executionTarget:M?.executionTarget??F,ideateClaims:M?.ideateClaims??L}},C=async()=>{if(H)return!0;let M=b().cardId;if(K8(M))return!0;if(W&&M)try{return(await D0({boardId:W,cardId:M})).adapter.supportsImages===!0}catch{return!1}return!1};return w.setRequestHandler(HQ,async()=>{let M=PQ(X,Z,{includeRunFolderTools:z!=="ideate-coordinator"&&Boolean(J||W&&Q),toolSurface:z,imagesSupported:await C(),workerToolNames:b().ideateClaims?.workerToolNames??null});return FQ(U,M),{tools:M}}),w.setRequestHandler(jQ,async(M)=>{let{name:G,arguments:g}=M.params,N=Y1(G),R=Date.now(),v=b();_("mcp.tool_call_received",{frontendSessionId:Z,cardId:v.cardId,toolName:N});try{if(!Y3(N,z,v.ideateClaims?.workerToolNames))throw Error(`Tool "${G}" is not available on the ${z} surface`);if(N===_2||N===k2)return await OQ({name:N,args:g,boardId:W,cardId:v.cardId,runFolder:J});if(L8.has(N)&&!await C())throw Error(`Tool "${G}" requires a runtime that supports image input`);let h=await X.callTool(Z,N,g??{},v.ideateClaims?.runId,v.cardId??void 0,v.executionTarget??void 0,v.ideateClaims??void 0,z);if(_("mcp.tool_result_returned",{frontendSessionId:Z,cardId:v.cardId,toolName:N,elapsedMs:Date.now()-R}),h&&typeof h==="object"&&Array.isArray(h.content)){let m=h;return N==="screenshot_board"||N==="screenshot_ideate_context"?await wQ(m,await C()):m}return{content:[{type:"text",text:typeof h==="string"?h:JSON.stringify(h)}]}}catch(h){return _("mcp.tool_result_returned",{frontendSessionId:Z,cardId:v.cardId,toolName:N,elapsedMs:Date.now()-R,hasError:!0}),{content:[{type:"text",text:h instanceof Error?h.message:"Tool call failed"}],isError:!0}}}),w}function w8(X,Z){return j8({buildServer:(W)=>xQ(X,W.frontendSessionId,W.boardId,W.cardId,W.runFolder,W.toolSurface,W.imagesSupported,W.executionTarget,W.ideateClaims,W.poolSessionId),port:Z})}var c0=new Map,z3=new Set;function V3(X){c0.get(X)?.controller.abort()}function P8(X){for(let[Z,W]of c0){if(W.frontendSessionId!==X)continue;W.controller.abort(),c0.delete(Z)}}function b8(){for(let X of c0.values())X.controller.abort();c0.clear()}function S1(X,Z){if(Z?.aborted)return!0;return X instanceof Error&&/abort signal received|session cancelled/i.test(X.message)}var q8=200;async function j3(X){try{return await X.open()}catch(Z){if(!(Z instanceof I)||S1(Z,X.signal))throw Z;if(_("cli.session_open_retry",{operation:X.operation,delayMs:q8,errorText:Z.message}),await new Promise((W)=>{setTimeout(W,q8)}),X.signal?.aborted)throw Z;return X.open()}}function H3(X,Z,W,Q){if((!Z.availableModels||Z.availableModels.length===0)&&Z.availableConfigOptions.length===0)return;F0((J)=>{let z=J.runtimes.find((H)=>H.id===X);if(z){if(Z.availableModels&&Z.availableModels.length>0)z.discoveredModels=f2({adapterId:W,models:Z.availableModels,currentModelId:Z.currentModelId??Q});if(Z.availableConfigOptions.length>0)z.discoveredConfigOptions=Z.availableConfigOptions}}).catch(()=>{return})}function vQ(X,Z,W){if(W==="ideate-coordinator"||W==="ideate-worker")return X;return`${X}
|
|
1143
|
+
`;z+=O.content.text,U=!1,k(z)}}else{let S=`agent_message_chunk:${O.content.type}`;w[S]=(w[S]??0)+1}return}case"agent_thought_chunk":{if(O.content.type!=="text")return;H+=O.content.text;let f=new Date().toISOString(),S=`${Z.runId}:thought`,T=b.get(S);C({toolCallId:S,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:T?.startedAt??f,completedAt:null,contentPreview:u0(H.trim())});return}case"user_message_chunk":return;case"tool_call":{F+=1,U=z.length>0;let f=g4(O.title),S=uX(O.status),T=new Date().toISOString();M(T),G(T),C({toolCallId:O.toolCallId,rawTitle:f,title:cX(f,O.rawInput),kind:lX(O.kind),status:S,startedAt:T,completedAt:S==="running"?null:T,inputPreview:y0(O.rawInput),outputPreview:dX(O.rawOutput),contentPreview:N2(O.content),locations:aX(O.locations)});return}case"tool_call_update":{let f=b.get(O.toolCallId);if(!f){let W0=g4(O.title),d=uX(O.status),m0=new Date().toISOString();C({toolCallId:O.toolCallId,rawTitle:W0,title:cX(W0,O.rawInput),kind:lX(O.kind),status:d,startedAt:m0,completedAt:d==="running"?null:m0,inputPreview:y0(O.rawInput),outputPreview:dX(O.rawOutput),contentPreview:N2(O.content),locations:aX(O.locations)});return}let S=O.status===void 0||O.status===null?f.status:uX(O.status),T=typeof O.title==="string"&&O.title.trim().length>0?O.title:f.rawTitle,o=typeof O.title==="string"&&O.title.trim().length>0,D=S==="running"?f.completedAt:f.completedAt??new Date().toISOString(),l=O.content===void 0?f.contentPreview:m4(f.contentPreview,N2(O.content)),u=O.rawOutput===void 0?f.outputPreview:m4(f.outputPreview,dX(O.rawOutput));C({...f,rawTitle:T,title:o?cX(T,O.rawInput):f.title,kind:O.kind===void 0?f.kind:lX(O.kind),status:S,completedAt:D,inputPreview:O.rawInput===void 0?f.inputPreview:y0(O.rawInput),outputPreview:u,contentPreview:l,locations:O.locations===void 0?f.locations:aX(O.locations)});return}case"plan":L=O.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>z,getToolCallCount:()=>F,getLatestPlan:()=>L,getUpdateTypeCounts:()=>({...w}),flush:(P)=>{let O=new Date().toISOString();if(M(O),P?.completeOpenToolCalls)g(O);$()}}}var RW=new Set(["ECONNRESET","EPIPE"]);function $2(X){if(!X||typeof X!=="object")return!1;if(X instanceof Error&&X.message==="ACP connection closed")return!0;let Z="code"in X?X.code:void 0;return typeof Z==="string"&&RW.has(Z)}var E1=1,k4=-32000;function S4(X){if(X.awaitingInput)return!1;return X.nowMs-X.lastUpdateMs>=X.windowMs}function T4(X){if(!X||typeof X!=="object")return!1;return X.code===k4}var fW=300000,hW=fW,MW=5000;function NW(X){let Z=Math.max(1,Math.round(X/1000));return`Runtime has not responded for ${Z} ${Z===1?"second":"seconds"}. Retry the agent run.`}function u4(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.99".trim()?"0.0.99":"dev"}}function l4(X){if(X===E1)return;throw new I(`Unsupported ACP protocol version ${X}; expected ${E1}`)}function c4(X){return CW.toWeb(X)}function d4(X){return yW.toWeb(X)}function iX(X){return X!==null&&typeof X==="object"}function DW(X){if(!Array.isArray(X))return[];let Z=[];for(let W of X){if(!iX(W))continue;if(typeof W.group==="string"&&Array.isArray(W.options)){let Q=typeof W.name==="string"?W.name:W.group;for(let J of W.options){if(!iX(J))continue;if(typeof J.value!=="string"||typeof J.name!=="string")continue;Z.push({value:J.value,name:J.name,description:typeof J.description==="string"?J.description:null,group:W.group,groupName:Q})}continue}if(typeof W.value!=="string"||typeof W.name!=="string")continue;Z.push({value:W.value,name:W.name,description:typeof W.description==="string"?W.description:null,group:null,groupName:null})}return Z}function $W(X){if(!iX(X))return null;if(typeof X.id!=="string"||typeof X.name!=="string")return null;let Z=typeof X.category==="string"?X.category:null,W=typeof X.description==="string"?X.description:null;if(X.type==="select"){let Q=typeof X.currentValue==="string"?X.currentValue:null;return{id:X.id,name:X.name,category:Z,description:W,type:"select",currentValue:Q,options:DW(X.options)}}if(X.type==="boolean"){let Q=typeof X.currentValue==="boolean"?X.currentValue:typeof X.value==="boolean"?X.value:null;return{id:X.id,name:X.name,category:Z,description:W,type:"boolean",currentValue:Q,options:[]}}return null}function pX(X){let Z=(X.configOptions??[]).map($W).filter((F)=>F!==null),W=Z.find((F)=>F.type==="select"&&F.category==="model")??Z.find((F)=>F.type==="select"&&F.id==="model")??null,Q=W?.options.map((F)=>({id:F.value,name:F.name,description:F.description??null})),J=GW(X.models),z=Q&&Q.length>0?Q:J&&J.length>0?J:null,H=(typeof W?.currentValue==="string"?W.currentValue:null)??gW(X.models)??null;return{models:z,currentModelId:H,configOptions:Z,modelConfigId:W?.id??null}}function GW(X){if(!X||!Array.isArray(X.availableModels))return null;let Z=[];for(let W of X.availableModels){if(typeof W.modelId!=="string")continue;Z.push({id:W.modelId,name:typeof W.name==="string"?W.name:null,description:typeof W.description==="string"?W.description:null})}return Z.length>0?Z:null}function gW(X){return typeof X?.currentModelId==="string"?X.currentModelId:null}function EW(X,Z){let W=[];if(X.trim())W.push({type:"text",text:X});for(let Q of Z)if(Q.content.trim())W.push({type:"text",text:Q.content});return W}var mW=500;function a4(X){return new Promise((Z)=>{let W=setTimeout(()=>Z({code:null,signal:null,stderr:""}),mW);X.then((Q)=>{clearTimeout(W),Z(Q)})})}function _W(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 kW(X,Z){let W=pX({configOptions:Z.configOptions});return{models:W.models??X.models,currentModelId:W.currentModelId??X.currentModelId,configOptions:W.configOptions,modelConfigId:W.modelConfigId??X.modelConfigId}}function i4(X,Z){if(X==="default")return null;if(!Z||Z.length===0)return X;let W=Z.find((U)=>U.id===X);if(W)return W.id;let Q=X.toLowerCase(),J=Q.includes("opus")?"opus":Q.includes("sonnet")?"sonnet":Q.includes("haiku")?"haiku":null;if(!J)return X;let z=(U)=>`${U.id} ${U.name??""} ${U.description??""}`.toLowerCase(),H=Z.filter((U)=>z(U).includes(J));if(H.length===0)return X;let L=(Q.includes("1m")?H.find((U)=>z(U).includes("1m")):void 0)??H[0];return L?L.id:X}async function G2(X){try{let Z=await X.conn.setSessionConfigOption(_W({sessionId:X.sessionId,configId:X.configId,value:X.value}));return kW(X.metadata,Z)}catch(Z){return console.warn(`[acp] setSessionConfigOption(${X.label}) failed; using agent default.`,Z instanceof Error?Z.message:Z),X.metadata}}async function g2(X){let Z=AX(X.spawn),W=[],Q=0,J=4096;Z.stderr.on("data",(D)=>{W.push(D),Q+=D.length;while(Q>J*2&&W.length>1){let l=W.shift();if(l)Q-=l.length}});let z=()=>{let D=Buffer.concat(W).toString("utf8");return D.length>J?D.slice(-J):D},H=G4(X.spawn.cwd),F={current:null},L={current:null},U={at:Date.now()},w=null,b=d4(Z.stdin),C=c4(Z.stdout),M=A4(b,C),g=new I4((D)=>({requestPermission:async(l)=>{let u=l.options,W0=u?.find((d)=>d.kind==="allow_once")??u?.find((d)=>d.kind==="allow_always");if(W0)return{outcome:{outcome:"selected",optionId:W0.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(l)=>{U.at=Date.now();let u=L.current;if(u){let d=l.update.sessionUpdate;if(u.updateCount+=1,u.updateCount===1||u.lastUpdateType!==d||d==="tool_call"||d==="tool_call_update")_("acp.session_update",{runId:u.runId,cardId:u.cardId,sessionId:w,updateType:d,updateCount:u.updateCount,elapsedMs:Date.now()-u.startedAt});u.lastUpdateType=d}let W0=F.current;if(W0)await W0.onSessionUpdate(l)},readTextFile:H.readTextFile}),M),N=()=>Z.kill();if(X.signal)X.signal.addEventListener("abort",N);let R=()=>{if(X.signal)X.signal.removeEventListener("abort",N)},v=async(D,l)=>{if(R(),Z.kill(),T4(D))throw new s0(D.message??"Authentication required",l);if($2(D)){if(X.signal?.aborted)throw new I("ACP session cancelled: abort signal received");let u=await a4(Z.waitForExit);throw new I(`Runtime process exited before completion: ${u.stderr?.trim()??""}`)}throw D},h;try{h=await g.initialize({protocolVersion:E1,clientCapabilities:IX,clientInfo:u4()})}catch(D){throw await v(D,[]),Error("unreachable")}try{l4(h.protocolVersion)}catch(D){throw R(),Z.kill(),D}let m=h.authMethods?.map((D)=>D.id)??[],$;try{$=await g.newSession({cwd:X.spawn.cwd,mcpServers:X.mcpServers??[],...X.isolateAmbientToolSources?{_meta:{claudeCode:{options:{settingSources:[]}}}}:{}})}catch(D){throw await v(D,m),Error("unreachable")}let k=$.sessionId;w=k;let P=pX($),O=X.modelId??null,f=O?i4(O,P.models):null;if(f&&f!==P.currentModelId)if(P.modelConfigId)P=await G2({conn:g,sessionId:k,configId:P.modelConfigId,value:f,metadata:P,label:`${P.modelConfigId}=${f}`});else console.warn(`[acp] runtime did not advertise a model config option for ${f}; using agent default.`);for(let[D,l]of Object.entries(X.configValues??{}).sort(([u],[W0])=>u.localeCompare(W0))){if(D===P.modelConfigId)continue;if(!P.configOptions.some((u)=>u.id===D))continue;P=await G2({conn:g,sessionId:k,configId:D,value:l,metadata:P,label:`${D}=${String(l)}`})}R();let S=!1,T=async()=>{if(S)return;S=!0,Z.kill(),await Promise.race([Z.waitForExit,new Promise((D)=>setTimeout(D,2000))])},o=!1;return Z.processCrashed.then(()=>{o=!0}),{sessionId:k,availableModels:P.models,currentModelId:P.currentModelId,availableConfigOptions:P.configOptions,isAlive:()=>!S&&!o,dispose:T,prompt:(D)=>SW({proc:Z,conn:g,sessionId:k,activeAdapter:F,activeTrace:L,lastUpdate:U,collectStderrTail:z},D)}}async function SW(X,Z){let{proc:W,conn:Q,sessionId:J,activeAdapter:z,activeTrace:H,lastUpdate:F}=X,L=Date.now(),U=Z.heartbeatMs??hW,w=NW(U),b={boardId:Z.boardId,cardId:Z.cardId,runId:Z.runId},C=_4({ctx:b,appendText:Z.appendText,appendToolActivity:Z.appendToolActivity,onAnyUpdate:Z.onAnyUpdate});z.current=C,H.current={runId:Z.runId,cardId:Z.cardId,startedAt:L,updateCount:0,lastUpdateType:null},F.at=Date.now(),_("acp.prompt_started",{runId:Z.runId,cardId:Z.cardId,sessionId:J,heartbeatWindowMs:U});let M=!1,G=null,g=()=>W.kill();Z.signal.addEventListener("abort",g);try{let N=async()=>{let m=Math.min(MW,Math.max(50,Math.floor(U/2)));G=setInterval(()=>{let k=Z.isAwaitingInput?.()??!1;if(k){F.at=Date.now();return}if(S4({nowMs:Date.now(),lastUpdateMs:F.at,windowMs:U,awaitingInput:k}))M=!0,_("acp.inactivity_timeout",{runId:Z.runId,cardId:Z.cardId,sessionId:J,windowMs:U,silentForMs:Date.now()-F.at}),Q.cancel({sessionId:J}).catch(()=>{return}),W.kill()},m);let $=EW(Z.prompt.systemPrompt,Z.prompt.messages);await Q.prompt({sessionId:J,prompt:$}),_("acp.prompt_resolved",{runId:Z.runId,cardId:Z.cardId,sessionId:J,elapsedMs:Date.now()-L}),C.flush({completeOpenToolCalls:!0})},R=W.waitForExit.then((m)=>({kind:"exited",exit:m})),v=N().then(()=>({kind:"ok"})).catch(async(m)=>{if($2(m))return W.kill(),{kind:"crashed",exit:await a4(W.waitForExit)};throw m}),h;try{h=await Promise.race([v,W.processCrashed.then((m)=>({kind:"crashed",exit:m})),R])}catch(m){if(M)throw new w0(w);throw m}if(M)throw new w0(w);if(h.kind!=="ok"&&Z.signal.aborted)throw new I("ACP session cancelled: abort signal received");if(h.kind==="crashed")throw new I(`Runtime process exited before completion: ${h.exit.stderr.trim()}`);if(h.kind==="exited"){if(M)throw new w0(w);throw new I(`Runtime process exited unexpectedly: ${h.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:C.getFinalText(),toolCallsExecuted:C.getToolCallCount(),stderrTail:X.collectStderrTail(),updateTypeCounts:C.getUpdateTypeCounts()}}finally{if(_("acp.prompt_finished",{runId:Z.runId,cardId:Z.cardId,sessionId:J,elapsedMs:Date.now()-L,timedOut:M,updateCount:H.current?.updateCount??0}),G!==null)clearInterval(G);Z.signal.removeEventListener("abort",g),C.flush({completeOpenToolCalls:!0}),z.current=null,H.current=null}}var IW=30000;async function p4(X){let Z=AX(X.spawn),W=d4(Z.stdin),Q=c4(Z.stdout),J=A4(W,Q),H=new I4((U)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),J),F=()=>Z.kill();if(X.signal)X.signal.addEventListener("abort",F);let L=null;try{let U=(async()=>{let b=await H.initialize({protocolVersion:E1,clientCapabilities:IX,clientInfo:u4()});l4(b.protocolVersion);let C=b.authMethods?.map((h)=>h.id)??[],M;try{M=await H.newSession({cwd:X.spawn.cwd,mcpServers:[]})}catch(h){if(T4(h))throw new s0(h.message??"Authentication required",C);throw h}let G=pX(M),g=X.modelId??null,N=g?i4(g,G.models):null;if(N&&N!==G.currentModelId)if(G.modelConfigId)G=await G2({conn:H,sessionId:M.sessionId,configId:G.modelConfigId,value:N,metadata:G,label:`${G.modelConfigId}=${N}`});else console.warn(`[acp] runtime did not advertise a model config option for ${N}; discovering agent default models.`);for(let[h,m]of Object.entries(X.configValues??{}).sort(([$],[k])=>$.localeCompare(k))){if(h===G.modelConfigId)continue;if(!G.configOptions.some(($)=>$.id===h))continue;G=await G2({conn:H,sessionId:M.sessionId,configId:h,value:m,metadata:G,label:`${h}=${String(m)}`})}let R=G.models??[],v=G.currentModelId;return H.cancel({sessionId:M.sessionId}).catch(()=>{return}),{models:R,configOptions:G.configOptions,currentModelId:v}})(),w=new Promise((b,C)=>{L=setTimeout(()=>{C(new w0)},IW)});return await Promise.race([U,w])}catch(U){if($2(U)){if(X.signal?.aborted)throw new I("ACP model discovery cancelled: abort signal received");throw new I("Runtime process exited during model discovery.")}throw U}finally{if(L)clearTimeout(L);if(X.signal)X.signal.removeEventListener("abort",F);Z.kill()}}import AW from"node:fs/promises";import E2 from"node:os";async function r4(X){let Z={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},W;try{W=await AW.readFile(X,"utf-8")}catch(Q){if(Q.code==="ENOENT")return structuredClone(Z);throw Q}return r1.parse(JSON.parse(W))}function rX(X,Z,W){return{...X.defaultConfigValues??{},...Z?.configValues??{},...W?.configValues??{}}}async function D0(X){let Z=X.configPath?await r4(X.configPath):await j0(),W=X.cardId?Z.cardOverrides[X.cardId]:void 0;if(W?.runtimeConfigId){let J=Z.runtimes.find((z)=>z.id===W.runtimeConfigId);if(J)return{entry:J,adapter:q0(J),runFolder:W.runFolder??J.runFolder??E2.homedir(),modelId:W.modelId??J.defaultModelId??null,configValues:rX(J,void 0,W)}}let Q=Z.boardOverrides[X.boardId];if(Q?.runtimeConfigId){let J=Z.runtimes.find((z)=>z.id===Q.runtimeConfigId);if(J)return{entry:J,adapter:q0(J),runFolder:Q.runFolder??J.runFolder??E2.homedir(),modelId:Q.modelId??J.defaultModelId??null,configValues:rX(J,Q)}}if(Z.globalDefaultConfigId){let J=Z.runtimes.find((z)=>z.id===Z.globalDefaultConfigId);if(J)return{entry:J,adapter:q0(J),runFolder:W?.runFolder??Q?.runFolder??J.runFolder??E2.homedir(),modelId:W?.modelId??Q?.modelId??J.defaultModelId??null,configValues:rX(J,Q,W)}}throw new v0}async function sX(X,Z={}){let Q=(Z.configPath?await r4(Z.configPath):await j0()).runtimes.find((J)=>J.id===X);if(!Q)return null;return{entry:Q,adapter:q0(Q),runFolder:Q.runFolder??E2.homedir(),modelId:Z.modelId??Q.defaultModelId??null,configValues:{...Q.defaultConfigValues??{},...Z.configValues??{}}}}var oX=new Map;function nX(X,Z){oX.set(X,Z)}function tX(X){oX.delete(X)}function s4(X){if(!X)return null;return oX.get(X)??null}import{lstat as YQ,readFile as JQ}from"node:fs/promises";import zQ from"node:os";import _1 from"node:path";import{Server as VQ}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as jQ,ListToolsRequestSchema as HQ}from"@modelcontextprotocol/sdk/types.js";import{z as a}from"zod";var z0={maxSteps:12,maxParticipants:4,maxChannels:2,maxHandoffsPerChannel:12,maxTotalDispatches:24},m1=["ideate_create_note","ideate_create_code","ideate_create_shape","ideate_create_browser","ideate_create_image_context_card","ideate_add_browser_note","ideate_add_board_callout","ideate_create_diagram","ideate_create_edge","ideate_update_note","ideate_update_code","ideate_update_shape","ideate_update_diagram","ideate_update_edge","ideate_delete_node","ideate_delete_edge"],TW=`
|
|
1144
|
+
<!-- ideawave:mutation-tool=`,uW=" -->",uV=new RegExp(`${TW.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(?<tool>${m1.join("|")})${uW.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}$`);var l0=a.string().trim().min(1).max(80),o4=a.string().trim().min(1).max(240).regex(/^(node|edge|diagram|browser|browser-annotation|comment|spatial-group|create):/),n4={type:"string",minLength:1,maxLength:240,pattern:"^(node|edge|diagram|browser|browser-annotation|comment|spatial-group|create):",description:"Exact lease key. A new artifact uses create:<runId>:<clientKey>, where clientKey exactly matches this step. An existing artifact uses its frozen UUID-backed node:, edge:, browser:, or diagram: key. External-only research declares no invented resource key."},lV={type:"object",description:`A bounded acyclic Ideate plan with at most ${z0.maxSteps} total steps. Each new visible artifact gets one step and one exact create lease.`,properties:{summary:{type:"string",minLength:1,maxLength:1500},semanticAnchorId:{type:"string",minLength:1,maxLength:160},participants:{type:"array",maxItems:z0.maxParticipants,items:{type:"object",properties:{clientKey:{type:"string",minLength:1,maxLength:80},label:{type:"string",minLength:1,maxLength:40},responsibility:{type:"string",minLength:1,maxLength:1000}},required:["clientKey","label","responsibility"],additionalProperties:!1}},collaborationChannels:{type:"array",maxItems:z0.maxChannels,items:{type:"object",properties:{clientKey:{type:"string",minLength:1,maxLength:80},protocol:{type:"string",enum:["handoff","turn-taking","request-response","barrier"]},participantKeys:{type:"array",minItems:2,maxItems:4,items:{type:"string",minLength:1,maxLength:80}},resourceScope:{type:"array",maxItems:40,items:n4},maxHandoffs:{type:"integer",minimum:1,maximum:z0.maxHandoffsPerChannel},maxDurationMs:{type:"integer",minimum:1000,maximum:1800000},completion:{type:"string",enum:["all-done","accepted","coordinator-decides"]}},required:["clientKey","protocol","participantKeys","resourceScope","maxHandoffs","maxDurationMs","completion"],additionalProperties:!1}},steps:{type:"array",minItems:1,maxItems:z0.maxSteps,description:`HARD LIMIT: 1-${z0.maxSteps} total steps. Count plan.steps before submitting. If a draft is larger, combine related work and retry the same plan tool immediately; never silently truncate required outcomes.`,items:{type:"object",properties:{clientKey:{type:"string",minLength:1,maxLength:80,description:"Stable step key. For a create step, this exact value is the final segment of its create lease and the worker create call clientKey."},participantKey:{type:"string",minLength:1,maxLength:80},channelKeys:{type:"array",maxItems:2,items:{type:"string",minLength:1,maxLength:80}},label:{type:"string",minLength:1,maxLength:80},kind:{type:"string",enum:["read","browser","write","synthesis"]},prompt:{type:"string",minLength:1,maxLength:4000},mutationTool:{type:"string",enum:m1,description:"Required exactly once for each fresh write step. This is the one fenced mutation capability its worker receives."},dependsOn:{type:"array",maxItems:z0.maxSteps,items:{type:"string",minLength:1,maxLength:80}},resources:{type:"array",maxItems:40,items:{type:"object",properties:{key:n4,mode:{type:"string",enum:["read","write"]}},required:["key","mode"],additionalProperties:!1}}},required:["clientKey","label","kind","prompt","dependsOn","resources"],additionalProperties:!1}}},required:["summary","steps"],additionalProperties:!1};var cV=a.object({summary:a.string().trim().min(1).max(1500),semanticAnchorId:a.string().trim().min(1).max(160).optional(),participants:a.array(a.object({clientKey:l0,label:a.string().trim().min(1).max(40),responsibility:a.string().trim().min(1).max(1000)}).strict()).max(z0.maxParticipants).optional(),collaborationChannels:a.array(a.object({clientKey:l0,protocol:a.enum(["handoff","turn-taking","request-response","barrier"]),participantKeys:a.array(l0).min(2).max(4),resourceScope:a.array(o4).max(40),maxHandoffs:a.number().int().min(1).max(z0.maxHandoffsPerChannel),maxDurationMs:a.number().int().min(1000).max(1800000),completion:a.enum(["all-done","accepted","coordinator-decides"])}).strict()).max(z0.maxChannels).optional(),steps:a.array(a.object({clientKey:l0,participantKey:l0.optional(),channelKeys:a.array(l0).max(2).optional(),label:a.string().trim().min(1).max(80),kind:a.enum(["read","browser","write","synthesis"]),prompt:a.string().trim().min(1).max(4000),mutationTool:a.enum(m1).optional(),dependsOn:a.array(l0).max(z0.maxSteps),resources:a.array(a.object({key:o4,mode:a.enum(["read","write"])}).strict()).max(40)}).strict()).min(1).max(z0.maxSteps,{error:`Plan exceeds the hard ${z0.maxSteps}-step limit. Combine related work into ${z0.maxSteps} or fewer steps and retry the same plan tool immediately; do not drop required outcomes.`})}).strict();var t4=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"]),lW=["screenshot_board","inspect_diagram","ask_user_question","create_agent_card","append_user_message","spawn_child_agents"],cW=new Set(lW),iV=new Set([...t4].filter((X)=>!cW.has(X)));var eX={coordinator:["inspect_ideate_context","get_ideate_run_status","screenshot_ideate_context","submit_ideate_plan","revise_ideate_plan","get_question_ui_guide","ask_ideate_question","complete_ideate_run","start_board_walkthrough"],worker:["inspect_ideate_context","get_ideate_run_status","get_ideate_worker_context","screenshot_ideate_context","get_board","list_nodes","list_edges","inspect_node","inspect_board_region","inspect_diagram","list_context_sources","read_context_card","read_context_file","read_context_image","list_context_folder","get_board_wiki","search_board","inspect_neighbors","read_diagram_guide","inspect_browser","list_browser_images","locate_browser_element","list_agent_cards","get_card_messages","inspect_table","get_table_schema","read_table","query_table","export_table_csv","start_board_walkthrough",...m1]},e4=new Set(eX.coordinator),m2=new Set(eX.worker);var pV=eX.worker.filter((X)=>X.startsWith("ideate_"));var dW=new Set([...e4,...m2,"set_ideate_placement"].filter((X)=>X.startsWith("ideate_")||X.includes("ideate_")));function X8(X,Z,W){if(Z==="full")return!dW.has(X);if(Z==="read")return t4.has(X);if(Z==="ideate-coordinator")return e4.has(X);return m2.has(X)&&(!W||W.includes(X))}import{randomUUID as iW}from"node:crypto";import{createServer as pW}from"node:http";import{StreamableHTTPServerTransport as rW}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as Y8}from"@modelcontextprotocol/sdk/types.js";var Z8=new Set(["127.0.0.1","localhost","[::1]","::1"]);function aW(X){let Z=X.trim();if(Z.length===0)return null;if(Z.startsWith("[")){let z=Z.indexOf("]");if(z===-1)return null;let H=Z.slice(0,z+1),F=Z.slice(z+1);if(F.length===0)return{host:H,port:null};if(!F.startsWith(":"))return null;let L=Number(F.slice(1));if(!Number.isInteger(L)||L<=0||L>65535)return null;return{host:H,port:L}}let W=Z.lastIndexOf(":");if(W===-1)return{host:Z,port:null};let Q=Z.slice(W+1),J=Number(Q);if(!Number.isInteger(J)||J<=0||J>65535)return{host:Z,port:null};return{host:Z.slice(0,W),port:J}}function W8(X){return Z8.has(X)||Z8.has(X.toLowerCase())}function Q8(X,Z){let W=X.headers.host;if(typeof W!=="string")return{ok:!1,status:403,reason:"missing-host"};let Q=aW(W);if(!Q)return{ok:!1,status:403,reason:"bad-host"};if(!W8(Q.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(Q.port!==null&&Q.port!==Z)return{ok:!1,status:403,reason:"host-port-mismatch"};let J=X.headers.origin;if(typeof J==="string"&&J.length>0){if(J!=="null"){let z;try{z=new URL(J)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!W8(z.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var J8="/mcp",sW=43274,V8=16777216,oW=1800000,nW=300000,z8=200,tW=-32700,$0=-32600,X3=-32603;function U0(X,Z,W,Q,J){X.statusCode=Z,X.setHeader("content-type","application/json"),X.end(JSON.stringify({jsonrpc:"2.0",error:{code:W,message:Q,...J?{data:J}:{}},id:null}))}class Z3 extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class W3 extends Error{constructor(){super(`body exceeds ${V8} bytes`);this.name="BodyTooLargeError"}}async function eW(X){if(X.method&&X.method!=="POST")return;let Z=X.headers["content-type"];if(typeof Z==="string"&&Z.trim().length>0){if(!Z.toLowerCase().includes("application/json"))throw new Z3}let W=0,Q=[];for await(let z of X){let H=typeof z==="string"?Buffer.from(z):z;if(W+=H.byteLength,W>V8)throw new W3;Q.push(H)}if(Q.length===0)return;let J=Buffer.concat(Q).toString("utf8");if(J.length===0)return;return JSON.parse(J)}function XQ(X){if(Array.isArray(X))return X.some(Y8);return Y8(X)}function ZQ(X){if(typeof X==="number")return X;let Z=process.env.IDEAWAVE_MCP_PORT;if(Z&&Z.trim().length>0){let W=Number(Z);if(Number.isInteger(W)&&W>=0&&W<65536)return W}return sW}async function WQ(X,Z){let W=(J)=>new Promise((z,H)=>{let F=(U)=>{X.off("listening",L),H(U)},L=()=>{X.off("error",F),z()};X.once("error",F),X.once("listening",L),X.listen(J,"127.0.0.1")});try{await W(Z)}catch(J){if(J.code!=="EADDRINUSE"||Z===0)throw J;console.warn(`[mcp] port ${Z} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await W(0)}let Q=X.address();if(Q==null||typeof Q==="string")throw Error("[mcp] failed to read bound address");return Q.port}function QQ(X,Z){if(Z&&typeof Z==="object"&&!Array.isArray(Z)){let Q=Z.params;if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let J=Q.clientInfo;if(J&&typeof J==="object"&&!Array.isArray(J)){let z=J.name;if(typeof z==="string"&&z.trim().length>0)return z.trim()}}}let W=X.headers["user-agent"];if(typeof W==="string"&&W.trim().length>0)return W.trim();return null}async function j8(X){let Z=new Map,W=0;function Q(U){let w=Z.get(U);if(w)w.lastActivity=Date.now()}async function J(U,w){Z.delete(U),await w.transport.close().catch(()=>{return})}async function z(){let U=null,w=1/0;for(let[b,C]of Z)if(C.lastActivity<w)w=C.lastActivity,U=b;if(U!==null){let b=Z.get(U);if(b)console.warn(`[mcp] session cap of ${z8} reached; evicting ${U}`),await J(U,b)}}let H=setInterval(()=>{let U=Date.now()-oW;for(let[w,b]of Z)if(b.lastActivity<U)console.log(`[mcp] sweeping idle session ${w}`),J(w,b)},nW);H.unref?.();let F=pW((U,w)=>{(async()=>{let b;try{b=new URL(U.url??"/","http://127.0.0.1").pathname}catch{U0(w,400,$0,"bad-url");return}if(b!==J8){U0(w,404,$0,"not-found");return}let C=U.method??"POST";if(C!=="POST"&&C!=="GET"&&C!=="DELETE"){w.setHeader("Allow","GET, POST, DELETE"),U0(w,405,$0,"method-not-allowed");return}let M=Q8(U,W);if(!M.ok){U0(w,M.status,$0,"forbidden",{reason:M.reason});return}let G=U.headers["mcp-session-id"],g=typeof G==="string"?G:void 0;if(C==="GET"||C==="DELETE"){if(!g||!Z.has(g)){U0(w,400,$0,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let v=Z.get(g).transport;Q(g);try{await v.handleRequest(U,w)}catch(h){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",h),!w.headersSent)U0(w,500,X3,"internal")}return}let N;try{N=await eW(U)}catch(v){if(v instanceof Z3){U0(w,415,$0,"expected-application-json");return}if(v instanceof W3){U0(w,413,$0,"body-too-large");return}U0(w,400,tW,"invalid-json");return}let R;if(g&&Z.has(g))R=Z.get(g).transport,Q(g);else if(!g&&N!==void 0&&XQ(N)){let v=U.headers["x-ideawave-user-id"],h=typeof v==="string"&&v.trim().length>0?v.trim():null,m=U.headers["x-ideawave-frontend-session-id"],$=typeof m==="string"&&m.trim().length>0?m.trim():null,k=U.headers["x-ideawave-tool-surface"],P=typeof k==="string"?k.trim():"full",O=P==="read"||P==="ideate-coordinator"||P==="ideate-worker"?P:"full",f=U.headers["x-ideawave-images-supported"],S=typeof f==="string"&&f.trim()==="1",T=U.headers["x-ideawave-card-id"],o=typeof T==="string"&&T.trim().length>0?T.trim():null,D=U.headers["x-ideawave-execution-kind"],l=U.headers["x-ideawave-execution-id"],u=typeof D==="string"?D.trim():"",W0=typeof l==="string"?l.trim():"",m0=W0&&new Set(["agent-card","ideate-coordinator","ideate-step","ideate-participant","board-insight","board-auto-title"]).has(u)?{kind:u,id:W0}:null,p2=U.headers["x-ideawave-ideate-claims"],r2=null;if(typeof p2==="string"&&p2.length>0)try{r2=JSON.parse(p2)}catch{r2=null}let s2=U.headers["x-ideawave-board-id"],z9=typeof s2==="string"&&s2.trim().length>0?s2.trim():null,o2=U.headers["x-ideawave-run-folder"],V9=typeof o2==="string"&&o2.trim().length>0?o2.trim():null,n2=U.headers["x-ideawave-pool-session-id"],j9=typeof n2==="string"&&n2.trim().length>0?n2.trim():null,H9=QQ(U,N);if(Z.size>=z8)await z();let t2=null,_0=new rW({sessionIdGenerator:()=>iW(),onsessioninitialized:(r0)=>{t2=r0,Z.set(r0,{transport:_0,lastActivity:Date.now()})},onsessionclosed:(r0)=>{Z.delete(r0)}});_0.onclose=()=>{if(_0.sessionId)Z.delete(_0.sessionId)};try{await X.buildServer({userId:h,frontendSessionId:$,boardId:z9,toolSurface:O,imagesSupported:S,cardId:o,executionTarget:m0,ideateClaims:r2,runFolder:V9,poolSessionId:j9,clientHint:H9}).connect(_0)}catch(r0){if(console.error("[mcp] buildServer/connect failed",r0),t2)Z.delete(t2);await _0.close().catch(()=>{return}),U0(w,500,X3,"server-init-failed");return}R=_0}else{U0(w,400,$0,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await R.handleRequest(U,w,N)}catch(v){if(console.error("[mcp] transport.handleRequest threw",v),!w.headersSent)U0(w,500,X3,"internal")}})().catch((b)=>{console.error("[mcp] unhandled request handler error:",b)})});return W=await WQ(F,ZQ(X.port)),{url:`http://127.0.0.1:${W}${J8}`,port:W,close:async()=>{clearInterval(H);for(let U of Z.values())await U.transport.close().catch(()=>{return});Z.clear(),await new Promise((U)=>F.close(()=>U()))}}}var H8=new Map;function Q3(X,Z){if(!X)return;H8.set(X,Z)}function K8(X){if(!X)return!1;return H8.get(X)??!1}var KQ={name:"ideawave-board",version:"1.0.0"},_2="list_run_folder",k2="read_run_folder_file",L8=new Set(["inspect_diagram"]),k1=new Map;function UQ(X,Z){let W=new Set(X.map(({name:J})=>Y1(J)).filter((J)=>m2.has(J))),Q=new Set(Z.map((J)=>Y1(J)));return W.size===Q.size&&[...W].every((J)=>Q.has(J))}function FQ(X,Z){if(!X)return;let W=k1.get(X);if(!W)return;for(let Q of W.waiters){if(!UQ(Z,Q.expectedWorkerTools))continue;W.waiters.delete(Q),Q.resolve(!0)}}async function B8(X){let Z=k1.get(X.poolSessionId);if(!Z)return!1;let W=X.timeoutMs??750;return new Promise((Q)=>{let J=!1,z=(L)=>{if(J)return;J=!0,clearTimeout(F),Z.waiters.delete(H),Q(L)},H={expectedWorkerTools:X.expectedWorkerTools,resolve:z},F=setTimeout(()=>z(!1),W);F.unref?.(),Z.waiters.add(H),Z.server.sendToolListChanged().catch(()=>z(!1))})}function Y3(X,Z,W){if(X===_2||X===k2)return Z==="full"||Z==="read";return X8(X,Z,W)}var LQ=[{name:_2,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:k2,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 J3(X){return{content:[{type:"text",text:X}]}}function BQ(X){return J3(JSON.stringify(X,null,2))}function U8(X){return{...J3(X),isError:!0}}async function wQ(X,Z){if(!Z||X.isError)return X;let W=X.content.find((z)=>z.type==="text");if(!W)return X;let Q;try{let z=JSON.parse(W.text);if(typeof z.path!=="string")return X;Q=_1.resolve(z.path)}catch{return X}let J=_1.resolve(_1.join(zQ.tmpdir(),"ideawave-screenshots"));if(_1.dirname(Q)!==J||!/^board-[a-z0-9-]+\.png$/i.test(_1.basename(Q)))return X;try{if(!(await YQ(Q)).isFile())return X;let H=await JQ(Q);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 qQ(X,Z,W="full",Q=!1,J){return X.getMetadata(Z).filter((z)=>{let H=Y1(z.name);if(!Y3(H,W,J))return!1;if(!Q&&L8.has(H))return!1;return!0}).map((z)=>({name:z.name,description:z.description,inputSchema:z.inputSchema}))}function PQ(X,Z,W={}){let Q=qQ(X,Z,W.toolSurface??"full",W.imagesSupported??!1,W.workerToolNames);if(!W.includeRunFolderTools)return Q;let J=W.toolSurface??"full",z=LQ.filter((H)=>Y3(H.name,J,W.workerToolNames));return[...Q,...z]}function F8(X,Z){if(!X||typeof X!=="object"||Array.isArray(X))return null;let W=X[Z];return typeof W==="string"?W:null}async function bQ(X,Z,W){if(W&&W.trim().length>0)return W.trim();if(!X||!Z)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await D0({boardId:X,cardId:Z})).runFolder}async function OQ(X){let Z=await bQ(X.boardId,X.cardId,X.runFolder);if(X.name===_2){let W=F8(X.args,"path")??"",Q=await $4(Z,W);return BQ(Q)}if(X.name===k2){let W=F8(X.args,"path");if(!W)return U8("read_run_folder_file requires a path.");return J3(await M2(Z,W))}return U8(`Unknown local tool "${X.name}"`)}function xQ(X,Z,W,Q,J,z="full",H=!1,F=null,L=null,U=null){let w=new VQ(KQ,{capabilities:{tools:{listChanged:!0}}});if(U){let M={server:w,waiters:new Set};k1.set(U,M),w.onclose=()=>{if(k1.get(U)!==M)return;k1.delete(U);for(let G of M.waiters)G.resolve(!1);M.waiters.clear()}}let b=()=>{let M=s4(U);return{cardId:M?.cardId??Q,executionTarget:M?.executionTarget??F,ideateClaims:M?.ideateClaims??L}},C=async()=>{if(H)return!0;let M=b().cardId;if(K8(M))return!0;if(W&&M)try{return(await D0({boardId:W,cardId:M})).adapter.supportsImages===!0}catch{return!1}return!1};return w.setRequestHandler(HQ,async()=>{let M=PQ(X,Z,{includeRunFolderTools:z!=="ideate-coordinator"&&Boolean(J||W&&Q),toolSurface:z,imagesSupported:await C(),workerToolNames:b().ideateClaims?.workerToolNames??null});return FQ(U,M),{tools:M}}),w.setRequestHandler(jQ,async(M)=>{let{name:G,arguments:g}=M.params,N=Y1(G),R=Date.now(),v=b();_("mcp.tool_call_received",{frontendSessionId:Z,cardId:v.cardId,toolName:N});try{if(!Y3(N,z,v.ideateClaims?.workerToolNames))throw Error(`Tool "${G}" is not available on the ${z} surface`);if(N===_2||N===k2)return await OQ({name:N,args:g,boardId:W,cardId:v.cardId,runFolder:J});if(L8.has(N)&&!await C())throw Error(`Tool "${G}" requires a runtime that supports image input`);let h=await X.callTool(Z,N,g??{},v.ideateClaims?.runId,v.cardId??void 0,v.executionTarget??void 0,v.ideateClaims??void 0,z);if(_("mcp.tool_result_returned",{frontendSessionId:Z,cardId:v.cardId,toolName:N,elapsedMs:Date.now()-R}),h&&typeof h==="object"&&Array.isArray(h.content)){let m=h;return N==="screenshot_board"||N==="screenshot_ideate_context"?await wQ(m,await C()):m}return{content:[{type:"text",text:typeof h==="string"?h:JSON.stringify(h)}]}}catch(h){return _("mcp.tool_result_returned",{frontendSessionId:Z,cardId:v.cardId,toolName:N,elapsedMs:Date.now()-R,hasError:!0}),{content:[{type:"text",text:h instanceof Error?h.message:"Tool call failed"}],isError:!0}}}),w}function w8(X,Z){return j8({buildServer:(W)=>xQ(X,W.frontendSessionId,W.boardId,W.cardId,W.runFolder,W.toolSurface,W.imagesSupported,W.executionTarget,W.ideateClaims,W.poolSessionId),port:Z})}var c0=new Map,z3=new Set;function V3(X){c0.get(X)?.controller.abort()}function P8(X){for(let[Z,W]of c0){if(W.frontendSessionId!==X)continue;W.controller.abort(),c0.delete(Z)}}function b8(){for(let X of c0.values())X.controller.abort();c0.clear()}function S1(X,Z){if(Z?.aborted)return!0;return X instanceof Error&&/abort signal received|session cancelled/i.test(X.message)}var q8=200;async function j3(X){try{return await X.open()}catch(Z){if(!(Z instanceof I)||S1(Z,X.signal))throw Z;if(_("cli.session_open_retry",{operation:X.operation,delayMs:q8,errorText:Z.message}),await new Promise((W)=>{setTimeout(W,q8)}),X.signal?.aborted)throw Z;return X.open()}}function H3(X,Z,W,Q){if((!Z.availableModels||Z.availableModels.length===0)&&Z.availableConfigOptions.length===0)return;F0((J)=>{let z=J.runtimes.find((H)=>H.id===X);if(z){if(Z.availableModels&&Z.availableModels.length>0)z.discoveredModels=f2({adapterId:W,models:Z.availableModels,currentModelId:Z.currentModelId??Q});if(Z.availableConfigOptions.length>0)z.discoveredConfigOptions=Z.availableConfigOptions}}).catch(()=>{return})}function vQ(X,Z,W){if(W==="ideate-coordinator"||W==="ideate-worker")return X;return`${X}
|
|
1145
1145
|
|
|
1146
1146
|
Runtime run folder:
|
|
1147
1147
|
- Effective run folder: ${Z}
|
|
@@ -1151,4 +1151,4 @@ Runtime run folder:
|
|
|
1151
1151
|
Connection: close\r
|
|
1152
1152
|
Content-Length: ${Buffer.byteLength(W)}\r
|
|
1153
1153
|
\r
|
|
1154
|
-
${W}`),X.destroy()}function BY(X,Z){return new Promise((W,Q)=>{let J=(H)=>{X.off("listening",z),Q(H)},z=()=>{X.off("error",J);let H=X.address();if(!H||typeof H==="string"){Q(Error("Failed to read CLI bridge server address"));return}W(H.port)};X.once("error",J),X.once("listening",z),X.listen(Z,"127.0.0.1")})}function o8(X){return new Promise((Z,W)=>{X.close((Q)=>{if(Q)W(Q);else Z()})})}async function e8(X,Z=O3()){let W=new Map,Q=new Map,J=X.maxMessageSize??XY,z=X.cliInstanceId??i8(),H=X.nativePingIntervalMs??QY,F=X.idleTimeoutMs??ZY,L=X.disconnectGraceMs??WY,U=!1,w=(R)=>{let v=Q.get(R);if(v)clearTimeout(v);Q.delete(R)},b=(R)=>{Q.delete(R);let{activeRunIds:v}=X.registry.disconnect(R);X.onDisconnect(R,v)},C=(R,v,h)=>{let m={type:"cli_status",connected:!0,runtime:X.runtime,mcpReady:X.mcpReady(),error:v,capabilities:X.capabilities??[],cliVersion:X.cliVersion,cliInstanceId:z,...h===void 0?{}:{sessionResumed:h},browserRuntime:X.browserRuntimeStatus?.()};if(R){let $=W.get(R);if($)a0($,m);return}for(let $ of W.values())a0($,m)},M=(R,v)=>{let h=v.sessionId.trim(),m=v.userId.trim();if(!h||!m){a0(R,{type:"cli_status",connected:!1,runtime:X.runtime,mcpReady:X.mcpReady(),error:"Missing frontend session or user id"}),R.close();return}let $=W.get(h),k=X.registry.register({frontendSessionId:h,userId:m,tools:v.tools,send:(P)=>a0(R,P)});if(!k.accepted){a0(R,{type:"cli_status",connected:!1,runtime:X.runtime,mcpReady:X.mcpReady(),error:"Frontend session belongs to another user. Reload the board and reconnect."}),R.close(1008,"Frontend session identity mismatch");return}if(w(h),R.data.frontendSessionId=h,R.idleTimer)clearTimeout(R.idleTimer);if(R.idleTimer=null,W.set(h,R),$&&$!==R)$.close();C(h,void 0,k.sessionResumed),X.onToolMetadata?.(h)},G=(R,v)=>{let h=X.registry.getUserId(R);if(!h)return;let m=($)=>{let k=LY($),P=X.registry.acceptInboundRequest(R,k);if(P!=="capacity")X.registry.sendToSession(R,{type:"delivery_ack",messageId:k});return P};switch(v.type){case"bridge_ping":{let $=W.get(R);if($)a0($,{type:"bridge_pong"});break}case"delivery_ack":X.registry.handleDeliveryAck(R,v.messageId);break;case"tool_metadata":X.registry.setMetadata(R,v.tools),X.onToolMetadata?.(R);break;case"tool_result":X.registry.handleToolResult(R,v);break;case"run_turn":{let $=m(v);if($==="duplicate"||$==="cancelled")break;if($==="capacity"){X.registry.sendToSession(R,{type:"run_settled",runId:v.run.runId,cardId:v.run.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"CLI request queue is full. Retry this run.",partialText:null}});break}_("bridge.run_received",{runId:v.run.runId,cardId:v.run.cardId,frontendSessionId:R}),X.registry.markRunActive(R,v.run.runId,v.run.cardId),X.onRunTurn(R,{...v.run,frontendSessionId:R,userId:h})}break;case"cancel_run":{if(X.registry.cancelInboundRequest(R,p8(v))!=="capacity")X.registry.sendToSession(R,{type:"delivery_ack",messageId:r8(v)});if(X.registry.ownsRun(R,v.runId))X.onCancelRun(R,v.runId)}break;case"runtime_rpc":{let $=m(v);if($==="duplicate"||$==="cancelled")break;if($==="capacity"){X.registry.sendToSession(R,{type:"runtime_rpc_result",requestId:v.requestId,ok:!1,error:"CLI request queue is full. Retry this operation."});break}X.onRuntimeRpc(R,v)}break;case"browser_rpc":{let $=m(v);if($==="duplicate"||$==="cancelled")break;if($==="capacity"){X.registry.sendToSession(R,{type:"browser_rpc_result",requestId:v.requestId,ok:!1,error:"CLI request queue is full. Retry this operation."});break}X.onBrowserRpc?.(R,W.get(R)?.data.frontendOrigin??"",v)}break;case"browser_rpc_cancel":{if(X.registry.cancelInboundRequest(R,p8(v))!=="capacity")X.registry.sendToSession(R,{type:"delivery_ack",messageId:r8(v)});X.onBrowserRpcCancel?.(R,v)}break;case"warmup_run":X.onWarmupRun(R,{...v,frontendSessionId:R},h);break;default:break}},g=(R,v)=>{let h=d2(R.headers.origin),m=x3(h),$={Vary:"Origin"};if(m&&h)$["Access-Control-Allow-Origin"]=h,$["Access-Control-Allow-Private-Network"]="true";if(R.method==="OPTIONS"){v.writeHead(204,{...$,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),v.end();return}if(R.method!=="GET"){v.writeHead(405,$),v.end();return}v.writeHead(200,{...$,"content-type":"application/json","cache-control":"no-store"}),v.end(JSON.stringify({ideawave:!0,runtime:X.runtime,mcpReady:X.mcpReady(),capabilities:X.capabilities??[],cliVersion:X.cliVersion,cliInstanceId:z,browserRuntime:X.browserRuntimeStatus?.()}))},N=(R,v)=>{let h=d2(R.headers.origin),m=x3(h),$={Vary:"Origin"};if(m&&h)$["Access-Control-Allow-Origin"]=h,$["Access-Control-Allow-Private-Network"]="true";if(R.method==="OPTIONS"){v.writeHead(204,{...$,"Access-Control-Allow-Methods":"POST, OPTIONS","Access-Control-Allow-Headers":"content-type","Access-Control-Max-Age":"600"}),v.end();return}if(!m){v.writeHead(403,$),v.end();return}if(R.method!=="POST"){v.writeHead(405,$),v.end();return}let k={...$,"content-type":"application/json"},P=(S,T)=>{v.writeHead(S,k),v.end(JSON.stringify(T))},O="",f=!1;R.on("data",(S)=>{if(O+=S.toString("utf8"),O.length>JY)f=!0,R.destroy()}),R.on("end",()=>{if(f){P(400,{ok:!1,error:"Request body too large"});return}let S;try{S=JSON.parse(O)}catch{P(400,{ok:!1,error:"Invalid JSON body"});return}let T=typeof S.url==="string"?S.url:"";if(!c8(T)){P(400,{ok:!1,error:"url must be an http(s) loopback or /static_boards/ page URL"});return}let o=(D,l)=>{let u=typeof D==="number"?D:Number.NaN;if(!Number.isFinite(u))return l;return Math.min(4000,Math.max(200,Math.round(u)))};d8({url:T,width:o(S.width,1440),height:o(S.height,900)}).then((D)=>P(200,{ok:!0,path:D.path,engine:D.engine})).catch((D)=>{let l=D instanceof A1?503:D instanceof c2?429:500;P(l,{ok:!1,...D instanceof A1?{installing:!0}:{},error:D instanceof Error?D.message:String(D)})})})};for(let R of Z){let v=tQ((P,O)=>{(async()=>{let f=new URL(P.url??"/","http://127.0.0.1").pathname;if(f===S8){g(P,O);return}if(f===YY){N(P,O);return}if(await X.onHttpRequest?.(P,O))return;O.writeHead(404,{"content-type":"text/plain"}),O.end("IdeaWave CLI bridge")})().catch((f)=>{if(O.headersSent){O.destroy(f instanceof Error?f:void 0);return}O.writeHead(500,{"content-type":"text/plain"}),O.end("IdeaWave CLI bridge request failed")})}),h=new eQ({noServer:!0,maxPayload:J}),m=(P)=>{if(P.idleTimer)clearTimeout(P.idleTimer);P.idleTimer=setTimeout(()=>{P.close()},F),P.idleTimer.unref?.()},$=(P)=>{if(P.nativePingTimer)clearInterval(P.nativePingTimer);P.nativePingTimer=null,P.awaitingNativePong=!1,P.nativePongMisses=0},k=(P)=>{$(P),P.nativePingTimer=setInterval(()=>{if(P.readyState!==v3.OPEN)return;if(P.awaitingNativePong){if(P.nativePongMisses+=1,P.nativePongMisses>=2){P.terminate();return}}P.awaitingNativePong=!0;try{P.ping()}catch{P.terminate()}},H),P.nativePingTimer.unref?.()};h.on("connection",(P,O)=>{let f=P;f.data={id:i8(),frontendSessionId:null,frontendOrigin:new URL(d2(O.headers.origin)??n8).origin},f.idleTimer=null,f.nativePingTimer=null,f.awaitingNativePong=!1,f.nativePongMisses=0,m(f),k(f),f.on("ping",()=>{if(!f.data.frontendSessionId)m(f)}),f.on("pong",()=>{if(f.awaitingNativePong=!1,f.nativePongMisses=0,!f.data.frontendSessionId)m(f)}),f.on("error",()=>{if(f.idleTimer)clearTimeout(f.idleTimer);$(f),f.close()}),f.on("message",(S)=>{if(!f.data.frontendSessionId)m(f);let T=FY(S);if(J>0&&T.length>J)return;let o=I2(T);if(!o)return;let D=f.data.frontendSessionId;if(!D){if(o.type==="bridge_probe")a0(f,{type:"bridge_probe_ack",protocolVersion:o.protocolVersion});else if(o.type==="frontend_hello")M(f,o);return}G(D,o)}),f.on("close",()=>{if(f.idleTimer)clearTimeout(f.idleTimer);$(f);let S=f.data.frontendSessionId;if(!S)return;if(W.get(S)!==f)return;if(W.delete(S),w(S),U)return;Q.set(S,setTimeout(()=>b(S),L))})}),v.on("upgrade",(P,O,f)=>{let S=new URL(P.url??"/","http://127.0.0.1").pathname;if(X.onHttpUpgrade?.(P,O,f))return;if(S!==b3){s8(O,404,"Not Found");return}if(!x3(d2(P.headers.origin))){s8(O,403,"Forbidden");return}h.handleUpgrade(P,O,f,(T)=>{h.emit("connection",T,P)})});try{let P=await BY(v,R);return{url:`ws://127.0.0.1:${P}${b3}`,port:P,sendStatus:C,close:async()=>{U=!0;for(let O of Q.values())clearTimeout(O);Q.clear();for(let O of h.clients){let f=O;if(f.idleTimer)clearTimeout(f.idleTimer);$(f),f.close()}h.close(),await o8(v).catch(()=>{return})}}}catch(P){if(h.close(),await o8(v).catch(()=>{return}),P?.code==="EADDRINUSE")continue;throw P}}throw Error(`No free IdeaWave CLI bridge port found in ${Z[0]}-${Z.at(-1)}`)}import a2 from"node:fs/promises";import R3 from"node:os";import i2 from"node:path";function X9(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function wY(){let[X,Z]=await Promise.all([j0(),w6()]),W=X.globalDefaultConfigId?X.runtimes.find((Q)=>Q.id===X.globalDefaultConfigId)??null:null;return{runtimes:X.runtimes,globalDefaultConfigId:X.globalDefaultConfigId,globalDefaultEffective:W?{runFolder:W.runFolder??R3.homedir(),modelId:W.defaultModelId??null,configValues:W.defaultConfigValues??{}}:null,knownAdapters:n0().map((Q)=>({id:Q.id,displayName:Q.displayName})),readiness:Z}}async function qY(X){try{let Z=await D0({boardId:X.boardId,cardId:X.cardId});return{resolved:{configId:Z.entry.id,adapterId:Z.entry.kind==="registered"?Z.entry.adapterId:null,displayName:Z.entry.displayName,runFolder:Z.runFolder,modelId:Z.modelId,configValues:Z.configValues}}}catch(Z){if(Z instanceof v0)return{resolved:null};throw Z}}async function PY(X){return F0((Z)=>{let W=Z.runtimes.find((z)=>z.kind==="registered"&&z.adapterId===X.adapterId);if(W)return W;let Q=n0().find((z)=>z.id===X.adapterId);if(!Q)throw Error(`Unknown adapterId: ${X.adapterId}`);let J={id:X9(),kind:"registered",adapterId:X.adapterId,displayName:Q.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return Z.runtimes.push(J),J})}async function bY(X){return F0((Z)=>{let W={id:X9(),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 Z.runtimes.push(W),W})}async function OY(X){await F0((Z)=>{if(Z.runtimes=Z.runtimes.filter((W)=>W.id!==X.runtimeConfigId),Z.globalDefaultConfigId===X.runtimeConfigId)Z.globalDefaultConfigId=null;for(let W of Object.keys(Z.boardOverrides))if(Z.boardOverrides[W].runtimeConfigId===X.runtimeConfigId)delete Z.boardOverrides[W];for(let W of Object.keys(Z.cardOverrides))if(Z.cardOverrides[W].runtimeConfigId===X.runtimeConfigId)delete Z.cardOverrides[W]})}async function xY(X){await F0((Z)=>{let W=Z.runtimes.find((Q)=>Q.id===X.runtimeConfigId);if(!W)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);if(Z.globalDefaultConfigId=X.runtimeConfigId,X.runFolder!==void 0)W.runFolder=X.runFolder;if(X.modelId!==void 0)W.defaultModelId=X.modelId;if(X.configValues!==void 0)W.defaultConfigValues=X.configValues})}async function vY(X){X.boardId,await F0((Z)=>{if(X.runtimeConfigId===null){delete Z.cardOverrides[X.cardId];return}if(!Z.runtimes.some((J)=>J.id===X.runtimeConfigId))throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let Q=Z.cardOverrides[X.cardId];Z.cardOverrides[X.cardId]={runtimeConfigId:X.runtimeConfigId,runFolder:X.runFolder!==void 0?X.runFolder:Q?.runFolder??null,modelId:X.modelId!==void 0?X.modelId:Q?.modelId??null,configValues:X.configValues!==void 0?X.configValues:Q?.configValues??{}}})}async function RY(X){let W=(await j0()).runtimes.find((H)=>H.id===X.runtimeConfigId);if(!W)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let Q=q0(W),J=await Q.resolveSpawnConfig(W),z=W.runFolder??R3.homedir();try{let H=await p4({spawn:{...J,cwd:z},modelId:X.modelId??W.defaultModelId??null,configValues:X.configValues??W.defaultConfigValues??{}}),F=f2({adapterId:Q.id,models:H.models,currentModelId:H.currentModelId}),L=new Date().toISOString();return await F0((U)=>{let w=U.runtimes.find((b)=>b.id===X.runtimeConfigId);if(w)w.discoveredModels=F,w.discoveredConfigOptions=H.configOptions,w.discoveredAt=L}),{ok:!0,models:F,configOptions:H.configOptions,currentModelId:H.currentModelId}}catch(H){if(H instanceof s0)throw Error(`${H.message}${Q.authHint?` ${Q.authHint}`:""}`);if(H instanceof I||H instanceof w0)throw Error(H.message);throw H}}async function CY(X){let Z=R3.homedir(),W=X.path?.trim()?X.path.trim():Z,Q=i2.resolve(W),J=!0;try{if(!(await a2.stat(Q)).isDirectory())Q=i2.dirname(Q)}catch{J=!1,Q=Z}let z=[];try{z=(await a2.readdir(Q,{withFileTypes:!0})).filter((L)=>L.isDirectory()&&!L.name.startsWith(".")).map((L)=>({name:L.name,path:i2.join(Q,L.name)})).sort((L,U)=>L.name.localeCompare(U.name))}catch{z=[]}let H=i2.dirname(Q);return{path:Q,parent:H===Q?null:H,home:Z,exists:J,entries:z}}var Z9={list:wY,getEffectiveForCard:qY,registerRegistered:PY,registerCustom:bY,unregister:OY,setUserDefault:xY,setCardOverride:vY,refreshModels:RY,browseFolder:CY};var yY=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function fY(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function W9(){try{let X=await j0();if(X.globalDefaultConfigId){if(X.runtimes.some((W)=>W.id===X.globalDefaultConfigId))return X.globalDefaultConfigId}for(let Z of yY){if((await q6(Z.id))?.status!=="ready")continue;let Q=null;if(await F0((J)=>{if(J.globalDefaultConfigId){if(J.runtimes.some((F)=>F.id===J.globalDefaultConfigId)){Q=J.globalDefaultConfigId;return}}let z=J.runtimes.find((H)=>H.kind==="registered"&&H.adapterId===Z.id);if(!z){let H={id:fY(),kind:"registered",adapterId:Z.id,displayName:Z.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};J.runtimes.push(H),z=H}J.globalDefaultConfigId=z.id,Q=z.id}),Q)return console.log(`[ideawave-cli] using agent runtime: ${Z.displayName}`),Q}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch(X){return console.warn("[ideawave-cli] runtime auto-seed failed",X),null}}var hY=240000,MY=256,NY=33554432,DY=128,$Y=512,GY=A8,gY=65536;function EY(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class C3{sessions=new Map;createCallId;toolCallTimeoutMs;maxPendingDeliveries;maxPendingDeliveryBytes;maxAcceptedInboundRequests;maxCancellationTombstones;cancellationTombstoneTtlMs;terminalReservationBytes;constructor(X={}){this.createCallId=X.createCallId??EY,this.toolCallTimeoutMs=X.toolCallTimeoutMs??hY,this.maxPendingDeliveries=X.maxPendingDeliveries??MY,this.maxPendingDeliveryBytes=X.maxPendingDeliveryBytes??NY,this.maxAcceptedInboundRequests=X.maxAcceptedInboundRequests??DY,this.maxCancellationTombstones=X.maxCancellationTombstones??$Y,this.cancellationTombstoneTtlMs=X.cancellationTombstoneTtlMs??GY,this.terminalReservationBytes=X.terminalReservationBytes??gY}register(X){let Z=this.sessions.get(X.frontendSessionId);if(Z){let W=Z.userId===X.userId;if(!W)return{accepted:!1,sessionResumed:!1};return this.pruneCancellationTombstones(Z),this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:Z.pendingToolCalls,pendingDeliveries:Z.pendingDeliveries,acceptedInboundRequests:Z.acceptedInboundRequests,cancelledInboundRequests:Z.cancelledInboundRequests,cancellationOverflowUntil:Z.cancellationOverflowUntil,activeRunIds:Z.activeRunIds,activeRunCardIds:Z.activeRunCardIds}),this.replayPendingDeliveries(X.frontendSessionId),{accepted:!0,sessionResumed:W}}return this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:new Map,pendingDeliveries:new Map,acceptedInboundRequests:new Map,cancelledInboundRequests:new Map,cancellationOverflowUntil:null,activeRunIds:new Set,activeRunCardIds:new Map}),{accepted:!0,sessionResumed:!1}}disconnect(X,Z="frontend session disconnected"){let W=this.sessions.get(X);if(!W)return{activeRunIds:[]};return this.sessions.delete(X),this.rejectPending(W,Z),{activeRunIds:Array.from(W.activeRunIds)}}sessionCount(){return this.sessions.size}has(X){return this.sessions.has(X)}getUserId(X){return this.sessions.get(X)?.userId??null}setMetadata(X,Z){let W=this.sessions.get(X);if(W)W.tools=Z}getMetadata(X){if(!X)return[];return this.sessions.get(X)?.tools??[]}acceptInboundRequest(X,Z){let W=this.sessions.get(X);if(!W)return"capacity";if(this.pruneCancellationTombstones(W),W.cancelledInboundRequests.has(Z))return"cancelled";if(W.acceptedInboundRequests.has(Z))return"duplicate";if(W.cancellationOverflowUntil!==null&&(Z.startsWith("run_turn:")||Z.startsWith("browser_rpc:")))return"capacity";if(W.acceptedInboundRequests.size>=this.maxAcceptedInboundRequests||W.pendingDeliveries.size+W.acceptedInboundRequests.size>=this.maxPendingDeliveries||this.pendingDeliveryBytes(W)+this.outstandingTerminalReservationBytes(W)+this.terminalReservationBytes>this.maxPendingDeliveryBytes)return"capacity";return W.acceptedInboundRequests.set(Z,{terminalReservation:!0,terminalReservationBytes:this.terminalReservationBytes}),"accepted"}cancelInboundRequest(X,Z){let W=this.sessions.get(X);if(!W)return"capacity";this.pruneCancellationTombstones(W);let Q=Date.now()+this.cancellationTombstoneTtlMs;if(W.cancelledInboundRequests.has(Z))return W.cancelledInboundRequests.set(Z,Q),"duplicate";if(W.cancelledInboundRequests.size>=this.maxCancellationTombstones)return W.cancellationOverflowUntil=Math.max(W.cancellationOverflowUntil??0,Q),"capacity";return W.cancelledInboundRequests.set(Z,Q),"accepted"}sendToSession(X,Z){let W=this.sessions.get(X);if(!W)return!1;let Q=this.toReliableMessage(Z);if(Q){let J=this.getReliableMessageId(Q),z=Buffer.byteLength(JSON.stringify(Q),"utf8"),H=W.pendingDeliveries.get(J),F=this.pendingDeliveryBytes(W),L=W.pendingDeliveries.size+(H?0:1),U=F-(H?.byteLength??0)+z,w=this.inboundRequestIdForTerminalDelivery(J),b=w?W.acceptedInboundRequests.get(w):void 0,C=Boolean(b?.terminalReservation),M=[...W.acceptedInboundRequests.values()].filter((g)=>g.terminalReservation).length-(C?1:0),G=this.outstandingTerminalReservationBytes(W)-(C?b?.terminalReservationBytes??0:0);if(C&&(L+M>this.maxPendingDeliveries||U+G>this.maxPendingDeliveryBytes))Q=this.compactTerminalFailure(Q),z=Buffer.byteLength(JSON.stringify(Q),"utf8"),U=F-(H?.byteLength??0)+z;if(L+M>this.maxPendingDeliveries||U+G>this.maxPendingDeliveryBytes)return _("bridge.delivery_rejected",{frontendSessionId:X,messageId:J,messageType:Q.type,byteLength:z,reason:"capacity"}),!1;if(W.pendingDeliveries.set(J,{message:Q,queuedAt:Date.now(),byteLength:z}),b)b.terminalReservation=!1;return _("bridge.delivery_queued",{frontendSessionId:X,messageId:J,messageType:Q.type,queueDepth:W.pendingDeliveries.size}),W.send(Q),!0}return W.send(Z),!0}handleDeliveryAck(X,Z){let W=this.sessions.get(X);if(!W)return;let Q=W.pendingDeliveries.get(Z);if(Q)W.pendingDeliveries.delete(Z),_("bridge.delivery_acknowledged",{frontendSessionId:X,messageId:Z,messageType:Q.message.type,elapsedMs:Date.now()-Q.queuedAt,queueDepth:W.pendingDeliveries.size});let J=this.inboundRequestIdForTerminalDelivery(Z);if(J)W.acceptedInboundRequests.delete(J)}callTool(X,Z,W,Q,J,z,H,F){if(!X)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let L=this.sessions.get(X);if(!L)return Promise.reject(Error(`Frontend session ${X} is not connected`));let U=this.createCallId();return new Promise((w,b)=>{let C=Q??(J?this.getActiveRunIdForCard(L,J):this.getSoleActiveRunId(L)),M=J??(C?L.activeRunCardIds.get(C):void 0),G=Date.now(),g=setTimeout(()=>{L.pendingToolCalls.delete(U),L.pendingDeliveries.delete(U),_("tool_queue.timeout",{frontendSessionId:X,runId:C,cardId:M,callId:U,toolName:Z,elapsedMs:Date.now()-G,queueDepth:L.pendingToolCalls.size}),b(Error(`Tool "${Z}" timed out waiting for the frontend`))},this.toolCallTimeoutMs);if(L.pendingToolCalls.set(U,{resolve:w,reject:b,timer:g,name:Z,runId:C??null,cardId:M??null,startedAt:G}),_("tool_queue.forwarded_to_browser",{frontendSessionId:X,runId:C,cardId:M,callId:U,toolName:Z,queueDepth:L.pendingToolCalls.size}),!this.sendToSession(X,{type:"tool_call",callId:U,messageId:U,name:Z,args:W,...C?{runId:C}:{},...M?{cardId:M}:{},...z?{executionTarget:z}:{},...H?{ideateClaims:H}:{},...F?{toolSurface:F}:{}}))L.pendingToolCalls.delete(U),clearTimeout(g),b(Error("Frontend delivery capacity reached"))})}handleToolResult(X,Z){let W=this.sessions.get(X);if(!W)return;let Q=W.pendingToolCalls.get(Z.callId);if(!Q){W.pendingDeliveries.delete(Z.callId),W.send({type:"delivery_ack",messageId:Z.callId});return}W.pendingToolCalls.delete(Z.callId),W.pendingDeliveries.delete(Z.callId),clearTimeout(Q.timer),W.send({type:"delivery_ack",messageId:Z.callId});let J=Z.ok?"":Z.error??Z.result?.content?.find(({text:F})=>typeof F==="string")?.text??"Tool execution failed",z=/network|fetch|connection|offline/i.test(J)?"network":/timeout|timed out/i.test(J)?"timeout":/unauthor|forbidden|permission/i.test(J)?"authorization":/conflict|revision|lease|fence/i.test(J)?"conflict":/invalid|missing|required|schema/i.test(J)?"validation":"unknown";if(_("tool_queue.result_received",{frontendSessionId:X,runId:Q.runId,cardId:Q.cardId,callId:Z.callId,toolName:Q.name,elapsedMs:Date.now()-Q.startedAt,queueDepth:W.pendingToolCalls.size,ok:Z.ok,...Z.ok?{}:{errorCategory:z}}),Z.ok){Q.resolve(Z.result);return}let H=Z.result;if(H&&typeof H==="object"&&Array.isArray(H.content)){Q.resolve({...H,isError:!0});return}Q.reject(Error(Z.error??"Tool execution failed"))}markRunActive(X,Z,W){let Q=this.sessions.get(X);if(!Q)return;if(Q.activeRunIds.add(Z),W)Q.activeRunCardIds.set(Z,W)}markRunSettled(X,Z){let W=this.sessions.get(X);if(!W)return;W.activeRunIds.delete(Z),W.activeRunCardIds.delete(Z)}ownsRun(X,Z){return this.sessions.get(X)?.activeRunIds.has(Z)??!1}rejectPending(X,Z){for(let W of X.pendingToolCalls.values())clearTimeout(W.timer),_("tool_queue.rejected",{frontendSessionId:X.frontendSessionId,runId:W.runId,cardId:W.cardId,toolName:W.name,elapsedMs:Date.now()-W.startedAt}),W.reject(Error(Z));X.pendingToolCalls.clear()}replayPendingDeliveries(X){let Z=this.sessions.get(X);if(!Z)return;for(let[W,Q]of Z.pendingDeliveries)_("bridge.delivery_replayed",{frontendSessionId:X,messageId:W,messageType:Q.message.type,elapsedMs:Date.now()-Q.queuedAt,queueDepth:Z.pendingDeliveries.size}),Z.send(Q.message)}pruneCancellationTombstones(X){let Z=Date.now();for(let[W,Q]of X.cancelledInboundRequests)if(Q<=Z)X.cancelledInboundRequests.delete(W);if(X.cancellationOverflowUntil!==null&&X.cancellationOverflowUntil<=Z)X.cancellationOverflowUntil=null}pendingDeliveryBytes(X){let Z=0;for(let W of X.pendingDeliveries.values())Z+=W.byteLength;return Z}outstandingTerminalReservationBytes(X){let Z=0;for(let W of X.acceptedInboundRequests.values())if(W.terminalReservation)Z+=W.terminalReservationBytes;return Z}compactTerminalFailure(X){switch(X.type){case"run_settled":return{...X,result:{assistantContent:"",model:null,latencyMs:X.result.latencyMs,errorText:"CLI terminal response exceeded the reliable bridge limit. Continue the paused run after reconnecting.",partialText:null}};case"runtime_rpc_result":return{...X,ok:!1,error:"CLI terminal response exceeded the reliable bridge limit. Continue the paused run after reconnecting.",result:void 0};case"browser_rpc_result":return{...X,ok:!1,error:"CLI terminal response exceeded the reliable bridge limit. Continue the paused run after reconnecting.",result:void 0};case"tool_call":return X}}inboundRequestIdForTerminalDelivery(X){if(X.startsWith("run_settled:"))return`run_turn:${X.slice(12)}`;if(X.startsWith("runtime_rpc_result:"))return`runtime_rpc:${X.slice(19)}`;if(X.startsWith("browser_rpc_result:"))return`browser_rpc:${X.slice(19)}`;return null}toReliableMessage(X){switch(X.type){case"tool_call":return{...X,messageId:X.messageId??X.callId};case"run_settled":return{...X,messageId:X.messageId??`run_settled:${X.runId}`};case"runtime_rpc_result":return{...X,messageId:X.messageId??`runtime_rpc_result:${X.requestId}`};case"browser_rpc_result":return{...X,messageId:X.messageId??`browser_rpc_result:${X.requestId}`};default:return null}}getReliableMessageId(X){if(!X.messageId)throw Error(`Reliable relay message ${X.type} is missing messageId`);return X.messageId}getSoleActiveRunId(X){return X.activeRunIds.size===1?X.activeRunIds.values().next().value:void 0}getActiveRunIdForCard(X,Z){let W=[...X.activeRunCardIds.entries()].filter(([Q,J])=>X.activeRunIds.has(Q)&&J===Z).map(([Q])=>Q);return W.length===1?W[0]:void 0}}function J9(){return"0.0.98".trim()?"0.0.98":"dev"}var mY=process.argv.slice(2),f3=a8(mY,process.env);if(f3.allowRailwayPrPreviews)process.env[T1]="1";var E0=f3.cliArgs[0],{browserKitEnabled:l1,captureEngineEnabled:_Y}=f3;if(E0==="--help"||E0==="-h"||E0==="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(E0==="--version"||E0==="-v"||E0==="version")console.log(J9()),process.exit(0);if(E0)console.error(`Unknown command: ${E0}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var c1=new C3,p0=null,kY=l1?{phase:"ready",message:"Local browser-kit proxy is ready"}:{phase:"idle"},j1=new y2,i0=new Map;function Q9(X,Z){return`${X}:${Z}`}function g0(X,Z){let W=c1.sendToSession(X,Z);if(!W)_("bridge.delivery_rejected_by_registry",{frontendSessionId:X,messageType:Z.type});return W}async function SY(X,Z){try{let W=Z9[Z.method],Q=await W(Z.params);g0(X,{type:"runtime_rpc_result",requestId:Z.requestId,ok:!0,result:Q})}catch(W){g0(X,{type:"runtime_rpc_result",requestId:Z.requestId,ok:!1,error:W instanceof Error?W.message:String(W)})}}var d1=!1,u1=null;async function y3(){if(d1)return;if(u1)return u1;return u1=(async()=>{try{let X=await w8(c1);m3({...X,requestedPort:X.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${X.url}`);try{await o3({onStatusChange:(Z)=>{if(P6(),p0?.sendStatus(),Z.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${Z.packageName}: ${Z.error??"unknown error"}`)}})}catch(Z){console.warn("[ideawave-cli] ACP bridge setup skipped:",Z instanceof Error?Z.message:String(Z))}await W9(),d1=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),p0?.sendStatus()}catch(X){console.error("[ideawave-cli] failed to start agent host:",X),p0?.sendStatus(void 0,X instanceof Error?X.message:String(X))}finally{u1=null}})(),u1}if(process.env.APP_ENV!=="development"){let X=await t8();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(_Y)E8().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"}`)});p0=await e8({registry:c1,runtime:null,mcpReady:()=>d1,capabilities:N8(l1),cliVersion:J9(),browserRuntimeStatus:()=>kY,onToolMetadata:(X)=>{console.log(`[ideawave-cli] session ${X} advertised ${c1.getMetadata(X).length} tools`),y3()},onRunTurn:(X,Z)=>{console.log(`[ideawave-cli] running agent turn for card ${Z.cardId} (session ${X})`),(async()=>{if(await y3(),!d1){g0(X,{type:"run_settled",runId:Z.runId,cardId:Z.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await x8(Z,(W)=>g0(X,W))})().catch(()=>{return}).finally(()=>c1.markRunSettled(X,Z.runId))},onCancelRun:(X,Z)=>{V3(Z)},onRuntimeRpc:(X,Z)=>{SY(X,Z)},onBrowserRpc:(X,Z,W)=>{if(!l1){g0(X,{type:"browser_rpc_result",requestId:W.requestId,ok:!1,error:"The development browser-kit proxy is not enabled"});return}let Q=Q9(X,W.requestId);i0.get(Q)?.abort();let J=new AbortController;i0.set(Q,J),j1.handleRpc(X,Z,W,{signal:J.signal}).then((z)=>{g0(X,{type:"browser_rpc_result",requestId:W.requestId,ok:!0,result:z})},(z)=>{g0(X,{type:"browser_rpc_result",requestId:W.requestId,ok:!1,error:mX(z)})}).finally(()=>{if(i0.get(Q)===J)i0.delete(Q)})},onBrowserRpcCancel:(X,Z)=>{i0.get(Q9(X,Z.requestId))?.abort()},onHttpRequest:(X,Z)=>l1?j1.handleHttpRequest(X,Z):!1,onHttpUpgrade:(X,Z,W)=>l1?j1.handleUpgrade(X,Z,W):!1,onWarmupRun:(X,Z,W)=>{(async()=>{if(await y3(),!d1)return{status:"retryable",error:"agent host is not ready"};if(Z.ideate)return K3({boardId:Z.boardId,userId:W,frontendSessionId:X,surface:Z.ideate.surface,runtimeConfigId:Z.ideate.runtimeConfigId,modelId:Z.ideate.modelId});return v8({cardId:Z.cardId,boardId:Z.boardId,userId:W,frontendSessionId:X})})().then((Q)=>{if(!Z.warmupId)return;g0(X,{type:"warmup_result",warmupId:Z.warmupId,cardId:Z.cardId,...Q})})},onDisconnect:(X,Z)=>{for(let[W,Q]of i0){if(!W.startsWith(`${X}:`))continue;Q.abort(),i0.delete(W)}j1.closeFrontendSession(X),P8(X);for(let W of Z)V3(W);_("bridge.frontend_disconnected",{frontendSessionId:X,activeRuns:Z.length}),D3(X).catch((W)=>{console.warn(`[ideawave-cli] failed to evict sessions for ${X}:`,W instanceof Error?W.message:String(W))}),console.log(`[ideawave-cli] browser session ${X} disconnected`)}});j1.setPort(p0.port);console.log(`[ideawave-cli] browser bridge listening on ${p0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var Y9=!1;for(let X of["SIGINT","SIGTERM"])process.once(X,()=>{if(Y9)return;Y9=!0,b8(),(async()=>{await j1.close(),await k8(),await p0?.close().catch(()=>{return}),process.exit(0)})()});
|
|
1154
|
+
${W}`),X.destroy()}function BY(X,Z){return new Promise((W,Q)=>{let J=(H)=>{X.off("listening",z),Q(H)},z=()=>{X.off("error",J);let H=X.address();if(!H||typeof H==="string"){Q(Error("Failed to read CLI bridge server address"));return}W(H.port)};X.once("error",J),X.once("listening",z),X.listen(Z,"127.0.0.1")})}function o8(X){return new Promise((Z,W)=>{X.close((Q)=>{if(Q)W(Q);else Z()})})}async function e8(X,Z=O3()){let W=new Map,Q=new Map,J=X.maxMessageSize??XY,z=X.cliInstanceId??i8(),H=X.nativePingIntervalMs??QY,F=X.idleTimeoutMs??ZY,L=X.disconnectGraceMs??WY,U=!1,w=(R)=>{let v=Q.get(R);if(v)clearTimeout(v);Q.delete(R)},b=(R)=>{Q.delete(R);let{activeRunIds:v}=X.registry.disconnect(R);X.onDisconnect(R,v)},C=(R,v,h)=>{let m={type:"cli_status",connected:!0,runtime:X.runtime,mcpReady:X.mcpReady(),error:v,capabilities:X.capabilities??[],cliVersion:X.cliVersion,cliInstanceId:z,...h===void 0?{}:{sessionResumed:h},browserRuntime:X.browserRuntimeStatus?.()};if(R){let $=W.get(R);if($)a0($,m);return}for(let $ of W.values())a0($,m)},M=(R,v)=>{let h=v.sessionId.trim(),m=v.userId.trim();if(!h||!m){a0(R,{type:"cli_status",connected:!1,runtime:X.runtime,mcpReady:X.mcpReady(),error:"Missing frontend session or user id"}),R.close();return}let $=W.get(h),k=X.registry.register({frontendSessionId:h,userId:m,tools:v.tools,send:(P)=>a0(R,P)});if(!k.accepted){a0(R,{type:"cli_status",connected:!1,runtime:X.runtime,mcpReady:X.mcpReady(),error:"Frontend session belongs to another user. Reload the board and reconnect."}),R.close(1008,"Frontend session identity mismatch");return}if(w(h),R.data.frontendSessionId=h,R.idleTimer)clearTimeout(R.idleTimer);if(R.idleTimer=null,W.set(h,R),$&&$!==R)$.close();C(h,void 0,k.sessionResumed),X.onToolMetadata?.(h)},G=(R,v)=>{let h=X.registry.getUserId(R);if(!h)return;let m=($)=>{let k=LY($),P=X.registry.acceptInboundRequest(R,k);if(P!=="capacity")X.registry.sendToSession(R,{type:"delivery_ack",messageId:k});return P};switch(v.type){case"bridge_ping":{let $=W.get(R);if($)a0($,{type:"bridge_pong"});break}case"delivery_ack":X.registry.handleDeliveryAck(R,v.messageId);break;case"tool_metadata":X.registry.setMetadata(R,v.tools),X.onToolMetadata?.(R);break;case"tool_result":X.registry.handleToolResult(R,v);break;case"run_turn":{let $=m(v);if($==="duplicate"||$==="cancelled")break;if($==="capacity"){X.registry.sendToSession(R,{type:"run_settled",runId:v.run.runId,cardId:v.run.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"CLI request queue is full. Retry this run.",partialText:null}});break}_("bridge.run_received",{runId:v.run.runId,cardId:v.run.cardId,frontendSessionId:R}),X.registry.markRunActive(R,v.run.runId,v.run.cardId),X.onRunTurn(R,{...v.run,frontendSessionId:R,userId:h})}break;case"cancel_run":{if(X.registry.cancelInboundRequest(R,p8(v))!=="capacity")X.registry.sendToSession(R,{type:"delivery_ack",messageId:r8(v)});if(X.registry.ownsRun(R,v.runId))X.onCancelRun(R,v.runId)}break;case"runtime_rpc":{let $=m(v);if($==="duplicate"||$==="cancelled")break;if($==="capacity"){X.registry.sendToSession(R,{type:"runtime_rpc_result",requestId:v.requestId,ok:!1,error:"CLI request queue is full. Retry this operation."});break}X.onRuntimeRpc(R,v)}break;case"browser_rpc":{let $=m(v);if($==="duplicate"||$==="cancelled")break;if($==="capacity"){X.registry.sendToSession(R,{type:"browser_rpc_result",requestId:v.requestId,ok:!1,error:"CLI request queue is full. Retry this operation."});break}X.onBrowserRpc?.(R,W.get(R)?.data.frontendOrigin??"",v)}break;case"browser_rpc_cancel":{if(X.registry.cancelInboundRequest(R,p8(v))!=="capacity")X.registry.sendToSession(R,{type:"delivery_ack",messageId:r8(v)});X.onBrowserRpcCancel?.(R,v)}break;case"warmup_run":X.onWarmupRun(R,{...v,frontendSessionId:R},h);break;default:break}},g=(R,v)=>{let h=d2(R.headers.origin),m=x3(h),$={Vary:"Origin"};if(m&&h)$["Access-Control-Allow-Origin"]=h,$["Access-Control-Allow-Private-Network"]="true";if(R.method==="OPTIONS"){v.writeHead(204,{...$,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),v.end();return}if(R.method!=="GET"){v.writeHead(405,$),v.end();return}v.writeHead(200,{...$,"content-type":"application/json","cache-control":"no-store"}),v.end(JSON.stringify({ideawave:!0,runtime:X.runtime,mcpReady:X.mcpReady(),capabilities:X.capabilities??[],cliVersion:X.cliVersion,cliInstanceId:z,browserRuntime:X.browserRuntimeStatus?.()}))},N=(R,v)=>{let h=d2(R.headers.origin),m=x3(h),$={Vary:"Origin"};if(m&&h)$["Access-Control-Allow-Origin"]=h,$["Access-Control-Allow-Private-Network"]="true";if(R.method==="OPTIONS"){v.writeHead(204,{...$,"Access-Control-Allow-Methods":"POST, OPTIONS","Access-Control-Allow-Headers":"content-type","Access-Control-Max-Age":"600"}),v.end();return}if(!m){v.writeHead(403,$),v.end();return}if(R.method!=="POST"){v.writeHead(405,$),v.end();return}let k={...$,"content-type":"application/json"},P=(S,T)=>{v.writeHead(S,k),v.end(JSON.stringify(T))},O="",f=!1;R.on("data",(S)=>{if(O+=S.toString("utf8"),O.length>JY)f=!0,R.destroy()}),R.on("end",()=>{if(f){P(400,{ok:!1,error:"Request body too large"});return}let S;try{S=JSON.parse(O)}catch{P(400,{ok:!1,error:"Invalid JSON body"});return}let T=typeof S.url==="string"?S.url:"";if(!c8(T)){P(400,{ok:!1,error:"url must be an http(s) loopback or /static_boards/ page URL"});return}let o=(D,l)=>{let u=typeof D==="number"?D:Number.NaN;if(!Number.isFinite(u))return l;return Math.min(4000,Math.max(200,Math.round(u)))};d8({url:T,width:o(S.width,1440),height:o(S.height,900)}).then((D)=>P(200,{ok:!0,path:D.path,engine:D.engine})).catch((D)=>{let l=D instanceof A1?503:D instanceof c2?429:500;P(l,{ok:!1,...D instanceof A1?{installing:!0}:{},error:D instanceof Error?D.message:String(D)})})})};for(let R of Z){let v=tQ((P,O)=>{(async()=>{let f=new URL(P.url??"/","http://127.0.0.1").pathname;if(f===S8){g(P,O);return}if(f===YY){N(P,O);return}if(await X.onHttpRequest?.(P,O))return;O.writeHead(404,{"content-type":"text/plain"}),O.end("IdeaWave CLI bridge")})().catch((f)=>{if(O.headersSent){O.destroy(f instanceof Error?f:void 0);return}O.writeHead(500,{"content-type":"text/plain"}),O.end("IdeaWave CLI bridge request failed")})}),h=new eQ({noServer:!0,maxPayload:J}),m=(P)=>{if(P.idleTimer)clearTimeout(P.idleTimer);P.idleTimer=setTimeout(()=>{P.close()},F),P.idleTimer.unref?.()},$=(P)=>{if(P.nativePingTimer)clearInterval(P.nativePingTimer);P.nativePingTimer=null,P.awaitingNativePong=!1,P.nativePongMisses=0},k=(P)=>{$(P),P.nativePingTimer=setInterval(()=>{if(P.readyState!==v3.OPEN)return;if(P.awaitingNativePong){if(P.nativePongMisses+=1,P.nativePongMisses>=2){P.terminate();return}}P.awaitingNativePong=!0;try{P.ping()}catch{P.terminate()}},H),P.nativePingTimer.unref?.()};h.on("connection",(P,O)=>{let f=P;f.data={id:i8(),frontendSessionId:null,frontendOrigin:new URL(d2(O.headers.origin)??n8).origin},f.idleTimer=null,f.nativePingTimer=null,f.awaitingNativePong=!1,f.nativePongMisses=0,m(f),k(f),f.on("ping",()=>{if(!f.data.frontendSessionId)m(f)}),f.on("pong",()=>{if(f.awaitingNativePong=!1,f.nativePongMisses=0,!f.data.frontendSessionId)m(f)}),f.on("error",()=>{if(f.idleTimer)clearTimeout(f.idleTimer);$(f),f.close()}),f.on("message",(S)=>{if(!f.data.frontendSessionId)m(f);let T=FY(S);if(J>0&&T.length>J)return;let o=I2(T);if(!o)return;let D=f.data.frontendSessionId;if(!D){if(o.type==="bridge_probe")a0(f,{type:"bridge_probe_ack",protocolVersion:o.protocolVersion});else if(o.type==="frontend_hello")M(f,o);return}G(D,o)}),f.on("close",()=>{if(f.idleTimer)clearTimeout(f.idleTimer);$(f);let S=f.data.frontendSessionId;if(!S)return;if(W.get(S)!==f)return;if(W.delete(S),w(S),U)return;Q.set(S,setTimeout(()=>b(S),L))})}),v.on("upgrade",(P,O,f)=>{let S=new URL(P.url??"/","http://127.0.0.1").pathname;if(X.onHttpUpgrade?.(P,O,f))return;if(S!==b3){s8(O,404,"Not Found");return}if(!x3(d2(P.headers.origin))){s8(O,403,"Forbidden");return}h.handleUpgrade(P,O,f,(T)=>{h.emit("connection",T,P)})});try{let P=await BY(v,R);return{url:`ws://127.0.0.1:${P}${b3}`,port:P,sendStatus:C,close:async()=>{U=!0;for(let O of Q.values())clearTimeout(O);Q.clear();for(let O of h.clients){let f=O;if(f.idleTimer)clearTimeout(f.idleTimer);$(f),f.close()}h.close(),await o8(v).catch(()=>{return})}}}catch(P){if(h.close(),await o8(v).catch(()=>{return}),P?.code==="EADDRINUSE")continue;throw P}}throw Error(`No free IdeaWave CLI bridge port found in ${Z[0]}-${Z.at(-1)}`)}import a2 from"node:fs/promises";import R3 from"node:os";import i2 from"node:path";function X9(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function wY(){let[X,Z]=await Promise.all([j0(),w6()]),W=X.globalDefaultConfigId?X.runtimes.find((Q)=>Q.id===X.globalDefaultConfigId)??null:null;return{runtimes:X.runtimes,globalDefaultConfigId:X.globalDefaultConfigId,globalDefaultEffective:W?{runFolder:W.runFolder??R3.homedir(),modelId:W.defaultModelId??null,configValues:W.defaultConfigValues??{}}:null,knownAdapters:n0().map((Q)=>({id:Q.id,displayName:Q.displayName})),readiness:Z}}async function qY(X){try{let Z=await D0({boardId:X.boardId,cardId:X.cardId});return{resolved:{configId:Z.entry.id,adapterId:Z.entry.kind==="registered"?Z.entry.adapterId:null,displayName:Z.entry.displayName,runFolder:Z.runFolder,modelId:Z.modelId,configValues:Z.configValues}}}catch(Z){if(Z instanceof v0)return{resolved:null};throw Z}}async function PY(X){return F0((Z)=>{let W=Z.runtimes.find((z)=>z.kind==="registered"&&z.adapterId===X.adapterId);if(W)return W;let Q=n0().find((z)=>z.id===X.adapterId);if(!Q)throw Error(`Unknown adapterId: ${X.adapterId}`);let J={id:X9(),kind:"registered",adapterId:X.adapterId,displayName:Q.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return Z.runtimes.push(J),J})}async function bY(X){return F0((Z)=>{let W={id:X9(),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 Z.runtimes.push(W),W})}async function OY(X){await F0((Z)=>{if(Z.runtimes=Z.runtimes.filter((W)=>W.id!==X.runtimeConfigId),Z.globalDefaultConfigId===X.runtimeConfigId)Z.globalDefaultConfigId=null;for(let W of Object.keys(Z.boardOverrides))if(Z.boardOverrides[W].runtimeConfigId===X.runtimeConfigId)delete Z.boardOverrides[W];for(let W of Object.keys(Z.cardOverrides))if(Z.cardOverrides[W].runtimeConfigId===X.runtimeConfigId)delete Z.cardOverrides[W]})}async function xY(X){await F0((Z)=>{let W=Z.runtimes.find((Q)=>Q.id===X.runtimeConfigId);if(!W)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);if(Z.globalDefaultConfigId=X.runtimeConfigId,X.runFolder!==void 0)W.runFolder=X.runFolder;if(X.modelId!==void 0)W.defaultModelId=X.modelId;if(X.configValues!==void 0)W.defaultConfigValues=X.configValues})}async function vY(X){X.boardId,await F0((Z)=>{if(X.runtimeConfigId===null){delete Z.cardOverrides[X.cardId];return}if(!Z.runtimes.some((J)=>J.id===X.runtimeConfigId))throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let Q=Z.cardOverrides[X.cardId];Z.cardOverrides[X.cardId]={runtimeConfigId:X.runtimeConfigId,runFolder:X.runFolder!==void 0?X.runFolder:Q?.runFolder??null,modelId:X.modelId!==void 0?X.modelId:Q?.modelId??null,configValues:X.configValues!==void 0?X.configValues:Q?.configValues??{}}})}async function RY(X){let W=(await j0()).runtimes.find((H)=>H.id===X.runtimeConfigId);if(!W)throw Error(`Runtime config not found: ${X.runtimeConfigId}`);let Q=q0(W),J=await Q.resolveSpawnConfig(W),z=W.runFolder??R3.homedir();try{let H=await p4({spawn:{...J,cwd:z},modelId:X.modelId??W.defaultModelId??null,configValues:X.configValues??W.defaultConfigValues??{}}),F=f2({adapterId:Q.id,models:H.models,currentModelId:H.currentModelId}),L=new Date().toISOString();return await F0((U)=>{let w=U.runtimes.find((b)=>b.id===X.runtimeConfigId);if(w)w.discoveredModels=F,w.discoveredConfigOptions=H.configOptions,w.discoveredAt=L}),{ok:!0,models:F,configOptions:H.configOptions,currentModelId:H.currentModelId}}catch(H){if(H instanceof s0)throw Error(`${H.message}${Q.authHint?` ${Q.authHint}`:""}`);if(H instanceof I||H instanceof w0)throw Error(H.message);throw H}}async function CY(X){let Z=R3.homedir(),W=X.path?.trim()?X.path.trim():Z,Q=i2.resolve(W),J=!0;try{if(!(await a2.stat(Q)).isDirectory())Q=i2.dirname(Q)}catch{J=!1,Q=Z}let z=[];try{z=(await a2.readdir(Q,{withFileTypes:!0})).filter((L)=>L.isDirectory()&&!L.name.startsWith(".")).map((L)=>({name:L.name,path:i2.join(Q,L.name)})).sort((L,U)=>L.name.localeCompare(U.name))}catch{z=[]}let H=i2.dirname(Q);return{path:Q,parent:H===Q?null:H,home:Z,exists:J,entries:z}}var Z9={list:wY,getEffectiveForCard:qY,registerRegistered:PY,registerCustom:bY,unregister:OY,setUserDefault:xY,setCardOverride:vY,refreshModels:RY,browseFolder:CY};var yY=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function fY(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function W9(){try{let X=await j0();if(X.globalDefaultConfigId){if(X.runtimes.some((W)=>W.id===X.globalDefaultConfigId))return X.globalDefaultConfigId}for(let Z of yY){if((await q6(Z.id))?.status!=="ready")continue;let Q=null;if(await F0((J)=>{if(J.globalDefaultConfigId){if(J.runtimes.some((F)=>F.id===J.globalDefaultConfigId)){Q=J.globalDefaultConfigId;return}}let z=J.runtimes.find((H)=>H.kind==="registered"&&H.adapterId===Z.id);if(!z){let H={id:fY(),kind:"registered",adapterId:Z.id,displayName:Z.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};J.runtimes.push(H),z=H}J.globalDefaultConfigId=z.id,Q=z.id}),Q)return console.log(`[ideawave-cli] using agent runtime: ${Z.displayName}`),Q}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch(X){return console.warn("[ideawave-cli] runtime auto-seed failed",X),null}}var hY=240000,MY=256,NY=33554432,DY=128,$Y=512,GY=A8,gY=65536;function EY(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class C3{sessions=new Map;createCallId;toolCallTimeoutMs;maxPendingDeliveries;maxPendingDeliveryBytes;maxAcceptedInboundRequests;maxCancellationTombstones;cancellationTombstoneTtlMs;terminalReservationBytes;constructor(X={}){this.createCallId=X.createCallId??EY,this.toolCallTimeoutMs=X.toolCallTimeoutMs??hY,this.maxPendingDeliveries=X.maxPendingDeliveries??MY,this.maxPendingDeliveryBytes=X.maxPendingDeliveryBytes??NY,this.maxAcceptedInboundRequests=X.maxAcceptedInboundRequests??DY,this.maxCancellationTombstones=X.maxCancellationTombstones??$Y,this.cancellationTombstoneTtlMs=X.cancellationTombstoneTtlMs??GY,this.terminalReservationBytes=X.terminalReservationBytes??gY}register(X){let Z=this.sessions.get(X.frontendSessionId);if(Z){let W=Z.userId===X.userId;if(!W)return{accepted:!1,sessionResumed:!1};return this.pruneCancellationTombstones(Z),this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:Z.pendingToolCalls,pendingDeliveries:Z.pendingDeliveries,acceptedInboundRequests:Z.acceptedInboundRequests,cancelledInboundRequests:Z.cancelledInboundRequests,cancellationOverflowUntil:Z.cancellationOverflowUntil,activeRunIds:Z.activeRunIds,activeRunCardIds:Z.activeRunCardIds}),this.replayPendingDeliveries(X.frontendSessionId),{accepted:!0,sessionResumed:W}}return this.sessions.set(X.frontendSessionId,{frontendSessionId:X.frontendSessionId,userId:X.userId,tools:X.tools,send:X.send,pendingToolCalls:new Map,pendingDeliveries:new Map,acceptedInboundRequests:new Map,cancelledInboundRequests:new Map,cancellationOverflowUntil:null,activeRunIds:new Set,activeRunCardIds:new Map}),{accepted:!0,sessionResumed:!1}}disconnect(X,Z="frontend session disconnected"){let W=this.sessions.get(X);if(!W)return{activeRunIds:[]};return this.sessions.delete(X),this.rejectPending(W,Z),{activeRunIds:Array.from(W.activeRunIds)}}sessionCount(){return this.sessions.size}has(X){return this.sessions.has(X)}getUserId(X){return this.sessions.get(X)?.userId??null}setMetadata(X,Z){let W=this.sessions.get(X);if(W)W.tools=Z}getMetadata(X){if(!X)return[];return this.sessions.get(X)?.tools??[]}acceptInboundRequest(X,Z){let W=this.sessions.get(X);if(!W)return"capacity";if(this.pruneCancellationTombstones(W),W.cancelledInboundRequests.has(Z))return"cancelled";if(W.acceptedInboundRequests.has(Z))return"duplicate";if(W.cancellationOverflowUntil!==null&&(Z.startsWith("run_turn:")||Z.startsWith("browser_rpc:")))return"capacity";if(W.acceptedInboundRequests.size>=this.maxAcceptedInboundRequests||W.pendingDeliveries.size+W.acceptedInboundRequests.size>=this.maxPendingDeliveries||this.pendingDeliveryBytes(W)+this.outstandingTerminalReservationBytes(W)+this.terminalReservationBytes>this.maxPendingDeliveryBytes)return"capacity";return W.acceptedInboundRequests.set(Z,{terminalReservation:!0,terminalReservationBytes:this.terminalReservationBytes}),"accepted"}cancelInboundRequest(X,Z){let W=this.sessions.get(X);if(!W)return"capacity";this.pruneCancellationTombstones(W);let Q=Date.now()+this.cancellationTombstoneTtlMs;if(W.cancelledInboundRequests.has(Z))return W.cancelledInboundRequests.set(Z,Q),"duplicate";if(W.cancelledInboundRequests.size>=this.maxCancellationTombstones)return W.cancellationOverflowUntil=Math.max(W.cancellationOverflowUntil??0,Q),"capacity";return W.cancelledInboundRequests.set(Z,Q),"accepted"}sendToSession(X,Z){let W=this.sessions.get(X);if(!W)return!1;let Q=this.toReliableMessage(Z);if(Q){let J=this.getReliableMessageId(Q),z=Buffer.byteLength(JSON.stringify(Q),"utf8"),H=W.pendingDeliveries.get(J),F=this.pendingDeliveryBytes(W),L=W.pendingDeliveries.size+(H?0:1),U=F-(H?.byteLength??0)+z,w=this.inboundRequestIdForTerminalDelivery(J),b=w?W.acceptedInboundRequests.get(w):void 0,C=Boolean(b?.terminalReservation),M=[...W.acceptedInboundRequests.values()].filter((g)=>g.terminalReservation).length-(C?1:0),G=this.outstandingTerminalReservationBytes(W)-(C?b?.terminalReservationBytes??0:0);if(C&&(L+M>this.maxPendingDeliveries||U+G>this.maxPendingDeliveryBytes))Q=this.compactTerminalFailure(Q),z=Buffer.byteLength(JSON.stringify(Q),"utf8"),U=F-(H?.byteLength??0)+z;if(L+M>this.maxPendingDeliveries||U+G>this.maxPendingDeliveryBytes)return _("bridge.delivery_rejected",{frontendSessionId:X,messageId:J,messageType:Q.type,byteLength:z,reason:"capacity"}),!1;if(W.pendingDeliveries.set(J,{message:Q,queuedAt:Date.now(),byteLength:z}),b)b.terminalReservation=!1;return _("bridge.delivery_queued",{frontendSessionId:X,messageId:J,messageType:Q.type,queueDepth:W.pendingDeliveries.size}),W.send(Q),!0}return W.send(Z),!0}handleDeliveryAck(X,Z){let W=this.sessions.get(X);if(!W)return;let Q=W.pendingDeliveries.get(Z);if(Q)W.pendingDeliveries.delete(Z),_("bridge.delivery_acknowledged",{frontendSessionId:X,messageId:Z,messageType:Q.message.type,elapsedMs:Date.now()-Q.queuedAt,queueDepth:W.pendingDeliveries.size});let J=this.inboundRequestIdForTerminalDelivery(Z);if(J)W.acceptedInboundRequests.delete(J)}callTool(X,Z,W,Q,J,z,H,F){if(!X)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let L=this.sessions.get(X);if(!L)return Promise.reject(Error(`Frontend session ${X} is not connected`));let U=this.createCallId();return new Promise((w,b)=>{let C=Q??(J?this.getActiveRunIdForCard(L,J):this.getSoleActiveRunId(L)),M=J??(C?L.activeRunCardIds.get(C):void 0),G=Date.now(),g=setTimeout(()=>{L.pendingToolCalls.delete(U),L.pendingDeliveries.delete(U),_("tool_queue.timeout",{frontendSessionId:X,runId:C,cardId:M,callId:U,toolName:Z,elapsedMs:Date.now()-G,queueDepth:L.pendingToolCalls.size}),b(Error(`Tool "${Z}" timed out waiting for the frontend`))},this.toolCallTimeoutMs);if(L.pendingToolCalls.set(U,{resolve:w,reject:b,timer:g,name:Z,runId:C??null,cardId:M??null,startedAt:G}),_("tool_queue.forwarded_to_browser",{frontendSessionId:X,runId:C,cardId:M,callId:U,toolName:Z,queueDepth:L.pendingToolCalls.size}),!this.sendToSession(X,{type:"tool_call",callId:U,messageId:U,name:Z,args:W,...C?{runId:C}:{},...M?{cardId:M}:{},...z?{executionTarget:z}:{},...H?{ideateClaims:H}:{},...F?{toolSurface:F}:{}}))L.pendingToolCalls.delete(U),clearTimeout(g),b(Error("Frontend delivery capacity reached"))})}handleToolResult(X,Z){let W=this.sessions.get(X);if(!W)return;let Q=W.pendingToolCalls.get(Z.callId);if(!Q){W.pendingDeliveries.delete(Z.callId),W.send({type:"delivery_ack",messageId:Z.callId});return}W.pendingToolCalls.delete(Z.callId),W.pendingDeliveries.delete(Z.callId),clearTimeout(Q.timer),W.send({type:"delivery_ack",messageId:Z.callId});let J=Z.ok?"":Z.error??Z.result?.content?.find(({text:F})=>typeof F==="string")?.text??"Tool execution failed",z=/network|fetch|connection|offline/i.test(J)?"network":/timeout|timed out/i.test(J)?"timeout":/unauthor|forbidden|permission/i.test(J)?"authorization":/conflict|revision|lease|fence/i.test(J)?"conflict":/invalid|missing|required|schema/i.test(J)?"validation":"unknown";if(_("tool_queue.result_received",{frontendSessionId:X,runId:Q.runId,cardId:Q.cardId,callId:Z.callId,toolName:Q.name,elapsedMs:Date.now()-Q.startedAt,queueDepth:W.pendingToolCalls.size,ok:Z.ok,...Z.ok?{}:{errorCategory:z}}),Z.ok){Q.resolve(Z.result);return}let H=Z.result;if(H&&typeof H==="object"&&Array.isArray(H.content)){Q.resolve({...H,isError:!0});return}Q.reject(Error(Z.error??"Tool execution failed"))}markRunActive(X,Z,W){let Q=this.sessions.get(X);if(!Q)return;if(Q.activeRunIds.add(Z),W)Q.activeRunCardIds.set(Z,W)}markRunSettled(X,Z){let W=this.sessions.get(X);if(!W)return;W.activeRunIds.delete(Z),W.activeRunCardIds.delete(Z)}ownsRun(X,Z){return this.sessions.get(X)?.activeRunIds.has(Z)??!1}rejectPending(X,Z){for(let W of X.pendingToolCalls.values())clearTimeout(W.timer),_("tool_queue.rejected",{frontendSessionId:X.frontendSessionId,runId:W.runId,cardId:W.cardId,toolName:W.name,elapsedMs:Date.now()-W.startedAt}),W.reject(Error(Z));X.pendingToolCalls.clear()}replayPendingDeliveries(X){let Z=this.sessions.get(X);if(!Z)return;for(let[W,Q]of Z.pendingDeliveries)_("bridge.delivery_replayed",{frontendSessionId:X,messageId:W,messageType:Q.message.type,elapsedMs:Date.now()-Q.queuedAt,queueDepth:Z.pendingDeliveries.size}),Z.send(Q.message)}pruneCancellationTombstones(X){let Z=Date.now();for(let[W,Q]of X.cancelledInboundRequests)if(Q<=Z)X.cancelledInboundRequests.delete(W);if(X.cancellationOverflowUntil!==null&&X.cancellationOverflowUntil<=Z)X.cancellationOverflowUntil=null}pendingDeliveryBytes(X){let Z=0;for(let W of X.pendingDeliveries.values())Z+=W.byteLength;return Z}outstandingTerminalReservationBytes(X){let Z=0;for(let W of X.acceptedInboundRequests.values())if(W.terminalReservation)Z+=W.terminalReservationBytes;return Z}compactTerminalFailure(X){switch(X.type){case"run_settled":return{...X,result:{assistantContent:"",model:null,latencyMs:X.result.latencyMs,errorText:"CLI terminal response exceeded the reliable bridge limit. Continue the paused run after reconnecting.",partialText:null}};case"runtime_rpc_result":return{...X,ok:!1,error:"CLI terminal response exceeded the reliable bridge limit. Continue the paused run after reconnecting.",result:void 0};case"browser_rpc_result":return{...X,ok:!1,error:"CLI terminal response exceeded the reliable bridge limit. Continue the paused run after reconnecting.",result:void 0};case"tool_call":return X}}inboundRequestIdForTerminalDelivery(X){if(X.startsWith("run_settled:"))return`run_turn:${X.slice(12)}`;if(X.startsWith("runtime_rpc_result:"))return`runtime_rpc:${X.slice(19)}`;if(X.startsWith("browser_rpc_result:"))return`browser_rpc:${X.slice(19)}`;return null}toReliableMessage(X){switch(X.type){case"tool_call":return{...X,messageId:X.messageId??X.callId};case"run_settled":return{...X,messageId:X.messageId??`run_settled:${X.runId}`};case"runtime_rpc_result":return{...X,messageId:X.messageId??`runtime_rpc_result:${X.requestId}`};case"browser_rpc_result":return{...X,messageId:X.messageId??`browser_rpc_result:${X.requestId}`};default:return null}}getReliableMessageId(X){if(!X.messageId)throw Error(`Reliable relay message ${X.type} is missing messageId`);return X.messageId}getSoleActiveRunId(X){return X.activeRunIds.size===1?X.activeRunIds.values().next().value:void 0}getActiveRunIdForCard(X,Z){let W=[...X.activeRunCardIds.entries()].filter(([Q,J])=>X.activeRunIds.has(Q)&&J===Z).map(([Q])=>Q);return W.length===1?W[0]:void 0}}function J9(){return"0.0.99".trim()?"0.0.99":"dev"}var mY=process.argv.slice(2),f3=a8(mY,process.env);if(f3.allowRailwayPrPreviews)process.env[T1]="1";var E0=f3.cliArgs[0],{browserKitEnabled:l1,captureEngineEnabled:_Y}=f3;if(E0==="--help"||E0==="-h"||E0==="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(E0==="--version"||E0==="-v"||E0==="version")console.log(J9()),process.exit(0);if(E0)console.error(`Unknown command: ${E0}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var c1=new C3,p0=null,kY=l1?{phase:"ready",message:"Local browser-kit proxy is ready"}:{phase:"idle"},j1=new y2,i0=new Map;function Q9(X,Z){return`${X}:${Z}`}function g0(X,Z){let W=c1.sendToSession(X,Z);if(!W)_("bridge.delivery_rejected_by_registry",{frontendSessionId:X,messageType:Z.type});return W}async function SY(X,Z){try{let W=Z9[Z.method],Q=await W(Z.params);g0(X,{type:"runtime_rpc_result",requestId:Z.requestId,ok:!0,result:Q})}catch(W){g0(X,{type:"runtime_rpc_result",requestId:Z.requestId,ok:!1,error:W instanceof Error?W.message:String(W)})}}var d1=!1,u1=null;async function y3(){if(d1)return;if(u1)return u1;return u1=(async()=>{try{let X=await w8(c1);m3({...X,requestedPort:X.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${X.url}`);try{await o3({onStatusChange:(Z)=>{if(P6(),p0?.sendStatus(),Z.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${Z.packageName}: ${Z.error??"unknown error"}`)}})}catch(Z){console.warn("[ideawave-cli] ACP bridge setup skipped:",Z instanceof Error?Z.message:String(Z))}await W9(),d1=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),p0?.sendStatus()}catch(X){console.error("[ideawave-cli] failed to start agent host:",X),p0?.sendStatus(void 0,X instanceof Error?X.message:String(X))}finally{u1=null}})(),u1}if(process.env.APP_ENV!=="development"){let X=await t8();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(_Y)E8().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"}`)});p0=await e8({registry:c1,runtime:null,mcpReady:()=>d1,capabilities:N8(l1),cliVersion:J9(),browserRuntimeStatus:()=>kY,onToolMetadata:(X)=>{console.log(`[ideawave-cli] session ${X} advertised ${c1.getMetadata(X).length} tools`),y3()},onRunTurn:(X,Z)=>{console.log(`[ideawave-cli] running agent turn for card ${Z.cardId} (session ${X})`),(async()=>{if(await y3(),!d1){g0(X,{type:"run_settled",runId:Z.runId,cardId:Z.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await x8(Z,(W)=>g0(X,W))})().catch(()=>{return}).finally(()=>c1.markRunSettled(X,Z.runId))},onCancelRun:(X,Z)=>{V3(Z)},onRuntimeRpc:(X,Z)=>{SY(X,Z)},onBrowserRpc:(X,Z,W)=>{if(!l1){g0(X,{type:"browser_rpc_result",requestId:W.requestId,ok:!1,error:"The development browser-kit proxy is not enabled"});return}let Q=Q9(X,W.requestId);i0.get(Q)?.abort();let J=new AbortController;i0.set(Q,J),j1.handleRpc(X,Z,W,{signal:J.signal}).then((z)=>{g0(X,{type:"browser_rpc_result",requestId:W.requestId,ok:!0,result:z})},(z)=>{g0(X,{type:"browser_rpc_result",requestId:W.requestId,ok:!1,error:mX(z)})}).finally(()=>{if(i0.get(Q)===J)i0.delete(Q)})},onBrowserRpcCancel:(X,Z)=>{i0.get(Q9(X,Z.requestId))?.abort()},onHttpRequest:(X,Z)=>l1?j1.handleHttpRequest(X,Z):!1,onHttpUpgrade:(X,Z,W)=>l1?j1.handleUpgrade(X,Z,W):!1,onWarmupRun:(X,Z,W)=>{(async()=>{if(await y3(),!d1)return{status:"retryable",error:"agent host is not ready"};if(Z.ideate)return K3({boardId:Z.boardId,userId:W,frontendSessionId:X,surface:Z.ideate.surface,runtimeConfigId:Z.ideate.runtimeConfigId,modelId:Z.ideate.modelId});return v8({cardId:Z.cardId,boardId:Z.boardId,userId:W,frontendSessionId:X})})().then((Q)=>{if(!Z.warmupId)return;g0(X,{type:"warmup_result",warmupId:Z.warmupId,cardId:Z.cardId,...Q})})},onDisconnect:(X,Z)=>{for(let[W,Q]of i0){if(!W.startsWith(`${X}:`))continue;Q.abort(),i0.delete(W)}j1.closeFrontendSession(X),P8(X);for(let W of Z)V3(W);_("bridge.frontend_disconnected",{frontendSessionId:X,activeRuns:Z.length}),D3(X).catch((W)=>{console.warn(`[ideawave-cli] failed to evict sessions for ${X}:`,W instanceof Error?W.message:String(W))}),console.log(`[ideawave-cli] browser session ${X} disconnected`)}});j1.setPort(p0.port);console.log(`[ideawave-cli] browser bridge listening on ${p0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var Y9=!1;for(let X of["SIGINT","SIGTERM"])process.once(X,()=>{if(Y9)return;Y9=!0,b8(),(async()=>{await j1.close(),await k8(),await p0?.close().catch(()=>{return}),process.exit(0)})()});
|