跨机文件获取:从微信随口说到文件到手
开发日志 · 2026-09-11 · 苑广山
一、这个功能解决什么问题
作为个人开发者,最痛苦的场景之一:人在外面,手机微信上突然想看电脑上的某个文件——一段代码、一个配置、一份刚改完的文档。传统做法是打开电脑远程桌面、SSH、或者让别人帮忙找。全部反人类。
我们要的是:在微信里说一句"把最近改的那个 py 发我",3 秒后文件就到手里。
这个功能今天落地了。它不是简单的"发文件"——它是一套跨机文件获取系统,让 weclaw 能从你所有电脑上按需拉取文件,自动包装格式,直投微信。
二、架构设计:三层管道
用户(微信) weclaw(u 机) wxwatcher(各机器)
│ │ │
│ "把最近改的 py 发我" │ │
├───────────────────→│ │
│ │ 意图解析 (gemini) │
│ │ file_get + 参数提取 │
│ │ │
│ │ HTTP GET /api/recent │
│ ├───────────────────────→│ Mac:9120
│ │ │ u:9120
│ │←───── 文件列表 ─────────│
│ │ │
│ │ HTTP GET /api/file │
│ ├───────────────────────→│ 取最新文件
│ │←───── 文件内容 ─────────│
│ │ │
│ │ 包装为 .md(代码高亮) │
│ │ 或打 .zip(目录) │
│ │ │
│ 📄 calc.py.md │ SendMediaFromPath │
│←───────────────────┤ (CDN 加密上传) │
│ │ │
核心理念:wxwatcher 是眼睛,weclaw 是大脑,微信是手。
- wxwatcher(Python,每台机器一个实例):本来只做文件变更监控+推送通知。我们给它加了文件 API(
/api/file+/api/recent),变成了一个轻量文件服务器。 - weclaw(Go,u 机):收到用户的自然语言请求后,通过意图路由解析出检索参数,调用 wxwatcher API 拉文件,包装格式,发到微信。
- 用户:全程只跟微信交互,不感知底层的跨机通信。
三、实现细节
3.1 wxwatcher 文件 API(Python)
wxwatcher 本身是一个轮询式文件监控服务。我们在它的进程里嵌入了一个后台 HTTP 服务器线程(http.server.HTTPServer + daemon thread),暴露三个端点:
| 端点 | 功能 | 参数 |
|---|---|---|
GET /api/file?path=... |
读文件内容 | path: 绝对路径 |
GET /api/recent?dir=...&ext=...&minutes=... |
最近修改文件列表 | dir, ext, minutes, limit |
GET /api/health |
健康检查 | 无 |
认证复用现有的 push_token(Bearer header)。文件大小限制 5MB。端口通过 WXWATCHER_FILE_API_PORT 环境变量或 --file-api-port CLI 参数配置。
关键设计决策:
- 嵌入而非独立部署:文件 API 和监控服务共用一个进程,共享 token 配置,运维零额外成本。
- daemon thread:HTTP 服务器在后台线程运行,不阻塞主监控循环。
- 安全边界:只提供读取能力(无写入/删除),token 认证,大小限制。
3.2 weclaw 文件客户端(Go)
messaging/file_client.go 实现了 MachineFileClient,封装了对 wxwatcher API 的 HTTP 调用:
type MachineFileClient struct {
MachineURL string // wxwatcher 地址
Token string // Bearer token
HTTPClient *http.Client
}
支持 GetFile(读内容)、GetRecent(最近文件)、DownloadFile(下载到本地临时路径)。多机配置通过 config.json 的 machines 字段管理:
{
"machines": {
"mac": {"url": "http://192.168.31.100:9120", "token": "xxx"},
"u": {"url": "http://127.0.0.1:9120", "token": "xxx"}
}
}
3.3 /get 命令(微信侧)
用户在微信里输入 /get 前缀的命令,走 weclaw 的命令分发管道:
| 命令 | 行为 |
|---|---|
/get ~/code/calc.py |
获取本地文件,代码自动包装为 .md |
/get /Users/ygs/project/src |
目录打 zip 发送 |
/get recent 5 md |
跨所有机器检索最近 5 分钟修改的 md 文件 |
格式智能决策:safeNativeExts(.md/.txt/.pdf/.png 等)直接发原件;其他扩展名(.py/.js/.go/.sh 等)自动包装为带语法高亮围栏的 .md,头部附加源路径、修改时间、文件大小元数据。
3.4 自然语言意图路由
在 gemini 意图路由器中新增 file_get 意图。用户说"把最近改的 py 发我",gemini 提取结构化参数:
{
"intent": "file_get",
"file_query": {"ext": ".py", "minutes": 5}
}
weclaw 的 executeIntentDecision 收到后调用 FindBestMatch,跨所有配置的机器检索,取最新修改的一个,自动包装发送。
3.5 安全考量
- 只读:文件 API 只暴露读取能力,无写入/删除/执行。
- 认证:Bearer token 与推送 token 相同,已有保护。
- 大小限制:单文件 5MB 上限,目录 zip 无硬限但跳过 .git/node_modules 等大目录。
- 路径无沙箱:因为是单人使用的个人助理,不设路径白名单(信任用户自己的输入)。多用户场景需加。
- 临时文件清理:包装/下载的临时文件在发送后立即
os.Remove。
四、wxwatcher v1.16.0 发布
文件 API 作为 wxwatcher v1.16.0 的核心特性已发布到 GitHub(github.com/yuanguangshan/wxwatcher)。
部署状态:
| 机器 | 端口 | hostname | 状态 |
|---|---|---|---|
| Mac mini (192.168.31.100) | 9120 | YGS-Mac-mini-2 | ✅ |
| Ubuntu R86S (u 机) | 9120 | Ubuntu-R86S | ✅ |
升级路径:pipx 安装的旧版无法直接使用文件 API(缺少 CLI 参数和模块入口)。解决方案:
- Mac 改为从源码运行(PYTHONPATH +
python3 -m wxwatcher) - 创建
__main__.py支持模块化执行 - launchd plist 更新为源码路径
五、对用户的意义
5.1 从"找文件"到"说文件"
以前要从电脑获取文件,你需要:
- 记住文件在哪台机器
- 记住完整路径
- 打开终端 SSH 过去
- scp 或者 cat 出来
- 手动转格式(如果后缀被微信拦截)
现在:
- 在微信里说"把最近改的那个 py 发我"
认知负担从 5 步降到 1 步,且不需要记住任何路径。
5.2 多机透明
配置了 machines 后,/get recent 会跨所有机器检索。你不需要知道文件在哪台机器上——说"最近改的 md",weclaw 自动从 Mac 和 u 上找最新的那个发给你。
5.3 格式零摩擦
代码文件自动包装为带语法高亮的 .md(微信原生支持渲染),目录自动打 zip。用户完全不感知格式转换。
5.4 与文件监控的闭环
wxwatcher 本来就在推文件变更通知。现在形成完整闭环:
- 文件变更 → wxwatcher 推通知到微信
- 用户看到通知 → 回一句"改了什么"或"发我看看"
- weclaw 通过
lastNotifiedFile缓存定位文件 → git diff 分析 → 投递
从"被动收到通知"到"主动追问+获取",信息消费的主动权回到用户手里。
六、后续规划
| 阶段 | 内容 | 状态 |
|---|---|---|
| Phase 1 | /get 命令 + md 包装 + zip 打包 |
✅ 已完成 |
| Phase 2 | 意图路由 file_get + 自然语言检索 |
✅ 已完成 |
| Phase 3 | wxwatcher 文件 API + 多机部署 | ✅ 已完成 |
| Phase 4 | "改了什么"追问 + git diff 分析 | 待做 |
| Phase 5 | 文件内容缓存(避免重复下载) | 待做 |
本文基于 2026-09-11 的实际开发过程撰写,代码已合入 weclaw main 分支(79631d1 + 29478cc)和 wxwatcher v1.16.0(5735882)。