MCPcopy Create free account
hub / github.com/Mnexa-AI/e2a / waitForBrowserLogin

Function waitForBrowserLogin

cli/src/commands/login.ts:115–236  ·  view source on GitHub ↗
(apiUrl: string, timeoutMs = LOGIN_TIMEOUT_MS)

Source from the content-addressed store, hash-verified

113};
114
115async function waitForBrowserLogin(apiUrl: string, timeoutMs = LOGIN_TIMEOUT_MS): Promise<BrowserLoginResult> {
116 const cliState = randomBytes(16).toString("hex");
117
118 let settled = false;
119 let server: Server | null = null;
120 // Single timeout handle that's cleared in finish() and the outer
121 // finally — earlier versions had two setTimeouts and one of them
122 // wasn't cleared on success, keeping the Node event loop alive for
123 // the full timeout (2 min) after a successful login. Symptom was
124 // the terminal hanging after "Logged in to <host>" printed.
125 let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
126
127 try {
128 return await new Promise<BrowserLoginResult>((resolve, reject) => {
129 const finish = async (value: BrowserLoginResult | Error, isError: boolean) => {
130 if (settled) return;
131 settled = true;
132 if (timeoutHandle) clearTimeout(timeoutHandle);
133 if (server) {
134 await closeServer(server);
135 }
136 if (isError) reject(value);
137 else resolve(value as BrowserLoginResult);
138 };
139
140 timeoutHandle = setTimeout(
141 () => void finish(new Error("timed out waiting for browser login"), true),
142 timeoutMs,
143 );
144
145 server = createServer(async (req, res) => {
146 res.setHeader("Connection", "close");
147 try {
148 if (req.method !== "POST") {
149 res.statusCode = 405;
150 res.setHeader("Content-Type", "text/html; charset=utf-8");
151 res.end(renderCallbackPage("Return to your terminal", "Run e2a login again to finish connecting the CLI."));
152 return;
153 }
154
155 const body = await readRequestBody(req);
156 const params = new URLSearchParams(body);
157 const returnedState = params.get("cli_state") || "";
158 const apiKey = params.get("api_key") || "";
159 const agentEmail = params.get("agent_email") || "";
160 const error = params.get("error") || "";
161
162 if (returnedState != cliState) {
163 res.statusCode = 400;
164 res.setHeader("Content-Type", "text/html; charset=utf-8");
165 res.end(renderCallbackPage("e2a login failed", "The browser login state did not match this terminal session. Return to the terminal and try again."));
166 await finish(new Error("browser login state mismatch"), true);
167 return;
168 }
169
170 if (error) {
171 res.statusCode = 400;
172 res.setHeader("Content-Type", "text/html; charset=utf-8");

Callers 1

loginFunction · 0.85

Calls 10

finishFunction · 0.85
renderCallbackPageFunction · 0.85
readRequestBodyFunction · 0.85
buildBrowserLoginURLFunction · 0.85
hostLabelFunction · 0.85
openBrowserFunction · 0.85
closeServerFunction · 0.85
onMethod · 0.80
getMethod · 0.45
listenMethod · 0.45

Tested by

no test coverage detected