dsh-click 0.3.26 → 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.
@@ -150,6 +150,27 @@ public static class DshClickWin32 {
150
150
  [DllImport("user32.dll")]
151
151
  public static extern int GetSystemMetrics(int index);
152
152
 
153
+ // DPI awareness. The helper is hosted by powershell.exe, whose manifest
154
+ // declares no DPI awareness, so GetWindowRect/GetSystemMetrics/GetClientRect
155
+ // return logical pixels while UIA BoundingRectangle and the screen DC are
156
+ // physical. On a 200% display that is a clean 2x mismatch (and a 1:1 BitBlt
157
+ // of a logical-sized rect is a crop of the physical surface, not a scaled
158
+ // image). Per-Monitor V2 is set before any window or metric API runs.
159
+ [DllImport("user32.dll", SetLastError = true)]
160
+ public static extern bool SetProcessDpiAwarenessContext(IntPtr context);
161
+
162
+ [DllImport("user32.dll")]
163
+ public static extern IntPtr GetThreadDpiAwarenessContext();
164
+
165
+ [DllImport("user32.dll")]
166
+ public static extern int GetAwarenessFromDpiAwarenessContext(IntPtr context);
167
+
168
+ [DllImport("shcore.dll")]
169
+ public static extern int SetProcessDpiAwareness(int awareness);
170
+
171
+ [DllImport("user32.dll")]
172
+ public static extern bool SetProcessDPIAware();
173
+
153
174
  [DllImport("kernel32.dll", SetLastError = true)]
154
175
  public static extern IntPtr OpenProcess(uint access, bool inherit, uint processId);
155
176
 
@@ -187,6 +208,33 @@ public static class DshClickWin32 {
187
208
  }
188
209
  '@ | Out-Null
189
210
 
211
+ # ---------------------------------------------------------------------------
212
+ # DPI awareness (must run before any HWND/metric API).
213
+ # ---------------------------------------------------------------------------
214
+ # DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = -4. Each helper process serves
215
+ # exactly one request, so setting it once here is enough. Fall back to the
216
+ # 8.1+ shcore call and then to the Vista-era system-aware call; if every call
217
+ # fails, keep the old behaviour instead of breaking the request.
218
+ $script:DpiAwareness = 0
219
+ try {
220
+ if ([DshClickWin32]::SetProcessDpiAwarenessContext([IntPtr](-4))) { $script:DpiAwareness = 2 }
221
+ } catch { }
222
+ if ($script:DpiAwareness -eq 0) {
223
+ try {
224
+ if ([DshClickWin32]::SetProcessDpiAwareness(2) -eq 0) { $script:DpiAwareness = 2 }
225
+ } catch { }
226
+ }
227
+ if ($script:DpiAwareness -eq 0) {
228
+ try {
229
+ if ([DshClickWin32]::SetProcessDPIAware()) { $script:DpiAwareness = 1 }
230
+ } catch { }
231
+ }
232
+ if ($script:DpiAwareness -eq 0) {
233
+ try {
234
+ $script:DpiAwareness = [DshClickWin32]::GetAwarenessFromDpiAwarenessContext([DshClickWin32]::GetThreadDpiAwarenessContext())
235
+ } catch { }
236
+ }
237
+
190
238
  # ---------------------------------------------------------------------------
191
239
  # Response plumbing.
192
240
  # ---------------------------------------------------------------------------
@@ -965,6 +1013,27 @@ function Invoke-OpLaunch($opArgs) {
965
1013
  return @{ processId = [int]$process.Id; executablePath = $path }
966
1014
  }
967
1015
 
1016
+ # ---------------------------------------------------------------------------
1017
+ # Metrics: DPU/DPI diagnostics without touching a window.
1018
+ # ---------------------------------------------------------------------------
1019
+ function Invoke-OpMetrics {
1020
+ # 0 = unaware (legacy bug), 1 = system-aware, 2 = per-monitor.
1021
+ return @{
1022
+ awareness = [int]$script:DpiAwareness
1023
+ screen = @{
1024
+ width = [int][DshClickWin32]::GetSystemMetrics(0) # SM_CXSCREEN
1025
+ height = [int][DshClickWin32]::GetSystemMetrics(1) # SM_CYSCREEN
1026
+ }
1027
+ virtualScreen = @{
1028
+ x = [int][DshClickWin32]::GetSystemMetrics(76) # SM_XVIRTUALSCREEN
1029
+ y = [int][DshClickWin32]::GetSystemMetrics(77) # SM_YVIRTUALSCREEN
1030
+ width = [int][DshClickWin32]::GetSystemMetrics(78) # SM_CXVIRTUALSCREEN
1031
+ height = [int][DshClickWin32]::GetSystemMetrics(79) # SM_CYVIRTUALSCREEN
1032
+ }
1033
+ monitors = [int][DshClickWin32]::GetSystemMetrics(80) # SM_CMONITORS
1034
+ }
1035
+ }
1036
+
968
1037
  # ---------------------------------------------------------------------------
969
1038
  # Entry point.
970
1039
  # ---------------------------------------------------------------------------
@@ -978,6 +1047,7 @@ try {
978
1047
  $script:focusFallbackDetail = $null
979
1048
  switch ([string]$request.op) {
980
1049
  'windows' { $result = Invoke-OpWindows }
1050
+ 'metrics' { $result = Invoke-OpMetrics }
981
1051
  'apps' { $result = Invoke-OpApps }
982
1052
  'snapshot' { $result = Invoke-OpSnapshot $opArgs }
983
1053
  'shot' { $result = Invoke-OpShot $opArgs }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-click",
3
- "version": "0.3.26",
3
+ "version": "0.3.28",
4
4
  "description": "Cross-platform native desktop control tools for DeepSeek Harness (Windows first): screen_shot, screen_read (accessibility tree + pixel description for text-only models), click/type/scroll/key, and app_list/app_launch — every mutating action gated by approval, never stealing foreground focus, with stale-observation rejection and process-identity checks",
5
5
  "repository": {
6
6
  "type": "git",
@@ -102,43 +102,46 @@
102
102
  "screen-reader"
103
103
  ],
104
104
  "engines": {
105
- "node": "^22.19.0 || >=24.0.0",
106
- "dsh": ">=0.2.1-0 <0.3.0"
105
+ "node": "^22.19.0 || >=24.9.0",
106
+ "dsh": ">=0.2.1-0 <0.3.0 || >=0.2.2-0 <0.3.0"
107
107
  },
108
108
  "packageManager": "pnpm@11.7.0",
109
109
  "peerDependencies": {
110
110
  "@deepseek-ai/cordis": "^4.0.5-alpha.1",
111
- "@deepseek-ai/dsh-agent": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0",
112
- "@deepseek-ai/dsh-attachment": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0",
113
- "@deepseek-ai/dsh-llm": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0",
114
- "@deepseek-ai/dsh-session": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0",
115
- "@deepseek-ai/dsh-subprocess": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0",
116
- "@deepseek-ai/dsh-tools": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0",
117
- "@deepseek-ai/dsh-user-approval": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0",
118
- "@deepseek-ai/schemastery": "^3.18.5"
111
+ "@deepseek-ai/dsh-agent": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0 || >=0.2.2-0 <0.3.0",
112
+ "@deepseek-ai/dsh-attachment": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0 || >=0.2.2-0 <0.3.0",
113
+ "@deepseek-ai/dsh-llm": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0 || >=0.2.2-0 <0.3.0",
114
+ "@deepseek-ai/dsh-session": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0 || >=0.2.2-0 <0.3.0",
115
+ "@deepseek-ai/dsh-subprocess": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0 || >=0.2.2-0 <0.3.0",
116
+ "@deepseek-ai/dsh-tools": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0 || >=0.2.2-0 <0.3.0",
117
+ "@deepseek-ai/dsh-user-approval": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0 || >=0.2.2-0 <0.3.0",
118
+ "@deepseek-ai/schemastery": "^3.18.5-alpha.1"
119
119
  },
120
120
  "dependencies": {},
121
121
  "devDependencies": {
122
- "@deepseek-ai/cordis": "^4.0.5-alpha.1",
123
- "@deepseek-ai/cordis-plugin-include": "^1.0.10-alpha.1",
124
- "@deepseek-ai/cordis-plugin-loader": "^1.0.6-alpha.1",
125
- "@deepseek-ai/dsh-agent": "0.2.1-rc.2",
126
- "@deepseek-ai/dsh-attachment": "0.2.1-rc.2",
127
- "@deepseek-ai/dsh-llm": "0.2.1-rc.2",
128
- "@deepseek-ai/dsh-session": "0.2.1-rc.2",
129
- "@deepseek-ai/dsh-subprocess": "0.2.1-rc.2",
130
- "@deepseek-ai/dsh-subprocess-local": "0.2.1-rc.2",
131
- "@deepseek-ai/dsh-system-prompt": "0.2.1-rc.2",
132
- "@deepseek-ai/dsh-tools": "0.2.1-rc.2",
133
- "@deepseek-ai/dsh-user-approval": "0.2.1-rc.2",
134
- "@deepseek-ai/schemastery": "^3.18.5",
135
- "@types/node": "^22.20.5",
136
- "@vitest/coverage-v8": "3.2.7",
122
+ "@deepseek-ai/cordis": "^4.1.0",
123
+ "@deepseek-ai/cordis-plugin-include": "^1.1.0",
124
+ "@deepseek-ai/cordis-plugin-loader": "^1.1.0",
125
+ "@deepseek-ai/dsh-agent": "0.2.2-rc.1",
126
+ "@deepseek-ai/dsh-attachment": "0.2.2-rc.1",
127
+ "@deepseek-ai/dsh-llm": "0.2.2-rc.1",
128
+ "@deepseek-ai/dsh-session": "0.2.2-rc.1",
129
+ "@deepseek-ai/dsh-session-projection": "0.2.2-rc.1",
130
+ "@deepseek-ai/dsh-subprocess": "0.2.2-rc.1",
131
+ "@deepseek-ai/dsh-subprocess-local": "0.2.2-rc.1",
132
+ "@deepseek-ai/dsh-system-prompt": "0.2.2-rc.1",
133
+ "@deepseek-ai/dsh-tool-executor-native": "0.2.2-rc.1",
134
+ "@deepseek-ai/dsh-tools": "0.2.2-rc.1",
135
+ "@deepseek-ai/dsh-user-approval": "0.2.2-rc.1",
136
+ "@deepseek-ai/schemastery": "~3.19.0",
137
+ "@types/node": "^22.19.0",
138
+ "@vitest/coverage-v8": "3.2.0",
137
139
  "oxlint": "0.18.1",
138
140
  "vitest": "^3.2.0",
139
- "@deepseek-ai/dsh-working-directory": "0.2.1-rc.2",
140
- "tsdown": "^0.23.2",
141
- "typescript": "^5.9.0"
141
+ "@deepseek-ai/dsh-working-directory": "0.2.2-rc.1",
142
+ "tsdown": "^0.22.14",
143
+ "typescript": "^5.9.0",
144
+ "@deepseek-ai/dsh-package-manifest": "0.2.2-rc.1"
142
145
  },
143
146
  "scripts": {
144
147
  "build": "node scripts/prepare.mjs",
package/README-es.md DELETED
@@ -1,377 +0,0 @@
1
- <div align="center">
2
-
3
- # 🖱️ dsh-click
4
- - **Canal 1024 store**: `npm i -g dsh1024` una vez, luego `dsh1024 plugin --profile web add dsh-click` (cuenta para el ranking de instalaciones de [deepseek1024.com](https://deepseek1024.com)).
5
-
6
- **Control nativo de escritorio multiplataforma para DeepSeek Harness — Windows primero.**
7
-
8
- *Mira la pantalla y luego actúa — cada clic autorizado, cada acción auditada.*
9
-
10
- [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
11
- [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-click)
12
- [![DSH plugin](https://img.shields.io/badge/dsh--plugin-✅-green)](https://github.com/topics/dsh-plugin)
13
- [![dsh-doctor](https://raw.githubusercontent.com/PerryLink/dsh-plugin-doctor/main/badges/PerryLink__dsh-click.svg)](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章)
14
- [![DSH Market](https://raw.githubusercontent.com/2BingLing/dsh-market/master/assets/readme/badge-listed-en.svg)](https://dsh.market/)
15
- [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
16
- [![CI](https://img.shields.io/github/actions/workflow/status/PerryLink/dsh-click/ci.yml?branch=main&label=CI)](https://github.com/PerryLink/dsh-click/actions)
17
- [![Version](https://img.shields.io/github/v/tag/PerryLink/dsh-click?label=version)](https://github.com/PerryLink/dsh-click/releases)
18
- [![npm version](https://img.shields.io/npm/v/dsh-click)](https://www.npmjs.com/package/dsh-click)
19
- [![npm downloads](https://img.shields.io/npm/dm/dsh-click)](https://www.npmjs.com/package/dsh-click)
20
- [![dshfind](https://dshfind.com/api/badge/PerryLink/dsh-click?metric=downloads&lang=es)](https://dshfind.com/es/plugins/PerryLink/dsh-click?ref=badge)
21
-
22
- [English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
23
-
24
- ```sh
25
- dsh plugin --profile <name> add dsh-click
26
- ```
27
-
28
-
29
- </div>
30
-
31
- ---
32
-
33
-
34
- **📖 Base de conocimiento del ecosistema** — datos medidos, no marketing: [guía de desarrollo · datos de selección · criterios de mantenimiento](https://perrylink.github.io/dsh-plugin-guide/).
35
-
36
- <!-- star-cta -->
37
- ## Instalación y desinstalación
38
-
39
- - **Canal git** (último `main`): `dsh plugin --profile web add github:PerryLink/dsh-click` — el script `prepare` compila solo con dependencias de producción.
40
- - **Canal npm** (versiones publicadas): `dsh plugin --profile web add dsh-click`.
41
- - **Canal tarball**: `pnpm pack` en este repositorio y luego `dsh plugin --profile web add ./dsh-click-<version>.tgz`.
42
- - **Desinstalar**: `dsh plugin --profile web remove dsh-click` (o elimina la fila del parche del perfil).
43
-
44
- > Si pnpm informa `ERR_PNPM_IGNORED_BUILDS` para este paquete (la validación inofensiva del binario de plataforma de esbuild), añade `allowBuilds: { esbuild: true }` a tu `pnpm-workspace.yaml` — el CLI `dsh` imprime el fragmento exacto.
45
-
46
- ## ⭐ 如果它帮到了你
47
-
48
- Este plugin forma parte de la [familia de plugins DSH](https://github.com/PerryLink) (más de 40, todos Apache-2.0). Si te resulta útil, **dale una estrella**: no desbloquea nada, pero ayuda a que la siguiente persona lo encuentre antes.
49
-
50
- *English:* part of a 95 plugin family for DeepSeek Harness. If it is useful, **a star helps the next person find it** — nothing is gated behind it.
51
-
52
- ## What is dsh-click?
53
-
54
- Control nativo de escritorio multiplataforma para DeepSeek Harness — Windows primero.
55
-
56
- Mira la pantalla y luego actúa — cada clic autorizado, cada acción auditada.
57
-
58
- ![Diagrama de flujo de dsh-click: instalar → abrir panel → actuar.](docs/assets/dsh-click-flow.svg)
59
-
60
- *Resumen del flujo: instalar → abrir panel → actuar. Los ejemplos siguientes usan la superficie de comandos real.*
61
-
62
-
63
- *La misma ejecución, animada.*
64
-
65
- ## Compatibilidad
66
-
67
- | Superficie | Estado |
68
- |---|---|
69
- | Harness | DeepSeek Harness `dsh-v0.2.1-alpha.1` (tag de GitHub, verificado el 2026-09-25). Verificado el 2026-09-11 contra el checkout master dsh-v0.1.7-alpha.1 (cadena completa de gates + smoke de instalación de perfil). |
70
- | Node | `^22.19.0 \|\| >=24.0.0` |
71
- | Plataformas | **Windows primero** (UIAutomation + entrada Win32, mediante un helper de PowerShell incluido); los backends de macOS/Linux están reservados y fallan cerrado con un motivo claro |
72
- | Modelo | Modelos solo-texto totalmente compatibles (`screen_read` devuelve texto estructurado); los modelos con visión reciben además las imágenes de `screen_shot` |
73
-
74
- ## Qué obtienes
75
-
76
- `dsh-click` le da al harness un ciclo completo de observar → actuar sobre aplicaciones de escritorio nativas:
77
-
78
- - **`screen_shot`** — captura de una ventana (o de la pantalla principal), reducida a un límite configurable. Con un modelo con visión el resultado incluye la imagen; en caso contrario, una descripción de texto mantiene funcionales a los modelos solo-texto.
79
- - **`screen_read`** — la observación estructurada: el árbol de accesibilidad de la ventana (ids de elementos, tipos, nombres, rectángulos, patrones soportados) más pistas de píxeles con colores — texto plano, sin necesidad de modelo de imagen.
80
- - **`click` / `type` / `scroll` / `key`** — acciones limitadas a la ventana, dirigidas por id de elemento o coordenadas. La entrega prefiere UIA invoke y recurre a mensajes de ventana enviados — y **nunca roba el foco de primer plano**.
81
- - **`app_list` / `app_launch`** — enumera las aplicaciones en ejecución y sus ventanas; inicia una por nombre o ruta.
82
-
83
- Cada acción que muta cruza una misma frontera de seguridad:
84
-
85
- 1. **Frescura** — la acción debe citar una observación `basedOn`; la ventana se vuelve a capturar justo antes de actuar y la acción se rechaza si la pantalla cambió (hash de píxeles + límite de antigüedad).
86
- 2. **Aprobación** — `ctx.approval` protege cada acción por defecto; las regex de título/ejecutable pueden permitir ventanas concretas (siguen auditadas).
87
- 3. **Identidad del proceso** — el pid y la ruta del ejecutable propietario se verifican antes **y** después del acto; un cambio rechaza el resultado en voz alta.
88
- 4. **Auditoría** — observaciones y acciones quedan en el registro de sesión como eventos `dsh-click/observed` / `dsh-click/action` (sanitizados, solo registro).
89
-
90
- ```text
91
- modelo harness
92
- │ screen_read ──▶ observationId (+ elementos, píxeles) ← texto estructurado
93
- │ click {basedOn, target} ──▶ verificación de frescura ──▶ aprobación ──▶ helper (UIA)
94
- │ ¿hash de píxeles cambió? ── rechazar + volver a observar
95
- │ ¿pid/exe cambió tras el acto? ── PROCESS_CHANGED
96
- │ ◀── JSON canónico + eventos de auditoría (dsh-click/action)
97
- ```
98
-
99
- ## Inicio rápido
100
-
101
- ```sh
102
- dsh plugin --profile web add github:PerryLink/dsh-click
103
- ```
104
-
105
- ```sh
106
- # 1. instala el bundle en tu perfil
107
- dsh plugin --profile web add github:PerryLink/dsh-click
108
-
109
- # o desde npm (versiones publicadas)
110
- dsh plugin --profile web add dsh-click
111
-
112
- # 2. reinicia y verifica la fila
113
- dsh --profile web --dump-config | grep -A2 'id: dsh-click'
114
- ```
115
-
116
- Luego pídele al agente que mire una ventana y actúe — el aviso de aprobación aparece en cada acción que muta:
117
-
118
- ```
119
- > Abre el Bloc de notas, escribe "hola" y lee de nuevo lo que hay en pantalla.
120
- ```
121
-
122
- ### Ejemplos
123
-
124
- Son los puntos de entrada reales; instala y llama a uno.
125
-
126
- #### Ejemplo detallado
127
-
128
- **Comando**
129
-
130
- ~~~sh
131
- app_list
132
- ~~~
133
-
134
- **Entrada**
135
-
136
- ~~~json
137
- {}
138
- ~~~
139
-
140
- **Salida**
141
-
142
- ~~~text
143
- 1 running application(s) with windows:
144
- - Demo (pid 4242, C:\Apps\demo.exe)
145
- - [windowId 1122867] "Demo App" at (10, 20) 800x600
146
- ~~~
147
-
148
- *Observado en `plugins/dsh-click/tests/tools.spec.ts:159-185; renderer at src/tools.ts:933-942`*
149
-
150
- #### Rama de fallo
151
-
152
- **Entrada**
153
-
154
- ~~~text
155
- {}
156
- ~~~
157
-
158
- **Salida**
159
-
160
- ~~~text
161
- Error: dsh-click backend unavailable on linux: Linux backend is reserved but not implemented yet (Windows-first); only Windows can act today
162
- ~~~
163
-
164
- *Observado en `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`*
165
-
166
- #### Ejemplos breves
167
-
168
- - `screen_read`
169
- - `app_list`
170
-
171
- ## Configuración
172
-
173
- Todos los ajustes son campos `Config` de Schemastery (modificables desde cordis.yml). Una sobrescritura dirigida por id reemplaza toda la fila — vuelve a declarar cada clave que necesites. `cordis.patch.yml` documenta cada clave en línea.
174
-
175
- | Clave | Por defecto | Significado |
176
- |---|---|---|
177
- | `requireApproval` | `true` | Proteger cada acción que muta tras la aprobación; los observadores nunca preguntan |
178
- | `autoApproveWindows` | `[]` | Regex de título de ventana/ruta de ejecutable que saltan la pregunta de aprobación (siguen con verificación de frescura y auditoría) |
179
- | `auditSessionEvents` | `true` | Añade eventos de auditoría `dsh-click/observed`/`dsh-click/action` a la sesión. La puerta adaptativa ya omite el append en hosts sin sobre (rc.6–rc.8, 0.1.1-rc.2 y 0.1.2-rc.1, que falla cerrado ante tipos desconocidos en lectura); ponlo en `false` para detener por completo los appends de auditoría 0.1.2-rc.1 (adaptado el 2026-09-02): el sobre de sesión conserva su campo ignorable solo para compatibilidad de lectura de logs almacenados - Session.append aún no puede estamparlo, por lo que el comportamiento de la puerta no cambia. |
180
- | `focusFallback` | `never` | Si una acción puede traer la ventana objetivo al primer plano como último recurso (`never` / `allow`) |
181
- | `imageMode` | `auto` | Renderizado de `screen_shot`: `auto` (imagen si el modelo acepta imágenes, texto en caso contrario) o `text` |
182
- | `helperTimeoutMs` | `30000` | Tiempo de espera por llamada al helper en ms (1..300000) |
183
- | `maxHelperOutputBytes` | `25165824` | Límite de una respuesta del helper en bytes (1024..67108864) |
184
- | `maxScreenshotSide` | `2560` | Lado más largo de la captura en píxeles (320..7680); las mayores se reducen |
185
- | `staleCheckPixels` | `true` | Comparar un hash de píxeles fresco antes de cada acción y rechazar si cambió |
186
- | `staleCheckTree` | `target` | Frescura del árbol: `target` verifica el elemento destino (por defecto), `strict` rechaza cualquier nodo cambiado, `off` omite el hash del árbol |
187
- | `maxObservationAgeMs` | `30000` | Antigüedad máxima en ms de una observación que una acción puede citar (1000..600000) |
188
- | `maxCachedObservations` | `8` | Límite LRU de observaciones en caché (1..64) |
189
- | `maxElements` | `500` | Límite de elementos de accesibilidad por `screen_read` (1..2000) |
190
- | `maxTreeDepth` | `32` | Profundidad máxima del recorrido del árbol de accesibilidad (1..64) |
191
- | `maxTextLength` | `200` | Longitud de truncado de las cadenas visibles para el modelo (16..10000) |
192
- | `rollbackEnabled` | `true` | Respaldar y restaurar el texto del control cuando `type` falla |
193
- | `ocr.enabled` / `command` / `language` | `true` / `tesseract` / `eng` | OCR opcional para `screen_find` (probado al montar; degrada a no disponible sin tesseract) |
194
-
195
- Ejemplo de sobrescritura en el parche de tu perfil:
196
-
197
- ```yaml
198
- - insert:
199
- - id: dsh-click
200
- name: dsh-click
201
- config:
202
- requireApproval: true
203
- autoApproveWindows: ['^Notepad']
204
- focusFallback: never
205
- ```
206
-
207
- ## Herramientas y superficies
208
-
209
- | Herramienta | Solo lectura | Requiere aprobación | Notas |
210
- |---|---|---|---|
211
- | `screen_shot` | ✅ | — | Devuelve un `observationId` que las acciones posteriores citan en `basedOn`; imagen adjunta cuando el modelo acepta imágenes |
212
- | `screen_read` | ✅ | — | Árbol de accesibilidad + pistas de píxeles; los ids de elementos son lo que direccionan las acciones |
213
- | `click` | | ✅ | Exactamente uno de `elementId` o `(x, y)`; se prefiere UIA invoke, con mensajes enviados como respaldo |
214
- | `type` | | ✅ | Solo elementos con patrón de valor; respalda y restaura el texto del control en caso de fallo |
215
- | `scroll` | | ✅ | Elemento (patrón scroll) o ventana (rueda enviada) |
216
- | `key` | | ✅ | Combinaciones de teclas enviadas (`"Ctrl+S"`); las apps que ignoran la entrada enviada rechazan en voz alta |
217
- | `app_list` | ✅ | — | Aplicaciones en ejecución y sus ventanas visibles |
218
- | `app_launch` | | ✅ | Por nombre o ruta de ejecutable, con argumentos opcionales |
219
-
220
- ## Permisos y datos
221
-
222
- - **Permisos**: las acciones que mutan cruzan la costura oficial `ctx.approval` — el plugin nunca la reimplementa ni la esquiva. La lista de permitidos solo *salta la pregunta para ventanas concretas*; no puede desactivar las verificaciones de frescura ni de identidad del proceso.
223
- - **Datos**: el plugin no guarda nada en disco salvo las capturas que conserva el almacén de adjuntos (direccionadas por contenido, bajo la política de adjuntos del harness). Las observaciones viven en memoria (LRU acotado). Sin peticiones de red, sin almacenamiento de credenciales.
224
- - **Registro de sesión**: `dsh-click/observed` y `dsh-click/action` son eventos de auditoría solo-registro con hechos sanitizados de ventana/proceso — títulos, rutas y texto libre se redactan y truncan antes de escribirse o mostrarse.
225
-
226
- ## Límites de seguridad
227
-
228
- - **Observar antes de actuar, siempre.** Las acciones deben citar una observación fresca; una pantalla cambiada (hash de píxeles) o una observación caducada se rechaza con un motivo legible por el modelo que exige volver a observar.
229
- - **La aprobación es el valor por defecto.** `requireApproval: true` salvo que permitas explícitamente ventanas concretas; cada acción — permitida o no — queda auditada.
230
- - **Sin robo de foco.** El helper nunca trae la ventana objetivo al primer plano (`focusFallback: 'never'` por defecto); la entrada se entrega por UIA o mensajes enviados para no molestar a las ventanas en segundo plano.
231
- - **La identidad del proceso se vuelve a verificar** inmediatamente antes y después de cada acción; un cambio de proceso a mitad de camino hace fallar el resultado (`PROCESS_CHANGED`).
232
- - **Salida sanitizada.** Los caracteres de control se eliminan, los tabuladores se colapsan y los valores con forma de credencial (claves, tokens, JWT, cabeceras bearer) se redactan antes de llegar al modelo o al registro.
233
- - **Fallo cerrado.** Plataformas no soportadas, un servicio de subprocesos ausente o un helper no disponible rechazan cada llamada en voz alta — los perfiles siguen arrancando en todas partes.
234
-
235
- ## Limitaciones conocidas
236
-
237
- - **Windows primero.** Los backends de macOS y Linux están reservados; en esas plataformas cada llamada falla cerrado con un motivo claro.
238
- - **Fidelidad solo-texto.** `screen_read` depende de que la aplicación exponga UIAutomation; las apps sin árbol accesible solo ofrecen pistas de píxeles. Los clics por coordenadas siguen disponibles.
239
- - **Apps de entrada enviada.** Algunas aplicaciones ignoran los mensajes de ventana enviados (juegos, algunas superficies Electron); `key` lo informa con honestidad en lugar de fingir éxito.
240
- - **Auditoría de sesión en builds del harness sin sobre.** Los eventos de auditoría cruzan una puerta adaptativa: los hosts que conocen el vocabulario agregan directamente, los hosts con el sobre `ignorable` agregan con el marcador, y los hosts sin sobre — `0.1.0-rc.6`–`0.1.0-rc.8`, `0.1.1-rc.2` y `0.1.2-rc.1` (que no puede estampar el marcador ignorable — el campo del sobre se conserva únicamente para compatibilidad de lectura de logs almacenados — y falla cerrado ante tipos desconocidos en lectura) — no reciben append de auditoría; los resultados de las herramientas siguen siendo la pista reconstruible. Pon `auditSessionEvents: false` para detener los appends por completo.
241
-
242
- ## Desarrollo
243
-
244
- ```sh
245
- pnpm install # node ^22.19 || >=24
246
- pnpm run typecheck # tsc: src + tests contra el checkout local del harness
247
- pnpm run typecheck:ci # tsc contra los tipos publicados 0.1.7-rc.2 (sin paths)
248
- pnpm test # vitest: 66 tests, 11 archivos (el smoke del helper corre en Windows)
249
- pnpm run build # bundle tsdown + declaraciones tsc (lib/)
250
- pnpm run verify:self-contained # las especificaciones de dependencias resuelven desde el registry
251
- pnpm run verify:artifacts # cara ESM construida + helper nativo presentes
252
- pnpm pack # el tarball publicado
253
- ```
254
-
255
- ## Topics
256
-
257
- `dsh`, `dsh-plugin`, `deepseek-harness`, `deepseek`, `cordis`, `computer-use`, `windows-automation`, `uiautomation`, `desktop-control`, `screen-reader`
258
-
259
- ## Contributors
260
-
261
- - [@PerryLink](https://github.com/PerryLink) — creador y mantenedor: superficie de herramientas, frontera de seguridad de acciones, helper nativo de Windows, sanitizadores y la documentación en cinco idiomas.
262
- - [@Mchsd](https://github.com/Mchsd) — añadió la opción `auditSessionEvents` para harnesses cuyo lector de sesión rechaza los eventos de auditoría de `dsh-click` (#2).
263
-
264
- ## PerryLink DSH Plugin Family
265
-
266
- Este proyecto forma parte de la familia de plugins de DeepSeek Harness de [PerryLink](https://github.com/PerryLink). El registro permanece plegado abajo para que cada README conserve una primera pantalla corta; expándelo para ver cada fila y su estado.
267
-
268
- <details>
269
- <summary>Expandir todos los plugins</summary>
270
-
271
- | Plugin | Estado |
272
- |---|---|
273
- | **[dsh-aqua-input-check](https://github.com/PerryLink/dsh-aqua-input-check)** | |
274
- | **[dsh-archive-check](https://github.com/PerryLink/dsh-archive-check)** | |
275
- | **[dsh-auto-review](https://github.com/PerryLink/dsh-auto-review)** | |
276
- | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | |
277
- | **[dsh-bid-ca-precheck](https://github.com/PerryLink/dsh-bid-ca-precheck)** | |
278
- | **[dsh-bid-qual-check](https://github.com/PerryLink/dsh-bid-qual-check)** | |
279
- | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | |
280
- | **[dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind)** | |
281
- | **[dsh-click](https://github.com/PerryLink/dsh-click)** | |
282
- | **[dsh-composer-history](https://github.com/PerryLink/dsh-composer-history)** | |
283
- | **[dsh-contract-stance](https://github.com/PerryLink/dsh-contract-stance)** | |
284
- | **[dsh-customs-doc-check](https://github.com/PerryLink/dsh-customs-doc-check)** | |
285
- | **[dsh-data-quality](https://github.com/PerryLink/dsh-data-quality)** | |
286
- | **[dsh-demurrage-ledger](https://github.com/PerryLink/dsh-demurrage-ledger)** | |
287
- | **[dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck)** | |
288
- | **[dsh-drill-script-check](https://github.com/PerryLink/dsh-drill-script-check)** | |
289
- | **[dsh-eia-guide-check](https://github.com/PerryLink/dsh-eia-guide-check)** | |
290
- | **[dsh-emergency-plan](https://github.com/PerryLink/dsh-emergency-plan)** | |
291
- | **[dsh-essay-rubric-check](https://github.com/PerryLink/dsh-essay-rubric-check)** | |
292
- | **[dsh-evidence-check](https://github.com/PerryLink/dsh-evidence-check)** | |
293
- | **[dsh-export-ctl-check](https://github.com/PerryLink/dsh-export-ctl-check)** | |
294
- | **[dsh-fast](https://github.com/PerryLink/dsh-fast)** | |
295
- | **[dsh-fmea-table-check](https://github.com/PerryLink/dsh-fmea-table-check)** | |
296
- | **[dsh-forecast-penalty](https://github.com/PerryLink/dsh-forecast-penalty)** | |
297
- | **[dsh-fund-research](https://github.com/PerryLink/dsh-fund-research)** | |
298
- | **[dsh-github](https://github.com/PerryLink/dsh-github)** | |
299
- | **[dsh-gongwen-flow-check](https://github.com/PerryLink/dsh-gongwen-flow-check)** | |
300
- | **[dsh-gongwen-word-check](https://github.com/PerryLink/dsh-gongwen-word-check)** | |
301
- | **[dsh-guard-plan-qc](https://github.com/PerryLink/dsh-guard-plan-qc)** | |
302
- | **[dsh-hazchem-check](https://github.com/PerryLink/dsh-hazchem-check)** | |
303
- | **[dsh-hazplan-check](https://github.com/PerryLink/dsh-hazplan-check)** | |
304
- | **[dsh-hidden-risk-map](https://github.com/PerryLink/dsh-hidden-risk-map)** | |
305
- | **[dsh-hs-classify](https://github.com/PerryLink/dsh-hs-classify)** | |
306
- | **[dsh-icd-rule-check](https://github.com/PerryLink/dsh-icd-rule-check)** | |
307
- | **[dsh-industry-research](https://github.com/PerryLink/dsh-industry-research)** | |
308
- | **[dsh-lawcite-adapter](https://github.com/PerryLink/dsh-lawcite-adapter)** | |
309
- | **[dsh-laya](https://github.com/PerryLink/dsh-laya)** | |
310
- | **[dsh-lc-doc-check](https://github.com/PerryLink/dsh-lc-doc-check)** | |
311
- | **[dsh-learning-gap-check](https://github.com/PerryLink/dsh-learning-gap-check)** | |
312
- | **[dsh-library](https://github.com/PerryLink/dsh-library)** | |
313
- | **[dsh-local-ai](https://github.com/PerryLink/dsh-local-ai)** | |
314
- | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | |
315
- | **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | |
316
- | **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | |
317
- | **[dsh-medrec-qc](https://github.com/PerryLink/dsh-medrec-qc)** | |
318
- | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | |
319
- | **[dsh-nsfc-form-check](https://github.com/PerryLink/dsh-nsfc-form-check)** | |
320
- | **[dsh-nurse-record-check](https://github.com/PerryLink/dsh-nurse-record-check)** | |
321
- | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | |
322
- | **[dsh-origin-rvc-check](https://github.com/PerryLink/dsh-origin-rvc-check)** | |
323
- | **[dsh-ota-review-check](https://github.com/PerryLink/dsh-ota-review-check)** | |
324
- | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | |
325
- | **[dsh-paper-doc-adapter](https://github.com/PerryLink/dsh-paper-doc-adapter)** | |
326
- | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | |
327
- | **[dsh-permit-report-check](https://github.com/PerryLink/dsh-permit-report-check)** | |
328
- | **[dsh-pipeline-check](https://github.com/PerryLink/dsh-pipeline-check)** | |
329
- | **[dsh-pleading-draft](https://github.com/PerryLink/dsh-pleading-draft)** | |
330
- | **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | |
331
- | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | |
332
- | **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | |
333
- | **[dsh-plugin-upgrade](https://github.com/PerryLink/dsh-plugin-upgrade)** | |
334
- | **[dsh-policy-brief-draft](https://github.com/PerryLink/dsh-policy-brief-draft)** | |
335
- | **[dsh-power-loss-split](https://github.com/PerryLink/dsh-power-loss-split)** | |
336
- | **[dsh-power-ticket-check](https://github.com/PerryLink/dsh-power-ticket-check)** | |
337
- | **[dsh-ppap-check](https://github.com/PerryLink/dsh-ppap-check)** | |
338
- | **[dsh-protest-deadline](https://github.com/PerryLink/dsh-protest-deadline)** | |
339
- | **[dsh-railway-window](https://github.com/PerryLink/dsh-railway-window)** | |
340
- | **[dsh-repair-order-qc](https://github.com/PerryLink/dsh-repair-order-qc)** | |
341
- | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | |
342
- | **[dsh-review-reply-check](https://github.com/PerryLink/dsh-review-reply-check)** | |
343
- | **[dsh-rulefile-check](https://github.com/PerryLink/dsh-rulefile-check)** | |
344
- | **[dsh-safety-brief-check](https://github.com/PerryLink/dsh-safety-brief-check)** | |
345
- | **[dsh-score](https://github.com/PerryLink/dsh-score)** | |
346
- | **[dsh-session-sync](https://github.com/PerryLink/dsh-session-sync)** | |
347
- | **[dsh-site-log-check](https://github.com/PerryLink/dsh-site-log-check)** | |
348
- | **[dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security)** | |
349
- | **[dsh-soe-decision-check](https://github.com/PerryLink/dsh-soe-decision-check)** | |
350
- | **[dsh-soilwater-check](https://github.com/PerryLink/dsh-soilwater-check)** | |
351
- | **[dsh-sop-sync-check](https://github.com/PerryLink/dsh-sop-sync-check)** | |
352
- | **[dsh-spc-gbt-adapter](https://github.com/PerryLink/dsh-spc-gbt-adapter)** | |
353
- | **[dsh-talk](https://github.com/PerryLink/dsh-talk)** | |
354
- | **[dsh-tender-extract](https://github.com/PerryLink/dsh-tender-extract)** | |
355
- | **[dsh-tender-matrix](https://github.com/PerryLink/dsh-tender-matrix)** | |
356
- | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | |
357
- | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | |
358
- | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | |
359
- | **[dsh-warranty-calc](https://github.com/PerryLink/dsh-warranty-calc)** | |
360
- | **[dsh-budget](https://github.com/PerryLink/dsh-budget)** | 🧊 CONGELADO — ver el README del repositorio |
361
- | **[dsh-claude-move](https://github.com/PerryLink/dsh-claude-move)** | 🧊 CONGELADO — ver el README del repositorio |
362
- | **[dsh-defend](https://github.com/PerryLink/dsh-defend)** | 🧊 CONGELADO — ver el README del repositorio |
363
- | **[dsh-draw](https://github.com/PerryLink/dsh-draw)** | 🧊 CONGELADO — ver el README del repositorio |
364
- | **[dsh-reach](https://github.com/PerryLink/dsh-reach)** | 🧊 CONGELADO — ver el README del repositorio |
365
- | **[dsh-background-agents](https://github.com/PerryLink/dsh-background-agents)** | 🚫 RETIRADO — ver el README del repositorio |
366
- | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | 🚫 RETIRADO — ver el README del repositorio |
367
- | **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | 🚫 RETIRADO — ver el README del repositorio |
368
-
369
- </details>
370
-
371
- ## License
372
-
373
- [Apache License 2.0](LICENSE) © 2026 dsh-click contributors
374
-
375
- ### Instalar desde el mercado de DSH Desktop
376
-
377
- Todos los plugins de PerryLink pueden explorarse en el mercado integrado de DSH Desktop: **Market → Sources → add source → pegar** `https://perrylink-dsh-catalog.perrylink.workers.dev/catalog-source.json` **→ seleccionarlo**. La instalación sigue pasando por la verificación de identidad npm del mercado y tu confirmación.