Integrate per-user browser runtimes into subagent API
This commit is contained in:
parent
952b2e7d17
commit
280247e1e5
11 changed files with 777 additions and 21 deletions
|
|
@ -5,6 +5,7 @@ from typing import Any
|
|||
from api.clients.browser_rpc_contracts import BrowserRpcError, BrowserRpcRunner
|
||||
from api.domain.task_status import TaskStatus
|
||||
from api.repositories.task_store import TaskRecord, TaskStore
|
||||
from api.services.browser_runtime_manager import cleanup_browser_runtime, ensure_browser_runtime
|
||||
|
||||
|
||||
class TaskService:
|
||||
|
|
@ -108,20 +109,28 @@ class TaskService:
|
|||
await self._store.publish(task_id, self._event(task_id, "started", {"status": TaskStatus.running.value}))
|
||||
|
||||
async with self._semaphore:
|
||||
runtime: dict[str, str] | None = None
|
||||
try:
|
||||
if rec.cancel_requested:
|
||||
await self._store.set_cancelled(task_id)
|
||||
await self._store.publish(task_id, self._event(task_id, "cancelled", {"status": TaskStatus.cancelled.value}))
|
||||
return
|
||||
|
||||
runtime = await asyncio.to_thread(
|
||||
ensure_browser_runtime,
|
||||
task_id=task_id,
|
||||
metadata=rec.metadata,
|
||||
thread_id=rec.thread_id,
|
||||
)
|
||||
rpc_timeout = float(rec.timeout)
|
||||
if self._rpc_timeout_cap is not None:
|
||||
rpc_timeout = min(rpc_timeout, self._rpc_timeout_cap)
|
||||
|
||||
raw = await asyncio.wait_for(
|
||||
self._rpc_client.run(task=rec.task, timeout_sec=rpc_timeout),
|
||||
self._rpc_client.run(task=rec.task, timeout_sec=rpc_timeout, rpc_url=runtime.get("rpc_url")),
|
||||
timeout=float(rec.timeout) + 5,
|
||||
)
|
||||
raw = self._with_runtime_metadata(raw, runtime)
|
||||
success = bool(raw.get("success"))
|
||||
await self._store.set_done(
|
||||
task_id=task_id,
|
||||
|
|
@ -188,6 +197,16 @@ class TaskService:
|
|||
"status": failed.status.value,
|
||||
"error": failed.error,
|
||||
}))
|
||||
finally:
|
||||
try:
|
||||
await asyncio.to_thread(
|
||||
cleanup_browser_runtime,
|
||||
task_id=task_id,
|
||||
metadata=rec.metadata,
|
||||
thread_id=rec.thread_id,
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
async def _publish_history_events(self, rec: TaskRecord) -> None:
|
||||
for index, item in enumerate(rec.history, start=1):
|
||||
|
|
@ -225,3 +244,17 @@ class TaskService:
|
|||
normalized.append(event)
|
||||
return normalized
|
||||
|
||||
@staticmethod
|
||||
def _with_runtime_metadata(raw: dict[str, Any], runtime: dict[str, str] | None) -> dict[str, Any]:
|
||||
if not isinstance(raw, dict) or not runtime:
|
||||
return raw
|
||||
|
||||
enriched = dict(raw)
|
||||
browser_view = runtime.get("browser_view")
|
||||
if browser_view and not enriched.get("browser_view"):
|
||||
enriched["browser_view"] = browser_view
|
||||
enriched["isolation_mode"] = runtime.get("isolation_mode", "shared")
|
||||
owner_hash = runtime.get("owner_hash")
|
||||
if owner_hash:
|
||||
enriched["owner_hash"] = owner_hash
|
||||
return enriched
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue