bridge-agent 0.13.3 → 0.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -418,7 +418,7 @@ ${hi("bridge_get_my_task","bridge_complete_task","bridge_fail_task","bridge_get_
|
|
|
418
418
|
`,"utf-8"),console.log("[daemon] persona.prompt.written",{agentId:n,tmpPath:r}),["--append-system-prompt-file",r]}catch(r){return console.warn("[daemon] persona.prompt.write.failed",{agentId:n,error:String(r)}),[]}return t==="qwen"?["--append-system-prompt",e.trim()]:[]}function Dt(t){return`"${t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function Hd(t){try{let e=process.env.BRIDGE_MCP_URL,n=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:We(),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"}}}},r=P.default.join(D.default.tmpdir(),`bridge-mcp-kimi-${t.agentId??(t.projectId||"workspace")}.json`);return A.default.writeFileSync(r,JSON.stringify(n,null,2)+`
|
|
419
419
|
`,{encoding:"utf-8",mode:384,flag:"w"}),A.default.chmodSync(r,384),console.log("[daemon] kimi.mcp.config.written",{tmpPath:r,transport:e?"http":"stdio"}),["--mcp-config-file",r]}catch(e){return console.warn("[daemon] kimi.mcp.config.build.failed",{error:String(e)}),[]}}function qd(t){try{let e=We(),n=`{BRIDGE_SERVER_URL=${Dt(t.serverUrl)},BRIDGE_TOKEN=${Dt(t.token)},BRIDGE_WORKSPACE_ID=${Dt(t.workspaceId)},BRIDGE_PROJECT_ID=${Dt(t.projectId||"workspace")},HTTP_MODE="false"}`;return["-c",'mcp_servers.bridge.transport="stdio"',"-c",`mcp_servers.bridge.command=${Dt(e)}`,"-c","mcp_servers.bridge.args=[]","-c",`mcp_servers.bridge.env=${n}`]}catch(e){return console.warn("[daemon] codex.mcp.config.build.failed",{error:String(e)}),[]}}function Vd(t){try{return A.default.statSync(t).isDirectory()}catch{return!1}}function Zr(t,e){try{return e(t)}catch{return!1}}function Kd(t,e,n,r,o=Vd){let s=r?.[t];if(s&&Zr(s,o))return{path:s,source:"local_override"};if(n){if(Zr(n,o))return{path:n,source:"daemon_override"};console.warn("[daemon] spawn.cwd.daemon_override_missing",{projectId:t,daemonLocalPath:n,hint:`Run: jerico link-project ${t} <local-path>`})}if(e&&Zr(e,o))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:s,daemonLocalPath:n??void 0,hint:a}),{path:D.default.homedir(),source:"fallback_home"}}function Yd(){let t=P.default.join(D.default.homedir(),".forge",".forge.toml");if(A.default.existsSync(t))try{let e=A.default.readFileSync(t,"utf-8");if(e.includes("auto_update = true")){let n=e.replace(/^auto_update\s*=\s*true$/m,"auto_update = false");A.default.writeFileSync(t,n),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 Jd(t){Yd();try{if(!t.cwd)return console.warn("[daemon] forge.mcp.setup.skipped",{reason:"missing_cwd",projectId:t.projectId||"workspace"}),!1;let e=We(),n=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"}}}}),r={cwd:t.cwd,encoding:"utf-8",timeout:5e3,stdio:"pipe"};(0,it.spawnSync)("forge",["mcp","remove","--scope","local","bridge"],r);let o=(0,it.spawnSync)("forge",["mcp","import",n,"--scope","local"],r);if(o.status===0){try{A.default.chmodSync(P.default.join(t.cwd,".mcp.json"),384)}catch{}return console.log("[daemon] forge.mcp.setup.ok",{cwd:t.cwd,projectId:t.projectId||"workspace"}),!0}return console.warn("[daemon] forge.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] forge.mcp.setup.error",{error:String(e),projectId:t.projectId}),!1}}function zd(t){try{let e=P.default.join(D.default.homedir(),".config","opencode","opencode.json"),n={};try{n=JSON.parse(A.default.readFileSync(e,"utf-8"))}catch{}delete n.mcpServers;let r=process.env.BRIDGE_MCP_URL,o=t.projectId||"workspace",s={...n.mcp??{}};return r?s.bridge={type:"remote",url:`${r}/mcp/${t.workspaceId}/${o}`,enabled:!0,headers:{Authorization:`Bearer ${t.token}`,"x-panel-id":t.agentId??"","x-panel-persona-id":t.personaId??""}}:s.bridge={type:"local",command:[We()],environment:{BRIDGE_SERVER_URL:t.serverUrl,BRIDGE_WORKSPACE_ID:t.workspaceId,BRIDGE_PROJECT_ID:o,BRIDGE_PANEL_ID:t.agentId??"",BRIDGE_PERSONA_ID:t.personaId??"",HTTP_MODE:"false"},enabled:!0},n.mcp=s,A.default.mkdirSync(P.default.dirname(e),{recursive:!0}),A.default.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
420
420
|
`,{encoding:"utf-8",mode:384}),A.default.chmodSync(e,384),console.log("[daemon] opencode.mcp.config.written",{configPath:e,transport:r?"http":"stdio"}),!0}catch(e){return console.warn("[daemon] opencode.mcp.config.build.failed",{error:String(e)}),!1}}function Xd(t){try{if(!t.cwd)return console.warn("[daemon] qwen.mcp.setup.skipped",{reason:"missing_cwd",projectId:t.projectId||"workspace"}),!1;let e=We(),n={cwd:t.cwd,encoding:"utf-8",timeout:5e3,stdio:"pipe"},r=P.default.resolve(t.cwd)===P.default.resolve(D.default.homedir()),o=r?"user":"project";r&&console.warn("[daemon] qwen.mcp.home_dir_fallback",{cwd:t.cwd,projectId:t.projectId||"workspace",scope:"user"}),(0,it.spawnSync)("qwen",["mcp","remove","--scope",o,"bridge"],n);let s=(0,it.spawnSync)("qwen",["mcp","add","--scope",o,"-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],n);if(s.status===0){let i=o==="user"?P.default.join(D.default.homedir(),".qwen"):P.default.join(t.cwd,".qwen");try{A.default.chmodSync(P.default.join(i,"settings.json"),384)}catch{}return console.log("[daemon] qwen.mcp.setup.ok",{cwd:t.cwd,projectId:t.projectId||"workspace"}),!0}return console.warn("[daemon] qwen.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] qwen.mcp.setup.error",{error:String(e),projectId:t.projectId}),!1}}function Qd(t){try{if(!t.cwd)return console.warn("[daemon] gemini.mcp.setup.skipped",{reason:"missing_cwd",projectId:t.projectId||"workspace"}),!1;let e=P.default.join(t.cwd,".gemini"),n=P.default.join(e,"settings.json"),r={};try{r=JSON.parse(A.default.readFileSync(n,"utf-8"))}catch{}let o=We(),s=t.projectId||"workspace",i=process.env.BRIDGE_MCP_URL,a={...r.mcpServers??{}};return i?a.bridge={type:"http",url:`${i}/mcp/${t.workspaceId}/${s}`,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:o,args:[],env:{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"},trust:!0,description:"Bridge MCP server"},r.mcpServers=a,A.default.mkdirSync(e,{recursive:!0}),A.default.writeFileSync(n,JSON.stringify(r,null,2)+`
|
|
421
|
-
`,{encoding:"utf-8",mode:384}),A.default.chmodSync(n,384),console.log("[daemon] gemini.mcp.config.written",{configPath:n,transport:i?"http":"stdio"}),!0}catch(e){return console.warn("[daemon] gemini.mcp.config.build.failed",{error:String(e)}),!1}}var Mt=[],eo=!1,la=!1;function da(){return eo}function ua(t){if(la)throw new Error("[daemon] startDaemonConnection called twice \u2014 only one connection manager allowed");if(la=!0,process.env.BRIDGE_TEST_SCRIPTED_REVIEW!=="1")try{let T=P.default.join(D.default.homedir(),".jerico","settings.json");A.default.existsSync(T)&&JSON.parse(A.default.readFileSync(T,"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=ve(),n=(0,at.createHash)("sha256").update(e.token).digest("hex");function r(T,O,_){a?.readyState===C.OPEN&&a.send(JSON.stringify({type:"tool_usage",daemonId:n,tool:T,kind:O,..._}))}let o=setInterval(()=>{Z&&a?.readyState===C.OPEN&&r("claude","quota",{prompts5h:Z.prompts5h,limit5h:Z.limit5h,resetAt:Z.resetAt,tier:Z.tier,estimate:!0})},6e4);In.push(()=>clearInterval(o));function s(T){for(let O of T){if(O.authStatus!=="ok"||Qr.has(O.key))continue;let _;switch(O.key){case"qwen":_=Yi(y=>{r("qwen","quota",{prompts5h:y.prompts5h,limit5h:y.limit5h,resetAt:y.resetAt,estimate:!0})});break;case"opencode":_=zi(y=>{r("opencode","spent",{tokensSpent5h:y.tokensSpent5h,tokensTotal:y.tokensTotal})});break;case"gemini":_=Zi(y=>{r("gemini","spent",{tokensSpent5h:y.tokensSpent5h,tokensTotal:y.tokensTotal})});break;case"kimi":_=na(y=>{r("kimi","spent",{contextPct:y.contextPct,contextTokens:y.contextTokens,maxContextTokens:y.maxContextTokens,tokensSpent5h:y.tokensSpent5h})});break}_&&(Qr.add(O.key),In.push(()=>{_(),Qr.delete(O.key)}),O.key==="claude"&&Z&&a?.readyState===C.OPEN&&r("claude","quota",{prompts5h:Z.prompts5h,limit5h:Z.limit5h,resetAt:Z.resetAt,tier:Z.tier,estimate:!0}))}}let i=new un(n),a=null,c=null,l=null,d=0,u=0,p=0n,f=0,h=0,g=!1;function b(){c&&(clearTimeout(c),c=null),l&&(clearInterval(l),l=null),g=!1;let T=Date.now(),O=process.hrtime.bigint();a=new C(e.server,{headers:{Authorization:`Bearer ${e.token}`}});let _=a,y=(0,at.randomUUID)();Xr=y;let m=D.default.networkInterfaces(),w=Object.entries(m).flatMap(([N,W])=>(W||[]).filter(Y=>!Y.internal).map(Y=>({iface:N,address:Y.address,family:Y.family}))),S=JSON.stringify(w);console.log(JSON.stringify({ts:Date.now(),level:"info",event:"net.interfaces",interfaces:w,connectionId:y})),En&&En!==S&&console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"net.interfaces.changed",previous:En,current:S,connectionId:y})),En=S;let I=_.send.bind(_);_.send=function(N){if(_.readyState!==C.OPEN){let W="unknown";try{W=JSON.parse(N).type}catch{}console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.send.dropped",messageType:W,readyState:_.readyState,connectionId:y}));return}return I(N)},console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.connecting",server:e.server,connectionId:y}));let v=null,R=0,j=null,V=!1;_.on("open",()=>{g=!0,eo=!0,console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.connected",server:e.server,connectionId:y})),l=setInterval(()=>{_.readyState===C.OPEN&&(_.ping(),R=Date.now(),j&&clearTimeout(j),j=setTimeout(()=>{console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.heartbeat.timeout",connectionId:y})),_.terminate()},aa))},ia),t.setCurrentWs(_);let N=!ns();_.send(JSON.stringify({type:"ready",version:"1.1",npmVersion:"0.13.3",installModel:process.pkg!==void 0?"pkg":"npm",name:e.name,spawnHelperBroken:N,liveAgentIds:t.getLiveAgentIds(),machineFingerprint:to(),connectionId:y,claudeTier:Pt()})),i.updateWs(_),Promise.all([Xn(e.agentPaths),Er()]).then(([W,Y])=>{Mt=Y?[...W,Y]:W,s(W),_.readyState===C.OPEN&&_.send(JSON.stringify({type:"agents",list:Mt}))}),v=sa(W=>{_.readyState===C.OPEN&&_.send(JSON.stringify({type:"system_metrics",daemonId:n,...W}))})}),_.on("message",N=>{let W;try{W=JSON.parse(N.toString())}catch{console.warn("[daemon] Invalid JSON from server, ignoring");return}Zd(W,_,t,e,i)}),_.on("pong",()=>{j&&(clearTimeout(j),j=null);let N=Date.now()-R;console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.heartbeat.pong",rttMs:N,connectionId:y})),V||(V=!0,u=0,p=0n,f=0,h=0)}),_.on("close",(N,W)=>{eo=!1,l&&(clearInterval(l),l=null),j&&(clearTimeout(j),j=null),v?.(),v=null,i.stopAll(),N===1008?(d++,d>=2&&(console.error("[daemon] ws.auth_failed \u2014 token invalid or expired (2 consecutive rejections), stopping. Re-run: bridge-agent auth"),E(),setTimeout(()=>process.exit(1),2e3)),console.warn("[daemon] ws.auth_rejected \u2014 transient 1008, will retry once",{attempt:d})):d=0;let Y=Number((process.hrtime.bigint()-O)/1000000n);if(console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.closed",code:N,reason:W?.toString()||void 0,uptimeMs:Y,connectionId:y})),c)return;if(g&&!V&&Y<ia+aa+5e3&&N!==1008&&N!==4002&&(f++,console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.reconnect.zombie",zombieStreak:f,uptimeMs:Y,connectionId:y}))),N===4002){console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.duplicate_daemon_detected",code:N,connectionId:y})),f=0,h=0,u=0,p=0n,c&&(clearTimeout(c),c=null);let ut=12e4+Math.random()*18e4;console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.duplicate_daemon_backoff",delayMs:Math.round(ut),connectionId:y})),c=setTimeout(b,ut);return}if(f>=3){if(h++,console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.zombie.escalate",zombieStreak:f,escalationCount:h,connectionId:y})),h>=3){let ut=process.env.BRIDGE_SUPERVISED==="1";console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.zombie.fatal",escalationCount:h,zombieStreak:f,connectionId:y,supervised:ut})),ut&&(E(),setTimeout(()=>process.exit(1),2e3)),console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.reconnect.zombie.non_fatal",message:"manual daemon \u2014 staying alive, backoff retry",escalationCount:h,connectionId:y})),f=0}f=0,_?.close?.(),_?.removeAllListeners?.(),l&&(clearInterval(l),l=null),j&&(clearTimeout(j),j=null),c&&(clearTimeout(c),c=null),c=setTimeout(b,1e4);return}u===0&&(p=process.hrtime.bigint()),u++;let Pe=Number((process.hrtime.bigint()-p)/1000000n);u>=10&&Pe<6e4&&(console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.storm",reconnectCount:u,connectionId:y})),E(),setTimeout(()=>process.exit(1),2e3));let Ft=Math.min(3e4,1e3*Math.pow(2,Math.min(u,5))),_o=Math.round(Ft+Math.random()*500);console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.reconnect.scheduled",delayMs:_o,reconnectCount:u,connectionId:y})),c=setTimeout(b,_o)}),_.on("error",N=>{console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.error",message:N.message,code:N.code,connectionId:y}))})}function E(){l&&(clearInterval(l),l=null),t.stopLivenessCheck(),Nd();for(let T of In)T();In.length=0;for(let T of Fe.values())T();i.stopAll(),t.killAll(),a?.close()}function x(T){console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.signal",signal:T,connectionId:Xr})),E(),setTimeout(()=>process.exit(0),100)}process.on("SIGINT",()=>x("SIGINT")),process.on("SIGTERM",()=>x("SIGTERM")),process.on("SIGHUP",()=>x("SIGHUP")),process.on("uncaughtException",T=>{console.log(JSON.stringify({ts:Date.now(),level:"error",event:"daemon.uncaught",error:String(T),stack:T.stack,connectionId:Xr}));try{E()}catch{}setTimeout(()=>process.exit(1),2e3)}),b()}function Zd(t,e,n,r,o){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"){o.start(t.agentId);return}let s=Mt.find(m=>m.key===t.agentKey);if(!s){e.readyState===C.OPEN&&e.send(JSON.stringify({type:"error",code:"AGENT_NOT_FOUND",message:`Agent '${t.agentKey}' is not installed on this machine`}));return}let i=Ae.find(m=>m.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"&&(Fe.get(t.agentId)?.(),Fe.set(t.agentId,Ur(t.agentId,t.sessionId,(m,w,S)=>{let I=n.getCurrentWs();I?.readyState===C.OPEN&&I.send(JSON.stringify({type:"panel_token_usage",agentId:m,usedPct:w,usedTokens:S}))})));else if(i?.assignSessionId){let m=crypto.randomUUID(),w=t.agentKey==="kimi"?"--session":t.agentKey==="forge"?"--conversation-id":"--session-id";a=[...i.spawnArgs??[],w,m],e.readyState===C.OPEN&&(e.send(JSON.stringify({type:"session_started",agentId:t.agentId,sessionId:m})),console.log("[daemon] session.assigned",{agentId:t.agentId,sessionId:m})),t.agentKey==="claude"&&(Fe.get(t.agentId)?.(),Fe.set(t.agentId,Ur(t.agentId,m,(S,I,v)=>{let R=n.getCurrentWs();R?.readyState===C.OPEN&&R.send(JSON.stringify({type:"panel_token_usage",agentId:S,usedPct:I,usedTokens:v}))})))}else a=[...i?.spawnArgs??[]],e.readyState===C.OPEN&&e.send(JSON.stringify({type:"session_started",agentId:t.agentId,sessionId:crypto.randomUUID()}));let c,l=!1,d,u;if(t.workspaceId){let m=Bd(r.server),w=Kd(t.projectId??"",t.cwd,t.daemonLocalPath,r.projectPaths),S=w.path;if(u=w.source,u==="fallback_home"&&t.sessionId){let v=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:v}),e.readyState===C.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 I=Mr(S);if(c={serverUrl:m,token:r.token,workspaceId:di(t.workspaceId),projectId:t.projectId?ui(t.projectId):void 0,agentId:t.agentId?li(t.agentId):void 0,personaId:t.personaId,cwd:S,projectEnv:I.env},t.agentKey==="claude"){let v=$d(c);l=v.length>0,d=process.env.BRIDGE_MCP_URL?"http":"stdio",a=[...a,...v]}else if(t.agentKey==="codex"){let v=qd(c);l=v.length>0,d="stdio",a=[...a,...v]}else if(t.agentKey==="qwen")l=Xd(c),d=l?"stdio":void 0;else if(t.agentKey==="kimi"){let v=Hd(c);l=v.length>0,d=process.env.BRIDGE_MCP_URL?"http":"stdio",a=[...a,...v]}else t.agentKey==="forge"?(l=Jd(c),d=l?"stdio":void 0):t.agentKey==="opencode"?(l=zd(c),d=l?process.env.BRIDGE_MCP_URL?"http":"stdio":void 0):t.agentKey==="gemini"?(l=Qd(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(kr("phase2a.verified_at")&&(w.source==="daemon_override"||w.source==="server_project")){let v=`${m}/api/workspaces/${t.workspaceId}/projects/${t.projectId}/machine-paths/${t.daemonId}/verify`;fetch(v,{method:"PATCH",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:"{}"}).catch(R=>{console.warn("[daemon] verify.patch_failed",{projectId:t.projectId,error:String(R)})})}if(kr("phase2a.auto_register")&&(w.source==="daemon_override"||w.source==="server_project"))try{let v=(0,it.spawnSync)("git",["remote","get-url","origin"],{cwd:S,timeout:5e3,encoding:"utf-8"});if(v.status===0&&v.stdout&&v.stdout.trim()){let R=v.stdout.trim();t.projectId&&(r.projectPaths||(r.projectPaths={}),r.projectPaths[t.projectId]=S,pe({projectPaths:r.projectPaths}));let j=`${m}/api/workspaces/${t.workspaceId}/projects/${t.projectId}/machine-paths`;fetch(j,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:JSON.stringify({daemonId:t.daemonId,localPath:S,repoUrl:R})}).catch(V=>{console.warn("[daemon] auto_register.post_failed",{projectId:t.projectId,error:String(V)})}),console.log("[daemon] auto_register.ok",{projectId:t.projectId,localPath:S,repoUrl:R})}}catch(v){console.log("[daemon] auto_register.skipped",{projectId:t.projectId,reason:String(v)})}}let p=Fd(t.role,t.systemPrompt,t.agentId,t.workspaceId,t.projectId,t.groupId),f=Wd(t.agentKey,p,t.agentId);f.length>0&&(a=[...a,...f]);let h=Gd(t.agentKey,t.systemPrompt,t.agentId);h.length>0&&(a=[...a,...h]);let g=Math.max(1,Math.min(500,t.cols)),b=Math.max(1,Math.min(500,t.rows)),E=Date.now(),x="",T=0,O=!1,_=!1;if(n.spawn(t.agentId,t.agentKey,s.binaryPath,a,g,b,m=>{if(T+=m.length,t.agentKey==="gemini")try{let S=Buffer.from(m,"base64").toString("utf-8");if(S.includes("shell mode enabled"))$e.get(t.agentId)||($e.set(t.agentId,!0),console.log("[daemon] gemini.shell_mode.entered",{agentId:t.agentId.slice(-8)}));else if(S.includes("Type your message")&&($e.get(t.agentId)&&($e.set(t.agentId,!1),console.log("[daemon] gemini.shell_mode.exited",{agentId:t.agentId.slice(-8)})),!st.get(t.agentId))){st.set(t.agentId,!0);let I=Ue.get(t.agentId)??[];Ue.delete(t.agentId),console.log("[daemon] gemini.ready",{agentId:t.agentId.slice(-8),flushing:I.length}),I.length>0&&setTimeout(()=>{for(let v of I)n.write(t.agentId,v,"orchestrator");setTimeout(()=>{n.write(t.agentId,Buffer.from("\r").toString("base64"),"orchestrator")},1e3)},500)}}catch{}try{let S=Buffer.from(m,"base64").toString("utf-8");if(t.agentKey==="kimi"&&t.role&&!_&&Date.now()-E<3e4&&(/yolo agent/.test(S)||/●/.test(S)||/○/.test(S))){_=!0;let I=p;if(I){let v=Rd(I),R=Buffer.from(v).toString("base64");n.write(t.agentId,R,"orchestrator"),console.log("[daemon] kimi.role.injected",{agentId:t.agentId,role:t.role})}}}catch{}if(!x)try{let S=Buffer.from(m,"base64").toString("utf-8"),I=Ld(S).replace(/\x00/g,"").trim();if(I&&(x=Md(I)),t.agentKey==="codex"&&!O&&Date.now()-E<2e4&&/included in your plan for free|let[’']s build together/i.test(I)&&/yes|no|\[y\/n\]|\(y\/n\)|y\/n/i.test(I)){O=!0;let v=Buffer.from("y").toString("base64");n.write(t.agentId,v,"orchestrator"),console.log("[daemon] codex.onboarding.auto_ack",{agentId:t.agentId})}}catch{}let w=n.getCurrentWs();if(w?.readyState===C.OPEN)if(w.bufferedAmount>ca){let S=Date.now(),I=xn.get(t.agentId);(!I||S-I>=1e3)&&(xn.set(t.agentId,S),console.log(JSON.stringify({ts:S,level:"warn",event:"pty.backpressure.drop",agentId:t.agentId,bufferedAmount:w.bufferedAmount,threshold:ca})))}else w.send(JSON.stringify({type:"output",agentId:t.agentId,data:m}));Pd(t.agentId,()=>n.getCurrentWs())},(m,w)=>{let S=Date.now()-E,I=S<=Dd;console.log("[daemon] pty.spawn.result",{agentId:t.agentId,agentKey:t.agentKey,daemonId:t.daemonId,exitCode:m,signal:w,uptimeMs:S,earlyExit:I,outputBytes:T,firstOutputSnippet:x||void 0});let v=n.getCurrentWs();if(I&&v?.readyState===C.OPEN&&v.send(JSON.stringify({type:"error",code:"SPAWN_FAILED",message:`Early exit: agent=${t.agentKey} code=${m??"null"} signal=${w??"null"} snippet="${x||"no output"}"`})),v?.readyState===C.OPEN&&v.send(JSON.stringify({type:"exit",agentId:t.agentId,exitCode:m,signal:w})),Cd(t.agentId),$e.delete(t.agentId),st.delete(t.agentId),Ue.delete(t.agentId),xn.delete(t.agentId),Promise.all([(0,jt.unlink)(P.default.join(D.default.tmpdir(),`bridge-persona-${t.agentId}.md`)),(0,jt.unlink)(P.default.join(D.default.tmpdir(),`bridge-role-${t.agentId}.md`)),(0,jt.unlink)(P.default.join(D.default.tmpdir(),`bridge-mcp-${t.agentId}.json`)),(0,jt.unlink)(P.default.join(D.default.tmpdir(),`bridge-mcp-kimi-${t.agentId}.json`))].map(R=>R.catch(()=>{}))).catch(()=>{}),t.agentKey==="opencode"){let R=P.default.join(D.default.homedir(),".config","opencode","opencode.json");try{let j=A.default.readFileSync(R,"utf-8"),V=JSON.parse(j);V?.mcp?.bridge&&(delete V.mcp.bridge,A.default.writeFileSync(R,JSON.stringify(V,null,2)+`
|
|
421
|
+
`,{encoding:"utf-8",mode:384}),A.default.chmodSync(n,384),console.log("[daemon] gemini.mcp.config.written",{configPath:n,transport:i?"http":"stdio"}),!0}catch(e){return console.warn("[daemon] gemini.mcp.config.build.failed",{error:String(e)}),!1}}var Mt=[],eo=!1,la=!1;function da(){return eo}function ua(t){if(la)throw new Error("[daemon] startDaemonConnection called twice \u2014 only one connection manager allowed");if(la=!0,process.env.BRIDGE_TEST_SCRIPTED_REVIEW!=="1")try{let T=P.default.join(D.default.homedir(),".jerico","settings.json");A.default.existsSync(T)&&JSON.parse(A.default.readFileSync(T,"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=ve(),n=(0,at.createHash)("sha256").update(e.token).digest("hex");function r(T,O,_){a?.readyState===C.OPEN&&a.send(JSON.stringify({type:"tool_usage",daemonId:n,tool:T,kind:O,..._}))}let o=setInterval(()=>{Z&&a?.readyState===C.OPEN&&r("claude","quota",{prompts5h:Z.prompts5h,limit5h:Z.limit5h,resetAt:Z.resetAt,tier:Z.tier,estimate:!0})},6e4);In.push(()=>clearInterval(o));function s(T){for(let O of T){if(O.authStatus!=="ok"||Qr.has(O.key))continue;let _;switch(O.key){case"qwen":_=Yi(y=>{r("qwen","quota",{prompts5h:y.prompts5h,limit5h:y.limit5h,resetAt:y.resetAt,estimate:!0})});break;case"opencode":_=zi(y=>{r("opencode","spent",{tokensSpent5h:y.tokensSpent5h,tokensTotal:y.tokensTotal})});break;case"gemini":_=Zi(y=>{r("gemini","spent",{tokensSpent5h:y.tokensSpent5h,tokensTotal:y.tokensTotal})});break;case"kimi":_=na(y=>{r("kimi","spent",{contextPct:y.contextPct,contextTokens:y.contextTokens,maxContextTokens:y.maxContextTokens,tokensSpent5h:y.tokensSpent5h})});break}_&&(Qr.add(O.key),In.push(()=>{_(),Qr.delete(O.key)}),O.key==="claude"&&Z&&a?.readyState===C.OPEN&&r("claude","quota",{prompts5h:Z.prompts5h,limit5h:Z.limit5h,resetAt:Z.resetAt,tier:Z.tier,estimate:!0}))}}let i=new un(n),a=null,c=null,l=null,d=0,u=0,p=0n,f=0,h=0,g=!1;function b(){c&&(clearTimeout(c),c=null),l&&(clearInterval(l),l=null),g=!1;let T=Date.now(),O=process.hrtime.bigint();a=new C(e.server,{headers:{Authorization:`Bearer ${e.token}`}});let _=a,y=(0,at.randomUUID)();Xr=y;let m=D.default.networkInterfaces(),w=Object.entries(m).flatMap(([N,W])=>(W||[]).filter(Y=>!Y.internal).map(Y=>({iface:N,address:Y.address,family:Y.family}))),S=JSON.stringify(w);console.log(JSON.stringify({ts:Date.now(),level:"info",event:"net.interfaces",interfaces:w,connectionId:y})),En&&En!==S&&console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"net.interfaces.changed",previous:En,current:S,connectionId:y})),En=S;let I=_.send.bind(_);_.send=function(N){if(_.readyState!==C.OPEN){let W="unknown";try{W=JSON.parse(N).type}catch{}console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.send.dropped",messageType:W,readyState:_.readyState,connectionId:y}));return}return I(N)},console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.connecting",server:e.server,connectionId:y}));let v=null,R=0,j=null,V=!1;_.on("open",()=>{g=!0,eo=!0,console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.connected",server:e.server,connectionId:y})),l=setInterval(()=>{_.readyState===C.OPEN&&(_.ping(),R=Date.now(),j&&clearTimeout(j),j=setTimeout(()=>{console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.heartbeat.timeout",connectionId:y})),_.terminate()},aa))},ia),t.setCurrentWs(_);let N=!ns();_.send(JSON.stringify({type:"ready",version:"1.1",npmVersion:"0.13.4",installModel:process.pkg!==void 0?"pkg":"npm",name:e.name,spawnHelperBroken:N,liveAgentIds:t.getLiveAgentIds(),machineFingerprint:to(),connectionId:y,claudeTier:Pt()})),i.updateWs(_),Promise.all([Xn(e.agentPaths),Er()]).then(([W,Y])=>{Mt=Y?[...W,Y]:W,s(W),_.readyState===C.OPEN&&_.send(JSON.stringify({type:"agents",list:Mt}))}),v=sa(W=>{_.readyState===C.OPEN&&_.send(JSON.stringify({type:"system_metrics",daemonId:n,...W}))})}),_.on("message",N=>{let W;try{W=JSON.parse(N.toString())}catch{console.warn("[daemon] Invalid JSON from server, ignoring");return}Zd(W,_,t,e,i)}),_.on("pong",()=>{j&&(clearTimeout(j),j=null);let N=Date.now()-R;console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.heartbeat.pong",rttMs:N,connectionId:y})),V||(V=!0,u=0,p=0n,f=0,h=0)}),_.on("close",(N,W)=>{eo=!1,l&&(clearInterval(l),l=null),j&&(clearTimeout(j),j=null),v?.(),v=null,i.stopAll(),N===1008?(d++,d>=2&&(console.error("[daemon] ws.auth_failed \u2014 token invalid or expired (2 consecutive rejections), stopping. Re-run: bridge-agent auth"),E(),setTimeout(()=>process.exit(1),2e3)),console.warn("[daemon] ws.auth_rejected \u2014 transient 1008, will retry once",{attempt:d})):d=0;let Y=Number((process.hrtime.bigint()-O)/1000000n);if(console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.closed",code:N,reason:W?.toString()||void 0,uptimeMs:Y,connectionId:y})),c)return;if(g&&!V&&Y<ia+aa+5e3&&N!==1008&&N!==4002&&(f++,console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.reconnect.zombie",zombieStreak:f,uptimeMs:Y,connectionId:y}))),N===4002){console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.duplicate_daemon_detected",code:N,connectionId:y})),f=0,h=0,u=0,p=0n,c&&(clearTimeout(c),c=null);let ut=12e4+Math.random()*18e4;console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.duplicate_daemon_backoff",delayMs:Math.round(ut),connectionId:y})),c=setTimeout(b,ut);return}if(f>=3){if(h++,console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.zombie.escalate",zombieStreak:f,escalationCount:h,connectionId:y})),h>=3){let ut=process.env.BRIDGE_SUPERVISED==="1";console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.zombie.fatal",escalationCount:h,zombieStreak:f,connectionId:y,supervised:ut})),ut&&(E(),setTimeout(()=>process.exit(1),2e3)),console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.reconnect.zombie.non_fatal",message:"manual daemon \u2014 staying alive, backoff retry",escalationCount:h,connectionId:y})),f=0}f=0,_?.close?.(),_?.removeAllListeners?.(),l&&(clearInterval(l),l=null),j&&(clearTimeout(j),j=null),c&&(clearTimeout(c),c=null),c=setTimeout(b,1e4);return}u===0&&(p=process.hrtime.bigint()),u++;let Pe=Number((process.hrtime.bigint()-p)/1000000n);u>=10&&Pe<6e4&&(console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.reconnect.storm",reconnectCount:u,connectionId:y})),E(),setTimeout(()=>process.exit(1),2e3));let Ft=Math.min(3e4,1e3*Math.pow(2,Math.min(u,5))),_o=Math.round(Ft+Math.random()*500);console.log(JSON.stringify({ts:Date.now(),level:"info",event:"ws.reconnect.scheduled",delayMs:_o,reconnectCount:u,connectionId:y})),c=setTimeout(b,_o)}),_.on("error",N=>{console.log(JSON.stringify({ts:Date.now(),level:"error",event:"ws.error",message:N.message,code:N.code,connectionId:y}))})}function E(){l&&(clearInterval(l),l=null),t.stopLivenessCheck(),Nd();for(let T of In)T();In.length=0;for(let T of Fe.values())T();i.stopAll(),t.killAll(),a?.close()}function x(T){console.log(JSON.stringify({ts:Date.now(),level:"warn",event:"ws.signal",signal:T,connectionId:Xr})),E(),setTimeout(()=>process.exit(0),100)}process.on("SIGINT",()=>x("SIGINT")),process.on("SIGTERM",()=>x("SIGTERM")),process.on("SIGHUP",()=>x("SIGHUP")),process.on("uncaughtException",T=>{console.log(JSON.stringify({ts:Date.now(),level:"error",event:"daemon.uncaught",error:String(T),stack:T.stack,connectionId:Xr}));try{E()}catch{}setTimeout(()=>process.exit(1),2e3)}),b()}function Zd(t,e,n,r,o){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"){o.start(t.agentId);return}let s=Mt.find(m=>m.key===t.agentKey);if(!s){e.readyState===C.OPEN&&e.send(JSON.stringify({type:"error",code:"AGENT_NOT_FOUND",message:`Agent '${t.agentKey}' is not installed on this machine`}));return}let i=Ae.find(m=>m.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"&&(Fe.get(t.agentId)?.(),Fe.set(t.agentId,Ur(t.agentId,t.sessionId,(m,w,S)=>{let I=n.getCurrentWs();I?.readyState===C.OPEN&&I.send(JSON.stringify({type:"panel_token_usage",agentId:m,usedPct:w,usedTokens:S}))})));else if(i?.assignSessionId){let m=crypto.randomUUID(),w=t.agentKey==="kimi"?"--session":t.agentKey==="forge"?"--conversation-id":"--session-id";a=[...i.spawnArgs??[],w,m],e.readyState===C.OPEN&&(e.send(JSON.stringify({type:"session_started",agentId:t.agentId,sessionId:m})),console.log("[daemon] session.assigned",{agentId:t.agentId,sessionId:m})),t.agentKey==="claude"&&(Fe.get(t.agentId)?.(),Fe.set(t.agentId,Ur(t.agentId,m,(S,I,v)=>{let R=n.getCurrentWs();R?.readyState===C.OPEN&&R.send(JSON.stringify({type:"panel_token_usage",agentId:S,usedPct:I,usedTokens:v}))})))}else a=[...i?.spawnArgs??[]],e.readyState===C.OPEN&&e.send(JSON.stringify({type:"session_started",agentId:t.agentId,sessionId:crypto.randomUUID()}));let c,l=!1,d,u;if(t.workspaceId){let m=Bd(r.server),w=Kd(t.projectId??"",t.cwd,t.daemonLocalPath,r.projectPaths),S=w.path;if(u=w.source,u==="fallback_home"&&t.sessionId){let v=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:v}),e.readyState===C.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 I=Mr(S);if(c={serverUrl:m,token:r.token,workspaceId:di(t.workspaceId),projectId:t.projectId?ui(t.projectId):void 0,agentId:t.agentId?li(t.agentId):void 0,personaId:t.personaId,cwd:S,projectEnv:I.env},t.agentKey==="claude"){let v=$d(c);l=v.length>0,d=process.env.BRIDGE_MCP_URL?"http":"stdio",a=[...a,...v]}else if(t.agentKey==="codex"){let v=qd(c);l=v.length>0,d="stdio",a=[...a,...v]}else if(t.agentKey==="qwen")l=Xd(c),d=l?"stdio":void 0;else if(t.agentKey==="kimi"){let v=Hd(c);l=v.length>0,d=process.env.BRIDGE_MCP_URL?"http":"stdio",a=[...a,...v]}else t.agentKey==="forge"?(l=Jd(c),d=l?"stdio":void 0):t.agentKey==="opencode"?(l=zd(c),d=l?process.env.BRIDGE_MCP_URL?"http":"stdio":void 0):t.agentKey==="gemini"?(l=Qd(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(kr("phase2a.verified_at")&&(w.source==="daemon_override"||w.source==="server_project")){let v=`${m}/api/workspaces/${t.workspaceId}/projects/${t.projectId}/machine-paths/${t.daemonId}/verify`;fetch(v,{method:"PATCH",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:"{}"}).catch(R=>{console.warn("[daemon] verify.patch_failed",{projectId:t.projectId,error:String(R)})})}if(kr("phase2a.auto_register")&&(w.source==="daemon_override"||w.source==="server_project"))try{let v=(0,it.spawnSync)("git",["remote","get-url","origin"],{cwd:S,timeout:5e3,encoding:"utf-8"});if(v.status===0&&v.stdout&&v.stdout.trim()){let R=v.stdout.trim();t.projectId&&(r.projectPaths||(r.projectPaths={}),r.projectPaths[t.projectId]=S,pe({projectPaths:r.projectPaths}));let j=`${m}/api/workspaces/${t.workspaceId}/projects/${t.projectId}/machine-paths`;fetch(j,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:JSON.stringify({daemonId:t.daemonId,localPath:S,repoUrl:R})}).catch(V=>{console.warn("[daemon] auto_register.post_failed",{projectId:t.projectId,error:String(V)})}),console.log("[daemon] auto_register.ok",{projectId:t.projectId,localPath:S,repoUrl:R})}}catch(v){console.log("[daemon] auto_register.skipped",{projectId:t.projectId,reason:String(v)})}}let p=Fd(t.role,t.systemPrompt,t.agentId,t.workspaceId,t.projectId,t.groupId),f=Wd(t.agentKey,p,t.agentId);f.length>0&&(a=[...a,...f]);let h=Gd(t.agentKey,t.systemPrompt,t.agentId);h.length>0&&(a=[...a,...h]);let g=Math.max(1,Math.min(500,t.cols)),b=Math.max(1,Math.min(500,t.rows)),E=Date.now(),x="",T=0,O=!1,_=!1;if(n.spawn(t.agentId,t.agentKey,s.binaryPath,a,g,b,m=>{if(T+=m.length,t.agentKey==="gemini")try{let S=Buffer.from(m,"base64").toString("utf-8");if(S.includes("shell mode enabled"))$e.get(t.agentId)||($e.set(t.agentId,!0),console.log("[daemon] gemini.shell_mode.entered",{agentId:t.agentId.slice(-8)}));else if(S.includes("Type your message")&&($e.get(t.agentId)&&($e.set(t.agentId,!1),console.log("[daemon] gemini.shell_mode.exited",{agentId:t.agentId.slice(-8)})),!st.get(t.agentId))){st.set(t.agentId,!0);let I=Ue.get(t.agentId)??[];Ue.delete(t.agentId),console.log("[daemon] gemini.ready",{agentId:t.agentId.slice(-8),flushing:I.length}),I.length>0&&setTimeout(()=>{for(let v of I)n.write(t.agentId,v,"orchestrator");setTimeout(()=>{n.write(t.agentId,Buffer.from("\r").toString("base64"),"orchestrator")},1e3)},500)}}catch{}try{let S=Buffer.from(m,"base64").toString("utf-8");if(t.agentKey==="kimi"&&t.role&&!_&&Date.now()-E<3e4&&(/yolo agent/.test(S)||/●/.test(S)||/○/.test(S))){_=!0;let I=p;if(I){let v=Rd(I),R=Buffer.from(v).toString("base64");n.write(t.agentId,R,"orchestrator"),console.log("[daemon] kimi.role.injected",{agentId:t.agentId,role:t.role})}}}catch{}if(!x)try{let S=Buffer.from(m,"base64").toString("utf-8"),I=Ld(S).replace(/\x00/g,"").trim();if(I&&(x=Md(I)),t.agentKey==="codex"&&!O&&Date.now()-E<2e4&&/included in your plan for free|let[’']s build together/i.test(I)&&/yes|no|\[y\/n\]|\(y\/n\)|y\/n/i.test(I)){O=!0;let v=Buffer.from("y").toString("base64");n.write(t.agentId,v,"orchestrator"),console.log("[daemon] codex.onboarding.auto_ack",{agentId:t.agentId})}}catch{}let w=n.getCurrentWs();if(w?.readyState===C.OPEN)if(w.bufferedAmount>ca){let S=Date.now(),I=xn.get(t.agentId);(!I||S-I>=1e3)&&(xn.set(t.agentId,S),console.log(JSON.stringify({ts:S,level:"warn",event:"pty.backpressure.drop",agentId:t.agentId,bufferedAmount:w.bufferedAmount,threshold:ca})))}else w.send(JSON.stringify({type:"output",agentId:t.agentId,data:m}));Pd(t.agentId,()=>n.getCurrentWs())},(m,w)=>{let S=Date.now()-E,I=S<=Dd;console.log("[daemon] pty.spawn.result",{agentId:t.agentId,agentKey:t.agentKey,daemonId:t.daemonId,exitCode:m,signal:w,uptimeMs:S,earlyExit:I,outputBytes:T,firstOutputSnippet:x||void 0});let v=n.getCurrentWs();if(I&&v?.readyState===C.OPEN&&v.send(JSON.stringify({type:"error",code:"SPAWN_FAILED",message:`Early exit: agent=${t.agentKey} code=${m??"null"} signal=${w??"null"} snippet="${x||"no output"}"`})),v?.readyState===C.OPEN&&v.send(JSON.stringify({type:"exit",agentId:t.agentId,exitCode:m,signal:w})),Cd(t.agentId),$e.delete(t.agentId),st.delete(t.agentId),Ue.delete(t.agentId),xn.delete(t.agentId),Promise.all([(0,jt.unlink)(P.default.join(D.default.tmpdir(),`bridge-persona-${t.agentId}.md`)),(0,jt.unlink)(P.default.join(D.default.tmpdir(),`bridge-role-${t.agentId}.md`)),(0,jt.unlink)(P.default.join(D.default.tmpdir(),`bridge-mcp-${t.agentId}.json`)),(0,jt.unlink)(P.default.join(D.default.tmpdir(),`bridge-mcp-kimi-${t.agentId}.json`))].map(R=>R.catch(()=>{}))).catch(()=>{}),t.agentKey==="opencode"){let R=P.default.join(D.default.homedir(),".config","opencode","opencode.json");try{let j=A.default.readFileSync(R,"utf-8"),V=JSON.parse(j);V?.mcp?.bridge&&(delete V.mcp.bridge,A.default.writeFileSync(R,JSON.stringify(V,null,2)+`
|
|
422
422
|
`,{encoding:"utf-8",mode:384}))}catch{}}if(t.agentKey==="gemini"){let R=c?.cwd;if(R){let j=P.default.join(R,".gemini","settings.json");try{let V=A.default.readFileSync(j,"utf-8"),N=JSON.parse(V);N?.mcpServers?.bridge&&(delete N.mcpServers.bridge,A.default.writeFileSync(j,JSON.stringify(N,null,2)+`
|
|
423
423
|
`,{encoding:"utf-8",mode:384}))}catch{}}}if(t.agentKey==="forge"){let R=c?.cwd;if(R){let j=P.default.join(R,".mcp.json");try{let V=A.default.readFileSync(j,"utf-8"),N=JSON.parse(V);N?.mcpServers?.bridge&&(delete N.mcpServers.bridge,A.default.writeFileSync(j,JSON.stringify(N,null,2)+`
|
|
424
424
|
`,{encoding:"utf-8",mode:384}))}catch{}}}if(t.agentKey==="qwen"){let R=c?.cwd;if(R){let V=P.default.resolve(R)===P.default.resolve(D.default.homedir())?P.default.join(D.default.homedir(),".qwen"):P.default.join(R,".qwen"),N=P.default.join(V,"settings.json");try{let W=A.default.readFileSync(N,"utf-8"),Y=JSON.parse(W);Y?.mcpServers?.bridge&&(delete Y.mcpServers.bridge,A.default.writeFileSync(N,JSON.stringify(Y,null,2)+`
|
|
@@ -471,7 +471,7 @@ ${c} </dict>
|
|
|
471
471
|
`;try{return(0,U.writeFileSync)(n,f,"utf-8"),!0}catch(h){return console.warn("[bridge] launchd.plist.write.failed",{error:String(h)}),!1}}function ma(){let t=le(),e=Q.default.join(no,t);try{return(0,Oe.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(n){let r=String(n);return{ok:!1,permissionDenied:r.includes("Permission denied")||r.includes("not allowed")||r.includes("bootstrap")}}}function tu(t){let{out:e,err:n}=Et();try{let r=(0,Oe.spawn)(t,["start"],{detached:!0,stdio:"ignore",env:{...process.env,PATH:ga(),BRIDGE_DAEMON:"1"}});r.unref(),setTimeout(()=>{r.pid&&process.kill(r.pid,0)?(console.log("[bridge] daemon.pid",{pid:r.pid}),console.log("[bridge] background.ok",{log:e})):console.error("[bridge] background.failed \u2014 check: tail -f",{log:n})},2e3)}catch(r){console.error("[bridge] background.spawn.failed",{error:String(r)})}}function _a(){let t=It(),e=Date.now()+6e3,n=()=>{if(Date.now()>e){console.error("[bridge] health.verify.timeout \u2014 daemon may have crashed immediately");return}try{let o=require("node:http").get(`http://127.0.0.1:${t}/health`,s=>{s.statusCode===200?console.log("[bridge] health.verify.ok"):setTimeout(n,500)});o.on("error",()=>{setTimeout(n,500)}),o.setTimeout(1e3,()=>{o.destroy(),setTimeout(n,500)})}catch{setTimeout(n,500)}};setTimeout(n,1e3)}function nu(){if(process.pkg!==void 0)try{let t=Q.default.join((0,Ge.homedir)(),".bridge","bin");(0,U.mkdirSync)(t,{recursive:!0});let e=Q.default.join(t,"bridge-mcp");(0,U.writeFileSync)(e,`#!/bin/sh
|
|
472
472
|
exec "${process.execPath}" bridge-mcp "$@"
|
|
473
473
|
`,{mode:493}),console.log("[daemon] mcp.wrapper.written",{path:e})}catch(t){console.warn("[daemon] mcp.wrapper.write.failed",{error:String(t)})}}function ru(){try{let t=(0,Oe.execSync)("ps -axo pid=,ppid=,command=",{encoding:"utf8",maxBuffer:8388608}),e=0;for(let n of t.split(`
|
|
474
|
-
`)){let r=n.match(/^\s*(\d+)\s+(\d+)\s+(.*)$/);if(!r)continue;let[,o,s,i]=r;if(s!=="1"||!/bridge-(mcp|role-panel|persona-panel)-/.test(i))continue;let a=parseInt(o,10);if(a!==process.pid)try{process.kill(a,"SIGTERM"),e++,console.log("[daemon] pty.orphan.reaped",{pid:a,cmd:i.slice(0,120)})}catch{}}e>0&&console.log("[daemon] pty.orphans.done",{count:e})}catch(t){console.warn("[daemon] pty.orphans.scan_failed",{error:String(t)})}}function ou(){os(),nu(),ha(),ru();let t=new qt;On=t,ua(t),t.startLivenessCheck(6e4);let e=It(),n=(0,pa.createServer)((r,o)=>{let s=da(),i=JSON.stringify({status:"ok",connected:s,uptime:process.uptime(),version:"0.13.
|
|
474
|
+
`)){let r=n.match(/^\s*(\d+)\s+(\d+)\s+(.*)$/);if(!r)continue;let[,o,s,i]=r;if(s!=="1"||!/bridge-(mcp|role-panel|persona-panel)-/.test(i))continue;let a=parseInt(o,10);if(a!==process.pid)try{process.kill(a,"SIGTERM"),e++,console.log("[daemon] pty.orphan.reaped",{pid:a,cmd:i.slice(0,120)})}catch{}}e>0&&console.log("[daemon] pty.orphans.done",{count:e})}catch(t){console.warn("[daemon] pty.orphans.scan_failed",{error:String(t)})}}function ou(){os(),nu(),ha(),ru();let t=new qt;On=t,ua(t),t.startLivenessCheck(6e4);let e=It(),n=(0,pa.createServer)((r,o)=>{let s=da(),i=JSON.stringify({status:"ok",connected:s,uptime:process.uptime(),version:"0.13.4",activePanels:On?.getLiveAgentIds().length??0,agentIds:On?.getLiveAgentIds()??[]});o.writeHead(s?200:503,{"Content-Type":"application/json"}),o.end(i)});n.listen(e,"127.0.0.1",()=>{console.log(`[bridge] health. listening on 127.0.0.1:${e}`)}),n.on("error",r=>{console.error("[bridge] health.error",{error:r.message})})}function ya(){let t=process.env.BRIDGE_DAEMON==="1"||process.argv.includes("--daemon");if(!t&&!process.env.BRIDGE_PROFILE){let r=process.argv[1]??"";(r.includes("packages/daemon/dist")||r.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){ou();return}let e=eu();if(!e.ok){let r=e.err,o=Me();r.code==="EEXIST"?console.warn("[bridge] start.aborted.already.running"):r.code==="EACCES"||r.code==="EPERM"?console.warn(`[bridge] start.aborted.permission_denied \u2014 cannot write ${o} (${r.code}). Directory may be owned by root from \`sudo npm install\`. Try: sudo chown -R "$(whoami):staff" ~/.bridge`):r.code==="ENOENT"?console.warn(`[bridge] start.aborted.lock_dir_missing \u2014 ${o}`):console.warn(`[bridge] start.aborted.lock_error \u2014 ${r.code}: ${r.message}`),process.exit(1)}console.log("[bridge] start.no_persist \u2014 starting without launchd service registration");let n=He();tu(n),process.exit(0)}var wa=k(require("https")),Sa=k(require("http")),Tn=require("node:fs");Be();de();gn();var su="https://lcars.jerico.appnova.io";function iu(t){return(t??"").trim()}var ba=`
|
|
475
475
|
jerico daemon \u2014 capability & data-access disclosure
|
|
476
476
|
|
|
477
477
|
This daemon accepts the following commands from the jerico server
|
|
@@ -499,4 +499,4 @@ You can remove this daemon at any time: bridge-agent uninstall
|
|
|
499
499
|
`),process.exit(o.errors.length>0?1:0)}async function fu(){return new Promise(t=>{process.stdout.write(`This will stop the daemon, remove the login service, delete the auth token,
|
|
500
500
|
config, logs, and wrapper script. This cannot be undone.
|
|
501
501
|
Type "yes" to continue: `);let e="";process.stdin.setEncoding("utf-8"),process.stdin.resume(),process.stdin.on("data",n=>{e+=n,e.includes(`
|
|
502
|
-
`)&&(process.stdin.pause(),t(e.trim().toLowerCase()==="yes"))})})}var co=k(require("path")),Ra=require("node:os");de();var hu=co.default.join((0,Ra.homedir)(),"Library","LaunchAgents");function Na(){console.log("[bridge] service.install.start");let t=He(),e=le(),n=co.default.join(hu,e);if(!Bt(t)){let i=`Failed to write plist at ${n}`;return console.error("[bridge] service.install.plist_write.failed",{path:n}),{ok:!1,reason:"plist_write",message:i}}console.log("[bridge] service.install.plist_write.ok",{path:n});let{ok:o,permissionDenied:s}=ma();if(!o){if(s)return console.error("[bridge] service.install.launchctl.permission_denied"),{ok:!1,reason:"permission_denied",message:`Permission denied. Manual: sudo launchctl bootstrap gui/$(id -u) "${n}"`};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"),_a(),{ok:!0}}var ct=require("node:child_process"),F=require("node:fs"),po=require("node:os"),Ma=k(require("node:http")),dt=k(require("path"));de();Be();var Da=require("node:child_process");function gu(t,e){let n=t.split("."),r=e.split(".");for(let o=0;o<3;o++){let s=parseInt(n[o]??"0",10),i=parseInt(r[o]??"0",10);if(isNaN(s)||isNaN(i))break;if(s!==i)return s-i}return t.localeCompare(e)}function lo(t,e){return gu(t,e)>0}function uo(t="latest"){let n=["latest","beta","next","canary"].includes(t)?t:"latest";try{let o=(0,Da.execSync)(`npm view bridge-agent@${n} version`,{timeout:5e3,stdio:"pipe"}).toString().trim();return/^\d+\.\d+\.\d+/.test(o)?o:null}catch{return null}}function ja(t="latest",e){let n=uo(t);return n?lo(e,n)?{updateAvailable:!1,currentVersion:e,latestVersion:n,reason:"ahead_of_channel"}:e===n?{updateAvailable:!1,currentVersion:e,latestVersion:n,reason:"up_to_date"}:{updateAvailable:!0,latestVersion:n,currentVersion:e}:{updateAvailable:!1,currentVersion:e,reason:"registry_unreachable"}}var Cn=dt.default.join((0,po.homedir)(),".bridge"),lt=dt.default.join(Cn,"update.lock"),mu=dt.default.join(Cn,"update-state.json"),_u=dt.default.join((0,po.homedir)(),"Library","LaunchAgents");function yu(){if((0,F.existsSync)(lt))try{let{pid:t}=JSON.parse((0,F.readFileSync)(lt,"utf8"));if(t&&process.kill(t,0))return;(0,F.unlinkSync)(lt)}catch{try{(0,F.unlinkSync)(lt)}catch{}}}function bu(){try{(0,F.mkdirSync)(Cn,{recursive:!0})}catch{}yu();try{let t=(0,F.openSync)(lt,"wx");return(0,F.writeSync)(t,JSON.stringify({pid:process.pid,startedAt:Date.now()})),(0,F.closeSync)(t),{ok:!0}}catch(t){return{ok:!1,err:t}}}function Te(){try{(0,F.unlinkSync)(lt)}catch{}}function wu(t){try{(0,F.mkdirSync)(Cn,{recursive:!0})}catch{}(0,F.writeFileSync)(mu,JSON.stringify(t,null,2),{mode:384})}function La(t,e=3e4){let n=It(),r=Date.now()+e;return new Promise(o=>{let s=()=>{if(Date.now()>r){o(!1);return}try{let i=Ma.default.get(`http://127.0.0.1:${n}/health`,a=>{let c="";a.on("data",l=>{c+=l}),a.on("end",()=>{try{if(JSON.parse(c).version===t){o(!0);return}}catch{}setTimeout(s,500)})});i.on("error",()=>{setTimeout(s,500)}),i.setTimeout(1e3,()=>{i.destroy(),setTimeout(s,500)})}catch{setTimeout(s,500)}};setTimeout(s,1e3)})}var Su=new Set(["latest","stable","beta","alpha","next","canary"]);async function Ba(t){let e="0.13.3",n=ve(),r=t.channel??n.updateChannel??"latest",o=Su.has(r)?r:"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=He();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 E=ja(o,e);E.updateAvailable&&(console.log(`[bridge] update.available: ${e} \u2192 ${E.latestVersion} (channel: ${o})`),process.exit(10));let x=E.reason??"unknown";console.log(`[bridge] update.unavailable: ${e} (channel: ${o}, reason: ${x})`),process.exit(0)}let i=uo(o);i||(console.error("[bridge] update.failed: cannot reach npm registry"),process.exit(1)),e===i&&(console.log(`[bridge] update.up_to_date: ${e} (channel: ${o})`),t.saveChannel&&(pe({updateChannel:o}),console.log(`[bridge] update.channel.saved: ${o}`)),process.exit(0)),lo(e,i)&&(console.log(`[bridge] update.ahead: ${e} > ${i} (channel: ${o}).`),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 ${i} (channel: ${o})`);let a=fa()?.getLiveAgentIds().length??0;a>0&&!t.force&&(console.error(`[bridge] update.blocked: ${a} 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)),a>0&&t.force&&console.log(`[bridge] update.force: ${a} active panel(s) will be terminated during update.`),t.saveChannel&&(pe({updateChannel:o}),console.log(`[bridge] update.channel.saved: ${o}`));let c=bu();if(!c.ok){let E=c.err;E.code==="EEXIST"?console.error("[bridge] update.aborted: another update is already in progress (update.lock exists)"):console.error(`[bridge] update.lock.failed: ${E.code} \u2014 ${E.message}`),process.exit(1)}console.log(`[bridge] update.installing: bridge-agent@${o}...`);let l=!1;try{(0,ct.execSync)(`npm install -g bridge-agent@${o}`,{stdio:"inherit",timeout:12e4}),l=!0}catch(E){console.error(`[bridge] update.install.failed: ${String(E)}`),l=!1}if(!l){console.error(`[bridge] update.install.failed: rolling back to bridge-agent@${e}...`);try{(0,ct.execSync)(`npm install -g bridge-agent@${e}`,{stdio:"inherit",timeout:12e4}),console.log("[bridge] update.install.rollback.ok \u2014 restored previous version")}catch(E){Te(),console.error(`[bridge] update.install.rollback.FAILED: ${String(E)}`),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)}Te(),console.error("[bridge] update.aborted: npm install failed, daemon is on previous version."),process.exit(1)}let d=le(),u=d.replace(".plist",""),p=dt.default.join(_u,d),f=He();if((0,F.existsSync)(p)?Bt(f)||(Te(),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,F.existsSync)(p))try{(0,ct.execSync)(`launchctl kickstart -kp gui/$(id -u)/${u}`,{stdio:"pipe"}),console.log("[bridge] update.kickstart.ok \u2014 daemon restarting with new version")}catch{Te(),console.error("[bridge] update.failed: launchctl kickstart failed"),console.error(`[bridge] Manual restart: launchctl kickstart -kp gui/$(id -u)/${u}`),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 ${i}...`),await La(i,3e4)&&(wu({previousVersion:e,channel:o,installedAt:new Date().toISOString()}),Te(),console.log(`[bridge] update.complete: ${e} \u2192 ${i}`),process.exit(0)),console.error(`[bridge] update.health.timeout: daemon did not report version ${i} within 30s`),console.error(`[bridge] update.rolling_back: reinstalling bridge-agent@${e}...`);try{(0,ct.execSync)(`npm install -g bridge-agent@${e}`,{stdio:"inherit",timeout:12e4}),console.log("[bridge] update.rollback.install.ok")}catch(E){Te(),console.error(`[bridge] update.rollback.install.FAILED: ${String(E)}`),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 g=He();if((0,F.existsSync)(p))try{Bt(g),(0,ct.execSync)(`launchctl kickstart -kp gui/$(id -u)/${u}`,{stdio:"pipe"}),console.log("[bridge] update.rollback.kickstart.ok")}catch{Te(),console.error("[bridge] update.rollback.kickstart.failed \u2014 daemon may need manual restart"),console.error(`[bridge] Run: launchctl kickstart -kp gui/$(id -u)/${u}`),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 b=await La(e,3e4);Te(),b&&(console.log(`[bridge] update.rollback.complete: restored to ${e}`),console.log(`[bridge] Update to ${i} 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 ho=k(require("node:fs")),go=k(require("node:os")),mo=k(require("node:path")),te=new Ao;te.name("bridge-agent").description("Bridge local agent \u2014 connects your AI tools to Jerico").version("0.13.3").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)});te.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),ya()});te.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=>{ka(t.server,!t.browser,t.token)});te.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,n)=>{xa(t,e,n)});te.command("cleanup-orphans").description("Remove orphaned daemon_project_paths rows for this user").action(()=>{Oa()});te.command("status").description("Show connection status").action(async()=>{try{let{loadConfig:t}=await Promise.resolve().then(()=>(Be(),Li)),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")}});te.command("stop").description("Stop the bridge-agent daemon").action(()=>{Pa()});te.command("install-service").description("Install bridge-agent as a persistent login service (launchd plist with RunAtLoad+KeepAlive)").action(()=>{let t=Na();t.ok||(console.error(`[bridge] install-service.failed: ${t.message}`),process.exit(1)),process.exit(0)});te.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=>{Aa(t)});te.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=>{Ba(t)});te.command("probe-fda").description("Probe ~/Documents to trigger macOS FDA auto-list entry (one-shot, exits 0 always)").action(()=>{try{ho.readdirSync(mo.join(go.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)});te.command("check-fda").description("Check ~/Documents readability (exit 0 = FDA granted, exit 1 = denied)").action(()=>{try{ho.readdirSync(mo.join(go.homedir(),"Documents")),console.log("[bridge] check-fda: granted"),process.exit(0)}catch{console.log("[bridge] check-fda: denied"),process.exit(1)}});te.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 fo=process.argv[2]??"",ku=fo.startsWith("/")&&(fo.endsWith(".js")||fo.endsWith(".cjs"))?process.argv.slice(1):process.argv;te.parse(ku);
|
|
502
|
+
`)&&(process.stdin.pause(),t(e.trim().toLowerCase()==="yes"))})})}var co=k(require("path")),Ra=require("node:os");de();var hu=co.default.join((0,Ra.homedir)(),"Library","LaunchAgents");function Na(){console.log("[bridge] service.install.start");let t=He(),e=le(),n=co.default.join(hu,e);if(!Bt(t)){let i=`Failed to write plist at ${n}`;return console.error("[bridge] service.install.plist_write.failed",{path:n}),{ok:!1,reason:"plist_write",message:i}}console.log("[bridge] service.install.plist_write.ok",{path:n});let{ok:o,permissionDenied:s}=ma();if(!o){if(s)return console.error("[bridge] service.install.launchctl.permission_denied"),{ok:!1,reason:"permission_denied",message:`Permission denied. Manual: sudo launchctl bootstrap gui/$(id -u) "${n}"`};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"),_a(),{ok:!0}}var ct=require("node:child_process"),F=require("node:fs"),po=require("node:os"),Ma=k(require("node:http")),dt=k(require("path"));de();Be();var Da=require("node:child_process");function gu(t,e){let n=t.split("."),r=e.split(".");for(let o=0;o<3;o++){let s=parseInt(n[o]??"0",10),i=parseInt(r[o]??"0",10);if(isNaN(s)||isNaN(i))break;if(s!==i)return s-i}return t.localeCompare(e)}function lo(t,e){return gu(t,e)>0}function uo(t="latest"){let n=["latest","beta","next","canary"].includes(t)?t:"latest";try{let o=(0,Da.execSync)(`npm view bridge-agent@${n} version`,{timeout:5e3,stdio:"pipe"}).toString().trim();return/^\d+\.\d+\.\d+/.test(o)?o:null}catch{return null}}function ja(t="latest",e){let n=uo(t);return n?lo(e,n)?{updateAvailable:!1,currentVersion:e,latestVersion:n,reason:"ahead_of_channel"}:e===n?{updateAvailable:!1,currentVersion:e,latestVersion:n,reason:"up_to_date"}:{updateAvailable:!0,latestVersion:n,currentVersion:e}:{updateAvailable:!1,currentVersion:e,reason:"registry_unreachable"}}var Cn=dt.default.join((0,po.homedir)(),".bridge"),lt=dt.default.join(Cn,"update.lock"),mu=dt.default.join(Cn,"update-state.json"),_u=dt.default.join((0,po.homedir)(),"Library","LaunchAgents");function yu(){if((0,F.existsSync)(lt))try{let{pid:t}=JSON.parse((0,F.readFileSync)(lt,"utf8"));if(t&&process.kill(t,0))return;(0,F.unlinkSync)(lt)}catch{try{(0,F.unlinkSync)(lt)}catch{}}}function bu(){try{(0,F.mkdirSync)(Cn,{recursive:!0})}catch{}yu();try{let t=(0,F.openSync)(lt,"wx");return(0,F.writeSync)(t,JSON.stringify({pid:process.pid,startedAt:Date.now()})),(0,F.closeSync)(t),{ok:!0}}catch(t){return{ok:!1,err:t}}}function Te(){try{(0,F.unlinkSync)(lt)}catch{}}function wu(t){try{(0,F.mkdirSync)(Cn,{recursive:!0})}catch{}(0,F.writeFileSync)(mu,JSON.stringify(t,null,2),{mode:384})}function La(t,e=3e4){let n=It(),r=Date.now()+e;return new Promise(o=>{let s=()=>{if(Date.now()>r){o(!1);return}try{let i=Ma.default.get(`http://127.0.0.1:${n}/health`,a=>{let c="";a.on("data",l=>{c+=l}),a.on("end",()=>{try{if(JSON.parse(c).version===t){o(!0);return}}catch{}setTimeout(s,500)})});i.on("error",()=>{setTimeout(s,500)}),i.setTimeout(1e3,()=>{i.destroy(),setTimeout(s,500)})}catch{setTimeout(s,500)}};setTimeout(s,1e3)})}var Su=new Set(["latest","stable","beta","alpha","next","canary"]);async function Ba(t){let e="0.13.4",n=ve(),r=t.channel??n.updateChannel??"latest",o=Su.has(r)?r:"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=He();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 E=ja(o,e);E.updateAvailable&&(console.log(`[bridge] update.available: ${e} \u2192 ${E.latestVersion} (channel: ${o})`),process.exit(10));let x=E.reason??"unknown";console.log(`[bridge] update.unavailable: ${e} (channel: ${o}, reason: ${x})`),process.exit(0)}let i=uo(o);i||(console.error("[bridge] update.failed: cannot reach npm registry"),process.exit(1)),e===i&&(console.log(`[bridge] update.up_to_date: ${e} (channel: ${o})`),t.saveChannel&&(pe({updateChannel:o}),console.log(`[bridge] update.channel.saved: ${o}`)),process.exit(0)),lo(e,i)&&(console.log(`[bridge] update.ahead: ${e} > ${i} (channel: ${o}).`),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 ${i} (channel: ${o})`);let a=fa()?.getLiveAgentIds().length??0;a>0&&!t.force&&(console.error(`[bridge] update.blocked: ${a} 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)),a>0&&t.force&&console.log(`[bridge] update.force: ${a} active panel(s) will be terminated during update.`),t.saveChannel&&(pe({updateChannel:o}),console.log(`[bridge] update.channel.saved: ${o}`));let c=bu();if(!c.ok){let E=c.err;E.code==="EEXIST"?console.error("[bridge] update.aborted: another update is already in progress (update.lock exists)"):console.error(`[bridge] update.lock.failed: ${E.code} \u2014 ${E.message}`),process.exit(1)}console.log(`[bridge] update.installing: bridge-agent@${o}...`);let l=!1;try{(0,ct.execSync)(`npm install -g bridge-agent@${o}`,{stdio:"inherit",timeout:12e4}),l=!0}catch(E){console.error(`[bridge] update.install.failed: ${String(E)}`),l=!1}if(!l){console.error(`[bridge] update.install.failed: rolling back to bridge-agent@${e}...`);try{(0,ct.execSync)(`npm install -g bridge-agent@${e}`,{stdio:"inherit",timeout:12e4}),console.log("[bridge] update.install.rollback.ok \u2014 restored previous version")}catch(E){Te(),console.error(`[bridge] update.install.rollback.FAILED: ${String(E)}`),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)}Te(),console.error("[bridge] update.aborted: npm install failed, daemon is on previous version."),process.exit(1)}let d=le(),u=d.replace(".plist",""),p=dt.default.join(_u,d),f=He();if((0,F.existsSync)(p)?Bt(f)||(Te(),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,F.existsSync)(p))try{(0,ct.execSync)(`launchctl kickstart -kp gui/$(id -u)/${u}`,{stdio:"pipe"}),console.log("[bridge] update.kickstart.ok \u2014 daemon restarting with new version")}catch{Te(),console.error("[bridge] update.failed: launchctl kickstart failed"),console.error(`[bridge] Manual restart: launchctl kickstart -kp gui/$(id -u)/${u}`),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 ${i}...`),await La(i,3e4)&&(wu({previousVersion:e,channel:o,installedAt:new Date().toISOString()}),Te(),console.log(`[bridge] update.complete: ${e} \u2192 ${i}`),process.exit(0)),console.error(`[bridge] update.health.timeout: daemon did not report version ${i} within 30s`),console.error(`[bridge] update.rolling_back: reinstalling bridge-agent@${e}...`);try{(0,ct.execSync)(`npm install -g bridge-agent@${e}`,{stdio:"inherit",timeout:12e4}),console.log("[bridge] update.rollback.install.ok")}catch(E){Te(),console.error(`[bridge] update.rollback.install.FAILED: ${String(E)}`),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 g=He();if((0,F.existsSync)(p))try{Bt(g),(0,ct.execSync)(`launchctl kickstart -kp gui/$(id -u)/${u}`,{stdio:"pipe"}),console.log("[bridge] update.rollback.kickstart.ok")}catch{Te(),console.error("[bridge] update.rollback.kickstart.failed \u2014 daemon may need manual restart"),console.error(`[bridge] Run: launchctl kickstart -kp gui/$(id -u)/${u}`),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 b=await La(e,3e4);Te(),b&&(console.log(`[bridge] update.rollback.complete: restored to ${e}`),console.log(`[bridge] Update to ${i} 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 ho=k(require("node:fs")),go=k(require("node:os")),mo=k(require("node:path")),te=new Ao;te.name("bridge-agent").description("Bridge local agent \u2014 connects your AI tools to Jerico").version("0.13.4").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)});te.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),ya()});te.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=>{ka(t.server,!t.browser,t.token)});te.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,n)=>{xa(t,e,n)});te.command("cleanup-orphans").description("Remove orphaned daemon_project_paths rows for this user").action(()=>{Oa()});te.command("status").description("Show connection status").action(async()=>{try{let{loadConfig:t}=await Promise.resolve().then(()=>(Be(),Li)),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")}});te.command("stop").description("Stop the bridge-agent daemon").action(()=>{Pa()});te.command("install-service").description("Install bridge-agent as a persistent login service (launchd plist with RunAtLoad+KeepAlive)").action(()=>{let t=Na();t.ok||(console.error(`[bridge] install-service.failed: ${t.message}`),process.exit(1)),process.exit(0)});te.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=>{Aa(t)});te.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=>{Ba(t)});te.command("probe-fda").description("Probe ~/Documents to trigger macOS FDA auto-list entry (one-shot, exits 0 always)").action(()=>{try{ho.readdirSync(mo.join(go.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)});te.command("check-fda").description("Check ~/Documents readability (exit 0 = FDA granted, exit 1 = denied)").action(()=>{try{ho.readdirSync(mo.join(go.homedir(),"Documents")),console.log("[bridge] check-fda: granted"),process.exit(0)}catch{console.log("[bridge] check-fda: denied"),process.exit(1)}});te.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 fo=process.argv[2]??"",ku=fo.startsWith("/")&&(fo.endsWith(".js")||fo.endsWith(".cjs"))?process.argv.slice(1):process.argv;te.parse(ku);
|