ideawave 0.0.54 → 0.0.55

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 E1($,X){if(!X)return $;if(!$)return X;if($===X||$.endsWith(X))return $;if(X.startsWith($))return X;return e(`${$}
17
17
 
18
- ${X}`)}function D$($){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 R1($){let{ctx:X,appendText:Z,appendToolActivity:J}=$,Q=$.flushIntervalMs??CX,K="",j="",U=0,G=null,Y={},z=new Map,B=(L)=>{if(z.set(L.toolCallId,L),!J)return;J({boardId:X.boardId,cardId:X.cardId,runId:X.runId,entry:L}).catch((W)=>{console.warn("[streamAdapter] appendToolActivity failed",W)})},H=(L)=>{let W=`${X.runId}:thought`,P=z.get(W);if(!P||P.status!=="running")return;B({...P,status:"completed",completedAt:P.completedAt??L})},M=(L)=>{for(let W of z.values()){if(W.status!=="running"||W.rawTitle.toLowerCase()!=="toolsearch")continue;B({...W,status:"completed",completedAt:W.completedAt??L})}},N=(L)=>{for(let W of Array.from(z.values())){if(W.status!=="running")continue;if(W.kind==="thought"||W.rawTitle==="agent_thought")continue;B({...W,status:"completed",completedAt:W.completedAt??L})}},x="",V=0,D=null,F=null,O=(L)=>{if(L===x)return;x=L,V=Date.now(),Z({boardId:X.boardId,cardId:X.cardId,runId:X.runId,text:L}).catch((W)=>{console.warn("[streamAdapter] appendText failed",W)})},C=()=>{if(D!==null)clearTimeout(D),D=null;if(F!==null){let L=F;F=null,O(L)}},A=(L)=>{let W=Date.now()-V;if(W>=Q&&D===null){O(L);return}if(F=L,D===null){let P=Math.max(0,Q-W);D=setTimeout(()=>{D=null,C()},P)}};return{onSessionUpdate:async(L)=>{let W=L.update;switch(Y[W.sessionUpdate]=(Y[W.sessionUpdate]??0)+1,W.sessionUpdate){case"agent_message_chunk":{let P=new Date().toISOString();if(H(P),W.content.type==="text")K+=W.content.text,A(K);else{let T=`agent_message_chunk:${W.content.type}`;Y[T]=(Y[T]??0)+1}return}case"agent_thought_chunk":{if(W.content.type!=="text")return;j+=W.content.text;let P=new Date().toISOString(),T=`${X.runId}:thought`,E=z.get(T);B({toolCallId:T,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:E?.startedAt??P,completedAt:null,contentPreview:e(j.trim())});return}case"user_message_chunk":return;case"tool_call":{U+=1;let P=w1(W.title),T=G$(W.status),E=new Date().toISOString();H(E),M(E),B({toolCallId:W.toolCallId,rawTitle:P,title:H$(P,W.rawInput),kind:z$(W.kind),status:T,startedAt:E,completedAt:T==="running"?null:E,inputPreview:l(W.rawInput),outputPreview:U$(W.rawOutput),contentPreview:y0(W.content),locations:D$(W.locations)});return}case"tool_call_update":{let P=z.get(W.toolCallId);if(!P){let p=w1(W.title),B0=G$(W.status),X0=new Date().toISOString();B({toolCallId:W.toolCallId,rawTitle:p,title:H$(p,W.rawInput),kind:z$(W.kind),status:B0,startedAt:X0,completedAt:B0==="running"?null:X0,inputPreview:l(W.rawInput),outputPreview:U$(W.rawOutput),contentPreview:y0(W.content),locations:D$(W.locations)});return}let T=W.status===void 0||W.status===null?P.status:G$(W.status),E=typeof W.title==="string"&&W.title.trim().length>0?W.title:P.rawTitle,k=typeof W.title==="string"&&W.title.trim().length>0,R=T==="running"?P.completedAt:P.completedAt??new Date().toISOString(),b=W.content===void 0?P.contentPreview:E1(P.contentPreview,y0(W.content)),v=W.rawOutput===void 0?P.outputPreview:E1(P.outputPreview,U$(W.rawOutput));B({...P,rawTitle:E,title:k?H$(E,W.rawInput):P.title,kind:W.kind===void 0?P.kind:z$(W.kind),status:T,completedAt:R,inputPreview:W.rawInput===void 0?P.inputPreview:l(W.rawInput),outputPreview:v,contentPreview:b,locations:W.locations===void 0?P.locations:D$(W.locations)});return}case"plan":G=W.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>K,getToolCallCount:()=>U,getLatestPlan:()=>G,getUpdateTypeCounts:()=>({...Y}),flush:(L)=>{let W=new Date().toISOString();if(H(W),L?.completeOpenToolCalls)N(W);C()}}}var U0=1,b1=-32000;function y1($){if($.awaitingInput)return!1;return $.nowMs-$.lastUpdateMs>$.windowMs}function v1($){if(!$||typeof $!=="object")return!1;return $.code===b1}var RX=300000,bX=5000;function I1(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.54".trim()?"0.0.54":"dev"}}function S1($){if($===U0)return;throw new _(`Unsupported ACP protocol version ${$}; expected ${U0}`)}function m1($){return TX.toWeb($)}function g1($){return EX.toWeb($)}function M$($){return $!==null&&typeof $==="object"}function yX($){if(!Array.isArray($))return[];let X=[];for(let Z of $){if(!M$(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(!M$(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 fX($){if(!M$($))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:yX($.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 N$($){let X=($.configOptions??[]).map(fX).filter((U)=>U!==null),Z=X.find((U)=>U.type==="select"&&U.category==="model")??X.find((U)=>U.type==="select"&&U.id==="model")??null,J=Z?.options.map((U)=>({id:U.value,name:U.name,description:U.description??null})),Q=hX($.models),K=J&&J.length>0?J:Q&&Q.length>0?Q:null,j=(typeof Z?.currentValue==="string"?Z.currentValue:null)??vX($.models)??null;return{models:K,currentModelId:j,configOptions:X,modelConfigId:Z?.id??null}}function hX($){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 vX($){return typeof $?.currentModelId==="string"?$.currentModelId:null}function IX($,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 SX($){if(typeof $.value==="boolean")return{sessionId:$.sessionId,configId:$.configId,type:"boolean",value:$.value};return{sessionId:$.sessionId,configId:$.configId,value:$.value}}function mX($,X){let Z=N$({configOptions:X.configOptions});return{models:Z.models??$.models,currentModelId:Z.currentModelId??$.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??$.modelConfigId}}function c1($,X){if($==="default")return null;if(!X||X.length===0)return $;let Z=X.find((Y)=>Y.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 K=(Y)=>`${Y.id} ${Y.name??""} ${Y.description??""}`.toLowerCase(),j=X.filter((Y)=>K(Y).includes(Q));if(j.length===0)return $;let G=(J.includes("1m")?j.find((Y)=>K(Y).includes("1m")):void 0)??j[0];return G?G.id:$}async function h0($){try{let X=await $.conn.setSessionConfigOption(SX({sessionId:$.sessionId,configId:$.configId,value:$.value}));return mX($.metadata,X)}catch(X){return console.warn(`[acp] setSessionConfigOption(${$.label}) failed; using agent default.`,X instanceof Error?X.message:X),$.metadata}}async function q$($){let X=W$($.spawn),Z=[],J=0,Q=4096;X.stderr.on("data",(k)=>{Z.push(k),J+=k.length;while(J>Q*2&&Z.length>1){let R=Z.shift();if(R)J-=R.length}});let K=()=>{let k=Buffer.concat(Z).toString("utf8");return k.length>Q?k.slice(-Q):k},j=C1($.spawn.cwd),U={current:null},G={at:Date.now()},Y=g1(X.stdin),z=m1(X.stdout),B=h1(Y,z),M=new f1((k)=>({requestPermission:async(R)=>{let b=R.options,v=b?.find((p)=>p.kind==="allow_once")??b?.find((p)=>p.kind==="allow_always");if(v)return{outcome:{outcome:"selected",optionId:v.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(R)=>{G.at=Date.now();let b=U.current;if(b)await b.onSessionUpdate(R)},readTextFile:j.readTextFile}),B),N=()=>X.kill();if($.signal)$.signal.addEventListener("abort",N);let x=()=>{if($.signal)$.signal.removeEventListener("abort",N)},V=async(k,R)=>{if(x(),X.kill(),v1(k))throw new J0(k.message??"Authentication required",R);if(k instanceof Error&&k.message==="ACP connection closed"){if($.signal?.aborted)throw new _("ACP session cancelled: abort signal received");let b=await Promise.race([X.processCrashed,X.waitForExit,new Promise((v)=>setTimeout(()=>v({stderr:""}),500))]);throw new _(`Runtime process exited before completion: ${b.stderr?.trim()??""}`)}throw k},D;try{D=await M.initialize({protocolVersion:U0,clientCapabilities:j$,clientInfo:I1()})}catch(k){throw await V(k,[]),Error("unreachable")}try{S1(D.protocolVersion)}catch(k){throw x(),X.kill(),k}let F=D.authMethods?.map((k)=>k.id)??[],O;try{O=await M.newSession({cwd:$.spawn.cwd,mcpServers:$.mcpServers??[]})}catch(k){throw await V(k,F),Error("unreachable")}let C=O.sessionId,A=N$(O),L=$.modelId??null,W=L?c1(L,A.models):null;if(W&&W!==A.currentModelId)if(A.modelConfigId)A=await h0({conn:M,sessionId:C,configId:A.modelConfigId,value:W,metadata:A,label:`${A.modelConfigId}=${W}`});else console.warn(`[acp] runtime did not advertise a model config option for ${W}; using agent default.`);for(let[k,R]of Object.entries($.configValues??{}).sort(([b],[v])=>b.localeCompare(v))){if(k===A.modelConfigId)continue;if(!A.configOptions.some((b)=>b.id===k))continue;A=await h0({conn:M,sessionId:C,configId:k,value:R,metadata:A,label:`${k}=${String(R)}`})}x();let P=!1,T=async()=>{if(P)return;P=!0,X.kill(),await Promise.race([X.waitForExit,new Promise((k)=>setTimeout(k,2000))])},E=!1;return X.processCrashed.then(()=>{E=!0}),{sessionId:C,availableModels:A.models,currentModelId:A.currentModelId,availableConfigOptions:A.configOptions,isAlive:()=>!P&&!E,dispose:T,prompt:(k)=>gX({proc:X,conn:M,sessionId:C,activeAdapter:U,lastUpdate:G,collectStderrTail:K},k)}}async function gX($,X){let{proc:Z,conn:J,sessionId:Q,activeAdapter:K,lastUpdate:j}=$,U={boardId:X.boardId,cardId:X.cardId,runId:X.runId},G=R1({ctx:U,appendText:X.appendText,appendToolActivity:X.appendToolActivity});K.current=G,j.at=Date.now();let Y=!1,z=null,B=()=>Z.kill();X.signal.addEventListener("abort",B);try{let H=async()=>{let V=X.heartbeatMs??RX,D=Math.min(bX,Math.max(50,Math.floor(V/2)));z=setInterval(()=>{let O=X.isAwaitingInput?.()??!1;if(O){j.at=Date.now();return}if(y1({nowMs:Date.now(),lastUpdateMs:j.at,windowMs:V,awaitingInput:O}))Y=!0,J.cancel({sessionId:Q}).catch(()=>{return}),Z.kill()},D);let F=IX(X.prompt.systemPrompt,X.prompt.messages);await J.prompt({sessionId:Q,prompt:F}),G.flush({completeOpenToolCalls:!0})},M=Z.waitForExit.then((V)=>({kind:"exited",exit:V})),N=H().then(()=>({kind:"ok"})).catch(async(V)=>{if(V instanceof Error&&V.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw V}),x;try{x=await Promise.race([N,Z.processCrashed.then((V)=>({kind:"crashed",exit:V})),M])}catch(V){if(Y)throw new a;throw V}if(Y)throw new a;if(x.kind==="crashed")throw new _(`Runtime process exited before completion: ${x.exit.stderr.trim()}`);if(x.kind==="exited"){if(X.signal.aborted)throw new _("ACP session cancelled: abort signal received");if(Y)throw new a;throw new _(`Runtime process exited unexpectedly: ${x.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:G.getFinalText(),toolCallsExecuted:G.getToolCallCount(),stderrTail:$.collectStderrTail(),updateTypeCounts:G.getUpdateTypeCounts()}}finally{if(z!==null)clearInterval(z);X.signal.removeEventListener("abort",B),G.flush({completeOpenToolCalls:!0}),K.current=null}}var cX=30000;async function l1($){let X=W$($.spawn),Z=g1(X.stdin),J=m1(X.stdout),Q=h1(Z,J),j=new f1((Y)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),U=()=>X.kill();if($.signal)$.signal.addEventListener("abort",U);let G=null;try{let Y=(async()=>{let B=await j.initialize({protocolVersion:U0,clientCapabilities:j$,clientInfo:I1()});S1(B.protocolVersion);let H=B.authMethods?.map((O)=>O.id)??[],M;try{M=await j.newSession({cwd:$.spawn.cwd,mcpServers:[]})}catch(O){if(v1(O))throw new J0(O.message??"Authentication required",H);throw O}let N=N$(M),x=$.modelId??null,V=x?c1(x,N.models):null;if(V&&V!==N.currentModelId)if(N.modelConfigId)N=await h0({conn:j,sessionId:M.sessionId,configId:N.modelConfigId,value:V,metadata:N,label:`${N.modelConfigId}=${V}`});else console.warn(`[acp] runtime did not advertise a model config option for ${V}; discovering agent default models.`);for(let[O,C]of Object.entries($.configValues??{}).sort(([A],[L])=>A.localeCompare(L))){if(O===N.modelConfigId)continue;if(!N.configOptions.some((A)=>A.id===O))continue;N=await h0({conn:j,sessionId:M.sessionId,configId:O,value:C,metadata:N,label:`${O}=${String(C)}`})}let D=N.models??[],F=N.currentModelId;return j.cancel({sessionId:M.sessionId}).catch(()=>{return}),{models:D,configOptions:N.configOptions,currentModelId:F}})(),z=new Promise((B,H)=>{G=setTimeout(()=>{H(new a)},cX)});return await Promise.race([Y,z])}catch(Y){if(Y instanceof Error&&Y.message==="ACP connection closed"){if($.signal?.aborted)throw new _("ACP model discovery cancelled: abort signal received");throw new _("Runtime process exited during model discovery.")}throw Y}finally{if(G)clearTimeout(G);if($.signal)$.signal.removeEventListener("abort",U);X.kill()}}var y=new Map,u=null;function v0($){$.then((X)=>X.dispose()).catch(()=>{return})}function lX(){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 uX(){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 B$($,X,Z){return`${$}:${X}:${Z}`}async function F$($){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();uX(),y.set($.key,{key:$.key,fingerprint:$.fingerprint,sessionPromise:Z,lastUsed:Date.now(),inUse:!0}),lX();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 pX(){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 P$($){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 u1=!1;function aX(){if(u1)return;u1=!0;let $=()=>{pX()};process.once("beforeExit",$),process.once("SIGTERM",$),process.once("SIGINT",$)}aX();import dX from"node:fs/promises";import I0 from"node:os";async function p1($){let X={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await dX.readFile($,"utf-8")}catch(J){if(J.code==="ENOENT")return structuredClone(X);throw J}return x0.parse(JSON.parse(Z))}function L$($,X,Z){return{...$.defaultConfigValues??{},...X?.configValues??{},...Z?.configValues??{}}}async function i($){let X=$.configPath?await p1($.configPath):await I(),Z=$.cardId?X.cardOverrides[$.cardId]:void 0;if(Z?.runtimeConfigId){let Q=X.runtimes.find((K)=>K.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:L$(Q,void 0,Z)}}let J=X.boardOverrides[$.boardId];if(J?.runtimeConfigId){let Q=X.runtimes.find((K)=>K.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:L$(Q,J)}}if(X.globalDefaultConfigId){let Q=X.runtimes.find((K)=>K.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:L$(Q,J,Z)}}throw new t}async function a1($,X={}){let J=(X.configPath?await p1(X.configPath):await I()).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 d1=new Map;function k$($,X){if(!$)return;d1.set($,X)}function i1($){if(!$)return!1;return d1.get($)??!1}var $0=new Map,O$=new Set;function A$($){$0.get($)?.controller.abort()}function o1($){for(let[X,Z]of $0){if(Z.frontendSessionId!==$)continue;Z.controller.abort(),$0.delete(X)}}function n1(){for(let $ of $0.values())$.controller.abort();$0.clear()}function _$($,X){if(X?.aborted)return!0;return $ instanceof Error&&/abort signal received|session cancelled/i.test($.message)}function s1($,X,Z,J){if((!X.availableModels||X.availableModels.length===0)&&X.availableConfigOptions.length===0)return;g((Q)=>{let K=Q.runtimes.find((j)=>j.id===$);if(K){if(X.availableModels&&X.availableModels.length>0)K.discoveredModels=T0({adapterId:Z,models:X.availableModels,currentModelId:X.currentModelId??J});if(X.availableConfigOptions.length>0)K.discoveredConfigOptions=X.availableConfigOptions}}).catch(()=>{return})}function iX($,X){return`${$}
18
+ ${X}`)}function D$($){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 R1($){let{ctx:X,appendText:Z,appendToolActivity:J}=$,Q=$.flushIntervalMs??CX,K="",j="",U=0,G=null,Y={},z=new Map,B=(L)=>{if(z.set(L.toolCallId,L),!J)return;J({boardId:X.boardId,cardId:X.cardId,runId:X.runId,entry:L}).catch((W)=>{console.warn("[streamAdapter] appendToolActivity failed",W)})},H=(L)=>{let W=`${X.runId}:thought`,P=z.get(W);if(!P||P.status!=="running")return;B({...P,status:"completed",completedAt:P.completedAt??L})},M=(L)=>{for(let W of z.values()){if(W.status!=="running"||W.rawTitle.toLowerCase()!=="toolsearch")continue;B({...W,status:"completed",completedAt:W.completedAt??L})}},N=(L)=>{for(let W of Array.from(z.values())){if(W.status!=="running")continue;if(W.kind==="thought"||W.rawTitle==="agent_thought")continue;B({...W,status:"completed",completedAt:W.completedAt??L})}},x="",V=0,D=null,F=null,O=(L)=>{if(L===x)return;x=L,V=Date.now(),Z({boardId:X.boardId,cardId:X.cardId,runId:X.runId,text:L}).catch((W)=>{console.warn("[streamAdapter] appendText failed",W)})},C=()=>{if(D!==null)clearTimeout(D),D=null;if(F!==null){let L=F;F=null,O(L)}},A=(L)=>{let W=Date.now()-V;if(W>=Q&&D===null){O(L);return}if(F=L,D===null){let P=Math.max(0,Q-W);D=setTimeout(()=>{D=null,C()},P)}};return{onSessionUpdate:async(L)=>{let W=L.update;switch(Y[W.sessionUpdate]=(Y[W.sessionUpdate]??0)+1,W.sessionUpdate){case"agent_message_chunk":{let P=new Date().toISOString();if(H(P),W.content.type==="text")K+=W.content.text,A(K);else{let T=`agent_message_chunk:${W.content.type}`;Y[T]=(Y[T]??0)+1}return}case"agent_thought_chunk":{if(W.content.type!=="text")return;j+=W.content.text;let P=new Date().toISOString(),T=`${X.runId}:thought`,E=z.get(T);B({toolCallId:T,rawTitle:"agent_thought",title:"Thought",kind:"thought",status:"running",startedAt:E?.startedAt??P,completedAt:null,contentPreview:e(j.trim())});return}case"user_message_chunk":return;case"tool_call":{U+=1;let P=w1(W.title),T=G$(W.status),E=new Date().toISOString();H(E),M(E),B({toolCallId:W.toolCallId,rawTitle:P,title:H$(P,W.rawInput),kind:z$(W.kind),status:T,startedAt:E,completedAt:T==="running"?null:E,inputPreview:l(W.rawInput),outputPreview:U$(W.rawOutput),contentPreview:y0(W.content),locations:D$(W.locations)});return}case"tool_call_update":{let P=z.get(W.toolCallId);if(!P){let p=w1(W.title),B0=G$(W.status),X0=new Date().toISOString();B({toolCallId:W.toolCallId,rawTitle:p,title:H$(p,W.rawInput),kind:z$(W.kind),status:B0,startedAt:X0,completedAt:B0==="running"?null:X0,inputPreview:l(W.rawInput),outputPreview:U$(W.rawOutput),contentPreview:y0(W.content),locations:D$(W.locations)});return}let T=W.status===void 0||W.status===null?P.status:G$(W.status),E=typeof W.title==="string"&&W.title.trim().length>0?W.title:P.rawTitle,k=typeof W.title==="string"&&W.title.trim().length>0,R=T==="running"?P.completedAt:P.completedAt??new Date().toISOString(),b=W.content===void 0?P.contentPreview:E1(P.contentPreview,y0(W.content)),v=W.rawOutput===void 0?P.outputPreview:E1(P.outputPreview,U$(W.rawOutput));B({...P,rawTitle:E,title:k?H$(E,W.rawInput):P.title,kind:W.kind===void 0?P.kind:z$(W.kind),status:T,completedAt:R,inputPreview:W.rawInput===void 0?P.inputPreview:l(W.rawInput),outputPreview:v,contentPreview:b,locations:W.locations===void 0?P.locations:D$(W.locations)});return}case"plan":G=W.entries;return;case"available_commands_update":return;case"current_mode_update":return;default:return}},getFinalText:()=>K,getToolCallCount:()=>U,getLatestPlan:()=>G,getUpdateTypeCounts:()=>({...Y}),flush:(L)=>{let W=new Date().toISOString();if(H(W),L?.completeOpenToolCalls)N(W);C()}}}var U0=1,b1=-32000;function y1($){if($.awaitingInput)return!1;return $.nowMs-$.lastUpdateMs>$.windowMs}function v1($){if(!$||typeof $!=="object")return!1;return $.code===b1}var RX=300000,bX=5000;function I1(){return{name:"ideawave-cli",title:"IdeaWave CLI",version:"0.0.55".trim()?"0.0.55":"dev"}}function S1($){if($===U0)return;throw new _(`Unsupported ACP protocol version ${$}; expected ${U0}`)}function m1($){return TX.toWeb($)}function g1($){return EX.toWeb($)}function M$($){return $!==null&&typeof $==="object"}function yX($){if(!Array.isArray($))return[];let X=[];for(let Z of $){if(!M$(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(!M$(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 fX($){if(!M$($))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:yX($.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 N$($){let X=($.configOptions??[]).map(fX).filter((U)=>U!==null),Z=X.find((U)=>U.type==="select"&&U.category==="model")??X.find((U)=>U.type==="select"&&U.id==="model")??null,J=Z?.options.map((U)=>({id:U.value,name:U.name,description:U.description??null})),Q=hX($.models),K=J&&J.length>0?J:Q&&Q.length>0?Q:null,j=(typeof Z?.currentValue==="string"?Z.currentValue:null)??vX($.models)??null;return{models:K,currentModelId:j,configOptions:X,modelConfigId:Z?.id??null}}function hX($){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 vX($){return typeof $?.currentModelId==="string"?$.currentModelId:null}function IX($,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 SX($){if(typeof $.value==="boolean")return{sessionId:$.sessionId,configId:$.configId,type:"boolean",value:$.value};return{sessionId:$.sessionId,configId:$.configId,value:$.value}}function mX($,X){let Z=N$({configOptions:X.configOptions});return{models:Z.models??$.models,currentModelId:Z.currentModelId??$.currentModelId,configOptions:Z.configOptions,modelConfigId:Z.modelConfigId??$.modelConfigId}}function c1($,X){if($==="default")return null;if(!X||X.length===0)return $;let Z=X.find((Y)=>Y.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 K=(Y)=>`${Y.id} ${Y.name??""} ${Y.description??""}`.toLowerCase(),j=X.filter((Y)=>K(Y).includes(Q));if(j.length===0)return $;let G=(J.includes("1m")?j.find((Y)=>K(Y).includes("1m")):void 0)??j[0];return G?G.id:$}async function h0($){try{let X=await $.conn.setSessionConfigOption(SX({sessionId:$.sessionId,configId:$.configId,value:$.value}));return mX($.metadata,X)}catch(X){return console.warn(`[acp] setSessionConfigOption(${$.label}) failed; using agent default.`,X instanceof Error?X.message:X),$.metadata}}async function q$($){let X=W$($.spawn),Z=[],J=0,Q=4096;X.stderr.on("data",(k)=>{Z.push(k),J+=k.length;while(J>Q*2&&Z.length>1){let R=Z.shift();if(R)J-=R.length}});let K=()=>{let k=Buffer.concat(Z).toString("utf8");return k.length>Q?k.slice(-Q):k},j=C1($.spawn.cwd),U={current:null},G={at:Date.now()},Y=g1(X.stdin),z=m1(X.stdout),B=h1(Y,z),M=new f1((k)=>({requestPermission:async(R)=>{let b=R.options,v=b?.find((p)=>p.kind==="allow_once")??b?.find((p)=>p.kind==="allow_always");if(v)return{outcome:{outcome:"selected",optionId:v.optionId}};return{outcome:{outcome:"cancelled"}}},sessionUpdate:async(R)=>{G.at=Date.now();let b=U.current;if(b)await b.onSessionUpdate(R)},readTextFile:j.readTextFile}),B),N=()=>X.kill();if($.signal)$.signal.addEventListener("abort",N);let x=()=>{if($.signal)$.signal.removeEventListener("abort",N)},V=async(k,R)=>{if(x(),X.kill(),v1(k))throw new J0(k.message??"Authentication required",R);if(k instanceof Error&&k.message==="ACP connection closed"){if($.signal?.aborted)throw new _("ACP session cancelled: abort signal received");let b=await Promise.race([X.processCrashed,X.waitForExit,new Promise((v)=>setTimeout(()=>v({stderr:""}),500))]);throw new _(`Runtime process exited before completion: ${b.stderr?.trim()??""}`)}throw k},D;try{D=await M.initialize({protocolVersion:U0,clientCapabilities:j$,clientInfo:I1()})}catch(k){throw await V(k,[]),Error("unreachable")}try{S1(D.protocolVersion)}catch(k){throw x(),X.kill(),k}let F=D.authMethods?.map((k)=>k.id)??[],O;try{O=await M.newSession({cwd:$.spawn.cwd,mcpServers:$.mcpServers??[]})}catch(k){throw await V(k,F),Error("unreachable")}let C=O.sessionId,A=N$(O),L=$.modelId??null,W=L?c1(L,A.models):null;if(W&&W!==A.currentModelId)if(A.modelConfigId)A=await h0({conn:M,sessionId:C,configId:A.modelConfigId,value:W,metadata:A,label:`${A.modelConfigId}=${W}`});else console.warn(`[acp] runtime did not advertise a model config option for ${W}; using agent default.`);for(let[k,R]of Object.entries($.configValues??{}).sort(([b],[v])=>b.localeCompare(v))){if(k===A.modelConfigId)continue;if(!A.configOptions.some((b)=>b.id===k))continue;A=await h0({conn:M,sessionId:C,configId:k,value:R,metadata:A,label:`${k}=${String(R)}`})}x();let P=!1,T=async()=>{if(P)return;P=!0,X.kill(),await Promise.race([X.waitForExit,new Promise((k)=>setTimeout(k,2000))])},E=!1;return X.processCrashed.then(()=>{E=!0}),{sessionId:C,availableModels:A.models,currentModelId:A.currentModelId,availableConfigOptions:A.configOptions,isAlive:()=>!P&&!E,dispose:T,prompt:(k)=>gX({proc:X,conn:M,sessionId:C,activeAdapter:U,lastUpdate:G,collectStderrTail:K},k)}}async function gX($,X){let{proc:Z,conn:J,sessionId:Q,activeAdapter:K,lastUpdate:j}=$,U={boardId:X.boardId,cardId:X.cardId,runId:X.runId},G=R1({ctx:U,appendText:X.appendText,appendToolActivity:X.appendToolActivity});K.current=G,j.at=Date.now();let Y=!1,z=null,B=()=>Z.kill();X.signal.addEventListener("abort",B);try{let H=async()=>{let V=X.heartbeatMs??RX,D=Math.min(bX,Math.max(50,Math.floor(V/2)));z=setInterval(()=>{let O=X.isAwaitingInput?.()??!1;if(O){j.at=Date.now();return}if(y1({nowMs:Date.now(),lastUpdateMs:j.at,windowMs:V,awaitingInput:O}))Y=!0,J.cancel({sessionId:Q}).catch(()=>{return}),Z.kill()},D);let F=IX(X.prompt.systemPrompt,X.prompt.messages);await J.prompt({sessionId:Q,prompt:F}),G.flush({completeOpenToolCalls:!0})},M=Z.waitForExit.then((V)=>({kind:"exited",exit:V})),N=H().then(()=>({kind:"ok"})).catch(async(V)=>{if(V instanceof Error&&V.message==="ACP connection closed")return{kind:"crashed",exit:await Promise.race([Z.processCrashed,Z.waitForExit])};throw V}),x;try{x=await Promise.race([N,Z.processCrashed.then((V)=>({kind:"crashed",exit:V})),M])}catch(V){if(Y)throw new a;throw V}if(Y)throw new a;if(x.kind==="crashed")throw new _(`Runtime process exited before completion: ${x.exit.stderr.trim()}`);if(x.kind==="exited"){if(X.signal.aborted)throw new _("ACP session cancelled: abort signal received");if(Y)throw new a;throw new _(`Runtime process exited unexpectedly: ${x.exit.stderr.trim()}`)}return{modelReported:"unknown",finalText:G.getFinalText(),toolCallsExecuted:G.getToolCallCount(),stderrTail:$.collectStderrTail(),updateTypeCounts:G.getUpdateTypeCounts()}}finally{if(z!==null)clearInterval(z);X.signal.removeEventListener("abort",B),G.flush({completeOpenToolCalls:!0}),K.current=null}}var cX=30000;async function l1($){let X=W$($.spawn),Z=g1(X.stdin),J=m1(X.stdout),Q=h1(Z,J),j=new f1((Y)=>({requestPermission:async()=>({outcome:{outcome:"cancelled"}}),sessionUpdate:async()=>{return},readTextFile:async()=>({content:""})}),Q),U=()=>X.kill();if($.signal)$.signal.addEventListener("abort",U);let G=null;try{let Y=(async()=>{let B=await j.initialize({protocolVersion:U0,clientCapabilities:j$,clientInfo:I1()});S1(B.protocolVersion);let H=B.authMethods?.map((O)=>O.id)??[],M;try{M=await j.newSession({cwd:$.spawn.cwd,mcpServers:[]})}catch(O){if(v1(O))throw new J0(O.message??"Authentication required",H);throw O}let N=N$(M),x=$.modelId??null,V=x?c1(x,N.models):null;if(V&&V!==N.currentModelId)if(N.modelConfigId)N=await h0({conn:j,sessionId:M.sessionId,configId:N.modelConfigId,value:V,metadata:N,label:`${N.modelConfigId}=${V}`});else console.warn(`[acp] runtime did not advertise a model config option for ${V}; discovering agent default models.`);for(let[O,C]of Object.entries($.configValues??{}).sort(([A],[L])=>A.localeCompare(L))){if(O===N.modelConfigId)continue;if(!N.configOptions.some((A)=>A.id===O))continue;N=await h0({conn:j,sessionId:M.sessionId,configId:O,value:C,metadata:N,label:`${O}=${String(C)}`})}let D=N.models??[],F=N.currentModelId;return j.cancel({sessionId:M.sessionId}).catch(()=>{return}),{models:D,configOptions:N.configOptions,currentModelId:F}})(),z=new Promise((B,H)=>{G=setTimeout(()=>{H(new a)},cX)});return await Promise.race([Y,z])}catch(Y){if(Y instanceof Error&&Y.message==="ACP connection closed"){if($.signal?.aborted)throw new _("ACP model discovery cancelled: abort signal received");throw new _("Runtime process exited during model discovery.")}throw Y}finally{if(G)clearTimeout(G);if($.signal)$.signal.removeEventListener("abort",U);X.kill()}}var y=new Map,u=null;function v0($){$.then((X)=>X.dispose()).catch(()=>{return})}function lX(){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 uX(){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 B$($,X,Z){return`${$}:${X}:${Z}`}async function F$($){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();uX(),y.set($.key,{key:$.key,fingerprint:$.fingerprint,sessionPromise:Z,lastUsed:Date.now(),inUse:!0}),lX();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 pX(){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 P$($){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 u1=!1;function aX(){if(u1)return;u1=!0;let $=()=>{pX()};process.once("beforeExit",$),process.once("SIGTERM",$),process.once("SIGINT",$)}aX();import dX from"node:fs/promises";import I0 from"node:os";async function p1($){let X={version:1,globalDefaultConfigId:null,runtimes:[],boardOverrides:{},cardOverrides:{}},Z;try{Z=await dX.readFile($,"utf-8")}catch(J){if(J.code==="ENOENT")return structuredClone(X);throw J}return x0.parse(JSON.parse(Z))}function L$($,X,Z){return{...$.defaultConfigValues??{},...X?.configValues??{},...Z?.configValues??{}}}async function i($){let X=$.configPath?await p1($.configPath):await I(),Z=$.cardId?X.cardOverrides[$.cardId]:void 0;if(Z?.runtimeConfigId){let Q=X.runtimes.find((K)=>K.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:L$(Q,void 0,Z)}}let J=X.boardOverrides[$.boardId];if(J?.runtimeConfigId){let Q=X.runtimes.find((K)=>K.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:L$(Q,J)}}if(X.globalDefaultConfigId){let Q=X.runtimes.find((K)=>K.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:L$(Q,J,Z)}}throw new t}async function a1($,X={}){let J=(X.configPath?await p1(X.configPath):await I()).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 d1=new Map;function k$($,X){if(!$)return;d1.set($,X)}function i1($){if(!$)return!1;return d1.get($)??!1}var $0=new Map,O$=new Set;function A$($){$0.get($)?.controller.abort()}function o1($){for(let[X,Z]of $0){if(Z.frontendSessionId!==$)continue;Z.controller.abort(),$0.delete(X)}}function n1(){for(let $ of $0.values())$.controller.abort();$0.clear()}function _$($,X){if(X?.aborted)return!0;return $ instanceof Error&&/abort signal received|session cancelled/i.test($.message)}function s1($,X,Z,J){if((!X.availableModels||X.availableModels.length===0)&&X.availableConfigOptions.length===0)return;g((Q)=>{let K=Q.runtimes.find((j)=>j.id===$);if(K){if(X.availableModels&&X.availableModels.length>0)K.discoveredModels=T0({adapterId:Z,models:X.availableModels,currentModelId:X.currentModelId??J});if(X.availableConfigOptions.length>0)K.discoveredConfigOptions=X.availableConfigOptions}}).catch(()=>{return})}function iX($,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 GZ($,X){return new Promise((Z,J)=>{let Q=(j)=>{$.off("listening",K),J(j)},K=()=>{$.off("error",Q);let j=$.address();if(!j||typeof j==="string"){J(Error("Failed to read CLI bridge server address"));return}Z(j.port)};$.once("error",Q),$.once("listening",K),$.listen(X,"127.0.0.1")})}function K6($){return new Promise((X,Z)=>{$.close((J)=>{if(J)Z(J);else X()})})}async function W6($,X=w$()){let Z=new Map,J=new Map,Q=$.maxMessageSize??eX,K=!1,j=(H)=>{let M=J.get(H);if(M)clearTimeout(M);J.delete(H)},U=(H)=>{J.delete(H);let{activeRunIds:M}=$.registry.disconnect(H);$.onDisconnect(H,M)},G=(H,M)=>{let N={type:"cli_status",connected:!0,runtime:$.runtime,mcpReady:$.mcpReady(),error:M};if(H){let x=Z.get(H);if(x)Y0(x,N);return}for(let x of Z.values())Y0(x,N)},Y=(H,M)=>{let N=M.sessionId.trim(),x=M.userId.trim();if(!N||!x){Y0(H,{type:"cli_status",connected:!1,runtime:$.runtime,mcpReady:$.mcpReady(),error:"Missing frontend session or user id"}),H.close();return}j(N);let V=Z.get(N);if(V&&V!==H)V.close();H.data.frontendSessionId=N,Z.set(N,H),$.registry.register({frontendSessionId:N,userId:x,tools:M.tools,send:(D)=>Y0(H,D)}),G(N),$.onToolMetadata?.(N)},z=(H,M)=>{let N=$.registry.getUserId(H);if(!N)return;switch(M.type){case"bridge_ping":{let x=Z.get(H);if(x)Y0(x,{type:"bridge_pong"});break}case"tool_metadata":$.registry.setMetadata(H,M.tools),$.onToolMetadata?.(H);break;case"tool_result":$.registry.handleToolResult(H,M);break;case"run_turn":$.registry.markRunActive(H,M.run.runId,M.run.cardId),$.onRunTurn(H,{...M.run,frontendSessionId:H,userId:N});break;case"cancel_run":if($.registry.ownsRun(H,M.runId))$.onCancelRun(H,M.runId);break;case"runtime_rpc":$.onRuntimeRpc(H,M);break;case"warmup_run":$.onWarmupRun(H,{...M,frontendSessionId:H},N);break;default:break}},B=(H,M)=>{let N=J6(H.headers.origin),x=Z6(N),V={Vary:"Origin"};if(x&&N)V["Access-Control-Allow-Origin"]=N,V["Access-Control-Allow-Private-Network"]="true";if(H.method==="OPTIONS"){M.writeHead(204,{...V,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),M.end();return}if(H.method!=="GET"){M.writeHead(405,V),M.end();return}M.writeHead(200,{...V,"content-type":"application/json","cache-control":"no-store"}),M.end(JSON.stringify({ideawave:!0,runtime:$.runtime,mcpReady:$.mcpReady()}))};for(let H of X){let M=tX((V,D)=>{if(new URL(V.url??"/","http://127.0.0.1").pathname===e1){B(V,D);return}D.writeHead(404,{"content-type":"text/plain"}),D.end("IdeaWave CLI bridge")}),N=new rX({noServer:!0,maxPayload:Q}),x=(V)=>{if(V.idleTimer)clearTimeout(V.idleTimer);V.idleTimer=setTimeout(()=>{V.close()},$Z),V.idleTimer.unref?.()};N.on("connection",(V)=>{let D=V;D.data={id:sX(),frontendSessionId:null},D.idleTimer=null,x(D),D.on("ping",()=>x(D)),D.on("pong",()=>x(D)),D.on("error",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);D.close()}),D.on("message",(F)=>{x(D);let O=VZ(F);if(Q>0&&O.length>Q)return;let C=S0(O);if(!C)return;let A=D.data.frontendSessionId;if(!A){if(C.type==="bridge_probe")Y0(D,{type:"bridge_probe_ack",protocolVersion:C.protocolVersion});else if(C.type==="frontend_hello")Y(D,C);return}z(A,C)}),D.on("close",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);let F=D.data.frontendSessionId;if(!F)return;if(Z.get(F)!==D)return;if(Z.delete(F),j(F),K)return;J.set(F,setTimeout(()=>U(F),XZ))})}),M.on("upgrade",(V,D,F)=>{if(new URL(V.url??"/","http://127.0.0.1").pathname!==C$){Q6(D,404,"Not Found");return}if(!Z6(J6(V.headers.origin))){Q6(D,403,"Forbidden");return}N.handleUpgrade(V,D,F,(C)=>{N.emit("connection",C,V)})});try{let V=await GZ(M,H);return{url:`ws://127.0.0.1:${V}${C$}`,port:V,sendStatus:G,close:async()=>{K=!0;for(let D of J.values())clearTimeout(D);J.clear();for(let D of N.clients){let F=D;if(F.idleTimer)clearTimeout(F.idleTimer);F.close()}N.close(),await K6(M).catch(()=>{return})}}}catch(V){if(N.close(),await K6(M).catch(()=>{return}),V?.code==="EADDRINUSE")continue;throw V}}throw Error(`No free IdeaWave CLI bridge port found in ${X[0]}-${X.at(-1)}`)}import{Server as OZ}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as _Z,ListToolsRequestSchema as AZ}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as HZ}from"node:crypto";import{createServer as UZ}from"node:http";import{StreamableHTTPServerTransport as DZ}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as H6}from"@modelcontextprotocol/sdk/types.js";var V6=new Set(["127.0.0.1","localhost","[::1]","::1"]);function zZ($){let X=$.trim();if(X.length===0)return null;if(X.startsWith("[")){let K=X.indexOf("]");if(K===-1)return null;let j=X.slice(0,K+1),U=X.slice(K+1);if(U.length===0)return{host:j,port:null};if(!U.startsWith(":"))return null;let G=Number(U.slice(1));if(!Number.isInteger(G)||G<=0||G>65535)return null;return{host:j,port:G}}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 G6($){return V6.has($)||V6.has($.toLowerCase())}function z6($,X){let Z=$.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let J=zZ(Z);if(!J)return{ok:!1,status:403,reason:"bad-host"};if(!G6(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 K;try{K=new URL(Q)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!G6(K.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var U6="/mcp",MZ=43274,M6=16777216,NZ=1800000,qZ=300000,D6=200,BZ=-32700,o=-32600,E$=-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 R$ extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class b$ extends Error{constructor(){super(`body exceeds ${M6} bytes`);this.name="BodyTooLargeError"}}async function FZ($){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 R$}let Z=0,J=[];for await(let K of $){let j=typeof K==="string"?Buffer.from(K):K;if(Z+=j.byteLength,Z>M6)throw new b$;J.push(j)}if(J.length===0)return;let Q=Buffer.concat(J).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function xZ($){if(Array.isArray($))return $.some(H6);return H6($)}function PZ($){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 MZ}async function LZ($,X){let Z=(Q)=>new Promise((K,j)=>{let U=(Y)=>{$.off("listening",G),j(Y)},G=()=>{$.off("error",U),K()};$.once("error",U),$.once("listening",G),$.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 kZ($,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 K=Q.name;if(typeof K==="string"&&K.trim().length>0)return K.trim()}}}let Z=$.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function N6($){let X=new Map,Z=0;function J(Y){let z=X.get(Y);if(z)z.lastActivity=Date.now()}async function Q(Y,z){X.delete(Y),await z.transport.close().catch(()=>{return})}async function K(){let Y=null,z=1/0;for(let[B,H]of X)if(H.lastActivity<z)z=H.lastActivity,Y=B;if(Y!==null){let B=X.get(Y);if(B)console.warn(`[mcp] session cap of ${D6} reached; evicting ${Y}`),await Q(Y,B)}}let j=setInterval(()=>{let Y=Date.now()-NZ;for(let[z,B]of X)if(B.lastActivity<Y)console.log(`[mcp] sweeping idle session ${z}`),Q(z,B)},qZ);j.unref?.();let U=UZ((Y,z)=>{(async()=>{let B;try{B=new URL(Y.url??"/","http://127.0.0.1").pathname}catch{m(z,400,o,"bad-url");return}if(B!==U6){m(z,404,o,"not-found");return}let H=Y.method??"POST";if(H!=="POST"&&H!=="GET"&&H!=="DELETE"){z.setHeader("Allow","GET, POST, DELETE"),m(z,405,o,"method-not-allowed");return}let M=z6(Y,Z);if(!M.ok){m(z,M.status,o,"forbidden",{reason:M.reason});return}let N=Y.headers["mcp-session-id"],x=typeof N==="string"?N:void 0;if(H==="GET"||H==="DELETE"){if(!x||!X.has(x)){m(z,400,o,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let F=X.get(x).transport;J(x);try{await F.handleRequest(Y,z)}catch(O){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",O),!z.headersSent)m(z,500,E$,"internal")}return}let V;try{V=await FZ(Y)}catch(F){if(F instanceof R$){m(z,415,o,"expected-application-json");return}if(F instanceof b$){m(z,413,o,"body-too-large");return}m(z,400,BZ,"invalid-json");return}let D;if(x&&X.has(x))D=X.get(x).transport,J(x);else if(!x&&V!==void 0&&xZ(V)){let F=Y.headers["x-ideawave-user-id"],O=typeof F==="string"&&F.trim().length>0?F.trim():null,C=Y.headers["x-ideawave-frontend-session-id"],A=typeof C==="string"&&C.trim().length>0?C.trim():null,L=Y.headers["x-ideawave-tool-surface"],W=typeof L==="string"&&L.trim()==="read"?"read":"full",P=Y.headers["x-ideawave-images-supported"],T=typeof P==="string"&&P.trim()==="1",E=Y.headers["x-ideawave-card-id"],k=typeof E==="string"&&E.trim().length>0?E.trim():null,R=Y.headers["x-ideawave-board-id"],b=typeof R==="string"&&R.trim().length>0?R.trim():null,v=Y.headers["x-ideawave-run-folder"],p=typeof v==="string"&&v.trim().length>0?v.trim():null,B0=kZ(Y,V);if(X.size>=D6)await K();let X0=null,s=new DZ({sessionIdGenerator:()=>HZ(),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:O,frontendSessionId:A,boardId:b,toolSurface:W,imagesSupported:T,cardId:k,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(z,500,E$,"server-init-failed");return}D=s}else{m(z,400,o,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await D.handleRequest(Y,z,V)}catch(F){if(console.error("[mcp] transport.handleRequest threw",F),!z.headersSent)m(z,500,E$,"internal")}})().catch((B)=>{console.error("[mcp] unhandled request handler error:",B)})});return Z=await LZ(U,PZ($.port)),{url:`http://127.0.0.1:${Z}${U6}`,port:Z,close:async()=>{clearInterval(j);for(let Y of X.values())await Y.transport.close().catch(()=>{return});X.clear(),await new Promise((Y)=>U.close(()=>Y()))}}}var CZ={name:"ideawave-board",version:"1.0.0"},g0="list_run_folder",c0="read_run_folder_file",F6=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",g0,c0]),x6=new Set(["inspect_diagram"]),wZ=[{name:g0,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:c0,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 y$($){return{content:[{type:"text",text:$}]}}function TZ($){return y$(JSON.stringify($,null,2))}function q6($){return{...y$($),isError:!0}}function EZ($,X,Z="full",J=!1){return $.getMetadata(X).filter((Q)=>{let K=b0(Q.name);if(Z==="read"&&!F6.has(K))return!1;if(!J&&x6.has(K))return!1;return!0}).map((Q)=>({name:Q.name,description:Q.description,inputSchema:Q.inputSchema}))}function RZ($,X,Z={}){let J=EZ($,X,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...J,...wZ]:J}function B6($,X){if(!$||typeof $!=="object"||Array.isArray($))return null;let Z=$[X];return typeof Z==="string"?Z:null}async function bZ($,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 yZ($){let X=await bZ($.boardId,$.cardId,$.runFolder);if($.name===g0){let Z=B6($.args,"path")??"",J=await A1(X,Z);return TZ(J)}if($.name===c0){let Z=B6($.args,"path");if(!Z)return q6("read_run_folder_file requires a path.");return y$(await R0(X,Z))}return q6(`Unknown local tool "${$.name}"`)}function fZ($,X,Z,J,Q,K="full",j=!1){let U=new OZ(CZ,{capabilities:{tools:{}}}),G=async()=>{if(j)return!0;if(i1(J))return!0;if(Z&&J)try{return(await i({boardId:Z,cardId:J})).adapter.supportsImages===!0}catch{return!1}return!1};return U.setRequestHandler(AZ,async()=>({tools:RZ($,X,{includeRunFolderTools:Boolean(Q||Z&&J),toolSurface:K,imagesSupported:await G()})})),U.setRequestHandler(_Z,async(Y)=>{let{name:z,arguments:B}=Y.params,H=b0(z);try{if(H===g0||H===c0)return await yZ({name:H,args:B,boardId:Z,cardId:J,runFolder:Q});if(K==="read"&&!F6.has(H))throw Error(`Tool "${z}" is not available in read-only mode`);if(x6.has(H)&&!await G())throw Error(`Tool "${z}" requires a runtime that supports image input`);let M=await $.callTool(X,H,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}}}),U}function P6($,X){return N6({buildServer:(Z)=>fZ($,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:X})}import l0 from"node:fs/promises";import f$ from"node:os";import u0 from"node:path";function L6(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function hZ(){let[$,X]=await Promise.all([I(),P1()]),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:K0().map((J)=>({id:J.id,displayName:J.displayName})),readiness:X}}async function vZ($){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 IZ($){return g((X)=>{let Z=X.runtimes.find((K)=>K.kind==="registered"&&K.adapterId===$.adapterId);if(Z)return Z;let J=K0().find((K)=>K.id===$.adapterId);if(!J)throw Error(`Unknown adapterId: ${$.adapterId}`);let Q={id:L6(),kind:"registered",adapterId:$.adapterId,displayName:J.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Q),Q})}async function SZ($){return g((X)=>{let Z={id:L6(),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 mZ($){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 gZ($){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 cZ($){$.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 lZ($){let Z=(await I()).runtimes.find((j)=>j.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=c(Z),Q=await J.resolveSpawnConfig(Z),K=Z.runFolder??f$.homedir();try{let j=await l1({spawn:{...Q,cwd:K},modelId:$.modelId??Z.defaultModelId??null,configValues:$.configValues??Z.defaultConfigValues??{}}),U=T0({adapterId:J.id,models:j.models,currentModelId:j.currentModelId}),G=new Date().toISOString();return await g((Y)=>{let z=Y.runtimes.find((B)=>B.id===$.runtimeConfigId);if(z)z.discoveredModels=U,z.discoveredConfigOptions=j.configOptions,z.discoveredAt=G}),{ok:!0,models:U,configOptions:j.configOptions,currentModelId:j.currentModelId}}catch(j){if(j instanceof J0)throw Error(`${j.message}${J.authHint?` ${J.authHint}`:""}`);if(j instanceof _||j instanceof a)throw Error(j.message);throw j}}async function uZ($){let X=f$.homedir(),Z=$.path?.trim()?$.path.trim():X,J=u0.resolve(Z),Q=!0;try{if(!(await l0.stat(J)).isDirectory())J=u0.dirname(J)}catch{Q=!1,J=X}let K=[];try{K=(await l0.readdir(J,{withFileTypes:!0})).filter((G)=>G.isDirectory()&&!G.name.startsWith(".")).map((G)=>({name:G.name,path:u0.join(J,G.name)})).sort((G,Y)=>G.name.localeCompare(Y.name))}catch{K=[]}let j=u0.dirname(J);return{path:J,parent:j===J?null:j,home:X,exists:Q,entries:K}}var k6={list:hZ,getEffectiveForCard:vZ,registerRegistered:IZ,registerCustom:SZ,unregister:mZ,setUserDefault:gZ,setCardOverride:cZ,refreshModels:lZ,browseFolder:uZ};var pZ=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function aZ(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function O6(){try{let $=await I();if($.globalDefaultConfigId){if($.runtimes.some((Z)=>Z.id===$.globalDefaultConfigId))return $.globalDefaultConfigId}for(let X of pZ){if((await L1(X.id))?.status!=="ready")continue;let J=null;if(await g((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((U)=>U.id===Q.globalDefaultConfigId)){J=Q.globalDefaultConfigId;return}}let K=Q.runtimes.find((j)=>j.kind==="registered"&&j.adapterId===X.id);if(!K){let j={id:aZ(),kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Q.runtimes.push(j),K=j}Q.globalDefaultConfigId=K.id,J=K.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 dZ(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class h${sessions=new Map;createCallId;toolCallTimeoutMs;constructor($={}){this.createCallId=$.createCallId??dZ,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 K=this.sessions.get($);if(!K)return Promise.reject(Error(`Frontend session ${$} is not connected`));let j=this.createCallId();return new Promise((U,G)=>{let Y=setTimeout(()=>{K.pendingToolCalls.delete(j),G(Error(`Tool "${X}" timed out waiting for the frontend`))},this.toolCallTimeoutMs),z=J??(Q?this.getActiveRunIdForCard(K,Q):this.getSoleActiveRunId(K)),B=Q??(z?K.activeRunCardIds.get(z):void 0);K.pendingToolCalls.set(j,{resolve:U,reject:G,timer:Y}),K.send({type:"tool_call",callId:j,name:X,args:Z,...z?{runId:z}:{},...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);return}let Q=X.result;if(Q&&typeof Q==="object"&&Array.isArray(Q.content)){J.resolve({...Q,isError:!0});return}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 iZ(){return"0.0.54".trim()?"0.0.54":"dev"}var oZ=process.argv.slice(2),A6=[];for(let $ of oZ){if($==="--dev"){process.env[T$]="1";continue}A6.push($)}var n=A6[0];if(n==="--help"||n==="-h"||n==="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(n==="--version"||n==="-v"||n==="version")console.log(iZ()),process.exit(0);if(n)console.error(`Unknown command: ${n}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var M0=new h$,j0=null;function N0($,X){M0.sendToSession($,X)}async function nZ($,X){try{let Z=k6[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 v$(){if(q0)return;if(D0)return D0;return D0=(async()=>{try{let $=await P6(M0);g$({...$,requestedPort:$.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${$.url}`);try{await Z1({onStatusChange:(X)=>{if(k1(),j0?.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 O6(),q0=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),j0?.sendStatus()}catch($){console.error("[ideawave-cli] failed to start agent host:",$),j0?.sendStatus(void 0,$ instanceof Error?$.message:String($))}finally{D0=null}})(),D0}if(process.env.APP_ENV!=="development"){let $=await j6();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)}j0=await W6({registry:M0,runtime:null,mcpReady:()=>q0,onToolMetadata:($)=>{console.log(`[ideawave-cli] session ${$} advertised ${M0.getMetadata($).length} tools`),v$()},onRunTurn:($,X)=>{console.log(`[ideawave-cli] running agent turn for card ${X.cardId} (session ${$})`),(async()=>{if(await v$(),!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 t1(X,(Z)=>N0($,Z))})().catch(()=>{return}).finally(()=>M0.markRunSettled($,X.runId))},onCancelRun:($,X)=>{A$(X)},onRuntimeRpc:($,X)=>{nZ($,X)},onWarmupRun:($,X,Z)=>{(async()=>{if(await v$(),!q0)return{status:"retryable",error:"agent host is not ready"};return r1({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)=>{o1($);for(let Z of X)A$(Z);console.log(`[ideawave-cli] browser session ${$} disconnected`)}});console.log(`[ideawave-cli] browser bridge listening on ${j0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var _6=!1;for(let $ of["SIGINT","SIGTERM"])process.once($,()=>{if(_6)return;_6=!0,n1(),(async()=>{await j0?.close().catch(()=>{return}),process.exit(0)})()});
28
+ ${Z}`),$.destroy()}function GZ($,X){return new Promise((Z,J)=>{let Q=(j)=>{$.off("listening",K),J(j)},K=()=>{$.off("error",Q);let j=$.address();if(!j||typeof j==="string"){J(Error("Failed to read CLI bridge server address"));return}Z(j.port)};$.once("error",Q),$.once("listening",K),$.listen(X,"127.0.0.1")})}function K6($){return new Promise((X,Z)=>{$.close((J)=>{if(J)Z(J);else X()})})}async function W6($,X=w$()){let Z=new Map,J=new Map,Q=$.maxMessageSize??eX,K=!1,j=(H)=>{let M=J.get(H);if(M)clearTimeout(M);J.delete(H)},U=(H)=>{J.delete(H);let{activeRunIds:M}=$.registry.disconnect(H);$.onDisconnect(H,M)},G=(H,M)=>{let N={type:"cli_status",connected:!0,runtime:$.runtime,mcpReady:$.mcpReady(),error:M};if(H){let x=Z.get(H);if(x)Y0(x,N);return}for(let x of Z.values())Y0(x,N)},Y=(H,M)=>{let N=M.sessionId.trim(),x=M.userId.trim();if(!N||!x){Y0(H,{type:"cli_status",connected:!1,runtime:$.runtime,mcpReady:$.mcpReady(),error:"Missing frontend session or user id"}),H.close();return}j(N);let V=Z.get(N);if(V&&V!==H)V.close();H.data.frontendSessionId=N,Z.set(N,H),$.registry.register({frontendSessionId:N,userId:x,tools:M.tools,send:(D)=>Y0(H,D)}),G(N),$.onToolMetadata?.(N)},z=(H,M)=>{let N=$.registry.getUserId(H);if(!N)return;switch(M.type){case"bridge_ping":{let x=Z.get(H);if(x)Y0(x,{type:"bridge_pong"});break}case"tool_metadata":$.registry.setMetadata(H,M.tools),$.onToolMetadata?.(H);break;case"tool_result":$.registry.handleToolResult(H,M);break;case"run_turn":$.registry.markRunActive(H,M.run.runId,M.run.cardId),$.onRunTurn(H,{...M.run,frontendSessionId:H,userId:N});break;case"cancel_run":if($.registry.ownsRun(H,M.runId))$.onCancelRun(H,M.runId);break;case"runtime_rpc":$.onRuntimeRpc(H,M);break;case"warmup_run":$.onWarmupRun(H,{...M,frontendSessionId:H},N);break;default:break}},B=(H,M)=>{let N=J6(H.headers.origin),x=Z6(N),V={Vary:"Origin"};if(x&&N)V["Access-Control-Allow-Origin"]=N,V["Access-Control-Allow-Private-Network"]="true";if(H.method==="OPTIONS"){M.writeHead(204,{...V,"Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*","Access-Control-Max-Age":"600"}),M.end();return}if(H.method!=="GET"){M.writeHead(405,V),M.end();return}M.writeHead(200,{...V,"content-type":"application/json","cache-control":"no-store"}),M.end(JSON.stringify({ideawave:!0,runtime:$.runtime,mcpReady:$.mcpReady()}))};for(let H of X){let M=tX((V,D)=>{if(new URL(V.url??"/","http://127.0.0.1").pathname===e1){B(V,D);return}D.writeHead(404,{"content-type":"text/plain"}),D.end("IdeaWave CLI bridge")}),N=new rX({noServer:!0,maxPayload:Q}),x=(V)=>{if(V.idleTimer)clearTimeout(V.idleTimer);V.idleTimer=setTimeout(()=>{V.close()},$Z),V.idleTimer.unref?.()};N.on("connection",(V)=>{let D=V;D.data={id:sX(),frontendSessionId:null},D.idleTimer=null,x(D),D.on("ping",()=>x(D)),D.on("pong",()=>x(D)),D.on("error",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);D.close()}),D.on("message",(F)=>{x(D);let O=VZ(F);if(Q>0&&O.length>Q)return;let C=S0(O);if(!C)return;let A=D.data.frontendSessionId;if(!A){if(C.type==="bridge_probe")Y0(D,{type:"bridge_probe_ack",protocolVersion:C.protocolVersion});else if(C.type==="frontend_hello")Y(D,C);return}z(A,C)}),D.on("close",()=>{if(D.idleTimer)clearTimeout(D.idleTimer);let F=D.data.frontendSessionId;if(!F)return;if(Z.get(F)!==D)return;if(Z.delete(F),j(F),K)return;J.set(F,setTimeout(()=>U(F),XZ))})}),M.on("upgrade",(V,D,F)=>{if(new URL(V.url??"/","http://127.0.0.1").pathname!==C$){Q6(D,404,"Not Found");return}if(!Z6(J6(V.headers.origin))){Q6(D,403,"Forbidden");return}N.handleUpgrade(V,D,F,(C)=>{N.emit("connection",C,V)})});try{let V=await GZ(M,H);return{url:`ws://127.0.0.1:${V}${C$}`,port:V,sendStatus:G,close:async()=>{K=!0;for(let D of J.values())clearTimeout(D);J.clear();for(let D of N.clients){let F=D;if(F.idleTimer)clearTimeout(F.idleTimer);F.close()}N.close(),await K6(M).catch(()=>{return})}}}catch(V){if(N.close(),await K6(M).catch(()=>{return}),V?.code==="EADDRINUSE")continue;throw V}}throw Error(`No free IdeaWave CLI bridge port found in ${X[0]}-${X.at(-1)}`)}import{Server as OZ}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as _Z,ListToolsRequestSchema as AZ}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as HZ}from"node:crypto";import{createServer as UZ}from"node:http";import{StreamableHTTPServerTransport as DZ}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as H6}from"@modelcontextprotocol/sdk/types.js";var V6=new Set(["127.0.0.1","localhost","[::1]","::1"]);function zZ($){let X=$.trim();if(X.length===0)return null;if(X.startsWith("[")){let K=X.indexOf("]");if(K===-1)return null;let j=X.slice(0,K+1),U=X.slice(K+1);if(U.length===0)return{host:j,port:null};if(!U.startsWith(":"))return null;let G=Number(U.slice(1));if(!Number.isInteger(G)||G<=0||G>65535)return null;return{host:j,port:G}}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 G6($){return V6.has($)||V6.has($.toLowerCase())}function z6($,X){let Z=$.headers.host;if(typeof Z!=="string")return{ok:!1,status:403,reason:"missing-host"};let J=zZ(Z);if(!J)return{ok:!1,status:403,reason:"bad-host"};if(!G6(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 K;try{K=new URL(Q)}catch{return{ok:!1,status:403,reason:"bad-origin"}}if(!G6(K.hostname))return{ok:!1,status:403,reason:"non-loopback-origin"}}}return{ok:!0}}var U6="/mcp",MZ=43274,M6=16777216,NZ=1800000,qZ=300000,D6=200,BZ=-32700,o=-32600,E$=-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 R$ extends Error{constructor(){super("expected application/json");this.name="BadContentTypeError"}}class b$ extends Error{constructor(){super(`body exceeds ${M6} bytes`);this.name="BodyTooLargeError"}}async function FZ($){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 R$}let Z=0,J=[];for await(let K of $){let j=typeof K==="string"?Buffer.from(K):K;if(Z+=j.byteLength,Z>M6)throw new b$;J.push(j)}if(J.length===0)return;let Q=Buffer.concat(J).toString("utf8");if(Q.length===0)return;return JSON.parse(Q)}function xZ($){if(Array.isArray($))return $.some(H6);return H6($)}function PZ($){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 MZ}async function LZ($,X){let Z=(Q)=>new Promise((K,j)=>{let U=(Y)=>{$.off("listening",G),j(Y)},G=()=>{$.off("error",U),K()};$.once("error",U),$.once("listening",G),$.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 kZ($,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 K=Q.name;if(typeof K==="string"&&K.trim().length>0)return K.trim()}}}let Z=$.headers["user-agent"];if(typeof Z==="string"&&Z.trim().length>0)return Z.trim();return null}async function N6($){let X=new Map,Z=0;function J(Y){let z=X.get(Y);if(z)z.lastActivity=Date.now()}async function Q(Y,z){X.delete(Y),await z.transport.close().catch(()=>{return})}async function K(){let Y=null,z=1/0;for(let[B,H]of X)if(H.lastActivity<z)z=H.lastActivity,Y=B;if(Y!==null){let B=X.get(Y);if(B)console.warn(`[mcp] session cap of ${D6} reached; evicting ${Y}`),await Q(Y,B)}}let j=setInterval(()=>{let Y=Date.now()-NZ;for(let[z,B]of X)if(B.lastActivity<Y)console.log(`[mcp] sweeping idle session ${z}`),Q(z,B)},qZ);j.unref?.();let U=UZ((Y,z)=>{(async()=>{let B;try{B=new URL(Y.url??"/","http://127.0.0.1").pathname}catch{m(z,400,o,"bad-url");return}if(B!==U6){m(z,404,o,"not-found");return}let H=Y.method??"POST";if(H!=="POST"&&H!=="GET"&&H!=="DELETE"){z.setHeader("Allow","GET, POST, DELETE"),m(z,405,o,"method-not-allowed");return}let M=z6(Y,Z);if(!M.ok){m(z,M.status,o,"forbidden",{reason:M.reason});return}let N=Y.headers["mcp-session-id"],x=typeof N==="string"?N:void 0;if(H==="GET"||H==="DELETE"){if(!x||!X.has(x)){m(z,400,o,"no-session",{hint:"Open a POST initialize first to receive an Mcp-Session-Id."});return}let F=X.get(x).transport;J(x);try{await F.handleRequest(Y,z)}catch(O){if(console.error("[mcp] transport.handleRequest (GET/DELETE) threw",O),!z.headersSent)m(z,500,E$,"internal")}return}let V;try{V=await FZ(Y)}catch(F){if(F instanceof R$){m(z,415,o,"expected-application-json");return}if(F instanceof b$){m(z,413,o,"body-too-large");return}m(z,400,BZ,"invalid-json");return}let D;if(x&&X.has(x))D=X.get(x).transport,J(x);else if(!x&&V!==void 0&&xZ(V)){let F=Y.headers["x-ideawave-user-id"],O=typeof F==="string"&&F.trim().length>0?F.trim():null,C=Y.headers["x-ideawave-frontend-session-id"],A=typeof C==="string"&&C.trim().length>0?C.trim():null,L=Y.headers["x-ideawave-tool-surface"],W=typeof L==="string"&&L.trim()==="read"?"read":"full",P=Y.headers["x-ideawave-images-supported"],T=typeof P==="string"&&P.trim()==="1",E=Y.headers["x-ideawave-card-id"],k=typeof E==="string"&&E.trim().length>0?E.trim():null,R=Y.headers["x-ideawave-board-id"],b=typeof R==="string"&&R.trim().length>0?R.trim():null,v=Y.headers["x-ideawave-run-folder"],p=typeof v==="string"&&v.trim().length>0?v.trim():null,B0=kZ(Y,V);if(X.size>=D6)await K();let X0=null,s=new DZ({sessionIdGenerator:()=>HZ(),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:O,frontendSessionId:A,boardId:b,toolSurface:W,imagesSupported:T,cardId:k,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(z,500,E$,"server-init-failed");return}D=s}else{m(z,400,o,"no-session",{hint:"Non-initialize requests must include a valid Mcp-Session-Id header obtained from a prior initialize."});return}try{await D.handleRequest(Y,z,V)}catch(F){if(console.error("[mcp] transport.handleRequest threw",F),!z.headersSent)m(z,500,E$,"internal")}})().catch((B)=>{console.error("[mcp] unhandled request handler error:",B)})});return Z=await LZ(U,PZ($.port)),{url:`http://127.0.0.1:${Z}${U6}`,port:Z,close:async()=>{clearInterval(j);for(let Y of X.values())await Y.transport.close().catch(()=>{return});X.clear(),await new Promise((Y)=>U.close(()=>Y()))}}}var CZ={name:"ideawave-board",version:"1.0.0"},g0="list_run_folder",c0="read_run_folder_file",F6=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",g0,c0]),x6=new Set(["inspect_diagram"]),wZ=[{name:g0,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:c0,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 y$($){return{content:[{type:"text",text:$}]}}function TZ($){return y$(JSON.stringify($,null,2))}function q6($){return{...y$($),isError:!0}}function EZ($,X,Z="full",J=!1){return $.getMetadata(X).filter((Q)=>{let K=b0(Q.name);if(Z==="read"&&!F6.has(K))return!1;if(!J&&x6.has(K))return!1;return!0}).map((Q)=>({name:Q.name,description:Q.description,inputSchema:Q.inputSchema}))}function RZ($,X,Z={}){let J=EZ($,X,Z.toolSurface??"full",Z.imagesSupported??!1);return Z.includeRunFolderTools?[...J,...wZ]:J}function B6($,X){if(!$||typeof $!=="object"||Array.isArray($))return null;let Z=$[X];return typeof Z==="string"?Z:null}async function bZ($,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 yZ($){let X=await bZ($.boardId,$.cardId,$.runFolder);if($.name===g0){let Z=B6($.args,"path")??"",J=await A1(X,Z);return TZ(J)}if($.name===c0){let Z=B6($.args,"path");if(!Z)return q6("read_run_folder_file requires a path.");return y$(await R0(X,Z))}return q6(`Unknown local tool "${$.name}"`)}function fZ($,X,Z,J,Q,K="full",j=!1){let U=new OZ(CZ,{capabilities:{tools:{}}}),G=async()=>{if(j)return!0;if(i1(J))return!0;if(Z&&J)try{return(await i({boardId:Z,cardId:J})).adapter.supportsImages===!0}catch{return!1}return!1};return U.setRequestHandler(AZ,async()=>({tools:RZ($,X,{includeRunFolderTools:Boolean(Q||Z&&J),toolSurface:K,imagesSupported:await G()})})),U.setRequestHandler(_Z,async(Y)=>{let{name:z,arguments:B}=Y.params,H=b0(z);try{if(H===g0||H===c0)return await yZ({name:H,args:B,boardId:Z,cardId:J,runFolder:Q});if(K==="read"&&!F6.has(H))throw Error(`Tool "${z}" is not available in read-only mode`);if(x6.has(H)&&!await G())throw Error(`Tool "${z}" requires a runtime that supports image input`);let M=await $.callTool(X,H,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}}}),U}function P6($,X){return N6({buildServer:(Z)=>fZ($,Z.frontendSessionId,Z.boardId,Z.cardId,Z.runFolder,Z.toolSurface,Z.imagesSupported),port:X})}import l0 from"node:fs/promises";import f$ from"node:os";import u0 from"node:path";function L6(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function hZ(){let[$,X]=await Promise.all([I(),P1()]),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:K0().map((J)=>({id:J.id,displayName:J.displayName})),readiness:X}}async function vZ($){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 IZ($){return g((X)=>{let Z=X.runtimes.find((K)=>K.kind==="registered"&&K.adapterId===$.adapterId);if(Z)return Z;let J=K0().find((K)=>K.id===$.adapterId);if(!J)throw Error(`Unknown adapterId: ${$.adapterId}`);let Q={id:L6(),kind:"registered",adapterId:$.adapterId,displayName:J.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};return X.runtimes.push(Q),Q})}async function SZ($){return g((X)=>{let Z={id:L6(),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 mZ($){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 gZ($){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 cZ($){$.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 lZ($){let Z=(await I()).runtimes.find((j)=>j.id===$.runtimeConfigId);if(!Z)throw Error(`Runtime config not found: ${$.runtimeConfigId}`);let J=c(Z),Q=await J.resolveSpawnConfig(Z),K=Z.runFolder??f$.homedir();try{let j=await l1({spawn:{...Q,cwd:K},modelId:$.modelId??Z.defaultModelId??null,configValues:$.configValues??Z.defaultConfigValues??{}}),U=T0({adapterId:J.id,models:j.models,currentModelId:j.currentModelId}),G=new Date().toISOString();return await g((Y)=>{let z=Y.runtimes.find((B)=>B.id===$.runtimeConfigId);if(z)z.discoveredModels=U,z.discoveredConfigOptions=j.configOptions,z.discoveredAt=G}),{ok:!0,models:U,configOptions:j.configOptions,currentModelId:j.currentModelId}}catch(j){if(j instanceof J0)throw Error(`${j.message}${J.authHint?` ${J.authHint}`:""}`);if(j instanceof _||j instanceof a)throw Error(j.message);throw j}}async function uZ($){let X=f$.homedir(),Z=$.path?.trim()?$.path.trim():X,J=u0.resolve(Z),Q=!0;try{if(!(await l0.stat(J)).isDirectory())J=u0.dirname(J)}catch{Q=!1,J=X}let K=[];try{K=(await l0.readdir(J,{withFileTypes:!0})).filter((G)=>G.isDirectory()&&!G.name.startsWith(".")).map((G)=>({name:G.name,path:u0.join(J,G.name)})).sort((G,Y)=>G.name.localeCompare(Y.name))}catch{K=[]}let j=u0.dirname(J);return{path:J,parent:j===J?null:j,home:X,exists:Q,entries:K}}var k6={list:hZ,getEffectiveForCard:vZ,registerRegistered:IZ,registerCustom:SZ,unregister:mZ,setUserDefault:gZ,setCardOverride:cZ,refreshModels:lZ,browseFolder:uZ};var pZ=[{id:"claude-code",displayName:"Claude Code"},{id:"codex",displayName:"Codex"},{id:"copilot",displayName:"Copilot"},{id:"opencode",displayName:"OpenCode"}];function aZ(){return`cfg_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`}async function O6(){try{let $=await I();if($.globalDefaultConfigId){if($.runtimes.some((Z)=>Z.id===$.globalDefaultConfigId))return $.globalDefaultConfigId}for(let X of pZ){if((await L1(X.id))?.status!=="ready")continue;let J=null;if(await g((Q)=>{if(Q.globalDefaultConfigId){if(Q.runtimes.some((U)=>U.id===Q.globalDefaultConfigId)){J=Q.globalDefaultConfigId;return}}let K=Q.runtimes.find((j)=>j.kind==="registered"&&j.adapterId===X.id);if(!K){let j={id:aZ(),kind:"registered",adapterId:X.id,displayName:X.displayName,runFolder:null,defaultModelId:null,defaultConfigValues:{},discoveredModels:[],discoveredConfigOptions:[],discoveredAt:null};Q.runtimes.push(j),K=j}Q.globalDefaultConfigId=K.id,J=K.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 dZ(){if(typeof crypto<"u"&&"randomUUID"in crypto)return`call_${crypto.randomUUID()}`;return`call_${Date.now()}_${Math.random().toString(16).slice(2)}`}class h${sessions=new Map;createCallId;toolCallTimeoutMs;constructor($={}){this.createCallId=$.createCallId??dZ,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 K=this.sessions.get($);if(!K)return Promise.reject(Error(`Frontend session ${$} is not connected`));let j=this.createCallId();return new Promise((U,G)=>{let Y=setTimeout(()=>{K.pendingToolCalls.delete(j),G(Error(`Tool "${X}" timed out waiting for the frontend`))},this.toolCallTimeoutMs),z=J??(Q?this.getActiveRunIdForCard(K,Q):this.getSoleActiveRunId(K)),B=Q??(z?K.activeRunCardIds.get(z):void 0);K.pendingToolCalls.set(j,{resolve:U,reject:G,timer:Y}),K.send({type:"tool_call",callId:j,name:X,args:Z,...z?{runId:z}:{},...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);return}let Q=X.result;if(Q&&typeof Q==="object"&&Array.isArray(Q.content)){J.resolve({...Q,isError:!0});return}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 iZ(){return"0.0.55".trim()?"0.0.55":"dev"}var oZ=process.argv.slice(2),A6=[];for(let $ of oZ){if($==="--dev"){process.env[T$]="1";continue}A6.push($)}var n=A6[0];if(n==="--help"||n==="-h"||n==="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(n==="--version"||n==="-v"||n==="version")console.log(iZ()),process.exit(0);if(n)console.error(`Unknown command: ${n}`),console.error("Run `ideawave --help` for usage."),process.exit(1);var M0=new h$,j0=null;function N0($,X){M0.sendToSession($,X)}async function nZ($,X){try{let Z=k6[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 v$(){if(q0)return;if(D0)return D0;return D0=(async()=>{try{let $=await P6(M0);g$({...$,requestedPort:$.port}),console.log(`[ideawave-cli] MCP endpoint for the agent: ${$.url}`);try{await Z1({onStatusChange:(X)=>{if(k1(),j0?.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 O6(),q0=!0,console.log("[ideawave-cli] ready — agent runs will drive the board."),j0?.sendStatus()}catch($){console.error("[ideawave-cli] failed to start agent host:",$),j0?.sendStatus(void 0,$ instanceof Error?$.message:String($))}finally{D0=null}})(),D0}if(process.env.APP_ENV!=="development"){let $=await j6();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)}j0=await W6({registry:M0,runtime:null,mcpReady:()=>q0,onToolMetadata:($)=>{console.log(`[ideawave-cli] session ${$} advertised ${M0.getMetadata($).length} tools`),v$()},onRunTurn:($,X)=>{console.log(`[ideawave-cli] running agent turn for card ${X.cardId} (session ${$})`),(async()=>{if(await v$(),!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 t1(X,(Z)=>N0($,Z))})().catch(()=>{return}).finally(()=>M0.markRunSettled($,X.runId))},onCancelRun:($,X)=>{A$(X)},onRuntimeRpc:($,X)=>{nZ($,X)},onWarmupRun:($,X,Z)=>{(async()=>{if(await v$(),!q0)return{status:"retryable",error:"agent host is not ready"};return r1({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)=>{o1($);for(let Z of X)A$(Z);console.log(`[ideawave-cli] browser session ${$} disconnected`)}});console.log(`[ideawave-cli] browser bridge listening on ${j0.url}`);console.log("[ideawave-cli] waiting for ideawave.app browser sessions…");var _6=!1;for(let $ of["SIGINT","SIGTERM"])process.once($,()=>{if(_6)return;_6=!0,n1(),(async()=>{await j0?.close().catch(()=>{return}),process.exit(0)})()});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ideawave",
3
- "version": "0.0.54",
3
+ "version": "0.0.55",
4
4
  "description": "IdeaWave CLI",
5
5
  "type": "module",
6
6
  "bin": {