logo
0
0
WeChat Login
wangzhenpu<wangzhenpu@accesscorporate.com.cn>
feat: implement channel control plane foundation

channel-plane

独立的通讯平面项目,用于统一接入外部渠道,并将任务路由给:

  • doops.sh
  • dowork

当前已经落地的最小可运行能力:

  • Spring Boot 3 + WebFlux 项目骨架
  • H2 内存库初始化
  • 统一任务创建入口
  • 通用 webhook 入口
  • 飞书 webhook 专用入口
  • 钉钉 webhook 专用入口
  • 钉钉 webhook / stream 模式切换
  • 任务路由器
  • DoopsAdapter / DoworkAdapter 统一适配器接口
  • 任务、入站消息、绑定关系、outbox 的基础落库
  • outbox 定时派发器
  • 飞书 / 钉钉 webhook 文本消息回传
  • 用户与渠道账号绑定
  • 后端回调驱动的任务状态回传
  • 任务停止 / 中断 / 状态刷新
  • 任务执行轨迹落库
  • 最小前端管理页

运行要求

  • Java 17+
  • Maven 3.8+

本地编译

在当前环境下建议使用本地已缓存依赖离线编译:

mvn -o -Dmaven.repo.local=$HOME/.m2/repository -DskipTests compile

配置方式

默认配置文件已经改成环境变量占位符,真实地址与密钥建议通过环境变量或本地覆盖文件注入。

仓库里额外提供了一份本地模板:

  • src/main/resources/application-local.yml.example

推荐做法:

  1. 复制为 application-local.yml
  2. 填入真实的 doops / dowork / 飞书 / 钉钉 配置
  3. 启动时附带 --spring.profiles.active=local

启动

mvn -o -Dmaven.repo.local=$HOME/.m2/repository spring-boot:run

默认端口:

  • 18088

前端入口:

  • http://127.0.0.1:18088/

当前接口

OpenAPI 提交任务

POST /api/v1/channel/api/submit

示例:

curl -X POST http://127.0.0.1:18088/api/v1/channel/api/submit \ -H 'Content-Type: application/json' \ -d '{ "tenantId": "tenant-a", "conversationId": "conv-001", "senderId": "user-001", "content": "请帮我查看 k8s deployment 日志" }'

通用 webhook 入口

POST /api/v1/channel/{source}/webhook

例如:

  • /api/v1/channel/feishu/webhook
  • /api/v1/channel/dingtalk/webhook

飞书 webhook 专用入口

POST /api/v1/channel/feishu/webhook

支持:

  • challenge 校验请求
  • 常见飞书消息事件结构标准化

钉钉 webhook 专用入口

POST /api/v1/channel/dingtalk/webhook

支持:

  • challenge 校验请求
  • 常见钉钉机器人消息结构标准化
  • 仅在 channel-plane.ingress.dingtalk.mode=webhook 时启用

查询任务详情

GET /api/v1/tasks/{taskId}

查询任务列表

GET /api/v1/tasks

可选参数:

  • tenantId

查询任务执行轨迹

GET /api/v1/tasks/{taskId}/events

刷新任务后端状态

POST /api/v1/tasks/{taskId}/refresh

中断任务

POST /api/v1/tasks/{taskId}/interrupt

停止任务

POST /api/v1/tasks/{taskId}/stop

手动触发 outbox 派发

POST /api/v1/outbox/dispatch

后端任务状态回调

POST /api/v1/backend/{backendType}/tasks/{taskId}/callbacks

示例:

curl -X POST http://127.0.0.1:18088/api/v1/backend/doops/tasks/task_xxx/callbacks \ -H 'Content-Type: application/json' \ -d '{ "status": "RUNNING", "currentStep": "collecting logs", "summary": "正在采集 deployment 与 pod 日志" }'

用户管理

POST /api/v1/users

POST /api/v1/users/{userId}/bindings

GET /api/v1/users?tenantId=default

GET /api/v1/users/{userId}

当前路由规则

  • 命中运维关键词:路由到 doops
  • 其他任务:默认路由到 dowork

当前后端适配器模式

当前两个后端适配器默认使用:

  • stub-mode = true

也就是:

  • 不直接访问真实 doops.sh
  • 不直接访问真实 dowork
  • 先返回模拟的 backendRefbackendSessionRef

后续接真实后端时,只需要:

  1. 关闭 stub-mode
  2. 配置对应 base-url
  3. 按需要调整 submit-path
  4. 如果后端需要鉴权,补 auth-headerauth-token
  5. 后端按 callbackUrl 回调任务状态

当前真实对接方式

doops.sh

channel-plane 已按 doops-agent 的真实协议接入:

  • 协议:WebSocket JSON-RPC
  • 默认路径:/ws
  • 默认鉴权头:X-Doops-Key
  • 调用工具:doops_agent_prompt
  • session_id 默认使用 taskId

