@solazah/solazah-runtime 0.1.124 → 0.1.134

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solazah/solazah-runtime",
3
- "version": "0.1.124",
3
+ "version": "0.1.134",
4
4
  "main": "index.cjs",
5
5
  "module": "index.js",
6
6
  "types": "types/index.d.ts",
package/types/Plugin.d.ts CHANGED
@@ -4,6 +4,11 @@ export interface PluginTool {
4
4
  cb: (args: any) => Promise<string> | string;
5
5
  description: string;
6
6
  schema: object | null;
7
+ timeoutMs?: number;
8
+ }
9
+ export interface PluginToolOptions {
10
+ /** 宿主等待回执的上限(毫秒),给执行耗时长的工具(如跑一段脚本)用 */
11
+ timeoutMs?: number;
7
12
  }
8
13
  export default class Plugin {
9
14
  private ipcRenderer;
@@ -15,14 +20,16 @@ export default class Plugin {
15
20
  name: string;
16
21
  description: string;
17
22
  schema: object | null;
23
+ timeoutMs: number | undefined;
18
24
  }[];
19
25
  /**
20
26
  * 给 Otta 注册 AI 工具。
21
27
  * schema 传 JSON Schema 对象(如 z.toJSONSchema(...) 的返回值),无参工具传 null;
22
28
  * cb 收到已按 schema 拆包的参数对象(无参工具收到 {}),返回字符串给 LLM(返回对象会被 JSON.stringify)。
29
+ * options.timeoutMs 是宿主等待回执的上限,执行耗时长的工具要显式给。
23
30
  * 同名重复注册为覆盖(HMR 安全)。
24
31
  */
25
- tool: (name: string, description: string, schema: object | null, cb: (args: any) => Promise<string> | string) => (args: any) => Promise<string> | string;
32
+ tool: (name: string, description: string, schema: object | null, cb: (args: any) => Promise<string> | string, options?: PluginToolOptions) => (args: any) => Promise<string> | string;
26
33
  onSearch: (commandName: string, handler: any) => Promise<void>;
27
34
  onAction: (commandName: string, action: string, handler: any) => Promise<void>;
28
35
  /**
@@ -57,4 +57,26 @@ export default class SystemMouse {
57
57
  * @returns 操作完成后兑现的 Promise。
58
58
  */
59
59
  rightClickAt: (point: Point) => Promise<any>;
60
+ /**
61
+ * 按住鼠标从 from 拖到 to 再松开。
62
+ *
63
+ * @param from 起点屏幕坐标 `{x, y}`。
64
+ * @param to 终点屏幕坐标 `{x, y}`。
65
+ * @param options `{button?, smooth?, durationMs?}`;smooth 为真时按插值路径逐步移动,给靠 mousemove 判定拖拽的应用用。
66
+ * @returns 无返回。
67
+ */
68
+ drag: (from: Point, to: Point, options?: {
69
+ button?: "left" | "right" | "middle";
70
+ smooth?: boolean;
71
+ durationMs?: number;
72
+ }) => Promise<any>;
73
+ /**
74
+ * 滚动滚轮。
75
+ *
76
+ * @param dx 水平格数,正数向右。
77
+ * @param dy 垂直格数,正数向上。
78
+ * @param at 可选,先把鼠标移到此屏幕坐标再滚。
79
+ * @returns 无返回。
80
+ */
81
+ scroll: (dx: number, dy: number, at?: Point) => Promise<any>;
60
82
  }
