openbird 2.4.0 → 3.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 +63 -22
- package/dist/bin/openbird.js +1 -1
- package/dist/index.js +11 -7
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
# OpenBird
|
|
2
2
|
|
|
3
|
-
飞书(Lark)非官方基础设施服务,运行在本地,通过浏览器 cookie
|
|
3
|
+
飞书(Lark)非官方基础设施服务,运行在本地,通过浏览器 cookie 连接飞书,提供两个显式运行模式:
|
|
4
4
|
|
|
5
|
-
1. **
|
|
6
|
-
2. **MCP
|
|
7
|
-
|
|
8
|
-
```
|
|
9
|
-
飞书 WebSocket ──> OpenBird ──> Webhook URL(你的代码)
|
|
10
|
-
│
|
|
11
|
-
MCP stdio ──> AI Agent
|
|
12
|
-
```
|
|
5
|
+
1. **Relay 模式** — 连接飞书 WebSocket,将消息标准化后 POST 到你提供的 webhook 地址
|
|
6
|
+
2. **MCP 模式** — 通过 stdio 暴露多个飞书 API 工具,供 AI Agent 调用
|
|
13
7
|
|
|
14
8
|
## 快速开始
|
|
15
9
|
|
|
@@ -24,41 +18,50 @@ cp .env.example .env
|
|
|
24
18
|
# 编辑 .env,粘贴你从浏览器 DevTools 复制的飞书 cookie
|
|
25
19
|
```
|
|
26
20
|
|
|
27
|
-
###
|
|
21
|
+
### MCP 模式
|
|
28
22
|
|
|
29
23
|
```bash
|
|
30
|
-
OPENBIRD_COOKIE="your_cookie_here" node bin/openbird.js
|
|
24
|
+
OPENBIRD_COOKIE="your_cookie_here" node bin/openbird.js mcp
|
|
31
25
|
```
|
|
32
26
|
|
|
33
27
|
仅启动 MCP Server(stdio),不连接 WebSocket,不转发事件。
|
|
34
28
|
|
|
35
|
-
###
|
|
29
|
+
### Relay 模式
|
|
36
30
|
|
|
37
31
|
```bash
|
|
38
32
|
OPENBIRD_COOKIE="your_cookie_here" \
|
|
39
|
-
|
|
40
|
-
node bin/openbird.js
|
|
33
|
+
node bin/openbird.js relay http://localhost:3000/webhook
|
|
41
34
|
```
|
|
42
35
|
|
|
43
|
-
连接飞书 WebSocket
|
|
36
|
+
连接飞书 WebSocket 并将所有事件转发到你提供的 webhook 地址。
|
|
44
37
|
|
|
45
38
|
### 运行示例
|
|
46
39
|
|
|
47
40
|
```bash
|
|
48
|
-
# 在一个进程里同时启动 webhook 接收端和 MCP 客户端
|
|
49
41
|
node examples/basic-usage.mjs
|
|
50
42
|
```
|
|
51
43
|
|
|
44
|
+
该示例以 MCP 模式启动 OpenBird,并演示如何通过 stdio 连接 MCP 客户端。
|
|
45
|
+
|
|
52
46
|
## 配置
|
|
53
47
|
|
|
54
48
|
| 环境变量 | 必填 | 说明 |
|
|
55
49
|
|---|---|---|
|
|
56
50
|
| `OPENBIRD_COOKIE` | 是 | 飞书浏览器 cookie 字符串 |
|
|
57
|
-
| `OPENBIRD_WEBHOOK_URL` | 否 | 接收事件的 webhook 地址,不设置则为纯 MCP 模式 |
|
|
58
51
|
| `OPENBIRD_DEBUG` | 否 | 设为 `true` 开启调试日志 |
|
|
52
|
+
| `OPENBIRD_ENRICH` | 否 | Relay 模式下设为 `false` 可关闭事件富化 |
|
|
59
53
|
|
|
60
54
|
支持 `.env` 文件配置。
|
|
61
55
|
|
|
56
|
+
### 迁移说明
|
|
57
|
+
|
|
58
|
+
旧版本通过 `OPENBIRD_WEBHOOK_URL` 是否存在来隐式决定是否同时启动 webhook 转发。现在改为显式命令:
|
|
59
|
+
|
|
60
|
+
- `node bin/openbird.js mcp`
|
|
61
|
+
- `node bin/openbird.js relay <webhook-url>`
|
|
62
|
+
|
|
63
|
+
Relay 模式不再自动启动 MCP server。
|
|
64
|
+
|
|
62
65
|
## Webhook 事件
|
|
63
66
|
|
|
64
67
|
OpenBird 将飞书 WebSocket 消息标准化为稳定的事件格式:
|
|
@@ -87,6 +90,34 @@ OpenBird 将飞书 WebSocket 消息标准化为稳定的事件格式:
|
|
|
87
90
|
}
|
|
88
91
|
```
|
|
89
92
|
|
|
93
|
+
`im.thread.reply_count_v1` 示例:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"type": "im.thread.reply_count_v1",
|
|
98
|
+
"event_id": "evt_123",
|
|
99
|
+
"timestamp": 1712023530000,
|
|
100
|
+
"semantic": {
|
|
101
|
+
"entity": "thread",
|
|
102
|
+
"action": "activity_detected",
|
|
103
|
+
"kind": "state_signal",
|
|
104
|
+
"consumable": false,
|
|
105
|
+
"requires_hydration": "fetch_thread_messages",
|
|
106
|
+
"dedupe_key": "thread:thread_1:reply_count:12",
|
|
107
|
+
"dedupe_strategy": "drop_exact_match",
|
|
108
|
+
"routing_hints": ["thread", "activity"]
|
|
109
|
+
},
|
|
110
|
+
"data": {
|
|
111
|
+
"chatId": "chat_1",
|
|
112
|
+
"threadId": "thread_1",
|
|
113
|
+
"replyCount": 12,
|
|
114
|
+
"updateTime": 1712023530000
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
当前仅 `im.thread.reply_count_v1` 会携带 `semantic` 字段。其他 webhook 事件仍保持现有结构。
|
|
120
|
+
|
|
90
121
|
### 事件类型
|
|
91
122
|
|
|
92
123
|
| 类型 | 说明 |
|
|
@@ -154,6 +185,13 @@ createServer({
|
|
|
154
185
|
})
|
|
155
186
|
```
|
|
156
187
|
|
|
188
|
+
然后用 Relay 模式启动 OpenBird:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
OPENBIRD_COOKIE="your_cookie_here" \
|
|
192
|
+
node bin/openbird.js relay http://localhost:3000/webhook
|
|
193
|
+
```
|
|
194
|
+
|
|
157
195
|
## MCP 工具
|
|
158
196
|
|
|
159
197
|
通过 [Model Context Protocol](https://modelcontextprotocol.io/) 提供多个工具(stdio 通信)。
|
|
@@ -252,7 +290,7 @@ createServer({
|
|
|
252
290
|
### 使用 MCP Inspector 测试
|
|
253
291
|
|
|
254
292
|
```bash
|
|
255
|
-
npx @modelcontextprotocol/inspector node bin/openbird.js
|
|
293
|
+
npx @modelcontextprotocol/inspector node bin/openbird.js mcp
|
|
256
294
|
```
|
|
257
295
|
|
|
258
296
|
## 项目结构
|
|
@@ -261,7 +299,7 @@ npx @modelcontextprotocol/inspector node bin/openbird.js
|
|
|
261
299
|
openbird/
|
|
262
300
|
├── bin/openbird.js # CLI 入口
|
|
263
301
|
├── src/
|
|
264
|
-
│ ├── index.js #
|
|
302
|
+
│ ├── index.js # 模式分发与共享启动逻辑
|
|
265
303
|
│ ├── logger.js # 日志(全部写 stderr,stdout 留给 MCP)
|
|
266
304
|
│ ├── core/ # 飞书协议实现
|
|
267
305
|
│ │ ├── api.js # HTTP API 客户端(34 个方法)
|
|
@@ -276,7 +314,7 @@ openbird/
|
|
|
276
314
|
│ └── mcp/
|
|
277
315
|
│ └── server.js # MCP Server(多个工具)
|
|
278
316
|
├── examples/
|
|
279
|
-
│ └── basic-usage.mjs #
|
|
317
|
+
│ └── basic-usage.mjs # MCP 示例
|
|
280
318
|
└── docs/
|
|
281
319
|
└── plans/ # 设计文档
|
|
282
320
|
```
|
|
@@ -296,8 +334,11 @@ pnpm test:coverage
|
|
|
296
334
|
# 修改 proto.proto 后重新生成代码
|
|
297
335
|
pnpm generate:proto
|
|
298
336
|
|
|
299
|
-
# 启动
|
|
300
|
-
node bin/openbird.js
|
|
337
|
+
# 启动 MCP 模式
|
|
338
|
+
node bin/openbird.js mcp
|
|
339
|
+
|
|
340
|
+
# 启动 Relay 模式
|
|
341
|
+
node bin/openbird.js relay http://localhost:3000/webhook
|
|
301
342
|
```
|
|
302
343
|
|
|
303
344
|
### 测试
|
package/dist/bin/openbird.js
CHANGED
|
@@ -3,4 +3,4 @@ console.log=(...a)=>process.stderr.write(a.join(" ")+"\n");
|
|
|
3
3
|
console.warn=(...a)=>process.stderr.write(a.join(" ")+"\n");
|
|
4
4
|
console.error=(...a)=>process.stderr.write(a.join(" ")+"\n");
|
|
5
5
|
import{main}from"../index.js";
|
|
6
|
-
main().catch(e=>{process.stderr.write("[openbird] Fatal: "+e.message+"\n");e.stack&&process.stderr.write(e.stack+"\n");process.exit(1)});
|
|
6
|
+
main(process.argv.slice(2)).then(c=>{if(c&&c!==0)process.exit(c)}).catch(e=>{process.stderr.write("[openbird] Fatal: "+e.message+"\n");e.stack&&process.stderr.write(e.stack+"\n");process.exit(1)});
|