dsh-click 0.3.25 → 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,10 +1,18 @@
1
1
  # Changelog
2
2
 
3
- ## [0.3.25] - 2026-10-26
3
+ ## [0.3.27] - 2026-11-05
4
4
 
5
- ### Added
5
+ ### Changed
6
+
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`.
8
+
9
+ ### Fixed
6
10
 
7
- - **`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.
8
16
 
9
17
  ## [0.3.24] - 2026-10-19
10
18
 
package/README-es.md CHANGED
@@ -183,7 +183,7 @@ Todos los ajustes son campos `Config` de Schemastery (modificables desde cordis.
183
183
  | `maxHelperOutputBytes` | `25165824` | Límite de una respuesta del helper en bytes (1024..67108864) |
184
184
  | `maxScreenshotSide` | `2560` | Lado más largo de la captura en píxeles (320..7680); las mayores se reducen |
185
185
  | `staleCheckPixels` | `true` | Comparar un hash de píxeles fresco antes de cada acción y rechazar si cambió |
186
- | `staleCheckTree` | `strict` | Frescura del árbol de toda la ventana: `strict` rechaza cualquier nodo cambiado; `off` omite el hash del árbol (escape para relojes/cursores; identidad/edad/píxeles siguen aplicando) |
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
187
  | `maxObservationAgeMs` | `30000` | Antigüedad máxima en ms de una observación que una acción puede citar (1000..600000) |
188
188
  | `maxCachedObservations` | `8` | Límite LRU de observaciones en caché (1..64) |
189
189
  | `maxElements` | `500` | Límite de elementos de accesibilidad por `screen_read` (1..2000) |
package/README-hi.md CHANGED
@@ -183,7 +183,7 @@ Error: dsh-click backend unavailable on linux: Linux backend is reserved but not
183
183
  | `maxHelperOutputBytes` | `25165824` | एक हेल्पर प्रतिक्रिया की बाइट सीमा (1024..67108864) |
184
184
  | `maxScreenshotSide` | `2560` | कैप्चर की सबसे लंबी भुजा पिक्सेल में (320..7680); बड़ी कैप्चर छोटी की जाती हैं |
185
185
  | `staleCheckPixels` | `true` | हर क्रिया से पहले ताज़ा पिक्सेल हैश मिलाएँ और बदलाव पर अस्वीकार करें |
186
- | `staleCheckTree` | `strict` | पूरी विंडो के ट्री की ताज़गी: `strict` किसी भी बदले नोड पर अस्वीकार करता है; `off` ट्री हैश छोड़ता है (घड़ी/कर्सर के लिए एस्केप; पहचान/आयु/पिक्सेल जाँच लागू रहती हैं) |
186
+ | `staleCheckTree` | `target` | ट्री ताज़गी: `target` लक्ष्य तत्व जाँचता है (डिफ़ॉल्ट), `strict` किसी भी बदले नोड पर अस्वीकार, `off` ट्री हैश छोड़ता है |
187
187
  | `maxObservationAgeMs` | `30000` | किसी अवलोकन की अधिकतम आयु ms में जिसे कोई क्रिया उद्धृत कर सकती है (1000..600000) |
188
188
  | `maxCachedObservations` | `8` | कैश किए गए अवलोकनों की LRU सीमा (1..64) |
189
189
  | `maxElements` | `500` | प्रति `screen_read` एक्सेसिबिलिटी एलिमेंट की सीमा (1..2000) |
package/README-pt.md CHANGED
@@ -183,7 +183,7 @@ Todos os ajustes são campos `Config` do Schemastery (alteráveis pelo cordis.ym
183
183
  | `maxHelperOutputBytes` | `25165824` | Limite de uma resposta do helper em bytes (1024..67108864) |
184
184
  | `maxScreenshotSide` | `2560` | Maior lado da captura em pixels (320..7680); capturas maiores são reduzidas |
185
185
  | `staleCheckPixels` | `true` | Comparar um hash de pixels novo antes de cada ação e recusar se mudou |
186
- | `staleCheckTree` | `strict` | Frescor da árvore de toda a janela: `strict` recusa qualquer nó alterado; `off` ignora o hash da árvore (escape para relógios/cursores; identidade/idade/pixels continuam valendo) |
186
+ | `staleCheckTree` | `target` | Frescor da árvore: `target` verifica o elemento alvo (padrão), `strict` recusa qualquer nó alterado, `off` ignora o hash da árvore |
187
187
  | `maxObservationAgeMs` | `30000` | Idade máxima em ms de uma observação que uma ação pode citar (1000..600000) |
188
188
  | `maxCachedObservations` | `8` | Limite LRU de observações em cache (1..64) |
189
189
  | `maxElements` | `500` | Limite de elementos de acessibilidade por `screen_read` (1..2000) |
package/README-zh.md CHANGED
@@ -183,7 +183,7 @@ Error: dsh-click backend unavailable on linux: Linux backend is reserved but not
183
183
  | `maxHelperOutputBytes` | `25165824` | 单次 helper 响应的字节上限(1024..67108864) |
184
184
  | `maxScreenshotSide` | `2560` | 截图最长边像素(320..7680);超出即缩放 |
185
185
  | `staleCheckPixels` | `true` | 每次操作前对比新像素哈希,变化即拒绝 |
186
- | `staleCheckTree` | `strict` | 整窗控件树新鲜度:`strict` 任一节点变化即拒绝;`off` 跳过整树哈希(时钟/光标的逃生口;身份/年龄/像素检查仍生效) |
186
+ | `staleCheckTree` | `target` | 控件树新鲜度:`target` 校验目标元素(默认),`strict` 任一节点变化即拒绝,`off` 跳过整树哈希(身份/年龄/像素检查仍生效) |
187
187
  | `maxObservationAgeMs` | `30000` | 操作可引用观察的最大时限(毫秒,1000..600000) |
188
188
  | `maxCachedObservations` | `8` | 观察缓存 LRU 上限(1..64) |
189
189
  | `maxElements` | `500` | 每次 `screen_read` 的无障碍元素上限(1..2000) |
package/README.md CHANGED
@@ -183,7 +183,7 @@ All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id
183
183
  | `maxHelperOutputBytes` | `25165824` | Cap on one helper response in bytes (1024..67108864) |
184
184
  | `maxScreenshotSide` | `2560` | Longest screenshot side in pixels (320..7680); larger captures are downscaled |
185
185
  | `staleCheckPixels` | `true` | Compare a fresh pixel hash before every action and refuse on change |
186
- | `staleCheckTree` | `strict` | Whole-window tree freshness: `strict` refuses any changed node; `off` skips the tree hash (escape hatch for clocks/cursors; identity/age/pixel checks still apply) |
186
+ | `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) |
187
187
  | `maxObservationAgeMs` | `30000` | Maximum age in ms of an observation an action may cite (1000..600000) |
188
188
  | `maxCachedObservations` | `8` | LRU cap on cached observations (1..64) |
189
189
  | `maxElements` | `500` | Cap on accessibility elements per `screen_read` (1..2000) |
@@ -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/cordis.patch.yml CHANGED
@@ -37,7 +37,7 @@
37
37
  # 'strict' refuses any changed tree node; 'off' skips the whole-tree
38
38
  # hash for windows with a ticking clock/cursor (identity/age/pixel
39
39
  # checks still apply).
40
- staleCheckTree: strict
40
+ staleCheckTree: target
41
41
  # Maximum age in ms of an observation that an action may still base
42
42
  # on (1000..600000). Older observations are refused and must be
43
43
  # re-observed.
package/lib/index.js CHANGED
@@ -192,12 +192,21 @@ var ActionExecutor = class {
192
192
  * @param signal - cancellation.
193
193
  * @returns the cited record and the fresh snapshot.
194
194
  */
195
- async requireFreshWindow(observationId, windowId, signal) {
195
+ async requireFreshWindow(observationId, windowId, signal, targetRef) {
196
196
  const record = this.deps.observations.get(observationId);
197
197
  if (record === void 0) throw new DshClickError(`unknown observation "${observationId}" — run screen_read or screen_shot again and cite the returned observationId`, "UNKNOWN_OBSERVATION");
198
198
  if (record.windowId !== windowId) throw new DshClickError(`observation ${observationId} belongs to window ${record.windowId}, not ${windowId}`, "UNKNOWN_OBSERVATION");
199
- const fresh = await this.deps.backend.snapshot(windowId, signal);
200
- const verdict = this.deps.observations.verify(record, fresh);
199
+ let fresh = await this.deps.backend.snapshot(windowId, signal);
200
+ let targetElements;
201
+ if (targetRef !== void 0 && record.elementHashes !== void 0 && this.config.staleCheckTree === "target") {
202
+ const tree = await this.deps.backend.tree({ windowId }, this.config.maxElements, this.config.maxTreeDepth, false, signal);
203
+ fresh = tree.snapshot;
204
+ targetElements = tree.elements;
205
+ }
206
+ const verdict = this.deps.observations.verify(record, fresh, Date.now(), targetRef === void 0 ? void 0 : {
207
+ ref: targetRef,
208
+ elements: targetElements ?? []
209
+ });
201
210
  if (!verdict.ok) throw new DshClickError(`${verdict.detail} — run screen_read or screen_shot again before acting`, verdict.code);
202
211
  return {
203
212
  record,
@@ -253,12 +262,12 @@ var ActionExecutor = class {
253
262
  * @param run - the backend call (receives the resolved focus flag).
254
263
  * @returns the validated backend outcome.
255
264
  */
256
- async perform(toolName, exec, observationId, windowId, run) {
265
+ async perform(toolName, exec, observationId, windowId, run, targetRef) {
257
266
  let approved = "none";
258
267
  let observationIdAudited;
259
268
  let windowIdAudited;
260
269
  try {
261
- const { record } = await this.requireFreshWindow(observationId, windowId, exec.signal);
270
+ const { record } = await this.requireFreshWindow(observationId, windowId, exec.signal, targetRef);
262
271
  observationIdAudited = observationId;
263
272
  windowIdAudited = windowId;
264
273
  approved = await this.gate(exec, toolName, {
@@ -375,7 +384,11 @@ const Config = z.object({
375
384
  maxHelperOutputBytes: z.number().min(1024).max(MAX_HELPER_OUTPUT_BYTES).default(DEFAULT_MAX_HELPER_OUTPUT_BYTES),
376
385
  maxScreenshotSide: z.number().min(320).max(MAX_SCREENSHOT_SIDE).default(DEFAULT_MAX_SCREENSHOT_SIDE),
377
386
  staleCheckPixels: z.boolean().default(true),
378
- staleCheckTree: z.union(["strict", "off"]).default("strict"),
387
+ staleCheckTree: z.union([
388
+ "strict",
389
+ "target",
390
+ "off"
391
+ ]).default("target"),
379
392
  maxObservationAgeMs: z.number().min(MIN_OBSERVATION_AGE_MS).max(MAX_OBSERVATION_AGE_MS).default(DEFAULT_MAX_OBSERVATION_AGE_MS),
380
393
  maxCachedObservations: z.number().min(1).max(64).default(8),
381
394
  maxElements: z.number().min(1).max(MAX_ELEMENTS).default(500),
@@ -424,8 +437,8 @@ function resolveConfig(config) {
424
437
  if (!Number.isInteger(maxScreenshotSide) || maxScreenshotSide < 320 || maxScreenshotSide > 7680) invalid("maxScreenshotSide", `must be an integer between 320 and ${MAX_SCREENSHOT_SIDE}`);
425
438
  const staleCheckPixels = config?.staleCheckPixels ?? true;
426
439
  if (typeof staleCheckPixels !== "boolean") invalid("staleCheckPixels", "must be a boolean");
427
- const staleCheckTree = config?.staleCheckTree ?? "strict";
428
- if (staleCheckTree !== "strict" && staleCheckTree !== "off") invalid("staleCheckTree", "must be \"strict\" or \"off\"");
440
+ const staleCheckTree = config?.staleCheckTree ?? "target";
441
+ if (staleCheckTree !== "strict" && staleCheckTree !== "target" && staleCheckTree !== "off") invalid("staleCheckTree", "must be \"strict\", \"target\", or \"off\"");
429
442
  const maxObservationAgeMs = config?.maxObservationAgeMs ?? 3e4;
430
443
  if (!Number.isFinite(maxObservationAgeMs) || maxObservationAgeMs < 1e3 || maxObservationAgeMs > 6e5) invalid("maxObservationAgeMs", `must be a finite number between ${MIN_OBSERVATION_AGE_MS} and ${MAX_OBSERVATION_AGE_MS}`);
431
444
  const maxCachedObservations = config?.maxCachedObservations ?? 8;
@@ -498,6 +511,18 @@ function observationIdOf(snapshot) {
498
511
  ]);
499
512
  return createHash("sha256").update(material).digest("hex").slice(0, 32);
500
513
  }
514
+ /** Hash one captured element's identity-relevant fields. */
515
+ function elementHashOf(element) {
516
+ return createHash("sha256").update(JSON.stringify([
517
+ element.elementId,
518
+ element.controlType,
519
+ element.name,
520
+ element.automationId,
521
+ element.rect,
522
+ element.enabled,
523
+ element.patterns
524
+ ])).digest("hex");
525
+ }
501
526
  /** Bounded LRU cache of observations, plus the staleness verdict logic. */
502
527
  var ObservationStore = class {
503
528
  config;
@@ -512,7 +537,7 @@ var ObservationStore = class {
512
537
  * @param snapshot - the snapshot facts it came from.
513
538
  * @returns the stored record (id = hash of the state).
514
539
  */
515
- record(snapshot) {
540
+ record(snapshot, elements) {
516
541
  const record = {
517
542
  id: observationIdOf(snapshot),
518
543
  windowId: snapshot.windowId,
@@ -523,6 +548,7 @@ var ObservationStore = class {
523
548
  rect: { ...snapshot.rect },
524
549
  treeHash: snapshot.treeHash,
525
550
  shotHash: snapshot.shotHash,
551
+ ...elements === void 0 ? {} : { elementHashes: Object.fromEntries(elements.map((element) => [element.elementId, elementHashOf(element)])) },
526
552
  elementCount: snapshot.elementCount,
527
553
  observedAt: Date.now()
528
554
  };
@@ -556,7 +582,7 @@ var ObservationStore = class {
556
582
  * @param now - wall-clock now (injectable for tests).
557
583
  * @returns the verdict.
558
584
  */
559
- verify(record, fresh, now = Date.now()) {
585
+ verify(record, fresh, now = Date.now(), target) {
560
586
  if (now - record.observedAt > this.config.maxObservationAgeMs) return {
561
587
  ok: false,
562
588
  code: "EXPIRED",
@@ -567,12 +593,18 @@ var ObservationStore = class {
567
593
  code: "STALE_IDENTITY",
568
594
  detail: `window ${record.windowId} no longer matches observation ${record.id} (title/class/process or rect changed)`
569
595
  };
570
- if (this.config.staleCheckTree !== "off" && fresh.treeHash !== record.treeHash) return {
571
- ok: false,
572
- code: "STALE_TREE",
573
- detail: `the accessibility tree of window ${record.windowId} changed since observation ${record.id}`
574
- };
575
- if (this.config.staleCheckPixels && fresh.shotHash !== record.shotHash) return {
596
+ let scopedTargetUnchanged = false;
597
+ if (this.config.staleCheckTree !== "off" && fresh.treeHash !== record.treeHash) {
598
+ const expected = target === void 0 || record.elementHashes === void 0 ? void 0 : record.elementHashes[target.ref];
599
+ const current = target?.elements.find((element) => element.elementId === target.ref);
600
+ if (this.config.staleCheckTree === "target" && expected !== void 0 && current !== void 0 && elementHashOf(current) === expected) scopedTargetUnchanged = true;
601
+ else return {
602
+ ok: false,
603
+ code: "STALE_TREE",
604
+ detail: target === void 0 ? `the accessibility tree of window ${record.windowId} changed since observation ${record.id}` : `target element ${target.ref} changed or disappeared since observation ${record.id}`
605
+ };
606
+ }
607
+ if (!scopedTargetUnchanged && this.config.staleCheckPixels && fresh.shotHash !== record.shotHash) return {
576
608
  ok: false,
577
609
  code: "STALE_PIXELS",
578
610
  detail: `the pixels of window ${record.windowId} changed since observation ${record.id}`
@@ -591,7 +623,7 @@ var ObservationStore = class {
591
623
  * @module dsh-click/version
592
624
  */
593
625
  /** Plugin version advertised in the helper-protocol handshake. */
594
- const VERSION = "0.3.25";
626
+ const VERSION = "0.3.27";
595
627
  /** The helper protocol revision; bump only on incompatible wire changes. */
596
628
  const HELPER_PROTOCOL_VERSION = 1;
597
629
  //#endregion
@@ -1533,7 +1565,7 @@ function screenReadTool(services) {
1533
1565
  const parsed = args;
1534
1566
  const tree = await backend.tree(parsed.target ?? {}, config.maxElements, config.maxTreeDepth, parsed.includePixels ?? true, exec.signal);
1535
1567
  const sanitized = observedWindow(tree.snapshot, config.maxTextLength);
1536
- const record = observations.record(tree.snapshot);
1568
+ const record = observations.record(tree.snapshot, tree.elements);
1537
1569
  auditObservation(exec, {
1538
1570
  observationId: record.id,
1539
1571
  windowId: tree.snapshot.windowId,
@@ -1858,7 +1890,7 @@ function clickTool(services) {
1858
1890
  y: target.y
1859
1891
  },
1860
1892
  button: parsed.button ?? "left"
1861
- }, focusFallback, exec.signal));
1893
+ }, focusFallback, exec.signal), byElement ? target.elementId : void 0);
1862
1894
  return {
1863
1895
  ok: true,
1864
1896
  windowId: outcome.windowId,
@@ -1917,7 +1949,7 @@ function typeTool(services) {
1917
1949
  elementId: parsed.elementId,
1918
1950
  text: parsed.text,
1919
1951
  rollback: config.rollbackEnabled
1920
- }, focusFallback, exec.signal));
1952
+ }, focusFallback, exec.signal), parsed.elementId);
1921
1953
  return {
1922
1954
  ok: true,
1923
1955
  windowId: outcome.windowId,
@@ -1986,7 +2018,7 @@ function scrollTool(services) {
1986
2018
  ...parsed.elementId !== void 0 ? { elementId: parsed.elementId } : {},
1987
2019
  direction: parsed.direction,
1988
2020
  amount
1989
- }, focusFallback, exec.signal));
2021
+ }, focusFallback, exec.signal), parsed.elementId);
1990
2022
  return {
1991
2023
  ok: true,
1992
2024
  windowId: outcome.windowId,
@@ -80,7 +80,7 @@ export declare class ActionExecutor {
80
80
  * @param run - the backend call (receives the resolved focus flag).
81
81
  * @returns the validated backend outcome.
82
82
  */
83
- perform(toolName: string, exec: ToolRunContext, observationId: string, windowId: number, run: (focusFallback: boolean) => Promise<ActionOutcome>): Promise<ActionOutcome>;
83
+ perform(toolName: string, exec: ToolRunContext, observationId: string, windowId: number, run: (focusFallback: boolean) => Promise<ActionOutcome>, targetRef?: string): Promise<ActionOutcome>;
84
84
  /**
85
85
  * Gate and launch one application. No window observation exists yet, so the
86
86
  * gate runs against the requested name/path alone and the launch outcome's
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,gBAAgB,EAA0B,MAAM,cAAc,CAAA;AAEvE,OAAO,EAAiB,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAuB,MAAM,qBAAqB,CAAA;AAErI,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAA;AAS5D,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;IACrB,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,kCAAkC;IAClC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAA;CACxC;AAED,yEAAyE;AACzE,qBAAa,cAAc;IAIb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,+DAA+D;IAC/D,OAAO,CAAC,eAAe,CAAQ;IAC/B,2CAA2C;gBACd,IAAI,EAAE,kBAAkB;IAErD,4BAA4B;IAC5B,OAAO,KAAK,GAAG,GAEd;IAED,2BAA2B;IAC3B,OAAO,KAAK,MAAM,GAEjB;IAED,gFAAgF;IAChF,OAAO,CAAC,KAAK;IAkBb;;;;;;;;OAQG;YACW,kBAAkB;IAyBhC;;;;;;;;;;;OAWG;YACW,IAAI;IAuClB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAS9B;;;;;;;;;;OAUG;IACG,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,cAAc,EACpB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,OAAO,CAAC,aAAa,CAAC,GACtD,OAAO,CAAC,aAAa,CAAC;IAwCzB;;;;;;;;;OASG;IACG,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;CAoBlG"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EAAE,gBAAgB,EAA0B,MAAM,cAAc,CAAA;AAEvE,OAAO,EAAiB,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAuB,MAAM,qBAAqB,CAAA;AAErI,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAA;AAS5D,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;IACrB,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,kCAAkC;IAClC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAA;CACxC;AAED,yEAAyE;AACzE,qBAAa,cAAc;IAIb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,+DAA+D;IAC/D,OAAO,CAAC,eAAe,CAAQ;IAC/B,2CAA2C;gBACd,IAAI,EAAE,kBAAkB;IAErD,4BAA4B;IAC5B,OAAO,KAAK,GAAG,GAEd;IAED,2BAA2B;IAC3B,OAAO,KAAK,MAAM,GAEjB;IAED,gFAAgF;IAChF,OAAO,CAAC,KAAK;IAkBb;;;;;;;;OAQG;YACW,kBAAkB;IAiChC;;;;;;;;;;;OAWG;YACW,IAAI;IAuClB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAS9B;;;;;;;;;;OAUG;IACG,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,cAAc,EACpB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,OAAO,CAAC,aAAa,CAAC,EACvD,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC;IAwCzB;;;;;;;;;OASG;IACG,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;CAoBlG"}
@@ -86,13 +86,13 @@ export interface Config {
86
86
  /** Compare a fresh pixel hash before every action (default true; the stale-state boundary). */
87
87
  staleCheckPixels?: boolean;
88
88
  /**
89
- * Whole-window accessibility-tree staleness policy. `strict` refuses an action when any
90
- * node in the window changed; `off` skips the whole-tree hash while keeping identity,
91
- * observation-age, and (unless disabled) pixel checks. `off` is the escape hatch for
92
- * windows with a ticking clock/cursor; per-element scoped verification is the planned
93
- * default replacement.
89
+ * Accessibility-tree staleness policy. `strict` refuses an action when any node in the
90
+ * window changed; `target` (default) lets `click`/`type`/`scroll` proceed when the
91
+ * addressed element itself is unchanged, even if an unrelated clock/cursor moved the
92
+ * whole-tree hash; `off` skips the tree hash entirely. Identity, observation-age, and
93
+ * (unless disabled) pixel checks still apply.
94
94
  */
95
- staleCheckTree?: 'strict' | 'off';
95
+ staleCheckTree?: 'strict' | 'target' | 'off';
96
96
  /** Maximum age in ms of an observation that an action may still base on (default 30000). */
97
97
  maxObservationAgeMs?: number;
98
98
  /** Cap on cached observations (default 8). */
@@ -129,7 +129,7 @@ export interface ResolvedConfig {
129
129
  /** Whether the pixel-level stale check runs. */
130
130
  staleCheckPixels: boolean;
131
131
  /** Whole-window tree-staleness policy. */
132
- staleCheckTree: 'strict' | 'off';
132
+ staleCheckTree: 'strict' | 'target' | 'off';
133
133
  /** Maximum observation age in milliseconds. */
134
134
  maxObservationAgeMs: number;
135
135
  /** Cap on cached observations. */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@
8
8
  * @module dsh-click/observe
9
9
  */
10
10
  import type { ResolvedConfig } from './config.js';
11
- import type { Rect, WindowSnapshot } from './platform/types.js';
11
+ import type { ElementInfo, Rect, WindowSnapshot } from './platform/types.js';
12
12
  /** One cached observation, immutable after construction. */
13
13
  export interface ObservationRecord {
14
14
  /** Observation id (content hash). */
@@ -21,6 +21,8 @@ export interface ObservationRecord {
21
21
  rect: Rect;
22
22
  treeHash: string;
23
23
  shotHash: string;
24
+ /** Per-element hashes captured from a tree read (absent for screenshot-only observations). */
25
+ elementHashes?: Readonly<Record<string, string>>;
24
26
  elementCount: number;
25
27
  /** Wall-clock capture time in milliseconds. */
26
28
  observedAt: number;
@@ -40,6 +42,8 @@ export type FreshnessVerdict = {
40
42
  * @returns a hex observation id.
41
43
  */
42
44
  export declare function observationIdOf(snapshot: WindowSnapshot): string;
45
+ /** Hash one captured element's identity-relevant fields. */
46
+ export declare function elementHashOf(element: ElementInfo): string;
43
47
  /** Bounded LRU cache of observations, plus the staleness verdict logic. */
44
48
  export declare class ObservationStore {
45
49
  private readonly config;
@@ -52,7 +56,7 @@ export declare class ObservationStore {
52
56
  * @param snapshot - the snapshot facts it came from.
53
57
  * @returns the stored record (id = hash of the state).
54
58
  */
55
- record(snapshot: WindowSnapshot): ObservationRecord;
59
+ record(snapshot: WindowSnapshot, elements?: readonly ElementInfo[]): ObservationRecord;
56
60
  /**
57
61
  * Look one observation up by id.
58
62
  *
@@ -72,6 +76,9 @@ export declare class ObservationStore {
72
76
  * @param now - wall-clock now (injectable for tests).
73
77
  * @returns the verdict.
74
78
  */
75
- verify(record: ObservationRecord, fresh: WindowSnapshot, now?: number): FreshnessVerdict;
79
+ verify(record: ObservationRecord, fresh: WindowSnapshot, now?: number, target?: {
80
+ readonly ref: string;
81
+ readonly elements: readonly ElementInfo[];
82
+ }): FreshnessVerdict;
76
83
  }
77
84
  //# sourceMappingURL=observe.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/observe.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAE/D,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,qBAAqB,GAAG,SAAS,GAAG,gBAAgB,GAAG,YAAY,GAAG,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7H;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAYhE;AAED,2EAA2E;AAC3E,qBAAa,gBAAgB;IAIf,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAE/D,wEAAwE;gBAC3C,MAAM,EAAE,cAAc;IAEnD;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,iBAAiB;IAwBnD;;;;;OAKG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAI9C;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,GAAE,MAAmB,GAAG,gBAAgB;CAsCrG"}
1
+ {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/observe.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAE5E,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,8FAA8F;IAC9F,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAChD,YAAY,EAAE,MAAM,CAAA;IACpB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,qBAAqB,GAAG,SAAS,GAAG,gBAAgB,GAAG,YAAY,GAAG,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7H;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAYhE;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAU1D;AAED,2EAA2E;AAC3E,qBAAa,gBAAgB;IAIf,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAE/D,wEAAwE;gBAC3C,MAAM,EAAE,cAAc;IAEnD;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,SAAS,WAAW,EAAE,GAAG,iBAAiB;IA2BtF;;;;;OAKG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAI9C;;;;;;;;;;;OAWG;IACH,MAAM,CACJ,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,cAAc,EACrB,GAAG,GAAE,MAAmB,EACxB,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;KAAE,GAC3E,gBAAgB;CAoDpB"}
@@ -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.25";
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.25",
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.1",
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",