@@ -0,0 +1,60 @@
1
+ import { default as IpcRenderer } from './IpcRenderer';
2
+ export interface RecorderStartOptions {
3
+ /** 帧率,缺省 4 */
4
+ fps?: number;
5
+ /** 结束录制的键(虚拟键码),缺省 F12;这一下本身不进轨迹 */
6
+ stopKey?: number;
7
+ /** 时长上限,缺省 10 分钟 */
8
+ maxMs?: number;
9
+ }
10
+ export interface RecorderStatus {
11
+ supported: boolean;
12
+ active: boolean;
13
+ id: string | null;
14
+ elapsedMs: number;
15
+ events: number;
16
+ frames: number;
17
+ /** 运行中的反作弊进程名;有它在时低层钩子整体收不到输入 */
18
+ antiCheat: string[];
19
+ }
20
+ export interface RecorderResult {
21
+ id: string;
22
+ /** 轨迹目录绝对路径 */
23
+ dir: string;
24
+ /** 轨迹目录在工作空间「图片」目录下的相对路径:scripts/_recordings/<id> */
25
+ relPath: string;
26
+ events: number;
27
+ frames: number;
28
+ durationMs: number;
29
+ stoppedBy: "hotkey" | "api" | "timeout";
30
+ }
31
+ export default class SystemRecorder {
32
+ private transport;
33
+ constructor(transport?: IpcRenderer);
34
+ /**
35
+ * 开始录制用户操作:低层钩子收鼠标键盘、定时截主屏,每个按下/抬起/按键带上前后帧与那一刻的前台窗口。
36
+ * 只记事实,不做任何手势归并;录制期间每一拍向发起方视图推 `recorder.progress`(RecorderStatus)。
37
+ * 产物落在工作空间「图片」目录 scripts/_recordings/<id>/:trajectory.json + frames/*.png。
38
+ *
39
+ * @param options `{fps?, stopKey?, maxMs?}`,缺省 4 帧/秒、F12 结束、10 分钟上限。
40
+ * @returns `{id, dir, relPath, antiCheat}`;antiCheat 非空表示有反作弊进程在跑,钩子会整体收不到输入。
41
+ * @throws 平台不支持(目前仅 Windows)、已有录制在进行、钩子安装失败时抛错。
42
+ */
43
+ start: (options?: RecorderStartOptions) => Promise<{
44
+ id: string;
45
+ dir: string;
46
+ relPath: string;
47
+ antiCheat: string[];
48
+ }>;
49
+ /**
50
+ * 结束录制并写出轨迹。按 stopKey 结束的录制不必再调。
51
+ *
52
+ * @returns `{id, dir, relPath, events, frames, durationMs, stoppedBy}`。
53
+ * @throws 没有进行中的录制时抛错。
54
+ */
55
+ stop: () => Promise<RecorderResult>;
56
+ /**
57
+ * 录制状态:是否支持、是否进行中、已录事件数与帧数、运行中的反作弊进程。
58
+ */
59
+ status: () => Promise<RecorderStatus>;
60
+ }
@@ -1,5 +1,33 @@
1
1
  import { default as IpcRenderer } from './IpcRenderer';
2
2
  import { Point } from '@computer-use/nut-js';
