"""L2 Locator 抽象层基类:GeomSpec + Selector + ElementHandle。 GeomSpec:几何定位规格(relative_to / ratio / offset) Selector:UI 元素选择器(kind / by_image / by_geom / threshold / require_image) ElementHandle:定位结果句柄(绝对坐标 + 置信度 + 策略) L3 Actions 通过 Selector 描述要找的元素,LocatorRegistry 解析为 ElementHandle(图像命中或几何兜底),Actions 据此调 Backend 执行点击。 """ from __future__ import annotations from dataclasses import dataclass from typing import Optional @dataclass class GeomSpec: """几何定位规格。 relative_to 取值:window / window_top_left / window_bottom_right(语义占位, 实际计算统一用 ratio + offset,offset 已含正负号区分方向)。 所有字段带默认值,避免构造时必填字段顺序问题。 """ relative_to: str = "window" x_ratio: float = 0.0 y_ratio: float = 0.0 x_offset: int = 0 y_offset: int = 0 @dataclass class Selector: """UI 元素选择器。 kind:元素类别键(如 search_box / send_button / input_box) by_image:图像模板名(P2 启用),非空时优先图像匹配 by_geom:几何规格,非空时图像失败或 P1 阶段走几何兜底 threshold:图像匹配置信度阈值(默认 0.80) require_image:高风险操作为 True 时,图像失败即拒绝执行 description:人类可读描述 所有字段带默认值。 """ kind: str = "" by_image: Optional[str] = None by_geom: Optional[GeomSpec] = None threshold: float = 0.80 require_image: bool = False description: str = "" @dataclass class ElementHandle: """定位结果句柄。 selector:来源 Selector(回溯用) x / y:元素中心绝对坐标(点击点) w / h:元素宽高(图像匹配时返回,几何兜底为 0) confidence:匹配置信度(图像命中时为模型分数,几何兜底为 1.0) strategy:定位策略 image / geom 所有字段带默认值。 """ selector: Optional[Selector] = None x: int = 0 y: int = 0 w: int = 0 h: int = 0 confidence: float = 1.0 strategy: str = "geom" @property def center(self) -> tuple[int, int]: """返回元素中心点(x, y)。""" return (self.x, self.y)