dsh-memory-palace 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/lib/client.js +8 -8
- package/lib/common/prompts.mjs +9 -4
- package/lib/distill.mjs +21 -5
- package/lib/index.js +6 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ turn/end ──► 轻量兜底闸门
|
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
76
|
dsh plugin --profile web add github:lovezi0/dsh-memory-palace
|
|
77
|
-
# 锁定版本:dsh plugin --profile web add github:lovezi0/dsh-memory-palace#v1.4.
|
|
77
|
+
# 锁定版本:dsh plugin --profile web add github:lovezi0/dsh-memory-palace#v1.4.1
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
方式二:clone 后本地安装(开发 / 修改源码场景)
|
|
@@ -93,7 +93,7 @@ dsh plugin --profile web add . # 装入 web profile(profile 名按你的实
|
|
|
93
93
|
# 直接由 dsh 从 npm 拉取并装入(本机若已配镜像会自动走镜像)
|
|
94
94
|
dsh plugin --profile web add dsh-memory-palace
|
|
95
95
|
# 锁定版本:
|
|
96
|
-
dsh plugin --profile web add dsh-memory-palace@1.4.
|
|
96
|
+
dsh plugin --profile web add dsh-memory-palace@1.4.1
|
|
97
97
|
|
|
98
98
|
# 或先手动用 npm 安装(显式指定镜像),再装入:
|
|
99
99
|
npm install dsh-memory-palace --registry=https://registry.npmmirror.com/
|
|
@@ -117,6 +117,9 @@ dsh plugin --profile web remove dsh-memory-palace
|
|
|
117
117
|
|
|
118
118
|
## 版本历史
|
|
119
119
|
|
|
120
|
+
- **1.4.1**
|
|
121
|
+
- 🐛修复输出预算使用错位的问题
|
|
122
|
+
- 🐛增加调试模式日志级别 *默认info 仅输出元数据日志,debug 输出完整LLM text*
|
|
120
123
|
- **1.4.0**
|
|
121
124
|
- 🔥智能模式增加最大输出Token限制
|
|
122
125
|
- 🔥智能模式增加失败重试机制
|
package/lib/client.js
CHANGED
|
@@ -64,14 +64,14 @@ window.__ModuleLoader__.load({
|
|
|
64
64
|
notifyProjectDone: "项目记忆蒸馏完成",
|
|
65
65
|
notifyFail: "记忆蒸馏失败",
|
|
66
66
|
distillDebugLogLabel: "蒸馏调试日志",
|
|
67
|
-
distillDebugLogHint: "开启后向 dsh 服务端控制台(stderr)输出蒸馏 LLM
|
|
67
|
+
distillDebugLogHint: "开启后向 dsh 服务端控制台(stderr)输出蒸馏 LLM 调用诊断。info 级别仅输出元数据(不含文本);配合 distillLogLevel=debug 会额外打印 LLM 原始响应(分隔符包裹),仅限受信本地排障。",
|
|
68
68
|
dev: "开发",
|
|
69
69
|
distillTimeoutLabel: "蒸馏超时(秒)",
|
|
70
70
|
distillTimeoutHint: "单次蒸馏 LLM 调用的超时上限(秒);超时视为失败并降级。覆盖智能模式摘要与手动蒸馏,默认 60 秒。",
|
|
71
71
|
summaryMaxTokensLabel: "会话摘要最大 Token(智能模式)",
|
|
72
|
-
summaryMaxTokensHint: "智能模式会话摘要 LLM
|
|
73
|
-
projectMaxTokensLabel: "
|
|
74
|
-
projectMaxTokensHint: "手动「蒸馏项目记忆」LLM
|
|
72
|
+
summaryMaxTokensHint: "智能模式会话摘要 LLM 的【最终输出软预算(prompt 约束,思考不受限;实际硬上限由模型自身 maxTokens 决定)】。默认 2000,可调大以容纳更多 durable 事实。",
|
|
73
|
+
projectMaxTokensLabel: "项目蒸馏输出软预算",
|
|
74
|
+
projectMaxTokensHint: "手动「蒸馏项目记忆」LLM 的【最终输出软预算(prompt 约束,思考不受限;实际硬上限由模型自身 maxTokens 决定)】。默认 8000。",
|
|
75
75
|
feedbackEnabledLabel: "蒸馏回喂存量记忆",
|
|
76
76
|
feedbackEnabledHint: "开启后,自动智能模式(turn/end)与手动蒸馏会话按钮均会把项目级 + 用户级 MEMORY.md 全文(逐行编号、无截断)回喂 LLM,使其能基于既有记忆做 add/replace/delete 增量维护。delete 仅手动蒸馏按钮开放,自动模式跳过(防误删)。默认关。"
|
|
77
77
|
};
|
|
@@ -130,14 +130,14 @@ window.__ModuleLoader__.load({
|
|
|
130
130
|
notifyProjectDone: "Project memory distilled",
|
|
131
131
|
notifyFail: "Memory distillation failed",
|
|
132
132
|
distillDebugLogLabel: "Distill debug log",
|
|
133
|
-
distillDebugLogHint: "When on, prints distill LLM call diagnostics to the dsh server console (stderr).
|
|
133
|
+
distillDebugLogHint: "When on, prints distill LLM call diagnostics to the dsh server console (stderr). info level prints metadata only (no text); with distillLogLevel=debug it additionally prints the raw LLM response (wrapped in delimiters), for trusted local troubleshooting only.",
|
|
134
134
|
dev: "Developer",
|
|
135
135
|
distillTimeoutLabel: "Distill timeout (s)",
|
|
136
136
|
distillTimeoutHint: "Timeout (in seconds) for a single distill LLM call; on timeout it fails and degrades. Covers both smart-mode summary and manual distillation. Default 60s.",
|
|
137
137
|
summaryMaxTokensLabel: "Session summary max tokens (smart mode)",
|
|
138
|
-
summaryMaxTokensHint: "
|
|
139
|
-
projectMaxTokensLabel: "Project distill
|
|
140
|
-
projectMaxTokensHint: "
|
|
138
|
+
summaryMaxTokensHint: "Smart-mode session summary LLM final output soft budget (prompt constraint, thinking not limited; the actual hard cap is the model's own maxTokens). Default 2000; raise to fit more durable facts.",
|
|
139
|
+
projectMaxTokensLabel: "Project distill output soft budget",
|
|
140
|
+
projectMaxTokensHint: "Manual 'distill project memory' LLM final output soft budget (prompt constraint, thinking not limited; actual hard cap is the model's own maxTokens). Default 8000.",
|
|
141
141
|
feedbackEnabledLabel: "Feed existing memory into distillation",
|
|
142
142
|
feedbackEnabledHint: "When on, both the auto smart-mode (turn/end) and the manual session distillation feed the full project-level + user-level MEMORY.md (line-numbered, no truncation) back to the LLM so it can maintain memory incrementally via add/replace/delete. delete is only allowed via the manual distill button; auto mode skips it (to avoid accidental memory loss). Off by default."
|
|
143
143
|
};
|
package/lib/common/prompts.mjs
CHANGED
|
@@ -9,7 +9,7 @@ export const SCENE_KEYWORDS = ["记住", "记一下", "remind", "偏好", "决
|
|
|
9
9
|
// allowDelete=true(手动蒸馏按钮):开放 add/replace/delete;false(自动智能模式):禁 delete,仅 add/replace。
|
|
10
10
|
// 注意:回喂是否实际发生由 distill.mjs 按 cfg().feedbackEnabled 决定(智能模式级,自动/手动均生效);
|
|
11
11
|
// 此处仅声明能力边界——allowDelete 决定 prompt 是否允许 delete 指令(自动模式禁 delete,手动按钮放开)。
|
|
12
|
-
export function SUMMARY_PROMPT({ allowDelete = false } = {}) {
|
|
12
|
+
export function SUMMARY_PROMPT({ allowDelete = false, outputBudget } = {}) {
|
|
13
13
|
const feedbackInstr = allowDelete
|
|
14
14
|
? "【维护现有记忆】若对话中提供了「项目级记忆 / 用户级记忆(逐行编号)」,你可在输出 memoryOps 中对现有记忆做增量维护:\n" +
|
|
15
15
|
'- add:新增一条事实(scope + fact),勿与现有重复;\n' +
|
|
@@ -35,6 +35,7 @@ export function SUMMARY_PROMPT({ allowDelete = false } = {}) {
|
|
|
35
35
|
"2) durable 每条必须是**可独立成立的客观事实**;**严禁**把「助手说过的话 / 向用户提问 / 未确认的提议」本身当作事实记录。\n" +
|
|
36
36
|
"3) 若对话中仅含未决的提问或提议、无确定结论,summary 写「本次对话为未决讨论,暂无确定结论」,durable 留空,绝不可照抄对话体文本。\n" +
|
|
37
37
|
feedbackInstr +
|
|
38
|
+
(outputBudget != null ? "\n【输出长度约束】你的最终 JSON(summary + durable + memoryOps 合计)请控制在约 " + outputBudget + " token(≈" + Math.round(outputBudget * 1.8) + " 字)以内。思考/推理过程不受此限、可充分判断(含「该不该记」「是否一次性操作」「与旧记忆是否冲突需 update/delete」),但**最终成稿必须精炼、不超预算**;严禁为凑结构而填充无用内容。\n" : "") +
|
|
38
39
|
"\n只输出 JSON,不要多余文字,格式:\n" +
|
|
39
40
|
'{"summary":"...","durable":[{"scope":"project","fact":"一句话"}],"memoryOps":[{"op":"add","scope":"project","fact":"..."},{"op":"replace","line":12,"oldText":"...","newText":"..."},{"op":"delete","line":7,"oldText":"..."}]}\n' +
|
|
40
41
|
"(没有需要维护的现有记忆时,memoryOps 留空数组 []。)"
|
|
@@ -43,8 +44,9 @@ export function SUMMARY_PROMPT({ allowDelete = false } = {}) {
|
|
|
43
44
|
|
|
44
45
|
// v1.2.0 项目记忆蒸馏 prompt(固化自 upgrade plan/v1.2.0/记忆蒸馏Prompt.md,供按钮「蒸馏项目记忆」稳定调用)。
|
|
45
46
|
// 用法:system = 本 prompt,user = 项目 MEMORY.md 全文,输出 = 精炼后的项目记忆(直接覆盖写回)。
|
|
46
|
-
export
|
|
47
|
-
|
|
47
|
+
export function DISTILL_PROMPT({ outputBudget } = {}) {
|
|
48
|
+
return (
|
|
49
|
+
"你是一名「项目记忆蒸馏器」。我会给你一份项目的原始材料(可能是记忆文件、会话记录、零散笔记,或多份材料的拼合)。你的任务:把它提炼成一段精炼的项目记忆。\n" +
|
|
48
50
|
"\n" +
|
|
49
51
|
"【提炼总原则】\n" +
|
|
50
52
|
"只保留「以后还会用到」的信息,删掉「一次性过程」。\n" +
|
|
@@ -93,4 +95,7 @@ export const DISTILL_PROMPT =
|
|
|
93
95
|
"5. 每个坑是否「现象 → 根因 → 解法」三要素齐全?\n" +
|
|
94
96
|
"6. 是否只输出了骨架要求的章节,没有额外发挥?\n" +
|
|
95
97
|
"\n" +
|
|
96
|
-
"
|
|
98
|
+
(outputBudget != null ? "【输出长度约束】你提炼后的项目记忆请控制在约 " + outputBudget + " token(≈" + Math.round(outputBudget * 1.8) + " 字)以内。思考不受限,但成稿须精炼、不超预算;只保留「以后还会用到」的信息,删掉「一次性过程」。\n" : "") +
|
|
99
|
+
"现在开始处理我提供的材料。"
|
|
100
|
+
);
|
|
101
|
+
}
|
package/lib/distill.mjs
CHANGED
|
@@ -167,11 +167,11 @@ export function createDistill({ ctx, getConfig, paths, records, state }) {
|
|
|
167
167
|
// (解析失败时抽取 {...} JSON 块兜底,仍失败则 summary 置空、记极简占位,绝不把 LLM 自由文本当 summary 落盘)。
|
|
168
168
|
const timeoutMs = c.summaryTimeoutMs || 60000;
|
|
169
169
|
const t0 = Date.now();
|
|
170
|
-
dbg("session request", { provider, model, messages: messages.length, maxTokens:
|
|
170
|
+
dbg("session request", { provider, model, messages: messages.length, maxTokens: "(model native cap)", timeoutMs, maxRetries: RETRY_CONSTANTS.MAX_RETRIES });
|
|
171
171
|
let result;
|
|
172
172
|
try {
|
|
173
173
|
result = await runWithRetry(
|
|
174
|
-
() => streamOnce({ provider, model, system: SUMMARY_PROMPT({ allowDelete
|
|
174
|
+
() => streamOnce({ provider, model, system: SUMMARY_PROMPT({ allowDelete, outputBudget: c.summaryMaxTokens }), messages }, timeoutMs),
|
|
175
175
|
{
|
|
176
176
|
maxRetries: RETRY_CONSTANTS.MAX_RETRIES,
|
|
177
177
|
onAttempt: ({ attempt, maxRetries }) => dbg("session attempt", { attempt, maxRetries }),
|
|
@@ -185,6 +185,15 @@ export function createDistill({ ctx, getConfig, paths, records, state }) {
|
|
|
185
185
|
const { finish, text, chunks, deltaChars, tFirstChunk } = result;
|
|
186
186
|
dbg("session finish", { kind: finish?.kind, attempts: result.attempts });
|
|
187
187
|
dbg("session stream done", { chunks, deltaChars, firstChunkMs: tFirstChunk });
|
|
188
|
+
// 本地调试(受 distillDebugLog + distillLogLevel==="debug" 双门控):把 LLM 原始响应 text 原样打到 stderr,
|
|
189
|
+
// 并用分隔符整段包裹,便于从 stderr 一眼框住起止、不与其它 dbg 行混淆。
|
|
190
|
+
if (cfg().distillDebugLog && cfg().distillLogLevel === "debug") {
|
|
191
|
+
console.error("[memory-palace][debug] session llm raw text begin >>>");
|
|
192
|
+
console.error("--------------------------->");
|
|
193
|
+
console.error(text);
|
|
194
|
+
console.error("<----------------------------");
|
|
195
|
+
console.error("[memory-palace][debug] session llm raw text end <<<");
|
|
196
|
+
}
|
|
188
197
|
if (finish && finish.kind === "max-tokens") {
|
|
189
198
|
console.error("[memory-palace] distill warn: llm finish max-tokens (attempting partial JSON)", JSON.stringify({}));
|
|
190
199
|
}
|
|
@@ -304,7 +313,7 @@ export function createDistill({ ctx, getConfig, paths, records, state }) {
|
|
|
304
313
|
return { ok: false, message: "无法确定蒸馏模型(summaryModel 未配置且会话无模型信息)。" };
|
|
305
314
|
}
|
|
306
315
|
({ provider, model } = resolved);
|
|
307
|
-
dbg("project request", { provider, model, inputChars: raw.length, maxTokens:
|
|
316
|
+
dbg("project request", { provider, model, inputChars: raw.length, maxTokens: "(model native cap)", timeoutMs: c.summaryTimeoutMs || 60000 });
|
|
308
317
|
|
|
309
318
|
// LLM 蒸馏:system = 固化 DISTILL_PROMPT,user = MEMORY.md 全文。带失败重试(runWithRetry)。
|
|
310
319
|
const timeoutMs = c.summaryTimeoutMs || 60000;
|
|
@@ -315,14 +324,13 @@ export function createDistill({ ctx, getConfig, paths, records, state }) {
|
|
|
315
324
|
{
|
|
316
325
|
provider,
|
|
317
326
|
model,
|
|
318
|
-
system: DISTILL_PROMPT,
|
|
327
|
+
system: DISTILL_PROMPT({ outputBudget: c.projectMaxTokens }),
|
|
319
328
|
messages: [
|
|
320
329
|
createUserMessage({
|
|
321
330
|
content: [{ type: "text", text: raw }],
|
|
322
331
|
source: { kind: "plugin", plugin: "memory-palace" },
|
|
323
332
|
}),
|
|
324
333
|
],
|
|
325
|
-
maxTokens: c.projectMaxTokens,
|
|
326
334
|
},
|
|
327
335
|
timeoutMs,
|
|
328
336
|
),
|
|
@@ -338,6 +346,14 @@ export function createDistill({ ctx, getConfig, paths, records, state }) {
|
|
|
338
346
|
return { ok: false, message: `蒸馏${kindZh}(重试 ${e?.attempts || 0} 次后仍失败):${cls.message || ""}` };
|
|
339
347
|
}
|
|
340
348
|
const { finish, text, chunks, deltaChars, gotFirstChunk, tFirstChunk } = result;
|
|
349
|
+
// 本地调试(受 distillDebugLog + distillLogLevel==="debug" 双门控,与会话蒸馏路径一致):分隔符包裹整段原始响应。
|
|
350
|
+
if (cfg().distillDebugLog && cfg().distillLogLevel === "debug") {
|
|
351
|
+
console.error("[memory-palace][debug] project llm raw text begin >>>");
|
|
352
|
+
console.error("--------------------------->");
|
|
353
|
+
console.error(text);
|
|
354
|
+
console.error("<----------------------------");
|
|
355
|
+
console.error("[memory-palace][debug] project llm raw text end <<<");
|
|
356
|
+
}
|
|
341
357
|
if (finish && finish.kind === "max-tokens") {
|
|
342
358
|
dbg("project finish", { kind: "max-tokens", attempts: result.attempts });
|
|
343
359
|
} else {
|
package/lib/index.js
CHANGED
|
@@ -53,10 +53,12 @@ export const Config = Schema.object({
|
|
|
53
53
|
memoryMode: Schema.union(["plugin", "smart"]).default("plugin").description("记忆模式:plugin=记忆公民指令+轮次轻量+错误捕获;smart=LLM 智能会话摘要(summary→每日日志 + durable→MEMORY.md,带 [smart] 标记)。切换需重启 dsh 生效。"),
|
|
54
54
|
summaryModel: Schema.string().default("").description("智能模式的摘要模型,留空=复用当前会话 provider/model;也可填 provider/model(如 deepseek/deepseek-chat)固定廉价模型省 token。"),
|
|
55
55
|
summaryTimeoutMs: Schema.number().default(60000).description("蒸馏 LLM 调用的超时(毫秒),超时视为失败并降级;覆盖智能模式摘要与手动蒸馏两条链路;默认 60000(60s)。"),
|
|
56
|
-
distillDebugLog: Schema.boolean().default(false).description("调试开关:向 dsh 服务端 stderr 输出蒸馏 LLM
|
|
57
|
-
// ---- v1.4.
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
distillDebugLog: Schema.boolean().default(false).description("调试开关:向 dsh 服务端 stderr 输出蒸馏 LLM 调用诊断。distillLogLevel=info 时仅输出元数据(模型解析/请求参数/流进度/错误详情,不含文本);distillLogLevel=debug 会额外打印 LLM 原始响应文本(分隔符包裹),仅限受信本地排障开启。"),
|
|
57
|
+
// ---- v1.4.1:蒸馏 stderr 日志级别(平铺键,不进 UI;默认 info;distillDebugLog=true 时生效) ----
|
|
58
|
+
distillLogLevel: Schema.string().default("info").description("蒸馏 stderr 日志级别:info=仅元数据诊断(默认,不打印 LLM 原始响应);debug=额外打印 LLM 原始响应文本(分隔符包裹),仅限受信本地排障开启。无需 UI 配置,经 profile/settings.yaml 设置 distillLogLevel 键。"),
|
|
59
|
+
// ---- v1.4.0:智能模式最终输出软预算(v1.4.1 起语义变更:prompt 软约束,思考不受限;实际硬上限由模型自身 maxTokens 决定) ----
|
|
60
|
+
summaryMaxTokens: Schema.number().default(2000).description("智能模式会话摘要 LLM 的【最终输出软预算(prompt 约束,思考不受限)】。默认 2000。实际硬上限由模型自身 maxTokens 决定;可调大以容纳更多 durable 事实。"),
|
|
61
|
+
projectMaxTokens: Schema.number().default(8000).description("手动「蒸馏项目记忆」LLM 的【最终输出软预算(prompt 约束,思考不受限)】。默认 8000。实际硬上限由模型自身 maxTokens 决定。"),
|
|
60
62
|
// ---- v1.4.0:蒸馏时回喂存量记忆(特性3,默认关;开启后自动智能模式 turn/end 与手动蒸馏按钮均回喂,delete 仅手动放开) ----
|
|
61
63
|
feedbackEnabled: Schema.boolean().default(false).description("蒸馏时把项目级 + 用户级 MEMORY.md 全文(逐行编号、无截断)回喂给 LLM,使其能基于既有记忆做 add/replace/delete 增量维护。默认关;开启后自动智能模式(turn/end)与手动蒸馏会话按钮均回喂存量记忆;delete 仍仅手动按钮开放,自动模式跳过(防误删)。"),
|
|
62
64
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-memory-palace",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "把 WorkBuddy 的文件式记忆系统移植进 DeepSeek Harness:用户级 + 工作区的人类可读 Markdown 记忆(~/.deepseek-harness/MEMORY.md 与 <cwd>/.deepseek-harness/memory/)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|