dsh-output-styles 0.6.26 → 0.8.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,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.1] - 2026-10-18
4
+
5
+ ### Changed
6
+
7
+ - Add a 1280×720 hero and a 960×540, 4-second terminal GIF rendered from the test run; `screenshots.json` is an object array and `capture.json` records the command.
8
+
9
+ ## [Unreleased]
10
+
11
+ ### Changed
12
+
13
+ - Compatibility docs: five READMEs now name `dsh-v0.2.1-rc.2` and the current 156-test count; `dshVersions` records `0.2.1-rc.2`.
14
+
15
+ ## [0.8.0] - 2026-10-18
16
+
17
+ ### Added
18
+
19
+ - **The `/style` picker states when prompt injection is disabled.** When the core `outputStyles` service is active, the projection reports `promptInjection: "disabled"`; the off row now carries the localized reason instead of leaving the user to wonder why a chosen style does nothing (C2).
20
+
21
+ ## [0.7.1] - 2026-10-17
22
+
23
+ ### Fixed
24
+
25
+ - **The client is a `window.__ModuleLoader__.load` factory, not bare ESM.** `tsdown.client.config.ts` emitted `export { apply, inject, name }`; the host executes `lib/client.js` as a classic script, so the `/style` picker never loaded. A post-build `scripts/bundle-client.mjs` wraps the bundle, and `verify-artifacts` now asserts the loader shape instead of dynamic-importing it.
26
+ - Compatibility: `engines.dsh` -> `>=0.2.1-0 <0.3.0`; the existing 0.2.x peer band is unchanged.
27
+
3
28
  All notable changes to this project are documented in this file. The format
4
29
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the
5
30
  project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
@@ -25,6 +50,31 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
25
50
 
26
51
  ## [Unreleased]
27
52
 
53
+ ### Fixed
54
+
55
+ - **Coexistence degradation was invisible to the user.** When a core
56
+ `outputStyles` service is composed, this plugin skips prompt injection and
57
+ keeps only hot-switch / rules / export. That state was announced by a single
58
+ `ctx.logger.info` line — and a logger line never reaches the session
59
+ transcript, so on a degraded composition `/style concise` answered exactly
60
+ `switched to concise`, in the same words as a working standalone run, while
61
+ nothing was injected. Reported by *someone looking at the phone*: the log is
62
+ invisible there, so the honest reading of that reply was "the style is broken".
63
+
64
+ Two user-visible traces now exist, neither of which existed before:
65
+
66
+ - every mutating `/style` reply (`/style <name>` and `/style off`) appends a
67
+ `degraded coexistence mode` note naming the setting that overrides it
68
+ (`respectCoreOutputStyles: false`);
69
+ - the `style` session projection exposes `promptInjection: 'enabled' |
70
+ 'disabled'`, so a client (Web picker, any projection reader) can state the
71
+ fact instead of implying the style is in force.
72
+
73
+ No behaviour changes in standalone mode: the reply text is byte-identical and
74
+ the projection's new field is `'enabled'`. The projection wire value is
75
+ additive — the field is required in the sealed view schema, so hosts and
76
+ clients built against this version agree on it.
77
+
28
78
  ## [0.6.24] - 2026-10-05
29
79
 
30
80
  undefined
