mooncat-browser 0.2.4 → 0.2.5

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/dist/actions.md CHANGED
@@ -1,17 +1,57 @@
1
- # operate action 清单
1
+ # SDK 能力清单
2
2
 
3
- `BrowserClient.operate({ pageHandle, action, params })` 的全部 action 取值与参数。
3
+ `BrowserClient` 有两套入口:
4
+ 1. **直接方法**(`browser.xxx()`)— 不走 operate,见下表一。
5
+ 2. **operate(action)**(`browser.operate({ pageHandle, action, params })`)— 见下表二。
4
6
 
5
- > 自动生成,来自 `browser-op/backend/browserd.cjs` 的 `@action` 标注。这是 browser 内核的公开契约,始终最新。
7
+ > 自动生成。operate(action) 来自 `browser-op/backend/browserd.cjs` 的 `@action` 标注;
8
+ > 直接方法来自 `src/client.ts`(脚本内维护,改公开方法时同步)。始终权威。
6
9
 
7
10
  ## 约定
8
11
 
9
- - **pageHandle**:所有 action 都需要,由 `newTab()` / `listTabs()` 返回的 `tab.pageHandle` 提供。
10
- - **selector 语法**:CSS / `aria-ref=eN`(来自 snapshot 的 ref)/ `.cls>>nth(n)` / `.cls>>last`。
11
- - **ext 列**:action 在双路由(CDP / WebPlater 扩展)的可用性。
12
+ - **pageHandle**:operate(action) 都需要,由 `newTab()` / `listTabs()` 返回的 `tab.pageHandle` 提供。
13
+ - **selector 语法**:CSS / `aria-ref=eN`(来自 snapshot 的 ref)/ `.cls>>nth(n)` / `.cls>>last`。
14
+ - **ext 列**:action 在双路由(CDP / WebPlater 扩展)的可用性。
12
15
  - ✓ = CDP 与扩展均支持
