dsh-memory-palace 1.6.2-alpha.4 → 1.6.3-alpha.4
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 -1
- package/lib/client.js +46 -38
- package/lib/hybrid/prompts.mjs +3 -1
- package/lib/hybrid/subagent.mjs +56 -5
- package/lib/index.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ turn/end ──► 轻量兜底闸门
|
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
84
|
dsh plugin --profile web add github:lovezi0/dsh-memory-palace
|
|
85
|
-
# 锁定版本:dsh plugin --profile web add github:lovezi0/dsh-memory-palace#v1.6.
|
|
85
|
+
# 锁定版本:dsh plugin --profile web add github:lovezi0/dsh-memory-palace#v1.6.3-alpha.4
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
方式二:clone 后本地安装(开发 / 修改源码场景)
|
|
@@ -123,6 +123,10 @@ dsh plugin --profile web remove dsh-memory-palace
|
|
|
123
123
|
|
|
124
124
|
## 版本历史
|
|
125
125
|
|
|
126
|
+
- **1.6.3**
|
|
127
|
+
- **1.6.3.alpha.4**
|
|
128
|
+
- 🐛修复三种记忆模式配置互串的问题
|
|
129
|
+
- 🐛修复记忆子agent工具幻觉问题
|
|
126
130
|
- **1.6.2**
|
|
127
131
|
- **1.6.2.alpha.4**
|
|
128
132
|
- 🔥适配deepseek harness 0.1.2-alpha.4
|
package/lib/client.js
CHANGED
|
@@ -28,6 +28,7 @@ window.__ModuleLoader__.load({
|
|
|
28
28
|
wsDirHint: "无 buddy 目录时回退到该目录,默认 .deepseek-harness/memory",
|
|
29
29
|
retentionLabel: "日志保留天数",
|
|
30
30
|
retentionHint: "超过该天数的每日日志会迁移进 MEMORY.md 后删除",
|
|
31
|
+
retentionHintHybrid: "hybrid 模式下此设置不生效:日志由记忆子代理维护、永不过期不删(证据层),保持完整。",
|
|
31
32
|
userBudgetLabel: "用户级预算(字符)",
|
|
32
33
|
userBudgetHint: "用户级 MEMORY.md 的最大字符数",
|
|
33
34
|
wsBudgetLabel: "工作区预算(字符)",
|
|
@@ -44,8 +45,8 @@ window.__ModuleLoader__.load({
|
|
|
44
45
|
reorgCooldownHint: "项目级 MEMORY.md 全量重整的冷却天数(距上次重整);与「超出注入预算」双条件同时满足才允许 memory_reorganize。默认 7 天。",
|
|
45
46
|
subagentLogBudgetLabel: "子代理日志回喂预算(字符)",
|
|
46
47
|
subagentLogBudgetHint: "记忆子代理回喂今日工作日志的字符上限;超出时仅回喂章节目录,子代理按需读取章节。默认 20000。",
|
|
47
|
-
summaryModelLabel: "
|
|
48
|
-
summaryModelHint: "
|
|
48
|
+
summaryModelLabel: "模型",
|
|
49
|
+
summaryModelHint: "记忆插件当前使用的模型(智能模式会话摘要 / 手动蒸馏 / hybrid 记忆子代理共用)。留空=复用当前会话的 provider/model;也可固定廉价小模型省 token。",
|
|
49
50
|
save: "保存",
|
|
50
51
|
saving: "保存中…",
|
|
51
52
|
discard: "放弃",
|
|
@@ -74,12 +75,12 @@ window.__ModuleLoader__.load({
|
|
|
74
75
|
dev: "开发",
|
|
75
76
|
distillTimeoutLabel: "蒸馏超时(秒)",
|
|
76
77
|
distillTimeoutHint: "单次蒸馏 LLM 调用的超时上限(秒);超时视为失败并降级。覆盖智能模式摘要与手动蒸馏,默认 60 秒。",
|
|
77
|
-
summaryMaxTokensLabel: "会话摘要最大 Token
|
|
78
|
-
summaryMaxTokensHint: "
|
|
79
|
-
projectMaxTokensLabel: "
|
|
80
|
-
projectMaxTokensHint: "
|
|
81
|
-
feedbackEnabledLabel: "
|
|
82
|
-
feedbackEnabledHint: "
|
|
78
|
+
summaryMaxTokensLabel: "会话摘要最大 Token",
|
|
79
|
+
summaryMaxTokensHint: "最终输出软预算(prompt 约束,思考不受限;实际硬上限由模型自身 maxTokens 决定)。默认 2000,可调大以容纳更多 durable 事实。",
|
|
80
|
+
projectMaxTokensLabel: "项目蒸馏最大 Token",
|
|
81
|
+
projectMaxTokensHint: "最终输出软预算(prompt 约束,思考不受限;实际硬上限由模型自身 maxTokens 决定)。默认 8000。",
|
|
82
|
+
feedbackEnabledLabel: "回喂存量记忆",
|
|
83
|
+
feedbackEnabledHint: "每次蒸馏时附带项目级 + 用户级记忆作为参考,使其能基于既有记忆做增量维护(delete 仅手动蒸馏开放)。混合模式下仅手动触发蒸馏受影响(自动路径走记忆子代理,自带日志回喂)。默认关。"
|
|
83
84
|
};
|
|
84
85
|
|
|
85
86
|
const en = {
|
|
@@ -99,6 +100,7 @@ window.__ModuleLoader__.load({
|
|
|
99
100
|
wsDirHint: "Used when no buddy dir exists, default .deepseek-harness/memory",
|
|
100
101
|
retentionLabel: "Daily log retention (days)",
|
|
101
102
|
retentionHint: "Older logs are migrated into MEMORY.md then removed",
|
|
103
|
+
retentionHintHybrid: "Not effective in hybrid mode: daily logs are maintained by the memory sub-agent and never expire (kept intact as an evidence layer).",
|
|
102
104
|
userBudgetLabel: "User budget (chars)",
|
|
103
105
|
userBudgetHint: "Max chars for the user-level MEMORY.md",
|
|
104
106
|
wsBudgetLabel: "Workspace budget (chars)",
|
|
@@ -115,8 +117,8 @@ window.__ModuleLoader__.load({
|
|
|
115
117
|
reorgCooldownHint: "Cooldown days between full reorganizes of the project MEMORY.md; combined with 'over injection budget' both gates must pass for memory_reorganize. Default 7.",
|
|
116
118
|
subagentLogBudgetLabel: "Sub-agent log feed budget (chars)",
|
|
117
119
|
subagentLogBudgetHint: "Max chars of today's daily log fed back to the memory sub-agent; beyond this only the chapter TOC is fed and the sub-agent reads sections on demand. Default 20000.",
|
|
118
|
-
summaryModelLabel: "
|
|
119
|
-
summaryModelHint: "Leave empty to reuse the current session's provider/model, or pin a cheap model (provider/model) to save tokens.",
|
|
120
|
+
summaryModelLabel: "Model",
|
|
121
|
+
summaryModelHint: "The model currently used by the memory plugin (shared by smart-mode session summarization / manual distillation / the hybrid memory sub-agent). Leave empty to reuse the current session's provider/model, or pin a cheap model (provider/model) to save tokens.",
|
|
120
122
|
save: "Save",
|
|
121
123
|
saving: "Saving…",
|
|
122
124
|
discard: "Discard",
|
|
@@ -145,16 +147,16 @@ window.__ModuleLoader__.load({
|
|
|
145
147
|
dev: "Developer",
|
|
146
148
|
distillTimeoutLabel: "Distill timeout (s)",
|
|
147
149
|
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.",
|
|
148
|
-
summaryMaxTokensLabel: "Session summary max tokens
|
|
149
|
-
summaryMaxTokensHint: "
|
|
150
|
-
projectMaxTokensLabel: "Project distill
|
|
151
|
-
projectMaxTokensHint: "
|
|
150
|
+
summaryMaxTokensLabel: "Session summary max tokens",
|
|
151
|
+
summaryMaxTokensHint: "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.",
|
|
152
|
+
projectMaxTokensLabel: "Project distill max tokens",
|
|
153
|
+
projectMaxTokensHint: "Final output soft budget (prompt constraint, thinking not limited; actual hard cap is the model's own maxTokens). Default 8000.",
|
|
152
154
|
feedbackEnabledLabel: "Feed existing memory into distillation",
|
|
153
|
-
feedbackEnabledHint: "
|
|
155
|
+
feedbackEnabledHint: "Feed the project-level + user-level memory in as reference on every distillation so the LLM can maintain existing memory incrementally (delete is only allowed via manual distillation). In hybrid mode only manual distillation is affected (the automatic path runs through the memory sub-agent, which feeds the log itself). Off by default."
|
|
154
156
|
};
|
|
155
157
|
|
|
156
158
|
|
|
157
|
-
const FIELD_NUMERIC = new Set(["dailyLogRetentionDays", "userBudgetChars", "workspaceBudgetChars", "summaryTimeoutMs", "summaryMaxTokens", "projectMaxTokens"]);
|
|
159
|
+
const FIELD_NUMERIC = new Set(["dailyLogRetentionDays", "userBudgetChars", "workspaceBudgetChars", "summaryTimeoutMs", "summaryMaxTokens", "projectMaxTokens", "reorgCooldownDays", "subagentLogBudget"]);
|
|
158
160
|
const FIELD_BOOL = new Set(["bridgeBuddyMemory", "summarize", "autoCaptureErrors", "distillDebugLog", "feedbackEnabled"]);
|
|
159
161
|
|
|
160
162
|
function projectDraft(snap) {
|
|
@@ -175,6 +177,8 @@ window.__ModuleLoader__.load({
|
|
|
175
177
|
summaryModel: v.summaryModel || "",
|
|
176
178
|
summaryMaxTokens: v.summaryMaxTokens != null ? String(v.summaryMaxTokens) : "2000",
|
|
177
179
|
projectMaxTokens: v.projectMaxTokens != null ? String(v.projectMaxTokens) : "8000",
|
|
180
|
+
reorgCooldownDays: v.reorgCooldownDays != null ? String(v.reorgCooldownDays) : "7",
|
|
181
|
+
subagentLogBudget: v.subagentLogBudget != null ? String(v.subagentLogBudget) : "20000",
|
|
178
182
|
feedbackEnabled: v.feedbackEnabled === false ? "false" : "true"
|
|
179
183
|
};
|
|
180
184
|
}
|
|
@@ -564,38 +568,42 @@ window.__ModuleLoader__.load({
|
|
|
564
568
|
h("option", { value: "smart" }, "智能模式"),
|
|
565
569
|
h("option", { value: "hybrid" }, "混合模式")
|
|
566
570
|
]), "memoryMode"),
|
|
567
|
-
draft.memoryMode === "
|
|
571
|
+
draft.memoryMode === "hybrid"
|
|
568
572
|
? h("div", null, [
|
|
569
|
-
row(t("
|
|
570
|
-
|
|
571
|
-
// 已存储值不在下拉选项内(如旧版双前缀脏数据)→ 归零为「复用当前会话模型」,
|
|
572
|
-
// 避免 select 显示悬空值、保存时又把脏值写回 settings.yaml。
|
|
573
|
-
value: modelOptions.some((o) => o.value === draft.summaryModel) ? draft.summaryModel : "",
|
|
574
|
-
disabled,
|
|
575
|
-
style: selectStyle,
|
|
576
|
-
onChange: (e) => edit("summaryModel", e.target.value)
|
|
577
|
-
}, [
|
|
578
|
-
h("option", { value: "" }, "复用当前会话模型"),
|
|
579
|
-
...modelOptions.map((o) => h("option", { value: o.value }, o.label))
|
|
580
|
-
]), "summaryModel"),
|
|
581
|
-
toggle(t("feedbackEnabledLabel"), t("feedbackEnabledHint"), "feedbackEnabled"),
|
|
582
|
-
row(t("summaryMaxTokensLabel"), t("summaryMaxTokensHint"), h("input", num("summaryMaxTokens")), "summaryMaxTokens"),
|
|
583
|
-
row(t("projectMaxTokensLabel"), t("projectMaxTokensHint"), h("input", num("projectMaxTokens")), "projectMaxTokens")
|
|
573
|
+
row(t("reorgCooldownLabel"), t("reorgCooldownHint"), h("input", num("reorgCooldownDays")), "reorgCooldownDays"),
|
|
574
|
+
row(t("subagentLogBudgetLabel"), t("subagentLogBudgetHint"), h("input", num("subagentLogBudget")), "subagentLogBudget")
|
|
584
575
|
])
|
|
585
|
-
: draft.memoryMode === "
|
|
576
|
+
: draft.memoryMode === "plugin"
|
|
586
577
|
? h("div", null, [
|
|
587
|
-
row(t("reorgCooldownLabel"), t("reorgCooldownHint"), h("input", num("reorgCooldownDays")), "reorgCooldownDays"),
|
|
588
|
-
row(t("subagentLogBudgetLabel"), t("subagentLogBudgetHint"), h("input", num("subagentLogBudget")), "subagentLogBudget")
|
|
589
|
-
])
|
|
590
|
-
: h("div", null, [
|
|
591
578
|
toggle(t("autoCaptureErrorsLabel"), t("autoCaptureErrorsHint"), "autoCaptureErrors")
|
|
592
579
|
])
|
|
580
|
+
: null,
|
|
581
|
+
// ---- v1.6.3:蒸馏/模型参数提为常显(三模式共用,不受 memoryMode 限制)----
|
|
582
|
+
// summaryModel 同时被智能摘要与 hybrid 记忆子代理读取(subagent resolveModel);
|
|
583
|
+
// summaryMaxTokens/projectMaxTokens/feedbackEnabled 覆盖自动摘要 + 手动蒸馏两条链路。
|
|
584
|
+
h("div", null, [
|
|
585
|
+
row(t("summaryModelLabel"), t("summaryModelHint"),
|
|
586
|
+
h("select", {
|
|
587
|
+
// 已存储值不在下拉选项内(如旧版双前缀脏数据)→ 归零为「复用当前会话模型」,
|
|
588
|
+
// 避免 select 显示悬空值、保存时又把脏值写回 settings.yaml。
|
|
589
|
+
value: modelOptions.some((o) => o.value === draft.summaryModel) ? draft.summaryModel : "",
|
|
590
|
+
disabled,
|
|
591
|
+
style: selectStyle,
|
|
592
|
+
onChange: (e) => edit("summaryModel", e.target.value)
|
|
593
|
+
}, [
|
|
594
|
+
h("option", { value: "" }, "复用当前会话模型"),
|
|
595
|
+
...modelOptions.map((o) => h("option", { value: o.value }, o.label))
|
|
596
|
+
]), "summaryModel"),
|
|
597
|
+
toggle(t("feedbackEnabledLabel"), t("feedbackEnabledHint"), "feedbackEnabled"),
|
|
598
|
+
row(t("summaryMaxTokensLabel"), t("summaryMaxTokensHint"), h("input", num("summaryMaxTokens")), "summaryMaxTokens"),
|
|
599
|
+
row(t("projectMaxTokensLabel"), t("projectMaxTokensHint"), h("input", num("projectMaxTokens")), "projectMaxTokens")
|
|
600
|
+
])
|
|
593
601
|
]),
|
|
594
602
|
h("div", { style: cardStyle }, [
|
|
595
603
|
h("p", { style: groupTitleStyle }, t("storage")),
|
|
596
604
|
row(t("userPathLabel"), t("userPathHint"), h("input", { ...num("userMemoryPath"), type: "text" }), "userMemoryPath"),
|
|
597
605
|
row(t("wsDirLabel"), t("wsDirHint"), h("input", { ...num("workspaceMemoryDir"), type: "text" }), "workspaceMemoryDir"),
|
|
598
|
-
row(t("retentionLabel"), t("retentionHint"), h("input", num("dailyLogRetentionDays")), "dailyLogRetentionDays"),
|
|
606
|
+
row(t("retentionLabel"), draft.memoryMode === "hybrid" ? t("retentionHintHybrid") : t("retentionHint"), h("input", num("dailyLogRetentionDays")), "dailyLogRetentionDays"),
|
|
599
607
|
row(t("userBudgetLabel"), t("userBudgetHint"), h("input", num("userBudgetChars")), "userBudgetChars"),
|
|
600
608
|
row(t("wsBudgetLabel"), t("wsBudgetHint"), h("input", num("workspaceBudgetChars")), "workspaceBudgetChars")
|
|
601
609
|
]),
|
package/lib/hybrid/prompts.mjs
CHANGED
|
@@ -37,6 +37,8 @@ export function SUBAGENT_SYSTEM() {
|
|
|
37
37
|
"6. 今日日志为空(新的一天)时直接用 append/new_section 建章节写入即可。\n" +
|
|
38
38
|
"7. 需要读取日志章节(目录模式回喂时)用 log_read_section;需要多个章节时务必在单次调用中把 sections 数组全部传齐,避免多轮往返浪费轮次。\n" +
|
|
39
39
|
"\n" +
|
|
40
|
-
"
|
|
40
|
+
"【输出】全程只做上述两件事:要么纯文本收尾,要么调工具写日志后收尾。不要向用户提问,不要输出多余解释。\n" +
|
|
41
|
+
"\n" +
|
|
42
|
+
"【环境边界】本环境不是代码执行环境,run_code 等工具均不存在;不要模仿上文出现过的任何工具调用,只能用 log_write_ops / log_read_section。"
|
|
41
43
|
);
|
|
42
44
|
}
|
package/lib/hybrid/subagent.mjs
CHANGED
|
@@ -17,6 +17,7 @@ import { HYBRID_PROACTIVE, SUBAGENT_SYSTEM } from "./prompts.mjs";
|
|
|
17
17
|
export { HYBRID_PROACTIVE };
|
|
18
18
|
|
|
19
19
|
const MAX_ROUNDS = 6; // 循环轮次上限(含首轮);超限降级
|
|
20
|
+
const MAX_RETRY = 3; // 未知工具触发的催促重试预算(v1.6.3,人定)
|
|
20
21
|
const SURFACE = new Set(["user/message", "assistant/message", "tool/result"]);
|
|
21
22
|
|
|
22
23
|
// 日志文件写锁(全局 promise 链串行化):子 agent 落盘与手动蒸馏按钮/其他写路径并发防护。
|
|
@@ -146,7 +147,16 @@ async function execLoopTool(block, logFiles, cfg) {
|
|
|
146
147
|
if (!ops.length) return { ok: false, message: "ops 为空。" };
|
|
147
148
|
return await applyLogOps(logFiles, todayISO(), ops);
|
|
148
149
|
}
|
|
149
|
-
return {
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
unknown: true,
|
|
153
|
+
name,
|
|
154
|
+
message:
|
|
155
|
+
`工具 ${name} 不存在,调用已拒绝。本环境仅提供两个工具:\n` +
|
|
156
|
+
`- log_write_ops:写入今日日志(ops 数组,支持 append / new_section / mark_delete)\n` +
|
|
157
|
+
`- log_read_section:读取今日日志中指定章节(sections 数组)\n` +
|
|
158
|
+
`请立即改用 log_write_ops 提交 ops 完成本轮写入;不要调用其他工具,也不要直接结束。`,
|
|
159
|
+
};
|
|
150
160
|
} catch (e) {
|
|
151
161
|
return { ok: false, message: `执行失败:${e?.message || String(e)}` };
|
|
152
162
|
}
|
|
@@ -214,7 +224,7 @@ export async function runMemorySubagent({ ctx, getConfig, paths, state, session,
|
|
|
214
224
|
// 调试日志(v1.6.0):与 distill.mjs 同款门控。dbgFail=失败/跳过留痕(无条件输出,排障可观测);
|
|
215
225
|
// dbg=受 distillDebugLog 开关控制的详单(模型解析/请求参数/流进度/ops 结果计数)。
|
|
216
226
|
// 隐私红线:只打计数/字符数/元数据/错误 message,绝不打印对话或日志正文文本。
|
|
217
|
-
const dbgFail = (why, extra) => console.error(`[memory-palace] subagent
|
|
227
|
+
const dbgFail = (why, extra) => console.error(`[memory-palace] subagent warn: ${why}`, extra ? JSON.stringify(extra) : "");
|
|
218
228
|
const dbg = (why, extra) => { if (!cfg.distillDebugLog) return; console.error(`[memory-palace][debug] subagent ${why}`, extra !== undefined ? JSON.stringify(extra) : ""); };
|
|
219
229
|
if (!cfg.enabled || !session || !dirs.length) {
|
|
220
230
|
dbgFail("disabled or no session/dirs", { enabled: !!cfg.enabled, hasSession: !!session, dirs: dirs.length });
|
|
@@ -308,12 +318,47 @@ export async function runMemorySubagent({ ctx, getConfig, paths, state, session,
|
|
|
308
318
|
const timeoutMs = cfg.summaryTimeoutMs || 60000;
|
|
309
319
|
|
|
310
320
|
try {
|
|
321
|
+
// v1.6.3:本轮工具执行统计——appliedWrites=成功落盘 ops 数、toolAttempts=调用过工具次数、
|
|
322
|
+
// unknownHits/unknownNames=误调未知工具次数与点名(供 stop 三态判定与催促重试文案)。
|
|
323
|
+
let appliedWrites = 0;
|
|
324
|
+
let toolAttempts = 0;
|
|
325
|
+
let unknownHits = 0;
|
|
326
|
+
let retries = 0;
|
|
327
|
+
const unknownNames = new Set();
|
|
311
328
|
for (let round = 0; round < MAX_ROUNDS; round++) {
|
|
312
329
|
const { finish, asm } = await streamTurn(ctx, { provider, model, system, messages, tools }, timeoutMs);
|
|
313
330
|
if (finish.kind === "stop") {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
331
|
+
// v1.6.3 stop 三态判定(修复:误调未知工具后模型直接收尾 → 日志丢失且断点被无脑推进)。
|
|
332
|
+
// ① 有落盘 → 正常完成,推进断点。
|
|
333
|
+
if (appliedWrites > 0) {
|
|
334
|
+
state.lastSummarizedSeq = session.seq;
|
|
335
|
+
dbg("done", { round, mode: "written", appliedWrites });
|
|
336
|
+
return { ok: true, mode: "written" };
|
|
337
|
+
}
|
|
338
|
+
// ② 从未调用任何工具 → 模型判定本轮无实质内容(noop),推进断点。
|
|
339
|
+
if (toolAttempts === 0) {
|
|
340
|
+
state.lastSummarizedSeq = session.seq;
|
|
341
|
+
dbg("done", { round, mode: "noop" });
|
|
342
|
+
return { ok: true, mode: "noop" };
|
|
343
|
+
}
|
|
344
|
+
// ③ 命中过未知工具且零写入 → 回告工具清单 + 催促重试(预算 MAX_RETRY 次)。
|
|
345
|
+
if (unknownHits > 0 && retries < MAX_RETRY) {
|
|
346
|
+
retries++;
|
|
347
|
+
const names = [...unknownNames].join("、");
|
|
348
|
+
messages.push(createUserMessage({
|
|
349
|
+
content: [{ type: "text", text:
|
|
350
|
+
`你刚才调用了不存在的工具(${names}),且尚未向日志写入任何内容,任务未完成。\n` +
|
|
351
|
+
`本轮唯一可用的写入工具是 log_write_ops(ops 支持 append / new_section / mark_delete);` +
|
|
352
|
+
`需要读取章节时用 log_read_section。请立即重新提交写入。\n` +
|
|
353
|
+
`若你重新判定本轮确实没有值得记录的内容,请输出一行纯文本说明后结束。` }],
|
|
354
|
+
source: { kind: "plugin", plugin: "memory-palace" },
|
|
355
|
+
}));
|
|
356
|
+
dbgFail("retry after unknown tool", { retries, names });
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
// ④ 重试预算耗尽 / 已知工具用错后自主放弃 → 零写入,不推进断点(下一轮 turn/end 补蒸)。
|
|
360
|
+
dbgFail("no write applied", { round, toolAttempts, unknownHits, retries });
|
|
361
|
+
return { ok: false, mode: "no-write" };
|
|
317
362
|
}
|
|
318
363
|
if (finish.kind !== "tool-calls") {
|
|
319
364
|
// max-tokens 等异常收尾:返回失败,断点不推进——下一次 turn/end 子代理自动补蒸。
|
|
@@ -325,7 +370,13 @@ export async function runMemorySubagent({ ctx, getConfig, paths, state, session,
|
|
|
325
370
|
const calls = asm.blocks().filter((b) => b.type === "tool-call");
|
|
326
371
|
dbg("tool-calls round", { round, calls: calls.length, names: calls.map((c) => c.name) });
|
|
327
372
|
for (const call of calls) {
|
|
373
|
+
toolAttempts++;
|
|
328
374
|
const result = await execLoopTool(call, logFiles, cfg);
|
|
375
|
+
if (result.unknown) {
|
|
376
|
+
unknownHits++;
|
|
377
|
+
unknownNames.add(call.name);
|
|
378
|
+
}
|
|
379
|
+
if (result.ok && result.applied > 0) appliedWrites += result.applied;
|
|
329
380
|
const body = result.ok && result.content !== undefined ? String(result.content) : JSON.stringify(result);
|
|
330
381
|
messages.push(
|
|
331
382
|
createToolResultMessage({
|
package/lib/index.js
CHANGED
|
@@ -56,16 +56,16 @@ export const Config = Schema.object({
|
|
|
56
56
|
// ---- v1.1.0:记忆模式(plugin=记忆公民指令+轮次轻量+错误捕获;smart=LLM 智能会话摘要)----
|
|
57
57
|
// v1.6.0:+hybrid(子 agent 自动维护日志 + agent 主动维护 MEMORY.md),三档并存,切换需重启 dsh。
|
|
58
58
|
memoryMode: Schema.union(["plugin", "smart", "hybrid"]).default("plugin").description("记忆模式:plugin=记忆公民指令+轮次轻量+错误捕获;smart=LLM 智能会话摘要(summary→每日日志 + durable→MEMORY.md);hybrid=记忆子代理自动维护今日日志(标删去重)+ agent 主动维护 MEMORY.md(章节化写入/整章节替换/门禁内全量重整)。切换需重启 dsh 生效。"),
|
|
59
|
-
summaryModel: Schema.string().default("").description("
|
|
59
|
+
summaryModel: Schema.string().default("").description("记忆插件当前使用的模型(智能模式会话摘要 / 手动蒸馏 / hybrid 记忆子代理共用)。留空=复用当前会话 provider/model;也可填 provider/model(如 deepseek/deepseek-chat)固定廉价模型省 token。"),
|
|
60
60
|
summaryTimeoutMs: Schema.number().default(60000).description("蒸馏 LLM 调用的超时(毫秒),超时视为失败并降级;覆盖智能模式摘要与手动蒸馏两条链路;默认 60000(60s)。"),
|
|
61
61
|
distillDebugLog: Schema.boolean().default(false).description("调试开关:向 dsh 服务端 stderr 输出蒸馏 LLM 调用诊断。distillLogLevel=info 时仅输出元数据(模型解析/请求参数/流进度/错误详情,不含文本);distillLogLevel=debug 会额外打印 LLM 原始响应文本(分隔符包裹),仅限受信本地排障开启。"),
|
|
62
62
|
// ---- v1.4.1:蒸馏 stderr 日志级别(平铺键,不进 UI;默认 info;distillDebugLog=true 时生效) ----
|
|
63
63
|
distillLogLevel: Schema.string().default("info").description("蒸馏 stderr 日志级别:info=仅元数据诊断(默认,不打印 LLM 原始响应);debug=额外打印 LLM 原始响应文本(分隔符包裹),仅限受信本地排障开启。无需 UI 配置,经 profile/settings.yaml 设置 distillLogLevel 键。"),
|
|
64
64
|
// ---- v1.4.0:智能模式最终输出软预算(v1.4.1 起语义变更:prompt 软约束,思考不受限;实际硬上限由模型自身 maxTokens 决定) ----
|
|
65
|
-
summaryMaxTokens: Schema.number().default(2000).description("
|
|
66
|
-
projectMaxTokens: Schema.number().default(8000).description("手动「蒸馏项目记忆」LLM
|
|
65
|
+
summaryMaxTokens: Schema.number().default(2000).description("会话摘要 LLM 的最终输出软预算(prompt 约束,思考不受限;实际硬上限由模型自身 maxTokens 决定)。默认 2000;可调大以容纳更多 durable 事实。"),
|
|
66
|
+
projectMaxTokens: Schema.number().default(8000).description("手动「蒸馏项目记忆」LLM 的最终输出软预算(prompt 约束,思考不受限;实际硬上限由模型自身 maxTokens 决定)。默认 8000。"),
|
|
67
67
|
// ---- v1.4.0:蒸馏时回喂存量记忆(特性3,默认关;开启后自动智能模式 turn/end 与手动蒸馏按钮均回喂,delete 仅手动放开) ----
|
|
68
|
-
feedbackEnabled: Schema.boolean().default(false).description("
|
|
68
|
+
feedbackEnabled: Schema.boolean().default(false).description("每次蒸馏时把项目级 + 用户级 MEMORY.md 全文(逐行编号、无截断)回喂给 LLM,使其能基于既有记忆做增量维护。delete 仍仅手动蒸馏按钮开放,自动模式跳过(防误删)。hybrid 模式下仅手动触发蒸馏受影响(自动路径走记忆子代理,自带日志回喂)。默认关。"),
|
|
69
69
|
// ---- v1.6.0:hybrid 模式配置(仅 memoryMode=hybrid 时生效) ----
|
|
70
70
|
reorgCooldownDays: Schema.number().default(7).description("hybrid 模式:项目级 MEMORY.md 全量重整的冷却天数(距上次重整)。与「超出注入预算」双条件同时满足才允许 memory_reorganize;时间戳以 HTML 注释落在 MEMORY.md 文件尾。"),
|
|
71
71
|
subagentLogBudget: Schema.number().default(20000).description("hybrid 模式:记忆子代理回喂今日工作日志的字符上限。超出时仅回喂章节目录,子代理用 log_read_section 按需读取章节。"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-memory-palace",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3-alpha.4",
|
|
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",
|