dsh-fast 0.2.12 → 0.2.13

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
@@ -5,6 +5,26 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.13] - 2026-09-18
9
+
10
+ ### Changed
11
+
12
+ - Read the session surface through the optional `sessionQuery` service instead of the deprecated synchronous `Session.eventAt(seq)` accessor (the peer set gains `@deepseek-ai/dsh-session-query`). A host that composes no `sessionQuery` keeps working through an equivalent synchronous read resolved from one accepted-log snapshot; a failing async read degrades to it with one warning. Internal implementation change: the reported metrics are byte-identical for the same log.
13
+ - All registrations and resources (the `/fast` command, the `fast_report` tool, the three session listeners, the sampling timer, and the storage domain) now live in one lifecycle effect whose disposer releases them in reverse order. Before this, an unmount that raced `apply` could lose the command and the tool for the rest of the process and leak the domain handle — a disable/enable round trip now restores both, exactly once.
14
+ - Declare `dsh.manifestVersion: 1` and the canonical three-clause `engines.dsh` range.
15
+
16
+ ### Added
17
+
18
+ - An optional `ctx.inspector` metrics outlet (read structurally, never injected, never the only outlet: every metric stays available through `/fast` and `fast_report`). Metric publishing to it is best-effort and cannot break a report.
19
+
20
+ ### Fixed
21
+
22
+ - Degradation paths are no longer silent: a missing token meter (heuristic token pricing) or a missing system-prompt service (single-bucket attribution) is announced once per process instead of quietly changing what the numbers mean. A failing inspector outlet is announced once too, with the report surfaces unaffected.
23
+
24
+ ### Notes
25
+
26
+ - Upstream follow-up (recorded, not implemented): once `ctx.inspector` leaves experimental status, the self-built metric publishing here can be folded into it. The structural read above is deliberately tolerant so that change stays local.
27
+
8
28
  ## [0.2.12] - 2026-09-12
9
29
 
10
30
  ### Changed
package/README-es.md CHANGED
@@ -8,6 +8,7 @@
8
8
  *Observa el flujo de eventos de sesión —nunca la ruta caliente del modelo— e informa de dónde se van la latencia y el presupuesto de contexto.*
9
9
 
