diff --git a/agent/copilot_acp_client.py b/agent/copilot_acp_client.py index 027defa22b..457b32b37b 100644 --- a/agent/copilot_acp_client.py +++ b/agent/copilot_acp_client.py @@ -477,8 +477,8 @@ class CopilotACPClient: proc.stdin.write(json.dumps(payload) + "\n") proc.stdin.flush() - deadline = time.time() + timeout_seconds - while time.time() < deadline: + deadline = time.monotonic() + timeout_seconds + while time.monotonic() < deadline: if proc.poll() is not None: break try: diff --git a/hermes_cli/auth.py b/hermes_cli/auth.py index 0e12e7157d..1bcb1af77f 100644 --- a/hermes_cli/auth.py +++ b/hermes_cli/auth.py @@ -894,7 +894,7 @@ def _file_lock( lock_path.write_text(" ", encoding="utf-8") with lock_path.open("r+" if msvcrt else "a+") as lock_file: - deadline = time.time() + max(1.0, timeout_seconds) + deadline = time.monotonic() + max(1.0, timeout_seconds) while True: try: if fcntl: @@ -904,7 +904,7 @@ def _file_lock( msvcrt.locking(lock_file.fileno(), msvcrt.LK_NBLCK, 1) break except (BlockingIOError, OSError, PermissionError): - if time.time() >= deadline: + if time.monotonic() >= deadline: raise TimeoutError(timeout_message) time.sleep(0.05) @@ -1974,9 +1974,9 @@ def _spotify_wait_for_callback( thread = threading.Thread(target=server.serve_forever, kwargs={"poll_interval": 0.1}, daemon=True) thread.start() - deadline = time.time() + max(5.0, timeout_seconds) + deadline = time.monotonic() + max(5.0, timeout_seconds) try: - while time.time() < deadline: + while time.monotonic() < deadline: if result["code"] or result["error"]: return result time.sleep(0.1) @@ -2739,10 +2739,10 @@ def _poll_for_token( poll_interval: int, ) -> Dict[str, Any]: """Poll the token endpoint until the user approves or the code expires.""" - deadline = time.time() + max(1, expires_in) + deadline = time.monotonic() + max(1, expires_in) current_interval = max(1, min(poll_interval, DEVICE_AUTH_POLL_INTERVAL_CAP_SECONDS)) - while time.time() < deadline: + while time.monotonic() < deadline: response = client.post( f"{portal_base_url}/api/oauth/token", data={ diff --git a/hermes_cli/copilot_auth.py b/hermes_cli/copilot_auth.py index 348e4efe83..7475f80a2b 100644 --- a/hermes_cli/copilot_auth.py +++ b/hermes_cli/copilot_auth.py @@ -212,9 +212,9 @@ def copilot_device_code_login( print(" Waiting for authorization...", end="", flush=True) # Step 3: Poll for completion - deadline = time.time() + timeout_seconds + deadline = time.monotonic() + timeout_seconds - while time.time() < deadline: + while time.monotonic() < deadline: time.sleep(interval + _DEVICE_CODE_POLL_SAFETY_MARGIN) poll_data = urllib.parse.urlencode({ diff --git a/hermes_cli/gateway.py b/hermes_cli/gateway.py index 232f8dac80..c751ced8ae 100644 --- a/hermes_cli/gateway.py +++ b/hermes_cli/gateway.py @@ -585,10 +585,10 @@ def _wait_for_systemd_service_restart( svc = get_service_name() scope_label = _service_scope_label(system).capitalize() - deadline = time.time() + timeout + deadline = time.monotonic() + timeout printed_runtime_wait = False - while time.time() < deadline: + while time.monotonic() < deadline: props = _read_systemd_unit_properties(system=system) active_state = props.get("ActiveState", "") sub_state = props.get("SubState", "") diff --git a/hermes_cli/web_server.py b/hermes_cli/web_server.py index 5469cff607..5527039cf1 100644 --- a/hermes_cli/web_server.py +++ b/hermes_cli/web_server.py @@ -1877,8 +1877,8 @@ async def _start_device_code_flow(provider_id: str) -> Dict[str, Any]: name=f"oauth-codex-{sid[:6]}", ).start() # Block briefly until the worker has populated the user_code, OR error. - deadline = time.time() + 10 - while time.time() < deadline: + deadline = time.monotonic() + 10 + while time.monotonic() < deadline: with _oauth_sessions_lock: s = _oauth_sessions.get(sid) if s and (s.get("user_code") or s["status"] != "pending"): @@ -2012,10 +2012,10 @@ def _codex_full_login_worker(session_id: str) -> None: sess["expires_at"] = time.time() + sess["expires_in"] # Step 2: poll until authorized - deadline = time.time() + sess["expires_in"] + deadline = time.monotonic() + sess["expires_in"] code_resp = None with httpx.Client(timeout=httpx.Timeout(15.0)) as client: - while time.time() < deadline: + while time.monotonic() < deadline: time.sleep(poll_interval) poll = client.post( f"{issuer}/api/accounts/deviceauth/token",