Files

10 KiB

name, description, version, tags
name description version tags
wecom-file-receive 通过企业微信接收文件并对接现有工作流(合同审查、文件处理等)。企微群里文件无法同时@人,需要用户引用文件消息后@小Maggie触发。 1.0.0
企业微信
文件接收
workflow

企业微信文件接收与处理

触发条件

  • 用户在企微群里发送文件后,引用该文件消息并@小Maggie
  • 收到的消息中包含文档附件(saved at路径)

文件接收机制

用户操作方式

  1. 用户在企微群里直接发送文件(此时无法同时@人,小Maggie收不到)
  2. 用户回复那条文件消息并@小Maggie(如"@小Maggie 审查这个合同")
  3. 网关从引用消息(quote)中提取文件的url和aeskey,下载并AES解密后保存到本地

文件保存位置

  • 自动保存到 ~/.hermes/cache/documents/ 目录
  • 文件名格式:doc_<hash>_<原始文件名>
  • 消息中会显示 The file is saved at: <完整路径>

支持的文件类型

  • 文档:.docx, .doc, .pdf, .xlsx, .xls
  • 图片:.jpg, .png, .gif, .webp
  • 其他:任意文件类型均可接收

收到文件后的通知规则

群里收到的文件

同一个群里回复确认收到,列出文件名和发送人。

私信收到的文件

不要主动往群里推送通知。 在私信里回复确认收到即可。如需通知群里的人,等群里有新的@消息时顺便汇报,或私信相关人员。

⚠️ 为什么不主动推群消息(铁律)

企微 AI Bot 不能用 APP_CMD_SEND 主动发群消息,Hermes 底层会复用旧的 inbound req_id 通过 APP_CMD_RESPONSE 发送。这种"拿过期会话凭证推送非用户发起的消息"的行为有风险:

  • 可能触发企微服务端风控/限流
  • 短时间频繁重启后叠加此行为,曾导致部分用户的群@消息不再被推送(2026-06-08事件)
  • sender 解析可能变成 "unknown",发出不专业的消息
  • 2026-06-09 Doro明确指令:"不要往群里发消息,已经触发风险机制了"

auto_notify_new_file.sh 守护进程也遵守此规则——只走 notify_doro(私信),不调 notify_group。详见 uwf skill。

⚠️ get_sender() 发件人检测不可靠

auto_notify_new_file.sh 中的 get_sender() 函数查 sessions 表最近5分钟的最后一个 session 的 user_id,经常误判(如邱律师的文件被识别为WeiWei)。准确确认发件人的方法是查 messages 表:

SELECT s.user_id, m.content FROM messages m
JOIN sessions s ON m.session_id = s.id
WHERE m.content LIKE '%sent a document%文件名关键词%'
ORDER BY m.timestamp DESC LIMIT 3

通知方式选择

  • 群里收到的文件 → 在同一个群里回复通知(这是正常的回复,有 reply_req_id)
  • 私信收到的文件私信 Doro 通知,不要主动往群里推。原因:AI Bot 不能 APP_CMD_SEND 主动发群消息,Hermes 靠复用旧 req_id 的 APP_CMD_RESPONSE 发送——旧 req_id 可能已过期,且频繁对过期 req_id 发消息可能被企微风控

邱律师(QiuTing)的合同:收到就开干

