weflow-cli 1.5.0 → 1.6.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 (331) hide show
  1. package/ARCHITECTURE.md +105 -0
  2. package/CHANGELOG.md +110 -0
  3. package/CONTRIBUTING.md +45 -0
  4. package/LICENSE +21 -21
  5. package/OPERATIONS.md +272 -0
  6. package/README.en.md +281 -0
  7. package/README.md +333 -149
  8. package/SECURITY.md +47 -0
  9. package/bin/weflow-cli.ts +4032 -583
  10. package/dist/bin/weflow-cli.js +4296 -593
  11. package/dist/bin/weflow-cli.js.map +1 -1
  12. package/dist/mcp-server/index.js +178 -236
  13. package/dist/mcp-server/index.js.map +1 -1
  14. package/dist/src/core/dbPathService.d.ts +15 -1
  15. package/dist/src/core/dbPathService.d.ts.map +1 -1
  16. package/dist/src/core/dbPathService.js +177 -19
  17. package/dist/src/core/dbPathService.js.map +1 -1
  18. package/dist/src/core/keyService.d.ts +8 -0
  19. package/dist/src/core/keyService.d.ts.map +1 -1
  20. package/dist/src/core/keyService.js +127 -22
  21. package/dist/src/core/keyService.js.map +1 -1
  22. package/dist/src/core/ntCore.d.ts +59 -1
  23. package/dist/src/core/ntCore.d.ts.map +1 -1
  24. package/dist/src/core/ntCore.js +188 -64
  25. package/dist/src/core/ntCore.js.map +1 -1
  26. package/dist/src/core/sqlcipherCore.d.ts.map +1 -1
  27. package/dist/src/core/sqlcipherCore.js +18 -1
  28. package/dist/src/core/sqlcipherCore.js.map +1 -1
  29. package/dist/src/core/wcdbCore.d.ts.map +1 -1
  30. package/dist/src/core/wcdbCore.js +3 -6
  31. package/dist/src/core/wcdbCore.js.map +1 -1
  32. package/dist/src/services/assistantDaemon.d.ts +19 -0
  33. package/dist/src/services/assistantDaemon.d.ts.map +1 -0
  34. package/dist/src/services/assistantDaemon.js +117 -0
  35. package/dist/src/services/assistantDaemon.js.map +1 -0
  36. package/dist/src/services/assistantMemory.d.ts +36 -0
  37. package/dist/src/services/assistantMemory.d.ts.map +1 -0
  38. package/dist/src/services/assistantMemory.js +182 -0
  39. package/dist/src/services/assistantMemory.js.map +1 -0
  40. package/dist/src/services/assistantPrivacy.d.ts +25 -0
  41. package/dist/src/services/assistantPrivacy.d.ts.map +1 -0
  42. package/dist/src/services/assistantPrivacy.js +77 -0
  43. package/dist/src/services/assistantPrivacy.js.map +1 -0
  44. package/dist/src/services/assistantRouting.d.ts +18 -0
  45. package/dist/src/services/assistantRouting.d.ts.map +1 -0
  46. package/dist/src/services/assistantRouting.js +68 -0
  47. package/dist/src/services/assistantRouting.js.map +1 -0
  48. package/dist/src/services/assistantService.d.ts +37 -0
  49. package/dist/src/services/assistantService.d.ts.map +1 -0
  50. package/dist/src/services/assistantService.js +284 -0
  51. package/dist/src/services/assistantService.js.map +1 -0
  52. package/dist/src/services/assistantTools.d.ts +24 -0
  53. package/dist/src/services/assistantTools.d.ts.map +1 -0
  54. package/dist/src/services/assistantTools.js +582 -0
  55. package/dist/src/services/assistantTools.js.map +1 -0
  56. package/dist/src/services/chatService.d.ts +44 -0
  57. package/dist/src/services/chatService.d.ts.map +1 -1
  58. package/dist/src/services/chatService.js +105 -4
  59. package/dist/src/services/chatService.js.map +1 -1
  60. package/dist/src/services/configService.d.ts +55 -0
  61. package/dist/src/services/configService.d.ts.map +1 -1
  62. package/dist/src/services/configService.js +147 -6
  63. package/dist/src/services/configService.js.map +1 -1
  64. package/dist/src/services/evidenceService.d.ts +30 -0
  65. package/dist/src/services/evidenceService.d.ts.map +1 -0
  66. package/dist/src/services/evidenceService.js +98 -0
  67. package/dist/src/services/evidenceService.js.map +1 -0
  68. package/dist/src/services/exportService.d.ts +13 -20
  69. package/dist/src/services/exportService.d.ts.map +1 -1
  70. package/dist/src/services/exportService.js +113 -47
  71. package/dist/src/services/exportService.js.map +1 -1
  72. package/dist/src/services/initKeyService.d.ts +19 -0
  73. package/dist/src/services/initKeyService.d.ts.map +1 -0
  74. package/dist/src/services/initKeyService.js +80 -0
  75. package/dist/src/services/initKeyService.js.map +1 -0
  76. package/dist/src/services/messageContract.d.ts +23 -0
  77. package/dist/src/services/messageContract.d.ts.map +1 -0
  78. package/dist/src/services/messageContract.js +49 -0
  79. package/dist/src/services/messageContract.js.map +1 -0
  80. package/dist/src/services/messageQuery.d.ts +7 -0
  81. package/dist/src/services/messageQuery.d.ts.map +1 -0
  82. package/dist/src/services/messageQuery.js +30 -0
  83. package/dist/src/services/messageQuery.js.map +1 -0
  84. package/dist/src/services/wechat-formatter.js +14 -14
  85. package/dist/src/services/wechatMessageService.d.ts.map +1 -1
  86. package/dist/src/services/wechatMessageService.js +31 -3
  87. package/dist/src/services/wechatMessageService.js.map +1 -1
  88. package/dist/src/services/whitelistService.d.ts +52 -4
  89. package/dist/src/services/whitelistService.d.ts.map +1 -1
  90. package/dist/src/services/whitelistService.js +183 -17
  91. package/dist/src/services/whitelistService.js.map +1 -1
  92. package/dist/src/types.d.ts +20 -0
  93. package/dist/src/types.d.ts.map +1 -1
  94. package/dist/src/utils/dateRange.d.ts +15 -0
  95. package/dist/src/utils/dateRange.d.ts.map +1 -0
  96. package/dist/src/utils/dateRange.js +48 -0
  97. package/dist/src/utils/dateRange.js.map +1 -0
  98. package/dist/src/utils/mcpSecurity.d.ts +5 -0
  99. package/dist/src/utils/mcpSecurity.d.ts.map +1 -0
  100. package/dist/src/utils/mcpSecurity.js +39 -0
  101. package/dist/src/utils/mcpSecurity.js.map +1 -0
  102. package/dist/src/utils/packageRoot.d.ts +2 -0
  103. package/dist/src/utils/packageRoot.d.ts.map +1 -0
  104. package/dist/src/utils/packageRoot.js +16 -0
  105. package/dist/src/utils/packageRoot.js.map +1 -0
  106. package/dist/src/utils/python.d.ts +2 -0
  107. package/dist/src/utils/python.d.ts.map +1 -0
  108. package/dist/src/utils/python.js +72 -0
  109. package/dist/src/utils/python.js.map +1 -0
  110. package/dist/src/utils/pythonProcessEnv.d.ts +3 -0
  111. package/dist/src/utils/pythonProcessEnv.d.ts.map +1 -0
  112. package/dist/src/utils/pythonProcessEnv.js +46 -0
  113. package/dist/src/utils/pythonProcessEnv.js.map +1 -0
  114. package/dist/src/utils/talkerUtils.d.ts +4 -1
  115. package/dist/src/utils/talkerUtils.d.ts.map +1 -1
  116. package/dist/src/utils/talkerUtils.js +9 -9
  117. package/dist/src/utils/talkerUtils.js.map +1 -1
  118. package/dist/src/utils/wechatEmoji.d.ts +5 -0
  119. package/dist/src/utils/wechatEmoji.d.ts.map +1 -0
  120. package/dist/src/utils/wechatEmoji.js +35 -0
  121. package/dist/src/utils/wechatEmoji.js.map +1 -0
  122. package/docs/AI_INTERFACE.md +189 -0
  123. package/docs/BRANCHES.md +87 -0
  124. package/docs/DATA_CONTRACT.md +74 -0
  125. package/docs/DECISIONS.md +270 -0
  126. package/docs/DEEPSEEK_V4_FLASH/346/226/275/345/267/245/346/226/207/346/241/243.md +234 -0
  127. package/docs/EVIDENCE_GUIDE.md +96 -0
  128. package/docs/MCP.md +95 -0
  129. package/docs/PARTNERS.md +41 -0
  130. package/docs/PROJECT_STATE.md +96 -0
  131. package/docs/ROADMAP.md +191 -0
  132. package/docs/SETUP.md +103 -0
  133. package/docs/images/weflow-architecture-gpt-image-2.png +0 -0
  134. package/docs/images/weflow-architecture.png +0 -0
  135. package/docs/images/weflow-architecture.svg +65 -0
  136. package/mcp-server/index.ts +169 -269
  137. package/package.json +81 -72
  138. package/requirements-3x.txt +4 -0
  139. package/requirements-voice.txt +15 -0
  140. package/requirements.txt +9 -0
  141. package/resources/js/marked.min.js +69 -0
  142. package/resources/wechat-emoji/666.png +0 -0
  143. package/resources/wechat-emoji/Awesome.png +0 -0
  144. package/resources/wechat-emoji/Concerned.png +0 -0
  145. package/resources/wechat-emoji/Cry.png +0 -0
  146. package/resources/wechat-emoji/Emm.png +0 -0
  147. package/resources/wechat-emoji/Facepalm.png +0 -0
  148. package/resources/wechat-emoji/Grin.png +0 -0
  149. package/resources/wechat-emoji/OK.png +0 -0
  150. package/resources/wechat-emoji/Respect.png +0 -0
  151. package/resources/wechat-emoji/Sick.png +0 -0
  152. package/resources/wechat-emoji/Sleep.png +0 -0
  153. package/resources/wechat-emoji/Smile.png +0 -0
  154. package/resources/wechat-emoji//344/272/262/344/272/262.png +0 -0
  155. package/resources/wechat-emoji//344/276/277/344/276/277.png +0 -0
  156. package/resources/wechat-emoji//345/201/267/347/254/221.png +0 -0
  157. package/resources/wechat-emoji//345/202/262/346/205/242.png +0 -0
  158. package/resources/wechat-emoji//345/206/215/350/247/201.png +0 -0
  159. package/resources/wechat-emoji//345/207/213/350/260/242.png +0 -0
  160. package/resources/wechat-emoji//345/212/240/346/262/271.png +0 -0
  161. package/resources/wechat-emoji//345/213/276/345/274/225.png +0 -0
  162. package/resources/wechat-emoji//345/217/221/345/221/206.png +0 -0
  163. package/resources/wechat-emoji//345/217/221/346/200/222.png +0 -0
  164. package/resources/wechat-emoji//345/217/221/346/212/226.png +0 -0
  165. package/resources/wechat-emoji//345/217/257/346/200/234.png +0 -0
  166. package/resources/wechat-emoji//345/217/263/345/223/274/345/223/274.png +0 -0
  167. package/resources/wechat-emoji//345/217/271/346/260/224.png +0 -0
  168. package/resources/wechat-emoji//345/220/203/347/223/234.png +0 -0
  169. package/resources/wechat-emoji//345/220/210/345/215/201.png +0 -0
  170. package/resources/wechat-emoji//345/220/220.png +0 -0
  171. package/resources/wechat-emoji//345/221/262/347/211/231.png +0 -0
  172. package/resources/wechat-emoji//345/222/222/351/252/202.png +0 -0
  173. package/resources/wechat-emoji//345/222/226/345/225/241.png +0 -0
  174. package/resources/wechat-emoji//345/223/207.png +0 -0
  175. package/resources/wechat-emoji//345/225/244/351/205/222.png +0 -0
  176. package/resources/wechat-emoji//345/230/230.png +0 -0
  177. package/resources/wechat-emoji//345/230/264/345/224/207.png +0 -0
  178. package/resources/wechat-emoji//345/230/277/345/223/210.png +0 -0
  179. package/resources/wechat-emoji//345/233/247.png +0 -0
  180. package/resources/wechat-emoji//345/233/260.png +0 -0
  181. package/resources/wechat-emoji//345/235/217/347/254/221.png +0 -0
  182. package/resources/wechat-emoji//345/244/247/345/223/255.png +0 -0
  183. package/resources/wechat-emoji//345/244/251/345/225/212.png +0 -0
  184. package/resources/wechat-emoji//345/244/252/351/230/263.png +0 -0
  185. package/resources/wechat-emoji//345/244/261/346/234/233.png +0 -0
  186. package/resources/wechat-emoji//345/245/270/347/254/221.png +0 -0
  187. package/resources/wechat-emoji//345/245/275/347/232/204.png +0 -0
  188. package/resources/wechat-emoji//345/247/224/345/261/210.png +0 -0
  189. package/resources/wechat-emoji//345/256/263/347/276/236.png +0 -0
  190. package/resources/wechat-emoji//345/260/264/345/260/254.png +0 -0
  191. package/resources/wechat-emoji//345/272/206/347/245/235.png +0 -0
  192. package/resources/wechat-emoji//345/274/261.png +0 -0
  193. package/resources/wechat-emoji//345/274/272.png +0 -0
  194. package/resources/wechat-emoji//345/276/227/346/204/217.png +0 -0
  195. package/resources/wechat-emoji//345/276/256/347/254/221.png +0 -0
  196. package/resources/wechat-emoji//345/277/203/347/242/216.png +0 -0
  197. package/resources/wechat-emoji//345/277/253/345/223/255/344/272/206.png +0 -0
  198. package/resources/wechat-emoji//346/201/220/346/203/247.png +0 -0
  199. package/resources/wechat-emoji//346/202/240/351/227/262.png +0 -0
  200. package/resources/wechat-emoji//346/203/212/346/201/220.png +0 -0
  201. package/resources/wechat-emoji//346/203/212/350/256/266.png +0 -0
  202. package/resources/wechat-emoji//346/204/211/345/277/253.png +0 -0
  203. package/resources/wechat-emoji//346/206/250/347/254/221.png +0 -0
  204. package/resources/wechat-emoji//346/211/223/350/204/270.png +0 -0
  205. package/resources/wechat-emoji//346/212/223/347/213/202.png +0 -0
  206. package/resources/wechat-emoji//346/212/240/351/274/273.png +0 -0
  207. package/resources/wechat-emoji//346/212/261/346/213/263.png +0 -0
  208. package/resources/wechat-emoji//346/213/245/346/212/261.png +0 -0
  209. package/resources/wechat-emoji//346/213/263/345/244/264.png +0 -0
  210. package/resources/wechat-emoji//346/215/202/350/204/270.png +0 -0
  211. package/resources/wechat-emoji//346/217/241/346/211/213.png +0 -0
  212. package/resources/wechat-emoji//346/222/207/345/230/264.png +0 -0
  213. package/resources/wechat-emoji//346/223/246/346/261/227.png +0 -0
  214. package/resources/wechat-emoji//346/225/262/346/211/223.png +0 -0
  215. package/resources/wechat-emoji//346/227/240/350/257/255.png +0 -0
  216. package/resources/wechat-emoji//346/227/272/346/237/264.png +0 -0
  217. package/resources/wechat-emoji//346/231/225.png +0 -0
  218. package/resources/wechat-emoji//346/234/210/344/272/256.png +0 -0
  219. package/resources/wechat-emoji//346/234/272/346/231/272.png +0 -0
  220. package/resources/wechat-emoji//346/261/227.png +0 -0
  221. package/resources/wechat-emoji//346/265/201/346/263/252.png +0 -0
  222. package/resources/wechat-emoji//347/202/270/345/274/271.png +0 -0
  223. package/resources/wechat-emoji//347/203/237/350/212/261.png +0 -0
  224. package/resources/wechat-emoji//347/210/206/347/253/271.png +0 -0
  225. package/resources/wechat-emoji//347/210/261/345/277/203.png +0 -0
  226. package/resources/wechat-emoji//347/214/252/345/244/264.png +0 -0
  227. package/resources/wechat-emoji//347/216/253/347/221/260.png +0 -0
  228. package/resources/wechat-emoji//347/224/237/347/227/205.png +0 -0
  229. package/resources/wechat-emoji//347/226/221/351/227/256.png +0 -0
  230. package/resources/wechat-emoji//347/231/274.png +0 -0
  231. package/resources/wechat-emoji//347/231/275/347/234/274.png +0 -0
  232. package/resources/wechat-emoji//347/232/261/347/234/211.png +0 -0
  233. package/resources/wechat-emoji//347/235/241.png +0 -0
  234. package/resources/wechat-emoji//347/240/264/346/266/225/344/270/272/347/254/221.png +0 -0
  235. package/resources/wechat-emoji//347/244/274/347/211/251.png +0 -0
  236. package/resources/wechat-emoji//347/244/276/344/274/232/347/244/276/344/274/232.png +0 -0
  237. package/resources/wechat-emoji//347/246/217.png +0 -0
  238. package/resources/wechat-emoji//347/254/221/350/204/270.png +0 -0
  239. package/resources/wechat-emoji//347/272/242/345/214/205.png +0 -0
  240. package/resources/wechat-emoji//347/277/273/347/231/275/347/234/274.png +0 -0
  241. package/resources/wechat-emoji//350/200/266.png +0 -0
  242. package/resources/wechat-emoji//350/203/234/345/210/251.png +0 -0
  243. package/resources/wechat-emoji//350/204/270/347/272/242.png +0 -0
  244. package/resources/wechat-emoji//350/211/262.png +0 -0
  245. package/resources/wechat-emoji//350/213/246/346/266/251.png +0 -0
  246. package/resources/wechat-emoji//350/217/234/345/210/200.png +0 -0
  247. package/resources/wechat-emoji//350/233/213/347/263/225.png +0 -0
  248. package/resources/wechat-emoji//350/241/260.png +0 -0
  249. package/resources/wechat-emoji//350/243/202/345/274/200.png +0 -0
  250. package/resources/wechat-emoji//350/256/251/346/210/221/347/234/213/347/234/213.png +0 -0
  251. package/resources/wechat-emoji//350/260/203/347/232/256.png +0 -0
  252. package/resources/wechat-emoji//350/267/263/350/267/263.png +0 -0
  253. package/resources/wechat-emoji//350/275/254/345/234/210.png +0 -0
  254. package/resources/wechat-emoji//351/204/231/350/247/206.png +0 -0
  255. package/resources/wechat-emoji//351/227/255/345/230/264.png +0 -0
  256. package/resources/wechat-emoji//351/230/264/351/231/251.png +0 -0
  257. package/resources/wechat-emoji//351/232/276/350/277/207.png +0 -0
  258. package/resources/wechat-emoji//351/252/267/351/253/205.png +0 -0
  259. package/resources/wechat-emoji//351/274/223/346/216/214.png +0 -0
  260. package/scripts/_batch_link_sources.py +73 -73
  261. package/scripts/_utils.py +29 -0
  262. package/scripts/annual_report.py +796 -796
  263. package/scripts/auto_tag.py +128 -128
  264. package/scripts/biz_daily.py +210 -53
  265. package/scripts/chat_report.py +10 -0
  266. package/scripts/chat_stats.py +702 -702
  267. package/scripts/classify_daily.py +17 -11
  268. package/scripts/create_reading_notes.py +370 -370
  269. package/scripts/daily_stats.py +132 -0
  270. package/scripts/enrich_backlinks.py +163 -163
  271. package/scripts/export_chat_html.py +1704 -107
  272. package/scripts/extract_todos.py +445 -404
  273. package/scripts/fav_server.py +119 -12
  274. package/scripts/fix_topics.py +111 -111
  275. package/scripts/generate_ai_report.py +1 -1
  276. package/scripts/generate_html.py +597 -277
  277. package/scripts/inspection_records.py +354 -0
  278. package/scripts/mcp_bridge.py +398 -398
  279. package/scripts/nt_decrypt.py +693 -48
  280. package/scripts/pipeline.py +27 -19
  281. package/scripts/promote_all.py +312 -310
  282. package/scripts/promote_ideas.py +299 -297
  283. package/scripts/rag_chat.py +194 -191
  284. package/scripts/semantic_search.py +435 -431
  285. package/scripts/sync_fav.py +201 -146
  286. package/scripts/sync_weread.py +192 -192
  287. package/scripts/vault_rag.py +140 -139
  288. package/scripts/vault_search.py +141 -141
  289. package/scripts/wechat_emoji.py +132 -0
  290. package/scripts/wechat_emoticon.py +433 -0
  291. package/scripts/wechat_image.py +258 -0
  292. package/scripts/wechat_voice.py +327 -0
  293. package/src/core/dbPathService.ts +163 -18
  294. package/src/core/keyService.ts +137 -25
  295. package/src/core/ntCore.ts +202 -61
  296. package/src/core/sqlcipherCore.ts +17 -1
  297. package/src/core/wcdbCore.ts +3 -7
  298. package/src/services/assistantDaemon.ts +111 -0
  299. package/src/services/assistantMemory.ts +193 -0
  300. package/src/services/assistantPrivacy.ts +87 -0
  301. package/src/services/assistantRouting.ts +92 -0
  302. package/src/services/assistantService.ts +295 -0
  303. package/src/services/assistantTools.ts +549 -0
  304. package/src/services/chatService.ts +133 -4
  305. package/src/services/configService.ts +194 -6
  306. package/src/services/evidenceService.ts +129 -0
  307. package/src/services/exportService.ts +113 -48
  308. package/src/services/initKeyService.ts +83 -0
  309. package/src/services/messageContract.ts +77 -0
  310. package/src/services/messageQuery.ts +38 -0
  311. package/src/services/wechat-formatter.ts +348 -348
  312. package/src/services/wechatMessageService.ts +25 -3
  313. package/src/services/wereadService.ts +308 -308
  314. package/src/services/whitelistService.ts +209 -22
  315. package/src/types.ts +20 -0
  316. package/src/utils/dateRange.ts +58 -0
  317. package/src/utils/mcpSecurity.ts +39 -0
  318. package/src/utils/packageRoot.ts +14 -0
  319. package/src/utils/python.ts +73 -0
  320. package/src/utils/pythonProcessEnv.ts +45 -0
  321. package/src/utils/talkerUtils.ts +14 -2
  322. package/dist/src/utils/errors.d.ts +0 -25
  323. package/dist/src/utils/errors.d.ts.map +0 -1
  324. package/dist/src/utils/errors.js +0 -43
  325. package/dist/src/utils/errors.js.map +0 -1
  326. package/dist/src/utils/pythonRunner.d.ts +0 -27
  327. package/dist/src/utils/pythonRunner.d.ts.map +0 -1
  328. package/dist/src/utils/pythonRunner.js +0 -62
  329. package/dist/src/utils/pythonRunner.js.map +0 -1
  330. package/src/utils/errors.ts +0 -42
  331. package/src/utils/pythonRunner.ts +0 -81
