tui_app_server: open ChatGPT login in the local browser (#15672)

## Summary

Fixes ChatGPT login in `tui_app_server` so the local browser opens again
during in-process login flows.

## Root cause

The app-server backend intentionally starts ChatGPT login with browser
auto-open disabled, expecting the TUI client to open the returned
`auth_url`. The app-server TUI was not doing that, so the login URL was
shown in the UI but no browser window opened.

## Changes

- Add a helper that opens the returned ChatGPT login URL locally
- Call it from the main ChatGPT login flow
- Call it from the device-code fallback-to-browser path as well
- Limit auto-open to in-process app-server handles so remote sessions do
not try to open a browser against a remote localhost callback
This commit is contained in:
Eric Traut
2026-03-24 15:11:21 -06:00
committed by GitHub
Unverified
parent 989e513969
commit 1b86377635
2 changed files with 13 additions and 0 deletions
@@ -771,6 +771,7 @@ impl AuthModeWidget {
.await
{
Ok(LoginAccountResponse::Chatgpt { login_id, auth_url }) => {
maybe_open_auth_url_in_browser(&request_handle, &auth_url);
*error.write().unwrap() = None;
*sign_in_state.write().unwrap() =
SignInState::ChatGptContinueInBrowser(ContinueInBrowserState {
@@ -880,6 +881,16 @@ impl WidgetRef for AuthModeWidget {
}
}
pub(super) fn maybe_open_auth_url_in_browser(request_handle: &AppServerRequestHandle, url: &str) {
if !matches!(request_handle, AppServerRequestHandle::InProcess(_)) {
return;
}
if let Err(err) = webbrowser::open(url) {
tracing::warn!("failed to open browser for login URL: {err}");
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -29,6 +29,7 @@ use super::ContinueInBrowserState;
use super::ContinueWithDeviceCodeState;
use super::SignInState;
use super::mark_url_hyperlink;
use super::maybe_open_auth_url_in_browser;
use super::onboarding_request_id;
pub(super) fn start_headless_chatgpt_login(widget: &mut AuthModeWidget) {
@@ -289,6 +290,7 @@ async fn fallback_to_browser_login(
.await
{
Ok(LoginAccountResponse::Chatgpt { login_id, auth_url }) => {
maybe_open_auth_url_in_browser(&request_handle, &auth_url);
*error.write().unwrap() = None;
let _updated = set_device_code_state_for_active_attempt(
&sign_in_state,