适配策略:

  • channel-plane 先受理任务并立即返回
  • 后台异步连接 doops-agent
  • 流式接收 notifications/message
  • 将进度和最终结果通过内部 callback 回写任务状态

dowork

channel-plane 已按 dowork-agent 的真实接口接入:

  • 协议:HTTP REST
  • 默认路径:/api/lab/instances/standalone
  • 启动路径:/api/lab/instances/{id}/start
  • 请求中的 user_id 使用通讯平面解析出的本地用户 ID

适配策略:

  • 先创建 opencode 实例
  • 再异步触发 start
  • 启动成功后回写 RUNNING
  • 启动失败后回写 FAILED
  • 支持实例状态查询
  • 支持停止实例
  • 中断统一映射为停止实例

同时会把以下上下文透传到实例环境变量:

  • CHANNEL_TASK_ID
  • CHANNEL_TASK_TITLE
  • CHANNEL_TASK_CONTENT
  • CHANNEL_INITIATOR_USER_ID
  • CHANNEL_INITIATOR_DISPLAY_NAME
  • CHANNEL_CALLBACK_URL

当前消息回传能力

目前 channel-plane 已经支持:

  • 飞书消息接入
  • 钉钉消息接入
  • 任务受理后写入 outbox
  • 后端任务状态回调
  • 定时将受理结果回传到飞书 / 钉钉
  • 自动把飞书 / 钉钉来信人解析或沉淀为本地用户

默认仍然是 stub-mode = true,因此本地调试不会真的往外发消息。

如果要接真实机器人 webhook,可以在 application.yml 中配置:

channel-plane: egress: feishu: stub-mode: false webhook-url: https://open.feishu.cn/open-apis/bot/v2/hook/xxx secret: your-feishu-secret dingtalk: stub-mode: false webhook-url: https://oapi.dingtalk.com/robot/send?access_token=xxx secret: your-dingtalk-secret

配置完成后,任务受理消息会自动通过 outbox 派发出去。

钉钉 Stream 配置

如果要改成钉钉 Stream 通道,在 application.yml 中配置:

channel-plane: ingress: dingtalk: mode: stream stream: client-id: your-client-id client-secret: your-client-secret consume-threads: 2

如果仍然走 webhook:

channel-plane: ingress: dingtalk: mode: webhook

两种模式共用同一套消息标准化和任务提交流程。

最小管理台

首页管理台已支持:

  • 查看用户列表
  • 查看用户与飞书 / 钉钉绑定
  • 查看任务列表与任务详情
  • 查看任务执行轨迹
  • 对任务执行刷新状态 / 中断 / 停止

用户追溯模型

现在每个任务会保存:

  • initiatorUserId
  • initiatorDisplayName
  • sourceUserId
  • sourceUserName

如果渠道消息的发送人还没有绑定到本地用户,系统会自动创建一个用户并建立绑定关系,这样任务从第一天开始就是可追溯的。

手工绑定示例:

curl -X POST http://127.0.0.1:18088/api/v1/users \ -H 'Content-Type: application/json' \ -d '{ "tenantId": "tenant-a", "displayName": "张三", "email": "zhangsan@example.com" }'
curl -X POST http://127.0.0.1:18088/api/v1/users/usr_xxx/bindings \ -H 'Content-Type: application/json' \ -d '{ "tenantId": "tenant-a", "sourceType": "FEISHU", "channelAccountId": "feishu-default", "externalUserId": "ou_001", "externalDisplayName": "张三" }'

入站校验与真实回调

飞书支持:

  • 可选 verification-token 校验
  • 请求时间戳窗口校验

钉钉支持:

  • 可选 verification-token 校验
  • 可选 timestamp + sign + secret 校验

后端回调支持:

  • 可选 auth-header + auth-token 鉴权
  • 回调地址由平台自动下发到后端任务请求中

推荐配置示例

channel-plane: backends: callback: base-url: http://channel-plane.xxx.svc.cluster.local:18088 auth-header: X-Callback-Token auth-token: your-callback-token doops: stub-mode: false base-url: http://doops-agent.example.internal:42222 submit-path: /ws auth-header: X-Doops-Key auth-token: your-doops-password dowork: stub-mode: false base-url: http://dowork-gateway.example.internal:8080 submit-path: /api/lab/instances/standalone auth-header: Authorization auth-token: Bearer your-token

用户适配边界

当前判断很明确:

  • doops.sh 没有完整业务用户模型,通讯平面负责补齐用户归属和渠道绑定
  • doworkuser_id / session ownership,但仍不是统一企业用户中心

因此统一策略是:

  • 用户身份以 channel-plane 为准
  • 飞书 / 钉钉账号先映射为本地用户
  • 下发到 doops.sh 时透传为任务上下文
  • 下发到 dowork 时直接适配为它的 user_id

About

No description, topics, or website provided.
Language
Java91.3%
JavaScript4.7%
CSS2.4%
HTML1.7%