dsh-click 0.3.27 → 0.3.28
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/CHANGELOG.md +7 -0
- package/README.en.md +441 -0
- package/README.es.md +441 -0
- package/README.hi.md +441 -0
- package/README.md +262 -194
- package/README.pt.md +441 -0
- package/lib/index.js +1 -1
- package/lib/types/version.d.ts +1 -1
- package/native/win32/dsh-click-helper.ps1 +70 -0
- package/package.json +1 -1
- package/README-es.md +0 -377
- package/README-hi.md +0 -377
- package/README-pt.md +0 -377
- package/README-zh.md +0 -377
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.28] - 2026-11-13
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **The helper is now DPI-aware, so every coordinate and screenshot is in physical pixels.** `powershell.exe` starts DPI-unaware, so `GetWindowRect` / `GetSystemMetrics` / `GetClientRect` returned logical pixels while UIA `BoundingRectangle` and the screen DC were physical. On a 200% display that is a clean 2x mismatch: `screen_shot` allocated a 1920x1080 bitmap and BitBlt copied the top-left 1920x1080 of the 3840x2160 surface (a crop, not a scaled image), and elements in the right/bottom half failed the client-area check. The helper now sets Per-Monitor V2 (`SetProcessDpiAwarenessContext(-4)`) before any window API, falling back to `SetProcessDpiAwareness(2)` and `SetProcessDPIAware()`. Fixes the size/unit half of #35.
|
|
8
|
+
- New read-only `metrics` op returns the effective DPI awareness, screen and virtual-screen metrics and the monitor count, so a user can report the DPI state without taking a screenshot.
|
|
9
|
+
|
|
3
10
|
## [0.3.27] - 2026-11-05
|
|
4
11
|
|
|
5
12
|
### Changed
|
package/README.en.md
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/dsh-click-hero-en-dark.webp">
|
|
5
|
+
<img src="docs/assets/dsh-click-hero-en-light.webp" width="100%" alt="dsh-click: a desktop window's accessibility elements (e12 Edit, e13 Button) are read by screen_read into an observationId; actions cite it via basedOn, cross the freshness, approval and process-identity safety boundary, run through the Windows UIA helper, and land as dsh-click/observed and dsh-click/action audit events">
|
|
6
|
+
</picture>
|
|
7
|
+
|
|
8
|
+
# dsh-click
|
|
9
|
+
|
|
10
|
+
**See the screen, then act — every mutating click is gated, every observation and action is audited.**
|
|
11
|
+
|
|
12
|
+
Native desktop control for DeepSeek Harness (Windows first): an accessibility tree plus pixel hints let text-only models “see”, window-scoped click and input let them “act”, and approval, freshness, and process-identity checks sit in between.
|
|
13
|
+
|
|
14
|
+
[Install](#three-step-setup) · [Configuration](#configuration) · [FAQ](#faq) · [简体中文](README.md) · [English](README.en.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
|
|
15
|
+
|
|
16
|
+
[](LICENSE)
|
|
17
|
+
[](#compatibility)
|
|
18
|
+
[](https://www.npmjs.com/package/dsh-click)
|
|
19
|
+
[](https://github.com/PerryLink/dsh-click/actions/workflows/ci.yml)
|
|
20
|
+
[](#compatibility)
|
|
21
|
+
|
|
22
|
+
[](https://github.com/PerryLink/dsh-click/stargazers)
|
|
23
|
+
[](https://www.npmjs.com/package/dsh-click)
|
|
24
|
+
[](https://dshfind.com/plugins/PerryLink/dsh-click?ref=badge)
|
|
25
|
+
[](https://securityscorecards.dev/viewer/?uri=github.com/PerryLink/dsh-click)
|
|
26
|
+
[](https://dsh.market/)
|
|
27
|
+
[](https://gitee.com/perrylink/dsh-click)
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
dsh plugin --profile <name> add dsh-click
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<sub>Community plugin, not affiliated with DeepSeek. Canonical repository: <https://github.com/PerryLink/dsh-click> (Gitee is a mirror).</sub>
|
|
36
|
+
|
|
37
|
+
## What it is
|
|
38
|
+
|
|
39
|
+
`dsh-click` gives the model a complete observe → act loop: `screen_read` returns a window’s accessibility tree (element ids, types, names, rectangles, supported patterns) plus pixel-location hints, or `screen_shot` captures an image; then `click` / `type` / `scroll` / `key` act on that same window by element id or coordinates. Every mutating action must cite a fresh observation (`basedOn`) — a changed screen or an expired observation is refused with a model-readable reason — and crosses `ctx.approval` by default, with the target process identity verified before and after. It does not steal foreground focus by default (`focusFallback: never`), and every observation and action lands as a sanitized `dsh-click/observed` / `dsh-click/action` audit event.
|
|
40
|
+
|
|
41
|
+
<picture>
|
|
42
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/dsh-click-flow-v5-dark.svg">
|
|
43
|
+
<img src="docs/assets/dsh-click-flow-v5-light.svg" width="100%" alt="dsh-click boundary two-sided structure: the read-only observe plane on the left produces an observationId; the SAFETY BOUNDARY in the middle checks basedOn, freshness, approval, helper dispatch and process identity, returning refusals to screen_read; the mutating act plane on the right acts through the helper; both sanitized audit events sit on the bottom rail">
|
|
44
|
+
</picture>
|
|
45
|
+
|
|
46
|
+
## Three-step setup
|
|
47
|
+
|
|
48
|
+
1. **Install** (pick one channel):
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
# git channel (latest main; equivalent to git+https://github.com/PerryLink/dsh-click.git)
|
|
52
|
+
dsh plugin --profile web add github:PerryLink/dsh-click
|
|
53
|
+
# npm channel (published releases)
|
|
54
|
+
dsh plugin --profile web add dsh-click
|
|
55
|
+
# tarball channel: pnpm pack in this repo, then
|
|
56
|
+
dsh plugin --profile web add ./dsh-click-<version>.tgz
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The git channel’s `prepare` script builds with production dependencies only.
|
|
60
|
+
|
|
61
|
+
2. **Minimal config** (sane defaults; touch `autoApproveWindows` only to exempt specific windows):
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
- insert:
|
|
65
|
+
- id: dsh-click
|
|
66
|
+
name: dsh-click
|
|
67
|
+
config:
|
|
68
|
+
requireApproval: true
|
|
69
|
+
autoApproveWindows: ['^Notepad']
|
|
70
|
+
focusFallback: never
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
3. **Verify it mounts** (after a restart):
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
dsh --profile web --dump-config | grep -A3 'id: dsh-click'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then ask the agent to look at a window and act — the approval prompt appears for every mutating action:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
> Open Notepad, type "hello", then read back what is on screen.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Uninstall**: `dsh plugin --profile web remove dsh-click` (or remove the row from the profile patch).
|
|
86
|
+
|
|
87
|
+
> If pnpm reports `ERR_PNPM_IGNORED_BUILDS` for this package (esbuild’s harmless platform-binary validation), add `allowBuilds: { esbuild: true }` to your `pnpm-workspace.yaml` — the `dsh` CLI prints the exact snippet.
|
|
88
|
+
|
|
89
|
+
<details>
|
|
90
|
+
<summary>Install from the DSH Desktop market</summary>
|
|
91
|
+
|
|
92
|
+
Every PerryLink plugin is listed in the built-in DSH Desktop market: **Market → Sources → Add source → paste** `https://perrylink-dsh-catalog.perrylink.workers.dev/catalog-source.json` **→ select**. Installation still requires the market’s npm identity check and your confirmation.
|
|
93
|
+
|
|
94
|
+
</details>
|
|
95
|
+
|
|
96
|
+
## Core capabilities
|
|
97
|
+
|
|
98
|
+
`dsh-click` splits the native desktop into an auditable observation face and action face:
|
|
99
|
+
|
|
100
|
+
- **`screen_shot`** — captures a window (or the primary screen) and downscales it to `maxScreenshotSide`. With a vision-capable model the result carries the image; text-only models get a text description and keep working.
|
|
101
|
+
- **`screen_read`** — the structured observation: the accessibility tree (element ids, types, names, rectangles, supported patterns) plus pixel-location hints with colors — plain text, no image model required.
|
|
102
|
+
- **`screen_find`** — for applications that expose no accessibility tree, finds clickable text or a described visual target via optional OCR (`ocr.*`, tesseract probed at mount) or visual grounding, returning screen coordinates plus an `observationId`; read-only, never needs approval.
|
|
103
|
+
- **`click` / `type` / `scroll` / `key`** — window-scoped actions addressed by element id or coordinates. Delivery prefers UIA invoke, falls back to posted window messages, and never steals foreground focus by default; `type` takes the UIA `ValuePattern` fast path and otherwise injects real keystrokes through `SendInput` (CJK-safe); `key` reports honestly when an app ignores posted input.
|
|
104
|
+
- **`app_list` / `app_launch`** — enumerate running applications and their visible windows; launch one by name or executable path.
|
|
105
|
+
|
|
106
|
+
Every mutating action crosses one shared safety boundary:
|
|
107
|
+
|
|
108
|
+
1. **Freshness** — the action must cite a `basedOn` observation; the window is re-captured right before acting, and the action is refused when the pixel hash (`staleCheckPixels`) or the accessibility tree (`staleCheckTree`) changed, or when the observation is older than `maxObservationAgeMs`.
|
|
109
|
+
2. **Approval** — `ctx.approval` gates every action by default; `autoApproveWindows` title/executable regexes can exempt specific windows (still freshness-checked, process-verified, and audited).
|
|
110
|
+
3. **Process identity** — the owning process’s pid and executable path are verified before **and** after the act; a mid-act swap refuses loudly (`PROCESS_CHANGED`).
|
|
111
|
+
4. **Audit** — observations and actions land in the session log as `dsh-click/observed` / `dsh-click/action` events (sanitized, log-only).
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
model harness
|
|
115
|
+
│ screen_read ──▶ observationId (+ elements, pixels) ← structured text
|
|
116
|
+
│ click {basedOn, target} ──▶ freshness check ──▶ approval ──▶ helper (UIA)
|
|
117
|
+
│ pixel hash changed? ── refuse + re-observe
|
|
118
|
+
│ pid/exe changed after act? ── PROCESS_CHANGED
|
|
119
|
+
│ ◀── canonical JSON + audit events (dsh-click/action)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Tool surface
|
|
123
|
+
|
|
124
|
+
| Tool | Read-only | Needs approval | Notes |
|
|
125
|
+
|---|---|---|---|
|
|
126
|
+
| `screen_shot` | ✅ | — | Returns an `observationId` later actions cite in `basedOn`; image attachment when the model accepts images |
|
|
127
|
+
| `screen_read` | ✅ | — | Accessibility tree + pixel hints; element ids are what actions address |
|
|
128
|
+
| `screen_find` | ✅ | — | OCR/visual grounding when there is no UIA tree; returns coordinate targets + an `observationId` |
|
|
129
|
+
| `click` | | ✅ | Exactly one of `elementId` or `(x, y)`; UIA invoke preferred, posted messages fallback |
|
|
130
|
+
| `type` | | ✅ | Value-pattern elements only; backs up and restores control text on failure |
|
|
131
|
+
| `scroll` | | ✅ | Element (scroll pattern) or window (posted wheel) |
|
|
132
|
+
| `key` | | ✅ | Posted key combinations (`"Ctrl+S"`); apps that ignore posted input refuse loudly |
|
|
133
|
+
| `app_list` | ✅ | — | Running applications and their visible windows |
|
|
134
|
+
| `app_launch` | | ✅ | By name or executable path, with optional arguments |
|
|
135
|
+
|
|
136
|
+
### Examples
|
|
137
|
+
|
|
138
|
+
These are the plugin’s real entry points; install once, then call one.
|
|
139
|
+
|
|
140
|
+
**Detailed example** — command `app_list`, input:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Output:
|
|
147
|
+
|
|
148
|
+
```text
|
|
149
|
+
1 running application(s) with windows:
|
|
150
|
+
- Demo (pid 4242, C:\Apps\demo.exe)
|
|
151
|
+
- [windowId 1122867] "Demo App" at (10, 20) 800x600
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
*Observed from `plugins/dsh-click/tests/tools.spec.ts:159-185; renderer at src/tools.ts:933-942`*
|
|
155
|
+
|
|
156
|
+
**Failure branch** — input:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
{}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Output:
|
|
163
|
+
|
|
164
|
+
```text
|
|
165
|
+
Error: dsh-click backend unavailable on linux: Linux backend is reserved but not implemented yet (Windows-first); only Windows can act today
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
*Observed from `plugins/dsh-click/src/platform/selection.ts:61-62,81; plugins/dsh-click/src/tools.ts:133-136; plugins/dsh-click/tests/tools.spec.ts:226-245`*
|
|
169
|
+
|
|
170
|
+
**Brief examples**: `screen_read` · `app_list`
|
|
171
|
+
|
|
172
|
+
## Configuration
|
|
173
|
+
|
|
174
|
+
All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. `cordis.patch.yml` documents each key inline.
|
|
175
|
+
|
|
176
|
+
Most-used keys:
|
|
177
|
+
|
|
178
|
+
| Key | Default | Meaning |
|
|
179
|
+
|---|---|---|
|
|
180
|
+
| `requireApproval` | `true` | Gate every mutating action behind approval; observers never ask |
|
|
181
|
+
| `autoApproveWindows` | `[]` | Window-title/executable regexes that skip the approval ask (still freshness-checked, process-verified, and audited) |
|
|
182
|
+
| `focusFallback` | `never` | Whether an action may bring the target window to the foreground as a last resort (`never` / `allow`) |
|
|
183
|
+
| `imageMode` | `auto` | `screen_shot` rendering: `auto` (image when the model accepts images, text otherwise) or `text` |
|
|
184
|
+
| `staleCheckPixels` | `true` | Compare a fresh pixel hash before every action and refuse on change |
|
|
185
|
+
| `staleCheckTree` | `target` | Accessibility-tree freshness: `target` verifies the addressed element (default), `strict` refuses any changed node, `off` skips the tree hash (identity/age/pixel checks still apply) |
|
|
186
|
+
| `maxObservationAgeMs` | `30000` | Maximum age in ms of an observation an action may cite (1000..600000) |
|
|
187
|
+
| `auditSessionEvents` | `true` | Whether to append `dsh-click/observed` / `dsh-click/action` audit events; set `false` to stop audit appends entirely |
|
|
188
|
+
|
|
189
|
+
<details>
|
|
190
|
+
<summary>Full configuration table (17 rows)</summary>
|
|
191
|
+
|
|
192
|
+
| Key | Default | Meaning |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| `requireApproval` | `true` | Gate every mutating action behind approval; observers never ask |
|
|
195
|
+
| `autoApproveWindows` | `[]` | Window-title/executable regexes that skip the approval ask (still freshness-checked, process-verified, and audited) |
|
|
196
|
+
| `auditSessionEvents` | `true` | Append `dsh-click/observed` / `dsh-click/action` session audit events. The adaptive gate already skips the append on envelope-less hosts (rc.6–rc.8, 0.1.1-rc.2, and 0.1.2-rc.1, which fails closed on unknown types at read); set `false` to stop audit appends entirely. `0.1.2-rc.1` (adapted 2026-09-02): the session envelope keeps its ignorable field for stored-log read compatibility only — `Session.append` still cannot stamp it, so audit-gate behavior is unchanged |
|
|
197
|
+
| `focusFallback` | `never` | Whether an action may bring the target window to the foreground as a last resort (`never` / `allow`) |
|
|
198
|
+
| `imageMode` | `auto` | `screen_shot` rendering: `auto` (image when the model accepts images, text otherwise) or `text` |
|
|
199
|
+
| `helperTimeoutMs` | `30000` | Per-helper-call timeout in ms (1..300000) |
|
|
200
|
+
| `maxHelperOutputBytes` | `25165824` | Cap on one helper response in bytes (1024..67108864) |
|
|
201
|
+
| `maxScreenshotSide` | `2560` | Longest screenshot side in pixels (320..7680); larger captures are downscaled |
|
|
202
|
+
| `staleCheckPixels` | `true` | Compare a fresh pixel hash before every action and refuse on change |
|
|
203
|
+
| `staleCheckTree` | `target` | Accessibility-tree freshness: `target` verifies the addressed element (default), `strict` refuses any changed node, `off` skips the whole-tree hash for windows with a ticking clock/cursor (identity/age/pixel checks still apply) |
|
|
204
|
+
| `maxObservationAgeMs` | `30000` | Maximum age in ms of an observation an action may cite (1000..600000) |
|
|
205
|
+
| `maxCachedObservations` | `8` | LRU cap on cached observations (1..64) |
|
|
206
|
+
| `maxElements` | `500` | Cap on accessibility elements per `screen_read` (1..2000) |
|
|
207
|
+
| `maxTreeDepth` | `32` | Maximum accessibility tree-walk depth (1..64) |
|
|
208
|
+
| `maxTextLength` | `200` | Truncation length for sanitized model-visible strings (16..10000) |
|
|
209
|
+
| `rollbackEnabled` | `true` | Back up and restore control text when `type` fails |
|
|
210
|
+
| `ocr.enabled` / `command` / `language` | `true` / `tesseract` / `eng` | Optional OCR for the `screen_find` path (probed at mount; degrades to unavailable when tesseract is absent) |
|
|
211
|
+
|
|
212
|
+
</details>
|
|
213
|
+
|
|
214
|
+
Example override in your profile patch:
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
- insert:
|
|
218
|
+
- id: dsh-click
|
|
219
|
+
name: dsh-click
|
|
220
|
+
config:
|
|
221
|
+
requireApproval: true
|
|
222
|
+
autoApproveWindows: ['^Notepad']
|
|
223
|
+
focusFallback: never
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## FAQ
|
|
227
|
+
|
|
228
|
+
<details>
|
|
229
|
+
<summary>Where do screenshots and observations live? Can screen content hit the disk?</summary>
|
|
230
|
+
|
|
231
|
+
A `screen_shot` image goes into the harness attachment store (content-addressed, under the host’s own attachment policy) and is provided to the model only through that tool result. Observations themselves stay in memory (bounded LRU, `maxCachedObservations`, lost on restart); beyond that the plugin writes nothing to disk, makes no network requests, and stores no credentials. The only session-log content is the `dsh-click/*` audit events, and window titles, executable paths, and free text are sanitized and length-capped before they are written or shown.
|
|
232
|
+
|
|
233
|
+
</details>
|
|
234
|
+
|
|
235
|
+
<details>
|
|
236
|
+
<summary>What happens on macOS / Linux? Silent breakage?</summary>
|
|
237
|
+
|
|
238
|
+
Nothing is silent. Both backends are reserved but unimplemented, so every call fails closed with a model-readable reason (`dsh-click backend unavailable on linux: ...`), and the profile still boots everywhere. On Windows, a missing `subprocess` service or an unavailable helper refuses the call loudly instead of pretending success.
|
|
239
|
+
|
|
240
|
+
</details>
|
|
241
|
+
|
|
242
|
+
<details>
|
|
243
|
+
<summary>Does it fight other plugins over commands, services, or slots?</summary>
|
|
244
|
+
|
|
245
|
+
It provides no service key and consumes only two optional seams (`dsh-click/backend`, `dsh-click/grounding`, for tests/embeddings); it registers no client slot, no `webServer` route, and no waterfall listener; every audit event sits in the `dsh-click/*` namespace. Each tool registration is wrapped in `ctx.effect`, so stop/hot-reload removes exactly the tools it registered.
|
|
246
|
+
|
|
247
|
+
</details>
|
|
248
|
+
|
|
249
|
+
<details>
|
|
250
|
+
<summary>How big is the performance overhead? Does every action re-capture the screen?</summary>
|
|
251
|
+
|
|
252
|
+
Observations are produced on demand: `screen_read` only walks the accessibility tree (plain text), while `screen_shot` encodes a PNG. Every mutating action re-captures the target window once for the freshness comparison (pixel hash plus tree by default) — that is part of the safety boundary. Helper calls are bounded by `helperTimeoutMs` / `maxHelperOutputBytes`, and the observation cache keeps 8 entries by default.
|
|
253
|
+
|
|
254
|
+
</details>
|
|
255
|
+
|
|
256
|
+
## Security boundaries
|
|
257
|
+
|
|
258
|
+
- **Observe before act, every time.** Actions must cite a fresh observation; a changed screen (pixel hash) or an expired observation is refused with a model-readable reason demanding re-observation.
|
|
259
|
+
- **Approval is the default.** `requireApproval: true` unless you explicitly exempt specific windows; every action — allowed or not — is audit-logged.
|
|
260
|
+
- **No foreground stealing.** The helper never brings a target window to the foreground (`focusFallback: 'never'` by default); input is delivered through UIA or posted messages so background windows are not disturbed. `focusFallback: 'allow'` is the only sanctioned exception.
|
|
261
|
+
- **Process identity is re-verified** immediately before and after each action; a mid-act process swap fails the outcome (`PROCESS_CHANGED`).
|
|
262
|
+
- **Sanitized output.** Control characters are stripped, tabs collapse, credential-shaped values (keys, tokens, JWTs, bearer headers) are redacted before anything reaches the model or the log.
|
|
263
|
+
- **Fail closed.** Unsupported platforms, a missing subprocess service, or an unavailable helper refuse every call loudly — profiles keep booting everywhere.
|
|
264
|
+
|
|
265
|
+
## Permissions & data
|
|
266
|
+
|
|
267
|
+
- **Permissions**: mutating actions cross the official `ctx.approval` seam — the plugin never re-implements or bypasses it. `autoApproveWindows` only ever *skips the ask for specific windows*; it cannot disable the freshness or process-identity checks. The `dshWorkshop` manifest declares `fs:read`, `subprocess:spawn`, `session:append`, `network:none`, `native-code:none`.
|
|
268
|
+
- **Data**: the plugin stores nothing on disk except the screenshots the attachment store keeps (content-addressed, under the harness’s own attachment policy). Observations are cached in memory (LRU, bounded). No network requests, no credential storage.
|
|
269
|
+
- **Session log**: `dsh-click/observed` and `dsh-click/action` are log-only audit events carrying sanitized window/process facts — titles, paths, and free text are redacted and length-capped before they are written or shown.
|
|
270
|
+
|
|
271
|
+
## Known limitations
|
|
272
|
+
|
|
273
|
+
- **Windows first.** macOS and Linux backends are reserved; on those platforms every call fails closed with a clear reason.
|
|
274
|
+
- **Text-only fidelity.** `screen_read` depends on the application exposing UIAutomation; apps without an accessible tree yield pixel hints only, plus the `screen_find` OCR/grounding path. Coordinate clicks remain available.
|
|
275
|
+
- **Posted-input apps.** Some applications ignore posted window messages (games, some Electron surfaces); `key` reports this honestly instead of pretending success. Since 0.3.24 the `type` `SendInput` fallback covers real keyboard input and CJK text, but it is still bounded by the target app’s own input model.
|
|
276
|
+
- **Session audit on envelope-less harness builds.** The audit events ride an adaptive gate: hosts that know the vocabulary append plainly, hosts with the `ignorable` envelope append with the marker, and envelope-less hosts — `0.1.0-rc.6`–`0.1.0-rc.8`, `0.1.1-rc.2`, and `0.1.2-rc.1` (which cannot stamp the ignorable marker — the envelope field is retained for stored-log read compatibility only — and fails closed on unknown types at read) — get no audit append; the tool results remain the reconstructable audit trail. Set `auditSessionEvents: false` to stop audit appends entirely.
|
|
277
|
+
|
|
278
|
+
## Interoperability with other DSH plugins
|
|
279
|
+
|
|
280
|
+
`dsh-click` exposes a tool surface only and does not join other plugins’ seams:
|
|
281
|
+
|
|
282
|
+
- **Two hard services only.** `inject = ['tools', 'subprocess']`; it provides no service key, so it cannot collide on one.
|
|
283
|
+
- **No client or HTTP resources.** It registers no client slot, no `webServer` route, and no `agent/pre-step` / `tools/post-execute` waterfall listener, and mutates no globals.
|
|
284
|
+
- **Namespaced audit.** It writes only `dsh-click/observed` and `dsh-click/action`; when a host does not know the vocabulary the adaptive gate skips them, and the tool results remain the reconstructable audit trail.
|
|
285
|
+
- **Optional seams degrade.** `dsh-click/backend` and `dsh-click/grounding` exist for tests/embeddings only; real deployments fall through to platform selection and require no other plugin.
|
|
286
|
+
- **Registrations are effects.** Every `ctx.tools.register` is wrapped in `ctx.effect`, so stop/hot-reload removes exactly the tools it registered.
|
|
287
|
+
|
|
288
|
+
## Compatibility
|
|
289
|
+
|
|
290
|
+
| Surface | Status |
|
|
291
|
+
|---|---|
|
|
292
|
+
| Harness | DeepSeek Harness `dsh-v0.2.1-alpha.1` (GitHub tag, verified 2026-09-25). Verified 2026-09-11 against the `dsh-v0.1.7-alpha.1` master checkout (full gate chain + profile install smoke). `engines.dsh`: `>=0.2.1-0 <0.3.0 \|\| >=0.2.2-0 <0.3.0` |
|
|
293
|
+
| Node | `^22.19.0 \|\| >=24.9.0` |
|
|
294
|
+
| Platforms | **Windows first** (UIAutomation + Win32 input, via a bundled PowerShell helper); macOS/Linux backends are reserved and fail closed with a clear reason |
|
|
295
|
+
| Model | Text-only models fully supported (`screen_read` returns structured text); vision models additionally get `screen_shot` images |
|
|
296
|
+
|
|
297
|
+
## Ecosystem & quality
|
|
298
|
+
|
|
299
|
+
- [Gitee mirror](https://gitee.com/perrylink/dsh-click) (sync mirror; GitHub is canonical)
|
|
300
|
+
- [dshfind plugin page](https://dshfind.com/plugins/PerryLink/dsh-click) (installs and ranking)
|
|
301
|
+
- [OpenSSF Scorecard report](https://securityscorecards.dev/viewer/?uri=github.com/PerryLink/dsh-click) (driven by [.github/workflows/scorecard.yml](.github/workflows/scorecard.yml))
|
|
302
|
+
- [dsh-plugin-doctor verification report](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章) (K10–K13 all `pass`)
|
|
303
|
+
- [DSH Market](https://dsh.market/) (listed)
|
|
304
|
+
- **1024 store channel**: `npm i -g dsh1024` once, then `dsh1024 plugin --profile web add dsh-click` (counts toward the [deepseek1024.com](https://deepseek1024.com) install ranking)
|
|
305
|
+
- [Ecosystem knowledge base](https://perrylink.github.io/dsh-plugin-guide/) — measured data, not marketing: plugin development guide · plugin-selection data · maintenance criteria
|
|
306
|
+
|
|
307
|
+
## Development
|
|
308
|
+
|
|
309
|
+
```sh
|
|
310
|
+
pnpm install # node ^22.19 || >=24
|
|
311
|
+
pnpm run typecheck # tsc: src + tests against the local harness checkout
|
|
312
|
+
pnpm run typecheck:ci # tsc against the published host types (no paths)
|
|
313
|
+
pnpm test # vitest: 79 tests, 13 files (helper smoke runs on Windows)
|
|
314
|
+
pnpm run build # tsdown bundle + tsc declarations (lib/)
|
|
315
|
+
pnpm run verify:self-contained # dependency specs resolve from the registry
|
|
316
|
+
pnpm run verify:artifacts # built ESM face + native helper present
|
|
317
|
+
pnpm run check:readmes # five-language README consistency
|
|
318
|
+
pnpm pack # the published tarball
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
The README images are generated programmatically by [`scripts/gen-readme-assets.py`](scripts/gen-readme-assets.py) (Python + Pillow) and are safe to re-run: `python scripts/gen-readme-assets.py`.
|
|
322
|
+
|
|
323
|
+
Topics: `dsh`, `dsh-plugin`, `deepseek-harness`, `deepseek`, `cordis`, `computer-use`, `windows-automation`, `uiautomation`, `desktop-control`, `screen-reader`
|
|
324
|
+
|
|
325
|
+
## Family & thanks
|
|
326
|
+
|
|
327
|
+
This project is part of the DeepSeek Harness plugin family from [PerryLink](https://github.com/PerryLink) (all Apache-2.0). If it is useful, **a star helps the next person find it** — nothing is gated behind it.
|
|
328
|
+
|
|
329
|
+
- [Windows helper smoke checklist](docs/windows-smoke.md) — real input/focus verification for 0.3.24+.
|
|
330
|
+
- [@LIU12312-Source](https://github.com/LIU12312-Source) — real `SendInput`/foreground-focus fallback for the Windows helper (PR #21).
|
|
331
|
+
- [@Mchsd](https://github.com/Mchsd) — added the `auditSessionEvents` opt-out for harnesses whose session reader rejects the `dsh-click` audit events (#2).
|
|
332
|
+
- [@PerryLink](https://github.com/PerryLink) — creator and maintainer: tool surface, action safety boundary, Windows native helper, sanitizers, and the five-language docs.
|
|
333
|
+
|
|
334
|
+
<details>
|
|
335
|
+
<summary>Expand all plugins</summary>
|
|
336
|
+
|
|
337
|
+
| Plugin | Status |
|
|
338
|
+
|---|---|
|
|
339
|
+
| **[dsh-aqua-input-check](https://github.com/PerryLink/dsh-aqua-input-check)** | |
|
|
340
|
+
| **[dsh-archive-check](https://github.com/PerryLink/dsh-archive-check)** | |
|
|
341
|
+
| **[dsh-auto-review](https://github.com/PerryLink/dsh-auto-review)** | |
|
|
342
|
+
| **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | 🧊 FROZEN — see the repo README |
|
|
343
|
+
| **[dsh-bid-ca-precheck](https://github.com/PerryLink/dsh-bid-ca-precheck)** | |
|
|
344
|
+
| **[dsh-bid-qual-check](https://github.com/PerryLink/dsh-bid-qual-check)** | |
|
|
345
|
+
| **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | 🧊 FROZEN — see the repo README |
|
|
346
|
+
| **[dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind)** | |
|
|
347
|
+
| **[dsh-click](https://github.com/PerryLink/dsh-click)** | |
|
|
348
|
+
| **[dsh-composer-history](https://github.com/PerryLink/dsh-composer-history)** | |
|
|
349
|
+
| **[dsh-contract-stance](https://github.com/PerryLink/dsh-contract-stance)** | |
|
|
350
|
+
| **[dsh-customs-doc-check](https://github.com/PerryLink/dsh-customs-doc-check)** | |
|
|
351
|
+
| **[dsh-data-quality](https://github.com/PerryLink/dsh-data-quality)** | 🧊 FROZEN — see the repo README |
|
|
352
|
+
| **[dsh-demurrage-ledger](https://github.com/PerryLink/dsh-demurrage-ledger)** | |
|
|
353
|
+
| **[dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck)** | |
|
|
354
|
+
| **[dsh-drill-script-check](https://github.com/PerryLink/dsh-drill-script-check)** | |
|
|
355
|
+
| **[dsh-eia-guide-check](https://github.com/PerryLink/dsh-eia-guide-check)** | |
|
|
356
|
+
| **[dsh-emergency-plan](https://github.com/PerryLink/dsh-emergency-plan)** | |
|
|
357
|
+
| **[dsh-essay-rubric-check](https://github.com/PerryLink/dsh-essay-rubric-check)** | |
|
|
358
|
+
| **[dsh-evidence-check](https://github.com/PerryLink/dsh-evidence-check)** | |
|
|
359
|
+
| **[dsh-export-ctl-check](https://github.com/PerryLink/dsh-export-ctl-check)** | |
|
|
360
|
+
| **[dsh-fast](https://github.com/PerryLink/dsh-fast)** | |
|
|
361
|
+
| **[dsh-fmea-table-check](https://github.com/PerryLink/dsh-fmea-table-check)** | |
|
|
362
|
+
| **[dsh-forecast-penalty](https://github.com/PerryLink/dsh-forecast-penalty)** | |
|
|
363
|
+
| **[dsh-fund-research](https://github.com/PerryLink/dsh-fund-research)** | |
|
|
364
|
+
| **[dsh-github](https://github.com/PerryLink/dsh-github)** | |
|
|
365
|
+
| **[dsh-gongwen-flow-check](https://github.com/PerryLink/dsh-gongwen-flow-check)** | |
|
|
366
|
+
| **[dsh-gongwen-word-check](https://github.com/PerryLink/dsh-gongwen-word-check)** | |
|
|
367
|
+
| **[dsh-guard-plan-qc](https://github.com/PerryLink/dsh-guard-plan-qc)** | |
|
|
368
|
+
| **[dsh-hazchem-check](https://github.com/PerryLink/dsh-hazchem-check)** | |
|
|
369
|
+
| **[dsh-hazplan-check](https://github.com/PerryLink/dsh-hazplan-check)** | |
|
|
370
|
+
| **[dsh-hidden-risk-map](https://github.com/PerryLink/dsh-hidden-risk-map)** | |
|
|
371
|
+
| **[dsh-hs-classify](https://github.com/PerryLink/dsh-hs-classify)** | |
|
|
372
|
+
| **[dsh-icd-rule-check](https://github.com/PerryLink/dsh-icd-rule-check)** | |
|
|
373
|
+
| **[dsh-industry-research](https://github.com/PerryLink/dsh-industry-research)** | |
|
|
374
|
+
| **[dsh-lawcite-adapter](https://github.com/PerryLink/dsh-lawcite-adapter)** | |
|
|
375
|
+
| **[dsh-laya](https://github.com/PerryLink/dsh-laya)** | |
|
|
376
|
+
| **[dsh-lc-doc-check](https://github.com/PerryLink/dsh-lc-doc-check)** | |
|
|
377
|
+
| **[dsh-learning-gap-check](https://github.com/PerryLink/dsh-learning-gap-check)** | |
|
|
378
|
+
| **[dsh-library](https://github.com/PerryLink/dsh-library)** | |
|
|
379
|
+
| **[dsh-local-ai](https://github.com/PerryLink/dsh-local-ai)** | |
|
|
380
|
+
| **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | |
|
|
381
|
+
| **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | |
|
|
382
|
+
| **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | |
|
|
383
|
+
| **[dsh-medrec-qc](https://github.com/PerryLink/dsh-medrec-qc)** | |
|
|
384
|
+
| **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | 🧊 FROZEN — see the repo README |
|
|
385
|
+
| **[dsh-nsfc-form-check](https://github.com/PerryLink/dsh-nsfc-form-check)** | |
|
|
386
|
+
| **[dsh-nurse-record-check](https://github.com/PerryLink/dsh-nurse-record-check)** | |
|
|
387
|
+
| **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | |
|
|
388
|
+
| **[dsh-origin-rvc-check](https://github.com/PerryLink/dsh-origin-rvc-check)** | |
|
|
389
|
+
| **[dsh-ota-review-check](https://github.com/PerryLink/dsh-ota-review-check)** | |
|
|
390
|
+
| **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | |
|
|
391
|
+
| **[dsh-paper-doc-adapter](https://github.com/PerryLink/dsh-paper-doc-adapter)** | |
|
|
392
|
+
| **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | |
|
|
393
|
+
| **[dsh-permit-report-check](https://github.com/PerryLink/dsh-permit-report-check)** | |
|
|
394
|
+
| **[dsh-pipeline-check](https://github.com/PerryLink/dsh-pipeline-check)** | |
|
|
395
|
+
| **[dsh-pleading-draft](https://github.com/PerryLink/dsh-pleading-draft)** | |
|
|
396
|
+
| **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | 🚫 RETIRED (repo archived) |
|
|
397
|
+
| **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | |
|
|
398
|
+
| **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | 🚫 RETIRED (repo archived) |
|
|
399
|
+
| **[dsh-plugin-upgrade](https://github.com/PerryLink/dsh-plugin-upgrade)** | 🚫 RETIRED (repo archived) |
|
|
400
|
+
| **[dsh-policy-brief-draft](https://github.com/PerryLink/dsh-policy-brief-draft)** | |
|
|
401
|
+
| **[dsh-power-loss-split](https://github.com/PerryLink/dsh-power-loss-split)** | |
|
|
402
|
+
| **[dsh-power-ticket-check](https://github.com/PerryLink/dsh-power-ticket-check)** | |
|
|
403
|
+
| **[dsh-ppap-check](https://github.com/PerryLink/dsh-ppap-check)** | |
|
|
404
|
+
| **[dsh-protest-deadline](https://github.com/PerryLink/dsh-protest-deadline)** | |
|
|
405
|
+
| **[dsh-railway-window](https://github.com/PerryLink/dsh-railway-window)** | |
|
|
406
|
+
| **[dsh-repair-order-qc](https://github.com/PerryLink/dsh-repair-order-qc)** | |
|
|
407
|
+
| **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | |
|
|
408
|
+
| **[dsh-review-reply-check](https://github.com/PerryLink/dsh-review-reply-check)** | |
|
|
409
|
+
| **[dsh-rulefile-check](https://github.com/PerryLink/dsh-rulefile-check)** | |
|
|
410
|
+
| **[dsh-safety-brief-check](https://github.com/PerryLink/dsh-safety-brief-check)** | |
|
|
411
|
+
| **[dsh-score](https://github.com/PerryLink/dsh-score)** | 🧊 FROZEN — see the repo README |
|
|
412
|
+
| **[dsh-session-sync](https://github.com/PerryLink/dsh-session-sync)** | |
|
|
413
|
+
| **[dsh-site-log-check](https://github.com/PerryLink/dsh-site-log-check)** | |
|
|
414
|
+
| **[dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security)** | |
|
|
415
|
+
| **[dsh-soe-decision-check](https://github.com/PerryLink/dsh-soe-decision-check)** | |
|
|
416
|
+
| **[dsh-soilwater-check](https://github.com/PerryLink/dsh-soilwater-check)** | |
|
|
417
|
+
| **[dsh-sop-sync-check](https://github.com/PerryLink/dsh-sop-sync-check)** | |
|
|
418
|
+
| **[dsh-spc-gbt-adapter](https://github.com/PerryLink/dsh-spc-gbt-adapter)** | |
|
|
419
|
+
| **[dsh-talk](https://github.com/PerryLink/dsh-talk)** | |
|
|
420
|
+
| **[dsh-tender-extract](https://github.com/PerryLink/dsh-tender-extract)** | |
|
|
421
|
+
| **[dsh-tender-matrix](https://github.com/PerryLink/dsh-tender-matrix)** | |
|
|
422
|
+
| **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | |
|
|
423
|
+
| **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | 🚫 RETIRED (repo archived) |
|
|
424
|
+
| **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | |
|
|
425
|
+
| **[dsh-warranty-calc](https://github.com/PerryLink/dsh-warranty-calc)** | |
|
|
426
|
+
| **[dsh-budget](https://github.com/PerryLink/dsh-budget)** | 🧊 FROZEN — see the repo README |
|
|
427
|
+
| **[dsh-claude-move](https://github.com/PerryLink/dsh-claude-move)** | 🧊 FROZEN — see the repo README |
|
|
428
|
+
| **[dsh-defend](https://github.com/PerryLink/dsh-defend)** | 🧊 FROZEN — see the repo README |
|
|
429
|
+
| **[dsh-draw](https://github.com/PerryLink/dsh-draw)** | 🧊 FROZEN — see the repo README |
|
|
430
|
+
| **[dsh-reach](https://github.com/PerryLink/dsh-reach)** | 🧊 FROZEN — see the repo README |
|
|
431
|
+
| **[dsh-background-agents](https://github.com/PerryLink/dsh-background-agents)** | 🚫 RETIRED (repo archived) |
|
|
432
|
+
| **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | 🚫 RETIRED (repo archived) |
|
|
433
|
+
| **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | 🚫 RETIRED (repo archived) |
|
|
434
|
+
|
|
435
|
+
</details>
|
|
436
|
+
|
|
437
|
+
## License
|
|
438
|
+
|
|
439
|
+
[LICENSE](LICENSE) (Apache License 2.0) © 2026 dsh-click contributors
|
|
440
|
+
|
|
441
|
+
<p align="center"><sub>Apache-2.0 · Community plugin, not affiliated with DeepSeek.</sub></p>
|