邱律师私信发的合同文件(.docx/.doc/.pdf),收到后不问处理方式,直接执行全流程

  1. 私信回复邱律师确认收到文件
  2. 上传Nextcloud待审查目录
  3. 启动review-contract workflow(setsid后台运行)
  4. workflow全链路自动跑完(含final_review)
  5. 小Maggie作为总负责人做终审质检——发现问题自己修,确认无误才通知Doro
  6. 终审通过→更新合同审查清单.xlsx→上传Nextcloud→私信Doro(简洁格式:任务交付/【修】xxx.docx

⚠️ 总负责人原则(Doro 2026-06-08确立):Doro看到的必须是终审确认无误的。workflow的final_review只是机器检查,真正的终审是小Maggie的判断。

⚠️ 全程走Doro私信通知,不发群消息。

其他人的文件:通知后等指示

Doro、洪总等其他人发的文件,私信Doro汇报后等Doro指示再处理

通知方法(私信Doro): 使用 send_message(target='wecom:doro', message='...') 即可。

处理流程

场景一:合同审查

用户发文件并说"审查这个合同"时:

  1. 从消息中获取文件保存路径
  2. 将文件复制到 Nextcloud 待审查目录:
    docker cp <本地文件> nextcloud-nextcloud-1:/var/www/html/data/doro/files/Doro合同审查任务/待审查/<原始文件名>
    docker exec nextcloud-nextcloud-1 chown www-data:www-data <目标路径>
    docker exec -u www-data nextcloud-nextcloud-1 php occ files:scan doro --path='/doro/files/Doro合同审查任务/待审查/'
    
  3. 按现有合同审查workflow执行(加载contract-reviewer + contract-editor skill)
  4. 完成后交付到任务交付目录

场景二:文件提取/处理

用户发文件并要求提取内容、翻译、格式转换等:

  1. 从消息中获取文件保存路径
  2. 直接在本地处理(读取docx/pdf内容、提取表格等)
  3. 按用户指示输出结果(生成新文件、上传到指定目录等)

场景三:文件转存

用户发文件并要求存到某个目录:

  1. 从消息中获取文件保存路径
  2. docker cp 到 Nextcloud 指定目录
  3. chown + occ files:scan 同步

文件不在cache——检查Nextcloud直传

当用户说"我上传了XX文件"但 ~/.hermes/cache/documents/ 里没有时,文件可能是通过Nextcloud网页/客户端直接上传的(不经过企微)。

排查步骤

  1. 先扫描Nextcloud刷新文件索引:
    sudo docker exec nextcloud-nextcloud-1 php occ files:scan doro --path="/doro/files/<预期目录>"
    
  2. 按文件名关键词搜索整个Doro目录树:
    sudo docker exec nextcloud-nextcloud-1 bash -c 'find /var/www/html/data/doro/files/ -name "*关键词*"'
    
  3. 检查 .part 文件——Nextcloud分块上传的临时文件:
    sudo docker exec nextcloud-nextcloud-1 bash -c 'find /var/www/html/data/doro/files/ -name "*.part"'
    
    • 文件名格式:<hash>.ocTransferId<number>.part
    • .part 文件存在 = 上传正在进行中
    • 大小在增长 = 还在传,等它完成
    • .part 消失且没有新文件出现 = 上传失败/取消,通知用户重新上传

⚠️ 注意事项

  • .part 文件不会被 occ files:scan 发现(Nextcloud不索引临时文件),必须用 find 直接查文件系统
  • 大文件上传可能很慢(通过Nextcloud网页上传取决于用户网速),不要过早判断失败
  • 上传失败时.part文件会被Nextcloud自动清理,不留痕迹
  • 确认上传失败后,告知用户"文件上传似乎中断了,请重新上传"

文件名处理

  • cache中的文件名经过URL编码,需要解码还原原始文件名
  • 上传到Nextcloud时使用原始文件名(从消息中提取)
  • 遵循文件命名规则skill(file-naming-convention)

注意事项

  1. 企微群文件限制:文件消息无法同时@人,必须通过引用回复触发
  2. URL有效期:企微文件下载URL有效期约5分钟,网关收到后立即下载,不存在过期问题
  3. AES加密:企微文件传输经过AES加密,网关自动解密(已修复base64 padding问题)
  4. 图片也支持:图片同样通过引用回复方式接收,保存到cache/images/目录

审计:统计某天某人发了多少文件

当Doro问"邱律师昨天发了多少合同"时,不能靠Nextcloud文件时间戳或cache/documents/时间戳。原因:

  • Nextcloud待审查目录的文件是小Maggie上传的,时间是上传时间不是接收时间
  • 有些文件是更早期的积压件(如班组慰问品、夏阳代建在6月5日就在Nextcloud了)
  • cache/documents/文件可能已被清理

方法1:查Nextcloud数据库(最可靠)

直接查MariaDB获取精确的存入时间和操作人。详见 references/nextcloud-db-queries.md

# 查文件存入时间
docker exec nextcloud-db-1 mariadb -u nextcloud -p'Nc2026Db!Szw' nextcloud \
  -e "SELECT fileid, path, FROM_UNIXTIME(storage_mtime) as stored_utc FROM oc_filecache WHERE path LIKE '%关键词%';"

# 查是谁上传的(仅限通过Nextcloud UI上传的文件)
docker exec nextcloud-db-1 mariadb -u nextcloud -p'Nc2026Db!Szw' nextcloud \
  -e "SELECT FROM_UNIXTIME(timestamp) as time_utc, user, subject, file FROM oc_activity WHERE file LIKE '%关键词%';"

⚠️ docker cp + occ files:scan 上传的文件不会产生 oc_activity 记录。无记录=自动流程上传。

方法2:查gateway日志中的接收确认记录

# 北京时间6月8日 = UTC Jun 7 16:00 ~ Jun 8 16:00
journalctl --user -u hermes-gateway \
  --since "2026-06-07 16:00:00" --until "2026-06-08 16:00:00" \
  | grep "收到邱律师私信发来\|邱律师好.*文件已收到"

每条匹配 = 一次文件接收。注意:

  • 同一份合同可能发了多次(如复达合同发了2次),要区分"文件发送次数"和"不同合同数"
  • 时区转换:服务器UTC,Doro问的是北京时间,必须先转换再查
  • 不要把上传/审查/交付时间当成接收时间

教训(2026-06-09)

Doro问"邱律师昨天发了多少合同",小Maggie第一次回答5份(基于Nextcloud文件时间戳),被Doro纠正。查gateway日志后确认是6次文件发送、5份不同合同。

Gateway断开期间的文件恢复

问题:企微WebSocket断开期间,私信文件消息收不到。 症状journalctl --user -u hermes-gateway | grep "WeCom.*websocket.*closed"

恢复方法

  1. 重启gateway:systemctl --user restart hermes-gateway
  2. WebSocket重连后,企微服务端通常会重新推送断开期间的消息(但不100%可靠)
  3. 重启后检查cache/documents/是否有新文件到达
  4. 如果文件没补回来,检查Nextcloud待审查目录是否已有同名文件(可能之前session已上传)
  5. 都没有→私信邱律师:"合同X的文件未收到,请重新发送"

预防:cron每15分钟检查WebSocket健康,发现断开及时重启,缩短丢消息窗口。

needs_clarification处理(问邱律师,不问Doro)

当classifier无法判断顾问单位(如甲方信息空白)返回needs_clarification时:

  1. 私信邱律师询问:"合同X甲方信息空白,请确认甲方单位"
  2. 不问Doro——Doro是最终确认人,不应被拉进执行环节
  3. 邱律师回复后,带补充信息创建新thread重新跑
  4. 同时跳过该合同,继续处理其他排队的合同