Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions bot/docs/CHANNEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,9 @@ vikingbot gateway
- 访问 [飞书开放平台](https://open.feishu.cn/app)
- 创建新应用 → 启用 **机器人** 功能
- **权限**:添加 `im:message`(发送消息)
- **事件**:添加 `im.message.receive_v1`(接收消息)
- **事件**:至少添加以下事件
- `im.message.receive_v1`(接收消息)
- `im.message.reaction.created_v1`(接收用户对 bot 回复的点赞/点踩等表情反馈)
- 选择 **长连接** 模式(需要先运行 vikingbot 来建立连接)
- 从「凭证与基础信息」获取 **App ID** 和 **App Secret**
- 发布应用
Expand Down Expand Up @@ -227,6 +229,7 @@ vikingbot gateway
> `allowFrom`:留空以允许所有用户,或添加 `["ou_xxx"]` 以限制访问。
> `botName`:用于在传给模型的群聊上下文中把 `@<open_id>` 提及替换为机器人名称,以及标注机器人自身发出的消息;留空则回退为 `"Bot"`。
> `threadRequireMention`:群聊是否需要 `@` 机器人才响应。默认 `true` —— 普通群和话题群的所有消息都需要 `@`;设为 `false` 时,普通群无需 `@`,话题群仅首条消息无需 `@`,非 `DEBUG` 模式下后续回复仍需 `@`。
> 如果你希望把飞书里的“赞/踩”表情统计进 `openviking_feedback_*` 指标,必须在飞书开放平台额外打开 `im.message.reaction.created_v1` 事件订阅;只开 `im.message.receive_v1` 时,聊天可正常工作,但表情反馈不会回调到 bot。

**3. 运行**

Expand Down Expand Up @@ -415,4 +418,4 @@ vikingbot gateway
vikingbot gateway
```

</details>
</details>
Original file line number Diff line number Diff line change
Expand Up @@ -328,17 +328,120 @@ bot gateway 侧预期返回 HTTP 404,OpenViking Server 当前会包一层统

---

## 6. 排查建议
## 6. Feishu Channel 真实测试案例

### 6.1 `/bot/v1/health` 不通
除了 OpenAPI `/chat -> /feedback` 闭环外,当前工作树还补充了 Feishu channel 的 reaction feedback 定向测试,用于验证“用户对 bot 回复点表情”这条链路能够稳定落到现有 `response_id -> feedback_events -> response_outcome` 体系。

### 6.1 测试目标

Feishu channel 的测试重点不是再次验证 OpenAPI,而是验证以下两段桥是否打通:

1. bot 发出的 Feishu 消息是否能建立 `platform_message_id -> response_id` 映射
2. 飞书 reaction callback 是否能把点赞/点踩正确翻译为现有 feedback 事件

当前测试约束如下:

1. 只处理 bot 自己回复上的 reaction
2. 只识别点赞/点踩类 reaction,其他表情忽略
3. 同一用户对同一回复重复点同类表情会去重
4. 同一用户先赞后踩或先踩后赞,以最后一次为准
5. 反馈事件仍然是 analytics-only,不应泄漏到用户可见 channel

### 6.2 真实 SDK payload 的关键差异

本轮对已安装的 `lark_oapi` 源码做了确认,真实 reaction callback model 为:

```python
lark_oapi.api.im.v1.model.p2_im_message_reaction_created_v1.P2ImMessageReactionCreatedV1
```

其核心字段为:

1. `event.message_id`
2. `event.reaction_type.emoji_type`
3. `event.operator_type`
4. `event.user_id.open_id` / `event.user_id.user_id` / `event.user_id.union_id`

与此前根据猜测构造的 payload 相比,真实 SDK event 有两个必须记录的差异:

1. 真实 event 默认不带 `chat_id` / `chat_type` / `root_id`
2. `user_id` 是对象,而不是纯字符串

因此当前 Feishu channel 的实现包含一条真实兼容兜底路径:

1. 如果 callback 自带 `chat_id/chat_type/root_id`,优先按 thread/group session key 查找
2. 如果 callback 不带这些上下文,则退回按 `message_id` 扫描当前 Feishu channel 已落盘 session metadata,回查 `response_id`

### 6.3 当前已覆盖的测试案例

测试文件:

```text
bot/tests/test_feishu_feedback.py
```

当前已覆盖 10 个案例:

1. `test_feishu_store_response_message_mapping_persists_lookup_fields`
验证发送成功后,`platform_message_id` 会同时写入 session metadata、`response_facts` 以及 assistant message。
2. `test_feishu_submit_reaction_feedback_emits_feedback_and_outcome`
验证正常 reaction 会写入 `feedback_events`,并发布 `FEEDBACK_SUBMITTED` 与 `RESPONSE_OUTCOME_EVALUATED`。
3. `test_feishu_submit_reaction_feedback_dedupes_same_reaction`
验证同一用户重复点同类表情会去重。
4. `test_feishu_submit_reaction_feedback_overwrites_previous_reaction`
验证同一用户正负反馈切换时,以最后一次为准。
5. `test_feishu_candidate_session_keys_prioritize_thread_session`
验证 group thread 场景优先查找 `chat_id#root_id`,再回退到 group session。
6. `test_feishu_reaction_event_accepts_dict_payload_shape`
验证兼容 dict 形态 payload,适合作为早期手工构造 callback 的兜底。
7. `test_feishu_reaction_event_accepts_object_payload_shape`
验证兼容对象嵌套 payload。
8. `test_feishu_reaction_event_ignores_non_user_or_unknown_reactions`
验证非用户 operator 与非点赞/点踩 reaction 会被忽略。
9. `test_feishu_reaction_event_accepts_real_sdk_payload_without_chat_context`
验证真实 `P2ImMessageReactionCreatedV1` payload 在缺少 `chat_id/chat_type/root_id` 时,仍能通过 `message_id` 回查 session,并正确提取 `user_id.open_id`。
10. `test_feishu_reaction_event_real_sdk_payload_dedupes_by_open_id`
验证真实 SDK payload 下,重复点赞会按 `open_id` 去重,而不是错误地把 `user_id` 对象当作新用户。

### 6.4 推荐执行命令

当前仓库统一使用 `uv` 环境执行 Feishu 相关测试:

```bash
uv sync --extra test --extra bot --extra bot-feishu
uv run pytest -o addopts='' bot/tests/test_feishu_feedback.py
uv run pytest -o addopts='' bot/tests/test_agent_loop_outcome.py
```

预期结果:

1. `bot/tests/test_feishu_feedback.py` 通过
2. `bot/tests/test_agent_loop_outcome.py` 通过
3. 不出现 reaction feedback 对现有 outcome 规则的回归破坏

### 6.5 当前验证口径

截至当前工作树,Feishu channel 的 reaction feedback 可以按以下口径描述:

1. 飞书点赞/点踩已经接入现有 `response_id` feedback 体系
2. 真实 SDK reaction callback 的字段差异已被代码和测试覆盖
3. 当前仅处理 reaction created,不处理 reaction deleted
4. 当前通过 session metadata 中的 `platform_message_id -> response_id` 映射完成回查
5. 当前 outcome 仍复用现有最小规则版 `evaluate_response_outcome`,不引入新的独立评价体系

---

## 7. 排查建议

### 7.1 `/bot/v1/health` 不通

优先检查:

1. 是否确实使用了 `openviking-server --with-bot`
2. 服务端口是否与 `ov.conf` 中的 `server.port` 一致
3. `18790` 是否被旧的 vikingbot 进程占用

### 6.2 `/chat` 失败但 `/health` 正常
### 7.2 `/chat` 失败但 `/health` 正常

优先检查 bot 日志文件,例如:

Expand All @@ -355,13 +458,13 @@ Unknown config field 'ovcli.url44'

这类问题会阻塞真实 agent 处理,但不代表 `/feedback` 的接口实现本身有问题。

### 6.3 `/chat` 成功但 `/feedback` 直接返回框架 404
### 7.3 `/chat` 成功但 `/feedback` 直接返回框架 404

优先检查 OpenViking Server 代理层是否真的暴露了 `/bot/v1/feedback`。

如果日志里根本没有 bot gateway 收到 `POST /bot/v1/feedback`,而 HTTP 返回是通用 404,则通常不是 bot gateway 本身的问题,而是 server proxy 没有转发该路由。

### 6.4 `/feedback` 命中 bot gateway 但仍返回 `Response not found`
### 7.4 `/feedback` 命中 bot gateway 但仍返回 `Response not found`

优先检查:

Expand All @@ -371,7 +474,7 @@ Unknown config field 'ovcli.url44'

---

## 7. 结论口径
## 8. 结论口径

截至当前,Phase 2 应使用如下口径描述:

Expand Down
Loading
Loading