ideawave 0.0.44 → 0.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +2 -2
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -15,7 +15,7 @@ ${Q}`:null].filter(Boolean).join(`
15
15
 
16
16
  `));return l($)}function A1($,X){if(!X)return $;if(!$)return X;if($===X||$.endsWith(X))return $;if(X.startsWith($))return X;return e(`${$}
17
17
 
18
- ${X}`)}function U$($){if(!Array.isArray($))return null;let X=$.flatMap((Z)=>{if(!Z||typeof Z!=="object")return[];let J=Z;if(typeof J.path!=="string"||!J.path.trim())return[];let Q=typeof J.line==="number"?`:${J.line}`:"";return[`${J.path}${Q}`]});return X.length>0?X.slice(0,5):null}function w1($){let{ctx:X,appendText:Z,appendToolActivity:J}=$,Q=$.flushIntervalMs??C6,j="",W="",G=0,z=null,K={},H=new Map,B=(P)=>{if(H.set(P.toolCallId,P),!J)return;J({boardId:X.boardId,cardId:X.cardId,runId:X.runId,entry:P}).catch((V)=>{console.warn("[streamAdapter] appendToolActivity failed",V)})},U=(P)=>{let V=`${X.runId}:thought`,F=H.get(V);if(!F||F.status!=="running")return;B({...F,status:"completed",completedAt:F.completedAt??P})},M=(P)=>{for(let V of H.values()){if(V.status!=="running"||V.rawTitle.toLowerCase()!=="toolsearch")continue;B({...V,status:"completed",completedAt:V.completedAt??P})}},N=(P)=>{for(let V of Array.from(H.values())){if(V.status!=="running")continue;if(V.kind==="thought"||V.rawTitle==="agent_thought")continue;B({...V,status:"completed",completedAt:V.completedAt??P})}},C="",Y=0,D=null,x=null,k=(P)=>{if(P===C)return;C=P,Y=Date.now(),Z({boardId:X.boardId,cardId:X.cardId,runId:X.runId,text:P}).catch((V)=>{console.warn("[streamAdapter] appendText failed",V)})},A=()=>{if(D!==null)clearTimeout(D),D=null;if(x!==null){let P=x;x=null,k(P)}},_=(P)=>{let V=Date.now()-Y;if(V>=Q&&D===null){k(P);return}if(x=P,D===null){let F=Math.max(0,Q-V);D=setTimeout(()=>{D=null,A()},F)}};return{onSessionUpdate:async(P)=>{let V=P.update;switch(K[V.sessionUpdate]=(K[V.sessionUpdate]??0)+1,V.sessionUpdate){case"agent_message_chunk":{let F=new Date().toISOString();if(U(F),V.content.type==="text")j+=V.content.text,_(j);else{let T=`agent_message_chunk:${V.content.type}`;K[T]=(K[T]??0)+1}return}case"agent_thought_chunk":{if(V.content.type!=="text")return;W+=V.content.text;let F=new Date().toISOString(),T=`${X.runId}:thought`,R=H.get(T);B({toolCallId:T,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:R?.startedAt??F,completedAt:null,contentPreview:e(W.trim())});return}case"user_message_chunk":return;case"tool_call":{G+=1;let F=O1(V.title),T=Y$(V.status),R=new Date().toISOString();U(R),M(R),B({toolCallId:V.toolCallId,rawTitle:F,title:G$(F,V.rawInput),kind:z$(V.kind),status:T,startedAt:R,completedAt:T==="running"?null:R,inputPreview:l(V.rawInput),outputPreview:H$(V.rawOutput),contentPreview:E0(V.content),locations:U$(V.locations)});return}case"tool_call_update":{let F=H.get(V.toolCallId);if(!F){let p=O1(V.title),B0=Y$(V.status),X0=new Date().toISOString();B({toolCallId:V.toolCallId,rawTitle:p,title:G$(p,V.rawInput),kind:z$(V.kind),status:B0,startedAt:X0,completedAt:B0==="running"?null:X0,inputPreview:l(V.rawInput),outputPreview:H$(V.rawOutput),contentPreview:E0(V.content),locations:U$(V.locations)});return}let T=V.status===void 0||V.status===null?F.status:Y$(V.status),R=typeof V.title==="string"&&V.title.trim().length>0?V.title:F.rawTitle,L=typeof V.title==="string"&&V.title.trim().length>0,f=T==="running"?F.completedAt:F.completedAt??new Date().toISOString(),E=V.content===void 0?F.contentPreview:A1(F.contentPreview,E0(V.content)),I=V.rawOutput===void 0?F.outputPreview:A1(F.outputPreview,H$(V.rawOutput));B({...F,rawTitle:R,title:L?G$(R,V.rawInput):F.title,kind:V.kind===void 0?F.kind:z$(V.kind),status:T,completedAt:f,inputPreview:V.rawInput===void 0?F.inputPreview:l(V.rawInput),outputPreview:I,contentPreview:E,locations:V.locations===void 0?F.locations:U$(V.locations)});return}case"plan":z=V.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>j,getToolCallCount:()=>G,getLatestPlan:()=>z,getUpdateTypeCounts:()=>({...K}),flush:(P)=>{let V=new Date().toISOString();if(U(V),P?.completeOpenToolCalls)N(V);A()}}}var U0=1,T1=-32000;function R1($){if($.awaitingInput)return!1;return $.nowMs-$.lastUpdateMs>$.windowMs}function y1($){if(!$||typeof $!=="object")return!1;return $.code===T1}var k6=300000,O6=5000;function b1(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.44".trim()?"0.0.44":"dev"}}function v1($){if($===U0)return;throw new O(`Unsupported ACP protocol version ${$}; expected ${U0}`)}function I1($){return P6.toWeb($)}function h1($){return L6.toWeb($)}function D$($){return $!==null&&typeof $==="object"}function _6($){if(!Array.isArray($))return[];let X=[];for(let Z of $){if(!D$(Z))continue;if(typeof Z.group==="string"&&Array.isArray(Z.options)){let J=typeof Z.name==="string"?Z.name:Z.group;for(let Q of Z.options){if(!D$(Q))continue;if(typeof Q.value!=="string"||typeof Q.name!=="string")continue;X.push({value:Q.value,name:Q.name,description:typeof Q.description==="string"?Q.description:null,group:Z.group,groupName:J})}continue}if(typeof Z.value!=="string"||typeof Z.name!=="string")continue;X.push({value:Z.value,name:Z.name,description:typeof Z.description==="string"?Z.description:null,group:null,groupName:null})}return X}function A6($){if(!D$($))return null;if(typeof $.id!=="string"||typeof $.name!=="string")return null;let X=typeof $.category==="string"?$.category:null,Z=typeof $.description==="string"?$.description:null;if($.type==="select"){let J=typeof $.currentValue==="string"?$.currentValue:null;return{id:$.id,name:$.name,category:X,description:Z,type:"select",currentValue:J,options:_6($.options)}}if($.type==="boolean"){let J=typeof $.currentValue==="boolean"?$.currentValue:typeof $.value==="boolean"?$.value:null;return{id:$.id,name:$.name,category:X,description:Z,type:"boolean",currentValue:J,options:[]}}return null}function M$($){let X=($.configOptions??[]).map(A6).filter((G)=>G!==null),Z=X.find((G)=>G.type==="select"&&G.category==="model")??X.find((G)=>G.type==="select"&&G.id==="model")??null,J=Z?.options.map((G)=>({id:G.value,name:G.name,description:G.description??null})),Q=w6($.models),j=J&&J.length>0?J:Q&&Q.length>0?Q:null,W=(typeof Z?.currentValue==="string"?Z.currentValue:null)??T6($.models)??null;return{models:j,currentModelId:W,configOptions:X,modelConfigId:Z?.id??null}}function w6($){if(!$||!Array.isArray($.availableModels))return null;let X=[];for(let Z of $.availableModels){if(typeof Z.modelId!=="string")continue;X.push({id:Z.modelId,name:typeof Z.name==="string"?Z.name:null,description:typeof Z.description==="string"?Z.description:null})}return X.length>0?X:null}function T6($){return typeof $?.currentModelId==="string"?$.currentModelId:null}function R6($,X){let Z=[];if($.trim())Z.push({type:"text",text:$});for(let J of X)if(J.content.trim())Z.push({type:"text",text:J.content});return Z}function f6($){if(typeof $.value==="boolean")return{sessionId:$.sessionId,configId:$.configId,type:"boolean",value:$.value};return{sessionId:$.sessionId,configId:$.configId,value:$.value}}function E6($,X){let Z=M$({configOptions:X.configOptions});return{models:Z.models??$.models,currentModelId:Z.currentModelId??$.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??$.modelConfigId}}function S1($,X){if($==="default")return null;if(!X||X.length===0)return $;let Z=X.find((K)=>K.id===$);if(Z)return Z.id;let J=$.toLowerCase(),Q=J.includes("opus")?"opus":J.includes("sonnet")?"sonnet":J.includes("haiku")?"haiku":null;if(!Q)return $;let j=(K)=>`${K.id} ${K.name??""} ${K.description??""}`.toLowerCase(),W=X.filter((K)=>j(K).includes(Q));if(W.length===0)return $;let z=(J.includes("1m")?W.find((K)=>j(K).includes("1m")):void 0)??W[0];return z?z.id:$}async function b0($){try{let X=await $.conn.setSessionConfigOption(f6({sessionId:$.sessionId,configId:$.configId,value:$.value}));return E6($.metadata,X)}catch(X){return console.warn(`[acp] setSessionConfigOption(${$.label}) failed; using agent default.`,X instanceof Error?X.message:X),$.metadata}}async function N$($){let X=K$($.spawn),Z=[],J=0,Q=4096;X.stderr.on("data",(L)=>{Z.push(L),J+=L.length;while(J>Q*2&&Z.length>1){let f=Z.shift();if(f)J-=f.length}});let j=()=>{let L=Buffer.concat(Z).toString("utf8");return L.length>Q?L.slice(-Q):L},W=k1($.spawn.cwd),G={current:null},z={at:Date.now()},K=h1(X.stdin),H=I1(X.stdout),B=E1(K,H),M=new f1((L)=>({requestPermission:async(f)=>{let E=f.options,I=E?.find((p)=>p.kind==="allow_once")??E?.find((p)=>p.kind==="allow_always");if(I)return{outcome:{outcome:"selected",optionId:I.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(f)=>{z.at=Date.now();let E=G.current;if(E)await E.onSessionUpdate(f)},readTextFile:W.readTextFile}),B),N=()=>X.kill();if($.signal)$.signal.addEventListener("abort",N);let C=()=>{if($.signal)$.signal.removeEventListener("abort",N)},Y=async(L,f)=>{if(C(),X.kill(),y1(L))throw new J0(L.message??"Authentication required",f);if(L instanceof Error&&L.message==="ACP connection closed"){if($.signal?.aborted)throw new O("ACP session cancelled: abort signal received");let E=await Promise.race([X.processCrashed,X.waitForExit,new Promise((I)=>setTimeout(()=>I({stderr:""}),500))]);throw new O(`Runtime process exited before completion: ${E.stderr?.trim()??""}`)}throw L},D;try{D=await M.initialize({protocolVersion:U0,clientCapabilities:W$,clientInfo:b1()})}catch(L){throw await Y(L,[]),Error("unreachable")}try{v1(D.protocolVersion)}catch(L){throw C(),X.kill(),L}let x=D.authMethods?.map((L)=>L.id)??[],k;try{k=await M.newSession({cwd:$.spawn.cwd,mcpServers:$.mcpServers??[]})}catch(L){throw await Y(L,x),Error("unreachable")}let A=k.sessionId,_=M$(k),P=$.modelId??null,V=P?S1(P,_.models):null;if(V&&V!==_.currentModelId)if(_.modelConfigId)_=await b0({conn:M,sessionId:A,configId:_.modelConfigId,value:V,metadata:_,label:`${_.modelConfigId}=${V}`});else console.warn(`[acp] runtime did not advertise a model config option for ${V}; using agent default.`);for(let[L,f]of Object.entries($.configValues??{}).sort(([E],[I])=>E.localeCompare(I))){if(L===_.modelConfigId)continue;if(!_.configOptions.some((E)=>E.id===L))continue;_=await b0({conn:M,sessionId:A,configId:L,value:f,metadata:_,label:`${L}=${String(f)}`})}C();let F=!1,T=async()=>{if(F)return;F=!0,X.kill(),await Promise.race([X.waitForExit,new Promise((L)=>setTimeout(L,2000))])},R=!1;return X.processCrashed.then(()=>{R=!0}),{sessionId:A,availableModels:_.models,currentModelId:_.currentModelId,availableConfigOptions:_.configOptions,isAlive:()=>!F&&!R,dispose:T,prompt:(L)=>y6({proc:X,conn:M,sessionId:A,activeAdapter:G,lastUpdate:z,collectStderrTail:j},L)}}async function y6($,X){let{proc:Z,conn:J,sessionId:Q,activeAdapter:j,lastUpdate:W}=$,G={boardId:X.boardId,cardId:X.cardId,runId:X.runId},z=w1({ctx:G,appendText:X.appendText,appendToolActivity:X.appendToolActivity});j.current=z,W.at=Date.now();let K=!1,H=null,B=()=>Z.kill();X.signal.addEventListener("abort",B);try{let U=async()=>{let Y=X.heartbeatMs??k6,D=Math.min(O6,Math.max(50,Math.floor(Y/2)));H=setInterval(()=>{let k=X.isAwaitingInput?.()??!1;if(k){W.at=Date.now();return}if(R1({nowMs:Date.now(),lastUpdateMs:W.at,windowMs:Y,awaitingInput:k}))K=!0,J.cancel({sessionId:Q}).catch(()=>{return}),Z.kill()},D);let x=R6(X.prompt.systemPrompt,X.prompt.messages);await J.prompt({sessionId:Q,prompt:x}),z.flush({completeOpenToolCalls:!0})},M=Z.waitForExit.then((Y)=>({kind:"exited",exit:Y})),N=U().then(()=>({kind:"ok"})).catch(async(Y)=>{if(Y instanceof Error&&Y.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw Y}),C;try{C=await Promise.race([N,Z.processCrashed.then((Y)=>({kind:"crashed",exit:Y})),M])}catch(Y){if(K)throw new a;throw Y}if(K)throw new a;if(C.kind==="crashed")throw new O(`Runtime process exited before completion: ${C.exit.stderr.trim()}`);if(C.kind==="exited"){if(X.signal.aborted)throw new O("ACP session cancelled: abort signal received");if(K)throw new a;throw new O(`Runtime process exited unexpectedly: ${C.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:z.getFinalText(),toolCallsExecuted:z.getToolCallCount(),stderrTail:$.collectStderrTail(),updateTypeCounts:z.getUpdateTypeCounts()}}finally{if(H!==null)clearInterval(H);X.signal.removeEventListener("abort",B),z.flush({completeOpenToolCalls:!0}),j.current=null}}var b6=30000;async function m1($){let X=K$($.spawn),Z=h1(X.stdin),J=I1(X.stdout),Q=E1(Z,J),W=new f1((K)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),G=()=>X.kill();if($.signal)$.signal.addEventListener("abort",G);let z=null;try{let K=(async()=>{let B=await W.initialize({protocolVersion:U0,clientCapabilities:W$,clientInfo:b1()});v1(B.protocolVersion);let U=B.authMethods?.map((k)=>k.id)??[],M;try{M=await W.newSession({cwd:$.spawn.cwd,mcpServers:[]})}catch(k){if(y1(k))throw new J0(k.message??"Authentication required",U);throw k}let N=M$(M),C=$.modelId??null,Y=C?S1(C,N.models):null;if(Y&&Y!==N.currentModelId)if(N.modelConfigId)N=await b0({conn:W,sessionId:M.sessionId,configId:N.modelConfigId,value:Y,metadata:N,label:`${N.modelConfigId}=${Y}`});else console.warn(`[acp] runtime did not advertise a model config option for ${Y}; discovering agent default models.`);for(let[k,A]of Object.entries($.configValues??{}).sort(([_],[P])=>_.localeCompare(P))){if(k===N.modelConfigId)continue;if(!N.configOptions.some((_)=>_.id===k))continue;N=await b0({conn:W,sessionId:M.sessionId,configId:k,value:A,metadata:N,label:`${k}=${String(A)}`})}let D=N.models??[],x=N.currentModelId;return W.cancel({sessionId:M.sessionId}).catch(()=>{return}),{models:D,configOptions:N.configOptions,currentModelId:x}})(),H=new Promise((B,U)=>{z=setTimeout(()=>{U(new a)},b6)});return await Promise.race([K,H])}catch(K){if(K instanceof Error&&K.message==="ACP connection closed"){if($.signal?.aborted)throw new O("ACP model discovery cancelled: abort signal received");throw new O("Runtime process exited during model discovery.")}throw K}finally{if(z)clearTimeout(z);if($.signal)$.signal.removeEventListener("abort",G);X.kill()}}var y=new Map,u=null;function v0($){$.then((X)=>X.dispose()).catch(()=>{return})}function v6(){if(u!==null)return;u=setInterval(()=>{let $=Date.now();for(let[X,Z]of y){if(Z.inUse)continue;if($-Z.lastUsed<600000)continue;y.delete(X),v0(Z.sessionPromise)}if(y.size===0&&u!==null)clearInterval(u),u=null},60000),u.unref?.()}function I6(){if(y.size<200)return;let $=null,X=1/0;for(let[J,Q]of y){if(Q.inUse)continue;if(Q.lastUsed>=X)continue;$=J,X=Q.lastUsed}if(!$)return;let Z=y.get($);if(!Z)return;y.delete($),v0(Z.sessionPromise)}function q$($,X,Z){return`${$}:${X}:${Z}`}async function B$($){let X=y.get($.key);if(X)if(X.fingerprint===$.fingerprint){X.inUse=!0,X.lastUsed=Date.now();try{let J=await X.sessionPromise;if(J.isAlive())return J}catch{}y.delete($.key)}else y.delete($.key),v0(X.sessionPromise);let Z=$.open();I6(),y.set($.key,{key:$.key,fingerprint:$.fingerprint,sessionPromise:Z,lastUsed:Date.now(),inUse:!0}),v6();try{return await Z}catch(J){throw y.delete($.key),J}}function x$($,X=!1){let Z=y.get($);if(!Z)return;if(X){y.delete($),v0(Z.sessionPromise);return}Z.inUse=!1,Z.lastUsed=Date.now()}async function h6(){let $=Array.from(y.values());if(y.clear(),u!==null)clearInterval(u),u=null;await Promise.all($.map((X)=>X.sessionPromise.then((Z)=>Z.dispose()).catch(()=>{return})))}function C$($){let X=Object.entries($.configValues??{}),Z=X.length>0?JSON.stringify(Object.fromEntries(X.sort(([J],[Q])=>J.localeCompare(Q)))):"";return[$.adapterId,$.configId??"",$.modelId??"",Z,$.mcpUrl??"",$.runFolder??"",$.toolSurface??"full"].join(" ")}var g1=!1;function S6(){if(g1)return;g1=!0;let $=()=>{h6()};process.once("beforeExit",$),process.once("SIGTERM",$),process.once("SIGINT",$)}S6();import m6 from"node:fs/promises";import I0 from"node:os";async function c1($){let X={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await m6.readFile($,"utf-8")}catch(J){if(J.code==="ENOENT")return structuredClone(X);throw J}return C0.parse(JSON.parse(Z))}function F$($,X,Z){return{...$.defaultConfigValues??{},...X?.configValues??{},...Z?.configValues??{}}}async function i($){let X=$.configPath?await c1($.configPath):await h(),Z=$.cardId?X.cardOverrides[$.cardId]:void 0;if(Z?.runtimeConfigId){let Q=X.runtimes.find((j)=>j.id===Z.runtimeConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:Z.runFolder??Q.runFolder??I0.homedir(),modelId:Z.modelId??Q.defaultModelId??null,configValues:F$(Q,void 0,Z)}}let J=X.boardOverrides[$.boardId];if(J?.runtimeConfigId){let Q=X.runtimes.find((j)=>j.id===J.runtimeConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:J.runFolder??Q.runFolder??I0.homedir(),modelId:J.modelId??Q.defaultModelId??null,configValues:F$(Q,J)}}if(X.globalDefaultConfigId){let Q=X.runtimes.find((j)=>j.id===X.globalDefaultConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:Z?.runFolder??J?.runFolder??Q.runFolder??I0.homedir(),modelId:Z?.modelId??J?.modelId??Q.defaultModelId??null,configValues:F$(Q,J,Z)}}throw new t}async function l1($,X={}){let J=(X.configPath?await c1(X.configPath):await h()).runtimes.find((Q)=>Q.id===$);if(!J)return null;return{entry:J,adapter:c(J),runFolder:J.runFolder??I0.homedir(),modelId:X.modelId??J.defaultModelId??null,configValues:{...J.defaultConfigValues??{},...X.configValues??{}}}}var u1=new Map;function P$($,X){if(!$)return;u1.set($,X)}function p1($){if(!$)return!1;return u1.get($)??!1}var $0=new Map,L$=new Set;function k$($){$0.get($)?.controller.abort()}function a1($){for(let[X,Z]of $0){if(Z.frontendSessionId!==$)continue;Z.controller.abort(),$0.delete(X)}}function d1(){for(let $ of $0.values())$.controller.abort();$0.clear()}function i1($,X){if(X?.aborted)return!0;return $ instanceof Error&&/abort signal received|session cancelled/i.test($.message)}function n1($,X,Z,J){if((!X.availableModels||X.availableModels.length===0)&&X.availableConfigOptions.length===0)return;g((Q)=>{let j=Q.runtimes.find((W)=>W.id===$);if(j){if(X.availableModels&&X.availableModels.length>0)j.discoveredModels=w0({adapterId:Z,models:X.availableModels,currentModelId:X.currentModelId??J});if(X.availableConfigOptions.length>0)j.discoveredConfigOptions=X.availableConfigOptions}}).catch(()=>{return})}function g6($,X){return`${$}
18
+ ${X}`)}function U$($){if(!Array.isArray($))return null;let X=$.flatMap((Z)=>{if(!Z||typeof Z!=="object")return[];let J=Z;if(typeof J.path!=="string"||!J.path.trim())return[];let Q=typeof J.line==="number"?`:${J.line}`:"";return[`${J.path}${Q}`]});return X.length>0?X.slice(0,5):null}function w1($){let{ctx:X,appendText:Z,appendToolActivity:J}=$,Q=$.flushIntervalMs??C6,j="",W="",G=0,z=null,K={},H=new Map,B=(P)=>{if(H.set(P.toolCallId,P),!J)return;J({boardId:X.boardId,cardId:X.cardId,runId:X.runId,entry:P}).catch((V)=>{console.warn("[streamAdapter] appendToolActivity failed",V)})},U=(P)=>{let V=`${X.runId}:thought`,F=H.get(V);if(!F||F.status!=="running")return;B({...F,status:"completed",completedAt:F.completedAt??P})},M=(P)=>{for(let V of H.values()){if(V.status!=="running"||V.rawTitle.toLowerCase()!=="toolsearch")continue;B({...V,status:"completed",completedAt:V.completedAt??P})}},N=(P)=>{for(let V of Array.from(H.values())){if(V.status!=="running")continue;if(V.kind==="thought"||V.rawTitle==="agent_thought")continue;B({...V,status:"completed",completedAt:V.completedAt??P})}},C="",Y=0,D=null,x=null,k=(P)=>{if(P===C)return;C=P,Y=Date.now(),Z({boardId:X.boardId,cardId:X.cardId,runId:X.runId,text:P}).catch((V)=>{console.warn("[streamAdapter] appendText failed",V)})},A=()=>{if(D!==null)clearTimeout(D),D=null;if(x!==null){let P=x;x=null,k(P)}},_=(P)=>{let V=Date.now()-Y;if(V>=Q&&D===null){k(P);return}if(x=P,D===null){let F=Math.max(0,Q-V);D=setTimeout(()=>{D=null,A()},F)}};return{onSessionUpdate:async(P)=>{let V=P.update;switch(K[V.sessionUpdate]=(K[V.sessionUpdate]??0)+1,V.sessionUpdate){case"agent_message_chunk":{let F=new Date().toISOString();if(U(F),V.content.type==="text")j+=V.content.text,_(j);else{let T=`agent_message_chunk:${V.content.type}`;K[T]=(K[T]??0)+1}return}case"agent_thought_chunk":{if(V.content.type!=="text")return;W+=V.content.text;let F=new Date().toISOString(),T=`${X.runId}:thought`,R=H.get(T);B({toolCallId:T,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:R?.startedAt??F,completedAt:null,contentPreview:e(W.trim())});return}case"user_message_chunk":return;case"tool_call":{G+=1;let F=O1(V.title),T=Y$(V.status),R=new Date().toISOString();U(R),M(R),B({toolCallId:V.toolCallId,rawTitle:F,title:G$(F,V.rawInput),kind:z$(V.kind),status:T,startedAt:R,completedAt:T==="running"?null:R,inputPreview:l(V.rawInput),outputPreview:H$(V.rawOutput),contentPreview:E0(V.content),locations:U$(V.locations)});return}case"tool_call_update":{let F=H.get(V.toolCallId);if(!F){let p=O1(V.title),B0=Y$(V.status),X0=new Date().toISOString();B({toolCallId:V.toolCallId,rawTitle:p,title:G$(p,V.rawInput),kind:z$(V.kind),status:B0,startedAt:X0,completedAt:B0==="running"?null:X0,inputPreview:l(V.rawInput),outputPreview:H$(V.rawOutput),contentPreview:E0(V.content),locations:U$(V.locations)});return}let T=V.status===void 0||V.status===null?F.status:Y$(V.status),R=typeof V.title==="string"&&V.title.trim().length>0?V.title:F.rawTitle,L=typeof V.title==="string"&&V.title.trim().length>0,f=T==="running"?F.completedAt:F.completedAt??new Date().toISOString(),E=V.content===void 0?F.contentPreview:A1(F.contentPreview,E0(V.content)),I=V.rawOutput===void 0?F.outputPreview:A1(F.outputPreview,H$(V.rawOutput));B({...F,rawTitle:R,title:L?G$(R,V.rawInput):F.title,kind:V.kind===void 0?F.kind:z$(V.kind),status:T,completedAt:f,inputPreview:V.rawInput===void 0?F.inputPreview:l(V.rawInput),outputPreview:I,contentPreview:E,locations:V.locations===void 0?F.locations:U$(V.locations)});return}case"plan":z=V.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>j,getToolCallCount:()=>G,getLatestPlan:()=>z,getUpdateTypeCounts:()=>({...K}),flush:(P)=>{let V=new Date().toISOString();if(U(V),P?.completeOpenToolCalls)N(V);A()}}}var U0=1,T1=-32000;function R1($){if($.awaitingInput)return!1;return $.nowMs-$.lastUpdateMs>$.windowMs}function y1($){if(!$||typeof $!=="object")return!1;return $.code===T1}var k6=300000,O6=5000;function b1(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.45".trim()?"0.0.45":"dev"}}function v1($){if($===U0)return;throw new O(`Unsupported ACP protocol version ${$}; expected ${U0}`)}function I1($){return P6.toWeb($)}function h1($){return L6.toWeb($)}function D$($){return $!==null&&typeof $==="object"}function _6($){if(!Array.isArray($))return[];let X=[];for(let Z of $){if(!D$(Z))continue;if(typeof Z.group==="string"&&Array.isArray(Z.options)){let J=typeof Z.name==="string"?Z.name:Z.group;for(let Q of Z.options){if(!D$(Q))continue;if(typeof Q.value!=="string"||typeof Q.name!=="string")continue;X.push({value:Q.value,name:Q.name,description:typeof Q.description==="string"?Q.description:null,group:Z.group,groupName:J})}continue}if(typeof Z.value!=="string"||typeof Z.name!=="string")continue;X.push({value:Z.value,name:Z.name,description:typeof Z.description==="string"?Z.description:null,group:null,groupName:null})}return X}function A6($){if(!D$($))return null;if(typeof $.id!=="string"||typeof $.name!=="string")return null;let X=typeof $.category==="string"?$.category:null,Z=typeof $.description==="string"?$.description:null;if($.type==="select"){let J=typeof $.currentValue==="string"?$.currentValue:null;return{id:$.id,name:$.name,category:X,description:Z,type:"select",currentValue:J,options:_6($.options)}}if($.type==="boolean"){let J=typeof $.currentValue==="boolean"?$.currentValue:typeof $.value==="boolean"?$.value:null;return{id:$.id,name:$.name,category:X,description:Z,type:"boolean",currentValue:J,options:[]}}return null}function M$($){let X=($.configOptions??[]).map(A6).filter((G)=>G!==null),Z=X.find((G)=>G.type==="select"&&G.category==="model")??X.find((G)=>G.type==="select"&&G.id==="model")??null,J=Z?.options.map((G)=>({id:G.value,name:G.name,description:G.description??null})),Q=w6($.models),j=J&&J.length>0?J:Q&&Q.length>0?Q:null,W=(typeof Z?.currentValue==="string"?Z.currentValue:null)??T6($.models)??null;return{models:j,currentModelId:W,configOptions:X,modelConfigId:Z?.id??null}}function w6($){if(!$||!Array.isArray($.availableModels))return null;let X=[];for(let Z of $.availableModels){if(typeof Z.modelId!=="string")continue;X.push({id:Z.modelId,name:typeof Z.name==="string"?Z.name:null,description:typeof Z.description==="string"?Z.description:null})}return X.length>0?X:null}function T6($){return typeof $?.currentModelId==="string"?$.currentModelId:null}function R6($,X){let Z=[];if($.trim())Z.push({type:"text",text:$});for(let J of X)if(J.content.trim())Z.push({type:"text",text:J.content});return Z}function f6($){if(typeof $.value==="boolean")return{sessionId:$.sessionId,configId:$.configId,type:"boolean",value:$.value};return{sessionId:$.sessionId,configId:$.configId,value:$.value}}function E6($,X){let Z=M$({configOptions:X.configOptions});return{models:Z.models??$.models,currentModelId:Z.currentModelId??$.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??$.modelConfigId}}function S1($,X){if($==="default")return null;if(!X||X.length===0)return $;let Z=X.find((K)=>K.id===$);if(Z)return Z.id;let J=$.toLowerCase(),Q=J.includes("opus")?"opus":J.includes("sonnet")?"sonnet":J.includes("haiku")?"haiku":null;if(!Q)return $;let j=(K)=>`${K.id} ${K.name??""} ${K.description??""}`.toLowerCase(),W=X.filter((K)=>j(K).includes(Q));if(W.length===0)return $;let z=(J.includes("1m")?W.find((K)=>j(K).includes("1m")):void 0)??W[0];return z?z.id:$}async function b0($){try{let X=await $.conn.setSessionConfigOption(f6({sessionId:$.sessionId,configId:$.configId,value:$.value}));return E6($.metadata,X)}catch(X){return console.warn(`[acp] setSessionConfigOption(${$.label}) failed; using agent default.`,X instanceof Error?X.message:X),$.metadata}}async function N$($){let X=K$($.spawn),Z=[],J=0,Q=4096;X.stderr.on("data",(L)=>{Z.push(L),J+=L.length;while(J>Q*2&&Z.length>1){let f=Z.shift();if(f)J-=f.length}});let j=()=>{let L=Buffer.concat(Z).toString("utf8");return L.length>Q?L.slice(-Q):L},W=k1($.spawn.cwd),G={current:null},z={at:Date.now()},K=h1(X.stdin),H=I1(X.stdout),B=E1(K,H),M=new f1((L)=>({requestPermission:async(f)=>{let E=f.options,I=E?.find((p)=>p.kind==="allow_once")??E?.find((p)=>p.kind==="allow_always");if(I)return{outcome:{outcome:"selected",optionId:I.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(f)=>{z.at=Date.now();let E=G.current;if(E)await E.onSessionUpdate(f)},readTextFile:W.readTextFile}),B),N=()=>X.kill();if($.signal)$.signal.addEventListener("abort",N);let C=()=>{if($.signal)$.signal.removeEventListener("abort",N)},Y=async(L,f)=>{if(C(),X.kill(),y1(L))throw new J0(L.message??"Authentication required",f);if(L instanceof Error&&L.message==="ACP connection closed"){if($.signal?.aborted)throw new O("ACP session cancelled: abort signal received");let E=await Promise.race([X.processCrashed,X.waitForExit,new Promise((I)=>setTimeout(()=>I({stderr:""}),500))]);throw new O(`Runtime process exited before completion: ${E.stderr?.trim()??""}`)}throw L},D;try{D=await M.initialize({protocolVersion:U0,clientCapabilities:W$,clientInfo:b1()})}catch(L){throw await Y(L,[]),Error("unreachable")}try{v1(D.protocolVersion)}catch(L){throw C(),X.kill(),L}let x=D.authMethods?.map((L)=>L.id)??[],k;try{k=await M.newSession({cwd:$.spawn.cwd,mcpServers:$.mcpServers??[]})}catch(L){throw await Y(L,x),Error("unreachable")}let A=k.sessionId,_=M$(k),P=$.modelId??null,V=P?S1(P,_.models):null;if(V&&V!==_.currentModelId)if(_.modelConfigId)_=await b0({conn:M,sessionId:A,configId:_.modelConfigId,value:V,metadata:_,label:`${_.modelConfigId}=${V}`});else console.warn(`[acp] runtime did not advertise a model config option for ${V}; using agent default.`);for(let[L,f]of Object.entries($.configValues??{}).sort(([E],[I])=>E.localeCompare(I))){if(L===_.modelConfigId)continue;if(!_.configOptions.some((E)=>E.id===L))continue;_=await b0({conn:M,sessionId:A,configId:L,value:f,metadata:_,label:`${L}=${String(f)}`})}C();let F=!1,T=async()=>{if(F)return;F=!0,X.kill(),await Promise.race([X.waitForExit,new Promise((L)=>setTimeout(L,2000))])},R=!1;return X.processCrashed.then(()=>{R=!0}),{sessionId:A,availableModels:_.models,currentModelId:_.currentModelId,availableConfigOptions:_.configOptions,isAlive:()=>!F&&!R,dispose:T,prompt:(L)=>y6({proc:X,conn:M,sessionId:A,activeAdapter:G,lastUpdate:z,collectStderrTail:j},L)}}async function y6($,X){let{proc:Z,conn:J,sessionId:Q,activeAdapter:j,lastUpdate:W}=$,G={boardId:X.boardId,cardId:X.cardId,runId:X.runId},z=w1({ctx:G,appendText:X.appendText,appendToolActivity:X.appendToolActivity});j.current=z,W.at=Date.now();let K=!1,H=null,B=()=>Z.kill();X.signal.addEventListener("abort",B);try{let U=async()=>{let Y=X.heartbeatMs??k6,D=Math.min(O6,Math.max(50,Math.floor(Y/2)));H=setInterval(()=>{let k=X.isAwaitingInput?.()??!1;if(k){W.at=Date.now();return}if(R1({nowMs:Date.now(),lastUpdateMs:W.at,windowMs:Y,awaitingInput:k}))K=!0,J.cancel({sessionId:Q}).catch(()=>{return}),Z.kill()},D);let x=R6(X.prompt.systemPrompt,X.prompt.messages);await J.prompt({sessionId:Q,prompt:x}),z.flush({completeOpenToolCalls:!0})},M=Z.waitForExit.then((Y)=>({kind:"exited",exit:Y})),N=U().then(()=>({kind:"ok"})).catch(async(Y)=>{if(Y instanceof Error&&Y.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw Y}),C;try{C=await Promise.race([N,Z.processCrashed.then((Y)=>({kind:"crashed",exit:Y})),M])}catch(Y){if(K)throw new a;throw Y}if(K)throw new a;if(C.kind==="crashed")throw new O(`Runtime process exited before completion: ${C.exit.stderr.trim()}`);if(C.kind==="exited"){if(X.signal.aborted)throw new O("ACP session cancelled: abort signal received");if(K)throw new a;throw new O(`Runtime process exited unexpectedly: ${C.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:z.getFinalText(),toolCallsExecuted:z.getToolCallCount(),stderrTail:$.collectStderrTail(),updateTypeCounts:z.getUpdateTypeCounts()}}finally{if(H!==null)clearInterval(H);X.signal.removeEventListener("abort",B),z.flush({completeOpenToolCalls:!0}),j.current=null}}var b6=30000;async function m1($){let X=K$($.spawn),Z=h1(X.stdin),J=I1(X.stdout),Q=E1(Z,J),W=new f1((K)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),G=()=>X.kill();if($.signal)$.signal.addEventListener("abort",G);let z=null;try{let K=(async()=>{let B=await W.initialize({protocolVersion:U0,clientCapabilities:W$,clientInfo:b1()});v1(B.protocolVersion);let U=B.authMethods?.map((k)=>k.id)??[],M;try{M=await W.newSession({cwd:$.spawn.cwd,mcpServers:[]})}catch(k){if(y1(k))throw new J0(k.message??"Authentication required",U);throw k}let N=M$(M),C=$.modelId??null,Y=C?S1(C,N.models):null;if(Y&&Y!==N.currentModelId)if(N.modelConfigId)N=await b0({conn:W,sessionId:M.sessionId,configId:N.modelConfigId,value:Y,metadata:N,label:`${N.modelConfigId}=${Y}`});else console.warn(`[acp] runtime did not advertise a model config option for ${Y}; discovering agent default models.`);for(let[k,A]of Object.entries($.configValues??{}).sort(([_],[P])=>_.localeCompare(P))){if(k===N.modelConfigId)continue;if(!N.configOptions.some((_)=>_.id===k))continue;N=await b0({conn:W,sessionId:M.sessionId,configId:k,value:A,metadata:N,label:`${k}=${String(A)}`})}let D=N.models??[],x=N.currentModelId;return W.cancel({sessionId:M.sessionId}).catch(()=>{return}),{models:D,configOptions:N.configOptions,currentModelId:x}})(),H=new Promise((B,U)=>{z=setTimeout(()=>{U(new a)},b6)});return await Promise.race([K,H])}catch(K){if(K instanceof Error&&K.message==="ACP connection closed"){if($.signal?.aborted)throw new O("ACP model discovery cancelled: abort signal received");throw new O("Runtime process exited during model discovery.")}throw K}finally{if(z)clearTimeout(z);if($.signal)$.signal.removeEventListener("abort",G);X.kill()}}var y=new Map,u=null;function v0($){$.then((X)=>X.dispose()).catch(()=>{return})}function v6(){if(u!==null)return;u=setInterval(()=>{let $=Date.now();for(let[X,Z]of y){if(Z.inUse)continue;if($-Z.lastUsed<600000)continue;y.delete(X),v0(Z.sessionPromise)}if(y.size===0&&u!==null)clearInterval(u),u=null},60000),u.unref?.()}function I6(){if(y.size<200)return;let $=null,X=1/0;for(let[J,Q]of y){if(Q.inUse)continue;if(Q.lastUsed>=X)continue;$=J,X=Q.lastUsed}if(!$)return;let Z=y.get($);if(!Z)return;y.delete($),v0(Z.sessionPromise)}function q$($,X,Z){return`${$}:${X}:${Z}`}async function B$($){let X=y.get($.key);if(X)if(X.fingerprint===$.fingerprint){X.inUse=!0,X.lastUsed=Date.now();try{let J=await X.sessionPromise;if(J.isAlive())return J}catch{}y.delete($.key)}else y.delete($.key),v0(X.sessionPromise);let Z=$.open();I6(),y.set($.key,{key:$.key,fingerprint:$.fingerprint,sessionPromise:Z,lastUsed:Date.now(),inUse:!0}),v6();try{return await Z}catch(J){throw y.delete($.key),J}}function x$($,X=!1){let Z=y.get($);if(!Z)return;if(X){y.delete($),v0(Z.sessionPromise);return}Z.inUse=!1,Z.lastUsed=Date.now()}async function h6(){let $=Array.from(y.values());if(y.clear(),u!==null)clearInterval(u),u=null;await Promise.all($.map((X)=>X.sessionPromise.then((Z)=>Z.dispose()).catch(()=>{return})))}function C$($){let X=Object.entries($.configValues??{}),Z=X.length>0?JSON.stringify(Object.fromEntries(X.sort(([J],[Q])=>J.localeCompare(Q)))):"";return[$.adapterId,$.configId??"",$.modelId??"",Z,$.mcpUrl??"",$.runFolder??"",$.toolSurface??"full"].join(" ")}var g1=!1;function S6(){if(g1)return;g1=!0;let $=()=>{h6()};process.once("beforeExit",$),process.once("SIGTERM",$),process.once("SIGINT",$)}S6();import m6 from"node:fs/promises";import I0 from"node:os";async function c1($){let X={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await m6.readFile($,"utf-8")}catch(J){if(J.code==="ENOENT")return structuredClone(X);throw J}return C0.parse(JSON.parse(Z))}function F$($,X,Z){return{...$.defaultConfigValues??{},...X?.configValues??{},...Z?.configValues??{}}}async function i($){let X=$.configPath?await c1($.configPath):await h(),Z=$.cardId?X.cardOverrides[$.cardId]:void 0;if(Z?.runtimeConfigId){let Q=X.runtimes.find((j)=>j.id===Z.runtimeConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:Z.runFolder??Q.runFolder??I0.homedir(),modelId:Z.modelId??Q.defaultModelId??null,configValues:F$(Q,void 0,Z)}}let J=X.boardOverrides[$.boardId];if(J?.runtimeConfigId){let Q=X.runtimes.find((j)=>j.id===J.runtimeConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:J.runFolder??Q.runFolder??I0.homedir(),modelId:J.modelId??Q.defaultModelId??null,configValues:F$(Q,J)}}if(X.globalDefaultConfigId){let Q=X.runtimes.find((j)=>j.id===X.globalDefaultConfigId);if(Q)return{entry:Q,adapter:c(Q),runFolder:Z?.runFolder??J?.runFolder??Q.runFolder??I0.homedir(),modelId:Z?.modelId??J?.modelId??Q.defaultModelId??null,configValues:F$(Q,J,Z)}}throw new t}async function l1($,X={}){let J=(X.configPath?await c1(X.configPath):await h()).runtimes.find((Q)=>Q.id===$);if(!J)return null;return{entry:J,adapter:c(J),runFolder:J.runFolder??I0.homedir(),modelId:X.modelId??J.defaultModelId??null,configValues:{...J.defaultConfigValues??{},...X.configValues??{}}}}var u1=new Map;function P$($,X){if(!$)return;u1.set($,X)}function p1($){if(!$)return!1;return u1.get($)??!1}var $0=new Map,L$=new Set;function k$($){$0.get($)?.controller.abort()}function a1($){for(let[X,Z]of $0){if(Z.frontendSessionId!==$)continue;Z.controller.abort(),$0.delete(X)}}function d1(){for(let $ of $0.values())$.controller.abort();$0.clear()}function i1($,X){if(X?.aborted)return!0;return $ instanceof Error&&/abort signal received|session cancelled/i.test($.message)}function n1($,X,Z,J){if((!X.availableModels||X.availableModels.length===0)&&X.availableConfigOptions.length===0)return;g((Q)=>{let j=Q.runtimes.find((W)=>W.id===$);if(j){if(X.availableModels&&X.availableModels.length>0)j.discoveredModels=w0({adapterId:Z,models:X.availableModels,currentModelId:X.currentModelId??J});if(X.availableConfigOptions.length>0)j.discoveredConfigOptions=X.availableConfigOptions}}).catch(()=>{return})}function g6($,X){return`${$}
19
19
 
20
20
  Runtime run folder:
21
21
  - Effective run folder: ${X}
@@ -25,4 +25,4 @@ Runtime run folder:
25
25
  Connection: close\r
26
26
  Content-Length: ${Buffer.byteLength(Z)}\r
27
27
  \r
28
- ${Z}`),$.destroy()}function XX($,X){return new Promise((Z,J)=>{let Q=(W)=>{$.off("listening",j),J(W)},j=()=>{$.off("error",Q);let W=$.address();if(!W||typeof W==="string"){J(Error("Failed to read CLI bridge server address"));return}Z(W.port)};$.once("error",Q),$.once("listening",j),$.listen(X,"127.0.0.1")})}function J2($){return new Promise((X,Z)=>{$.close((J)=>{if(J)Z(J);else X()})})}async function W2($,X=_$()){let Z=new Map,J=new Map,Q=$.maxMessageSize??d6,j=!1,W=(U)=>{let M=J.get(U);if(M)clearTimeout(M);J.delete(U)},G=(U)=>{J.delete(U);let{activeRunIds:M}=$.registry.disconnect(U);$.onDisconnect(U,M)},z=(U,M)=>{let N={type:"cli_status",connected:!0,runtime:$.runtime,mcpReady:$.mcpReady(),error:M};if(U){let C=Z.get(U);if(C)W0(C,N);return}for(let C of Z.values())W0(C,N)},K=(U,M)=>{let N=M.sessionId.trim(),C=M.userId.trim();if(!N||!C){W0(U,{type:"cli_status",connected:!1,runtime:$.runtime,mcpReady:$.mcpReady(),error:"Missing frontend session or user id"}),U.close();return}W(N);let Y=Z.get(N);if(Y&&Y!==U)Y.close();U.data.frontendSessionId=N,Z.set(N,U),$.registry.register({frontendSessionId:N,userId:C,tools:M.tools,send:(D)=>W0(U,D)}),z(N),$.onToolMetadata?.(N)},H=(U,M)=>{let N=$.registry.getUserId(U);if(!N)return;switch(M.type){case"bridge_ping":{let C=Z.get(U);if(C)W0(C,{type:"bridge_pong"});break}case"tool_metadata":$.registry.setMetadata(U,M.tools),$.onToolMetadata?.(U);break;case"tool_result":$.registry.handleToolResult(U,M);break;case"run_turn":$.registry.markRunActive(U,M.run.runId,M.run.cardId),$.onRunTurn(U,{...M.run,frontendSessionId:U,userId:N});break;case"cancel_run":if($.registry.ownsRun(U,M.runId))$.onCancelRun(U,M.runId);break;case"runtime_rpc":$.onRuntimeRpc(U,M);break;case"warmup_run":$.onWarmupRun(U,{...M,frontendSessionId:U},N);break;default:break}},B=(U,M)=>{let N=X2(U.headers.origin),C=$2(N),Y={Vary:"Origin"};if(C&&N)Y["Access-Control-Allow-Origin"]=N,Y["Access-Control-Allow-Private-Network"]="true";if(U.method==="OPTIONS"){M.writeHead(204,{...Y,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),M.end();return}if(U.method!=="GET"){M.writeHead(405,Y),M.end();return}M.writeHead(200,{...Y,"content-type":"application/json","cache-control":"no-store"}),M.end(JSON.stringify({ideawave:!0,runtime:$.runtime,mcpReady:$.mcpReady()}))};for(let U of X){let M=p6((Y,D)=>{if(new URL(Y.url??"/","http://127.0.0.1").pathname===t1){B(Y,D);return}D.writeHead(404,{"content-type":"text/plain"}),D.end("IdeaWave CLI bridge")}),N=new a6({noServer:!0,maxPayload:Q}),C=(Y)=>{if(Y.idleTimer)clearTimeout(Y.idleTimer);Y.idleTimer=setTimeout(()=>{Y.close()},i6),Y.idleTimer.unref?.()};N.on("connection",(Y)=>{let D=Y;D.data={id:u6(),frontendSessionId:null},D.idleTimer=null,C(D),D.on("ping",()=>C(D)),D.on("pong",()=>C(D)),D.on("error",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);D.close()}),D.on("message",(x)=>{C(D);let k=$X(x);if(Q>0&&k.length>Q)return;let A=h0(k);if(!A)return;let _=D.data.frontendSessionId;if(!_){if(A.type==="bridge_probe")W0(D,{type:"bridge_probe_ack",protocolVersion:A.protocolVersion});else if(A.type==="frontend_hello")K(D,A);return}H(_,A)}),D.on("close",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);let x=D.data.frontendSessionId;if(!x)return;if(Z.get(x)!==D)return;if(Z.delete(x),W(x),j)return;J.set(x,setTimeout(()=>G(x),n6))})}),M.on("upgrade",(Y,D,x)=>{if(new URL(Y.url??"/","http://127.0.0.1").pathname!==O$){Z2(D,404,"Not Found");return}if(!$2(X2(Y.headers.origin))){Z2(D,403,"Forbidden");return}N.handleUpgrade(Y,D,x,(A)=>{N.emit("connection",A,Y)})});try{let Y=await XX(M,U);return{url:`ws://127.0.0.1:${Y}${O$}`,port:Y,sendStatus:z,close:async()=>{j=!0;for(let D of J.values())clearTimeout(D);J.clear();for(let D of N.clients){let x=D;if(x.idleTimer)clearTimeout(x.idleTimer);x.close()}N.close(),await J2(M).catch(()=>{return})}}}catch(Y){if(N.close(),await J2(M).catch(()=>{return}),Y?.code==="EADDRINUSE")continue;throw Y}}throw Error(`No free IdeaWave CLI bridge port found in ${X[0]}-${X.at(-1)}`)}import{Server as MX}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as NX,ListToolsRequestSchema as qX}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as JX}from"node:crypto";import{createServer as QX}from"node:http";import{StreamableHTTPServerTransport as jX}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as z2}from"@modelcontextprotocol/sdk/types.js";var K2=new Set(["127.0.0.1","localhost","[::1]","::1"]);function ZX($){let X=$.trim();if(X.length===0)return null;if(X.startsWith("[")){let j=X.indexOf("]");if(j===-1)return null;let W=X.slice(0,j+1),G=X.slice(j+1);if(G.length===0)return{host:W,port:null};if(!G.startsWith(":"))return null;let z=Number(G.slice(1));if(!Number.isInteger(z)||z<=0||z>65535)return null;return{host:W,port:z}}let Z=X.lastIndexOf(":");if(Z===-1)return{host:X,port:null};let J=X.slice(Z+1),Q=Number(J);if(!Number.isInteger(Q)||Q<=0||Q>65535)return{host:X,port:null};return{host:X.slice(0,Z),port:Q}}function V2($){return K2.has($)||K2.has($.toLowerCase())}function Y2($,X){let Z=$.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let J=ZX(Z);if(!J)return{ok:!1,status:403,reason:"bad-host"};if(!V2(J.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(J.port!==null&&J.port!==X)return{ok:!1,status:403,reason:"host-port-mismatch"};let Q=$.headers.origin;if(typeof Q==="string"&&Q.length>0){if(Q!=="null"){let j;try{j=new URL(Q)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!V2(j.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var G2="/mcp",WX=43274,U2=16777216,KX=1800000,VX=300000,H2=200,YX=-32700,n=-32600,A$=-32603;function m($,X,Z,J,Q){$.statusCode=X,$.setHeader("content-type","application/json"),$.end(JSON.stringify({jsonrpc:"2.0",error:{code:Z,message:J,...Q?{data:Q}:{}},id:null}))}class w$ extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class T$ extends Error{constructor(){super(`body exceeds ${U2} bytes`);this.name="BodyTooLargeError"}}async function zX($){if($.method&&$.method!=="POST")return;let X=$.headers["content-type"];if(typeof X==="string"&&X.trim().length>0){if(!X.toLowerCase().includes("application/json"))throw new w$}let Z=0,J=[];for await(let j of $){let W=typeof j==="string"?Buffer.from(j):j;if(Z+=W.byteLength,Z>U2)throw new T$;J.push(W)}if(J.length===0)return;let Q=Buffer.concat(J).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function GX($){if(Array.isArray($))return $.some(z2);return z2($)}function HX($){if(typeof $==="number")return $;let X=process.env.IDEAWAVE_MCP_PORT;if(X&&X.trim().length>0){let Z=Number(X);if(Number.isInteger(Z)&&Z>=0&&Z<65536)return Z}return WX}async function UX($,X){let Z=(Q)=>new Promise((j,W)=>{let G=(K)=>{$.off("listening",z),W(K)},z=()=>{$.off("error",G),j()};$.once("error",G),$.once("listening",z),$.listen(Q,"127.0.0.1")});try{await Z(X)}catch(Q){if(Q.code!=="EADDRINUSE"||X===0)throw Q;console.warn(`[mcp] port ${X} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await Z(0)}let J=$.address();if(J==null||typeof J==="string")throw Error("[mcp] failed to read bound address");return J.port}function DX($,X){if(X&&typeof X==="object"&&!Array.isArray(X)){let J=X.params;if(J&&typeof J==="object"&&!Array.isArray(J)){let Q=J.clientInfo;if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let j=Q.name;if(typeof j==="string"&&j.trim().length>0)return j.trim()}}}let Z=$.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function D2($){let X=new Map,Z=0;function J(K){let H=X.get(K);if(H)H.lastActivity=Date.now()}async function Q(K,H){X.delete(K),await H.transport.close().catch(()=>{return})}async function j(){let K=null,H=1/0;for(let[B,U]of X)if(U.lastActivity<H)H=U.lastActivity,K=B;if(K!==null){let B=X.get(K);if(B)console.warn(`[mcp] session cap of ${H2} reached; evicting ${K}`),await Q(K,B)}}let W=setInterval(()=>{let K=Date.now()-KX;for(let[H,B]of X)if(B.lastActivity<K)console.log(`[mcp] sweeping idle session ${H}`),Q(H,B)},VX);W.unref?.();let G=QX((K,H)=>{(async()=>{let B;try{B=new URL(K.url??"/","http://127.0.0.1").pathname}catch{m(H,400,n,"bad-url");return}if(B!==G2){m(H,404,n,"not-found");return}let U=K.method??"POST";if(U!=="POST"&&U!=="GET"&&U!=="DELETE"){H.setHeader("Allow","GET, POST, DELETE"),m(H,405,n,"method-not-allowed");return}let M=Y2(K,Z);if(!M.ok){m(H,M.status,n,"forbidden",{reason:M.reason});return}let N=K.headers["mcp-session-id"],C=typeof N==="string"?N:void 0;if(U==="GET"||U==="DELETE"){if(!C||!X.has(C)){m(H,400,n,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let x=X.get(C).transport;J(C);try{await x.handleRequest(K,H)}catch(k){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",k),!H.headersSent)m(H,500,A$,"internal")}return}let Y;try{Y=await zX(K)}catch(x){if(x instanceof w$){m(H,415,n,"expected-application-json");return}if(x instanceof T$){m(H,413,n,"body-too-large");return}m(H,400,YX,"invalid-json");return}let D;if(C&&X.has(C))D=X.get(C).transport,J(C);else if(!C&&Y!==void 0&&GX(Y)){let x=K.headers["x-ideawave-user-id"],k=typeof x==="string"&&x.trim().length>0?x.trim():null,A=K.headers["x-ideawave-frontend-session-id"],_=typeof A==="string"&&A.trim().length>0?A.trim():null,P=K.headers["x-ideawave-tool-surface"],V=typeof P==="string"&&P.trim()==="read"?"read":"full",F=K.headers["x-ideawave-images-supported"],T=typeof F==="string"&&F.trim()==="1",R=K.headers["x-ideawave-card-id"],L=typeof R==="string"&&R.trim().length>0?R.trim():null,f=K.headers["x-ideawave-board-id"],E=typeof f==="string"&&f.trim().length>0?f.trim():null,I=K.headers["x-ideawave-run-folder"],p=typeof I==="string"&&I.trim().length>0?I.trim():null,B0=DX(K,Y);if(X.size>=H2)await j();let X0=null,s=new jX({sessionIdGenerator:()=>JX(),onsessioninitialized:(Z0)=>{X0=Z0,X.set(Z0,{transport:s,lastActivity:Date.now()})},onsessionclosed:(Z0)=>{X.delete(Z0)}});s.onclose=()=>{if(s.sessionId)X.delete(s.sessionId)};try{await $.buildServer({userId:k,frontendSessionId:_,boardId:E,toolSurface:V,imagesSupported:T,cardId:L,runFolder:p,clientHint:B0}).connect(s)}catch(Z0){if(console.error("[mcp] buildServer/connect failed",Z0),X0)X.delete(X0);await s.close().catch(()=>{return}),m(H,500,A$,"server-init-failed");return}D=s}else{m(H,400,n,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await D.handleRequest(K,H,Y)}catch(x){if(console.error("[mcp] transport.handleRequest threw",x),!H.headersSent)m(H,500,A$,"internal")}})().catch((B)=>{console.error("[mcp] unhandled request handler error:",B)})});return Z=await UX(G,HX($.port)),{url:`http://127.0.0.1:${Z}${G2}`,port:Z,close:async()=>{clearInterval(W);for(let K of X.values())await K.transport.close().catch(()=>{return});X.clear(),await new Promise((K)=>G.close(()=>K()))}}}var BX={name:"ideawave-board",version:"1.0.0"},m0="list_run_folder",g0="read_run_folder_file",q2=new Set(["list_boards","get_board","list_nodes","list_edges","inspect_node","list_context_sources","read_context_card","read_context_file","read_context_image","list_context_folder","get_board_wiki","search_board","get_card_messages","list_agent_cards","inspect_neighbors",m0,g0]),B2=new Set(["inspect_diagram"]),xX=[{name:m0,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:g0,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 R$($){return{content:[{type:"text",text:$}]}}function CX($){return R$(JSON.stringify($,null,2))}function M2($){return{...R$($),isError:!0}}function FX($,X,Z="full",J=!1){return $.getMetadata(X).filter((Q)=>{let j=f0(Q.name);if(Z==="read"&&!q2.has(j))return!1;if(!J&&B2.has(j))return!1;return!0}).map((Q)=>({name:Q.name,description:Q.description,inputSchema:Q.inputSchema}))}function PX($,X,Z={}){let J=FX($,X,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...J,...xX]:J}function N2($,X){if(!$||typeof $!=="object"||Array.isArray($))return null;let Z=$[X];return typeof Z==="string"?Z:null}async function LX($,X,Z){if(Z&&Z.trim().length>0)return Z.trim();if(!$||!X)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await i({boardId:$,cardId:X})).runFolder}async function kX($){let X=await LX($.boardId,$.cardId,$.runFolder);if($.name===m0){let Z=N2($.args,"path")??"",J=await L1(X,Z);return CX(J)}if($.name===g0){let Z=N2($.args,"path");if(!Z)return M2("read_run_folder_file requires a path.");return R$(await R0(X,Z))}return M2(`Unknown local tool "${$.name}"`)}function OX($,X,Z,J,Q,j="full",W=!1){let G=new MX(BX,{capabilities:{tools:{}}}),z=async()=>{if(W)return!0;if(p1(J))return!0;if(Z&&J)try{return(await i({boardId:Z,cardId:J})).adapter.supportsImages===!0}catch{return!1}return!1};return G.setRequestHandler(qX,async()=>({tools:PX($,X,{includeRunFolderTools:Boolean(Q||Z&&J),toolSurface:j,imagesSupported:await z()})})),G.setRequestHandler(NX,async(K)=>{let{name:H,arguments:B}=K.params,U=f0(H);try{if(U===m0||U===g0)return await kX({name:U,args:B,boardId:Z,cardId:J,runFolder:Q});if(j==="read"&&!q2.has(U))throw Error(`Tool "${H}" is not available in read-only mode`);if(B2.has(U)&&!await z())throw Error(`Tool "${H}" requires a runtime that supports image input`);let M=await $.callTool(X,U,B??{},void 0,J??void 0);if(M&&typeof M==="object"&&Array.isArray(M.content))return M;return{content:[{type:"text",text:typeof M==="string"?M:JSON.stringify(M)}]}}catch(M){return{content:[{type:"text",text:M instanceof Error?M.message:"Tool call failed"}],isError:!0}}}),G}function x2($,X){return D2({buildServer:(Z)=>OX($,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:X})}import c0 from"node:fs/promises";import f$ from"node:os";import l0 from"node:path";function C2(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function _X(){let[$,X]=await Promise.all([h(),B1()]),Z=$.globalDefaultConfigId?$.runtimes.find((J)=>J.id===$.globalDefaultConfigId)??null:null;return{runtimes:$.runtimes,globalDefaultConfigId:$.globalDefaultConfigId,globalDefaultEffective:Z?{runFolder:Z.runFolder??f$.homedir(),modelId:Z.defaultModelId??null,configValues:Z.defaultConfigValues??{}}:null,knownAdapters:j0().map((J)=>({id:J.id,displayName:J.displayName})),readiness:X}}async function AX($){try{let X=await i({boardId:$.boardId,cardId:$.cardId});return{resolved:{configId:X.entry.id,adapterId:X.entry.kind==="registered"?X.entry.adapterId:null,displayName:X.entry.displayName,runFolder:X.runFolder,modelId:X.modelId,configValues:X.configValues}}}catch(X){if(X instanceof t)return{resolved:null};throw X}}async function wX($){return g((X)=>{let Z=X.runtimes.find((j)=>j.kind==="registered"&&j.adapterId===$.adapterId);if(Z)return Z;let J=j0().find((j)=>j.id===$.adapterId);if(!J)throw Error(`Unknown adapterId: ${$.adapterId}`);let Q={id:C2(),kind:"registered",adapterId:$.adapterId,displayName:J.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Q),Q})}async function TX($){return g((X)=>{let Z={id:C2(),kind:"custom",displayName:$.displayName,command:$.command,args:$.args,env:$.env,runFolder:$.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Z),Z})}async function RX($){await g((X)=>{if(X.runtimes=X.runtimes.filter((Z)=>Z.id!==$.runtimeConfigId),X.globalDefaultConfigId===$.runtimeConfigId)X.globalDefaultConfigId=null;for(let Z of Object.keys(X.boardOverrides))if(X.boardOverrides[Z].runtimeConfigId===$.runtimeConfigId)delete X.boardOverrides[Z];for(let Z of Object.keys(X.cardOverrides))if(X.cardOverrides[Z].runtimeConfigId===$.runtimeConfigId)delete X.cardOverrides[Z]})}async function fX($){await g((X)=>{let Z=X.runtimes.find((J)=>J.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);if(X.globalDefaultConfigId=$.runtimeConfigId,$.runFolder!==void 0)Z.runFolder=$.runFolder;if($.modelId!==void 0)Z.defaultModelId=$.modelId;if($.configValues!==void 0)Z.defaultConfigValues=$.configValues})}async function EX($){$.boardId,await g((X)=>{if($.runtimeConfigId===null){delete X.cardOverrides[$.cardId];return}if(!X.runtimes.some((Q)=>Q.id===$.runtimeConfigId))throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=X.cardOverrides[$.cardId];X.cardOverrides[$.cardId]={runtimeConfigId:$.runtimeConfigId,runFolder:$.runFolder!==void 0?$.runFolder:J?.runFolder??null,modelId:$.modelId!==void 0?$.modelId:J?.modelId??null,configValues:$.configValues!==void 0?$.configValues:J?.configValues??{}}})}async function yX($){let Z=(await h()).runtimes.find((W)=>W.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=c(Z),Q=await J.resolveSpawnConfig(Z),j=Z.runFolder??f$.homedir();try{let W=await m1({spawn:{...Q,cwd:j},modelId:$.modelId??Z.defaultModelId??null,configValues:$.configValues??Z.defaultConfigValues??{}}),G=w0({adapterId:J.id,models:W.models,currentModelId:W.currentModelId}),z=new Date().toISOString();return await g((K)=>{let H=K.runtimes.find((B)=>B.id===$.runtimeConfigId);if(H)H.discoveredModels=G,H.discoveredConfigOptions=W.configOptions,H.discoveredAt=z}),{ok:!0,models:G,configOptions:W.configOptions,currentModelId:W.currentModelId}}catch(W){if(W instanceof J0)throw Error(`${W.message}${J.authHint?` ${J.authHint}`:""}`);if(W instanceof O||W instanceof a)throw Error(W.message);throw W}}async function bX($){let X=f$.homedir(),Z=$.path?.trim()?$.path.trim():X,J=l0.resolve(Z),Q=!0;try{if(!(await c0.stat(J)).isDirectory())J=l0.dirname(J)}catch{Q=!1,J=X}let j=[];try{j=(await c0.readdir(J,{withFileTypes:!0})).filter((z)=>z.isDirectory()&&!z.name.startsWith(".")).map((z)=>({name:z.name,path:l0.join(J,z.name)})).sort((z,K)=>z.name.localeCompare(K.name))}catch{j=[]}let W=l0.dirname(J);return{path:J,parent:W===J?null:W,home:X,exists:Q,entries:j}}var F2={list:_X,getEffectiveForCard:AX,registerRegistered:wX,registerCustom:TX,unregister:RX,setUserDefault:fX,setCardOverride:EX,refreshModels:yX,browseFolder:bX};var vX=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function IX(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function P2(){try{let $=await h();if($.globalDefaultConfigId){if($.runtimes.some((Z)=>Z.id===$.globalDefaultConfigId))return $.globalDefaultConfigId}for(let X of vX){if((await x1(X.id))?.status!=="ready")continue;let J=null;if(await g((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((G)=>G.id===Q.globalDefaultConfigId)){J=Q.globalDefaultConfigId;return}}let j=Q.runtimes.find((W)=>W.kind==="registered"&&W.adapterId===X.id);if(!j){let W={id:IX(),kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Q.runtimes.push(W),j=W}Q.globalDefaultConfigId=j.id,J=j.id}),J)return console.log(`[ideawave-cli] using agent runtime: ${X.displayName}`),J}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch($){return console.warn("[ideawave-cli] runtime auto-seed failed",$),null}}function hX(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class E${sessions=new Map;createCallId;toolCallTimeoutMs;constructor($={}){this.createCallId=$.createCallId??hX,this.toolCallTimeoutMs=$.toolCallTimeoutMs??120000}register($){let X=this.sessions.get($.frontendSessionId);if(X){if(X.userId!==$.userId)this.rejectPending(X,"frontend session user changed"),X.activeRunIds.clear();this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:X.pendingToolCalls,activeRunIds:X.activeRunIds,activeRunCardIds:X.activeRunCardIds});return}this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect($,X="frontend session disconnected"){let Z=this.sessions.get($);if(!Z)return{activeRunIds:[]};return this.sessions.delete($),this.rejectPending(Z,X),{activeRunIds:Array.from(Z.activeRunIds)}}sessionCount(){return this.sessions.size}has($){return this.sessions.has($)}getUserId($){return this.sessions.get($)?.userId??null}setMetadata($,X){let Z=this.sessions.get($);if(Z)Z.tools=X}getMetadata($){if(!$)return[];return this.sessions.get($)?.tools??[]}sendToSession($,X){let Z=this.sessions.get($);if(!Z)return!1;return Z.send(X),!0}callTool($,X,Z,J,Q){if(!$)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let j=this.sessions.get($);if(!j)return Promise.reject(Error(`Frontend session ${$} is not connected`));let W=this.createCallId();return new Promise((G,z)=>{let K=setTimeout(()=>{j.pendingToolCalls.delete(W),z(Error(`Tool "${X}" timed out waiting for the frontend`))},this.toolCallTimeoutMs),H=J??(Q?this.getActiveRunIdForCard(j,Q):this.getSoleActiveRunId(j)),B=Q??(H?j.activeRunCardIds.get(H):void 0);j.pendingToolCalls.set(W,{resolve:G,reject:z,timer:K}),j.send({type:"tool_call",callId:W,name:X,args:Z,...H?{runId:H}:{},...B?{cardId:B}:{}})})}handleToolResult($,X){let Z=this.sessions.get($);if(!Z)return;let J=Z.pendingToolCalls.get(X.callId);if(!J)return;if(Z.pendingToolCalls.delete(X.callId),clearTimeout(J.timer),X.ok)J.resolve(X.result);else J.reject(Error(X.error??"Tool execution failed"))}markRunActive($,X,Z){let J=this.sessions.get($);if(!J)return;if(J.activeRunIds.add(X),Z)J.activeRunCardIds.set(X,Z)}markRunSettled($,X){let Z=this.sessions.get($);if(!Z)return;Z.activeRunIds.delete(X),Z.activeRunCardIds.delete(X)}ownsRun($,X){return this.sessions.get($)?.activeRunIds.has(X)??!1}rejectPending($,X){for(let Z of $.pendingToolCalls.values())clearTimeout(Z.timer),Z.reject(Error(X));$.pendingToolCalls.clear()}getSoleActiveRunId($){return $.activeRunIds.size===1?$.activeRunIds.values().next().value:void 0}getActiveRunIdForCard($,X){let Z=[...$.activeRunCardIds.entries()].filter(([J,Q])=>$.activeRunIds.has(J)&&Q===X).map(([J])=>J);return Z.length===1?Z[0]:void 0}}function SX(){return"0.0.44".trim()?"0.0.44":"dev"}var o=process.argv[2];if(o==="--help"||o==="-h"||o==="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(o==="--version"||o==="-v"||o==="version")console.log(SX()),process.exit(0);if(o)console.error(`Unknown command: ${o}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var M0=new E$,K0=null;function N0($,X){M0.sendToSession($,X)}async function mX($,X){try{let Z=F2[X.method],J=await Z(X.params);N0($,{type:"runtime_rpc_result",requestId:X.requestId,ok:!0,result:J})}catch(Z){N0($,{type:"runtime_rpc_result",requestId:X.requestId,ok:!1,error:Z instanceof Error?Z.message:String(Z)})}}var q0=!1,D0=null;async function y$(){if(q0)return;if(D0)return D0;return D0=(async()=>{try{let $=await x2(M0);h$({...$,requestedPort:$.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${$.url}`);try{await e$({onStatusChange:(X)=>{if(C1(),K0?.sendStatus(),X.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${X.packageName}: ${X.error??"unknown error"}`)}})}catch(X){console.warn("[ideawave-cli] ACP bridge setup skipped:",X instanceof Error?X.message:String(X))}await P2(),q0=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),K0?.sendStatus()}catch($){console.error("[ideawave-cli] failed to start agent host:",$),K0?.sendStatus(void 0,$ instanceof Error?$.message:String($))}finally{D0=null}})(),D0}if(process.env.APP_ENV!=="development"){let $=await j2();if($)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${$}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}K0=await W2({registry:M0,runtime:null,mcpReady:()=>q0,onToolMetadata:($)=>{console.log(`[ideawave-cli] session ${$} advertised ${M0.getMetadata($).length} tools`),y$()},onRunTurn:($,X)=>{console.log(`[ideawave-cli] running agent turn for card ${X.cardId} (session ${$})`),(async()=>{if(await y$(),!q0){N0($,{type:"run_settled",runId:X.runId,cardId:X.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await o1(X,(Z)=>N0($,Z))})().catch(()=>{return}).finally(()=>M0.markRunSettled($,X.runId))},onCancelRun:($,X)=>{k$(X)},onRuntimeRpc:($,X)=>{mX($,X)},onWarmupRun:($,X,Z)=>{(async()=>{if(await y$(),!q0)return{status:"retryable",error:"agent host is not ready"};return s1({cardId:X.cardId,boardId:X.boardId,userId:Z,frontendSessionId:$})})().then((J)=>{if(!X.warmupId)return;N0($,{type:"warmup_result",warmupId:X.warmupId,cardId:X.cardId,...J})})},onDisconnect:($,X)=>{a1($);for(let Z of X)k$(Z);console.log(`[ideawave-cli] browser session ${$} disconnected`)}});console.log(`[ideawave-cli] browser bridge listening on ${K0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var L2=!1;for(let $ of["SIGINT","SIGTERM"])process.once($,()=>{if(L2)return;L2=!0,d1(),(async()=>{await K0?.close().catch(()=>{return}),process.exit(0)})()});
28
+ ${Z}`),$.destroy()}function XX($,X){return new Promise((Z,J)=>{let Q=(W)=>{$.off("listening",j),J(W)},j=()=>{$.off("error",Q);let W=$.address();if(!W||typeof W==="string"){J(Error("Failed to read CLI bridge server address"));return}Z(W.port)};$.once("error",Q),$.once("listening",j),$.listen(X,"127.0.0.1")})}function J2($){return new Promise((X,Z)=>{$.close((J)=>{if(J)Z(J);else X()})})}async function W2($,X=_$()){let Z=new Map,J=new Map,Q=$.maxMessageSize??d6,j=!1,W=(U)=>{let M=J.get(U);if(M)clearTimeout(M);J.delete(U)},G=(U)=>{J.delete(U);let{activeRunIds:M}=$.registry.disconnect(U);$.onDisconnect(U,M)},z=(U,M)=>{let N={type:"cli_status",connected:!0,runtime:$.runtime,mcpReady:$.mcpReady(),error:M};if(U){let C=Z.get(U);if(C)W0(C,N);return}for(let C of Z.values())W0(C,N)},K=(U,M)=>{let N=M.sessionId.trim(),C=M.userId.trim();if(!N||!C){W0(U,{type:"cli_status",connected:!1,runtime:$.runtime,mcpReady:$.mcpReady(),error:"Missing frontend session or user id"}),U.close();return}W(N);let Y=Z.get(N);if(Y&&Y!==U)Y.close();U.data.frontendSessionId=N,Z.set(N,U),$.registry.register({frontendSessionId:N,userId:C,tools:M.tools,send:(D)=>W0(U,D)}),z(N),$.onToolMetadata?.(N)},H=(U,M)=>{let N=$.registry.getUserId(U);if(!N)return;switch(M.type){case"bridge_ping":{let C=Z.get(U);if(C)W0(C,{type:"bridge_pong"});break}case"tool_metadata":$.registry.setMetadata(U,M.tools),$.onToolMetadata?.(U);break;case"tool_result":$.registry.handleToolResult(U,M);break;case"run_turn":$.registry.markRunActive(U,M.run.runId,M.run.cardId),$.onRunTurn(U,{...M.run,frontendSessionId:U,userId:N});break;case"cancel_run":if($.registry.ownsRun(U,M.runId))$.onCancelRun(U,M.runId);break;case"runtime_rpc":$.onRuntimeRpc(U,M);break;case"warmup_run":$.onWarmupRun(U,{...M,frontendSessionId:U},N);break;default:break}},B=(U,M)=>{let N=X2(U.headers.origin),C=$2(N),Y={Vary:"Origin"};if(C&&N)Y["Access-Control-Allow-Origin"]=N,Y["Access-Control-Allow-Private-Network"]="true";if(U.method==="OPTIONS"){M.writeHead(204,{...Y,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),M.end();return}if(U.method!=="GET"){M.writeHead(405,Y),M.end();return}M.writeHead(200,{...Y,"content-type":"application/json","cache-control":"no-store"}),M.end(JSON.stringify({ideawave:!0,runtime:$.runtime,mcpReady:$.mcpReady()}))};for(let U of X){let M=p6((Y,D)=>{if(new URL(Y.url??"/","http://127.0.0.1").pathname===t1){B(Y,D);return}D.writeHead(404,{"content-type":"text/plain"}),D.end("IdeaWave CLI bridge")}),N=new a6({noServer:!0,maxPayload:Q}),C=(Y)=>{if(Y.idleTimer)clearTimeout(Y.idleTimer);Y.idleTimer=setTimeout(()=>{Y.close()},i6),Y.idleTimer.unref?.()};N.on("connection",(Y)=>{let D=Y;D.data={id:u6(),frontendSessionId:null},D.idleTimer=null,C(D),D.on("ping",()=>C(D)),D.on("pong",()=>C(D)),D.on("error",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);D.close()}),D.on("message",(x)=>{C(D);let k=$X(x);if(Q>0&&k.length>Q)return;let A=h0(k);if(!A)return;let _=D.data.frontendSessionId;if(!_){if(A.type==="bridge_probe")W0(D,{type:"bridge_probe_ack",protocolVersion:A.protocolVersion});else if(A.type==="frontend_hello")K(D,A);return}H(_,A)}),D.on("close",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);let x=D.data.frontendSessionId;if(!x)return;if(Z.get(x)!==D)return;if(Z.delete(x),W(x),j)return;J.set(x,setTimeout(()=>G(x),n6))})}),M.on("upgrade",(Y,D,x)=>{if(new URL(Y.url??"/","http://127.0.0.1").pathname!==O$){Z2(D,404,"Not Found");return}if(!$2(X2(Y.headers.origin))){Z2(D,403,"Forbidden");return}N.handleUpgrade(Y,D,x,(A)=>{N.emit("connection",A,Y)})});try{let Y=await XX(M,U);return{url:`ws://127.0.0.1:${Y}${O$}`,port:Y,sendStatus:z,close:async()=>{j=!0;for(let D of J.values())clearTimeout(D);J.clear();for(let D of N.clients){let x=D;if(x.idleTimer)clearTimeout(x.idleTimer);x.close()}N.close(),await J2(M).catch(()=>{return})}}}catch(Y){if(N.close(),await J2(M).catch(()=>{return}),Y?.code==="EADDRINUSE")continue;throw Y}}throw Error(`No free IdeaWave CLI bridge port found in ${X[0]}-${X.at(-1)}`)}import{Server as MX}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as NX,ListToolsRequestSchema as qX}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as JX}from"node:crypto";import{createServer as QX}from"node:http";import{StreamableHTTPServerTransport as jX}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as z2}from"@modelcontextprotocol/sdk/types.js";var K2=new Set(["127.0.0.1","localhost","[::1]","::1"]);function ZX($){let X=$.trim();if(X.length===0)return null;if(X.startsWith("[")){let j=X.indexOf("]");if(j===-1)return null;let W=X.slice(0,j+1),G=X.slice(j+1);if(G.length===0)return{host:W,port:null};if(!G.startsWith(":"))return null;let z=Number(G.slice(1));if(!Number.isInteger(z)||z<=0||z>65535)return null;return{host:W,port:z}}let Z=X.lastIndexOf(":");if(Z===-1)return{host:X,port:null};let J=X.slice(Z+1),Q=Number(J);if(!Number.isInteger(Q)||Q<=0||Q>65535)return{host:X,port:null};return{host:X.slice(0,Z),port:Q}}function V2($){return K2.has($)||K2.has($.toLowerCase())}function Y2($,X){let Z=$.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let J=ZX(Z);if(!J)return{ok:!1,status:403,reason:"bad-host"};if(!V2(J.host))return{ok:!1,status:403,reason:"non-loopback-host"};if(J.port!==null&&J.port!==X)return{ok:!1,status:403,reason:"host-port-mismatch"};let Q=$.headers.origin;if(typeof Q==="string"&&Q.length>0){if(Q!=="null"){let j;try{j=new URL(Q)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!V2(j.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var G2="/mcp",WX=43274,U2=16777216,KX=1800000,VX=300000,H2=200,YX=-32700,n=-32600,A$=-32603;function m($,X,Z,J,Q){$.statusCode=X,$.setHeader("content-type","application/json"),$.end(JSON.stringify({jsonrpc:"2.0",error:{code:Z,message:J,...Q?{data:Q}:{}},id:null}))}class w$ extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class T$ extends Error{constructor(){super(`body exceeds ${U2} bytes`);this.name="BodyTooLargeError"}}async function zX($){if($.method&&$.method!=="POST")return;let X=$.headers["content-type"];if(typeof X==="string"&&X.trim().length>0){if(!X.toLowerCase().includes("application/json"))throw new w$}let Z=0,J=[];for await(let j of $){let W=typeof j==="string"?Buffer.from(j):j;if(Z+=W.byteLength,Z>U2)throw new T$;J.push(W)}if(J.length===0)return;let Q=Buffer.concat(J).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function GX($){if(Array.isArray($))return $.some(z2);return z2($)}function HX($){if(typeof $==="number")return $;let X=process.env.IDEAWAVE_MCP_PORT;if(X&&X.trim().length>0){let Z=Number(X);if(Number.isInteger(Z)&&Z>=0&&Z<65536)return Z}return WX}async function UX($,X){let Z=(Q)=>new Promise((j,W)=>{let G=(K)=>{$.off("listening",z),W(K)},z=()=>{$.off("error",G),j()};$.once("error",G),$.once("listening",z),$.listen(Q,"127.0.0.1")});try{await Z(X)}catch(Q){if(Q.code!=="EADDRINUSE"||X===0)throw Q;console.warn(`[mcp] port ${X} in use, falling back to an OS-assigned port; external CLIs will need to re-paste the install command from Settings → External agents`),await Z(0)}let J=$.address();if(J==null||typeof J==="string")throw Error("[mcp] failed to read bound address");return J.port}function DX($,X){if(X&&typeof X==="object"&&!Array.isArray(X)){let J=X.params;if(J&&typeof J==="object"&&!Array.isArray(J)){let Q=J.clientInfo;if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let j=Q.name;if(typeof j==="string"&&j.trim().length>0)return j.trim()}}}let Z=$.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function D2($){let X=new Map,Z=0;function J(K){let H=X.get(K);if(H)H.lastActivity=Date.now()}async function Q(K,H){X.delete(K),await H.transport.close().catch(()=>{return})}async function j(){let K=null,H=1/0;for(let[B,U]of X)if(U.lastActivity<H)H=U.lastActivity,K=B;if(K!==null){let B=X.get(K);if(B)console.warn(`[mcp] session cap of ${H2} reached; evicting ${K}`),await Q(K,B)}}let W=setInterval(()=>{let K=Date.now()-KX;for(let[H,B]of X)if(B.lastActivity<K)console.log(`[mcp] sweeping idle session ${H}`),Q(H,B)},VX);W.unref?.();let G=QX((K,H)=>{(async()=>{let B;try{B=new URL(K.url??"/","http://127.0.0.1").pathname}catch{m(H,400,n,"bad-url");return}if(B!==G2){m(H,404,n,"not-found");return}let U=K.method??"POST";if(U!=="POST"&&U!=="GET"&&U!=="DELETE"){H.setHeader("Allow","GET, POST, DELETE"),m(H,405,n,"method-not-allowed");return}let M=Y2(K,Z);if(!M.ok){m(H,M.status,n,"forbidden",{reason:M.reason});return}let N=K.headers["mcp-session-id"],C=typeof N==="string"?N:void 0;if(U==="GET"||U==="DELETE"){if(!C||!X.has(C)){m(H,400,n,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let x=X.get(C).transport;J(C);try{await x.handleRequest(K,H)}catch(k){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",k),!H.headersSent)m(H,500,A$,"internal")}return}let Y;try{Y=await zX(K)}catch(x){if(x instanceof w$){m(H,415,n,"expected-application-json");return}if(x instanceof T$){m(H,413,n,"body-too-large");return}m(H,400,YX,"invalid-json");return}let D;if(C&&X.has(C))D=X.get(C).transport,J(C);else if(!C&&Y!==void 0&&GX(Y)){let x=K.headers["x-ideawave-user-id"],k=typeof x==="string"&&x.trim().length>0?x.trim():null,A=K.headers["x-ideawave-frontend-session-id"],_=typeof A==="string"&&A.trim().length>0?A.trim():null,P=K.headers["x-ideawave-tool-surface"],V=typeof P==="string"&&P.trim()==="read"?"read":"full",F=K.headers["x-ideawave-images-supported"],T=typeof F==="string"&&F.trim()==="1",R=K.headers["x-ideawave-card-id"],L=typeof R==="string"&&R.trim().length>0?R.trim():null,f=K.headers["x-ideawave-board-id"],E=typeof f==="string"&&f.trim().length>0?f.trim():null,I=K.headers["x-ideawave-run-folder"],p=typeof I==="string"&&I.trim().length>0?I.trim():null,B0=DX(K,Y);if(X.size>=H2)await j();let X0=null,s=new jX({sessionIdGenerator:()=>JX(),onsessioninitialized:(Z0)=>{X0=Z0,X.set(Z0,{transport:s,lastActivity:Date.now()})},onsessionclosed:(Z0)=>{X.delete(Z0)}});s.onclose=()=>{if(s.sessionId)X.delete(s.sessionId)};try{await $.buildServer({userId:k,frontendSessionId:_,boardId:E,toolSurface:V,imagesSupported:T,cardId:L,runFolder:p,clientHint:B0}).connect(s)}catch(Z0){if(console.error("[mcp] buildServer/connect failed",Z0),X0)X.delete(X0);await s.close().catch(()=>{return}),m(H,500,A$,"server-init-failed");return}D=s}else{m(H,400,n,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await D.handleRequest(K,H,Y)}catch(x){if(console.error("[mcp] transport.handleRequest threw",x),!H.headersSent)m(H,500,A$,"internal")}})().catch((B)=>{console.error("[mcp] unhandled request handler error:",B)})});return Z=await UX(G,HX($.port)),{url:`http://127.0.0.1:${Z}${G2}`,port:Z,close:async()=>{clearInterval(W);for(let K of X.values())await K.transport.close().catch(()=>{return});X.clear(),await new Promise((K)=>G.close(()=>K()))}}}var BX={name:"ideawave-board",version:"1.0.0"},m0="list_run_folder",g0="read_run_folder_file",q2=new Set(["list_boards","get_board","list_nodes","list_edges","inspect_node","list_context_sources","read_context_card","read_context_file","read_context_image","list_context_folder","get_board_wiki","search_board","get_card_messages","list_agent_cards","inspect_neighbors",m0,g0]),B2=new Set(["inspect_diagram"]),xX=[{name:m0,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:g0,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 R$($){return{content:[{type:"text",text:$}]}}function CX($){return R$(JSON.stringify($,null,2))}function M2($){return{...R$($),isError:!0}}function FX($,X,Z="full",J=!1){return $.getMetadata(X).filter((Q)=>{let j=f0(Q.name);if(Z==="read"&&!q2.has(j))return!1;if(!J&&B2.has(j))return!1;return!0}).map((Q)=>({name:Q.name,description:Q.description,inputSchema:Q.inputSchema}))}function PX($,X,Z={}){let J=FX($,X,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...J,...xX]:J}function N2($,X){if(!$||typeof $!=="object"||Array.isArray($))return null;let Z=$[X];return typeof Z==="string"?Z:null}async function LX($,X,Z){if(Z&&Z.trim().length>0)return Z.trim();if(!$||!X)throw Error("Run-folder tools require an active IdeaWave board and card.");return(await i({boardId:$,cardId:X})).runFolder}async function kX($){let X=await LX($.boardId,$.cardId,$.runFolder);if($.name===m0){let Z=N2($.args,"path")??"",J=await L1(X,Z);return CX(J)}if($.name===g0){let Z=N2($.args,"path");if(!Z)return M2("read_run_folder_file requires a path.");return R$(await R0(X,Z))}return M2(`Unknown local tool "${$.name}"`)}function OX($,X,Z,J,Q,j="full",W=!1){let G=new MX(BX,{capabilities:{tools:{}}}),z=async()=>{if(W)return!0;if(p1(J))return!0;if(Z&&J)try{return(await i({boardId:Z,cardId:J})).adapter.supportsImages===!0}catch{return!1}return!1};return G.setRequestHandler(qX,async()=>({tools:PX($,X,{includeRunFolderTools:Boolean(Q||Z&&J),toolSurface:j,imagesSupported:await z()})})),G.setRequestHandler(NX,async(K)=>{let{name:H,arguments:B}=K.params,U=f0(H);try{if(U===m0||U===g0)return await kX({name:U,args:B,boardId:Z,cardId:J,runFolder:Q});if(j==="read"&&!q2.has(U))throw Error(`Tool "${H}" is not available in read-only mode`);if(B2.has(U)&&!await z())throw Error(`Tool "${H}" requires a runtime that supports image input`);let M=await $.callTool(X,U,B??{},void 0,J??void 0);if(M&&typeof M==="object"&&Array.isArray(M.content))return M;return{content:[{type:"text",text:typeof M==="string"?M:JSON.stringify(M)}]}}catch(M){return{content:[{type:"text",text:M instanceof Error?M.message:"Tool call failed"}],isError:!0}}}),G}function x2($,X){return D2({buildServer:(Z)=>OX($,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:X})}import c0 from"node:fs/promises";import f$ from"node:os";import l0 from"node:path";function C2(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function _X(){let[$,X]=await Promise.all([h(),B1()]),Z=$.globalDefaultConfigId?$.runtimes.find((J)=>J.id===$.globalDefaultConfigId)??null:null;return{runtimes:$.runtimes,globalDefaultConfigId:$.globalDefaultConfigId,globalDefaultEffective:Z?{runFolder:Z.runFolder??f$.homedir(),modelId:Z.defaultModelId??null,configValues:Z.defaultConfigValues??{}}:null,knownAdapters:j0().map((J)=>({id:J.id,displayName:J.displayName})),readiness:X}}async function AX($){try{let X=await i({boardId:$.boardId,cardId:$.cardId});return{resolved:{configId:X.entry.id,adapterId:X.entry.kind==="registered"?X.entry.adapterId:null,displayName:X.entry.displayName,runFolder:X.runFolder,modelId:X.modelId,configValues:X.configValues}}}catch(X){if(X instanceof t)return{resolved:null};throw X}}async function wX($){return g((X)=>{let Z=X.runtimes.find((j)=>j.kind==="registered"&&j.adapterId===$.adapterId);if(Z)return Z;let J=j0().find((j)=>j.id===$.adapterId);if(!J)throw Error(`Unknown adapterId: ${$.adapterId}`);let Q={id:C2(),kind:"registered",adapterId:$.adapterId,displayName:J.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Q),Q})}async function TX($){return g((X)=>{let Z={id:C2(),kind:"custom",displayName:$.displayName,command:$.command,args:$.args,env:$.env,runFolder:$.runFolder,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Z),Z})}async function RX($){await g((X)=>{if(X.runtimes=X.runtimes.filter((Z)=>Z.id!==$.runtimeConfigId),X.globalDefaultConfigId===$.runtimeConfigId)X.globalDefaultConfigId=null;for(let Z of Object.keys(X.boardOverrides))if(X.boardOverrides[Z].runtimeConfigId===$.runtimeConfigId)delete X.boardOverrides[Z];for(let Z of Object.keys(X.cardOverrides))if(X.cardOverrides[Z].runtimeConfigId===$.runtimeConfigId)delete X.cardOverrides[Z]})}async function fX($){await g((X)=>{let Z=X.runtimes.find((J)=>J.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);if(X.globalDefaultConfigId=$.runtimeConfigId,$.runFolder!==void 0)Z.runFolder=$.runFolder;if($.modelId!==void 0)Z.defaultModelId=$.modelId;if($.configValues!==void 0)Z.defaultConfigValues=$.configValues})}async function EX($){$.boardId,await g((X)=>{if($.runtimeConfigId===null){delete X.cardOverrides[$.cardId];return}if(!X.runtimes.some((Q)=>Q.id===$.runtimeConfigId))throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=X.cardOverrides[$.cardId];X.cardOverrides[$.cardId]={runtimeConfigId:$.runtimeConfigId,runFolder:$.runFolder!==void 0?$.runFolder:J?.runFolder??null,modelId:$.modelId!==void 0?$.modelId:J?.modelId??null,configValues:$.configValues!==void 0?$.configValues:J?.configValues??{}}})}async function yX($){let Z=(await h()).runtimes.find((W)=>W.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=c(Z),Q=await J.resolveSpawnConfig(Z),j=Z.runFolder??f$.homedir();try{let W=await m1({spawn:{...Q,cwd:j},modelId:$.modelId??Z.defaultModelId??null,configValues:$.configValues??Z.defaultConfigValues??{}}),G=w0({adapterId:J.id,models:W.models,currentModelId:W.currentModelId}),z=new Date().toISOString();return await g((K)=>{let H=K.runtimes.find((B)=>B.id===$.runtimeConfigId);if(H)H.discoveredModels=G,H.discoveredConfigOptions=W.configOptions,H.discoveredAt=z}),{ok:!0,models:G,configOptions:W.configOptions,currentModelId:W.currentModelId}}catch(W){if(W instanceof J0)throw Error(`${W.message}${J.authHint?` ${J.authHint}`:""}`);if(W instanceof O||W instanceof a)throw Error(W.message);throw W}}async function bX($){let X=f$.homedir(),Z=$.path?.trim()?$.path.trim():X,J=l0.resolve(Z),Q=!0;try{if(!(await c0.stat(J)).isDirectory())J=l0.dirname(J)}catch{Q=!1,J=X}let j=[];try{j=(await c0.readdir(J,{withFileTypes:!0})).filter((z)=>z.isDirectory()&&!z.name.startsWith(".")).map((z)=>({name:z.name,path:l0.join(J,z.name)})).sort((z,K)=>z.name.localeCompare(K.name))}catch{j=[]}let W=l0.dirname(J);return{path:J,parent:W===J?null:W,home:X,exists:Q,entries:j}}var F2={list:_X,getEffectiveForCard:AX,registerRegistered:wX,registerCustom:TX,unregister:RX,setUserDefault:fX,setCardOverride:EX,refreshModels:yX,browseFolder:bX};var vX=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function IX(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function P2(){try{let $=await h();if($.globalDefaultConfigId){if($.runtimes.some((Z)=>Z.id===$.globalDefaultConfigId))return $.globalDefaultConfigId}for(let X of vX){if((await x1(X.id))?.status!=="ready")continue;let J=null;if(await g((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((G)=>G.id===Q.globalDefaultConfigId)){J=Q.globalDefaultConfigId;return}}let j=Q.runtimes.find((W)=>W.kind==="registered"&&W.adapterId===X.id);if(!j){let W={id:IX(),kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Q.runtimes.push(W),j=W}Q.globalDefaultConfigId=j.id,J=j.id}),J)return console.log(`[ideawave-cli] using agent runtime: ${X.displayName}`),J}return console.warn("[ideawave-cli] no agent runtime detected on PATH (tried claude, codex, gh copilot, opencode). Install one to run agents."),null}catch($){return console.warn("[ideawave-cli] runtime auto-seed failed",$),null}}function hX(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class E${sessions=new Map;createCallId;toolCallTimeoutMs;constructor($={}){this.createCallId=$.createCallId??hX,this.toolCallTimeoutMs=$.toolCallTimeoutMs??120000}register($){let X=this.sessions.get($.frontendSessionId);if(X){if(X.userId!==$.userId)this.rejectPending(X,"frontend session user changed"),X.activeRunIds.clear();this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:X.pendingToolCalls,activeRunIds:X.activeRunIds,activeRunCardIds:X.activeRunCardIds});return}this.sessions.set($.frontendSessionId,{frontendSessionId:$.frontendSessionId,userId:$.userId,tools:$.tools,send:$.send,pendingToolCalls:new Map,activeRunIds:new Set,activeRunCardIds:new Map})}disconnect($,X="frontend session disconnected"){let Z=this.sessions.get($);if(!Z)return{activeRunIds:[]};return this.sessions.delete($),this.rejectPending(Z,X),{activeRunIds:Array.from(Z.activeRunIds)}}sessionCount(){return this.sessions.size}has($){return this.sessions.has($)}getUserId($){return this.sessions.get($)?.userId??null}setMetadata($,X){let Z=this.sessions.get($);if(Z)Z.tools=X}getMetadata($){if(!$)return[];return this.sessions.get($)?.tools??[]}sendToSession($,X){let Z=this.sessions.get($);if(!Z)return!1;return Z.send(X),!0}callTool($,X,Z,J,Q){if(!$)return Promise.reject(Error("MCP tool call is missing a frontend session id"));let j=this.sessions.get($);if(!j)return Promise.reject(Error(`Frontend session ${$} is not connected`));let W=this.createCallId();return new Promise((G,z)=>{let K=setTimeout(()=>{j.pendingToolCalls.delete(W),z(Error(`Tool "${X}" timed out waiting for the frontend`))},this.toolCallTimeoutMs),H=J??(Q?this.getActiveRunIdForCard(j,Q):this.getSoleActiveRunId(j)),B=Q??(H?j.activeRunCardIds.get(H):void 0);j.pendingToolCalls.set(W,{resolve:G,reject:z,timer:K}),j.send({type:"tool_call",callId:W,name:X,args:Z,...H?{runId:H}:{},...B?{cardId:B}:{}})})}handleToolResult($,X){let Z=this.sessions.get($);if(!Z)return;let J=Z.pendingToolCalls.get(X.callId);if(!J)return;if(Z.pendingToolCalls.delete(X.callId),clearTimeout(J.timer),X.ok)J.resolve(X.result);else J.reject(Error(X.error??"Tool execution failed"))}markRunActive($,X,Z){let J=this.sessions.get($);if(!J)return;if(J.activeRunIds.add(X),Z)J.activeRunCardIds.set(X,Z)}markRunSettled($,X){let Z=this.sessions.get($);if(!Z)return;Z.activeRunIds.delete(X),Z.activeRunCardIds.delete(X)}ownsRun($,X){return this.sessions.get($)?.activeRunIds.has(X)??!1}rejectPending($,X){for(let Z of $.pendingToolCalls.values())clearTimeout(Z.timer),Z.reject(Error(X));$.pendingToolCalls.clear()}getSoleActiveRunId($){return $.activeRunIds.size===1?$.activeRunIds.values().next().value:void 0}getActiveRunIdForCard($,X){let Z=[...$.activeRunCardIds.entries()].filter(([J,Q])=>$.activeRunIds.has(J)&&Q===X).map(([J])=>J);return Z.length===1?Z[0]:void 0}}function SX(){return"0.0.45".trim()?"0.0.45":"dev"}var o=process.argv[2];if(o==="--help"||o==="-h"||o==="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(o==="--version"||o==="-v"||o==="version")console.log(SX()),process.exit(0);if(o)console.error(`Unknown command: ${o}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var M0=new E$,K0=null;function N0($,X){M0.sendToSession($,X)}async function mX($,X){try{let Z=F2[X.method],J=await Z(X.params);N0($,{type:"runtime_rpc_result",requestId:X.requestId,ok:!0,result:J})}catch(Z){N0($,{type:"runtime_rpc_result",requestId:X.requestId,ok:!1,error:Z instanceof Error?Z.message:String(Z)})}}var q0=!1,D0=null;async function y$(){if(q0)return;if(D0)return D0;return D0=(async()=>{try{let $=await x2(M0);h$({...$,requestedPort:$.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${$.url}`);try{await e$({onStatusChange:(X)=>{if(C1(),K0?.sendStatus(),X.status==="failed")console.warn(`[ideawave-cli] ACP bridge setup failed for ${X.packageName}: ${X.error??"unknown error"}`)}})}catch(X){console.warn("[ideawave-cli] ACP bridge setup skipped:",X instanceof Error?X.message:String(X))}await P2(),q0=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),K0?.sendStatus()}catch($){console.error("[ideawave-cli] failed to start agent host:",$),K0?.sendStatus(void 0,$ instanceof Error?$.message:String($))}finally{D0=null}})(),D0}if(process.env.APP_ENV!=="development"){let $=await j2();if($)console.error(`[ideawave-cli] An IdeaWave CLI is already running at ${$}.`),console.error("[ideawave-cli] Only one CLI per machine is supported — it already serves every browser tab. Exiting."),process.exit(0)}K0=await W2({registry:M0,runtime:null,mcpReady:()=>q0,onToolMetadata:($)=>{console.log(`[ideawave-cli] session ${$} advertised ${M0.getMetadata($).length} tools`),y$()},onRunTurn:($,X)=>{console.log(`[ideawave-cli] running agent turn for card ${X.cardId} (session ${$})`),(async()=>{if(await y$(),!q0){N0($,{type:"run_settled",runId:X.runId,cardId:X.cardId,result:{assistantContent:"",model:null,latencyMs:0,errorText:"IdeaWave CLI agent host is not ready",partialText:null}});return}await o1(X,(Z)=>N0($,Z))})().catch(()=>{return}).finally(()=>M0.markRunSettled($,X.runId))},onCancelRun:($,X)=>{k$(X)},onRuntimeRpc:($,X)=>{mX($,X)},onWarmupRun:($,X,Z)=>{(async()=>{if(await y$(),!q0)return{status:"retryable",error:"agent host is not ready"};return s1({cardId:X.cardId,boardId:X.boardId,userId:Z,frontendSessionId:$})})().then((J)=>{if(!X.warmupId)return;N0($,{type:"warmup_result",warmupId:X.warmupId,cardId:X.cardId,...J})})},onDisconnect:($,X)=>{a1($);for(let Z of X)k$(Z);console.log(`[ideawave-cli] browser session ${$} disconnected`)}});console.log(`[ideawave-cli] browser bridge listening on ${K0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var L2=!1;for(let $ of["SIGINT","SIGTERM"])process.once($,()=>{if(L2)return;L2=!0,d1(),(async()=>{await K0?.close().catch(()=>{return}),process.exit(0)})()});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideawave",
3
- "version": "0.0.44",
3
+ "version": "0.0.45",
4
4
  "description": "IdeaWave CLI",
5
5
  "type": "module",
6
6
  "bin": {