From 2f954bddcf365985186006ba73adb8cf9735cdf4 Mon Sep 17 00:00:00 2001 From: Richard Abrich Date: Tue, 27 Jan 2026 17:19:06 -0500 Subject: [PATCH] fix(ci): resolve ruff linter and format errors - Move warnings.warn() after imports to fix E402 in viewer files - Remove unused imports (Any, base64, os, Service) to fix F401 - Remove f-string without placeholders to fix F541 - Apply ruff formatting to 5 files Files changed (7): - benchmarks/viewer.py - E402 fix - benchmarks/waa_deploy/api_agent.py - F401 + format - benchmarks/azure_ops_tracker.py - format only - benchmarks/vm_monitor.py - format only - cloud/local.py - format only - scripts/capture_screenshots.py - F401, F541 + format - training/viewer.py - E402 fix Co-Authored-By: Claude Opus 4.5 --- openadapt_ml/benchmarks/azure_ops_tracker.py | 24 ++++++++--- openadapt_ml/benchmarks/viewer.py | 17 ++++---- openadapt_ml/benchmarks/vm_monitor.py | 4 +- .../benchmarks/waa_deploy/api_agent.py | 41 ++++++++++--------- openadapt_ml/cloud/local.py | 24 ++++++++--- openadapt_ml/scripts/capture_screenshots.py | 9 ++-- openadapt_ml/training/viewer.py | 15 ++++--- 7 files changed, 79 insertions(+), 55 deletions(-) diff --git a/openadapt_ml/benchmarks/azure_ops_tracker.py b/openadapt_ml/benchmarks/azure_ops_tracker.py index 660dbf9..9459fdd 100644 --- a/openadapt_ml/benchmarks/azure_ops_tracker.py +++ b/openadapt_ml/benchmarks/azure_ops_tracker.py @@ -160,7 +160,9 @@ def start_operation( log_tail=[], # Clear stale logs started_at=self._start_time.isoformat(), elapsed_seconds=0.0, - eta_seconds=TYPICAL_DURATIONS.get(operation), # Use typical duration as initial ETA + eta_seconds=TYPICAL_DURATIONS.get( + operation + ), # Use typical duration as initial ETA cost_usd=0.0, hourly_rate_usd=self.hourly_rate, vm_ip=vm_ip, @@ -284,7 +286,9 @@ def parse_docker_build_line(self, line: str) -> dict[str, Any]: downloaded_unit = download_match.group(2) total = float(download_match.group(3)) total_unit = download_match.group(4) - result["download_bytes"] = int(downloaded * size_multipliers[downloaded_unit]) + result["download_bytes"] = int( + downloaded * size_multipliers[downloaded_unit] + ) result["download_total_bytes"] = int(total * size_multipliers[total_unit]) # Extract phase from buildx output @@ -384,7 +388,9 @@ def _update_progress(self) -> None: # ETA from download speed if self._status.download_bytes > 0 and self._status.elapsed_seconds > 1: - bytes_per_sec = self._status.download_bytes / self._status.elapsed_seconds + bytes_per_sec = ( + self._status.download_bytes / self._status.elapsed_seconds + ) remaining_bytes = ( self._status.download_total_bytes - self._status.download_bytes ) @@ -402,9 +408,15 @@ def _update_progress(self) -> None: remaining_steps = self._status.total_steps - self._status.step step_eta = time_per_step * remaining_steps # Use step ETA if we don't have download ETA or if step progress > download - if eta_seconds is None or step_pct > ( - self._status.download_bytes / max(self._status.download_total_bytes, 1) - ) * 100: + if ( + eta_seconds is None + or step_pct + > ( + self._status.download_bytes + / max(self._status.download_total_bytes, 1) + ) + * 100 + ): eta_seconds = step_eta # 3. Fallback: Use typical duration if no progress info diff --git a/openadapt_ml/benchmarks/viewer.py b/openadapt_ml/benchmarks/viewer.py index 51248bc..d2b6549 100644 --- a/openadapt_ml/benchmarks/viewer.py +++ b/openadapt_ml/benchmarks/viewer.py @@ -38,18 +38,10 @@ from __future__ import annotations -import warnings - -warnings.warn( - "openadapt_ml.benchmarks.viewer is deprecated. " - "Use openadapt_viewer instead: from openadapt_viewer import generate_benchmark_viewer", - DeprecationWarning, - stacklevel=2, -) - import base64 import json import logging +import warnings from pathlib import Path from typing import Any @@ -58,6 +50,13 @@ generate_shared_header_html as _generate_shared_header_html, ) +warnings.warn( + "openadapt_ml.benchmarks.viewer is deprecated. " + "Use openadapt_viewer instead: from openadapt_viewer import generate_benchmark_viewer", + DeprecationWarning, + stacklevel=2, +) + logger = logging.getLogger(__name__) diff --git a/openadapt_ml/benchmarks/vm_monitor.py b/openadapt_ml/benchmarks/vm_monitor.py index 52caf08..bda3362 100644 --- a/openadapt_ml/benchmarks/vm_monitor.py +++ b/openadapt_ml/benchmarks/vm_monitor.py @@ -1014,7 +1014,9 @@ def detect_vm_activity( return VMActivity( is_active=is_running, activity_type="benchmark_running" if is_running else "idle", - description="WAA benchmark running" if is_running else "WAA ready - idle", + description="WAA benchmark running" + if is_running + else "WAA ready - idle", benchmark_progress=probe_data, ) except json.JSONDecodeError: diff --git a/openadapt_ml/benchmarks/waa_deploy/api_agent.py b/openadapt_ml/benchmarks/waa_deploy/api_agent.py index 9eddfb6..2d4f416 100644 --- a/openadapt_ml/benchmarks/waa_deploy/api_agent.py +++ b/openadapt_ml/benchmarks/waa_deploy/api_agent.py @@ -43,7 +43,7 @@ import os import re from io import BytesIO -from typing import Any, Dict, List +from typing import Dict, List from PIL import Image @@ -210,6 +210,7 @@ def __init__( ) try: from anthropic import Anthropic + self._client = Anthropic(api_key=self.api_key) except ImportError: raise RuntimeError( @@ -225,6 +226,7 @@ def __init__( ) try: from openai import OpenAI + self._client = OpenAI(api_key=self.api_key) except ImportError: raise RuntimeError( @@ -240,9 +242,13 @@ def __init__( self.memory_block_text = "# empty memory block" self.step_counter = 0 - logger.info(f"ApiAgent initialized with provider={provider}, model={self.model}") + logger.info( + f"ApiAgent initialized with provider={provider}, model={self.model}" + ) if self.demo: - logger.info(f"Demo trajectory provided ({len(self.demo)} chars) - will persist across all steps") + logger.info( + f"Demo trajectory provided ({len(self.demo)} chars) - will persist across all steps" + ) def predict(self, instruction: str, obs: Dict) -> tuple: """Predict the next action based on observation. @@ -325,10 +331,9 @@ def predict(self, instruction: str, obs: Dict) -> tuple: # Add action history if enabled (enhanced: includes reasoning, not just raw actions) if self.use_history and self.history: # Use rich history with reasoning (like PC Agent-E) - history_entries = self.history[-self.history_cutoff:] + history_entries = self.history[-self.history_cutoff :] history_str = "\n\n".join( - f"[Step {i+1}] {entry}" - for i, entry in enumerate(history_entries) + f"[Step {i + 1}] {entry}" for i, entry in enumerate(history_entries) ) content_parts.append(f"History of previous steps:\n{history_str}") logs["history_entries"] = len(history_entries) @@ -381,14 +386,18 @@ def predict(self, instruction: str, obs: Dict) -> tuple: actions = [code_text] self.prev_actions.append(code_text) # Store rich history with reasoning (memory + action) - self._add_to_history(f"Thought: {self.memory_block_text}\nAction: {code_text}") + self._add_to_history( + f"Thought: {self.memory_block_text}\nAction: {code_text}" + ) else: # Try to extract action from response text action = self._parse_action_from_text(response_text, w, h) if action: actions = [action] self.prev_actions.append(action) - self._add_to_history(f"Thought: {self.memory_block_text}\nAction: {action}") + self._add_to_history( + f"Thought: {self.memory_block_text}\nAction: {action}" + ) else: logger.warning("Could not extract action from response") actions = ["# Could not parse action"] @@ -483,33 +492,25 @@ def _parse_action_from_text(self, text: str, width: int, height: int) -> str | N Python code string or None if parsing failed. """ # Try to find click coordinates - click_match = re.search( - r"click.*?(\d+)\s*,\s*(\d+)", text, re.IGNORECASE - ) + click_match = re.search(r"click.*?(\d+)\s*,\s*(\d+)", text, re.IGNORECASE) if click_match: x, y = int(click_match.group(1)), int(click_match.group(2)) return f"computer.click({x}, {y})" # Try to find type text - type_match = re.search( - r'type[:\s]+["\'](.+?)["\']', text, re.IGNORECASE - ) + type_match = re.search(r'type[:\s]+["\'](.+?)["\']', text, re.IGNORECASE) if type_match: text_to_type = type_match.group(1) return f'computer.type("{text_to_type}")' # Try to find key press - key_match = re.search( - r"press[:\s]+(\w+)", text, re.IGNORECASE - ) + key_match = re.search(r"press[:\s]+(\w+)", text, re.IGNORECASE) if key_match: key = key_match.group(1).lower() return f'computer.press("{key}")' # Try to find hotkey - hotkey_match = re.search( - r"hotkey[:\s]+(\w+)\s*\+\s*(\w+)", text, re.IGNORECASE - ) + hotkey_match = re.search(r"hotkey[:\s]+(\w+)\s*\+\s*(\w+)", text, re.IGNORECASE) if hotkey_match: key1, key2 = hotkey_match.group(1).lower(), hotkey_match.group(2).lower() return f'computer.hotkey("{key1}", "{key2}")' diff --git a/openadapt_ml/cloud/local.py b/openadapt_ml/cloud/local.py index e7f387c..1a54240 100644 --- a/openadapt_ml/cloud/local.py +++ b/openadapt_ml/cloud/local.py @@ -1078,11 +1078,17 @@ def do_GET(self): status["session_id"] = session.get("session_id") status["session_is_active"] = session.get("is_active", False) # Include accumulated time from previous sessions for hybrid display - status["accumulated_seconds"] = session.get("accumulated_seconds", 0.0) + status["accumulated_seconds"] = session.get( + "accumulated_seconds", 0.0 + ) # Calculate current session time (total - accumulated) - current_session_seconds = max(0, status["elapsed_seconds"] - status["accumulated_seconds"]) + current_session_seconds = max( + 0, status["elapsed_seconds"] - status["accumulated_seconds"] + ) status["current_session_seconds"] = current_session_seconds - status["current_session_cost_usd"] = (current_session_seconds / 3600) * session.get("hourly_rate_usd", 0.422) + status["current_session_cost_usd"] = ( + current_session_seconds / 3600 + ) * session.get("hourly_rate_usd", 0.422) try: tunnel_mgr = get_tunnel_manager() @@ -3212,12 +3218,18 @@ def compute_server_side_values(status: dict) -> dict: status["session_id"] = session.get("session_id") status["session_is_active"] = session.get("is_active", False) # Include accumulated time from previous sessions for hybrid display - status["accumulated_seconds"] = session.get("accumulated_seconds", 0.0) + status["accumulated_seconds"] = session.get( + "accumulated_seconds", 0.0 + ) # Calculate current session time (total - accumulated) - current_session_seconds = max(0, status["elapsed_seconds"] - status["accumulated_seconds"]) + current_session_seconds = max( + 0, status["elapsed_seconds"] - status["accumulated_seconds"] + ) status["current_session_seconds"] = current_session_seconds hourly_rate = session.get("hourly_rate_usd", 0.422) - status["current_session_cost_usd"] = (current_session_seconds / 3600) * hourly_rate + status["current_session_cost_usd"] = ( + current_session_seconds / 3600 + ) * hourly_rate try: tunnel_mgr = get_tunnel_manager() diff --git a/openadapt_ml/scripts/capture_screenshots.py b/openadapt_ml/scripts/capture_screenshots.py index c7597ea..b23e363 100644 --- a/openadapt_ml/scripts/capture_screenshots.py +++ b/openadapt_ml/scripts/capture_screenshots.py @@ -35,9 +35,7 @@ from __future__ import annotations import argparse -import base64 import datetime -import os import re import subprocess import sys @@ -108,7 +106,6 @@ def capture_web_page_selenium(url: str, output_path: Path) -> bool: try: from selenium import webdriver from selenium.webdriver.chrome.options import Options - from selenium.webdriver.chrome.service import Service options = Options() options.add_argument("--headless") @@ -358,7 +355,9 @@ def capture_vm_screenshot_from_vm(output_path: Path) -> bool: ) if result.returncode != 0: - print(f" VM screenshot failed: {result.stderr[:200] if result.stderr else 'Unknown error'}") + print( + f" VM screenshot failed: {result.stderr[:200] if result.stderr else 'Unknown error'}" + ) return False # The CLI saves to training_output/current/vm_screenshot.png @@ -499,7 +498,7 @@ def main(): print(f" OK: {output_path.name} ({size_kb:.1f} KB)") results[target] = str(output_path) else: - print(f" SKIP: Not available or capture failed") + print(" SKIP: Not available or capture failed") results[target] = None except Exception as e: print(f" ERROR: {e}") diff --git a/openadapt_ml/training/viewer.py b/openadapt_ml/training/viewer.py index 15e722c..df08e75 100644 --- a/openadapt_ml/training/viewer.py +++ b/openadapt_ml/training/viewer.py @@ -13,7 +13,14 @@ from __future__ import annotations +import json import warnings +from pathlib import Path + +from openadapt_ml.training.shared_ui import ( + get_shared_header_css as _get_shared_header_css, + generate_shared_header_html as _generate_shared_header_html, +) warnings.warn( "openadapt_ml.training.viewer is deprecated. " @@ -22,14 +29,6 @@ stacklevel=2, ) -import json -from pathlib import Path - -from openadapt_ml.training.shared_ui import ( - get_shared_header_css as _get_shared_header_css, - generate_shared_header_html as _generate_shared_header_html, -) - def _copy_transcript_and_audio(capture_path: Path | None, output_dir: Path) -> None: """Copy transcript.json and convert audio to mp3 for viewer playback.