dsh-click 0.3.26 → 0.3.27

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 CHANGED
@@ -1,16 +1,18 @@
1
1
  # Changelog
2
2
 
3
- ## [0.3.26] - 2026-10-27
3
+ ## [0.3.27] - 2026-11-05
4
4
 
5
- ### Fixed
6
-
7
- - **Element-targeted actions now verify the target instead of the whole window (issue #29).** `screen_read` stores a per-element hash; `click`/`type`/`scroll` re-read the tree and allow the action when the addressed element is unchanged, even if an unrelated clock, cursor, spinner, or memory label moved the whole-tree hash. `staleCheckTree` gains `target` and becomes the default; `strict` preserves the old whole-window refusal, and `off` remains the explicit escape hatch. Screenshot-only observations and `key` fall back to the strict whole-tree check. Added unchanged-target and changed-target regression tests.
5
+ ### Changed
8
6
 
9
- ## [0.3.25] - 2026-10-26
7
+ - **Host 0.2.2 line support.** devDependencies move from `0.2.1-rc.2` to `0.2.2-rc.1`, `@deepseek-ai/cordis` to `^4.1.0`, the include/loader plugins to `^1.1.0`, and schemastery to `~3.19.0` so one copy resolves against `@deepseek-ai/dsh-llm` 0.2.2. Add `@deepseek-ai/dsh-tool-executor-native` and `@deepseek-ai/dsh-session-projection` (both 0.2.2-rc.1) plus `@deepseek-ai/dsh-package-manifest`, which dsh-llm 0.2.2 types import without declaring. `engines.dsh` appends `>=0.2.2-0 <0.3.0` (append-only) and `engines.node` becomes `^22.19.0 || >=24.9.0`.
10
8
 
11
- ### Added
9
+ ### Fixed
12
10
 
13
- - **`staleCheckTree: "strict" | "off"` (default `strict`) — an explicit escape hatch for windows with a ticking clock, cursor, spinner, or live memory label (issue #29).** `strict` preserves the existing whole-window tree-hash refusal; `off` skips only the tree hash, while identity, observation age, and (unless `staleCheckPixels: false`) pixel checks still apply. This makes dynamic windows operable today; per-element scoped verification remains the planned default replacement.
11
+ - **Batch tool dispatch in the suites and the Loader runner.** 0.2.2 replaced the single-call `tools.execute({ callId, name, arguments })` with `ToolBatchInput` → `ToolBatchResult`; every call site now builds a one-call batch (`calls: [{ type: 'tool-call', id, name, arguments: JSON.stringify(...) }]`) and projects `results[0].result`, so the assertions keep their flat result shape.
12
+ - **Raw execution is behind a pluggable executor.** The test harness mounts `@deepseek-ai/dsh-tool-executor-native` right after `ToolRuntime`, and the Loader composition profile carries its row; without them `ctx.tools.execute()` has no provider.
13
+ - **Loader failures surface again.** `cordis` 4.1.0 settles a failed row's error on that row's fiber instead of rejecting `loader.await()`, so `scripts/loader-runner.mjs` now awaits every row fiber after `loader.await()`; the invalid-config and default-export negations fail on the real reason instead of a downstream missing-tool symptom. The row-state scan remains as a fallback.
14
+ - **Approval service mounting in the harness.** `ApprovalService` 0.2.2 statically injects `sessionProjections`, so the harness constructs `SessionProjectionRegistry` on the root context before mounting it, and the `systemPrompt` stub gains `context` / `getContextOrder` because the service registers an approval-policy context section.
15
+ - **Invalid-config composition case timeout.** Its three sequential child boots now import the full 0.2.2 host graph and can exceed the 5 s vitest default on a drvfs/Windows mount; the case gets an explicit 30 s budget inside the runner's own 120 s spawn timeout.
14
16
 
15
17
  ## [0.3.24] - 2026-10-19
16
18
 
package/README.md CHANGED
@@ -275,10 +275,10 @@ This project is part of the DeepSeek Harness plugin family from [PerryLink](http
275
275
  | **[dsh-aqua-input-check](https://github.com/PerryLink/dsh-aqua-input-check)** | |
276
276
  | **[dsh-archive-check](https://github.com/PerryLink/dsh-archive-check)** | |
277
277
  | **[dsh-auto-review](https://github.com/PerryLink/dsh-auto-review)** | |
278
- | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | |
278
+ | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | 🧊 FROZEN — see the repo README |
279
279
  | **[dsh-bid-ca-precheck](https://github.com/PerryLink/dsh-bid-ca-precheck)** | |
280
280
  | **[dsh-bid-qual-check](https://github.com/PerryLink/dsh-bid-qual-check)** | |
281
- | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | |
281
+ | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | 🧊 FROZEN — see the repo README |
282
282
  | **[dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind)** | |
283
283
  | **[dsh-click](https://github.com/PerryLink/dsh-click)** | |
284
284
  | **[dsh-composer-history](https://github.com/PerryLink/dsh-composer-history)** | |
package/lib/index.js CHANGED
@@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url";
7
7
  import { defineTool } from "@deepseek-ai/dsh-tools";
8
8
  import { mkdtemp, rm, writeFile } from "node:fs/promises";
9
9
  import { tmpdir } from "node:os";
10
- // src/events.ts
10
+ //#region src/events.ts
11
11
  /** The observation audit event type. */
12
12
  const OBSERVED_EVENT = "dsh-click/observed";
13
13
  /** The action audit event type. */
@@ -36,7 +36,8 @@ function appendAuditEvent(session, type, data) {
36
36
  else session.append(type, data);
37
37
  return "appended";
38
38
  }
39
- // src/sanitize.ts
39
+ //#endregion
40
+ //#region src/sanitize.ts
40
41
  /**
41
42
  * Pure display/audit redaction for everything dsh-click shows to the model or
42
43
  * writes to a session log: window titles, executable paths, and free text that
@@ -103,7 +104,8 @@ function redactSensitive(text) {
103
104
  function sanitizeVisible(text, maxLength) {
104
105
  return sanitizeText(redactSensitive(text), maxLength);
105
106
  }
106
- // src/platform/types.ts
107
+ //#endregion
108
+ //#region src/platform/types.ts
107
109
  /** Error with a stable machine-routing code, model-readable message included. */
108
110
  var DshClickError = class extends Error {
109
111
  code;
@@ -144,7 +146,8 @@ function expectProcessFacts(value, op) {
144
146
  executablePath
145
147
  };
146
148
  }
147
- // src/actions.ts
149
+ //#endregion
150
+ //#region src/actions.ts
148
151
  /** Approval failure detail, model-readable. */
149
152
  const APPROVAL_DETAIL = {
150
153
  rejected: "rejected by the approval answerer",
@@ -340,7 +343,8 @@ var ActionExecutor = class {
340
343
  }
341
344
  }
342
345
  };
343
- // src/config.ts
346
+ //#endregion
347
+ //#region src/config.ts
344
348
  /**
345
349
  * Plugin configuration and its explicit resolve step. `resolveConfig` re-judges
346
350
  * every default and bound so programmatic construction that bypasses
@@ -477,7 +481,8 @@ function resolveConfig(config) {
477
481
  })
478
482
  });
479
483
  }
480
- // src/observe.ts
484
+ //#endregion
485
+ //#region src/observe.ts
481
486
  /**
482
487
  * Observation cache and the staleness boundary. Every observation stores the
483
488
  * window's identity facts plus content hashes; before any action the executor
@@ -607,7 +612,8 @@ var ObservationStore = class {
607
612
  return { ok: true };
608
613
  }
609
614
  };
610
- // src/version.ts
615
+ //#endregion
616
+ //#region src/version.ts
611
617
  /**
612
618
  * The plugin version, hardcoded on purpose: it rides the helper-process
613
619
  * protocol handshake, so it must track `package.json` or released helpers
@@ -617,10 +623,11 @@ var ObservationStore = class {
617
623
  * @module dsh-click/version
618
624
  */
619
625
  /** Plugin version advertised in the helper-protocol handshake. */
620
- const VERSION = "0.3.26";
626
+ const VERSION = "0.3.27";
621
627
  /** The helper protocol revision; bump only on incompatible wire changes. */
622
628
  const HELPER_PROTOCOL_VERSION = 1;
623
- // src/platform/runner.ts
629
+ //#endregion
630
+ //#region src/platform/runner.ts
624
631
  /**
625
632
  * The Windows backend: every operation spawns the native PowerShell helper
626
633
  * (`native/win32/dsh-click-helper.ps1`) through the harness's `ctx.subprocess`
@@ -904,7 +911,8 @@ var HelperBackend = class {
904
911
  };
905
912
  }
906
913
  };
907
- // src/platform/selection.ts
914
+ //#endregion
915
+ //#region src/platform/selection.ts
908
916
  /** A backend that cannot act: every operation fails closed with the given reason. */
909
917
  var UnavailableBackend = class {
910
918
  platform;
@@ -975,7 +983,8 @@ function createBackend(ctx, config) {
975
983
  }
976
984
  return new UnavailableBackend(process.platform, RESERVED_BACKENDS[process.platform] ?? "unsupported platform");
977
985
  }
978
- // src/vision.ts
986
+ //#endregion
987
+ //#region src/vision.ts
979
988
  /**
980
989
  * Resolve whether the calling agent's current model declares image input.
981
990
  *
@@ -997,7 +1006,8 @@ async function sessionAcceptsImages(agent, ctx, signal) {
997
1006
  return false;
998
1007
  }
999
1008
  }
1000
- // src/vision/ocr.ts
1009
+ //#endregion
1010
+ //#region src/vision/ocr.ts
1001
1011
  /**
1002
1012
  * Optical character recognition seam for windows without a UIA tree. OCR is
1003
1013
  * optional and probed at mount: the `tesseract` provider is used only when the
@@ -1142,7 +1152,8 @@ async function probeTesseract(subprocess, command, language) {
1142
1152
  return new UnavailableOcrProvider("tesseract", `tesseract (${command}) is not installed`);
1143
1153
  }
1144
1154
  }
1145
- // src/vision/grounding.ts
1155
+ //#endregion
1156
+ //#region src/vision/grounding.ts
1146
1157
  /**
1147
1158
  * Visual grounding seam: turning a screenshot plus a natural-language prompt
1148
1159
  * into labeled bounding boxes. Kept as an independent provider so a vision
@@ -1170,7 +1181,8 @@ var UnavailableGroundingProvider = class {
1170
1181
  return Promise.reject(new DshClickError(`visual grounding unavailable: ${this.reason}`, "GROUNDING_UNAVAILABLE"));
1171
1182
  }
1172
1183
  };
1173
- // src/vision/index.ts
1184
+ //#endregion
1185
+ //#region src/vision/index.ts
1174
1186
  /**
1175
1187
  * Map one screenshot box (possibly downscaled by `maxScreenshotSide`) to its
1176
1188
  * screen-space box, centering on the window's screen rect origin.
@@ -1197,7 +1209,8 @@ function centerOf(box) {
1197
1209
  y: Math.round(box.y + box.height / 2)
1198
1210
  };
1199
1211
  }
1200
- // src/tools.ts
1212
+ //#endregion
1213
+ //#region src/tools.ts
1201
1214
  /** Sanitize one snapshot into the model-visible window value. */
1202
1215
  function observedWindow(snapshot, maxTextLength) {
1203
1216
  return {
@@ -2233,7 +2246,8 @@ function allTools(services) {
2233
2246
  appLaunchTool(services)
2234
2247
  ];
2235
2248
  }
2236
- // src/index.ts
2249
+ //#endregion
2250
+ //#region src/index.ts
2237
2251
  const name = "dsh-click";
2238
2252
  /** Hard services: the tool registry every contribution lands in, plus the subprocess runtime the Windows helper spawns through. */
2239
2253
  const inject = ["tools", "subprocess"];
@@ -2268,4 +2282,5 @@ async function apply(ctx, config) {
2268
2282
  };
2269
2283
  for (const tool of allTools(services)) ctx.effect(() => ctx.tools.register(tool), `dsh-click: ${tool.name} tool`);
2270
2284
  }
2285
+ //#endregion
2271
2286
  export { ACTION_EVENT, ActionExecutor, Config, DshClickError, HELPER_PROTOCOL_VERSION, HelperBackend, OBSERVED_EVENT, ObservationStore, TesseractOcrProvider, UnavailableBackend, UnavailableGroundingProvider, UnavailableOcrProvider, VERSION, allTools, apply, centerOf, createBackend, inject, name, observationIdOf, parseTesseractTsv, probeTesseract, redactSensitive, resolveConfig, sanitizePath, sanitizeText, sanitizeVisible, screenBoxFor, tesseractArgv };
@@ -7,7 +7,7 @@
7
7
  * @module dsh-click/version
8
8
  */
9
9
  /** Plugin version advertised in the helper-protocol handshake. */
10
- export declare const VERSION = "0.3.26";
10
+ export declare const VERSION = "0.3.27";
11
11
  /** The helper protocol revision; bump only on incompatible wire changes. */
12
12
  export declare const HELPER_PROTOCOL_VERSION = 1;
13
13
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-click",
3
- "version": "0.3.26",
3
+ "version": "0.3.27",
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",