3
+ /** 屏幕原生坐标系里的矩形。 */
4
+ export interface ScreenRect {
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ }
10
+ export interface FindImageOptions {
11
+ /** 匹配阈值 0..1,缺省 0.8 */
12
+ confidence?: number;
13
+ /** 只在此区域内找,结果仍是屏幕坐标 */
14
+ searchRegion?: ScreenRect;
15
+ /** 固定模板缩放;省略则按常见显示缩放自适应 */
16
+ scale?: number;
17
+ /** findAll 最多返回几个 */
18
+ maxResults?: number;
19
+ }
20
+ export interface WaitOptions {
21
+ /** 缺省 5000 */
22
+ timeoutMs?: number;
23
+ /** 缺省 500 */
24
+ intervalMs?: number;
25
+ }
26
+ export interface FindTextOptions {
27
+ searchRegion?: ScreenRect;
28
+ /** OCR 检测缩放比,小于 1 更快但更粗 */
29
+ detRatio?: number;
30
+ }
3
31
  export default class SystemScreen {
4
32
  private transport;
5
33
  constructor(transport?: IpcRenderer);
@@ -35,33 +63,116 @@ export default class SystemScreen {
35
63
  */
36
64
  getCursorPoint: () => Promise<any>;
37
65
  /**
38
- * 在当前屏幕中查找与给定模板图片匹配的区域,返回匹配区域中心坐标。
39
- * 使用 nut-js 图像匹配引擎在屏幕中搜索模板。
66
+ * 在当前屏幕中查找与模板图片匹配的区域,返回屏幕原生坐标系里的矩形。
67
+ *
68
+ * @param base64String 模板图片的 Base64(支持 `data:image/...;base64,` 前缀)。
69
+ * @param options `{confidence?, searchRegion?, scale?}`;scale 省略时按常见显示缩放自适应。
70
+ * @returns 匹配矩形 `{x, y, width, height}`。
71
+ * @throws 未达阈值时抛错,信息里带最佳候选分数与位置。
72
+ */
73
+ find: (base64String: string, options?: FindImageOptions) => Promise<ScreenRect>;
74
+ /**
75
+ * 找出屏幕上模板图片的所有命中,按匹配分数降序。
76
+ *
77
+ * @param base64String 模板图片的 Base64。
78
+ * @param options `{confidence?, searchRegion?, scale?, maxResults?}`。
79
+ * @returns 匹配矩形数组,可能为空。
80
+ */
81
+ findAll: (base64String: string, options?: FindImageOptions) => Promise<ScreenRect[]>;
82
+ /**
83
+ * 轮询屏幕直到模板图片出现,返回其矩形。
84
+ *
85
+ * @param base64String 模板图片的 Base64。
86
+ * @param options 查找参数外加 `{timeoutMs?, intervalMs?}`,缺省 5000 / 500。
87
+ * @returns 匹配矩形 `{x, y, width, height}`。
88
+ * @throws 超时仍未出现时抛错。
89
+ */
90
+ waitFor: (base64String: string, options?: FindImageOptions & WaitOptions) => Promise<ScreenRect>;
91
+ /**
92
+ * 轮询屏幕直到模板图片消失。
93
+ *
94
+ * @param base64String 模板图片的 Base64。
95
+ * @param options 查找参数外加 `{timeoutMs?, intervalMs?}`。
96
+ * @returns 无返回。
97
+ * @throws 超时仍在屏幕上时抛错。
98
+ */
99
+ waitUntilGone: (base64String: string, options?: FindImageOptions & WaitOptions) => Promise<void>;
100
+ /**
101
+ * 用 OCR 在屏幕上找一段文字,返回该词的矩形。
102
+ *
103
+ * @param text 目标文字,整词匹配。
104
+ * @param options `{searchRegion?, detRatio?}`。
105
+ * @returns 文字矩形 `{x, y, width, height}`。
106
+ * @throws 未找到时抛错,信息里带当前屏幕可见的文字列表。
107
+ */
108
+ findText: (text: string, options?: FindTextOptions) => Promise<ScreenRect>;
109
+ /**
110
+ * 轮询屏幕直到指定文字出现,返回该词的矩形。
111
+ *
112
+ * @param text 目标文字,整词匹配。
113
+ * @param options `{searchRegion?, detRatio?, timeoutMs?, intervalMs?}`。
114
+ * @returns 文字矩形 `{x, y, width, height}`。
115
+ * @throws 超时仍未出现时抛错,信息里带当前屏幕可见的文字列表。
116
+ */
117
+ waitForText: (text: string, options?: FindTextOptions & WaitOptions) => Promise<ScreenRect>;
118
+ /**
119
+ * 对显示器(或其中一块区域)做 OCR,返回每段文字及其屏幕坐标矩形。
120
+ *
121
+ * @param options `{display?, region?}`,region 为该显示器物理像素坐标;缺省光标所在显示器整屏。
122
+ * @returns `[{text, score, x, y, width, height}]`,坐标已加上显示器原点。
123
+ */
124
+ recognizeText: (options?: {
125
+ display?: number;
126
+ region?: ScreenRect;
127
+ }) => Promise<Array<ScreenRect & {
128
+ text: string;
129
+ score: number;
130
+ }>>;
131
+ /**
132
+ * 对显示器(或其中一块区域)做候选控件切分,返回图标尺寸的连通块矩形(屏幕坐标)。
40
133
  *
41
- * @param base64String 模板图片的 Base64 编码字符串(支持 `data:image/...;base64,` 前缀)。
42
- * @returns 匹配区域中心在屏幕原生坐标系中的坐标 `{x, y}`。
43
- * @throws 未找到匹配区域时抛错。
134
+ * @param options `{display?, region?, textBoxes?, minSide?, maxSide?}`;textBoxes 是屏幕坐标的文字框,用来剔除文字行。
135
+ * @returns `[{x, y, width, height, pixels}]`,按 y 再 x 排序。
44
136
  */
45
- find: (base64String: string) => Promise<any>;
137
+ proposeElements: (options?: {
138
+ display?: number;
139
+ region?: ScreenRect;
140
+ textBoxes?: ScreenRect[];
141
+ minSide?: number;
142
+ maxSide?: number;
143
+ }) => Promise<Array<ScreenRect & {
144
+ pixels: number;
145
+ }>>;
46
146
  /**
47
- * 持续监视屏幕,等待指定模板图片出现后返回其中心坐标。
48
- * 会阻塞直到匹配成功或 nut-js 内部超时。推送而非直接返回 —— 匹配成功前调用方一直挂起。
147
+ * 在一张给定图片(而不是当前屏幕)里做模板匹配,给「用采集时的截图验证模板唯一性」用。
49
148
  *
50
- * @param base64String 模板图片的 Base64 编码字符串(支持 `data:image/...;base64,` 前缀)。
51
- * @returns 匹配区域中心在屏幕原生坐标系中的坐标 `{x, y}`。
52
- * @throws 超时仍未匹配到图片时抛错。
149
+ * @param haystack 被搜索图片的 Base64。
150
+ * @param needle 模板图片的 Base64。
151
+ * @param options `{maxResults?, scale?, minScore?, region?}`。
152
+ * @returns `[{x, y, width, height, score, scale}]`,按分数降序,第一个是全图最佳。
53
153
  */
54
- waitFor: (base64String: any) => Promise<any>;
154
+ matchTemplate: (haystack: string, needle: string, options?: {
155
+ maxResults?: number;
156
+ scale?: number;
157
+ minScore?: number;
158
+ region?: ScreenRect;
159
+ }) => Promise<Array<ScreenRect & {
160
+ score: number;
161
+ scale: number;
162
+ }>>;
55
163
  /**
56
- * 持续监视屏幕,等待指定文字出现后返回其中心坐标。
57
- * 通过 OCR 识别屏幕文字后匹配,会阻塞直到匹配成功或超时。推送而非直接返回。
164
+ * 两张同尺寸截图的差异包围框。
58
165
  *
59
- * @param text 要查找的目标文字(支持 OCR 识别的自然语言)。
60
- * @param providerData 可选的 provider 特定搜索参数,如限定 OCR 识别区域。
61
- * @returns 匹配文字区域中心在屏幕原生坐标系中的坐标 `{x, y}`。
62
- * @throws 超时仍未匹配到文字时抛错。
166
+ * @param before 前一帧的 Base64。
167
+ * @param after 后一帧的 Base64。
168
+ * @param options `{threshold?}`,灰度差超过阈值算变化,缺省 24。
169
+ * @returns `{x, y, width, height, changed}`;没有变化返回 null。
63
170
  */
64
- waitForText: (text: string) => Promise<any>;
171
+ diffRegion: (before: string, after: string, options?: {
172
+ threshold?: number;
173
+ }) => Promise<(ScreenRect & {
174
+ changed: number;
175
+ }) | null>;
65
176
  /**
66
177
  * 读取屏幕上指定坐标点的像素颜色(RGBA)。
67
178
  *
@@ -46,4 +46,28 @@ export default class SystemShell {
46
46
  label: string;
47
47
  available: boolean;
48
48
  }>>;
49
+ /**
50
+ * 启动一个可执行文件,进程脱离宿主独立运行。
51
+ *
52
+ * @param path 可执行文件绝对路径。
53
+ * @param args 命令行参数。
54
+ * @param cwd 工作目录,缺省为可执行文件所在目录。
55
+ * @returns 新进程的 pid。
56
+ * @throws 文件不存在或无法启动时抛错。
57
+ */
58
+ launch: (path: string, args?: string[], cwd?: string) => Promise<number>;
59
+ /**
60
+ * 判断某个可执行文件名的进程是否在运行。
61
+ *
62
+ * @param name 进程名,如 `Code.exe`;大小写不敏感,可带或不带 .exe。
63
+ * @returns 在运行返回 true。
64
+ */
65
+ isProcessRunning: (name: string) => Promise<boolean>;
66
+ /**
67
+ * 结束所有同名进程。
68
+ *
69
+ * @param name 进程名,如 `notepad.exe`。
70
+ * @returns 结束了至少一个进程返回 true;没有同名进程返回 false。
71
+ */
72
+ terminateProcess: (name: string) => Promise<boolean>;
49
73
  }
@@ -78,4 +78,66 @@ export default class SystemWindow {
78
78
  defaultName?: string;
79
79
  filters?: Electron.FileFilter[];
80
80
  }) => Promise<string | null>;
