dsh-sidebar-browser-control 0.0.0-stage → 0.2.0
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/LICENSE +21 -0
- package/README.md +202 -2
- package/README.zh.md +149 -0
- package/client.js +1365 -0
- package/cordis.patch.yml +12 -0
- package/icon.svg +7 -0
- package/index.js +912 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +70 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 XUFENGCHINA
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,203 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-sidebar-browser-control
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-sidebar-browser-control)
|
|
4
|
+
[](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/LICENSE)
|
|
6
|
+
[](#compatibility)
|
|
7
|
+
|
|
8
|
+
**Let the agent drive DSH's own built-in browser** — the Browser tab in the
|
|
9
|
+
right-hand Sidebar — instead of launching a second Chromium.
|
|
10
|
+
|
|
11
|
+
[中文说明 →](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/README.zh.md)
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
you › open the docs page in the built-in browser and tell me what the API section says
|
|
15
|
+
agent › browser_control { action: "open", url: "https://example.com/docs" }
|
|
16
|
+
browser_page { action: "text" }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Why not a CDP/Playwright plugin
|
|
20
|
+
|
|
21
|
+
There is already a DSH plugin that drives browsers over CDP
|
|
22
|
+
(`dsh-browser-control`). This one is the in-app counterpart, and the differences
|
|
23
|
+
are the point:
|
|
24
|
+
|
|
25
|
+
| | This plugin | CDP / Playwright wrapper |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| What it drives | the Browser tab DSH already ships | a separate browser process |
|
|
28
|
+
| Where you see it | in the Sidebar, next to your session | in another window |
|
|
29
|
+
| Extra runtime | none | a browser + driver |
|
|
30
|
+
| Logins | the workspace partition the tab already uses | whatever you set up |
|
|
31
|
+
| Reach | that tab only | any page, headless, screenshots |
|
|
32
|
+
|
|
33
|
+
Use this one when you want the agent to look at something *with* you, in the
|
|
34
|
+
place you are already working. Use a CDP wrapper when you need headless
|
|
35
|
+
automation, downloads or screenshots.
|
|
36
|
+
|
|
37
|
+
## What it can do
|
|
38
|
+
|
|
39
|
+
| Tool | Actions |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `browser_tabs` | list open built-in-browser tabs: id, live title, URL, owning session, panel state, whether page control is available, plus capture diagnostics |
|
|
42
|
+
| `browser_control` | `open` · `navigate` · `back` · `forward` · `reload` · `close` · `focus` · `expand` · `collapse` · `fullscreen` · `split` · `float` · `dock` · `external` |
|
|
43
|
+
| `browser_page` | `text` · `links` · `elements` · `eval` · `click` · `type` · `fill` · `key` · `login` · `scroll` · `wait` · `images` · `image` · `screenshot` *(page actions: Desktop only)* |
|
|
44
|
+
| `/browser` | `open <url>` · `tabs` · `back` · `forward` · `reload` · `close` · `focus` · `expand` · `collapse` · `fullscreen` · `split` · `float` · `dock` · `external` · `read` · `images` · `image <N>` · `screenshot` |
|
|
45
|
+
|
|
46
|
+
The tools and the slash command share one implementation, so `/browser open …`
|
|
47
|
+
costs no model round trip and behaves exactly like the tool.
|
|
48
|
+
|
|
49
|
+
### Operating the page, not just reading it
|
|
50
|
+
|
|
51
|
+
- `elements` reports what a person sees: `type`, `name`, `label`, `placeholder`,
|
|
52
|
+
`autocomplete`, `value`, `checked`, plus a selector for `click`.
|
|
53
|
+
- `fill` takes several fields at once and matches them by **label or
|
|
54
|
+
placeholder**, not only by CSS selector — `[{ label: "用户名", value: "alice" },
|
|
55
|
+
{ label: "密码", value: "…" }, { label: "记住我", value: true }]` — and can
|
|
56
|
+
submit. Passwords are masked in every result.
|
|
57
|
+
- `login` is the whole flow in one call: find the account and password fields
|
|
58
|
+
(also inside a same-origin iframe), fill, submit, wait, then report which
|
|
59
|
+
fields were found, whether the password field disappeared, the address it
|
|
60
|
+
landed on and an excerpt of the page. It never echoes the password back.
|
|
61
|
+
- `key` presses Enter/Tab/Escape; Enter submits the surrounding form.
|
|
62
|
+
- `wait` can wait for a selector, a text, or `url_contains`.
|
|
63
|
+
|
|
64
|
+
### Seeing the page
|
|
65
|
+
|
|
66
|
+
Two ways to give the model actual pixels:
|
|
67
|
+
|
|
68
|
+
- `images` lists the pictures in the viewport; `image { index }` attaches one of
|
|
69
|
+
them, so the model can look at a photo, chart, QR code or captcha. HTTP(S)
|
|
70
|
+
sources are fetched by the Host (the page's own `fetch` is bound by CORS);
|
|
71
|
+
`data:`, `blob:` and `<canvas>` sources are decoded inside the page.
|
|
72
|
+
- `screenshot` captures the Browser pane itself and attaches it. It deliberately
|
|
73
|
+
avoids every native capture API — `webview.capturePage()` crashed the renderer
|
|
74
|
+
(see below) — and instead reads the pane's geometry from the page, then
|
|
75
|
+
captures the DSH window with `PrintWindow` through PowerShell and crops to that
|
|
76
|
+
rectangle. Because it renders the window's own pixels, it also works while
|
|
77
|
+
other applications cover the window. A **minimized** window has no rendered
|
|
78
|
+
surface, so the tool refuses with that reason — pass `restore: true` to let it
|
|
79
|
+
bring the window back first. This path is Windows-only today; elsewhere the
|
|
80
|
+
tool says so instead of failing quietly.
|
|
81
|
+
|
|
82
|
+
## Install
|
|
83
|
+
|
|
84
|
+
The plugin is a normal DSH bundle, so any spec the plugin manager accepts works.
|
|
85
|
+
|
|
86
|
+
**From npm** (published as `dsh-sidebar-browser-control`). Ask the agent, no
|
|
87
|
+
restart needed:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
plugin_manager { action: install_bundle, target: "dsh-sidebar-browser-control" }
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
or with the CLI:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
dsh plugin --profile desktop add dsh-sidebar-browser-control
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**From GitHub**, if you prefer tracking `main`:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
plugin_manager { action: install_bundle, target: "github:XUFENGCHINA/dsh-sidebar-browser-control" }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**From a checkout**, for development:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
dsh plugin --profile desktop add link:/abs/path/to/checkout
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Remove it with `plugin_manager { action: "remove_bundle", target: "dsh-sidebar-browser-control" }`.
|
|
112
|
+
|
|
113
|
+
After editing `client.js` in a checkout, ask the Host to re-scan the bundle
|
|
114
|
+
(`set_bundle` off, then on) — the client artifact is served from a snapshot.
|
|
115
|
+
|
|
116
|
+
## Use
|
|
117
|
+
|
|
118
|
+
Just ask, in any session whose Sidebar is on screen:
|
|
119
|
+
|
|
120
|
+
- "open `https://news.ycombinator.com` in the built-in browser and summarise the top 5"
|
|
121
|
+
- "in the built-in browser, click the *Sign in* link and tell me what the form asks for"
|
|
122
|
+
- "search Bing in the built-in browser for DeepSeek Harness and give me the first three results"
|
|
123
|
+
- `/browser open https://example.com` — straight from the composer, no model call
|
|
124
|
+
|
|
125
|
+
Two behaviours worth knowing while driving it:
|
|
126
|
+
|
|
127
|
+
- **A link that opens a new window becomes a new sidebar tab** — DSH turns the
|
|
128
|
+
popup request into a tab of its own. `browser_page click` reports it as
|
|
129
|
+
`opened_tab`/`opened_url`; continue with that id, because the original tab
|
|
130
|
+
stays where it was.
|
|
131
|
+
- **A page that fails to load says so** — DNS, network, certificate and bot-check
|
|
132
|
+
failures leave Chromium's error page in the tab, and page actions report that
|
|
133
|
+
explicitly instead of returning empty content that reads as "the page is
|
|
134
|
+
empty".
|
|
135
|
+
|
|
136
|
+
## How it works
|
|
137
|
+
|
|
138
|
+
The browser lives in the Web renderer, tools live in the Host, and DSH exposes no
|
|
139
|
+
supported Host → Client call to third-party plugins. So the plugin is two halves
|
|
140
|
+
joined by four loopback routes (a long-poll carries Host → Client commands, with
|
|
141
|
+
no timer in either direction), and all layout/navigation goes through
|
|
142
|
+
`ctx.sidebarRight` so the shipped address bar, history and restore logic stay
|
|
143
|
+
authoritative.
|
|
144
|
+
|
|
145
|
+
Full protocol, design decisions and the DSH internals it depends on:
|
|
146
|
+
[docs/architecture.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/docs/architecture.md).
|
|
147
|
+
|
|
148
|
+
## Security
|
|
149
|
+
|
|
150
|
+
`browser_page eval` runs arbitrary JavaScript inside the browser tab, with that
|
|
151
|
+
page's cookies — if you are logged in there, the agent can act as you in that
|
|
152
|
+
tab. Tool calls are logged with their arguments, but treat these tools like
|
|
153
|
+
letting someone read your screen. The four routes admit only the DSH application
|
|
154
|
+
origin (no cross-site CSRF) and only this plugin's own tools can enqueue a
|
|
155
|
+
command. Details:
|
|
156
|
+
[SECURITY.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/SECURITY.md).
|
|
157
|
+
|
|
158
|
+
## Compatibility
|
|
159
|
+
|
|
160
|
+
Verified end to end on **DSH Desktop 0.2.0-rc.2 / Electron 44 / Windows x64**:
|
|
161
|
+
list, open, navigate, back/forward/reload, read text, `eval`, list elements,
|
|
162
|
+
click, type + submit, float/dock, close, expand/collapse. The Web profile gets
|
|
163
|
+
tab and layout control (its sandboxed iframe cannot be read).
|
|
164
|
+
|
|
165
|
+
The plugin talks to public services (`ctx.sidebarRight`, `ctx.webServer`,
|
|
166
|
+
`ctx.tools`, `ctx.commands`) plus a few DOM markers owned by the shipped Sidebar
|
|
167
|
+
packages. If a marker changes, page-level actions fail with an explicit message
|
|
168
|
+
while tab and layout control keep working; the table of those dependencies is in
|
|
169
|
+
[docs/architecture.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/docs/architecture.md#dsh-internals-this-plugin-depends-on).
|
|
170
|
+
|
|
171
|
+
## Known limitations
|
|
172
|
+
|
|
173
|
+
- **No screenshots through Electron.** `webview.capturePage()` natively crashed
|
|
174
|
+
the Electron renderer on the verified deployment, so it is not used anywhere.
|
|
175
|
+
`browser_page screenshot` goes through PrintWindow instead: the window must not
|
|
176
|
+
be minimized, and only Windows is implemented (macOS/Linux report that).
|
|
177
|
+
Evidence and survivable alternatives:
|
|
178
|
+
[docs/architecture.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/docs/architecture.md#why-there-is-no-screenshot).
|
|
179
|
+
- Page-level actions are **Desktop only**.
|
|
180
|
+
- Tab ids are unique per session; an ambiguous id is reported and accepted as
|
|
181
|
+
`<sessionId>#<tabId>`.
|
|
182
|
+
- Actions are selector-based — no coordinate clicks, uploads or downloads — and
|
|
183
|
+
they target the session currently on screen (`ctx.sidebarRight` semantics).
|
|
184
|
+
|
|
185
|
+
## Development
|
|
186
|
+
|
|
187
|
+
No build step and no dependencies: `client.js` is the shipped artifact, written
|
|
188
|
+
by hand in the loader's classic-script format.
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
npm test # offline protocol test: stub context + real HTTP + a fake client half
|
|
192
|
+
npm run verify # syntax + protocol test + packaged-tarball check
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`npm test` needs no DSH running, so it works in CI and on a clean checkout.
|
|
196
|
+
Guidelines and the list of invariants that keep this plugin loadable:
|
|
197
|
+
[CONTRIBUTING.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/CONTRIBUTING.md).
|
|
198
|
+
Releasing:
|
|
199
|
+
[RELEASING.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/RELEASING.md).
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
[MIT](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/LICENSE)
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# dsh-sidebar-browser-control
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-sidebar-browser-control)
|
|
4
|
+
[](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/LICENSE)
|
|
6
|
+
[](#兼容性)
|
|
7
|
+
|
|
8
|
+
**让 Agent 直接驱动 DSH 自带的内置浏览器**(右侧栏的「浏览器」tab),而不是再开一个 Chromium。
|
|
9
|
+
|
|
10
|
+
[English →](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/README.md)
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
你 › 在内置浏览器里打开文档页,告诉我 API 那一节讲了什么
|
|
14
|
+
AI › browser_control { action: "open", url: "https://example.com/docs" }
|
|
15
|
+
browser_page { action: "text" }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 为什么不用 CDP / Playwright 方案
|
|
19
|
+
|
|
20
|
+
npm 上已有一个走 CDP 的 DSH 浏览器插件(`dsh-browser-control`)。本插件是它的**应用内对照物**,
|
|
21
|
+
差别就是价值所在:
|
|
22
|
+
|
|
23
|
+
| | 本插件 | CDP / Playwright 封装 |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| 驱动对象 | DSH 已经自带的那只浏览器 tab | 另起的浏览器进程 |
|
|
26
|
+
| 你在哪看到 | 右侧栏,就在会话旁边 | 另一个窗口 |
|
|
27
|
+
| 额外运行时 | 无 | 浏览器 + driver |
|
|
28
|
+
| 登录态 | 该 tab 已在用的工作区分区 | 你自己另外配 |
|
|
29
|
+
| 能力边界 | 只有这个 tab | 任意页面、无头、截图 |
|
|
30
|
+
|
|
31
|
+
想和 AI **一起看着同一个页面**做事,用这个;要无头自动化、下载、截图,用 CDP 方案。
|
|
32
|
+
|
|
33
|
+
## 能做什么
|
|
34
|
+
|
|
35
|
+
| 工具 | 动作 |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `browser_tabs` | 列出内置浏览器已打开的标签:id、实时标题、URL、所属会话、面板状态、是否支持页面级控制 |
|
|
38
|
+
| `browser_control` | `open` · `navigate` · `back` · `forward` · `reload` · `close` · `focus` · `expand` · `collapse` · `fullscreen` · `split` · `float` · `dock` · `external` |
|
|
39
|
+
| `browser_page` | `text` · `links` · `elements` · `eval` · `click` · `type` · `scroll` · `wait`(**仅 Desktop**) |
|
|
40
|
+
| `/browser` | `open <url>` · `tabs` · `back` · `forward` · `reload` · `close` · `focus` · `expand` · `collapse` · `fullscreen` · `split` · `float` · `dock` · `external` · `read` |
|
|
41
|
+
|
|
42
|
+
工具和斜杠命令**共用同一份实现**,所以 `/browser open …` 不花模型轮次,行为与工具完全一致。
|
|
43
|
+
|
|
44
|
+
## 安装
|
|
45
|
+
|
|
46
|
+
它就是一个普通 DSH bundle,plugin manager 接受的任何 spec 都能用。
|
|
47
|
+
|
|
48
|
+
**从 npm 安装**(已发布为 `dsh-sidebar-browser-control`)。让 Agent 装,无需重启:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
plugin_manager { action: install_bundle, target: "dsh-sidebar-browser-control" }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
或用 CLI:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
dsh plugin --profile desktop add dsh-sidebar-browser-control
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**从 GitHub 安装**(想跟 `main` 分支时用):
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
plugin_manager { action: install_bundle, target: "github:XUFENGCHINA/dsh-sidebar-browser-control" }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**从本地 checkout 安装**(开发用):
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
dsh plugin --profile desktop add link:/绝对路径/到/本仓库
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
卸载:`plugin_manager { action: "remove_bundle", target: "dsh-sidebar-browser-control" }`。
|
|
73
|
+
|
|
74
|
+
本地开发时改完 `client.js` 要请 Host 重新扫描 bundle(`set_bundle` 关一次再开一次)——
|
|
75
|
+
客户端产物是按快照提供的,光改文件不会生效。
|
|
76
|
+
|
|
77
|
+
## 用法
|
|
78
|
+
|
|
79
|
+
直接说就行(右侧栏要有屏幕上的会话):
|
|
80
|
+
|
|
81
|
+
- 「在内置浏览器打开 `https://news.ycombinator.com`,总结前 5 条」
|
|
82
|
+
- 「在内置浏览器里点 *Sign in*,告诉我表单要填什么」
|
|
83
|
+
- 「在内置浏览器用 Bing 搜 DeepSeek Harness,给我前三条结果」
|
|
84
|
+
- `/browser open https://example.com` —— 输入框直接敲,不经过模型
|
|
85
|
+
|
|
86
|
+
驱动它时值得知道的两条实际行为:
|
|
87
|
+
|
|
88
|
+
- **新窗口打开的链接会变成一个**新的侧栏标签**:DSH 把 popup 请求转成了独立的 tab。
|
|
89
|
+
`browser_page click` 会把它报成 `opened_tab`/`opened_url`,请接着用那个 id——
|
|
90
|
+
原标签仍停在原来的页面上。
|
|
91
|
+
- **加载失败的页面会明确报出来**:DNS、网络、证书、以及反爬挑战失败时,标签里是
|
|
92
|
+
Chromium 错误页;页面级动作会明确说明这一点,而不是返回空内容让你误以为"页面是空的"。
|
|
93
|
+
|
|
94
|
+
## 工作原理
|
|
95
|
+
|
|
96
|
+
浏览器活在 Web 渲染进程里,工具活在 Host 进程里,而 DSH 没有面向第三方插件的
|
|
97
|
+
Host → Client 调用。于是插件拆成两半,用 4 条回环路由相连(Host → Client 走**长轮询**,
|
|
98
|
+
两个方向都没有定时轮询);导航与布局全部走公开的 `ctx.sidebarRight`,
|
|
99
|
+
所以内置地址栏、历史、重启恢复逻辑始终是权威。
|
|
100
|
+
|
|
101
|
+
完整协议、设计取舍、以及它依赖的 DSH 内部细节见
|
|
102
|
+
[docs/architecture.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/docs/architecture.md)。
|
|
103
|
+
|
|
104
|
+
## 安全
|
|
105
|
+
|
|
106
|
+
`browser_page eval` 会在该 tab 的页面里执行任意 JavaScript,并带着那个页面的 Cookie——
|
|
107
|
+
你在里面登录过什么,Agent 就能以你的身份在那个 tab 里做什么。工具调用会连同参数进会话日志,
|
|
108
|
+
但请把这三个工具当作「允许对方看你的屏幕」来对待。4 条路由只放行 DSH 自身来源(跨站 CSRF 打不进来),
|
|
109
|
+
且只有本插件自己的工具能下发命令。细节见
|
|
110
|
+
[SECURITY.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/SECURITY.md)。
|
|
111
|
+
|
|
112
|
+
## 兼容性
|
|
113
|
+
|
|
114
|
+
已在 **DSH Desktop 0.2.0-rc.2 / Electron 44 / Windows x64** 上端到端实测:
|
|
115
|
+
列出、打开、导航、前进后退、刷新、读取正文、`eval`、列出元素、点击、输入并提交、
|
|
116
|
+
浮窗/停靠、关闭、展开/收起。Web profile 只能做标签与布局控制(sandbox iframe 读不到页面内容)。
|
|
117
|
+
|
|
118
|
+
插件只依赖公开服务(`ctx.sidebarRight`、`ctx.webServer`、`ctx.tools`、`ctx.commands`)
|
|
119
|
+
以及若干由随包 Sidebar 拥有的 DOM 标记。标记一旦变化,页面级动作会**明确报错**,
|
|
120
|
+
而标签与布局控制照常可用;依赖清单见
|
|
121
|
+
[docs/architecture.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/docs/architecture.md#dsh-internals-this-plugin-depends-on)。
|
|
122
|
+
|
|
123
|
+
## 已知限制
|
|
124
|
+
|
|
125
|
+
- **没有截图。** `webview.capturePage()` 在实测环境下让 Electron 渲染进程**原生崩溃**,
|
|
126
|
+
因此该能力被移除,调用会明确拒绝并说明原因。证据与可行替代方案见
|
|
127
|
+
[docs/architecture.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/docs/architecture.md#why-there-is-no-screenshot)。
|
|
128
|
+
- 页面级操作**仅 Desktop**。
|
|
129
|
+
- tab id 只在会话内唯一;重名时以 `<会话id>#<tabN>` 形式给出并接受。
|
|
130
|
+
- 动作为选择器式(无坐标点击、上传、下载),且作用于**屏幕上显示的会话**(`ctx.sidebarRight` 的语义)。
|
|
131
|
+
|
|
132
|
+
## 开发
|
|
133
|
+
|
|
134
|
+
无构建步骤、无依赖:`client.js` 就是交付产物,按 loader 的 classic-script 格式手写。
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
npm test # 离线协议测试:stub context + 真实 HTTP + 假 Client 半
|
|
138
|
+
npm run verify # 语法 + 协议测试 + 打包产物自足性检查
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`npm test` 不需要运行中的 DSH,因此在 CI 和全新 checkout 上都能跑。
|
|
142
|
+
规范与「保证可加载」的几条硬约束见
|
|
143
|
+
[CONTRIBUTING.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/CONTRIBUTING.md),
|
|
144
|
+
发布流程见
|
|
145
|
+
[RELEASING.md](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/RELEASING.md)。
|
|
146
|
+
|
|
147
|
+
## 许可
|
|
148
|
+
|
|
149
|
+
[MIT](https://github.com/XUFENGCHINA/dsh-sidebar-browser-control/blob/main/LICENSE)
|