dsh-memoir 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -12,13 +12,13 @@
12
12
  No embeddings, vector database, or cloud memory service. The npm package has zero bundled runtime dependencies; DSH and Zod 4 peers are supplied by the host environment; Zod validates session projections and is not bundled.
13
13
 
14
14
  > [!IMPORTANT]
15
- > **0.8.1 requires DSH `>=0.1.7-rc.1 <0.1.8-0`**, with SDKs pinned to `0.1.7-rc.2`. It refines unskinned Desktop settings backgrounds, spacing and cards, adds actual-save diagnostics, and adopts public Session projections. Keep `dsh-memoir@0.7.1` on DSH 0.1.5.
15
+ > **0.9.0 requires DSH `>=0.2.0-rc.1 <0.3.0-0`**, built and tested against the published `0.2.0-rc.1` (not an unqualified final 0.2.0 release). Adds a visible plugin guide, native plugin configuration, German/Russian agent copy and offline release highlights. Retains separate distillation turns, provenance, frozen snapshots and zero bundled runtime dependencies. **On DSH 0.1.7, pin `dsh-memoir@0.8.2`; upgrade the host before installing 0.9.0.**
16
16
  >
17
17
  > `dsh-memoir@0.7.1` fixes lost session snapshots after restart or RAM eviction (#10), supporting DSH **0.1.5-rc.1 / rc.2**. It requires `>=0.1.5-rc.1 <0.1.6-0`; check your host first. Keep `0.6.2` on DSH 0.1.2, or `0.5.6` on DSH 0.1.1-rc.2; those older lines do not include this fix.
18
18
 
19
19
  ```bash
20
- npm install --global @deepseek-ai/dsh@0.1.7-rc.2
21
- dsh plugin --profile web add dsh-memoir@0.8.1
20
+ npm install --global @deepseek-ai/dsh@0.2.0-rc.1
21
+ dsh plugin --profile web add dsh-memoir@0.9.0
22
22
  ```
23
23
 
24
24
  Restart `dsh web`. Memory remains local and is not automatically deleted when the plugin is updated or removed.
@@ -37,7 +37,11 @@ Restart `dsh web`. Memory remains local and is not automatically deleted when th
37
37
 
38
38
  It fits personal and local development workflows where a new agent should continue understanding a project. It is not a raw chat backup, multi-user cloud sync service, or vector-semantic knowledge base.
39
39
 
40
- ![dsh-memoir v0.6.1 global memory grouped and collapsed by project](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.6.1/picture/v0.6.1-global-project-groups-zh.png)
40
+ ### UI preview
41
+
42
+ **0.9.0 component preview with demonstration data.** Plugin identity, GitHub, documentation and memory settings stay at the top, before long lists.
43
+
44
+ ![0.9.0 UI preview: visible plugin guide and memory browsing](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.9.0/picture/v0.9.0-preview-guide-zh.png)
41
45
 
42
46
  ## How it works
43
47
 
@@ -88,15 +92,21 @@ Similar-memory governance starts with BM25 candidates, then combines title simil
88
92
 
89
93
  ## Automatic distillation
90
94
 
91
- 0.8.1 diagnostics distinguish reminders, persistence, failures, cancellation, unresolved similarity, and unavailable receipts. Only persisted `memoir_record` / `memoir_update` operations suppress reminders; failed calls or unresolved candidates do not count as saves. Host cancellation may follow persistence, so counters can overlap. Correlation with a reminder proves neither causation nor semantic correctness. GUI writes are excluded from Agent-tool counters.
95
+ 0.8.2 diagnostics distinguish reminders, persistence, failures, cancellation, unresolved similarity, and unavailable receipts. Only persisted `memoir_record` / `memoir_update` operations suppress reminders; failed calls or unresolved candidates do not count as saves. Host cancellation may follow persistence, so counters can overlap. Correlation with a reminder proves neither causation nor semantic correctness. GUI writes are excluded from Agent-tool counters.
92
96
 
93
- 0.8.1 uses public `sessionProjections` to reconstruct current-turn activity from logs and checkpoints without deprecated `snapshotEvents()` reads. Each session retains at most 4096 current-turn call IDs, without arguments or content; evicted IDs degrade to session-only provenance. Gate state is capped at 1024 agents and cleared on disposal. Legacy writes have no receipts: a historical call alone cannot prove persistence. BM25 remains lexical retrieval, not guaranteed cross-language semantic matching.
97
+ 0.8.2 uses public `sessionProjections` to reconstruct current-turn activity from logs and checkpoints without deprecated `snapshotEvents()` reads. Each session retains at most 4096 current-turn call IDs, without arguments or content; evicted IDs degrade to session-only provenance. Gate state is capped at 1024 agents and cleared on disposal. Legacy writes have no receipts: a historical call alone cannot prove persistence. BM25 remains lexical retrieval, not guaranteed cross-language semantic matching.
94
98
 
95
99
  Automatic distillation is an observable agent turn-end reminder, not silent background scraping of every chat. The default `1 / 0 / 1` means every eligible worked turn, no extra cooldown, and at least one tool call.
96
100
 
101
+ > **0.8.2 fixes distillation-induced answer folding for new turns ([#13](https://github.com/Qinling-Melon-Farmers/dsh-memoir/issues/13)):** The public `followup` API queues a separate memory wrap-up turn instead of using same-turn `steer`. A short receipt, empty output or failed wrap-up tool cannot change the original task answer’s turn boundary. Memory provenance still points to the source work turn. Wrap-up turns neither advance the worked-turn cadence nor recursively trigger distillation. This is still visible, cancelable model work—not a free background task—and may increase the displayed turn count.
102
+ >
103
+ > Upgrading does not rewrite history. For same-turn folding already recorded by 0.8.0 / 0.8.1, expand the process disclosure or use Normal (`normal`) transcript mode. This fix does not change DSH’s answer selection for arbitrary same-turn continuations from other producers, and does not rely on a “remain silent” prompt.
104
+
97
105
  `autoDistillEvery`, `autoDistillCooldownMin`, and `autoDistillMinTools` are AND conditions isolated per agent. Idle, aborted, subagent, and already-recorded turns do not trigger. Cooldown advances only after a successful reminder. All cadence parameters are live-editable in the GUI.
98
106
 
99
- `language` independently controls agent-visible tool descriptions and parameters, the distillation prompt, tool results, Hot Memory / `PROJECT_MEMORY.md` headings, and validation or governance errors. It defaults to `zh` for backward compatibility and can be switched to `en` in the GUI. Tool schemas and subsequent prompts update live without restarting DSH.
107
+ `language` independently controls agent-visible tool descriptions and parameters, the distillation prompt, tool results, Hot Memory / `PROJECT_MEMORY.md` headings, and validation or governance errors. Released 0.8.2 supports `zh` / `en`, defaulting to `zh`. Tool descriptions and subsequent prompts update live without restarting DSH.
108
+
109
+ **0.9.0 adds `de` (Deutsch) and `ru` (Русский)**, explicitly selected in Memory settings rather than inferred from the agent or user messages. Tool names, parameter keys and enums remain unchanged. The GUI remains Chinese/English and existing memory content is not automatically translated. Switching language alone does not rewrite JSON or Markdown; projection headings use the current language on subsequent normal writes. Each of the four languages has its own frozen-snapshot namespace; switching back reuses the previous baseline. Select `zh` or `en` before downgrading to 0.8.2.
100
110
 
101
111
  ## Local recall and caching
102
112
 
@@ -107,11 +117,13 @@ Automatic distillation is an observable agent turn-end reminder, not silent back
107
117
  - epoch-aware LRU query cache with one-hour time buckets; `limit` and output detail stay outside the key so output shapes share rankings;
108
118
  - the GUI and `memoir_read` use the same RetrievalEngine and expose hits, misses, evictions, hit rate, and last-query latency.
109
119
 
120
+ 0.9.0 extends word splitting to Unicode letters, combining marks and numbers with NFC normalization, preserving German umlauts and Russian Cyrillic. Original content and existing Chinese/code-identifier rules are preserved. This remains lexical retrieval, not automatic translation, stemming or cross-language semantic search.
121
+
110
122
  Top-5 recall on the fixed quality set is 100%; the repository gate requires at least 90%.
111
123
 
112
124
  ## Web GUI
113
125
 
114
- Installing into a DSH-alpha `web` profile registers a native Memory Conversation view and Memory Settings section through official slots. The DSH shell owns layout, navigation, and unload lifecycle; Memoir no longer takes over the legacy sidebar through DOM selectors.
126
+ Installing into a compatible DSH `web` profile registers a native Memory Conversation view and Memory Settings section through official slots. The DSH shell owns layout, navigation, and unload lifecycle; Memoir no longer takes over the legacy sidebar through DOM selectors.
115
127
 
116
128
  - Project memory and all-project global memory, with project groups collapsed by default and complete lifecycle totals;
117
129
  - status, section, and keyword filters with BM25 scores;
@@ -126,7 +138,22 @@ Installing into a DSH-alpha `web` profile registers a native Memory Conversation
126
138
  - live GUI Chinese/English switching from `<html lang>`, with a separate `language` setting for agent-facing copy.
127
139
 
128
140
  <details>
129
- <summary>More GUI screenshots</summary>
141
+ <summary>0.9.0 UI previews: native plugin configuration and language settings</summary>
142
+
143
+ The native plugin detail page reuses Memory settings directly, without opening the memory list. Shown below is the native plugin detail page in DSH 0.2.0-rc.1.
144
+
145
+ ![0.9.0 native plugin detail configuration](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.9.0/picture/v0.9.0-host-plugin-zh.png)
146
+
147
+ Choose German agent-facing copy independently of the English GUI; settings and memory browsing scroll separately.
148
+
149
+ ![0.9.0 UI preview: German agent copy selected in the English GUI](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.9.0/picture/v0.9.0-preview-settings-en.png)
150
+
151
+ </details>
152
+
153
+ <details>
154
+ <summary>GUI screenshots from previous releases</summary>
155
+
156
+ ![v0.6.1 global memory grouped by project](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.6.1/picture/v0.6.1-global-project-groups-zh.png)
130
157
 
131
158
  ![v0.7.1 durable snapshot diagnostics on DSH rc.2](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.7.1/picture/v0.7.1-snapshot-persistence-zh.png)
132
159
 
@@ -152,31 +179,55 @@ Installing into a DSH-alpha `web` profile registers a native Memory Conversation
152
179
 
153
180
  | Channel | DSH baseline | Installation | Status |
154
181
  | --- | --- | --- | --- |
155
- | npm `latest` (`0.8.1`) | `>=0.1.7-rc.1 <0.1.8-0` | `dsh plugin --profile web add dsh-memoir@0.8.1` | DSH 0.1.7 line |
182
+ | npm `latest` (`0.9.0`) | `>=0.2.0-rc.1 <0.3.0-0` | `dsh plugin --profile web add dsh-memoir@0.9.0` | Tested on 0.2.0-rc.1 |
183
+ | pinned npm `0.8.2` | `>=0.1.7-rc.1 <0.1.8-0` | `dsh plugin --profile web add dsh-memoir@0.8.2` | Legacy 0.1.7 line |
156
184
  | pinned npm `0.7.1` | `>=0.1.5-rc.1 <0.1.6-0` | `dsh plugin --profile web add dsh-memoir@0.7.1` | Legacy 0.1.5 line |
157
185
  | pinned npm `0.6.2` | `>=0.1.2-alpha.2 <0.1.3` | `dsh plugin --profile web add dsh-memoir@0.6.2` | Legacy 0.1.2 line |
158
186
  | pinned npm `0.5.6` | `0.1.1-rc.2` | `dsh plugin --profile web add dsh-memoir@0.5.6` | rc2 compatibility line |
159
- | Source `v0.8.1` | `>=0.1.7-rc.1 <0.1.8-0` | local build + `link:` | Development; not compatible with legacy 0.1.5 / 0.1.6 |
187
+ | Source `v0.9.0` | `>=0.2.0-rc.1 <0.3.0-0` | local build + `link:` | Development; not compatible with legacy 0.1.x |
160
188
 
161
189
  Node.js `^22.19.0 || >=24.0.0` is required. 0.7.1 keeps the native `conversation.view` / `settings.section` slots and `snapshotEvents()`. DSH 0.1.5 uses Session log V3, independent of Memoir store v4 / settings v3. Back up DSH_HOME before upgrading DSH; migrated sessions are not guaranteed readable by older hosts. This Memoir release neither migrates nor resets memory and retains frozen session snapshots without enabling new dynamic-prompt behavior.
162
190
 
163
191
  <details>
164
192
  <summary>Install from source</summary>
165
193
 
166
- Published 0.7.1 source (legacy DSH 0.1.5):
194
+ 0.9.0 source (DSH 0.2.0-rc.1):
167
195
 
168
196
  ```bash
169
- git clone --branch v0.7.1 https://github.com/Qinling-Melon-Farmers/dsh-memoir.git
197
+ git clone --branch v0.9.0 https://github.com/Qinling-Melon-Farmers/dsh-memoir.git
170
198
  cd dsh-memoir
171
199
  pnpm install --frozen-lockfile
172
200
  pnpm run build
173
- npm install --global @deepseek-ai/dsh@0.1.5-rc.1
201
+ npm install --global @deepseek-ai/dsh@0.2.0-rc.1
174
202
  dsh plugin --profile web add "link:/absolute/path/dsh-memoir"
175
203
  ```
176
204
 
177
205
  </details>
178
206
 
179
- 0.8.1 uses native `uiWorkspace`, `conversation.view` / `settings.section`, and the Session V4 producer-owned distillation source. Links open sessions and turn IDs remain copyable; no global DOM turn scrolling is used. Settings inherit the host background and cards use theme layers while preserving skins and independent scrolling. Store v4 / settings v3 / snapshot v1 are unchanged. Back up DSH_HOME before upgrading: host session migration is separate from plugin memory storage.
207
+ 0.8.2 uses native `uiWorkspace`, `conversation.view` / `settings.section`, and the Session V4 producer-owned distillation source. Links open sessions and turn IDs remain copyable; no global DOM turn scrolling is used. Settings inherit the host background and cards use theme layers while preserving skins and independent scrolling. Store v4 / settings v3 / snapshot v1 are unchanged. Back up DSH_HOME before upgrading: host session migration is separate from plugin memory storage.
208
+
209
+ ## Native sidebar and help
210
+
211
+ **Released 0.8.2:**
212
+
213
+ - Existing Conversation and Settings entries stay unchanged. The right-sidebar guide now offers Memory for browsing project memory, Hot Memory and diagnostics alongside chat; it never opens automatically or replaces another panel.
214
+ - Each sidebar instance follows its own session workspace and reuses the same data layer, with independent active surfaces and scroll state. Conversation and Settings remain available when the optional sidebar service is absent.
215
+ - Under Memory settings, the collapsed About & help card shows the plugin version, host range, SDK baseline, maintainer, repository, bilingual documentation, releases and issue links. The plugin repository is explicitly distinct from the current workspace.
216
+ - No background update requests, workspace Git-remote inspection or path/memory uploads. Use the host plugin manager to update, after checking the target package’s DSH requirements and prerelease channel. The panel does not auto-upgrade.
217
+
218
+ **0.9.0:**
219
+
220
+ - Plugin identity, version, GitHub project, documentation and Open memory settings move to the top of Conversation, Settings and sidebar panels, before any long memory or configuration list. Detailed compatibility information stays collapsed; no forced navigation or Star prompt.
221
+ - Open `dsh-memoir` on the native Plugins page to use the same memory-settings form. No duplicate configuration store or registration pretending to be an official plugin; existing entries still work without this host page.
222
+ - Develop and validate against official npm `0.2.0-rc.1`. Check the host version before installation; keep Memoir 0.8.2 on DSH 0.1.7.
223
+
224
+ ## Offline release highlights
225
+
226
+ The first Memory Conversation opening shows the bundled 0.9.0 highlights without blocking chat. Choose “Got it” to stop automatic display for this version in the same browser origin. Reopen anytime from “About & help → View release highlights”. Settings and sidebar panels never open the notice automatically.
227
+
228
+ The Chinese/English notice is offline: no network requests, uploads, memory changes or conversation edits. Only the acknowledged version is stored locally by the UI. If storage is unavailable, acknowledgment lasts for the current page; Web/Desktop and different origins are not guaranteed to share it.
229
+
230
+ ![0.9.0 offline announcement component preview with demonstration data](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.9.0/picture/v0.9.0-announcement-zh.png)
180
231
 
181
232
  ## Storage, privacy, and security boundaries
182
233
 
@@ -202,7 +253,7 @@ Every field below can be set in the memoir `config` row in `cordis.patch.yml`. E
202
253
  | Field | Default | Purpose |
203
254
  | --- | ---: | --- |
204
255
  | `enabled` | `true` | master switch for tools, routes, and prompt injection |
205
- | `language` | `zh` | agent-facing prompt, tool schema/result, projection-heading, and error language; `zh` or `en` |
256
+ | `language` | `zh` | agent-facing copy; `zh` / `en` in 0.8.2, plus `de` / `ru` in 0.9.0; independent of GUI language |
206
257
  | `announceToAgent` | `true` | announce memory tools and rules to the agent |
207
258
  | `autoDistill` | `true` | enable top-level worked-turn reminders |
208
259
  | `autoDistillEvery` | `1` | remind at most once per N worked turns |
@@ -258,6 +309,6 @@ pnpm test
258
309
  npm run bench
259
310
  ```
260
311
 
261
- Read [CONTRIBUTING.md](./CONTRIBUTING.md) before submitting changes. See [CHANGELOG.md](./CHANGELOG.md) for version history. Formal packages are published by the tag workflow through npm OIDC. The current version is [v0.8.1](https://github.com/Qinling-Melon-Farmers/dsh-memoir/releases/tag/v0.8.1), targeting DSH 0.1.7. Keep 0.7.1 on legacy DSH 0.1.5.
312
+ Read [CONTRIBUTING.md](./CONTRIBUTING.md) before submitting changes. See [CHANGELOG.md](./CHANGELOG.md) for version history. Formal packages are published by the tag workflow through npm OIDC. The current version is [v0.9.0](https://github.com/Qinling-Melon-Farmers/dsh-memoir/releases/tag/v0.9.0), targeting DSH 0.2.0-rc.1. Pin 0.8.2 on DSH 0.1.7, or 0.7.1 on DSH 0.1.5.
262
313
 
263
314
  Apache-2.0
package/README.md CHANGED
@@ -11,13 +11,13 @@
11
11
  无需 embedding、向量数据库或云端记忆服务;npm 包零捆绑运行时依赖,DSH 与 Zod 4 peer 由宿主环境提供;Zod 用于验证宿主会话投影,不捆绑进插件。
12
12
 
13
13
  > [!IMPORTANT]
14
- > **0.8.1 要求 DSH `>=0.1.7-rc.1 <0.1.8-0`**,开发 SDK 为 `0.1.7-rc.2`。优化桌面端无皮肤设置页的底色、留白及卡片排版;增加实际保存诊断,并迁移到公开 Session projection。旧 DSH 0.1.5 请固定安装 `dsh-memoir@0.7.1`。
14
+ > **0.9.0 要求 DSH `>=0.2.0-rc.1 <0.3.0-0`**,开发与实测基线为已发布的 `0.2.0-rc.1`(不是无后缀正式 0.2.0)。新增首屏插件导引、原生插件配置、德语/俄语 Agent 文案和离线更新公告;保留独立蒸馏回合、溯源、冻结快照与零捆绑运行时依赖。**DSH 0.1.7 用户请固定 `dsh-memoir@0.8.2`,先升级宿主再安装 0.9.0。**
15
15
  >
16
16
  > `dsh-memoir@0.7.1` 修复重启和内存淘汰后旧会话快照丢失(#10),支持 DSH **0.1.5-rc.1 / rc.2**。要求 `>=0.1.5-rc.1 <0.1.6-0`;请先核对宿主版本。旧 DSH 0.1.2 用户固定使用 `0.6.2`,0.1.1-rc.2 用户固定使用 `0.5.6`;这些旧版未包含本次修复。
17
17
 
18
18
  ```bash
19
- npm install --global @deepseek-ai/dsh@0.1.7-rc.2
20
- dsh plugin --profile web add dsh-memoir@0.8.1
19
+ npm install --global @deepseek-ai/dsh@0.2.0-rc.1
20
+ dsh plugin --profile web add dsh-memoir@0.9.0
21
21
  ```
22
22
 
23
23
  重启 `dsh web` 即可。记忆保存在本机,不会随插件升级或卸载自动删除。
@@ -32,11 +32,15 @@ dsh plugin --profile web add dsh-memoir@0.8.1
32
32
  | BM25 排序召回 | 中文短语、英文关键词、代码标识符和路径都可检索;跨项目 Top-K 与查询 LRU 缓存共用同一引擎 |
33
33
  | 可治理的记忆 | 重要度、置顶、标签、归档、恢复和 supersede 生命周期;相似写入必须显式更新、替代或并存 |
34
34
  | 可追溯 | Agent 写入记录可信 session/turn 来源,Web 面板可复制并尽力跳回原会话 |
35
- | 完整 Web GUI | 中英双语项目/全局浏览、排序搜索、编辑、Hot Memory 预览、诊断和实时设置;可独立选择 Agent 侧中文或英文 |
35
+ | 完整 Web GUI | 中英双语项目/全局浏览、排序搜索、编辑、Hot Memory 预览、诊断和实时设置;可独立选择 Agent 侧中文、英文、德语或俄语 |
36
36
 
37
37
  适合需要“新 Agent 接手时继续理解项目”的个人或本地开发工作流。它不是原始聊天记录备份、多人云同步服务或向量语义知识库。
38
38
 
39
- ![dsh-memoir v0.6.1 按项目折叠的全局记忆](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.6.1/picture/v0.6.1-global-project-groups-zh.png)
39
+ ### 界面预览
40
+
41
+ **0.9.0 组件界面预览,使用演示数据。** 顶部常驻插件身份、GitHub、文档与记忆设置入口,无需滚过长列表。
42
+
43
+ ![0.9.0 界面预览:首屏插件导引与记忆浏览](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.9.0/picture/v0.9.0-preview-guide-zh.png)
40
44
 
41
45
  ## 工作原理
42
46
 
@@ -87,15 +91,21 @@ memoir_record / memoir_update
87
91
 
88
92
  ## 自动蒸馏
89
93
 
90
- 0.8.1 诊断页区分提醒提交、实际保存、失败、取消、相似记忆待确认和回执降级。只有成功保存的 `memoir_record` / `memoir_update` 才抑制本回合提醒;失败或相似候选待确认不算写入。保存后宿主仍可能取消最终工具结果,因此计数可以重叠。提醒与后续保存的关联不证明因果或内容正确。GUI 手工写入不计入 Agent 工具计数。
94
+ 0.8.2 诊断页区分提醒提交、实际保存、失败、取消、相似记忆待确认和回执降级。只有成功保存的 `memoir_record` / `memoir_update` 才抑制本回合提醒;失败或相似候选待确认不算写入。保存后宿主仍可能取消最终工具结果,因此计数可以重叠。提醒与后续保存的关联不证明因果或内容正确。GUI 手工写入不计入 Agent 工具计数。
91
95
 
92
- 0.8.1 使用公开 `sessionProjections` 从日志和 checkpoint 重建当前回合,不再读取弃用的 `snapshotEvents()`。每会话只保留当前回合最多 4096 个调用 ID,不保存参数或正文;超出保留范围时来源降级为 session-only。门控最多保留 1024 个 Agent,销毁时清理;旧版写入没有保存回执,不能仅从历史调用推断成功。BM25 是词项召回,不承诺跨语言语义匹配。
96
+ 0.8.2 使用公开 `sessionProjections` 从日志和 checkpoint 重建当前回合,不再读取弃用的 `snapshotEvents()`。每会话只保留当前回合最多 4096 个调用 ID,不保存参数或正文;超出保留范围时来源降级为 session-only。门控最多保留 1024 个 Agent,销毁时清理;旧版写入没有保存回执,不能仅从历史调用推断成功。BM25 是词项召回,不承诺跨语言语义匹配。
93
97
 
94
98
  自动蒸馏是可观察的 Agent 收尾提醒,不是后台静默抓取聊天内容。默认 `1 / 0 / 1` 表示:每个有效 worked turn、无额外冷却、至少一次工具调用即可提醒。
95
99
 
96
- `autoDistillEvery`、`autoDistillCooldownMin`、`autoDistillMinTools` 三个条件按 AND 判定并按 Agent 隔离。idle、aborted、subagent 和已调用 `memoir_record` 的回合不会触发;冷却只在提醒成功后更新。所有频率参数都可在 GUI 中即时修改。
100
+ > **0.8.2 修复了新回合的蒸馏答案折叠问题([#13](https://github.com/Qinling-Melon-Farmers/dsh-memoir/issues/13))**:通过公开 `followup` 排入独立记忆收尾回合,不再用同回合 `steer` 抢占原任务回合的最后一步。短回执、空输出或收尾工具失败都不会改变原任务答复的回合边界;记忆来源仍指向原工作回合。收尾回合不计入 worked-turn 频率,也不会递归触发蒸馏。它仍是可见、可取消的模型收尾,不是无成本后台任务,可能增加会话显示的回合数。
101
+ >
102
+ > 升级不会改写旧会话:0.8.0 / 0.8.1 产生的同回合折叠历史仍需展开“用时 / 过程”或切到标准(`normal`)模式查看。本修复不改变 DSH 对任意其他同回合追加步骤的答案选择,也不靠“禁止输出”的提示词掩盖问题。
103
+
104
+ `autoDistillEvery`、`autoDistillCooldownMin`、`autoDistillMinTools` 三个条件按 AND 判定并按 Agent 隔离。idle、aborted、subagent 和已成功保存记忆的回合不会触发;冷却只在提醒成功后更新。所有频率参数都可在 GUI 中即时修改。
105
+
106
+ `language` 独立控制 Agent 可见的工具描述、参数说明、蒸馏提示、工具结果、Hot Memory / `PROJECT_MEMORY.md` 标题以及校验与治理错误。已发布 0.8.2 支持 `zh` / `en`,默认 `zh`;切换后工具描述与后续提示即时更新,不要求重启 DSH。
97
107
 
98
- `language` 独立控制 Agent 可见的工具描述、参数说明、蒸馏提示、工具结果、Hot Memory / `PROJECT_MEMORY.md` 标题以及校验与治理错误。默认 `zh` 保持向后兼容,也可在 GUI 中切换为 `en`;切换后工具 schema 与后续提示即时更新,不要求重启 DSH。
108
+ **0.9.0新增 `de`(Deutsch)和 `ru`(Русский)**,可在记忆设置中明确选择;不是根据 Agent 或用户消息自动猜测语言。工具名、参数名与枚举不变,GUI 仍为中英双语,既有记忆正文不会自动翻译。切换语言本身不重写 JSON 或 Markdown;后续正常写入时投影标题使用当前语言。四种语言各有独立冻结快照空间,切回原语言可继续复用旧基线。降级到 0.8.2 前请先改回 `zh` 或 `en`。
99
109
 
100
110
  ## 本地召回与缓存
101
111
 
@@ -106,11 +116,13 @@ memoir_record / memoir_update
106
116
  - epoch 感知、1 小时时间桶的 LRU 查询缓存;`limit` 与输出详略不进入缓存键,因此不同输出形态共享排序结果;
107
117
  - GUI 和 `memoir_read` 使用同一个 RetrievalEngine,并暴露 hits、misses、evictions、命中率与最近查询耗时。
108
118
 
119
+ 0.9.0将词项分割扩展为 Unicode 字母/组合标记/数字并做 NFC 归一化,保留德语变音字符与俄语西里尔字母;不修改原始正文,保留中文和代码标识符规则。它仍是词项检索,不提供自动翻译、词形还原或跨语言语义搜索。
120
+
109
121
  固定质量集的 Top-5 命中率为 100%,仓库门禁要求不低于 90%。
110
122
 
111
123
  ## Web GUI
112
124
 
113
- 安装到 DSH alpha 的 `web` profile 后,Memoir 通过官方 slot 注册原生「记忆」会话视图和「记忆」Settings 分区;布局、导航与卸载生命周期均由 DSH shell 管理,不再通过 DOM 选择器接管旧侧边栏。
125
+ 安装到兼容 DSH 的 `web` profile 后,Memoir 通过官方 slot 注册原生「记忆」会话视图和「记忆」Settings 分区;布局、导航与卸载生命周期均由 DSH shell 管理,不再通过 DOM 选择器接管旧侧边栏。
114
126
 
115
127
  - 项目记忆与所有项目的全局记忆;全局视图按项目默认折叠并显示完整生命周期计数;
116
128
  - 状态、分类和关键词筛选,BM25 分数展示;
@@ -125,7 +137,22 @@ memoir_record / memoir_update
125
137
  - GUI 跟随 `<html lang>` 在中文和英文间即时切换;Agent 侧语言由独立的 `language` 设置控制。
126
138
 
127
139
  <details>
128
- <summary>查看更多 GUI 截图</summary>
140
+ <summary>0.9.0 界面预览:原生插件配置入口与多语言设置</summary>
141
+
142
+ 原生插件详情页直接复用记忆设置,不必先打开记忆列表。下图为 DSH 0.2.0-rc.1 的原生插件详情页。
143
+
144
+ ![0.9.0 原生插件详情配置](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.9.0/picture/v0.9.0-host-plugin-zh.png)
145
+
146
+ 英文 GUI 中也可独立选择德语 Agent 文案;设置与记忆浏览分别滚动。
147
+
148
+ ![0.9.0 界面预览:英文界面选择德语 Agent 文案](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.9.0/picture/v0.9.0-preview-settings-en.png)
149
+
150
+ </details>
151
+
152
+ <details>
153
+ <summary>已发布历史版本 GUI 截图</summary>
154
+
155
+ ![v0.6.1 按项目折叠的全局记忆](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.6.1/picture/v0.6.1-global-project-groups-zh.png)
129
156
 
130
157
  ![v0.7.1 在 DSH rc.2 中的快照持久化诊断](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.7.1/picture/v0.7.1-snapshot-persistence-zh.png)
131
158
 
@@ -151,31 +178,55 @@ memoir_record / memoir_update
151
178
 
152
179
  | 渠道 | DSH 基线 | 安装方式 | 状态 |
153
180
  | --- | --- | --- | --- |
154
- | npm `latest`(`0.8.1`) | `>=0.1.7-rc.1 <0.1.8-0` | `dsh plugin --profile web add dsh-memoir@0.8.1` | 0.1.7 兼容线 |
181
+ | npm `latest`(`0.9.0`) | `>=0.2.0-rc.1 <0.3.0-0` | `dsh plugin --profile web add dsh-memoir@0.9.0` | 实测 0.2.0-rc.1 |
182
+ | npm 固定版 `0.8.2` | `>=0.1.7-rc.1 <0.1.8-0` | `dsh plugin --profile web add dsh-memoir@0.8.2` | 旧 0.1.7 兼容线 |
155
183
  | npm 固定版 `0.7.1` | `>=0.1.5-rc.1 <0.1.6-0` | `dsh plugin --profile web add dsh-memoir@0.7.1` | 旧 0.1.5 维护线 |
156
184
  | npm 固定版 `0.6.2` | `>=0.1.2-alpha.2 <0.1.3` | `dsh plugin --profile web add dsh-memoir@0.6.2` | 旧 0.1.2 兼容线 |
157
185
  | npm 固定版 `0.5.6` | `0.1.1-rc.2` | `dsh plugin --profile web add dsh-memoir@0.5.6` | rc2 兼容线 |
158
- | 源码 `v0.8.1` | `>=0.1.7-rc.1 <0.1.8-0` | 本地构建 + `link:` | 开发调试,不兼容旧 0.1.5 / 0.1.6 |
186
+ | 源码 `v0.9.0` | `>=0.2.0-rc.1 <0.3.0-0` | 本地构建 + `link:` | 开发调试,不兼容旧 0.1.x |
159
187
 
160
188
  需要 Node.js `^22.19.0 || >=24.0.0`。0.7.1 继续使用原生 `conversation.view` / `settings.section` 与 `snapshotEvents()`。DSH 0.1.5 的会话日志升级至 V3;其迁移与 Memoir 的 store v4 / settings v3 是独立格式。升级 DSH 前备份 DSH_HOME,迁移后的 DSH 会话不能承诺被旧宿主读取。Memoir 本次不迁移或清空记忆,也不启用新动态提示词行为;既有会话快照语义保持不变。
161
189
 
162
190
  <details>
163
191
  <summary>从源码安装</summary>
164
192
 
165
- 已发布 0.7.1 源码(旧 DSH 0.1.5):
193
+ 0.9.0 源码(DSH 0.2.0-rc.1):
166
194
 
167
195
  ```bash
168
- git clone --branch v0.7.1 https://github.com/Qinling-Melon-Farmers/dsh-memoir.git
196
+ git clone --branch v0.9.0 https://github.com/Qinling-Melon-Farmers/dsh-memoir.git
169
197
  cd dsh-memoir
170
198
  pnpm install --frozen-lockfile
171
199
  pnpm run build
172
- npm install --global @deepseek-ai/dsh@0.1.5-rc.1
200
+ npm install --global @deepseek-ai/dsh@0.2.0-rc.1
173
201
  dsh plugin --profile web add "link:/absolute/path/dsh-memoir"
174
202
  ```
175
203
 
176
204
  </details>
177
205
 
178
- 0.8.1 使用原生 `uiWorkspace`、`conversation.view` / `settings.section` 与 Session V4 专属蒸馏来源。来源链接打开会话,回合编号可复制;不通过全局 DOM 自动滚到回合。设置页继承宿主背景、卡片使用主题层级色,保留皮肤覆盖与独立滚动。store v4 / settings v3 / snapshot v1 不变。升级 DSH 前备份 DSH_HOME,其会话迁移与插件记忆是两回事。
206
+ 0.8.2 使用原生 `uiWorkspace`、`conversation.view` / `settings.section` 与 Session V4 专属蒸馏来源。来源链接打开会话,回合编号可复制;不通过全局 DOM 自动滚到回合。设置页继承宿主背景、卡片使用主题层级色,保留皮肤覆盖与独立滚动。store v4 / settings v3 / snapshot v1 不变。升级 DSH 前备份 DSH_HOME,其会话迁移与插件记忆是两回事。
207
+
208
+ ## 原生侧栏与帮助入口
209
+
210
+ **已发布 0.8.2:**
211
+
212
+ - 会话“记忆”和设置页入口保持不变;右侧栏引导页新增“记忆”,可边对话边看项目记忆、Hot Memory 和诊断,不会自动打开或抢占其它面板。
213
+ - 侧栏读取所属会话的工作区,复用同一数据层;每个实例独立保存当前功能区和滚动状态。缺少侧栏服务时,会话页和设置页仍可用。
214
+ - 任一记忆面板的“记忆设置”底部提供默认折叠的“关于与帮助”:显示插件版本、宿主范围、SDK 基线、维护者,以及仓库、双语文档、Release、反馈链接。插件仓库与当前工作区明确区分。
215
+ - 关于区不后台联网、不探测工作区 Git remote、不上传路径或记忆内容。更新通过宿主插件管理器操作,先核对目标包要求的 DSH 版本和预发布通道;本面板不自动升级。
216
+
217
+ **0.9.0:**
218
+
219
+ - 插件名、版本、GitHub 项目、文档和“打开记忆设置”前移到面板顶部,打开会话、设置或右侧记忆面板即可看到,无须先滚过记忆或设置列表。详细兼容信息保持折叠,不强制跳转或请求 Star。
220
+ - 原生“插件”页面中打开 `dsh-memoir` 详情,即可使用同一套记忆设置表单;不另建一份配置,不向官方插件分组冒充注册。宿主没有此页面时,原有记忆入口仍可用。
221
+ - 开发 SDK 与兼容性基线升级到官方 npm `0.2.0-rc.1`;安装前核对宿主版本。旧 DSH 0.1.7 请固定安装 Memoir 0.8.2。
222
+
223
+ ## 离线更新公告
224
+
225
+ 首次打开记忆会话页时展示 0.9.0 更新摘要,不阻塞对话;点击“知道了”后,同一浏览器 origin 的本版本不再自动展示。“关于与帮助 → 查看本版更新”可随时重看。设置页和右侧栏不会自动弹出公告。
226
+
227
+ 公告随包内置、中英双语,不联网、不上传信息、不改变记忆或对话。仅在 UI 本地存储记录已确认版本;存储不可用时退化为当前页面去重,Web/桌面端或不同 origin 的确认状态不承诺同步。
228
+
229
+ ![0.9.0 离线公告组件预览(演示数据)](https://raw.githubusercontent.com/Qinling-Melon-Farmers/dsh-memoir/v0.9.0/picture/v0.9.0-announcement-zh.png)
179
230
 
180
231
  ## 存储、隐私与安全边界
181
232
 
@@ -201,7 +252,7 @@ dsh plugin --profile web add "link:/absolute/path/dsh-memoir"
201
252
  | 字段 | 默认值 | 作用 |
202
253
  | --- | ---: | --- |
203
254
  | `enabled` | `true` | 工具、路由和 prompt 注入总开关 |
204
- | `language` | `zh` | Agent 可见的 prompt、工具 schema/结果、投影标题与错误语言;可选 `zh` / `en` |
255
+ | `language` | `zh` | Agent 文案语言;0.8.2 为 `zh` / `en`,0.9.0 新增 `de` / `ru`;与 GUI 语言独立 |
205
256
  | `announceToAgent` | `true` | 向 Agent 公告记忆工具与规则 |
206
257
  | `autoDistill` | `true` | 启用顶层有效回合收尾提醒 |
207
258
  | `autoDistillEvery` | `1` | 每 N 个 worked turn 最多提醒一次 |
@@ -257,6 +308,6 @@ pnpm test
257
308
  npm run bench
258
309
  ```
259
310
 
260
- 提交前请阅读 [CONTRIBUTING.md](./CONTRIBUTING.md)。版本变化见 [CHANGELOG.md](./CHANGELOG.md),正式包由 tag 工作流通过 npm OIDC 发布。当前版本是 [v0.8.1](https://github.com/Qinling-Melon-Farmers/dsh-memoir/releases/tag/v0.8.1),面向 DSH 0.1.7;旧 0.1.5 保留 0.7.1。
311
+ 提交前请阅读 [CONTRIBUTING.md](./CONTRIBUTING.md)。版本变化见 [CHANGELOG.md](./CHANGELOG.md),正式包由 tag 工作流通过 npm OIDC 发布。当前版本是 [v0.9.0](https://github.com/Qinling-Melon-Farmers/dsh-memoir/releases/tag/v0.9.0),面向 DSH 0.2.0-rc.1;旧 0.1.7 固定 0.8.2,旧 0.1.5 固定 0.7.1。
261
312
 
262
313
  Apache-2.0
package/cordis.patch.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  # dsh-memoir bundle patch: inserts the host-half plugin row into the web
2
2
  # profile roster. Applied as a profile bundle layer (the `dsh.bundle.patch`
3
- # manifest field) over dsh-base. dsh-memoir v0.8.1 targets the DSH
4
- # line >=0.1.7-rc.1 <0.1.8-0. Keep Memoir 0.7.1 on older DSH 0.1.5.
3
+ # manifest field) over dsh-base. dsh-memoir v0.9.0 targets the DSH
4
+ # line >=0.2.0-rc.1 <0.3.0-0. Keep Memoir 0.8.2 on older DSH 0.1.7.
5
5
  #
6
6
  # The row is a bare plugin by package name: the node half (exports ".")
7
7
  # registers the memoir_record / memoir_read tools, the /api/dsh-memoir panel
@@ -12,9 +12,9 @@
12
12
  # Optional config (all default true):
13
13
  # config:
14
14
  # enabled: true # master switch (tools, routes, prompt section)
15
- # language: zh # agent-facing copy: zh (default) or en
15
+ # language: zh # agent-facing copy: zh (default), en, de, ru
16
16
  # announceToAgent: true # system-prompt announcement
17
- # autoDistill: true # steer a distill prompt after each worked turn
17
+ # autoDistill: true # queue a separate wrap-up after each worked turn
18
18
  # autoDistillEvery: 1 # remind at most once per N worked turns
19
19
  # autoDistillCooldownMin: 0 # minimum minutes between successful reminders
20
20
  # autoDistillMinTools: 1 # minimum tool calls on the triggering turn
package/lib/activity.d.ts CHANGED
@@ -9,6 +9,8 @@ declare const schema: z.ZodObject<{
9
9
  calls: z.ZodArray<z.ZodString>;
10
10
  recorded: z.ZodBoolean;
11
11
  reminded: z.ZodBoolean;
12
+ distilling: z.ZodBoolean;
13
+ originTurn: z.ZodNullable<z.ZodNumber>;
12
14
  }, z.core.$strip>;
13
15
  export type MemoirActivity = z.infer<typeof schema>;
14
16
  export declare const emptyActivity: () => MemoirActivity;
package/lib/activity.js CHANGED
@@ -8,11 +8,13 @@ const schema = z.object({
8
8
  calls: z.array(z.string()).max(CALL_LIMIT),
9
9
  recorded: z.boolean(),
10
10
  reminded: z.boolean(),
11
+ distilling: z.boolean(),
12
+ originTurn: z.number().int().positive().nullable(),
11
13
  });
12
- export const emptyActivity = () => ({ turn: 0, toolCalls: 0, calls: [], recorded: false, reminded: false });
14
+ export const emptyActivity = () => ({ turn: 0, toolCalls: 0, calls: [], recorded: false, reminded: false, distilling: false, originTurn: null });
13
15
  export const activityProjection = {
14
16
  key: ACTIVITY_KEY,
15
- stateVersion: 1,
17
+ stateVersion: 2,
16
18
  stateSchema: schema,
17
19
  init: emptyActivity,
18
20
  apply(previous, event) {
@@ -29,10 +31,19 @@ export const activityProjection = {
29
31
  return state;
30
32
  return { ...state, toolCalls: state.toolCalls + 1, calls: [...state.calls, event.data.callId].slice(-CALL_LIMIT) };
31
33
  }
32
- if (event.type === 'agent/inbox/spliced' && event.data.target === 'next-step' &&
34
+ // next-step is retained for replay of pre-0.8.2 sessions. New reminders
35
+ // use next-turn, protecting the original turn's compact answer boundary.
36
+ if (event.type === 'agent/inbox/spliced' &&
33
37
  event.data.inserted.some(message => message.source.kind === 'dsh-memoir')) {
34
38
  return previous.reminded ? previous : { ...previous, reminded: true };
35
39
  }
40
+ // Persisted source identity survives reloads/remounts. Do not rely on a
41
+ // process-local flag: a failed or empty distillation must not recurse.
42
+ if (event.type === 'user/message' && event.data.source.kind === 'dsh-memoir') {
43
+ const origin = event.data.source.originTurn;
44
+ const originTurn = typeof origin === 'number' && Number.isInteger(origin) && origin > 0 && origin < previous.turn ? origin : null;
45
+ return { ...previous, reminded: true, distilling: true, originTurn };
46
+ }
36
47
  return previous;
37
48
  },
38
49
  };
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Automatic turn-end distillation: when the plugin is enabled, each turn of a
3
3
  * top-level agent that did real work (made tool calls) and did not already
4
- * persist memory is followed by one steering step asking the agent to distill
4
+ * persist memory is followed by a separate turn asking the agent to distill
5
5
  * the turn into memoir_record entries. Turns without tool activity are left
6
- * alone (no extra model cost), subagent sessions are never steered, and each
7
- * turn is steered at most once — the steering step runs inside the same turn,
8
- * so the per-turn gate is what lets the turn close afterwards.
6
+ * alone (no extra model cost), subagent sessions are excluded, and each work
7
+ * turn queues at most one reminder. Never steer inside the completed work
8
+ * turn: compact chat selects its last step as the answer. The replayable
9
+ * activity projection excludes reminder turns, including failed/no-op ones.
9
10
  *
10
11
  * Pure decision helpers are exported for unit tests.
11
12
  */
@@ -16,14 +17,15 @@ declare module '@deepseek-ai/dsh-llm/message' {
16
17
  interface MessageSourceMap {
17
18
  'dsh-memoir': {
18
19
  kind: 'dsh-memoir';
20
+ originTurn?: number;
19
21
  };
20
22
  }
21
23
  }
22
- /** The steering prompt injected at the end of an active turn. */
23
- export declare function distillPrompt(language?: MemoirLanguage): string;
24
+ /** The follow-up instruction; the originating work turn is not rewritten. */
25
+ export declare function distillPrompt(language?: MemoirLanguage, originTurn?: number): string;
24
26
  /** Backwards-compatible Chinese prompt constant. */
25
27
  export declare const DISTILL_PROMPT: string;
26
- /** Plugin identity stamped on the steering message source. */
28
+ /** Plugin identity stamped on the follow-up message source. */
27
29
  export declare const AUTO_DISTILL_PLUGIN = "dsh-memoir";
28
30
  /** A minimal event view for the turn-activity scan (data is narrowed inside). */
29
31
  export interface TurnEventLike {
@@ -48,7 +50,7 @@ export interface AutoDistillAgentLike {
48
50
  readonly events?: readonly TurnEventLike[];
49
51
  snapshotEvents?: () => readonly TurnEventLike[];
50
52
  };
51
- steer(message: UserMessage): void;
53
+ followup(message: UserMessage): void;
52
54
  }
53
55
  /** Subagent sessions (and any nested delegation) never get distilled. */
54
56
  export declare function isSubagentSession(agent: AutoDistillAgentLike): boolean;
@@ -69,12 +71,12 @@ export declare class AutoDistillGate {
69
71
  * are ready. Duplicate events never advance the worked-turn counter.
70
72
  */
71
73
  consume(agentId: string, turn: number, toolCalls: number, policy: AutoDistillPolicy, now: number): boolean;
72
- /** Record a successful steer; failed steer attempts do not start cooldown. */
73
- recordSteer(agentId: string, now: number): void;
74
+ /** Record a successful followup; failed followup attempts do not start cooldown. */
75
+ recordReminder(agentId: string, now: number): void;
74
76
  /** Drop all state for one agent (disposal hygiene). */
75
77
  forget(agentId: string): void;
76
78
  }
77
- export type DistillOutcome = 'disabled' | 'subagent' | 'aborted' | 'idle' | 'recorded' | 'duplicate' | 'interval' | 'tools' | 'cooldown' | 'steered' | 'failed' | 'unavailable';
79
+ export type DistillOutcome = 'disabled' | 'subagent' | 'aborted' | 'idle' | 'recorded' | 'duplicate' | 'interval' | 'tools' | 'cooldown' | 'queued' | 'distillation' | 'failed' | 'unavailable';
78
80
  /** Process-local counters only; never retains message content or credentials. */
79
81
  export declare class DistillDiagnostics {
80
82
  private counts;
@@ -95,7 +97,8 @@ export declare class DistillDiagnostics {
95
97
  disabled?: number | undefined;
96
98
  aborted?: number | undefined;
97
99
  idle?: number | undefined;
98
- steered?: number | undefined;
100
+ queued?: number | undefined;
101
+ distillation?: number | undefined;
99
102
  failed?: number | undefined;
100
103
  unavailable?: number | undefined;
101
104
  };
@@ -144,7 +147,7 @@ export declare function installAutoDistill(wire: AutoDistillWire, options: {
144
147
  cooldownMin?: number;
145
148
  minTools?: number;
146
149
  };
147
- /** Optional live language source for the steering instruction. */
150
+ /** Optional live language source for the follow-up instruction. */
148
151
  language?: () => MemoirLanguage;
149
152
  now?: () => number;
150
153
  diagnostics?: DistillDiagnostics;