dsh-patch-edit-plus 0.2.6 → 0.3.1

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,20 +1,16 @@
1
1
  # Changelog
2
2
 
3
3
 
4
- ## [0.2.6] — 2026-10-01
4
+ ## [0.3.1] — 2026-10-01
5
5
 
6
6
  ### Fixed
7
- - **A bare multi-file unified diff collapsed into one file section** (ported from the 0.1.7 line, 0.2.5): with no `diff --git` separators, the second file's `--- `/`+++ ` headers rewrote the previous section's paths and its hunks were matched against the wrong content, failing every section after the first with "the context does not match the file". `--- ` now opens a new section whenever the current one is already claimed; parser-level and end-to-end regression tests added.
8
- ## [0.2.2] — 2026-09-29
7
+ - **A bare multi-file unified diff collapsed into one file section** (same defect fixed on the 0.1.7 line in 0.2.5): with no `diff --git` separators, the second file's `--- `/`+++ ` headers rewrote the previous section's paths and its hunks were matched against the wrong content, failing every section after the first with `the context does not match the file`. `--- ` now opens a new section whenever the current one is already claimed; parser-level and end-to-end regression tests added.
8
+ ## [0.3.0] — 2026-09-29
9
9
 
10
10
  ### Changed
11
- - **DSH line split**: this release serves the `0.1.5-rc` segment only — `peerDependencies`/`engines.dsh` capped to `>=0.1.5-rc.1 <0.1.6-0` (both manifests), published under the `dsh-0.1.5` dist-tag. `0.1.2-rc.1` ~ `0.1.4` remain served by the published `0.1.2` (main); `0.1.7` by `dsh-0.1.7` (v0.2.1+); `0.2.0` by `dsh-0.2.0` (v0.3.0+).
12
- - devDependencies 4x `@deepseek-ai/dsh-*` `0.1.2-rc.1` → `0.1.5-rc.3`: the type baseline now matches the hosts this line serves (the stale `0.1.2` pin was the "fake green" pattern — a baseline older than the served line can mask real contract breaks).
13
- - Docs x4 (README/INSTALL): compatibility matrix re-based to the `0.1.5-rc` segment.
14
11
 
15
- ### Verified
16
- - No source changes required: `ShellExecutor.run(spec)` is intact across `0.1.5-rc.1`–`rc.3` (the `run` → `execute` rename lands in the 0.1.6→0.1.7 window), and the imperative settings fallback (`settings.register` / `installSection`) still exists on 0.1.5 hosts.
17
- - build / typecheck / test (94) / lint / smoke / `typecheck:0.1.5` (static proof against real `0.1.5-rc.2` peers) all green; lockfile regenerated against `0.1.5-rc.3`.
12
+ - **DSH 0.2.0 line support (`compat/0.2.0` branch).** Peer ranges and `engines.dsh` (both manifests) now declare `>=0.2.0-rc.1 <0.2.1-0`; version 0.3.0. devDependencies pin the real `0.2.0-rc.1` type baseline, and the cross-check script is upgraded to `npm run typecheck:0.2.0` (installs the real peer packages from the registry). 0.1.x hosts remain served by the `compat/0.1.7` branch / `dsh-0.1.7` dist-tag.
13
+ - **Delete/Move migrated to the current shell executor API.** `ShellExecutor.run(spec)` was renamed `execute(spec)` — returning a `ShellProcess` handle with a `result()` foreground projection — between the 0.1.2 and 0.1.7 host lines. The old devDependency pin (`0.1.2-rc.1`) masked this: the 0.1.7-line package (0.2.1) typechecked green against a stale baseline, and at runtime on real 0.1.7+ hosts its `run`-based duck-typing never matched, so Delete/Move degraded to the structured UNSUPPORTED error. This line calls `shell.execute(...)` and awaits `execution.result()`; the executor is detected via `execute`.
18
14
 
19
15
  ## [0.1.2] — 2026-09-19
20
16
 
package/CHANGELOG.zh.md CHANGED
@@ -1,20 +1,16 @@
1
1
  # 更新日志
2
2
 
3
3
 
4
- ## [0.2.6] — 2026-10-01
4
+ ## [0.3.1] — 2026-10-01
5
5
 
6
6
  ### 修复
7
- - **裸多文件 unified diff 被折叠进同一个文件 section**(自 0.1.7 线 0.2.5 移植):没有 `diff --git` 分隔时,第二个文件的 `--- `/`+++ ` 头改写前一个 section 的路径,其 hunk 被拿到错误内容上匹配,第一个文件之后的每个 section 都报 "the context does not match the file"。现在当前 section 已被认领时 `--- ` 即开新 section;新增解析层与端到端回归测试。
8
- ## [0.2.2] — 2026-09-29
7
+ - **裸多文件 unified diff 被折叠进同一个文件 section**(与 0.1.7 线 0.2.5 修复的同一缺陷):没有 `diff --git` 分隔时,第二个文件的 `--- `/`+++ ` 头改写前一个 section 的路径,其 hunk 被拿到错误内容上匹配,第一个文件之后的每个 section 都报 `the context does not match the file`。现在当前 section 已被认领时 `--- ` 即开新 section;新增解析层与端到端回归测试。
8
+ ## [0.3.0] — 2026-09-29
9
9
 
10
10
  ### 变更
11
- - **DSH 线拆分**:本版本只服务 `0.1.5-rc` 线段——`peerDependencies`/`engines.dsh` 封顶到 `>=0.1.5-rc.1 <0.1.6-0`(双清单),经 `dsh-0.1.5` dist-tag 发布。`0.1.2-rc.1` ~ `0.1.4` 仍由已发布的 `0.1.2`(main)服务;`0.1.7` 由 `dsh-0.1.7`(v0.2.1+)服务;`0.2.0` 由 `dsh-0.2.0`(v0.3.0+)服务。
12
- - devDependencies 4 项 `@deepseek-ai/dsh-*` `0.1.2-rc.1` → `0.1.5-rc.3`:类型基线与本线服务的宿主对齐(过期的 `0.1.2` 钉版正是「假绿」形态——基线早于服务线会掩盖真实契约断裂)。
13
- - 文档 ×4(README/INSTALL):兼容矩阵重基于 `0.1.5-rc` 线段。
14
11
 
15
- ### 验证
16
- - 无需源码改动:`ShellExecutor.run(spec)` 在 `0.1.5-rc.1`–`rc.3` 全程未变(`run` → `execute` 改名落在 0.1.6→0.1.7 区间),且 0.1.5 宿主仍有命令式设置回退(`settings.register` / `installSection`)。
17
- - build / typecheck / test(94)/ lint / smoke / `typecheck:0.1.5`(对真实 `0.1.5-rc.2` peer 静态核验)全绿;lockfile 按 `0.1.5-rc.3` 重新生成。
12
+ - **支持 DSH 0.2.0 线(`compat/0.2.0` 分支)。** peer 范围与两份清单的 `engines.dsh` 改为 `>=0.2.0-rc.1 <0.2.1-0`;版本 0.3.0。devDependencies 钉住真实的 `0.2.0-rc.1` 类型基线,交叉校验脚本升级为 `npm run typecheck:0.2.0`(从 registry 干净安装真实 peer 包做核验)。0.1.x 宿主继续由 `compat/0.1.7` 分支 / `dsh-0.1.7` dist-tag 服务。
13
+ - **Delete/Move 迁移到现行 shell 执行器 API。** 宿主在 0.1.2 → 0.1.7 线之间把 `ShellExecutor.run(spec)` 改名为 `execute(spec)`——返回 `ShellProcess` 句柄,前台结果经 `result()` 获取。旧的 devDependency 钉版(`0.1.2-rc.1`)掩盖了这一点:0.1.7 线的包(0.2.1)对过期基线假绿,且在真实 0.1.7+ 宿主上运行时基于 `run` 的鸭子探测永不命中,Delete/Move 实际降级为结构化 UNSUPPORTED 错误。本线改为调用 `shell.execute(...)` 并等待 `execution.result()`;执行器经 `execute` 做结构探测。
18
14
 
19
15
  ## [0.1.2] — 2026-09-19
20
16
 
