dsh-memu-memory 1.1.0 → 1.1.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/AGENTS.md +3 -1
- package/README.md +5 -3
- package/README.zh.md +4 -2
- package/docs/memory-semantics.md +57 -0
- package/docs/troubleshooting.md +366 -315
- package/lib/client.js +78 -51
- package/lib/cycle.js +53 -7
- package/lib/inbound.js +9 -1
- package/lib/index.js +25 -4
- package/lib/inject.js +66 -21
- package/lib/memory.js +41 -34
- package/lib/migrate.js +119 -0
- package/lib/preset-scope.js +121 -0
- package/lib/private.js +97 -6
- package/lib/prompts/private-policy.coding.md +1 -1
- package/lib/prompts/private-policy.md +1 -1
- package/lib/prompts/private-policy.mixed.md +1 -1
- package/lib/prompts/private-policy.rp.md +1 -1
- package/lib/prompts/system-guide.md +1 -1
- package/lib/remote-summary.js +5 -1
- package/lib/rpc.js +13 -14
- package/lib/state.js +26 -9
- package/lib/tools.js +8 -5
- package/lib/visibility.js +63 -0
- package/package.json +1 -1
- package/scripts/migrate-visibility.mjs +94 -0
package/AGENTS.md
CHANGED
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
待复核的记忆被用上 → T3.9 改了没反应 / 没有 memu_* → T3.10
|
|
46
46
|
待发区冒出整理提示 → T3.11 新对话读不到文件夹记忆 → T3.12
|
|
47
47
|
注入整段没了 → T3.13 日期语义错 / 看不见日期 → T3.14
|
|
48
|
-
保存成功但没变 / 字段改不回来 → T3.15
|
|
48
|
+
保存成功但没变 / 字段改不回来 → T3.15 记忆凭空消失 / 侧边栏空 → T3.17
|
|
49
|
+
弹窗选了却两侧都勾上 → T3.16 聊很久一条记忆都没写 → T3.18
|
|
50
|
+
人格预设会话里完全没有记忆 → T3.19
|
|
49
51
|
```
|
|
50
52
|
|
|
51
53
|
---
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ It is **local-first by default**. The default `agent` backend stores full text i
|
|
|
30
30
|
> [!WARNING]
|
|
31
31
|
> **Early-stage software.** This plugin is still early and may contain unforeseen errors, bugs or breaking changes. Back up your data, and please [report an issue](https://github.com/Tkingxiao/dsh-memu-memory/issues) or send a pull request — feedback helps the project improve.
|
|
32
32
|
|
|
33
|
-
> **Status:** 1.1.
|
|
33
|
+
> **Status:** 1.1.2. The first public release was 1.0.0. The manual now lives in [`docs/`](docs/), with [`AGENTS.md`](AGENTS.md) as a short index. Back up `~/.dsh/dsh-memu-memory` before upgrades, and read [Compatibility & limits](#compatibility--limits) before storing data you cannot re-create.
|
|
34
34
|
|
|
35
35
|
## Screenshots
|
|
36
36
|
|
|
@@ -62,7 +62,7 @@ All screenshots are the real WebUI on isolated example data, not anyone's memori
|
|
|
62
62
|
- **Memory fades unevenly.** Recency, access count, arousal, mood congruence, peak and end effects, primacy, habituation and flashbulb accuracy all feed one strength score. A vivid memory can be more confident than it is accurate, and the UI says so.
|
|
63
63
|
- **Provenance is a fact, not a style.** Every entry carries `source` (`user_said` / `inferred` / `imagined` / `told`), `confidence`, `accuracy`, and disclosure rules. A vague recollection cannot impersonate a quote.
|
|
64
64
|
- **Contradictions wait.** A write that rewrites or contradicts an existing entry lands as `pending_review`: it is not injected, not recalled, and appears in a review queue until someone accepts or rejects it.
|
|
65
|
-
- **Secrets stay excluded.** `
|
|
65
|
+
- **Secrets stay excluded.** `secret` visibility, group-chat channels, characters, worlds, branches and `knownBy` all constrain reads and edits. Automatic recall never injects a `secret` memory, and a `secret` is still readable by an explicit recall from the same folder — it hides a memory from the prompt, it is not a lock. What actually separates two conversations in one folder is the `context` scope (`channelId` / `characterId` / `worldId` / `branchId`); a blank scope on both sides means one shared scope, which is the point of a folder. The old `visibility: 'session'` level is gone — reading turns it into `shared` with its `context` untouched, and `node scripts/migrate-visibility.mjs` rewrites libraries that still store it (`--apply`, backs up first).
|
|
66
66
|
- **People and stories are structured.** Group chat uses stable `speakerId` / `channelId`, not display names. RP uses `characterId` / `worldId` / `branchId`. Relationships are edges with a note and confidence, entities can be renamed without rewriting memory bodies, and the current relationship state (familiarity, trust, warmth, boundaries, promises) is a snapshot that keeps its history and evidence.
|
|
67
67
|
- **Images are pointers and captions, not pretend vision.** Attachments are deduplicated by SHA-256, quota-limited and tiered; an image without a description is remembered as "received an image", never as a scene the model did not see.
|
|
68
68
|
- **Housekeeping happens in the background.** Consolidation runs in a seeded fork sub-session, never as an editable turn in your chat. Failed runs back off instead of reporting success.
|
|
@@ -182,7 +182,7 @@ To use the `api` backend, point it at an OpenAI-compatible **embedding** endpoin
|
|
|
182
182
|
|
|
183
183
|
1. Install, then restart DSH.
|
|
184
184
|
2. Open **MemU WebUI** from the sidebar (or Settings → MemU).
|
|
185
|
-
3. New conversations ask once whether this chat should use memory: private only, global only, both, or none. **Remember my choice** skips the question later.
|
|
185
|
+
3. New conversations ask once whether this chat should use memory: private only, global only, both, or none. **Remember my choice** skips the question later. The card you pick **sets both switches at once**, so the sidebar shows the card you chose; the advanced "existing / new library" pick only changes which library the private layer reads, never the two switches.
|
|
186
186
|
4. If you want a folder-wide ceiling, set it under **文件夹** — a folder can forbid private or global memory, and the chat switches will respect that ceiling.
|
|
187
187
|
5. Talk. The agent writes private memories itself. The **MemU 记忆** wall is where you review, edit, archive, link and export them.
|
|
188
188
|
|
|
@@ -288,6 +288,7 @@ the idle window starts from real message activity or the agent's return to idle.
|
|
|
288
288
|
- **No cloud sync, no accounts, no cross-device sync.** This is a local plugin with no server-side identity.
|
|
289
289
|
- **Images without vision:** without an optional caption/vision endpoint, an image memory is a pointer plus what a person wrote about it. The plugin does not claim to see pixels.
|
|
290
290
|
- **Poisoned v4 sessions:** historical `format v4 message requires a producer-owned source kind` rows can be diagnosed but not rewritten; the plugin never edits private session files.
|
|
291
|
+
- **Agent presets:** a conversation whose preset (`i-am-yuike`, `yuike-standard`, …) carries its own `cordis.yml` composes its model-facing plugins from that list alone, and its scope never delivers `agent/pre-step` to this plugin. `lib/preset-scope.js` attaches the memory anchor on such an agent's own context at runtime, so **recall works** — but the `memu_*` **tools do not exist there**, because a preset that does not list this plugin has no tool rows. Write memories from a standard conversation. The plugin never edits anyone's preset files.
|
|
291
292
|
- **"Tomorrow" is resolved at write time.** A relative day (今天 / 明天 / 后天 / today / tomorrow) together with a month-day settles into one dated memory; a memory that only says "sometime next month" keeps no date rather than inventing one. A date that was already written as `MM-DD` is not rewritten — the fix applies to new writes.
|
|
292
293
|
- **Not in scope:** cloud MemU integration, source backfill for old entries, automatic repair of already-written v4 corruption.
|
|
293
294
|
|
|
@@ -299,6 +300,7 @@ npm test # full suite; the isolated real-engine
|
|
|
299
300
|
npm run check # syntax + i18n key alignment + package.json
|
|
300
301
|
npm run build:graph # rebuild shipped offline assets after graph source changes
|
|
301
302
|
node scripts/acceptance-local.mjs # 50 automated acceptance checks
|
|
303
|
+
node scripts/migrate-visibility.mjs # report (add --apply to rewrite) libraries that still store the removed session level
|
|
302
304
|
node --import ./tests/loader-register.mjs scripts/preview.mjs --port 7789
|
|
303
305
|
```
|
|
304
306
|
|
package/README.zh.md
CHANGED
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
- **记忆会不均匀地淡。** 新近、访问次数、唤醒度、情绪同调、峰终、首因、习惯化、闪光灯记忆的准确度共同参与强度;一条生动但可能记错的记忆会显示「细节未必准」,而不是假装确定。
|
|
63
63
|
- **来源是事实,不是文风。** 每条记忆带 `source`(`user_said` / `inferred` / `imagined` / `told`)、`confidence`、`accuracy` 与说出口径。模糊的推断不能冒充原话。
|
|
64
64
|
- **矛盾先挂起。** 与已有记忆同题改写或说法相反的新条进入 `pending_review`:不注入、不召回,只出现在复核队列,等人或整理作业裁决。
|
|
65
|
-
- **秘密不进自动召回。** `
|
|
65
|
+
- **秘密不进自动召回。** `secret`、群聊频道、角色、世界线、剧情分支与 `knownBy` 共同约束读写;`secret` 永远不会被自动注入,但同文件夹里**主动检索仍然读得到**——它挡的是「自己冒出来」,不是保险箱。真正把同一文件夹里的两段对话隔开的是 `context` 作用域(`channelId` / `characterId` / `worldId` / `branchId`);两边都没填就是同一个作用域,这正是「文件夹」的含义。旧的 `visibility: 'session'` 级别已删除:读到就按 `shared` 处理、`context` 原样保留,仍存着该级别的库用 `node scripts/migrate-visibility.mjs` 重写(`--apply` 才写,先备份)。
|
|
66
66
|
- **人与故事是有结构的。** 群聊用稳定的 `speakerId` / `channelId`,不拿显示名当身份;RP 用 `characterId` / `worldId` / `branchId` 隔离知识。关系边有理由和置信度,实体改名不动记忆正文,关系当前状态(熟悉、信任、温度、边界、承诺)是带证据和历史快照。
|
|
67
67
|
- **图片是指针加描述,不是假装能看图。** 附件按 SHA-256 去重、有配额、分三级留存;没有描述时只记「收到一张图片」,绝不编造画面。
|
|
68
68
|
- **整理在后台。** 整理跑在种子 fork 子会话里,不会在你的待发区多出一轮;失败退避重试,不伪记成功。
|
|
@@ -182,7 +182,7 @@ npx --package dsh-memu-memory dsh-memu-memory-setup
|
|
|
182
182
|
|
|
183
183
|
1. 安装后重启 DSH。
|
|
184
184
|
2. 从右侧栏打开 **MemU WebUI**(或设置 → MemU)。
|
|
185
|
-
3. 新会话会问一次:这个对话要不要记忆——只用私有 / 只用全局 / 私有 + 全局 /
|
|
185
|
+
3. 新会话会问一次:这个对话要不要记忆——只用私有 / 只用全局 / 私有 + 全局 / 不用。「记住我的选择」之后不再问。选哪张卡就**同时定下两个开关**,侧边栏显示的就是你点的那张卡;高级区块里「选已有记忆库 / 新建记忆库」只改记忆落在哪个库,不改这两个开关。
|
|
186
186
|
4. 如果想按文件夹设上限,去 **文件夹**:文件夹可以禁止私有或全局记忆,对话里的开关会受这个上限约束。
|
|
187
187
|
5. 正常对话。私有记忆由 agent 自己写;**MemU 记忆** 墙用来审阅、编辑、归档、连边和导出。
|
|
188
188
|
|
|
@@ -280,6 +280,7 @@ return { content: originalContent, meta: { ...originalMeta, memoryInbound: batch
|
|
|
280
280
|
- **没有云同步、账号或跨设备同步。** 这是本地插件,没有服务端身份。
|
|
281
281
|
- **没有视觉时:** 图片记忆只是「指针 + 人写的描述」。插件不会声称看过像素。
|
|
282
282
|
- **v4 污染会话:** 历史 `format v4 message requires a producer-owned source kind` 行只能诊断,不能改写;插件不会编辑私有会话文件。
|
|
283
|
+
- **人格预设(agent preset):** 预设(`i-am-yuike`、`yuike-standard` 等)自带 `cordis.yml`,会话的模型可见插件集只由那份清单决定,它的 scope 也不会把 `agent/pre-step` 送到本插件。`lib/preset-scope.js` 会在运行时把「记忆锚点」挂到该 agent 自己的 ctx 上,所以**注入能用**;但那里**没有 `memu_*` 工具**——清单里没有这一行就没有工具行。要写记忆请在标准会话里写。插件不会改任何人的预设文件。
|
|
283
284
|
- **相对日期在写入时结算:** 「今天 / 明天 / 后天 / today / tomorrow」加上一个月日落成带年份的日期;只说「下个月某天」的记忆不产生日期,也不替它编一个。已经按 `MM-DD` 写进去的旧条目不会被改写——这条只对新写入生效。
|
|
284
285
|
- **不在范围:** 云端 MemU 联调、旧条目的 source 回填、已写坏 v4 消息的自动修复。
|
|
285
286
|
|
|
@@ -291,6 +292,7 @@ npm test # 全量测试;真实引擎用例在
|
|
|
291
292
|
npm run check # 语法 + i18n 键对齐 + package.json
|
|
292
293
|
npm run build:graph # 修改图谱源码后重建随包分发的离线资源
|
|
293
294
|
node scripts/acceptance-local.mjs # 50 条自动验收
|
|
295
|
+
node scripts/migrate-visibility.mjs # 报告(--apply 才重写)仍存着旧 session 级别的库
|
|
294
296
|
node --import ./tests/loader-register.mjs scripts/preview.mjs --port 7789
|
|
295
297
|
```
|
|
296
298
|
|
package/docs/memory-semantics.md
CHANGED
|
@@ -48,4 +48,61 @@
|
|
|
48
48
|
- RP 与 coding 是**内容**差异:coding 记事实(决定、约束、踩过的坑、工程偏好),召回当「可能过期的事实」,与代码冲突时以代码为准;rp 记经验(具体瞬间、半句原话、身体感觉、没说出口的话),允许模糊记错,不确定就标低 `confidence`。
|
|
49
49
|
- **KV cache**:section 文本随 domain 变,但同一会话内恒定,缓存不受影响;中途改 domain 会让该会话失效一次缓存。别在文档里写「文本恒定」。
|
|
50
50
|
|
|
51
|
+
### 8.6 可见范围只剩两档,它决定「自动浮现」而不是「谁能读」
|
|
52
|
+
|
|
53
|
+
- `shared`(默认):库级,整个文件夹共用。`secret`:只是「不自动推给你」的开关,**不是保险箱**。
|
|
54
|
+
- 按通道分开看:
|
|
55
|
+
|
|
56
|
+
| 通道 | `shared` | `secret` |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| 每回合锚点 / pin / 纪念日 | ✅ | ❌ |
|
|
59
|
+
| 自动召回注入 | ✅ | ❌ |
|
|
60
|
+
| 随机回响 cue / 短期到期提示 | ✅ | ❌ |
|
|
61
|
+
| 模型主动 `memu_private_recall` | ✅ | ✅ |
|
|
62
|
+
| `memu_private_list` / 侧边栏 / 记忆墙 | ✅ | ✅ |
|
|
63
|
+
| 附件像素 | ✅ | ❌(`hidden: true`;`never_say` 的 caption 也不回显) |
|
|
64
|
+
|
|
65
|
+
- 所以 `secret` 的实际边界是「**不被自动注入、不当回响源、附件不出像素**」;同一文件夹里另一个会话**主动检索时照样能拿到**。它挡的是「自己冒出来」,不是「别人查到」。要「跨会话绝不外泄」,靠 §8.7 的上下文边界,不是 `secret`。
|
|
66
|
+
- 「只有我知道」= `disclosure: never_say`(不许说出口)+ `secret`(不许自动浮现)两个字段的组合,不是加密。侧边栏和记忆墙始终能看到正文——这是**事后监督**的设计,不是疏漏。
|
|
67
|
+
- 全局 curator 读的是会话日志与全局库,不读私有库条目(`compactGlobalIndex`),所以 `secret` 不会被复制进「每会话都注入」的全局记忆;跨文件夹(不同库)之间也读不到。
|
|
68
|
+
|
|
69
|
+
### 8.7 上下文作用域:`channelId / characterId / worldId / branchId` + `knownBy`
|
|
70
|
+
|
|
71
|
+
- 边界是这四个字段(`lib/context.js` 的 `BOUNDARIES`);`speakerId` 只是身份标签,**不参与可见性**;`knownBy` 是「谁知道」的白名单,按当前 `characterId` 判。
|
|
72
|
+
- 会话侧是 `binding.memoryContext`(+ `sceneTime`),入口 RPC `setMemoryContext`(侧边栏「记忆上下文」表单,`lib/client.js` 的 `contextScope`)。**它不由宿主自动提供**:没填就是 `{}`,等于整个文件夹共享——两个会话都没填,它们在记忆层就是同一个上下文。
|
|
73
|
+
- 写端只能收紧:`{...binding.memoryContext, ...传入 context}`;改边界或放宽一律 `memory context cannot widen or change the bound conversation`(传空字符串也算放宽)。
|
|
74
|
+
- 读端严格相等:条目有某边界字段 → 必须等于当前会话同名字段;条目没有 → 不限制;`knownBy` 有值且不含当前角色 → 不可见。**宽会话看不到窄条目**(条目 `characterId=hero`、会话没设角色 → 不等 → 看不到)。
|
|
75
|
+
- **存储不按上下文分库**:一个文件夹 = 一个库 = `index/<libraryId>.json` 一个文件,所有上下文条目同库共存,靠每条 entry 的 `context` 字段区分、读取时过滤。于是「同群组不同角色」是同一个文件里 `characterId` 不同的两条,「不同群组同角色」是 `channelId` 不同的两条,互相都看不到。
|
|
76
|
+
- 去重与矛盾检测也按上下文分组(`sameFactContext` = 五个 IDENTITY 全等):只有 context 完全一致才算「同一件事」;不同 `speakerId` 的同标题不算矛盾,不同世界/分支的两种说法可以并存。
|
|
77
|
+
- 记忆墙 `browseLibrary` 不带 session,显示整库——这是唯一能编辑「别处上下文」条目的通路,也是修可见范围的兜底入口。
|
|
78
|
+
|
|
79
|
+
### 8.8 `session` 级别已删除,老数据升级为 `shared`
|
|
80
|
+
- 曾经有第三档 `visibility: 'session'`:条目绑定写下它的那段对话,只有那段对话能召回。**它在三种状态下都错**:①会话还在——同文件夹的其它对话读不到,而「同文件夹共享」正是这个插件存在的理由;②会话被删——条目变成谁也读不到的孤儿(侧边栏空白、记忆凭空消失就是这么来的);③想让人读到——模型只能改成 `shared`,于是「作用域」变成了一次性开关,而不是约束。真正需要「只给某个角色/某条世界线看」的场景由 §8.7 的 `context` 表达,那一维是可读、可审计、可放宽的。
|
|
81
|
+
- 升级:读到 `visibility: 'session'` 一律当 `shared`(`lib/visibility.js` 的 `migrateEntryVisibility`),**`context` 原封不动**——原本限定在某个角色/分支的条目,升级后仍然只有那个上下文看得到,丢掉的只是「哪段对话写的」这一维(以及 `sessionId` 字段)。标记 `migratedFromVisibility: 'session'` + `visibilityMigratedAt`,便于事后审计。
|
|
82
|
+
- 落在哪一层:`lib/state.js` 的 `loadPrivateIndex` 在读取时升级视图(所有读写都经过这里,消费者不必知道该级别存在),基线仍是磁盘原文,所以下一次普通写入就会把升级落盘;`lib/migrate.js` 的周期巡检与侧边栏轮询(60 秒节流)把没人再写的库也重写掉。
|
|
83
|
+
- 手工/一次性:`node scripts/migrate-visibility.mjs`(默认只报告,`--apply` 先 `backupDatabases()` 再写,`--json` 机器可读)。退出码 3 = 有老数据待转换,1 = 转换失败。
|
|
84
|
+
- 导入导出:老版本导出的 `session` 条目按 `shared` 导入(同 `migratedFromVisibility` 标记),报告里记在 `downgraded` 并写明「session -> shared,要收窄请补 context」——丢一条记忆比放宽一条更糟,但「读者从一段对话变成整个文件夹」必须让用户看得见。
|
|
85
|
+
- 工具面:`visibility` 只接受 `shared` / `secret`,传 `session` 会得到解释性报错(而不是静默降级);面板下拉与中英文标签同步删掉了这一档。
|
|
86
|
+
|
|
87
|
+
### 8.9 空闲整理:什么时候跑,以及为什么可以什么都不写
|
|
88
|
+
- 触发:`settings.sleepConsolidation` 开着时,每 5 分钟扫一遍(`lib/cycle.js` 的 `runSleepPass`),挑「`lastTurnAt` 早于 `lastSleepAt` 且已经安静 ≥ `sleepAfterIdleMinutes`」的会话,交给 `requestPrivateConsolidation` 起一个 fork 去读转录、写记忆。**默认 3 分钟**(`lib/state.js` 的 `DEFAULT_SETTINGS`);旧值 8/20 的安装保留原选择,只是新装默认更短。
|
|
89
|
+
- 应用启动后 8 秒补跑一次(`STARTUP_SWEEP_MS`),因为定时器只在应用开着时存在:一段对话如果是在应用关着的时候结束的,它永远等不到那个「空闲窗口」——用户一回来发消息,`lastTurnAt` 就被顶新了。补偿每次最多处理 **2 个**会话(`runSleepPass` 的 `limit`),按最近活动排序。
|
|
90
|
+
- **有新回合 ≠ 该写记忆。** 进 fork 之前先做一次本地评估(`lib/private.js` 的 `assessConsolidationValue`,只看 `lastSleepSeq` 之后的转录):①没有任何人类消息(只有插件通知、工具结果、心跳)→ 跳过;②只有一条**纯应答**(「谢谢」「好的」「ok」「收到」,且没有任何工具调用)→ 跳过。**这里刻意不按字数判断**:字数少的偏好句(「我不吃香菜」)比一千字的闲聊更该留,长度是坏代理。其余一律交给 fork——**跳过只是省一次 fork,「该不该留」仍由整理提示词判断**,它完全可以读完写 0 条。宁可多跑一次,也不要在本地猜「这条不重要」。
|
|
91
|
+
- 评估通过但整理写了 0 条 = 正常成功(`lastSleepAt` 前移),不会每小时重来。
|
|
92
|
+
- 会话被删:host 对 `readSession` 报 `session "…" not found`,这是**不变量**而不是瞬时故障。`runSleepPass` 一旦看到就把 binding 标 `sessionGone: true` 并清掉重试计数,此后直接跳过(以前会按 2 的幂退避、封顶 1 小时,永远重试);同名会话后来真的收到新消息时(`lib/inbound.js`)会清掉这个标记。
|
|
93
|
+
- 手动「整理这场对话」(RPC `generatePrivate`)带 `force: true`,跳过上面那道评估:用户已经决定了。
|
|
94
|
+
|
|
51
95
|
---
|
|
96
|
+
|
|
97
|
+
### 8.10 人格预设(agent preset)会话:接得上注入,接不上工具
|
|
98
|
+
|
|
99
|
+
预设会话的「模型可见插件集」不是 host composition,而是它自己那份 `cordis.yml`——整棵子树是独立 scope,`agent/pre-step` 只向自己的祖先冒泡,到不了部署级实例的监听器。所以预设会话最初的表现是「连 binding 都没有」,不是「写了没读到」。
|
|
100
|
+
|
|
101
|
+
插件侧的处理(`lib/preset-scope.js`):每 10 秒枚举 `ctx.get('agents').list()`,沿 `agent.ctx.fiber` 往上找本插件的 fiber——找不到(= 不在自己这棵树里)才在**该 agent 自己的 ctx** 上补挂 `registerInjection(ctx, { guide: false })`。同树的正常会话跳过,避免注入两遍;agent 消失就卸载。只挂锚点、不挂 guide,因为预设清单里没有 `memu_*` 工具,guide 会把不存在的工具说成可用。
|
|
102
|
+
|
|
103
|
+
**提示词怎么办**:`persona` 常带 `complete: true`——装配完成后它会被恢复为唯一的 system prompt 段,本插件 `systemPrompt.section()` 注册的 guide 会被整段丢弃(实测 RP 会话的 `system/message` 只有人格正文)。所以预设会话改用**消息**投放规则:首步追加一次 `<memory-guide>` 插件消息(`withGuideMessage`,按 `binding.guideMessageAt` 会话内只发一次),并注明「工具列表里没有 `memu_*` 就忽略本段」。工具确实存在的预设会话(例如 RP 里的 `yuike`,工具链里有 `memu_private_*`)因此重新拿到主动性规则,而不是只有一个 anchor。
|
|
104
|
+
|
|
105
|
+
**边界要讲清楚**:这样接上的会话只有**注入**(锚点、召回上下文),**没有工具**——工具面由预设的清单决定,宿主的 tool registry 全局层对这些会话是空的。要写记忆,得让这段对话进一次标准会话。反过来说,**不要为了这个去改别人的人格插件**:预设文件属于它的维护者,插件只能在自己的 scope 里做适配。
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|