package/README-es.md CHANGED
@@ -39,7 +39,7 @@ Este plugin forma parte de la [familia de plugins DSH](https://github.com/PerryL
39
39
 
40
40
  `/style concise` — y a partir de ahora toda respuesta es concisa. `/style off` — de vuelta al valor por defecto del proyecto.
41
41
 
42
- ![Demostración de terminal de dsh-output-styles: dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.png)
42
+ ![Demostración de terminal de dsh-output-styles: dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-hero.png)
43
43
 
44
44
  ![Animated terminal demo of dsh-output-styles](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.gif)
45
45
 
@@ -49,7 +49,7 @@ Este plugin forma parte de la [familia de plugins DSH](https://github.com/PerryL
49
49
 
50
50
  | Surface | Status |
51
51
  |---|---|
52
- | Harness | DeepSeek Harness `dsh-v0.2.1-alpha.1` (adaptado el 2026-09-09): el sobre de sesión conserva su campo ignorable solo para compatibilidad de lectura de logs almacenados - Session.append aún no puede estamparlo, por lo que el comportamiento de la puerta no cambia. Verificado el 2026-09-11 contra el checkout master dsh-v0.1.7-alpha.1 (cadena de puertas completa + smoke de instalación del perfil). |
52
+ | Harness | DeepSeek Harness `dsh-v0.2.1-rc.2` (adaptado el 2026-09-09): el sobre de sesión conserva su campo ignorable solo para compatibilidad de lectura de logs almacenados - Session.append aún no puede estamparlo, por lo que el comportamiento de la puerta no cambia. Verificado el 2026-09-11 contra el checkout master dsh-v0.1.7-alpha.1 (cadena de puertas completa + smoke de instalación del perfil). |
53
53
  | Node | `^22.19.0 || >=24.0.0` |
54
54
  | Platforms | Todas (host + cliente web) |
55
55
  | Model | Cualquiera (inyección en el prompt del sistema) |
@@ -231,6 +231,7 @@ Filtrado contra el ecosistema DSH antes del desarrollo (instantánea 2026-08): n
231
231
 
232
232
  ## Known limitations
233
233
 
234
+ - **Coexistencia con el core.** Si aparece una capacidad `outputStyles` de primera parte, este plugin detecta su servicio `outputStyles` y degrada a la superficie incremental (hot-switch, rules, `/transcript`) dejando la inyección del prompt al core — ver [`docs/COEXISTENCE.md`](docs/COEXISTENCE.md) y las funciones exportadas `detectCoreOutputStyles` / `coexistenceReport`. **El modo degradado se declara donde se ve**: cada respuesta de `/style <estilo>` y `/style off` lleva una nota `degraded coexistence mode`, y la proyección de sesión `style` expone `promptInjection: 'enabled' | 'disabled'`, así que ninguna superficie insinúa que el estilo está en vigor cuando no lo está. (Antes de 0.7.0 el único rastro era una línea `ctx.logger.info`, que nunca llega a la transcripción.)
234
235
  - **Solo conversación principal.** Los estilos se aplican a la conversación principal; las sesiones de subagente conservan sus propios prompts (igual que Claude Code).
235
236
  - **Truncado.** Los cuerpos de estilo más largos que `maxStyleChars` se truncan con un marcador.
236
237
  - **Archivos omitidos.** Un archivo de estilo defectuoso se omite con una advertencia y nunca rompe el profile.
@@ -240,7 +241,7 @@ Filtrado contra el ecosistema DSH antes del desarrollo (instantánea 2026-08): n
240
241
  ```sh
241
242
  pnpm install
242
243
  pnpm run typecheck # ambos proyectos tsc
243
- pnpm test # vitest — 148 tests
244
+ pnpm test # vitest — 156 tests
244
245
  pnpm run verify # typecheck + tests + self-contained (la puerta de prepublishOnly)
245
246
  pnpm run build # artefactos lib/ (bundles host + client)
246
247
  pnpm pack # tarball para dsh plugin add
@@ -276,7 +277,7 @@ Evidencia estática: `dsh-plugin-doctor` K10–K13 dan `pass` en todas las compr
276
277
 
277
278
  ## PerryLink DSH Plugin Family
278
279
 
279
- Este proyecto es uno de los **33 plugins activamente mantenidos** de DeepSeek Harness de [PerryLink](https://github.com/PerryLink): el registro tiene **42**, de los cuales **6** están congelados y **3** retirados; cada uno conserva su fila abajo, con el motivo en la columna Estado. Si este te ayuda, probablemente los demás también:
280
+ Este proyecto es uno de los **34 plugins activamente mantenidos** de DeepSeek Harness de [PerryLink](https://github.com/PerryLink): el registro tiene **42**, de los cuales **5** están congelados y **3** retirados; cada uno conserva su fila abajo, con el motivo en la columna Estado. Si este te ayuda, probablemente los demás también:
280
281
 
281
282
  | Plugin | En una línea | Estado |
282
283
  |---|---|---|
@@ -304,7 +305,7 @@ Este proyecto es uno de los **33 plugins activamente mantenidos** de DeepSeek Ha
304
305
  | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | LSP diagnostics, formatting, completion, code actions and rename over language servers | |
305
306
  | **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | PII masking middleware: anonymize at the model boundary, restore at the display layer | |
306
307
  | **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors | |
307
- | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | 🧊 CONGELADO — ver el README del repositorio |
308
+ | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | |
308
309
  | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. | |
309
310
  | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | Claude Code outputStyles-equivalent runtime style switching | |
310
311
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code-style declarative allow/deny/ask permission rules with audit | |
package/README-hi.md CHANGED
@@ -39,7 +39,7 @@
39
39
 
40
40
  `/style concise` — और अब से हर उत्तर संक्षिप्त। `/style off` — वापस परियोजना के डिफ़ॉल्ट पर।
41
41
 
42
- ![dsh-output-styles का टर्मिनल डेमो: dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.png)
42
+ ![dsh-output-styles का टर्मिनल डेमो: dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-hero.png)
43
43
 
44
44
  ![Animated terminal demo of dsh-output-styles](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.gif)
45
45
 
@@ -49,7 +49,7 @@
49
49
 
50
50
  | Surface | Status |
51
51
  |---|---|
52
- | Harness | DeepSeek Harness `dsh-v0.2.1-alpha.1` (2026-09-09 को अनुकूलित): सत्र लिफ़ाफ़ा अपना ignorable फ़ील्ड केवल संग्रहीत-लॉग पठन संगतता के लिए रखता है - Session.append अभी भी इसे स्टैम्प नहीं कर सकता, इसलिए गेट व्यवहार अपरिवर्तित है। 2026-09-11 को dsh-v0.1.7-alpha.1 master checkout के विरुद्ध सत्यापित (पूर्ण गेट श्रृंखला + प्रोफ़ाइल इंस्टॉल स्मोक)। |
52
+ | Harness | DeepSeek Harness `dsh-v0.2.1-rc.2` (2026-09-09 को अनुकूलित): सत्र लिफ़ाफ़ा अपना ignorable फ़ील्ड केवल संग्रहीत-लॉग पठन संगतता के लिए रखता है - Session.append अभी भी इसे स्टैम्प नहीं कर सकता, इसलिए गेट व्यवहार अपरिवर्तित है। 2026-09-11 को dsh-v0.2.1-rc.2 checkout के विरुद्ध सत्यापित (पूर्ण गेट श्रृंखला + प्रोफ़ाइल इंस्टॉल स्मोक)। |
53
53
  | Node | `^22.19.0 || >=24.0.0` |
54
54
  | Platforms | सभी (host + वेब क्लाइंट) |
55
55
  | Model | कोई भी (सिस्टम-प्रॉम्प्ट इंजेक्शन) |
@@ -231,6 +231,7 @@ flowchart LR
231
231
 
232
232
  ## Known limitations
233
233
 
234
+ - **कोर के साथ सहअस्तित्व।** यदि कोई फ़र्स्ट-पार्टी `outputStyles` क्षमता आती है, तो यह प्लगइन उसकी `outputStyles` सेवा पहचानकर इंक्रीमेंटल सतह (hot-switch, rules, `/transcript`) पर डिग्रेड हो जाता है और prompt इंजेक्शन कोर को छोड़ देता है — देखें [`docs/COEXISTENCE.md`](docs/COEXISTENCE.md) तथा निर्यातित `detectCoreOutputStyles` / `coexistenceReport`. **डिग्रेडेड मोड वहाँ लिखा जाता है जहाँ आप उसे देख सकें**: हर `/style <शैली>` और `/style off` के उत्तर में `degraded coexistence mode` नोट आता है, और `style` सेशन projection `promptInjection: 'enabled' | 'disabled'` देता है, इसलिए कोई सतह शैली को लागू बताकर भ्रम नहीं फैलाती। (0.7.0 से पहले इसका एकमात्र निशान एक `ctx.logger.info` पंक्ति थी, जो सेशन ट्रांसक्रिप्ट तक कभी नहीं पहुँचती।)
234
235
  - **केवल मुख्य वार्तालाप।** शैलियाँ मुख्य वार्तालाप पर लागू होती हैं; उप-एजेंट सत्र अपने प्रॉम्प्ट रखते हैं (Claude Code की तरह)।
235
236
  - **कटाव।** `maxStyleChars` से लंबे शैली मुख्य भाग एक मार्कर से काटे जाते हैं।
236
237
  - **छोड़ी गई फ़ाइलें।** एक ख़राब शैली फ़ाइल चेतावनी से छोड़ दी जाती है और profile को कभी नहीं तोड़ती।
@@ -240,7 +241,7 @@ flowchart LR
240
241
  ```sh
241
242
  pnpm install
242
243
  pnpm run typecheck # दोनों tsc परियोजनाएँ
243
- pnpm test # vitest — 148 tests
244
+ pnpm test # vitest — 156 tests
244
245
  pnpm run verify # typecheck + tests + self-contained (prepublishOnly द्वार)
245
246
  pnpm run build # lib/ कलाकृतियाँ (host + client बंडल)
246
247
  pnpm pack # dsh plugin add के लिए tarball
@@ -276,7 +277,7 @@ pnpm pack # dsh plugin add के लिए tarball
276
277
 
277
278
  ## PerryLink DSH Plugin Family
278
279
 
279
- यह प्रोजेक्ट [PerryLink](https://github.com/PerryLink) के DeepSeek Harness प्लगइन परिवार का हिस्सा है — **33 सक्रिय रूप से अनुरक्षित**, कुल सूची **42** है जिसमें **6 फ़्रोज़न** और **3 सेवानिवृत्त** हैं; हर एक की पंक्ति नीचे बनी रहती है, कारण “स्थिति” कॉलम में है। अगर यह उपयोगी लगे, तो अन्य भी मददगार होंगे:
280
+ यह प्रोजेक्ट [PerryLink](https://github.com/PerryLink) के DeepSeek Harness प्लगइन परिवार का हिस्सा है — **34 सक्रिय रूप से अनुरक्षित**, कुल सूची **42** है जिसमें **5 फ़्रोज़न** और **3 सेवानिवृत्त** हैं; हर एक की पंक्ति नीचे बनी रहती है, कारण “स्थिति” कॉलम में है। अगर यह उपयोगी लगे, तो अन्य भी मददगार होंगे:
280
281
 
281
282
  | Plugin | एक पंक्ति में | स्थिति |
282
283
  |---|---|---|
@@ -304,7 +305,7 @@ pnpm pack # dsh plugin add के लिए tarball
304
305
  | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | LSP diagnostics, formatting, completion, code actions and rename over language servers | |
305
306
  | **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | PII masking middleware: anonymize at the model boundary, restore at the display layer | |
306
307
  | **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors | |
307
- | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | 🧊 फ़्रोज़न — रिपॉज़िटरी README देखें |
308
+ | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | |
308
309
  | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. | |
309
310
  | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | Claude Code outputStyles-equivalent runtime style switching | |
310
311
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code-style declarative allow/deny/ask permission rules with audit | |
package/README-pt.md CHANGED
@@ -39,7 +39,7 @@ Este plugin faz parte da [família de plugins DSH](https://github.com/PerryLink)
39
39
 
40
40
  `/style concise` — e a partir de agora toda resposta é concisa. `/style off` — de volta ao padrão do projeto.
41
41
 
42
- ![Demonstração de terminal do dsh-output-styles: dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.png)
42
+ ![Demonstração de terminal do dsh-output-styles: dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-hero.png)
43
43
 
44
44
  ![Animated terminal demo of dsh-output-styles](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.gif)
45
45
 
@@ -49,7 +49,7 @@ Este plugin faz parte da [família de plugins DSH](https://github.com/PerryLink)
49
49
 
50
50
  | Surface | Status |
51
51
  |---|---|
52
- | Harness | DeepSeek Harness `dsh-v0.2.1-alpha.1` (adaptado em 2026-09-09): o envelope de sessão mantém seu campo ignorable apenas para compatibilidade de leitura de logs armazenados - o Session.append ainda não consegue estampá-lo, então o comportamento da porta não muda. Verificado em 2026-09-11 contra o checkout master dsh-v0.1.7-alpha.1 (cadeia de portas completa + smoke de instalação do perfil). |
52
+ | Harness | DeepSeek Harness `dsh-v0.2.1-rc.2` (adaptado em 2026-09-09): o envelope de sessão mantém seu campo ignorable apenas para compatibilidade de leitura de logs armazenados - o Session.append ainda não consegue estampá-lo, então o comportamento da porta não muda. Verificado em 2026-09-11 contra o checkout master dsh-v0.1.7-alpha.1 (cadeia de portas completa + smoke de instalação do perfil). |
53
53
  | Node | `^22.19.0 || >=24.0.0` |
54
54
  | Platforms | Todas (host + cliente web) |
55
55
  | Model | Qualquer (injeção no prompt do sistema) |
@@ -231,6 +231,7 @@ Filtrado contra o ecossistema DSH antes do desenvolvimento (instantânea 2026-08
231
231
 
232
232
  ## Known limitations
233
233
 
234
+ - **Coexistência com o core.** Se surgir um recurso `outputStyles` de primeira parte, este plugin detecta o serviço `outputStyles` e degrada para a superfície incremental (hot-switch, rules, `/transcript`), deixando a injeção do prompt para o core — ver [`docs/COEXISTENCE.md`](docs/COEXISTENCE.md) e as funções exportadas `detectCoreOutputStyles` / `coexistenceReport`. **O modo degradado é declarado onde dá para ver**: toda resposta de `/style <estilo>` e `/style off` traz uma nota `degraded coexistence mode`, e a projeção de sessão `style` expõe `promptInjection: 'enabled' | 'disabled'`, então nenhuma superfície insinua que o estilo está em vigor quando não está. (Antes de 0.7.0 o único rastro era uma linha `ctx.logger.info`, que nunca chega à transcrição.)
234
235
  - **Somente conversa principal.** Os estilos se aplicam à conversa principal; sessões de subagente mantêm seus próprios prompts (como no Claude Code).
235
236
  - **Truncamento.** Corpos de estilo mais longos que `maxStyleChars` são truncados com um marcador.
236
237
  - **Arquivos omitidos.** Um arquivo de estilo defeituoso é omitido com um aviso e nunca quebra o profile.
@@ -240,7 +241,7 @@ Filtrado contra o ecossistema DSH antes do desenvolvimento (instantânea 2026-08
240
241
  ```sh
241
242
  pnpm install
242
243
  pnpm run typecheck # ambos os projetos tsc
243
- pnpm test # vitest — 148 tests
244
+ pnpm test # vitest — 156 tests
244
245
  pnpm run verify # typecheck + tests + self-contained (a porta de prepublishOnly)
245
246
  pnpm run build # artefatos lib/ (bundles host + client)
246
247
  pnpm pack # tarball para dsh plugin add
@@ -276,7 +277,7 @@ Evidência estática: `dsh-plugin-doctor` K10–K13 retornam `pass` em todas as
276
277
 
277
278
  ## PerryLink DSH Plugin Family
278
279
 
279
- Este projeto é um dos **33 plugins ativamente mantidos** do DeepSeek Harness da [PerryLink](https://github.com/PerryLink): o registro tem **42**, dos quais **6** estão congelados e **3** aposentados; cada um mantém sua linha abaixo, com o motivo na coluna Status. Se este ajudou você, provavelmente os outros também ajudarão:
280
+ Este projeto é um dos **34 plugins ativamente mantidos** do DeepSeek Harness da [PerryLink](https://github.com/PerryLink): o registro tem **42**, dos quais **5** estão congelados e **3** aposentados; cada um mantém sua linha abaixo, com o motivo na coluna Status. Se este ajudou você, provavelmente os outros também ajudarão:
280
281
 
281
282
  | Plugin | Em uma linha | Status |
282
283
  |---|---|---|
@@ -304,7 +305,7 @@ Este projeto é um dos **33 plugins ativamente mantidos** do DeepSeek Harness da
304
305
  | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | LSP diagnostics, formatting, completion, code actions and rename over language servers | |
305
306
  | **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | PII masking middleware: anonymize at the model boundary, restore at the display layer | |
306
307
  | **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors | |
307
- | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | 🧊 CONGELADO — ver o README do repositório |
308
+ | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | |
308
309
  | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. | |
309
310
  | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | Claude Code outputStyles-equivalent runtime style switching | |
310
311
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code-style declarative allow/deny/ask permission rules with audit | |
package/README-zh.md CHANGED
@@ -41,7 +41,7 @@
41
41
 
42
42
  `/style concise` —— 从此每条回复都简洁。`/style off` —— 回到项目默认。
43
43
 
44
- ![dsh-output-styles 终端演示:dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.png)
44
+ ![dsh-output-styles 终端演示:dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-hero.png)
45
45
 
46
46
  ![Animated terminal demo of dsh-output-styles](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.gif)
47
47
 
@@ -51,7 +51,7 @@
51
51
 
52
52
  | Surface | Status |
53
53
  |---|---|
54
- | Harness | DeepSeek Harness `dsh-v0.2.1-alpha.1`(2026-09-09 已适配):会话信封保留 ignorable 字段但仅用于存量日志读取兼容——Session.append 仍无法盖章,门控行为不变。2026-09-11 对照 dsh-v0.1.7-alpha.1 master checkout 已核验(完整门禁链 + profile 安装冒烟)。 |
54
+ | Harness | DeepSeek Harness `dsh-v0.2.1-rc.2`(2026-09-09 已适配):会话信封保留 ignorable 字段但仅用于存量日志读取兼容——Session.append 仍无法盖章,门控行为不变。2026-09-11 对照 dsh-v0.2.1-rc.2 checkout 已核验(完整门禁链 + profile 安装冒烟)。 |
55
55
  | Node | `^22.19.0 || >=24.0.0` |
56
56
  | Platforms | 全部(host + Web 客户端) |
57
57
  | Model | 任意(系统提示注入) |
@@ -233,6 +233,7 @@ flowchart LR
233
233
 
234
234
  ## Known limitations
235
235
 
236
+ - **核心共存。** 若官方推出第一方 `outputStyles` 能力,本插件检测到其 `outputStyles` 服务后降级到增量面(热切换 / rules / `/transcript`),提示词注入交给核心 —— 见 [`docs/COEXISTENCE.md`](docs/COEXISTENCE.md) 与导出的 `detectCoreOutputStyles` / `coexistenceReport`。**降级状态会写在你看得到的地方**:每次 `/style <风格>` 与 `/style off` 的回复都带一条 `degraded coexistence mode` 说明,`style` 会话 projection 也暴露 `promptInjection: 'enabled' | 'disabled'`,任何界面都不会在风格未生效时暗示它已生效。(0.7.0 之前唯一的痕迹是一行 `ctx.logger.info`,它进不了会话转录。)
236
237
  - **仅主会话。** 风格只作用于主会话;子代理会话保留各自提示(与 Claude Code 一致)。
237
238
  - **截断。** 超过 `maxStyleChars` 的风格正文带标记截断。
238
239
  - **跳过坏文件。** 损坏的风格文件带警告跳过,绝不破坏 profile。
@@ -278,7 +279,7 @@ pnpm pack # 供 dsh plugin add 的 tarball
278
279
 
279
280
  ## PerryLink DSH Plugin Family
280
281
 
281
- 本项目是 [PerryLink](https://github.com/PerryLink) 维护的 DeepSeek Harness 插件家族成员:**33 个活跃维护**,名册共 **42** 个,其中 **6 个已冻结**、**3 个已退役**——每一个都在下表保留自己的行,原因见「状态」列。如果它能帮到你,其他的也会:
282
+ 本项目是 [PerryLink](https://github.com/PerryLink) 维护的 DeepSeek Harness 插件家族成员:**34 个活跃维护**,名册共 **42** 个,其中 **5 个已冻结**、**3 个已退役**——每一个都在下表保留自己的行,原因见「状态」列。如果它能帮到你,其他的也会:
282
283
 
283
284
  | Plugin | 一句话 | 状态 |
284
285
  |---|---|---|
@@ -306,7 +307,7 @@ pnpm pack # 供 dsh plugin add 的 tarball
306
307
  | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | LSP diagnostics, formatting, completion, code actions and rename over language servers | |
307
308
  | **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | PII masking middleware: anonymize at the model boundary, restore at the display layer | |
308
309
  | **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors | |
309
- | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | 🧊 已冻结 — 见仓库 README |
310
+ | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | |
310
311
  | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. | |
311
312
  | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | Claude Code outputStyles-equivalent runtime style switching | |
312
313
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code-style declarative allow/deny/ask permission rules with audit | |
package/README.md CHANGED
@@ -42,7 +42,7 @@
42
42
 
43
43
  `/style concise` — and every reply from now on is terse. `/style off` — back to the project default.
44
44
 
45
- ![Terminal demo of dsh-output-styles: dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.png)
45
+ ![Terminal demo of dsh-output-styles: dsh-output-styles — /style lists, then switches at runtime](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-hero.png)
46
46
 
47
47
  ![Animated terminal demo of dsh-output-styles](https://raw.githubusercontent.com/PerryLink/dsh-output-styles/main/docs/assets/dsh-output-styles-demo.gif)
48
48
 
@@ -52,7 +52,7 @@
52
52
 
53
53
  | Surface | Status |
54
54
  |---|---|
55
- | Harness | DeepSeek Harness `dsh-v0.2.1-alpha.1` (adapted 2026-09-09): the session envelope keeps its ignorable field for stored-log read compatibility only - Session.append still cannot stamp it, so audit-gate behavior is unchanged. Verified 2026-09-11 against the dsh-v0.1.7-alpha.1 master checkout (full gate chain + profile install smoke). |
55
+ | Harness | DeepSeek Harness `dsh-v0.2.1-rc.2` (adapted 2026-09-09): the session envelope keeps its ignorable field for stored-log read compatibility only - Session.append still cannot stamp it, so audit-gate behavior is unchanged. Verified 2026-09-11 against the dsh-v0.2.1-rc.2 checkout (full gate chain + profile install smoke). |
56
56
  | Node | `^22.19.0 || >=24.0.0` |
57
57
  | Platforms | All (host + web client) |
58
58
  | Model | Any (system-prompt injection) |
@@ -240,7 +240,7 @@ Screened against the DSH ecosystem before development (2026-08 snapshot): no `st
240
240
 
241
241
  ## Known limitations
242
242
 
243
- - **Core coexistence.** If a first-party `outputStyles` capability lands, this plugin detects its `outputStyles` service and degrades to the incremental surface (hot-switch, rules, `/transcript`) while leaving prompt injection to the core — see [`docs/COEXISTENCE.md`](docs/COEXISTENCE.md) and the exported `detectCoreOutputStyles` / `coexistenceReport` functions.
243
+ - **Core coexistence.** If a first-party `outputStyles` capability lands, this plugin detects its `outputStyles` service and degrades to the incremental surface (hot-switch, rules, `/transcript`) while leaving prompt injection to the core — see [`docs/COEXISTENCE.md`](docs/COEXISTENCE.md) and the exported `detectCoreOutputStyles` / `coexistenceReport` functions. **Degraded mode is stated where you can see it**: every `/style` switch and `/style off` reply carries a `degraded coexistence mode` note, and the `style` session projection exposes `promptInjection: 'enabled' | 'disabled'`, so no surface implies the style is in force when it is not. (Before 0.7.0 the only trace was a `ctx.logger.info` line, which never reaches the session transcript.)
244
244
  - **Main conversation only.** Styles apply to the main conversation; subagent sessions keep their own prompts (matching Claude Code).
245
245
  - **Truncation.** Style bodies longer than `maxStyleChars` are truncated with a marker.
246
246
  - **Skipped style files.** A bad style file is skipped with a warning and never breaks the profile.
@@ -250,7 +250,7 @@ Screened against the DSH ecosystem before development (2026-08 snapshot): no `st
250
250
  ```sh
251
251
  pnpm install
252
252
  pnpm run typecheck # both tsc projects
253
- pnpm test # vitest — 148 tests
253
+ pnpm test # vitest — 156 tests
254
254
  pnpm run verify # typecheck + tests + self-contained (the prepublishOnly gate)
255
255
  pnpm run build # lib/ artifacts (host + client bundles)
256
256
  pnpm pack # tarball for dsh plugin add
@@ -286,7 +286,7 @@ Static evidence: `dsh-plugin-doctor` K10–K13 report `pass` for every check on
286
286
 
287
287
  ## PerryLink DSH Plugin Family
288
288
 
289
- This project is one of the **33 actively maintained** DeepSeek Harness plugins from [PerryLink](https://github.com/PerryLink) — the roster is **42**, of which **6** are frozen and **3** retired; every one keeps its row below, with the reason in the Status column. If this one helps you, the others likely will too:
289
+ This project is one of the **34 actively maintained** DeepSeek Harness plugins from [PerryLink](https://github.com/PerryLink) — the roster is **42**, of which **5** are frozen and **3** retired; every one keeps its row below, with the reason in the Status column. If this one helps you, the others likely will too:
290
290
 
291
291
  | Plugin | One-liner | Status |
292
292
  |---|---|---|
@@ -314,7 +314,7 @@ This project is one of the **33 actively maintained** DeepSeek Harness plugins f
314
314
  | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | LSP diagnostics, formatting, completion, code actions and rename over language servers | |
315
315
  | **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | PII masking middleware: anonymize at the model boundary, restore at the display layer | |
316
316
  | **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors | |
317
- | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | 🧊 FROZEN — see the repo README |
317
+ | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | |
318
318
  | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. | |
319
319
  | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | Claude Code outputStyles-equivalent runtime style switching | |
320
320
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code-style declarative allow/deny/ask permission rules with audit | |
@@ -60,3 +60,21 @@ In `degraded` mode the plugin still contributes:
60
60
 
61
61
  Only the two prompt-injection registrations (the prompt section and the
62
62
  `system-prompt/assemble` waterfall) are skipped.
63
+
64
+ ## How degraded mode reaches the user
65
+
66
+ `ctx.logger.info` is not a user-visible channel: the plugin log never reaches the
67
+ session transcript, and on a phone the log is not reachable at all. Until
68
+ 0.7.0 the only trace of degraded mode was that one logger line, so a degraded
69
+ `/style concise` answered `switched to concise` — the same reply as a working
70
+ standalone run — while the style was not injected. That is why degraded mode is
71
+ stated on two surfaces that are visible:
72
+
73
+ - **Command reply** — `/style <name>` and `/style off` append a
74
+ `degraded coexistence mode` note that names the override
75
+ (`respectCoreOutputStyles: false`). Standalone replies are unchanged.
76
+ - **Session projection** — the `style` projection's wire value carries
77
+ `promptInjection: 'enabled' | 'disabled'`, so the Web picker and any other
78
+ projection reader can render the state instead of implying the style is in
79
+ force. The field is part of the sealed `StyleSelectionView` schema, so a
80
+ client never guesses it.
package/lib/client.js CHANGED
@@ -1,102 +1,115 @@
1
- //#region lib/types/client/locales.js
2
- /**
3
- * Simplified Chinese dictionary (the key-set source of truth).
4
- *
5
- * Only `zh` and `en` are shipped: the DSH Web locale system (dsh-client-locale
6
- * rc.6) exposes exactly the `zh`/`en` locale pair in its settings row, so
7
- * further dictionaries would be dead weight the framework can never select.
8
- * When a future harness release ships more locales, extend this pair.
9
- */
10
- const zh = {
11
- "option.off": "关闭(默认)",
12
- "option.offDetail": "恢复项目默认输出风格"
13
- };
14
- /** English dictionary, checked complete against the zh key set. */
15
- const en = {
16
- "option.off": "Off (default)",
17
- "option.offDetail": "Restore the project default output style"
18
- };
19
- //#endregion
20
- //#region lib/types/client/index.js
21
- /**
22
- * Browser half of `dsh-output-styles`: a popup picker decorating the HOST
23
- * `/style` command. The picker reads the `style` session projection
24
- * (`{ options, currentValue }`), which the host plugin keeps fresh, and
25
- * submits the completed `/style <name>` / `/style off` line back through the
26
- * command Remote — so every switch keeps the host's durable command
27
- * lifecycle (`command/run`/`command/done`) and the projection stays the
28
- * single displayed fact.
29
- * @module dsh-output-styles/client
30
- */
31
- /** Client plugin name; keep stable after publishing. */
32
- const name = "dsh-output-styles-client";
33
- /** Required client services: the command surface, the sessions face, the command Remote, and locale. */
34
- const inject = [
35
- "commandUi",
36
- "locale",
37
- "remote",
38
- "sessions"
39
- ];
40
- /** Dictionary namespace owned by this plugin. */
41
- const NS = "style";
42
- /** The picker row that restores the project default; stable, never a style name. */
43
- const OFF_ID = "off";
44
- /** Flatten the projection into picker rows: the off row first, then one row per style. */
45
- function optionsOf(view, t) {
46
- const rows = [{
47
- id: OFF_ID,
48
- label: t("option.off"),
49
- detail: t("option.offDetail"),
50
- active: view.currentValue === null
51
- }];
52
- for (const option of view.options) rows.push({
53
- id: option.value,
54
- label: option.name,
55
- detail: option.whenToUse !== void 0 ? `${option.description} · ${option.whenToUse}` : option.description,
56
- active: view.currentValue === option.value
57
- });
58
- return rows;
59
- }
60
- /**
61
- * Client plugin body: register the `style` dictionaries and decorate the
62
- * host `/style` command's bare invocation with the projection-backed picker.
63
- * @param ctx - client root context.
64
- */
65
- function apply(ctx) {
66
- ctx.effect(() => ctx.locale.register(NS, {
67
- zh,
68
- en
69
- }), "dsh-output-styles: style dictionaries");
70
- const t = ctx.locale.bind(NS);
71
- ctx.inject([
72
- "commandUi",
73
- "remote",
74
- "sessions"
75
- ], (scope) => {
76
- const commandUi = scope.get("commandUi");
77
- const sessions = scope.get("sessions");
78
- const remote = scope.remote;
79
- scope.effect(() => commandUi.decorate({
80
- name: "style",
81
- available: () => true,
82
- ui: {
83
- kind: "popupSelect",
84
- options: async (session, signal) => {
85
- if (signal.aborted) return [];
86
- const view = sessions.binding(session.sessionId)?.session.projections.faceOf("style").getSnapshot();
87
- if (view === void 0) return [];
88
- if (signal.aborted) return [];
89
- return optionsOf(view, t);
90
- },
91
- onSelect: async (option, session) => {
92
- const line = option.id === OFF_ID ? "/style off" : `/style ${option.id}`;
93
- const result = await remote.commands.execute(session.sessionId, line, []);
94
- if (!result.ok) throw new Error(`command.execute failed: ${result.error.code}: ${result.error.message}`);
95
- if (result.value === void 0) throw new Error(`unknown or malformed command: ${line}`);
96
- }
97
- }
98
- }), "dsh-output-styles: /style picker");
99
- });
100
- }
101
- //#endregion
102
- export { apply, inject, name };
1
+ window.__ModuleLoader__.load({
2
+ id: "dsh-output-styles",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ //#region lib/types/client/locales.js
8
+ /**
9
+ * Simplified Chinese dictionary (the key-set source of truth).
10
+ *
11
+ * Only `zh` and `en` are shipped: the DSH Web locale system (dsh-client-locale
12
+ * rc.6) exposes exactly the `zh`/`en` locale pair in its settings row, so
13
+ * further dictionaries would be dead weight the framework can never select.
14
+ * When a future harness release ships more locales, extend this pair.
15
+ */
16
+ const zh = {
17
+ "option.off": "关闭(默认)",
18
+ "option.offDetail": "恢复项目默认输出风格",
19
+ "option.injectionDisabled": "核心 outputStyles 已接管,本插件的提示词注入不可用"
20
+ };
21
+ /** English dictionary, checked complete against the zh key set. */
22
+ const en = {
23
+ "option.off": "Off (default)",
24
+ "option.offDetail": "Restore the project default output style",
25
+ "option.injectionDisabled": "Core outputStyles is active; this plugin's prompt injection is disabled"
26
+ };
27
+ //#endregion
28
+ //#region lib/types/client/index.js
29
+ /**
30
+ * Browser half of `dsh-output-styles`: a popup picker decorating the HOST
31
+ * `/style` command. The picker reads the `style` session projection
32
+ * (`{ options, currentValue }`), which the host plugin keeps fresh, and
33
+ * submits the completed `/style <name>` / `/style off` line back through the
34
+ * command Remote — so every switch keeps the host's durable command
35
+ * lifecycle (`command/run`/`command/done`) and the projection stays the
36
+ * single displayed fact.
37
+ * @module dsh-output-styles/client
38
+ */
39
+ /** Client plugin name; keep stable after publishing. */
40
+ const name = "dsh-output-styles-client";
41
+ /** Required client services: the command surface, the sessions face, the command Remote, and locale. */
42
+ const inject = [
43
+ "commandUi",
44
+ "locale",
45
+ "remote",
46
+ "sessions"
47
+ ];
48
+ /** Dictionary namespace owned by this plugin. */
49
+ const NS = "style";
50
+ /** The picker row that restores the project default; stable, never a style name. */
51
+ const OFF_ID = "off";
52
+ /** Flatten the projection into picker rows: the off row first, then one row per style. */
53
+ function optionsOf(view, t) {
54
+ const rows = [{
55
+ id: OFF_ID,
56
+ label: t("option.off"),
57
+ detail: view.promptInjection === "disabled" ? `${t("option.offDetail")} · ${t("option.injectionDisabled")}` : t("option.offDetail"),
58
+ active: view.currentValue === null
59
+ }];
60
+ for (const option of view.options) rows.push({
61
+ id: option.value,
62
+ label: option.name,
63
+ detail: option.whenToUse !== void 0 ? `${option.description} · ${option.whenToUse}` : option.description,
64
+ active: view.currentValue === option.value
65
+ });
66
+ return rows;
67
+ }
68
+ /**
69
+ * Client plugin body: register the `style` dictionaries and decorate the
70
+ * host `/style` command's bare invocation with the projection-backed picker.
71
+ * @param ctx - client root context.
72
+ */
73
+ function apply(ctx) {
74
+ ctx.effect(() => ctx.locale.register(NS, {
75
+ zh,
76
+ en
77
+ }), "dsh-output-styles: style dictionaries");
78
+ const t = ctx.locale.bind(NS);
79
+ ctx.inject([
80
+ "commandUi",
81
+ "remote",
82
+ "sessions"
83
+ ], (scope) => {
84
+ const commandUi = scope.get("commandUi");
85
+ const sessions = scope.get("sessions");
86
+ const remote = scope.remote;
87
+ scope.effect(() => commandUi.decorate({
88
+ name: "style",
89
+ available: () => true,
90
+ ui: {
91
+ kind: "popupSelect",
92
+ options: async (session, signal) => {
93
+ if (signal.aborted) return [];
94
+ const view = sessions.binding(session.sessionId)?.session.projections.faceOf("style").getSnapshot();
95
+ if (view === void 0) return [];
96
+ if (signal.aborted) return [];
97
+ return optionsOf(view, t);
98
+ },
99
+ onSelect: async (option, session) => {
100
+ const line = option.id === OFF_ID ? "/style off" : `/style ${option.id}`;
101
+ const result = await remote.commands.execute(session.sessionId, line, []);
102
+ if (!result.ok) throw new Error(`command.execute failed: ${result.error.code}: ${result.error.message}`);
103
+ if (result.value === void 0) throw new Error(`unknown or malformed command: ${line}`);
104
+ }
105
+ }
106
+ }), "dsh-output-styles: /style picker");
107
+ });
108
+ }
109
+ //#endregion
110
+ exports.apply = apply;
111
+ exports.inject = inject;
112
+ exports.name = name;
113
+ return module.exports;
114
+ }
115
+ });
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as STYLE_SOURCE_KIND, b as styleSelectionViewSchema, c as loadStyleLibrary, d as STYLE_COMMAND, f as applyStyleEvent, g as STYLE_SOURCE, h as OUTPUT_STYLE_DOMAIN, i as installInvariant, l as truncateStyle, m as OFF, o as STYLE_NAME_RE, p as parseStyleInput, s as isValidStyleName, t as PACKAGE_NAME, u as EMPTY_STYLE_STATE, v as styleFoldStateSchema, y as styleSelectionSchema } from "./invariant--N6fzwyV.js";
1
+ import { _ as STYLE_SOURCE_KIND, b as styleSelectionViewSchema, c as loadStyleLibrary, d as STYLE_COMMAND, f as applyStyleEvent, g as STYLE_SOURCE, h as OUTPUT_STYLE_DOMAIN, i as installInvariant, l as truncateStyle, m as OFF, o as STYLE_NAME_RE, p as parseStyleInput, s as isValidStyleName, t as PACKAGE_NAME, u as EMPTY_STYLE_STATE, v as styleFoldStateSchema, y as styleSelectionSchema } from "./invariant-J1Havru2.js";
2
2
  import z from "@deepseek-ai/schemastery";
3
3
  import { createVolatile } from "@deepseek-ai/cosmokit";
4
4
  import { resolve } from "node:path";
@@ -752,7 +752,7 @@ var OutputStyleRuntime = class {
752
752
  }
753
753
  };
754
754
  /** Build the `style` projection's wire value for one folded state. */
755
- function viewStyleSelection(runtime, state) {
755
+ function viewStyleSelection(runtime, state, promptInjection) {
756
756
  const currentValue = state.current !== null && runtime.styles.has(state.current) ? state.current : null;
757
757
  return {
758
758
  options: [...runtime.styles.entries()].map(([value, style]) => ({
@@ -761,7 +761,8 @@ function viewStyleSelection(runtime, state) {
761
761
  description: style.description,
762
762
  ...style.whenToUse === void 0 ? {} : { whenToUse: style.whenToUse }
763
763
  })),
764
- currentValue
764
+ currentValue,
765
+ promptInjection
765
766
  };
766
767
  }
767
768
  /**
@@ -781,6 +782,17 @@ async function apply(ctx, config) {
781
782
  const resolved = resolveConfig(live, DEFAULT_STYLES_DIR);
782
783
  const coreActive = resolved.respectCoreOutputStyles && detectCoreOutputStyles(ctx);
783
784
  if (coreActive) ctx.logger.info("dsh-output-styles: core outputStyles detected — degrading to hot-switch + rules + export (no prompt injection)");
785
+ /**
786
+ * The coexistence note appended to every mutating `/style` reply.
787
+ *
788
+ * A logger line is not a user-visible channel: `ctx.logger.info` never
789
+ * reaches the session transcript, so on a degraded composition the user saw
790
+ * exactly `switched to concise` and nothing else — a reply identical to the
791
+ * standalone one, while the style was no longer injected into the prompt.
792
+ * The command result *is* the user's channel, so the fact is stated there.
793
+ * @returns the note line, or '' in standalone mode.
794
+ */
795
+ const degradedNote = () => coreActive ? "\nnote: this session is in degraded coexistence mode — a core `outputStyles` capability is composed, so this plugin does not inject the style into the prompt; the selection still drives hot-switch, rules and /transcript. Set `respectCoreOutputStyles: false` to force this plugin's injection." : "";
784
796
  const styles = loadStyleLibrary(resolved.stylesDirs, { compatJson: resolved.compatJson }, (message) => {
785
797
  ctx.logger.warn(`dsh-output-styles: ${message}`);
786
798
  });
@@ -886,7 +898,7 @@ async function apply(ctx, config) {
886
898
  const forced = runtime.forcedName;
887
899
  return {
888
900
  kind: "success",
889
- text: forced === void 0 ? "output style off" : `output style off (style "${forced}" remains in force)`
901
+ text: (forced === void 0 ? "output style off" : `output style off (style "${forced}" remains in force)`) + degradedNote()
890
902
  };
891
903
  }
892
904
  if (runtime.get(input.name) === void 0) return {
@@ -896,7 +908,7 @@ async function apply(ctx, config) {
896
908
  await runtime.select(agent.session, input.name);
897
909
  return {
898
910
  kind: "success",
899
- text: `switched to ${input.name}`
911
+ text: `switched to ${input.name}${degradedNote()}`
900
912
  };
901
913
  }
902
914
  });
@@ -909,7 +921,7 @@ async function apply(ctx, config) {
909
921
  apply: applyStyleEvent,
910
922
  wire: {
911
923
  viewSchema: styleSelectionViewSchema,
912
- view: (state) => viewStyleSelection(runtime, state)
924
+ view: (state) => viewStyleSelection(runtime, state, coreActive ? "disabled" : "enabled")
913
925
  },
914
926
  stateVersion: 2
915
927
  });
@@ -59,7 +59,8 @@ const styleSelectionViewSchema = z.object({
59
59
  description: z.string().min(1),
60
60
  whenToUse: z.string().min(1).optional()
61
61
  })),
62
- currentValue: z.string().min(1).nullable()
62
+ currentValue: z.string().min(1).nullable(),
63
+ promptInjection: z.union([z.literal("enabled"), z.literal("disabled")])
63
64
  });
64
65
  /**
65
66
  * Validates the `style` projection's persisted fold state before it seeds a
package/lib/invariant.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as name, i as installInvariant, n as apply, r as inject, t as PACKAGE_NAME } from "./invariant--N6fzwyV.js";
1
+ import { a as name, i as installInvariant, n as apply, r as inject, t as PACKAGE_NAME } from "./invariant-J1Havru2.js";
2
2
  export { PACKAGE_NAME, apply, inject, installInvariant, name };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAMnE,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEpD,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,+BAA+B;QAC/B,KAAK,EAAE,QAAQ,CAAA;KAChB;CACF;AAED,wDAAwD;AACxD,eAAO,MAAM,IAAI,6BAA6B,CAAA;AAE9C,wGAAwG;AACxG,eAAO,MAAM,MAAM,UAAgD,CAAA;AA4DnE;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAyC9C;AAED,YAAY,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAMnE,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEpD,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,+BAA+B;QAC/B,KAAK,EAAE,QAAQ,CAAA;KAChB;CACF;AAED,wDAAwD;AACxD,eAAO,MAAM,IAAI,6BAA6B,CAAA;AAE9C,wGAAwG;AACxG,eAAO,MAAM,MAAM,UAAgD,CAAA;AA8DnE;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAyC9C;AAED,YAAY,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA"}
@@ -9,6 +9,7 @@
9
9
  export declare const zh: {
10
10
  'option.off': string;
11
11
  'option.offDetail': string;
12
+ 'option.injectionDisabled': string;
12
13
  };
13
14
  /** The style picker namespace key union. */
14
15
  export type StyleKey = keyof typeof zh;
@@ -16,5 +17,6 @@ export type StyleKey = keyof typeof zh;
16
17
  export declare const en: {
17
18
  'option.off': string;
18
19
  'option.offDetail': string;
20
+ 'option.injectionDisabled': string;
19
21
  };
20
22
  //# sourceMappingURL=locales.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,EAAE;;;CAGmB,CAAA;AAElC,4CAA4C;AAC5C,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,EAAE,CAAA;AAEtC,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;CAGqB,CAAA"}
1
+ {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,EAAE;;;;CAImB,CAAA;AAElC,4CAA4C;AAC5C,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,EAAE,CAAA;AAEtC,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;CAIqB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,OAAO,EAAgB,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAKhF,OAAO,KAAK,EAAE,MAAM,EAA2B,MAAM,iCAAiC,CAAA;AAMtF,OAAO,EAAkC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAGzE,OAAO,EAAmC,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEtF,OAAO,EAAE,mBAAmB,EAAgE,KAAK,cAAc,EAA2B,MAAM,YAAY,CAAA;AAqB5J,kGAAkG;AAClG,eAAO,MAAM,kBAAkB,QAAwD,CAAA;AAEvF,mFAAmF;AACnF,eAAO,MAAM,kBAAkB,2BAA2B,CAAA;AAK1D;;;;;;GAMG;AACH,qBAAa,kBAAkB;IAqB3B,OAAO,CAAC,QAAQ,CAAC,MAAM;IApBzB,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,WAAW,CAAyB;IAE5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoC;IAC9D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,cAAc,CAAc;IAEpC,2DAA2D;IAC3D,IAAI,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAE7C;IAED;;;;OAIG;gBAEgB,MAAM,EAAE,MAAM,CAAC,OAAO,mBAAmB,CAAC,EAC3D,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EACxC,OAAO,EAAE;QACP,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;QAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;QAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;KAClC;IAWH,qDAAqD;IACrD,IAAI,KAAK,IAAI,SAAS,MAAM,EAAE,CAE7B;IAED,4EAA4E;IAC5E,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAEnC;IAED;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI;IAKtD;;;;OAIG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,MAAM,GAAG,IAAI;IAI1C;;;;OAIG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI1C;;;;OAIG;IACH,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,cAAc,GAAG,SAAS;IAI9D;;;;;;;OAOG;IACH,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS;IAO7D;;;;OAIG;IACH,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM;IAIzC;;;;;;;OAOG;IACH,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM;IAOxC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM;IAUtC;;;;;OAKG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAItC;;;;;;OAMG;IACG,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO3D;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAoBD;;;;;;;;;GASG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuUvE;AAED,uCAAuC;AACvC,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,UAAU,GAAG,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAErB,wGAAwG;AACxG,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,WAAW,CA0C/D;AAED,gGAAgG;AAChG,KAAK,eAAe,GAAG,cAAc,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,CAAA;AAEhF,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACtF,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC9D;AAED,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;CACvH;AAED,6FAA6F;AAC7F,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,sBAAsB,GAAG,iBAAiB,GAAG,oBAAoB,CAAA;AAEtH,0FAA0F;AAC1F,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,gBAAgB,GAAG,SAAS,EAChC,QAAQ,EAAE,cAAc,GAAG,SAAS,EACpC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAoD3B"}
@@ -81,6 +81,14 @@ export interface StyleSelectionView {
81
81
  options: StyleOption[];
82
82
  /** Current selection, or null when the session has none. */
83
83
  currentValue: string | null;
84
+ /**
85
+ * Whether this plugin injects the style section into the system prompt.
86
+ * `disabled` is the coexistence-degraded state: a core `outputStyles`
87
+ * capability owns injection, and the selection still drives hot-switch,
88
+ * rules and `/transcript`. Clients and session projections read this to
89
+ * state the fact instead of implying the style is in force.
90
+ */
91
+ promptInjection: 'enabled' | 'disabled';
84
92
  }
85
93
  /** Validates the `style` projection's wire payload before it leaves the host. */
86
94
  export declare const styleSelectionViewSchema: zod.ZodObject<{
@@ -91,6 +99,7 @@ export declare const styleSelectionViewSchema: zod.ZodObject<{
91
99
  whenToUse: zod.ZodOptional<zod.ZodString>;
92
100
  }, zod.core.$strip>>;
93
101
  currentValue: zod.ZodNullable<zod.ZodString>;
102
+ promptInjection: zod.ZodUnion<readonly [zod.ZodLiteral<"enabled">, zod.ZodLiteral<"disabled">]>;
94
103
  }, zod.core.$strip>;
95
104
  /**
96
105
  * Validates the `style` projection's persisted fold state before it seeds a
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE,MAAM,KAAK,CAAA;AAE9B,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,qEAAqE;AACrE,eAAO,MAAM,GAAG,QAAQ,CAAA;AAExB,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,sBAAsB,CAAA;AAEpD;;;;;GAKG;AACH,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB,mBAAmB,EAAE;YAAE,IAAI,EAAE,mBAAmB,CAAA;SAAE,GAAG,aAAa,CAAA;KACnE;CACF;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY;;;CAAoE,CAAA;AAE7F,gDAAgD;AAChD,eAAO,MAAM,oBAAoB;;;;;;mBAU/B,CAAA;AAEF,kDAAkD;AAClD,MAAM,WAAW,cAAe,SAAQ,GAAG,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC;CAAG;AAEjF;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;CAM9B,CAAA;AAEF,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAA;IACnB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAED,0DAA0D;AAC1D,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,iFAAiF;AACjF,eAAO,MAAM,wBAAwB;;;;;;;;mBAQnC,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;mBAS/B,CAAA;AAEF,OAAO,QAAQ,2CAA2C,CAAC;IACzD,UAAU,oBAAoB;QAC5B,KAAK,EAAE,kBAAkB,CAAA;KAC1B;IACD,UAAU,yBAAyB;QACjC,KAAK,EAAE,cAAc,CAAA;KACtB;CACF;AAED,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI,CAAA;IAC9C,wFAAwF;IACxF,IAAI,IAAI,cAAc,EAAE,CAAA;IACxB,4DAA4D;IAC5D,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,EAAE,CAAA;IACjD,gGAAgG;IAChG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;CACxE;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,2EAA2E;QAC3E,eAAe,EAAE,sBAAsB,CAAA;KACxC;IACD,UAAU,MAAM;QACd;;;;WAIG;QACH,sBAAsB,CAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,aAAa,CAAA;SAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,aAAa,CAAA;SAAE,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;KACrL;CACF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-output-styles",
3
- "version": "0.6.26",
3
+ "version": "0.8.1",
4
4
  "description": "Claude Code outputStyles-equivalent runtime output-style switching for DeepSeek Harness",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -20,7 +20,7 @@
20
20
  "packageManager": "pnpm@11.7.0",
21
21
  "engines": {
22
22
  "node": "^22.19.0 || >=24.0.0",
23
- "dsh": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0 || >=0.2.0-0 <0.3.0 || >=0.2.1-0 <0.3.0"
23
+ "dsh": ">=0.2.1-0 <0.3.0"
24
24
  },
25
25
  "main": "lib/index.js",
26
26
  "types": "lib/types/index.d.ts",
@@ -108,8 +108,15 @@
108
108
  "settings:read"
109
109
  ],
110
110
  "compatibility": {
111
- "dshVersions": ["0.1.2-rc.1","0.1.5-rc.2","0.1.7-alpha.2","0.1.7-rc.1", "0.1.7-rc.2",
112
- "0.2.1-alpha.1"]
111
+ "dshVersions": [
112
+ "0.1.2-rc.1",
113
+ "0.1.5-rc.2",
114
+ "0.1.7-alpha.2",
115
+ "0.1.7-rc.1",
116
+ "0.1.7-rc.2",
117
+ "0.2.1-alpha.1",
118
+ "0.2.1-rc.2"
119
+ ]
113
120
  },
114
121
  "capability": {
115
122
  "id": "style-command",
@@ -229,7 +236,7 @@
229
236
  "vitest": "^4.1.8"
230
237
  },
231
238
  "scripts": {
232
- "build": "node -e \"require('node:fs').rmSync('lib',{recursive:true,force:true})\" && tsc -p tsconfig.json --noEmitOnError --pretty false && tsdown && tsdown -c tsdown.client.config.ts && node scripts/fix-dts.mjs",
239
+ "build": "node -e \"require('node:fs').rmSync('lib',{recursive:true,force:true})\" && tsc -p tsconfig.json --noEmitOnError --pretty false && tsdown && tsdown -c tsdown.client.config.ts && node scripts/fix-dts.mjs && node scripts/bundle-client.mjs",
233
240
  "test": "vitest run",
234
241
  "test:coverage": "vitest run --coverage",
235
242
  "lint": "oxlint",
@@ -72,7 +72,9 @@ function optionsOf(view: StyleSelectionView, t: TranslateNS<typeof NS>): SelectO
72
72
  const rows: SelectOption[] = [{
73
73
  id: OFF_ID,
74
74
  label: t('option.off'),
75
- detail: t('option.offDetail'),
75
+ detail: view.promptInjection === 'disabled'
76
+ ? `${t('option.offDetail')} · ${t('option.injectionDisabled')}`
77
+ : t('option.offDetail'),
76
78
  active: view.currentValue === null,
77
79
  }]
78
80
  for (const option of view.options) {
@@ -9,6 +9,7 @@
9
9
  export const zh = {
10
10
  'option.off': '关闭(默认)',
11
11
  'option.offDetail': '恢复项目默认输出风格',
12
+ 'option.injectionDisabled': '核心 outputStyles 已接管,本插件的提示词注入不可用',
12
13
  } satisfies Record<string, string>
13
14
 
14
15
  /** The style picker namespace key union. */
@@ -18,4 +19,5 @@ export type StyleKey = keyof typeof zh
18
19
  export const en = {
19
20
  'option.off': 'Off (default)',
20
21
  'option.offDetail': 'Restore the project default output style',
22
+ 'option.injectionDisabled': "Core outputStyles is active; this plugin's prompt injection is disabled",
21
23
  } satisfies Record<StyleKey, string>
package/src/runtime.ts CHANGED
@@ -247,7 +247,7 @@ export class OutputStyleRuntime {
247
247
  }
248
248
 
249
249
  /** Build the `style` projection's wire value for one folded state. */
250
- function viewStyleSelection(runtime: OutputStyleRuntime, state: StyleFoldState): StyleSelectionView {
250
+ function viewStyleSelection(runtime: OutputStyleRuntime, state: StyleFoldState, promptInjection: 'enabled' | 'disabled'): StyleSelectionView {
251
251
  // The library-membership guard covers a settled selection whose style later
252
252
  // left the library: the view degrades to "no selection" until the session
253
253
  // switches again.
@@ -260,6 +260,7 @@ function viewStyleSelection(runtime: OutputStyleRuntime, state: StyleFoldState):
260
260
  ...style.whenToUse === undefined ? {} : { whenToUse: style.whenToUse },
261
261
  })),
262
262
  currentValue,
263
+ promptInjection,
263
264
  }
264
265
  }
265
266
 
@@ -302,6 +303,20 @@ export async function apply(ctx: Context, config: Config): Promise<void> {
302
303
  if (coreActive) {
303
304
  ctx.logger.info('dsh-output-styles: core outputStyles detected — degrading to hot-switch + rules + export (no prompt injection)')
304
305
  }
306
+ /**
307
+ * The coexistence note appended to every mutating `/style` reply.
308
+ *
309
+ * A logger line is not a user-visible channel: `ctx.logger.info` never
310
+ * reaches the session transcript, so on a degraded composition the user saw
311
+ * exactly `switched to concise` and nothing else — a reply identical to the
312
+ * standalone one, while the style was no longer injected into the prompt.
313
+ * The command result *is* the user's channel, so the fact is stated there.
314
+ * @returns the note line, or '' in standalone mode.
315
+ */
316
+ const degradedNote = (): string => coreActive
317
+ ? '\nnote: this session is in degraded coexistence mode — a core `outputStyles` capability is composed, so this plugin does not inject the style into the prompt; the selection still drives hot-switch, rules and /transcript.'
318
+ + ' Set `respectCoreOutputStyles: false` to force this plugin\'s injection.'
319
+ : ''
305
320
  const styles = loadStyleLibrary(
306
321
  resolved.stylesDirs,
307
322
  { compatJson: resolved.compatJson },
@@ -451,16 +466,16 @@ export async function apply(ctx: Context, config: Config): Promise<void> {
451
466
  const forced = runtime.forcedName
452
467
  return {
453
468
  kind: 'success',
454
- text: forced === undefined
469
+ text: (forced === undefined
455
470
  ? 'output style off'
456
- : `output style off (style "${forced}" remains in force)`,
471
+ : `output style off (style "${forced}" remains in force)`) + degradedNote(),
457
472
  }
458
473
  }
459
474
  if (runtime.get(input.name) === undefined) {
460
475
  return { kind: 'error', text: runtime.unknownStyleLine(input.name) }
461
476
  }
462
477
  await runtime.select(agent.session, input.name)
463
- return { kind: 'success', text: `switched to ${input.name}` }
478
+ return { kind: 'success', text: `switched to ${input.name}${degradedNote()}` }
464
479
  },
465
480
  })
466
481
  })
