@zooique/memora 4.0.0 → 5.1.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 (245) hide show
  1. package/CHANGELOG.md +235 -1743
  2. package/README.en.md +43 -36
  3. package/README.md +308 -303
  4. package/dist/agent/agent.d.ts +46 -82
  5. package/dist/agent/agent.d.ts.map +1 -1
  6. package/dist/agent/agent.js +153 -220
  7. package/dist/agent/agent.js.map +1 -1
  8. package/dist/agent/assembler.d.ts +3 -16
  9. package/dist/agent/assembler.d.ts.map +1 -1
  10. package/dist/agent/assembler.js +76 -47
  11. package/dist/agent/assembler.js.map +1 -1
  12. package/dist/agent/backgroundTasks.d.ts +8 -1
  13. package/dist/agent/backgroundTasks.d.ts.map +1 -1
  14. package/dist/agent/backgroundTasks.js +8 -1
  15. package/dist/agent/backgroundTasks.js.map +1 -1
  16. package/dist/agent/budget.d.ts +23 -5
  17. package/dist/agent/budget.d.ts.map +1 -1
  18. package/dist/agent/budget.js +8 -2
  19. package/dist/agent/budget.js.map +1 -1
  20. package/dist/agent/builtinToolHandlers.d.ts +50 -10
  21. package/dist/agent/builtinToolHandlers.d.ts.map +1 -1
  22. package/dist/agent/builtinToolHandlers.js +67 -20
  23. package/dist/agent/builtinToolHandlers.js.map +1 -1
  24. package/dist/agent/builtinTools.d.ts +16 -0
  25. package/dist/agent/builtinTools.d.ts.map +1 -1
  26. package/dist/agent/builtinTools.js +15 -4
  27. package/dist/agent/builtinTools.js.map +1 -1
  28. package/dist/agent/constants.d.ts +0 -6
  29. package/dist/agent/constants.d.ts.map +1 -1
  30. package/dist/agent/constants.js +7 -8
  31. package/dist/agent/constants.js.map +1 -1
  32. package/dist/agent/contextManager.d.ts +8 -0
  33. package/dist/agent/contextManager.d.ts.map +1 -1
  34. package/dist/agent/contextManager.js +45 -3
  35. package/dist/agent/contextManager.js.map +1 -1
  36. package/dist/agent/contextPreparer.d.ts +1 -1
  37. package/dist/agent/contextPreparer.d.ts.map +1 -1
  38. package/dist/agent/contextPreparer.js +15 -10
  39. package/dist/agent/contextPreparer.js.map +1 -1
  40. package/dist/agent/guardRail.d.ts +25 -10
  41. package/dist/agent/guardRail.d.ts.map +1 -1
  42. package/dist/agent/guardRail.js +154 -46
  43. package/dist/agent/guardRail.js.map +1 -1
  44. package/dist/agent/loop.d.ts +46 -13
  45. package/dist/agent/loop.d.ts.map +1 -1
  46. package/dist/agent/loop.js +145 -32
  47. package/dist/agent/loop.js.map +1 -1
  48. package/dist/agent/managers/archiveCoordinator.d.ts +15 -3
  49. package/dist/agent/managers/archiveCoordinator.d.ts.map +1 -1
  50. package/dist/agent/managers/archiveCoordinator.js +13 -7
  51. package/dist/agent/managers/archiveCoordinator.js.map +1 -1
  52. package/dist/agent/managers/chatLockManager.d.ts +3 -9
  53. package/dist/agent/managers/chatLockManager.d.ts.map +1 -1
  54. package/dist/agent/managers/chatLockManager.js +7 -25
  55. package/dist/agent/managers/chatLockManager.js.map +1 -1
  56. package/dist/agent/managers/llmCaller.d.ts.map +1 -1
  57. package/dist/agent/managers/llmCaller.js +27 -1
  58. package/dist/agent/managers/llmCaller.js.map +1 -1
  59. package/dist/agent/managers/memoryInspector.d.ts +12 -7
  60. package/dist/agent/managers/memoryInspector.d.ts.map +1 -1
  61. package/dist/agent/managers/memoryInspector.js +32 -19
  62. package/dist/agent/managers/memoryInspector.js.map +1 -1
  63. package/dist/agent/managers/roundSummaryGenerator.d.ts +3 -1
  64. package/dist/agent/managers/roundSummaryGenerator.d.ts.map +1 -1
  65. package/dist/agent/managers/roundSummaryGenerator.js +14 -4
  66. package/dist/agent/managers/roundSummaryGenerator.js.map +1 -1
  67. package/dist/agent/managers/sessionArchiver.d.ts +20 -6
  68. package/dist/agent/managers/sessionArchiver.d.ts.map +1 -1
  69. package/dist/agent/managers/sessionArchiver.js +19 -5
  70. package/dist/agent/managers/sessionArchiver.js.map +1 -1
  71. package/dist/agent/managers/sessionManager.d.ts +21 -88
  72. package/dist/agent/managers/sessionManager.d.ts.map +1 -1
  73. package/dist/agent/managers/sessionManager.js +77 -278
  74. package/dist/agent/managers/sessionManager.js.map +1 -1
  75. package/dist/agent/seed/orchestrator.d.ts.map +1 -1
  76. package/dist/agent/seed/orchestrator.js +3 -3
  77. package/dist/agent/seed/orchestrator.js.map +1 -1
  78. package/dist/agent/seed/prepare.d.ts.map +1 -1
  79. package/dist/agent/seed/prepare.js +9 -4
  80. package/dist/agent/seed/prepare.js.map +1 -1
  81. package/dist/agent/seed/types.d.ts +11 -4
  82. package/dist/agent/seed/types.d.ts.map +1 -1
  83. package/dist/agent/seed/types.js +2 -2
  84. package/dist/agent/toolExecutor.d.ts +69 -18
  85. package/dist/agent/toolExecutor.d.ts.map +1 -1
  86. package/dist/agent/toolExecutor.js +188 -28
  87. package/dist/agent/toolExecutor.js.map +1 -1
  88. package/dist/agent/toolResultCache.js +1 -1
  89. package/dist/agent/toolRunner.d.ts +4 -2
  90. package/dist/agent/toolRunner.d.ts.map +1 -1
  91. package/dist/agent/toolRunner.js +7 -4
  92. package/dist/agent/toolRunner.js.map +1 -1
  93. package/dist/agent/types.d.ts +8 -25
  94. package/dist/agent/types.d.ts.map +1 -1
  95. package/dist/index.d.ts +9 -20
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +35 -32
  98. package/dist/index.js.map +1 -1
  99. package/dist/logging/logger.d.ts +4 -1
  100. package/dist/logging/logger.d.ts.map +1 -1
  101. package/dist/logging/logger.js +5 -2
  102. package/dist/logging/logger.js.map +1 -1
  103. package/dist/memory/gcService.d.ts.map +1 -1
  104. package/dist/memory/gcService.js +3 -5
  105. package/dist/memory/gcService.js.map +1 -1
  106. package/dist/memory/inMemorySessionStore.d.ts +2 -2
  107. package/dist/memory/inMemorySessionStore.js +2 -2
  108. package/dist/memory/inMemoryStorage.d.ts +4 -3
  109. package/dist/memory/inMemoryStorage.d.ts.map +1 -1
  110. package/dist/memory/inMemoryStorage.js +2 -2
  111. package/dist/memory/inMemoryStorage.js.map +1 -1
  112. package/dist/memory/nodeSqliteStorage.d.ts +17 -0
  113. package/dist/memory/nodeSqliteStorage.d.ts.map +1 -0
  114. package/dist/memory/nodeSqliteStorage.js +393 -0
  115. package/dist/memory/nodeSqliteStorage.js.map +1 -0
  116. package/dist/memory/projectManager.d.ts +10 -20
  117. package/dist/memory/projectManager.d.ts.map +1 -1
  118. package/dist/memory/projectManager.js +27 -41
  119. package/dist/memory/projectManager.js.map +1 -1
  120. package/dist/memory/roundStore.d.ts +76 -1
  121. package/dist/memory/roundStore.d.ts.map +1 -1
  122. package/dist/memory/roundStore.js.map +1 -1
  123. package/dist/memory/roundSummaryLookup.d.ts +26 -0
  124. package/dist/memory/roundSummaryLookup.d.ts.map +1 -0
  125. package/dist/memory/roundSummaryLookup.js +19 -0
  126. package/dist/memory/roundSummaryLookup.js.map +1 -0
  127. package/dist/memory/sessionStore.d.ts +19 -2
  128. package/dist/memory/sessionStore.d.ts.map +1 -1
  129. package/dist/memory/sessionStore.js.map +1 -1
  130. package/dist/memory/sourceValidation.d.ts +2 -13
  131. package/dist/memory/sourceValidation.d.ts.map +1 -1
  132. package/dist/memory/sourceValidation.js +5 -16
  133. package/dist/memory/sourceValidation.js.map +1 -1
  134. package/dist/memory/storageInterface.d.ts +26 -16
  135. package/dist/memory/storageInterface.d.ts.map +1 -1
  136. package/dist/memory/supersedeResolve.d.ts +39 -0
  137. package/dist/memory/supersedeResolve.d.ts.map +1 -0
  138. package/dist/memory/supersedeResolve.js +16 -0
  139. package/dist/memory/supersedeResolve.js.map +1 -0
  140. package/dist/memory/types.d.ts +3 -2
  141. package/dist/memory/types.d.ts.map +1 -1
  142. package/dist/memory/types.js +2 -1
  143. package/dist/memory/types.js.map +1 -1
  144. package/dist/role-pack/rolePackManager.d.ts +33 -24
  145. package/dist/role-pack/rolePackManager.d.ts.map +1 -1
  146. package/dist/role-pack/rolePackManager.js +48 -42
  147. package/dist/role-pack/rolePackManager.js.map +1 -1
  148. package/dist/role-pack/strategyKeys.d.ts +8 -0
  149. package/dist/role-pack/strategyKeys.d.ts.map +1 -1
  150. package/dist/role-pack/strategyKeys.js +10 -0
  151. package/dist/role-pack/strategyKeys.js.map +1 -1
  152. package/dist/role-pack/strategyResolver.d.ts +6 -1
  153. package/dist/role-pack/strategyResolver.d.ts.map +1 -1
  154. package/dist/role-pack/strategyResolver.js +20 -2
  155. package/dist/role-pack/strategyResolver.js.map +1 -1
  156. package/dist/role-pack/types.d.ts +5 -1
  157. package/dist/role-pack/types.d.ts.map +1 -1
  158. package/dist/security/confirmEntries.d.ts +21 -6
  159. package/dist/security/confirmEntries.d.ts.map +1 -1
  160. package/dist/security/confirmEntries.js +21 -6
  161. package/dist/security/confirmEntries.js.map +1 -1
  162. package/dist/security/pathGuard.d.ts +44 -10
  163. package/dist/security/pathGuard.d.ts.map +1 -1
  164. package/dist/security/pathGuard.js +70 -10
  165. package/dist/security/pathGuard.js.map +1 -1
  166. package/dist/utils/backgroundTask.d.ts +56 -34
  167. package/dist/utils/backgroundTask.d.ts.map +1 -1
  168. package/dist/utils/backgroundTask.js +130 -99
  169. package/dist/utils/backgroundTask.js.map +1 -1
  170. package/dist/utils/errors.d.ts +3 -2
  171. package/dist/utils/errors.d.ts.map +1 -1
  172. package/dist/utils/errors.js +3 -2
  173. package/dist/utils/errors.js.map +1 -1
  174. package/dist/utils/eventEmitter.d.ts +20 -22
  175. package/dist/utils/eventEmitter.d.ts.map +1 -1
  176. package/dist/utils/eventEmitter.js +0 -3
  177. package/dist/utils/eventEmitter.js.map +1 -1
  178. package/dist/utils/time.d.ts +3 -3
  179. package/dist/utils/time.d.ts.map +1 -1
  180. package/dist/utils/time.js +3 -3
  181. package/dist/utils/time.js.map +1 -1
  182. package/dist/utils/toError.d.ts +1 -1
  183. package/dist/utils/toError.js +1 -1
  184. package/dist/web-fetch/loginWall.d.ts +39 -0
  185. package/dist/web-fetch/loginWall.d.ts.map +1 -0
  186. package/dist/web-fetch/loginWall.js +78 -0
  187. package/dist/web-fetch/loginWall.js.map +1 -0
  188. package/dist/web-fetch/types.d.ts +8 -0
  189. package/dist/web-fetch/types.d.ts.map +1 -1
  190. package/dist/web-fetch/webFetchProvider.d.ts.map +1 -1
  191. package/dist/web-fetch/webFetchProvider.js +3 -1
  192. package/dist/web-fetch/webFetchProvider.js.map +1 -1
  193. package/dist/web-search/fetchWebSearchProvider.js +28 -23
  194. package/dist/web-search/fetchWebSearchProvider.js.map +1 -1
  195. package/docs/architecture/role-pack-authoring-guide.md +7 -1
  196. package/docs/architecture/role-pack-spec.md +11 -6
  197. package/docs/memora-api-reference.md +1354 -1276
  198. 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
  199. package/docs/memora-/346/216/245/345/205/245/346/214/207/345/215/227.md +89 -49
  200. package/docs/role-pack-/345/274/200/346/224/276/351/224/256/346/214/207/345/215/227.md +148 -148
  201. package/package.json +13 -4
  202. package/role-packs/README.md +41 -40
  203. package/role-packs/memora/345/212/251/346/211/213/rules.md +5 -4
  204. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/manifest.json +1 -0
  205. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/persona.md +46 -46
  206. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/rules.md +17 -16
  207. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/emotion-wave.md +46 -46
  208. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/foreshadow.md +29 -29
  209. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/outline-expand.md +73 -48
  210. 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 +445 -441
  211. package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/story-bible.md +62 -62
  212. 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
  213. package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/rules.md +2 -1
  214. package/dist/agent/managers/dedupManager.d.ts +0 -85
  215. package/dist/agent/managers/dedupManager.d.ts.map +0 -1
  216. package/dist/agent/managers/dedupManager.js +0 -248
  217. package/dist/agent/managers/dedupManager.js.map +0 -1
  218. package/dist/agent/managers/goalConsistencyChecker.d.ts +0 -42
  219. package/dist/agent/managers/goalConsistencyChecker.d.ts.map +0 -1
  220. package/dist/agent/managers/goalConsistencyChecker.js +0 -178
  221. package/dist/agent/managers/goalConsistencyChecker.js.map +0 -1
  222. package/dist/agent/managers/llmJudgeHelper.d.ts +0 -21
  223. package/dist/agent/managers/llmJudgeHelper.d.ts.map +0 -1
  224. package/dist/agent/managers/llmJudgeHelper.js +0 -32
  225. package/dist/agent/managers/llmJudgeHelper.js.map +0 -1
  226. package/dist/agent/managers/memoryAdvisor.d.ts +0 -105
  227. package/dist/agent/managers/memoryAdvisor.d.ts.map +0 -1
  228. package/dist/agent/managers/memoryAdvisor.js +0 -322
  229. package/dist/agent/managers/memoryAdvisor.js.map +0 -1
  230. package/dist/agent/managers/memoryGovernance.d.ts +0 -24
  231. package/dist/agent/managers/memoryGovernance.d.ts.map +0 -1
  232. package/dist/agent/managers/memoryGovernance.js +0 -46
  233. package/dist/agent/managers/memoryGovernance.js.map +0 -1
  234. package/dist/memory/governance.d.ts +0 -17
  235. package/dist/memory/governance.d.ts.map +0 -1
  236. package/dist/memory/governance.js +0 -17
  237. package/dist/memory/governance.js.map +0 -1
  238. package/dist/memory/projectRegistry.d.ts +0 -47
  239. package/dist/memory/projectRegistry.d.ts.map +0 -1
  240. package/dist/memory/projectRegistry.js +0 -151
  241. package/dist/memory/projectRegistry.js.map +0 -1
  242. package/dist/utils/recallDefaults.d.ts +0 -16
  243. package/dist/utils/recallDefaults.d.ts.map +0 -1
  244. package/dist/utils/recallDefaults.js +0 -16
  245. package/dist/utils/recallDefaults.js.map +0 -1
