dsh-patch-edit-plus 0.3.1 → 0.4.0

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,6 +1,19 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [0.4.0] — 2026-10-09
5
+
6
+ ### Added
7
+
8
+ - **Single release across all host lines.** One version (0.4.0) serves every DSH host from `0.1.0-rc.8` to `0.2.0-rc.2` — all 15 rc releases plus desktop; the peer ranges enumerate all 15 rcs and `engines.dsh` declares `>=0.1.0-rc.8`. The retired compat branches (`compat/0.1.2`, `compat/0.1.5`, `compat/0.1.7`) and the `main` split-line scheme are gone; after publishing, the npm dist-tags `latest`, `dsh-0.2.0`, `dsh-0.1.7`, `dsh-0.1.5` and `dsh-0.1.2` all converge on 0.4.0.
9
+ - **Three settings generations in one codebase**: declarative `.volatile()` plus `loader/volatile-update` re-registration on 0.1.7+ (and desktop); instance `settings.installSection`/`register` on 0.1.2/0.1.5; module-level `installSettingsSection` from `@deepseek-ai/dsh-settings` on 0.1.0/0.1.1. The plugin-page configuration card (client half) has a seat only on 0.1.7+/desktop and is gracefully absent on older lines.
10
+ - `defineTool` authoring path with fs soft-degradation: on host lines whose `fs` lacks write-intent, writes degrade to a direct write with a single `console.warn` instead of failing.
11
+ - Six-line typecheck matrix, plus a smoke gate covering the graceful-absence scenarios.
12
+
13
+ ### Changed
14
+
15
+ - **Breaking: `allowCodexPatch` now defaults to `false`** (opt-in, aligned with the 0.2.0 line; the old 0.1.7-line default was `true`). Existing 0.1.7-line users must enable it manually after upgrading to 0.4.0.
16
+
4
17
  ## [0.3.1] — 2026-10-01
5
18
 
6
19
  ### Fixed
package/CHANGELOG.zh.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # 更新日志
2
2
 
3
3
 
4
+ ## [0.4.0] — 2026-10-09
5
+
6
+ ### 新增
7
+
8
+ - **单版本覆盖全宿主线。** 一个版本(0.4.0)服务 `0.1.0-rc.8` 到 `0.2.0-rc.2` 的所有 DSH 宿主——全部 15 个 rc + desktop;peer 范围枚举全部 15 个 rc,`engines.dsh` 声明 `>=0.1.0-rc.8`。退役的 compat 分支(`compat/0.1.2`、`compat/0.1.5`、`compat/0.1.7`)与 `main` 分线方案全部移除;发布后 npm dist-tag `latest`、`dsh-0.2.0`、`dsh-0.1.7`、`dsh-0.1.5`、`dsh-0.1.2` 将全部收敛到 0.4.0。
9
+ - **一份代码覆盖三代设置面**:0.1.7+(及 desktop)为声明式 `.volatile()` + `loader/volatile-update` 重注册;0.1.2/0.1.5 为实例 `settings.installSection`/`register`;0.1.0/0.1.1 为 `@deepseek-ai/dsh-settings` 模块级 `installSettingsSection`。插件页配置卡(client 半)仅在 0.1.7+/desktop 有席位,老线优雅缺席。
10
+ - `defineTool` 编写路径与 fs 软降级:宿主 `fs` 缺 write-intent 的线上,写入自动降级为直写并 `console.warn` 一次,不再失败。
11
+ - 六线 typecheck 矩阵,以及覆盖优雅缺席场景的 smoke 闸。
12
+
13
+ ### 变更
14
+
15
+ - **破坏性变更:`allowCodexPatch` 默认值改为 `false`**(opt-in,与 0.2.0 线对齐;旧 0.1.7 线默认为 `true`)。存量 0.1.7 线用户升级到 0.4.0 后需手动打开该开关。
16
+
4
17
  ## [0.3.1] — 2026-10-01
5
18
 
6
19
  ### 修复
