feat(integrations): 微信里发一句话,变成一条任务或知识
CI / backend (push) Canceled after 0s

一条通道一张令牌,机器人把消息 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:
Steven
2026-11-05 22:04:34 +08:00
parent 33a3fc03e0
commit 90b99f8253
16 changed files with 1606 additions and 4 deletions
+12 -1
View File
@@ -16,7 +16,16 @@ from starlette.responses import Response
from starlette.staticfiles import StaticFiles
from starlette.types import Scope
from .api import app_release, attachments, auth, items, knowledge, tickets, workspaces
from .api import (
app_release,
attachments,
auth,
integrations,
items,
knowledge,
tickets,
workspaces,
)
from .api import settings as settings_api
from .config import get_settings
from .db import SessionFactory, current_app_role, engine
@@ -118,6 +127,8 @@ app.include_router(knowledge.router, prefix=settings.api_prefix)
app.include_router(attachments.router, prefix=settings.api_prefix)
app.include_router(app_release.router, prefix=settings.api_prefix)
app.include_router(settings_api.router, prefix=settings.api_prefix)
app.include_router(integrations.admin_router, prefix=settings.api_prefix)
app.include_router(integrations.webhook_router, prefix=settings.api_prefix)
@app.get("/health", tags=["运维"], summary="存活探针")