Implement Apex Agent MVP scaffold
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import asdict, is_dataclass
|
||||
from datetime import date, datetime
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
class ArtifactStore:
|
||||
def __init__(self, root: str | Path = "tasks/history") -> None:
|
||||
self.root = Path(root)
|
||||
|
||||
def task_dir(self, task_id: str) -> Path:
|
||||
return self.root / task_id
|
||||
|
||||
def write_step(
|
||||
self,
|
||||
*,
|
||||
task_id: str,
|
||||
index: int,
|
||||
screenshot: bytes | None,
|
||||
record: dict[str, Any],
|
||||
) -> dict[str, str | None]:
|
||||
task_dir = self.task_dir(task_id)
|
||||
task_dir.mkdir(parents=True, exist_ok=True)
|
||||
stem = f"{index:03d}"
|
||||
screenshot_path: Path | None = None
|
||||
if screenshot is not None:
|
||||
screenshot_path = task_dir / f"{stem}.png"
|
||||
screenshot_path.write_bytes(screenshot)
|
||||
|
||||
json_path = task_dir / f"{stem}.json"
|
||||
payload = {
|
||||
**record,
|
||||
"screenshot_path": str(screenshot_path) if screenshot_path else None,
|
||||
}
|
||||
json_path.write_text(
|
||||
json.dumps(_jsonable(payload), ensure_ascii=False, indent=2),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return {
|
||||
"json_path": str(json_path),
|
||||
"screenshot_path": str(screenshot_path) if screenshot_path else None,
|
||||
}
|
||||
|
||||
def read_steps(self, task_id: str) -> list[dict[str, Any]]:
|
||||
task_dir = self.task_dir(task_id)
|
||||
if not task_dir.exists():
|
||||
return []
|
||||
steps = []
|
||||
for path in sorted(task_dir.glob("*.json")):
|
||||
steps.append(json.loads(path.read_text(encoding="utf-8")))
|
||||
return steps
|
||||
|
||||
|
||||
def _jsonable(value: Any) -> Any:
|
||||
if hasattr(value, "to_dict"):
|
||||
return value.to_dict()
|
||||
if is_dataclass(value):
|
||||
return asdict(value)
|
||||
if isinstance(value, dict):
|
||||
return {key: _jsonable(inner) for key, inner in value.items()}
|
||||
if isinstance(value, list):
|
||||
return [_jsonable(inner) for inner in value]
|
||||
if isinstance(value, tuple):
|
||||
return [_jsonable(inner) for inner in value]
|
||||
if isinstance(value, (datetime, date)):
|
||||
return value.isoformat()
|
||||
return value
|
||||
|
||||
Reference in New Issue
Block a user