@modusensus/dsh-mneme 0.4.0 → 0.4.2
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.md +4 -2
- package/lib/config.js +5 -0
- package/lib/summarize.js +6 -3
- package/package.json +2 -2
- package/src/config.js +5 -0
- package/src/summarize.js +6 -3
- package/test/summarize.test.js +35 -0
package/README.md
CHANGED
|
@@ -131,6 +131,7 @@ v0.3.0 起新增**记忆基因**层:从记忆里抽取**命名实体**、**带
|
|
|
131
131
|
|
|
132
132
|
| 版本 | 亮点 |
|
|
133
133
|
|------|------|
|
|
134
|
+
| **v0.4.2** | autoSummarize 自定义模型:`summarizeProvider`/`summarizeModel` 配置项,可独立指定轻量模型(如 qwen3.6-plus)用于会话摘要,节省主模型 token;473 测试全绿 |
|
|
134
135
|
| **v0.4.0** | 系统级睡眠 Sleep Mode:空闲触发的四阶段深度维护(冲突消解 / 归档降级 / 模式发现 / 关系补全),可中断、串行安全、fail-safe,分层压缩释放冷记忆;471 测试全绿 |
|
|
135
136
|
| **v0.3.9** | 修复第三方审计 4 项 FAIL:CAS 同事务原子化、Mirror 降级回执透传、逐 type 物理终态收敛、Generation 强整数校验与并发初始化稳定化 |
|
|
136
137
|
| **v0.3.8** | audit peer 复验 6 项运行时阻断全部修复:desired generation 同事务原子递增(崩溃窗口不再静默跳过)、同步失败不静默、原子 generation 增量(多进程零丢失)、逐 type committed/failed/pending 回执、读取失败显式 unknown、generation 上界/负数 CHECK |
|
|
@@ -146,8 +147,8 @@ v0.3.0 起新增**记忆基因**层:从记忆里抽取**命名实体**、**带
|
|
|
146
147
|
| v0.3.0 | ✅ 完成 | 记忆基因 | entities/attrs/relations 三表 + 时间轴 + 实体搜索 |
|
|
147
148
|
| v0.3.6–0.3.8 | ✅ 完成 | 镜像一致性 + 审计加固 | generation 同步状态机、audit peer 6 项运行时阻断修复、450 测试全绿 |
|
|
148
149
|
| v0.3.9 | ✅ 完成 | 审计加固 A/B/D/F | compareAndUpdate 同事务原子性、degraded 回执、逐 type 物理终态、整数 fail-closed、并发初始化稳定 |
|
|
149
|
-
| **v0.4.0** |
|
|
150
|
-
| **v0.4.
|
|
150
|
+
| **v0.4.0** | ✅ 完成 | 系统级睡眠 Sleep Mode | 空闲触发的四阶段深度维护(冲突消解 / 归档降级 / 模式发现 / 关系补全)、分层压缩、可中断串行 fail-safe;471 测试全绿 |
|
|
151
|
+
| **v0.4.2** | ✅ 完成 | autoSummarize 自定义模型 | `summarizeProvider`/`summarizeModel` 配置项支持,可独立指定轻量模型(如 qwen3.6-plus)用于会话摘要,节省主模型 token;473 测试全绿 |
|
|
151
152
|
| **v0.5.0+** | 🚀 远期 | 自进化记忆 | 兴趣漂移跟踪 + 跨 workspace 记忆共享(等 DSH 支持) |
|
|
152
153
|
|
|
153
154
|
> 新能力一律做成**可开关的功能**(配置启用/关闭),默认保守开启、不破坏现有行为。`failure_memories` 表与 autoDream 决策引擎已为后续反思性成长铺好路。
|
|
@@ -210,6 +211,7 @@ dsh web
|
|
|
210
211
|
| `memoryDir` | `~/.dsh/memory` | 记忆存储目录(SQLite + Markdown) |
|
|
211
212
|
| `autoInject` | `true` | 会话启动自动注入记忆 |
|
|
212
213
|
| `autoSummarize` | `true` | 会话结束自动提炼摘要 |
|
|
214
|
+
| `summarizeProvider` / `summarizeModel` | 空 | 摘要的 LLM 路由覆盖(空=使用当前会话模型);推荐轻量模型节省主模型 token |
|
|
213
215
|
| `maxInjectedItems` | `5` | 最多注入几条记忆 |
|
|
214
216
|
| `importanceThreshold` | `3` | 注入的最低重要性(1-5) |
|
|
215
217
|
| `autoDream` | `true` | 自动记忆整理开关 |
|
package/lib/config.js
CHANGED
|
@@ -4,6 +4,11 @@ export const Config = z.object({
|
|
|
4
4
|
memoryDir: z.string().default("~/.dsh/memory"),
|
|
5
5
|
autoInject: z.boolean().default(true),
|
|
6
6
|
autoSummarize: z.boolean().default(true),
|
|
7
|
+
// Optional model override for summarization. When both are non-empty, they
|
|
8
|
+
// take priority over the session's current model. Empty = use the session's
|
|
9
|
+
// active provider/model (same as before).
|
|
10
|
+
summarizeProvider: z.string().default(""),
|
|
11
|
+
summarizeModel: z.string().default(""),
|
|
7
12
|
maxInjectedItems: z.natural().min(1).max(20).default(5),
|
|
8
13
|
importanceThreshold: z.natural().min(1).max(5).default(3),
|
|
9
14
|
autoDream: z.boolean().default(true),
|
package/lib/summarize.js
CHANGED
|
@@ -100,9 +100,12 @@ export function createSummarizer(ctx, service, config) {
|
|
|
100
100
|
inFlight.set(session.id, controller);
|
|
101
101
|
try {
|
|
102
102
|
const header = session.requestHeader?.()?.config;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
:
|
|
103
|
+
// Config override takes priority, then session header, then nothing.
|
|
104
|
+
const route = (config.summarizeProvider && config.summarizeModel)
|
|
105
|
+
? { provider: config.summarizeProvider, model: config.summarizeModel }
|
|
106
|
+
: (header?.provider && header?.model)
|
|
107
|
+
? { provider: header.provider, model: header.model }
|
|
108
|
+
: undefined;
|
|
106
109
|
if (!route) return;
|
|
107
110
|
const messages = collectMessages(session);
|
|
108
111
|
if (!messages.length) return;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modusensus/dsh-mneme",
|
|
3
3
|
"description": "Cross-session memory plugin for DeepSeek Harness with autoDream consolidation: SQLite store, Markdown mirrors, 7 model tools, automatic injection, session summarization, user profile/rules, custom slash commands, vector (semantic) search, and a Web GUI panel",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|
|
@@ -64,4 +64,4 @@
|
|
|
64
64
|
"overrides": {
|
|
65
65
|
"adm-zip": "0.6.0"
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|
package/src/config.js
CHANGED
|
@@ -4,6 +4,11 @@ export const Config = z.object({
|
|
|
4
4
|
memoryDir: z.string().default("~/.dsh/memory"),
|
|
5
5
|
autoInject: z.boolean().default(true),
|
|
6
6
|
autoSummarize: z.boolean().default(true),
|
|
7
|
+
// Optional model override for summarization. When both are non-empty, they
|
|
8
|
+
// take priority over the session's current model. Empty = use the session's
|
|
9
|
+
// active provider/model (same as before).
|
|
10
|
+
summarizeProvider: z.string().default(""),
|
|
11
|
+
summarizeModel: z.string().default(""),
|
|
7
12
|
maxInjectedItems: z.natural().min(1).max(20).default(5),
|
|
8
13
|
importanceThreshold: z.natural().min(1).max(5).default(3),
|
|
9
14
|
autoDream: z.boolean().default(true),
|
package/src/summarize.js
CHANGED
|
@@ -100,9 +100,12 @@ export function createSummarizer(ctx, service, config) {
|
|
|
100
100
|
inFlight.set(session.id, controller);
|
|
101
101
|
try {
|
|
102
102
|
const header = session.requestHeader?.()?.config;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
:
|
|
103
|
+
// Config override takes priority, then session header, then nothing.
|
|
104
|
+
const route = (config.summarizeProvider && config.summarizeModel)
|
|
105
|
+
? { provider: config.summarizeProvider, model: config.summarizeModel }
|
|
106
|
+
: (header?.provider && header?.model)
|
|
107
|
+
? { provider: header.provider, model: header.model }
|
|
108
|
+
: undefined;
|
|
106
109
|
if (!route) return;
|
|
107
110
|
const messages = collectMessages(session);
|
|
108
111
|
if (!messages.length) return;
|
package/test/summarize.test.js
CHANGED
|
@@ -154,3 +154,38 @@ test("aborted finish does not store entries", async () => {
|
|
|
154
154
|
assert.equal(calls.length, 1); // the stream was actually reached
|
|
155
155
|
assert.equal(store.count(), 0);
|
|
156
156
|
});
|
|
157
|
+
|
|
158
|
+
test("uses summarizeProvider/summarizeModel config override when set", async () => {
|
|
159
|
+
const { events, calls } = setup({
|
|
160
|
+
summarizeProvider: "aliyun",
|
|
161
|
+
summarizeModel: "qwen3.6-plus"
|
|
162
|
+
});
|
|
163
|
+
const handler = events.find((e) => e.name === "session/event").fn;
|
|
164
|
+
const session = {
|
|
165
|
+
id: "s4",
|
|
166
|
+
// Session header has a different model — config override should win.
|
|
167
|
+
requestHeader: () => ({ config: { provider: "deepseek", model: "deepseek-v4-pro" } }),
|
|
168
|
+
events: [userMessage("测试覆盖"), { seq: 2, type: "turn/end" }]
|
|
169
|
+
};
|
|
170
|
+
await handler(session, { seq: 2, type: "turn/end" });
|
|
171
|
+
assert.equal(calls.length, 1);
|
|
172
|
+
assert.equal(calls[0].provider, "aliyun");
|
|
173
|
+
assert.equal(calls[0].model, "qwen3.6-plus");
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test("falls back to session header when summarize config is empty", async () => {
|
|
177
|
+
const { events, calls } = setup({
|
|
178
|
+
summarizeProvider: "",
|
|
179
|
+
summarizeModel: ""
|
|
180
|
+
});
|
|
181
|
+
const handler = events.find((e) => e.name === "session/event").fn;
|
|
182
|
+
const session = {
|
|
183
|
+
id: "s5",
|
|
184
|
+
requestHeader: () => ({ config: { provider: "deepseek", model: "deepseek-chat" } }),
|
|
185
|
+
events: [userMessage("回退测试"), { seq: 2, type: "turn/end" }]
|
|
186
|
+
};
|
|
187
|
+
await handler(session, { seq: 2, type: "turn/end" });
|
|
188
|
+
assert.equal(calls.length, 1);
|
|
189
|
+
assert.equal(calls[0].provider, "deepseek");
|
|
190
|
+
assert.equal(calls[0].model, "deepseek-chat");
|
|
191
|
+
});
|