bridge-agent 0.13.0 → 0.13.1

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.js +3 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -410,7 +410,7 @@ ${jo("bridge_get_my_task","bridge_complete_task","bridge_fail_task","bridge_get_
410
410
  `,"utf-8"),console.log("[daemon] persona.prompt.written",{agentId:r,tmpPath:n}),["--append-system-prompt-file",n]}catch(n){return console.warn("[daemon] persona.prompt.write.failed",{agentId:r,error:String(n)}),[]}return t==="qwen"?["--append-system-prompt",e.trim()]:[]}function Et(t){return`"${t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function zl(t){try{let e=process.env.BRIDGE_MCP_URL,r=e?{mcpServers:{bridge:{type:"http",url:`${e}/mcp/${t.workspaceId}/${t.projectId||"workspace"}`,headers:{Authorization:`Bearer ${t.token}`,"x-panel-id":t.agentId??"","x-panel-persona-id":t.personaId??""}}}}:{mcpServers:{bridge:{command:je(),args:[],env:{BRIDGE_SERVER_URL:t.serverUrl,BRIDGE_TOKEN:t.token,BRIDGE_WORKSPACE_ID:t.workspaceId,BRIDGE_PROJECT_ID:t.projectId||"workspace",BRIDGE_PANEL_ID:t.agentId??"",BRIDGE_PERSONA_ID:t.personaId??"",HTTP_MODE:"false"}}}},n=C.default.join(N.default.tmpdir(),`bridge-mcp-kimi-${t.agentId??(t.projectId||"workspace")}.json`);return L.default.writeFileSync(n,JSON.stringify(r,null,2)+`
411
411
  `,"utf-8"),console.log("[daemon] kimi.mcp.config.written",{tmpPath:n,transport:e?"http":"stdio"}),["--mcp-config-file",n]}catch(e){return console.warn("[daemon] kimi.mcp.config.build.failed",{error:String(e)}),[]}}function Ql(t){try{let e=je(),r=`{BRIDGE_SERVER_URL=${Et(t.serverUrl)},BRIDGE_TOKEN=${Et(t.token)},BRIDGE_WORKSPACE_ID=${Et(t.workspaceId)},BRIDGE_PROJECT_ID=${Et(t.projectId||"workspace")},HTTP_MODE="false"}`;return["-c",'mcp_servers.bridge.transport="stdio"',"-c",`mcp_servers.bridge.command=${Et(e)}`,"-c","mcp_servers.bridge.args=[]","-c",`mcp_servers.bridge.env=${r}`]}catch(e){return console.warn("[daemon] codex.mcp.config.build.failed",{error:String(e)}),[]}}function Xl(t){try{return L.default.statSync(t).isDirectory()}catch{return!1}}function Sn(t,e){try{return e(t)}catch{return!1}}function Zl(t,e,r,n,s=Xl){let o=n?.[t];if(o&&Sn(o,s))return{path:o,source:"local_override"};if(r){if(Sn(r,s))return{path:r,source:"daemon_override"};console.warn("[daemon] spawn.cwd.daemon_override_missing",{projectId:t,daemonLocalPath:r,hint:`Run: jerico link-project ${t} <local-path>`})}if(e&&Sn(e,s))return{path:e,source:"server_project"};let a=!t||t.trim()===""?"Missing projectId in spawn message \u2014 server-side bug, file issue at https://github.com/alperduzgun/jerico/issues":`Set projectPaths["${t}"] in ~/.jerico/settings.json`;return console.warn("[daemon] spawn.cwd.fallback_home",{projectId:t,serverCwd:e,localOverride:o,daemonLocalPath:r??void 0,hint:a}),{path:N.default.homedir(),source:"fallback_home"}}function ed(){let t=C.default.join(N.default.homedir(),".forge",".forge.toml");if(L.default.existsSync(t))try{let e=L.default.readFileSync(t,"utf-8");if(e.includes("auto_update = true")){let r=e.replace(/^auto_update\s*=\s*true$/m,"auto_update = false");L.default.writeFileSync(t,r),console.log("[daemon] forge.auto_update.disabled",{reason:"prevents-spawn-crash"})}}catch(e){console.warn("[daemon] forge.auto_update.patch.failed",{error:String(e)})}}function td(t){ed();try{if(!t.cwd)return console.warn("[daemon] forge.mcp.setup.skipped",{reason:"missing_cwd",projectId:t.projectId||"workspace"}),!1;let e=je(),r=JSON.stringify({mcpServers:{bridge:{command:e,args:[],env:{BRIDGE_SERVER_URL:t.serverUrl,BRIDGE_TOKEN:t.token,BRIDGE_WORKSPACE_ID:t.workspaceId,BRIDGE_PROJECT_ID:t.projectId||"workspace",BRIDGE_PANEL_ID:t.agentId??"",BRIDGE_PERSONA_ID:t.personaId??"",HTTP_MODE:"false"}}}}),n={cwd:t.cwd,encoding:"utf-8",timeout:5e3,stdio:"pipe"};(0,tt.spawnSync)("forge",["mcp","remove","--scope","local","bridge"],n);let s=(0,tt.spawnSync)("forge",["mcp","import",r,"--scope","local"],n);return s.status===0?(console.log("[daemon] forge.mcp.setup.ok",{cwd:t.cwd,projectId:t.projectId||"workspace"}),!0):(console.warn("[daemon] forge.mcp.setup.failed",{cwd:t.cwd,projectId:t.projectId,status:s.status,stderr:(s.stderr??"").toString().slice(0,300)}),!1)}catch(e){return console.warn("[daemon] forge.mcp.setup.error",{error:String(e),projectId:t.projectId}),!1}}function rd(t){try{let e=C.default.join(N.default.homedir(),".config","opencode","opencode.json"),r={};try{r=JSON.parse(L.default.readFileSync(e,"utf-8"))}catch{}delete r.mcpServers;let n=process.env.BRIDGE_MCP_URL,s=t.projectId||"workspace",o={...r.mcp??{}};return n?o.bridge={type:"remote",url:`${n}/mcp/${t.workspaceId}/${s}`,enabled:!0,headers:{Authorization:`Bearer ${t.token}`,"x-panel-id":t.agentId??"","x-panel-persona-id":t.personaId??""}}:o.bridge={type:"local",command:[je()],environment:{BRIDGE_SERVER_URL:t.serverUrl,BRIDGE_TOKEN:t.token,BRIDGE_WORKSPACE_ID:t.workspaceId,BRIDGE_PROJECT_ID:s,BRIDGE_PANEL_ID:t.agentId??"",BRIDGE_PERSONA_ID:t.personaId??"",HTTP_MODE:"false"},enabled:!0},r.mcp=o,L.default.mkdirSync(C.default.dirname(e),{recursive:!0}),L.default.writeFileSync(e,JSON.stringify(r,null,2)+`
412
412
  `,"utf-8"),console.log("[daemon] opencode.mcp.config.written",{configPath:e,transport:n?"http":"stdio"}),!0}catch(e){return console.warn("[daemon] opencode.mcp.config.build.failed",{error:String(e)}),!1}}function nd(t){try{if(!t.cwd)return console.warn("[daemon] qwen.mcp.setup.skipped",{reason:"missing_cwd",projectId:t.projectId||"workspace"}),!1;let e=je(),r={cwd:t.cwd,encoding:"utf-8",timeout:5e3,stdio:"pipe"},n=C.default.resolve(t.cwd)===C.default.resolve(N.default.homedir()),s=n?"user":"project";n&&console.warn("[daemon] qwen.mcp.home_dir_fallback",{cwd:t.cwd,projectId:t.projectId||"workspace",scope:"user"}),(0,tt.spawnSync)("qwen",["mcp","remove","--scope",s,"bridge"],r);let o=(0,tt.spawnSync)("qwen",["mcp","add","--scope",s,"-t","stdio","-e",`BRIDGE_SERVER_URL=${t.serverUrl}`,"-e",`BRIDGE_TOKEN=${t.token}`,"-e",`BRIDGE_WORKSPACE_ID=${t.workspaceId}`,"-e",`BRIDGE_PROJECT_ID=${t.projectId||"workspace"}`,"-e",`BRIDGE_PANEL_ID=${t.agentId??""}`,"-e",`BRIDGE_PERSONA_ID=${t.personaId??""}`,"-e","HTTP_MODE=false","bridge",e],r);return o.status===0?(console.log("[daemon] qwen.mcp.setup.ok",{cwd:t.cwd,projectId:t.projectId||"workspace"}),!0):(console.warn("[daemon] qwen.mcp.setup.failed",{cwd:t.cwd,projectId:t.projectId,status:o.status,stderr:(o.stderr??"").toString().slice(0,300)}),!1)}catch(e){return console.warn("[daemon] qwen.mcp.setup.error",{error:String(e),projectId:t.projectId}),!1}}function sd(t){try{if(!t.cwd)return console.warn("[daemon] gemini.mcp.setup.skipped",{reason:"missing_cwd",projectId:t.projectId||"workspace"}),!1;let e=C.default.join(t.cwd,".gemini"),r=C.default.join(e,"settings.json"),n={};try{n=JSON.parse(L.default.readFileSync(r,"utf-8"))}catch{}let s=je(),o=t.projectId||"workspace",i=process.env.BRIDGE_MCP_URL,a={...n.mcpServers??{}};return i?a.bridge={type:"http",url:`${i}/mcp/${t.workspaceId}/${o}`,headers:{Authorization:`Bearer ${t.token}`,"x-panel-id":t.agentId??"","x-panel-persona-id":t.personaId??""},trust:!0,description:"Bridge MCP server"}:a.bridge={command:s,args:[],env:{BRIDGE_SERVER_URL:t.serverUrl,BRIDGE_TOKEN:t.token,BRIDGE_WORKSPACE_ID:t.workspaceId,BRIDGE_PROJECT_ID:o,BRIDGE_PANEL_ID:t.agentId??"",BRIDGE_PERSONA_ID:t.personaId??"",HTTP_MODE:"false"},trust:!0,description:"Bridge MCP server"},n.mcpServers=a,L.default.mkdirSync(e,{recursive:!0}),L.default.writeFileSync(r,JSON.stringify(n,null,2)+`
413
- `,"utf-8"),console.log("[daemon] gemini.mcp.config.written",{configPath:r,transport:i?"http":"stdio"}),!0}catch(e){return console.warn("[daemon] gemini.mcp.config.build.failed",{error:String(e)}),!1}}var Ot=[],vn=!1,_i=!1;function yi(){return vn}function bi(t){if(_i)throw new Error("[daemon] startDaemonConnection called twice \u2014 only one connection manager allowed");if(_i=!0,process.env.BRIDGE_TEST_SCRIPTED_REVIEW!=="1")try{let b=C.default.join(N.default.homedir(),".jerico","settings.json");L.default.existsSync(b)&&JSON.parse(L.default.readFileSync(b,"utf-8")).testScriptedReview===!0&&(process.env.BRIDGE_TEST_SCRIPTED_REVIEW="1",console.log("[daemon] scripted-review-mode enabled from ~/.jerico/settings.json"))}catch{}process.env.BRIDGE_TEST_SCRIPTED_REVIEW==="1"&&console.log("[daemon] scripted-review-mode ENABLED");let e=pe(),r=(0,Ct.createHash)("sha256").update(e.token).digest("hex");function n(b,w,y){i?.readyState===E.OPEN&&i.send(JSON.stringify({type:"tool_usage",daemonId:r,tool:b,kind:w,...y}))}function s(b){for(let w of be)w();be.length=0;for(let w of b)if(w.authStatus==="ok")switch(w.key){case"qwen":be.push(ri(y=>{n("qwen","quota",{prompts5h:y.prompts5h,limit5h:y.limit5h,resetAt:y.resetAt,estimate:!0})}));break;case"opencode":be.push(ii(y=>{n("opencode","spent",{tokensSpent5h:y.tokensSpent5h,tokensTotal:y.tokensTotal})}));break;case"gemini":be.push(ci(y=>{n("gemini","spent",{tokensSpent5h:y.tokensSpent5h,tokensTotal:y.tokensTotal})}));break;case"kimi":be.push(di(y=>{n("kimi","spent",{contextPct:y.contextPct,contextTokens:y.contextTokens,maxContextTokens:y.maxContextTokens,tokensSpent5h:y.tokensTotal})}));break}}let o=new er(r),i=null,a=null,c=null,l=0,d=0,u=0n,p=0,f=0;function h(){a&&(clearTimeout(a),a=null),c&&(clearInterval(c),c=null);let b=Date.now(),w=process.hrtime.bigint();i=new E(e.server,{headers:{Authorization:`Bearer ${e.token}`}});let y=i,v=(0,Ct.randomUUID)();wn=v;let T=N.default.networkInterfaces(),J=Object.entries(T).flatMap(([B,U])=>(U||[]).filter(Q=>!Q.internal).map(Q=>({iface:B,address:Q.address,family:Q.family}))),k=JSON.stringify(J);console.log(JSON.stringify({ts:Date.now(),level:"info",event:"net.interfaces",interfaces:J,connectionId:v})),ar&&ar!==k&&console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"net.interfaces.changed",previous:ar,current:k,connectionId:v})),ar=k;let O=y.send.bind(y);y.send=function(B){if(y.readyState!==E.OPEN){let U="unknown";try{U=JSON.parse(B).type}catch{}console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.send.dropped",messageType:U,readyState:y.readyState,connectionId:v}));return}return O(B)},console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.connecting",server:e.server,connectionId:v}));let I=null,x=0,S=null,F=!1;y.on("open",()=>{vn=!0,console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.connected",server:e.server,connectionId:v})),c=setInterval(()=>{y.readyState===E.OPEN&&(y.ping(),x=Date.now(),S&&clearTimeout(S),S=setTimeout(()=>{console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.heartbeat.timeout",connectionId:v})),y.terminate()},gi))},hi),t.setCurrentWs(y);let B=!vs();y.send(JSON.stringify({type:"ready",version:"1.1",npmVersion:"0.13.0",installModel:process.pkg!==void 0?"pkg":"npm",name:e.name,spawnHelperBroken:B,liveAgentIds:t.getLiveAgentIds(),machineFingerprint:kn(),connectionId:v,claudeTier:rr()})),o.updateWs(y),Promise.all([Rr(e.agentPaths),sn()]).then(([U,Q])=>{Ot=Q?[...U,Q]:U,s(U),y.readyState===E.OPEN&&y.send(JSON.stringify({type:"agents",list:Ot}))}),I=fi(U=>{y.readyState===E.OPEN&&y.send(JSON.stringify({type:"system_metrics",daemonId:r,...U}))})}),y.on("message",B=>{let U;try{U=JSON.parse(B.toString())}catch{console.warn("[daemon] Invalid JSON from server, ignoring");return}od(U,y,t,e,o)}),y.on("pong",()=>{S&&(clearTimeout(S),S=null);let B=Date.now()-x;console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.heartbeat.pong",rttMs:B,connectionId:v})),F||(F=!0,d=0,u=0n,p=0,f=0)}),y.on("close",(B,U)=>{vn=!1,c&&(clearInterval(c),c=null),S&&(clearTimeout(S),S=null),I?.(),I=null,o.stopAll(),B===1008?(l++,l>=2&&(console.error("[daemon] ws.auth_failed \u2014 token invalid or expired (2 consecutive rejections), stopping. Re-run: bridge-agent auth"),g(),setTimeout(()=>process.exit(1),2e3)),console.warn("[daemon] ws.auth_rejected \u2014 transient 1008, will retry once",{attempt:l})):l=0;let Q=Number((process.hrtime.bigint()-w)/1000000n);if(console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.closed",code:B,reason:U?.toString()||void 0,uptimeMs:Q,connectionId:v})),a)return;if(!F&&Q<hi+gi+5e3&&B!==1008&&(p++,console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.reconnect.zombie",zombieStreak:p,uptimeMs:Q,connectionId:v}))),p>=3){f++,console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.zombie.escalate",zombieStreak:p,escalationCount:f,connectionId:v})),f>=3&&(console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.zombie.fatal",escalationCount:f,zombieStreak:p,connectionId:v})),g(),setTimeout(()=>process.exit(1),2e3)),p=0,y?.removeAllListeners?.(),c&&(clearInterval(c),c=null),S&&(clearTimeout(S),S=null),a&&(clearTimeout(a),a=null),a=setTimeout(h,1e4);return}d===0&&(u=process.hrtime.bigint()),d++;let Ji=Number((process.hrtime.bigint()-u)/1000000n);d>=10&&Ji<6e4&&(console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.storm",reconnectCount:d,connectionId:v})),g(),setTimeout(()=>process.exit(1),2e3));let Ki=Math.min(3e4,1e3*Math.pow(2,Math.min(d,5))),Mn=Math.round(Ki+Math.random()*500);console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.reconnect.scheduled",delayMs:Mn,reconnectCount:d,connectionId:v})),a=setTimeout(h,Mn)}),y.on("error",B=>{console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.error",message:B.message,code:B.code,connectionId:v}))})}function g(){c&&(clearInterval(c),c=null),t.stopLivenessCheck(),$l();for(let b of be)b();be.length=0;for(let b of De.values())b();o.stopAll(),t.killAll(),i?.close()}function _(b){console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.signal",signal:b,connectionId:wn})),g(),setTimeout(()=>process.exit(0),100)}process.on("SIGINT",()=>_("SIGINT")),process.on("SIGTERM",()=>_("SIGTERM")),process.on("SIGHUP",()=>_("SIGHUP")),process.on("uncaughtException",b=>{console.log(JSON.stringify({ts:Date.now(),level:"error",event:"daemon.uncaught",error:String(b),stack:b.stack,connectionId:wn}));try{g()}catch{}setTimeout(()=>process.exit(1),2e3)}),h()}function od(t,e,r,n,s){switch(t.type){case"spawn":{if(console.log("[daemon] pty.spawn.start",{agentId:t.agentId,agentKey:t.agentKey,sessionId:t.sessionId,projectId:t.projectId,workspaceId:t.workspaceId,role:t.role}),t.agentKey==="sim_ios"){s.start(t.agentId);return}let o=Ot.find(k=>k.key===t.agentKey);if(!o){e.readyState===E.OPEN&&e.send(JSON.stringify({type:"error",code:"AGENT_NOT_FOUND",message:`Agent '${t.agentKey}' is not installed on this machine`}));return}let i=ve.find(k=>k.key===t.agentKey),a=[];if(t.sessionId&&i?.resumeArgs)a=i.resumeArgs(t.sessionId),console.log("[daemon] pty.spawn.resume",{agentId:t.agentId,sessionId:t.sessionId}),t.agentKey==="claude"&&(De.get(t.agentId)?.(),De.set(t.agentId,fn(t.agentId,t.sessionId,(k,O,I)=>{let x=r.getCurrentWs();x?.readyState===E.OPEN&&x.send(JSON.stringify({type:"panel_token_usage",agentId:k,usedPct:O,usedTokens:I,...et}))})));else if(i?.assignSessionId){let k=crypto.randomUUID(),O=t.agentKey==="kimi"?"--session":t.agentKey==="forge"?"--conversation-id":"--session-id";a=[...i.spawnArgs??[],O,k],e.readyState===E.OPEN&&(e.send(JSON.stringify({type:"session_started",agentId:t.agentId,sessionId:k})),console.log("[daemon] session.assigned",{agentId:t.agentId,sessionId:k})),t.agentKey==="claude"&&(De.get(t.agentId)?.(),De.set(t.agentId,fn(t.agentId,k,(I,x,S)=>{let F=r.getCurrentWs();F?.readyState===E.OPEN&&F.send(JSON.stringify({type:"panel_token_usage",agentId:I,usedPct:x,usedTokens:S,...et}))})))}else a=[...i?.spawnArgs??[]],e.readyState===E.OPEN&&e.send(JSON.stringify({type:"session_started",agentId:t.agentId,sessionId:crypto.randomUUID()}));let c,l=!1,d,u;if(t.workspaceId){let k=Hl(n.server),O=Zl(t.projectId??"",t.cwd,t.daemonLocalPath,n.projectPaths),I=O.path;if(u=O.source,u==="fallback_home"&&t.sessionId){let S=t.daemonLocalPath?"daemon_override_missing":"not_found";console.warn("[daemon] resume.cwd_fallback_blocked",{agentId:t.agentId,sessionId:t.sessionId,requestedCwd:t.cwd,projectId:t.projectId,reason:S}),e.readyState===E.OPEN&&e.send(JSON.stringify({type:"error",code:"CWD_MISSING_ON_DAEMON",message:`Cannot resume session \u2014 project path not found on this machine. Run: bridge-agent link-project ${t.projectId??"?"} <local-path>`,agentId:t.agentId,sessionId:t.sessionId}));return}let x=un(I);if(c={serverUrl:k,token:n.token,workspaceId:Ao(t.workspaceId),projectId:t.projectId?Ro(t.projectId):void 0,agentId:t.agentId?To(t.agentId):void 0,personaId:t.personaId,cwd:I,projectEnv:x.env},t.agentKey==="claude"){let S=ql(c);l=S.length>0,d=process.env.BRIDGE_MCP_URL?"http":"stdio",a=[...a,...S]}else if(t.agentKey==="codex"){let S=Ql(c);l=S.length>0,d="stdio",a=[...a,...S]}else if(t.agentKey==="qwen")l=nd(c),d=l?"stdio":void 0;else if(t.agentKey==="kimi"){let S=zl(c);l=S.length>0,d=process.env.BRIDGE_MCP_URL?"http":"stdio",a=[...a,...S]}else t.agentKey==="forge"?(l=td(c),d=l?"stdio":void 0):t.agentKey==="opencode"?(l=rd(c),d=l?process.env.BRIDGE_MCP_URL?"http":"stdio":void 0):t.agentKey==="gemini"?(l=sd(c),d=l?process.env.BRIDGE_MCP_URL?"http":"stdio":void 0):(l=!1,console.log("[daemon] mcp.config.skipped",{agentId:t.agentId,agentKey:t.agentKey,reason:"unsupported_agent_path"}));if(rn("phase2a.verified_at")&&(O.source==="daemon_override"||O.source==="server_project")){let S=`${k}/api/workspaces/${t.workspaceId}/projects/${t.projectId}/machine-paths/${t.daemonId}/verify`;fetch(S,{method:"PATCH",headers:{Authorization:`Bearer ${n.token}`,"Content-Type":"application/json"},body:"{}"}).catch(F=>{console.warn("[daemon] verify.patch_failed",{projectId:t.projectId,error:String(F)})})}if(rn("phase2a.auto_register")&&(O.source==="daemon_override"||O.source==="server_project"))try{let S=(0,tt.spawnSync)("git",["remote","get-url","origin"],{cwd:I,timeout:5e3,encoding:"utf-8"});if(S.status===0&&S.stdout&&S.stdout.trim()){let F=S.stdout.trim();t.projectId&&(n.projectPaths||(n.projectPaths={}),n.projectPaths[t.projectId]=I,re({projectPaths:n.projectPaths}));let B=`${k}/api/workspaces/${t.workspaceId}/projects/${t.projectId}/machine-paths`;fetch(B,{method:"POST",headers:{Authorization:`Bearer ${n.token}`,"Content-Type":"application/json"},body:JSON.stringify({daemonId:t.daemonId,localPath:I,repoUrl:F})}).catch(U=>{console.warn("[daemon] auto_register.post_failed",{projectId:t.projectId,error:String(U)})}),console.log("[daemon] auto_register.ok",{projectId:t.projectId,localPath:I,repoUrl:F})}}catch(S){console.log("[daemon] auto_register.skipped",{projectId:t.projectId,reason:String(S)})}}let p=Jl(t.role,t.systemPrompt,t.agentId,t.workspaceId,t.projectId,t.groupId),f=Kl(t.agentKey,p,t.agentId);f.length>0&&(a=[...a,...f]);let h=Yl(t.agentKey,t.systemPrompt,t.agentId);h.length>0&&(a=[...a,...h]);let g=Math.max(1,Math.min(500,t.cols)),_=Math.max(1,Math.min(500,t.rows)),b=Date.now(),w="",y=0,v=!1,T=!1;if(r.spawn(t.agentId,t.agentKey,o.binaryPath,a,g,_,k=>{if(y+=k.length,t.agentKey==="gemini")try{let I=Buffer.from(k,"base64").toString("utf-8");if(I.includes("shell mode enabled"))Re.get(t.agentId)||(Re.set(t.agentId,!0),console.log("[daemon] gemini.shell_mode.entered",{agentId:t.agentId.slice(-8)}));else if(I.includes("Type your message")&&(Re.get(t.agentId)&&(Re.set(t.agentId,!1),console.log("[daemon] gemini.shell_mode.exited",{agentId:t.agentId.slice(-8)})),!Ze.get(t.agentId))){Ze.set(t.agentId,!0);let x=Ne.get(t.agentId)??[];Ne.delete(t.agentId),console.log("[daemon] gemini.ready",{agentId:t.agentId.slice(-8),flushing:x.length}),x.length>0&&setTimeout(()=>{for(let S of x)r.write(t.agentId,S,"orchestrator");setTimeout(()=>{r.write(t.agentId,Buffer.from("\r").toString("base64"),"orchestrator")},1e3)},500)}}catch{}try{let I=Buffer.from(k,"base64").toString("utf-8");if(t.agentKey==="kimi"&&t.role&&!T&&Date.now()-b<3e4&&(/yolo agent/.test(I)||/●/.test(I)||/○/.test(I))){T=!0;let x=p;if(x){let S=Ml(x),F=Buffer.from(S).toString("base64");r.write(t.agentId,F,"orchestrator"),console.log("[daemon] kimi.role.injected",{agentId:t.agentId,role:t.role})}}}catch{}if(!w)try{let I=Buffer.from(k,"base64").toString("utf-8"),x=Fl(I).replace(/\x00/g,"").trim();if(x&&(w=Gl(x)),t.agentKey==="codex"&&!v&&Date.now()-b<2e4&&/included in your plan for free|let[’']s build together/i.test(x)&&/yes|no|\[y\/n\]|\(y\/n\)|y\/n/i.test(x)){v=!0;let S=Buffer.from("y").toString("base64");r.write(t.agentId,S,"orchestrator"),console.log("[daemon] codex.onboarding.auto_ack",{agentId:t.agentId})}}catch{}let O=r.getCurrentWs();if(O?.readyState===E.OPEN)if(O.bufferedAmount>mi){let I=Date.now(),x=cr.get(t.agentId);(!x||I-x>=1e3)&&(cr.set(t.agentId,I),console.log(JSON.stringify({ts:I,level:"warn",event:"pty.backpressure.drop",agentId:t.agentId,bufferedAmount:O.bufferedAmount,threshold:mi})))}else O.send(JSON.stringify({type:"output",agentId:t.agentId,data:k}));jl(t.agentId,()=>r.getCurrentWs())},(k,O)=>{let I=Date.now()-b,x=I<=Ul;console.log("[daemon] pty.spawn.result",{agentId:t.agentId,agentKey:t.agentKey,daemonId:t.daemonId,exitCode:k,signal:O,uptimeMs:I,earlyExit:x,outputBytes:y,firstOutputSnippet:w||void 0});let S=r.getCurrentWs();x&&S?.readyState===E.OPEN&&S.send(JSON.stringify({type:"error",code:"SPAWN_FAILED",message:`Early exit: agent=${t.agentKey} code=${k??"null"} signal=${O??"null"} snippet="${w||"no output"}"`})),S?.readyState===E.OPEN&&S.send(JSON.stringify({type:"exit",agentId:t.agentId,exitCode:k,signal:O})),Ll(t.agentId),Re.delete(t.agentId),Ze.delete(t.agentId),Ne.delete(t.agentId),cr.delete(t.agentId),Promise.all([(0,It.unlink)(C.default.join(N.default.tmpdir(),`bridge-persona-${t.agentId}.md`)),(0,It.unlink)(C.default.join(N.default.tmpdir(),`bridge-role-${t.agentId}.md`)),(0,It.unlink)(C.default.join(N.default.tmpdir(),`bridge-mcp-${t.agentId}.json`)),(0,It.unlink)(C.default.join(N.default.tmpdir(),`bridge-mcp-kimi-${t.agentId}.json`))].map(F=>F.catch(()=>{}))).catch(()=>{})},c)){if(t.agentKey==="gemini"&&setTimeout(()=>{if(!Ze.get(t.agentId)){Ze.set(t.agentId,!0);let k=Ne.get(t.agentId)??[];Ne.delete(t.agentId),k.length>0&&(console.warn("[daemon] gemini.ready.timeout_fallback",{agentId:t.agentId.slice(-8),flushing:k.length}),setTimeout(()=>{for(let O of k)r.write(t.agentId,O,"orchestrator");setTimeout(()=>{r.write(t.agentId,Buffer.from("\r").toString("base64"),"orchestrator")},1e3)},500))}},3e4),u==="fallback_home"&&e.readyState===E.OPEN){let k=t.daemonLocalPath?"daemon_override_missing":"not_found";console.warn("[daemon] cwd_fallback",{agentId:t.agentId,requestedCwd:t.cwd,actualCwd:N.default.homedir(),reason:k,projectId:t.projectId,daemonId:t.daemonId}),e.send(JSON.stringify({type:"cwd_fallback",agentId:t.agentId,requestedCwd:t.cwd,actualCwd:N.default.homedir(),source:"fallback_home",reason:k,projectId:t.projectId,daemonId:t.daemonId}))}e.readyState===E.OPEN&&e.send(JSON.stringify({type:"mcp_status",agentId:t.agentId,mcpConfigured:l,transport:l?d:void 0,projectId:c?.projectId,effectiveCwd:c?.cwd,cwdSource:u}))}else{let O=r.getLastError(t.agentId)?.includes("posix_spawnp failed")&&Bl(t.agentKey);e.readyState===E.OPEN&&(O?e.send(JSON.stringify({type:"error",code:"SPAWN_HELPER_BROKEN",message:"node-pty spawn-helper is not executable. Upgrade bridge-agent to v0.2.10+."})):e.send(JSON.stringify({type:"error",code:"SPAWN_FAILED",message:`Failed to spawn panel ${t.agentId}`})))}e.readyState===E.OPEN&&e.send(JSON.stringify({type:"agent_spawned",agentId:t.agentId,agentKey:t.agentKey,daemonId:t.daemonId,role:t.role,personaId:t.personaId}));break}case"input":{if(r.getAgentKey(t.agentId)==="gemini"&&t.source==="orchestrator"){if(!Ze.get(t.agentId)){let a=Ne.get(t.agentId)??[];a.push(t.data),Ne.set(t.agentId,a),console.log("[daemon] gemini.input.buffered",{agentId:t.agentId.slice(-8),queued:a.length});break}if(Re.get(t.agentId)){let a=r.write(t.agentId,Buffer.from("\x1B").toString("base64"),"user");if(Re.set(t.agentId,!1),console.log("[daemon] gemini.shell_mode.esc_before_inject",{agentId:t.agentId.slice(-8)}),!a){e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}));break}setTimeout(()=>{!r.write(t.agentId,t.data,t.source)&&e.readyState===E.OPEN&&e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}))},100);break}}r.write(t.agentId,t.data,t.source)||e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}));break}case"kill":console.log("[daemon] kill.received",{agentId:t.agentId,force:t.force??!1}),De.get(t.agentId)?.(),De.delete(t.agentId),s.stop(t.agentId),r.kill(t.agentId,t.force),cr.delete(t.agentId);break;case"resize":r.resize(t.agentId,t.cols,t.rows);break;case"sim_tap":case"sim_swipe":case"sim_key":case"sim_button":case"sim_get_source":case"sim_subscribe":case"sim_unsubscribe":case"sim_healthcheck":case"sim_install_run":case"sim_install_cancel":s.handle(t);break;case"detect_agents":Promise.all([Rr(n.agentPaths),sn()]).then(([o,i])=>{Ot=i?[...o,i]:o,e.readyState===E.OPEN&&e.send(JSON.stringify({type:"agents",list:Ot}))});break;case"dir_list":{let o=N.default.homedir(),i=(t.path||"~").replace(/^~/,o),a=C.default.resolve(i);if(a!==o&&!a.startsWith(o+C.default.sep)){e.readyState===E.OPEN&&e.send(JSON.stringify({type:"error",code:"INVALID_MSG",message:"Path outside home directory"}));return}try{let c=L.default.readdirSync(a,{withFileTypes:!0}).filter(l=>l.isDirectory()&&!l.name.startsWith(".")).map(l=>({name:l.name,path:C.default.join(a,l.name)})).sort((l,d)=>l.name.localeCompare(d.name));e.readyState===E.OPEN&&e.send(JSON.stringify({type:"dir_list_result",requestId:t.requestId,path:a,entries:c}))}catch(c){e.readyState===E.OPEN&&e.send(JSON.stringify({type:"dir_list_result",requestId:t.requestId,path:a,entries:[],error:c instanceof Error?c.message:"Cannot read directory"}))}break}case"persona_apply":{let o=r.getAgentKey(t.agentId);if(!o){console.warn("[daemon] persona_apply.no_panel",{agentId:t.agentId});break}let i;t.systemPrompt?i=`[BRIDGE-ORCH] Persona updated: ${t.personaId}
413
+ `,"utf-8"),console.log("[daemon] gemini.mcp.config.written",{configPath:r,transport:i?"http":"stdio"}),!0}catch(e){return console.warn("[daemon] gemini.mcp.config.build.failed",{error:String(e)}),!1}}var Ot=[],vn=!1,_i=!1;function yi(){return vn}function bi(t){if(_i)throw new Error("[daemon] startDaemonConnection called twice \u2014 only one connection manager allowed");if(_i=!0,process.env.BRIDGE_TEST_SCRIPTED_REVIEW!=="1")try{let b=C.default.join(N.default.homedir(),".jerico","settings.json");L.default.existsSync(b)&&JSON.parse(L.default.readFileSync(b,"utf-8")).testScriptedReview===!0&&(process.env.BRIDGE_TEST_SCRIPTED_REVIEW="1",console.log("[daemon] scripted-review-mode enabled from ~/.jerico/settings.json"))}catch{}process.env.BRIDGE_TEST_SCRIPTED_REVIEW==="1"&&console.log("[daemon] scripted-review-mode ENABLED");let e=pe(),r=(0,Ct.createHash)("sha256").update(e.token).digest("hex");function n(b,w,y){i?.readyState===E.OPEN&&i.send(JSON.stringify({type:"tool_usage",daemonId:r,tool:b,kind:w,...y}))}function s(b){for(let w of be)w();be.length=0;for(let w of b)if(w.authStatus==="ok")switch(w.key){case"qwen":be.push(ri(y=>{n("qwen","quota",{prompts5h:y.prompts5h,limit5h:y.limit5h,resetAt:y.resetAt,estimate:!0})}));break;case"opencode":be.push(ii(y=>{n("opencode","spent",{tokensSpent5h:y.tokensSpent5h,tokensTotal:y.tokensTotal})}));break;case"gemini":be.push(ci(y=>{n("gemini","spent",{tokensSpent5h:y.tokensSpent5h,tokensTotal:y.tokensTotal})}));break;case"kimi":be.push(di(y=>{n("kimi","spent",{contextPct:y.contextPct,contextTokens:y.contextTokens,maxContextTokens:y.maxContextTokens,tokensSpent5h:y.tokensTotal})}));break}}let o=new er(r),i=null,a=null,c=null,l=0,d=0,u=0n,p=0,f=0;function h(){a&&(clearTimeout(a),a=null),c&&(clearInterval(c),c=null);let b=Date.now(),w=process.hrtime.bigint();i=new E(e.server,{headers:{Authorization:`Bearer ${e.token}`}});let y=i,v=(0,Ct.randomUUID)();wn=v;let T=N.default.networkInterfaces(),J=Object.entries(T).flatMap(([B,U])=>(U||[]).filter(Q=>!Q.internal).map(Q=>({iface:B,address:Q.address,family:Q.family}))),k=JSON.stringify(J);console.log(JSON.stringify({ts:Date.now(),level:"info",event:"net.interfaces",interfaces:J,connectionId:v})),ar&&ar!==k&&console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"net.interfaces.changed",previous:ar,current:k,connectionId:v})),ar=k;let O=y.send.bind(y);y.send=function(B){if(y.readyState!==E.OPEN){let U="unknown";try{U=JSON.parse(B).type}catch{}console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.send.dropped",messageType:U,readyState:y.readyState,connectionId:v}));return}return O(B)},console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.connecting",server:e.server,connectionId:v}));let I=null,x=0,S=null,F=!1;y.on("open",()=>{vn=!0,console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.connected",server:e.server,connectionId:v})),c=setInterval(()=>{y.readyState===E.OPEN&&(y.ping(),x=Date.now(),S&&clearTimeout(S),S=setTimeout(()=>{console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.heartbeat.timeout",connectionId:v})),y.terminate()},gi))},hi),t.setCurrentWs(y);let B=!vs();y.send(JSON.stringify({type:"ready",version:"1.1",npmVersion:"0.13.1",installModel:process.pkg!==void 0?"pkg":"npm",name:e.name,spawnHelperBroken:B,liveAgentIds:t.getLiveAgentIds(),machineFingerprint:kn(),connectionId:v,claudeTier:rr()})),o.updateWs(y),Promise.all([Rr(e.agentPaths),sn()]).then(([U,Q])=>{Ot=Q?[...U,Q]:U,s(U),y.readyState===E.OPEN&&y.send(JSON.stringify({type:"agents",list:Ot}))}),I=fi(U=>{y.readyState===E.OPEN&&y.send(JSON.stringify({type:"system_metrics",daemonId:r,...U}))})}),y.on("message",B=>{let U;try{U=JSON.parse(B.toString())}catch{console.warn("[daemon] Invalid JSON from server, ignoring");return}od(U,y,t,e,o)}),y.on("pong",()=>{S&&(clearTimeout(S),S=null);let B=Date.now()-x;console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.heartbeat.pong",rttMs:B,connectionId:v})),F||(F=!0,d=0,u=0n,p=0,f=0)}),y.on("close",(B,U)=>{vn=!1,c&&(clearInterval(c),c=null),S&&(clearTimeout(S),S=null),I?.(),I=null,o.stopAll(),B===1008?(l++,l>=2&&(console.error("[daemon] ws.auth_failed \u2014 token invalid or expired (2 consecutive rejections), stopping. Re-run: bridge-agent auth"),g(),setTimeout(()=>process.exit(1),2e3)),console.warn("[daemon] ws.auth_rejected \u2014 transient 1008, will retry once",{attempt:l})):l=0;let Q=Number((process.hrtime.bigint()-w)/1000000n);if(console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.closed",code:B,reason:U?.toString()||void 0,uptimeMs:Q,connectionId:v})),a)return;if(!F&&Q<hi+gi+5e3&&B!==1008&&(p++,console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.reconnect.zombie",zombieStreak:p,uptimeMs:Q,connectionId:v}))),p>=3){f++,console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.zombie.escalate",zombieStreak:p,escalationCount:f,connectionId:v})),f>=3&&(console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.zombie.fatal",escalationCount:f,zombieStreak:p,connectionId:v})),g(),setTimeout(()=>process.exit(1),2e3)),p=0,y?.removeAllListeners?.(),c&&(clearInterval(c),c=null),S&&(clearTimeout(S),S=null),a&&(clearTimeout(a),a=null),a=setTimeout(h,1e4);return}d===0&&(u=process.hrtime.bigint()),d++;let Ji=Number((process.hrtime.bigint()-u)/1000000n);d>=10&&Ji<6e4&&(console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.storm",reconnectCount:d,connectionId:v})),g(),setTimeout(()=>process.exit(1),2e3));let Ki=Math.min(3e4,1e3*Math.pow(2,Math.min(d,5))),Mn=Math.round(Ki+Math.random()*500);console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.reconnect.scheduled",delayMs:Mn,reconnectCount:d,connectionId:v})),a=setTimeout(h,Mn)}),y.on("error",B=>{console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.error",message:B.message,code:B.code,connectionId:v}))})}function g(){c&&(clearInterval(c),c=null),t.stopLivenessCheck(),$l();for(let b of be)b();be.length=0;for(let b of De.values())b();o.stopAll(),t.killAll(),i?.close()}function _(b){console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.signal",signal:b,connectionId:wn})),g(),setTimeout(()=>process.exit(0),100)}process.on("SIGINT",()=>_("SIGINT")),process.on("SIGTERM",()=>_("SIGTERM")),process.on("SIGHUP",()=>_("SIGHUP")),process.on("uncaughtException",b=>{console.log(JSON.stringify({ts:Date.now(),level:"error",event:"daemon.uncaught",error:String(b),stack:b.stack,connectionId:wn}));try{g()}catch{}setTimeout(()=>process.exit(1),2e3)}),h()}function od(t,e,r,n,s){switch(t.type){case"spawn":{if(console.log("[daemon] pty.spawn.start",{agentId:t.agentId,agentKey:t.agentKey,sessionId:t.sessionId,projectId:t.projectId,workspaceId:t.workspaceId,role:t.role}),t.agentKey==="sim_ios"){s.start(t.agentId);return}let o=Ot.find(k=>k.key===t.agentKey);if(!o){e.readyState===E.OPEN&&e.send(JSON.stringify({type:"error",code:"AGENT_NOT_FOUND",message:`Agent '${t.agentKey}' is not installed on this machine`}));return}let i=ve.find(k=>k.key===t.agentKey),a=[];if(t.sessionId&&i?.resumeArgs)a=i.resumeArgs(t.sessionId),console.log("[daemon] pty.spawn.resume",{agentId:t.agentId,sessionId:t.sessionId}),t.agentKey==="claude"&&(De.get(t.agentId)?.(),De.set(t.agentId,fn(t.agentId,t.sessionId,(k,O,I)=>{let x=r.getCurrentWs();x?.readyState===E.OPEN&&x.send(JSON.stringify({type:"panel_token_usage",agentId:k,usedPct:O,usedTokens:I,...et}))})));else if(i?.assignSessionId){let k=crypto.randomUUID(),O=t.agentKey==="kimi"?"--session":t.agentKey==="forge"?"--conversation-id":"--session-id";a=[...i.spawnArgs??[],O,k],e.readyState===E.OPEN&&(e.send(JSON.stringify({type:"session_started",agentId:t.agentId,sessionId:k})),console.log("[daemon] session.assigned",{agentId:t.agentId,sessionId:k})),t.agentKey==="claude"&&(De.get(t.agentId)?.(),De.set(t.agentId,fn(t.agentId,k,(I,x,S)=>{let F=r.getCurrentWs();F?.readyState===E.OPEN&&F.send(JSON.stringify({type:"panel_token_usage",agentId:I,usedPct:x,usedTokens:S,...et}))})))}else a=[...i?.spawnArgs??[]],e.readyState===E.OPEN&&e.send(JSON.stringify({type:"session_started",agentId:t.agentId,sessionId:crypto.randomUUID()}));let c,l=!1,d,u;if(t.workspaceId){let k=Hl(n.server),O=Zl(t.projectId??"",t.cwd,t.daemonLocalPath,n.projectPaths),I=O.path;if(u=O.source,u==="fallback_home"&&t.sessionId){let S=t.daemonLocalPath?"daemon_override_missing":"not_found";console.warn("[daemon] resume.cwd_fallback_blocked",{agentId:t.agentId,sessionId:t.sessionId,requestedCwd:t.cwd,projectId:t.projectId,reason:S}),e.readyState===E.OPEN&&e.send(JSON.stringify({type:"error",code:"CWD_MISSING_ON_DAEMON",message:`Cannot resume session \u2014 project path not found on this machine. Run: bridge-agent link-project ${t.projectId??"?"} <local-path>`,agentId:t.agentId,sessionId:t.sessionId}));return}let x=un(I);if(c={serverUrl:k,token:n.token,workspaceId:Ao(t.workspaceId),projectId:t.projectId?Ro(t.projectId):void 0,agentId:t.agentId?To(t.agentId):void 0,personaId:t.personaId,cwd:I,projectEnv:x.env},t.agentKey==="claude"){let S=ql(c);l=S.length>0,d=process.env.BRIDGE_MCP_URL?"http":"stdio",a=[...a,...S]}else if(t.agentKey==="codex"){let S=Ql(c);l=S.length>0,d="stdio",a=[...a,...S]}else if(t.agentKey==="qwen")l=nd(c),d=l?"stdio":void 0;else if(t.agentKey==="kimi"){let S=zl(c);l=S.length>0,d=process.env.BRIDGE_MCP_URL?"http":"stdio",a=[...a,...S]}else t.agentKey==="forge"?(l=td(c),d=l?"stdio":void 0):t.agentKey==="opencode"?(l=rd(c),d=l?process.env.BRIDGE_MCP_URL?"http":"stdio":void 0):t.agentKey==="gemini"?(l=sd(c),d=l?process.env.BRIDGE_MCP_URL?"http":"stdio":void 0):(l=!1,console.log("[daemon] mcp.config.skipped",{agentId:t.agentId,agentKey:t.agentKey,reason:"unsupported_agent_path"}));if(rn("phase2a.verified_at")&&(O.source==="daemon_override"||O.source==="server_project")){let S=`${k}/api/workspaces/${t.workspaceId}/projects/${t.projectId}/machine-paths/${t.daemonId}/verify`;fetch(S,{method:"PATCH",headers:{Authorization:`Bearer ${n.token}`,"Content-Type":"application/json"},body:"{}"}).catch(F=>{console.warn("[daemon] verify.patch_failed",{projectId:t.projectId,error:String(F)})})}if(rn("phase2a.auto_register")&&(O.source==="daemon_override"||O.source==="server_project"))try{let S=(0,tt.spawnSync)("git",["remote","get-url","origin"],{cwd:I,timeout:5e3,encoding:"utf-8"});if(S.status===0&&S.stdout&&S.stdout.trim()){let F=S.stdout.trim();t.projectId&&(n.projectPaths||(n.projectPaths={}),n.projectPaths[t.projectId]=I,re({projectPaths:n.projectPaths}));let B=`${k}/api/workspaces/${t.workspaceId}/projects/${t.projectId}/machine-paths`;fetch(B,{method:"POST",headers:{Authorization:`Bearer ${n.token}`,"Content-Type":"application/json"},body:JSON.stringify({daemonId:t.daemonId,localPath:I,repoUrl:F})}).catch(U=>{console.warn("[daemon] auto_register.post_failed",{projectId:t.projectId,error:String(U)})}),console.log("[daemon] auto_register.ok",{projectId:t.projectId,localPath:I,repoUrl:F})}}catch(S){console.log("[daemon] auto_register.skipped",{projectId:t.projectId,reason:String(S)})}}let p=Jl(t.role,t.systemPrompt,t.agentId,t.workspaceId,t.projectId,t.groupId),f=Kl(t.agentKey,p,t.agentId);f.length>0&&(a=[...a,...f]);let h=Yl(t.agentKey,t.systemPrompt,t.agentId);h.length>0&&(a=[...a,...h]);let g=Math.max(1,Math.min(500,t.cols)),_=Math.max(1,Math.min(500,t.rows)),b=Date.now(),w="",y=0,v=!1,T=!1;if(r.spawn(t.agentId,t.agentKey,o.binaryPath,a,g,_,k=>{if(y+=k.length,t.agentKey==="gemini")try{let I=Buffer.from(k,"base64").toString("utf-8");if(I.includes("shell mode enabled"))Re.get(t.agentId)||(Re.set(t.agentId,!0),console.log("[daemon] gemini.shell_mode.entered",{agentId:t.agentId.slice(-8)}));else if(I.includes("Type your message")&&(Re.get(t.agentId)&&(Re.set(t.agentId,!1),console.log("[daemon] gemini.shell_mode.exited",{agentId:t.agentId.slice(-8)})),!Ze.get(t.agentId))){Ze.set(t.agentId,!0);let x=Ne.get(t.agentId)??[];Ne.delete(t.agentId),console.log("[daemon] gemini.ready",{agentId:t.agentId.slice(-8),flushing:x.length}),x.length>0&&setTimeout(()=>{for(let S of x)r.write(t.agentId,S,"orchestrator");setTimeout(()=>{r.write(t.agentId,Buffer.from("\r").toString("base64"),"orchestrator")},1e3)},500)}}catch{}try{let I=Buffer.from(k,"base64").toString("utf-8");if(t.agentKey==="kimi"&&t.role&&!T&&Date.now()-b<3e4&&(/yolo agent/.test(I)||/●/.test(I)||/○/.test(I))){T=!0;let x=p;if(x){let S=Ml(x),F=Buffer.from(S).toString("base64");r.write(t.agentId,F,"orchestrator"),console.log("[daemon] kimi.role.injected",{agentId:t.agentId,role:t.role})}}}catch{}if(!w)try{let I=Buffer.from(k,"base64").toString("utf-8"),x=Fl(I).replace(/\x00/g,"").trim();if(x&&(w=Gl(x)),t.agentKey==="codex"&&!v&&Date.now()-b<2e4&&/included in your plan for free|let[’']s build together/i.test(x)&&/yes|no|\[y\/n\]|\(y\/n\)|y\/n/i.test(x)){v=!0;let S=Buffer.from("y").toString("base64");r.write(t.agentId,S,"orchestrator"),console.log("[daemon] codex.onboarding.auto_ack",{agentId:t.agentId})}}catch{}let O=r.getCurrentWs();if(O?.readyState===E.OPEN)if(O.bufferedAmount>mi){let I=Date.now(),x=cr.get(t.agentId);(!x||I-x>=1e3)&&(cr.set(t.agentId,I),console.log(JSON.stringify({ts:I,level:"warn",event:"pty.backpressure.drop",agentId:t.agentId,bufferedAmount:O.bufferedAmount,threshold:mi})))}else O.send(JSON.stringify({type:"output",agentId:t.agentId,data:k}));jl(t.agentId,()=>r.getCurrentWs())},(k,O)=>{let I=Date.now()-b,x=I<=Ul;console.log("[daemon] pty.spawn.result",{agentId:t.agentId,agentKey:t.agentKey,daemonId:t.daemonId,exitCode:k,signal:O,uptimeMs:I,earlyExit:x,outputBytes:y,firstOutputSnippet:w||void 0});let S=r.getCurrentWs();x&&S?.readyState===E.OPEN&&S.send(JSON.stringify({type:"error",code:"SPAWN_FAILED",message:`Early exit: agent=${t.agentKey} code=${k??"null"} signal=${O??"null"} snippet="${w||"no output"}"`})),S?.readyState===E.OPEN&&S.send(JSON.stringify({type:"exit",agentId:t.agentId,exitCode:k,signal:O})),Ll(t.agentId),Re.delete(t.agentId),Ze.delete(t.agentId),Ne.delete(t.agentId),cr.delete(t.agentId),Promise.all([(0,It.unlink)(C.default.join(N.default.tmpdir(),`bridge-persona-${t.agentId}.md`)),(0,It.unlink)(C.default.join(N.default.tmpdir(),`bridge-role-${t.agentId}.md`)),(0,It.unlink)(C.default.join(N.default.tmpdir(),`bridge-mcp-${t.agentId}.json`)),(0,It.unlink)(C.default.join(N.default.tmpdir(),`bridge-mcp-kimi-${t.agentId}.json`))].map(F=>F.catch(()=>{}))).catch(()=>{})},c)){if(t.agentKey==="gemini"&&setTimeout(()=>{if(!Ze.get(t.agentId)){Ze.set(t.agentId,!0);let k=Ne.get(t.agentId)??[];Ne.delete(t.agentId),k.length>0&&(console.warn("[daemon] gemini.ready.timeout_fallback",{agentId:t.agentId.slice(-8),flushing:k.length}),setTimeout(()=>{for(let O of k)r.write(t.agentId,O,"orchestrator");setTimeout(()=>{r.write(t.agentId,Buffer.from("\r").toString("base64"),"orchestrator")},1e3)},500))}},3e4),u==="fallback_home"&&e.readyState===E.OPEN){let k=t.daemonLocalPath?"daemon_override_missing":"not_found";console.warn("[daemon] cwd_fallback",{agentId:t.agentId,requestedCwd:t.cwd,actualCwd:N.default.homedir(),reason:k,projectId:t.projectId,daemonId:t.daemonId}),e.send(JSON.stringify({type:"cwd_fallback",agentId:t.agentId,requestedCwd:t.cwd,actualCwd:N.default.homedir(),source:"fallback_home",reason:k,projectId:t.projectId,daemonId:t.daemonId}))}e.readyState===E.OPEN&&e.send(JSON.stringify({type:"mcp_status",agentId:t.agentId,mcpConfigured:l,transport:l?d:void 0,projectId:c?.projectId,effectiveCwd:c?.cwd,cwdSource:u}))}else{let O=r.getLastError(t.agentId)?.includes("posix_spawnp failed")&&Bl(t.agentKey);e.readyState===E.OPEN&&(O?e.send(JSON.stringify({type:"error",code:"SPAWN_HELPER_BROKEN",message:"node-pty spawn-helper is not executable. Upgrade bridge-agent to v0.2.10+."})):e.send(JSON.stringify({type:"error",code:"SPAWN_FAILED",message:`Failed to spawn panel ${t.agentId}`})))}e.readyState===E.OPEN&&e.send(JSON.stringify({type:"agent_spawned",agentId:t.agentId,agentKey:t.agentKey,daemonId:t.daemonId,role:t.role,personaId:t.personaId}));break}case"input":{if(r.getAgentKey(t.agentId)==="gemini"&&t.source==="orchestrator"){if(!Ze.get(t.agentId)){let a=Ne.get(t.agentId)??[];a.push(t.data),Ne.set(t.agentId,a),console.log("[daemon] gemini.input.buffered",{agentId:t.agentId.slice(-8),queued:a.length});break}if(Re.get(t.agentId)){let a=r.write(t.agentId,Buffer.from("\x1B").toString("base64"),"user");if(Re.set(t.agentId,!1),console.log("[daemon] gemini.shell_mode.esc_before_inject",{agentId:t.agentId.slice(-8)}),!a){e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}));break}setTimeout(()=>{!r.write(t.agentId,t.data,t.source)&&e.readyState===E.OPEN&&e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}))},100);break}}r.write(t.agentId,t.data,t.source)||e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}));break}case"kill":console.log("[daemon] kill.received",{agentId:t.agentId,force:t.force??!1}),De.get(t.agentId)?.(),De.delete(t.agentId),s.stop(t.agentId),r.kill(t.agentId,t.force),cr.delete(t.agentId);break;case"resize":r.resize(t.agentId,t.cols,t.rows);break;case"sim_tap":case"sim_swipe":case"sim_key":case"sim_button":case"sim_get_source":case"sim_subscribe":case"sim_unsubscribe":case"sim_healthcheck":case"sim_install_run":case"sim_install_cancel":s.handle(t);break;case"detect_agents":Promise.all([Rr(n.agentPaths),sn()]).then(([o,i])=>{Ot=i?[...o,i]:o,e.readyState===E.OPEN&&e.send(JSON.stringify({type:"agents",list:Ot}))});break;case"dir_list":{let o=N.default.homedir(),i=(t.path||"~").replace(/^~/,o),a=C.default.resolve(i);if(a!==o&&!a.startsWith(o+C.default.sep)){e.readyState===E.OPEN&&e.send(JSON.stringify({type:"error",code:"INVALID_MSG",message:"Path outside home directory"}));return}try{let c=L.default.readdirSync(a,{withFileTypes:!0}).filter(l=>l.isDirectory()&&!l.name.startsWith(".")).map(l=>({name:l.name,path:C.default.join(a,l.name)})).sort((l,d)=>l.name.localeCompare(d.name));e.readyState===E.OPEN&&e.send(JSON.stringify({type:"dir_list_result",requestId:t.requestId,path:a,entries:c}))}catch(c){e.readyState===E.OPEN&&e.send(JSON.stringify({type:"dir_list_result",requestId:t.requestId,path:a,entries:[],error:c instanceof Error?c.message:"Cannot read directory"}))}break}case"persona_apply":{let o=r.getAgentKey(t.agentId);if(!o){console.warn("[daemon] persona_apply.no_panel",{agentId:t.agentId});break}let i;t.systemPrompt?i=`[BRIDGE-ORCH] Persona updated: ${t.personaId}
414
414
  ${t.systemPrompt}
415
415
  `:i=`[BRIDGE-ORCH] Persona assigned: ${t.personaId}
416
416
  Call bridge_get_persona({ id: "${t.personaId}" }) immediately for your authoritative operating instructions.
@@ -456,7 +456,7 @@ ${c} </dict>
456
456
  </plist>
457
457
  `;try{return(0,D.writeFileSync)(r,f,"utf-8"),!0}catch(h){return console.warn("[bridge] launchd.plist.write.failed",{error:String(h)}),!1}}function Ei(){let t=te(),e=G.default.join(En,t);try{return(0,Be.execSync)(`launchctl kickstart -kp gui/$(id -u)/${t} 2>/dev/null; launchctl unload "${e}" 2>/dev/null; launchctl load "${e}"`,{stdio:"pipe"}),{ok:!0,permissionDenied:!1}}catch(r){let n=String(r);return{ok:!1,permissionDenied:n.includes("Permission denied")||n.includes("not allowed")||n.includes("bootstrap")}}}function ad(t){let{out:e,err:r}=_t();try{let n=(0,Be.spawn)(t,["start"],{detached:!0,stdio:"ignore",env:{...process.env,PATH:ki(),BRIDGE_DAEMON:"1"}});n.unref(),setTimeout(()=>{n.pid&&process.kill(n.pid,0)?(console.log("[bridge] daemon.pid",{pid:n.pid}),console.log("[bridge] background.ok",{log:e})):console.error("[bridge] background.failed \u2014 check: tail -f",{log:r})},2e3)}catch(n){console.error("[bridge] background.spawn.failed",{error:String(n)})}}function Ii(){let t=yt(),e=Date.now()+6e3,r=()=>{if(Date.now()>e){console.error("[bridge] health.verify.timeout \u2014 daemon may have crashed immediately");return}try{let s=require("node:http").get(`http://127.0.0.1:${t}/health`,o=>{o.statusCode===200?console.log("[bridge] health.verify.ok"):setTimeout(r,500)});s.on("error",()=>{setTimeout(r,500)}),s.setTimeout(1e3,()=>{s.destroy(),setTimeout(r,500)})}catch{setTimeout(r,500)}};setTimeout(r,1e3)}function cd(){if(process.pkg!==void 0)try{let t=G.default.join((0,Le.homedir)(),".bridge","bin");(0,D.mkdirSync)(t,{recursive:!0});let e=G.default.join(t,"bridge-mcp");(0,D.writeFileSync)(e,`#!/bin/sh
458
458
  exec "${process.execPath}" bridge-mcp "$@"
459
- `,{mode:493}),console.log("[daemon] mcp.wrapper.written",{path:e})}catch(t){console.warn("[daemon] mcp.wrapper.write.failed",{error:String(t)})}}function ld(){Es(),cd(),vi();let t=new jt;lr=t,bi(t),t.startLivenessCheck(6e4);let e=yt(),r=(0,wi.createServer)((n,s)=>{let o=yi(),i=JSON.stringify({status:"ok",connected:o,uptime:process.uptime(),version:"0.13.0",activePanels:lr?.getLiveAgentIds().length??0,agentIds:lr?.getLiveAgentIds()??[]});s.writeHead(o?200:503,{"Content-Type":"application/json"}),s.end(i)});r.listen(e,"127.0.0.1",()=>{console.log(`[bridge] health. listening on 127.0.0.1:${e}`)}),r.on("error",n=>{console.error("[bridge] health.error",{error:n.message})})}function xi(){let t=process.env.BRIDGE_DAEMON==="1"||process.argv.includes("--daemon");if(!t&&!process.env.BRIDGE_PROFILE){let n=process.argv[1]??"";(n.includes("packages/daemon/dist")||n.includes("packages/daemon/src"))&&(console.warn("[bridge] WARNING: running monorepo daemon without --profile \u2014 will use prod config (~/.jerico/settings.json)."),console.warn("[bridge] If this is unintentional, stop and rerun with: node packages/daemon/dist/index.js --profile dev start"))}if(console.log("[bridge] Starting bridge-agent daemon..."),t){ld();return}let e=id();if(!e.ok){let n=e.err,s=Ce();n.code==="EEXIST"?console.warn("[bridge] start.aborted.already.running"):n.code==="EACCES"||n.code==="EPERM"?console.warn(`[bridge] start.aborted.permission_denied \u2014 cannot write ${s} (${n.code}). Directory may be owned by root from \`sudo npm install\`. Try: sudo chown -R "$(whoami):staff" ~/.bridge`):n.code==="ENOENT"?console.warn(`[bridge] start.aborted.lock_dir_missing \u2014 ${s}`):console.warn(`[bridge] start.aborted.lock_error \u2014 ${n.code}: ${n.message}`),process.exit(1)}console.log("[bridge] start.no_persist \u2014 starting without launchd service registration");let r=Me();ad(r),process.exit(0)}var Ci=m(require("https")),Pi=m(require("http")),dr=require("node:fs");Pe();oe();var dd="https://lcars.jerico.appnova.io";function ud(t){return(t??"").trim()}var Oi=`
459
+ `,{mode:493}),console.log("[daemon] mcp.wrapper.written",{path:e})}catch(t){console.warn("[daemon] mcp.wrapper.write.failed",{error:String(t)})}}function ld(){Es(),cd(),vi();let t=new jt;lr=t,bi(t),t.startLivenessCheck(6e4);let e=yt(),r=(0,wi.createServer)((n,s)=>{let o=yi(),i=JSON.stringify({status:"ok",connected:o,uptime:process.uptime(),version:"0.13.1",activePanels:lr?.getLiveAgentIds().length??0,agentIds:lr?.getLiveAgentIds()??[]});s.writeHead(o?200:503,{"Content-Type":"application/json"}),s.end(i)});r.listen(e,"127.0.0.1",()=>{console.log(`[bridge] health. listening on 127.0.0.1:${e}`)}),r.on("error",n=>{console.error("[bridge] health.error",{error:n.message})})}function xi(){let t=process.env.BRIDGE_DAEMON==="1"||process.argv.includes("--daemon");if(!t&&!process.env.BRIDGE_PROFILE){let n=process.argv[1]??"";(n.includes("packages/daemon/dist")||n.includes("packages/daemon/src"))&&(console.warn("[bridge] WARNING: running monorepo daemon without --profile \u2014 will use prod config (~/.jerico/settings.json)."),console.warn("[bridge] If this is unintentional, stop and rerun with: node packages/daemon/dist/index.js --profile dev start"))}if(console.log("[bridge] Starting bridge-agent daemon..."),t){ld();return}let e=id();if(!e.ok){let n=e.err,s=Ce();n.code==="EEXIST"?console.warn("[bridge] start.aborted.already.running"):n.code==="EACCES"||n.code==="EPERM"?console.warn(`[bridge] start.aborted.permission_denied \u2014 cannot write ${s} (${n.code}). Directory may be owned by root from \`sudo npm install\`. Try: sudo chown -R "$(whoami):staff" ~/.bridge`):n.code==="ENOENT"?console.warn(`[bridge] start.aborted.lock_dir_missing \u2014 ${s}`):console.warn(`[bridge] start.aborted.lock_error \u2014 ${n.code}: ${n.message}`),process.exit(1)}console.log("[bridge] start.no_persist \u2014 starting without launchd service registration");let r=Me();ad(r),process.exit(0)}var Ci=m(require("https")),Pi=m(require("http")),dr=require("node:fs");Pe();oe();var dd="https://lcars.jerico.appnova.io";function ud(t){return(t??"").trim()}var Oi=`
460
460
  jerico daemon \u2014 capability & data-access disclosure
461
461
 
462
462
  This daemon accepts the following commands from the jerico server
@@ -484,4 +484,4 @@ You can remove this daemon at any time: bridge-agent uninstall
484
484
  `),process.exit(s.errors.length>0?1:0)}async function yd(){return new Promise(t=>{process.stdout.write(`This will stop the daemon, remove the login service, delete the auth token,
485
485
  config, logs, and wrapper script. This cannot be undone.
486
486
  Type "yes" to continue: `);let e="";process.stdin.setEncoding("utf-8"),process.stdin.resume(),process.stdin.on("data",r=>{e+=r,e.includes(`
487
- `)&&(process.stdin.pause(),t(e.trim().toLowerCase()==="yes"))})})}var Tn=m(require("path")),Ui=require("node:os");oe();var bd=Tn.default.join((0,Ui.homedir)(),"Library","LaunchAgents");function Wi(){console.log("[bridge] service.install.start");let t=Me(),e=te(),r=Tn.default.join(bd,e);if(!Pt(t)){let i=`Failed to write plist at ${r}`;return console.error("[bridge] service.install.plist_write.failed",{path:r}),{ok:!1,reason:"plist_write",message:i}}console.log("[bridge] service.install.plist_write.ok",{path:r});let{ok:s,permissionDenied:o}=Ei();if(!s){if(o)return console.error("[bridge] service.install.launchctl.permission_denied"),{ok:!1,reason:"permission_denied",message:`Permission denied. Manual: sudo launchctl bootstrap gui/$(id -u) "${r}"`};let i="launchctl load failed";return console.error("[bridge] service.install.launchctl.failed"),{ok:!1,reason:"launchctl_load",message:i}}return console.log("[bridge] service.install.ok"),Ii(),{ok:!0}}var rt=require("node:child_process"),j=require("node:fs"),Nn=require("node:os"),qi=m(require("node:http")),st=m(require("path"));oe();Pe();var Fi=require("node:child_process");function wd(t,e){let r=t.split("."),n=e.split(".");for(let s=0;s<3;s++){let o=parseInt(r[s]??"0",10),i=parseInt(n[s]??"0",10);if(isNaN(o)||isNaN(i))break;if(o!==i)return o-i}return t.localeCompare(e)}function An(t,e){return wd(t,e)>0}function Rn(t="latest"){let r=["latest","beta","next","canary"].includes(t)?t:"latest";try{let s=(0,Fi.execSync)(`npm view bridge-agent@${r} version`,{timeout:5e3,stdio:"pipe"}).toString().trim();return/^\d+\.\d+\.\d+/.test(s)?s:null}catch{return null}}function Gi(t="latest",e){let r=Rn(t);return r?An(e,r)?{updateAvailable:!1,currentVersion:e,latestVersion:r,reason:"ahead_of_channel"}:e===r?{updateAvailable:!1,currentVersion:e,latestVersion:r,reason:"up_to_date"}:{updateAvailable:!0,latestVersion:r,currentVersion:e}:{updateAvailable:!1,currentVersion:e,reason:"registry_unreachable"}}var pr=st.default.join((0,Nn.homedir)(),".bridge"),nt=st.default.join(pr,"update.lock"),Sd=st.default.join(pr,"update-state.json"),vd=st.default.join((0,Nn.homedir)(),"Library","LaunchAgents");function kd(){if((0,j.existsSync)(nt))try{let{pid:t}=JSON.parse((0,j.readFileSync)(nt,"utf8"));if(t&&process.kill(t,0))return;(0,j.unlinkSync)(nt)}catch{try{(0,j.unlinkSync)(nt)}catch{}}}function Ed(){try{(0,j.mkdirSync)(pr,{recursive:!0})}catch{}kd();try{let t=(0,j.openSync)(nt,"wx");return(0,j.writeSync)(t,JSON.stringify({pid:process.pid,startedAt:Date.now()})),(0,j.closeSync)(t),{ok:!0}}catch(t){return{ok:!1,err:t}}}function we(){try{(0,j.unlinkSync)(nt)}catch{}}function Id(t){try{(0,j.mkdirSync)(pr,{recursive:!0})}catch{}(0,j.writeFileSync)(Sd,JSON.stringify(t,null,2),{mode:384})}function Hi(t,e=3e4){let r=yt(),n=Date.now()+e;return new Promise(s=>{let o=()=>{if(Date.now()>n){s(!1);return}try{let i=qi.default.get(`http://127.0.0.1:${r}/health`,a=>{let c="";a.on("data",l=>{c+=l}),a.on("end",()=>{try{if(JSON.parse(c).version===t){s(!0);return}}catch{}setTimeout(o,500)})});i.on("error",()=>{setTimeout(o,500)}),i.setTimeout(1e3,()=>{i.destroy(),setTimeout(o,500)})}catch{setTimeout(o,500)}};setTimeout(o,1e3)})}async function Vi(t){let e="0.13.0",r=pe(),n=t.channel??r.updateChannel??"latest";process.pkg!==void 0&&(console.error("[bridge] update.refused: bundled install \u2014 cannot self-update via npm."),console.error("[bridge] Update via the Jerico desktop app (tray \u2192 Update)."),process.exit(1));let s=Me();if((s.includes("packages/daemon/dist")||s.includes("packages/daemon/src"))&&(console.error("[bridge] update.refused: running from monorepo \u2014 cannot self-update a dev checkout."),console.error("[bridge] To test update logic, install the published package globally:"),console.error("[bridge] npm i -g bridge-agent"),process.exit(1)),t.check){let _=Gi(n,e);_.updateAvailable&&(console.log(`[bridge] update.available: ${e} \u2192 ${_.latestVersion} (channel: ${n})`),process.exit(10));let b=_.reason??"unknown";console.log(`[bridge] update.unavailable: ${e} (channel: ${n}, reason: ${b})`),process.exit(0)}let o=Rn(n);o||(console.error("[bridge] update.failed: cannot reach npm registry"),process.exit(1)),e===o&&(console.log(`[bridge] update.up_to_date: ${e} (channel: ${n})`),t.saveChannel&&(re({updateChannel:n}),console.log(`[bridge] update.channel.saved: ${n}`)),process.exit(0)),An(e,o)&&(console.log(`[bridge] update.ahead: ${e} > ${o} (channel: ${n}).`),console.log("[bridge] You are on a build ahead of the public channel. Update not available."),process.exit(0)),console.log(`[bridge] update.available: ${e} \u2192 ${o} (channel: ${n})`);let i=Si()?.getLiveAgentIds().length??0;i>0&&!t.force&&(console.error(`[bridge] update.blocked: ${i} active panel(s) \u2014 cannot update without --force`),console.error("[bridge] Use --force to bypass this safety check, or stop panels first."),console.error("[bridge] bridge-agent stop # stop the daemon"),process.exit(1)),i>0&&t.force&&console.log(`[bridge] update.force: ${i} active panel(s) will be terminated during update.`),t.saveChannel&&(re({updateChannel:n}),console.log(`[bridge] update.channel.saved: ${n}`));let a=Ed();if(!a.ok){let _=a.err;_.code==="EEXIST"?console.error("[bridge] update.aborted: another update is already in progress (update.lock exists)"):console.error(`[bridge] update.lock.failed: ${_.code} \u2014 ${_.message}`),process.exit(1)}console.log(`[bridge] update.installing: bridge-agent@${n}...`);let c=!1;try{(0,rt.execSync)(`npm install -g bridge-agent@${n}`,{stdio:"inherit",timeout:12e4}),c=!0}catch(_){console.error(`[bridge] update.install.failed: ${String(_)}`),c=!1}if(!c){console.error(`[bridge] update.install.failed: rolling back to bridge-agent@${e}...`);try{(0,rt.execSync)(`npm install -g bridge-agent@${e}`,{stdio:"inherit",timeout:12e4}),console.log("[bridge] update.install.rollback.ok \u2014 restored previous version")}catch(_){we(),console.error(`[bridge] update.install.rollback.FAILED: ${String(_)}`),console.error("[bridge] \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.error("[bridge] \u2551 CRITICAL: npm install failed AND rollback failed. \u2551"),console.error("[bridge] \u2551 Binary may be broken. Manual recovery needed. \u2551"),console.error(`[bridge] \u2551 Try: npm install -g bridge-agent@${e} \u2551`),console.error("[bridge] \u2551 Then: bridge-agent start \u2551"),console.error("[bridge] \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),process.exit(1)}we(),console.error("[bridge] update.aborted: npm install failed, daemon is on previous version."),process.exit(1)}let l=te(),d=l.replace(".plist",""),u=st.default.join(vd,l),p=Me();if((0,j.existsSync)(u)?Pt(p)||(we(),console.error("[bridge] update.failed: could not write launchd plist"),console.error("[bridge] npm install succeeded but launchd setup failed. Run: bridge-agent install-service"),process.exit(1)):console.log("[bridge] update.launchd.skipped",{reason:"not_installed"}),(0,j.existsSync)(u))try{(0,rt.execSync)(`launchctl kickstart -kp gui/$(id -u)/${d}`,{stdio:"pipe"}),console.log("[bridge] update.kickstart.ok \u2014 daemon restarting with new version")}catch{we(),console.error("[bridge] update.failed: launchctl kickstart failed"),console.error(`[bridge] Manual restart: launchctl kickstart -kp gui/$(id -u)/${d}`),process.exit(1)}else console.log("[bridge] update.complete.no_service \u2014 binary updated; restart with: bridge-agent start");console.log(`[bridge] update.verifying: polling health for version ${o}...`),await Hi(o,3e4)&&(Id({previousVersion:e,channel:n,installedAt:new Date().toISOString()}),we(),console.log(`[bridge] update.complete: ${e} \u2192 ${o}`),process.exit(0)),console.error(`[bridge] update.health.timeout: daemon did not report version ${o} within 30s`),console.error(`[bridge] update.rolling_back: reinstalling bridge-agent@${e}...`);try{(0,rt.execSync)(`npm install -g bridge-agent@${e}`,{stdio:"inherit",timeout:12e4}),console.log("[bridge] update.rollback.install.ok")}catch(_){we(),console.error(`[bridge] update.rollback.install.FAILED: ${String(_)}`),console.error("[bridge] \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.error("[bridge] \u2551 CRITICAL: update failed AND rollback failed. \u2551"),console.error("[bridge] \u2551 Daemon may be broken. Manual recovery needed. \u2551"),console.error(`[bridge] \u2551 Try: npm install -g bridge-agent@${e} \u2551`),console.error("[bridge] \u2551 Then: bridge-agent start \u2551"),console.error("[bridge] \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),process.exit(1)}let h=Me();if((0,j.existsSync)(u))try{Pt(h),(0,rt.execSync)(`launchctl kickstart -kp gui/$(id -u)/${d}`,{stdio:"pipe"}),console.log("[bridge] update.rollback.kickstart.ok")}catch{we(),console.error("[bridge] update.rollback.kickstart.failed \u2014 daemon may need manual restart"),console.error(`[bridge] Run: launchctl kickstart -kp gui/$(id -u)/${d}`),process.exit(1)}else console.log("[bridge] update.rollback.complete.no_service \u2014 binary restored; restart with: bridge-agent start");console.log(`[bridge] update.rollback.verifying: polling for version ${e}...`);let g=await Hi(e,3e4);we(),g&&(console.log(`[bridge] update.rollback.complete: restored to ${e}`),console.log(`[bridge] Update to ${o} failed \u2014 daemon is running on previous version.`),process.exit(1)),console.error("[bridge] \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.error("[bridge] \u2551 CRITICAL: update failed AND rollback health-check failed.\u2551"),console.error("[bridge] \u2551 Daemon may still be running \u2014 DO NOT KILL IT. \u2551"),console.error("[bridge] \u2551 Manual check: bridge-agent status \u2551"),console.error("[bridge] \u2551 Check logs: tail -f ~/bridge-daemon.log \u2551"),console.error("[bridge] \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),process.exit(1)}var jn=m(require("node:fs")),Ln=m(require("node:os")),Bn=m(require("node:path")),q=new Zn;q.name("bridge-agent").description("Bridge local agent \u2014 connects your AI tools to Jerico").version("0.13.0").option("--profile <name>","Config profile name (e.g. dev). Isolates config, lock, and fingerprint from the default prod profile.").hook("preAction",t=>{let e=t.opts().profile;e&&(process.env.BRIDGE_PROFILE=e)});q.command("start").description("Start the bridge-agent daemon").option("--health-port <port>","Health check HTTP port (default: 3101 prod, 3102 for --profile <name>). Overrides the per-profile default.").action(t=>{t.healthPort&&(process.env.HEALTH_PORT=t.healthPort),xi()});q.command("auth").description("Authenticate with Bridge server").option("-s, --server <url>","Server URL (default: https://lcars.jerico.appnova.io)").option("-t, --token <token>","Use token non-interactively").option("--no-browser","Print auth URL without opening browser or interactive prompt").action(t=>{Ti(t.server,!t.browser,t.token)});q.command("link-project <workspace-id> <project-id> <local-path>").description("Link a local directory to a project for this machine (Issue #152)").action((t,e,r)=>{Di(t,e,r)});q.command("cleanup-orphans").description("Remove orphaned daemon_project_paths rows for this user").action(()=>{ji()});q.command("status").description("Show connection status").action(async()=>{try{let{loadConfig:t}=await Promise.resolve().then(()=>(Pe(),Ko)),e=t();console.log("[bridge] Config found"),console.log(" Server:",e.server),console.log(" Name:",e.name)}catch{console.log("[bridge] Not authenticated. Run: bridge-agent auth")}});q.command("stop").description("Stop the bridge-agent daemon").action(()=>{Bi()});q.command("install-service").description("Install bridge-agent as a persistent login service (launchd plist with RunAtLoad+KeepAlive)").action(()=>{let t=Wi();t.ok||(console.error(`[bridge] install-service.failed: ${t.message}`),process.exit(1)),process.exit(0)});q.command("uninstall").description("Remove the daemon, its login service plist, auth token, config, logs, and wrapper").option("--dry-run","Show what would be removed without removing anything").option("--force","Skip confirmation prompt (for non-TTY / scripted use)").option("--json","Emit JSON result summary to stdout").action(t=>{$i(t)});q.command("update").description("Update bridge-agent to the latest version (or a specific channel)").option("--check","Check for update availability (exit 0 if up-to-date or ahead, 10 if update available)").option("--channel <name>","npm dist-tag channel (latest, beta, next, canary)").option("--save-channel","Persist the channel to config (default: only used for this run)").option("--force","Bypass active-panel safety block (allows update with live panels)").option("--yes","Non-interactive mode (skip TTY prompts; still refuses if panels are active without --force)").action(t=>{Vi(t)});q.command("probe-fda").description("Probe ~/Documents to trigger macOS FDA auto-list entry (one-shot, exits 0 always)").action(()=>{try{jn.readdirSync(Bn.join(Ln.homedir(),"Documents")),console.log("[bridge] probe-fda: Documents readable")}catch{console.log("[bridge] probe-fda: Documents access denied \u2014 entry added to FDA list")}process.exit(0)});q.command("check-fda").description("Check ~/Documents readability (exit 0 = FDA granted, exit 1 = denied)").action(()=>{try{jn.readdirSync(Bn.join(Ln.homedir(),"Documents")),console.log("[bridge] check-fda: granted"),process.exit(0)}catch{console.log("[bridge] check-fda: denied"),process.exit(1)}});q.command("bridge-mcp").description("Run the bundled Bridge MCP server (stdio)").action(()=>{process.env.HTTP_MODE=process.env.HTTP_MODE??"false",console.error("[bridge] bridge-mcp.start",{mode:"stdio"}),require("./bridge-mcp.cjs")});var Dn=process.argv[2]??"",xd=Dn.startsWith("/")&&(Dn.endsWith(".js")||Dn.endsWith(".cjs"))?process.argv.slice(1):process.argv;q.parse(xd);
487
+ `)&&(process.stdin.pause(),t(e.trim().toLowerCase()==="yes"))})})}var Tn=m(require("path")),Ui=require("node:os");oe();var bd=Tn.default.join((0,Ui.homedir)(),"Library","LaunchAgents");function Wi(){console.log("[bridge] service.install.start");let t=Me(),e=te(),r=Tn.default.join(bd,e);if(!Pt(t)){let i=`Failed to write plist at ${r}`;return console.error("[bridge] service.install.plist_write.failed",{path:r}),{ok:!1,reason:"plist_write",message:i}}console.log("[bridge] service.install.plist_write.ok",{path:r});let{ok:s,permissionDenied:o}=Ei();if(!s){if(o)return console.error("[bridge] service.install.launchctl.permission_denied"),{ok:!1,reason:"permission_denied",message:`Permission denied. Manual: sudo launchctl bootstrap gui/$(id -u) "${r}"`};let i="launchctl load failed";return console.error("[bridge] service.install.launchctl.failed"),{ok:!1,reason:"launchctl_load",message:i}}return console.log("[bridge] service.install.ok"),Ii(),{ok:!0}}var rt=require("node:child_process"),j=require("node:fs"),Nn=require("node:os"),qi=m(require("node:http")),st=m(require("path"));oe();Pe();var Fi=require("node:child_process");function wd(t,e){let r=t.split("."),n=e.split(".");for(let s=0;s<3;s++){let o=parseInt(r[s]??"0",10),i=parseInt(n[s]??"0",10);if(isNaN(o)||isNaN(i))break;if(o!==i)return o-i}return t.localeCompare(e)}function An(t,e){return wd(t,e)>0}function Rn(t="latest"){let r=["latest","beta","next","canary"].includes(t)?t:"latest";try{let s=(0,Fi.execSync)(`npm view bridge-agent@${r} version`,{timeout:5e3,stdio:"pipe"}).toString().trim();return/^\d+\.\d+\.\d+/.test(s)?s:null}catch{return null}}function Gi(t="latest",e){let r=Rn(t);return r?An(e,r)?{updateAvailable:!1,currentVersion:e,latestVersion:r,reason:"ahead_of_channel"}:e===r?{updateAvailable:!1,currentVersion:e,latestVersion:r,reason:"up_to_date"}:{updateAvailable:!0,latestVersion:r,currentVersion:e}:{updateAvailable:!1,currentVersion:e,reason:"registry_unreachable"}}var pr=st.default.join((0,Nn.homedir)(),".bridge"),nt=st.default.join(pr,"update.lock"),Sd=st.default.join(pr,"update-state.json"),vd=st.default.join((0,Nn.homedir)(),"Library","LaunchAgents");function kd(){if((0,j.existsSync)(nt))try{let{pid:t}=JSON.parse((0,j.readFileSync)(nt,"utf8"));if(t&&process.kill(t,0))return;(0,j.unlinkSync)(nt)}catch{try{(0,j.unlinkSync)(nt)}catch{}}}function Ed(){try{(0,j.mkdirSync)(pr,{recursive:!0})}catch{}kd();try{let t=(0,j.openSync)(nt,"wx");return(0,j.writeSync)(t,JSON.stringify({pid:process.pid,startedAt:Date.now()})),(0,j.closeSync)(t),{ok:!0}}catch(t){return{ok:!1,err:t}}}function we(){try{(0,j.unlinkSync)(nt)}catch{}}function Id(t){try{(0,j.mkdirSync)(pr,{recursive:!0})}catch{}(0,j.writeFileSync)(Sd,JSON.stringify(t,null,2),{mode:384})}function Hi(t,e=3e4){let r=yt(),n=Date.now()+e;return new Promise(s=>{let o=()=>{if(Date.now()>n){s(!1);return}try{let i=qi.default.get(`http://127.0.0.1:${r}/health`,a=>{let c="";a.on("data",l=>{c+=l}),a.on("end",()=>{try{if(JSON.parse(c).version===t){s(!0);return}}catch{}setTimeout(o,500)})});i.on("error",()=>{setTimeout(o,500)}),i.setTimeout(1e3,()=>{i.destroy(),setTimeout(o,500)})}catch{setTimeout(o,500)}};setTimeout(o,1e3)})}async function Vi(t){let e="0.13.1",r=pe(),n=t.channel??r.updateChannel??"latest";process.pkg!==void 0&&(console.error("[bridge] update.refused: bundled install \u2014 cannot self-update via npm."),console.error("[bridge] Update via the Jerico desktop app (tray \u2192 Update)."),process.exit(1));let s=Me();if((s.includes("packages/daemon/dist")||s.includes("packages/daemon/src"))&&(console.error("[bridge] update.refused: running from monorepo \u2014 cannot self-update a dev checkout."),console.error("[bridge] To test update logic, install the published package globally:"),console.error("[bridge] npm i -g bridge-agent"),process.exit(1)),t.check){let _=Gi(n,e);_.updateAvailable&&(console.log(`[bridge] update.available: ${e} \u2192 ${_.latestVersion} (channel: ${n})`),process.exit(10));let b=_.reason??"unknown";console.log(`[bridge] update.unavailable: ${e} (channel: ${n}, reason: ${b})`),process.exit(0)}let o=Rn(n);o||(console.error("[bridge] update.failed: cannot reach npm registry"),process.exit(1)),e===o&&(console.log(`[bridge] update.up_to_date: ${e} (channel: ${n})`),t.saveChannel&&(re({updateChannel:n}),console.log(`[bridge] update.channel.saved: ${n}`)),process.exit(0)),An(e,o)&&(console.log(`[bridge] update.ahead: ${e} > ${o} (channel: ${n}).`),console.log("[bridge] You are on a build ahead of the public channel. Update not available."),process.exit(0)),console.log(`[bridge] update.available: ${e} \u2192 ${o} (channel: ${n})`);let i=Si()?.getLiveAgentIds().length??0;i>0&&!t.force&&(console.error(`[bridge] update.blocked: ${i} active panel(s) \u2014 cannot update without --force`),console.error("[bridge] Use --force to bypass this safety check, or stop panels first."),console.error("[bridge] bridge-agent stop # stop the daemon"),process.exit(1)),i>0&&t.force&&console.log(`[bridge] update.force: ${i} active panel(s) will be terminated during update.`),t.saveChannel&&(re({updateChannel:n}),console.log(`[bridge] update.channel.saved: ${n}`));let a=Ed();if(!a.ok){let _=a.err;_.code==="EEXIST"?console.error("[bridge] update.aborted: another update is already in progress (update.lock exists)"):console.error(`[bridge] update.lock.failed: ${_.code} \u2014 ${_.message}`),process.exit(1)}console.log(`[bridge] update.installing: bridge-agent@${n}...`);let c=!1;try{(0,rt.execSync)(`npm install -g bridge-agent@${n}`,{stdio:"inherit",timeout:12e4}),c=!0}catch(_){console.error(`[bridge] update.install.failed: ${String(_)}`),c=!1}if(!c){console.error(`[bridge] update.install.failed: rolling back to bridge-agent@${e}...`);try{(0,rt.execSync)(`npm install -g bridge-agent@${e}`,{stdio:"inherit",timeout:12e4}),console.log("[bridge] update.install.rollback.ok \u2014 restored previous version")}catch(_){we(),console.error(`[bridge] update.install.rollback.FAILED: ${String(_)}`),console.error("[bridge] \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.error("[bridge] \u2551 CRITICAL: npm install failed AND rollback failed. \u2551"),console.error("[bridge] \u2551 Binary may be broken. Manual recovery needed. \u2551"),console.error(`[bridge] \u2551 Try: npm install -g bridge-agent@${e} \u2551`),console.error("[bridge] \u2551 Then: bridge-agent start \u2551"),console.error("[bridge] \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),process.exit(1)}we(),console.error("[bridge] update.aborted: npm install failed, daemon is on previous version."),process.exit(1)}let l=te(),d=l.replace(".plist",""),u=st.default.join(vd,l),p=Me();if((0,j.existsSync)(u)?Pt(p)||(we(),console.error("[bridge] update.failed: could not write launchd plist"),console.error("[bridge] npm install succeeded but launchd setup failed. Run: bridge-agent install-service"),process.exit(1)):console.log("[bridge] update.launchd.skipped",{reason:"not_installed"}),(0,j.existsSync)(u))try{(0,rt.execSync)(`launchctl kickstart -kp gui/$(id -u)/${d}`,{stdio:"pipe"}),console.log("[bridge] update.kickstart.ok \u2014 daemon restarting with new version")}catch{we(),console.error("[bridge] update.failed: launchctl kickstart failed"),console.error(`[bridge] Manual restart: launchctl kickstart -kp gui/$(id -u)/${d}`),process.exit(1)}else console.log("[bridge] update.complete.no_service \u2014 binary updated; restart with: bridge-agent start");console.log(`[bridge] update.verifying: polling health for version ${o}...`),await Hi(o,3e4)&&(Id({previousVersion:e,channel:n,installedAt:new Date().toISOString()}),we(),console.log(`[bridge] update.complete: ${e} \u2192 ${o}`),process.exit(0)),console.error(`[bridge] update.health.timeout: daemon did not report version ${o} within 30s`),console.error(`[bridge] update.rolling_back: reinstalling bridge-agent@${e}...`);try{(0,rt.execSync)(`npm install -g bridge-agent@${e}`,{stdio:"inherit",timeout:12e4}),console.log("[bridge] update.rollback.install.ok")}catch(_){we(),console.error(`[bridge] update.rollback.install.FAILED: ${String(_)}`),console.error("[bridge] \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.error("[bridge] \u2551 CRITICAL: update failed AND rollback failed. \u2551"),console.error("[bridge] \u2551 Daemon may be broken. Manual recovery needed. \u2551"),console.error(`[bridge] \u2551 Try: npm install -g bridge-agent@${e} \u2551`),console.error("[bridge] \u2551 Then: bridge-agent start \u2551"),console.error("[bridge] \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),process.exit(1)}let h=Me();if((0,j.existsSync)(u))try{Pt(h),(0,rt.execSync)(`launchctl kickstart -kp gui/$(id -u)/${d}`,{stdio:"pipe"}),console.log("[bridge] update.rollback.kickstart.ok")}catch{we(),console.error("[bridge] update.rollback.kickstart.failed \u2014 daemon may need manual restart"),console.error(`[bridge] Run: launchctl kickstart -kp gui/$(id -u)/${d}`),process.exit(1)}else console.log("[bridge] update.rollback.complete.no_service \u2014 binary restored; restart with: bridge-agent start");console.log(`[bridge] update.rollback.verifying: polling for version ${e}...`);let g=await Hi(e,3e4);we(),g&&(console.log(`[bridge] update.rollback.complete: restored to ${e}`),console.log(`[bridge] Update to ${o} failed \u2014 daemon is running on previous version.`),process.exit(1)),console.error("[bridge] \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"),console.error("[bridge] \u2551 CRITICAL: update failed AND rollback health-check failed.\u2551"),console.error("[bridge] \u2551 Daemon may still be running \u2014 DO NOT KILL IT. \u2551"),console.error("[bridge] \u2551 Manual check: bridge-agent status \u2551"),console.error("[bridge] \u2551 Check logs: tail -f ~/bridge-daemon.log \u2551"),console.error("[bridge] \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),process.exit(1)}var jn=m(require("node:fs")),Ln=m(require("node:os")),Bn=m(require("node:path")),q=new Zn;q.name("bridge-agent").description("Bridge local agent \u2014 connects your AI tools to Jerico").version("0.13.1").option("--profile <name>","Config profile name (e.g. dev). Isolates config, lock, and fingerprint from the default prod profile.").hook("preAction",t=>{let e=t.opts().profile;e&&(process.env.BRIDGE_PROFILE=e)});q.command("start").description("Start the bridge-agent daemon").option("--health-port <port>","Health check HTTP port (default: 3101 prod, 3102 for --profile <name>). Overrides the per-profile default.").action(t=>{t.healthPort&&(process.env.HEALTH_PORT=t.healthPort),xi()});q.command("auth").description("Authenticate with Bridge server").option("-s, --server <url>","Server URL (default: https://lcars.jerico.appnova.io)").option("-t, --token <token>","Use token non-interactively").option("--no-browser","Print auth URL without opening browser or interactive prompt").action(t=>{Ti(t.server,!t.browser,t.token)});q.command("link-project <workspace-id> <project-id> <local-path>").description("Link a local directory to a project for this machine (Issue #152)").action((t,e,r)=>{Di(t,e,r)});q.command("cleanup-orphans").description("Remove orphaned daemon_project_paths rows for this user").action(()=>{ji()});q.command("status").description("Show connection status").action(async()=>{try{let{loadConfig:t}=await Promise.resolve().then(()=>(Pe(),Ko)),e=t();console.log("[bridge] Config found"),console.log(" Server:",e.server),console.log(" Name:",e.name)}catch{console.log("[bridge] Not authenticated. Run: bridge-agent auth")}});q.command("stop").description("Stop the bridge-agent daemon").action(()=>{Bi()});q.command("install-service").description("Install bridge-agent as a persistent login service (launchd plist with RunAtLoad+KeepAlive)").action(()=>{let t=Wi();t.ok||(console.error(`[bridge] install-service.failed: ${t.message}`),process.exit(1)),process.exit(0)});q.command("uninstall").description("Remove the daemon, its login service plist, auth token, config, logs, and wrapper").option("--dry-run","Show what would be removed without removing anything").option("--force","Skip confirmation prompt (for non-TTY / scripted use)").option("--json","Emit JSON result summary to stdout").action(t=>{$i(t)});q.command("update").description("Update bridge-agent to the latest version (or a specific channel)").option("--check","Check for update availability (exit 0 if up-to-date or ahead, 10 if update available)").option("--channel <name>","npm dist-tag channel (latest, beta, next, canary)").option("--save-channel","Persist the channel to config (default: only used for this run)").option("--force","Bypass active-panel safety block (allows update with live panels)").option("--yes","Non-interactive mode (skip TTY prompts; still refuses if panels are active without --force)").action(t=>{Vi(t)});q.command("probe-fda").description("Probe ~/Documents to trigger macOS FDA auto-list entry (one-shot, exits 0 always)").action(()=>{try{jn.readdirSync(Bn.join(Ln.homedir(),"Documents")),console.log("[bridge] probe-fda: Documents readable")}catch{console.log("[bridge] probe-fda: Documents access denied \u2014 entry added to FDA list")}process.exit(0)});q.command("check-fda").description("Check ~/Documents readability (exit 0 = FDA granted, exit 1 = denied)").action(()=>{try{jn.readdirSync(Bn.join(Ln.homedir(),"Documents")),console.log("[bridge] check-fda: granted"),process.exit(0)}catch{console.log("[bridge] check-fda: denied"),process.exit(1)}});q.command("bridge-mcp").description("Run the bundled Bridge MCP server (stdio)").action(()=>{process.env.HTTP_MODE=process.env.HTTP_MODE??"false",console.error("[bridge] bridge-mcp.start",{mode:"stdio"}),require("./bridge-mcp.cjs")});var Dn=process.argv[2]??"",xd=Dn.startsWith("/")&&(Dn.endsWith(".js")||Dn.endsWith(".cjs"))?process.argv.slice(1):process.argv;q.parse(xd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bridge-agent",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "Bridge local agent — connects your AI tools to Jerico",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",