@@ -7,10 +7,10 @@
7
7
  * 宿主拿不到它(实测宿主 `nowIso` 引用 = 0),宿主侧取当前时间仍是各自内联。
8
8
  * 本文件只是内核内部的推荐入口,不是跨包单一真源。
9
9
  *
10
- * API 对齐:formatDateKey(date) 与精灵 shared/dateUtils.ts 语义一致,
10
+ * API 对齐(历史):formatDateKey(date) 曾与精灵宿主 shared/dateUtils.ts 语义一致(该宿主已移除),
11
11
  * 用于格式化任意 Date 为 YYYY-MM-DD(本地时区)。
12
12
  */
13
- /** 一天对应的毫秒数(跨层共享,供天数差换算:诊断展示 daysSinceLastAccess / 推荐时效权重) */
13
+ /** 一天对应的毫秒数(天数差换算基准;当前消费者 = 存储契约测试构造 purgeExpired 过期时间戳) */
14
14
  export const ONE_DAY_MS = 24 * 60 * 60 * 1000;
15
15
  /**
16
16
  * 获取当前时间的 ISO 8601 时间戳
@@ -27,7 +27,7 @@ export function nowIso() {
27
27
  * 修复场景:Asia/Shanghai 凌晨 00:00-08:00 期间 UTC 仍是前一天,导致按日期分组的
28
28
  * 计数(chatTurns / dailyMessageCount)写入错误的日期 key。
29
29
  *
30
- * 与精灵 shared/dateUtils.ts:formatDateKey 行为完全对齐。
30
+ * 历史对齐对象:精灵宿主 shared/dateUtils.ts:formatDateKey(该宿主已移除,现本函数为内核内唯一实现)。
31
31
  *
32
32
  * @param date Date 对象
33
33
  * @returns YYYY-MM-DD 字符串(本地日期)
@@ -1 +1 @@
1
- {"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,aAAa,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,8CAA8C;AAC9C,gEAAgE;AAChE,qDAAqD;AACrD,iEAAiE;AACjE,uDAAuD;AACvD,sDAAsD;AACtD,EAAE;AACF,wBAAwB;AACxB,qDAAqD;AACrD,oEAAoE;AACpE,0CAA0C;AAC1C,4BAA4B;AAE5B;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAAe;IAC1D,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,OAAO,4BAA4B,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,aAAa,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,8CAA8C;AAC9C,gEAAgE;AAChE,qDAAqD;AACrD,iEAAiE;AACjE,uDAAuD;AACvD,sDAAsD;AACtD,EAAE;AACF,wBAAwB;AACxB,qDAAqD;AACrD,oEAAoE;AACpE,0CAA0C;AAC1C,4BAA4B;AAE5B;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAAe;IAC1D,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,OAAO,4BAA4B,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACtD,CAAC"}
@@ -4,7 +4,7 @@
4
4
  * 将 catch 块中的 unknown 值安全转换为 Error 对象。
5
5
  * 从 errors.ts 中提取,确保浏览器端可直接 import 而不引入 logging/ 模块。
6
6
  *
7
- * 转换规则(5 分支,与精灵 shared/toError.ts 行为对齐):
7
+ * 转换规则(5 分支;历史对齐对象精灵宿主 shared/toError.ts 已随该宿主移除,现为内核内唯一实现):
8
8
  * 1. Error 实例:原样返回
9
9
  * 2. 字符串:包装为 Error
10
10
  * 3. 含 message 属性的对象:提取 message 包装为 Error
@@ -4,7 +4,7 @@
4
4
  * 将 catch 块中的 unknown 值安全转换为 Error 对象。
5
5
  * 从 errors.ts 中提取,确保浏览器端可直接 import 而不引入 logging/ 模块。
6
6
  *
7
- * 转换规则(5 分支,与精灵 shared/toError.ts 行为对齐):
7
+ * 转换规则(5 分支;历史对齐对象精灵宿主 shared/toError.ts 已随该宿主移除,现为内核内唯一实现):
8
8
  * 1. Error 实例:原样返回
9
9
  * 2. 字符串:包装为 Error
10
10
  * 3. 含 message 属性的对象:提取 message 包装为 Error
@@ -0,0 +1,39 @@
1
+ /**
2
+ * 登录墙识别(SEARCH-QUALITY-1 P2-1)
3
+ *
4
+ * 问题:HTTP 200 的登录页被 `stripHtmlToText` 洗成「正文」——LLM 拿到一堆
5
+ * 「请登录 / 输入密码 / 注册新账号」的表单碎片,还以为是目标页面内容
6
+ * (「搜不准」的第二种形态:搜到了、也抓到了,但抓到的是一堵墙)。
7
+ *
8
+ * 判据(保守取向——**漏判 = 现状(可读页照常交付),误判 = 藏起可读页**,
9
+ * 故宁漏勿误,两条路径都要求「不像普通内容」才判墙):
10
+ * 1. **URL 强信号**:host/path 的**段边界**命中 login/signin/logon/passport/sso
11
+ * (段边界 = 段首/段尾由 `/` `.` `?` 或串首尾界定——防 `how-to-login`
12
+ * 教程、`mylogin` 之类词内子串误判;查询参数**值**里的 login 不算;
13
+ * `#fragment` 先剥除——锚点是**页内位置**不是页面身份,`article#login` 是文章)。
14
+ * 只认重定向后的 finalUrl(`FetchedPage.url`):带登录态参数的原始 URL
15
+ * 常常恰恰是要抓的页面,不能拿它判墙。
16
+ * 2. **弱信号组合**:标题登录词 **且** 正文密码词 **且** 正文很短
17
+ * (< `LOGIN_WALL_MAX_CONTENT_CHARS`)——单标题命中放行(教程/文档页
18
+ * 常谈「如何登录」),三条件同时满足才判墙。
19
+ * ⚠️ 长度判据只在**正文未被截断到阈值以下**时可信:调用方须传 `contentCap`
20
+ * (本次抓取的截断上限),cap < 阈值时「短正文」可能是截断假象 → 弱信号禁用
21
+ * (强信号不受影响——URL 身份与正文长短无关)。
22
+ *
23
+ * 纯函数:无 IO、零依赖,判据集中单点(toolExecutor web_fetch case 消费)。
24
+ * 命中后由调用方返回 hedged 提示(「可能」需登录——判据是启发式,不谎称确定);
25
+ * 「这页是否抓取失败」不归本函数(调用方以 `FetchedPage.fetchFailed` 先行排除)。
26
+ */
27
+ /**
28
+ * 判定抓取结果是否为登录墙(保守启发式,见文件头「宁漏勿误」)
29
+ *
30
+ * @param finalUrl 重定向后的实际 URL(`FetchedPage.url`;空串 = 无 URL 信息)
31
+ * @param title 页面标题(清洗后)
32
+ * @param content 页面正文(清洗后)
33
+ * @param contentCap 本次抓取的正文截断上限(toolExecutor 传 maxChars):
34
+ * 小于弱信号阈值时「短正文」可能是截断假象 → 弱信号禁用(强信号照常);
35
+ * 缺省 = 视为未截断(向后兼容既有调用形状)
36
+ * @returns true = 判为登录墙(调用方应明示不可读并引导换源)
37
+ */
38
+ export declare function isLoginWallPage(finalUrl: string, title: string, content: string, contentCap?: number): boolean;
39
+ //# sourceMappingURL=loginWall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loginWall.d.ts","sourceRoot":"","sources":["../../src/web-fetch/loginWall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AA2BH;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAoBT"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * 登录墙识别(SEARCH-QUALITY-1 P2-1)
3
+ *
4
+ * 问题:HTTP 200 的登录页被 `stripHtmlToText` 洗成「正文」——LLM 拿到一堆
5
+ * 「请登录 / 输入密码 / 注册新账号」的表单碎片,还以为是目标页面内容
6
+ * (「搜不准」的第二种形态:搜到了、也抓到了,但抓到的是一堵墙)。
7
+ *
8
+ * 判据(保守取向——**漏判 = 现状(可读页照常交付),误判 = 藏起可读页**,
9
+ * 故宁漏勿误,两条路径都要求「不像普通内容」才判墙):
10
+ * 1. **URL 强信号**:host/path 的**段边界**命中 login/signin/logon/passport/sso
11
+ * (段边界 = 段首/段尾由 `/` `.` `?` 或串首尾界定——防 `how-to-login`
12
+ * 教程、`mylogin` 之类词内子串误判;查询参数**值**里的 login 不算;
13
+ * `#fragment` 先剥除——锚点是**页内位置**不是页面身份,`article#login` 是文章)。
14
+ * 只认重定向后的 finalUrl(`FetchedPage.url`):带登录态参数的原始 URL
15
+ * 常常恰恰是要抓的页面,不能拿它判墙。
16
+ * 2. **弱信号组合**:标题登录词 **且** 正文密码词 **且** 正文很短
17
+ * (< `LOGIN_WALL_MAX_CONTENT_CHARS`)——单标题命中放行(教程/文档页
18
+ * 常谈「如何登录」),三条件同时满足才判墙。
19
+ * ⚠️ 长度判据只在**正文未被截断到阈值以下**时可信:调用方须传 `contentCap`
20
+ * (本次抓取的截断上限),cap < 阈值时「短正文」可能是截断假象 → 弱信号禁用
21
+ * (强信号不受影响——URL 身份与正文长短无关)。
22
+ *
23
+ * 纯函数:无 IO、零依赖,判据集中单点(toolExecutor web_fetch case 消费)。
24
+ * 命中后由调用方返回 hedged 提示(「可能」需登录——判据是启发式,不谎称确定);
25
+ * 「这页是否抓取失败」不归本函数(调用方以 `FetchedPage.fetchFailed` 先行排除)。
26
+ */
27
+ /**
28
+ * URL 登录段(段边界匹配)
29
+ *
30
+ * 段界定符:串首 `^`、`/`、`.`、`?`、串尾 `$`(`#fragment` 在判定前已剥除——
31
+ * 锚点是页内位置不是页面身份,`article#login` 是文章不是登录页)。
32
+ * `-` 刻意**不在**界定符内——`how-to-login` / `sign-in-page` 这类连字符复合词
33
+ * 是教程页的高频形态,放行它们(漏判代价)优于误判(藏可读页)。
34
+ * `sign-in` 以显式 alternation 收录(它是登录墙的常见路径形态)。
35
+ */
36
+ const URL_LOGIN_SEGMENT_RE = /(?:^|\/|\.|\?)(?:login|logon|signin|sign-in|passport|sso)(?:\/|\.|\?|$)/i;
37
+ /** 标题登录词(中英;不含「密码」——谈密码的文章标题不应触发弱信号) */
38
+ const TITLE_LOGIN_RE = /登录|登陆|登入|sign\s*in|log\s*in|logon/i;
39
+ /** 正文密码词(登录表单/提示语特征) */
40
+ const PASSWORD_WORD_RE = /密码|password|passcode/i;
41
+ /**
42
+ * 弱信号组合的正文长度上限(字符)
43
+ *
44
+ * 登录墙表单页天然短(几个输入框 + 按钮);长正文即使带登录词也更是教程/文档。
45
+ */
46
+ const LOGIN_WALL_MAX_CONTENT_CHARS = 600;
47
+ /**
48
+ * 判定抓取结果是否为登录墙(保守启发式,见文件头「宁漏勿误」)
49
+ *
50
+ * @param finalUrl 重定向后的实际 URL(`FetchedPage.url`;空串 = 无 URL 信息)
51
+ * @param title 页面标题(清洗后)
52
+ * @param content 页面正文(清洗后)
53
+ * @param contentCap 本次抓取的正文截断上限(toolExecutor 传 maxChars):
54
+ * 小于弱信号阈值时「短正文」可能是截断假象 → 弱信号禁用(强信号照常);
55
+ * 缺省 = 视为未截断(向后兼容既有调用形状)
56
+ * @returns true = 判为登录墙(调用方应明示不可读并引导换源)
57
+ */
58
+ export function isLoginWallPage(finalUrl, title, content, contentCap) {
59
+ // 强信号:URL 段边界命中即判(不要求正文佐证——登录态 URL 抓到 200 就是墙)。
60
+ // 先剥 #fragment:锚点是页内位置不是页面身份(article#login 是文章);
61
+ // split('#') 安全——合法 URL 中首个 # 即 fragment 起点(RFC 3986,查询串内 # 同义)
62
+ const urlWithoutFragment = finalUrl.split('#')[0] ?? finalUrl;
63
+ if (urlWithoutFragment && URL_LOGIN_SEGMENT_RE.test(urlWithoutFragment))
64
+ return true;
65
+ // 弱信号组合:标题登录词 + 正文密码词 + 短正文,三条件同时满足才判。
66
+ // contentCap < 阈值 → 长度判据失真(截断制造伪短正文)→ 整组禁用(宁漏勿误)
67
+ const weakSignalsUsable = contentCap === undefined || contentCap >= LOGIN_WALL_MAX_CONTENT_CHARS;
68
+ if (weakSignalsUsable &&
69
+ title &&
70
+ TITLE_LOGIN_RE.test(title) &&
71
+ content &&
72
+ PASSWORD_WORD_RE.test(content) &&
73
+ content.length < LOGIN_WALL_MAX_CONTENT_CHARS) {
74
+ return true;
75
+ }
76
+ return false;
77
+ }
78
+ //# sourceMappingURL=loginWall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loginWall.js","sourceRoot":"","sources":["../../src/web-fetch/loginWall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;;;;GAQG;AACH,MAAM,oBAAoB,GACxB,0EAA0E,CAAC;AAE7E,wCAAwC;AACxC,MAAM,cAAc,GAAG,oCAAoC,CAAC;AAE5D,wBAAwB;AACxB,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,KAAa,EACb,OAAe,EACf,UAAmB;IAEnB,gDAAgD;IAChD,iDAAiD;IACjD,gEAAgE;IAChE,MAAM,kBAAkB,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;IAC9D,IAAI,kBAAkB,IAAI,oBAAoB,CAAC,IAAI,CAAC,kBAAkB,CAAC;QAAE,OAAO,IAAI,CAAC;IACrF,uCAAuC;IACvC,iDAAiD;IACjD,MAAM,iBAAiB,GAAG,UAAU,KAAK,SAAS,IAAI,UAAU,IAAI,4BAA4B,CAAC;IACjG,IACE,iBAAiB;QACjB,KAAK;QACL,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1B,OAAO;QACP,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC;QAC9B,OAAO,CAAC,MAAM,GAAG,4BAA4B,EAC7C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -13,6 +13,14 @@ export interface FetchedPage {
13
13
  content: string;
