Files
skill-template/tools/ui_inspector/models/action.py
chendelian 633ecff4e2 chore: archive tools/ui_inspector snapshot before migration removal.
Keep the last in-template copy on main so history can restore it; product continues in jiangchang-ui-recorder.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 11:19:14 +08:00

120 lines
3.7 KiB
Python

"""ActionRecord + ActionFlow models."""
from __future__ import annotations
import uuid
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, Optional
SCHEMA_ACTION = "openclaw.ui_inspector.action.v1"
SCHEMA_ACTION_FLOW = "openclaw.ui_inspector.action_flow.v1"
# Full vocabulary — capability flags live elsewhere for unimplemented types.
ACTION_TYPES: tuple[str, ...] = (
"click",
"double_click",
"right_click",
"fill",
"type",
"clear",
"press_key",
"hotkey",
"select",
"toggle",
"hover",
"scroll",
"drag_drop",
"focus",
"window_switch",
"navigation",
"checkpoint",
"wait",
"verify",
"unknown",
)
# Capability status for this Inspector release.
ACTION_CAPABILITY: dict[str, str] = {
"click": "implemented",
"double_click": "schema_only",
"right_click": "schema_only",
"fill": "implemented",
"type": "implemented", # aggregated into fill/type
"clear": "schema_only",
"press_key": "implemented",
"hotkey": "schema_only",
"select": "schema_only",
"toggle": "schema_only",
"hover": "schema_only",
"scroll": "schema_only",
"drag_drop": "schema_only",
"focus": "schema_only",
"window_switch": "schema_only",
"navigation": "partial",
"checkpoint": "implemented",
"wait": "schema_only",
"verify": "schema_only",
"unknown": "fallback",
}
def _now_iso() -> str:
return datetime.now().astimezone().isoformat()
def _new_id(prefix: str = "act") -> str:
return f"{prefix}_{uuid.uuid4().hex[:12]}"
@dataclass
class ActionRecord:
schema: str = SCHEMA_ACTION
id: str = field(default_factory=lambda: _new_id("act"))
sequence: int = 0
action_type: str = "unknown"
started_at: str = field(default_factory=_now_iso)
ended_at: Optional[str] = None
surface: str = "windows"
target_element_id: Optional[str] = None
target_snapshot: dict[str, Any] = field(default_factory=dict)
input: dict[str, Any] = field(default_factory=dict)
sensitive: bool = False
before_state_id: Optional[str] = None
after_state_id: Optional[str] = None
before_observation_id: Optional[str] = None
after_observation_id: Optional[str] = None
observed_changes: list[dict[str, Any]] = field(default_factory=list)
proposed_postconditions: list[dict[str, Any]] = field(default_factory=list)
status: str = "ok" # ok | partial | failed | skipped
confidence: float = 0.0
evidence: dict[str, Any] = field(default_factory=dict)
raw_event: dict[str, Any] = field(default_factory=dict)
raw_event_ids: list[str] = field(default_factory=list)
capability: str = ""
def __post_init__(self) -> None:
if self.action_type not in ACTION_TYPES:
self.action_type = "unknown"
if not self.capability:
self.capability = ACTION_CAPABILITY.get(self.action_type, "schema_only")
@dataclass
class ActionFlow:
schema: str = SCHEMA_ACTION_FLOW
flow_id: str = ""
flow_name: str = ""
created_at: str = field(default_factory=_now_iso)
ended_at: Optional[str] = None
states: list[str] = field(default_factory=list) # state ids in order seen
observations: list[str] = field(default_factory=list) # every concrete capture
actions: list[str] = field(default_factory=list) # action ids in sequence
elements: list[str] = field(default_factory=list) # element ids
entry_state_id: Optional[str] = None
final_state_id: Optional[str] = None
metadata: dict[str, Any] = field(default_factory=dict)
recording_mode: str = "auto" # auto | guided | checkpoint | legacy_interval
surface: str = ""
status: str = "open"