81
+ /**
82
+ * 把匹配的外部应用窗口拉到前台并激活。优先按 execPath 精确匹配,其次按 title 模糊匹配;已在前台则不操作。
83
+ *
84
+ * @param title 窗口标题(模糊匹配)。
85
+ * @param execPath 可选的进程可执行文件路径(精确匹配)。
86
+ * @returns 成功返回 true;没有匹配窗口返回 false。
87
+ */
88
+ bringToFront: (title: string, execPath?: string) => Promise<boolean>;
89
+ /**
90
+ * 列出桌面上可见、有标题的顶层窗口,z 序自上而下。
91
+ *
92
+ * @returns `[{id, title, execPath, processId, x, y, width, height, active}]`,矩形为屏幕原生坐标。
93
+ */
94
+ listWindows: () => Promise<Array<{
95
+ id: number;
96
+ title: string;
97
+ execPath: string;
98
+ processId: number;
99
+ x: number;
100
+ y: number;
101
+ width: number;
102
+ height: number;
103
+ active: boolean;
104
+ }>>;
105
+ /**
106
+ * 取匹配窗口此刻的矩形与状态。匹配逻辑同 bringToFront。
107
+ *
108
+ * @param title 窗口标题(模糊匹配)。
109
+ * @param execPath 可选的进程可执行文件路径(精确匹配)。
110
+ * @returns `{id, title, x, y, width, height, active, minimized}`;没有匹配窗口返回 null。
111
+ */
112
+ windowBounds: (title: string, execPath?: string) => Promise<{
113
+ id: number;
114
+ title: string;
115
+ x: number;
116
+ y: number;
117
+ width: number;
118
+ height: number;
119
+ active: boolean;
120
+ minimized: boolean;
121
+ } | null>;
122
+ /**
123
+ * 轮询直到匹配窗口出现,返回其矩形与状态。
124
+ *
125
+ * @param title 窗口标题(模糊匹配)。
126
+ * @param options `{execPath?, timeoutMs?, intervalMs?}`,缺省 10000 / 300。
127
+ * @returns 同 windowBounds;超时返回 null。
128
+ */
129
+ waitForWindow: (title: string, options?: {
130
+ execPath?: string;
131
+ timeoutMs?: number;
132
+ intervalMs?: number;
133
+ }) => Promise<{
134
+ id: number;
135
+ title: string;
136
+ x: number;
137
+ y: number;
138
+ width: number;
139
+ height: number;
140
+ active: boolean;
141
+ minimized: boolean;
142
+ } | null>;
81
143
  }