一条通道一张令牌,机器人把消息 POST 到 /integrations/clawbot/{token},
正文按前缀落到任务或知识草稿:没有前缀就是任务,「知识:」「笔记:」记成知识,
「帮助」只回用法。首行当标题、其余当正文,`#标签` 摘出来挂到事项上。
同一个 msg_id 只处理一次——微信会重推,重推不能变成两条任务。
为什么不塞进 system_setting 的 JSON:一个工作区可能挂多个通道,还得能单独停用。
令牌库里只存 sha256,只在创建/重新生成时显示一次;收消息时还不知道是哪个工作区,
所以 bot_channel 的 RLS 额外放行 token_hash = current_setting('app.bot_token_hash'),
读到通道再 bind_tenant 进上下文,按通道创建者记账。
- 后端:models_integrations.py(bot_channel / bot_message)、迁移 0012(RLS)、
api/integrations.py(收消息 + 管理接口)、错误码 9002/9003
- Web:/w/:wsId/integrations「接入」页——建通道、复制回调地址与令牌、最近消息、
停用/换令牌/删除,只有 owner/admin 能改
- 测试:test_clawbot.py 10 例;web/e2e/integrations.mjs 7 项(冒充 clawbot 真推一条)
验证:pytest 150 passed,ruff check/format 全绿,tsc 0,vite build 通过,e2e 7 项全绿。
This commit is contained in:
@@ -739,3 +739,60 @@
|
||||
- 新增 `web/e2e/session-refresh.mjs`(6 项):access 换成假串但 refresh 是真的 → 不被踢、首页正常、
|
||||
拿到新令牌、新令牌能调接口;access 与 refresh 都假 → 才回登录页;控制台零异常。
|
||||
- 安卓 `assembleDebug` 通过(JDK 17 + Gradle 8.9)。
|
||||
|
||||
## 13. 微信接入(clawbot,2026-11-05)
|
||||
|
||||
### 13.1 要解决的问题
|
||||
|
||||
记事的动作发生在手机上,而任务和知识都在浏览器里。人正在外面、手上只有微信的时候,
|
||||
"回去再记"通常等于"再也想不起来"。所以要有一条从微信直接落到工作区里的路。
|
||||
|
||||
### 13.2 决定
|
||||
|
||||
1. **一条通道一张令牌,令牌在 URL 里**。机器人不会登我们的账号;它只会照着配置好的地址
|
||||
POST。令牌是 32 字节随机串,库里只存 `sha256`,页面上"创建/重新生成"时显示一次。
|
||||
2. **一个工作区可以有多个通道**,各自能单独停用。塞进 `system_setting` 的 JSON 里就做不到
|
||||
"停这个、留那个"。
|
||||
3. **收消息用宽松解析**。clawbot 的消息壳子没有公开的固定 schema,与其猜错就 422,
|
||||
不如按常见字段名依次摸一遍,摸不到正文就记一条 `ignored` 留痕。
|
||||
4. **同一 `msg_id` 只处理一次**。微信会重推,重推变成第二条任务是最难解释的脏数据。
|
||||
5. **每条消息都留痕**(`bot_message`,含原始 JSON、处理结果、 reply)。
|
||||
出问题时能直接回答"那条任务到底进没进"。
|
||||
|
||||
### 13.3 后端
|
||||
|
||||
| 位置 | 内容 |
|
||||
|---|---|
|
||||
| `backend/app/models_integrations.py` | `BotChannel`(令牌哈希、状态、最后收信时间)、`BotMessage`(文本、动作、item_id、reply、原始 JSON) |
|
||||
| `backend/alembic/versions/0012_bot_channel.py` | 建两张表 + RLS;`bot_channel` 策略额外放行 `token_hash = current_setting('app.bot_token_hash')` |
|
||||
| `backend/app/api/integrations.py` | 收消息 `GET/POST /integrations/clawbot/{token}`;管理接口 `/workspaces/{ws}/integrations` |
|
||||
| `backend/app/errors.py` | `9002` 令牌无效、`9003` 通道停用 |
|
||||
|
||||
正文解析:首行是标题(180 字封顶),其余是正文;`#标签` 摘出来挂事项上(纯数字不算);
|
||||
前缀 `知识:`/`笔记:` → 知识草稿,`任务:`/`todo:` → 任务,没有前缀就是任务。
|
||||
|
||||
### 13.4 Web
|
||||
|
||||
新增 `/w/:wsId/integrations`「接入」页(左侧栏最后一项):
|
||||
|
||||
- 「怎么用」三步说明;
|
||||
- 「新建通道」→ 一次性展示**回调地址 + 令牌**,各带复制按钮(clawbot 后台要粘的就是这里);
|
||||
- 每条通道:状态、最后收信时间、`最近消息`(最近 5 条,带"建了任务/建了知识"标签)、
|
||||
停用/启用、重新生成令牌、删除;
|
||||
- 只有 owner/admin 看得到写操作。
|
||||
|
||||

|
||||
|
||||
### 13.5 验证
|
||||
|
||||
- `backend/tests/test_clawbot.py` 10 例:纯文本成任务、`知识:`前缀成草稿并带标签、
|
||||
`帮助`只回复不建事项、错令牌 404/9002、停用通道 403/9003、同 `msg_id` 幂等、
|
||||
GET `echostr` 原样回、令牌只属于一个工作区、换令牌后旧地址失效、普通成员不能建通道。
|
||||
- `web/e2e/integrations.mjs` 7 项(真跑):页面建通道 → 取回调地址 → 冒充 clawbot POST →
|
||||
任务出现在任务列表 → 重复推送不建第二条 → 「最近消息」看得到 → 控制台零报错。
|
||||
|
||||
### 13.6 还没做
|
||||
|
||||
- 只做了"进"(收消息建事项),没做"出"(改完任务回一条微信通知)。
|
||||
- 消息不认人:机器人只知道"这是这个工作区的消息",按通道创建者记账;要认人得先做微信身份绑定。
|
||||
- 语音、图片、文件只留痕不处理。
|
||||
|
||||
Reference in New Issue
Block a user