🤖 Feishu: expand channel support

What:
- add post parsing, doc link extraction, routing, replies, reactions, typing, and user lookup
- fix media download/send flows and make doc fetches domain-aware
- update Feishu docs and clawtributor credits

Why:
- raise Feishu parity with other channels and avoid dropped group messages
- keep replies threaded while supporting Lark domains
- document new configuration and credit the contributor

Tests:
- pnpm build
- pnpm check
- pnpm test (gateway suite timed out; reran pnpm vitest run --config vitest.gateway.config.ts)

Co-authored-by: 九灵云 <server@jiulingyun.cn>
This commit is contained in:
Josh Palmer
2026-02-05 12:29:04 -08:00
parent eb80b9acb3
commit 4fc4c5256a
17 changed files with 1517 additions and 76 deletions

View File

@@ -447,7 +447,75 @@ openclaw pairing list feishu
### Streaming
Feishu does not support message editing, so block streaming is enabled by default (`blockStreaming: true`). The bot waits for the full reply before sending.
Feishu supports streaming replies via interactive cards. When enabled, the bot updates a card as it generates text.
```json5
{
channels: {
feishu: {
streaming: true, // enable streaming card output (default true)
blockStreaming: true, // enable block-level streaming (default true)
},
},
}
```
Set `streaming: false` to wait for the full reply before sending.
### Multi-agent routing
Use `bindings` to route Feishu DMs or groups to different agents.
```json5
{
agents: {
list: [
{ id: "main" },
{
id: "clawd-fan",
workspace: "/home/user/clawd-fan",
agentDir: "/home/user/.openclaw/agents/clawd-fan/agent",
},
{
id: "clawd-xi",
workspace: "/home/user/clawd-xi",
agentDir: "/home/user/.openclaw/agents/clawd-xi/agent",
},
],
},
bindings: [
{
agentId: "main",
match: {
channel: "feishu",
peer: { kind: "dm", id: "ou_xxx" },
},
},
{
agentId: "clawd-fan",
match: {
channel: "feishu",
peer: { kind: "dm", id: "ou_yyy" },
},
},
{
agentId: "clawd-xi",
match: {
channel: "feishu",
peer: { kind: "group", id: "oc_zzz" },
},
},
],
}
```
Routing fields:
- `match.channel`: `"feishu"`
- `match.peer.kind`: `"dm"` or `"group"`
- `match.peer.id`: user Open ID (`ou_xxx`) or group ID (`oc_xxx`)
See [Get group/user IDs](#get-groupuser-ids) for lookup tips.
---
@@ -472,7 +540,8 @@ Key options:
| `channels.feishu.groups.<chat_id>.enabled` | Enable group | `true` |
| `channels.feishu.textChunkLimit` | Message chunk size | `2000` |
| `channels.feishu.mediaMaxMb` | Media size limit | `30` |
| `channels.feishu.blockStreaming` | Disable streaming | `true` |
| `channels.feishu.streaming` | Enable streaming card output | `true` |
| `channels.feishu.blockStreaming` | Enable block streaming | `true` |
---
@@ -492,6 +561,7 @@ Key options:
### Receive
- ✅ Text
- ✅ Rich text (post)
- ✅ Images
- ✅ Files
- ✅ Audio

View File

@@ -17,6 +17,7 @@ Use these hubs to discover every page, including deep dives and reference docs t
- [Index](/)
- [Getting Started](/start/getting-started)
- [Quick start](/start/quickstart)
- [Onboarding](/start/onboarding)
- [Wizard](/start/wizard)
- [Setup](/start/setup)

View File

@@ -109,17 +109,23 @@ Lark国际版请使用 https://open.larksuite.com/app并在配置中设
"application:application.app_message_stats.overview:readonly",
"application:application:self_manage",
"application:bot.menu:write",
"cardkit:card:write",
"contact:user.employee_id:readonly",
"corehr:file:download",
"docs:document.content:read",
"event:ip_list",
"im:chat",
"im:chat.access_event.bot_p2p_chat:read",
"im:chat.members:bot_access",
"im:message",
"im:message.group_at_msg:readonly",
"im:message.group_msg",
"im:message.p2p_msg:readonly",
"im:message:readonly",
"im:message:send_as_bot",
"im:resource"
"im:resource",
"sheets:spreadsheet",
"wiki:wiki:readonly"
],
"user": ["aily:file:read", "aily:file:write", "im:chat.access_event.bot_p2p_chat:read"]
}
@@ -453,7 +459,116 @@ openclaw pairing list feishu
### 流式输出
飞书目前不支持消息编辑,因此默认禁用流式输出(`blockStreaming: true`)。机器人会等待完整回复后一次性发送。
飞书支持通过交互式卡片实现流式输出,机器人会实时更新卡片内容显示生成进度。默认配置:
```json5
{
channels: {
feishu: {
streaming: true, // 启用流式卡片输出(默认 true
blockStreaming: true, // 启用块级流式(默认 true
},
},
}
```
如需禁用流式输出(等待完整回复后一次性发送),可设置 `streaming: false`。
### 消息引用
在群聊中,机器人的回复可以引用用户发送的原始消息,让对话上下文更加清晰。
配置选项:
```json5
{
channels: {
feishu: {
// 账户级别配置(默认 "all"
replyToMode: "all",
groups: {
oc_xxx: {
// 特定群组可以覆盖
replyToMode: "first",
},
},
},
},
}
```
`replyToMode` 值说明:
| 值 | 行为 |
| --------- | ---------------------------------- |
| `"off"` | 不引用原消息(私聊默认值) |
| `"first"` | 仅在第一条回复时引用原消息 |
| `"all"` | 所有回复都引用原消息(群聊默认值) |
> 注意:消息引用功能与流式卡片输出(`streaming: true`)不能同时使用。当启用流式输出时,回复会以卡片形式呈现,不会显示引用。
### 多 Agent 路由
通过 `bindings` 配置,您可以用一个飞书机器人对接多个不同功能或性格的 Agent。系统会根据用户 ID 或群组 ID 自动将对话分发到对应的 Agent。
配置示例:
```json5
{
agents: {
list: [
{ id: "main" },
{
id: "clawd-fan",
workspace: "/home/user/clawd-fan",
agentDir: "/home/user/.openclaw/agents/clawd-fan/agent",
},
{
id: "clawd-xi",
workspace: "/home/user/clawd-xi",
agentDir: "/home/user/.openclaw/agents/clawd-xi/agent",
},
],
},
bindings: [
{
// 用户 A 的私聊 → main agent
agentId: "main",
match: {
channel: "feishu",
peer: { kind: "dm", id: "ou_28b31a88..." },
},
},
{
// 用户 B 的私聊 → clawd-fan agent
agentId: "clawd-fan",
match: {
channel: "feishu",
peer: { kind: "dm", id: "ou_0fe6b1c9..." },
},
},
{
// 某个群组 → clawd-xi agent
agentId: "clawd-xi",
match: {
channel: "feishu",
peer: { kind: "group", id: "oc_xxx..." },
},
},
],
}
```
匹配规则说明:
| 字段 | 说明 |
| ----------------- | --------------------------------------------- |
| `agentId` | 目标 Agent 的 ID需要在 `agents.list` 中定义 |
| `match.channel` | 渠道类型,这里固定为 `"feishu"` |
| `match.peer.kind` | 对话类型:`"dm"`(私聊)或 `"group"`(群组) |
| `match.peer.id` | 用户 Open ID`ou_xxx`)或群组 ID`oc_xxx` |
> 获取 ID 的方法:参见上文 [获取群组/用户 ID](#获取群组用户-id) 章节。
---
@@ -478,7 +593,8 @@ openclaw pairing list feishu
| `channels.feishu.groups.<chat_id>.enabled` | 是否启用该群组 | `true` |
| `channels.feishu.textChunkLimit` | 消息分块大小 | `2000` |
| `channels.feishu.mediaMaxMb` | 媒体大小限制 | `30` |
| `channels.feishu.blockStreaming` | 用流式输出 | `true` |
| `channels.feishu.streaming` | 用流式卡片输出 | `true` |
| `channels.feishu.blockStreaming` | 启用块级流式 | `true` |
---