package/README.de.md CHANGED
@@ -6,13 +6,18 @@ Patch-basierte Dateibearbeitung für [DeepSeek Harness (DSH)](https://github.com
6
6
 
7
7
  ## DSH-Versionskompatibilität
8
8
 
9
+ **v0.4.0 ist eine einzelne Version, die die gesamte Host-Linie abdeckt**: eine Version bedient alle DSH von `0.1.0-rc.8` bis `0.2.0-rc.2` (alle 15 RCs plus Desktop). Die vier eingestellten Linien (`compat/0.1.2`, `compat/0.1.5`, `compat/0.1.7` und das `main`-Aufteilungsschema) sind retired; nach der Veröffentlichung zeigen die npm-Dist-Tags `latest`, `dsh-0.2.0`, `dsh-0.1.7`, `dsh-0.1.5` und `dsh-0.1.2` alle auf 0.4.0.
10
+
9
11
  | DSH-Version | Status | Hinweise |
10
12
  |---|---|---|
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. |
13
+ | `0.2.0-rc.1+` | ✅ unterstützt (dieselbe v0.4.0) | Deklarative Einstellungen: mit `.volatile()` markierte Felder werden zum Einstellungsformular, und `loader/volatile-update` registriert das Werkzeug ohne Remount neu. Die Konfigurationskarte auf der Plugin-Seite (Client-Hälfte) hat auf dieser Linie einen Platz. |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ unterstützt (dieselbe v0.4.0) | Einstellungen je Generation: Instanz-`settings.installSection`/`register` (0.1.2/0.1.5) oder das modulweite `installSettingsSection` von `@deepseek-ai/dsh-settings` (0.1.0/0.1.1). Die Konfigurationskarte auf der Plugin-Seite fehlt hier elegant. |
15
+
16
+ **Verhaltensänderung:** `allowCodexPatch` hat nun den Standardwert `false` (Opt-in, an der 0.2.0-Linie ausgerichtet). Wer von der alten 0.1.7-Linie (dort Standard `true`) aufrüstet, muss den Schalter nach dem Upgrade manuell aktivieren.
17
+
18
+ Die Einstellungen umfassen drei Host-Generationen, alle von dieser einen Version bedient: auf 0.1.7+ (und Desktop) ist die Konfiguration deklarativ — mit `.volatile()` markierte Felder in `Config` sind das Einstellungsformular, und das Plugin abonniert `loader/volatile-update`; auf 0.1.2/0.1.5 nutzt es die Instanz-APIs `settings.installSection`/`register`; auf 0.1.0/0.1.1 das modulweite `installSettingsSection` von `@deepseek-ai/dsh-settings`. Die Konfigurationskarte auf der Plugin-Seite (Client-Hälfte) hat nur auf 0.1.7+/Desktop einen Platz und fehlt auf älteren Linien elegant.
14
19
 
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.
20
+ Die Werkzeugfähigkeiten sind auf jeder Linie identisch: ein einziges `apply_patch`-Werkzeug, git/unified diff als Standard plus Codex als Opt-in, Alles-oder-Nichts-Anwendung, der Read-before-Write-Intent-Tanz (auf Linien ohne write-intent im `fs` degradieren Schreibvorgänge zu direkten Schreibzugriffen mit genau einem `console.warn`) und sandbox-bewusstes Delete/Move.
16
21
 
17
22
  ## Warum überhaupt Patches? (Tool-Routing-Leitfaden)
18
23
 
package/README.es.md CHANGED
@@ -6,13 +6,18 @@ Edición de archivos estilo parche para [DeepSeek Harness (DSH)](https://github.
6
6
 
7
7
  ## Compatibilidad de versiones de DSH
8
8
 
9
+ **La v0.4.0 es una única versión que cubre toda la línea de hosts**: una sola versión atiende todos los DSH desde `0.1.0-rc.8` hasta `0.2.0-rc.2` (los 15 rc más desktop). Las cuatro líneas retiradas (`compat/0.1.2`, `compat/0.1.5`, `compat/0.1.7` y el esquema de división por `main`) se jubilan; tras la publicación, los dist-tags de npm `latest`, `dsh-0.2.0`, `dsh-0.1.7`, `dsh-0.1.5` y `dsh-0.1.2` apuntarán todos a 0.4.0.
10
+
9
11
  | Versión de DSH | Estado | Notas |
10
12
  |---|---|---|
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. |
13
+ | `0.2.0-rc.1+` | ✅ compatible (misma v0.4.0) | Ajustes declarativos: los campos marcados con `.volatile()` se convierten en el formulario de ajustes, y `loader/volatile-update` vuelve a registrar la herramienta sin remontaje. La tarjeta de configuración de la página del plugin (mitad cliente) tiene sitio en esta línea. |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ compatible (misma v0.4.0) | Ajustes por generación: `settings.installSection`/`register` de instancia (0.1.2/0.1.5) o `installSettingsSection` a nivel de módulo de `@deepseek-ai/dsh-settings` (0.1.0/0.1.1). La tarjeta de configuración de la página del plugin está ausente con elegancia aquí. |
15
+
16
+ **Cambio de comportamiento:** `allowCodexPatch` ahora es `false` por defecto (opt-in, alineado con la línea 0.2.0). Si actualizas desde la antigua línea 0.1.7 (donde el valor por defecto era `true`), activa el interruptor manualmente tras la actualización.
17
+
18
+ Los ajustes abarcan tres generaciones de hosts, todas atendidas por esta única versión: en 0.1.7+ (y desktop) la configuración es declarativa — los campos marcados con `.volatile()` en `Config` son el formulario de ajustes y el plugin se suscribe a `loader/volatile-update`; en 0.1.2/0.1.5 usa las API de instancia `settings.installSection`/`register`; en 0.1.0/0.1.1 usa el `installSettingsSection` a nivel de módulo de `@deepseek-ai/dsh-settings`. La tarjeta de configuración de la página del plugin (mitad cliente) solo tiene sitio en 0.1.7+/desktop y en las líneas antiguas está ausente con elegancia.
14
19
 
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.
20
+ Las capacidades de la herramienta son idénticas en cada línea: una única herramienta `apply_patch`, diff git/unificado por defecto más Codex como opcional, aplicación todo-o-nada, la danza de intención de leer-antes-de-escribir (en las líneas cuyo `fs` carece de write-intent, las escrituras degradan a escritura directa con un único `console.warn`) y delete/move consciente del sandbox.
16
21
 
17
22
  ## ¿Por qué usar parches? (guía de enrutamiento de herramientas)
18
23
 
package/README.fr.md CHANGED
@@ -6,13 +6,18 @@ Français | [English](./README.md) | [简体中文](./README.zh.md) | [日本語
6
6
 
7
7
  ## Compatibilité des versions de DSH
8
8
 
9
+ **La v0.4.0 est une version unique couvrant toute la ligne d'hôtes** : une seule version sert tous les DSH de `0.1.0-rc.8` à `0.2.0-rc.2` (les 15 rc plus desktop). Les quatre anciennes lignes (`compat/0.1.2`, `compat/0.1.5`, `compat/0.1.7` et le schéma de scission `main`) sont retirées ; après publication, les dist-tags npm `latest`, `dsh-0.2.0`, `dsh-0.1.7`, `dsh-0.1.5` et `dsh-0.1.2` pointeront tous vers 0.4.0.
10
+
9
11
  | Version de DSH | Statut | Notes |
10
12
  |---|---|---|
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). |
13
+ | `0.2.0-rc.1+` | ✅ pris en charge (même v0.4.0) | Paramètres déclaratifs : les champs marqués `.volatile()` constituent le formulaire de paramètres, et `loader/volatile-update` réenregistre l'outil sans remontage (remount). La carte de configuration de la page du plugin (moitié client) a sa place sur cette ligne. |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ pris en charge (même v0.4.0) | Paramètres par génération : `settings.installSection`/`register` d'instance (0.1.2/0.1.5) ou `installSettingsSection` au niveau module de `@deepseek-ai/dsh-settings` (0.1.0/0.1.1). La carte de configuration de la page du plugin est absente avec élégance ici. |
15
+
16
+ **Changement de comportement :** `allowCodexPatch` est désormais `false` par défaut (opt-in, aligné sur la ligne 0.2.0). Si vous mettez à niveau depuis l'ancienne ligne 0.1.7 (où la valeur par défaut était `true`), activez l'interrupteur manuellement après la mise à niveau.
17
+
18
+ Les paramètres couvrent trois générations d'hôtes, toutes servies par cette version unique : sur 0.1.7+ (et desktop), la configuration est déclarative — les champs marqués `.volatile()` dans `Config` sont le formulaire de paramètres et le plugin s'abonne à `loader/volatile-update` ; sur 0.1.2/0.1.5, il utilise les API d'instance `settings.installSection`/`register` ; sur 0.1.0/0.1.1, le `installSettingsSection` au niveau module de `@deepseek-ai/dsh-settings`. La carte de configuration de la page du plugin (moitié client) n'a sa place que sur 0.1.7+/desktop et est absente avec élégance sur les anciennes lignes.
14
19
 
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.
20
+ Les capacités de l'outil sont identiques sur chaque ligne : un seul outil `apply_patch`, diff git/unifié par défaut plus Codex en opt-in, application tout-ou-rien, la danse d'intention lecture-avant-écriture (sur les lignes dont le `fs` n'a pas write-intent, les écritures dégradent en écriture directe avec un seul `console.warn`), et delete/move conscient du bac à sable.
16
21
 
17
22
  ## Pourquoi faire des patchs ? (guide de routage des outils)
18
23
 
package/README.it.md CHANGED
@@ -6,13 +6,18 @@ Modifica di file in stile patch per [DeepSeek Harness (DSH)](https://github.com/
6
6
 
7
7
  ## Compatibilità delle versioni DSH
8
8
 
9
+ **La v0.4.0 è una singola versione che copre l'intera linea di host**: una sola versione serve tutti i DSH da `0.1.0-rc.8` a `0.2.0-rc.2` (tutti i 15 rc più desktop). Le quattro linee dismesse (`compat/0.1.2`, `compat/0.1.5`, `compat/0.1.7` e lo schema di biforcazione `main`) sono ritirate; dopo la pubblicazione, i dist-tag npm `latest`, `dsh-0.2.0`, `dsh-0.1.7`, `dsh-0.1.5` e `dsh-0.1.2` punteranno tutti a 0.4.0.
10
+
9
11
  | Versione DSH | Stato | Note |
10
12
  |---|---|---|
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. |
13
+ | `0.2.0-rc.1+` | ✅ supportato (stessa v0.4.0) | Impostazioni dichiarative: i campi contrassegnati con `.volatile()` diventano il modulo delle impostazioni, e `loader/volatile-update` registra nuovamente lo strumento senza remount. La scheda di configurazione nella pagina del plugin (metà client) ha un posto su questa linea. |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ supportato (stessa v0.4.0) | Impostazioni per generazione: `settings.installSection`/`register` di istanza (0.1.2/0.1.5) oppure `installSettingsSection` a livello di modulo di `@deepseek-ai/dsh-settings` (0.1.0/0.1.1). La scheda di configurazione nella pagina del plugin è assente con eleganza qui. |
15
+
16
+ **Cambio di comportamento:** `allowCodexPatch` ora è `false` per impostazione predefinita (opt-in, allineato alla linea 0.2.0). Chi esegue l'aggiornamento dalla vecchia linea 0.1.7 (dove il predefinito era `true`) deve attivare l'interruttore manualmente dopo l'aggiornamento.
17
+
18
+ Le impostazioni attraversano tre generazioni di host, tutte servite da questa singola versione: su 0.1.7+ (e desktop) la configurazione è dichiarativa — i campi contrassegnati con `.volatile()` in `Config` sono il modulo delle impostazioni e il plugin si iscrive a `loader/volatile-update`; su 0.1.2/0.1.5 usa le API di istanza `settings.installSection`/`register`; su 0.1.0/0.1.1 usa `installSettingsSection` a livello di modulo di `@deepseek-ai/dsh-settings`. La scheda di configurazione nella pagina del plugin (metà client) ha un posto solo su 0.1.7+/desktop ed è assente con eleganza sulle linee precedenti.
14
19
 
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.
20
+ Le capacità dello strumento sono identiche su ogni linea: un unico strumento `apply_patch`, diff git/unificato per impostazione predefinita più Codex come opt-in, applicazione tutto-o-nulla, la danza d'intento read-before-write (sulle linee il cui `fs` è privo di write-intent le scritture degradano a scrittura diretta con un solo `console.warn`) e delete/move consapevole della sandbox.
16
21
 
17
22
  ## Perché proprio le patch? (guida al routing degli strumenti)
18
23
 
package/README.ja.md CHANGED
@@ -6,13 +6,18 @@
6
6
 
7
7
  ## DSH バージョン互換性
8
8
 
9
+ **v0.4.0 は全ホストラインを 1 つのバージョンでカバーします**:`0.1.0-rc.8` から `0.2.0-rc.2` まで(15 個の rc 全部 + desktop)のすべての DSH ホストを同じバージョンが担当します。旧来の 4 本のライン(`compat/0.1.2`、`compat/0.1.5`、`compat/0.1.7`、`main` 分割スキーム)は引退しました。公開後、npm dist-tag の `latest`、`dsh-0.2.0`、`dsh-0.1.7`、`dsh-0.1.5`、`dsh-0.1.2` はすべて 0.4.0 を指します。
10
+
9
11
  | DSH バージョン | ステータス | 備考 |
10
12
  |---|---|---|
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 を削除しました。 |
13
+ | `0.2.0-rc.1+` | ✅ サポート対象(同じ v0.4.0) | 宣言的設定:`.volatile()` を付けたフィールドがそのまま設定フォームになり、`loader/volatile-update` が再マウントなしでツールをその場で再登録します。プラグインページの設定カード(client 側)はこのラインに席があります。 |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ サポート対象(同じ v0.4.0) | 世代ごとの設定:インスタンスの `settings.installSection`/`register`(0.1.2/0.1.5)、または `@deepseek-ai/dsh-settings` のモジュールレベル `installSettingsSection`(0.1.0/0.1.1)。プラグインページの設定カードはここでは適切に省かれます。 |
15
+
16
+ **挙動変更**:`allowCodexPatch` の既定値は `false` になりました(オプトイン、0.2.0 ラインに合わせました)。旧 0.1.7 ライン(既定 `true`)からアップグレードした場合は、アップグレード後に手動でスイッチを有効にしてください。
17
+
18
+ 設定面は 3 世代のホストにまたがり、すべてこの単一バージョンが担います:0.1.7+(および desktop)では宣言的 —— `Config` 内で `.volatile()` を付けたフィールドが設定フォームそのものであり、プラグインは `loader/volatile-update` を購読します。0.1.2/0.1.5 ではインスタンスの `settings.installSection`/`register` API を、0.1.0/0.1.1 では `@deepseek-ai/dsh-settings` のモジュールレベル `installSettingsSection` を使用します。プラグインページの設定カード(client 側)は 0.1.7+/desktop のみに席があり、旧ラインでは適切に省かれます。
14
19
 
15
- 本ラインの設定は宣言的です:`Config` 内で `.volatile()` を付けたフィールドがそのまま設定フォームになり、プラグインは登録フックの代わりに `loader/volatile-update` を購読します。
20
+ ツール機能は全ラインで同一です:`apply_patch` 1 本、git/unified diff がデフォルト + Codex はオプトイン、全検証のうえアトミック適用、read-before-write の intent ダンス(ホストの `fs` に write-intent がないラインでは直接書き込みへ自動低下し `console.warn` を 1 回出力)、サンドボックス対応の delete/move。
16
21
 
17
22
  ## そもそもなぜパッチなのか?(ツールルーティングガイド)
18
23
 
package/README.ko.md CHANGED
@@ -6,13 +6,18 @@
6
6
 
7
7
  ## DSH 버전 호환성
8
8
 
9
+ **v0.4.0은 전체 호스트 라인을 단일 버전으로 커버합니다**: `0.1.0-rc.8`부터 `0.2.0-rc.2`까지(15개 rc 전부 + desktop) 모든 DSH 호스트를 같은 버전이 지원합니다. 이전의 4개 라인(`compat/0.1.2`, `compat/0.1.5`, `compat/0.1.7`, `main` 분할 방식)은 모두 은퇴했습니다. 배포 후 npm dist-tag `latest`, `dsh-0.2.0`, `dsh-0.1.7`, `dsh-0.1.5`, `dsh-0.1.2`는 모두 0.4.0을 가리킵니다.
10
+
9
11
  | DSH 버전 | 상태 | 비고 |
10
12
  |---|---|---|
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를 제거했습니다. |
13
+ | `0.2.0-rc.1+` | ✅ 지원됨(동일한 v0.4.0) | 선언적 설정: `.volatile()`로 표시된 필드가 곧 설정 폼이며, `loader/volatile-update`가 리마운트 없이 도구를 그 자리에서 재등록합니다. 플러그인 페이지 설정 카드(client 쪽)는 이 라인에 자리가 있습니다. |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ 지원됨(동일한 v0.4.0) | 세대별 설정: 인스턴스 `settings.installSection`/`register`(0.1.2/0.1.5) 또는 `@deepseek-ai/dsh-settings`의 모듈 수준 `installSettingsSection`(0.1.0/0.1.1). 플러그인 페이지 설정 카드는 여기에 우아하게 부재합니다. |
15
+
16
+ **동작 변경**: `allowCodexPatch` 기본값이 `false`로 바뀌었습니다(옵트인, 0.2.0 라인과 정렬). 기존 0.1.7 라인(기본값 `true`)에서 업그레이드하는 사용자는 업그레이드 후 스위치를 수동으로 켜야 합니다.
17
+
18
+ 설정 면은 3세대 호스트에 걸쳐 있으며 모두 이 단일 버전이 지원합니다: 0.1.7+(및 desktop)에서는 선언적 —— `Config`에서 `.volatile()`로 표시된 필드가 설정 폼이고, 플러그인은 `loader/volatile-update`를 구독합니다. 0.1.2/0.1.5에서는 인스턴스 `settings.installSection`/`register` API를, 0.1.0/0.1.1에서는 `@deepseek-ai/dsh-settings`의 모듈 수준 `installSettingsSection`을 사용합니다. 플러그인 페이지 설정 카드(client 쪽)는 0.1.7+/desktop에만 자리가 있고 구 라인에서는 우아하게 부재합니다.
14
19
 
15
- 본 라인의 설정은 선언적입니다: `Config`에서 `.volatile()`로 표시된 필드가 곧 설정 폼이며, 플러그인은 등록 훅 대신 `loader/volatile-update`를 구독합니다.
20
+ 도구 기능은 모든 라인에서 동일합니다: `apply_patch` 1개, git/unified diff 기본 + Codex 옵트인, 전체 검증 후 원자적 적용, read-before-write intent 댄스(호스트 `fs`에 write-intent가 없는 라인에서는 직접 쓰기로 자동 강등하며 `console.warn`을 1회 출력), 샌드박스 인식 delete/move.
16
21
 
17
22
  ## 왜 굳이 패치인가? (도구 라우팅 가이드)
18
23
 
package/README.md CHANGED
@@ -6,13 +6,18 @@ Patch-style file editing for [DeepSeek Harness (DSH)](https://github.com/deepsee
6
6
 
7
7
  ## DSH version compatibility
8
8
 
9
+ **v0.4.0 is a single release covering the whole host line**: one version serves every DSH from `0.1.0-rc.8` to `0.2.0-rc.2` (all 15 rc releases plus desktop). The four retired lines (`compat/0.1.2`, `compat/0.1.5`, `compat/0.1.7`, and the `main` split-line scheme) are gone; after publishing, the npm dist-tags `latest`, `dsh-0.2.0`, `dsh-0.1.7`, `dsh-0.1.5` and `dsh-0.1.2` all point to 0.4.0.
10
+
9
11
  | DSH version | Status | Notes |
10
12
  |---|---|---|
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. |
13
+ | `0.2.0-rc.1+` | ✅ supported (same v0.4.0) | Declarative settings: fields marked `.volatile()` become the settings form, and `loader/volatile-update` re-registers the tool in place without a remount. The plugin-page configuration card (client half) has a seat on this line. |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ supported (same v0.4.0) | Settings per generation: instance `settings.installSection`/`register` (0.1.2/0.1.5) or the module-level `installSettingsSection` of `@deepseek-ai/dsh-settings` (0.1.0/0.1.1). The plugin-page configuration card is gracefully absent here. |
15
+
16
+ **Behavior change:** `allowCodexPatch` now defaults to `false` (opt-in, aligned with the 0.2.0 line). If you upgrade from the old 0.1.7 line (where the default was `true`), enable the switch manually after upgrading.
17
+
18
+ Settings span three host generations, all served by this single version: on 0.1.7+ (and desktop) the config is declarative — fields marked `.volatile()` in `Config` are the settings form, and the plugin subscribes to `loader/volatile-update`; on 0.1.2/0.1.5 it uses the instance `settings.installSection`/`register` APIs; on 0.1.0/0.1.1 it uses the module-level `installSettingsSection` of `@deepseek-ai/dsh-settings`. The plugin-page configuration card (client half) only has a seat on 0.1.7+/desktop and is gracefully absent on older lines.
14
19
 
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.
20
+ Tool capabilities are identical on every line: one `apply_patch` tool, git/unified diff by default plus Codex opt-in, all-or-nothing application, the read-before-write intent dance (on host lines whose `fs` lacks write-intent, writes degrade to a direct write with a single `console.warn`), and sandbox-aware delete/move.
16
21
 
17
22
  ## Why patch at all? (tool routing guide)
18
23
 
package/README.ru.md CHANGED
@@ -6,13 +6,18 @@
6
6
 
7
7
  ## Совместимость с версиями DSH
8
8
 
9
+ **v0.4.0 — единая версия, покрывающая всю линию хостов**: одна версия обслуживает все DSH от `0.1.0-rc.8` до `0.2.0-rc.2` (все 15 rc плюс desktop). Четыре прежние линии (`compat/0.1.2`, `compat/0.1.5`, `compat/0.1.7` и схема разделения по `main`) выведены из эксплуатации; после публикации npm dist-tag'и `latest`, `dsh-0.2.0`, `dsh-0.1.7`, `dsh-0.1.5` и `dsh-0.1.2` будут указывать на 0.4.0.
10
+
9
11
  | Версия DSH | Статус | Примечания |
10
12
  |---|---|---|
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-фолбэк. |
13
+ | `0.2.0-rc.1+` | ✅ поддерживается (та же v0.4.0) | Декларативные настройки: поля, помеченные `.volatile()`, становятся формой настроек, а `loader/volatile-update` перерегистрирует инструмент без перемонтирования. Карточка конфигурации на странице плагина (клиентская половина) на этой линии присутствует. |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ поддерживается (та же v0.4.0) | Настройки по поколениям: экземплярные `settings.installSection`/`register` (0.1.2/0.1.5) либо модульный `installSettingsSection` из `@deepseek-ai/dsh-settings` (0.1.0/0.1.1). Карточка конфигурации на странице плагина здесь изящно отсутствует. |
15
+
16
+ **Изменение поведения:** значение `allowCodexPatch` по умолчанию теперь `false` (включение вручную, выровнено с линией 0.2.0). При обновлении со старой линии 0.1.7 (где по умолчанию было `true`) переключатель нужно включить вручную после обновления.
17
+
18
+ Настройки охватывают три поколения хостов, и все они обслуживаются этой единственной версией: на 0.1.7+ (и desktop) конфигурация декларативна — поля, помеченные `.volatile()` в `Config`, и есть форма настроек, а плагин подписывается на `loader/volatile-update`; на 0.1.2/0.1.5 используются экземплярные API `settings.installSection`/`register`; на 0.1.0/0.1.1 — модульный `installSettingsSection` из `@deepseek-ai/dsh-settings`. Карточка конфигурации на странице плагина (клиентская половина) присутствует только на 0.1.7+/desktop и на старых линиях изящно отсутствует.
14
19
 
15
- На этой линии настройки декларативны: поля, помеченные `.volatile()` в `Config`, становятся формой настроек; плагин подписывается на `loader/volatile-update` вместо получения регистрационных хуков.
20
+ Возможности инструмента идентичны на каждой линии: один инструмент `apply_patch`, git/unified diff по умолчанию плюс Codex по явному включению, применение всё-или-ничего, intent-танец «сначала прочитай, потом пиши» (на линиях, где в `fs` нет write-intent, запись деградирует до прямой с одним `console.warn`) и sandbox-осознанные delete/move.
16
21
 
17
22
  ## Зачем вообще патчи? (руководство по маршрутизации инструментов)
18
23
 
package/README.zh.md CHANGED
@@ -6,13 +6,18 @@
6
6
 
7
7
  ## DSH 版本适配矩阵
8
8
 
9
+ **v0.4.0 是单版本覆盖全宿主线**:一个版本服务 `0.1.0-rc.8` 到 `0.2.0-rc.2` 的所有 DSH 宿主(全部 15 个 rc + desktop)。旧的四条线(`compat/0.1.2`、`compat/0.1.5`、`compat/0.1.7` 与 `main` 分线方案)全部退役;发布后 npm dist-tag `latest`、`dsh-0.2.0`、`dsh-0.1.7`、`dsh-0.1.5`、`dsh-0.1.2` 将全部指向 0.4.0。
10
+
9
11
  | DSH 版本 | 状态 | 说明 |
10
12
  |---|---|---|
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。 |
13
+ | `0.2.0-rc.1+` | ✅ 支持(同一个 v0.4.0) | 声明式设置:`Config` 中标记 `.volatile()` 的字段即设置表单,`loader/volatile-update` 驱动工具原位重注册(不 remount)。插件页配置卡(client 半)在本线有席位。 |
14
+ | `0.1.0-rc.8` ~ `0.1.7-rc.2` | ✅ 支持(同一个 v0.4.0) | 按代际提供设置:实例 `settings.installSection`/`register`(0.1.2/0.1.5)或 `@deepseek-ai/dsh-settings` 模块级 `installSettingsSection`(0.1.0/0.1.1)。插件页配置卡在本线优雅缺席。 |
15
+
16
+ **行为变更**:`allowCodexPatch` 默认值改为 `false`(opt-in,与 0.2.0 线对齐)。从旧 0.1.7 线(默认 `true`)升级的用户需在升级后手动打开该开关。
17
+
18
+ 设置面覆盖三代宿主,均由这同一个版本服务:0.1.7+(及 desktop)是声明式 —— `Config` 中标记 `.volatile()` 的字段即设置表单,插件订阅 `loader/volatile-update`;0.1.2/0.1.5 使用实例 `settings.installSection`/`register` API;0.1.0/0.1.1 使用 `@deepseek-ai/dsh-settings` 的模块级 `installSettingsSection`。插件页配置卡(client 半)仅在 0.1.7+/desktop 有席位,老线优雅缺席。
14
19
 
15
- 本线的 settings 是声明式的:`Config` 中标记 `.volatile()` 的字段即设置表单;插件订阅 `loader/volatile-update`,不再接收注册 hooks。
20
+ 工具能力在各线完全一致:只注册 1 个 `apply_patch` 工具、git/unified diff 默认 + Codex 可选、全量验证原子应用、read-before-write intent 舞蹈(宿主 `fs` 缺 write-intent 时自动降级直写并 `console.warn` 一次)、沙箱感知的 delete/move。
16
21
 
17
22
  ## 工具路由指引(为什么该用谁)
18
23
 
package/cordis.patch.yml CHANGED
@@ -1,6 +1,12 @@
1
1
  # Assembly layer for the dsh profiles whose bundles list includes this package.
2
2
  # A pure addition: one insert row with an id no shipped entry uses. No shipped
3
3
  # row is disabled, renamed, or reconfigured here.
4
+ # Config rides the inserted row: both patch syntaxes ship enabled. On this line
5
+ # the schema default for allowCodexPatch is false, so the row must carry
6
+ # allowCodexPatch: true explicitly to keep both syntaxes on out of the box.
4
7
  - insert:
5
8
  - id: dsh-patch-edit-plus
6
9
  name: dsh-patch-edit-plus
10
+ config:
11
+ allowUnifiedDiff: true
12
+ allowCodexPatch: true
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.3.1",
4
+ "version": "0.4.0",
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.2.0-rc.1 <0.2.1-0"
16
+ "dsh": ">=0.1.0-rc.8 <0.2.1-0"
17
17
  },
18
18
  "components": {
19
19
  "host": "lib/index.js"
@@ -0,0 +1,151 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * dsh-patch-edit-plus — 浏览器 half(0.2.0 新增)。
4
+ *
5
+ * 单一职责:在 Plugins 页 bundle 详情页的 `plugins.bundle.config` 席位
6
+ * (key = 包名)下注册一张配置卡,暴露两个补丁风格开关——
7
+ * - `allowUnifiedDiff`(Git/unified diff,默认开)
8
+ * - `allowCodexPatch`(Codex apply_patch,默认关)
9
+ *
10
+ * 字段全部是 host 侧 `Config` 的 `.volatile()` 字段:卡片经
11
+ * `configForms.get('dsh-patch-edit-plus')` 自绑本插件 entry(entry id 与
12
+ * 包名一致,无错位),写入走 `form.set(field, !cur)`,提交后宿主经
13
+ * `loader/volatile-update` 原地重注册工具(见 src/index.ts 的 rejudge)。
14
+ *
15
+ * 构建:tsdown → lib/client.js(__ModuleLoader__.load 闭包工厂,id = 包名)。
16
+ * react 是唯一 value-import(平台 external);slots/configForms 经 cordis
17
+ * 服务消费,configForms 缺席时(理论上仅剩极老宿主)卡片整卡隐藏,不阻塞
18
+ * 客户端半。文案内联双语字典(zh/en),不建 locale 文件。
19
+ */
20
+ import { createElement, useSyncExternalStore } from 'react';
21
+ /** 客户端所需服务:slots 全世代都有,准声明;configForms 是 0.1.7+ 服务,
22
+ * **不准**进顶层 inject——在老宿主上声明缺失服务会把 client entry 永久挂起
23
+ * (web boot 拒渲染整树,「1 entry did not activate」家族教训)。configForms
24
+ * 走软读(strict proxy 直读 throw → try/catch 落 ctx.get),缺席时整卡隐藏。 */
25
+ export const inject = ['slots'];
26
+ /** 内联双语字典(zh/en;按 document.documentElement.lang → navigator.language 兜底)。 */
27
+ const STRINGS = {
28
+ zh: {
29
+ cardName: '补丁风格',
30
+ cardDesc: 'apply_patch 接受的补丁语法',
31
+ unifiedTitle: 'Git 风格补丁',
32
+ unifiedDesc: '接受 Git/unified diff 补丁语法(默认开)',
33
+ codexTitle: 'Codex 风格补丁',
34
+ codexDesc: '接受 Codex apply_patch 语法(默认关)',
35
+ readonlyHint: '当前只读,无法修改。',
36
+ },
37
+ en: {
38
+ cardName: 'Patch style',
39
+ cardDesc: 'Patch syntax accepted by apply_patch',
40
+ unifiedTitle: 'Git-style patches',
41
+ unifiedDesc: 'Accept Git/unified diff patch syntax (default on)',
42
+ codexTitle: 'Codex-style patches',
43
+ codexDesc: 'Accept Codex apply_patch syntax (default off)',
44
+ readonlyHint: 'Read-only right now; changes are not allowed.',
45
+ },
46
+ };
47
+ /** 解析当前语言:document.documentElement.lang 优先,navigator.language 兜底,再退 zh。 */
48
+ function pickLang() {
49
+ try {
50
+ const docLang = typeof document !== 'undefined' ? document.documentElement.lang : '';
51
+ const navLang = typeof navigator !== 'undefined' ? navigator.language : '';
52
+ for (const tag of [docLang, navLang]) {
53
+ if (typeof tag === 'string' && /^zh/i.test(tag))
54
+ return 'zh';
55
+ if (typeof tag === 'string' && /^en/i.test(tag))
56
+ return 'en';
57
+ }
58
+ }
59
+ catch {
60
+ // 非 DOM 环境保底 zh
61
+ }
62
+ return 'zh';
63
+ }
64
+ /** 卡片样式,注入一次(保持 bundle CSS-free;变量与 session-guard 卡同源)。 */
65
+ const CARD_CSS = `
66
+ .ppeCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:4px 16px 8px}
67
+ .ppeCardName{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4;margin:10px 0 2px}
68
+ .ppeCardDesc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5;margin:0 0 4px}
69
+ .ppeRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:14px 0;display:flex}
70
+ .ppeRow:last-of-type{border-bottom:0}
71
+ .ppeRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}
72
+ .ppeTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}
73
+ .ppeDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}
74
+ .ppeSwitch{appearance:none;position:relative;width:40px;height:22px;flex:none;cursor:pointer;background:transparent;border:0;padding:0}
75
+ .ppeSwitch:disabled{cursor:not-allowed}
76
+ .ppeSwitchTrack{position:absolute;inset:0;border-radius:22px;background:var(--dsw-alias-interactive-bg-hover);transition:background .16s}
77
+ .ppeSwitch-on>.ppeSwitchTrack{background:var(--dsw-alias-button-primary-fill)}
78
+ .ppeSwitchThumb{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .16s}
79
+ .ppeSwitch-on>.ppeSwitchThumb{transform:translateX(18px)}
80
+ .ppeSwitch:disabled>.ppeSwitchTrack{opacity:.5}
81
+ .ppeReadonly{color:var(--dsw-alias-label-tertiary);font-size:12px;margin:8px 0 4px}
82
+ `;
83
+ /** 注入一次卡片样式。 */
84
+ function injectCss() {
85
+ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css="patch-edit-plus-card"]') === null) {
86
+ const tag = document.createElement('style');
87
+ tag.dataset.plugin = 'dsh-patch-edit-plus';
88
+ tag.dataset.pluginCss = 'patch-edit-plus-card';
89
+ tag.textContent = CARD_CSS;
90
+ document.head.appendChild(tag);
91
+ }
92
+ }
93
+ const NOOP_SNAPSHOT = { status: 'unavailable', value: undefined, writable: false };
94
+ const unsubscribeNoop = () => { };
95
+ /** 一行 role="switch" 开关(aria-checked + data-* 便于测试选择器)。 */
96
+ function SwitchRow(props) {
97
+ const { field, title, description, checked, disabled, onToggle } = props;
98
+ return (_jsxs("div", { className: "ppeRow", children: [_jsxs("div", { className: "ppeRowText", children: [_jsx("div", { className: "ppeTitle", children: title }), _jsx("div", { className: "ppeDesc", children: description })] }), _jsxs("button", { type: "button", role: "switch", "aria-checked": checked, "data-plugin": "dsh-patch-edit-plus", "data-field": field, "data-checked": checked ? 'true' : 'false', className: 'ppeSwitch' + (checked ? ' ppeSwitch-on' : ''), disabled: disabled, onClick: () => onToggle(field, checked), children: [_jsx("span", { className: "ppeSwitchTrack" }), _jsx("span", { className: "ppeSwitchThumb" })] })] }));
99
+ }
100
+ /**
101
+ * 插件页配置卡主体:两行补丁风格开关。
102
+ * - status === 'unavailable'(无 configForms / entry 未装配)→ 整卡隐藏(null);
103
+ * - status === 'loading' → 开关禁用;
104
+ * - 仅 snapshot.writable 时可写(写路径 `form.set(field, !cur)`)。
105
+ */
106
+ export function PatchStyleCard(props) {
107
+ const form = props.form;
108
+ const snapshot = useSyncExternalStore(form
109
+ ? (listener) => form.subscribe(listener)
110
+ : () => unsubscribeNoop, () => form?.getSnapshot() ?? NOOP_SNAPSHOT);
111
+ injectCss();
112
+ if (snapshot.status === 'unavailable')
113
+ return null;
114
+ const t = STRINGS[pickLang()];
115
+ // loading / 只读都归约为「不可写」:开关禁用,仅 ready + writable 时可写。
116
+ const editable = snapshot.status === 'ready' && snapshot.writable;
117
+ const value = snapshot.value ?? {};
118
+ const toggle = (field, current) => {
119
+ if (form === undefined || !editable)
120
+ return;
121
+ void form.set(field, !current).catch(() => { });
122
+ };
123
+ return (_jsxs("section", { className: "ppeCard", "data-plugin": "dsh-patch-edit-plus", children: [_jsx("div", { className: "ppeCardName", children: t.cardName }), _jsx("p", { className: "ppeCardDesc", children: t.cardDesc }), _jsx(SwitchRow, { field: "allowUnifiedDiff", title: t.unifiedTitle, description: t.unifiedDesc, checked: value.allowUnifiedDiff ?? true, disabled: !editable, onToggle: toggle }), _jsx(SwitchRow, { field: "allowCodexPatch", title: t.codexTitle, description: t.codexDesc, checked: value.allowCodexPatch ?? false, disabled: !editable, onToggle: toggle }), snapshot.status === 'ready' && !snapshot.writable && _jsx("p", { className: "ppeReadonly", children: t.readonlyHint })] }));
124
+ }
125
+ /**
126
+ * 客户端插件体:在 Plugins 页 bundle 详情页的 keyed 席位(key = 包名)下
127
+ * 注册配置卡。卡片自绑 `configForms.get('dsh-patch-edit-plus')`——form 在
128
+ * 渲染期解析(而非 apply 期固化),宿主晚于客户端半开始服务该 entry 时
129
+ * 也能追上;页面注入的 owner props(`{ view: 'page', form }`)不消费,
130
+ * 以本插件 entry 的作用域为唯一事实来源。
131
+ */
132
+ export function apply(ctx) {
133
+ // 软读:strict ctx proxy 对未声明服务的属性直读会 throw(「1 entry did not
134
+ // activate」家族纪律:按代服务一律软取,绝不进顶层 inject)。
135
+ let configForms;
136
+ try {
137
+ configForms = (ctx.configForms
138
+ ?? (typeof ctx.get === 'function' ? ctx.get('configForms') : undefined));
139
+ }
140
+ catch {
141
+ configForms = undefined;
142
+ }
143
+ // 老宿主不认识 plugins.bundle.config 席位——激活期 throw 会拖死整个
144
+ // client entry,包 safeSeat 降级为「本线无配置卡」。
145
+ try {
146
+ ctx.slots.inject('plugins.bundle.config', () => ctx.slots.register({ name: 'plugins.bundle.config', key: 'dsh-patch-edit-plus' }, () => createElement(PatchStyleCard, { form: configForms?.get?.('dsh-patch-edit-plus') })));
147
+ }
148
+ catch (error) {
149
+ console.warn('[dsh-patch-edit-plus] plugins.bundle.config seat unavailable on this host line:', error);
150
+ }
151
+ }