@zooique/memora 3.0.1 → 5.0.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.
Files changed (282) hide show
  1. package/CHANGELOG.md +161 -1033
  2. package/README.en.md +46 -39
  3. package/README.md +40 -35
  4. package/config.example.json +1 -8
  5. package/dist/agent/agent.d.ts +88 -80
  6. package/dist/agent/agent.d.ts.map +1 -1
  7. package/dist/agent/agent.js +272 -221
  8. package/dist/agent/agent.js.map +1 -1
  9. package/dist/agent/assembler.d.ts +22 -21
  10. package/dist/agent/assembler.d.ts.map +1 -1
  11. package/dist/agent/assembler.js +120 -46
  12. package/dist/agent/assembler.js.map +1 -1
  13. package/dist/agent/backgroundTasks.d.ts +194 -0
  14. package/dist/agent/backgroundTasks.d.ts.map +1 -0
  15. package/dist/agent/backgroundTasks.js +314 -0
  16. package/dist/agent/backgroundTasks.js.map +1 -0
  17. package/dist/agent/budget.d.ts +23 -5
  18. package/dist/agent/budget.d.ts.map +1 -1
  19. package/dist/agent/budget.js +8 -2
  20. package/dist/agent/budget.js.map +1 -1
  21. package/dist/agent/builtinToolHandlers.d.ts +29 -9
  22. package/dist/agent/builtinToolHandlers.d.ts.map +1 -1
  23. package/dist/agent/builtinToolHandlers.js +53 -13
  24. package/dist/agent/builtinToolHandlers.js.map +1 -1
  25. package/dist/agent/builtinTools.d.ts +15 -1
  26. package/dist/agent/builtinTools.d.ts.map +1 -1
  27. package/dist/agent/builtinTools.js +111 -30
  28. package/dist/agent/builtinTools.js.map +1 -1
  29. package/dist/agent/constants.d.ts +31 -6
  30. package/dist/agent/constants.d.ts.map +1 -1
  31. package/dist/agent/constants.js +38 -8
  32. package/dist/agent/constants.js.map +1 -1
  33. package/dist/agent/contextManager.d.ts +8 -0
  34. package/dist/agent/contextManager.d.ts.map +1 -1
  35. package/dist/agent/contextManager.js +45 -3
  36. package/dist/agent/contextManager.js.map +1 -1
  37. package/dist/agent/contextPreparer.d.ts +1 -1
  38. package/dist/agent/contextPreparer.d.ts.map +1 -1
  39. package/dist/agent/contextPreparer.js +15 -10
  40. package/dist/agent/contextPreparer.js.map +1 -1
  41. package/dist/agent/guardRail.d.ts +12 -1
  42. package/dist/agent/guardRail.d.ts.map +1 -1
  43. package/dist/agent/guardRail.js +37 -2
  44. package/dist/agent/guardRail.js.map +1 -1
  45. package/dist/agent/loop.d.ts +319 -34
  46. package/dist/agent/loop.d.ts.map +1 -1
  47. package/dist/agent/loop.js +713 -110
  48. package/dist/agent/loop.js.map +1 -1
  49. package/dist/agent/managers/archiveCoordinator.d.ts +19 -4
  50. package/dist/agent/managers/archiveCoordinator.d.ts.map +1 -1
  51. package/dist/agent/managers/archiveCoordinator.js +25 -4
  52. package/dist/agent/managers/archiveCoordinator.js.map +1 -1
  53. package/dist/agent/managers/chatLockManager.d.ts +3 -9
  54. package/dist/agent/managers/chatLockManager.d.ts.map +1 -1
  55. package/dist/agent/managers/chatLockManager.js +7 -25
  56. package/dist/agent/managers/chatLockManager.js.map +1 -1
  57. package/dist/agent/managers/llmCaller.d.ts.map +1 -1
  58. package/dist/agent/managers/llmCaller.js +27 -1
  59. package/dist/agent/managers/llmCaller.js.map +1 -1
  60. package/dist/agent/managers/loopMetrics.d.ts +14 -0
  61. package/dist/agent/managers/loopMetrics.d.ts.map +1 -1
  62. package/dist/agent/managers/loopMetrics.js +15 -0
  63. package/dist/agent/managers/loopMetrics.js.map +1 -1
  64. package/dist/agent/managers/memoryInspector.d.ts +13 -15
  65. package/dist/agent/managers/memoryInspector.d.ts.map +1 -1
  66. package/dist/agent/managers/memoryInspector.js +38 -49
  67. package/dist/agent/managers/memoryInspector.js.map +1 -1
  68. package/dist/agent/managers/roundSummaryGenerator.d.ts +31 -1
  69. package/dist/agent/managers/roundSummaryGenerator.d.ts.map +1 -1
  70. package/dist/agent/managers/roundSummaryGenerator.js +81 -6
  71. package/dist/agent/managers/roundSummaryGenerator.js.map +1 -1
  72. package/dist/agent/managers/sessionArchiver.d.ts +35 -3
  73. package/dist/agent/managers/sessionArchiver.d.ts.map +1 -1
  74. package/dist/agent/managers/sessionArchiver.js +34 -3
  75. package/dist/agent/managers/sessionArchiver.js.map +1 -1
  76. package/dist/agent/managers/sessionManager.d.ts +21 -88
  77. package/dist/agent/managers/sessionManager.d.ts.map +1 -1
  78. package/dist/agent/managers/sessionManager.js +94 -278
  79. package/dist/agent/managers/sessionManager.js.map +1 -1
  80. package/dist/agent/managers/toolCallHelpers.d.ts +109 -28
  81. package/dist/agent/managers/toolCallHelpers.d.ts.map +1 -1
  82. package/dist/agent/managers/toolCallHelpers.js +93 -37
  83. package/dist/agent/managers/toolCallHelpers.js.map +1 -1
  84. package/dist/agent/messageHistory.d.ts.map +1 -1
  85. package/dist/agent/messageHistory.js +9 -5
  86. package/dist/agent/messageHistory.js.map +1 -1
  87. package/dist/agent/seed/orchestrator.d.ts +12 -1
  88. package/dist/agent/seed/orchestrator.d.ts.map +1 -1
  89. package/dist/agent/seed/orchestrator.js +15 -4
  90. package/dist/agent/seed/orchestrator.js.map +1 -1
  91. package/dist/agent/seed/prepare.d.ts.map +1 -1
  92. package/dist/agent/seed/prepare.js +9 -4
  93. package/dist/agent/seed/prepare.js.map +1 -1
  94. package/dist/agent/seed/types.d.ts +11 -4
  95. package/dist/agent/seed/types.d.ts.map +1 -1
  96. package/dist/agent/seed/types.js +2 -2
  97. package/dist/agent/textSanitize.d.ts +36 -0
  98. package/dist/agent/textSanitize.d.ts.map +1 -0
  99. package/dist/agent/textSanitize.js +55 -0
  100. package/dist/agent/textSanitize.js.map +1 -0
  101. package/dist/agent/toolExecutor.d.ts +97 -26
  102. package/dist/agent/toolExecutor.d.ts.map +1 -1
  103. package/dist/agent/toolExecutor.js +444 -78
  104. package/dist/agent/toolExecutor.js.map +1 -1
  105. package/dist/agent/toolLedger.d.ts +93 -41
  106. package/dist/agent/toolLedger.d.ts.map +1 -1
  107. package/dist/agent/toolLedger.js +114 -42
  108. package/dist/agent/toolLedger.js.map +1 -1
  109. package/dist/agent/toolResultCache.js +1 -1
  110. package/dist/agent/toolResultOffload.d.ts +8 -0
  111. package/dist/agent/toolResultOffload.d.ts.map +1 -1
  112. package/dist/agent/toolResultOffload.js +10 -3
  113. package/dist/agent/toolResultOffload.js.map +1 -1
  114. package/dist/agent/toolRunner.d.ts +16 -7
  115. package/dist/agent/toolRunner.d.ts.map +1 -1
  116. package/dist/agent/toolRunner.js +74 -29
  117. package/dist/agent/toolRunner.js.map +1 -1
  118. package/dist/agent/tracer.d.ts +13 -1
  119. package/dist/agent/tracer.d.ts.map +1 -1
  120. package/dist/agent/types.d.ts +74 -30
  121. package/dist/agent/types.d.ts.map +1 -1
  122. package/dist/code-exec/types.d.ts +9 -0
  123. package/dist/code-exec/types.d.ts.map +1 -1
  124. package/dist/index.d.ts +28 -41
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +65 -54
  127. package/dist/index.js.map +1 -1
  128. package/dist/logging/logger.d.ts +4 -1
  129. package/dist/logging/logger.d.ts.map +1 -1
  130. package/dist/logging/logger.js +5 -2
  131. package/dist/logging/logger.js.map +1 -1
  132. package/dist/memory/gcService.d.ts.map +1 -1
  133. package/dist/memory/gcService.js +3 -5
  134. package/dist/memory/gcService.js.map +1 -1
  135. package/dist/memory/inMemorySessionStore.d.ts +2 -2
  136. package/dist/memory/inMemorySessionStore.js +2 -2
  137. package/dist/memory/inMemoryStorage.d.ts +4 -3
  138. package/dist/memory/inMemoryStorage.d.ts.map +1 -1
  139. package/dist/memory/inMemoryStorage.js +2 -2
  140. package/dist/memory/inMemoryStorage.js.map +1 -1
  141. package/dist/memory/nodeSqliteStorage.d.ts +17 -0
  142. package/dist/memory/nodeSqliteStorage.d.ts.map +1 -0
  143. package/dist/memory/nodeSqliteStorage.js +393 -0
  144. package/dist/memory/nodeSqliteStorage.js.map +1 -0
  145. package/dist/memory/projectManager.d.ts +10 -20
  146. package/dist/memory/projectManager.d.ts.map +1 -1
  147. package/dist/memory/projectManager.js +27 -41
  148. package/dist/memory/projectManager.js.map +1 -1
  149. package/dist/memory/roundStore.d.ts +143 -82
  150. package/dist/memory/roundStore.d.ts.map +1 -1
  151. package/dist/memory/roundStore.js +4 -15
  152. package/dist/memory/roundStore.js.map +1 -1
  153. package/dist/memory/roundSummaryLookup.d.ts +26 -0
  154. package/dist/memory/roundSummaryLookup.d.ts.map +1 -0
  155. package/dist/memory/roundSummaryLookup.js +19 -0
  156. package/dist/memory/roundSummaryLookup.js.map +1 -0
  157. package/dist/memory/sessionStore.d.ts +19 -2
  158. package/dist/memory/sessionStore.d.ts.map +1 -1
  159. package/dist/memory/sessionStore.js.map +1 -1
  160. package/dist/memory/sourceValidation.d.ts +2 -13
  161. package/dist/memory/sourceValidation.d.ts.map +1 -1
  162. package/dist/memory/sourceValidation.js +5 -16
  163. package/dist/memory/sourceValidation.js.map +1 -1
  164. package/dist/memory/storageInterface.d.ts +26 -16
  165. package/dist/memory/storageInterface.d.ts.map +1 -1
  166. package/dist/memory/supersedeResolve.d.ts +39 -0
  167. package/dist/memory/supersedeResolve.d.ts.map +1 -0
  168. package/dist/memory/supersedeResolve.js +16 -0
  169. package/dist/memory/supersedeResolve.js.map +1 -0
  170. package/dist/memory/types.d.ts +10 -2
  171. package/dist/memory/types.d.ts.map +1 -1
  172. package/dist/memory/types.js +6 -1
  173. package/dist/memory/types.js.map +1 -1
  174. package/dist/role-pack/rolePackManager.d.ts +74 -33
  175. package/dist/role-pack/rolePackManager.d.ts.map +1 -1
  176. package/dist/role-pack/rolePackManager.js +112 -53
  177. package/dist/role-pack/rolePackManager.js.map +1 -1
  178. package/dist/role-pack/strategyKeys.d.ts +44 -0
  179. package/dist/role-pack/strategyKeys.d.ts.map +1 -1
  180. package/dist/role-pack/strategyKeys.js +55 -0
  181. package/dist/role-pack/strategyKeys.js.map +1 -1
  182. package/dist/role-pack/strategyResolver.d.ts +6 -1
  183. package/dist/role-pack/strategyResolver.d.ts.map +1 -1
  184. package/dist/role-pack/strategyResolver.js +20 -2
  185. package/dist/role-pack/strategyResolver.js.map +1 -1
  186. package/dist/role-pack/types.d.ts +5 -1
  187. package/dist/role-pack/types.d.ts.map +1 -1
  188. package/dist/security/confirmEntries.d.ts +44 -0
  189. package/dist/security/confirmEntries.d.ts.map +1 -0
  190. package/dist/security/confirmEntries.js +59 -0
  191. package/dist/security/confirmEntries.js.map +1 -0
  192. package/dist/security/pathGuard.d.ts +42 -6
  193. package/dist/security/pathGuard.d.ts.map +1 -1
  194. package/dist/security/pathGuard.js +126 -5
  195. package/dist/security/pathGuard.js.map +1 -1
  196. package/dist/skill/skillScriptRunner.d.ts +147 -15
  197. package/dist/skill/skillScriptRunner.d.ts.map +1 -1
  198. package/dist/skill/skillScriptRunner.js +479 -68
  199. package/dist/skill/skillScriptRunner.js.map +1 -1
  200. package/dist/utils/backgroundTask.d.ts +56 -34
  201. package/dist/utils/backgroundTask.d.ts.map +1 -1
  202. package/dist/utils/backgroundTask.js +130 -99
  203. package/dist/utils/backgroundTask.js.map +1 -1
  204. package/dist/utils/configResourceManager.d.ts +6 -2
  205. package/dist/utils/configResourceManager.d.ts.map +1 -1
  206. package/dist/utils/configResourceManager.js +8 -2
  207. package/dist/utils/configResourceManager.js.map +1 -1
  208. package/dist/utils/errors.d.ts +12 -2
  209. package/dist/utils/errors.d.ts.map +1 -1
  210. package/dist/utils/errors.js +12 -2
  211. package/dist/utils/errors.js.map +1 -1
  212. package/dist/utils/eventEmitter.d.ts +76 -23
  213. package/dist/utils/eventEmitter.d.ts.map +1 -1
  214. package/dist/utils/eventEmitter.js +23 -3
  215. package/dist/utils/eventEmitter.js.map +1 -1
  216. package/dist/utils/time.d.ts +8 -5
  217. package/dist/utils/time.d.ts.map +1 -1
  218. package/dist/utils/time.js +8 -5
  219. package/dist/utils/time.js.map +1 -1
  220. package/dist/utils/toError.d.ts +1 -1
  221. package/dist/utils/toError.js +1 -1
  222. package/dist/web-fetch/loginWall.d.ts +39 -0
  223. package/dist/web-fetch/loginWall.d.ts.map +1 -0
  224. package/dist/web-fetch/loginWall.js +78 -0
  225. package/dist/web-fetch/loginWall.js.map +1 -0
  226. package/dist/web-fetch/types.d.ts +8 -0
  227. package/dist/web-fetch/types.d.ts.map +1 -1
  228. package/dist/web-fetch/webFetchProvider.d.ts.map +1 -1
  229. package/dist/web-fetch/webFetchProvider.js +3 -1
  230. package/dist/web-fetch/webFetchProvider.js.map +1 -1
  231. package/dist/web-search/fetchWebSearchProvider.js +28 -23
  232. package/dist/web-search/fetchWebSearchProvider.js.map +1 -1
  233. package/docs/architecture/role-pack-authoring-guide.md +3 -1
  234. package/docs/architecture/role-pack-spec.md +2 -1
  235. package/docs/memora-api-reference.md +1349 -1175
  236. package/docs/memora-/345/215/207/347/272/247/346/214/207/345/215/227-4.x-/345/210/260-5.0.0.md +385 -0
  237. package/docs/memora-/346/216/245/345/205/245/346/214/207/345/215/227.md +91 -52
  238. package/docs/role-pack-/345/274/200/346/224/276/351/224/256/346/214/207/345/215/227.md +148 -148
  239. package/package.json +9 -4
  240. package/role-packs/README.md +41 -40
  241. package/role-packs/memora/345/212/251/346/211/213/rules.md +4 -4
  242. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/manifest.json +1 -0
  243. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/persona.md +1 -1
  244. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/rules.md +1 -0
  245. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/emotion-wave.md +1 -1
  246. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/foreshadow.md +1 -1
  247. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/outline-expand.md +32 -5
  248. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/project-init/scripts/init-novel-project.mjs +10 -6
  249. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/story-bible.md +3 -1
  250. package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/manifest.json +1 -0
  251. package/dist/agent/managers/dedupManager.d.ts +0 -85
  252. package/dist/agent/managers/dedupManager.d.ts.map +0 -1
  253. package/dist/agent/managers/dedupManager.js +0 -248
  254. package/dist/agent/managers/dedupManager.js.map +0 -1
  255. package/dist/agent/managers/goalConsistencyChecker.d.ts +0 -42
  256. package/dist/agent/managers/goalConsistencyChecker.d.ts.map +0 -1
  257. package/dist/agent/managers/goalConsistencyChecker.js +0 -178
  258. package/dist/agent/managers/goalConsistencyChecker.js.map +0 -1
  259. package/dist/agent/managers/llmJudgeHelper.d.ts +0 -21
  260. package/dist/agent/managers/llmJudgeHelper.d.ts.map +0 -1
  261. package/dist/agent/managers/llmJudgeHelper.js +0 -32
  262. package/dist/agent/managers/llmJudgeHelper.js.map +0 -1
  263. package/dist/agent/managers/memoryAdvisor.d.ts +0 -105
  264. package/dist/agent/managers/memoryAdvisor.d.ts.map +0 -1
  265. package/dist/agent/managers/memoryAdvisor.js +0 -322
  266. package/dist/agent/managers/memoryAdvisor.js.map +0 -1
  267. package/dist/agent/managers/memoryGovernance.d.ts +0 -24
  268. package/dist/agent/managers/memoryGovernance.d.ts.map +0 -1
  269. package/dist/agent/managers/memoryGovernance.js +0 -46
  270. package/dist/agent/managers/memoryGovernance.js.map +0 -1
  271. package/dist/memory/governance.d.ts +0 -17
  272. package/dist/memory/governance.d.ts.map +0 -1
  273. package/dist/memory/governance.js +0 -17
  274. package/dist/memory/governance.js.map +0 -1
  275. package/dist/memory/projectRegistry.d.ts +0 -47
  276. package/dist/memory/projectRegistry.d.ts.map +0 -1
  277. package/dist/memory/projectRegistry.js +0 -151
  278. package/dist/memory/projectRegistry.js.map +0 -1
  279. package/dist/utils/recallDefaults.d.ts +0 -16
  280. package/dist/utils/recallDefaults.d.ts.map +0 -1
  281. package/dist/utils/recallDefaults.js +0 -16
  282. package/dist/utils/recallDefaults.js.map +0 -1