package/README.de.md ADDED
@@ -0,0 +1,127 @@
1
+ # dsh-patch-edit-plus
2
+
3
+ Deutsch | [English](./README.md) | [简体中文](./README.zh.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [Français](./README.fr.md) | [Italiano](./README.it.md) | [Русский](./README.ru.md) | [Español](./README.es.md)
4
+
5
+ Patch-basierte Dateibearbeitung für [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness): ein einzelnes, dem Modell zugängliches `apply_patch`-Werkzeug, das **git/unified diff** (Standard) und die **Codex-`apply_patch`-Syntax** (Opt-in) akzeptiert, jede Änderung nach dem **Alles-oder-Nichts**-Prinzip anwendet und DSH dabei vollständig aus dem Weg geht.
6
+
7
+ ## DSH-Versionskompatibilität
8
+
9
+ | DSH-Version | Status | Hinweise |
10
+ |---|---|---|
11
+ | `0.2.0-rc.1+` | ✅ unterstützt (diese Linie, v0.3.0+) | Deklarative Einstellungen: `allowCodexPatch` ist mit `.volatile()` markiert — das Einstellungsformular wird automatisch gerendert, und `loader/volatile-update` registriert das Werkzeug ohne Remount neu. Kein Registrierungsaufruf. Delete/Move wurde auf die Foreground-API `ShellExecutor.execute()` + `result()` migriert. |
12
+ | `0.1.7-rc.1+` | ↗ Wartungslinie | Wird vom Zweig `compat/0.1.7` / dem Dist-Tag `dsh-0.1.7` bedient (dort v0.2.1). Der Shell-Executor von 0.2.0 benannte `run` → `execute` um (eingeführt zwischen 0.1.2 und 0.1.7), daher kann eine einzige Codebasis nicht typsicher beide Linien bedienen. |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ Wartungslinie | Wird vom Zweig vor 0.1.7 / dem Dist-Tag `dsh-0.1.5` bedient. 0.1.7 entfernte die imperativen Einstellungs-APIs, auf die der Dual-API-Fallback angewiesen war. |
14
+
15
+ Einstellungen sind auf dieser Linie deklarativ: In `Config` mit `.volatile()` markierte Felder werden zum Einstellungsformular; das Plugin abonniert `loader/volatile-update`, statt Registrierungs-Hooks zu empfangen.
16
+
17
+ ## Warum überhaupt Patches? (Tool-Routing-Leitfaden)
18
+
19
+ Die Werkzeugbeschreibung leitet das Modell ausdrücklich:
20
+
21
+ - **Einzelne kleine Änderung in einer bereits gelesenen Datei** → bevorzugen Sie das native `edit`-Werkzeug (ein Patch kostet mehr Tokens als eine wörtliche Bearbeitung).
22
+ - **Kleine Änderung in einer GROSSEN Datei** → `apply_patch` (die ganze Datei muss nicht zurückgeschickt werden).
23
+ - **Gebündelte Änderungen über VIELE Dateien** → `apply_patch` (ein Aufruf, atomar verifiziert).
24
+ - **Neue Datei mit substanziellem Inhalt / Löschen / Umbenennen** → `apply_patch`.
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ dsh plugin --profile web add <path-to-dsh-patch-edit-plus>
30
+ dsh web --dump-config # verify the plugin row appears
31
+ # restart DSH
32
+ ```
33
+
34
+ ## Verwendung
35
+
36
+ ### Unified Diff (Standard, aktiviert)
37
+
38
+ ```text
39
+ --- a/src/app.ts
40
+ +++ b/src/app.ts
41
+ @@ -10,4 +10,4 @@ export function main() {
42
+ init()
43
+ - start(oldPort)
44
+ + start(newPort)
45
+ await shutdown()
46
+ }
47
+ ```
48
+
49
+ ### Codex apply_patch-Syntax (Opt-in)
50
+
51
+ ```text
52
+ *** Begin Patch
53
+ *** Update File: src/app.ts
54
+ @@
55
+ init()
56
+ - start(oldPort)
57
+ + start(newPort)
58
+ *** Add File: docs/notes.md
59
+ +# Notes
60
+ *** Delete File: tmp/junk.txt
61
+ *** Move to: src/app.ts (via `*** Move to:` after *** Update File:)
62
+ *** End Patch
63
+ ```
64
+
65
+ Aktivieren mit `allowCodexPatch: true`. Trifft ein Codex-Patch ein, während die Option deaktiviert ist, liefert das Werkzeug einen **umsetzbaren Hinweis** (wie man sie aktiviert oder wie man im Unified-Diff-Format wiederholt) statt eines generischen Parse-Fehlers — die Codex-Syntax ist ein starker Prior für Modelle der GPT-Familie, und ein stilles Scheitern fängt sie in Wiederholungsschleifen.
66
+
67
+ ### Operationen
68
+
69
+ | Operation | Unified Diff | Codex | Ausführungspfad |
70
+ |---|---|---|---|
71
+ | Hinzufügen | `new file mode` + `/dev/null` | `*** Add File:` | `ctx.fs.writeText` (offizieller Intent-Ablauf) |
72
+ | Aktualisieren (multi-hunk) | `@@` hunks | `@@` hunks | `ctx.fs.writeText` |
73
+ | Löschen | `deleted file mode` + `/dev/null` | `*** Delete File:` | `ctx.shell` (sandbox-bewusst, Pfad per env übergeben) |
74
+ | Verschieben / Umbenennen | `rename from/to` | `*** Move to:` | `ctx.shell` |
75
+
76
+ ## Garantien
77
+
78
+ - **Alles-oder-Nichts**: Der gesamte Patch wird zuerst gegen den aktuellen Dateiinhalt verifiziert (Kontextlokalisierung, Workspace-Eingrenzung, Symlink-Richtlinie, doppelte Pfade); jeder Fehler bricht ab, ohne dass ein einziges Byte geschrieben wurde.
79
+ - **Einhaltung der Read-before-Write-Schranke**: Jeder Schreibvorgang reproduziert den Intent-Ablauf des offiziellen `write`-Werkzeugs — `fs/write-intent`-Wasserfall → geschütztes `writeText` → `fs/observed`-Emission. Ein nacktes `writeText` würde die Schranke still umgehen, da DSH-Provider `fs/*`-Ereignisse nie selbst dispatchen.
80
+ - **Präzise Fehlerdiagnostik**: Bei einer Hunk-Fehlanpassung trägt der Fehler Datei + Hunk-Index, Ursprungszeile der Suche, Vorschau der erwarteten Zeile (Whitespace sichtbar gemacht), den tatsächlichen Dateiauszug sowie einen gezielten Hinweis.
81
+ - **Zeilenende-Treue**: CRLF-Dateien werden als CRLF zurückgeschrieben; Enden ohne abschließenden Zeilenumbruch bleiben erhalten, sofern der Patch das Ende nicht ändert.
82
+ - **Reine Ergänzung**: Das Plugin registriert genau ein Werkzeug, ruft nie `tools.restrict()` auf, überschreibt nie ein natives Werkzeug, registriert keine globalen Dienste und entfernt beim Entladen alles. Namenskonflikte mit anderen `apply_patch`-Providern (`bainianlaoyao/dsh-codex-mode`, `shuind/dsh-codex-harness`, …) werden durch Umbenennungs-Vermeidung gelöst (`apply_patch_1`, `…_2`, …), sodass DSH beim Start nie scheitert.
83
+
84
+ ## Konfiguration
85
+
86
+ | Option | Standard | Beschreibung |
87
+ |---|---|---|
88
+ | `toolName` | `apply_patch` | Name des dem Modell zugänglichen Werkzeugs. |
89
+ | `conflictPolicy` | `rename` | `rename` / `skip` / `fail`, wenn der Werkzeugname bereits vergeben ist. |
90
+ | `renameSuffix` | `_1` | Suffix, das von der Umbenennungs-Vermeidung verwendet wird. |
91
+ | `allowUnifiedDiff` | `true` | Akzeptiert git/unified diffs. |
92
+ | `allowCodexPatch` | `false` | Akzeptiert die Codex-`apply_patch`-Syntax. Auch im DSH-Einstellungspanel änderbar; Änderungen wirken sofort, kein Neustart nötig. |
93
+ | `deleteBackend` | `shell` | `shell` oder `none` (Delete/Move liefern einen strukturierten Fehler). |
94
+ | `shellDialect` | `auto` | `auto` (pwsh unter win32) / `posix` / `pwsh`. |
95
+ | `deleteCommand` / `moveCommand` | built-in | Eigene Befehlsvorlagen. Pfade kommen weiterhin **ausschließlich per env** an (`DSH_PATCH_TARGET` / `DSH_PATCH_SOURCE`); interpolieren Sie sie nie in den Befehlsstring. |
96
+ | `dryRunByDefault` | `false` | Aufrufe als Probelauf (Dry Run) behandeln, außer bei `dryRun: false`. |
97
+ | `followSymlinks` | `false` | Erlauben, dass Patch-Pfade Symlinks folgen. |
98
+ | `maxFiles` | `50` | Maximale Anzahl Dateiabschnitte pro Patch. |
99
+ | `maxPatchBytes` | `524288` | Maximale Größe des Patch-Texts in Bytes. |
100
+ | `maxDiffBytes` | `16384` | Maximale Größe des je Datei in den Ergebnis-Metadaten behaltenen Diffs (größere Diffs werden geleert und mit `truncated` markiert). |
101
+
102
+ ## Einschränkungen (offengelegt)
103
+
104
+ - **Delete/Move laufen über `ctx.shell`.** Die Sandbox-Stärke ist genau die, die der geladene Shell-Executor durchsetzt (`bash-sandbox` grenzt ab; `bash-local` nicht) — dieselbe Risikoposition wie beim nativen bash-Werkzeug. Jede Anfrage trägt eine `sandboxPolicy` und berichtet Sandbox-Fakten, damit „Richtlinie verweigert“ von „Befehl fehlgeschlagen“ unterscheidbar ist.
105
+ - **Jeder Schreibvorgang und jeder Delete/Move trägt die Sitzungsbezogene Richtlinie.** `apply_patch` löst `ctx.sandboxPolicy.resolve({ session })` pro Aufruf auf — die Modus-Übersteuerung der Sitzung plus deren cwd als Workspace-Wurzel — genau wie die nativen `write`/`edit`-Werkzeuge, und löst die Planknotenpfade gegen dieselbe Wurzel auf. Ohne sie fällt das durchsetzende Dateisystem auf die Deployment-Wurzel zurück, wodurch Schreibvorgänge im Workspace als `workspace-write`-Verweigerungen fehlschlagen, selbst in einer `danger-full-access`-Sitzung. Eine `workspace-write`-Verweigerung tritt als `PatchError` auf, deren Nachricht den Backend-Text trägt (der strukturierte `[sandbox: …]`-Marker und die Same-Turn-Escalation-Felder sind nicht implementiert; benutzen Sie die nativen `write`/`edit`-Werkzeuge, wenn Sie eskalieren müssen).
106
+ - **Add erzeugt keine übergeordneten Verzeichnisse.** Das entspricht dem nativen `write`-Werkzeug (`ctx.fs` hat kein mkdir); der Fehler nennt das fehlende Verzeichnis.
107
+ - Kein unscharfes/Offset-basiertes Matching: Die Hunk-Lokalisierung ist exakt → `trimEnd` → `trim`, und das absichtlich (unscharfes Matching ist bei destruktiven Operationen unsicher; es steht auf der Roadmap).
108
+ - Binär-Patches werden mit einer klaren Fehlermeldung abgelehnt.
109
+
110
+ ## Entwicklung
111
+
112
+ ```bash
113
+ npm install
114
+ npm run typecheck # against 0.2.0-rc.1 peers (devDependencies)
115
+ npm run typecheck:0.2.0 # against real 0.2.0-rc.1 peer packages installed from the registry (dual-baseline proof)
116
+ npm test # vitest, 92 tests
117
+ npm run lint
118
+ npm run build # lib/
119
+ npm run verify:source # static safety assertions (intent dance, no node:fs, …)
120
+ npm run smoke # load-level smoke against a stub host
121
+ ```
122
+
123
+ Die manuelle Verifikation auf einem laufenden DSH (`dsh plugin --profile web add` → Neustart → Aufruf des Werkzeugs in einer Sitzung) ist bewusst dem Betreiber überlassen.
124
+
125
+ ## Lizenz
126
+
127
+ MIT
package/README.es.md ADDED
@@ -0,0 +1,127 @@
1
+ # dsh-patch-edit-plus
2
+
3
+ Español | [English](./README.md) | [简体中文](./README.zh.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [Français](./README.fr.md) | [Deutsch](./README.de.md) | [Italiano](./README.it.md) | [Русский](./README.ru.md)
4
+
5
+ Edición de archivos estilo parche para [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness): una única herramienta `apply_patch` expuesta al modelo, que acepta **diff git/unificado** (por defecto) y la **sintaxis `apply_patch` de Codex** (opcional), aplica cada cambio bajo el principio de **todo-o-nada** y no estorba en absoluto a DSH.
6
+
7
+ ## Compatibilidad de versiones de DSH
8
+
9
+ | Versión de DSH | Estado | Notas |
10
+ |---|---|---|
11
+ | `0.2.0-rc.1+` | ✅ compatible (esta línea, v0.3.0+) | Ajustes declarativos: `allowCodexPatch` está marcado con `.volatile()` — el formulario de ajustes se genera automáticamente y `loader/volatile-update` vuelve a registrar la herramienta sin remontaje. Sin llamada de registro. Delete/Move migrados a la API de primer plano `ShellExecutor.execute()` + `result()`. |
12
+ | `0.1.7-rc.1+` | ↗ línea de mantenimiento | Atendida por la rama `compat/0.1.7` / el dist-tag `dsh-0.1.7` (v0.2.1 allí). El ejecutor de shell de 0.2.0 renombró `run` → `execute` (cambio introducido entre 0.1.2 y 0.1.7), así que una sola base de código no puede atender ambas líneas de forma type-safe. |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ línea de mantenimiento | Atendida por la rama anterior a 0.1.7 / el dist-tag `dsh-0.1.5`. La 0.1.7 eliminó las API imperativas de ajustes de las que dependía el fallback de doble API. |
14
+
15
+ En esta línea los ajustes son declarativos: los campos marcados con `.volatile()` en `Config` se convierten en el formulario de ajustes; el plugin se suscribe a `loader/volatile-update` en lugar de recibir hooks de registro.
16
+
17
+ ## ¿Por qué usar parches? (guía de enrutamiento de herramientas)
18
+
19
+ La descripción de la herramienta dirige explícitamente al modelo:
20
+
21
+ - **Un único cambio pequeño en un archivo ya leído** → prefiere la herramienta nativa `edit` (un parche cuesta más tokens que una edición literal).
22
+ - **Cambio pequeño dentro de un archivo GRANDE** → `apply_patch` (no hace falta reenviar el archivo entero).
23
+ - **Cambios por lotes en MUCHOS archivos** → `apply_patch` (una sola llamada, verificada atómicamente).
24
+ - **Archivo nuevo con contenido sustancial / borrado / renombrado** → `apply_patch`.
25
+
26
+ ## Instalación
27
+
28
+ ```bash
29
+ dsh plugin --profile web add <path-to-dsh-patch-edit-plus>
30
+ dsh web --dump-config # verify the plugin row appears
31
+ # restart DSH
32
+ ```
33
+
34
+ ## Uso
35
+
36
+ ### Diff unificado (por defecto, activado)
37
+
38
+ ```text
39
+ --- a/src/app.ts
40
+ +++ b/src/app.ts
41
+ @@ -10,4 +10,4 @@ export function main() {
42
+ init()
43
+ - start(oldPort)
44
+ + start(newPort)
45
+ await shutdown()
46
+ }
47
+ ```
48
+
49
+ ### Sintaxis apply_patch de Codex (opcional)
50
+
51
+ ```text
52
+ *** Begin Patch
53
+ *** Update File: src/app.ts
54
+ @@
55
+ init()
56
+ - start(oldPort)
57
+ + start(newPort)
58
+ *** Add File: docs/notes.md
59
+ +# Notes
60
+ *** Delete File: tmp/junk.txt
61
+ *** Move to: src/app.ts (via `*** Move to:` after *** Update File:)
62
+ *** End Patch
63
+ ```
64
+
65
+ Se activa con `allowCodexPatch: true`. Cuando llega un parche de Codex con la opción desactivada, la herramienta devuelve una **pista accionable** (cómo activarla o cómo reintentar en diff unificado) en lugar de un error genérico de análisis — la sintaxis de Codex es un prior fuerte para los modelos de la familia GPT, y un fallo silencioso los atrapa en bucles de reintentos.
66
+
67
+ ### Operaciones
68
+
69
+ | Operación | Diff unificado | Codex | Ruta de ejecución |
70
+ |---|---|---|---|
71
+ | Añadir | `new file mode` + `/dev/null` | `*** Add File:` | `ctx.fs.writeText` (secuencia de intent oficial) |
72
+ | Actualizar (multi-hunk) | `@@` hunks | `@@` hunks | `ctx.fs.writeText` |
73
+ | Eliminar | `deleted file mode` + `/dev/null` | `*** Delete File:` | `ctx.shell` (consciente de la sandbox, ruta pasada por env) |
74
+ | Mover / renombrar | `rename from/to` | `*** Move to:` | `ctx.shell` |
75
+
76
+ ## Garantías
77
+
78
+ - **Todo-o-nada**: el parche completo se verifica primero contra el contenido actual de los archivos (localización del contexto, contención del workspace, política de symlinks, rutas duplicadas); cualquier fallo aborta sin escribir un solo byte.
79
+ - **Se respeta la barrera de leer-antes-de-escribir**: cada escritura replica la secuencia de intent de la herramienta oficial `write` — cascada `fs/write-intent` → `writeText` protegido → emisión `fs/observed`. Un `writeText` a secas sortearía silenciosamente la barrera, porque los providers de DSH nunca despachan ellos mismos los eventos `fs/*`.
80
+ - **Diagnóstico preciso de fallos**: ante un hunk que no coincide, el error incluye archivo + índice del hunk, línea de origen de la búsqueda, vista previa de la línea esperada (con los espacios hechos visibles), el extracto real del archivo y una pista concreta.
81
+ - **Fidelidad de los finales de línea**: los archivos CRLF se reescriben como CRLF; los finales sin salto de línea final se preservan, salvo que el parche cambie el final.
82
+ - **Adición pura**: el plugin registra exactamente una herramienta, nunca llama a `tools.restrict()`, nunca sobrescribe una herramienta nativa, no registra servicios globales y lo elimina todo al descargarse. Los conflictos de nombre con otros proveedores de `apply_patch` (`bainianlaoyao/dsh-codex-mode`, `shuind/dsh-codex-harness`, …) se resuelven evitando el renombrado (`apply_patch_1`, `…_2`, …), de modo que DSH nunca falle al arrancar.
83
+
84
+ ## Configuración
85
+
86
+ | Opción | Predeterminado | Descripción |
87
+ |---|---|---|
88
+ | `toolName` | `apply_patch` | Nombre de la herramienta expuesta al modelo. |
89
+ | `conflictPolicy` | `rename` | `rename` / `skip` / `fail` cuando el nombre de la herramienta ya está ocupado. |
90
+ | `renameSuffix` | `_1` | Sufijo usado por la evitación del renombrado. |
91
+ | `allowUnifiedDiff` | `true` | Aceptar diffs git/unificados. |
92
+ | `allowCodexPatch` | `false` | Aceptar la sintaxis `apply_patch` de Codex. También editable en el panel de ajustes de DSH; los cambios surten efecto de inmediato, sin reinicio. |
93
+ | `deleteBackend` | `shell` | `shell` o `none` (Delete/Move devuelven un error estructurado). |
94
+ | `shellDialect` | `auto` | `auto` (pwsh en win32) / `posix` / `pwsh`. |
95
+ | `deleteCommand` / `moveCommand` | built-in | Plantillas de comando personalizadas. Las rutas siguen llegando **solo por variables de entorno** (`DSH_PATCH_TARGET` / `DSH_PATCH_SOURCE`); nunca las interpole en la cadena de comando. |
96
+ | `dryRunByDefault` | `false` | Tratar las llamadas como ensayos en seco (dry run) salvo `dryRun: false`. |
97
+ | `followSymlinks` | `false` | Permitir que las rutas del parche atraviesen symlinks. |
98
+ | `maxFiles` | `50` | Número máximo de secciones de archivo por parche. |
99
+ | `maxPatchBytes` | `524288` | Tamaño máximo del texto del parche en bytes. |
100
+ | `maxDiffBytes` | `16384` | Tamaño máximo del diff por archivo conservado en los metadatos del resultado (los diffs mayores se vacían y se marcan como `truncated`). |
101
+
102
+ ## Limitaciones (declaradas)
103
+
104
+ - **Delete/Move se ejecutan a través de `ctx.shell`.** La fortaleza de la sandbox es la que haga cumplir el ejecutor de shell cargado (`bash-sandbox` aisla; `bash-local` no) — la misma postura de riesgo que la herramienta bash nativa. Cada petición lleva una `sandboxPolicy` e informa de los hechos de la sandbox, de modo que «política denegada» sea distinguible de «comando fallido».
105
+ - **Cada escritura y cada Delete/Move llevan la política con alcance de sesión.** `apply_patch` resuelve `ctx.sandboxPolicy.resolve({ session })` en cada llamada — la anulación de modo de la sesión más su cwd como raíz del workspace — exactamente igual que las herramientas nativas `write`/`edit`, y resuelve las rutas del plan contra esa misma raíz. Sin ello, el sistema de archivos que hace cumplir la política retrocede a la raíz de despliegue, lo que hace que las escrituras dentro del workspace fallen como denegaciones `workspace-write` incluso en una sesión `danger-full-access`. Una denegación `workspace-write` se manifiesta como una `PatchError` cuyo mensaje incluye el texto del backend (el marcador estructurado `[sandbox: …]` y los campos de escalada del mismo turno no están implementados; use las herramientas nativas `write`/`edit` si necesita escalar).
106
+ - **Add no crea los directorios padre.** Esto coincide con la herramienta nativa `write` (`ctx.fs` no tiene mkdir); el error nombra el directorio que falta.
107
+ - Sin coincidencia difusa/por desplazamiento: la localización de los hunks es exacta → `trimEnd` → `trim`, deliberadamente (la coincidencia difusa no es segura para operaciones destructivas; está en la hoja de ruta).
108
+ - Los parches binarios se rechazan con un error claro.
109
+
110
+ ## Desarrollo
111
+
112
+ ```bash
113
+ npm install
114
+ npm run typecheck # against 0.2.0-rc.1 peers (devDependencies)
115
+ npm run typecheck:0.2.0 # against real 0.2.0-rc.1 peer packages installed from the registry (dual-baseline proof)
116
+ npm test # vitest, 92 tests
117
+ npm run lint
118
+ npm run build # lib/
119
+ npm run verify:source # static safety assertions (intent dance, no node:fs, …)
120
+ npm run smoke # load-level smoke against a stub host
121
+ ```
122
+
123
+ La verificación manual sobre un DSH en vivo (`dsh plugin --profile web add` → reinicio → llamada a la herramienta en una sesión) se deja deliberadamente al operador.
124
+
125
+ ## Licencia
126
+
127
+ MIT
package/README.fr.md ADDED
@@ -0,0 +1,127 @@
1
+ # dsh-patch-edit-plus
2
+
3
+ Français | [English](./README.md) | [简体中文](./README.zh.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [Deutsch](./README.de.md) | [Italiano](./README.it.md) | [Русский](./README.ru.md) | [Español](./README.es.md)
4
+
5
+ Édition de fichiers en mode patch pour [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) : un outil unique `apply_patch` exposé au modèle, qui accepte les **diffs git/unifiés** (par défaut) et la **syntaxe `apply_patch` de Codex** (opt-in), applique chaque changement selon le principe du **tout-ou-rien** et reste totalement hors du chemin de DSH.
6
+
7
+ ## Compatibilité des versions de DSH
8
+
9
+ | Version de DSH | Statut | Notes |
10
+ |---|---|---|
11
+ | `0.2.0-rc.1+` | ✅ pris en charge (cette ligne, v0.3.0+) | Paramètres déclaratifs : `allowCodexPatch` est marqué `.volatile()` — le formulaire de paramètres est généré automatiquement et `loader/volatile-update` réenregistre l'outil sans remontage (remount). Aucun appel d'enregistrement. Delete/Move migrés vers l'API de premier plan `ShellExecutor.execute()` + `result()`. |
12
+ | `0.1.7-rc.1+` | ↗ ligne de maintenance | Assurée par la branche `compat/0.1.7` / le dist-tag `dsh-0.1.7` (v0.2.1 sur cette ligne). L'exécuteur shell de 0.2.0 a renommé `run` → `execute` (changement introduit entre 0.1.2 et 0.1.7) ; une seule base de code ne peut donc pas servir les deux lignes de manière type-safe. |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ ligne de maintenance | Assurée par la branche antérieure à 0.1.7 / le dist-tag `dsh-0.1.5`. La 0.1.7 a supprimé les API impératives de paramétrage dont dépendait le repli bi-API (dual-API fallback). |
14
+
15
+ Sur cette ligne, les paramètres sont déclaratifs : les champs marqués `.volatile()` dans `Config` constituent le formulaire de paramètres ; le plugin s'abonne à `loader/volatile-update` au lieu de recevoir des hooks d'enregistrement.
16
+
17
+ ## Pourquoi faire des patchs ? (guide de routage des outils)
18
+
19
+ La description de l'outil oriente explicitement le modèle :
20
+
21
+ - **Petite modification unique dans un fichier déjà lu** → privilégiez l'outil natif `edit` (un patch coûte plus de tokens qu'une édition littérale).
22
+ - **Petite modification au sein d'un fichier VOLUMINEUX** → `apply_patch` (inutile de renvoyer l'intégralité du fichier).
23
+ - **Modifications groupées sur DE NOMBREUX fichiers** → `apply_patch` (un seul appel, vérifié atomiquement).
24
+ - **Nouveau fichier au contenu substantiel / suppression / renommage** → `apply_patch`.
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ dsh plugin --profile web add <path-to-dsh-patch-edit-plus>
30
+ dsh web --dump-config # verify the plugin row appears
31
+ # restart DSH
32
+ ```
33
+
34
+ ## Utilisation
35
+
36
+ ### Diff unifié (par défaut, activé)
37
+
38
+ ```text
39
+ --- a/src/app.ts
40
+ +++ b/src/app.ts
41
+ @@ -10,4 +10,4 @@ export function main() {
42
+ init()
43
+ - start(oldPort)
44
+ + start(newPort)
45
+ await shutdown()
46
+ }
47
+ ```
48
+
49
+ ### Syntaxe apply_patch de Codex (opt-in)
50
+
51
+ ```text
52
+ *** Begin Patch
53
+ *** Update File: src/app.ts
54
+ @@
55
+ init()
56
+ - start(oldPort)
57
+ + start(newPort)
58
+ *** Add File: docs/notes.md
59
+ +# Notes
60
+ *** Delete File: tmp/junk.txt
61
+ *** Move to: src/app.ts (via `*** Move to:` after *** Update File:)
62
+ *** End Patch
63
+ ```
64
+
65
+ Activez avec `allowCodexPatch: true`. Quand un patch Codex arrive alors que l'option est désactivée, l'outil renvoie une **aide actionnable** (comment l'activer ou comment réessayer en diff unifié) au lieu d'une erreur d'analyse générique — la syntaxe Codex est un prior fort pour les modèles de la famille GPT, et un échec silencieux les enferme dans des boucles de réessai.
66
+
67
+ ### Opérations
68
+
69
+ | Opération | Diff unifié | Codex | Chemin d'exécution |
70
+ |---|---|---|---|
71
+ | Ajout | `new file mode` + `/dev/null` | `*** Add File:` | `ctx.fs.writeText` (séquence d'intent officielle) |
72
+ | Mise à jour (multi-hunks) | `@@` hunks | `@@` hunks | `ctx.fs.writeText` |
73
+ | Suppression | `deleted file mode` + `/dev/null` | `*** Delete File:` | `ctx.shell` (conscient de la sandbox, chemin passé par env) |
74
+ | Déplacement / renommage | `rename from/to` | `*** Move to:` | `ctx.shell` |
75
+
76
+ ## Garanties
77
+
78
+ - **Tout-ou-rien** : l'ensemble du patch est d'abord vérifié par rapport au contenu actuel des fichiers (localisation du contexte, confinement de l'espace de travail, politique des symlinks, chemins dupliqués) ; tout échec avorte sans écrire le moindre octet.
79
+ - **Respect du verrou lecture-avant-écriture** : chaque écriture reproduit la séquence d'intent de l'outil `write` officiel — cascade `fs/write-intent` → `writeText` gardé → émission `fs/observed`. Un `writeText` brut contournerait silencieusement ce verrou, car les providers DSH n'émettent jamais eux-mêmes les événements `fs/*`.
80
+ - **Diagnostics d'échec précis** : en cas de hunk non correspondant, l'erreur embarque fichier + index du hunk, ligne d'origine de la recherche, aperçu de la ligne attendue (espaces rendus visibles), extrait réel du fichier, ainsi qu'une indication ciblée.
81
+ - **Fidélité des fins de ligne** : les fichiers CRLF sont réécrits en CRLF ; les fins sans nouvelle ligne finale sont préservées, sauf si le patch modifie la fin.
82
+ - **Pure addition** : le plugin enregistre exactement un outil, n'appelle jamais `tools.restrict()`, ne surcharge jamais un outil natif, n'enregistre aucun service global et supprime tout au déchargement. Les conflits de noms avec d'autres fournisseurs d'`apply_patch` (`bainianlaoyao/dsh-codex-mode`, `shuind/dsh-codex-harness`, …) sont résolus par évitement de renommage (`apply_patch_1`, `…_2`, …), afin que DSH ne tombe jamais en échec au démarrage.
83
+
84
+ ## Configuration
85
+
86
+ | Option | Par défaut | Description |
87
+ |---|---|---|
88
+ | `toolName` | `apply_patch` | Nom de l'outil exposé au modèle. |
89
+ | `conflictPolicy` | `rename` | `rename` / `skip` / `fail` quand le nom de l'outil est déjà pris. |
90
+ | `renameSuffix` | `_1` | Suffixe utilisé par l'évitement de renommage. |
91
+ | `allowUnifiedDiff` | `true` | Accepte les diffs git/unifiés. |
92
+ | `allowCodexPatch` | `false` | Accepte la syntaxe `apply_patch` de Codex. Également modifiable dans le panneau de paramètres DSH ; les changements prennent effet immédiatement, sans redémarrage. |
93
+ | `deleteBackend` | `shell` | `shell` ou `none` (Delete/Move renvoient une erreur structurée). |
94
+ | `shellDialect` | `auto` | `auto` (pwsh sous win32) / `posix` / `pwsh`. |
95
+ | `deleteCommand` / `moveCommand` | built-in | Modèles de commandes personnalisés. Les chemins n'arrivent toujours **que via les variables d'environnement** (`DSH_PATCH_TARGET` / `DSH_PATCH_SOURCE`) ; ne les interpolez jamais dans la chaîne de commande. |
96
+ | `dryRunByDefault` | `false` | Traiter les appels comme des essais à vide (dry run) sauf si `dryRun: false`. |
97
+ | `followSymlinks` | `false` | Autoriser les chemins de patch à traverser les symlinks. |
98
+ | `maxFiles` | `50` | Nombre maximal de sections de fichiers par patch. |
99
+ | `maxPatchBytes` | `524288` | Taille maximale du texte de patch, en octets. |
100
+ | `maxDiffBytes` | `16384` | Taille maximale du diff par fichier conservé dans les métadonnées du résultat (les diffs plus grands sont vidés et marqués `truncated`). |
101
+
102
+ ## Limitations (divulguées)
103
+
104
+ - **Delete/Move passent par `ctx.shell`.** La force de la sandbox est celle que l'exécuteur shell chargé fait respecter (`bash-sandbox` cloisonne ; `bash-local` non) — la même posture de risque que l'outil bash natif. Chaque requête porte un `sandboxPolicy` et rapporte les faits relatifs à la sandbox, de sorte qu'un « refus de politique » soit distinguable d'un « échec de commande ».
105
+ - **Chaque écriture et chaque Delete/Move porte la politique à la portée de la session.** `apply_patch` résout `ctx.sandboxPolicy.resolve({ session })` à chaque appel — la surcharge de mode de la session plus son cwd comme racine de l'espace de travail — exactement comme les outils natifs `write`/`edit`, et résout les chemins du plan par rapport à cette même racine. Sans cela, le système de fichiers contraignant retombe sur la racine de déploiement, ce qui fait échouer les écritures intra-espace de travail comme refus `workspace-write`, même dans une session `danger-full-access`. Un refus `workspace-write` se manifeste par une `PatchError` dont le message contient le texte du backend (le marqueur structuré `[sandbox: …]` et les champs d'escalade du même tour ne sont pas implémentés ; utilisez les outils natifs `write`/`edit` si vous devez escalader).
106
+ - **Add ne crée pas les répertoires parents.** Cela correspond à l'outil natif `write` (`ctx.fs` n'a pas de mkdir) ; l'erreur nomme le répertoire manquant.
107
+ - Pas de correspondance floue/avec décalage : la localisation des hunks est exacte → `trimEnd` → `trim`, volontairement (la correspondance floue n'est pas sûre pour les opérations destructrices ; elle figure sur la feuille de route).
108
+ - Les patchs binaires sont rejetés avec une erreur claire.
109
+
110
+ ## Développement
111
+
112
+ ```bash
113
+ npm install
114
+ npm run typecheck # against 0.2.0-rc.1 peers (devDependencies)
115
+ npm run typecheck:0.2.0 # against real 0.2.0-rc.1 peer packages installed from the registry (dual-baseline proof)
116
+ npm test # vitest, 92 tests
117
+ npm run lint
118
+ npm run build # lib/
119
+ npm run verify:source # static safety assertions (intent dance, no node:fs, …)
120
+ npm run smoke # load-level smoke against a stub host
121
+ ```
122
+
123
+ La vérification manuelle sur un DSH en fonctionnement (`dsh plugin --profile web add` → redémarrage → appel de l'outil dans une session) est volontairement laissée à l'opérateur.
124
+
125
+ ## Licence
126
+
127
+ MIT
package/README.it.md ADDED
@@ -0,0 +1,127 @@
1
+ # dsh-patch-edit-plus
2
+
3
+ Italiano | [English](./README.md) | [简体中文](./README.zh.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [Français](./README.fr.md) | [Deutsch](./README.de.md) | [Русский](./README.ru.md) | [Español](./README.es.md)
4
+
5
+ Modifica di file in stile patch per [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness): un unico strumento `apply_patch` esposto al modello, che accetta i **diff git/unificati** (predefinito) e la **sintassi `apply_patch` di Codex** (opt-in), applica ogni modifica secondo il principio del **tutto-o-nulla** e resta completamente fuori dai piedi di DSH.
6
+
7
+ ## Compatibilità delle versioni DSH
8
+
9
+ | Versione DSH | Stato | Note |
10
+ |---|---|---|
11
+ | `0.2.0-rc.1+` | ✅ supportato (questa linea, v0.3.0+) | Impostazioni dichiarative: `allowCodexPatch` è contrassegnato con `.volatile()` — il modulo delle impostazioni viene generato automaticamente e `loader/volatile-update` registra nuovamente lo strumento senza remount. Nessuna chiamata di registrazione. Delete/Move sono migrati all'API in primo piano `ShellExecutor.execute()` + `result()`. |
12
+ | `0.1.7-rc.1+` | ↗ linea di manutenzione | Servita dal ramo `compat/0.1.7` / dal dist-tag `dsh-0.1.7` (v0.2.1 lì). L'esecutore shell di 0.2.0 ha rinominato `run` → `execute` (modifica introdotta tra 0.1.2 e 0.1.7), quindi una singola codebase non può servire entrambe le linee in modo type-safe. |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ linea di manutenzione | Servita dal ramo precedente a 0.1.7 / dal dist-tag `dsh-0.1.5`. La 0.1.7 ha rimosso le API imperative delle impostazioni da cui dipendeva il fallback dual-API. |
14
+
15
+ Su questa linea le impostazioni sono dichiarative: i campi contrassegnati con `.volatile()` in `Config` diventano il modulo delle impostazioni; il plugin si iscrive a `loader/volatile-update` invece di ricevere hook di registrazione.
16
+
17
+ ## Perché proprio le patch? (guida al routing degli strumenti)
18
+
19
+ La descrizione dello strumento indirizza esplicitamente il modello:
20
+
21
+ - **Singola piccola modifica in un file già letto** → preferisci lo strumento nativo `edit` (una patch costa più token di una modifica letterale).
22
+ - **Piccola modifica all'interno di un file GRANDE** → `apply_patch` (non serve rinviare l'intero file).
23
+ - **Modifiche raggruppate su MOLTI file** → `apply_patch` (una sola chiamata, verificata atomicamente).
24
+ - **Nuovo file con contenuto sostanzioso / cancellazione / rinomina** → `apply_patch`.
25
+
26
+ ## Installazione
27
+
28
+ ```bash
29
+ dsh plugin --profile web add <path-to-dsh-patch-edit-plus>
30
+ dsh web --dump-config # verify the plugin row appears
31
+ # restart DSH
32
+ ```
33
+
34
+ ## Utilizzo
35
+
36
+ ### Diff unificato (predefinito, attivo)
37
+
38
+ ```text
39
+ --- a/src/app.ts
40
+ +++ b/src/app.ts
41
+ @@ -10,4 +10,4 @@ export function main() {
42
+ init()
43
+ - start(oldPort)
44
+ + start(newPort)
45
+ await shutdown()
46
+ }
47
+ ```
48
+
49
+ ### Sintassi apply_patch di Codex (opt-in)
50
+
51
+ ```text
52
+ *** Begin Patch
53
+ *** Update File: src/app.ts
54
+ @@
55
+ init()
56
+ - start(oldPort)
57
+ + start(newPort)
58
+ *** Add File: docs/notes.md
59
+ +# Notes
60
+ *** Delete File: tmp/junk.txt
61
+ *** Move to: src/app.ts (via `*** Move to:` after *** Update File:)
62
+ *** End Patch
63
+ ```
64
+
65
+ Si abilita con `allowCodexPatch: true`. Quando arriva una patch Codex mentre l'opzione è disattivata, lo strumento restituisce un **suggerimento azionabile** (come abilitarla o come riprovare in diff unificato) invece di un generico errore di parsing — la sintassi Codex è un forte prior per i modelli della famiglia GPT, e un fallimento silenzioso li intrappola in cicli di tentativi.
66
+
67
+ ### Operazioni
68
+
69
+ | Operazione | Diff unificato | Codex | Percorso di esecuzione |
70
+ |---|---|---|---|
71
+ | Aggiunta | `new file mode` + `/dev/null` | `*** Add File:` | `ctx.fs.writeText` (sequenza di intent ufficiale) |
72
+ | Aggiornamento (multi-hunk) | `@@` hunks | `@@` hunks | `ctx.fs.writeText` |
73
+ | Cancellazione | `deleted file mode` + `/dev/null` | `*** Delete File:` | `ctx.shell` (consapevole della sandbox, percorso passato via env) |
74
+ | Spostamento / rinomina | `rename from/to` | `*** Move to:` | `ctx.shell` |
75
+
76
+ ## Garanzie
77
+
78
+ - **Tutto-o-nulla**: l'intera patch viene prima verificata rispetto al contenuto attuale dei file (localizzazione del contesto, contenimento del workspace, politica dei symlink, percorsi duplicati); qualsiasi fallimento interrompe l'operazione senza scrivere un solo byte.
79
+ - **Rispetto del cancello leggi-prima-di-scrivere**: ogni scrittura replica la sequenza di intent dello strumento `write` ufficiale — cascata `fs/write-intent` → `writeText` protetto → emissione `fs/observed`. Un `writeText` nudo bypasserebbe silenziosamente il cancello, perché i provider DSH non dispatchano mai da soli gli eventi `fs/*`.
80
+ - **Diagnostica dei guasti precisa**: in caso di hunk non corrispondente, l'errore riporta file + indice dell'hunk, riga di origine della ricerca, anteprima della riga attesa (con spazi resi visibili), l'estratto reale del file e un suggerimento mirato.
81
+ - **Fedeltà dei fine riga**: i file CRLF vengono riscritti come CRLF; le code senza newline finale sono preservate, a meno che la patch non modifichi la coda.
82
+ - **Pura aggiunta**: il plugin registra esattamente uno strumento, non chiama mai `tools.restrict()`, non sovrascrive mai uno strumento nativo, non registra servizi globali e rimuove tutto allo scaricamento. I conflitti di nome con altri provider di `apply_patch` (`bainianlaoyao/dsh-codex-mode`, `shuind/dsh-codex-harness`, …) sono risolti evitando la rinomina (`apply_patch_1`, `…_2`, …), così che DSH non fallisca mai l'avvio.
83
+
84
+ ## Configurazione
85
+
86
+ | Opzione | Predefinito | Descrizione |
87
+ |---|---|---|
88
+ | `toolName` | `apply_patch` | Nome dello strumento esposto al modello. |
89
+ | `conflictPolicy` | `rename` | `rename` / `skip` / `fail` quando il nome dello strumento è già occupato. |
90
+ | `renameSuffix` | `_1` | Suffisso usato dall'evitamento della rinomina. |
91
+ | `allowUnifiedDiff` | `true` | Accetta i diff git/unificati. |
92
+ | `allowCodexPatch` | `false` | Accetta la sintassi `apply_patch` di Codex. Modificabile anche nel pannello delle impostazioni DSH; le modifiche hanno effetto immediato, senza riavvio. |
93
+ | `deleteBackend` | `shell` | `shell` oppure `none` (Delete/Move restituiscono un errore strutturato). |
94
+ | `shellDialect` | `auto` | `auto` (pwsh su win32) / `posix` / `pwsh`. |
95
+ | `deleteCommand` / `moveCommand` | built-in | Modelli di comando personalizzati. I percorsi arrivano comunque **solo tramite le variabili d'ambiente** (`DSH_PATCH_TARGET` / `DSH_PATCH_SOURCE`); non interpolarli mai nella stringa di comando. |
96
+ | `dryRunByDefault` | `false` | Tratta le chiamate come prove a vuoto (dry run) salvo `dryRun: false`. |
97
+ | `followSymlinks` | `false` | Consente ai percorsi delle patch di attraversare i symlink. |
98
+ | `maxFiles` | `50` | Numero massimo di sezioni file per patch. |
99
+ | `maxPatchBytes` | `524288` | Dimensione massima del testo della patch in byte. |
100
+ | `maxDiffBytes` | `16384` | Dimensione massima del diff per file conservato nei metadati del risultato (i diff più grandi vengono svuotati e marcati `truncated`). |
101
+
102
+ ## Limitazioni (dichiarate)
103
+
104
+ - **Delete/Move passano attraverso `ctx.shell`.** La robustezza della sandbox è quella che l'esecutore shell caricato fa rispettare (`bash-sandbox` isola; `bash-local` no) — la stessa postura di rischio dello strumento bash nativo. Ogni richiesta porta una `sandboxPolicy` e riporta i fatti della sandbox, così che un «rifiuto della politica» sia distinguibile da un «fallimento del comando».
105
+ - **Ogni scrittura e ogni Delete/Move porta la politica nell'ambito della sessione.** `apply_patch` risolve `ctx.sandboxPolicy.resolve({ session })` a ogni chiamata — l'override di modalità della sessione più il suo cwd come radice del workspace — esattamente come gli strumenti nativi `write`/`edit`, e risolve i percorsi del piano rispetto alla stessa radice. Senza di essa, il filesystem di applicazione ricade sulla radice di deployment, il che fa fallire le scritture nel workspace come rifiuti `workspace-write`, persino in una sessione `danger-full-access`. Un rifiuto `workspace-write` emerge come `PatchError` il cui messaggio contiene il testo del backend (il marcatore strutturato `[sandbox: …]` e i campi di escalation nello stesso turno non sono implementati; usate gli strumenti nativi `write`/`edit` quando dovete escalare).
106
+ - **Add non crea le directory madri.** Questo rispecchia lo strumento nativo `write` (`ctx.fs` non ha mkdir); l'errore nomina la directory mancante.
107
+ - Nessuna corrispondenza fuzzy/per offset: la localizzazione degli hunk è esatta → `trimEnd` → `trim`, deliberatamente (il matching fuzzy non è sicuro per le operazioni distruttive; è nella roadmap).
108
+ - Le patch binarie vengono rifiutate con un errore chiaro.
109
+
110
+ ## Sviluppo
111
+
112
+ ```bash
113
+ npm install
114
+ npm run typecheck # against 0.2.0-rc.1 peers (devDependencies)
115
+ npm run typecheck:0.2.0 # against real 0.2.0-rc.1 peer packages installed from the registry (dual-baseline proof)
116
+ npm test # vitest, 92 tests
117
+ npm run lint
118
+ npm run build # lib/
119
+ npm run verify:source # static safety assertions (intent dance, no node:fs, …)
120
+ npm run smoke # load-level smoke against a stub host
121
+ ```
122
+
123
+ La verifica manuale su un DSH in esecuzione (`dsh plugin --profile web add` → riavvio → chiamata dello strumento in una sessione) è lasciata deliberatamente all'operatore.
124
+
125
+ ## Licenza
126
+
127
+ MIT
package/README.ja.md CHANGED
@@ -1,15 +1,18 @@
1
1
  # dsh-patch-edit-plus
2
2
 
3
+ [English](./README.md) | [简体中文](./README.zh.md) | 日本語 | [한국어](./README.ko.md) | [Français](./README.fr.md) | [Deutsch](./README.de.md) | [Italiano](./README.it.md) | [Русский](./README.ru.md) | [Español](./README.es.md)
4
+
3
5
  [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) 向けのパッチ形式ファイル編集。モデルに公開される単一の `apply_patch` ツールが **git/unified diff**(既定)と **Codex `apply_patch` 構文**(オプトイン)を受け付け、すべての変更を **オール・オア・ナッシング**で適用し、DSH の動作には一切干渉しません。
4
6
 
5
7
  ## DSH バージョン互換性
6
8
 
7
9
  | DSH バージョン | ステータス | 備考 |
8
10
  |---|---|---|
9
- | `0.1.5-rc.1+` | ✅ サポート対象(本ライン、v0.2.2+) | 型ベースラインを実在の `0.1.5-rc.3` ピアに固定し、`peerDependencies`/`engines.dsh` は `>=0.1.5-rc.1 <0.1.6-0` にキャップ。`dsh-0.1.5` dist-tag で公開。 |
10
- | `0.1.2-rc.1` ~ `0.1.4` | ↗ メンテナンスライン | 公開済みの `0.1.2`(main ブランチ)が担います。`0.1.6+` は別契約(shell の `run` → `execute`)であり、compat/0.1.7・compat/0.2.0 ラインが担います。 |
11
+ | `0.2.0-rc.1+` | ✅ サポート対象(本ライン、v0.3.0+) | 宣言的設定:`allowCodexPatch` は `.volatile()` 付きで、設定フォームは自動生成され、`loader/volatile-update` が再マウントなしでツールをその場で再登録します。登録呼び出しは不要。Delete/Move は `ShellExecutor.execute()` + `result()` フォアグラウンド API に移行済み。 |
12
+ | `0.1.7-rc.1+` | ↗ メンテナンスライン | `compat/0.1.7` ブランチ / `dsh-0.1.7` dist-tag が担当(同ラインの v0.2.1)。0.2.0 より前にシェル実行器の `run` が `execute` に改名されており(0.1.2 → 0.1.7 の間)、1 つのコードベースで両ラインを型安全に支えることはできません。 |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ メンテナンスライン | 0.1.7 以前のブランチ / `dsh-0.1.5` dist-tag が担当。0.1.7 はデュアル API フォールバックが依存する命令型登録 API を削除しました。 |
11
14
 
12
- 設定の登録はデュアル API フォールバック(0.1.2 以降では `settings.installSection`、旧ホストでは `settings.register`)を使用します。
15
+ 本ラインの設定は宣言的です:`Config` 内で `.volatile()` を付けたフィールドがそのまま設定フォームになり、プラグインは登録フックの代わりに `loader/volatile-update` を購読します。
13
16
 
14
17
  ## そもそもなぜパッチなのか?(ツールルーティングガイド)
15
18
 
@@ -108,9 +111,9 @@ dsh web --dump-config # verify the plugin row appears
108
111
 
109
112
  ```bash
110
113
  npm install
111
- npm run typecheck # against 0.1.5-rc.3 peers (devDependencies)
112
- npm run typecheck:0.1.5 # 実在の 0.1.5-rc.2 ピアに対する静的クロス検証
113
- npm test # vitest, 90 tests
114
+ npm run typecheck # against 0.2.0-rc.1 peers (devDependencies)
115
+ npm run typecheck:0.2.0 # against real 0.2.0-rc.1 peer packages installed from the registry (dual-baseline proof)
116
+ npm test # vitest, 92 tests
114
117
  npm run lint
115
118
  npm run build # lib/
116
119
  npm run verify:source # static safety assertions (intent dance, no node:fs, …)
package/README.ko.md CHANGED
@@ -1,15 +1,18 @@
1
1
  # dsh-patch-edit-plus
2
2
 
3
+ [English](./README.md) | [简体中文](./README.zh.md) | [日本語](./README.ja.md) | 한국어 | [Français](./README.fr.md) | [Deutsch](./README.de.md) | [Italiano](./README.it.md) | [Русский](./README.ru.md) | [Español](./README.es.md)
4
+
3
5
  [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness)를 위한 패치 스타일 파일 편집 도구입니다. 모델에 노출되는 단일 `apply_patch` 도구가 **git/unified diff**(기본)와 **Codex `apply_patch` 문법**(옵트인)을 받아들이고, 모든 변경을 **전부 아니면 전무(all-or-nothing)** 방식으로 적용하며, DSH의 동작에는 전혀 간섭하지 않습니다.
4
6
 
5
7
  ## DSH 버전 호환성
6
8
 
7
9
  | DSH 버전 | 상태 | 비고 |
8
10
  |---|---|---|
9
- | `0.1.5-rc.1+` | ✅ 지원됨(본 라인, v0.2.2+) | 타입 베이스라인을 실제 `0.1.5-rc.3` peer에 고정하고, `peerDependencies`/`engines.dsh`는 `>=0.1.5-rc.1 <0.1.6-0`으로 제한합니다. `dsh-0.1.5` dist-tag로 게시됩니다. |
10
- | `0.1.2-rc.1` ~ `0.1.4` | ↗ 유지보수 라인 | 게시된 `0.1.2`(main 브랜치)가 담당합니다. `0.1.6+`은 별도 계약(shell `run` → `execute`)이며 compat/0.1.7·compat/0.2.0 라인이 지원합니다. |
11
+ | `0.2.0-rc.1+` | ✅ 지원됨(본 라인, v0.3.0+) | 선언적 설정: `allowCodexPatch`에 `.volatile()`가 표시되어 설정 폼이 자동 생성되고, `loader/volatile-update`가 리마운트 없이 도구를 그 자리에서 재등록합니다. 등록 호출이 없습니다. Delete/Move는 `ShellExecutor.execute()` + `result()` 포그라운드 API로 이전되었습니다. |
12
+ | `0.1.7-rc.1+` | ↗ 유지보수 라인 | `compat/0.1.7` 브랜치 / `dsh-0.1.7` dist-tag가 담당(해당 라인의 v0.2.1). 0.2.0 이전에 셸 실행기의 `run`이 `execute`로 이름이 바뀌었고(0.1.2 → 0.1.7 사이), 하나의 코드베이스로 두 라인을 타입 안전하게 지원할 수 없습니다. |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ 유지보수 라인 | 0.1.7 이전 브랜치 / `dsh-0.1.5` dist-tag가 담당. 0.1.7은 이중 API 폴백이 의존하던 명령형 등록 API를 제거했습니다. |
11
14
 
12
- 설정 등록은 이중 API 폴백을 사용합니다(0.1.2+ 에서는 `settings.installSection`, 이전 호스트에서는 `settings.register`).
15
+ 본 라인의 설정은 선언적입니다: `Config`에서 `.volatile()`로 표시된 필드가 곧 설정 폼이며, 플러그인은 등록 훅 대신 `loader/volatile-update`를 구독합니다.
13
16
 
14
17
  ## 왜 굳이 패치인가? (도구 라우팅 가이드)
15
18
 
@@ -108,9 +111,9 @@ dsh web --dump-config # verify the plugin row appears
108
111
 
109
112
  ```bash
110
113
  npm install
111
- npm run typecheck # against 0.1.5-rc.3 peers (devDependencies)
112
- npm run typecheck:0.1.5 # 실제 0.1.5-rc.2 peer 대상 정적 교차 검증
113
- npm test # vitest, 90 tests
114
+ npm run typecheck # against 0.2.0-rc.1 peers (devDependencies)
115
+ npm run typecheck:0.2.0 # against real 0.2.0-rc.1 peer packages installed from the registry (dual-baseline proof)
116
+ npm test # vitest, 92 tests
114
117
  npm run lint
115
118
  npm run build # lib/
116
119
  npm run verify:source # static safety assertions (intent dance, no node:fs, …)
package/README.md CHANGED
@@ -1,15 +1,18 @@
1
1
  # dsh-patch-edit-plus
2
2
 
3
+ English | [简体中文](./README.zh.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [Français](./README.fr.md) | [Deutsch](./README.de.md) | [Italiano](./README.it.md) | [Русский](./README.ru.md) | [Español](./README.es.md)
4
+
3
5
  Patch-style file editing for [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness): one model-facing `apply_patch` tool that accepts **git/unified diff** (default) and **Codex `apply_patch` syntax** (opt-in), applies every change **all-or-nothing**, and stays completely out of DSH's way.
4
6
 
5
7
  ## DSH version compatibility
6
8
 
7
9
  | DSH version | Status | Notes |
8
10
  |---|---|---|
9
- | `0.1.5-rc.1+` | ✅ supported (this line, v0.2.2+) | Type baseline pinned to the real `0.1.5-rc.3` peers; `peerDependencies`/`engines.dsh` capped to `>=0.1.5-rc.1 <0.1.6-0`. Published under the `dsh-0.1.5` dist-tag. |
10
- | `0.1.2-rc.1` ~ `0.1.4` | ↗ maintenance line | Served by the published `0.1.2` (main branch). `0.1.6+` is a different contract (shell `run` → `execute`) and is served by the compat/0.1.7 and compat/0.2.0 lines. |
11
+ | `0.2.0-rc.1+` | ✅ supported (this line, v0.3.0+) | Declarative settings: `allowCodexPatch` is marked `.volatile()` — the settings form renders automatically and `loader/volatile-update` re-registers the tool without a remount. No registration call. Delete/Move migrated to the `ShellExecutor.execute()` + `result()` foreground API. |
12
+ | `0.1.7-rc.1+` | ↗ maintenance line | Served by the `compat/0.1.7` branch / `dsh-0.1.7` dist-tag (v0.2.1 there). 0.2.0's shell executor renamed `run` → `execute` (introduced between 0.1.2 and 0.1.7), so one codebase cannot serve both lines type-safely. |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ maintenance line | Served by the pre-0.1.7 branch / `dsh-0.1.5` dist-tag. 0.1.7 removed the imperative settings APIs the dual-API fallback relied on. |
11
14
 
12
- Settings registration uses the dual-API fallback (`settings.installSection` on 0.1.2+, `settings.register` on older hosts).
15
+ Settings are declarative on this line: fields marked `.volatile()` in `Config` become the settings form; the plugin subscribes to `loader/volatile-update` instead of receiving registration hooks.
13
16
 
14
17
  ## Why patch at all? (tool routing guide)
15
18
 
@@ -108,9 +111,9 @@ Enable with `allowCodexPatch: true`. When a Codex patch arrives while disabled,
108
111
 
109
112
  ```bash
110
113
  npm install
111
- npm run typecheck # against 0.1.5-rc.3 peers (devDependencies)
112
- npm run typecheck:0.1.5 # static cross-proof against real 0.1.5-rc.2 peers
113
- npm test # vitest, 90 tests
114
+ npm run typecheck # against 0.2.0-rc.1 peers (devDependencies)
115
+ npm run typecheck:0.2.0 # against real 0.2.0-rc.1 peer packages installed from the registry (dual-baseline proof)
116
+ npm test # vitest, 92 tests
114
117
  npm run lint
115
118
  npm run build # lib/
116
119
  npm run verify:source # static safety assertions (intent dance, no node:fs, …)
package/README.ru.md ADDED
@@ -0,0 +1,127 @@
1
+ # dsh-patch-edit-plus
2
+
3
+ Русский | [English](./README.md) | [简体中文](./README.zh.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [Français](./README.fr.md) | [Deutsch](./README.de.md) | [Italiano](./README.it.md) | [Español](./README.es.md)
4
+
5
+ Патчевое редактирование файлов для [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness): единственный доступный модели инструмент `apply_patch`, который принимает **git/unified diff** (по умолчанию) и **синтаксис `apply_patch` от Codex** (по явному включению), применяет каждое изменение по принципу **всё-или-ничего** и абсолютно не мешает работе DSH.
6
+
7
+ ## Совместимость с версиями DSH
8
+
9
+ | Версия DSH | Статус | Примечания |
10
+ |---|---|---|
11
+ | `0.2.0-rc.1+` | ✅ поддерживается (эта линия, v0.3.0+) | Декларативные настройки: `allowCodexPatch` помечен `.volatile()` — форма настроек формируется автоматически, а `loader/volatile-update` перерегистрирует инструмент без перемонтирования. Вызов регистрации не нужен. Delete/Move переведены на foreground-API `ShellExecutor.execute()` + `result()`. |
12
+ | `0.1.7-rc.1+` | ↗ линия сопровождения | Обслуживается веткой `compat/0.1.7` / dist-tag `dsh-0.1.7` (там v0.2.1). Shell-исполнитель 0.2.0 переименовал `run` → `execute` (изменение появилось между 0.1.2 и 0.1.7), поэтому одна кодовая база не может типобезопасно обслуживать обе линии. |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ линия сопровождения | Обслуживается веткой до 0.1.7 / dist-tag `dsh-0.1.5`. В 0.1.7 удалены императивные API настроек, на которых держался двух-API-фолбэк. |
14
+
15
+ На этой линии настройки декларативны: поля, помеченные `.volatile()` в `Config`, становятся формой настроек; плагин подписывается на `loader/volatile-update` вместо получения регистрационных хуков.
16
+
17
+ ## Зачем вообще патчи? (руководство по маршрутизации инструментов)
18
+
19
+ Описание инструмента явно направляет модель:
20
+
21
+ - **Одиночное небольшое изменение в уже прочитанном файле** → предпочитайте нативный инструмент `edit` (патч стоит больше токенов, чем буквальное редактирование).
22
+ - **Небольшое изменение внутри БОЛЬШОГО файла** → `apply_patch` (не нужно повторять весь файл).
23
+ - **Пакетные изменения во МНОГИХ файлах** → `apply_patch` (один вызов, атомарная проверка).
24
+ - **Новый файл с существенным содержимым / удаление / переименование** → `apply_patch`.
25
+
26
+ ## Установка
27
+
28
+ ```bash
29
+ dsh plugin --profile web add <path-to-dsh-patch-edit-plus>
30
+ dsh web --dump-config # verify the plugin row appears
31
+ # restart DSH
32
+ ```
33
+
34
+ ## Использование
35
+
36
+ ### Unified diff (по умолчанию, включён)
37
+
38
+ ```text
39
+ --- a/src/app.ts
40
+ +++ b/src/app.ts
41
+ @@ -10,4 +10,4 @@ export function main() {
42
+ init()
43
+ - start(oldPort)
44
+ + start(newPort)
45
+ await shutdown()
46
+ }
47
+ ```
48
+
49
+ ### Синтаксис apply_patch от Codex (по явному включению)
50
+
51
+ ```text
52
+ *** Begin Patch
53
+ *** Update File: src/app.ts
54
+ @@
55
+ init()
56
+ - start(oldPort)
57
+ + start(newPort)
58
+ *** Add File: docs/notes.md
59
+ +# Notes
60
+ *** Delete File: tmp/junk.txt
61
+ *** Move to: src/app.ts (via `*** Move to:` after *** Update File:)
62
+ *** End Patch
63
+ ```
64
+
65
+ Включается через `allowCodexPatch: true`. Если патч Codex приходит при выключенной опции, инструмент возвращает **действенную подсказку** (как её включить или как повторить попытку в unified diff) вместо общей ошибки разбора — синтаксис Codex является сильным априорным признаком для моделей семейства GPT, и молчаливый сбой затягивает их в циклы повторов.
66
+
67
+ ### Операции
68
+
69
+ | Операция | Unified diff | Codex | Путь выполнения |
70
+ |---|---|---|---|
71
+ | Добавление | `new file mode` + `/dev/null` | `*** Add File:` | `ctx.fs.writeText` (официальная intent-последовательность) |
72
+ | Обновление (multi-hunk) | `@@` hunks | `@@` hunks | `ctx.fs.writeText` |
73
+ | Удаление | `deleted file mode` + `/dev/null` | `*** Delete File:` | `ctx.shell` (с учётом sandbox, путь передаётся через env) |
74
+ | Перемещение / переименование | `rename from/to` | `*** Move to:` | `ctx.shell` |
75
+
76
+ ## Гарантии
77
+
78
+ - **Всё-или-ничего**: весь патч сначала проверяется на соответствие текущему содержимому файлов (локализация контекста, удержание в рабочей области, политика symlink, дубликаты путей); любой сбой прерывает операцию без записи хотя бы байта.
79
+ - **Соблюдение запрета на запись без чтения**: каждая запись воспроизводит intent-последовательность официального инструмента `write` — водопад `fs/write-intent` → защищённый `writeText` → эмиссия `fs/observed`. Голый `writeText` молча обходил бы этот барьер, поскольку провайдеры DSH никогда сами не диспетчеризуют события `fs/*`.
80
+ - **Точная диагностика сбоев**: при несовпадении хунка ошибка содержит файл + индекс хунка, исходную строку поиска, превью ожидаемой строки (с показанными пробелами), фактический фрагмент файла и адресную подсказку.
81
+ - **Точность переводов строк**: файлы CRLF записываются обратно как CRLF; окончания без завершающего перевода строки сохраняются, если только патч не меняет окончание.
82
+ - **Чистое дополнение**: плагин регистрирует ровно один инструмент, никогда не вызывает `tools.restrict()`, никогда не переопределяет нативный инструмент, не регистрирует глобальных служб и при выгрузке удаляет всё. Конфликты имён с другими провайдерами `apply_patch` (`bainianlaoyao/dsh-codex-mode`, `shuind/dsh-codex-harness`, …) разрешаются избеганием переименования (`apply_patch_1`, `…_2`, …), так что DSH никогда не падает при старте.
83
+
84
+ ## Конфигурация
85
+
86
+ | Опция | По умолчанию | Описание |
87
+ |---|---|---|
88
+ | `toolName` | `apply_patch` | Имя инструмента, доступного модели. |
89
+ | `conflictPolicy` | `rename` | `rename` / `skip` / `fail`, если имя инструмента уже занято. |
90
+ | `renameSuffix` | `_1` | Суффикс, используемый при избегании переименования. |
91
+ | `allowUnifiedDiff` | `true` | Принимать git/unified diff. |
92
+ | `allowCodexPatch` | `false` | Принимать синтаксис `apply_patch` от Codex. Также редактируется в панели настроек DSH; изменения вступают в силу немедленно, без перезапуска. |
93
+ | `deleteBackend` | `shell` | `shell` или `none` (Delete/Move возвращают структурированную ошибку). |
94
+ | `shellDialect` | `auto` | `auto` (pwsh на win32) / `posix` / `pwsh`. |
95
+ | `deleteCommand` / `moveCommand` | built-in | Пользовательские шаблоны команд. Пути по-прежнему передаются **только через переменные окружения** (`DSH_PATCH_TARGET` / `DSH_PATCH_SOURCE`); никогда не подставляйте их в строку команды интерполяцией. |
96
+ | `dryRunByDefault` | `false` | Считать вызовы пробными запусками (dry run), если не задано `dryRun: false`. |
97
+ | `followSymlinks` | `false` | Разрешить путям патча переходить по symlink. |
98
+ | `maxFiles` | `50` | Максимум файловых секций на один патч. |
99
+ | `maxPatchBytes` | `524288` | Максимальный размер текста патча в байтах. |
100
+ | `maxDiffBytes` | `16384` | Максимальный размер диффа на файл, сохраняемого в метаданных результата (большие диффы опустошаются и помечаются `truncated`). |
101
+
102
+ ## Ограничения (раскрытые)
103
+
104
+ - **Delete/Move выполняются через `ctx.shell`.** Сила sandbox такова, каков обеспечивающий её загруженный shell-исполнитель (`bash-sandbox` изолирует; `bash-local` — нет) — та же позиция риска, что и у нативного инструмента bash. Каждый запрос несёт `sandboxPolicy` и сообщает факты о sandbox, чтобы «отказ политики» можно было отличить от «сбоя команды».
105
+ - **Каждая запись и каждый Delete/Move несут политику в области действия сессии.** `apply_patch` разрешает `ctx.sandboxPolicy.resolve({ session })` при каждом вызове — переопределение режима сессии плюс её cwd как корень рабочей области — в точности как нативные инструменты `write`/`edit`, и разрешает пути плана относительно того же корня. Без этого файловая система принуждения откатывается к корню развёртывания, из-за чего записи внутри рабочей области завершаются отказами `workspace-write` даже в сессии `danger-full-access`. Отказ `workspace-write` проявляется как `PatchError`, сообщение которой несёт текст бэкенда (структурированный маркер `[sandbox: …]` и поля эскалации в том же ходе не реализованы; если нужна эскалация, пользуйтесь нативными `write`/`edit`).
106
+ - **Add не создаёт родительские каталоги.** Это соответствует нативному инструменту `write` (у `ctx.fs` нет mkdir); в ошибке называется недостающий каталог.
107
+ - Нет нечёткого/со смещением сопоставления: локализация хунка точная → `trimEnd` → `trim`, причём намеренно (нечёткое сопоставление небезопасно для разрушающих операций; оно есть в дорожной карте).
108
+ - Двоичные патчи отклоняются с понятной ошибкой.
109
+
110
+ ## Разработка
111
+
112
+ ```bash
113
+ npm install
114
+ npm run typecheck # against 0.2.0-rc.1 peers (devDependencies)
115
+ npm run typecheck:0.2.0 # against real 0.2.0-rc.1 peer packages installed from the registry (dual-baseline proof)
116
+ npm test # vitest, 92 tests
117
+ npm run lint
118
+ npm run build # lib/
119
+ npm run verify:source # static safety assertions (intent dance, no node:fs, …)
120
+ npm run smoke # load-level smoke against a stub host
121
+ ```
122
+
123
+ Ручная проверка на живом DSH (`dsh plugin --profile web add` → перезапуск → вызов инструмента в сессии) намеренно оставлена оператору.
124
+
125
+ ## Лицензия
126
+
127
+ MIT
package/README.zh.md CHANGED
@@ -1,15 +1,18 @@
1
1
  # dsh-patch-edit-plus
2
2
 
3
+ [English](./README.md) | 简体中文 | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [Français](./README.fr.md) | [Deutsch](./README.de.md) | [Italiano](./README.it.md) | [Русский](./README.ru.md) | [Español](./README.es.md)
4
+
3
5
  面向 [DeepSeek Harness(DSH)](https://github.com/deepseek-ai/deepseek-harness) 的补丁风格文件编辑插件:只提供 **1 个**模型可见工具 `apply_patch`,接受 **git/unified diff**(默认开启)与 **Codex `apply_patch` 语法**(可选开启),全量验证后**原子应用**,对 DSH 既有功能零负面影响。
4
6
 
5
7
  ## DSH 版本适配矩阵
6
8
 
7
9
  | DSH 版本 | 状态 | 说明 |
8
10
  |---|---|---|
9
- | `0.1.5-rc.1+` | ✅ 支持(本线,v0.2.2+) | 类型基线钉在真实 `0.1.5-rc.3` peer 包;`peerDependencies`/`engines.dsh` 封顶到 `>=0.1.5-rc.1 <0.1.6-0`。经 `dsh-0.1.5` dist-tag 发布。 |
10
- | `0.1.2-rc.1` ~ `0.1.4` | ↗ 维护线 | 由已发布的 `0.1.2`(main 分支)服务。`0.1.6+` 是另一套契约(shell `run` → `execute`),由 compat/0.1.7 与 compat/0.2.0 线服务。 |
11
+ | `0.2.0-rc.1+` | ✅ 支持(本线,v0.3.0+) | 声明式设置:`allowCodexPatch` 标记 `.volatile()`——设置表单自动生成,`loader/volatile-update` 驱动工具原位重注册(不 remount),无任何注册调用。Delete/Move 已迁移到 `ShellExecutor.execute()` + `result()` 前台 API。 |
12
+ | `0.1.7-rc.1+` | ↗ 维护线 | 由 `compat/0.1.7` 分支 / `dsh-0.1.7` dist-tag 服务(该线 v0.2.1)。0.2.0 之前 shell 执行器已把 `run` 改名为 `execute`(发生在 0.1.2 → 0.1.7 之间),一份代码无法对两条线同时类型安全。 |
13
+ | `0.1.2-rc.1` ~ `0.1.5-rc.2` | ↗ 维护线 | 由 0.1.7 前的分支 / `dsh-0.1.5` dist-tag 服务。0.1.7 删除了双 API 回退所依赖的命令式注册 API。 |
11
14
 
12
- settings 注册走双 API 回退:0.1.2+ 的 `settings.installSection` 优先,旧版回退 `settings.register`。
15
+ 本线的 settings 是声明式的:`Config` 中标记 `.volatile()` 的字段即设置表单;插件订阅 `loader/volatile-update`,不再接收注册 hooks。
13
16
 
14
17
  ## 工具路由指引(为什么该用谁)
15
18
 
@@ -107,9 +110,9 @@ dsh web --dump-config # 确认插件行出现
107
110
 
108
111
  ```bash
109
112
  npm install
110
- npm run typecheck # 针对 0.1.5-rc.3 peer 包(devDependencies)
111
- npm run typecheck:0.1.5 # 对真实 0.1.5-rc.2 peer 包做交叉静态核验
112
- npm test # vitest,90 个用例
113
+ npm run typecheck # 针对 0.2.0-rc.1 peer 包(devDependencies)
114
+ npm run typecheck:0.2.0 # 从 registry 干净安装真实 0.2.0-rc.1 peer 包做类型核验(双基线证明)
115
+ npm test # vitest,92 个用例
113
116
  npm run lint
114
117
  npm run build # lib/
115
118
  npm run verify:source # 静态安全断言(intent 舞蹈、无 node:fs 等)
package/dsh.plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "dsh-patch-edit-plus",
3
3
  "name": "dsh-patch-edit-plus",
4
- "version": "0.2.6",
4
+ "version": "0.3.1",
5
5
  "description": {
6
6
  "en": "Patch-style file editing: one apply_patch tool for git/unified diff (default) and Codex apply_patch syntax (opt-in), with all-or-nothing application and sandbox-aware delete/move.",
7
7
  "zh": "补丁风格文件编辑:单个 apply_patch 工具,接受 git/unified diff(默认)与 Codex apply_patch 语法(可选开启),全量验证后原子应用,删除/移动走沙箱感知 shell。"
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "license": "MIT",
15
15
  "engines": {
16
- "dsh": ">=0.1.5-rc.1 <0.1.6-0"
16
+ "dsh": ">=0.2.0-rc.1 <0.2.1-0"
17
17
  },
18
18
  "components": {
19
19
  "host": "lib/index.js"
package/lib/config.js CHANGED
@@ -12,7 +12,7 @@ export const Config = z.object({
12
12
  conflictPolicy: z.union(['rename', 'skip', 'fail']).default('rename'),
13
13
  renameSuffix: z.string().default('_1'),
14
14
  allowUnifiedDiff: z.boolean().default(true),
15
- allowCodexPatch: z.boolean().default(false),
15
+ allowCodexPatch: z.boolean().default(false).volatile(),
16
16
  deleteBackend: z.union(['shell', 'none']).default('shell'),
17
17
  shellDialect: z.union(['auto', 'posix', 'pwsh']).default('auto'),
18
18
  deleteCommand: z.string(),
@@ -23,6 +23,14 @@ export const Config = z.object({
23
23
  maxPatchBytes: z.number().step(1).min(1024).default(512 * 1024),
24
24
  maxDiffBytes: z.number().step(1).min(256).default(16 * 1024),
25
25
  });
26
+ /** Read a `.volatile()` field: a live ref on 0.1.7+, a plain boolean otherwise. */
27
+ export function readVolatileBoolean(value, fallback) {
28
+ if (typeof value === 'boolean')
29
+ return value;
30
+ if (value && typeof value.get === 'function')
31
+ return Boolean(value.get());
32
+ return fallback;
33
+ }
26
34
  /** Fill user config with defaults; `undefined`/null entries fall back too. */
27
35
  export function resolveConfig(config) {
28
36
  const c = config ?? {};
@@ -31,7 +39,7 @@ export function resolveConfig(config) {
31
39
  conflictPolicy: c.conflictPolicy ?? 'rename',
32
40
  renameSuffix: typeof c.renameSuffix === 'string' ? c.renameSuffix : '_1',
33
41
  allowUnifiedDiff: c.allowUnifiedDiff ?? true,
34
- allowCodexPatch: c.allowCodexPatch ?? false,
42
+ allowCodexPatch: readVolatileBoolean(c.allowCodexPatch, false),
35
43
  deleteBackend: c.deleteBackend ?? 'shell',
36
44
  shellDialect: c.shellDialect ?? 'auto',
37
45
  deleteCommand: typeof c.deleteCommand === 'string' && c.deleteCommand !== '' ? c.deleteCommand : undefined,
package/lib/index.js CHANGED
@@ -4,14 +4,15 @@
4
4
  * One `apply_patch` tool accepting git/unified diff (default) and Codex
5
5
  * `apply_patch` syntax (opt-in). All-or-nothing application through the
6
6
  * official fs write-intent dance; delete/move through the sandbox-aware
7
- * shell. Compatible with DSH 0.1.2-rc.1 through 0.1.5-rc.2: the tool
8
- * authoring contract is byte-identical across those versions, so a single
9
- * code path serves both; only settings registration needs the dual-API
10
- * fallback (`installSection` first, `register` second).
7
+ * shell. Targets DSH 0.1.7+: settings are declarative — the fields marked
8
+ * `.volatile()` in `Config` render the settings form automatically (no
9
+ * registration call), and `loader/volatile-update` drives re-registration
10
+ * without a plugin remount. This line drops the pre-0.1.7 hosts; the
11
+ * 0.1.2-rc.1 ~ 0.1.5-rc.2 line stays on its maintenance branch.
11
12
  *
12
13
  * @module dsh-patch-edit-plus
13
14
  */
14
- import { Config, resolveConfig } from './config.js';
15
+ import { resolveConfig } from './config.js';
15
16
  import { registerApplyPatchTool } from './register.js';
16
17
  /** Cordis plugin name used by Loader diagnostics. */
17
18
  export const name = 'dsh-patch-edit-plus';
@@ -31,26 +32,21 @@ export const name = 'dsh-patch-edit-plus';
31
32
  * in every profile that has no shell capability.
32
33
  */
33
34
  export const inject = ['tools', 'fs'];
35
+ export { Config } from './config.js';
34
36
  /**
35
- * Settings namespace. Must match dsh-settings `NAMESPACE_PATTERN`
36
- * (`/^[a-z][a-z0-9-]*$/`) on every target version: letters, digits and
37
- * hyphens only — an underscore made `register()` throw before anything
38
- * persisted, so no migration is needed.
37
+ * Register the tool from the current config snapshot.
38
+ *
39
+ * 登记级 key。工具「描述」把可用语法固化进去了(tool.ts 拼 `Accepts ${styles}`),
40
+ * 所以判定必须覆盖整份 resolved config,而不是只看 allowCodexPatch。
39
41
  */
40
- export const SETTINGS_NAMESPACE = 'patch-edit-plus';
41
- export { Config };
42
- /** Register the tool and the settings namespace. Every registration is scoped to this plugin. */
43
42
  export function apply(ctx, config) {
43
+ // 组合条目(0.1.7 起 volatile 字段在其中是 live 引用):rejudge 每次整体
44
+ // 重解析一次,一次调用内是同一份快照;跨调用的最新值由事件驱动重取。
44
45
  const compositionEntry = config ?? {};
45
- // 权威来源:设置层挂载时是解析后的 scope,否则是组合条目。
46
- // installSection 保证在每次匹配的 onChange 之前先调用 setSource(attach 与 detach 各一次)。
47
- let readSource = () => compositionEntry;
48
46
  let disposer = null;
49
- // 登记级 key。工具「描述」把可用语法固化进去了(tool.ts 拼 `Accepts ${styles}`),
50
- // 所以判定必须覆盖整份 resolved config,而不是只看 allowCodexPatch。
51
47
  let registeredKey = null;
52
48
  const rejudge = () => {
53
- const next = resolveConfig(readSource());
49
+ const next = resolveConfig(compositionEntry);
54
50
  const key = JSON.stringify(next);
55
51
  if (key === registeredKey)
56
52
  return;
@@ -66,23 +62,9 @@ export function apply(ctx, config) {
66
62
  registeredKey = null;
67
63
  };
68
64
  });
69
- ctx.inject(['settings'], (settingsCtx) => {
70
- const settings = settingsCtx.settings
71
- ?? settingsCtx;
72
- if (typeof settings?.installSection === 'function') {
73
- settings.installSection(ctx, SETTINGS_NAMESPACE, Config, compositionEntry, {
74
- setSource: (current) => { readSource = current; },
75
- onChange: () => { rejudge(); },
76
- });
77
- return;
78
- }
79
- if (typeof settings?.register === 'function') {
80
- const scope = settings.register(SETTINGS_NAMESPACE, Config, { base: compositionEntry });
81
- if (scope !== undefined) {
82
- readSource = () => scope.get();
83
- scope.watch(() => { rejudge(); });
84
- rejudge();
85
- }
86
- }
65
+ // 0.1.7+: 只有 volatile 字段变更才走这里(不 remount);普通字段变更会整体
66
+ // remount 插件,新一次 `apply` 自然读到全部新值。等值变更宿主不通知。
67
+ ctx.on('loader/volatile-update', () => {
68
+ rejudge();
87
69
  });
88
70
  }
package/lib/shellops.js CHANGED
@@ -36,7 +36,7 @@ export function moveTemplate(cfg) {
36
36
  export function resolveShell(ctx) {
37
37
  try {
38
38
  const shell = ctx.shell;
39
- return shell !== undefined && typeof shell.run === 'function' && typeof shell.resolve === 'function' ? shell : undefined;
39
+ return shell !== undefined && typeof shell.execute === 'function' && typeof shell.resolve === 'function' ? shell : undefined;
40
40
  }
41
41
  catch {
42
42
  return undefined;
@@ -87,7 +87,8 @@ function requireShell(ctx, cfg) {
87
87
  }
88
88
  async function runShell(shell, request) {
89
89
  try {
90
- return await shell.run(shell.resolve(request));
90
+ const execution = await shell.execute(shell.resolve(request));
91
+ return await execution.result();
91
92
  }
92
93
  catch (error) {
93
94
  const detail = error instanceof Error ? error.message : String(error);
@@ -6,6 +6,7 @@
6
6
  * @module dsh-patch-edit-plus/config
7
7
  */
8
8
  import z from '@deepseek-ai/schemastery';
9
+ import type { Volatile } from '@deepseek-ai/cosmokit';
9
10
  /** What to do when the configured tool name is already taken at registration. */
10
11
  export type ConflictPolicy = 'rename' | 'skip' | 'fail';
11
12
  /** Backend used for Delete/Move operations (`ctx.fs` has no delete/move). */
@@ -22,8 +23,10 @@ export interface Config {
22
23
  renameSuffix?: string;
23
24
  /** Accept git/unified diff patches. Defaults to true. */
24
25
  allowUnifiedDiff?: boolean;
25
- /** Accept Codex `apply_patch` syntax. Defaults to false. */
26
- allowCodexPatch?: boolean;
26
+ /** Accept Codex `apply_patch` syntax. Defaults to false.
27
+ * 0.1.7 `.volatile()`: the loader hands `apply` a live `Volatile` ref for this
28
+ * field — always read it through `readVolatileBoolean`, never cache the ref. */
29
+ allowCodexPatch?: boolean | Volatile<boolean>;
27
30
  /** Delete/Move backend. Defaults to `shell`. `none` rejects Delete/Move with a structured error. */
28
31
  deleteBackend?: DeleteBackend;
29
32
  /** Shell dialect for the constant delete/move templates. Defaults to `auto` (pwsh on win32). */
@@ -44,7 +47,37 @@ export interface Config {
44
47
  maxDiffBytes?: number;
45
48
  }
46
49
  /** Schemastery schema for Loader defaults and generated configuration docs. */
47
- export declare const Config: z<Config>;
50
+ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
51
+ toolName: z<string, string, "defined">;
52
+ conflictPolicy: z<"rename" | "skip" | "fail", "rename" | "skip" | "fail", "defined">;
53
+ renameSuffix: z<string, string, "defined">;
54
+ allowUnifiedDiff: z<boolean, boolean, "defined">;
55
+ allowCodexPatch: z<boolean, boolean, "volatile-defined">;
56
+ deleteBackend: z<"shell" | "none", "shell" | "none", "defined">;
57
+ shellDialect: z<"auto" | "posix" | "pwsh", "auto" | "posix" | "pwsh", "defined">;
58
+ deleteCommand: z<string, string, "plain">;
59
+ moveCommand: z<string, string, "plain">;
60
+ dryRunByDefault: z<boolean, boolean, "defined">;
61
+ followSymlinks: z<boolean, boolean, "defined">;
62
+ maxFiles: z<number, number, "defined">;
63
+ maxPatchBytes: z<number, number, "defined">;
64
+ maxDiffBytes: z<number, number, "defined">;
65
+ }>>, Schemastery.ObjectT<NoInfer<{
66
+ toolName: z<string, string, "defined">;
67
+ conflictPolicy: z<"rename" | "skip" | "fail", "rename" | "skip" | "fail", "defined">;
68
+ renameSuffix: z<string, string, "defined">;
69
+ allowUnifiedDiff: z<boolean, boolean, "defined">;
70
+ allowCodexPatch: z<boolean, boolean, "volatile-defined">;
71
+ deleteBackend: z<"shell" | "none", "shell" | "none", "defined">;
72
+ shellDialect: z<"auto" | "posix" | "pwsh", "auto" | "posix" | "pwsh", "defined">;
73
+ deleteCommand: z<string, string, "plain">;
74
+ moveCommand: z<string, string, "plain">;
75
+ dryRunByDefault: z<boolean, boolean, "defined">;
76
+ followSymlinks: z<boolean, boolean, "defined">;
77
+ maxFiles: z<number, number, "defined">;
78
+ maxPatchBytes: z<number, number, "defined">;
79
+ maxDiffBytes: z<number, number, "defined">;
80
+ }>>, "plain">;
48
81
  /** Fully-resolved configuration used by the tool body. */
49
82
  export interface ResolvedConfig {
50
83
  toolName: string;
@@ -62,5 +95,7 @@ export interface ResolvedConfig {
62
95
  maxPatchBytes: number;
63
96
  maxDiffBytes: number;
64
97
  }
98
+ /** Read a `.volatile()` field: a live ref on 0.1.7+, a plain boolean otherwise. */
99
+ export declare function readVolatileBoolean(value: boolean | Volatile<boolean> | undefined, fallback: boolean): boolean;
65
100
  /** Fill user config with defaults; `undefined`/null entries fall back too. */
66
101
  export declare function resolveConfig(config: Config | undefined): ResolvedConfig;
@@ -4,16 +4,21 @@
4
4
  * One `apply_patch` tool accepting git/unified diff (default) and Codex
5
5
  * `apply_patch` syntax (opt-in). All-or-nothing application through the
6
6
  * official fs write-intent dance; delete/move through the sandbox-aware
7
- * shell. Compatible with DSH 0.1.2-rc.1 through 0.1.5-rc.2: the tool
8
- * authoring contract is byte-identical across those versions, so a single
9
- * code path serves both; only settings registration needs the dual-API
10
- * fallback (`installSection` first, `register` second).
7
+ * shell. Targets DSH 0.1.7+: settings are declarative — the fields marked
8
+ * `.volatile()` in `Config` render the settings form automatically (no
9
+ * registration call), and `loader/volatile-update` drives re-registration
10
+ * without a plugin remount. This line drops the pre-0.1.7 hosts; the
11
+ * 0.1.2-rc.1 ~ 0.1.5-rc.2 line stays on its maintenance branch.
11
12
  *
12
13
  * @module dsh-patch-edit-plus
13
14
  */
14
15
  import type { Context } from '@deepseek-ai/cordis';
15
- import { Config } from './config.js';
16
16
  import type { Config as PluginConfig } from './config.js';
17
+ declare module '@deepseek-ai/cordis' {
18
+ interface Events {
19
+ 'loader/volatile-update': (paths: string[]) => void;
20
+ }
21
+ }
17
22
  /** Cordis plugin name used by Loader diagnostics. */
18
23
  export declare const name = "dsh-patch-edit-plus";
19
24
  /**
@@ -32,13 +37,11 @@ export declare const name = "dsh-patch-edit-plus";
32
37
  * in every profile that has no shell capability.
33
38
  */
34
39
  export declare const inject: string[];
40
+ export { Config } from './config.js';
35
41
  /**
36
- * Settings namespace. Must match dsh-settings `NAMESPACE_PATTERN`
37
- * (`/^[a-z][a-z0-9-]*$/`) on every target version: letters, digits and
38
- * hyphens only — an underscore made `register()` throw before anything
39
- * persisted, so no migration is needed.
42
+ * Register the tool from the current config snapshot.
43
+ *
44
+ * 登记级 key。工具「描述」把可用语法固化进去了(tool.ts 拼 `Accepts ${styles}`),
45
+ * 所以判定必须覆盖整份 resolved config,而不是只看 allowCodexPatch。
40
46
  */
41
- export declare const SETTINGS_NAMESPACE = "patch-edit-plus";
42
- export { Config };
43
- /** Register the tool and the settings namespace. Every registration is scoped to this plugin. */
44
47
  export declare function apply(ctx: Context, config?: PluginConfig): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-patch-edit-plus",
3
- "version": "0.2.6",
4
- "description": "Patch-style file editing for DeepSeek Harness: one apply_patch tool accepting git/unified diff (default) and Codex apply_patch syntax (opt-in), with all-or-nothing application, read-before-write intent dance, sandbox-aware delete/move, and 0.1.5-rc line compatibility (dsh-0.1.5 dist-tag).",
3
+ "version": "0.3.1",
4
+ "description": "Patch-style file editing for DeepSeek Harness: one apply_patch tool accepting git/unified diff (default) and Codex apply_patch syntax (opt-in), with all-or-nothing application, read-before-write intent dance, sandbox-aware delete/move, targeting the DSH 0.2.0 line (declarative volatile settings).",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -37,7 +37,7 @@
37
37
  "build": "tsc -p tsconfig.build.json",
38
38
  "prepublishOnly": "npm run build",
39
39
  "typecheck": "tsc -p tsconfig.json",
40
- "typecheck:0.1.5": "node scripts/typecheck-0.1.5.mjs",
40
+ "typecheck:0.2.0": "node scripts/typecheck-0.2.0.mjs",
41
41
  "lint": "eslint src tests scripts _smoke",
42
42
  "lint:fix": "eslint src tests scripts _smoke --fix",
43
43
  "test": "vitest run",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "engines": {
49
49
  "node": ">=20",
50
- "dsh": ">=0.1.5-rc.1 <0.1.6-0"
50
+ "dsh": ">=0.2.0-rc.1 <0.2.1-0"
51
51
  },
52
52
  "license": "MIT",
53
53
  "keywords": [
@@ -62,10 +62,10 @@
62
62
  ],
63
63
  "peerDependencies": {
64
64
  "@deepseek-ai/cordis": "^4.0.1",
65
- "@deepseek-ai/dsh-fs": ">=0.1.5-rc.1 <0.1.6-0",
66
- "@deepseek-ai/dsh-sandbox": ">=0.1.5-rc.1 <0.1.6-0",
67
- "@deepseek-ai/dsh-shell": ">=0.1.5-rc.1 <0.1.6-0",
68
- "@deepseek-ai/dsh-tools": ">=0.1.5-rc.1 <0.1.6-0"
65
+ "@deepseek-ai/dsh-fs": ">=0.2.0-rc.1 <0.2.1-0",
66
+ "@deepseek-ai/dsh-sandbox": ">=0.2.0-rc.1 <0.2.1-0",
67
+ "@deepseek-ai/dsh-shell": ">=0.2.0-rc.1 <0.2.1-0",
68
+ "@deepseek-ai/dsh-tools": ">=0.2.0-rc.1 <0.2.1-0"
69
69
  },
70
70
  "peerDependenciesMeta": {
71
71
  "@deepseek-ai/cordis": {
@@ -85,19 +85,23 @@
85
85
  }
86
86
  },
87
87
  "dependencies": {
88
- "@deepseek-ai/schemastery": "^3.18.2"
88
+ "@deepseek-ai/schemastery": "^3.18.4"
89
89
  },
90
90
  "devDependencies": {
91
91
  "@deepseek-ai/cordis": "^4.0.2",
92
- "@deepseek-ai/dsh-fs": "0.1.5-rc.3",
93
- "@deepseek-ai/dsh-sandbox": "0.1.5-rc.3",
94
- "@deepseek-ai/dsh-shell": "0.1.5-rc.3",
95
- "@deepseek-ai/dsh-tools": "0.1.5-rc.3",
92
+ "@deepseek-ai/dsh-fs": "0.2.0-rc.1",
93
+ "@deepseek-ai/dsh-sandbox": "0.2.0-rc.1",
94
+ "@deepseek-ai/dsh-shell": "0.2.0-rc.1",
95
+ "@deepseek-ai/dsh-tools": "0.2.0-rc.1",
96
96
  "@eslint/js": "^9.0.0",
97
97
  "@types/node": "^22.0.0",
98
98
  "eslint": "^9.0.0",
99
99
  "typescript": "^5.6.0",
100
100
  "typescript-eslint": "^8.0.0",
101
- "vitest": "^3.0.0"
101
+ "vitest": "^3.0.0",
102
+ "@deepseek-ai/schemastery": "^3.18.4"
103
+ },
104
+ "publishConfig": {
105
+ "tag": "dsh-0.2.0"
102
106
  }
103
107
  }