export interface Point { x: number; y: number; } export interface Rect { x: number; y: number; width: number; height: number; } /** * 自动等待配置 */ export interface AutoWaitConfig { enable: boolean; delays: { afterFind?: number; afterClick?: number; afterType?: number; beforeAction?: number; }; } /** * 日志配置 */ export interface LoggingConfig { enable: boolean; level: 'debug' | 'info' | 'warn' | 'error'; showElementInfo?: boolean; showCoordinates?: boolean; } /** 缓存时间配置。null = 永不过期,number = 毫秒 */ export type CacheTime = number | null; export interface SDKConfig { baseUrl: string; timeout?: number; autoWait?: AutoWaitConfig; logging?: LoggingConfig; idleMotion?: IdleOptions; humanMonitor?: HumanMonitorStartOptions; scroll?: ScrollConfig; scrollToVisible?: ScrollToVisibleOptions; /** 图像算法族全局配置(findImage/clickImage/accel) */ image?: ImageConfig; speedFactor?: number; /** 全局元素缓存时间(毫秒),默认 null = 永不过期 */ cacheTime?: CacheTime; /** 图像匹配默认精度(0~1),默认 0.8 */ imagePrecision?: number; } export interface WindowSelector { title?: string; className?: string; processName?: string; processId?: number; } export interface WindowInfo { title: string; className: string; processId: number; processName: string; /** 窗口屏幕坐标矩形(物理像素)。可能为 undefined。 */ rect?: Rect; /** 父进程 PID。可能为 undefined(获取失败或旧版本服务未提供)。 */ parentPid?: number; /** 进程创建时间(Unix 毫秒,UTC)。可能为 undefined。 * 与 processId 组合可构成稳定身份标识(Windows 会复用 PID)。 */ createTime?: number; } export interface ElementQueryParams { window: string; element: string; runtimeId?: string; randomRange?: number; /** Chrome TreeWalker 回退开关(默认 true)。 * 当 Fast 模式 (ControlView) 的 descendant 步骤返回 0 结果时, * 自动回退到 Full 模式 (RawView) 重新搜索。 * 适用于 Chrome/WebView 的 UIA Provider 无法被 FindAll(Subtree) 穿透的场景。 * 设为 false 可禁用此回退行为。 */ chromeTreewalkerFallback?: boolean; } /** * find 系列函数的选项 */ export interface FindOptions { chromeTreewalkerFallback?: boolean; /** 元素属性名列表(element.ts 内部使用) */ propNames?: string[]; /** 元素缓存时间 ms(element.ts 内部使用) */ cacheTime?: number | null; /** * 图像加速(opt-in)。 * * 开启后:首次 UIA 查找截取元素图像缓存; * 后续调用优先 findImage,未命中抛错。 * `:all` 模式下此选项被忽略。 */ accel?: AccelConfig; /** @internal 轮询模式下抑制 ERROR 日志(waitFor/exists 使用) */ _silent?: boolean; } /** * 图像掩码:按百分比或像素去除动态区域。 * 截取元素图像时,从各边去除,仅保留中间区域作为模板。 * * 格式: * - `"50%"`:百分比(相对于图像对应边) * - `"2px"`:绝对像素(自动转为百分比) */ export interface ImageMask { /** 顶部去除 */ top?: string; /** 右边去除 */ right?: string; /** 底部去除 */ bottom?: string; /** 左边去除 */ left?: string; } /** * 图像加速配置。 * - `true`: 启用默认配置 * - 对象: 自定义模板路径和掩码 */ export type AccelConfig = boolean | { /** 模板缓存目录(默认: 系统临时目录下自动创建) */ templateDir?: string; /** 模板文件名(默认: 基于 xpath hash 自动生成) */ templateName?: string; /** * 模板掩码:截取时按百分比去除动态区域(0~100)。 * 例如按钮上半部有动态文字,设置 { top: 50 } 去掉上半部。 */ mask?: ImageMask; }; export interface ElementInfo { findSelector?: string; rect?: Rect; /** 元素真正可见、可点击的矩形区域(元素矩形 ∩ 窗口视口矩形) */ visibleRect?: Rect; center?: Point; centerRandom?: Point; /** 元素 RuntimeId(用于缓存快速查找) */ runtimeId?: string; controlType: string; name: string; automationId: string; className: string; frameworkId: string; helpText: string; localizedControlType: string; isEnabled: boolean; isOffscreen: boolean; isPassword: boolean; acceleratorKey: string; accessKey: string; itemType: string; itemStatus: string; processId: number; isCheckable?: boolean; isChecked?: boolean | null; isClickable?: boolean; isScrollable?: boolean; isSelected?: boolean | null; } import type { UiaElement } from './element'; /** * findAll 返回的扩展数组,支持 position() 方法。 */ export interface ElementList extends Array { /** 按 position 重新查询列表中第 N 个元素(1-based) */ position(n: number): Promise; } /** * 元素查找响应 * ElementInfo 以嵌套形式返回,SDK 直接消费。 */ export interface ElementResponse { found: boolean; findSelector: string; /** 匹配到的元素总数 */ total: number; error: string | null; element?: ElementInfo | null; } /** 导航步骤类型 */ export type NavigateStep = { type: 'parent'; levels: number; } | { type: 'child'; index: number; } | { type: 'sibling_abs'; index: number; } | { type: 'sibling_left'; offset: number; } | { type: 'sibling_right'; offset: number; }; /** 导航响应 */ export interface NavigateResponse { found: boolean; findSelector?: string; element?: ElementInfo | null; error?: string | null; } export interface MoveParams { target: Point; options?: MoveOptions; } export interface MoveResult { success: boolean; startPoint: Point; endPoint: Point; durationMs: number; error: string | null; } /** * ClickArea 边界值:支持数字、像素字符串、百分比字符串 * * - 数字 (0~1):向后兼容,等同百分比。`0.3` = `"30%"` * - `"10px"`:绝对 10 像素内缩 * - `"-5px"`:绝对 5 像素外扩(突破元素边界) * - `"30%"`:元素宽/高的 30% 内缩 * - `"-5%"`:元素宽/高的 5% 外扩 */ export type ClickAreaValue = number | string; /** * 点击区域(Inset 模型) * * 每个字段表示从元素对应边的**内缩量**(正值)或**外扩量**(负值): * - 正值 = 向元素中心收缩(内缩) * - 负值 = 向元素外部扩展(外扩) * * @example * // 元素内部中间 60% 区域(左右各缩 20%) * { left: "20%", right: "20%" } * // 等同旧写法(向后兼容) * { left: 0.2, right: 0.2 } * * // 元素右侧外侧 10px * { left: "210px", right: "-10px", top: "45%", bottom: "45%" } */ export interface ClickArea { /** 左边内缩量(正=右移,负=左扩) */ left?: ClickAreaValue; /** 右边内缩量(正=左移,负=右扩) */ right?: ClickAreaValue; /** 顶边内缩量(正=下移,负=上扩) */ top?: ClickAreaValue; /** 底边内缩量(正=上移,负=下扩) */ bottom?: ClickAreaValue; } /** 视口内边距值(支持像素或百分比) */ export type InsetValue = number | string; /** 视口内边距(用于排除固定遮挡区域如悬浮底部栏、顶部导航等) */ export interface ViewportInset { /** 左侧排除(像素数或百分比字符串如 "5%") */ left?: InsetValue; /** 顶部排除 */ top?: InsetValue; /** 右侧排除 */ right?: InsetValue; /** 底部排除 */ bottom?: InsetValue; } export interface ClickParams { window: WindowSelector | string; element: string; runtimeId?: string; /** 是否使用缓存(默认 true)。false: 忽略 runtimeId,直接走 XPath 搜索 */ useCache?: boolean; options?: ClickOptions; } export interface ClickedElement { controlType: string; name: string; } export interface ClickResult { success: boolean; clickPoint: Point; element: ClickedElement | null; error: string | null; } export interface TypeResult { success: boolean; charsTyped: number; durationMs: number; error: string | null; } export interface HumanDetectConfig { enable: boolean; pauseOnMouse?: boolean; pauseOnKeyboard?: boolean; resumeDelay?: number; } export interface IdleMotionParams { window: WindowSelector; xpath: string; speed?: 'slow' | 'normal' | 'fast'; moveInterval?: number; idleTimeout?: number; humanDetect?: HumanDetectConfig; } export type PauseReason = 'api_call' | 'human_mouse' | 'human_keyboard' | 'manual' | null; export interface IdleMotionStatus { active: boolean; paused: boolean; pauseReason: PauseReason; currentRect: Rect | null; runningDurationMs: number | null; lastActivityMs: number | null; } export interface StopResult { success: boolean; durationMs: number; error: string | null; } export interface HealthStatus { status: string; version: string; service: string; } export declare const DEFAULTS: { baseUrl: string; timeout: number; imagePrecision: number; speedFactor: number; image: { precision: number; accel: boolean; autoCache: boolean; usePositionCache: boolean; templateDir: string; }; move: { humanize: boolean; movePath: "curve"; duration: number; waitBefore: number; waitAfter: number; }; click: { humanize: boolean; randomRange: number; offset: string; waitBefore: number; waitAfter: number; }; idleMotion: { speed: "normal"; moveInterval: number; idleTimeout: number; humanDetect: { enable: boolean; pauseOnMouse: boolean; pauseOnKeyboard: boolean; resumeDelay: number; }; }; humanMonitor: { idleThreshold: number; pollInterval: number; detectKeyboard: boolean; mouseJitterPx: number; deviationPx: number; deviationCount: number; stationaryCount: number; safetyNetSecs: number; }; type: { charDelay: { min: number; max: number; }; waitBefore: number; waitAfter: number; }; autoWait: { enable: boolean; delays: { afterFind: number; afterClick: number; afterType: number; beforeAction: number; }; }; logging: { enable: boolean; level: "info"; showElementInfo: boolean; showCoordinates: boolean; }; scroll: { scrollAmount: number; times: number; timeout: number; useIdle: boolean; autoScrollAmount: boolean; scrollAmountRatio: number; scrollToCenter: boolean; centerAdjustTimes: number; scrollInterval: number; autoScrollDelay: number; minScrollRatio: number; centerSnapThreshold: number; }; scrollToVisible: { direction: "down"; timeout: number; scrollTimes: number; autoScrollAmount: boolean; scrollAmountRatio: number; scrollToCenter: boolean; centerAdjustTimes: number; scrollInterval: number; autoScrollDelay: number; minScrollRatio: number; centerSnapThreshold: number; scrollEndDetection: { mode: "bottomChangeRate"; bottomChangeThreshold: number; scrollbarWidth: number; sampleRatio: number; consecutiveFrames: number; saveDebugFrames: boolean; historyDepth: number; dynamicPixelEps: number; minDynamicRatio: number; }; scrollInset: { top: string; right: string; bottom: string; left: string; }; scrollFindThreading: { scrollIntervalMinMs: number; scrollIntervalMaxMs: number; matchIntervalMs: number; cursorMoveDurationMs: number; cursorMotionMode: "reading"; cursorMoveIntervalMs: number; cursorHorizontalRatio: number; scrollBatchSize: number; pixelStride: number; cpuThrottleMs: number; }; }; }; /** * 通用等待选项 - 适用于所有操作 */ export interface WaitTiming { waitBefore?: number; waitAfter?: number; } /** * 点击偏移配置 * * 支持两种形式: * 1. 预设位置:'top' | 'bottom' | 'left' | 'right' | 'center' * 2. 自定义表达式:如 'left+20%', 'top-10px', 'right-5%', 'bottom+15px' * - 参考边:left | right | top | bottom * - 运算符:+ | - * - 值:数字 + 单位 (% 或 px) */ export type ClickOffset = 'top' | 'bottom' | 'left' | 'right' | 'center' | string; /** * 点击选项 */ export interface ClickOptions extends WaitTiming { humanize?: boolean; randomRange?: number; button?: 'left' | 'right'; clickArea?: ClickArea; /** 点击偏移配置(优先级高于 clickArea) */ offset?: ClickOffset; /** 是否在点击位置显示圆点标记 */ showDot?: boolean; /** 圆点显示持续时间(ms),默认 3000 */ dotDuration?: number; /** * 点击前是否闪烁高亮元素框(调用 Element.flash())。 * - true: 使用默认闪烁参数(timeout=1000ms) * - 对象: 透传为 FlashOptions(如 { timeout: 2000 }) * - 默认 undefined: 不闪烁 * 可与 showDot 同时启用:先闪烁元素框,再点击并在点击位置画圆点。 */ flash?: boolean | FlashOptions; /** 点击模式:'mouse'=鼠标点击,'invoke'=InvokePattern 调用 */ clickMode?: 'mouse' | 'invoke'; /** 是否检查被遮挡(点击前检查元素是否被挡住) */ checkBlocked?: boolean; /** * 是否使用元素缓存(默认 true)。 * - true: 将 runtimeId 传给后端,走缓存路径(缓存未命中则报错) * - false: 忽略 runtimeId,直接走 XPath 搜索 */ useCache?: boolean; /** 图像加速:首次 UIA 查找截取元素图像,后续 findImage 加速 */ accel?: AccelConfig; } /** * 输入选项 */ export interface TypeOptions extends WaitTiming { charDelay?: { min: number; max: number; }; humanize?: boolean; /** 输入模式,默认 'key' * - 'key': 键盘模拟逐字输入(默认),支持 {Enter} 等虚拟键 * - 'set': UIA ValuePattern.SetValue(),直接设置控件文本值(无需焦点/可见) * - 'paste': 剪贴板粘贴 Ctrl+V,适合长文本 */ typeMode?: 'key' | 'set' | 'paste'; } /** * 移动选项 */ export interface MoveOptions extends WaitTiming { humanize?: boolean; /** 移动路径:'line'=直线,'curve'=曲线 */ movePath?: 'line' | 'curve'; duration?: number; } /** * 空闲移动选项 */ export interface IdleOptions { speed?: 'slow' | 'normal' | 'fast'; moveInterval?: number; /** 人工检测配置(检测到用户操作时自动暂停) */ humanDetect?: HumanDetectConfig; } /** * 滚动选项(Element 层和 Flow 层共用) * * 纯滚动职责:按方向和量滚动,不等待元素、不居中、不自适应。 * "滚到目标可见" 请用 {@link Element.scrollToVisible}。 */ export interface ScrollOptions { /** 滚动方向:'up'=视口上移看上方,'down'=视口下移看下方 */ direction: 'up' | 'down'; /** 总滚动量(WHEEL_DELTA 单位,120=1次滚轮),内部按 120/次拆分。优先于 times */ amount?: number; /** 滚动次数,默认 1。amount 优先时此字段被忽略 */ times?: number; /** 每次滚动间隔(ms),默认 300 */ scrollInterval?: number; /** Element 层专用:用于构造唯一 XPath 的属性名列表 */ propNames?: string[]; /** Flow 层专用:是否启用 pushIdle/popIdle,默认 false */ useIdle?: boolean; } /** * 图像算法族全局配置(findImage/clickImage/accel) */ export interface ImageConfig { /** 图像匹配默认精度(0~1),默认 0.8 */ precision?: number; /** 全局图像加速开关。默认 false(可用性优先,函数级显式 accel:true 开启) */ accel?: boolean; /** 首次 UIA 查找后自动截图缓存模板。默认 false */ autoCache?: boolean; /** 命中位置缓存(opt-in)。默认 false */ usePositionCache?: boolean; /** 模板缓存目录,默认 "./images" */ templateDir?: string; } /** * 图像算法族全局配置(findImage/clickImage/accel) */ export interface ImageConfig { /** 图像匹配默认精度(0~1),默认 0.8 */ precision?: number; /** 全局图像加速开关。默认 false(可用性优先,函数级显式 accel:true 开启) */ accel?: boolean; /** 首次 UIA 查找后自动截图缓存模板。默认 false */ autoCache?: boolean; /** 命中位置缓存(opt-in)。默认 false */ usePositionCache?: boolean; /** 模板缓存目录,默认 "./images" */ templateDir?: string; } /** * 图像算法族全局配置(findImage/clickImage/accel) */ export interface ImageConfig { /** 图像匹配默认精度(0~1),默认 0.8 */ precision?: number; /** 全局图像加速开关。默认 false(可用性优先,函数级显式 accel:true 开启) */ accel?: boolean; /** 首次 UIA 查找后自动截图缓存模板。默认 false */ autoCache?: boolean; /** 命中位置缓存(opt-in)。默认 false */ usePositionCache?: boolean; /** 模板缓存目录,默认 "./images" */ templateDir?: string; } /** * 滚动结果 */ export interface ScrollResult { success: boolean; scrolled: number; targetFound: boolean; /** 目标元素的矩形区域(仅当 targetFound=true 时有值) */ targetRect?: Rect; /** 目标元素在容器视口内可见的矩形区域(targetRect ∩ 容器rect) */ visibleRect?: Rect; /** 是否滚动到了边界(内容不再移动) */ scrolledToEnd?: boolean; error: string | null; } /** * 滚动配置 */ export interface ScrollConfig { /** 每次滚动量(WHEEL_DELTA 单位),默认 120 */ scrollAmount?: number; times?: number; timeout?: number; useIdle?: boolean; /** 是否自动计算滚动量 */ autoScrollAmount?: boolean; /** 容器高度倍率(0-1) */ scrollAmountRatio?: number; scrollToCenter?: boolean; /** 居中最大调整次数,默认 5 */ centerAdjustTimes?: number; /** 滚动间隔(毫秒),默认 1000 */ scrollInterval?: number; /** autoScrollAmount 首次滚动后延迟(毫秒),默认 1000 */ autoScrollDelay?: number; /** 最小滚动量比例,默认 0.1 */ minScrollRatio?: number; /** 居中吸附阈值,默认 0.10 */ centerSnapThreshold?: number; /** 视口内边距(排除固定遮挡区域) */ viewportInset?: ViewportInset; /** 平滑滚动步长(每次小步滚动的 delta),默认 40。设为 0 则使用原有 delta 逻辑。 * 注意:与 autoScrollAmount=true 互斥,autoScrollAmount 优先 */ smoothStepDelta?: number; } /** * 图像算法族全局配置(findImage/clickImage/accel) */ export interface ImageConfig { /** 图像匹配默认精度(0~1),默认 0.8 */ precision?: number; /** 全局图像加速开关。默认 false(可用性优先,函数级显式 accel:true 开启) */ accel?: boolean; /** 首次 UIA 查找后自动截图缓存模板。默认 false */ autoCache?: boolean; /** 命中位置缓存(opt-in)。默认 false */ usePositionCache?: boolean; /** 模板缓存目录,默认 "./images" */ templateDir?: string; } /** * 图像算法族全局配置(findImage/clickImage/accel) */ export interface ImageConfig { /** 图像匹配默认精度(0~1),默认 0.8 */ precision?: number; /** 全局图像加速开关。默认 false(可用性优先,函数级显式 accel:true 开启) */ accel?: boolean; /** 首次 UIA 查找后自动截图缓存模板。默认 false */ autoCache?: boolean; /** 命中位置缓存(opt-in)。默认 false */ usePositionCache?: boolean; /** 模板缓存目录,默认 "./images" */ templateDir?: string; } /** * 图像算法族全局配置(findImage/clickImage/accel) */ export interface ImageConfig { /** 图像匹配默认精度(0~1),默认 0.8 */ precision?: number; /** 全局图像加速开关。默认 false(可用性优先,函数级显式 accel:true 开启) */ accel?: boolean; /** 首次 UIA 查找后自动截图缓存模板。默认 false */ autoCache?: boolean; /** 命中位置缓存(opt-in)。默认 false */ usePositionCache?: boolean; /** 模板缓存目录,默认 "./images" */ templateDir?: string; } /** * scrollToVisible 选项 */ export interface ScrollToVisibleOptions { direction?: 'up' | 'down'; timeout?: number; scrollTimes?: number; /** 是否自动计算滚动量,默认 true */ autoScrollAmount?: boolean; /** 容器高度倍率(0-1),默认 0.8 */ scrollAmountRatio?: number; /** 每次滚动后的等待时间(ms),默认 1000 */ scrollInterval?: number; scrollToCenter?: boolean; /** 居中最大调整次数,默认 5 */ centerAdjustTimes?: number; /** autoScrollAmount 首次滚动后延迟(毫秒),默认 1000 */ autoScrollDelay?: number; /** 最小滚动量比例,默认 0.1 */ minScrollRatio?: number; /** 居中吸附阈值,默认 0.10 */ centerSnapThreshold?: number; /** 视口内边距(排除固定遮挡区域) */ viewportInset?: ViewportInset; /** 平滑滚动步长(每次小步滚动的 delta),默认 40。设为 0 则使用原有 delta 逻辑。 * 注意:与 autoScrollAmount=true 互斥,autoScrollAmount 优先 */ smoothStepDelta?: number; /** 图像加速:首次 UIA 查找截取元素图像,后续 findImage 加速 */ accel?: AccelConfig; /** 滚动到底检测配置 */ scrollEndDetection?: { /** 检测模式:'scrollbar'=右侧滚动条区域对比(默认),'bottomChangeRate'=底部区域变化率 */ mode?: 'scrollbar' | 'bottomChangeRate'; /** 底部区域变化率阈值(< 此值视为到底),默认 0.02 */ bottomChangeThreshold?: number; /** 滚动条宽度(像素),默认 17 */ scrollbarWidth?: number; /** 底部采样比例(0~1),默认 0.2 */ sampleRatio?: number; /** 连续多少帧变化率低才判定到底,默认 3 */ consecutiveFrames?: number; /** 是否保存最后两帧截图(调试用),默认 false */ saveDebugFrames?: boolean; /** 跨帧对比深度 x:rate = max(rate(N,N-1), rate(N,N-x)),默认 3 */ historyDepth?: number; /** 像素级变化阈值(标 dynamic 用,0~1),默认 0.02 (≈5/255) */ dynamicPixelEps?: number; /** dynamic 像素占比下限(护栏,0~1),低于此值不判 reached,默认 0.1 */ minDynamicRatio?: number; }; /** 滚动位置 inset:在容器内随机位置滚动(拟人化)。复用 ClickArea 模式。 */ scrollInset?: { top?: string; right?: string; bottom?: string; left?: string; }; /** 三线程参数配置 */ scrollFindThreading?: { scrollIntervalMinMs?: number; scrollIntervalMaxMs?: number; matchIntervalMs?: number; cursorMoveDurationMs?: number; /** 光标移动模式:"reading"=阅读式水平扫视(5s 0-1次),"off"=不移动,"random"=原随机游走。默认 "reading" */ cursorMotionMode?: 'reading' | 'off' | 'random'; /** 光标移动间隔(ms),reading 模式下为平均间隔(实际 0.5x~1.5x 抖动),默认 5000 */ cursorMoveIntervalMs?: number; /** 水平移动占比 (0-1),reading 模式下垂直移动幅度 = (1-ratio) * 区域高度,默认 0.8 */ cursorHorizontalRatio?: number; scrollBatchSize?: number; pixelStride?: number; cpuThrottleMs?: number; }; } /** * scrollToVisible 返回结果 */ export interface ScrollToVisibleResult { /** 目标元素是否可见 */ visible: boolean; /** 是否滚动到了边界(内容不再移动) */ scrolledToEnd: boolean; /** 实际滚动次数 */ scrolled: number; /** 目标元素的矩形区域 */ targetRect?: Rect; /** 目标元素在容器视口内可见的矩形区域(targetRect ∩ 容器rect) */ visibleRect?: Rect; } /** * 滚动边界检测结果 */ export interface ScrollDetectResult { success: boolean; /** 是否到达边界(排除exclude后,所有监控元素位置均未变化) */ atEnd: boolean; /** 监控的元素总数(排除后) */ watchedCount: number; /** 发生位置变化的元素数 */ changedCount: number; /** 变化元素的详情列表 */ details: ScrollDetectElementChange[]; /** 是否执行了反向回滚 */ rolledBack: boolean; error: string | null; } /** * 元素变化详情(滚动前后对比) */ export interface ScrollDetectElementChange { /** 元素标识(automationId / name / className 组合) */ identifier: string; /** 滚动前 bound.top */ beforeTop?: number; /** 滚动后 bound.top */ afterTop?: number; /** bound.top 变化量 */ deltaTop?: number; /** isOffscreen 是否变化 */ offscreenChanged: boolean; } /** * 滚动边界检测方向 */ export type ScrollDetectDirection = 'up' | 'down'; /** * 元素可视区域位置结果 */ export interface ElementVisibilityResult { /** 是否找到元素 */ found: boolean; /** UIA 的 IsOffscreen 属性 */ isOffscreen: boolean | null; /** 可视性:fully_visible / partially_visible / offscreen / not_found / error / unknown */ visibility: string; /** 相对位置:above / below / left / right / inside / unknown */ position: string; /** 元素的边界矩形 */ elementRect: Rect | null; /** 元素真正可见、可点击的矩形区域(元素矩形 ∩ 容器矩形 ∩ 视口矩形) */ visibleRect: Rect | null; /** 窗口(视口)的边界矩形 */ viewportRect: Rect | null; /** 各方向超出视口的像素数(正值=超出,0=在视口内) */ overflow: { /** 元素顶部超出视口顶部的像素 */ top: number; /** 元素底部超出视口底部的像素 */ bottom: number; /** 元素左侧超出视口左侧的像素 */ left: number; /** 元素右侧超出视口右侧的像素 */ right: number; } | null; /** 建议滚动方向:up / down / left / right */ scrollDirection: string | null; /** 错误信息 */ error: string | null; } /** * 元素高亮闪烁选项 */ export interface FlashOptions { timeout?: number; } /** * 元素高亮闪烁结果 */ export interface FlashResult { success: boolean; elementRect: Rect | null; error: string | null; } /** * Inspect 区域过滤类型 * * 基于当前元素(父元素)的 Rect,将区域划分为 5 个部分: * - top: 上半部分 * - bottom: 下半部分 * - left: 左半部分 * - right: 右半部分 * - center: 中心区域(各边内缩 25%) * * 仅保留与指定区域有非零 RECT 交集的子元素。 */ export type InspectRegion = 'top' | 'bottom' | 'left' | 'right' | 'center'; /** * Inspect 区域过滤选项 */ export interface InspectRegionFilter { /** 过滤区域:仅保留与该区域有交集的元素 */ region: InspectRegion; /** 区域占比(0~1),默认 0.5。例如 region='top', ratio=0.3 表示上 30% 区域 */ ratio?: number; } /** * Inspect 选项 */ export interface InspectOptions { /** 返回格式:'json'(默认)返回结构化树,'txt'/'text' 返回缩进文本 */ format?: 'json' | 'txt' | 'text'; /** 用于唯一标识当前元素的属性名列表 */ propNames?: string[]; /** 仅保留可见元素(isOffscreen === false)。regionFilter 启用时自动生效 */ visibleOnly?: boolean; /** 区域过滤:仅保留与指定区域有 RECT 交集的子元素(前提:isOffscreen === false) */ regionFilter?: InspectRegionFilter; } /** * Inspect 返回的单个节点信息 */ export interface InspectNodeInfo { /** 元素层级深度(根元素为 0) */ depth: number; /** 控件类型,如 "Button"、"Text"、"Edit" 等 */ controlType: string; /** 控件的 Name 属性 */ name: string; /** 控件的 ClassName 属性 */ className: string; /** 控件的 AutomationId 属性 */ automationId: string; /** 控件的 FrameworkId 属性 */ frameworkId: string; /** 控件的文本内容(通过 ValuePattern 获取) */ textValue?: string; /** 控件的 HelpText 属性(辅助说明文字) */ helpText?: string; /** 控件的 ItemType 属性 */ itemType?: string; /** 控件的 ItemStatus 属性 */ itemStatus?: string; /** 控件的区域位置 */ rect: Rect | null; /** 是否在屏幕外 */ isOffscreen: boolean; /** 选中该控件相对于根元素的 XPath 表达式 */ xpath: string; /** 从根元素导航到此控件的罗盘路径(如 "c1>0",根元素自身为 "") */ compass: string; /** 子节点列表 */ children: InspectNodeInfo[]; } /** * Inspect 扁平节点信息(无 children 嵌套,方便遍历和过滤) */ export interface FlatInspectNodeInfo { /** 元素层级深度(根元素为 0) */ depth: number; /** 控件类型,如 "Button"、"Text"、"Edit" 等 */ controlType: string; /** 控件的 Name 属性 */ name: string; /** 控件的 ClassName 属性 */ className: string; /** 控件的 AutomationId 属性 */ automationId: string; /** 控件的 FrameworkId 属性 */ frameworkId: string; /** 控件的文本内容(通过 ValuePattern 获取) */ textValue?: string; /** 控件的 HelpText 属性(辅助说明文字) */ helpText?: string; /** 控件的 ItemType 属性 */ itemType?: string; /** 控件的 ItemStatus 属性 */ itemStatus?: string; /** 控件的区域位置 */ rect: Rect | null; /** 是否在屏幕外 */ isOffscreen: boolean; /** 选中该控件相对于根元素的 XPath 表达式 */ xpath: string; /** 从根元素导航到此控件的罗盘路径(如 "c1>0",根元素自身为 "") */ compass: string; } /** * Inspect 过滤条件 */ export interface InspectFilter { /** 按 name 包含匹配(模糊) */ name?: string; /** 按 controlType 精确匹配 */ controlType?: string; /** 按 className 包含匹配(模糊) */ className?: string; /** 按 automationId 包含匹配(模糊) */ automationId?: string; /** 按 textValue 包含匹配(模糊) */ textValue?: string; /** 按 helpText 包含匹配(模糊) */ helpText?: string; } /** * Inspect 请求参数 */ export interface InspectRequest { /** 窗口选择器 XPath */ window: string; /** 目标元素 XPath(inspect 此元素下的所有子元素) */ element: string; /** 元素 RuntimeId(优先于 XPath 搜索) */ runtimeId?: string; /** 返回格式:'json'(默认)或 'txt' */ format?: 'json' | 'txt'; } /** * Inspect 响应 */ export interface InspectResponse { /** 是否成功 */ success: boolean; /** 根元素 XPath */ rootXpath: string; /** 结构化节点树(format='json' 时有值) */ nodes: InspectNodeInfo | null; /** 扁平化节点列表(DFS 顺序,方便遍历和过滤) */ flatNodes: FlatInspectNodeInfo[]; /** 格式化文本(format='txt'/'text' 时有值) */ text: string | null; /** 子元素总数 */ totalChildren: number; /** 错误信息 */ error: string | null; /** * 过滤 flatNodes,返回匹配的节点列表。 * * 支持两种调用方式: * 1. 回调函数(与 Array.filter 一致):可自由编写任意过滤逻辑 * 2. InspectFilter 对象:字符串条件为包含匹配,controlType 为精确匹配 * * @param predicate - 回调函数或过滤条件对象 * @returns 匹配的扁平节点列表 * * @example * const result = await element.inspect(); * // 回调函数形式(推荐,灵活度最高) * const items = result.filter(node => node.name.includes('新华社')); * const items2 = result.filter(node => node.name.indexOf('sssss') > 0); * const buttons = result.filter(node => node.controlType === 'Button'); * const deep = result.filter((node, i) => node.depth > 2 && i < 10); * * // 对象条件形式(便捷简写) * const items3 = result.filter({ name: '新华社' }); * const buttons2 = result.filter({ controlType: 'Button' }); */ filter(predicate: (node: FlatInspectNodeInfo, index: number, array: FlatInspectNodeInfo[]) => unknown): FlatInspectNodeInfo[]; filter(filter: InspectFilter): FlatInspectNodeInfo[]; } /** * 性能统计 */ export interface ProfileStats { startTime: number; endTime: number; totalTime: number; operations: Array<{ type: string; duration: number; timestamp: number; details?: any; }>; } /** * POST /api/element/refresh 请求 */ export interface RefreshByRuntimeIdRequest { window: string; runtimeId: string; } /** * POST /api/element/refresh 响应 */ export interface RefreshByRuntimeIdResponse { found: boolean; element: ElementInfo | null; error: string | null; } /** * PUT /api/element/cache/config 请求 */ export interface CacheConfigRequest { /** 全局缓存时间(毫秒),null = 永不过期 */ cacheTime?: number | null; } /** * GET /api/element/cache/stats 响应 */ export interface CacheStatsResponse { size: number; maxSize: number; defaultCacheTime: number | null; } /** * POST /api/element/find-from 请求(从 RuntimeId 缓存元素查找子元素) */ export interface FindFromElementRequest { /** 父元素的 RuntimeId */ runtimeId: string; /** 相对于父元素的 XPath 表达式 */ xpath: string; /** 搜索策略 */ searchStrategy?: 'Fast' | 'Full'; /** 随机偏移范围 */ randomRange?: number; } /** * POST /api/element/find-from 响应 */ export interface FindFromElementResponse { found: boolean; elements: ElementInfo[]; total: number; error: string | null; /** 未找到原因(如 InvalidParent / LeafNotUnique / StepNotFound 等) */ notFoundReason?: NotFoundReason; } /** * 未找到元素的原因(与后端 NotFoundReason 枚举对应) */ export type NotFoundReason = 'WindowNotFound' | { ChildHwndNotFound: { class: string; }; } | { StepNotFound: { step: number; xpath_step: string; }; } | 'ElementGone' | { Timeout: { budget_ms: number; elapsed_ms: number; }; } | { LeafNotUnique: { candidates: number; }; } | { InvalidParent: { runtime_id: string; }; }; /** * 鼠标悬停参数 */ export interface HoverMouseParams { window: string; element: string; runtimeId?: string; duration?: number; humanize?: boolean; } /** * 拖拽参数 */ export interface DragMouseParams { window: string; sourceElement: string; sourceRuntimeId?: string; targetElement: string; targetRuntimeId?: string; duration?: number; } /** * 导航请求参数(带 runtimeId) */ export interface NavigateRequest { window: string; element: string; runtimeId?: string; steps: NavigateStep[]; } export interface ScreenshotCaptureRequest { x: number; y: number; width: number; height: number; } export interface ScreenshotCaptureResponse { success: boolean; base64?: string; width?: number; height?: number; error?: string; } export interface FindImageRequest { templateBase64: string; precision?: number; algorithm?: 'segmented' | 'fft'; region?: { x: number; y: number; width: number; height: number; }; /** 模板截取时的 DPI(来自 meta.json)。后端据此自动缩放模板。 */ templateDpi?: number; } export interface FindImageMatch { /** 命中矩形中心 X(屏幕绝对坐标) */ x: number; /** 命中矩形中心 Y(屏幕绝对坐标) */ y: number; /** 命中矩形宽 */ width: number; /** 命中矩形高 */ height: number; confidence: number; } export interface FindImageResponse { found: boolean; matches: FindImageMatch[]; error?: string; /** 0 命中时的全局最高相似度(诊断用,后端仅 0 命中时返回) */ bestScore?: number; } export interface SaveElementImageRequest { x: number; y: number; width: number; height: number; savePath: string; } export interface SaveElementImageResponse { success: boolean; path?: string; error?: string; } /** * findImage 选项 * * region 语义: * - `'window'`(或省略):当前窗口矩形(**默认**) * - `'element'`:scrollContainer 指定的元素矩形(用于 scrollToImage) * - `Rect`:屏幕绝对坐标矩形 */ export interface FindImageOptions { precision?: number; algorithm?: 'segmented' | 'fft'; region?: 'window' | 'element' | Rect; /** region='element' 时传入的滚动容器 XPath(仅 scrollToImage 使用) */ scrollContainer?: string; /** * 启用命中位置缓存(默认关闭)。 * * 开启后:首次全窗口搜索,命中后记住归一化坐标;下次同模板 * 优先在上次命中位置的 2×2 子区域内搜索,未命中再 fallback 全窗口。 * * 适用于重复脚本中控件位置相对固定的场景(如微信底部输入框)。 */ usePositionCache?: boolean; /** 等待超时 ms(仅 waitFor / waitUntil 系列使用) */ timeout?: number; /** 轮询间隔 ms(仅 waitFor / waitUntil 系列使用) */ interval?: number; } /** * clickImage 点击行为选项(不含 findImage 选项) */ export interface ImageClickOptions { /** 选第几个命中(0 起),默认 0。all=true 时忽略此字段 */ nth?: number; /** 鼠标按键,默认 left */ button?: 'left' | 'right'; /** 是否双击 */ doubleClick?: boolean; /** 是否依次点击所有命中(返回 FindImageMatch 数组而非单个) */ all?: boolean; /** * 点击区域(Inset 模型,与元素族 ClickArea 类型一致) * * 不传:命中矩形中心。传了:根据各边内缩量从中心偏移后点击。 */ clickArea?: ClickArea; } /** * 人介入监控状态(GET /api/human-monitor/status 响应) */ export interface HumanMonitorStatus { /** 是否正在监控 */ monitoring: boolean; /** 是否检测到人介入(鼠标主动移动) */ humanActive: boolean; /** 距上次人活动经过的毫秒数(无人活动时为 null) */ lastActivityMs: number | null; } /** * SSE 推送的事件载荷(GET /api/human-monitor/events 的 data 行) */ export interface HumanMonitorEvent { /** 是否检测到人介入 */ humanActive: boolean; /** Unix 时间戳(毫秒) */ ts: number; /** 距上次人活动经过的毫秒数(无人活动时为 null) */ lastActivityMs: number | null; } /** * 启动人介入监控的选项 */ export interface HumanMonitorStartOptions { /** 人离开恢复阈值(ms):无任何输入超过此时间后恢复 RPA,默认 5000 */ idleThreshold?: number; /** 轮询间隔(ms),默认 100 */ pollInterval?: number; /** 使用 GetLastInputInfo 检测键盘输入(否则仅鼠标),默认 true */ detectKeyboard?: boolean; /** 鼠标抖动阈值(px),默认 2 */ mouseJitterPx?: number; /** 轨迹偏离阈值(px),默认 50 */ deviationPx?: number; /** 连续偏离次数,默认 3 */ deviationCount?: number; /** server_moving=true 分支静止恢复次数,默认 10 */ stationaryCount?: number; /** 安全网超时(秒),默认 30 */ safetyNetSecs?: number; }