@@ -1,12 +1,12 @@
1
- # Memora · 接入指南 v3.0.0
1
+ # Memora · 接入指南 v5.0.0
2
2
 
3
3
  > 帮助宿主项目开发者快速理解 Memora 的设计理念和接入方法。
4
4
  >
5
- > **当前稳定版**:v3.0.0。各版完整变更见 [CHANGELOG](../CHANGELOG.md)。
5
+ > **当前内核版本**:v5.0.0(对齐当前内核包版本 `package.json`;npm 已发布最新为 v4.0.0、v5.0.0 待发布)。各版完整变更见 [CHANGELOG](../CHANGELOG.md)。
6
6
  >
7
7
  > **对接入者有影响的迁移结论**(不含历史流水,细节见 [API 参考手册](./memora-api-reference.md)):
8
8
  > - 1.0 为正式发布,API 已稳定;2.0 起设定记忆(persona/rules/skills)解耦为纯文件 + 内存缓存,唯一归角色包、不进记忆库(ADR-025),角色管理统一走 `agent.rolePack`。
9
- > - 已移除:`SqliteStorage`(移出内核,由宿主实现 `IMemoryStorage`)、洞察层(`insight.*`)、AutoConfigRefiner / ConfigManager、记忆关系图谱与用户画像层(偏好收敛为 round-summary,冲突改用 `supersededBy` 布尔标记)。
9
+ > - 已移除:`SqliteStorage`(**原 better-sqlite3 实现**移出内核,由宿主实现 `IMemoryStorage`——注意这是 native 实现出内核,**不等于**内核不再提供任何 SQLite 实现;5.0.0 起内核另有基于 `node:*` 内建模块的 `createNodeSqliteStorage`)、洞察层(`insight.*`)、AutoConfigRefiner / ConfigManager、记忆关系图谱与用户画像层(偏好收敛为 round-summary,冲突改用 `supersededBy` 布尔标记)。
10
10
  >