@@ -0,0 +1,105 @@
1
+ # WeFlow CLI 技术架构
2
+
3
+ > 本文描述当前代码的边界和数据流。维护时先以 `bin/weflow-cli.ts`、`src/` 和 `scripts/` 为准,再更新本文。
4
+
5
+ ## 定位
6
+
7
+ WeFlow CLI 是一个本地优先的命令行工具和 stdio MCP Server,面向用户本人有权访问的微信本地数据,提供查询、导出、公众号阅读、知识整理和可选 AI 助手能力。
8
+
9
+ ## 分层结构
10
+
11
+ ```text
12
+ MCP 客户端 / 终端用户
13
+ |
14
+ v
15
+ CLI 入口 bin/weflow-cli.ts ---- mcp-server/index.ts
16
+ |
17
+ v
18
+ 业务服务层
19
+ chat / contact / export / evidence / favorites / sns
20
+ daily / vault / weread / assistant / config / privacy
21
+ |
22
+ +--> Node 原生层:路径发现、配置、数据库适配、消息通道
23
+ +--> Python 工作流:NT 数据、公众号日报、HTML 阅读器、知识管道
24
+ |
25
+ v
26
+ 本地数据与明确选择的外部服务
27
+ 微信本地数据库、缓存、日报输出、Vault
28
+ 公众号网页、微信读书、用户配置的 AI 端点、官方 Bot 通道
29
+ ```
30
+
31
+ ## 代码边界
32
+
33
+ | 目录 | 职责 |
34
+ | --- | --- |
35
+ | `bin/` | Commander 命令定义、参数校验和交互式菜单。 |
36
+ | `src/core/` | 数据目录发现、数据库连接、密钥配置适配和客户端底层集成。 |
37
+ | `src/services/` | 聊天、导出、证据包、日报、助手、白名单和隐私策略。 |
38
+ | `scripts/` | Python 数据读取、公众号抓取、日报、HTML、搜索和报告脚本。 |
39
+ | `mcp-server/` | 通过 stdio 暴露受控工具,不监听网络端口。 |
40
+ | `test/` | Node 和 Python 回归测试,优先使用合成数据。 |
41
+ | `resources/` | 随包发布的只读资源,例如默认表情素材。 |
42
+
43
+ ## 主要数据流
44
+
45
+ ### 聊天查询与导出
46
+
47
+ ```text
48
+ 用户指定的数据根目录
49
+ -> 分片数据库发现与配置验证
50
+ -> 聊天/联系人查询
51
+ -> 导出 JSON、TXT、Markdown、HTML 或 Excel
52
+ -> HTML 按稳定消息身份匹配媒体,无法确认时保留占位符
53
+ ```
54
+
55
+ 4.x 数据可能包含多个 `message_*.db` 分片,以及联系人、朋友圈、收藏和媒体资源库。跨分片查询时不能把本地消息 ID 当作全局唯一值;媒体关联优先使用稳定的服务端消息身份,并结合内容指纹和资源记录。这个策略用于避免把别的消息图片串到当前聊天中。
56
+
57
+ ### 公众号日报与阅读器
58
+
59
+ ```text
60
+ 本地公众号推送数据
61
+ -> 按来源筛选
62
+ -> 抓取用户选择的文章正文(需要联网)
63
+ -> AI 摘要/分类(可关闭)
64
+ -> output/biz-daily/YYYY-MM-DD/
65
+ -> 127.0.0.1:8765 本地阅读器
66
+ ```
67
+
68
+ 来源类别优先于文章主题分类:已配置类别的公众号保留其类别,并跳过该文章的自动主题分类;未配置类别时才使用文章分类逻辑。`daily --no-ai` 或持久化配置 `dailyAiEnabled=false` 时不调用 AI,但仍可抓取、生成 HTML 和更新本地索引。
69
+
70
+ 未指定日期运行 `daily` 时,会先检查昨天是否缺少 `README.md`、`.articles.json` 或 `index.html`;昨天不完整则先补齐,成功后再生成今天。显式 `--date` 和 `--dry-run` 是单日期操作。
71
+
72
+ ### 知识库与报告
73
+
74
+ ```text
75
+ 日报 / 收藏 / 微信读书笔记
76
+ -> Vault 文件与 Wiki 概念页
77
+ -> 本地搜索或可选 AI RAG
78
+ -> review、report、annual-report、todos 等报告
79
+ ```
80
+
81
+ Vault promotion 默认不调用 AI;只有显式使用 `--with-ai` 并提供凭据时才生成 AI 内容。
82
+
83
+ ### 助手与 MCP
84
+
85
+ ```text
86
+ MCP stdio 或官方 Bot 通道
87
+ -> 白名单与隐私策略
88
+ -> 受控工具调用
89
+ -> 本地数据查询 / 可选云端模型
90
+ -> 脱敏后的回复或工具结果
91
+ ```
92
+
93
+ MCP 客户端本身是可信调用方,配置前必须审查其权限和工作目录。默认 MCP 工具面只读,不提供发布、发送、记忆写入、待办修改、配置变更或删除。助手默认拒绝所有来信;`send` 仅用于已建立的官方 Bot 通道会话,不等于操控个人微信账号,也不能向普通个人联系人或群聊发消息。
94
+
95
+ ## 支持与限制
96
+
97
+ - 当前重点验证 Windows 微信 4.x;Linux 可使用相应 NT 数据路径;macOS 不提供自动初始化,需用户自行提供合法的本地访问凭据。
98
+ - 数据库格式、微信版本、官方通道和账号策略可能变化;本地运行不保证兼容性、账号安全或法律结果。
99
+ - 图片和表情导出会尽力使用本地缓存、媒体资源记录和消息提供的 URL。没有可靠身份或原始资源时不会猜测其他图片,而是显示占位信息。
100
+ - 阅读器只绑定回环地址,默认不是局域网服务。
101
+ - 云端 AI、文章抓取、微信读书和发布草稿都可能产生网络请求;本地推理可避免对应的正文出网,但仍应审查客户端和模型配置。
102
+
103
+ ## 维护规则
104
+
105
+ 功能、平台、限制或验证状态变化时更新 `docs/PROJECT_STATE.md`;影响安全、数据流或兼容性的取舍写入 `docs/DECISIONS.md`;用户可见变化才写入 `CHANGELOG.md`。
package/CHANGELOG.md ADDED
@@ -0,0 +1,110 @@
1
+ # Changelog
2
+
3
+ The npm package is published separately from GitHub. It may lag behind the `master` branch until a release is published.
4
+
5
+ All notable user-facing changes are recorded here. This project follows [Semantic Versioning](https://semver.org/).
6
+
7
+ ## 1.6.0
8
+
9
+ ### Documentation
10
+
11
+ - Synchronized setup, operations, architecture, security, MCP, and maintenance guidance with the current `1.6.0` source baseline.
12
+ - Clarified source-versus-npm version drift, no-AI daily runs, staged data-directory discovery, media-export limitations, and local-data privacy boundaries.
13
+ - Replaced the outdated architecture image with a GPT-image-2 diagram covering current CLI, MCP, service, workflow, data, and privacy boundaries.
14
+
15
+ ### Fixed
16
+
17
+ - Decode locally cached WeChat 4.x V2 image containers during HTML chat export by deriving and validating the account-specific media key from local `kvcomm` data.
18
+ - Match exported chat media by stable server-message identity so reused local IDs cannot attach an unrelated image or emoji.
19
+ - Match NT cache media by the exact local-message-ID and timestamp pair when server-resource metadata is unavailable, including reused local IDs.
20
+ - Preserve forwarded app cards with cached covers, including CDATA-wrapped Bilibili links, and decrypt remote WeChat 4.x emoticons with their message-provided AES key.
21
+ - Decode entity-escaped emoji XML and try `encrypturl`, `thumburl`, `cdnurl`, and `externurl` fallbacks; resolve Bilibili BV covers when a share page omits `og:image`.
22
+ - Render signature-only WeChat default `[打脸]` messages with the bundled official `Facepalm` asset when no message-specific resource is available.
23
+ - Cache remote export media (covers, article thumbnails, emoticon CDN) on disk, misses included, so a re-export no longer repeats hundreds of requests against dead WeChat CDN links. First export of a link-heavy conversation dropped from 228s to 28s and re-export to 1.8s, with identical output.
24
+ - Fetch that remote media concurrently instead of one URL per message. A throwaway local-only pass records what the conversation needs, the URLs are fetched in parallel, then the real pass runs against a warm cache.
25
+ - Try WeChat's local sticker cache before the CDN for custom emoticons. The local path is offline and instant; the CDN cost 1.32s per sticker and was tried first.
26
+ - Discover the account's sticker seed automatically. `find_seed`/`any_sticker_file` existed but nothing called them, so `emoticonSeed` stayed empty, local decryption never ran, and custom stickers silently degraded. The export now derives it from a real cached sticker, memoises it, and prints the command to persist it.
27
+ - Render `local_type=10000` system rows as text. Escaping the raw row put WeChat's own display markup (`<img src="SystemMessages_HongbaoIcon.png"/>`, `<_wc_custom_link_ ...>`) in the bubble as a wall of `&lt;sysmsg ...&gt;`, so a revoke notice read as XML instead of naming who revoked what. `$wxid_...$` placeholders are expanded too.
28
+ - Flatten quoted replies (appmsg type 57) whose `<des>` carries a whole escaped nested message, instead of dumping the nested markup.
29
+ - Surface the Python exporter's progress and diagnostics in `export html` output; only the trailing JSON summary was read, so a multi-minute export showed nothing in between.
30
+ - Name the actual speaker in group chats. `display_name` is the group, so every bubble was labelled with the group name and no message could be attributed; group rows now use the sender id carried by the content prefix, falling back to the sender map.
31
+ - Render `local_type=48` location rows as their place label (`[位置] ...`) instead of dumping the location XML.
32
+ - Strip the redundant `wxid_...: ` content prefix from group rows once it has been used to identify the speaker.
33
+ - Resolve group senders to names from the contact database (remark, then nickname, then alias). A group transcript previously showed raw wxids for every speaker; unresolved ids still fall back to the id rather than a blank.
34
+ - Merge the conversation cache and the account media index instead of choosing between them. A `--cache-dir` short-circuited the account scan, and a conversation cache only keeps recent months, so a group photo from last year resolved 0 of 1444 images and every one rendered as a bare `[图片]`. The same fix also recovered 82 additional images in a 1:1 conversation.
35
+ - Show a cached poster frame for `local_type=43` videos when one exists, and always show the clip's duration (`[视频 10″]`) instead of a bare `[视频]`. Where WeChat never downloaded the video, no poster exists locally to show.
36
+ - Fix HTML part navigation, which linked to `<talker>_partN.html` while the files were written as `<remark>_partN.html`, so every "第 N 部分" link opened a missing file (`ERR_FILE_NOT_FOUND`). Affected both group and 1:1 exports; all 16165 links across the two test conversations now resolve.
37
+ - Correct the exported page footer, which still claimed images cover only the most recent two months.
38
+ - Show the drawn frame of a `wxgf` sticker instead of a blank white square. Sticker H.265 streams routinely open with a blank transition frame, and taking frame 1 embedded that; decoding a few frames and keeping the one carrying the most artwork fixes it (one sticker measured 99.1% white before, 2.1% after). Verified across three conversations: 2215 embedded images, 0 blank.
39
+ - Treat an all-blank sticker payload as a failed decode rather than an image, so a truncated local download or a CDN placeholder falls back to the `[表情]` label instead of rendering an empty square.
40
+ - Test the plain-text branch against the message body rather than the row's combined metadata. `metadata_content` always carries `<msgsource>`, so the check always saw a `<` and every text message that had sender metadata skipped the text branch and fell through to the emoji one - rendering a Tencent Meeting invite as `[表情]` beside a broken image.
41
+ - Label `local_type=10000` system rows as `系统` and never fall back to the conversation name for a group speaker. A revoke notice or join template resolves to no member, and the fallback labelled it with the group name, reading as if the group itself had spoken.
42
+ - Render `sysmsgtemplate` join notices from their template and member list (`"彪弟"邀请你和"777"加入了群聊`) instead of stripping the tags and leaving only the chatroom id.
43
+ - Never emit a remote URL as an `<img>` source. The candidate comes from a catch-all that accepts any URL in the row, and a sample of 57 such sources found 56 were web page links (`meeting.tencent.com`, `github.com`, `support.weixin.qq.com`) rather than images, each rendering as a broken-image icon. Images we could not fetch are now simply not shown.
44
+ - Improved WeChat data-directory discovery for custom locations, nested folders, and database subdirectories.
45
+ - Added staged guidance and optional `init --full-scan` fallback when automatic discovery cannot find the data.
46
+ - Completed incomplete yesterday output before an unqualified daily report run.
47
+
48
+ ### Added
49
+
50
+ - Transcribe voice messages into HTML exports. WeChat voice is SILK v3, which browsers cannot play and ffmpeg cannot decode at all, so a voice message previously carried no information whatsoever. `scripts/wechat_voice.py` decodes the payloads from `media_*.db`'s `VoiceInfo` table and recognises them on-device, and the export renders `[语音 6″]` with the transcript beneath it.
51
+ - Transcription is a separate, resumable pass rather than part of the export: exports only read a content-addressed transcript cache, so a long conversation never blocks an export and an interrupted run continues where it stopped.
52
+ - Prefer a Cantonese fine-tune over stock Whisper. Stock Whisper answers Cantonese speech with fluent, confident Mandarin that was never said — worse than no transcript, because it reads as a real sentence. The Cantonese model transcribes the same clips into actual Cantonese, and stock `large-v3` was measurably worse still, hallucinating Vietnamese and English.
53
+ - Use the GPU when one is available, falling back to CPU. The same clip goes from 2.0s to 0.07s, which is the difference between a ~30 minute pass and an overnight one. Includes the Windows DLL-path setup the recognition library needs for its CUDA runtime.
54
+ - `requirements-voice.txt` declares the optional voice dependencies.
55
+ - Label machine transcripts and state the limitation in the page footer. Sampling a Cantonese family group found the recogniser producing Cantonese-shaped text whose meaning often does not hold - right sounds, wrong words. A confidently wrong transcript is worse than an obvious placeholder in a record that may be cited, so transcripts are marked `机器转写·粤语欠准` and the footer says they must not be quoted as the original words. See OPERATIONS.md for the measurements that rule out decoding, audio quality, and model confidence as causes.
56
+
57
+ ### Security and reliability
58
+
59
+ - Run the regression suite in CI and make NT path-discovery checks independent of the optional SQLCipher runtime.
60
+ - Make data-directory search staged: common locations by default, explicit cross-drive search, then explicit deep structural search.
61
+ - Avoid printing database salts, account identifiers, and message paths in `dbkey` diagnostics.
62
+ - Added `daily favorites` commands to synchronize and manage reader favorites as local files.
63
+ - Added `vault promote ideas` and `vault promote all`; both default to no-AI local generation and require explicit opt-in for AI outputs.
64
+ - Keep the default MCP surface read-only and require unique conversation-name resolution with bounded query limits.
65
+ - Require preview and explicit confirmation for machine-driven messaging, configuration, access-control, todo, assistant lifecycle, MCP configuration, key reset, and Vault synchronization changes.
66
+ - Require preview and explicit confirmation for Vault initialization, semantic indexing, knowledge pipelines, and report generation; expose no-AI/source filtering and strict bounded parameters for Agent use.
67
+ - Validate local-reader ports before process startup and open browser URLs without shell interpolation.
68
+ - Restrict MCP article fetching to bounded HTTPS requests on the exact WeChat article host, including redirect revalidation.
69
+ - Validate outbound media files and remove full local paths from message previews and audit records.
70
+ - Resolve bundled Python scripts consistently from both source and compiled package layouts, and propagate worker failures through nonzero exit codes.
71
+ - Remove the ineffective `mcp-config --port` option; the MCP server uses stdio and does not bind a network port.
72
+ - Reject absolute, non-Markdown, symlink-escaping, and parent-traversal entries in daily favorite state before linking or copying files.
73
+ - Add preview, confirmation, and content-free JSON results to Vault content mutations, WeRead synchronization, daily favorites, and personal consumption reports.
74
+ - Add preview and confirmation to Wiki compilation and AI todo extraction; keep process-memory key capture explicitly human-gated.
75
+ - Add a machine-safe preview for database-key capture and require an interactive terminal for execution.
76
+ - Add a content-free initialization preview while keeping actual database discovery and key capture human-gated.
77
+ - Require preview and confirmation before Vault RAG reads local knowledge or sends selected context to AI.
78
+ - Require preview and confirmation for semantic search and RAG chat, and keep their private inputs out of child-process arguments.
79
+ - Keep report conversation selections and NT scan roots out of child-process arguments, and clear unrelated internal values from long-lived worker environments.
80
+ - Require preview and confirmation for evidence review, with content-free and path-free machine results.
81
+ - Reject unsupported WCDB query parameters instead of silently executing SQL without bindings.
82
+
83
+ ### Agent interfaces
84
+
85
+ - Added `capabilities --json`, redacted configuration status, structured export results, reader status, diagnostics, access-list JSON, and no-AI daily JSON output.
86
+ - Added the versioned `weflow-message/v1` contract to CLI exports and the read-only `wechat.export_messages` MCP tool for downstream projects.
87
+ - Added conservative `coverage` metadata to versioned message exports and capability discovery, while preserving the legacy raw JSON array.
88
+ - Added bounded local evidence-package and explicitly authorized evidence-review commands.
89
+ - Applied message date ranges before pagination and preserved unknown message types in downstream contracts.
90
+ - Added content-free JSON summaries for account scanning and assistant logs, plus structured todo reminders.
91
+ - Added preview and confirmed background startup for Agent-controlled local daily readers.
92
+ - Apply the same startup confirmation to the legacy `fav-server` compatibility command.
93
+ - Require explicit confirmation for machine-driven daily generation, including no-AI runs, while preserving human and scheduled non-JSON commands.
94
+ - Add content-free previews for configuration, key, access-list, and audit-log clearing before confirmed deletion.
95
+
96
+ ### Documentation and packaging
97
+
98
+ - Added a unified Python dependency manifest for the standard Windows 4.x workflow and an optional legacy 3.x manifest.
99
+ - Added MCP integration, contribution and security guidance.
100
+ - Included README architecture assets and installation manifests in npm and portable releases.
101
+
102
+ ## 1.5.0
103
+
104
+ ### Added
105
+
106
+ - Local reader dark mode, keyboard navigation and read/favorite tracking.
107
+ - WeChat Moments local-cache commands and AI learning daily reports.
108
+ - Improved knowledge-pipeline and reader workflows.
109
+
110
+ For earlier history, see the [commit log](https://github.com/zhuobichen/weflow-cli/commits/master).
@@ -0,0 +1,45 @@
1
+ # Contributing to WeFlow CLI
2
+
3
+ Thanks for improving WeFlow CLI. This project handles local personal data, so correctness, privacy and reproducibility matter more than broad refactors.
4
+
5
+ ## Before opening an issue
6
+
7
+ Include the command you ran, the operating system, Node.js and Python versions, the WeChat version, and a minimal reproduction. Remove names, wxid values, database paths, API keys, tokens, chat content and screenshots containing private data.
8
+
9
+ For security-sensitive reports, use the process in [SECURITY.md](./SECURITY.md) instead of a public issue.
10
+
11
+ ## Development setup
12
+
13
+ ```powershell
14
+ git clone https://github.com/zhuobichen/weflow-cli.git
15
+ cd weflow-cli
16
+ npm install
17
+ python -m pip install -r requirements.txt
18
+ npm run build
19
+ ```
20
+
21
+ Use `npm run dev -- <command>` while developing. Run `npm run build` before opening a pull request.
22
+
23
+ ## Pull request guidelines
24
+
25
+ - Keep pull requests focused on one user-visible change or repair.
26
+ - Do not commit `.env`, `.mcp.json`, `output/`, databases, decrypted data, keys, tokens, chat exports or screenshots containing personal data.
27
+ - Update README, setup instructions or command help when a workflow changes.
28
+ - Explain the validation performed and any platform limitation in the pull request description.
29
+ - Preserve Windows compatibility unless the change explicitly documents a supported-platform adjustment.
30
+
31
+ ## Documentation changes
32
+
33
+ Keep documentation responsibilities separate:
34
+
35
+ - `README.md`: product overview and shortest path to first use.
36
+ - `docs/SETUP.md`: a complete fresh-machine installation.
37
+ - `OPERATIONS.md`: maintenance and deep troubleshooting.
38
+ - `docs/MCP.md`: MCP client integration and tool boundaries.
39
+ - `docs/EVIDENCE_GUIDE.md`: evidence preservation and legal limitations.
40
+ - `docs/PROJECT_STATE.md`: current baseline, verified capabilities and constraints.
41
+ - `docs/DECISIONS.md`: durable design decisions and their consequences.
42
+ - `ARCHITECTURE.md`: current module boundaries and data flows.
43
+ - `OPERATIONS.md`: operational procedures and troubleshooting.
44
+
45
+ Before opening a PR, verify command examples against `weflow-cli <command> --help`, update the relevant documentation in the same change, and run `npm run build`, `npm test`, and `git diff --check`. Do not use the changelog as an engineering diary.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 shixiansheng
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/OPERATIONS.md ADDED
@@ -0,0 +1,272 @@
1
+ # WeFlow CLI 操作与排障手册
2
+
3
+ 本文面向用户和维护 Agent。所有命令都应在项目目录或已安装 CLI 的终端中执行;示例中的路径、联系人和密钥均为占位符。
4
+
5
+ ## 1. 环境
6
+
7
+ | 依赖 | 用途 | 检查 |
8
+ | --- | --- | --- |
9
+ | Node.js 18+ | CLI、MCP、构建 | `node --version` |
10
+ | Python 3.10+ | NT 数据、日报、阅读器 | `python --version` |
11
+ | `requirements.txt` | 标准 4.x 工作流 | `python -m pip install -r requirements.txt` |
12
+ | `requirements-3x.txt` | 旧版 3.x 数据,可选 | `python -m pip install -r requirements-3x.txt` |
13
+
14
+ 先运行:
15
+
16
+ ```powershell
17
+ weflow-cli check
18
+ ```
19
+
20
+ 源码开发使用:
21
+
22
+ ```powershell
23
+ npm install
24
+ npm run build
25
+ npm run dev -- check
26
+ ```
27
+
28
+ ## 2. 初始化与已有配置
29
+
30
+ 首次使用:
31
+
32
+ ```powershell
33
+ weflow-cli init
34
+ ```
35
+
36
+ 初始化会发现常见数据位置、识别账号目录并验证本地数据库访问。默认优先复用已验证配置;配置有效时不会重复初始化。迁移、切换账号或访问失败时显式刷新:
37
+
38
+ ```powershell
39
+ weflow-cli init --refresh
40
+ ```
41
+
42
+ 数据目录不在常见位置时按成本递增尝试:
43
+
44
+ ```powershell
45
+ weflow-cli init --path "D:\WeChatData"
46
+ weflow-cli init --search-drives
47
+ weflow-cli init --full-scan
48
+ ```
49
+
50
+ `--path` 可以指向微信数据根目录、账号目录或其 `db_storage` 目录。全盘结构搜索可能耗时较长,且会枚举更多本地目录,只有前两种方式找不到时再使用。
51
+
52
+ 测试“密钥缺失但不破坏当前配置”的首次初始化流程:
53
+
54
+ ```powershell
55
+ weflow-cli init --test-missing-keys
56
+ ```
57
+
58
+ 确认密钥确实需要重新获取时,才使用:
59
+
60
+ ```powershell
61
+ weflow-cli config forget-keys --yes
62
+ weflow-cli init --refresh
63
+ ```
64
+
65
+ ## 3. 数据读取验证
66
+
67
+ ```powershell
68
+ weflow-cli config show
69
+ weflow-cli sessions -n 10
70
+ weflow-cli contacts -k "关键词"
71
+ weflow-cli messages "联系人A" -n 10
72
+ ```
73
+
74
+ 看到 `WCDB 初始化失败: -1006` 时,先不要反复登录或删除全部配置。先运行 `check`,确认 Python、数据路径和 NT 数据库状态;然后检查 `config show` 是否只显示“已设置”,不要把密钥复制到 Issue 或日志中。若配置失效,再按第二节执行 `init --refresh`。
75
+
76
+ ## 4. 导出聊天记录
77
+
78
+ ```powershell
79
+ weflow-cli export "联系人A" html --output ./output
80
+ weflow-cli export "联系人A" json --output ./output
81
+ ```
82
+
83
+ 支持 `json`、`txt`、`md`、`html` 和 `excel`。HTML 导出会尽力匹配本地图片、表情、公众号卡片和其他媒体;匹配不到时应显示类型或占位信息,不应从其他会话猜图。跨分片数据尤其要保留原始导出和完整上下文,导出后请人工抽查发送者、时间和媒体对应关系。
84
+
85
+ ### 导出耗时与远程媒体
86
+
87
+ HTML 导出的时间几乎全部花在远程媒体上(公众号封面、B 站封面、表情 CDN)。这些结果按 URL 缓存在输出目录的 `.cover-cache/`,**成功和失败都会记**——多数是已失效的微信 CDN 链接,不记负结果的话每次重导都要把几百次请求重跑一遍。因此:
88
+
89
+ - 同一会话的**重复导出接近瞬时**(实测 1614 条约 2 秒);首次导出才是真正要付网络成本的。
90
+ - 首次导出会先做一遍**只记录 URL、不联网**的扫描,再用 24 线程并发取回,最后用热缓存正式生成。逐条串行取回会慢一个数量级。
91
+ - `.cover-cache/` 可以随时删除,删了只会退回「首次导出」的耗时,不会影响产出内容。
92
+ - 原图(5–24MB/张)默认不嵌入,用微信缓存里的缩略图;确需原图时加 `--full-images`,代价是数分钟。
93
+
94
+ ### 图片显示为 `[图片]`、群聊看不出谁在说话
95
+
96
+ 导出会同时合并两个索引:**会话缓存**(`cache/YYYY-MM/Message/<会话md5>/`,只有最近几个月)和**账号媒体索引**(`msg/attach/<会话md5>/`,历史图片都在这里)。只有前者时,去年的群图片命中率是 0,全部退化成光秃秃的 `[图片]`。
97
+
98
+ 群聊的发言人从联系人库解析:**备注 > 昵称 > 别名**。都取不到时显示 wxid 本身——它仍能区分是谁,比留空或写群名有用。
99
+
100
+ 以下情况是**数据本身不在本机**,改代码也解决不了,导出会如实标注而不是猜:
101
+
102
+ - 视频显示为 `[视频 10″]` 而没有封面图。微信只在视频被完整下载过之后才在本地留下封面(`msg/video/<月份>/<md5>_thumb.jpg`);没下载过就没有,而 `cdnthumburl` 是加密标识、不是能直接下载的地址,离线拿不到。
103
+ - 图片显示为 `[图片]` 且无图:该图片从未在这台设备上下载过。
104
+ - `[位置]` 只有地名、没有地图:位置消息本身不携带地图图片。
105
+
106
+ ### 语音消息转文字
107
+
108
+ HTML 里放不出语音:微信语音是 **SILK v3** 格式,浏览器不支持,ffmpeg 也没有 SILK 解码器(只有 AMR)。所以语音转文字是让语音消息在导出里能携带信息的唯一办法。
109
+
110
+ **它是独立的、可断点续跑的一步,不在导出过程里。** 导出只读转写缓存;缓存没有的语音显示为 `[语音 6″]`。这样可以随时跑、随时停,跑过一遍就永久命中(按语音内容的 md5 缓存,同一条语音被转发到别处也只识别一次)。
111
+
112
+ 安装(可选,较重):
113
+
114
+ ```powershell
115
+ python -m pip install -r requirements-voice.txt
116
+ ```
117
+
118
+ 下载模型。**这一步对粤语是必须的**:原版 Whisper 遇到粤语会输出通顺但完全是编造的普通话——看着像真句子,实际什么都没说过,比不转写更危险。粤语微调版才转得出真正的粤语:
119
+
120
+ ```powershell
121
+ $env:HF_ENDPOINT = "https://hf-mirror.com"; $env:HF_HUB_DISABLE_XET = "1"
122
+ python -c "from huggingface_hub import snapshot_download; snapshot_download('alvanlii/whisper-small-cantonese', allow_patterns=['cts/*'], local_dir='models/whisper-small-cantonese')"
123
+ ```
124
+
125
+ > `HF_HUB_DISABLE_XET=1` 是必需的:hf-mirror 不代理 HuggingFace 的 Xet 传输,不加会报 401。
126
+
127
+ 模型放好后会自动被优先使用(`models/whisper-small-cantonese/cts` 存在即可,该目录已在 `.gitignore` 中)。跑转写:
128
+
129
+ ```powershell
130
+ python scripts/wechat_voice.py --db "<message_0.db>" --key <key> --salt <salt> `
131
+ --passphrase <passphrase> --talker "<会话id>" --cache-dir "output\.voice-cache"
132
+ ```
133
+
134
+ - **有 NVIDIA GPU 时自动走 GPU**,约快 30 倍(实测 0.07 秒/条 vs 2.0 秒/条);GPU 不可用则退回 CPU,不会报错。需要 `pip install nvidia-cublas-cu12 nvidia-cudnn-cu12`。
135
+ - 语言**自动检测**。强制 `--language yue` 在粤语模型上会返回空,别加。
136
+ - 中断后重跑会从缓存未命中的地方继续,不会从头再来。
137
+ - 实测:1775 条语音(约 2.5 小时音频)全量约 9 分钟。
138
+
139
+ > **⚠️ 粤语/方言的准确率有限,务必当作草稿。** 实测一个钦州/东兴一带的家族群
140
+ > (疑为钦廉片白话)1777 条语音:模型输出的是**粤语形态的文字,但相当一部分句子
141
+ > 意思不成立**——音对、词不对。公开的粤语微调模型基本训练于广府片(香港/广州话),
142
+ > 与钦廉片差异明显,这很可能是主因。
143
+ >
144
+ > 排除了这些可能:SILK 解码(三种采样率结果一致、`\x02` 前缀处理无差别)、
145
+ > 音频质量(峰值/RMS/过零率均为正常语音特征)、模型置信度(`avg_logprob` 中位
146
+ > -0.25,模型对自己输出的内容很有把握——这恰恰说明它错得自信)。
147
+ >
148
+ > 因此导出的每条转写都标注「机器转写·粤语欠准」,页脚也写明**不可作为原话引用**。
149
+ > 需要确证时以录音为准。若某个会话不需要转写,删掉输出目录下的 `.voice-cache`
150
+ > 即可,导出会退回只显示 `[语音 N″]`。
151
+
152
+ 实测对比(同一条粤语语音):
153
+
154
+ | 设置 | 输出 |
155
+ | --- | --- |
156
+ | 原版 small,`zh` | 有些人在拍攝,我們都很懶拍七六歲 ← 编造 |
157
+ | large-v3,自动检测 | `Các bạn hãy đăng ký kênh...` ← 幻觉成越南语 |
158
+ | **粤语 small,自动检测** | 你所以東興人沒處來囉,東興人沒處來開囉 ← 正确识别出地名 |
159
+
160
+ ### 自定义表情包(表情包/贴纸)
161
+
162
+ 自定义表情包是 AES 加密的,密钥由一个**账号级 seed** 参与派生。该 seed 只存在于微信进程内存中:
163
+
164
+ - 导出时如果 `emoticonSeed` 未配置,会自动扫描微信内存反推(用真实缓存文件验证,误报基本不可能),结果记在输出目录的 `.sticker-cache/seed`,只需扫一次。
165
+ - 扫描要求**微信正在运行**,且账号曾在微信里查看过表情包。否则自定义表情包会退回 CDN 或显示为 `[表情]`(若其后紧跟图片,说明已渲染成功,`[表情]` 只是标签文字)。
166
+ - 固化:`weflow-cli config set emoticonSeed <值>`,之后不再需要扫描。导出日志里会直接给出这条命令。
167
+ - wxgf(H.265)贴纸需要 ffmpeg,由 `imageio-ffmpeg` 提供;缺失时这类贴纸无法解码。
168
+
169
+ ## 5. 公众号日报与阅读器
170
+
171
+ 生成今天的日报:
172
+
173
+ ```powershell
174
+ weflow-cli daily
175
+ ```
176
+
177
+ 关闭本次运行的全部 AI:
178
+
179
+ ```powershell
180
+ weflow-cli daily --no-ai
181
+ ```
182
+
183
+ 无日期运行会先补齐昨天的不完整产物;指定日期只处理该日期:
184
+
185
+ ```powershell
186
+ weflow-cli daily --date YYYY-MM-DD --no-ai
187
+ ```
188
+
189
+ 只处理指定来源:
190
+
191
+ ```powershell
192
+ weflow-cli daily --source "公众号A" --source "公众号B"
193
+ weflow-cli daily --source "公众号A,公众号B"
194
+ ```
195
+
196
+ 仅预览来源文章,不写日报、不调用 AI:
197
+
198
+ ```powershell
199
+ weflow-cli daily --dry-run
200
+ ```
201
+
202
+ 持久化来源和 AI 设置:
203
+
204
+ ```powershell
205
+ weflow-cli config set dailySources "公众号A,公众号B"
206
+ weflow-cli config set dailyAiEnabled false
207
+ weflow-cli config set dailyAiEnabled true
208
+ weflow-cli config show
209
+ ```
210
+
211
+ 来源类别配置使用 JSON;值可以是公众号名称或稳定来源 ID:
212
+
213
+ ```powershell
214
+ weflow-cli config set dailySourceCategories '{"公众号A":"新闻","公众号B":"政治"}'
215
+ ```
216
+
217
+ 启动指定日期阅读器:
218
+
219
+ ```powershell
220
+ weflow-cli daily-server --date YYYY-MM-DD --open
221
+ ```
222
+
223
+ 默认地址为 `http://127.0.0.1:8765/`。阅读器是本地服务,已生成的日报可离线阅读;文章正文、封面或图片的抓取可能需要联网。
224
+
225
+ 查看来源阅读频率:
226
+
227
+ ```powershell
228
+ weflow-cli daily-stats --days 30 --limit 30
229
+ ```
230
+
231
+ ## 6. AI 和助手
232
+
233
+ 日报关闭 AI 不会自动关闭其他命令的 AI。报告、RAG、助手和证据线索分析分别按命令参数和配置决定是否调用模型。云端分析前应确认输入范围、供应商和隐私设置;优先使用本地模型处理聊天正文。
234
+
235
+ 助手基础配置:
236
+
237
+ ```powershell
238
+ weflow-cli config set aiEngine ollama
239
+ weflow-cli login-wechat
240
+ weflow-cli assistant start
241
+ weflow-cli assistant status
242
+ ```
243
+
244
+ 助手默认拒绝所有发送者,需明确设置 `assistantWhitelist`。群聊还需要群白名单、成员白名单和 @ 门槛;项目不通过客户端自动化或非官方协议拉群。
245
+
246
+ ## 7. 常见问题
247
+
248
+ | 现象 | 处理 |
249
+ | --- | --- |
250
+ | 找不到数据目录 | 先 `init --path`,再 `--search-drives`,最后 `--full-scan`。 |
251
+ | `Python not found` | 安装 Python 并确保当前 PowerShell 能执行 `python --version`。 |
252
+ | 缺少 `sqlcipher3` 等依赖 | 用同一个 Python 执行 `python -m pip install -r requirements.txt`,再 `weflow-cli check`。 |
253
+ | `WCDB ... -1006` | 检查 NT 配置和数据库路径,不要只看 WCDB 降级信息;必要时刷新初始化。 |
254
+ | 日报缺昨天 | 无日期运行 `daily` 会检查并补齐昨天;补齐失败会停止今天,不覆盖失败状态。 |
255
+ | `daily --dry-run` 不识别 | 确认使用的是当前源码或最新发布包;当前源码支持该参数,旧 npm 包可能落后。 |
256
+ | 阅读器打不开 | 使用 `daily-server --date YYYY-MM-DD --open`,不要直接双击 `file://` 页面。 |
257
+ | 图片或表情串错 | 保留原始数据库和导出日志,反馈脱敏后的消息类型、版本和最小复现;不要提交真实媒体。 |
258
+
259
+ ## 8. 安全排查原则
260
+
261
+ 不要在 Issue、PR、截图或共享日志中包含数据库、密钥、token、账号 ID、聊天正文或完整本地路径。公开报告只需操作系统、Node/Python 版本、微信版本、命令和脱敏错误。安全漏洞按 `SECURITY.md` 私下报告。
262
+
263
+ ## 9. 维护验证
264
+
265
+ ```powershell
266
+ npm run build
267
+ npm test
268
+ python -m unittest discover -s test -p '*_test.py' -v
269
+ git diff --check
270
+ ```
271
+
272
+ 测试优先使用合成数据。涉及真实账号时只做最小范围读取,并在完成后关闭本地服务和清理临时导出。