@tobeyoureyes/feishu 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,290 @@
1
+ # @openclaw/feishu
2
+
3
+ 飞书/Lark 企业消息平台的 OpenClaw 插件。支持私聊、群聊、消息回复、媒体处理和卡片消息渲染。
4
+
5
+ ## 概述
6
+
7
+ 此插件将飞书作为消息通道添加到 OpenClaw,使你的 AI 机器人能够:
8
+
9
+ - 接收和回复私聊消息
10
+ - 在群聊中被 @提及 后回复
11
+ - 处理图片、文件等媒体消息
12
+ - 使用卡片格式渲染代码块、表格等富文本
13
+ - 通过 WebSocket 长连接实时接收消息
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ openclaw plugins install @openclaw/feishu
19
+ ```
20
+
21
+ ## 快速开始
22
+
23
+ ### 1. 创建飞书应用
24
+
25
+ 1. 访问 [飞书开放平台](https://open.feishu.cn/app)
26
+ 2. 创建企业自建应用
27
+ 3. 获取 App ID 和 App Secret
28
+ 4. 在"事件订阅"中启用"使用长连接接收事件"
29
+ 5. 订阅 `im.message.receive_v1` 事件
30
+ 6. 发布应用版本
31
+
32
+ ### 2. 配置 OpenClaw
33
+
34
+ ```yaml
35
+ channels:
36
+ feishu:
37
+ enabled: true
38
+ appId: "cli_xxxxx"
39
+ appSecret: "your-app-secret"
40
+ # 或使用环境变量
41
+ # appId: "${FEISHU_APP_ID}"
42
+ # appSecret: "${FEISHU_APP_SECRET}"
43
+ ```
44
+
45
+ ### 3. 启动
46
+
47
+ ```bash
48
+ openclaw start
49
+ ```
50
+
51
+ ## 配置选项
52
+
53
+ ### 基础配置
54
+
55
+ | 选项 | 类型 | 默认值 | 说明 |
56
+ |------|------|--------|------|
57
+ | `enabled` | boolean | `false` | 是否启用飞书通道 |
58
+ | `appId` | string | - | 飞书应用 App ID |
59
+ | `appSecret` | string | - | 飞书应用 App Secret |
60
+ | `domain` | string | `"feishu"` | API 域名:`"feishu"` (国内) 或 `"lark"` (国际) |
61
+ | `connectionMode` | string | `"websocket"` | 连接模式:`"websocket"` (推荐) 或 `"webhook"` |
62
+
63
+ ### 访问控制
64
+
65
+ | 选项 | 类型 | 默认值 | 说明 |
66
+ |------|------|--------|------|
67
+ | `dmPolicy` | string | `"pairing"` | 私聊策略:`"pairing"` / `"allowlist"` / `"open"` / `"disabled"` |
68
+ | `allowFrom` | string[] | `[]` | 允许的发送者 ID 列表 |
69
+ | `groupPolicy` | string | `"allowlist"` | 群聊策略:`"allowlist"` / `"open"` / `"disabled"` |
70
+ | `requireMention` | boolean | `true` | 群聊是否需要 @机器人 才回复 |
71
+ | `groups` | object | `{}` | 群聊配置,如 `{ "oc_xxx": { enabled: true } }` |
72
+
73
+ ### 消息渲染
74
+
75
+ | 选项 | 类型 | 默认值 | 说明 |
76
+ |------|------|--------|------|
77
+ | `renderMode` | string | `"auto"` | 渲染模式:`"auto"` / `"raw"` / `"card"` |
78
+ | `mediaMaxMb` | number | `30` | 最大媒体文件大小 (MB) |
79
+
80
+ ### 渲染模式说明
81
+
82
+ | 模式 | 说明 |
83
+ |------|------|
84
+ | `auto` | 自动检测:有代码块、表格、链接或长文本时使用卡片,否则纯文本 |
85
+ | `raw` | 始终纯文本,表格转为 ASCII 格式 |
86
+ | `card` | 始终使用卡片,支持 Markdown 语法高亮、表格、链接等 |
87
+
88
+ ## 访问控制策略
89
+
90
+ ### 私聊策略 (dmPolicy)
91
+
92
+ | 策略 | 说明 |
93
+ |------|------|
94
+ | `pairing` | 默认。未知发送者会收到配对码,需要管理员审批 |
95
+ | `allowlist` | 只有 `allowFrom` 列表中的用户可以发消息 |
96
+ | `open` | 任何人都可以发消息(谨慎使用) |
97
+ | `disabled` | 禁用私聊 |
98
+
99
+ ### 群聊策略 (groupPolicy)
100
+
101
+ | 策略 | 说明 |
102
+ |------|------|
103
+ | `allowlist` | 默认。只有 `groups` 中配置的群可以使用机器人 |
104
+ | `open` | 所有群都可以使用机器人(需配合 `requireMention`) |
105
+ | `disabled` | 禁用群聊 |
106
+
107
+ ## 功能特性
108
+
109
+ ### 支持的消息类型
110
+
111
+ - **接收**:文本、富文本 (post)、图片、文件、音频、视频、卡片、分享
112
+ - **发送**:文本、富文本、图片、文件、卡片
113
+
114
+ ### 消息处理流程
115
+
116
+ ```
117
+ ┌─────────────────────────────────────────────────────────────┐
118
+ │ 飞书消息处理流程 │
119
+ ├─────────────────────────────────────────────────────────────┤
120
+ │ │
121
+ │ WebSocket/Webhook ──► 解析事件 ──► 消息去重 │
122
+ │ │ │ │
123
+ │ │ ▼ │
124
+ │ │ 策略检查 │
125
+ │ │ (dmPolicy/groupPolicy) │
126
+ │ │ │ │
127
+ │ │ ▼ │
128
+ │ │ @ 提及检测 │
129
+ │ │ (群聊 requireMention) │
130
+ │ │ │ │
131
+ │ │ ▼ │
132
+ │ │ 获取回复上下文 (parent_id) │
133
+ │ │ │ │
134
+ │ │ ▼ │
135
+ │ │ 构建群聊历史上下文 │
136
+ │ │ │ │
137
+ │ │ ▼ │
138
+ │ │ AI Agent 处理 │
139
+ │ │ │ │
140
+ │ │ ▼ │
141
+ │ │ 渲染模式判断 │
142
+ │ │ (auto/raw/card) │
143
+ │ │ │ │
144
+ │ │ ▼ │
145
+ │ └─────────────────────► 发送回复 │
146
+ │ │
147
+ └─────────────────────────────────────────────────────────────┘
148
+ ```
149
+
150
+ ### 群聊上下文
151
+
152
+ 当机器人被 @提及 时,会自动收集该群最近的未处理消息作为上下文,帮助 AI 理解对话背景。
153
+
154
+ ### 回复引用
155
+
156
+ 当用户回复某条消息时,机器人会自动获取被回复消息的内容作为上下文。
157
+
158
+ ### 卡片消息
159
+
160
+ 自动检测以下内容并使用卡片渲染:
161
+
162
+ - 代码块 (\`\`\`code\`\`\`)
163
+ - 表格 (|header|)
164
+ - Markdown 链接 [text](url)
165
+ - 长文本 (>500 字符)
166
+ - 多段落 (>=3 个空行)
167
+
168
+ ## 多账户配置
169
+
170
+ ```yaml
171
+ channels:
172
+ feishu:
173
+ enabled: true
174
+ # 默认账户配置
175
+ appId: "cli_default"
176
+ appSecret: "secret_default"
177
+
178
+ # 命名账户
179
+ accounts:
180
+ production:
181
+ enabled: true
182
+ appId: "cli_prod"
183
+ appSecret: "secret_prod"
184
+ dmPolicy: "allowlist"
185
+ allowFrom: ["ou_xxx", "ou_yyy"]
186
+
187
+ testing:
188
+ enabled: true
189
+ appId: "cli_test"
190
+ appSecret: "secret_test"
191
+ dmPolicy: "open"
192
+ ```
193
+
194
+ ## 环境变量
195
+
196
+ | 变量 | 说明 |
197
+ |------|------|
198
+ | `FEISHU_APP_ID` | 飞书应用 App ID |
199
+ | `FEISHU_APP_SECRET` | 飞书应用 App Secret |
200
+
201
+ ## 故障排除
202
+
203
+ ### 机器人不接收消息
204
+
205
+ 1. 确认应用已发布且已启用
206
+ 2. 检查"事件订阅"是否启用了"使用长连接接收事件"
207
+ 3. 确认已订阅 `im.message.receive_v1` 事件
208
+ 4. 检查应用权限:需要 `im:message`、`im:message:receive`
209
+
210
+ ### 群聊不回复
211
+
212
+ 1. 确认 `groupPolicy` 不是 `"disabled"`
213
+ 2. 如果 `groupPolicy` 是 `"allowlist"`,确认群 ID 在 `groups` 配置中
214
+ 3. 如果 `requireMention` 是 `true`,确认消息中 @了机器人
215
+
216
+ ### 私聊不回复
217
+
218
+ 1. 确认 `dmPolicy` 不是 `"disabled"`
219
+ 2. 如果是 `"pairing"` 模式,用户需要先完成配对审批
220
+ 3. 如果是 `"allowlist"` 模式,确认用户 ID 在 `allowFrom` 列表中
221
+
222
+ ### WebSocket 连接失败
223
+
224
+ 1. 检查网络连接
225
+ 2. 确认 App ID 和 App Secret 正确
226
+ 3. 检查应用是否已发布
227
+ 4. 查看日志中的具体错误信息
228
+
229
+ ## API 参考
230
+
231
+ ### 卡片创建函数
232
+
233
+ ```typescript
234
+ import {
235
+ createSimpleCard,
236
+ createMarkdownCard,
237
+ createCodeCard,
238
+ createTableCard,
239
+ createCardWithButtons,
240
+ createMultiSectionCard,
241
+ } from "@openclaw/feishu/api";
242
+
243
+ // 简单卡片
244
+ const card1 = createSimpleCard("标题", "Markdown 内容", "blue");
245
+
246
+ // 代码卡片
247
+ const card2 = createCodeCard("console.log('hello')", "javascript", "示例代码");
248
+
249
+ // 表格卡片
250
+ const card3 = createTableCard(
251
+ ["名称", "值"],
252
+ [["项目1", "100"], ["项目2", "200"]],
253
+ "数据表格"
254
+ );
255
+
256
+ // 按钮卡片
257
+ const card4 = createCardWithButtons(
258
+ "请选择操作",
259
+ [
260
+ { text: "确认", value: "confirm", type: "primary" },
261
+ { text: "取消", value: "cancel", type: "default" },
262
+ ],
263
+ "操作确认"
264
+ );
265
+ ```
266
+
267
+ ## 文件结构
268
+
269
+ ```
270
+ extensions/feishu/
271
+ ├── src/
272
+ │ ├── api.ts # Feishu API 封装
273
+ │ ├── auth.ts # Token 认证管理
274
+ │ ├── channel.ts # 插件主入口
275
+ │ ├── dedupe.ts # 消息去重模块
276
+ │ ├── history.ts # 群聊历史管理
277
+ │ ├── inbound.ts # 入站消息处理
278
+ │ ├── message.ts # 消息格式化工具
279
+ │ ├── runtime.ts # 运行时上下文
280
+ │ ├── types.ts # 类型定义
281
+ │ ├── webhook.ts # Webhook 事件解析
282
+ │ └── websocket.ts # WebSocket 连接管理
283
+ ├── index.ts # 模块导出
284
+ ├── package.json
285
+ └── README.md
286
+ ```
287
+
288
+ ## 许可证
289
+
290
+ MIT
package/index.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
+ import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
3
+
4
+ import { feishuPlugin } from "./src/channel.js";
5
+ import { setFeishuRuntime } from "./src/runtime.js";
6
+
7
+ const plugin = {
8
+ id: "feishu",
9
+ name: "Feishu",
10
+ description: "Feishu (Lark) channel plugin",
11
+ configSchema: emptyPluginConfigSchema(),
12
+ register(api: OpenClawPluginApi) {
13
+ setFeishuRuntime(api.runtime);
14
+ api.registerChannel({ plugin: feishuPlugin });
15
+ },
16
+ };
17
+
18
+ export default plugin;
@@ -0,0 +1,9 @@
1
+ {
2
+ "id": "feishu",
3
+ "channels": ["feishu"],
4
+ "configSchema": {
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "properties": {}
8
+ }
9
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@tobeyoureyes/feishu",
3
+ "version": "1.0.0",
4
+ "description": "OpenClaw Feishu (Lark) channel plugin",
5
+ "type": "module",
6
+ "files": [
7
+ "index.ts",
8
+ "src",
9
+ "openclaw.plugin.json"
10
+ ],
11
+ "devDependencies": {
12
+ "@larksuiteoapi/node-sdk": "^1.58.0",
13
+ "openclaw": "workspace:*"
14
+ },
15
+ "peerDependencies": {
16
+ "@larksuiteoapi/node-sdk": "^1.58.0"
17
+ },
18
+ "peerDependenciesMeta": {
19
+ "@larksuiteoapi/node-sdk": {
20
+ "optional": true
21
+ }
22
+ },
23
+ "openclaw": {
24
+ "extensions": [
25
+ "./index.ts"
26
+ ],
27
+ "channel": {
28
+ "id": "feishu",
29
+ "label": "Feishu",
30
+ "selectionLabel": "Feishu (飞书)",
31
+ "docsPath": "/channels/feishu",
32
+ "docsLabel": "feishu",
33
+ "blurb": "Feishu/Lark enterprise messaging platform",
34
+ "order": 75
35
+ },
36
+ "install": {
37
+ "npmSpec": "@tobeyoureyes/feishu",
38
+ "localPath": "extensions/feishu",
39
+ "defaultChoice": "npm"
40
+ }
41
+ }
42
+ }