mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
fix: latch xAI OAuth callback result
This commit is contained in:
parent
eac198b6d5
commit
0d63661702
2 changed files with 39 additions and 5 deletions
|
|
@ -2372,6 +2372,7 @@ def _make_xai_callback_handler(expected_path: str) -> tuple[type[BaseHTTPRequest
|
|||
"error": None,
|
||||
"error_description": None,
|
||||
}
|
||||
result_lock = threading.Lock()
|
||||
|
||||
class _XAICallbackHandler(BaseHTTPRequestHandler):
|
||||
def _maybe_write_cors_headers(self) -> None:
|
||||
|
|
@ -2398,16 +2399,27 @@ def _make_xai_callback_handler(expected_path: str) -> tuple[type[BaseHTTPRequest
|
|||
return
|
||||
|
||||
params = parse_qs(parsed.query)
|
||||
result["code"] = params.get("code", [None])[0]
|
||||
result["state"] = params.get("state", [None])[0]
|
||||
result["error"] = params.get("error", [None])[0]
|
||||
result["error_description"] = params.get("error_description", [None])[0]
|
||||
incoming = {
|
||||
"code": params.get("code", [None])[0],
|
||||
"state": params.get("state", [None])[0],
|
||||
"error": params.get("error", [None])[0],
|
||||
"error_description": params.get("error_description", [None])[0],
|
||||
}
|
||||
# ThreadingHTTPServer allows a fallback/manual callback to complete
|
||||
# while a browser connection is stuck. Once we have a terminal
|
||||
# OAuth result (code or error), keep the first one so a later
|
||||
# concurrent/invalid callback cannot overwrite state before
|
||||
# validation in _xai_oauth_loopback_login().
|
||||
if incoming["code"] or incoming["error"]:
|
||||
with result_lock:
|
||||
if not (result["code"] or result["error"]):
|
||||
result.update(incoming)
|
||||
|
||||
self.send_response(200)
|
||||
self._maybe_write_cors_headers()
|
||||
self.send_header("Content-Type", "text/html; charset=utf-8")
|
||||
self.end_headers()
|
||||
if result["error"]:
|
||||
if incoming["error"]:
|
||||
body = "<html><body><h1>xAI authorization failed.</h1>You can close this tab.</body></html>"
|
||||
else:
|
||||
body = "<html><body><h1>xAI authorization received.</h1>You can close this tab.</body></html>"
|
||||
|
|
|
|||
|
|
@ -304,6 +304,28 @@ def test_xai_callback_server_accepts_fallback_code_while_browser_connection_is_s
|
|||
thread.join(timeout=1.0)
|
||||
|
||||
|
||||
def test_xai_callback_server_latches_first_terminal_callback_result():
|
||||
server, thread, result, redirect_uri = _xai_start_callback_server(preferred_port=0)
|
||||
try:
|
||||
with urllib.request.urlopen(f"{redirect_uri}?code=first-code&state=state-1", timeout=2) as response:
|
||||
assert response.status == 200
|
||||
with urllib.request.urlopen(
|
||||
f"{redirect_uri}?error=access_denied&error_description=late&state=state-2",
|
||||
timeout=2,
|
||||
) as response:
|
||||
body = response.read().decode("utf-8")
|
||||
assert response.status == 200
|
||||
assert "xAI authorization failed" in body
|
||||
assert result["code"] == "first-code"
|
||||
assert result["state"] == "state-1"
|
||||
assert result["error"] is None
|
||||
assert result["error_description"] is None
|
||||
finally:
|
||||
server.shutdown()
|
||||
server.server_close()
|
||||
thread.join(timeout=1.0)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Token roundtrip + reads
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue