import{d as e,s as t,u as n}from"./envUtils-BWeoiL4Y.js";import{Cn as r,In as i,Ln as a,t as o}from"./src-Di342QoJ.js";import{M as s,Ms as c,Ns as l,Ps as u,S as d,l as f,z as p}from"./paths-Ci1iwL5Y.js";import{D as m,E as h,O as g,U as _,l as v,p as y,z as b}from"./debug-otxXY3j-.js";import{i as x,n as S,r as C}from"./analytics-DqMQntaB.js";import{F as w,P as T}from"./git-C0IuvuIy.js";import{o as E,s as D}from"./log-DSV4Ht5l.js";import{E as O,d as k,x as A}from"./startupProfiler-CAntGAbs.js";import{n as j,t as M}from"./sleep-C6koP5Ka.js";import{Fa as N,Hb as P,IE as F,Ia as I,Ib as L,LE as R,La as z,Lb as B,Na as V,Nt as H,Ot as U,Pa as W,Pb as G,Ra as ee,Rb as K,Ub as q,Vb as J,bt as te,zb as Y}from"./loadAgentsDir-C_wFhytF.js";import{n as ne,t as X}from"./rcDebugLog-C42A0pX1.js";import{c as re,d as ie,f as ae,n as oe,o as se,r as ce}from"./debugUtils-l8nsUZ6R.js";import{r as le,t as ue}from"./datadog-YsyhnDmr.js";import{a as Z,i as de}from"./trustedDevice-C5s2au0k.js";import{a as Q,t as fe}from"./types-C0nqJFkV.js";import{t as $}from"./lib-Cf16LgKj.js";import{i as pe,n as me,r as he}from"./cliLaunch-Citfs01Q.js";import{t as ge}from"./capacityWake-DtmDHwEt.js";import{t as _e}from"./jwtUtils-BQXXBwqW.js";import{t as ve}from"./pollConfig-_2W7bHoW.js";import{a as ye,i as be,n as xe,r as Se,t as Ce}from"./workSecret-DJu7k30X.js";import{hostname as we,tmpdir as Te}from"os";import{basename as Ee,dirname as De,join as Oe,resolve as ke}from"path";import{createWriteStream as Ae}from"fs";import{randomUUID as je}from"crypto";import{spawn as Me}from"child_process";import{createInterface as Ne}from"readline";t(),S(),_(),h(),T(),E(),A(),M(),s(),d(),R(),ue(),se(),X(),Q(),N(),U(),pe(),a();var Pe=$();u(),o(),v(),J();var Fe={type:`utf8`,errorCorrectionLevel:`L`,small:!0};async function Ie(e){return(await(0,Pe.toString)(e,Fe)).split(`
`).filter(e=>e.length>0)}function Le(e){let t=e.write??(e=>process.stdout.write(e)),n=e.verbose,a=0,o=`idle`,s=`Ready`,u=``,d=``,f=``,p=``,m=``,h=``,g=null,_=[],v=!1,b=null,x=0,S=0,C=1,w=null,T=`single-session`,E=new Map,D=null,A=0;function j(e){let t=process.stdout.columns||80,n=0;for(let i of e.split(`
`)){if(i.length===0){n++;continue}let e=r(i);n+=Math.max(1,Math.ceil(e/t))}return e.endsWith(`
`)&&n--,n}function M(e){t(e),a+=j(e)}function N(){a<=0||(y(`[bridge:ui] clearStatusLines count=${a}`),t(`\x1b[${a}A`),t(`\x1B[J`),a=0)}function F(e){N(),t(e)}function I(e){Ie(e).then(e=>{_=e,H()}).catch(e=>{y(`QR code generation failed: ${e}`,{level:`error`})})}function R(){N();let e=l[A%l.length],t=``;u&&(t+=i.dim(` · `)+i.dim(u)),d&&(t+=i.dim(` · `)+i.dim(d)),M(`${i.yellow(e)} ${i.yellow(`Connecting`)}${t}\n`)}function z(){V(),R(),D=setInterval(()=>{A++,R()},150)}function V(){D&&(clearInterval(D),D=null)}function H(){if(o===`reconnecting`||o===`failed`)return;N();let e=o===`idle`;if(v)for(let e of _)M(`${i.dim(e)}\n`);let t=c,n=e?i.green:i.cyan,r=(e?i.green:i.cyan)(s),a=``;if(u&&(a+=i.dim(` · `)+i.dim(u)),d&&T!==`worktree`&&(a+=i.dim(` · `)+i.dim(d)),process.env.USER_TYPE===`ant`&&f&&M(`${i.yellow(`[ANT-ONLY] Logs:`)} ${i.dim(f)}\n`),M(`${n(t)} ${r}${a}\n`),C>1){let e=T===`worktree`?`New sessions will be created in an isolated worktree`:`New sessions will be created in the current directory`;M(`    ${i.dim(`Capacity: ${S}/${C} \u00b7 ${e}`)}\n`);for(let[,e]of E){let t=q(e.title?O(e.title,35):i.dim(`Attached`),e.url),n=e.activity;M(`    ${t}${n&&n.type!==`result`&&n.type!==`error`?i.dim(` ${O(n.summary,40)}`):``}
`)}}if(C===1){let e=T===`single-session`?`Single session · exits when complete`:T===`worktree`?`Capacity: ${S}/1 \u00b7 New sessions will be created in an isolated worktree`:`Capacity: ${S}/1 \u00b7 New sessions will be created in the current directory`;M(`    ${i.dim(e)}\n`)}C===1&&!e&&b&&Date.now()-x<3e4&&M(`  ${i.dim(O(b,60))}\n`);let l=g??p;if(l){M(`
`);let t=e?Y(l):L(l),n=v?i.dim.italic(`space to hide QR code`):i.dim.italic(`space to show QR code`),r=w?i.dim.italic(` · w to toggle spawn mode`):``;M(`${i.dim(t)}\n`),M(`${n}${r}\n`)}}return{printBanner(e,r){m=e.sessionIngressUrl,h=r,p=B(r,m),I(p),n&&t(i.dim(`Remote Control`)+` v2.7.1
`),n&&(e.spawnMode!==`single-session`&&(t(i.dim(`Spawn mode: `)+`${e.spawnMode}\n`),t(i.dim(`Max concurrent sessions: `)+`${e.maxSessions}\n`)),t(i.dim(`Environment ID: `)+`${r}\n`)),e.sandbox&&t(i.dim(`Sandbox: `)+`${i.green(`Enabled`)}\n`),t(`
`),z()},logSessionStart(e,t){if(n){let n=O(t,80);F(i.dim(`[${P()}]`)+` Session started: ${i.white(`"${n}"`)} (${i.dim(e)})\n`)}},logSessionComplete(e,t){F(i.dim(`[${P()}]`)+` Session ${i.green(`completed`)} (${k(t)}) ${i.dim(e)}\n`)},logSessionFailed(e,t){F(i.dim(`[${P()}]`)+` Session ${i.red(`failed`)}: ${t} ${i.dim(e)}\n`)},logStatus(e){F(i.dim(`[${P()}]`)+` ${e}\n`)},logVerbose(e){n&&F(i.dim(`[${P()}] ${e}`)+`
`)},logError(e){F(i.red(`[${P()}] Error: ${e}`)+`
`)},logReconnected(e){F(i.dim(`[${P()}]`)+` ${i.green(`Reconnected`)} after ${k(e)}\n`)},setRepoInfo(e,t){u=e,d=t},setDebugLogPath(e){f=e},updateIdleStatus(){V(),o=`idle`,s=`Ready`,b=null,x=0,g=null,I(p),H()},setAttached(e){V(),o=`attached`,s=`Connected`,b=null,x=0,C<=1&&(g=K(e,h,m),I(g)),H()},updateReconnectingStatus(e,t){if(V(),N(),o=`reconnecting`,v)for(let e of _)M(`${i.dim(e)}\n`);let n=l[A%l.length];A++,M(`${i.yellow(n)} ${i.yellow(`Reconnecting`)} ${i.dim(`·`)} ${i.dim(`retrying in ${e}`)} ${i.dim(`·`)} ${i.dim(`disconnected ${t}`)}\n`)},updateFailedStatus(e){V(),N(),o=`failed`;let t=``;u&&(t+=i.dim(` · `)+i.dim(u)),d&&(t+=i.dim(` · `)+i.dim(d)),M(`${i.red(`×`)} ${i.red(`Remote Control Failed`)}${t}\n`),M(`${i.dim(G)}\n`),e&&M(`${i.red(e)}\n`)},updateSessionStatus(e,t,n,r){n.type===`tool_start`&&(b=n.summary,x=Date.now()),H()},clearStatus(){V(),N()},toggleQr(){v=!v,H()},updateSessionCount(e,t,n){S===e&&C===t&&T===n||(S=e,C=t,T=n)},setSpawnModeDisplay(e){w!==e&&(w=e,e&&(T=e))},addSession(e,t){E.set(e,{url:t})},updateSessionActivity(e,t){let n=E.get(e);n&&(n.activity=t)},setSessionTitle(e,t){let n=E.get(e);n&&(n.title=t,!(o===`reconnecting`||o===`failed`)&&(C===1&&(o=`titled`,s=O(t,40)),H()))},removeSession(e){E.delete(e)},refreshDisplay(){o===`reconnecting`||o===`failed`||H()}}}re();var Re=10,ze=10;function Be(e){return e.replace(/[^a-zA-Z0-9_-]/g,`_`)}var Ve={Read:`Reading`,Write:`Writing`,Edit:`Editing`,MultiEdit:`Editing`,Bash:`Running`,Glob:`Searching`,Grep:`Searching`,WebFetch:`Fetching`,WebSearch:`Searching`,Task:`Running task`,FileReadTool:`Reading`,FileWriteTool:`Writing`,FileEditTool:`Editing`,GlobTool:`Searching`,GrepTool:`Searching`,BashTool:`Running`,NotebookEditTool:`Editing notebook`,LSP:`LSP`};function He(e,t){let n=Ve[e]??e,r=t.file_path??t.filePath??t.pattern??t.command?.slice(0,60)??t.url??t.query??``;return r?`${n} ${r}`:n}function Ue(e,t,n){let r;try{r=m(e)}catch{return[]}if(!r||typeof r!=`object`)return[];let i=r,a=[],o=Date.now();switch(i.type){case`assistant`:{let e=i.message;if(!e)break;let r=e.content;if(!Array.isArray(r))break;for(let e of r){if(!e||typeof e!=`object`)continue;let r=e;if(r.type===`tool_use`){let e=r.name??`Tool`,i=r.input??{},s=He(e,i);a.push({type:`tool_start`,summary:s,timestamp:o}),n(`[bridge:activity] sessionId=${t} tool_use name=${e} ${Ge(i)}`)}else if(r.type===`text`){let e=r.text??``;e.length>0&&(a.push({type:`text`,summary:e.slice(0,80),timestamp:o}),n(`[bridge:activity] sessionId=${t} text "${e.slice(0,100)}"`))}}break}case`result`:{let e=i.subtype;if(e===`success`)a.push({type:`result`,summary:`Session completed`,timestamp:o}),n(`[bridge:activity] sessionId=${t} result subtype=success`);else if(e){let r=i.errors?.[0]??`Error: ${e}`;a.push({type:`error`,summary:r,timestamp:o}),n(`[bridge:activity] sessionId=${t} result subtype=${e} error="${r}"`)}else n(`[bridge:activity] sessionId=${t} result subtype=undefined`);break}default:break}return a}function We(e){if(e.parent_tool_use_id!=null||e.isSynthetic||e.isReplay)return;let t=e.message?.content,n;if(typeof t==`string`)n=t;else if(Array.isArray(t)){for(let e of t)if(e&&typeof e==`object`&&e.type===`text`){n=e.text;break}}return n=n?.trim(),n||void 0}function Ge(e){let t=[];for(let[n,r]of Object.entries(e))if(typeof r==`string`&&t.push(`${n}="${r.slice(0,100)}"`),t.length>=3)break;return t.join(` `)}function Ke(e){return{spawn(t,n){let r=Be(t.sessionId),i;if(e.debugFile){let t=e.debugFile.lastIndexOf(`.`);i=t>0?`${e.debugFile.slice(0,t)}-${r}${e.debugFile.slice(t)}`:`${e.debugFile}-${r}`}else (e.verbose||process.env.USER_TYPE===`ant`)&&(i=Oe(Te(),`claude`,`bridge-session-${r}.log`));let a=null,o;e.debugFile&&(o=Oe(De(e.debugFile),`bridge-transcript-${r}.jsonl`),a=Ae(o,{flags:`a`}),a.on(`error`,t=>{e.onDebug(`[bridge:session] Transcript write error: ${t.message}`),a=null}),e.onDebug(`[bridge:session] Transcript log: ${o}`));let s=[...e.scriptArgs,`--print`,`--sdk-url`,t.sdkUrl,`--session-id`,t.sessionId,`--input-format`,`stream-json`,`--output-format`,`stream-json`,`--replay-user-messages`,...e.verbose?[`--verbose`]:[],...i?[`--debug-file`,i]:[],...e.permissionMode?[`--permission-mode`,e.permissionMode]:[]],c={...e.env,CLAUDE_CODE_OAUTH_TOKEN:void 0,CLAUDE_CODE_ENVIRONMENT_KIND:`bridge`,...e.sandbox&&{CLAUDE_CODE_FORCE_SANDBOX:`1`},CLAUDE_CODE_SESSION_ACCESS_TOKEN:t.accessToken,CLAUDE_CODE_POST_FOR_SESSION_INGRESS_V2:`1`,...t.useCcrV2&&{CLAUDE_CODE_USE_CCR_V2:`1`,CLAUDE_CODE_WORKER_EPOCH:String(t.workerEpoch)}};e.onDebug(`[bridge:session] Spawning sessionId=${t.sessionId} sdkUrl=${t.sdkUrl} accessToken=${t.accessToken?`present`:`MISSING`}`),e.onDebug(`[bridge:session] Child args: ${s.join(` `)}`),i&&e.onDebug(`[bridge:session] Debug log: ${i}`);let l=Me(e.execPath,s,{cwd:n,stdio:[`pipe`,`pipe`,`pipe`],env:c,windowsHide:!0});e.onDebug(`[bridge:session] sessionId=${t.sessionId} pid=${l.pid}`);let u=[],d=null,f=[],p=!1,h=!1;l.stderr&&Ne({input:l.stderr}).on(`line`,t=>{e.verbose&&process.stderr.write(t+`
`),f.length>=ze&&f.shift(),f.push(t)}),l.stdout&&Ne({input:l.stdout}).on(`line`,n=>{a&&a.write(n+`
`),e.onDebug(`[bridge:ws] sessionId=${t.sessionId} <<< ${oe(n)}`),e.verbose&&process.stderr.write(n+`
`);let r=Ue(n,t.sessionId,e.onDebug);for(let n of r)u.length>=Re&&u.shift(),u.push(n),d=n,e.onActivity?.(t.sessionId,n);{let r;try{r=m(n)}catch{}if(r&&typeof r==`object`){let n=r;if(n.type===`control_request`)n.request?.subtype===`can_use_tool`&&e.onPermissionRequest&&e.onPermissionRequest(t.sessionId,r,t.accessToken);else if(n.type===`user`&&!h&&t.onFirstUserMessage){let e=We(n);e&&(h=!0,t.onFirstUserMessage(e))}}}});let _=new Promise(n=>{l.on(`close`,(r,i)=>{a&&(a.end(),a=null),i===`SIGTERM`||i===`SIGINT`?(e.onDebug(`[bridge:session] sessionId=${t.sessionId} interrupted signal=${i} pid=${l.pid}`),n(`interrupted`)):r===0?(e.onDebug(`[bridge:session] sessionId=${t.sessionId} completed exit_code=0 pid=${l.pid}`),n(`completed`)):(e.onDebug(`[bridge:session] sessionId=${t.sessionId} failed exit_code=${r} pid=${l.pid}`),n(`failed`))}),l.on(`error`,r=>{e.onDebug(`[bridge:session] sessionId=${t.sessionId} spawn error: ${r.message}`),n(`failed`)})}),v={sessionId:t.sessionId,done:_,activities:u,accessToken:t.accessToken,lastStderr:f,get currentActivity(){return d},kill(){l.killed||(e.onDebug(`[bridge:session] Sending SIGTERM to sessionId=${t.sessionId} pid=${l.pid}`),process.platform===`win32`?l.kill():l.kill(`SIGTERM`))},forceKill(){!p&&l.pid&&(p=!0,e.onDebug(`[bridge:session] Sending SIGKILL to sessionId=${t.sessionId} pid=${l.pid}`),process.platform===`win32`?l.kill():l.kill(`SIGKILL`))},writeStdin(n){l.stdin&&!l.stdin.destroyed&&(e.onDebug(`[bridge:ws] sessionId=${t.sessionId} >>> ${oe(n)}`),l.stdin.write(n))},updateAccessToken(n){v.accessToken=n,v.writeStdin(g({type:`update_environment_variables`,variables:{CLAUDE_CODE_SESSION_ACCESS_TOKEN:n}})+`
`),e.onDebug(`[bridge:session] Sent token refresh via stdin for sessionId=${t.sessionId}`)}};return v}}}v(),J(),se(),Z();var qe={connInitialMs:2e3,connCapMs:12e4,connGiveUpMs:6e5,generalInitialMs:500,generalCapMs:3e4,generalGiveUpMs:6e5},Je=1e3,Ye=32;async function Xe(){return f(`tengu_ccr_bridge_multi_session`)}function Ze(e){return e.connCapMs*2}function Qe(){let e=[...me()],t=he();return t&&e.push(t),e}function $e(e,t,n){try{return e.spawn(t,n)}catch(e){let t=b(e);return D(Error(`Session spawn failed: ${t}`)),t}}async function et(t,r,i,a,o,s,c,l=qe,u,d){let f=new AbortController;c.aborted?f.abort():c.addEventListener(`abort`,()=>f.abort(),{once:!0});let p=f.signal,m=new Map,h=new Map,g=new Map,_=new Map,v=new Map,x=new Map,S=new Set,T=new Map,E=new Set,O=new Set,A=ge(p);async function M(){ne(`heartbeat: checking ${m.size} active session(s)`);let e=!1,t=!1,n=[];for(let[i]of m){let o=g.get(i),s=v.get(i);if(!(!o||!s))try{await a.heartbeatWork(r,o,s),e=!0}catch(e){y(`[bridge:heartbeat] Failed for sessionId=${i} workId=${o}: ${b(e)}`),e instanceof V&&(C(`tengu_bridge_heartbeat_error`,{status:e.status,error_type:e.status===401||e.status===403?`auth_failed`:`fatal`}),e.status===401||e.status===403?n.push(i):t=!0)}}for(let e of n){s.logVerbose(`Session ${e} token expired — re-queuing via bridge/reconnect`);try{await a.reconnectSession(r,e),y(`[bridge:heartbeat] Re-queued sessionId=${e} via bridge/reconnect`)}catch(t){s.logError(`Failed to refresh session ${e} token: ${b(t)}`),y(`[bridge:heartbeat] reconnectSession(${e}) failed: ${b(t)}`,{level:`error`})}}return t?`fatal`:n.length>0?`auth_failed`:e?`ok`:`failed`}let N=new Set,P=d?_e({getAccessToken:d,onRefresh:(e,t)=>{let n=m.get(e);n&&(N.has(e)?(s.logVerbose(`Refreshing session ${e} token via bridge/reconnect`),a.reconnectSession(r,e).catch(t=>{s.logError(`Failed to refresh session ${e} token: ${b(t)}`),y(`[bridge:token] reconnectSession(${e}) failed: ${b(t)}`,{level:`error`})})):n.updateAccessToken(t))},label:`bridge`}):null,L=Date.now(),R=new Set;function B(e){R.add(e),e.finally(()=>R.delete(e))}let U=0,W=0,G=null,K=null,q=null,J=null,Y=!1;if(y(`[bridge:work] Starting poll loop spawnMode=${t.spawnMode} maxSessions=${t.maxSessions} environmentId=${r}`),w(`info`,`bridge_loop_started`,{max_sessions:t.maxSessions,spawn_mode:t.spawnMode}),process.env.USER_TYPE===`ant`){let e;if(t.debugFile){let n=t.debugFile.lastIndexOf(`.`);e=n>0?`${t.debugFile.slice(0,n)}-*${t.debugFile.slice(n)}`:`${t.debugFile}-*`}else e=Oe(Te(),`claude`,`bridge-session-*.log`);s.setDebugLogPath(e)}s.printBanner(t,r),s.updateSessionCount(0,t.maxSessions,t.spawnMode),u&&s.setAttached(u);function X(){s.updateSessionCount(m.size,t.maxSessions,t.spawnMode);for(let[e,t]of m){let n=t.currentActivity;n&&s.updateSessionActivity(_.get(e)??e,n)}if(m.size===0){s.updateIdleStatus();return}let[e,n]=[...m.entries()].pop(),r=h.get(e);if(!r)return;let i=n.currentActivity;if(!i||i.type===`result`||i.type===`error`){t.maxSessions>1&&s.refreshDisplay();return}let a=k(Date.now()-r),o=n.activities.filter(e=>e.type===`tool_start`).slice(-5).map(e=>e.summary);s.updateSessionStatus(e,a,i,o)}function re(){ae(),X(),J=setInterval(X,Je)}function ae(){J&&(clearInterval(J),J=null)}function oe(e,n,i){return o=>{let c=g.get(e);ne(`session done: sessionId=${e} workId=${c??`none`} status=${o} wasTimedOut=${E.has(e)} duration=${Math.round((Date.now()-n)/1e3)}s stderr=${i.lastStderr.length>0?i.lastStderr.join(`\\n`).slice(0,500):`(none)`}`),m.delete(e),h.delete(e),g.delete(e),v.delete(e);let u=_.get(e)??e;_.delete(e),s.removeSession(u),O.delete(u),N.delete(e);let d=x.get(e);d&&(clearTimeout(d),x.delete(e)),P?.cancel(e),A.wake();let j=E.delete(e),M=j&&o===`interrupted`?`failed`:o,F=Date.now()-n;y(`[bridge:session] sessionId=${e} workId=${c??`unknown`} exited status=${M} duration=${k(F)}`),C(`tengu_bridge_session_done`,{status:M,duration_ms:F}),w(`info`,`bridge_session_done`,{status:M,duration_ms:F}),s.clearStatus(),ae();let I=i.lastStderr.length>0?i.lastStderr.join(`
`):void 0,L;switch(M){case`completed`:s.logSessionComplete(e,F);break;case`failed`:!j&&!p.aborted&&(L=I??`Process exited with error`,s.logSessionFailed(e,L),D(Error(`Bridge session failed: ${L}`)));break;case`interrupted`:s.logVerbose(`Session ${e} interrupted`);break}M!==`interrupted`&&c&&(B(ot(a,r,c,s,l.stopWorkBaseDelayMs)),S.add(c));let R=T.get(e);if(R&&(T.delete(e),B(H(R.worktreePath,R.worktreeBranch,R.gitRoot,R.hookBased).catch(e=>s.logVerbose(`Failed to remove worktree ${R.worktreePath}: ${b(e)}`)))),M!==`interrupted`&&!p.aborted)if(t.spawnMode!==`single-session`)B(a.archiveSession(u).catch(t=>s.logVerbose(`Failed to archive session ${e}: ${b(t)}`))),y(`[bridge:session] Session ${M}, returning to idle (multi-session mode)`);else{y(`[bridge:session] Session ${M}, aborting poll loop to tear down environment`),f.abort();return}p.aborted||re()}}for(u||re();!p.aborted;){let c=ve();try{ne(`poll: envId=${r} activeSessions=${m.size}`);let d=await a.pollForWork(r,i,p,c.reclaim_older_than_ms);if(G!==null||K!==null){let e=Date.now()-(G??K??Date.now());s.logReconnected(e),y(`[bridge:poll] Reconnected after ${k(e)}`),C(`tengu_bridge_reconnected`,{disconnected_ms:e})}if(U=0,W=0,G=null,K=null,q=null,!d){if(m.size>=t.maxSessions){let e=c.multisession_poll_interval_ms_at_capacity;if(c.non_exclusive_heartbeat_interval_ms>0){C(`tengu_bridge_heartbeat_mode_entered`,{active_sessions:m.size,heartbeat_interval_ms:c.non_exclusive_heartbeat_interval_ms});let n=e>0?Date.now()+e:null,r=`ok`,i=0;for(;!p.aborted&&m.size>=t.maxSessions&&(n===null||Date.now()<n);){let e=ve();if(e.non_exclusive_heartbeat_interval_ms<=0)break;let t=A.signal();if(r=await M(),r===`auth_failed`||r===`fatal`){t.cleanup();break}i++,await j(e.non_exclusive_heartbeat_interval_ms,t.signal),t.cleanup()}let a=r===`auth_failed`||r===`fatal`?r:p.aborted?`shutdown`:m.size<t.maxSessions?`capacity_changed`:n!==null&&Date.now()>=n?`poll_due`:`config_disabled`;if(C(`tengu_bridge_heartbeat_mode_exited`,{reason:a,heartbeat_cycles:i,active_sessions:m.size}),a===`poll_due`&&y(`[bridge:poll] Heartbeat poll_due after ${i} cycles — falling through to pollForWork`),r===`auth_failed`||r===`fatal`){let t=A.signal();await j(e>0?e:c.non_exclusive_heartbeat_interval_ms,t.signal),t.cleanup()}}else if(e>0){let t=A.signal();await j(e,t.signal),t.cleanup()}}else await j(m.size>0?c.multisession_poll_interval_ms_partial_capacity:c.multisession_poll_interval_ms_not_at_capacity,p);continue}let f=m.size>=t.maxSessions;if(S.has(d.id)){if(y(`[bridge:work] Skipping already-completed workId=${d.id}`),f){let e=A.signal();c.non_exclusive_heartbeat_interval_ms>0?(await M(),await j(c.non_exclusive_heartbeat_interval_ms,e.signal)):c.multisession_poll_interval_ms_at_capacity>0&&await j(c.multisession_poll_interval_ms_at_capacity,e.signal),e.cleanup()}else await j(1e3,p);continue}let I;try{I=Se(d.secret)}catch(e){let t=b(e);if(s.logError(`Failed to decode work secret for workId=${d.id}: ${t}`),C(`tengu_bridge_work_secret_failed`,{}),S.add(d.id),B(ot(a,r,d.id,s,l.stopWorkBaseDelayMs)),f){let e=A.signal();c.non_exclusive_heartbeat_interval_ms>0?(await M(),await j(c.non_exclusive_heartbeat_interval_ms,e.signal)):c.multisession_poll_interval_ms_at_capacity>0&&await j(c.multisession_poll_interval_ms_at_capacity,e.signal),e.cleanup()}continue}let L=async()=>{y(`[bridge:work] Acknowledging workId=${d.id}`);try{await a.acknowledgeWork(r,d.id,I.session_ingress_token)}catch(e){y(`[bridge:work] Acknowledge failed workId=${d.id}: ${b(e)}`)}},R=d.data.type;switch(d.data.type){case`healthcheck`:await L(),y(`[bridge:work] Healthcheck received`),s.logVerbose(`Healthcheck received`);break;case`session`:{let i=d.data.id;ne(`work received: type=session sessionId=${i} workId=${d.id}`);try{ee(i,`session_id`)}catch{await L(),s.logError(`Invalid session_id received: ${i}`);break}let c=m.get(i);if(c){c.updateAccessToken(I.session_ingress_token),v.set(i,I.session_ingress_token),g.set(i,d.id),P?.schedule(i,I.session_ingress_token),y(`[bridge:work] Updated access token for existing sessionId=${i} workId=${d.id}`),await L();break}if(m.size>=t.maxSessions){y(`[bridge:work] At capacity (${m.size}/${t.maxSessions}), cannot spawn new session for workId=${d.id}`);break}await L();let f=Date.now(),k,A=!1,M;if(I.use_code_sessions===!0||n(process.env.CLAUDE_BRIDGE_USE_CCR_V2)){k=Ce(t.apiBaseUrl,i);for(let e=1;e<=2;e++)try{M=await be(k,I.session_ingress_token),A=!0,y(`[bridge:session] CCR v2: registered worker sessionId=${i} epoch=${M} attempt=${e}`);break}catch(t){let n=b(t);if(e<2){if(y(`[bridge:session] CCR v2: registerWorker attempt ${e} failed, retrying: ${n}`),await j(2e3,p),p.aborted)break;continue}s.logError(`CCR v2 worker registration failed for session ${i}: ${n}`),D(Error(`registerWorker failed: ${n}`)),S.add(d.id),B(ot(a,r,d.id,s,l.stopWorkBaseDelayMs))}if(!A)break}else k=xe(t.sessionIngressUrl,i);let R=t.spawnMode,z=t.dir,V=0;if(R===`worktree`&&(u===void 0||!ye(i,u))){let e=Date.now();try{let t=await te(`bridge-${Be(i)}`);V=Date.now()-e,T.set(i,{worktreePath:t.worktreePath,worktreeBranch:t.worktreeBranch,gitRoot:t.gitRoot,hookBased:t.hookBased}),z=t.worktreePath,y(`[bridge:session] Created worktree for sessionId=${i} at ${t.worktreePath}`)}catch(e){let t=b(e);s.logError(`Failed to create worktree for session ${i}: ${t}`),D(Error(`Worktree creation failed: ${t}`)),S.add(d.id),B(ot(a,r,d.id,s,l.stopWorkBaseDelayMs));break}}y(`[bridge:session] Spawning sessionId=${i} sdkUrl=${k}`);let U=ie(i);ne(`spawning session: sessionId=${i} sdkUrl=${k} useCcrV2=${A} workerEpoch=${M} dir=${z} accessToken=${I.session_ingress_token?I.session_ingress_token.slice(0,8)+`...`:`NONE`}`);let W=$e(o,{sessionId:i,sdkUrl:k,accessToken:I.session_ingress_token,useCcrV2:A,workerEpoch:M,onFirstUserMessage:e=>{if(O.has(U))return;O.add(U);let n=mt(e);s.setSessionTitle(U,n),y(`[bridge:title] derived title for ${U}: ${n}`),import(`./createSession-Czx7_nf6.js`).then(({updateBridgeSessionTitle:e})=>e(U,n,{baseUrl:t.apiBaseUrl})).catch(e=>y(`[bridge:title] failed to update title for ${U}: ${e}`,{level:`error`}))}},z);if(typeof W==`string`){s.logError(`Failed to spawn session ${i}: ${W}`);let e=T.get(i);e&&(T.delete(i),B(H(e.worktreePath,e.worktreeBranch,e.gitRoot,e.hookBased).catch(t=>s.logVerbose(`Failed to remove worktree ${e.worktreePath}: ${b(t)}`)))),S.add(d.id),B(ot(a,r,d.id,s,l.stopWorkBaseDelayMs));break}let G=W,K=Date.now()-f;C(`tengu_bridge_session_started`,{active_sessions:m.size,spawn_mode:R,in_worktree:T.has(i),spawn_duration_ms:K,worktree_create_ms:V,inProtectedNamespace:e()}),w(`info`,`bridge_session_started`,{spawn_mode:R,in_worktree:T.has(i),spawn_duration_ms:K,worktree_create_ms:V}),m.set(i,G),g.set(i,d.id),v.set(i,I.session_ingress_token),_.set(i,U);let q=Date.now();h.set(i,q),s.logSessionStart(i,`Session ${i}`);let J=Be(i),Y;if(t.debugFile){let e=t.debugFile.lastIndexOf(`.`);Y=e>0?`${t.debugFile.slice(0,e)}-${J}${t.debugFile.slice(e)}`:`${t.debugFile}-${J}`}else (t.verbose||process.env.USER_TYPE===`ant`)&&(Y=Oe(Te(),`claude`,`bridge-session-${J}.log`));Y&&s.logVerbose(`Debug log: ${Y}`),s.addSession(U,F(U,t.sessionIngressUrl)),re(),s.setAttached(U),ht(U,t.apiBaseUrl).then(e=>{e&&m.has(i)&&(O.add(U),s.setSessionTitle(U,e),y(`[bridge:title] server title for ${U}: ${e}`))}).catch(e=>y(`[bridge:title] failed to fetch title for ${U}: ${e}`,{level:`error`}));let X=t.sessionTimeoutMs??864e5;if(X>0){let e=setTimeout(st,X,i,X,s,E,G);x.set(i,e)}A&&N.add(i),P?.schedule(i,I.session_ingress_token),G.done.then(oe(i,q,G));break}default:await L(),y(`[bridge:work] Unknown work type: ${R}, skipping`);break}if(f){let e=A.signal();c.non_exclusive_heartbeat_interval_ms>0?(await M(),await j(c.non_exclusive_heartbeat_interval_ms,e.signal)):c.multisession_poll_interval_ms_at_capacity>0&&await j(c.multisession_poll_interval_ms_at_capacity,e.signal),e.cleanup()}}catch(e){if(p.aborted)break;if(e instanceof V){Y=!0,I(e.errorType)?s.logStatus(e.message):z(e)?y(`[bridge:work] Suppressed 403 error: ${e.message}`):(s.logError(e.message),D(e)),C(`tengu_bridge_fatal_error`,{status:e.status,error_type:e.errorType}),w(I(e.errorType)?`info`:`error`,`bridge_fatal_error`,{status:e.status,error_type:e.errorType});break}let t=ce(e);if(ne(`poll error: ${t} isConn=${nt(e)} isServer=${rt(e)} activeSessions=${m.size}`),nt(e)||rt(e)){let e=Date.now();q!==null&&e-q>Ze(l)&&(y(`[bridge:work] Detected system sleep (${Math.round((e-q)/1e3)}s gap), resetting error budget`),w(`info`,`bridge_poll_sleep_detected`,{gapMs:e-q}),G=null,U=0,K=null,W=0),q=e,G||(G=e);let n=e-G;if(n>=l.connGiveUpMs){s.logError(`Server unreachable for ${Math.round(n/6e4)} minutes, giving up.`),C(`tengu_bridge_poll_give_up`,{error_type:`connection`,elapsed_ms:n}),w(`error`,`bridge_poll_give_up`,{error_type:`connection`,elapsed_ms:n}),Y=!0;break}K=null,W=0,U=U?Math.min(U*2,l.connCapMs):l.connInitialMs;let r=it(U);s.logVerbose(`Connection error, retrying in ${at(r)} (${Math.round(n/1e3)}s elapsed): ${t}`),s.updateReconnectingStatus(at(r),k(n)),ve().non_exclusive_heartbeat_interval_ms>0&&await M(),await j(r,p)}else{let e=Date.now();q!==null&&e-q>Ze(l)&&(y(`[bridge:work] Detected system sleep (${Math.round((e-q)/1e3)}s gap), resetting error budget`),w(`info`,`bridge_poll_sleep_detected`,{gapMs:e-q}),G=null,U=0,K=null,W=0),q=e,K||(K=e);let n=e-K;if(n>=l.generalGiveUpMs){s.logError(`Persistent errors for ${Math.round(n/6e4)} minutes, giving up.`),C(`tengu_bridge_poll_give_up`,{error_type:`general`,elapsed_ms:n}),w(`error`,`bridge_poll_give_up`,{error_type:`general`,elapsed_ms:n}),Y=!0;break}G=null,U=0,W=W?Math.min(W*2,l.generalCapMs):l.generalInitialMs;let r=it(W);s.logVerbose(`Poll failed, retrying in ${at(r)} (${Math.round(n/1e3)}s elapsed): ${t}`),s.updateReconnectingStatus(at(r),k(n)),ve().non_exclusive_heartbeat_interval_ms>0&&await M(),await j(r,p)}}}ae(),s.clearStatus();let se=Date.now()-L;C(`tengu_bridge_shutdown`,{active_sessions:m.size,loop_duration_ms:se}),w(`info`,`bridge_shutdown`,{active_sessions:m.size,loop_duration_ms:se});let le=new Set(m.keys());u&&le.add(u);let ue=new Map(_);if(m.size>0){y(`[bridge:shutdown] Shutting down ${m.size} active session(s)`),s.logStatus(`Shutting down ${m.size} active session(s)\u2026`);let e=new Map(g);for(let[e,t]of m.entries())y(`[bridge:shutdown] Sending SIGTERM to sessionId=${e}`),t.kill();let t=new AbortController;await Promise.race([Promise.allSettled([...m.values()].map(e=>e.done)),j(l.shutdownGraceMs??3e4,t.signal)]),t.abort();for(let[e,t]of m.entries())y(`[bridge:shutdown] Force-killing stuck sessionId=${e}`),t.forceKill();for(let e of x.values())clearTimeout(e);if(x.clear(),P?.cancelAll(),T.size>0){let e=[...T.values()];T.clear(),y(`[bridge:shutdown] Cleaning up ${e.length} worktree(s)`),await Promise.allSettled(e.map(e=>H(e.worktreePath,e.worktreeBranch,e.gitRoot,e.hookBased)))}await Promise.allSettled([...e.entries()].map(([e,t])=>a.stopWork(r,t,!0).catch(n=>s.logVerbose(`Failed to stop work ${t} for session ${e}: ${b(n)}`))))}if(R.size>0&&await Promise.allSettled([...R]),t.spawnMode===`single-session`&&u&&!Y){s.logStatus("Resume this session by running `claude remote-control --continue`"),y(`[bridge:shutdown] Skipping archive+deregister to allow resume of session ${u}`);return}le.size>0&&(y(`[bridge:shutdown] Archiving ${le.size} session(s)`),await Promise.allSettled([...le].map(e=>a.archiveSession(ue.get(e)??ie(e)).catch(t=>s.logVerbose(`Failed to archive session ${e}: ${b(t)}`)))));try{await a.deregisterEnvironment(r),y(`[bridge:shutdown] Environment deregistered, bridge offline`),s.logVerbose(`Environment deregistered.`)}catch(e){s.logVerbose(`Failed to deregister environment: ${b(e)}`)}let{clearBridgePointer:Z}=await import(`./bridgePointer-Clcvh52n.js`);await Z(t.dir),s.logVerbose(`Environment offline.`)}var tt=new Set([`ECONNREFUSED`,`ECONNRESET`,`ETIMEDOUT`,`ENETUNREACH`,`EHOSTUNREACH`]);function nt(e){return!!(e&&typeof e==`object`&&`code`in e&&typeof e.code==`string`&&tt.has(e.code))}function rt(e){return!!e&&typeof e==`object`&&`code`in e&&typeof e.code==`string`&&e.code===`ERR_BAD_RESPONSE`}function it(e){return Math.max(0,e+e*.25*(2*Math.random()-1))}function at(e){return e>=1e3?`${(e/1e3).toFixed(1)}s`:`${Math.round(e)}ms`}async function ot(e,t,n,r,i=1e3){for(let a=1;a<=3;a++)try{await e.stopWork(t,n,!1),y(`[bridge:work] stopWork succeeded for workId=${n} on attempt ${a}/3`);return}catch(e){if(e instanceof V){z(e)?y(`[bridge:work] Suppressed stopWork 403 for ${n}: ${e.message}`):r.logError(`Failed to stop work ${n}: ${e.message}`),w(`error`,`bridge_stop_work_failed`,{attempts:a,fatal:!0});return}let t=b(e);if(a<3){let e=it(i*2**(a-1));r.logVerbose(`Failed to stop work ${n} (attempt ${a}/3), retrying in ${at(e)}: ${t}`),await j(e)}else r.logError(`Failed to stop work ${n} after 3 attempts: ${t}`),w(`error`,`bridge_stop_work_failed`,{attempts:3})}}function st(e,t,n,r,i){y(`[bridge:session] sessionId=${e} timed out after ${k(t)}`),C(`tengu_bridge_session_timeout`,{timeout_ms:t}),n.logSessionFailed(e,`Session timed out after ${k(t)}`),r.add(e),i.kill()}var ct=[`session`,`same-dir`,`worktree`];function lt(e){return e===`session`?`single-session`:e===`same-dir`?`same-dir`:e===`worktree`?`worktree`:`--spawn requires one of: ${ct.join(`, `)} (got: ${e??`<missing>`})`}function ut(e){let t=e===void 0?NaN:parseInt(e,10);return isNaN(t)||t<1?`--capacity requires a positive integer (got: ${e??`<missing>`})`:t}function dt(e){let t=!1,n=!1,r,i,a,o,s=!1,c,l,u,d,f=!1;for(let m=0;m<e.length;m++){let h=e[m];if(h===`--help`||h===`-h`)s=!0;else if(h===`--verbose`||h===`-v`)t=!0;else if(h===`--sandbox`)n=!0;else if(h===`--no-sandbox`)n=!1;else if(h===`--debug-file`&&m+1<e.length)r=ke(e[++m]);else if(h.startsWith(`--debug-file=`))r=ke(h.slice(13));else if(h===`--session-timeout`&&m+1<e.length)i=parseInt(e[++m],10)*1e3;else if(h.startsWith(`--session-timeout=`))i=parseInt(h.slice(18),10)*1e3;else if(h===`--permission-mode`&&m+1<e.length)a=e[++m];else if(h.startsWith(`--permission-mode=`))a=h.slice(18);else if(h===`--name`&&m+1<e.length)o=e[++m];else if(h.startsWith(`--name=`))o=h.slice(7);else if(h===`--session-id`&&m+1<e.length){if(d=e[++m],!d)return p(`--session-id requires a value`)}else if(h.startsWith(`--session-id=`)){if(d=h.slice(13),!d)return p(`--session-id requires a value`)}else if(h===`--continue`||h===`-c`)f=!0;else if(h===`--spawn`||h.startsWith(`--spawn=`)){if(c!==void 0)return p(`--spawn may only be specified once`);let t=lt(h.startsWith(`--spawn=`)?h.slice(8):e[++m]);if(t===`single-session`||t===`same-dir`||t===`worktree`)c=t;else return p(t)}else if(h===`--capacity`||h.startsWith(`--capacity=`)){if(l!==void 0)return p(`--capacity may only be specified once`);let t=ut(h.startsWith(`--capacity=`)?h.slice(11):e[++m]);if(typeof t==`number`)l=t;else return p(t)}else if(h===`--create-session-in-dir`)u=!0;else if(h===`--no-create-session-in-dir`)u=!1;else return p(`Unknown argument: ${h}\nRun 'claude remote-control --help' for usage.`)}if(c===`single-session`&&l!==void 0)return p(`--capacity cannot be used with --spawn=session (single-session mode has fixed capacity 1).`);if((d||f)&&(c!==void 0||l!==void 0||u!==void 0))return p(`--session-id and --continue cannot be used with --spawn, --capacity, or --create-session-in-dir.`);if(d&&f)return p(`--session-id and --continue cannot be used together.`);return{verbose:t,sandbox:n,debugFile:r,sessionTimeoutMs:i,permissionMode:a,name:o,spawnMode:c,capacity:l,createSessionInDir:u,sessionId:d,continueSession:f,help:s};function p(e){return{verbose:t,sandbox:n,debugFile:r,sessionTimeoutMs:i,permissionMode:a,name:o,spawnMode:c,capacity:l,createSessionInDir:u,sessionId:d,continueSession:f,help:s,error:e}}}async function ft(){let{EXTERNAL_PERMISSION_MODES:e}=await import(`./permissions-BE-1pIly.js`),t=e.join(`, `),n=await Xe(),r=`
Remote Control - Connect your local environment to claude.ai/code

USAGE
  claude remote-control [options]
OPTIONS
  --name <name>                    Name for the session (shown in claude.ai/code)
  -c, --continue                   Resume the last session in this directory
  --session-id <id>                Resume a specific session by ID (cannot be
                                   used with spawn flags or --continue)
  --permission-mode <mode>         Permission mode for spawned sessions
                                   (${t})
  --debug-file <path>              Write debug logs to file
  -v, --verbose                    Enable verbose output
  -h, --help                       Show this help
${n?`  --spawn <mode>                   Spawn mode: same-dir, worktree, session
                                   (default: same-dir)
  --capacity <N>                   Max concurrent sessions in worktree or
                                   same-dir mode (default: ${Ye})
  --[no-]create-session-in-dir     Pre-create a session in the current
                                   directory; in worktree mode this session
                                   stays in cwd while on-demand sessions get
                                   isolated worktrees (default: on)
`:``}
DESCRIPTION
  Remote Control allows you to control sessions on your local device from
  claude.ai/code (https://claude.ai/code). Run this command in the
  directory you want to work in, then connect from the Claude app or web.
${n?`
  Remote Control runs as a persistent server that accepts multiple concurrent
  sessions in the current directory. One session is pre-created on start so
  you have somewhere to type immediately. Use --spawn=worktree to isolate
  each on-demand session in its own git worktree, or --spawn=session for
  the classic single-session mode (exits when that session ends). Press 'w'
  during runtime to toggle between same-dir and worktree.
`:``}
NOTES
  - You must be logged in with a Claude account that has a subscription
  - Run \`claude\` first in the directory to accept the workspace trust dialog
${n?`  - Worktree mode requires a git repository or WorktreeCreate/WorktreeRemove hooks
`:``}`;console.log(r)}var pt=80;function mt(e){return O(e.replace(/\s+/g,` `).trim(),pt)}async function ht(e,t){let{getBridgeSession:n}=await import(`./createSession-Czx7_nf6.js`);return(await n(e,{baseUrl:t}))?.title||void 0}async function gt(e){let t=dt(e);if(t.help){await ft();return}t.error&&(console.error(`Error: ${t.error}`),process.exit(1));let{verbose:n,sandbox:r,debugFile:i,sessionTimeoutMs:a,permissionMode:o,name:s,spawnMode:c,capacity:l,createSessionInDir:u,sessionId:d,continueSession:f}=t,m=d,h,g=c!==void 0||l!==void 0||u!==void 0;if(o!==void 0){let{PERMISSION_MODES:e}=await import(`./permissions-BE-1pIly.js`),t=e;t.includes(o)||(console.error(`Error: Invalid permission mode '${o}'. Valid modes: ${t.join(`, `)}`),process.exit(1))}let _=ke(`.`),{enableConfigs:v,checkHasTrustDialogAccepted:S}=await import(`./config-CJd9kJ57.js`);v();let{initSinks:T}=await import(`./sinks-BnkxTOU9.js`);T();let E=await Xe();g&&!E&&(await x(`tengu_bridge_multi_session_denied`,{used_spawn:c!==void 0,used_capacity:l!==void 0,used_create_session_in_dir:u!==void 0}),await Promise.race([Promise.all([p(),le()]),j(500,void 0,{unref:!0})]).catch(()=>{}),console.error(`Error: Multi-session Remote Control is not enabled for your account yet.`),process.exit(1));let{setOriginalCwd:O,setCwdState:k}=await import(`./state-B2GIOsTB.js`);O(_),k(_),S()||(console.error(`Error: Workspace not trusted. Please run \`claude\` in ${_} first to review and accept the workspace trust dialog.`),process.exit(1));let{clearOAuthTokenCache:A,checkAndRefreshOAuthTokenIfNeeded:M}=await import(`./auth-CvHVr2A5.js`),{getBridgeAccessToken:N,getBridgeBaseUrl:P}=await import(`./bridgeConfig-B49H_B9L.js`);N()||(console.error(fe),process.exit(1));let{getGlobalConfig:F,saveGlobalConfig:I,getCurrentProjectConfig:L,saveCurrentProjectConfig:R}=await import(`./config-CJd9kJ57.js`);if(!F().remoteDialogSeen){let e=(await import(`readline`)).createInterface({input:process.stdin,output:process.stdout});console.log(`
Remote Control lets you access this CLI session from the web (claude.ai/code)
or the Claude app, so you can pick up where you left off on any device.

You can disconnect remote access anytime by running /remote-control again.
`);let t=await new Promise(t=>{e.question(`Enable Remote Control? (y/n) `,t)});e.close(),I(e=>e.remoteDialogSeen?e:{...e,remoteDialogSeen:!0}),t.toLowerCase()!==`y`&&t.toLowerCase()!==`yes`&&process.exit(0)}if(f){let{readBridgePointerAcrossWorktrees:e}=await import(`./bridgePointer-Clcvh52n.js`),t=await e(_);t||(console.error("Error: No recent session found in this directory or its worktrees. Run `claude remote-control` to start a new one."),process.exit(1));let{pointer:n,dir:r}=t,i=Math.round(n.ageMs/6e4),a=i<60?`${i}m`:`${Math.round(i/60)}h`,o=r===_?``:` from worktree ${r}`;console.error(`Resuming session ${n.sessionId} (${a} ago)${o}\u2026`),m=n.sessionId,h=r}let z=P();z.startsWith(`http://`)&&!z.includes(`localhost`)&&!z.includes(`127.0.0.1`)&&(console.error(`Error: Remote Control base URL uses HTTP. Only HTTPS or localhost HTTP is allowed.`),process.exit(1));let B=process.env.CLAUDE_BRIDGE_SESSION_INGRESS_URL||z,{getBranch:H,getRemoteUrl:U,findGitRoot:G}=await import(`./git-hSvFiuiG.js`),{hasWorktreeCreateHook:K}=await import(`./hooks-DOej0jqp.js`),q=K()||G(_)!==null,J=E?L().remoteControlSpawnMode:void 0;if(J===`worktree`&&!q&&(console.error(`Warning: Saved spawn mode is worktree but this directory is not a git repository. Falling back to same-dir.`),J=void 0,R(e=>e.remoteControlSpawnMode===void 0?e:{...e,remoteControlSpawnMode:void 0})),E&&!J&&q&&c===void 0&&!m&&process.stdin.isTTY){let e=(await import(`readline`)).createInterface({input:process.stdin,output:process.stdout});console.log(`
Claude Remote Control is launching in spawn mode which lets you create new sessions in this project from Claude Code on Web or your Mobile app. Learn more here: https://code.claude.com/docs/en/remote-control

Spawn mode for this project:
  [1] same-dir — sessions share the current directory (default)
  [2] worktree — each session gets an isolated git worktree

This can be changed later or explicitly set with --spawn=same-dir or --spawn=worktree.
`);let t=await new Promise(t=>{e.question(`Choose [1/2] (default: 1): `,t)});e.close();let n=t.trim()===`2`?`worktree`:`same-dir`;J=n,C(`tengu_bridge_spawn_mode_chosen`,{spawn_mode:n}),R(e=>e.remoteControlSpawnMode===n?e:{...e,remoteControlSpawnMode:n})}let te,Y;m?(Y=`single-session`,te=`resume`):c===void 0?J===void 0?(Y=E?`same-dir`:`single-session`,te=`gate_default`):(Y=J,te=`saved`):(Y=c,te=`flag`);let ne=Y===`single-session`?1:l??Ye,X=u??!0;if(!m){let{clearBridgePointer:e}=await import(`./bridgePointer-Clcvh52n.js`);await e(_)}Y===`worktree`&&!q&&(console.error(`Error: Worktree mode requires a git repository or WorktreeCreate hooks configured. Use --spawn=session for single-session mode.`),process.exit(1));let re=await H(),ie=await U(),oe=we(),se=je(),{handleOAuth401Error:ce}=await import(`./auth-CvHVr2A5.js`),ue=W({baseUrl:z,getAccessToken:N,runnerVersion:`2.7.1`,onDebug:y,onAuth401:ce,getTrustedDeviceToken:de}),Z;if(m){try{ee(m,`sessionId`)}catch{console.error(`Error: Invalid session ID "${m}". Session IDs must not contain unsafe characters.`),process.exit(1)}await M(),A();let{getBridgeSession:e}=await import(`./createSession-Czx7_nf6.js`),t=await e(m,{baseUrl:z,getAccessToken:N});if(!t){if(h){let{clearBridgePointer:e}=await import(`./bridgePointer-Clcvh52n.js`);await e(h)}console.error(`Error: Session ${m} not found. It may have been archived or expired, or your login may have lapsed (run \`claude /login\`).`),process.exit(1)}if(!t.environment_id){if(h){let{clearBridgePointer:e}=await import(`./bridgePointer-Clcvh52n.js`);await e(h)}console.error(`Error: Session ${m} has no environment_id. It may never have been attached to a bridge.`),process.exit(1)}Z=t.environment_id,y(`[bridge:init] Resuming session ${m} on environment ${Z}`)}let Q={dir:_,machineName:oe,branch:re,gitRepoUrl:ie,maxSessions:ne,spawnMode:Y,verbose:n,sandbox:r,bridgeId:se,workerType:`claude_code`,environmentId:je(),reuseEnvironmentId:Z,apiBaseUrl:z,sessionIngressUrl:B,debugFile:i,sessionTimeoutMs:a};y(`[bridge:init] bridgeId=${se}${Z?` reuseEnvironmentId=${Z}`:``} dir=${_} branch=${re} gitRepoUrl=${ie} machine=${oe}`),y(`[bridge:init] apiBaseUrl=${z} sessionIngressUrl=${B}`),y(`[bridge:init] sandbox=${r}${i?` debugFile=${i}`:``}`);let $,pe;try{let e=await ue.registerBridgeEnvironment(Q);$=e.environment_id,pe=e.environment_secret}catch(e){C(`tengu_bridge_registration_failed`,{status:e instanceof V?e.status:void 0}),console.error(e instanceof V&&e.status===404?`Remote Control environments are not available for your account.`:`Error: ${b(e)}`),process.exit(1)}let me;if(m)if(Z&&$!==Z)D(Error(`Bridge resume env mismatch: requested ${Z}, backend returned ${$}. Falling back to fresh session.`)),console.warn(`Warning: Could not resume session ${m} — its environment has expired. Creating a fresh session instead.`);else{let e=ae(m),t=e===m?[m]:[m,e],n=!1,r;for(let e of t)try{await ue.reconnectSession($,e),y(`[bridge:init] Session ${e} re-queued via bridge/reconnect`),me=m,n=!0;break}catch(t){r=t,y(`[bridge:init] reconnectSession(${e}) failed: ${b(t)}`)}if(!n){let e=r,t=e instanceof V;if(h&&t){let{clearBridgePointer:e}=await import(`./bridgePointer-Clcvh52n.js`);await e(h)}console.error(t?`Error: ${b(e)}`:`Error: Failed to reconnect session ${m}: ${b(e)}\nThe session may still be resumable — try running the same command again.`),process.exit(1)}}y(`[bridge:init] Registered, server environmentId=${$}`);let he=ve();C(`tengu_bridge_started`,{max_sessions:Q.maxSessions,has_debug_file:!!Q.debugFile,sandbox:Q.sandbox,verbose:Q.verbose,heartbeat_interval_ms:he.non_exclusive_heartbeat_interval_ms,spawn_mode:Q.spawnMode,spawn_mode_source:te,multi_session_gate:E,pre_create_session:X,worktree_available:q}),w(`info`,`bridge_started`,{max_sessions:Q.maxSessions,sandbox:Q.sandbox,spawn_mode:Q.spawnMode});let ge=Ke({execPath:process.execPath,scriptArgs:Qe(),env:process.env,verbose:n,sandbox:r,debugFile:i,permissionMode:o,onDebug:y,onActivity:(e,t)=>{y(`[bridge:activity] sessionId=${e} ${t.type} ${t.summary}`)},onPermissionRequest:(e,t,n)=>{y(`[bridge:perm] sessionId=${e} tool=${t.request.tool_name} request_id=${t.request_id} (not auto-approving)`)}}),_e=Le({verbose:n}),{parseGitHubRepository:ye}=await import(`./detectRepository-BLwSmun2.js`),be=ie?ye(ie):null,xe=be?be.split(`/`).pop():Ee(_);_e.setRepoInfo(xe,re);let Se=Y!==`single-session`&&q;Se&&_e.setSpawnModeDisplay(Y);let Ce=e=>{if(e[0]===3||e[0]===4){process.emit(`SIGINT`);return}if(e[0]===32){_e.toggleQr();return}if(e[0]===119){if(!Se)return;let e=Q.spawnMode===`same-dir`?`worktree`:`same-dir`;Q.spawnMode=e,C(`tengu_bridge_spawn_mode_toggled`,{spawn_mode:e}),_e.logStatus(e===`worktree`?`Spawn mode: worktree (new sessions get isolated git worktrees)`:`Spawn mode: same-dir (new sessions share the current directory)`),_e.setSpawnModeDisplay(e),_e.refreshDisplay(),R(t=>t.remoteControlSpawnMode===e?t:{...t,remoteControlSpawnMode:e});return}};process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.on(`data`,Ce));let Te=new AbortController,De=()=>{y(`[bridge:shutdown] SIGINT received, shutting down`),Te.abort()},Oe=()=>{y(`[bridge:shutdown] SIGTERM received, shutting down`),Te.abort()};process.on(`SIGINT`,De),process.on(`SIGTERM`,Oe);let Ae=me||null;if(X&&!me){let{createBridgeSession:e}=await import(`./createSession-Czx7_nf6.js`);try{Ae=await e({environmentId:$,title:s,events:[],gitRepoUrl:ie,branch:re,signal:Te.signal,baseUrl:z,getAccessToken:N,permissionMode:o}),Ae&&y(`[bridge:init] Created initial session ${Ae}`)}catch(e){y(`[bridge:init] Session creation failed (non-fatal): ${b(e)}`)}}let Me=null;if(Ae&&Y===`single-session`){let{writeBridgePointer:e}=await import(`./bridgePointer-Clcvh52n.js`),t={sessionId:Ae,environmentId:$,source:`standalone`};await e(Q.dir,t),Me=setInterval(e,3600*1e3,Q.dir,t),Me.unref?.()}try{await et(Q,$,pe,ue,ge,_e,Te.signal,void 0,Ae??void 0,async()=>(A(),await M(),N()))}finally{Me!==null&&clearInterval(Me),process.off(`SIGINT`,De),process.off(`SIGTERM`,Oe),process.stdin.off(`data`,Ce),process.stdin.isTTY&&process.stdin.setRawMode(!1),process.stdin.pause()}process.exit(0)}var _t=class extends Error{constructor(e){super(e),this.name=`BridgeHeadlessPermanentError`}};async function vt(e,t){let{dir:n,log:r}=e;process.chdir(n);let{setOriginalCwd:i,setCwdState:a}=await import(`./state-B2GIOsTB.js`);i(n),a(n);let{enableConfigs:o,checkHasTrustDialogAccepted:s}=await import(`./config-CJd9kJ57.js`);o();let{initSinks:c}=await import(`./sinks-BnkxTOU9.js`);if(c(),!s())throw new _t(`Workspace not trusted: ${n}. Run \`claude\` in that directory first to accept the trust dialog.`);if(!e.getAccessToken())throw Error(fe);let{getBridgeBaseUrl:l}=await import(`./bridgeConfig-B49H_B9L.js`),u=l();if(u.startsWith(`http://`)&&!u.includes(`localhost`)&&!u.includes(`127.0.0.1`))throw new _t(`Remote Control base URL uses HTTP. Only HTTPS or localhost HTTP is allowed.`);let d=process.env.CLAUDE_BRIDGE_SESSION_INGRESS_URL||u,{getBranch:f,getRemoteUrl:p,findGitRoot:m}=await import(`./git-hSvFiuiG.js`),{hasWorktreeCreateHook:h}=await import(`./hooks-DOej0jqp.js`);if(e.spawnMode===`worktree`&&!(h()||m(n)!==null))throw new _t(`Worktree mode requires a git repository or WorktreeCreate hooks. Directory ${n} has neither.`);let g=await f(),_=await p(),v=we(),y=je(),x={dir:n,machineName:v,branch:g,gitRepoUrl:_,maxSessions:e.capacity,spawnMode:e.spawnMode,verbose:!1,sandbox:e.sandbox,bridgeId:y,workerType:`claude_code`,environmentId:je(),apiBaseUrl:u,sessionIngressUrl:d,sessionTimeoutMs:e.sessionTimeoutMs},S=W({baseUrl:u,getAccessToken:e.getAccessToken,runnerVersion:`2.7.1`,onDebug:r,onAuth401:e.onAuth401,getTrustedDeviceToken:de}),C,w;try{let e=await S.registerBridgeEnvironment(x);C=e.environment_id,w=e.environment_secret}catch(e){throw Error(`Bridge registration failed: ${b(e)}`)}let T=Ke({execPath:process.execPath,scriptArgs:Qe(),env:process.env,verbose:!1,sandbox:e.sandbox,permissionMode:e.permissionMode,onDebug:r}),E=yt(r);E.printBanner(x,C);let D;if(e.createSessionOnStart){let{createBridgeSession:n}=await import(`./createSession-Czx7_nf6.js`);try{let i=await n({environmentId:C,title:e.name,events:[],gitRepoUrl:_,branch:g,signal:t,baseUrl:u,getAccessToken:e.getAccessToken,permissionMode:e.permissionMode});i&&(D=i,r(`created initial session ${i}`))}catch(e){r(`session pre-creation failed (non-fatal): ${b(e)}`)}}await et(x,C,w,S,T,E,t,void 0,D,async()=>e.getAccessToken())}function yt(e){let t=()=>{};return{printBanner:(t,n)=>e(`registered environmentId=${n} dir=${t.dir} spawnMode=${t.spawnMode} capacity=${t.maxSessions}`),logSessionStart:(t,n)=>e(`session start ${t}`),logSessionComplete:(t,n)=>e(`session complete ${t} (${n}ms)`),logSessionFailed:(t,n)=>e(`session failed ${t}: ${n}`),logStatus:e,logVerbose:e,logError:t=>e(`error: ${t}`),logReconnected:t=>e(`reconnected after ${t}ms`),addSession:(t,n)=>e(`session attached ${t}`),removeSession:t=>e(`session detached ${t}`),updateIdleStatus:t,updateReconnectingStatus:t,updateSessionStatus:t,updateSessionActivity:t,updateSessionCount:t,updateFailedStatus:t,setSpawnModeDisplay:t,setRepoInfo:t,setDebugLogPath:t,setAttached:t,setSessionTitle:t,clearStatus:t,toggleQr:t,refreshDisplay:t}}export{dt as a,rt as i,gt as n,vt as o,nt as r,et as s,_t as t};