@zooique/memora 0.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 (239) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -0
  3. package/dist/agent/agent.d.ts +343 -0
  4. package/dist/agent/agent.d.ts.map +1 -0
  5. package/dist/agent/agent.js +893 -0
  6. package/dist/agent/agent.js.map +1 -0
  7. package/dist/agent/assembler.d.ts +77 -0
  8. package/dist/agent/assembler.d.ts.map +1 -0
  9. package/dist/agent/assembler.js +115 -0
  10. package/dist/agent/assembler.js.map +1 -0
  11. package/dist/agent/builtinToolHandlers.d.ts +96 -0
  12. package/dist/agent/builtinToolHandlers.d.ts.map +1 -0
  13. package/dist/agent/builtinToolHandlers.js +388 -0
  14. package/dist/agent/builtinToolHandlers.js.map +1 -0
  15. package/dist/agent/builtinTools.d.ts +35 -0
  16. package/dist/agent/builtinTools.d.ts.map +1 -0
  17. package/dist/agent/builtinTools.js +75 -0
  18. package/dist/agent/builtinTools.js.map +1 -0
  19. package/dist/agent/constants.d.ts +67 -0
  20. package/dist/agent/constants.d.ts.map +1 -0
  21. package/dist/agent/constants.js +67 -0
  22. package/dist/agent/constants.js.map +1 -0
  23. package/dist/agent/contextManager.d.ts +130 -0
  24. package/dist/agent/contextManager.d.ts.map +1 -0
  25. package/dist/agent/contextManager.js +287 -0
  26. package/dist/agent/contextManager.js.map +1 -0
  27. package/dist/agent/loop.d.ts +288 -0
  28. package/dist/agent/loop.d.ts.map +1 -0
  29. package/dist/agent/loop.js +756 -0
  30. package/dist/agent/loop.js.map +1 -0
  31. package/dist/agent/managers/autoConfigRefiner.d.ts +39 -0
  32. package/dist/agent/managers/autoConfigRefiner.d.ts.map +1 -0
  33. package/dist/agent/managers/autoConfigRefiner.js +150 -0
  34. package/dist/agent/managers/autoConfigRefiner.js.map +1 -0
  35. package/dist/agent/managers/configManager.d.ts +114 -0
  36. package/dist/agent/managers/configManager.d.ts.map +1 -0
  37. package/dist/agent/managers/configManager.js +186 -0
  38. package/dist/agent/managers/configManager.js.map +1 -0
  39. package/dist/agent/managers/insightExtractor.d.ts +141 -0
  40. package/dist/agent/managers/insightExtractor.d.ts.map +1 -0
  41. package/dist/agent/managers/insightExtractor.js +420 -0
  42. package/dist/agent/managers/insightExtractor.js.map +1 -0
  43. package/dist/agent/managers/memoryAdvisor.d.ts +96 -0
  44. package/dist/agent/managers/memoryAdvisor.d.ts.map +1 -0
  45. package/dist/agent/managers/memoryAdvisor.js +198 -0
  46. package/dist/agent/managers/memoryAdvisor.js.map +1 -0
  47. package/dist/agent/managers/memoryInspector.d.ts +231 -0
  48. package/dist/agent/managers/memoryInspector.d.ts.map +1 -0
  49. package/dist/agent/managers/memoryInspector.js +327 -0
  50. package/dist/agent/managers/memoryInspector.js.map +1 -0
  51. package/dist/agent/managers/sessionManager.d.ts +89 -0
  52. package/dist/agent/managers/sessionManager.d.ts.map +1 -0
  53. package/dist/agent/managers/sessionManager.js +178 -0
  54. package/dist/agent/managers/sessionManager.js.map +1 -0
  55. package/dist/agent/managers/userFactExtractor.d.ts +25 -0
  56. package/dist/agent/managers/userFactExtractor.d.ts.map +1 -0
  57. package/dist/agent/managers/userFactExtractor.js +81 -0
  58. package/dist/agent/managers/userFactExtractor.js.map +1 -0
  59. package/dist/agent/managers/workProjection.d.ts +117 -0
  60. package/dist/agent/managers/workProjection.d.ts.map +1 -0
  61. package/dist/agent/managers/workProjection.js +290 -0
  62. package/dist/agent/managers/workProjection.js.map +1 -0
  63. package/dist/agent/messageHistory.d.ts +157 -0
  64. package/dist/agent/messageHistory.d.ts.map +1 -0
  65. package/dist/agent/messageHistory.js +288 -0
  66. package/dist/agent/messageHistory.js.map +1 -0
  67. package/dist/agent/toolExecutor.d.ts +137 -0
  68. package/dist/agent/toolExecutor.d.ts.map +1 -0
  69. package/dist/agent/toolExecutor.js +209 -0
  70. package/dist/agent/toolExecutor.js.map +1 -0
  71. package/dist/agent/tracer.d.ts +122 -0
  72. package/dist/agent/tracer.d.ts.map +1 -0
  73. package/dist/agent/tracer.js +64 -0
  74. package/dist/agent/tracer.js.map +1 -0
  75. package/dist/agent/types.d.ts +98 -0
  76. package/dist/agent/types.d.ts.map +1 -0
  77. package/dist/agent/types.js +19 -0
  78. package/dist/agent/types.js.map +1 -0
  79. package/dist/config/loader.d.ts +229 -0
  80. package/dist/config/loader.d.ts.map +1 -0
  81. package/dist/config/loader.js +194 -0
  82. package/dist/config/loader.js.map +1 -0
  83. package/dist/eval/evalTypes.d.ts +118 -0
  84. package/dist/eval/evalTypes.d.ts.map +1 -0
  85. package/dist/eval/evalTypes.js +102 -0
  86. package/dist/eval/evalTypes.js.map +1 -0
  87. package/dist/index.d.ts +61 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +44 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/llm/embedding.d.ts +62 -0
  92. package/dist/llm/embedding.d.ts.map +1 -0
  93. package/dist/llm/embedding.js +162 -0
  94. package/dist/llm/embedding.js.map +1 -0
  95. package/dist/llm/factory.d.ts +39 -0
  96. package/dist/llm/factory.d.ts.map +1 -0
  97. package/dist/llm/factory.js +108 -0
  98. package/dist/llm/factory.js.map +1 -0
  99. package/dist/llm/openaiCompatible.d.ts +63 -0
  100. package/dist/llm/openaiCompatible.d.ts.map +1 -0
  101. package/dist/llm/openaiCompatible.js +340 -0
  102. package/dist/llm/openaiCompatible.js.map +1 -0
  103. package/dist/llm/provider.d.ts +91 -0
  104. package/dist/llm/provider.d.ts.map +1 -0
  105. package/dist/llm/provider.js +14 -0
  106. package/dist/llm/provider.js.map +1 -0
  107. package/dist/llm/types.d.ts +25 -0
  108. package/dist/llm/types.d.ts.map +1 -0
  109. package/dist/llm/types.js +7 -0
  110. package/dist/llm/types.js.map +1 -0
  111. package/dist/logging/logger.d.ts +39 -0
  112. package/dist/logging/logger.d.ts.map +1 -0
  113. package/dist/logging/logger.js +279 -0
  114. package/dist/logging/logger.js.map +1 -0
  115. package/dist/logging/loggerInterface.d.ts +33 -0
  116. package/dist/logging/loggerInterface.d.ts.map +1 -0
  117. package/dist/logging/loggerInterface.js +2 -0
  118. package/dist/logging/loggerInterface.js.map +1 -0
  119. package/dist/memory/inMemoryRelationStore.d.ts +51 -0
  120. package/dist/memory/inMemoryRelationStore.d.ts.map +1 -0
  121. package/dist/memory/inMemoryRelationStore.js +65 -0
  122. package/dist/memory/inMemoryRelationStore.js.map +1 -0
  123. package/dist/memory/inMemoryStorage.d.ts +97 -0
  124. package/dist/memory/inMemoryStorage.d.ts.map +1 -0
  125. package/dist/memory/inMemoryStorage.js +177 -0
  126. package/dist/memory/inMemoryStorage.js.map +1 -0
  127. package/dist/memory/loader.d.ts +49 -0
  128. package/dist/memory/loader.d.ts.map +1 -0
  129. package/dist/memory/loader.js +93 -0
  130. package/dist/memory/loader.js.map +1 -0
  131. package/dist/memory/projectManager.d.ts +182 -0
  132. package/dist/memory/projectManager.d.ts.map +1 -0
  133. package/dist/memory/projectManager.js +441 -0
  134. package/dist/memory/projectManager.js.map +1 -0
  135. package/dist/memory/recall.d.ts +77 -0
  136. package/dist/memory/recall.d.ts.map +1 -0
  137. package/dist/memory/recall.js +147 -0
  138. package/dist/memory/recall.js.map +1 -0
  139. package/dist/memory/relationStore.d.ts +78 -0
  140. package/dist/memory/relationStore.d.ts.map +1 -0
  141. package/dist/memory/relationStore.js +2 -0
  142. package/dist/memory/relationStore.js.map +1 -0
  143. package/dist/memory/sessionStore.d.ts +84 -0
  144. package/dist/memory/sessionStore.d.ts.map +1 -0
  145. package/dist/memory/sessionStore.js +2 -0
  146. package/dist/memory/sessionStore.js.map +1 -0
  147. package/dist/memory/storageInterface.d.ts +107 -0
  148. package/dist/memory/storageInterface.d.ts.map +1 -0
  149. package/dist/memory/storageInterface.js +2 -0
  150. package/dist/memory/storageInterface.js.map +1 -0
  151. package/dist/memory/store.d.ts +50 -0
  152. package/dist/memory/store.d.ts.map +1 -0
  153. package/dist/memory/store.js +160 -0
  154. package/dist/memory/store.js.map +1 -0
  155. package/dist/memory/types.d.ts +189 -0
  156. package/dist/memory/types.d.ts.map +1 -0
  157. package/dist/memory/types.js +230 -0
  158. package/dist/memory/types.js.map +1 -0
  159. package/dist/memory/userProfile.d.ts +156 -0
  160. package/dist/memory/userProfile.d.ts.map +1 -0
  161. package/dist/memory/userProfile.js +315 -0
  162. package/dist/memory/userProfile.js.map +1 -0
  163. package/dist/memory/vectorStore.d.ts +75 -0
  164. package/dist/memory/vectorStore.d.ts.map +1 -0
  165. package/dist/memory/vectorStore.js +144 -0
  166. package/dist/memory/vectorStore.js.map +1 -0
  167. package/dist/persona/personaManager.d.ts +121 -0
  168. package/dist/persona/personaManager.d.ts.map +1 -0
  169. package/dist/persona/personaManager.js +349 -0
  170. package/dist/persona/personaManager.js.map +1 -0
  171. package/dist/persona/types.d.ts +32 -0
  172. package/dist/persona/types.d.ts.map +1 -0
  173. package/dist/persona/types.js +5 -0
  174. package/dist/persona/types.js.map +1 -0
  175. package/dist/security/pathGuard.d.ts +121 -0
  176. package/dist/security/pathGuard.d.ts.map +1 -0
  177. package/dist/security/pathGuard.js +276 -0
  178. package/dist/security/pathGuard.js.map +1 -0
  179. package/dist/skill/skillManager.d.ts +82 -0
  180. package/dist/skill/skillManager.d.ts.map +1 -0
  181. package/dist/skill/skillManager.js +198 -0
  182. package/dist/skill/skillManager.js.map +1 -0
  183. package/dist/skill/types.d.ts +28 -0
  184. package/dist/skill/types.d.ts.map +1 -0
  185. package/dist/skill/types.js +5 -0
  186. package/dist/skill/types.js.map +1 -0
  187. package/dist/utils/errors.d.ts +86 -0
  188. package/dist/utils/errors.d.ts.map +1 -0
  189. package/dist/utils/errors.js +143 -0
  190. package/dist/utils/errors.js.map +1 -0
  191. package/dist/utils/eventEmitter.d.ts +87 -0
  192. package/dist/utils/eventEmitter.d.ts.map +1 -0
  193. package/dist/utils/eventEmitter.js +79 -0
  194. package/dist/utils/eventEmitter.js.map +1 -0
  195. package/dist/utils/frontmatter.d.ts +24 -0
  196. package/dist/utils/frontmatter.d.ts.map +1 -0
  197. package/dist/utils/frontmatter.js +44 -0
  198. package/dist/utils/frontmatter.js.map +1 -0
  199. package/dist/utils/json.d.ts +20 -0
  200. package/dist/utils/json.d.ts.map +1 -0
  201. package/dist/utils/json.js +65 -0
  202. package/dist/utils/json.js.map +1 -0
  203. package/dist/utils/loggerHolder.d.ts +37 -0
  204. package/dist/utils/loggerHolder.d.ts.map +1 -0
  205. package/dist/utils/loggerHolder.js +49 -0
  206. package/dist/utils/loggerHolder.js.map +1 -0
  207. package/dist/utils/math.d.ts +5 -0
  208. package/dist/utils/math.d.ts.map +1 -0
  209. package/dist/utils/math.js +19 -0
  210. package/dist/utils/math.js.map +1 -0
  211. package/dist/utils/path.d.ts +28 -0
  212. package/dist/utils/path.d.ts.map +1 -0
  213. package/dist/utils/path.js +33 -0
  214. package/dist/utils/path.js.map +1 -0
  215. package/dist/utils/safeTimer.d.ts +26 -0
  216. package/dist/utils/safeTimer.d.ts.map +1 -0
  217. package/dist/utils/safeTimer.js +49 -0
  218. package/dist/utils/safeTimer.js.map +1 -0
  219. package/dist/utils/scanner.d.ts +54 -0
  220. package/dist/utils/scanner.d.ts.map +1 -0
  221. package/dist/utils/scanner.js +115 -0
  222. package/dist/utils/scanner.js.map +1 -0
  223. package/dist/utils/segmenter.d.ts +30 -0
  224. package/dist/utils/segmenter.d.ts.map +1 -0
  225. package/dist/utils/segmenter.js +80 -0
  226. package/dist/utils/segmenter.js.map +1 -0
  227. package/dist/utils/strings.d.ts +18 -0
  228. package/dist/utils/strings.d.ts.map +1 -0
  229. package/dist/utils/strings.js +25 -0
  230. package/dist/utils/strings.js.map +1 -0
  231. package/dist/utils/time.d.ts +23 -0
  232. package/dist/utils/time.d.ts.map +1 -0
  233. package/dist/utils/time.js +31 -0
  234. package/dist/utils/time.js.map +1 -0
  235. package/dist/utils/toError.d.ts +13 -0
  236. package/dist/utils/toError.d.ts.map +1 -0
  237. package/dist/utils/toError.js +22 -0
  238. package/dist/utils/toError.js.map +1 -0
  239. package/package.json +73 -0
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Frontmatter 通用解析/序列化工具
3
+ *
4
+ * 为 memory/store.ts、persona/personaManager.ts、skill/skillManager.ts 提供共享的 frontmatter 处理
5
+ * 详见 ADR-004 · 记忆统一为"类型 + 永久性标记"模型
6
+ */
7
+ /**
8
+ * 解析 frontmatter 块为键值对
9
+ *
10
+ * @param raw 完整 markdown 内容(含 `---` 包围的 frontmatter)
11
+ * @returns `{ frontmatter, body }`——frontmatter 为键值对对象,body 为 frontmatter 之后的内容
12
+ */
13
+ export declare function parseFrontmatter(raw: string): {
14
+ frontmatter: Record<string, string>;
15
+ body: string;
16
+ };
17
+ /**
18
+ * 序列化 frontmatter 为 YAML 块内容(不含 `---` 包围符)
19
+ *
20
+ * @param frontmatter 键值对对象
21
+ * @returns 可拼接进 `---\n${result}\n---\n${body}` 的字符串
22
+ */
23
+ export declare function serializeFrontmatter(frontmatter: Record<string, string>): string;
24
+ //# sourceMappingURL=frontmatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAC7C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd,CAkBA;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAKhF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Frontmatter 通用解析/序列化工具
3
+ *
4
+ * 为 memory/store.ts、persona/personaManager.ts、skill/skillManager.ts 提供共享的 frontmatter 处理
5
+ * 详见 ADR-004 · 记忆统一为"类型 + 永久性标记"模型
6
+ */
7
+ /**
8
+ * 解析 frontmatter 块为键值对
9
+ *
10
+ * @param raw 完整 markdown 内容(含 `---` 包围的 frontmatter)
11
+ * @returns `{ frontmatter, body }`——frontmatter 为键值对对象,body 为 frontmatter 之后的内容
12
+ */
13
+ export function parseFrontmatter(raw) {
14
+ const normalized = raw.replace(/\r\n/g, '\n');
15
+ const match = normalized.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
16
+ if (!match || !match[1] || !match[2]) {
17
+ return { frontmatter: {}, body: raw };
18
+ }
19
+ const [, fmBlock, body] = match;
20
+ const frontmatter = {};
21
+ for (const line of fmBlock.split('\n')) {
22
+ const idx = line.indexOf(':');
23
+ if (idx < 0)
24
+ continue;
25
+ const k = line.slice(0, idx).trim();
26
+ const v = line.slice(idx + 1).trim();
27
+ if (k && v)
28
+ frontmatter[k] = v;
29
+ }
30
+ return { frontmatter, body };
31
+ }
32
+ /**
33
+ * 序列化 frontmatter 为 YAML 块内容(不含 `---` 包围符)
34
+ *
35
+ * @param frontmatter 键值对对象
36
+ * @returns 可拼接进 `---\n${result}\n---\n${body}` 的字符串
37
+ */
38
+ export function serializeFrontmatter(frontmatter) {
39
+ return Object.entries(frontmatter)
40
+ .filter(([, v]) => v !== undefined && v !== null)
41
+ .map(([k, v]) => `${k}: ${v}`)
42
+ .join('\n');
43
+ }
44
+ //# sourceMappingURL=frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAI1C,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACpE,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;IAChC,MAAM,WAAW,GAA2B,EAAE,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,GAAG,CAAC;YAAE,SAAS;QACtB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC;YAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmC;IACtE,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;SAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC;SAChD,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;SAC7B,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * JSON 工具函数
3
+ *
4
+ * 从 InsightExtractor 和 WorkProjectionManager 提取的公共 JSON 解析函数,
5
+ * 统一 LLM 输出的 JSON 解析策略。
6
+ */
7
+ /**
8
+ * 从 LLM 输出中解析 JSON
9
+ *
10
+ * 解析策略(逐级回退):
11
+ * 1. 直接 JSON.parse
12
+ * 2. 剥离 markdown 代码块标记后重试
13
+ * 3. 修复常见错误(单引号、尾逗号)后重试
14
+ * 4. 正则提取首个 JSON 对象
15
+ *
16
+ * @param raw - LLM 原始输出文本
17
+ * @returns 解析结果,解析失败返回 null
18
+ */
19
+ export declare function parseLlmJson<T = unknown>(raw: string): T | null;
20
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/utils/json.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CA6C/D"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * JSON 工具函数
3
+ *
4
+ * 从 InsightExtractor 和 WorkProjectionManager 提取的公共 JSON 解析函数,
5
+ * 统一 LLM 输出的 JSON 解析策略。
6
+ */
7
+ /**
8
+ * 从 LLM 输出中解析 JSON
9
+ *
10
+ * 解析策略(逐级回退):
11
+ * 1. 直接 JSON.parse
12
+ * 2. 剥离 markdown 代码块标记后重试
13
+ * 3. 修复常见错误(单引号、尾逗号)后重试
14
+ * 4. 正则提取首个 JSON 对象
15
+ *
16
+ * @param raw - LLM 原始输出文本
17
+ * @returns 解析结果,解析失败返回 null
18
+ */
19
+ export function parseLlmJson(raw) {
20
+ const trimmed = raw.trim();
21
+ if (!trimmed || trimmed === 'null')
22
+ return null;
23
+ // 1. 直接解析
24
+ try {
25
+ return JSON.parse(trimmed);
26
+ }
27
+ catch {
28
+ // 继续
29
+ }
30
+ // 2. 剥离 markdown 代码块标记(```json ... ```)
31
+ const codeBlockMatch = trimmed.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
32
+ if (codeBlockMatch?.[1]) {
33
+ try {
34
+ return JSON.parse(codeBlockMatch[1].trim());
35
+ }
36
+ catch {
37
+ // 继续
38
+ }
39
+ }
40
+ // 3. 修复常见错误后重试
41
+ // 只替换作为 JSON key/value 定界符的单引号,不替换字符串内容中的单引号
42
+ // 匹配模式:单引号紧跟在 {, [, :, , 后面(定界符位置),或紧靠在 }, ], ,, : 前面
43
+ const fixed = trimmed
44
+ .replace(/(?<=[{\[:,\s])'|'(?=[}\]:,\s])/g, '"')
45
+ .replace(/,\s*}/g, '}')
46
+ .replace(/,\s*]/g, ']');
47
+ try {
48
+ return JSON.parse(fixed);
49
+ }
50
+ catch {
51
+ // 继续
52
+ }
53
+ // 4. 正则提取首个 JSON 对象
54
+ const objectMatch = trimmed.match(/\{[\s\S]*\}/);
55
+ if (objectMatch) {
56
+ try {
57
+ return JSON.parse(objectMatch[0]);
58
+ }
59
+ catch {
60
+ // 放弃
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/utils/json.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAc,GAAW;IACnD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAEhD,UAAU;IACV,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,KAAK;IACP,CAAC;IAED,wCAAwC;IACxC,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC9E,IAAI,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAM,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,KAAK;QACP,CAAC;IACH,CAAC;IAED,eAAe;IACf,6CAA6C;IAC7C,sDAAsD;IACtD,MAAM,KAAK,GAAG,OAAO;SAClB,OAAO,CAAC,iCAAiC,EAAE,GAAG,CAAC;SAC/C,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,KAAK;IACP,CAAC;IAED,oBAAoB;IACpB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACjD,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAM,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,KAAK;QACP,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * utils 层日志持有器 — 解耦 utils → logging 的运行时依赖
3
+ *
4
+ * 设计动机:
5
+ * utils 是最底层工具层,不应运行时依赖 logging/(业务层)。
6
+ * 但 utils 中的错误日志、事件容错、扫描诊断需要日志能力。
7
+ * 通过 holder 模式,utils 运行时只依赖此模块(同层),
8
+ * 实际 logger 实例由 logging/ 在模块加载时注入。
9
+ *
10
+ * 依赖方向:
11
+ * - utils/* → utils/loggerHolder.ts(同层,运行时)
12
+ * - utils/loggerHolder.ts → logging/loggerInterface.ts(type-only,编译时擦除)
13
+ * - logging/logger.ts → utils/loggerHolder.ts(运行时,桥接注入)
14
+ *
15
+ * 使用方式:
16
+ * // utils 内部使用
17
+ * import { getLogger } from './loggerHolder.js';
18
+ * getLogger().warn({ dir }, '扫描目录失败');
19
+ *
20
+ * // logging 层桥接(自动执行,无需手动调用)
21
+ * // logging/logger.ts 模块加载时自动调用 setLogger(logger)
22
+ */
23
+ import type { ILogger } from '../logging/loggerInterface.js';
24
+ /**
25
+ * 获取当前 logger 实例
26
+ *
27
+ * utils 模块统一通过此函数获取 logger,而非直接 import logging/logger.ts。
28
+ * 在 logging/logger.ts 模块加载前,返回 noopLogger(不输出日志)。
29
+ */
30
+ export declare function getLogger(): ILogger;
31
+ /**
32
+ * 注入 logger 实例(由 logging/logger.ts 自动调用)
33
+ *
34
+ * 传入 undefined 则恢复为 noopLogger。
35
+ */
36
+ export declare function setLogger(logger: ILogger | undefined): void;
37
+ //# sourceMappingURL=loggerHolder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loggerHolder.d.ts","sourceRoot":"","sources":["../../src/utils/loggerHolder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAa5D;;;;;GAKG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAE3D"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * utils 层日志持有器 — 解耦 utils → logging 的运行时依赖
3
+ *
4
+ * 设计动机:
5
+ * utils 是最底层工具层,不应运行时依赖 logging/(业务层)。
6
+ * 但 utils 中的错误日志、事件容错、扫描诊断需要日志能力。
7
+ * 通过 holder 模式,utils 运行时只依赖此模块(同层),
8
+ * 实际 logger 实例由 logging/ 在模块加载时注入。
9
+ *
10
+ * 依赖方向:
11
+ * - utils/* → utils/loggerHolder.ts(同层,运行时)
12
+ * - utils/loggerHolder.ts → logging/loggerInterface.ts(type-only,编译时擦除)
13
+ * - logging/logger.ts → utils/loggerHolder.ts(运行时,桥接注入)
14
+ *
15
+ * 使用方式:
16
+ * // utils 内部使用
17
+ * import { getLogger } from './loggerHolder.js';
18
+ * getLogger().warn({ dir }, '扫描目录失败');
19
+ *
20
+ * // logging 层桥接(自动执行,无需手动调用)
21
+ * // logging/logger.ts 模块加载时自动调用 setLogger(logger)
22
+ */
23
+ /** 空操作 logger — 默认实现,不输出任何日志 */
24
+ const noopLogger = {
25
+ debug: () => { },
26
+ info: () => { },
27
+ warn: () => { },
28
+ error: () => { },
29
+ };
30
+ /** 当前注入的 logger 实例(默认 noop,由 logging/logger.ts 桥接注入) */
31
+ let currentLogger = noopLogger;
32
+ /**
33
+ * 获取当前 logger 实例
34
+ *
35
+ * utils 模块统一通过此函数获取 logger,而非直接 import logging/logger.ts。
36
+ * 在 logging/logger.ts 模块加载前,返回 noopLogger(不输出日志)。
37
+ */
38
+ export function getLogger() {
39
+ return currentLogger;
40
+ }
41
+ /**
42
+ * 注入 logger 实例(由 logging/logger.ts 自动调用)
43
+ *
44
+ * 传入 undefined 则恢复为 noopLogger。
45
+ */
46
+ export function setLogger(logger) {
47
+ currentLogger = logger ?? noopLogger;
48
+ }
49
+ //# sourceMappingURL=loggerHolder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loggerHolder.js","sourceRoot":"","sources":["../../src/utils/loggerHolder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,gCAAgC;AAChC,MAAM,UAAU,GAAY;IAC1B,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;CAChB,CAAC;AAEF,wDAAwD;AACxD,IAAI,aAAa,GAAY,UAAU,CAAC;AAExC;;;;;GAKG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,MAA2B;IACnD,aAAa,GAAG,MAAM,IAAI,UAAU,CAAC;AACvC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 数学工具函数
3
+ */
4
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
5
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/utils/math.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAajE"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 数学工具函数
3
+ */
4
+ export function cosineSimilarity(a, b) {
5
+ if (a.length !== b.length)
6
+ return 0;
7
+ let dot = 0;
8
+ let normA = 0;
9
+ let normB = 0;
10
+ for (let i = 0; i < a.length; i++) {
11
+ // QC-17 移除非空断言:循环条件保证索引有效,用 ?? 0 兜底(数学上 0 不影响点积)
12
+ dot += (a[i] ?? 0) * (b[i] ?? 0);
13
+ normA += (a[i] ?? 0) * (a[i] ?? 0);
14
+ normB += (b[i] ?? 0) * (b[i] ?? 0);
15
+ }
16
+ const denominator = Math.sqrt(normA) * Math.sqrt(normB);
17
+ return denominator === 0 ? 0 : dot / denominator;
18
+ }
19
+ //# sourceMappingURL=math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.js","sourceRoot":"","sources":["../../src/utils/math.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAW,EAAE,CAAW;IACvD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IACpC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,iDAAiD;QACjD,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACnC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,OAAO,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,WAAW,CAAC;AACnD,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 路径工具函数
3
+ *
4
+ * 从 workProjection.ts 提取的公共路径处理函数,
5
+ * 消除跨模块 `filePath.split(/[/\\]/).pop()` 内联重复。
6
+ * 跨平台兼容(同时处理 / 和 \ 分隔符)。
7
+ */
8
+ /**
9
+ * 提取路径的 basename(最后一段)
10
+ *
11
+ * 跨平台兼容:同时处理 Unix `/` 和 Windows `\` 分隔符。
12
+ * 空路径或纯分隔符路径返回空字符串。
13
+ *
14
+ * @param filePath 文件路径
15
+ * @returns basename,如 "/a/b/c.txt" → "c.txt"
16
+ */
17
+ export declare function basename(filePath: string): string;
18
+ /**
19
+ * 展开路径中的 `~` 为用户家目录
20
+ *
21
+ * 仅处理开头的 `~`,不处理 `~otheruser` 等形式。
22
+ * 不含 `~` 的路径原样返回。
23
+ *
24
+ * @param p 可能包含 `~` 的路径字符串
25
+ * @returns 展开后的路径,如 "~/data" → "C:\\Users\\SJ\\data"
26
+ */
27
+ export declare function expandHome(p: string): string;
28
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 路径工具函数
3
+ *
4
+ * 从 workProjection.ts 提取的公共路径处理函数,
5
+ * 消除跨模块 `filePath.split(/[/\\]/).pop()` 内联重复。
6
+ * 跨平台兼容(同时处理 / 和 \ 分隔符)。
7
+ */
8
+ import { homedir } from 'node:os';
9
+ /**
10
+ * 提取路径的 basename(最后一段)
11
+ *
12
+ * 跨平台兼容:同时处理 Unix `/` 和 Windows `\` 分隔符。
13
+ * 空路径或纯分隔符路径返回空字符串。
14
+ *
15
+ * @param filePath 文件路径
16
+ * @returns basename,如 "/a/b/c.txt" → "c.txt"
17
+ */
18
+ export function basename(filePath) {
19
+ return filePath.split(/[/\\]/).pop() ?? '';
20
+ }
21
+ /**
22
+ * 展开路径中的 `~` 为用户家目录
23
+ *
24
+ * 仅处理开头的 `~`,不处理 `~otheruser` 等形式。
25
+ * 不含 `~` 的路径原样返回。
26
+ *
27
+ * @param p 可能包含 `~` 的路径字符串
28
+ * @returns 展开后的路径,如 "~/data" → "C:\\Users\\SJ\\data"
29
+ */
30
+ export function expandHome(p) {
31
+ return p.replace(/^~/, homedir());
32
+ }
33
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 安全定时器工具 — 提供可追踪的生命周期管理
3
+ *
4
+ * 原生 setTimeout / setInterval 不跟踪定时器 ID,
5
+ * 如果忘记清理可能导致内存泄漏。本模块提供轻量包装,
6
+ * 统一管理定时器的创建和清理。
7
+ */
8
+ /**
9
+ * 安全的 setTimeout 包装
10
+ * 返回的 timer ID 可用于 clearSafeTimeout 清理
11
+ */
12
+ export declare function safeSetTimeout(callback: () => void, ms: number): ReturnType<typeof setTimeout>;
13
+ /**
14
+ * 安全的 setInterval 包装
15
+ * 返回的 timer ID 可用于 clearSafeInterval 清理
16
+ */
17
+ export declare function safeSetInterval(callback: () => void, ms: number): ReturnType<typeof setInterval>;
18
+ /**
19
+ * 清理安全的 setTimeout
20
+ */
21
+ export declare function clearSafeTimeout(id: ReturnType<typeof setTimeout> | null): void;
22
+ /**
23
+ * 清理安全的 setInterval
24
+ */
25
+ export declare function clearSafeInterval(id: ReturnType<typeof setInterval> | null): void;
26
+ //# sourceMappingURL=safeTimer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safeTimer.d.ts","sourceRoot":"","sources":["../../src/utils/safeTimer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,IAAI,EACpB,EAAE,EAAE,MAAM,GACT,UAAU,CAAC,OAAO,UAAU,CAAC,CAO/B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,IAAI,EACpB,EAAE,EAAE,MAAM,GACT,UAAU,CAAC,OAAO,WAAW,CAAC,CAIhC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,GAAG,IAAI,CAK/E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,IAAI,GAAG,IAAI,CAKjF"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * 安全定时器工具 — 提供可追踪的生命周期管理
3
+ *
4
+ * 原生 setTimeout / setInterval 不跟踪定时器 ID,
5
+ * 如果忘记清理可能导致内存泄漏。本模块提供轻量包装,
6
+ * 统一管理定时器的创建和清理。
7
+ */
8
+ /** 定时器注册表,用于跟踪所有活跃定时器 */
9
+ const activeTimers = new Set();
10
+ /**
11
+ * 安全的 setTimeout 包装
12
+ * 返回的 timer ID 可用于 clearSafeTimeout 清理
13
+ */
14
+ export function safeSetTimeout(callback, ms) {
15
+ const id = setTimeout(() => {
16
+ activeTimers.delete(id);
17
+ callback();
18
+ }, ms);
19
+ activeTimers.add(id);
20
+ return id;
21
+ }
22
+ /**
23
+ * 安全的 setInterval 包装
24
+ * 返回的 timer ID 可用于 clearSafeInterval 清理
25
+ */
26
+ export function safeSetInterval(callback, ms) {
27
+ const id = setInterval(callback, ms);
28
+ activeTimers.add(id);
29
+ return id;
30
+ }
31
+ /**
32
+ * 清理安全的 setTimeout
33
+ */
34
+ export function clearSafeTimeout(id) {
35
+ if (id !== null) {
36
+ clearTimeout(id);
37
+ activeTimers.delete(id);
38
+ }
39
+ }
40
+ /**
41
+ * 清理安全的 setInterval
42
+ */
43
+ export function clearSafeInterval(id) {
44
+ if (id !== null) {
45
+ clearInterval(id);
46
+ activeTimers.delete(id);
47
+ }
48
+ }
49
+ //# sourceMappingURL=safeTimer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safeTimer.js","sourceRoot":"","sources":["../../src/utils/safeTimer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,yBAAyB;AACzB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkE,CAAC;AAE/F;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAoB,EACpB,EAAU;IAEV,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE;QACzB,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,QAAQ,EAAE,CAAC;IACb,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAoB,EACpB,EAAU;IAEV,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAwC;IACvE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QAChB,YAAY,CAAC,EAAE,CAAC,CAAC;QACjB,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAyC;IACzE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QAChB,aAAa,CAAC,EAAE,CAAC,CAAC;QAClB,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Markdown 目录扫描工具
3
+ *
4
+ * 从 PersonaManager / SkillManager 提取的公共目录扫描逻辑,
5
+ * 消除跨模块重复的"扫描 *.md → 解析 frontmatter → 提取字段"代码。
6
+ *
7
+ * 使用异步 I/O(与 FileStore / ToolExecutor 保持一致)。
8
+ */
9
+ /** 扫描结果条目(通用 frontmatter 解析产物) */
10
+ export interface ScannedMarkdownEntry {
11
+ /** 名称(frontmatter name 字段或文件名去 .md) */
12
+ name: string;
13
+ /** frontmatter 原始键值对 */
14
+ frontmatter: Record<string, string>;
15
+ /** frontmatter 之后的正文 */
16
+ body: string;
17
+ /** 文件绝对路径 */
18
+ filePath: string;
19
+ }
20
+ /**
21
+ * 扫描目录下的 *.md 文件,解析 frontmatter
22
+ *
23
+ * 排除规则:
24
+ * - 文件名以 `.` 开头的隐藏文件
25
+ * - 文件名以 `_` 前缀的私有文件
26
+ * - README.md / CHANGELOG.md / LICENSE
27
+ *
28
+ * @param dir 目录路径
29
+ * @returns 解析后的条目列表
30
+ */
31
+ export declare function scanMarkdownDir(dir: string): Promise<ScannedMarkdownEntry[]>;
32
+ /**
33
+ * 从 frontmatter 中解析逗号分隔的关键词列表
34
+ *
35
+ * @param fm frontmatter 键值对
36
+ * @param key 关键词字段名(默认 'keywords')
37
+ * @returns 关键词数组
38
+ */
39
+ export declare function parseKeywords(fm: Record<string, string>, key?: string): string[];
40
+ /**
41
+ * 从 frontmatter 中解析正则触发器
42
+ *
43
+ * 支持格式:/pattern/flags 或纯 pattern(默认 'i' flag)
44
+ *
45
+ * @param fm frontmatter 键值对
46
+ * @param key 触发器字段名(默认 'trigger')
47
+ * @returns 正则表达式,解析失败返回 undefined
48
+ */
49
+ export declare function parseTrigger(fm: Record<string, string>, key?: string): RegExp | undefined;
50
+ /**
51
+ * 解析目录路径:如果 configDir 存在则 resolve 子目录,否则返回 undefined
52
+ */
53
+ export declare function resolveSubdir(configDir: string | undefined, sub: string): string | undefined;
54
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/utils/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,kCAAkC;AAClC,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CA0ClF;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,SAAa,GAAG,MAAM,EAAE,CAOpF;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,SAAY,GAAG,MAAM,GAAG,SAAS,CAgB5F;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG5F"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Markdown 目录扫描工具
3
+ *
4
+ * 从 PersonaManager / SkillManager 提取的公共目录扫描逻辑,
5
+ * 消除跨模块重复的"扫描 *.md → 解析 frontmatter → 提取字段"代码。
6
+ *
7
+ * 使用异步 I/O(与 FileStore / ToolExecutor 保持一致)。
8
+ */
9
+ import { readFile, readdir, access } from 'node:fs/promises';
10
+ import { resolve, join, basename } from 'node:path';
11
+ import { parseFrontmatter } from '../utils/frontmatter.js';
12
+ import { getLogger } from '../utils/loggerHolder.js';
13
+ /** 排除的文件名(README / CHANGELOG / LICENSE 不纳入扫描) */
14
+ const EXCLUDED_FILES = new Set(['README.md', 'CHANGELOG.md', 'LICENSE']);
15
+ /**
16
+ * 扫描目录下的 *.md 文件,解析 frontmatter
17
+ *
18
+ * 排除规则:
19
+ * - 文件名以 `.` 开头的隐藏文件
20
+ * - 文件名以 `_` 前缀的私有文件
21
+ * - README.md / CHANGELOG.md / LICENSE
22
+ *
23
+ * @param dir 目录路径
24
+ * @returns 解析后的条目列表
25
+ */
26
+ export async function scanMarkdownDir(dir) {
27
+ try {
28
+ await access(dir);
29
+ }
30
+ catch {
31
+ getLogger().debug({ dir }, '扫描目录不存在,跳过');
32
+ return [];
33
+ }
34
+ let files;
35
+ try {
36
+ files = (await readdir(dir)).filter((f) => f.endsWith('.md') &&
37
+ !f.startsWith('.') &&
38
+ !f.startsWith('_') &&
39
+ !EXCLUDED_FILES.has(f));
40
+ }
41
+ catch {
42
+ getLogger().warn({ dir }, '扫描目录失败');
43
+ return [];
44
+ }
45
+ const entries = [];
46
+ for (const file of files) {
47
+ try {
48
+ const filePath = join(dir, file);
49
+ const raw = await readFile(filePath, 'utf-8');
50
+ const { frontmatter: fm, body } = parseFrontmatter(raw);
51
+ entries.push({
52
+ name: fm['name'] ?? basename(file, '.md'),
53
+ frontmatter: fm,
54
+ body,
55
+ filePath,
56
+ });
57
+ }
58
+ catch (err) {
59
+ getLogger().warn({ file, err }, '解析 Markdown 文件失败');
60
+ }
61
+ }
62
+ return entries;
63
+ }
64
+ /**
65
+ * 从 frontmatter 中解析逗号分隔的关键词列表
66
+ *
67
+ * @param fm frontmatter 键值对
68
+ * @param key 关键词字段名(默认 'keywords')
69
+ * @returns 关键词数组
70
+ */
71
+ export function parseKeywords(fm, key = 'keywords') {
72
+ const raw = fm[key];
73
+ if (!raw)
74
+ return [];
75
+ return String(raw)
76
+ .split(',')
77
+ .map((s) => s.trim())
78
+ .filter(Boolean);
79
+ }
80
+ /**
81
+ * 从 frontmatter 中解析正则触发器
82
+ *
83
+ * 支持格式:/pattern/flags 或纯 pattern(默认 'i' flag)
84
+ *
85
+ * @param fm frontmatter 键值对
86
+ * @param key 触发器字段名(默认 'trigger')
87
+ * @returns 正则表达式,解析失败返回 undefined
88
+ */
89
+ export function parseTrigger(fm, key = 'trigger') {
90
+ const raw = fm[key];
91
+ if (!raw)
92
+ return undefined;
93
+ try {
94
+ const pattern = String(raw).trim();
95
+ const match = pattern.match(/^\/(.+)\/([gimsuy]*)$/);
96
+ // QC-17 移除非空断言:使用空值合并回退到 pattern(与 match 为 null 时逻辑一致)
97
+ const clean = match?.[1] ?? pattern;
98
+ // 修复 UTIL-02:使用捕获的 flags(默认 'i'),原实现硬编码 'i' 丢弃了声明的 flags
99
+ const flags = match?.[2] || 'i';
100
+ return new RegExp(clean, flags);
101
+ }
102
+ catch {
103
+ getLogger().warn({ trigger: raw }, '触发正则无效,已忽略');
104
+ return undefined;
105
+ }
106
+ }
107
+ /**
108
+ * 解析目录路径:如果 configDir 存在则 resolve 子目录,否则返回 undefined
109
+ */
110
+ export function resolveSubdir(configDir, sub) {
111
+ if (!configDir)
112
+ return undefined;
113
+ return resolve(configDir, sub);
114
+ }
115
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/utils/scanner.ts"],"names":[],"mappings":"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"}