10
10
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
11
+ [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-fast)
11
12
  [![DSH plugin](https://img.shields.io/badge/dsh--plugin-✅-green)](https://github.com/topics/dsh-plugin)
12
13
  [![dsh-doctor](https://raw.githubusercontent.com/PerryLink/dsh-plugin-doctor/main/badges/PerryLink__dsh-fast.svg)](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章)
13
14
  [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
@@ -24,9 +25,9 @@
24
25
 
25
26
  ## Compatibility
26
27
 
27
- - DeepSeek Harness `dsh-v0.1.5-rc.2` (adaptado el 2026-09-09; commit público de la etiqueta `fb2c4b9e69`): el system prompt es ahora el nodo 0 de la superficie (un `system/message`) en lugar de un campo del sobre de la petición, así que el informe lo lee de la superficie y descuenta su precio de la superficie del token meter. Verificado el 2026-09-11 con los peers publicados `0.1.5-rc.2` (cadena de puertas local completa); el workflow compat mensual repite el smoke de instalación de profile con los mismos pines.
28
+ - DeepSeek Harness `dsh-v0.1.6-alpha.2` (adaptado el 2026-09-18): la superficie de sesión se lee a través del servicio opcional `sessionQuery` — el accesor síncrono obsoleto `Session.eventAt(seq)` desaparece y queda una lectura síncrona equivalente como respaldo — y todos los registros viven ahora en un único efecto de ciclo de vida que los libera en orden inverso. Cambio interno: las métricas son idénticas para el mismo log. Verificado el 2026-09-18 con la cadena de puertas local (doble typecheck + 70 pruebas); el workflow compat repite el smoke de instalación de profile con los pines publicados.
28
29
  - Node `^22.19.0 || >=24.0.0`, solo ESM (`"type": "module"`).
29
- - Peers: `@deepseek-ai/cordis ^4.0.2`, `@deepseek-ai/schemastery ^3.18.2`, y `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-compaction`, `@deepseek-ai/dsh-storage-domain` en `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0` (devDependencies fijan `0.1.5-rc.2`); la línea `0.1.2-rc.1` sigue soportada en ejecución mediante un fallback estructural al `header.system` anterior a 0.1.5.
30
+ - Peers: `@deepseek-ai/cordis ^4.0.2`, `@deepseek-ai/schemastery ^3.18.2`, y `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-compaction`, `@deepseek-ai/dsh-session-query`, `@deepseek-ai/dsh-storage-domain` en `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0` (devDependencies fijan `0.1.5-rc.2`); la línea `0.1.2-rc.1` sigue soportada en ejecución mediante un fallback estructural al `header.system` anterior a 0.1.5.
30
31
 
31
32
  ## What you get
32
33
 
@@ -106,6 +107,7 @@ Todos los ajustes son campos Schemastery `Config`; valores inválidos fallan la
106
107
  - **La detección de spill es heurística** — lee el aviso persistente (`Full … stored at:`); no hay evento de sesión dedicado.
107
108
  - **El system prompt es un solo cajón** — AGENTS.md, skills y persona forman el system prompt ensamblado; desde `0.1.5-alpha.1` es el nodo 0 de la superficie (un `system/message`) y no trae contabilidad por sección, así que se reportan juntos.
108
109
  - **El tiempo de carga empieza en la publicación** — la lectura de disco de una restauración ocurre antes de `session/created`; la duración reportada es publicación→primera petición.
110
+ - **Las degradaciones se anuncian una vez** — un host sin `tokenMeter` cae al precio heurístico de tokens, un host sin `systemPrompt` atribuye todo el prompt a un solo cajón, y una salida `inspector` que falla se ignora; cada caso lo dice ahora una vez por proceso en lugar de cambiar el significado de las cifras en silencio.
109
111
 
110
112
  ## Development
111
113
 
@@ -131,7 +133,7 @@ Gracias a todas las personas que han contribuido a `dsh-fast`:
131
133
 
132
134
  ## PerryLink DSH Plugin Family
133
135
 
134
- Este proyecto es uno de los [37 complementos de DeepSeek Harness](https://github.com/PerryLink) mantenidos por [PerryLink](https://github.com/PerryLink). Si este te ayuda, probablemente los demás también:
136
+ Este proyecto es uno de los [40 complementos de DeepSeek Harness](https://github.com/PerryLink) mantenidos por [PerryLink](https://github.com/PerryLink). Si este te ayuda, probablemente los demás también:
135
137
 
136
138
  | Plugin | One-liner |
137
139
  |---|---|
@@ -161,6 +163,7 @@ Este proyecto es uno de los [37 complementos de DeepSeek Harness](https://github
161
163
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Reglas de permisos declarativas allow/deny/ask estilo Claude Code con auditoría | |
162
164
  | **[dsh-personal-directive](https://github.com/PerryLink/dsh-personal-directive)** | Inyector de directivas personales con interruptor en la barra superior (edición framework) |
163
165
  | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | Base de conocimiento de desarrollo de plugins como habilidad de agente bajo demanda | |
166
+ | **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | Zero-dependency static + sandbox smoke detector for DSH plugins | |
164
167
  | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | Motor de informes de investigación verificables con evidencia direccionada por contenido | |
165
168
  | **[dsh-score](https://github.com/PerryLink/dsh-score)** | Puntuación de calidad multidimensional para plugins de DeepSeek Harness. | |
166
169
  | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | Fija sesiones en la barra lateral web con orden durable | |
@@ -170,7 +173,16 @@ Este proyecto es uno de los [37 complementos de DeepSeek Harness](https://github
170
173
  | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | Pruebas de instalación y humo aisladas para plugins de DeepSeek Harness. | |
171
174
  | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | Puente de tareas TickTick/Dida365: panel de cabecera de sesión + 11 herramientas |
172
175
  | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | Traducción de parámetros entre proveedores y reparación determinista de JSON para DeepSeek Harness. | |
173
- | **[dsh-wechat](https://github.com/PerryLink/dsh-wechat)** | Puente WeChat ↔ DSH (bot Tencent iLink): texto/imagen/archivo/voz, aprobaciones en el chat |
176
+ | **[dsh-wechat](https://github.com/pan17/dsh-wechat)** | Puente WeChat ↔ DSH (bot Tencent iLink): texto/imagen/archivo/voz, aprobaciones en el chat |
177
+ | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | Automatic strong/cheap model-tier routing with deterministic risk guards and a `/tier` command | |
178
+ | **[dsh-catalog](https://github.com/PerryLink/dsh-catalog)** | DSH Desktop Market standard catalog source for the PerryLink family | |
179
+ | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence | |
180
+ | **[dsh-kit](https://github.com/PerryLink/dsh-kit)** | One-command starter pack that installs the core family | |
181
+ | **[dsh-plugin-certification](https://github.com/PerryLink/dsh-plugin-certification)** | Community certification registry with repro-checkable grades and badges | |
182
+ | **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins | |
183
+ | **[dsh-plugin-portal](https://github.com/PerryLink/dsh-plugin-portal)** | Zero-dependency static portal rendering the whole plugin family as one page | |
184
+ | **[dsh-plugin-upgrade-015](https://github.com/PerryLink/dsh-plugin-upgrade-015)** | Merged `0.1.3-alpha.1` → `0.1.5-rc.1` upgrade corridor card plus a zero-dependency seam scanner | |
185
+ | **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | Cross-session team rooms: shared message bus, task board and timeline | |
174
186
 
175
187
  ## License
176
188
 
package/README-hi.md CHANGED
@@ -8,6 +8,7 @@
8
8
  *सत्र घटना-धारा का अवलोकन करता है — मॉडल के हॉट पाथ को कभी नहीं — और बताता है कि विलंबता और संदर्भ बजट कहाँ जा रहा है।*
9
9
 
10
10
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
11
+ [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-fast)
11
12
  [![DSH plugin](https://img.shields.io/badge/dsh--plugin-✅-green)](https://github.com/topics/dsh-plugin)
12
13
  [![dsh-doctor](https://raw.githubusercontent.com/PerryLink/dsh-plugin-doctor/main/badges/PerryLink__dsh-fast.svg)](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章)
13
14
  [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
@@ -24,9 +25,9 @@
24
25
 
25
26
  ## Compatibility
26
27
 
27
- - DeepSeek Harness `dsh-v0.1.5-rc.2` (2026-09-09 को अनुकूलित; सार्वजनिक tag commit `fb2c4b9e69`): system prompt अब अनुरोध लिफ़ाफ़े के फ़ील्ड के बजाय सतह का नोड 0 (एक `system/message`) है, इसलिए रिपोर्ट उसे सतह से पढ़ती है और token meter की सतह से उसका मूल्य घटा देती है। 2026-09-11 को प्रकाशित `0.1.5-rc.2` peers के साथ सत्यापित (पूर्ण स्थानीय गेट शृंखला); मासिक compat workflow उन्हीं pins के साथ profile इंस्टॉल स्मोक दोहराता है।
28
+ - DeepSeek Harness `dsh-v0.1.6-alpha.2` (2026-09-18 को अनुकूलित): सत्र सतह अब वैकल्पिक `sessionQuery` सेवा से पढ़ी जाती है — पदावनत सिंक्रोनस `Session.eventAt(seq)` एक्सेसर हट गया और उसकी जगह समतुल्य सिंक्रोनस रीड fallback है — और सभी रजिस्ट्रेशन अब एक ही lifecycle effect में रहते हैं जो उन्हें उल्टे क्रम में मुक्त करता है। आंतरिक बदलाव: एक ही लॉग पर मेट्रिक्स बिल्कुल समान रहते हैं। 2026-09-18 को स्थानीय गेट शृंखला (दोहरा typecheck + 70 टेस्ट) से सत्यापित; compat workflow प्रकाशित pins के साथ profile इंस्टॉल स्मोक दोहराता है।
28
29
  - Node `^22.19.0 || >=24.0.0`, केवल ESM (`"type": "module"`)।
29
- - Peers: `@deepseek-ai/cordis ^4.0.2`, `@deepseek-ai/schemastery ^3.18.2`, और `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-compaction`, `@deepseek-ai/dsh-storage-domain` (`>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0`; devDependencies `0.1.5-rc.2` पर पिन); `0.1.2-rc.1` पंक्ति रनटाइम पर pre-0.1.5 `header.system` के संरचनात्मक fallback से अभी भी समर्थित है।
30
+ - Peers: `@deepseek-ai/cordis ^4.0.2`, `@deepseek-ai/schemastery ^3.18.2`, और `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-compaction`, `@deepseek-ai/dsh-session-query`, `@deepseek-ai/dsh-storage-domain` (`>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0`; devDependencies `0.1.5-rc.2` पर पिन); `0.1.2-rc.1` पंक्ति रनटाइम पर pre-0.1.5 `header.system` के संरचनात्मक fallback से अभी भी समर्थित है।
30
31
 
31
32
  ## What you get
32
33
 
@@ -106,6 +107,7 @@ dsh plugin --profile demo remove dsh-fast # हटाएँ
106
107
  - **spill पहचान अनुमानी है** — यह स्थायी सूचना (`Full … stored at:`) पढ़ती है; कोई समर्पित सत्र घटना नहीं है।
107
108
  - **system prompt एक ही बकेट है** — AGENTS.md, skills और persona असेंबल किए गए system prompt का हिस्सा हैं; `0.1.5-alpha.1` से यह सतह का नोड 0 (एक `system/message`) है और प्रति-अनुभाग गणना नहीं रखता, इसलिए इन्हें एक साथ रिपोर्ट किया जाता है।
108
109
  - **लोड समय प्रकाशन से शुरू होता है** — पुनर्स्थापना का डिस्क-रीड `session/created` से पहले होता है; रिपोर्ट की गई अवधि प्रकाशन→पहली अनुरोध है।
110
+ - **गिरावट की सूचना एक बार दी जाती है** — `tokenMeter` न होने पर ह्यूरिस्टिक टोकन मूल्यांकन, `systemPrompt` न होने पर पूरा प्रॉम्प्ट एक ही बाल्टी में, और विफल `inspector` आउटलेट अनदेखा; अब इनमें से प्रत्येक प्रति प्रक्रिया एक बार बताता है, चुपचाप संख्याओं का अर्थ नहीं बदलता।
109
111
 
110
112
  ## Development
111
113
 
@@ -131,7 +133,7 @@ pnpm pack
131
133
 
132
134
  ## PerryLink DSH Plugin Family
133
135
 
134
- यह प्रोजेक्ट [PerryLink](https://github.com/PerryLink) द्वारा अनुरक्षित [37 DeepSeek Harness प्लगइनों](https://github.com/PerryLink) में से एक है। अगर यह आपकी मदद करता है, तो बाकी भी करेंगे:
136
+ यह प्रोजेक्ट [PerryLink](https://github.com/PerryLink) द्वारा अनुरक्षित [40 DeepSeek Harness प्लगइनों](https://github.com/PerryLink) में से एक है। अगर यह आपकी मदद करता है, तो बाकी भी करेंगे:
135
137
 
136
138
  | Plugin | One-liner |
137
139
  |---|---|
@@ -161,6 +163,7 @@ pnpm pack
161
163
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | ऑडिट के साथ Claude Code-शैली घोषणात्मक allow/deny/ask अनुमति नियम | |
162
164
  | **[dsh-personal-directive](https://github.com/PerryLink/dsh-personal-directive)** | शीर्ष-बार टॉगल के साथ व्यक्तिगत निर्देश इंजेक्टर (फ्रेमवर्क संस्करण) |
163
165
  | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | माँग पर एजेंट कौशल के रूप में प्लगइन-विकास ज्ञान आधार | |
166
+ | **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | Zero-dependency static + sandbox smoke detector for DSH plugins | |
164
167
  | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | सामग्री-पता साक्ष्य और सीलबंद संस्करणों वाला सत्यापन-योग्य अनुसंधान-रिपोर्ट इंजन | |
165
168
  | **[dsh-score](https://github.com/PerryLink/dsh-score)** | DeepSeek Harness प्लगिनों की बहु-आयामी गुणवत्ता स्कोरिंग। | |
166
169
  | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | टिकाऊ क्रम के साथ वेब साइडबार में सत्र पिन करें | |
@@ -170,7 +173,16 @@ pnpm pack
170
173
  | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | DeepSeek Harness प्लगिनों के लिए पृथक इंस्टॉल-एंड-स्मोक टेस्ट ड्राइव। | |
171
174
  | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | TickTick/Dida365 कार्य ब्रिज: सत्र-हेडर पैनल + 11 टूल |
172
175
  | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | DeepSeek Harness के लिए वेंडर पैरामीटर अनुवाद और नियतात्मक JSON मरम्मत। | |
173
- | **[dsh-wechat](https://github.com/PerryLink/dsh-wechat)** | WeChat ↔ DSH ब्रिज (Tencent iLink bot): टेक्स्ट/इमेज/फ़ाइल/आवाज़, चैट में अनुमोदन |
176
+ | **[dsh-wechat](https://github.com/pan17/dsh-wechat)** | WeChat ↔ DSH ब्रिज (Tencent iLink bot): टेक्स्ट/इमेज/फ़ाइल/आवाज़, चैट में अनुमोदन |
177
+ | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | Automatic strong/cheap model-tier routing with deterministic risk guards and a `/tier` command | |
178
+ | **[dsh-catalog](https://github.com/PerryLink/dsh-catalog)** | DSH Desktop Market standard catalog source for the PerryLink family | |
179
+ | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence | |
180
+ | **[dsh-kit](https://github.com/PerryLink/dsh-kit)** | One-command starter pack that installs the core family | |
181
+ | **[dsh-plugin-certification](https://github.com/PerryLink/dsh-plugin-certification)** | Community certification registry with repro-checkable grades and badges | |
182
+ | **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins | |
183
+ | **[dsh-plugin-portal](https://github.com/PerryLink/dsh-plugin-portal)** | Zero-dependency static portal rendering the whole plugin family as one page | |
184
+ | **[dsh-plugin-upgrade-015](https://github.com/PerryLink/dsh-plugin-upgrade-015)** | Merged `0.1.3-alpha.1` → `0.1.5-rc.1` upgrade corridor card plus a zero-dependency seam scanner | |
185
+ | **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | Cross-session team rooms: shared message bus, task board and timeline | |
174
186
 
175
187
  ## License
176
188
 
package/README-pt.md CHANGED
@@ -8,6 +8,7 @@
8
8
  *Observa o fluxo de eventos da sessão — nunca o caminho quente do modelo — e informa para onde vão a latência e o orçamento de contexto.*
9
9
 
10
10
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
11
+ [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-fast)
11
12
  [![DSH plugin](https://img.shields.io/badge/dsh--plugin-✅-green)](https://github.com/topics/dsh-plugin)
12
13
  [![dsh-doctor](https://raw.githubusercontent.com/PerryLink/dsh-plugin-doctor/main/badges/PerryLink__dsh-fast.svg)](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章)
13
14
  [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
@@ -24,9 +25,9 @@
24
25
 
25
26
  ## Compatibility
26
27
 
27
- - DeepSeek Harness `dsh-v0.1.5-rc.2` (adaptado em 2026-09-09; commit público da tag `fb2c4b9e69`): o system prompt agora é o nó 0 da superfície (um `system/message`) em vez de um campo do envelope da requisição, então o relatório o lê da superfície e desconta seu preço da superfície do token meter. Verificado em 2026-09-11 com os peers publicados `0.1.5-rc.2` (cadeia completa de portas local); o workflow compat mensal repete o smoke de instalação de profile com os mesmos pins.
28
+ - DeepSeek Harness `dsh-v0.1.6-alpha.2` (adaptado em 2026-09-18): a superfície da sessão é lida pelo serviço opcional `sessionQuery` — o acessor síncrono obsoleto `Session.eventAt(seq)` sai de cena, com uma leitura síncrona equivalente como fallback — e todos os registros agora vivem em um único efeito de ciclo de vida que os libera em ordem inversa. Mudança interna: as métricas são idênticas para o mesmo log. Verificado em 2026-09-18 com a cadeia de portas local (typecheck duplo + 70 testes); o workflow compat repete o smoke de instalação de profile com os pins publicados.
28
29
  - Node `^22.19.0 || >=24.0.0`, somente ESM (`"type": "module"`).
29
- - Peers: `@deepseek-ai/cordis ^4.0.2`, `@deepseek-ai/schemastery ^3.18.2`, e `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-compaction`, `@deepseek-ai/dsh-storage-domain` em `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0` (devDependencies fixam `0.1.5-rc.2`); a linha `0.1.2-rc.1` continua suportada em execução por um fallback estrutural ao `header.system` anterior ao 0.1.5.
30
+ - Peers: `@deepseek-ai/cordis ^4.0.2`, `@deepseek-ai/schemastery ^3.18.2`, e `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-compaction`, `@deepseek-ai/dsh-session-query`, `@deepseek-ai/dsh-storage-domain` em `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0` (devDependencies fixam `0.1.5-rc.2`); a linha `0.1.2-rc.1` continua suportada em execução por um fallback estrutural ao `header.system` anterior ao 0.1.5.
30
31
 
31
32
  ## What you get
32
33
 
@@ -106,6 +107,7 @@ O `dsh-fast` consome apenas seams públicos: eventos `session/*` e `agent/*`, o
106
107
  - **A detecção de spill é heurística** — lê o aviso persistente (`Full … stored at:`); não há evento de sessão dedicado.
107
108
  - **O system prompt é um único balde** — AGENTS.md, skills e persona formam o system prompt montado; desde `0.1.5-alpha.1` é o nó 0 da superfície (um `system/message`) e não traz contagem por seção, então são reportados juntos.
108
109
  - **O tempo de carga começa na publicação** — a leitura de disco de uma restauração ocorre antes de `session/created`; a duração reportada é publicação→primeira requisição.
110
+ - **As degradações são anunciadas uma vez** — um host sem `tokenMeter` cai no preço heurístico de tokens, um host sem `systemPrompt` atribui todo o prompt a um único balde, e uma saída `inspector` que falha é ignorada; cada caso agora avisa uma vez por processo em vez de mudar o significado dos números em silêncio.
109
111
 
110
112
  ## Development
111
113
 
@@ -131,7 +133,7 @@ Obrigado a todas as pessoas que contribuíram com o `dsh-fast`:
131
133
 
132
134
  ## PerryLink DSH Plugin Family
133
135
 
134
- Este projeto é um dos [37 plugins de DeepSeek Harness](https://github.com/PerryLink) mantidos por [PerryLink](https://github.com/PerryLink). Se este ajuda você, os outros provavelmente também:
136
+ Este projeto é um dos [40 plugins de DeepSeek Harness](https://github.com/PerryLink) mantidos por [PerryLink](https://github.com/PerryLink). Se este ajuda você, os outros provavelmente também:
135
137
 
136
138
  | Plugin | One-liner |
137
139
  |---|---|
@@ -161,6 +163,7 @@ Este projeto é um dos [37 plugins de DeepSeek Harness](https://github.com/Perry
161
163
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Regras de permissão declarativas allow/deny/ask estilo Claude Code com auditoria | |
162
164
  | **[dsh-personal-directive](https://github.com/PerryLink/dsh-personal-directive)** | Injetor de diretivas pessoais com alternância na barra superior (edição framework) |
163
165
  | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | Base de conhecimento de desenvolvimento de plugins como habilidade de agente sob demanda | |
166
+ | **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | Zero-dependency static + sandbox smoke detector for DSH plugins | |
164
167
  | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | Motor de relatórios de pesquisa verificáveis com evidência endereçada por conteúdo | |
165
168
  | **[dsh-score](https://github.com/PerryLink/dsh-score)** | Pontuação de qualidade multidimensional para plugins de DeepSeek Harness. | |
166
169
  | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | Fixe sessões na barra lateral web com ordenação durável | |
@@ -170,7 +173,16 @@ Este projeto é um dos [37 plugins de DeepSeek Harness](https://github.com/Perry
170
173
  | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | Test drives isolados de instalação e smoke para plugins de DeepSeek Harness. | |
171
174
  | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | Ponte de tarefas TickTick/Dida365: painel no cabeçalho da sessão + 11 ferramentas |
172
175
  | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | Tradução de parâmetros entre fornecedores e reparo determinístico de JSON para DeepSeek Harness. | |
173
- | **[dsh-wechat](https://github.com/PerryLink/dsh-wechat)** | Ponte WeChat ↔ DSH (bot Tencent iLink): texto/imagem/arquivo/voz, aprovações no chat |
176
+ | **[dsh-wechat](https://github.com/pan17/dsh-wechat)** | Ponte WeChat ↔ DSH (bot Tencent iLink): texto/imagem/arquivo/voz, aprovações no chat |
177
+ | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | Automatic strong/cheap model-tier routing with deterministic risk guards and a `/tier` command | |
178
+ | **[dsh-catalog](https://github.com/PerryLink/dsh-catalog)** | DSH Desktop Market standard catalog source for the PerryLink family | |
179
+ | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence | |
180
+ | **[dsh-kit](https://github.com/PerryLink/dsh-kit)** | One-command starter pack that installs the core family | |
181
+ | **[dsh-plugin-certification](https://github.com/PerryLink/dsh-plugin-certification)** | Community certification registry with repro-checkable grades and badges | |
182
+ | **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins | |
183
+ | **[dsh-plugin-portal](https://github.com/PerryLink/dsh-plugin-portal)** | Zero-dependency static portal rendering the whole plugin family as one page | |
184
+ | **[dsh-plugin-upgrade-015](https://github.com/PerryLink/dsh-plugin-upgrade-015)** | Merged `0.1.3-alpha.1` → `0.1.5-rc.1` upgrade corridor card plus a zero-dependency seam scanner | |
185
+ | **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | Cross-session team rooms: shared message bus, task board and timeline | |
174
186
 
175
187
  ## License
176
188
 
package/README-zh.md CHANGED
@@ -10,6 +10,7 @@
10
10
  > **官方仓库。** 本仓库是 dsh-fast 的唯一官方仓库,由 PerryLink 维护。其他账号下的同名仓库与本项目无关。
11
11
 
12
12
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
13
+ [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-fast)
13
14
  [![DSH plugin](https://img.shields.io/badge/dsh--plugin-✅-green)](https://github.com/topics/dsh-plugin)
14
15
  [![dsh-doctor](https://raw.githubusercontent.com/PerryLink/dsh-plugin-doctor/main/badges/PerryLink__dsh-fast.svg)](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章)
15
16
  [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
@@ -26,9 +27,9 @@
26
27
 
27
28
  ## Compatibility
28
29
 
29
- - DeepSeek Harness `dsh-v0.1.5-rc.2`(2026-09-09 已适配;公开 tag commit `fb2c4b9e69`):系统提示词改为 surface 节点 0(`system/message`)而不再放在请求信封里,因此报告从会话表面读取它,并把 token meter 的 surface 计价扣除系统提示词后再上报。已于 2026-09-11 用已发布的 `0.1.5-rc.2` peers 核验(本地全门控链);每月的 compat workflow 用同一钉号重跑 profile 安装冒烟。
30
+ - DeepSeek Harness `dsh-v0.1.6-alpha.2`(2026-09-18 已适配):会话表面改经可选的 `sessionQuery` 服务读取——已弃用的同步 `Session.eventAt(seq)` 访问器退役,改由等价的同步回退读兜底;所有注册收进同一个 lifecycle effect 并按逆序释放。属内部实现变更:同一日志下上报指标逐字相同。已于 2026-09-18 核验本地门控链(双 typecheck 尺子 + 70 项测试);compat workflow 用已发布钉号重跑 profile 安装冒烟。
30
31
  - Node `^22.19.0 || >=24.0.0`,纯 ESM(`"type": "module"`)。
31
- - peer 依赖:`@deepseek-ai/cordis ^4.0.2`、`@deepseek-ai/schemastery ^3.18.2`,以及 `@deepseek-ai/dsh-session`、`@deepseek-ai/dsh-tools`、`@deepseek-ai/dsh-commands`、`@deepseek-ai/dsh-compaction`、`@deepseek-ai/dsh-storage-domain`(`>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0`;devDependencies 钉 `0.1.5-rc.2`);`0.1.2-rc.1` 旧线仍通过结构式回退读取 pre-0.1.5 的 `header.system` 在运行时受支持。
32
+ - peer 依赖:`@deepseek-ai/cordis ^4.0.2`、`@deepseek-ai/schemastery ^3.18.2`,以及 `@deepseek-ai/dsh-session`、`@deepseek-ai/dsh-tools`、`@deepseek-ai/dsh-commands`、`@deepseek-ai/dsh-compaction`、`@deepseek-ai/dsh-session-query`、`@deepseek-ai/dsh-storage-domain`(`>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0`;devDependencies 钉 `0.1.5-rc.2`);`0.1.2-rc.1` 旧线仍通过结构式回退读取 pre-0.1.5 的 `header.system` 在运行时受支持。
32
33
 
33
34
  ## What you get
34
35
 
@@ -108,6 +109,7 @@ dsh plugin --profile demo remove dsh-fast # 卸载
108
109
  - **spill 检测是启发式** —— 读取持久化的 spill 提示(`Full … stored at:`);没有专门的会话事件。
109
110
  - **系统提示词是单个桶** —— AGENTS.md、技能目录与人设都属于组装后的系统提示词;自 `0.1.5-alpha.1` 起它是 surface 节点 0(`system/message`),本身不携带分段 token 统计,因此合并上报。
110
111
  - **加载耗时从发布时刻起算** —— 恢复时的磁盘读取发生在 `session/created` 之前(由 `sessionPersistence` 负责),本插件允许的事件观察不到;上报的时长是发布到首次请求的延迟。
112
+ - **降级路径只播报一次** —— 无 `tokenMeter` 的宿主回退到启发式 token 计价,无 `systemPrompt` 的宿主把整段提示词并入一个桶,`inspector` 出口失败则被忽略;这三者现在各在每进程播报一次,而不是静默改变数字的含义。
111
113
 
112
114
  ## Development
113
115
 
@@ -133,7 +135,7 @@ pnpm pack
133
135
 
134
136
  ## PerryLink DSH Plugin Family
135
137
 
136
- 这是 [PerryLink](https://github.com/PerryLink) 维护的 [37 个 DeepSeek Harness 插件](https://github.com/PerryLink) 之一。如果它能帮到你,其他的也会:
138
+ 这是 [PerryLink](https://github.com/PerryLink) 维护的 [40 个 DeepSeek Harness 插件](https://github.com/PerryLink) 之一。如果它能帮到你,其他的也会:
137
139
 
138
140
  | Plugin | One-liner |
139
141
  |---|---|
@@ -163,6 +165,7 @@ pnpm pack
163
165
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code 风格声明式 allow/deny/ask 权限规则,带审计 | |
164
166
  | **[dsh-personal-directive](https://github.com/PerryLink/dsh-personal-directive)** | 个人指令注入器:顶栏开关(框架版) |
165
167
  | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | 作为按需代理技能的插件开发知识库 | |
168
+ | **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | Zero-dependency static + sandbox smoke detector for DSH plugins | |
166
169
  | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | 可验证研究报告引擎:内容寻址证据账本与封存版本 | |
167
170
  | **[dsh-score](https://github.com/PerryLink/dsh-score)** | DeepSeek Harness 插件的多维质量评分。 | |
168
171
  | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | 在 Web 侧栏置顶会话,带持久排序 | |
@@ -172,7 +175,16 @@ pnpm pack
172
175
  | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | DeepSeek Harness 插件的隔离试装冒烟。 | |
173
176
  | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | TickTick/滴答清单任务桥接:会话头面板 + 11 个工具 |
174
177
  | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | DeepSeek Harness 的厂商参数翻译与确定性 JSON 修复。 | |
175
- | **[dsh-wechat](https://github.com/PerryLink/dsh-wechat)** | 微信 ↔ DSH 桥接(Tencent iLink 机器人):文本/图片/文件/语音,聊天内审批卡片 |
178
+ | **[dsh-wechat](https://github.com/pan17/dsh-wechat)** | 微信 ↔ DSH 桥接(Tencent iLink 机器人):文本/图片/文件/语音,聊天内审批卡片 |
179
+ | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | Automatic strong/cheap model-tier routing with deterministic risk guards and a `/tier` command | |
180
+ | **[dsh-catalog](https://github.com/PerryLink/dsh-catalog)** | DSH Desktop Market standard catalog source for the PerryLink family | |
181
+ | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence | |
182
+ | **[dsh-kit](https://github.com/PerryLink/dsh-kit)** | One-command starter pack that installs the core family | |
183
+ | **[dsh-plugin-certification](https://github.com/PerryLink/dsh-plugin-certification)** | Community certification registry with repro-checkable grades and badges | |
184
+ | **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins | |
185
+ | **[dsh-plugin-portal](https://github.com/PerryLink/dsh-plugin-portal)** | Zero-dependency static portal rendering the whole plugin family as one page | |
186
+ | **[dsh-plugin-upgrade-015](https://github.com/PerryLink/dsh-plugin-upgrade-015)** | Merged `0.1.3-alpha.1` → `0.1.5-rc.1` upgrade corridor card plus a zero-dependency seam scanner | |
187
+ | **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | Cross-session team rooms: shared message bus, task board and timeline | |
176
188
 
177
189
  ## License
178
190
 
package/README.md CHANGED
@@ -27,9 +27,9 @@
27
27
 
28
28
  ## Compatibility
29
29
 
30
- - DeepSeek Harness `dsh-v0.1.5-rc.2` (adapted 2026-09-09; public tag commit `fb2c4b9e69`): the system prompt is surface node 0 (a `system/message`) instead of a request-envelope field, so the report reads it from the surface and prices the meter's surface net of it. Verified 2026-09-11 with the published `0.1.5-rc.2` peers (full local gate chain); the monthly compat workflow re-runs the profile install smoke against the same pins.
30
+ - DeepSeek Harness `dsh-v0.1.6-alpha.2` (adapted 2026-09-18): the session surface is read through the optional `sessionQuery` service — the deprecated synchronous `Session.eventAt(seq)` accessor is gone, with an equivalent synchronous read as the fallback — and every registration now lives in one lifecycle effect that releases them in reverse order. Internal implementation change: the reported metrics are identical for the same log. Verified 2026-09-18 against the local gate chain (dual typecheck rulers + 70 tests); the compat workflow re-runs the profile install smoke against the published pins.
31
31
  - Node `^22.19.0 || >=24.0.0`, ESM only (`"type": "module"`).
32
- - Peer dependencies: `@deepseek-ai/cordis ^4.0.2`, `@deepseek-ai/schemastery ^3.18.2`, and `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-compaction`, `@deepseek-ai/dsh-storage-domain` at `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0` (devDependencies pin `0.1.5-rc.2`); the `0.1.2-rc.1` line stays supported at runtime through a structural fallback to the pre-0.1.5 `header.system`.
32
+ - Peer dependencies: `@deepseek-ai/cordis ^4.0.2`, `@deepseek-ai/schemastery ^3.18.2`, and `@deepseek-ai/dsh-session`, `@deepseek-ai/dsh-tools`, `@deepseek-ai/dsh-commands`, `@deepseek-ai/dsh-compaction`, `@deepseek-ai/dsh-session-query`, `@deepseek-ai/dsh-storage-domain` at `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0` (devDependencies pin `0.1.5-rc.2`); the `0.1.2-rc.1` line stays supported at runtime through a structural fallback to the pre-0.1.5 `header.system`.
33
33
 
34
34
  ## What you get
35
35
 
@@ -109,6 +109,7 @@ All tunables are Schemastery `Config` fields; invalid values fail the profile lo
109
109
  - **Spill detection is heuristic** — it reads the durable spill notice (`Full … stored at:`); no dedicated session event exists.
110
110
  - **System prompt is one bucket** — AGENTS.md, skill directory, and persona are all part of the assembled system prompt; since `0.1.5-alpha.1` it is surface node 0 (a `system/message`) and carries no per-section token accounting, so they are reported together.
111
111
  - **Load timing starts at publication** — the disk-read portion of a restore happens before `session/created` (owned by `sessionPersistence`) and is not observable from this plugin's allowed events; the reported duration is publication-to-first-request.
112
+ - **Degradations are announced once** — a host without `tokenMeter` falls back to heuristic token pricing, a host without `systemPrompt` attributes the whole prompt to one bucket, and a failing `inspector` outlet is ignored; each of these now says so once per process instead of changing what the numbers mean in silence.
112
113
 
113
114
  ## Development
114
115
 
@@ -134,7 +135,7 @@ Thanks to everyone who has contributed to `dsh-fast`:
134
135
 
135
136
  ## PerryLink DSH Plugin Family
136
137
 
137
- This project is one of the [37 DeepSeek Harness plugins](https://github.com/PerryLink) maintained by [PerryLink](https://github.com/PerryLink). If this one helps you, the others likely will too:
138
+ This project is one of the [40 DeepSeek Harness plugins](https://github.com/PerryLink) maintained by [PerryLink](https://github.com/PerryLink). If this one helps you, the others likely will too:
138
139
 
139
140
  | Plugin | One-liner |
140
141
  |---|---|
@@ -164,6 +165,7 @@ This project is one of the [37 DeepSeek Harness plugins](https://github.com/Perr
164
165
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code-style declarative allow/deny/ask permission rules with audit | |
165
166
  | **[dsh-personal-directive](https://github.com/PerryLink/dsh-personal-directive)** | Personal directive injector with top-bar toggle (framework edition) |
166
167
  | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | Plugin-development knowledge base as an on-demand agent skill | |
168
+ | **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | Zero-dependency static + sandbox smoke detector for DSH plugins | |
167
169
  | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | Verifiable research-report engine: content-addressed evidence ledger and sealed versions | |
168
170
  | **[dsh-score](https://github.com/PerryLink/dsh-score)** | Multi-dimensional quality scoring for DeepSeek Harness plugins. | |
169
171
  | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | Pin sessions in the Web sidebar with durable ordering | |
@@ -173,7 +175,16 @@ This project is one of the [37 DeepSeek Harness plugins](https://github.com/Perr
173
175
  | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | Isolated install-and-smoke test drives for DeepSeek Harness plugins. | |
174
176
  | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | TickTick/Dida365 task bridge: session-header panel + 11 tools |
175
177
  | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | Vendor parameter translation and deterministic JSON repair for DeepSeek Harness. | |
176
- | **[dsh-wechat](https://github.com/PerryLink/dsh-wechat)** | WeChat ↔ DSH bridge (Tencent iLink bot): text/image/file/voice, approvals in chat |
178
+ | **[dsh-wechat](https://github.com/pan17/dsh-wechat)** | WeChat ↔ DSH bridge (Tencent iLink bot): text/image/file/voice, approvals in chat |
179
+ | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | Automatic strong/cheap model-tier routing with deterministic risk guards and a `/tier` command | |
180
+ | **[dsh-catalog](https://github.com/PerryLink/dsh-catalog)** | DSH Desktop Market standard catalog source for the PerryLink family | |
181
+ | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence | |
182
+ | **[dsh-kit](https://github.com/PerryLink/dsh-kit)** | One-command starter pack that installs the core family | |
183
+ | **[dsh-plugin-certification](https://github.com/PerryLink/dsh-plugin-certification)** | Community certification registry with repro-checkable grades and badges | |
184
+ | **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins | |
185
+ | **[dsh-plugin-portal](https://github.com/PerryLink/dsh-plugin-portal)** | Zero-dependency static portal rendering the whole plugin family as one page | |
186
+ | **[dsh-plugin-upgrade-015](https://github.com/PerryLink/dsh-plugin-upgrade-015)** | Merged `0.1.3-alpha.1` → `0.1.5-rc.1` upgrade corridor card plus a zero-dependency seam scanner | |
187
+ | **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | Cross-session team rooms: shared message bus, task board and timeline | |
177
188
 
178
189
  ### Install from the DSH Desktop Market
179
190
 
package/lib/index.js CHANGED
@@ -202,20 +202,39 @@ const SPILL_NOTICE_MARKERS = ["Full", "stored at:"];
202
202
  * surface order. 0.1.5-alpha.1 derives the prompt from surface node 0; an empty
203
203
  * node is dormant and never restores older text. Mirrors
204
204
  * `SystemPromptProjection` in the host agent loop.
205
- * @param session - the session to read.
205
+ * @param surfaceEvents - the current surface events in model-history order
206
+ * (from the optional `sessionQuery` service, or {@link surfaceEventsOf}).
206
207
  * @returns the effective system message, or undefined when none is active.
207
208
  */
208
- function effectiveSystemMessage(session) {
209
+ function effectiveSystemMessage(surfaceEvents) {
209
210
  let effective;
210
- for (const seq of session.surface.nodes) {
211
- const event = session.eventAt(seq);
212
- if (event?.type !== "system/message") continue;
211
+ for (const event of surfaceEvents) {
212
+ if (event.type !== "system/message") continue;
213
213
  const message = event.data.message;
214
214
  if (message.content.length === 0) continue;
215
215
  effective = message;
216
216
  }
217
217
  return effective;
218
218
  }
219
+ /**
220
+ * The current surface events of a live session, resolved from one snapshot of
221
+ * the accepted log. This is the fallback read for hosts that compose no
222
+ * `sessionQuery` service: it replaces the deprecated `Session.eventAt(seq)`
223
+ * accessor (new calls are prohibited) while keeping the same surface-node
224
+ * order and the same log as the source of truth.
225
+ * @param session - the session to read.
226
+ * @returns the surface events in model-history order.
227
+ */
228
+ function surfaceEventsOf(session) {
229
+ const bySeq = /* @__PURE__ */ new Map();
230
+ for (const event of session.snapshotEvents()) bySeq.set(event.seq, event);
231
+ const events = [];
232
+ for (const seq of session.surface.nodes) {
233
+ const event = bySeq.get(seq);
234
+ if (event !== void 0) events.push(event);
235
+ }
236
+ return events;
237
+ }
219
238
  /** The display/durable text of a system message (text blocks plus structural JSON). */
220
239
  function systemTextOf(message) {
221
240
  let text = "";
@@ -350,13 +369,15 @@ var FastCollector = class {
350
369
  * @param sections - optional named system-prompt sections (from the optional
351
370
  * `systemPrompt` service); absent = the whole rendered system prompt is
352
371
  * attributed to the `other` bucket.
372
+ * @param surfaceEvents - optional pre-read surface events (the async
373
+ * `sessionQuery` read path); absent = the sync fallback read.
353
374
  * @returns the snapshot.
354
375
  */
355
- snapshot(session, measure, sections) {
376
+ snapshot(session, measure, sections, surfaceEvents) {
356
377
  const state = this.live.get(session);
357
378
  if (state === void 0) return emptySnapshot();
358
379
  const measurement = measure === void 0 ? void 0 : measure(session);
359
- const systemMessage = effectiveSystemMessage(session);
380
+ const systemMessage = effectiveSystemMessage(surfaceEvents ?? surfaceEventsOf(session));
360
381
  const legacySystem = systemMessage === void 0 ? legacySystemText(state.lastHeader) : void 0;
361
382
  const systemTokens = systemMessage === void 0 ? estimateLegacySystemTokens(legacySystem) : estimateSystemTokens(systemMessage);
362
383
  const toolSchemaTokens = estimateToolsTokens(state.lastHeader);
@@ -745,9 +766,25 @@ function appendSample(history, sample, maxSamples) {
745
766
  return { samples: [...history?.samples ?? [], sample].slice(-maxSamples) };
746
767
  }
747
768
  //#endregion
769
+ //#region src/notices.ts
770
+ /**
771
+ * Build a {@link OnceNotifier} that forwards the first message per key to the
772
+ * sink and swallows every later one.
773
+ * @param sink - where the first message per key goes (typically `logger.warn`).
774
+ * @returns the notifier.
775
+ */
776
+ function createOnceNotifier(sink) {
777
+ const seen = /* @__PURE__ */ new Set();
778
+ return (key, message) => {
779
+ if (seen.has(key)) return;
780
+ seen.add(key);
781
+ sink(message);
782
+ };
783
+ }
784
+ //#endregion
748
785
  //#region src/version.ts
749
786
  /** Single-source plugin version, bumped by `scripts/release.mjs`. @module dsh-fast/version */
750
- const VERSION = "0.2.12";
787
+ const VERSION = "0.2.13";
751
788
  //#endregion
752
789
  //#region src/index.ts
753
790
  const name = "fast";
@@ -772,11 +809,37 @@ async function apply(ctx, config = {}) {
772
809
  }
773
810
  const collector = new FastCollector(resolved);
774
811
  const domain = await ctx.storageDomain.open(fastDomainSpec);
812
+ if (ctx.fiber.uid === null) {
813
+ await domain.close();
814
+ return;
815
+ }
775
816
  const sessions = domain.table("sessions");
817
+ /**
818
+ * One-time visible degradation notices: a subsystem fallback that used to be
819
+ * silent now says so once per process, so a report built from heuristics is
820
+ * never mistaken for a measured one.
821
+ */
822
+ const warnFallbackOnce = createOnceNotifier((message) => logger.warn(message));
823
+ /** The optional metrics outlet; a no-op when the service is absent or throws. */
824
+ const inspector = ctx.get("inspector");
825
+ const publishSnapshot = (session, snapshot) => {
826
+ if (inspector === void 0 || typeof inspector.publish !== "function") return;
827
+ try {
828
+ inspector.publish("dsh-fast/snapshot", {
829
+ sessionId: session.id,
830
+ snapshot
831
+ });
832
+ } catch (error) {
833
+ warnFallbackOnce("inspector", `inspector metric outlet failed, continuing with the report surfaces only: ${error instanceof Error ? error.message : String(error)}`);
834
+ }
835
+ };
776
836
  /** Lazy, contained lookup of the optional token meter. */
777
837
  const measure = (session) => {
778
838
  const meter = ctx.get("tokenMeter");
779
- if (meter === void 0) return void 0;
839
+ if (meter === void 0) {
840
+ warnFallbackOnce("tokenMeter", "tokenMeter is not composed: total/surface tokens fall back to the fixed-density heuristic (spill and compaction counters stay exact)");
841
+ return;
842
+ }
780
843
  try {
781
844
  const measurement = meter.measure(session);
782
845
  return {
@@ -791,7 +854,10 @@ async function apply(ctx, config = {}) {
791
854
  /** Assemble the named system-prompt sections for the per-section breakdown. */
792
855
  const assembleSections = async () => {
793
856
  const systemPrompt = ctx.get("systemPrompt");
794
- if (systemPrompt === void 0) return void 0;
857
+ if (systemPrompt === void 0) {
858
+ warnFallbackOnce("systemPrompt", "systemPrompt is not composed: the whole rendered prompt is attributed to the \"other\" bucket instead of the per-section breakdown");
859
+ return;
860
+ }
795
861
  try {
796
862
  return (await systemPrompt.assemble()).sections.map((section) => ({
797
863
  name: section.name,
@@ -802,9 +868,30 @@ async function apply(ctx, config = {}) {
802
868
  return;
803
869
  }
804
870
  };
871
+ /**
872
+ * Read the current surface events for one session through the optional
873
+ * `sessionQuery` service. This replaces the deprecated synchronous
874
+ * `Session.eventAt(seq)` read; a host that composes no `sessionQuery` leaves
875
+ * the collector on its own non-deprecated sync fallback, and a failing read
876
+ * degrades to that fallback with one warning instead of failing the report.
877
+ * @param session - the session to read.
878
+ * @returns the surface events in model-history order, or undefined to fall back.
879
+ */
880
+ const readSurfaceEvents = async (session) => {
881
+ const sessionQuery = ctx.get("sessionQuery");
882
+ if (sessionQuery === void 0) return void 0;
883
+ try {
884
+ return (await sessionQuery.readSurface(session.id)).events;
885
+ } catch (error) {
886
+ logger.warn(`session "${session.id}": surface read failed, falling back to the synchronous read: ${error instanceof Error ? error.message : String(error)}`);
887
+ return;
888
+ }
889
+ };
805
890
  /** Build the complete report for one session. */
806
891
  const reportFor = async (session) => {
807
- return buildReport(collector.snapshot(session, measure, await assembleSections()), {
892
+ const snapshot = collector.snapshot(session, measure, await assembleSections(), await readSurfaceEvents(session));
893
+ publishSnapshot(session, snapshot);
894
+ return buildReport(snapshot, {
808
895
  sessionId: session.id,
809
896
  ...resolved.includeCwd && session.header.cwd !== void 0 ? { cwd: session.header.cwd } : {},
810
897
  generatedAt: Date.now()
@@ -812,7 +899,8 @@ async function apply(ctx, config = {}) {
812
899
  };
813
900
  /** Append one snapshot to the session's durable history (fire-and-forget). */
814
901
  const persist = async (session) => {
815
- const snapshot = collector.snapshot(session, measure, await assembleSections());
902
+ const snapshot = collector.snapshot(session, measure, await assembleSections(), await readSurfaceEvents(session));
903
+ publishSnapshot(session, snapshot);
816
904
  const next = appendSample(sessions.get(session.id), {
817
905
  at: Date.now(),
818
906
  snapshot
@@ -821,7 +909,7 @@ async function apply(ctx, config = {}) {
821
909
  logger.warn(`session "${session.id}": persist failed: ${error instanceof Error ? error.message : String(error)}`);
822
910
  });
823
911
  };
824
- ctx.commands.register({
912
+ const fastCommand = {
825
913
  name: "fast",
826
914
  description: "Print the dsh-fast performance report for the active session.",
827
915
  async handler(invocation) {
@@ -830,8 +918,8 @@ async function apply(ctx, config = {}) {
830
918
  text: renderFastText(await reportFor(invocation.agent.session))
831
919
  };
832
920
  }
833
- });
834
- ctx.tools.register(defineTool({
921
+ };
922
+ const fastReportTool = defineTool({
835
923
  name: "fast_report",
836
924
  description: "Return the current dsh-fast performance report for the active session: session load timing, spill hits, compaction count and trigger, context-injection volume (AGENTS.md/skills/tool-schema token share), LLM cache hit rate, and optimization suggestions.",
837
925
  parameters: {},
@@ -1077,21 +1165,25 @@ async function apply(ctx, config = {}) {
1077
1165
  if (session === void 0) throw new Error("fast_report requires an agent-owned session");
1078
1166
  return await reportFor(session);
1079
1167
  }
1080
- }));
1081
- ctx.on("session/created", (session) => {
1082
- collector.handleSessionCreated(session);
1083
- });
1084
- ctx.on("session/disposed", (session) => {
1085
- collector.handleSessionDisposed(session);
1086
- });
1087
- ctx.on("session/event", (session, event) => {
1088
- try {
1089
- collector.handleEvent(session, event);
1090
- } catch (error) {
1091
- logger.warn(`session "${session.id}": event handling failed: ${error instanceof Error ? error.message : String(error)}`);
1092
- }
1093
1168
  });
1094
1169
  ctx.effect(() => {
1170
+ const disposers = [
1171
+ ctx.commands.register(fastCommand),
1172
+ ctx.tools.register(fastReportTool),
1173
+ ctx.on("session/created", (session) => {
1174
+ collector.handleSessionCreated(session);
1175
+ }),
1176
+ ctx.on("session/disposed", (session) => {
1177
+ collector.handleSessionDisposed(session);
1178
+ }),
1179
+ ctx.on("session/event", (session, event) => {
1180
+ try {
1181
+ collector.handleEvent(session, event);
1182
+ } catch (error) {
1183
+ logger.warn(`session "${session.id}": event handling failed: ${error instanceof Error ? error.message : String(error)}`);
1184
+ }
1185
+ })
1186
+ ];
1095
1187
  const timer = setInterval(() => {
1096
1188
  for (const session of collector.liveSessions()) {
1097
1189
  if (!collector.isDirty(session)) continue;
@@ -1101,6 +1193,7 @@ async function apply(ctx, config = {}) {
1101
1193
  }, resolved.snapshotIntervalMs);
1102
1194
  return async () => {
1103
1195
  clearInterval(timer);
1196
+ for (const dispose of disposers.reverse()) dispose();
1104
1197
  await domain.close();
1105
1198
  };
1106
1199
  });