mirror of
https://github.com/usestrix/strix.git
synced 2026-09-15 23:31:27 +00:00
88 lines
2.3 KiB
Python
88 lines
2.3 KiB
Python
import inspect
|
|
|
|
from pytest_check import check
|
|
|
|
from . import console as ui
|
|
|
|
|
|
class Browser:
|
|
def __init__(self, agent_id, agent_state=None):
|
|
self._agent_id = agent_id
|
|
self._agent_state = agent_state
|
|
|
|
def _call(self, action, **kwargs):
|
|
import asyncio
|
|
|
|
from strix.tools.browser.browser_actions import browser_action
|
|
from strix.tools.context import set_current_agent_id
|
|
|
|
from .conftest import _bg_loop
|
|
|
|
async def _run():
|
|
set_current_agent_id(self._agent_id)
|
|
return await browser_action(
|
|
agent_state=self._agent_state,
|
|
action=action,
|
|
**kwargs,
|
|
)
|
|
|
|
future = asyncio.run_coroutine_threadsafe(_run(), _bg_loop)
|
|
result = future.result(timeout=120)
|
|
if "screenshot" in result:
|
|
result["screenshot"] = "[Image]"
|
|
return result
|
|
|
|
def __getattr__(self, action):
|
|
def call(**kwargs):
|
|
result = self._call(action, **kwargs)
|
|
if "error" in result:
|
|
Fail(result).error(result["error"])
|
|
return result
|
|
|
|
return call
|
|
|
|
|
|
def act_parallel(tasks):
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
def _run_one(browser, kwargs):
|
|
action = kwargs.pop("action")
|
|
return getattr(browser, action)(**kwargs)
|
|
|
|
with ThreadPoolExecutor(max_workers=len(tasks)) as pool:
|
|
futures = [pool.submit(_run_one, b, dict(kw)) for b, kw in tasks]
|
|
return [f.result(timeout=120) for f in futures]
|
|
|
|
|
|
def _caller_test_name():
|
|
for frame in inspect.stack():
|
|
if frame.function.startswith("test_"):
|
|
return frame.function
|
|
return "unknown"
|
|
|
|
|
|
class Fail:
|
|
def __init__(self, result=None):
|
|
self._result = result
|
|
self._name = _caller_test_name()
|
|
|
|
def expected(self, value):
|
|
self._expected = value
|
|
return self
|
|
|
|
def got(self, value):
|
|
self._emit(f"expected {self._expected!r}, got {value!r}")
|
|
|
|
def error(self, msg):
|
|
self._emit(msg)
|
|
|
|
def _emit(self, reason):
|
|
ui.log_error(f" \\[{self._name}] {reason}")
|
|
ui.record_failure(
|
|
self._name,
|
|
self._name,
|
|
reason,
|
|
self._result,
|
|
)
|
|
with check:
|
|
check.fail(f"[{self._name}] {reason}")
|