weflow-cli 1.8.2 → 1.10.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.
- package/ARCHITECTURE.md +62 -26
- package/CHANGELOG.md +1290 -0
- package/OPERATIONS.md +144 -11
- package/README.en.md +20 -4
- package/README.md +30 -5
- package/bin/weflow-cli-electron.cjs +2 -0
- package/bin/weflow-cli.ts +996 -118
- package/dist/bin/weflow-cli.js +1038 -146
- package/dist/bin/weflow-cli.js.map +1 -1
- package/dist/mcp-server/http.d.ts +14 -0
- package/dist/mcp-server/http.d.ts.map +1 -0
- package/dist/mcp-server/http.js +84 -0
- package/dist/mcp-server/http.js.map +1 -0
- package/dist/mcp-server/httpConfig.d.ts +50 -0
- package/dist/mcp-server/httpConfig.d.ts.map +1 -0
- package/dist/mcp-server/httpConfig.js +104 -0
- package/dist/mcp-server/httpConfig.js.map +1 -0
- package/dist/mcp-server/index.d.ts +13 -1
- package/dist/mcp-server/index.d.ts.map +1 -1
- package/dist/mcp-server/index.js +58 -374
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/src/core/dbPathService.d.ts +12 -0
- package/dist/src/core/dbPathService.d.ts.map +1 -1
- package/dist/src/core/dbPathService.js +20 -3
- package/dist/src/core/dbPathService.js.map +1 -1
- package/dist/src/panel/server.d.ts.map +1 -1
- package/dist/src/panel/server.js +61 -1
- package/dist/src/panel/server.js.map +1 -1
- package/dist/src/services/assistantEval.d.ts +69 -0
- package/dist/src/services/assistantEval.d.ts.map +1 -1
- package/dist/src/services/assistantEval.js +270 -8
- package/dist/src/services/assistantEval.js.map +1 -1
- package/dist/src/services/assistantScenes.d.ts +81 -0
- package/dist/src/services/assistantScenes.d.ts.map +1 -0
- package/dist/src/services/assistantScenes.js +322 -0
- package/dist/src/services/assistantScenes.js.map +1 -0
- package/dist/src/services/assistantService.d.ts +33 -4
- package/dist/src/services/assistantService.d.ts.map +1 -1
- package/dist/src/services/assistantService.js +102 -6
- package/dist/src/services/assistantService.js.map +1 -1
- package/dist/src/services/assistantSkills.d.ts +94 -0
- package/dist/src/services/assistantSkills.d.ts.map +1 -0
- package/dist/src/services/assistantSkills.js +330 -0
- package/dist/src/services/assistantSkills.js.map +1 -0
- package/dist/src/services/assistantTools.d.ts +34 -1
- package/dist/src/services/assistantTools.d.ts.map +1 -1
- package/dist/src/services/assistantTools.js +931 -88
- package/dist/src/services/assistantTools.js.map +1 -1
- package/dist/src/services/assistantTrace.d.ts +4 -0
- package/dist/src/services/assistantTrace.d.ts.map +1 -1
- package/dist/src/services/assistantTrace.js +9 -0
- package/dist/src/services/assistantTrace.js.map +1 -1
- package/dist/src/services/configService.d.ts +9 -0
- package/dist/src/services/configService.d.ts.map +1 -1
- package/dist/src/services/configService.js +5 -2
- package/dist/src/services/configService.js.map +1 -1
- package/dist/src/services/messageQuery.d.ts +18 -0
- package/dist/src/services/messageQuery.d.ts.map +1 -1
- package/dist/src/services/messageQuery.js +29 -0
- package/dist/src/services/messageQuery.js.map +1 -1
- package/dist/src/services/outboundSend.d.ts +53 -0
- package/dist/src/services/outboundSend.d.ts.map +1 -0
- package/dist/src/services/outboundSend.js +90 -0
- package/dist/src/services/outboundSend.js.map +1 -0
- package/dist/src/services/pythonBridge.d.ts.map +1 -1
- package/dist/src/services/pythonBridge.js +1 -0
- package/dist/src/services/pythonBridge.js.map +1 -1
- package/dist/src/services/wechatClient.d.ts +125 -0
- package/dist/src/services/wechatClient.d.ts.map +1 -0
- package/dist/src/services/wechatClient.js +344 -0
- package/dist/src/services/wechatClient.js.map +1 -0
- package/dist/src/services/wechatMedia.d.ts +44 -0
- package/dist/src/services/wechatMedia.d.ts.map +1 -0
- package/dist/src/services/wechatMedia.js +155 -0
- package/dist/src/services/wechatMedia.js.map +1 -0
- package/dist/src/services/wechatMessageService.d.ts +11 -0
- package/dist/src/services/wechatMessageService.d.ts.map +1 -1
- package/dist/src/services/wechatMessageService.js +55 -11
- package/dist/src/services/wechatMessageService.js.map +1 -1
- package/dist/src/types.d.ts +4 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/python.js +2 -2
- package/dist/src/utils/python.js.map +1 -1
- package/docs/BRANCHES.md +37 -0
- package/docs/CONTACT_DB_SCHEMA.md +1085 -0
- package/docs/DECISIONS.md +1624 -0
- package/docs/EXTENDING.md +98 -10
- package/docs/FUNCTIONAL-IMPROVEMENT-SPEC.md +6 -0
- package/docs/HEALTH-CHECK.md +12 -7
- package/docs/JEV/345/272/224/347/224/250/346/226/275/345/267/245/346/226/207/346/241/243.md +2 -2
- package/docs/MCP.md +58 -4
- package/docs/PROJECT_STATE.md +180 -11
- package/docs/RELEASING.md +115 -1
- package/docs/images/weflow-architecture-gpt-image-2.png +0 -0
- package/logo.png +0 -0
- package/mcp-server/http.ts +108 -0
- package/mcp-server/httpConfig.ts +126 -0
- package/mcp-server/index.ts +359 -681
- package/package.json +5 -3
- package/resources/js/graph3d/NOTICE.txt +35 -0
- package/resources/js/graph3d/d3-binarytree.min.js +2 -0
- package/resources/js/graph3d/d3-dispatch.min.js +2 -0
- package/resources/js/graph3d/d3-force-3d.min.js +2 -0
- package/resources/js/graph3d/d3-octree.min.js +2 -0
- package/resources/js/graph3d/d3-quadtree.min.js +2 -0
- package/resources/js/graph3d/d3-timer.min.js +2 -0
- package/resources/js/graph3d/layout.mjs +63 -0
- package/resources/js/graph3d/three.min.js +6 -0
- package/resources/js/graph3d/viewer2d.js +448 -0
- package/resources/panel/ball-position.cjs +48 -2
- package/resources/panel/index.html +18 -4
- package/resources/panel/main.cjs +137 -5
- package/resources/panel/mascot-base.png +0 -0
- package/resources/panel/mascot-blink-1.png +0 -0
- package/resources/panel/mascot-blink-2.png +0 -0
- package/resources/panel/mascot-iris.png +0 -0
- package/resources/panel/mascot-lift-down-1.png +0 -0
- package/resources/panel/mascot-lift-down-2.png +0 -0
- package/resources/panel/mascot-lift-down-3.png +0 -0
- package/resources/panel/mascot-lift-down-4.png +0 -0
- package/resources/panel/mascot-lift-down-5.png +0 -0
- package/resources/panel/mascot-lift-down-6.png +0 -0
- package/resources/panel/mascot-lift-up-1.png +0 -0
- package/resources/panel/mascot-lift-up-2.png +0 -0
- package/resources/panel/mascot-lift-up-3.png +0 -0
- package/resources/panel/mascot-lift-up-4.png +0 -0
- package/resources/panel/mascot-lift-up-5.png +0 -0
- package/resources/panel/mascot-lift-up-6.png +0 -0
- package/resources/panel/mascot-peek.png +0 -0
- package/resources/panel/mascot-tickle-1.png +0 -0
- package/resources/panel/mascot-tickle-2.png +0 -0
- package/resources/panel/mascot-tickle-3.png +0 -0
- package/resources/panel/mascot-tickle-4.png +0 -0
- package/resources/panel/panel.css +205 -59
- package/resources/panel/preload.cjs +26 -0
- package/resources/panel/renderer.js +646 -17
- package/scripts/_utils.py +1203 -931
- package/scripts/backfill_articles.py +202 -21
- package/scripts/biz_daily.py +26 -34
- package/scripts/bonds.py +331 -0
- package/scripts/chat_notes.py +561 -470
- package/scripts/chat_stats.py +8 -7
- package/scripts/check_readme_commands.py +426 -0
- package/scripts/compile_wiki.py +187 -59
- package/scripts/contact_schema.py +339 -0
- package/scripts/data/wechat_emoji.json +225 -0
- package/scripts/export_chat_html.py +3 -1
- package/scripts/fav_notes.py +4 -1
- package/scripts/graph_2d.py +151 -0
- package/scripts/graph_3d.py +646 -0
- package/scripts/health_check.py +163 -26
- package/scripts/mcp_bridge.py +6 -7
- package/scripts/nt_decrypt.py +3 -3
- package/scripts/panel_frames.py +683 -0
- package/scripts/pipeline.py +21 -10
- package/scripts/quality_eval.py +5 -0
- package/scripts/rag_chat.py +33 -16
- package/scripts/reply_debt.py +26 -6
- package/scripts/semantic_search.py +130 -22
- package/scripts/vault_rag.py +42 -16
- package/scripts/vault_search.py +44 -8
- package/scripts/wechat_emoticon.py +6 -0
- package/scripts/wechat_voice.py +9 -0
- package/scripts/wiki_lint.py +124 -24
- package/src/core/dbPathService.ts +22 -4
- package/src/panel/server.ts +58 -1
- package/src/services/assistantEval.ts +323 -12
- package/src/services/assistantScenes.ts +342 -0
- package/src/services/assistantService.ts +107 -6
- package/src/services/assistantSkills.ts +364 -0
- package/src/services/assistantTools.ts +2452 -1640
- package/src/services/assistantTrace.ts +9 -0
- package/src/services/configService.ts +415 -403
- package/src/services/messageQuery.ts +29 -0
- package/src/services/outboundSend.ts +126 -0
- package/src/services/pythonBridge.ts +1 -0
- package/src/services/wechatClient.ts +380 -0
- package/src/services/wechatMedia.ts +166 -0
- package/src/services/wechatMessageService.ts +62 -11
- package/src/types.ts +4 -0
- package/src/utils/python.ts +2 -2
- package/dist/src/utils/wechatEmoji.d.ts +0 -5
- package/dist/src/utils/wechatEmoji.d.ts.map +0 -1
- package/dist/src/utils/wechatEmoji.js +0 -35
- package/dist/src/utils/wechatEmoji.js.map +0 -1
package/OPERATIONS.md
CHANGED
|
@@ -39,14 +39,18 @@ weflow-cli init
|
|
|
39
39
|
weflow-cli init --refresh
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
数据目录不在常见位置时,`init` 按**可信度**递减来找 —— **先问在跑的客户端**(它的命令行上带着
|
|
43
|
+
`--wechat-files-path`,是唯一"来自客户端自己"的来源,其余都是按目录名猜),找到了会写明是哪种来源;
|
|
44
|
+
找不到再按成本递增试:
|
|
43
45
|
|
|
44
46
|
```powershell
|
|
45
|
-
weflow-cli init --path "D:\WeChatData"
|
|
46
|
-
weflow-cli init --search-drives
|
|
47
|
-
weflow-cli init --full-scan
|
|
47
|
+
weflow-cli init --path "D:\WeChatData" # 你直接告诉它
|
|
48
|
+
weflow-cli init --search-drives # 跨盘按目录名找
|
|
49
|
+
weflow-cli init --full-scan # 名字也没命中时按结构扫
|
|
48
50
|
```
|
|
49
51
|
|
|
52
|
+
(客户端没在跑就没有那条线索,`init` 照旧从常见位置开始 —— 不会因此失败。)
|
|
53
|
+
|
|
50
54
|
`--path` 可以指向微信数据根目录、账号目录或其 `db_storage` 目录。全盘结构搜索可能耗时较长,且会枚举更多本地目录,只有前两种方式找不到时再使用。
|
|
51
55
|
|
|
52
56
|
测试“密钥缺失但不破坏当前配置”的首次初始化流程:
|
|
@@ -68,6 +72,8 @@ weflow-cli init --refresh
|
|
|
68
72
|
weflow-cli config show
|
|
69
73
|
weflow-cli sessions -n 10
|
|
70
74
|
weflow-cli contacts -k "关键词"
|
|
75
|
+
weflow-cli contact-schema -n 3 # 读群 ext_buffer 里**已验证**的字段(成员/status/inviter)
|
|
76
|
+
weflow-cli contact-schema --contacts -n 5 # 改看联系人:地区码 / 服务类型 / 资料更新时间(#4/#9 是账号资料文本,不打印)
|
|
71
77
|
weflow-cli messages "联系人A" -n 10
|
|
72
78
|
```
|
|
73
79
|
|
|
@@ -298,7 +304,7 @@ python scripts/quality_eval.py consistency ~/.weflow-cli/labels/labels-<时间
|
|
|
298
304
|
|
|
299
305
|
**清单是盲的**:`sample` 打印给你的那张表**不印 Jev 的答案**(只有日期与历史标注)。
|
|
300
306
|
先看见模型说了什么,人就会往它靠,测出来的"一致率"会偏高——而偏高的量无法估计。
|
|
301
|
-
`topicConfidence`/`relevanceScore`/`includeScore`
|
|
307
|
+
`topicConfidence`/`relevanceScore`/`includeScore` **只在被判断层判过的那篇文章上存在**(它们由 `_apply_decision` 从判断结果写进去)。走 LLM 回退路径的文章没有这几个分 ——所以判断层按地区不可用(见下面的 451)时,日报里整批都没有它们;标注时别翻它。
|
|
302
308
|
|
|
303
309
|
`score` 会给出四件事:
|
|
304
310
|
|
|
@@ -416,9 +422,11 @@ weflow-cli search-index --days 3650 --article-days 365 --yes # 要"整段历
|
|
|
416
422
|
| `weflow-cli user-notes --limit N --yes` | **你自己写的**笔记发给 DeepSeek(每篇一次) | 你的笔记**只读、绝不修改**;卡上标 `summary_by: model`(那是模型的理解,不是你的原话);**你笔记里的 `[[链接]]` 优先** |
|
|
417
423
|
| `weflow-cli wiki compile --source … --min-refs 2 --yes` | 概念发给 DeepSeek(每个概念一次) | `--min-refs 2` 滤掉只被一篇提到的一次性实体 |
|
|
418
424
|
| `weflow-cli wiki compile --refresh-sources --yes` | **不出境** | 只把**已有页**的「来源」段补齐成当前全部来源(本地重写)。**拉完新文章要跑这一条**,否则新文章提到老概念时,那一页不会多出这条边 |
|
|
425
|
+
| `weflow-cli wiki compile --qualify-links --dry-run` | **不出境** | 两条线同名(本机 36 个)时,把指向它们的链接改成带路径的 `[[Chat/Concepts/DeepSeek|DeepSeek]]` —— 否则 Obsidian 里那条裸链接会**命中另一条线**的那张。只改同名的、不碰「来源」段;幂等,重跑不改第二遍。本机实测 539 条 / 477 张页 |
|
|
419
426
|
| `weflow-cli wiki compile --merge-duplicates --dry-run` | **不出境** | 把「规范化后同名」的多张页合并成一张(`GPT 5.6`/`GPT-5.6`/`GPT5.6`)。留来源最多的那张,其余名字进 `aliases`——**指向旧名字的链接一条都不断**,不必改别的文件。**它会删页**,先跑 `--dry-run` 看名单 |
|
|
420
427
|
| `weflow-cli wiki compile --pages-from-cards --cards <线> --dry-run` | **不出境** | 给还没有页的概念建页:定义复用卡片里那句原话、相关概念取共现。**必须指定 `--cards`**(一条线一条线建,否则聊天线会被建进文章线) |
|
|
421
|
-
| `weflow-cli wiki lint` | **不出境** | 断链 / 孤儿 / 空页 /
|
|
428
|
+
| `weflow-cli wiki lint` | **不出境** | 断链 / 孤儿 / 空页 / **同一条线内**的同名 / **二义链接**(`ambiguousLinks`,修法见下一行的 `--qualify-links`)/ 近似重名 / 退化字段;两条线都有同一个概念名会**单列一节**报出来(`crossLineSameName` —— 设计如此,不是要修的东西)。不传 `--dir` 就体检清单里的全部线 |
|
|
429
|
+
| `weflow-cli wiki graph --open` | **不出境** | 把概念图谱导成一张**自包含**的 3D 页面(`output/knowledge-graph-3d.html`,本机 49,956 个概念约 9MB,**双击就能逛,不需要起服务器**)。库、数据、坐标全部内联进去,所以它不联网 —— `file://` 下 `fetch` 会被 CORS 挡死,而引 CDN 又会把"本地优先"变成"要有网"。坐标是构建期用 Node 算好缓存的(`output/.graph3d-cache/`),只改渲染不会重算;先看规模用 `--dry-run`。**`--min-degree N`** 只画**在原图里**连接数 ≥N 的概念(去掉细枝看骨架:本机 ≥10 只剩 **3,825 点 / 1.09MB**,全量是 5 万点 / 9MB —— 5 万点时那张图看不清,不是不好看,是布局本身就糊);**`--line wiki|chat`** 只画一条线(文章线 4.8 万 / 聊天线 1,527,两套概念口径不同,混在一起看不出结构)。两者都只改**给页面看的点集**;坐标按图内容分槽缓存(`graph-<hash>.json`),核心图与全量图来回切都不用重算。**`--flat`** 出 2D 版(canvas 平面图,更像 Obsidian 那种;默认写到 `output/knowledge-graph-2d.html`):布局同样是构建期算好,但**按 2D 重算**而不是把 3D 的 x/y 拍扁(z 那一维也承载结构,拍扁会把两团不相干的点叠在一起),而且它**一个库都不引**(渲染是裸 canvas)。2D 的快得多:3,825 点 250 tick 只要 2.4 秒,页面 0.71MB(3D 同图 1.34MB)。 |
|
|
422
430
|
|
|
423
431
|
四条卡片来源(文章 / 聊天 / 收藏 / 你自己的笔记)产出的东西是**同一种形状**(带 frontmatter +
|
|
424
432
|
`## AI 摘要` + `[[概念]] — 说明`),所以 `wiki compile` 一视同仁——再加一条来源时改的是产卡那一步,
|
|
@@ -442,6 +450,12 @@ weflow-cli wiki compile --source ./output/chat-notes --output ./output/wechat-va
|
|
|
442
450
|
- **`--output` 要指到 `Chat/Concepts`**:文章线与聊天线在库里是**两个目录**(`Wiki/` 与 `Chat/`,
|
|
443
451
|
同一个 Obsidian 库)。`wiki compile` 一次只产一条线的页,默认写文章线——用默认值跑聊天线,
|
|
444
452
|
两边的页会混进同一个目录,而图谱里就再也分不出"我读到的"和"我们聊过的"。
|
|
453
|
+
- **跨线同名不再跳过**(2026-10-10 起):两条线各留一张 `DeepSeek` 是设计,图谱里它们标着各自的
|
|
454
|
+
线。**代价**:Obsidian 里 `[[DeepSeek]]` 这条**裸链接未必命中你想要的那一张**(官方判据:有同名
|
|
455
|
+
文件时会 deterministic 地解析,但不保证是哪一张;自带路径的 `[[Chat/Concepts/DeepSeek]]` 才确定)。
|
|
456
|
+
这个代价**已经按"同库内消歧"修掉了**:`weflow-cli wiki compile --qualify-links` 把指向同名的链接
|
|
457
|
+
改成带路径的形式(本机 539 条 / 477 张页,幂等)。**新出现的同名要重跑它** —— 体检的
|
|
458
|
+
`ambiguousLinks` 那一节就是盯着这件事的(列出来并给出命令)。
|
|
445
459
|
- 三种形状自然落下来:**按会话的知识卡**就是第一步入库的那些卡;**主题汇总**与
|
|
446
460
|
**人物/时间线**是第二步把卡里的 `[[话题]]`/`[[人名]]` 聚出来的概念页。
|
|
447
461
|
- **文章线要先用一道提炼**(2026-09-26 实测后补上):
|
|
@@ -541,11 +555,20 @@ weflow-cli wiki lint --json # 机器可读
|
|
|
541
555
|
```powershell
|
|
542
556
|
weflow-cli search "PM2.5 对植物用水效率的影响"
|
|
543
557
|
weflow-cli search "..." --no-rerank # 只按向量/关键词相似度,不调决策模型
|
|
558
|
+
weflow-cli search "项目排期" --line chat # 只看聊天那条线
|
|
559
|
+
weflow-cli search "..." --line all # 两条线一起(默认只搜文章线)
|
|
544
560
|
```
|
|
545
561
|
|
|
562
|
+
**`--line wiki|chat|all` 四处都有**(`search` 语义检索、`chat` RAG、`vault search`、`vault rag`),
|
|
563
|
+
助手的 `search_semantic` / `search_knowledge` 也有同名参数。两条知识库分开之后,**默认只搜
|
|
564
|
+
文章线**,要把聊天那条也搜上就显式给 `all`。输出里每一处都会写明这一趟搜的是哪条线,空了
|
|
565
|
+
还会说清"是没命中还是这条线在索引里根本没有记录"——不写的话,"这条线里没有"会被读成
|
|
566
|
+
"整个知识库里没有"。
|
|
567
|
+
|
|
546
568
|
检索分两段:第一段算相似度取回 20 条候选,第二段用**一次**决策请求给每条候选问一个
|
|
547
569
|
"是否真的回答了这个问题",按概率重排后返回 `--top-k` 条(默认 10)。第二段约 1 秒,
|
|
548
|
-
|
|
570
|
+
与候选数基本无关。`--line` 的过滤发生在**取候选之前**(不是取完再筛),所以不会出现
|
|
571
|
+
"要 10 条只回 3 条"或者"另一条线的结果混进来还标着本线的名字"。
|
|
549
572
|
|
|
550
573
|
- 返回里 `score` 仍是相似度(含义没变),重排的分数在 `rerankScore`。
|
|
551
574
|
- 没配 `typesafeApiKey`、连接失败或服务过载(529)时,**原序返回并打一行 WARN**,
|
|
@@ -736,6 +759,7 @@ python scripts/generate_html.py --date 2026-09-05 --exclude-topics "新闻,投
|
|
|
736
759
|
- 相关度会写进 frontmatter 的 `relevance`(仍是「高/中/低」三个字),并额外写入
|
|
737
760
|
`relevanceScore`(原始分值)与 `topicConfidence`(主题的置信度)。那三档的切点是
|
|
738
761
|
暂定的,原始分留着,将来重新校准时不用重跑历史日报。
|
|
762
|
+
**前提**:这三个分只在判断层(Jev)判过的文章上才有(它们来自 `decision`)。判断层不可用、整轮走 LLM 回退路径时,日报里就没有它们 —— 2026-10-10 实测:回填日的 383 篇里 0 篇带 `relevanceScore`,而 `biz_daily.py` 的 `_article_entry` 本身是会写这几个键的。
|
|
739
763
|
- 同一批问题里还问了一个**「该不该收进今天的日报」**(`includeScore`,0~1)。
|
|
740
764
|
日报的收录门用它,而不是拿相关度顶替——相关度答的是"对读者的实用价值",
|
|
741
765
|
答不了"今天该不该收它"。切点默认 `0.5`,同样暂定;`generate_ai_report.py`
|
|
@@ -748,6 +772,9 @@ python scripts/generate_html.py --date 2026-09-05 --exclude-topics "新闻,投
|
|
|
748
772
|
- 分类要把文章标题与正文发往 `api.typesafe.ai`——和生成摘要发给 DeepSeek 是同一类动作,
|
|
749
773
|
想完全不出网就用 `weflow-cli daily --no-ai`。
|
|
750
774
|
- 排查用 `python scripts/biz_daily.py --date <日期> --classifier llm`(强制老路径)对比。
|
|
775
|
+
- 如果日志里出现 `HTTP 451 … not available in your region`:那是**判断层按地区不可用**(服务端策略,不是配置错)。
|
|
776
|
+
日报不会因此坏掉——每篇都会退回老的 LLM 解析路径,只是白试一次;想让这一天的日报**连试都不试**,
|
|
777
|
+
加 `--classifier llm` 就行。同一条失败在日志里已经折叠成一次(`另有 N 篇因…被折叠`),不会刷屏。
|
|
751
778
|
- 只要判断、不要生成(连 DeepSeek key 都不需要):`weflow-cli daily --no-summary`。摘要/标签/简报一律不生成,md 里不会有 `## AI 摘要` 段;主题与相关度仍由 Jev 判断。流水线里下游步骤(行动建议/概念编译/AI 报告)仍会用 LLM,要全关再加 `--skip-classify --skip-wiki --skip-ai-report`。
|
|
752
779
|
|
|
753
780
|
启动指定日期阅读器:
|
|
@@ -811,6 +838,23 @@ weflow-cli assistant start
|
|
|
811
838
|
weflow-cli assistant status
|
|
812
839
|
```
|
|
813
840
|
|
|
841
|
+
### 入站图片/文件要不要落地(默认不落)
|
|
842
|
+
|
|
843
|
+
别人发给助手一张图,助手默认只知道"有这么一张图",不知道图里是什么。打开这个开关后,通道会把图片、语音、文件、视频从 CDN 拉下来、在本地解密并写盘:
|
|
844
|
+
|
|
845
|
+
```powershell
|
|
846
|
+
weflow-cli config set wechatMediaDownload true
|
|
847
|
+
weflow-cli assistant stop
|
|
848
|
+
weflow-cli assistant start
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
- **这是显式的网络访问**,所以默认是关的(`false`)。不打开时,进程不会为入站媒体发任何请求。
|
|
852
|
+
- 文件落在 `output/wechat-media/` 下;换位置用环境变量 `WEFLOW_WECHAT_MEDIA_DIR`(目录会在首次落地时自动建)。
|
|
853
|
+
- **文件名由本地决定**:服务端给的名字只取最后一段并过滤字符,所以它写不到 `output/` 之外去。
|
|
854
|
+
- 单件超过 **25 MB**、下载失败、或解出来是空的,都**不会留下文件**:`filePath` 是空的,日志里有一行写明原因(`入站媒体未落地(image):…`)。看到这行就是没存下来,不是"存了但你没找到"。
|
|
855
|
+
- 关掉就回到原样:`weflow-cli config set wechatMediaDownload false`。
|
|
856
|
+
- ⚠️ **它是"谁发来的都下",不是"只下白名单的"**:下载发生在长轮询解析消息的那一步,比"助手要不要回答"的判断更早。所以只要有人能给这个机器人发消息,他发来的图片/文件就会落到你磁盘上;白名单管的是**助手回不回答**,管不到**下不下载**。介意这一点就别开这个开关(或把机器人只留给自己能联系)。
|
|
857
|
+
|
|
814
858
|
### 本机面板:不扫码也能跟助手说话
|
|
815
859
|
|
|
816
860
|
```powershell
|
|
@@ -864,10 +908,19 @@ npm i -g electron
|
|
|
864
908
|
球被拖到屏幕外时会回到右下角。展开后气泡这一整块**不置顶**——去点别的窗口时会到后面去,
|
|
865
909
|
从任务栏点回来即可。
|
|
866
910
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
911
|
+
**球有表情**(球是 96px,素材是 256px 的图,都在 `resources/panel/`):**按住**它像被拎住后颈一样
|
|
912
|
+
浮起来 —— 十二帧硬切(6 帧拎起来 + 6 帧落回去),松手接着播完落地那几帧回到原样,全程约 0.7 秒,按下那一帧
|
|
913
|
+
是同步出的(不留空档);助手**忙**、**离线**、**配额用完**时各有一张脸;空闲时球背后什么都没有
|
|
914
|
+
(那层光晕 2026-09-29 已整层删掉)。这些是"真状态",不是动画效果:状态脸由 `renderer.js` 的
|
|
915
|
+
`setBallFace()` 统一设置(加新状态时改那一个入口),动作帧由同一个文件里的 `showLift()` 统一切换。
|
|
916
|
+
系统开了"减少动态效果"时不播动作,只保留按住时那张笑脸 —— 那正是那张笑脸现在唯一的用处。
|
|
917
|
+
|
|
918
|
+
**鼠标从它身上划过时它会扭**(挠痒痒,2026-10-02):4 张姿势帧循环播放,停下约 0.3 秒收。
|
|
919
|
+
|
|
920
|
+
**划过只扭、不倾斜** —— 它早先还带一个按速度算的小倾斜(往哪边划就往反方向倒),2026-10-02 去掉了:
|
|
921
|
+
旋转现在只归"被拎起来"那条,因为两者共用 `#ball` 上的 transform,随手扫过看起来像一次小号起飞
|
|
922
|
+
(用户的原话:「为什么鼠标划动也会晃,而不是在起飞状态才会晃」)。系统开了"减少动态效果"时不扭;
|
|
923
|
+
它半隐在屏幕边时也不扭;按住时也让位给"被拎起来"那套。
|
|
871
924
|
|
|
872
925
|
**关掉窗口 ≠ 停止助手**:窗口没了,守护进程还在跑(微信那边可能还在用)。要停:
|
|
873
926
|
|
|
@@ -892,6 +945,7 @@ weflow-cli assistant stop
|
|
|
892
945
|
# 端口与 token 在 ~/.weflow-cli/assistant_endpoint.json 里;token 不要贴到别处
|
|
893
946
|
curl.exe -i http://127.0.0.1:8766/api/status # 401(没 token)
|
|
894
947
|
curl.exe -i -H "Authorization: Bearer <token>" http://127.0.0.1:8766/api/status # 200
|
|
948
|
+
curl.exe -i -H "Authorization: Bearer <token>" http://127.0.0.1:8766/api/memory # 200:它记住了什么(只读)
|
|
895
949
|
```
|
|
896
950
|
|
|
897
951
|
**中文别用 Git Bash 的 `curl -d '中文'`**:那条路径会把正文按控制台代码页编出去,
|
|
@@ -1087,6 +1141,85 @@ npm run eval:assistant -- --json # 附机器可读报告
|
|
|
1087
1141
|
会把守护进程刚写的状态覆盖掉)。用的 key 是你配置里那一个(`lock:` 密文,只在本机解),
|
|
1088
1142
|
临时配置里只放这一个字段。
|
|
1089
1143
|
|
|
1144
|
+
### 技能:让助手读上你自己的技能包
|
|
1145
|
+
|
|
1146
|
+
技能就是一份 `SKILL.md`(`name` + `description` frontmatter)。助手**不会安装、不会执行**它们——
|
|
1147
|
+
它把技能当资料:提示词里列出有哪些,要用时用 `read_skill` 读正文再照着做。所以装一百个技能也不会让模型多出一个工具。
|
|
1148
|
+
|
|
1149
|
+
默认扫两个目录:`~/.claude/skills`(你已有的技能立刻可用)和 `~/.weflow-cli/skills`(本项目自己的落脚点)。
|
|
1150
|
+
换目录:`weflow-cli config set skillDirs "D:/我的技能,~/.claude/skills"`。
|
|
1151
|
+
|
|
1152
|
+
```powershell
|
|
1153
|
+
weflow-cli skill list # 有哪些(带版本与状态)
|
|
1154
|
+
weflow-cli skill list --query 日报 # 按 id/名称/说明/触发词过滤
|
|
1155
|
+
weflow-cli skill show memory-organizer # 打印正文
|
|
1156
|
+
weflow-cli skill check # 体检:读不出来的、跨目录同名的、id 不合规的、被禁用的
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
`skill check` 值得偶尔跑一次:少一个技能不会报错,只会少一个技能——它会告诉你少了哪个、为什么。
|
|
1160
|
+
两种禁用方式:`weflow-cli config set skillDisabled "某技能,另一个"`,或在技能自己的 `SKILL.md` 里写 `enabled: false`。
|
|
1161
|
+
|
|
1162
|
+
**边界(有意为之)**:`read_skill` 只可能读到名字叫 `SKILL.md`、且被目录扫描扫到的文件,读不到配置、数据库或任意路径。
|
|
1163
|
+
符号链接进来的技能**算数**(在 git 仓库里开发技能、再 `ln -s` 到技能目录是常见做法)。
|
|
1164
|
+
|
|
1165
|
+
### 助手现在能调哪些工具(以及两条要注意的)
|
|
1166
|
+
|
|
1167
|
+
2026-09-29 把三个界面拉平了:助手能调的,基本就是 MCP 客户端早就能调的那一批(详见 `docs/DECISIONS.md` 的 D-058)。
|
|
1168
|
+
新增里平时最用得上的几条:
|
|
1169
|
+
|
|
1170
|
+
- **抓公众号正文**:贴一个 `https://mp.weixin.qq.com/...` 链接让它读(白名单 + 逐跳复检;非这个域一律拒绝)
|
|
1171
|
+
- **搜公开文章**:按关键词搜公开的公众号文章标题与摘要(走第三方搜索页,**搜索词会离开本机且没有预览**)
|
|
1172
|
+
- **排版**:「把这段 Markdown 排成公众号格式」→ 它给 HTML 片段,主题用 `list_themes` 查
|
|
1173
|
+
- **通讯录**:「我有哪些联系人」——只给名字,**不给 wxid**
|
|
1174
|
+
- **学习回顾 / 知识库体检 / 技能体检**:`get_review`、`lint_wiki`、`check_skills`
|
|
1175
|
+
- **把待办标记完成**:「交季度报表那条做完了」——它能改状态,**不能删待办**;指代不清(重名)时它会拒绝而不是猜
|
|
1176
|
+
|
|
1177
|
+
两条边界要记住:
|
|
1178
|
+
|
|
1179
|
+
1. **`search_public` 的搜索词没有闸门**。这是明确的取舍(D-058),不是遗漏——从一条微信消息就能让模型去搜任意词。
|
|
1180
|
+
介意的话就别在群里开助手,或者把它从工具表里去掉(改代码)。
|
|
1181
|
+
2. **待办修改在 MCP 那条路上不可达**。助手在微信/面板里能改,外部 MCP 客户端不能(项目自己的天花板:
|
|
1182
|
+
mutating todos stays out)。
|
|
1183
|
+
|
|
1184
|
+
### 场景:让某个会话有固定的做法
|
|
1185
|
+
|
|
1186
|
+
一个场景 = 关键词 + 附加指令 + 输出规范 + 所需技能。消息进来时按三档挑:**绑定**(你显式指定)→
|
|
1187
|
+
**关键词**(这条消息里出现了它的关键词)→ **上次用过的**。都没中就没有场景段,助手行为与以前一字不差。
|
|
1188
|
+
|
|
1189
|
+
```powershell
|
|
1190
|
+
# 加一个:关键词命中就带上(长文本用 --from-file,别在命令行里塞多行中文)
|
|
1191
|
+
weflow-cli scene add --id 日报 --name "日报整理" --keywords 日报,推文 `
|
|
1192
|
+
--instruction "把这些推文按主题分组,标注来源。" --output-spec "先列表后总结" --dry-run
|
|
1193
|
+
weflow-cli scene add ... --yes # 确认执行(所有写操作都要先 --dry-run 再 --yes)
|
|
1194
|
+
|
|
1195
|
+
weflow-cli scene list # 有哪些、本会话绑的是哪个
|
|
1196
|
+
weflow-cli scene show 日报 # 看全部字段
|
|
1197
|
+
weflow-cli scene disable 日报 # 停用(不再参与匹配)
|
|
1198
|
+
weflow-cli scene remove 日报 # 删掉(连指向它的绑定一起清)
|
|
1199
|
+
weflow-cli scene bind wxid_xxx --scene 日报 --yes # 固定绑到某个会话
|
|
1200
|
+
weflow-cli scene unbind wxid_xxx --yes
|
|
1201
|
+
```
|
|
1202
|
+
|
|
1203
|
+
在对话里(微信或面板)也能用:
|
|
1204
|
+
|
|
1205
|
+
- `场景` —— 列出所有场景,标出本会话生效的那个
|
|
1206
|
+
- `场景 <id>` —— 把这个场景绑到当前会话
|
|
1207
|
+
- `场景 无` —— 解绑
|
|
1208
|
+
|
|
1209
|
+
只有后半段**是真实存在的场景 id** 时才算指令,所以「场景切换怎么用」这种问话不会被吃掉。
|
|
1210
|
+
指令不调用模型(省一次调用,也省配额)。
|
|
1211
|
+
|
|
1212
|
+
**改完场景要重启助手才生效**:场景是助手启动时读一次(和配置一样),而**技能是每一轮现扫的**——
|
|
1213
|
+
所以新装一个技能立刻可用,但 `scene add` 出来的场景在运行中的助手那里看不见。
|
|
1214
|
+
要 `weflow-cli assistant stop` 再 `assistant start` 之后才生效(**没有 `assistant restart` 这个命令**)。
|
|
1215
|
+
|
|
1216
|
+
场景里可以写 `{{skill:技能id}}` 行内引用技能;技能缺失时会明确写成「技能文件不可用,请直接完成」,
|
|
1217
|
+
并让助手在回答里说明哪部分没做——**不会静默跳过**。
|
|
1218
|
+
|
|
1219
|
+
**场景只由你在电脑上改**:没有任何助手工具能读写场景,一条微信消息改不了它(同 `隐私` 那条的立场)。
|
|
1220
|
+
助手回答下面展开的「思考过程」里会写清这一次用了哪个场景、因为哪一档命中;如果有两个场景同样匹配,
|
|
1221
|
+
它**不带场景**,并在那里说明原因。
|
|
1222
|
+
|
|
1090
1223
|
## 7. 常见问题
|
|
1091
1224
|
|
|
1092
1225
|
| 现象 | 处理 |
|
package/README.en.md
CHANGED
|
@@ -94,11 +94,14 @@ Automatic initialization on Linux depends on the WeChat distribution, the Python
|
|
|
94
94
|
| --- | --- |
|
|
95
95
|
| Chat history | Query sessions, contacts, and messages; export to JSON, TXT, HTML, Excel. An HTML export also writes a media coverage report saying which images and stickers could not be embedded, and why. |
|
|
96
96
|
| Official-account digest | Crawl articles, AI summarization and classification, generate a local reading page, keep favorites and read states. |
|
|
97
|
-
| Personal knowledge base | Sync WeRead notes, build an Obsidian vault, semantic search, RAG Q&A, and a
|
|
97
|
+
| Personal knowledge base | Sync WeRead notes, build an Obsidian vault, semantic search, RAG Q&A, a concept wiki, and a **self-contained graph page** you can open by double-clicking (`weflow-cli wiki graph --open` for 3D, `--flat` for 2D - no server, no network; `--min-degree N` keeps only the hubs, `--line wiki\|chat` draws one corpus). |
|
|
98
98
|
| AI collaboration | Expose article crawling, knowledge-base retrieval, digests, and selected local-data tools to MCP-compatible clients. The inventory follows the current code and `docs/MCP.md`. |
|
|
99
99
|
| Personal review | Monthly chat reports, annual reports, todo extraction, and local Moments cache queries. |
|
|
100
100
|
| WeChat favorites | Read WeChat "Favorites" (official-account articles, text, images, videos, chat records) with type filters, keyword search, and Markdown/JSON export. |
|
|
101
|
-
| Second-brain agent | Chat with a local AI assistant inside WeChat: natural-language queries over chats, favorites, Moments, digests, WeRead, todos, and the knowledge base; three-tier memory across sessions, daemonized background service. |
|
|
101
|
+
| Second-brain agent | Chat with a local AI assistant inside WeChat: natural-language queries over chats, favorites, Moments, digests, WeRead, todos, and the knowledge base; three-tier memory across sessions, daemonized background service. It can also **fetch an official-account article**, search public articles, format Markdown for the WeChat editor, list contacts, read your learning reviews, health-check the knowledge base and skill packages, and mark a todo done (**never delete one**). What it can reach, and what stays out of reach, is in `docs/PROJECT_STATE.md` and `docs/DECISIONS.md` (D-058). |
|
|
102
|
+
| On-device panel | A floating ball on your desktop: click to chat with **the same brain as the WeChat side** (same memory, same quota), and each reply expands into a **thinking process** - what tool it called, how many round trips, why it stopped. The ball itself is transparent with a face per state, and a **Memory** button lists what it has stored about you long-term - each fact with the time it was written and the quote it came from (read-only). |
|
|
103
|
+
| Skill packages | The assistant reads the `SKILL.md` packages already on your machine (by default `~/.claude/skills` and `~/.weflow-cli/skills`): the prompt lists what exists, and a body is read on demand before following it. **A skill grants the assistant no new tools** - it is material: not executed, not installed, and unable to read configuration or databases. `weflow-cli skill check` reports unreadable frontmatter, cross-directory collisions, and non-conforming ids. |
|
|
104
|
+
| Conversation scenes | Give one conversation a fixed way of working: keywords plus an extra instruction, an output spec, and required skills. Each message picks one by **binding → keyword → last used**, and picks none when nothing matches, leaving the previous behaviour untouched. Manage with `weflow-cli scene`, or bind from the conversation with `场景 <id>`. **Scenes are not readable or writable by the model**, and which scene applied is recorded in the thinking process. |
|
|
102
105
|
|
|
103
106
|
> **⚠️ Intended use**: this tool only accesses data of **your own** WeChat account, on your own machine, with your own consent. Do not use it to monitor a partner, employee, or any third party without explicit consent, deploy it onto someone else's device, or run it remotely and silently. Review WeChat's terms, account-risk policies, and local legal requirements. See [SECURITY.md](SECURITY.md).
|
|
104
107
|
|
|
@@ -229,7 +232,13 @@ weflow-cli panel # open the on-device panel window (usable without
|
|
|
229
232
|
|
|
230
233
|
`weflow-cli panel` opens a small always-on window that talks to **the same brain as the WeChat side** — the same memory, the same daily quota. **No WeChat login is required**: the messaging channel is optional. The window is only a client; its messages go to the daemon's entry point on `127.0.0.1`, so the two entry points never keep separate copies of memory.
|
|
231
234
|
|
|
232
|
-
The floating ball needs Electron (`npm i -g electron`); without it the panel degrades to an Edge/Chrome `--app` window — same UI, but no frameless always-on-top ball, no tray, no global shortcut. With the ball (a 96px mascot): **click it and the chat bubble opens beside it (the ball itself stays put; click again to collapse)**. The bubble opens to the left of the ball by default, flips to the right when there is no room on the left, and top-aligns when vertical space runs short; drag the ball to move it, and the position is remembered. The ball
|
|
235
|
+
The floating ball needs Electron (`npm i -g electron`); without it the panel degrades to an Edge/Chrome `--app` window — same UI, but no frameless always-on-top ball, no tray, no global shortcut. With the ball (a 96px mascot): **click it and the chat bubble opens beside it (the ball itself stays put; click again to collapse)**. The bubble opens to the left of the ball by default, flips to the right when there is no room on the left, and top-aligns when vertical space runs short; drag the ball to move it, and the position is remembered. **The ball is transparent - only the mascot shows through** - calm at rest, and switching to a *thinking* face for the seconds you are waiting on an answer (offline and quota-exhausted have faces of their own). **Press and hold it and it is picked up by the scruff - a twelve-frame lift (six up, six back down) that settles on release** (skipped when the system asks for reduced motion). **Run the pointer across it and it squirms as if tickled** - four poses, with **no tilt** (the 4-degree rotation it
|
|
236
|
+
used to work out from how fast you move was removed on 2026-10-02, so that running the pointer across it no longer
|
|
237
|
+
looks like a small take-off: rotation belongs to the lift alone). **Carried around it swings left and right - the side you move towards swings further, and faster movement swings wider.** It **hops when a reply lands**, **blinks every 7-13 seconds**, its eyes follow the pointer, and dragged to a screen edge it hides half-way behind it.
|
|
238
|
+
|
|
239
|
+
**Every reply carries a collapsible "thinking process" (closed by default)**: how that turn actually went - the routing decision, which tool it called, its arguments, how many round trips, and why it stopped. It is the same record you get in WeChat by sending 轨迹 (or 思考过程), so the two cannot drift apart.
|
|
240
|
+
|
|
241
|
+
**Right-click anywhere in the panel** to draft a reply for someone on your list (`weflow-cli config set quickReplyContacts "Alice,Bob"` — a click sends that conversation to two cloud models and returns text only, never sending for you). The menu also carries a row of one-click actions (who is waiting on a reply, todos, digests, stats, reading stats, sessions, Moments, WeRead), and its last item tucks the ball away; the tray icon brings it back. Running a tool **never pops up a console window**, and the window recovers by itself after the assistant restarts - you do not have to reopen it.
|
|
233
242
|
|
|
234
243
|
Then just talk to ClawBot on your phone. The assistant queries local chats and favorites to answer, with memory that survives across sessions:
|
|
235
244
|
|
|
@@ -272,7 +281,8 @@ Management: `weflow-cli assistant status` / `log` / `stop`; send "帮助" in WeC
|
|
|
272
281
|
| Initialize or specify paths | `weflow-cli init [--path <dir>]` |
|
|
273
282
|
| Browse chat data | `weflow-cli sessions` · `weflow-cli messages <contact>` · `weflow-cli contacts` |
|
|
274
283
|
| Who is waiting on a reply | `weflow-cli awaiting --dry-run` · `weflow-cli awaiting --yes` |
|
|
275
|
-
| Draft a reply (text
|
|
284
|
+
| Draft a reply (text unless you pick and send) | `weflow-cli draft <contact> --dry-run` · `--yes` (**only** `--pick N --send --yes` actually sends; both flags are required) |
|
|
285
|
+
| Relationship temperature | `weflow-cli bonds` (who is cooling, who is warming, who only has WeChat; read-only, local, no model) |
|
|
276
286
|
| Local judgement primitive | `weflow-cli decide --request <file> --dry-run` · `--yes` |
|
|
277
287
|
| Export chat history | `weflow-cli export <contact> <json\|txt\|html\|excel>` |
|
|
278
288
|
| Sync checkpoint | `weflow-cli sync run <contact> --since <date>` · `sync status` · `sync verify` |
|
|
@@ -310,6 +320,11 @@ Main Python workflows:
|
|
|
310
320
|
# Article crawling -> AI classification -> HTML reading page -> Wiki / learning digest
|
|
311
321
|
python scripts/pipeline.py --date YYYY-MM-DD --api-key "Your API Key" --engine deepseek
|
|
312
322
|
|
|
323
|
+
# Note: this does **not** write your Obsidian Vault by default (no Sources/WeChat copy, no concept pages).
|
|
324
|
+
# Obsidian's own graph view is live - it watches the vault's files and re-renders when one changes.
|
|
325
|
+
# To make the graph follow the content, ask for it explicitly (either flag works alone too):
|
|
326
|
+
python scripts/pipeline.py --date YYYY-MM-DD --api-key "Your API Key" --with-vault --with-wiki
|
|
327
|
+
|
|
313
328
|
# Run step by step
|
|
314
329
|
python scripts/biz_daily.py --date YYYY-MM-DD --api-key "Your API Key"
|
|
315
330
|
python scripts/generate_html.py --date YYYY-MM-DD
|
|
@@ -319,6 +334,7 @@ python scripts/fav_server.py --date YYYY-MM-DD
|
|
|
319
334
|
## Architecture
|
|
320
335
|
|
|
321
336
|

|
|
337
|
+
> Illustrative only: [`ARCHITECTURE.md`](./ARCHITECTURE.md) is authoritative for links, ports and authentication — this figure is model-generated, so its fine detail is not word-for-word reliable.
|
|
322
338
|
|
|
323
339
|
The project is split into five clearly bounded parts:
|
|
324
340
|
|
package/README.md
CHANGED
|
@@ -94,11 +94,14 @@ Linux 的自动初始化能力取决于微信发行版、Python 依赖和当前
|
|
|
94
94
|
| --- | --- |
|
|
95
95
|
| 聊天记录 | 查询会话、联系人和消息;导出 JSON、TXT、HTML、Excel。HTML 导出会同时给出一份媒体覆盖报告,说明哪些图片/表情没能嵌入以及原因。 |
|
|
96
96
|
| 公众号日报 | 抓取文章、AI 摘要与分类、生成本地阅读页,保留收藏和已读状态。 |
|
|
97
|
-
| 个人知识库 | 同步微信读书笔记、构建 Obsidian Vault、语义搜索、RAG 问答和概念 Wiki
|
|
97
|
+
| 个人知识库 | 同步微信读书笔记、构建 Obsidian Vault、语义搜索、RAG 问答和概念 Wiki,以及**双击就能打开**的概念图谱页面(`weflow-cli wiki graph --open` 出 3D、加 `--flat` 出 2D;自包含、不联网、不需要服务器;`--min-degree N` 只看枢纽、`--line wiki\|chat` 只看一条线)。 |
|
|
98
98
|
| AI 协作 | 通过 MCP 把文章、知识库、日报和受控的本地数据能力交给兼容客户端;工具清单以 `weflow-cli mcp-config` 和 `docs/MCP.md` 为准。 |
|
|
99
99
|
| 个人回顾 | 聊天月报、年度报告、待办提取与朋友圈本地缓存查询。 |
|
|
100
100
|
| 微信收藏 | 读取微信"收藏"内容(公众号文章、文字、图片、视频、聊天记录),支持类型过滤、关键词搜索与 Markdown/JSON 导出。 |
|
|
101
|
-
| 第二大脑 Agent | 在微信里和本地 AI
|
|
101
|
+
| 第二大脑 Agent | 在微信里和本地 AI 助手对话:自然语言查询聊天记录、收藏、朋友圈、日报、微信读书、待办与知识库;三层记忆跨会话延续,守护进程常驻后台。也能**抓一篇公众号正文**、在公开文章里搜、把 Markdown 排成公众号格式、列通讯录、读学习回顾、体检知识库与技能包、把待办标记完成(**不能删除**)。它调得到的工具与不可达的边界见 `docs/PROJECT_STATE.md` 与 `docs/DECISIONS.md`(D-058)。 |
|
|
102
|
+
| 本机面板 | 桌面常驻的悬浮球:点开即对话(与微信里**同一个大脑**、同一份记忆与配额),每条回答下面可展开**「思考过程」**(它调了什么工具、几轮、为什么停),球本身有状态表情、透明底,面板里还有一个**「记忆」**按钮:能看它对你长期记下了什么(每条带写入时间和来源原话,只读)。 |
|
|
103
|
+
| 技能包 | 助手能读你机器上已有的 `SKILL.md` 技能包(默认扫 `~/.claude/skills` 与 `~/.weflow-cli/skills`):提示词里列出有哪些,要用时读正文再照着做。**技能不给助手增加任何工具**——它只是资料,不执行、不安装、读不到配置和数据库。`weflow-cli skill check` 报出读不出来、跨目录同名和 id 不合规的技能。 |
|
|
104
|
+
| 会话场景 | 给某个会话一套固定的做法:关键词 + 附加指令 + 输出规范 + 所需技能。消息进来按「绑定 → 关键词 → 上次用过的」挑一个,都没中就完全按原来的行为。用 `weflow-cli scene` 管理,或在对话里发「场景 <id>」绑定。**场景不让模型读写**,本次用了哪个场景会记在「思考过程」里。 |
|
|
102
105
|
|
|
103
106
|
> **⚠️ 合法使用边界**:本工具仅限访问**你自己拥有并登录的微信账号**在自己设备上的数据。未经他人明确同意,不得用它监控配偶、员工或任何第三方,也不得部署到他人设备或远程静默运行。请同时留意微信服务条款、账号风控和当地法律要求。详见 [SECURITY.md](SECURITY.md)。
|
|
104
107
|
|
|
@@ -196,6 +199,14 @@ weflow-cli config set typesafeApiKey "..."
|
|
|
196
199
|
|
|
197
200
|
阅读器默认在 `http://localhost:8765/` 提供服务。
|
|
198
201
|
|
|
202
|
+
**约定版本的导出格式**
|
|
203
|
+
|
|
204
|
+
```powershell
|
|
205
|
+
weflow-cli export "联系人" json --contract weflow-v1 --output ./output
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
生成的信封里字段是稳定的,并带一份保守的 `coverage` 说明。增量读取用带重叠的 `--from` 时间窗自己按「会话 + `localId`/`serverId`」去重,或者交给 `sync` 记住检查点并报告覆盖范围。稳定游标还没对外:要等每个数据库后端都支持才敢承诺。旧的 JSON 导出仍是一个顶层数组。
|
|
209
|
+
|
|
199
210
|
**接入 AI 编辑器**
|
|
200
211
|
|
|
201
212
|
```powershell
|
|
@@ -204,7 +215,7 @@ weflow-cli mcp-config > .mcp.json
|
|
|
204
215
|
|
|
205
216
|
将生成的配置放到所用 MCP 客户端的配置位置后重启客户端即可。MCP 的工具列表与配置方式见 `weflow-cli mcp-config` 输出。
|
|
206
217
|
|
|
207
|
-
除知识库类工具外,MCP
|
|
218
|
+
除知识库类工具外,MCP 也暴露本机微信数据能力(会话、聊天记录、收藏、朋友圈、日报、微信读书、待办、知识库与助手记忆查询)。它的工具面**由助手的工具表派生**(少掉 `save_memory`、`look_at_image`、`set_todo_status` 三个),所以**不是纯只读**:写入类调用都要显式 `confirm`;而**发送消息、发布文章、改配置这三件事没有任何工具**——`weflow-cli capabilities --json` 里的 `safety.mcpDefaultReadOnly` 记着这条边界。工具清单以当前代码和 [MCP 集成指南](./docs/MCP.md) 为准,不固定写死数量。
|
|
208
219
|
|
|
209
220
|
**在微信里挂一个本地 AI 助手(第二大脑)**
|
|
210
221
|
|
|
@@ -222,7 +233,14 @@ weflow-cli panel # 打开本机面板窗口 (不扫码也能用)
|
|
|
222
233
|
悬浮球需要 Electron(`npm i -g electron`);没装的话会降级成 Edge/Chrome 的 `--app` 小窗,
|
|
223
234
|
界面一样,但没有无边框置顶、没有托盘与快捷键。有球时:**点一下它在旁边展开对话气泡
|
|
224
235
|
(球不动,再点一下收起)**;气泡默认开在球的左边,左边放不下会自己翻到右边,上方不够就
|
|
225
|
-
|
|
236
|
+
改成顶对齐;拖动球可以换位置(位置会记住)。**球是透明底的,只有吉祥物本身**——空闲时一脸
|
|
237
|
+
平静,**在你等它回答的那几秒换成"思考"的表情**(连不上、额度用完时各有各的脸)。**按住它会像被拎住后颈一样浮起来,松手落回**(十二帧硬切的动作;系统开了"减少动态效果"时不播)。**被拎着挪动时它会左右摆**——往哪边移哪边摆得更大、动得越快摆得越狠;**答复落地时它跳一下**;**平时每 7–13 秒眨一次眼**,眼睛还会跟着鼠标;拖到屏幕边会半隐起来。**鼠标从它身上划过,它会像被挠到一样扭一扭**——只有扭动、**不倾斜**(旋转只归"被拎起来"那条,2026-10-02 起)。
|
|
238
|
+
|
|
239
|
+
**每条回答下面可以展开「思考过程」(默认收起)**:里面是它这一轮怎么走的——路由判断、
|
|
240
|
+
调了哪个工具、参数摘要、往返几次、为什么结束。在微信里发「轨迹」(或「思考过程」)看的是
|
|
241
|
+
同一份记录,两处不会各说各话。
|
|
242
|
+
|
|
243
|
+
**在面板里点右键**可以给名单上的人快速起草回复(`weflow-cli config set quickReplyContacts "某人,另一人"`;点一下就是把那段对话发给两个云端模型,只产出文本、不会替你发送),菜单里还有一排一键功能(谁在等我回话 / 待办 / 日报 / 统计 / 阅读统计 / 会话 / 朋友圈 / 微信读书),最后一项能把球收起来(点托盘图标叫回来)。助手跑工具时**不会弹出黑色命令行窗口**;助手重启之后窗口也会自己恢复,不用重新打开。
|
|
226
244
|
|
|
227
245
|
之后在手机微信的 ClawBot 对话里直接说话,助手会自动查询本地聊天记录和收藏作答,并具备跨会话记忆:
|
|
228
246
|
|
|
@@ -266,7 +284,8 @@ weflow-cli config set assistantGroupRequireMention true
|
|
|
266
284
|
| 初始化或手动指定路径 | `weflow-cli init [--path <目录>]` |
|
|
267
285
|
| 浏览聊天数据 | `weflow-cli sessions` · `weflow-cli messages <联系人>` · `weflow-cli contacts` |
|
|
268
286
|
| 谁在等我回话 | `weflow-cli awaiting --dry-run` · `weflow-cli awaiting --yes` |
|
|
269
|
-
|
|
|
287
|
+
| 帮我起草回复(默认只出文字) | `weflow-cli draft <联系人> --dry-run` · `--yes`(**只有** `--pick N --send --yes` 会真的替你发出去;两步缺一不可)|
|
|
288
|
+
| 关系温度 | `weflow-cli bonds`(谁在冷却、谁在变热、谁只有微信这一条线;只读本地库,不联网、不调模型)|
|
|
270
289
|
| 本机判断层 | `weflow-cli decide --request <file> --dry-run` · `--yes` |
|
|
271
290
|
| 导出聊天记录 | `weflow-cli export <联系人> <json\|txt\|html\|excel>` |
|
|
272
291
|
| 同步检查点 | `weflow-cli sync run <联系人> --since <日期>` · `sync status` · `sync verify` |
|
|
@@ -304,6 +323,11 @@ npm run dev -- init
|
|
|
304
323
|
# 文章抓取 -> AI 分类 -> HTML 阅读页 -> Wiki / 学习日报
|
|
305
324
|
python scripts/pipeline.py --date YYYY-MM-DD --api-key "你的 API Key" --engine deepseek
|
|
306
325
|
|
|
326
|
+
# 注意:这条**默认不写 Obsidian Vault**(不拷 Sources/WeChat,也不编译概念页)。
|
|
327
|
+
# 原因:Obsidian 自带的图谱视图是**实时**的 —— 它盯着 vault 里的文件,文件一变就重画。
|
|
328
|
+
# 想让图谱跟着变,显式加上这两个开关(也可以分开用):
|
|
329
|
+
python scripts/pipeline.py --date YYYY-MM-DD --api-key "你的 API Key" --with-vault --with-wiki
|
|
330
|
+
|
|
307
331
|
# 分步运行
|
|
308
332
|
python scripts/biz_daily.py --date YYYY-MM-DD --api-key "你的 API Key"
|
|
309
333
|
python scripts/generate_html.py --date YYYY-MM-DD
|
|
@@ -313,6 +337,7 @@ python scripts/fav_server.py --date YYYY-MM-DD
|
|
|
313
337
|
## 架构
|
|
314
338
|
|
|
315
339
|

|
|
340
|
+
> 示意图:链路、端口与鉴权以 [`ARCHITECTURE.md`](./ARCHITECTURE.md) 为准 —— 这张图是生图模型画的,细节文字不逐字采信。
|
|
316
341
|
|
|
317
342
|
项目分为五个边界清晰的部分:
|
|
318
343
|
|