11
11
  ---
12
12
 
@@ -32,13 +32,13 @@
32
32
 
33
33
  **摘要即记忆(memory-as-summary)。** Memora 的记忆只有单一轨道——**对话记忆**(round-summary 摘要,宿主持久化 + **纯关键词召回**,带 `summaryType` 语义标签);**设定**(角色包 persona/rules/skills)是 Agent 的骨骼,.md 文件 + 内存缓存,唯一归角色包、确定性注入不经过召回,不属记忆库(ADR-025)。二者边界一刀切:记忆系统只承载对话摘要、角色包承载设定;偏好类信息沉淀为摘要记忆,不设独立"用户画像"记忆层。
34
34
 
35
- **单 Agent 模型。** 一个 Agent 实例的对话与记忆由**同一组存储实例**承载(`storage` / `sessionStore` 均在构造时注入、实例级),**`switchProject()` 切换项目时复用同一实例,不重建、不丢记忆**。要按工作区彼此隔离,就各自 `new Agent`——隔离粒度由宿主决定,内核不规定。
35
+ **单 Agent 模型(一个项目一个 Agent)。** 一个 Agent 实例的对话与记忆由**同一组存储实例**承载(`storage` / `sessionStore` 均在构造时注入、实例级),**切会话不换存储、不丢记忆**。要按项目彼此隔离,就各自 `new Agent`——**隔离粒度由宿主决定,内核不规定**(形态与取舍见 [§8](#8-多项目一个项目一个-agent形态定案))。
36
36
 
37
37
  **配置文件是真理源,对话记忆由宿主持久化。** 角色包(persona/rules/skills)为纯文件 + 内存缓存,设定记忆唯一归角色包、不进记忆库(ADR-025);对话记忆(round-summary 摘要记忆,带 `summaryType` 标签)经宿主注入的 `IMemoryStorage` 持久化——**后端由宿主自选**(SQLite / JSON 文件 / 内存皆可),检索为 **纯关键词召回**(向量语义通道已随 2026-09-18 B0 收编移除,见 [API 参考手册](./memora-api-reference.md) §〇.5 构造参数表)。
38
38
 
39
39
  **内核零越界。** 核心库模块不直接调用 `console.*`(唯一日志出口为 `logging/` 单例,默认实现写 stderr)、不读 `process.stdin`、不管理 API Key、不写用户配置文件。
40
40
 
41
- **Manager 委托模式。** Agent 面类只做编排,领域操作委托给专职 Manager:`agent.rolePack`(角色包)/ `agent.tools`(工具)/ `agent.skills`(技能)/ `agent.memory`(记忆查询+写入)/ `agent.governance`(记忆治理)/ `agent.works`(作品投影)/ `agent.polish`(文本润色)共 7 个业务 Manager(另有 `projects` / `security` / `sessionManager` 等)。
41
+ **Manager 委托模式。** Agent 面类只做编排,领域操作委托给专职 Manager:`agent.rolePack`(角色包)/ `agent.tools`(工具)/ `agent.skills`(技能)/ `agent.memory`(记忆查询+写入)/ `agent.works`(作品投影)/ `agent.polish`(文本润色)共 6 个业务 Manager(另有 `projects` / `security` / `sessionManager` 等)。
42
42
 
43
43
  ```
44
44
  ┌────────────────────────────────────────────────────────────┐
@@ -51,7 +51,7 @@
51
51
  │ ┌──────────────────────────────────────────┐ │
52
52
  │ │ Memora 内核(Agent) │ │
53
53
  │ │ - chat(input) → 流式响应 │ │
54
- │ │ - 7 个业务 Manager getter(rolePack/tools/skills/memory/governance/works/polish,委托模式) │ │
54
+ │ │ - 6 个业务 Manager getter(rolePack/tools/skills/memory/works/polish,委托模式) │ │
55
55
  │ │ ⚠️ 不包含:UI / LLM 配置 / 用户配置模板 │ │
56
56
  │ └──────────────────────────────────────────┘ │
57
57
  └────────────────────────────────────────────────────────────┘
@@ -71,11 +71,13 @@
71
71
  ```
72
72
  小说项目/
73
73
  ├── .memora/ ← 项目级配置(rules + skills)+ 内核写入的 .lock
74
- └── .memora-data/ ← dataDir 指向此处(记住:内核只往这里写 projects.json 注册表)
75
- ├── projects.json ← 内核写入:项目注册表
74
+ └── .memora-data/ ← dataDir 指向此处(Agent 级资源目录;宿主注入 storage 时内核不在此落文件)
76
75
  └── <记忆库> ← 由宿主的 storage 决定形态与文件名
77
76
  ```
78
77
 
78
+ > **多项目怎么办**:一个 Agent 绑定一个项目,不做项目切换;多项目请为每个项目各创建一个
79
+ > Agent 实例。完整形态、取舍与代码示例见 [§8 多项目:一个项目一个 Agent](#8-多项目一个项目一个-agent形态定案)。
80
+
79
81
  ---
80
82
 
81
83
  ## 三、最小接入步骤
@@ -109,7 +111,8 @@ const backgroundProvider = createProviderFromConfig('background', {
109
111
  model: 'deepseek-chat', // 可用更便宜的模型
110
112
  });
111
113
 
112
- // 可选:注入存储层(不传则使用 InMemoryStorage)。后端由宿主自选,二选一即可:
114
+ // 可选:注入存储层(不传则用内核内置内存实现,仅内存不落盘;该类不挂公共面——PUB-API-PRUNE-2 收面)。
115
+ // 后端由宿主自选,二选一即可:
113
116
  const storage: IMemoryStorage = new MySqliteStorage('/path/to/memora.db'); // SQLite(同步实现天然对齐)
114
117
  // const storage: IMemoryStorage = new MyJsonStorage('/path/to/memories.json'); // JSON 文件(第一宿主 memora-vscode 的选法)
115
118
 
@@ -123,7 +126,7 @@ const agent = new Agent({
123
126
  backgroundProvider, // 后台 Provider(可选)
124
127
  configDir: '/path/to/agent-config',
125
128
  dataDir: '/path/to/novel-project/.memora-data', // 必填;相对路径会以进程 cwd 为基准,建议传绝对路径
126
- maxContextTokens: 120000,
129
+ maxContextTokens: 120000, // 示例值——缺省时以内核 AGENT_CONSTANTS.DEFAULT_MAX_CONTEXT_TOKENS 为真源,数字以该常量为准
127
130
  activeRolePack: '作家',
128
131
  permission: 'owner',
129
132
  allowedPaths: ['.'],
@@ -161,7 +164,7 @@ Agent 向宿主广播对话外事件(记忆变更、角色切换、会话分
161
164
  import type { AgentEventMap } from '@zooique/memora';
162
165
 
163
166
  agent.on('memoryAdded', (e) => console.log(`新记忆: ${e.source}:${e.name}`));
164
- agent.on('personaSwitched', (e) => console.log(`角色: ${e.from} → ${e.to}`));
167
+ agent.on('rolePackSwitched', (e) => console.log(`角色: ${e.from} → ${e.to}`));
165
168
  agent.on('memoryRecalled', (e) => console.log(`想起 ${e.count} 条记忆`));
166
169
  agent.on('sessionForked', (e) => console.log(`分叉: ${e.from} → ${e.to},${e.roundCount} 个问答闭环`));
167
170
 
@@ -235,8 +238,8 @@ const snap = agent.memory.snapshot();
235
238
  console.log('工作记忆:', snap.working.total, '条');
236
239
  console.log('引导记忆:', snap.bootstrap.total, '条');
237
240
 
238
- // 关键词搜索
239
- const hits = agent.memory.search('世界观');
241
+ // 关键词搜索(异步 API,需 await)
242
+ const hits = await agent.memory.searchByKeyword('世界观');
240
243
  hits.forEach(h => console.log(`${h.source}:${h.name}`));
241
244
 
242
245
  // 记忆库统计
@@ -263,22 +266,50 @@ if (rp) {
263
266
  }
264
267
  ```
265
268
 
266
- ### 8. 切换项目
269
+ ### 8. 多项目:一个项目一个 Agent(形态定案)
270
+
271
+ **一个 Agent 绑定一个项目**,内核不做项目切换。多项目请为**每个项目各创建一个 Agent 实例**:
267
272
 
268
273
  ```typescript
269
- // 按路径切换(最稳):传项目根目录的绝对路径,无需预先注册
270
- const ctx = await agent.switchProject('/path/to/another-novel');
271
- console.log(`已切换到:${ctx.projectName}`);
272
-
273
- // 按名切换:依赖项目注册表命中,须先注册
274
- // 注册表缺省落在 dataDir 内 —— 只有多项目共用同一 dataDir(或显式指定共同的 registryDir)时,
275
- // 按名切换才成立;若 dataDir 是项目级目录,注册表会随之落进各项目、只含自身条目,按名切换不成立。
276
- agent.projects.registerProject('/path/to/another-novel', 'another-novel');
277
- const ctx2 = await agent.switchProject('another-novel');
274
+ // 项目 A
275
+ const agentA = new Agent({
276
+ projectPath: '/repo/app-a',
277
+ dataDir: '/repo/app-a/.memora',
278
+ storage: makeStorage('/repo/app-a'), // 宿主实现的 IMemoryStorage
279
+ sessionStore: makeSessionStore('/repo/app-a'),
280
+ provider, configDir,
281
+ });
282
+ await agentA.init();
283
+
284
+ // 项目 B:独立实例,与 A 并行运行、互不干扰
285
+ const agentB = new Agent({
286
+ projectPath: '/repo/app-b',
287
+ dataDir: '/repo/app-b/.memora',
288
+ storage: makeStorage('/repo/app-b'),
289
+ sessionStore: makeSessionStore('/repo/app-b'),
290
+ provider, configDir,
291
+ });
292
+ await agentB.init();
278
293
  ```
279
294
 
280
- > 未命中注册表且传入的又不是绝对路径时,`switchProject` 直接抛错(相对路径会以进程 cwd 为基准,
281
- > 可能静默创建出非预期的项目目录并占用其锁)。
295
+ 每个实例各自持有:记忆库(宿主注入的 storage)、会话存储、项目锁、安全守卫、角色包管理器。
296
+ 项目数据天然隔离在项目自己的 `.memora/` 下。
297
+
298
+ | 维度 | 形态 |
299
+ |------|------|
300
+ | 并行度 | **按项目计** —— N 个项目 = N 个会话同时跑 |
301
+ | 项目内多会话 | 可拥有 N 个会话(`switchSession` / `switchToSession` / `forkSession`),**同一时刻只跑一个** |
302
+ | 项目内多会话的记忆 | **共享同一个记忆库**(`searchByKeyword` 无 sessionId 过滤)⇒ 经验跨会话连续 |
303
+
304
+ **取舍(明写,勿反复重议)**:本形态**不对标主流「一个会话 = 一个 Agent 实例」**。代价是
305
+ **同一项目内不能并行跑两个会话**(主流开两个终端各推各的任务即可)——已知并接受,登记
306
+ `MULTI-SESS-1`(观察,不修)。**理由**:记忆库归**项目**所有,会话只是项目内的对话线程;
307
+ 把身份边界画在项目而非会话,才能让同一项目的经验跨会话连续。仅当出现「同一仓库要并行
308
+ 两个任务」的真实需求时才重议形态。
309
+
310
+ > 历史留痕:5.0.0 前曾有 `agent.switchProject()` / `agent.projects.*` / `AgentOptions.registryDir`
311
+ > / `projects.json` 跨项目注册表整链,随形态定案一并删除(PR-SWITCH-1)。**勿按旧文档找回**——
312
+ > 内核既不切换项目,也不维护跨项目名单。
282
313
 
283
314
  ### 9. 关闭
284
315
 
@@ -323,7 +354,7 @@ const agent = new Agent({
323
354
  **会话持久化特性:**
324
355
  - 日期使用 `todayDate()` 动态获取,确保跨日后消息写入当天目录
325
356
  - `appendUser()` / `appendAssistant()` 自动调用 `appendMessage()`
326
- - `loadSessionMessages()` 自动调用 `loadMessages()`
357
+ - `loadSessionMessages()`(内部方法,非公开 API)自动调用 `loadMessages()`
327
358
  - `SessionMessage.role` 支持 `'user' | 'assistant' | 'system'`,宿主直接调用 `appendMessage()` 时可传入任意角色
328
359
 
329
360
  ---
@@ -448,12 +479,14 @@ app.put('/api/sessions/:id/archive', (req, res) => {
448
479
  |------|------|------|
449
480
  | 构造 | `new Agent({ projectPath, provider, configDir, dataDir })` | §二 · AgentOptions |
450
481
  | 对话 | `agent.chat(input)`(流式)/ `agent.chatSync(input)` | §三 |
451
- | 记忆 | `agent.memory.snapshot()/search()/writeXxx()` | §四 |
482
+ | 记忆 | `agent.memory.snapshot()/searchByKeyword()/writeXxx()` | §四 |
452
483
  | 角色包 | `agent.rolePack.listMeta()/activate()` | §七 |
453
484
  | 工具 | `agent.tools.registerTool()/execute()` | §八 |
485
+ | 后台命令 | 内置工具 `run_command`(`background: true`)/ `agent.listBackgroundTasks()` / `agent.killBackgroundTask()` | §8.1 · §8.7 |
454
486
  | 会话 | `agent.forkSession()` / `agent.sessionManager.*` | §六 |
455
487
 
456
- > 记忆治理(去重/冲突)统一走 `agent.governance` 或 Agent 层方法,见参考手册 §四 与「记忆治理」章节。
488
+ > 记忆**写入期**治理由 `supersede`(写时取代)承担,无需宿主调用;写入入口统一是 `agent.memory.writeXxx()`。
489
+ > 订阅式事后治理(去重 / 冲突检测 / 关联推荐)已于 5.0.0 整链退役,`agent.governance` 不再存在——见参考手册 §四 注记。
457
490
 
458
491
  ---
459
492
 
@@ -463,33 +496,39 @@ app.put('/api/sessions/:id/archive', (req, res) => {
463
496
 
464
497
  | 函数/类型 | 用途 |
465
498
  |-----------|------|
466
- | `createLlmProvider(config)` | 从完整 Config(`llm.providers` + `active`)创建激活 Provider(配合 `loadConfig`) |
467
499
  | `createProviderFromConfig(name, config)` | 从命名配置创建单个 Provider 实例(扁平参数) |
468
500
  | `loadConfig(path?)` | 加载 `.memora/config.json` 项目级配置文件(或传入显式 configPath) |
469
- | `InMemoryStorage` | IMemoryStorage 的纯内存实现(测试用) |
501
+ | `createNodeSqliteStorage(dbPath[, options])` | 内核提供的 SQLite 落盘实现**工厂**(基于 `node:*` 内建模块,零第三方依赖)。不可用时抛专属错误(错误码 `NOT_AVAILABLE`)——「当前环境能否用 SQLite」的**唯一判据**(勿自行解析版本号)。第二参数 `{ readOnly: true }` 返回只读视图 |
502
+ | `ReadOnlyMemoryStorage` | 只读存储视图**类型**(`IMemoryStorage` 的读方法子集,结构上无写方法)。供只读宿主(如 MCP)复用同一实现,避免自写第二份 SQLite 语义 |
470
503
  | `setLogger(logger)` | 替换全局日志实现 |
471
504
  | `logger` | 全局日志实例 |
472
- | `segmentText(text)` | 中文分词工具 |
473
505
  | `parseFrontmatter(text)` | 解析 Markdown frontmatter |
474
- | `serializeFrontmatter(fm, body)` | 序列化 frontmatter + body 为 Markdown |
475
- | `safeSetTimeout(fn, ms)` | 安全定时器(可跟踪清理) |
476
- | `safeSetInterval(fn, ms)` | 安全间隔器(可跟踪清理) |
477
- | `clearSafeTimeout(id)` | 清除安全定时器 |
478
- | `clearSafeInterval(id)` | 清除安全间隔器 |
479
506
  | `extractKeywords(text)` | 提取关键词 |
480
507
  | `SOURCE_LABELS` | source 标签常量(PERSONA / RULE / SKILL / WORK_PROJECTION / ROUND_SUMMARY / UNKNOWN) |
481
- | `escapeLike(query)` | 转义 SQLite LIKE 通配符(`%` / `_` → `\%` / `\_`)。**SQL 必须写成 `LIKE ? ESCAPE '\'`**——不写 ESCAPE 子句则反斜杠被视为普通字符,转义后的模式匹配不到任何字面值,查询**静默返回空** |
482
- | `escapeLikeSnippet(text, maxLen?)` | 截断至 maxLen(默认 50)后转义 LIKE 通配符——搜索输入防超长解析 + 防通配符被当模式符(SQL 后端检索的配套动作,同样须配 `ESCAPE '\'`) |
483
508
  | `validateSource(source)` | 校验 source 标签是否为已知标签(返回 warning,不阻止写入) |
484
509
  | `MemoraError` | 统一错误类型(结构化错误码 + 上下文) |
485
- | `toError(err)` | 将任意值转为 Error(浏览器端安全,不引入 `logging/` 模块) |
486
- | `NOOP_TRACER` | ITracer 的空实现(静默丢弃所有 span,零开销) |
510
+ | (无 Noop 导出) | 不注入 `tracer` 即自动降级为内核内部 Noop 实现(静默丢弃所有 span,零开销) |
487
511
  | `TRACE_SPANS` | AgentLoop 预定义 Span 名称常量(RECALL / LLM_CALL / TOOL_EXEC / RESPONSE) |
488
512
  | `ToolErrorCode` | 工具错误码枚举(10 种,含 PATH_NOT_ALLOWED / FILE_NOT_FOUND 等) |
489
513
  | `isRetryableErrorCode(code)` | 判断错误码是否可重试(5 种 retryable) |
490
514
  | `TypedEventEmitter` | 类型安全的事件发射器(Agent 继承此类) |
491
515
 
492
- **注意**:`SqliteStorage` 已移出到宿主项目,不再从 memora 导出。宿主需自行实现 `IMemoryStorage` 接口。
516
+ **注意**:基于 **better-sqlite3** 的 `SqliteStorage` 仍已移出到宿主项目(native 编译模块不入内核),宿主可继续自行实现 `IMemoryStorage`。**但自 5.0.0 起,内核另提供可选的 SQLite 实现**:`createNodeSqliteStorage(dbPath)`——基于 `node:*` 内建模块(不引入第三方/native 依赖),宿主**无需自写**即可接入 SQLite;也可选择不接(继续 JSON / 内存实现)。用法:
517
+
518
+ ```typescript
519
+ import { createNodeSqliteStorage, type IMemoryStorage } from '@zooique/memora';
520
+
521
+ // 读写:文件不存在则建库(路径由宿主决定,内核不拼目录)
522
+ let storage: IMemoryStorage;
523
+ try {
524
+ storage = createNodeSqliteStorage(join(dataDir, 'memory.db'));
525
+ } catch (err) {
526
+ // 唯一判据:工厂抛出的专属错误(errorCode = ToolErrorCode.NOT_AVAILABLE)→ 降级到 JSON/内存实现
527
+ storage = new MyJsonStorage(join(dataDir, 'memories.json'));
528
+ }
529
+ // 只读宿主:返回对象结构上不含写方法
530
+ // const readOnly = createNodeSqliteStorage(join(dataDir, 'memory.db'), { readOnly: true });
531
+ ```
493
532
 
494
533
  `IMemoryStorage` 接口要求实现 `count()` 和 `countBySource(source)` 方法,用于高效统计记忆数量(避免全量加载数据)。详见 [API 参考手册](./memora-api-reference.md)。
495
534
 
@@ -554,7 +593,7 @@ const agent = new Agent({
554
593
  });
555
594
  ```
556
595
 
557
- > **不注入时**:默认使用 `NOOP_TRACER`(静默丢弃所有 span,零运行时开销)。
596
+ > **不注入时**:内核自动降级为内部 Noop 实现(静默丢弃所有 span,零运行时开销)——无需引用任何实现类。
558
597
 
559
598
  ---
560
599
 
@@ -599,20 +638,20 @@ for (const chapter of chapters) {
599
638
 
600
639
  ## 十、关键约束
601
640
 
602
- **前提:存储方案由宿主自选,内核只定契约。** 内核只定义 `IMemoryStorage` / `ISessionStore` 接口,**不规定后端**——SQLite(better-sqlite3)、JSON 文件、内存实现一视同仁,任何后端都不得被写进内核逻辑。接口方法为**同步语义**(对齐 better-sqlite3),异步后端需另行扩展接口;JSON 落地实现在同步路径上做全量重写,记忆量增长时由宿主自行评估更优后端(阈值与权衡见 `storageInterface.ts` 头注释)。第一宿主 memora-vscode 当前用 JSON 文件,换成 SQLite **不需要改内核**。
641
+ **前提:存储方案由宿主自选,内核只定契约。** 内核只定义 `IMemoryStorage` / `ISessionStore` 接口,**不规定后端**——SQLite、JSON 文件、内存实现一视同仁,任何后端都不得被写进内核逻辑(5.0.0 起内核**提供**可选的 SQLite 实现 `createNodeSqliteStorage`,但那是「多一个可选实现」,**不是**把后端写进逻辑——选哪个仍归宿主,`Agent` 构造契约不变)。接口方法为**同步语义**(对齐 better-sqlite3),异步后端需另行扩展接口;JSON 落地实现在同步路径上做全量重写,记忆量增长时由宿主自行评估更优后端(阈值与权衡见 `storageInterface.ts` 头注释)。第一宿主 memora-vscode 当前用 JSON 文件,换成 SQLite **不需要改内核**。
603
642
 
604
643
  1. **`provider` 是必填项** — Agent 无法独立运行
605
644
  2. **configDir** 指向 Agent 级配置目录,所有项目共享
606
645
  3. **项目级 `.memora/`** 放项目级配置(`rules/`、`skills/`)与内核写入的项目锁 `.lock`;`dataDir` 若指向此处(第一宿主 memora-vscode 即如此),记忆库与会话也落在这里
607
646
  4. **角色包只能手动切换**(`agent.switchRolePack(name)` / `agent.rolePack.activate(name)`)——无输入自动匹配、无粘性锁存、无互斥触发;已激活的角色包在当前会话内保持固定(v0.13 已移除自动匹配全链)
608
- 5. **对话历史随 Agent 持久化** — `sessionStore` 是实例级注入的,`switchProject()` 不换存储;未注入则仅内存保存
647
+ 5. **对话历史随 Agent 持久化** — `sessionStore` 是实例级注入的,**切会话不换存储**;未注入则仅内存保存
609
648
  6. **Manager 访问器在 `init()` 前返回 `null`** — 所有 `agent.rolePack.xxx()` / `agent.memory.xxx()` 等调用必须在 `init()` 之后
610
649
  7. **作品原始内容不进记忆库**,Agent 通过工具按需读取(大文本走 `read_file` 分段,提炼后只留情报,不全量入库 / 入上下文)
611
650
  8. **配置文件是真理源**,`<configDir>/role-packs/` 下的角色包由 RolePackManager 启动时扫描加载
612
- 9. **一个 Agent = 一份记忆库** — `storage` 与 `dataDir` 都是 **Agent 实例级**的:`switchProject()` 复用同一实例,不按项目 / 子项目分裂。**要按工作区彼此隔离,就各自 `new Agent`**——隔离粒度归宿主决定,内核不规定
613
- 10. **项目切换不重建、不关闭存储** — `switchProject()` 复用已注入的实例,只在 `close()` 时关闭(`ProjectManager` 在 Agent 生命周期内缓存)
651
+ 9. **一个 Agent = 一份记忆库** — `storage` 与 `dataDir` 都是 **Agent 实例级**的:切会话复用同一实例,不按会话 / 子项目分裂。**要按项目彼此隔离,就各自 `new Agent`**——隔离粒度归宿主决定,内核不规定(见 [§8](#8-多项目一个项目一个-agent形态定案))
652
+ 10. **切会话不重建、不关闭存储** — 会话切换只换身份(`sessionId`),复用已注入的实例;只在 `close()` 时关闭(`ProjectManager` 在 Agent 生命周期内缓存)
614
653
  11. **禁止把配置放进记忆库** — 配置(角色包 / persona / rules / skills)的真理源是文件(`configDir` / 角色包),设定记忆归角色包内容层、不进记忆库(ADR-025 / `memory-role-pack-boundary`)
615
- 12. **项目切换** `switchProject()` 已自动 rebuild,通常无需手动调用 `rebuildComponents()`
654
+ 12. **组件重装配** 由内核在 `init()` / `reloadConfig()` 内部完成,无公开重建入口,宿主无需也无法手动触发
616
655
  13. **Tracer 未注入时**自动降级为 NoopTracer,零运行时开销
617
656
 
618
657
  ---
@@ -693,15 +732,15 @@ chatProvider.setAgentFactory((projectPath) =>
693
732
 
694
733
  > 本约束原仅存于宿主实现注释(`extension.ts` 的"杜绝双实例覆盖写";仓库内参考实现,**非随包产物**),现提升为宿主接入契约基线,避免新宿主对接踩坑。原子写实锤已具备(`atomicWriteFileSync`),单例 + 原子写已对齐主流硬化做法(grida / Chatbox 同款 tmp+rename);唯一真实残留为跨进程锁,已列入检查清单第 4 项。
695
734
 
696
- ## 十.7、策略键消费矩阵(16 键 SSOT 落点)📌 参考
735
+ ## 十.7、策略键消费矩阵(17 键 SSOT 落点)📌 参考
697
736
 
698
- > 逐键矩阵(16 键 × 内核消费位置 × UI 侧消费)为仓库内开发文档(SSOT:`src/role-pack/strategyKeys.ts`),**不随包发布**;宿主对接所需的键语义见 [role-pack-authoring-guide.md](./architecture/role-pack-authoring-guide.md) §三。此处只给新宿主对接必知的结论与边界。
737
+ > 逐键矩阵(17 键 × 内核消费位置 × UI 侧消费)为仓库内开发文档(SSOT:`src/role-pack/strategyKeys.ts`),**不随包发布**;宿主对接所需的键语义见 [role-pack-authoring-guide.md](./architecture/role-pack-authoring-guide.md) §三。此处只给新宿主对接必知的结论与边界。
699
738
 
700
- - **16 键全部被内核真实消费、零 `[草案]`**(prepare 1 / act 7 / reflect 3 / global 5)。解析层 `rolePackManager` + `strategyResolver` 84 项测试守护,消费层跨 `contextPreparer` / `loop` / `agent` / `managers/llmCaller` / `toolRunner` / `orchestrator` / `prepare` 多文件覆盖。
739
+ - **17 键全部被内核真实消费、零 `[草案]`**(prepare 1 / act 7 / reflect 3 / global 6)。解析层 `rolePackManager` + `strategyResolver` 测试守护,消费层跨 `contextPreparer` / `loop` / `agent` / `managers/llmCaller` / `toolRunner` / `orchestrator` / `prepare` 多文件覆盖。
701
740
  - **三类流向,单一收口无镜像**:
702
- 1. act 5 键(`toolMode`/`toolStepLimit`/`providerRouting`/`multiStepReasoning`/`toolReadonly`)+ `selfReview` + global 4 键(`errorHandling`/`contextLimit`/`stepBudget`/`askLimit`),统一经 `resolveL2Strategy()` 聚合注入 `L2RuntimeStrategy`,loop 经 `this.strategy.<field>` 读取;`act.temperature`/`outputLimit` 由 `agent.ts` 直映射 `ChatOptions`(不经聚合);
741
+ 1. act 5 键(`toolMode`/`toolStepLimit`/`providerRouting`/`multiStepReasoning`/`toolReadonly`)+ `selfReview` + **global 键中经聚合的 5 键**(`errorHandling`/`contextLimit`/`stepBudget`/`askLimit`/`webSearchLimit`)——此「5 键」是「**经 `resolveL2Strategy()` 聚合这一层**」的子集,global 第 6 键 `askOn` 不走聚合(归第 3 类);上列各键统一经 `resolveL2Strategy()` 聚合注入 `L2RuntimeStrategy`,loop 经 `this.strategy.<field>` 读取;`act.temperature`/`outputLimit` 由 `agent.ts` 直映射 `ChatOptions`(不经聚合);
703
742
  2. prepare 键经 `resolveActiveStrategy()` 单一真理源流入 `contextPreparer` / `roundSummaryGenerator`;
704
- 3. persona 指令类(`userFollowup`/`askOn`/`askLimit`)由 `assembleRolePack()` 单收口注入。
743
+ 3. persona 指令类(`userFollowup`/`askOn`/`askLimit`)由 `assembleRolePack()` 单收口注入——**`askLimit` 是双面键**:既在第 1 类经聚合进 `L2RuntimeStrategy` 供 loop 硬护栏消费,又在此处随 persona prompt 注入,两处各占一面、**非重复计数**。
705
744
  - **⚠️ 边界纠正:`toolReadonly` 内核已执行,非「无宿主执行方」**。`toolRunner.ts` 只剩两层闸:闸①(只读闸 `toolReadonly==='readonly'`)**由内核执行**;闸③(宿主 `preExecutionCheck` 注入点)当前 VS Code 宿主恒放行(`assemble.ts` 恒返回 `() => ({ skip: false })`)只是单用户信任模型下的显式让行(关联 十.5 / 设计纪律 D5),未来多用户/服务端须替换真实审批。原闸② `toolApproval` 审批链已随 3.0.0 删键(2026-09-11,故代码注释 ①/③ 编号保留):单用户本地无真实审批场景,原"通知宿主 + UI 需审批 chip"是展示性假承诺——整键删除,新宿主切勿再期待 `onToolApproval` 回调或 `toolApproval==='confirm'` 语义,审批须自行在 `preExecutionCheck` 实现。
706
745
  - **UI 侧 6 键有呈现**:宿主角色列表视图渲染策略 chip 5 键(`toolReadonly` / `summaryFocus` / `outputLimit` / `temperature` / `multiStepReasoning`)+ `toolMode` 经对话视图 capability badge 渲染('纯 LLM' / '全部工具')。能力名映射与策略键无关,**勿混淆**。(上述 UI 实现均为仓库内宿主参考实现,**非随包产物**。)
707
746
 
@@ -1,148 +1,148 @@
1
- # 角色包开放键使用指南(发布包版)
2
-
3
- > **面向对象**:安装 `@zooique/memora` 后,编写 / 理解角色包(role pack)的开发者——既包括**宿主接入者**(要把角色包能力接进自己的产品),也包括**角色包作者**(要填写 `manifest.json`)。
4
- > **定位**:本指南回答「manifest.json 里的开放键填什么、**被谁消费**、有什么上限」。它是 memora 发布包内的角色包使用入口。
5
- > **相关文档**:
6
- > - 中立规范(跨所有 Agent 实现的契约,随包发布):[role-pack-spec.md](./architecture/role-pack-spec.md)
7
- > - 详细填写手册(含全部区间 / 错误修正 / 键的落实状态,随包发布):[role-pack-authoring-guide.md](./architecture/role-pack-authoring-guide.md)
8
- > - 示例角色包(结构参考,随包发布、不参与宿主运行时装载):[role-packs/](../role-packs/README.md)
9
-
10
- ---
11
-
12
- ## 一、角色包是什么
13
-
14
- 角色包 = 一个文件夹 + `manifest.json`(唯一核心控制文件)+ 内容文件:
15
-
16
- ```
17
- 角色包名/
18
- ├── manifest.json # ★ 元数据 + strategy 策略 + capabilities + skills 白名单
19
- ├── persona.md # 角色身份设定(约定文件名,可缺省)
20
- ├── rules.md # 确定性规则(约定文件名,逐行解析)
21
- └── skills/ # 技能目录(动态扫描,新增技能只写文件即可)
22
- ```
23
-
24
- 把角色包文件夹放进 `configDir/role-packs/` 即可装载。`manifest.json` 里的字段统称**开放键**——它们是内核、宿主、UI 三方协作的契约,本文档回答「谁在用它们」。
25
-
26
- ---
27
-
28
- ## 二、三层消费方逻辑(先理解"键被谁用")
29
-
30
- 所有开放键的消费方分三层,**不是所有键都是给宿主接入的**:
31
-
32
- | 层 | 消费方 | 键 | 用途 |
33
- |----|--------|-----|------|
34
- | **① 内核直接消费** | memora 内核 | `skills` / `strategy` | 技能扫描、行为策略 |
35
- | **② 中立接口(宿主接入点)** | 宿主 / 其他实现 | `capabilities` / `handoffPrompt` | 能力映射、接手话术 |
36
- | **③ 元数据(UI 展示)** | 宿主 UI | `name` / `displayName` / `description` / `author` | 标识与展示 |
37
-
38
- ### 2.1 ① 内核直接消费层(memora 实现细节)
39
-
40
- 这些键由 memora 内核自己跑逻辑,**宿主不需要处理**:
41
-
42
- - `skills`:内嵌技能白名单(目录动态扫描,声明项仅作白名单过滤;不声明则全量扫描 `skills/`)。
43
- - `strategy`:L2 行为策略(`prepare` / `act` / `reflect` / `global` 四组),控制工具暴露、摘要视角、自审查、预算与提问等行为偏好。
44
-
45
- > 这些键的**上限由内核统一守门**(见 §2.4),因为解析入口在内核。
46
-
47
- ### 2.2 ② 中立接口层(宿主接入点)
48
-
49
- 这一层是**为宿主 / 跨实现接入预留的中立契约**——角色包不绑具体实现,由各实现自己消费:
50
-
51
- - **`capabilities`(能力声明)**:以**中立能力命名空间**声明(`域:动作`,如 `file:write` / `web:search`),不绑具体工具。**各实现(memora 是 reference implementation)自行映射到自有工具**:
52
- - **特权声明模型(2026-09-08 定,2026-09-16 扩)**:memora 侧映射表在 `src/role-pack/capabilityMap.ts`(SSOT)——仅 `web:search` / `web:fetch` / `code:execute` 映射为**特权工具白名单**;`file:*` / `memory:recall` / **`task:plan`(对应任务表)** 属**默认常驻工具**(`toolExecutor.DEFAULT_EXPOSED_TOOLS`),声明与否都不影响可见性、不再映射。任务表系内核多步任务必要基建(2026-09-16 用户拍板),非角色包可选的领域深度能力;
53
- - **宿主可以有自己的映射表**:例如 `code:execute` 需宿主注入 `ICodeExecutionProvider` 才真正暴露;
54
- - 未知能力(不在映射表)跳过,不阻塞装载。
55
- - 角色包声明 `capabilities` 后,工具暴露面 = 常驻豁免集 + 能力白名单内的特权工具(换角色 → 特权工具集切换)。
56
- - **`handoffPrompt`(接手话术)**:该角色包**被宿主带入对话(激活 + 聚焦)时**预填输入框的特色衔接话术——作者为「这个角色接手任务时怎么说」定制的提示词,缺省由宿主回退通用话术。**宿主消费**(如 memora-vscode 在 `roles_handoff` 处理中读取 `listMeta().handoffPrompt` 预填);内核仅透传 + 校验(非字符串 warning 不阻塞装载)。
57
-
58
- ### 2.3 ③ 元数据层(UI 展示)
59
-
60
- - `name`(唯一标识,缺失用文件夹名兜底)、`displayName`(UI 展示名,缺省回退 `name`)、`description`、`author`。
61
- - 内核仅作标识/校验;真正消费是宿主的角色包清单 / UI 展示。
62
-
63
- ### 2.4 为什么上限由内核统一守门
64
-
65
- **无论最终消费方是谁,`manifest.json` 的解析入口都在 memora 内核**(`validator.ts` 校验 + `rolePackManager.ts` 装载)。内核作为装载器在入口守门——对所有开放字段统一限长:
66
-
67
- - 对**内核字段**:防资源失控(匹配词列表膨胀拖慢匹配、巨型内容占内存/上下文);
68
- - 对**宿主字段**:防巨型数据透传给宿主(宿主收到的是已被内核约束过的安全数据)。
69
-
70
- 这正是「零依赖内核」哲学:**内核做守门,宿主做消费**。所以上表中所有字段的上限,全部由内核入口统一控制(见 §三),不区分消费方。
71
-
72
- ---
73
-
74
- ## 三、开放键速查表(消费方 + 上限)
75
-
76
- > 详细区间 / 错误修正 / 键的落实状态见 [role-pack-authoring-guide.md](./architecture/role-pack-authoring-guide.md)(仓库内文档)。下表是发布包内的精简速查。
77
- > **上限 SSOT**:`src/role-pack/validator.ts`(非策略键)与 `src/role-pack/strategyKeys.ts`(策略键数值区间)。
78
-
79
- ### 3.1 元数据层
80
-
81
- | 键 | 类型 | 消费方 | 上限 | 说明 |
82
- |----|------|--------|------|------|
83
- | `name` | string | ③ UI / 内核标识 | ≤200 字符 | 唯一标识(缺失用文件夹名兜底) |
84
- | `formatVersion` | string | ① 内核校验(可选,缺省 `1.0.0`) | semver(x.y.z) | 格式版本,绑定固定 schema URL,发布后不变;建议声明 |
85
- | `displayName` | string | ③ UI | ≤200 字符 | UI 展示名,缺省回退 `name` |
86
- | `description` | string | ③ UI | ≤200 字符 | 角色包描述 |
87
- | `author` | string | ③ UI | ≤200 字符 | 作者/来源 |
88
- | `version` | string | ③ 分发 | semver(x.y.z) | 角色包自身版本(可选) |
89
-
90
- ### 3.2 中立接口层(宿主接入)
91
-
92
- | 键 | 类型 | 消费方 | 上限 | 说明 |
93
- |----|------|--------|------|------|
94
- | `capabilities` | 对象数组 | ② 宿主 / 各实现映射 | ≤50 项 | `{ capability: "域:动作", description? }`;映射到各实现自有工具 |
95
- | `handoffPrompt` | string | ② 宿主预填 | ≤2000 字符 | 被带入对话时预填的接手话术 |
96
-
97
- ### 3.3 内核消费层
98
-
99
- | 键 | 类型 | 消费方 | 上限 | 说明 |
100
- |----|------|--------|------|------|
101
- | `skills` | 对象数组 | ① 内核扫描 | ≤50 项 | 技能白名单(`{ file, name?, description? }`) |
102
- | `strategy` | 嵌套对象 | ① 内核行为 | 各数值键有上下限(见 authoring-guide §四) | L2 行为策略(prepare/act/reflect/global) |
103
-
104
- ### 3.4 合规 / 分档层
105
-
106
- | 键 | 类型 | 消费方 | 上限 | 说明 |
107
- |----|------|--------|------|------|
108
- | `interactionType` | string 枚举 | ① 内核合规 | `tool_assistant` / `companion`(缺省 `tool_assistant`) | 交互类型:工具型(豁免区间)vs 拟人化陪伴(完整合规校验) |
109
- | `aiIdentityDisclosure` | boolean | ① 内核合规 | `true`(缺省) | 是否向用户明确标注 AI 身份(companion 必须显式 true) |
110
- | `minorProtection` | string 枚举 | ① 内核合规 | `required`(缺省) | 未成年人保护模式(当前仅支持 required) |
111
-
112
- > **越界行为统一**:开发期 `validator` 校验报 error(拒绝装载提示);运行时按上限截断 / 回退默认(宽容容错)。
113
-
114
- ---
115
-
116
- ## 四、内容文件约定(零声明)
117
-
118
- `persona.md` / `rules.md` / `skills/` 全部**约定俗成**——manifest **不注册内容路径**(防路径写错静默丢内容):
119
-
120
- | 文件 | 约定 | 说明 |
121
- |------|------|------|
122
- | `persona.md` | 约定名 | 角色身份设定(frontmatter 可声明 `traits.*` 数值 trait,clamp 0-1) |
123
- | `rules.md` | 约定名 | 确定性规则(逐行解析 `- ` / `* ` / `n. ` 列表) |
124
- | `skills/` | 目录动态扫描 | 新增技能只写文件即可,frontmatter 声明 `name` / `description`(渐进披露 L1) |
125
-
126
- ---
127
-
128
- ## 五、最小示例
129
-
130
- ```json
131
- {
132
- "name": "plain-designer",
133
- "displayName": "白话方案设计师",
134
- "description": "白话方案设计角色包",
135
- "formatVersion": "1.0.0",
136
- "interactionType": "tool_assistant",
137
- "strategy": {
138
- "prepare": { "summaryFocus": "以方案设计视角提炼要点" },
139
- "act": { "toolMode": "allow", "temperature": 0.3 },
140
- "global": { "contextLimit": 0 }
141
- },
142
- "capabilities": [
143
- { "capability": "file:write", "description": "写文件" },
144
- { "capability": "web:search", "description": "搜索" }
145
- ],
146
- "handoffPrompt": "你好,我是白话方案设计师,请告诉我你想解决什么模糊想法或痛点。"
147
- }
148
- ```
1
+ # 角色包开放键使用指南(发布包版)
2
+
3
+ > **面向对象**:安装 `@zooique/memora` 后,编写 / 理解角色包(role pack)的开发者——既包括**宿主接入者**(要把角色包能力接进自己的产品),也包括**角色包作者**(要填写 `manifest.json`)。
4
+ > **定位**:本指南回答「manifest.json 里的开放键填什么、**被谁消费**、有什么上限」。它是 memora 发布包内的角色包使用入口。
5
+ > **相关文档**:
6
+ > - 中立规范(跨所有 Agent 实现的契约,随包发布):[role-pack-spec.md](./architecture/role-pack-spec.md)
7
+ > - 详细填写手册(含全部区间 / 错误修正 / 键的落实状态,随包发布):[role-pack-authoring-guide.md](./architecture/role-pack-authoring-guide.md)
8
+ > - 示例角色包(结构参考,随包发布、不参与宿主运行时装载):[role-packs/](../role-packs/README.md)
9
+
10
+ ---
11
+
12
+ ## 一、角色包是什么
13
+
14
+ 角色包 = 一个文件夹 + `manifest.json`(唯一核心控制文件)+ 内容文件:
15
+
16
+ ```
17
+ 角色包名/
18
+ ├── manifest.json # ★ 元数据 + strategy 策略 + capabilities + skills 白名单
19
+ ├── persona.md # 角色身份设定(约定文件名,可缺省)
20
+ ├── rules.md # 确定性规则(约定文件名,逐行解析)
21
+ └── skills/ # 技能目录(动态扫描,新增技能只写文件即可)
22
+ ```
23
+
24
+ 把角色包文件夹放进 `configDir/role-packs/` 即可装载。`manifest.json` 里的字段统称**开放键**——它们是内核、宿主、UI 三方协作的契约,本文档回答「谁在用它们」。
25
+
26
+ ---
27
+
28
+ ## 二、三层消费方逻辑(先理解"键被谁用")
29
+
30
+ 所有开放键的消费方分三层,**不是所有键都是给宿主接入的**:
31
+
32
+ | 层 | 消费方 | 键 | 用途 |
33
+ |----|--------|-----|------|
34
+ | **① 内核直接消费** | memora 内核 | `skills` / `strategy` | 技能扫描、行为策略 |
35
+ | **② 中立接口(宿主接入点)** | 宿主 / 其他实现 | `capabilities` / `handoffPrompt` | 能力映射、接手话术 |
36
+ | **③ 元数据(UI 展示)** | 宿主 UI | `name` / `displayName` / `description` / `author` | 标识与展示 |
37
+
38
+ ### 2.1 ① 内核直接消费层(memora 实现细节)
39
+
40
+ 这些键由 memora 内核自己跑逻辑,**宿主不需要处理**:
41
+
42
+ - `skills`:内嵌技能白名单(目录动态扫描,声明项仅作白名单过滤;不声明则全量扫描 `skills/`)。
43
+ - `strategy`:L2 行为策略(`prepare` / `act` / `reflect` / `global` 四组),控制工具暴露、摘要视角、自审查、预算与提问等行为偏好。
44
+
45
+ > 这些键的**上限由内核统一守门**(见 §2.4),因为解析入口在内核。
46
+
47
+ ### 2.2 ② 中立接口层(宿主接入点)
48
+
49
+ 这一层是**为宿主 / 跨实现接入预留的中立契约**——角色包不绑具体实现,由各实现自己消费:
50
+
51
+ - **`capabilities`(能力声明)**:以**中立能力命名空间**声明(`域:动作`,如 `file:write` / `web:search`),不绑具体工具。**各实现(memora 是 reference implementation)自行映射到自有工具**:
52
+ - **特权声明模型(2026-09-08 定,2026-09-16 扩)**:memora 侧映射表在 `src/role-pack/capabilityMap.ts`(SSOT)——仅 `web:search` / `web:fetch` / `code:execute` 映射为**特权工具白名单**;`file:*` / `memory:recall` / **`task:plan`(对应任务表)** 属**默认常驻工具**(`toolExecutor.DEFAULT_EXPOSED_TOOLS`),声明与否都不影响可见性、不再映射。任务表系内核多步任务必要基建(2026-09-16 用户拍板),非角色包可选的领域深度能力;
53
+ - **宿主可以有自己的映射表**:例如 `code:execute` 需宿主注入 `ICodeExecutionProvider` 才真正暴露;
54
+ - 未知能力(不在映射表)跳过,不阻塞装载。
55
+ - 角色包声明 `capabilities` 后,工具暴露面 = 常驻豁免集 + 能力白名单内的特权工具(换角色 → 特权工具集切换)。
56
+ - **`handoffPrompt`(接手话术)**:该角色包**被宿主带入对话(激活 + 聚焦)时**预填输入框的特色衔接话术——作者为「这个角色接手任务时怎么说」定制的提示词,缺省由宿主回退通用话术。**宿主消费**(如 memora-vscode 在 `roles_handoff` 处理中读取 `listMeta().handoffPrompt` 预填);内核仅透传 + 校验(非字符串 warning 不阻塞装载)。
57
+
58
+ ### 2.3 ③ 元数据层(UI 展示)
59
+
60
+ - `name`(唯一标识,缺失用文件夹名兜底)、`displayName`(UI 展示名,缺省回退 `name`)、`description`、`author`。
61
+ - 内核仅作标识/校验;真正消费是宿主的角色包清单 / UI 展示。
62
+
63
+ ### 2.4 为什么上限由内核统一守门
64
+
65
+ **无论最终消费方是谁,`manifest.json` 的解析入口都在 memora 内核**(`validator.ts` 校验 + `rolePackManager.ts` 装载)。内核作为装载器在入口守门——对所有开放字段统一限长:
66
+
67
+ - 对**内核字段**:防资源失控(匹配词列表膨胀拖慢匹配、巨型内容占内存/上下文);
68
+ - 对**宿主字段**:防巨型数据透传给宿主(宿主收到的是已被内核约束过的安全数据)。
69
+
70
+ 这正是「零依赖内核」哲学:**内核做守门,宿主做消费**。所以上表中所有字段的上限,全部由内核入口统一控制(见 §三),不区分消费方。
71
+
72
+ ---
73
+
74
+ ## 三、开放键速查表(消费方 + 上限)
75
+
76
+ > 详细区间 / 错误修正 / 键的落实状态见 [role-pack-authoring-guide.md](./architecture/role-pack-authoring-guide.md)(仓库内文档)。下表是发布包内的精简速查。
77
+ > **上限 SSOT**:`src/role-pack/validator.ts`(非策略键)与 `src/role-pack/strategyKeys.ts`(策略键数值区间)。
78
+
79
+ ### 3.1 元数据层
80
+
81
+ | 键 | 类型 | 消费方 | 上限 | 说明 |
82
+ |----|------|--------|------|------|
83
+ | `name` | string | ③ UI / 内核标识 | ≤200 字符 | 唯一标识(缺失用文件夹名兜底) |
84
+ | `formatVersion` | string | ① 内核校验(可选,缺省 `1.0.0`) | semver(x.y.z) | 格式版本,绑定固定 schema URL,发布后不变;建议声明 |
85
+ | `displayName` | string | ③ UI | ≤200 字符 | UI 展示名,缺省回退 `name` |
86
+ | `description` | string | ③ UI | ≤200 字符 | 角色包描述 |
87
+ | `author` | string | ③ UI | ≤200 字符 | 作者/来源 |
88
+ | `version` | string | ③ 分发 | semver(x.y.z) | 角色包自身版本(可选) |
89
+
90
+ ### 3.2 中立接口层(宿主接入)
91
+
92
+ | 键 | 类型 | 消费方 | 上限 | 说明 |
93
+ |----|------|--------|------|------|
94
+ | `capabilities` | 对象数组 | ② 宿主 / 各实现映射 | ≤50 项 | `{ capability: "域:动作", description? }`;映射到各实现自有工具 |
95
+ | `handoffPrompt` | string | ② 宿主预填 | ≤2000 字符 | 被带入对话时预填的接手话术 |
96
+
97
+ ### 3.3 内核消费层
98
+
99
+ | 键 | 类型 | 消费方 | 上限 | 说明 |
100
+ |----|------|--------|------|------|
101
+ | `skills` | 对象数组 | ① 内核扫描 | ≤50 项 | 技能白名单(`{ file, name?, description? }`) |
102
+ | `strategy` | 嵌套对象 | ① 内核行为 | 各数值键有上下限(见 authoring-guide §四) | L2 行为策略(prepare/act/reflect/global) |
103
+
104
+ ### 3.4 合规 / 分档层
105
+
106
+ | 键 | 类型 | 消费方 | 上限 | 说明 |
107
+ |----|------|--------|------|------|
108
+ | `interactionType` | string 枚举 | ① 内核合规 | `tool_assistant` / `companion`(缺省 `tool_assistant`) | 交互类型:工具型(豁免区间)vs 拟人化陪伴(完整合规校验) |
109
+ | `aiIdentityDisclosure` | boolean | ① 内核合规 | `true`(缺省) | 是否向用户明确标注 AI 身份(companion 必须显式 true) |
110
+ | `minorProtection` | string 枚举 | ① 内核合规 | `required`(缺省) | 未成年人保护模式(当前仅支持 required) |
111
+
112
+ > **越界行为统一**:开发期 `validator` 校验报 error(拒绝装载提示);运行时按上限截断 / 回退默认(宽容容错)。
113
+
114
+ ---
115
+
116
+ ## 四、内容文件约定(零声明)
117
+
118
+ `persona.md` / `rules.md` / `skills/` 全部**约定俗成**——manifest **不注册内容路径**(防路径写错静默丢内容):
119
+
120
+ | 文件 | 约定 | 说明 |
121
+ |------|------|------|
122
+ | `persona.md` | 约定名 | 角色身份设定(frontmatter 可声明 `traits.*` 数值 trait,clamp 0-1) |
123
+ | `rules.md` | 约定名 | 确定性规则(逐行解析 `- ` / `* ` / `n. ` 列表) |
124
+ | `skills/` | 目录动态扫描 | 新增技能只写文件即可,frontmatter 声明 `name` / `description`(渐进披露 L1) |
125
+
126
+ ---
127
+
128
+ ## 五、最小示例
129
+
130
+ ```json
131
+ {
132
+ "name": "plain-designer",
133
+ "displayName": "白话方案设计师",
134
+ "description": "白话方案设计角色包",
135
+ "formatVersion": "1.0.0",
136
+ "interactionType": "tool_assistant",
137
+ "strategy": {
138
+ "prepare": { "summaryFocus": "以方案设计视角提炼要点" },
139
+ "act": { "toolMode": "allow", "temperature": 0.3 },
140
+ "global": { "contextLimit": 0 }
141
+ },
142
+ "capabilities": [
143
+ { "capability": "file:write", "description": "写文件" },
144
+ { "capability": "web:search", "description": "搜索" }
145
+ ],
146
+ "handoffPrompt": "你好,我是白话方案设计师,请告诉我你想解决什么模糊想法或痛点。"
147
+ }
148
+ ```