14
14
  /** 内容类型(如 "text/html"、"application/pdf"),无法识别时为空串 */
15
15
  contentType?: string;
16
+ /**
17
+ * 抓取失败降级页标记(safeFetch 专有;成功路径恒缺省,宿主自定义 provider 不打标)
18
+ *
19
+ * 值恒 `true`:只有降级页会置位,无人能置 false——「这不是一次成功抓取」是单向事实。
20
+ * 消费方(toolExecutor 登录墙判断)据此排除「抓取失败 + 登录段 URL 被误报为登录墙」
21
+ * 的谎报路径(失败语义不得改写成别的原因)。可选字段 = 契约放宽,向后兼容。
22
+ */
23
+ fetchFailed?: true;
16
24
  }
17
25
  /** 抓取选项 */
18
26
  export interface FetchOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/web-fetch/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAe;AACf,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,WAAW;AACX,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,0BAA0B;IAC1B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAClE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/web-fetch/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAe;AACf,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,IAAI,CAAC;CACpB;AAED,WAAW;AACX,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,0BAA0B;IAC1B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAClE"}
@@ -1 +1 @@
1
- {"version":3,"file":"webFetchProvider.d.ts","sourceRoot":"","sources":["../../src/web-fetch/webFetchProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAKtF;;GAEG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,WAAW,CAAC,CAoBtB"}
1
+ {"version":3,"file":"webFetchProvider.d.ts","sourceRoot":"","sources":["../../src/web-fetch/webFetchProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAKtF;;GAEG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,WAAW,CAAC,CAsBtB"}
@@ -12,12 +12,14 @@ export async function safeFetch(provider, url, options) {
12
12
  return await Promise.race([provider.fetch(url, options), timeoutPromise]);
13
13
  }
14
14
  catch (err) {
15
- // 抓取失败不抛异常,返回降级提示页
15
+ // 抓取失败不抛异常,返回降级提示页;fetchFailed 单向标记 = 「这不是一次成功抓取」,
16
+ // 供消费方(toolExecutor 登录墙判断)排除「失败被误报为登录墙」的谎报路径
16
17
  const message = err instanceof Error ? err.message : String(err);
17
18
  return {
18
19
  url,
19
20
  title: '网页抓取暂不可用',
20
21
  content: `抓取失败:${message}。请稍后重试,或检查网络连接。`,
22
+ fetchFailed: true,
21
23
  };
22
24
  }
23
25
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"webFetchProvider.js","sourceRoot":"","sources":["../../src/web-fetch/webFetchProvider.ts"],"names":[],"mappings":"AAMA,mBAAmB;AACnB,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAwB,EACxB,GAAW,EACX,OAAsB;IAEtB,IAAI,KAAgD,CAAC;IACrD,MAAM,cAAc,GAAG,IAAI,OAAO,CAAc,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC5D,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,mBAAmB;QACnB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO;YACL,GAAG;YACH,KAAK,EAAE,UAAU;YACjB,OAAO,EAAE,QAAQ,OAAO,iBAAiB;SAC1C,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,2BAA2B;QAC3B,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"webFetchProvider.js","sourceRoot":"","sources":["../../src/web-fetch/webFetchProvider.ts"],"names":[],"mappings":"AAMA,mBAAmB;AACnB,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAwB,EACxB,GAAW,EACX,OAAsB;IAEtB,IAAI,KAAgD,CAAC;IACrD,MAAM,cAAc,GAAG,IAAI,OAAO,CAAc,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC5D,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,mDAAmD;QACnD,6CAA6C;QAC7C,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO;YACL,GAAG;YACH,KAAK,EAAE,UAAU;YACjB,OAAO,EAAE,QAAQ,OAAO,iBAAiB;YACzC,WAAW,EAAE,IAAI;SAClB,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,2BAA2B;QAC3B,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
@@ -2,34 +2,39 @@ import { BROWSER_UA, fetchWithTimeout } from '../utils/http.js';
2
2
  /** 单端点请求超时(ms):Bing 通常 1-2s 返回,10s 覆盖慢网络且不至于拖死主循环 */
3
3
  const ENDPOINT_TIMEOUT_MS = 10_000;
4
4
  /**
5
- * 从 Bing 结果页 HTML 提取结果:标题+链接在 <h2><a>,摘要在 <p class="b_lineclamp*">。
5
+ * 从 Bing 结果页 HTML 提取结果:结果条目 = `<li class="b_algo">` 块,块内 `<h2><a>` 取
6
+ * 标题+链接、块内 `<p class="b_lineclamp*">` 取摘要。
6
7
  * 用正则而非 DOM 解析,避免引入 jsdom 依赖。
8
+ *
9
+ * **块内配对**(而非全文两个正则数组按 index 配对,SEARCH-QUALITY-1 P2-2 修订):
10
+ * 标题与摘要必须在同一结果块内成对——全文收集 `titles[]`/`snippets[]` 后按 index 配对时,
11
+ * 结果块之外的任何 `b_lineclamp`(推荐位/广告位/侧栏)都会造成错位:模块摘要被贴到
12
+ * 下一个结果标题上,LLM 读到「标题二 + 干扰摘要」的错位组合(搜不准的解析层根因)。
13
+ * 结构漂移(无 b_algo 块)→ 零结果 → 降级链切下一端点 = 诚实失败,不产错位垃圾。
14
+ * 块内提取范式同 parseBaiduHtml(仓内既有正确先例,嫁接而非新造)。
7
15
  */
8
16
  function parseBingHtml(html, limit) {
9
17
  const results = [];
10
- const titleRegex = /<h2[^>]*><a[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a><\/h2>/g;
11
- const snippetRegex = /<p[^>]*class="b_lineclamp[^"]*"[^>]*>([\s\S]*?)<\/p>/g;
12
- const titles = [];
18
+ // 结果块:<li …b_algo…>…</li>([^>]* 容忍附加 class/属性,如 b_algoBorder)。
19
+ // ⚠️ 正则内**禁写引号**(如 class="[^"]*b_algo…):toolFailurePrefixGuard 的字符串字面量
20
+ // 提取器会把正则内的引号配对成伪字面量(`[^` → 盲区标记 `^`,旧 `^>` 同源产物)——
21
+ // 无引号写法对 Bing 的 <li class="b_algo"> 同等正确且不新增扫描噪声。
22
+ const blockRegex = /<li[^>]*b_algo[^>]*>([\s\S]*?)<\/li>/gi;
13
23
  let match;
14
- while ((match = titleRegex.exec(html)) !== null && titles.length < limit) {
15
- const url = match[1].replace(/&amp;/g, '&').trim();
16
- const title = match[2].replace(/<[^>]*>/g, '').trim();
17
- if (title && url) {
18
- titles.push({ url, title });
19
- }
20
- }
21
- const snippets = [];
22
- while ((match = snippetRegex.exec(html)) !== null && snippets.length < limit) {
23
- const snippet = match[1].replace(/<[^>]*>/g, '').trim();
24
- if (snippet)
25
- snippets.push(snippet);
26
- }
27
- for (let i = 0; i < Math.min(titles.length, limit); i++) {
28
- results.push({
29
- title: titles[i].title,
30
- url: titles[i].url,
31
- snippet: snippets[i] ?? '',
32
- });
24
+ while ((match = blockRegex.exec(html)) !== null && results.length < limit) {
25
+ const block = match[1];
26
+ // 标题 + 链接:块内 <h2><a href>(块内无标题 = 非结果块,跳过不占结果位)
27
+ const titleMatch = /<h2[^>]*><a[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/i.exec(block);
28
+ if (!titleMatch)
29
+ continue;
30
+ const url = titleMatch[1].replace(/&amp;/g, '&').trim();
31
+ const title = titleMatch[2].replace(/<[^>]*>/g, '').trim();
32
+ if (!url || !title)
33
+ continue;
34
+ // 摘要:块内 <p class="b_lineclamp*>(块内无摘要 → 空串,不跨块借用)
35
+ const snipMatch = /<p[^>]*class="b_lineclamp[^"]*"[^>]*>([\s\S]*?)<\/p>/i.exec(block);
36
+ const snippet = snipMatch?.[1]?.replace(/<[^>]*>/g, '').trim() ?? '';
37
+ results.push({ title, url, snippet });
33
38
  }
34
39
  return results;
35
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetchWebSearchProvider.js","sourceRoot":"","sources":["../../src/web-search/fetchWebSearchProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetchWebSearchProvider.js","sourceRoot":"","sources":["../../src/web-search/fetchWebSearchProvider.ts"],"names":[],"mappings":"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"}
@@ -79,6 +79,10 @@
79
79
 
80
80
  **推荐**:规则用**列表写**(每条一行,语义独立、可读性强);长段说明自然写成段落,会被合并为一条完整规则。写作时避免把示例代码/表格塞进 rules.md(会被忽略)——需要代码/资源放 `skills/` 目录(渐进披露 L3)。
81
81
 
82
+ **工具纪律基线(2026-10-25 增补)**:除角色专属规则外,建议每个包写一条**领域无关的编辑纪律**——增量写入优先(write_file 的 replace / insert / append)、同一文件的多处修订在**同一回复内连续发出**、整文件覆盖仅用于确需重建且不反复覆盖、复核只读改动片段。**为什么**:内核写侧护栏按「无进展」判据拦截(真源 `src/agent/guardRail.ts`;拒绝消息里的定位令牌只属运行时消息,见下方禁令),且同一 step 内同路径写已串行(`src/agent/loop.ts` 的同路径写链)——规则不写,模型会退化成「一处一停 + 反复整篇重写」(真机 `round-1792904123909`:7 次被拦、5 处修订拖到下轮、27 分钟 / 116 万输入 token)。三个内置包(`memora助手` / `共鸣小说家` / `白话方案设计师`)与宿主 `role-pack-creator` 模板均已内置该条。
83
+
84
+ > ⚠️ **令牌只在本指南里解释,勿写进 L1**:`[WRITE_LOOP_STOP]` / `[WRITE_FAIL_STOP]` 是**运行时拒绝消息**里的定位令牌,而 `rules.md` / `persona.md` 会常驻 system prompt——把令牌抄进 L1 会干扰「按令牌定位运行时拒绝消息」的消费方(纪律真源:`src/agent/guardRail.ts` 的 GUIDELINES)。L1 里只写行为纪律本身(如「反复整文件覆盖会被写侧护栏拦下」),不带令牌。
85
+
82
86
  ### 2.5 技能使用引导(persona/rules 里明确"何时用")
83
87
 
84
88
  > **推荐(2026-09-13 双锚点结论)**:角色包每内置一个 `skills/*.md`,都应在设定文本(persona.md 工作流程 / rules.md 纪律)里为它补一处**「使用时机」引导**——明示「什么情况使用这个 skill」。
@@ -157,6 +161,7 @@
157
161
  | --------------- | ---------------------------- | -------------------- | ------------------------------------- | ------------- | --------------------------- |
158
162
  | `askOn` | 数组(元素见下) | 1\~4 个元素 | `[ambiguity, decision, missing_info]` | 主动提问触发场景(可组合) | `["ambiguity", "decision"]` |
159
163
  | `askLimit` | 整数 | `1 ~ 10` | `10` | 每轮主动提问次数上限 | `2` |
164
+ | `webSearchLimit` | 整数 | `1 ~ 20` | `6` | 每轮联网搜索次数上限(web_search 硬护栏,超限确定性拒绝 + 停搜;与 `askLimit` 同构) | `12` |
160
165
  | `errorHandling` | `retry` / `degrade` / `stop` | — | `retry` | 异常处理策略 | `"degrade"` |
161
166
  | `contextLimit` | 整数 | `0` 或 `120000 ~ 2000000` | 未声明→`0`(跟随 provider 窗口) | 角色包上下文上限(**推荐 0**) | `0` |
162
167
  | `stepBudget` | 整数 | `0 ~ 500`(0=兜底,非不限) | `50` | 每轮工具步数上限(0=走内核 maxIterations 兜底,无「不限」路径) | `60` |
@@ -183,6 +188,7 @@
183
188
  | `toolStepLimit` | 0 | 100 | error | 回退默认 `0`(无限制) |
184
189
  | `selfReview` | 0 | 10 | error | 回退 `0`(关闭) |
185
190
  | `askLimit` | 1 | 10 | error | 回退默认 `10` |
191
+ | `webSearchLimit` | 1 | 20 | error | 回退默认 `6` |
186
192
  | `contextLimit` | 0 | 2000000 | error | 回退 `0`(跟随 provider 窗口) |
187
193
  | `stepBudget` | 0 | 500 | error | 回退默认 `50` |
188
194
 
@@ -211,7 +217,7 @@
211
217
 
212
218
  | 状态 | 含义 | 键 |
213
219
  | ----------- | ----------- | ------------- |
214
- | **已消费(冻结)** | 内核真实读取并影响行为 | 上述 §三 全部 16 键(prepare 1 / act 7 / reflect 3 / global 5) |
220
+ | **已消费(冻结)** | 内核真实读取并影响行为 | 上述 §三 全部 17 键(prepare 1 / act 7 / reflect 3 / global 6) |
215
221
 
216
222
  > 全部策略键现均已落地,无纯预留死键。`understandingConfirm` 已回收(2026-09-13,turn-intent-reasoning-design Part 3):confirm 并入 `askOn['confirm']`/ask_user 工具通道,echo 由内核 Turn 起始策略指令覆盖——确认场景统一走 ask_user 单一通道,不再作为开放键。已撤键先例:`costBudget`(2026-08-28,内核无定价能力、宿主无执行者)、`taskLoopLimit`(2026-09-06,多 turn 编排删除 + 会议确定性预置退役后无常量消费方)、prepare 召回策略键族 6 键(2026-09-09 阶段2,记忆纯工具化召回后无自动注入消费端)、`toolApproval`(2026-09-11,审批链无执行方的展示性假承诺)、`streaming`(2026-09-11,写而不读的假旋钮——内核 provider 恒 `stream:true`)、`loopContinue`(2026-09-11,v0.13- 别名;安装基数 0 → 兼容防的是从未发生的场景,按版本契约分面「作者输入面可不兼容」删除)——**无消费者 / 无真实兼容对象的策略键不保留**。诚实化声明见 `src/role-pack/types.ts` `BehaviorStrategy` 注释。
217
223
 
@@ -258,9 +258,11 @@ description: 把成稿写入本地文件
258
258
 
259
259
  **技能引用格式(内容面约定)**:技能名同时是**文件名**与**引用名**——**名字即契约**(`skills/<name>.md` 的 `name` 与载入标识一致,改名属破坏性变更)。设定文本(persona / rules)引用技能时须用**反引号包裹技能名**(写成 `foreshadow` 这样的形式),使引用可被机器**双向校验**:每个技能至少被引用一次(防僵尸技能)+ 每条引用都指向真实存在的技能(防改名残留的悬空引用)。完整作者侧规范见 [role-pack-authoring-guide.md](./role-pack-authoring-guide.md) §2.6。
260
260
 
261
- **具体连接桥(L2 可选,`mcp.json`)**:capabilities 是**抽象能力声明**(要什么能力、实现无关);当角色包需要**开箱即用**的具象连接时,可在文件夹根放 `mcp.json`(对齐 Agent Plugins 1.0 的 transport 声明:`stdio` / `streamable-http` / `http+sse`),由实现映射到自有运行时。两者不冲突:**capabilities 是 L1 中立契约,mcp.json 是 L2 可选实现加速**——不声明 mcp.json 的角色包仍可被任何实现按 capabilities 装载。
261
+ **具体连接桥(L2 可选,`mcp.json`)——⛔ 已撤销(2026-10-25),见下条状态行**:capabilities 是**抽象能力声明**(要什么能力、实现无关);当角色包需要**开箱即用**的具象连接时,可在文件夹根放 `mcp.json`(对齐 Agent Plugins 1.0 的 transport 声明:`stdio` / `streamable-http` / `http+sse`),由实现映射到自有运行时。两者不冲突:**capabilities 是 L1 中立契约,mcp.json 是 L2 可选实现加速**——不声明 mcp.json 的角色包仍可被任何实现按 capabilities 装载。
262
262
 
263
- > **`[草案]`(2026-09-08 状态收敛)**:`mcp.json` 为 L2 可选机制,当前**无参考实现消费**(memora 参考实现不装载 mcp.json,实现按「未知文件忽略」回退 L1 capabilities)。按 §六 双闸门纪律标注 `[草案]`,征集实现验证后冻结。
263
+ > **`[草案]`(2026-09-08 状态收敛,已被下条取代)**:`mcp.json` 为 L2 可选机制,当前**无参考实现消费**(memora 参考实现不装载 mcp.json,实现按「未知文件忽略」回退 L1 capabilities)。按 §六 双闸门纪律标注 `[草案]`,征集实现验证后冻结。
264
+
265
+ > **⛔ 已撤销(2026-10-25 定案)**:上面 `[草案]` 的语义是「暂无参考实现消费,征集验证后冻结」——**该语义已不成立**。同日用户拍板 **角色包不得声明 MCP server**,这是**性质否决**而非「暂无实现」:角色包管**内容面**(persona / rules / skills = 你是谁、怎么做事),MCP server = **在本机拉起的任意进程**(写一条配置 = 授权一条命令在你的机器上执行 = **用户授权面**);两者不同源,塞进同一容器即「配置来源与授权来源合流」= 仓库作者替使用者点同意。⇒ **不再征集实现验证**,任何实现不得据此装载角色包级 MCP 声明。现行锚点(仓库内,不随本文件发布):`docs/方案-MCP工具接入-20261023.md` §4.4(授权边界)· `.trae/rules/memory-role-pack-boundary-rules.md` R10。
264
266
 
265
267
  ### 四·一 标准能力命名空间(中立语义字典,v1 最小集)
266
268
 
@@ -287,9 +289,11 @@ description: 把成稿写入本地文件
287
289
  2. **中立门**:冻结后的能力名不可重命名,语义不可变更——实现向标准看齐,而非标准向实现看齐;
288
290
  3. 已知能力名(不在本表内)按「未知能力跳过」装载(§四),不阻塞。
289
291
 
290
- ### 四·二 MCP 集成设计(接口定义 + 角色包声明路径)
292
+ ### 四·二 MCP 集成设计(⛔ 已撤销 · 仅历史记录,不属现行标准)
291
293
 
292
294
  > **定位**:MCP(Model Context Protocol)是 2026 年行业标准工具调用协议。角色包标准不要求任何实现必须支持 MCP,但支持 MCP 的实现应遵循本节定义的抽象接口和声明路径,以保证角色包跨实现可移植性。
295
+ >
296
+ > **⛔ 本节已整体撤销(2026-10-25)**:以下 `mcp.json` 声明格式与 `IMcpTransport` 接口**仅为历史设计记录,不属现行标准**——「支持 MCP 的实现应遵循本节」这句已失效。角色包不得声明 MCP server(判据见 §四 末条状态行);memora 参考实现的 MCP 接入是**宿主侧用户级配置**,与角色包无关。
293
297
 
294
298
  **核心原则**:MCP 是 L2 传输层细节,不是 L1 能力声明。
295
299
 
@@ -460,7 +464,8 @@ export interface IMcpTransport {
460
464
  | reflect | `reflect.selfReview` | 布尔数字:`0` / 正整数(兼容旧 'on'→1 / 'off'→0) | 自审查开关(**布尔数字语义(2026-09-12 定案)**:0=不自审查;**正整数 >0 一律收敛为 1=自审查一次,大于 1 的数同样算作 1**)。当且仅当本 turn 执行过工具步(多 step 文本交付)后做一次终审;纯文本一遍问答不触发 | 冻结 | memora 消费(strategyResolver `resolveL2Strategy` 收敛 >0 → `selfReviewEnabled=true`,消费端终审即停);**由实现提炼进标准**(spec 原缺,对账发现被真实消费后补录) |
461
465
  | reflect | `reflect.userFollowup` | `ask` / `silent` | 用户追问策略:ask=主动引导对话 / silent=只等输入 | 冻结 | memora 消费(agent.ts 衔接 + types.ts 提问指令注入);**由实现提炼进标准**(spec 原缺,对账发现被真实消费后补录) |
462
466
  | global | `global.askOn` | `ambiguity` / `decision` / `missing_info` / `confirm` | Agent 主动提问触发(可组合) | 冻结-条件消费 | memora 消费(types.ts `assembleRolePack` 提问指令注入,**仅** **`reflect.userFollowup=ask`** **时生效**);条件消费 = 字段冻结,但行为仅在指定策略组合下激活 |
463
- | global | `global.askLimit` | 正整数(默认 3) | 每任务提问上限 | 冻结-条件消费 | memora 消费(同上,userFollowup=ask 时生效,缺省 3) |
467
+ | global | `global.askLimit` | 正整数(默认 10) | 每任务提问上限 | 冻结-条件消费 | memora 消费(同上,userFollowup=ask 时生效,缺省 10) |
468
+ | global | `global.webSearchLimit` | 正整数(1~20,默认 6) | 每任务联网搜索次数上限(web_search 硬护栏:turn 粒度超限确定性拒绝 + 停搜) | 冻结 | memora 消费(strategyResolver `resolveWebSearchLimit` → `resolveL2Strategy` → loop `executeToolCalls` 构 `GuardThresholds.maxWebSearch`,`guardRail.ts` 消费阈值与文案);**由实现提炼进标准**(对账发现被真实消费后补录,GUARD-SEARCH-1 2026-10-14) |
464
469
  | global | `global.errorHandling` | `retry` / `degrade` / `stop` | 异常策略 | 冻结 | memora 消费(strategyResolver `resolveErrorHandling` → loop 异常处理分支,非法值归位 retry);**由实现提炼进标准**(对账发现被真实消费后补录) |
465
470
  | global | `global.taskLoopLimit` | 非负整数(默认 10,0=关闭) | 外部任务驱动循环步数上限(**删除**:多 turn 任务编排 2026-09-04 删除后语义收窄为「会议步骤数截断」,2026-09-06 会议确定性预置退役(ADR-028 收敛补记)后键已无常量消费方,实现直接移除,不留过渡兼容) | 废弃 | 三度收敛:多 turn 上限 → 会议截断 → 删除;现迭代上限由 `stepBudget`/`maxIterations` 承载 |
466
471
 
@@ -756,12 +761,12 @@ loop 何时收敛停止,由以下三条确定性信号 OR 触发,任一命
756
761
 
757
762
  1. **角色包不自洽**:角色包不包含执行引擎,依赖宿主 Agent 的闭环引擎运行。这一特性天然适用于多 Agent 场景——每个角色包实例是一个独立 Agent,由宿主编排。
758
763
  2. **interactionType 扩展点**:`interactionType` 字段(§七)当前为 `tool_assistant` / `companion` 二分,未来可扩展 `gateway` 或 `coordinator` 等角色类型,由宿主注入 A2A 路由逻辑。
759
- 3. **能力声明可路由**:`capabilities` 声明(§四)是中立能力名,多 Agent 宿主可基于能力名将子任务路由到对应角色包实例——memora 的插卡模型天然支持这种"Triage and Specialist"架构(2026 年行业标准,见 [§四·二 MCP 集成设计](#四二-mcp-集成设计接口定义--角色包声明路径))。
764
+ 3. **能力声明可路由**:`capabilities` 声明(§四)是中立能力名,多 Agent 宿主可基于能力名将子任务路由到对应角色包实例——memora 的插卡模型天然支持这种"Triage and Specialist"架构(2026 年行业标准;宿主注入范式可参考既有 `IWebSearchProvider` / `ICodeExecutionProvider`)。
760
765
  4. **当前不实现**:memora 内核不包含 A2A 客户端代码,不定义 A2A 传输接口。多 Agent 编排由宿主在闭环引擎之上实现,内核不感知。
761
766
 
762
767
  **未来演进方向**(非承诺):
763
768
 
764
769
  * 当生态需要多角色包协作时,可定义 `A2A 声明` 字段(如 `dependsOn: ["role-pack-a", "role-pack-b"]`),由宿主负责解析依赖并启动对应的 Agent 实例;
765
770
 
766
- * A2A 传输层可复用 `IMcpTransport` 相同的注入模式(依赖倒置,宿主注入),不引入内核依赖。
771
+ * A2A 传输层可复用宿主侧的依赖倒置注入范式(与 `IWebSearchProvider` 同构、由宿主注入),不引入内核依赖。
767
772