test: add pytest verification suite and gitea ci workflow
All checks were successful
CI / test (push) Successful in 48s

This commit is contained in:
Space-Banane
2026-05-27 17:55:34 +02:00
parent 8fe6ad2d75
commit a19b285232
9 changed files with 360 additions and 13 deletions

View File

@@ -18,9 +18,10 @@ from .utils import clamp, draw_global_grid, image_to_data_url, utc_now_iso
try:
import pyautogui
except Exception as import_exc:
raise RuntimeError(
"pyautogui is required. Install dependencies with: pip install pyautogui pillow"
) from import_exc
pyautogui = None # type: ignore[assignment]
_PYAUTOGUI_IMPORT_ERROR = import_exc
else:
_PYAUTOGUI_IMPORT_ERROR = None
SYSTEM_PROMPT = """
@@ -52,6 +53,12 @@ class ScreenJobAgent:
cancel_event: threading.Event | None = None,
event_callback: Callable[[dict[str, Any]], None] | None = None,
) -> None:
if pyautogui is None:
raise RuntimeError(
"pyautogui is required for agent execution. "
"Install dependencies and ensure GUI access. "
f"Import error: {_PYAUTOGUI_IMPORT_ERROR}"
)
self.client = client
self.logger = logger
self.artifacts = artifacts
@@ -784,4 +791,3 @@ class ScreenJobAgent:
usage=self.usage,
error=result_text,
)

View File

@@ -14,9 +14,10 @@ from .utils import setup_artifacts, setup_logger
try:
import pyautogui
except Exception as import_exc:
raise RuntimeError(
"pyautogui is required. Install dependencies with: pip install pyautogui pillow"
) from import_exc
pyautogui = None # type: ignore[assignment]
_PYAUTOGUI_IMPORT_ERROR = import_exc
else:
_PYAUTOGUI_IMPORT_ERROR = None
def create_openai_client(api_key: str) -> OpenAI:
@@ -34,6 +35,12 @@ def run_job(
event_callback: Callable[[dict[str, Any]], None] | None = None,
logger: logging.Logger | None = None,
) -> tuple[AgentResult, RunArtifacts]:
if pyautogui is None:
raise RuntimeError(
"pyautogui is required for runtime execution. "
"Install dependencies and ensure GUI access. "
f"Import error: {_PYAUTOGUI_IMPORT_ERROR}"
)
pyautogui.FAILSAFE = not no_failsafe
pyautogui.PAUSE = 0.05
@@ -54,4 +61,3 @@ def run_job(
result = agent.run(objective)
active_logger.info("Run finished. completed=%s elapsed=%.2fs", result.completed, result.ended_at - result.started_at)
return result, artifacts

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
import asyncio
import secrets
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Any
@@ -73,20 +74,22 @@ def create_app(config: AppConfig | None = None) -> FastAPI:
if not app_config.screenjob_token:
raise RuntimeError("SCREENJOB_TOKEN is required in environment or .env.")
app = FastAPI(title="ScreenJob API", version="1.0.0")
db = HistoryDB(app_config.db_path)
ws_hub = _WebSocketHub()
manager = JobManager(config=app_config, db=db, broadcast=ws_hub.broadcast_from_thread)
@asynccontextmanager
async def lifespan(_: FastAPI):
ws_hub.set_loop(asyncio.get_running_loop())
yield
app = FastAPI(title="ScreenJob API", version="1.0.0", lifespan=lifespan)
app.state.config = app_config
app.state.db = db
app.state.ws_hub = ws_hub
app.state.manager = manager
@app.on_event("startup")
async def _on_startup() -> None:
ws_hub.set_loop(asyncio.get_running_loop())
def _extract_token(
authorization: str | None,
x_screenjob_token: str | None,