@@ -476,7 +491,7 @@ export async function apply(ctx: Context, config: Config): Promise<void> {
476
491
  apply: applyStyleEvent,
477
492
  wire: {
478
493
  viewSchema: styleSelectionViewSchema,
479
- view: state => viewStyleSelection(runtime, state),
494
+ view: state => viewStyleSelection(runtime, state, coreActive ? 'disabled' : 'enabled'),
480
495
  },
481
496
  stateVersion: 2,
482
497
  })
package/src/types.ts CHANGED
@@ -90,6 +90,14 @@ export interface StyleSelectionView {
90
90
  options: StyleOption[]
91
91
  /** Current selection, or null when the session has none. */
92
92
  currentValue: string | null
93
+ /**
94
+ * Whether this plugin injects the style section into the system prompt.
95
+ * `disabled` is the coexistence-degraded state: a core `outputStyles`
96
+ * capability owns injection, and the selection still drives hot-switch,
97
+ * rules and `/transcript`. Clients and session projections read this to
98
+ * state the fact instead of implying the style is in force.
99
+ */
100
+ promptInjection: 'enabled' | 'disabled'
93
101
  }
94
102
 
95
103
  /** Validates the `style` projection's wire payload before it leaves the host. */
@@ -101,6 +109,7 @@ export const styleSelectionViewSchema = zod.object({
101
109
  whenToUse: zod.string().min(1).optional(),
102
110
  })),
103
111
  currentValue: zod.string().min(1).nullable(),
112
+ promptInjection: zod.union([zod.literal('enabled'), zod.literal('disabled')]),
104
113
  })
105
114
 
106
115
  /**