64 lines
1.9 KiB
Python
64 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
import threading
|
|
from pathlib import Path
|
|
from typing import Any, Callable
|
|
|
|
from openai import OpenAI
|
|
|
|
from .agent import ScreenJobAgent
|
|
from .models import AgentResult, RunArtifacts, RuntimeOptions
|
|
from .utils import setup_artifacts, setup_logger
|
|
|
|
try:
|
|
import pyautogui
|
|
except Exception as 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:
|
|
return OpenAI(api_key=api_key)
|
|
|
|
|
|
def run_job(
|
|
*,
|
|
api_key: str,
|
|
objective: str,
|
|
options: RuntimeOptions,
|
|
runs_base: Path,
|
|
no_failsafe: bool = False,
|
|
cancel_event: threading.Event | None = None,
|
|
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
|
|
|
|
artifacts = setup_artifacts(runs_base)
|
|
active_logger = logger or setup_logger(artifacts.log_file, verbose=True)
|
|
active_logger.info("ScreenJob booting. Artifacts: %s", str(artifacts.root_dir.resolve()))
|
|
active_logger.info("PyAutoGUI FAILSAFE=%s", pyautogui.FAILSAFE)
|
|
|
|
client = create_openai_client(api_key)
|
|
agent = ScreenJobAgent(
|
|
client=client,
|
|
logger=active_logger,
|
|
artifacts=artifacts,
|
|
options=options,
|
|
cancel_event=cancel_event,
|
|
event_callback=event_callback,
|
|
)
|
|
result = agent.run(objective)
|
|
active_logger.info("Run finished. completed=%s elapsed=%.2fs", result.completed, result.ended_at - result.started_at)
|
|
return result, artifacts
|