fix(desktop): address Copilot review on xAI loopback flow

- web_server: join the callback-server thread in the start error path so a
  failed discovery/URL build doesn't leave a daemon thread running
- web_server: loopback worker now bails if the session was cancelled while
  waiting for the callback or exchanging the code, instead of persisting
  tokens the user no longer wants (+ regression test)
- onboarding: fall back to window.open when the desktop bridge's
  openExternal is unavailable, so the flow never silently stalls
This commit is contained in:
Brooklyn Nicholson 2026-06-02 17:55:22 -05:00
parent 63e824831c
commit 3be9fb7317
3 changed files with 76 additions and 2 deletions

View file

@ -3540,12 +3540,17 @@ def _start_xai_loopback_flow() -> Dict[str, Any]:
)
except Exception:
# Binding succeeded but URL construction failed — release the socket
# so we don't leak a listener on the loopback port.
# and join the serving thread so we don't leak a listener (or a
# lingering daemon thread) on the loopback port.
try:
server.shutdown()
server.server_close()
except Exception:
pass
try:
thread.join(timeout=1.0)
except Exception:
pass
raise
sid, sess = _new_oauth_session("xai-oauth", "loopback")
@ -3589,6 +3594,14 @@ def _xai_loopback_worker(session_id: str) -> None:
s["status"] = "error"
s["error_message"] = message
def _cancelled() -> bool:
# The session is removed from the registry when the user cancels
# (DELETE /sessions/{id}). If that happened while we were blocked on
# the callback or token exchange, abort instead of persisting tokens
# the user no longer wants.
with _oauth_sessions_lock:
return session_id not in _oauth_sessions
try:
callback = hauth._xai_wait_for_callback(
sess["server"],
@ -3600,6 +3613,9 @@ def _xai_loopback_worker(session_id: str) -> None:
_fail(f"xAI authorization timed out: {exc}")
return
if _cancelled():
return
if callback.get("error"):
detail = callback.get("error_description") or callback["error"]
_fail(f"xAI authorization failed: {detail}")
@ -3638,6 +3654,8 @@ def _xai_loopback_worker(session_id: str) -> None:
"expires_in": payload.get("expires_in"),
"token_type": str(payload.get("token_type") or "Bearer").strip() or "Bearer",
}
if _cancelled():
return
hauth._save_xai_oauth_tokens(
tokens,
discovery=sess.get("discovery"),