13
- - ✗ = 仅 CDP(扩展路不支持,如 `waitForFunction`,因扩展路 CSP 拦截 eval
14
- - 仅 ext = 仅扩展路(如 `setDialogHandler`、`listDownloads`,依赖扩展 API
16
+ - ✗ = 仅 CDP(扩展路不支持,如 `waitForFunction`,因扩展路 CSP 拦截 eval)
17
+ - 仅 ext = 仅扩展路(如 `setDialogHandler`、`listDownloads`,依赖扩展 API)
18
+
19
+ ## 一、BrowserClient 直接方法(不走 operate)
20
+
21
+ ### 生命周期 / tab
22
+
23
+ | 方法 | 签名 | 说明 |
24
+ | --- | --- | --- |
25
+ | `health` | health(timeoutMs?) | 探测 browserd 是否就绪 + browser 是否 open。返回 null = 连不上 |
26
+ | `open` | open({ routeMode: "cdp"\|"extension", headless? }) | 打开/复用浏览器(幂等)。routeMode 必填(无 auto) |
27
+ | `close` | close() | graceful 关浏览器(保留登录态)。用户满意前不要 close |
28
+ | `newTab` | newTab({ url?, force? }) | 新建 tab(或复用同 url 的 tab)。返回含 pageHandle |
29
+ | `listTabs` | listTabs() | 列所有 tab(每项含 pageHandle) |
30
+ | `reuseTab` | reuseTab({ url?, urlMatch? }) | 按 url/urlMatch 找已有 tab 复用;没有才 newTab。高危平台频繁重开触发风控,已开的 tab 应复用 |
31
+
32
+ ### cookie
33
+
34
+ | 方法 | 签名 | 说明 |
35
+ | --- | --- | --- |
36
+ | `getCookies` | getCookies({ url?, domain? }) | 读 cookie(按 url 或 domain 过滤) |
37
+ | `setCookies` | setCookies(cookies[]) | 写 cookie |
38
+ | `clearCookies` | clearCookies({ url? \| domain? }) | 清 cookie(按 url 或 domain;不传清该域全部) |
39
+
40
+ ### 下载(仅 extension 路)
41
+
42
+ | 方法 | 签名 | 说明 |
43
+ | --- | --- | --- |
44
+ | `listDownloads` | listDownloads(limit?) | 列最近下载(默认 20) |
45
+ | `getDownload` | getDownload(id) | 查单个下载状态 |
46
+ | `waitForDownload` | waitForDownload({ filenameRegex?, sinceMs?, timeoutMs?, intervalMs? }) | 轮询等下载完成(reason=complete 成功,timeout 超时)。点了下载按钮后调用 |
47
+
48
+ ### 通用等待
49
+
50
+ | 方法 | 签名 | 说明 |
51
+ | --- | --- | --- |
52
+ | `waitFor` | waitFor({ tab, selector?, text?, pollTimeoutMs?, intervalMs?, maxRefresh?, refreshSettleMs?, frameId? }) | 等 DOM 节点(selector)或文本(text)出现。延迟重试+刷新重试。SPA 异步加载用,比 sleep 固定等待稳 |
53
+
54
+ ## 二、operate(action) 清单
15
55
 
16
56
  ### 交互
17
57
 
@@ -30,8 +70,6 @@
30
70
  | `selectOption` | `selector`:string, `value`:string | {ok,selector,value} | 选择option | ✓ |
31
71
  | `dblclick` | `selector`:string | {ok,selector} | 双击元素 | ✓ |
32
72
  | `mouseMove` | `x`:number, `y`:number | {ok,x,y} | 移动鼠标到坐标 | ✓ |
33
- | `clickAt` | `x`:number, `y`:number, `button`?:string=left, `clickCount`?:number=1 | {ok,x,y,route} | 坐标点击(CDP路page.mouse真实鼠标) | ✓ |
34
- | `clickByText` | `text`:string, `exact`?:boolean=false, `index`?:number=0, `offsetX`?:number=0, `offsetY`?:number=0 | {ok,text,x,y,match,route} | 定位可见文本后立即点击(CDP路原子) | ✓ |
35
73
  | `dragTo` | `source`:string, `target`:string | {ok,source,target} | 拖拽source到target(双兼容mouse+HTML5) | ✓ |
36
74
 
37
75
  ### 读取
@@ -39,7 +77,6 @@
39
77
  | action | params | returns | description | ext |
40
78
  | --- | --- | --- | --- | --- |
41
79
  | `locateVisibleText` | `text`:string, `exact`?:boolean=false, `index`?:number=0 | {ok,matches:[{text,x,y,width,height,centerX,centerY,visible}]} | 定位可见文本节点返回bbox(不返回DOM handle) | ✓ |
42
- | `locateVisibleText` | `text`:string, `exact`?:boolean=false, `index`?:number=0 | {ok,matches:[{text,x,y,width,height,centerX,centerY,visible}]} | 定位可见文本节点返回bbox | ✓ |
43
80
  | `innerHTML` | `selector`:string | {ok,selector,value} | 读元素innerHTML | ✓ |
44
81
  | `innerText` | `selector`:string | {ok,selector,value} | 读元素innerText | ✓ |
45
82
  | `textContent` | `selector`:string | {ok,selector,value} | 读元素textContent | ✓ |
@@ -55,7 +92,6 @@
55
92
  | --- | --- | --- | --- | --- |
56
93
  | `operateSequence` | `steps`:array | {ok,results} | 原子序列执行(locate/click/wait在同一页面上下文串行) | ✓ |
57
94
  | `setDialogHandler` | `handler`:string | {ok} | 设置JS对话框处理 | 仅 ext |
58
- | `operateSequence` | `steps`:array | {ok,results} | 原子序列执行 | ✓ |
59
95
  | `evaluate` | `source`:string, `args`?:any | 由函数返回值决定 | 执行页面JS函数(返回其结果) | ✓ |
60
96
  | `setInputFiles` | `selector`:string, `files`:array, `timeout`?:number=10000 | {ok,selector,count} | 上传文件到file input | ✓ |
61
97
 
@@ -67,7 +103,7 @@
67
103
  | `goBack` | `timeout`?:number=15000 | {ok,url} | 后退一页 | ✓ |
68
104
  | `goForward` | `timeout`?:number=15000 | {ok,url} | 前进一页 | ✓ |
69
105
  | `reload` | `timeout`?:number=15000 | {ok,url} | 刷新当前页 | ✓ |
70
- | `status` | — | {ok,url,title,readyState,textLength} | 读当前页状态(url/title/readyState) | ✓ |
106
+ | `status` | — | {ok,url,title,readyState,textLength} | 读当前页状态(url/title/readyState/textLength) | ✓ |
71
107
 
72
108
  ### 等待
73
109
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mooncat-browser",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "浏览器自动化工具包:可独立启动的本地服务(browserd)+ JS/TS client。双路由(WebPlater 扩展 / CDP),不依赖 mooncat 总发行体。",
5
5
  "type": "module",
6
6
  "main": "./dist/client.js",
@@ -1,128 +1,132 @@
1
1
  # SDK 能力清单
2
2
 
3
- `BrowserClient` 有**两套**入口,不要混:
3
+ `BrowserClient` 有**两套**入口,不要混:
4
4
 
5
- 1. **直接方法**(`browser.xxx()`)— 生命周期 / tab / cookie / 下载 / 通用等待。不走 operate。
6
- 2. **operate(action)**(`browser.operate({ pageHandle, action, params })`)— 页面内动作(导航/交互/读取/存储/截图),40+ 个 action。
5
+ 1. **直接方法**(`browser.xxx()`)— 生命周期/tab/cookie/下载/通用等待。不走 operate。
6
+ 2. **operate(action)**(`browser.operate({ pageHandle, action, params })`)— 页面内动作,见下表。
7
7
 
8
- 下面两段分开列。表里没有 ≠ 工具没有 —— 先看另一段。
8
+ 两段分开看。表里没有 ≠ 工具没有 —— 先看另一段。
9
9
 
10
- ## 一、BrowserClient 直接方法(不走 operate
10
+ ## 一、BrowserClient 直接方法(不走 operate)
11
11
 
12
12
  ### 生命周期 / tab
13
13
 
14
14
  | 方法 | 签名 | 说明 |
15
15
  | --- | --- | --- |
16
- | `health` | `health(timeoutMs?)` → `/health` body 或 null | 探测 browserd 是否就绪 + browser 是否 open。返回 null = 连不上 |
17
- | `open` | `open({ routeMode: "cdp"\|"extension", headless? })` → BrowserHandle | 打开/复用浏览器(幂等)。routeMode 必填(无 auto |
18
- | `close` | `close()` → `{ ok, closed }` | graceful 关浏览器(保留登录态)。用户满意前不要 close |
19
- | `newTab` | `newTab({ url?, force? })` → TabInfo | 新建 tab(或复用同 url 的 tab)。返回含 `pageHandle` |
20
- | `listTabs` | `listTabs()` → TabInfo[] | 列所有 tab(每项含 pageHandle |
21
- | `reuseTab` | `reuseTab({ url?, urlMatch? })` → TabInfo & { reused } | 按 url/urlMatch 找已有 tab 复用;没有才 newTab。**高危平台频繁重开触发风控,已开的 tab 应复用** |
16
+ | `health` | health(timeoutMs?) | 探测 browserd 是否就绪 + browser 是否 open。返回 null = 连不上 |
17
+ | `open` | open({ routeMode: "cdp"\|"extension", headless? }) | 打开/复用浏览器(幂等)。routeMode 必填(无 auto) |
18
+ | `close` | close() | graceful 关浏览器(保留登录态)。用户满意前不要 close |
19
+ | `newTab` | newTab({ url?, force? }) | 新建 tab(或复用同 url 的 tab)。返回含 pageHandle |
20
+ | `listTabs` | listTabs() | 列所有 tab(每项含 pageHandle) |
21
+ | `reuseTab` | reuseTab({ url?, urlMatch? }) | 按 url/urlMatch 找已有 tab 复用;没有才 newTab。高危平台频繁重开触发风控,已开的 tab 应复用 |
22
22
 
23
23
  ### cookie
24
24
 
25
25
  | 方法 | 签名 | 说明 |
26
26
  | --- | --- | --- |
27
- | `getCookies` | `getCookies({ url?, domain? })` → `{ cookies }` | 读 cookie(按 url 或 domain 过滤) |
28
- | `setCookies` | `setCookies(cookies[])` → `{ ok, count }` | 写 cookie |
29
- | `clearCookies` | `clearCookies({ url? \| domain? })` | 清 cookie(按 url 或 domain;不传清该域全部) |
27
+ | `getCookies` | getCookies({ url?, domain? }) | 读 cookie(按 url 或 domain 过滤) |
28
+ | `setCookies` | setCookies(cookies[]) | 写 cookie |
29
+ | `clearCookies` | clearCookies({ url? \| domain? }) | 清 cookie(按 url 或 domain;不传清该域全部) |
30
30
 
31
- ### 下载(仅 extension 路,chrome.downloads API)
31
+ ### 下载(仅 extension 路)
32
32
 
33
33
  | 方法 | 签名 | 说明 |
34
34
  | --- | --- | --- |
35
- | `listDownloads` | `listDownloads(limit?)` → `{ downloads }` | 列最近下载(默认 20 |
36
- | `getDownload` | `getDownload(id)` → `{ download }` | 查单个下载状态 |
37
- | `waitForDownload` | `waitForDownload({ filenameRegex?, sinceMs?, timeoutMs?, intervalMs? })` → `{ download, reason }` | 轮询等下载完成(reason=complete 成功,timeout 超时)。**点了下载按钮后调用** |
35
+ | `listDownloads` | listDownloads(limit?) | 列最近下载(默认 20) |
36
+ | `getDownload` | getDownload(id) | 查单个下载状态 |
37
+ | `waitForDownload` | waitForDownload({ filenameRegex?, sinceMs?, timeoutMs?, intervalMs? }) | 轮询等下载完成(reason=complete 成功,timeout 超时)。点了下载按钮后调用 |
38
38
 
39
- ### 通用等待(轮询页面,复用 operate(evaluate))
39
+ ### 通用等待
40
40
 
41
41
  | 方法 | 签名 | 说明 |
42
42
  | --- | --- | --- |
43
- | `waitFor` | `waitFor({ tab, selector?, text?, pollTimeoutMs?, intervalMs?, maxRefresh?, refreshSettleMs?, frameId? })` → `{ ok, matched, refreshCount, elapsedMs }` | 等 DOM 节点(selector)或文本(text)出现。延迟重试 + 刷新重试。SPA 异步加载用,比 sleep 固定等待稳 |
44
-
45
- > `waitFor` 内部用 operate(evaluate) 轮询,但它本身是直接方法(语义封装,不让你手写 operate+evaluate 循环)。
43
+ | `waitFor` | waitFor({ tab, selector?, text?, pollTimeoutMs?, intervalMs?, maxRefresh?, refreshSettleMs?, frameId? }) | 等 DOM 节点(selector)或文本(text)出现。延迟重试+刷新重试。SPA 异步加载用,比 sleep 固定等待稳 |
46
44
 
47
45
  ## 二、operate(action) 清单
48
46
 
49
- `browser.operate({ pageHandle, action, params })` 40+ 个 action。**都要传 pageHandle**(从 newTab/listTabs/reuseTab 拿)。
50
-
51
- ### 导航
52
-
53
- | action | params | returns | 说明 | ext |
54
- | --- | --- | --- | --- | --- |
55
- | `goto` | `url`:string | {ok,url} | 导航到 URL,等待 DOMContentLoaded | ✓ |
56
- | `goBack` | `timeout?`:number=15000 | {ok,url} | 后退一页 | ✓ |
57
- | `goForward` | `timeout?`:number=15000 | {ok,url} | 前进一页 | ✓ |
58
- | `reload` | `timeout?`:number=15000 | {ok,url} | 刷新当前页 | ✓ |
59
- | `status` | — | {ok,url,title,readyState,textLength} | 读当前页状态 | ✓ |
47
+ `browser.operate({ pageHandle, action, params })` 的全部 action。**都要传 pageHandle**(从 newTab/listTabs/reuseTab 拿)。
48
+ 完整说明见包内 `dist/actions.md`。
60
49
 
61
50
  ### 交互
62
51
 
63
- | action | params | returns | 说明 | ext |
52
+ | action | params | returns | description | ext |
64
53
  | --- | --- | --- | --- | --- |
65
- | `click` | `selector`:string, `x`?, `y`? | {ok,selector} | 点击元素(或坐标 x,y) | ✓ |
66
- | `clickAt` | `x`:number, `y`:number, `button?`=left, `clickCount?`=1 | {ok,x,y,route} | 坐标点击(绕过 selector) | ✓ |
67
- | `clickByText` | `text`:string, `exact?`=false, `index?`=0, `offsetX?`, `offsetY?` | {ok,text,x,y,match,route} | 定位可见文本后立即点击(原子,防 DOM 重渲染) | ✓ |
68
- | `fill` | `selector`:string, `value`:string | {ok,selector,value} | 在 selector 元素填文本(先清空) | ✓ |
69
- | `type` | `selector`:string, `value`:string, `delay?`=0 | {ok,selector} | 逐字输入(带延迟,模拟键盘) | ✓ |
54
+ | `clickAt` | `x`:number, `y`:number, `button`?:string=left, `clickCount`?:number=1 | {ok,x,y,route} | 坐标点击(绕过selector,CDP路真实鼠标/扩展路合成事件) | ✓ |
55
+ | `clickByText` | `text`:string, `exact`?:boolean=false, `index`?:number=0, `offsetX`?:number=0, `offsetY`?:number=0 | {ok,text,x,y,match,route} | 定位可见文本后立即点击(原子,防DOM重渲染) | ✓ |
56
+ | `click` | `selector`:string, `x`?:number, `y`?:number | {ok,selector} | 点击元素(或坐标x,y) | ✓ |
57
+ | `fill` | `selector`:string, `value`:string | {ok,selector,value} | 在selector元素填入文本(先清空) | ✓ |
58
+ | `type` | `selector`:string, `value`:string, `delay`?:number=0 | {ok,selector} | 逐字输入(带延迟,模拟键盘) | ✓ |
70
59
  | `press` | `selector`:string, `key`:string | {ok,selector,key} | 在元素上按键 | ✓ |
71
- | `hover` | `selector`:string, `x`?, `y`? | {ok,selector} | 悬停(或坐标) | ✓ |
60
+ | `hover` | `selector`:string, `x`?:number, `y`?:number | {ok,selector} | 悬停元素(或坐标) | ✓ |
72
61
  | `focus` | `selector`:string | {ok,selector} | 聚焦元素 | ✓ |
73
- | `check` | `selector`:string | {ok,selector} | 勾选 checkbox/radio | ✓ |
62
+ | `check` | `selector`:string | {ok,selector} | 勾选checkbox/radio | ✓ |
74
63
  | `uncheck` | `selector`:string | {ok,selector} | 取消勾选 | ✓ |
75
- | `selectOption` | `selector`:string, `value`:string | {ok,selector,value} | 选择 option | ✓ |
64
+ | `selectOption` | `selector`:string, `value`:string | {ok,selector,value} | 选择option | ✓ |
76
65
  | `dblclick` | `selector`:string | {ok,selector} | 双击元素 | ✓ |
77
66
  | `mouseMove` | `x`:number, `y`:number | {ok,x,y} | 移动鼠标到坐标 | ✓ |
78
- | `dragTo` | `source`:string, `target`:string | {ok,source,target} | 拖拽 source target | ✓ |
79
- | `setInputFiles` | `selector`:string, `files`:array, `timeout?`=10000 | {ok,selector,count} | 上传文件到 file input | ✓ |
67
+ | `dragTo` | `source`:string, `target`:string | {ok,source,target} | 拖拽source到target(双兼容mouse+HTML5) | ✓ |
80
68
 
81
69
  ### 读取
82
70
 
83
- | action | params | returns | 说明 | ext |
71
+ | action | params | returns | description | ext |
84
72
  | --- | --- | --- | --- | --- |
85
- | `snapshot` | `depth?`, `timeout?`=15000, `rootSelector?`, `interactiveOnly?`, `chunkId?`, `chunkSize?`, `refresh?` | {ok,yaml,...} | aria 无障碍快照(返回 yaml,可分块) | ✓ |
86
- | `innerHTML` | `selector`:string | {ok,selector,value} | innerHTML | ✓ |
87
- | `innerText` | `selector`:string | {ok,selector,value} | innerText | ✓ |
88
- | `textContent` | `selector`:string | {ok,selector,value} | textContent | ✓ |
73
+ | `locateVisibleText` | `text`:string, `exact`?:boolean=false, `index`?:number=0 | {ok,matches:[{text,x,y,width,height,centerX,centerY,visible}]} | 定位可见文本节点返回bbox(不返回DOM handle) | ✓ |
74
+ | `innerHTML` | `selector`:string | {ok,selector,value} | 读元素innerHTML | ✓ |
75
+ | `innerText` | `selector`:string | {ok,selector,value} | 读元素innerText | ✓ |
76
+ | `textContent` | `selector`:string | {ok,selector,value} | 读元素textContent | ✓ |
89
77
  | `getAttribute` | `selector`:string, `name`:string | {ok,selector,name,value} | 读元素属性 | ✓ |
90
- | `inputValue` | `selector`:string, `timeout?`=10000 | {ok,selector,value} | 读 input/select 当前值 | ✓ |
91
- | `boundingBox` | `selector`:string | {ok,selector,x,y,width,height} | 读元素包围盒 | ✓ |
92
- | `count` | `selector`:string | {ok,selector,count} | 统计 selector 匹配数 | ✓ |
93
- | `locateVisibleText` | `text`:string, `exact?`=false, `index?`=0 | {ok,matches:[{text,x,y,width,height,centerX,centerY,visible}]} | 定位可见文本节点返回 bbox(不返回 DOM handle) | ✓ |
94
- | `evaluate` | `source`:string, `args?`:any | 函数返回值 | 执行页面 JS 函数,返回其结果 | ✓ |
95
- | `listFrames` | — | [{frameId,url,parentFrameId}] | 列当前 tab 的所有 frame(iframe 结构) | ✓ |
78
+ | `inputValue` | `selector`:string, `timeout`?:number=10000 | {ok,selector,value} | 读input/select当前值 | ✓ |
79
+ | `boundingBox` | `selector`:string | {ok,selector,x,y,width,height} | 读元素包围盒(坐标+尺寸) | ✓ |
80
+ | `count` | `selector`:string | {ok,selector,count} | 统计selector匹配数 | ✓ |
81
+ | `snapshot` | `depth`?:number, `timeout`?:number=15000 | {ok,yaml,totalChars} | aria无障碍快照(返回yaml) | ✓ |
82
+
83
+ ### 进阶
84
+
85
+ | action | params | returns | description | ext |
86
+ | --- | --- | --- | --- | --- |
87
+ | `operateSequence` | `steps`:array | {ok,results} | 原子序列执行(locate/click/wait在同一页面上下文串行) | ✓ |
88
+ | `setDialogHandler` | `handler`:string | {ok} | 设置JS对话框处理 | 仅 ext |
89
+ | `evaluate` | `source`:string, `args`?:any | 由函数返回值决定 | 执行页面JS函数(返回其结果) | ✓ |
90
+ | `setInputFiles` | `selector`:string, `files`:array, `timeout`?:number=10000 | {ok,selector,count} | 上传文件到file input | ✓ |
91
+
92
+ ### 导航
93
+
94
+ | action | params | returns | description | ext |
95
+ | --- | --- | --- | --- | --- |
96
+ | `goto` | `url`:string | {ok,url} | 导航到URL,等待DOMContentLoaded | ✓ |
97
+ | `goBack` | `timeout`?:number=15000 | {ok,url} | 后退一页 | ✓ |
98
+ | `goForward` | `timeout`?:number=15000 | {ok,url} | 前进一页 | ✓ |
99
+ | `reload` | `timeout`?:number=15000 | {ok,url} | 刷新当前页 | ✓ |
100
+ | `status` | — | {ok,url,title,readyState,textLength} | 读当前页状态(url/title/readyState/textLength) | ✓ |
96
101
 
97
102
  ### 等待
98
103
 
99
- | action | params | returns | 说明 | ext |
104
+ | action | params | returns | description | ext |
100
105
  | --- | --- | --- | --- | --- |
101
- | `waitForLoadState` | `state?`=load, `timeout?`=30000 | {ok} | 等待指定加载状态(load/domcontentloaded/networkidle) | ✓ |
102
- | `waitForSelector` | `selector`:string, `timeout?`=30000 | {ok,selector,visible,inViewport} | selector 元素可见 | ✓ |
103
- | `waitForFunction` | `source`:string, `timeout?`=30000 | 函数返回值 | 等页面函数返回 truthy | ✗(extension CSPeval |
104
- | `waitForURL` | `url`:string, `timeout?`=30000 | {ok,url} | URL 匹配 | ✓ |
105
- | `waitForTimeout` | `ms?`=1000 | {ok,ms} | 固定等待 | ✓ |
106
+ | `waitForLoadState` | `state`?:string=load, `timeout`?:number=30000 | {ok} | 等待指定加载状态 | ✓ |
107
+ | `waitForSelector` | `selector`:string, `timeout`?:number=30000 | {ok,selector,visible,inViewport} | 等待selector元素可见 | ✓ |
108
+ | `waitForFunction` | `source`:string, `timeout`?:number=30000 | 由函数返回值决定 | 等待页面函数返回truthy | ✗ (extension路CSP拦截eval) |
109
+ | `waitForURL` | `url`:string, `timeout`?:number=30000 | {ok,url} | 等待URL匹配 | ✓ |
110
+ | `waitForTimeout` | `ms`?:number=1000 | {ok,ms} | 固定等待 | ✓ |
106
111
 
107
- ### 存储(localStorage)
112
+ ### 标签页
108
113
 
109
- | action | params | returns | 说明 | ext |
114
+ | action | params | returns | description | ext |
110
115
  | --- | --- | --- | --- | --- |
111
- | `getLocalStorage` | `keys?`:array | {ok,storage} | localStorage(不传读全部) | ✓ |
112
- | `setLocalStorage` | `items`:object | {ok,count} | localStorage | ✓ |
113
- | `removeLocalStorage` | `keys?`:array | {ok,count} | 删 localStorage(不传删全部) | ✓ |
114
- | `clearLocalStorage` | — | {ok} | 清空 localStorage | ✓ |
116
+ | `closeTab` | | {ok} | 关闭当前page | ✓ |
117
+ | `activate` | | {ok} | 切到最前(仅可视) | ✓ |
115
118
 
116
- ### 标签页 / 截图 / 对话框
119
+ ### 截图
117
120
 
118
- | action | params | returns | 说明 | ext |
121
+ | action | params | returns | description | ext |
119
122
  | --- | --- | --- | --- | --- |
120
- | `closeTab` | — | {ok} | 关闭当前 page | ✓ |
121
- | `activate` | — | {ok} | 切到最前(仅可视) | ✓ |
122
- | `screenshot` | — | {ok,format,dataUrl} | 截整页 PNG(返回 dataUrl;extension 模式需先 activate) | ✓ |
123
- | `setDialogHandler` | `handler`:string | {ok} | 设置 JS 对话框处理 | 仅 ext |
124
- | `operateSequence` | `steps`:array | {ok,results} | 原子序列执行(locate/click/wait 在同页面上下文串行) | ✓ |
123
+ | `screenshot` | — | {ok,format,dataUrl} | 截整页PNG(返回dataUrl) | ✓ |
125
124
 
126
- ## ext 列说明
125
+ ### 存储
127
126
 
128
- `ext=✓` 表示 action extension 路和 CDP 路行为一致。`✗` 或"仅 ext"见注释。多数 action 双路由统一(路由不泄漏原则)。
127
+ | action | params | returns | description | ext |
128
+ | --- | --- | --- | --- | --- |
129
+ | `getLocalStorage` | `keys`?:array | {ok,storage} | 读localStorage(不传keys读全部) | ✓ |
130
+ | `setLocalStorage` | `items`:object | {ok,count} | 写localStorage | ✓ |
131
+ | `removeLocalStorage` | `keys`?:array | {ok,count} | 删localStorage(不传keys删全部) | ✓ |
132
+ | `clearLocalStorage` | — | {ok} | 清空localStorage | ✓ |