eve-lark 0.4.5 → 0.5.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 +17 -16
- package/README.zh-CN.md +17 -13
- package/dist/index.js +209 -107
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,15 +30,11 @@ A [Lark](https://www.larksuite.com) / [Feishu](https://www.feishu.cn) channel fo
|
|
|
30
30
|
### Out of scope (v1)
|
|
31
31
|
|
|
32
32
|
These are intentionally **not** shipped — file an issue if you need them:
|
|
33
|
-
-
|
|
33
|
+
- Non-text inbound beyond image / file / audio: sticker / share_chat / share_user / interactive cards (ack-and-skip). Audio inbound is transcribed when an `asrProvider` is configured; without one it is also ack-and-skip.
|
|
34
34
|
- Multi-account configuration
|
|
35
35
|
- Per-user OAuth (`user_access_token` device flow)
|
|
36
36
|
- Feishu API tools (docs / bitable / calendar / tasks / drive)
|
|
37
|
-
|
|
38
|
-
> Card action buttons from ask_question ARE shipped (0.3.0+). The remaining
|
|
39
|
-
> "card action buttons" gap in the list below refers to fully custom card
|
|
40
|
-
> schemas authored by the agent itself.
|
|
41
|
-
- Card action buttons (no interactive form handling)
|
|
37
|
+
- Fully custom agent-authored card schemas (interactive forms beyond `ask_question` buttons, which shipped in 0.3.0+)
|
|
42
38
|
|
|
43
39
|
## Quick start
|
|
44
40
|
|
|
@@ -75,7 +71,7 @@ In the [Feishu developer console](https://open.feishu.cn/app):
|
|
|
75
71
|
4. Subscribe to `im.message.receive_v1`.
|
|
76
72
|
5. Add the bot to a chat or DM it directly.
|
|
77
73
|
|
|
78
|
-
|
|
74
|
+
Both transport modes work in production; the right one depends on your deployment topology. See [Production deploy](#production-deploy).
|
|
79
75
|
|
|
80
76
|
## Configuration reference
|
|
81
77
|
|
|
@@ -92,7 +88,7 @@ All fields can be supplied as options or read from the matching env var (options
|
|
|
92
88
|
| `mode` | `"long-connection" \| "webhook"` | no | `"long-connection"` | `LARK_MODE` |
|
|
93
89
|
| `port` | `number` | no | `$PORT` or `2000` | `PORT` |
|
|
94
90
|
| `webhookPath` | `string` | no | `/lark/webhook` | — |
|
|
95
|
-
| `replyMode` | `"post" \| "streaming" \| "streaming-v2" \| "static"` | no | `"
|
|
91
|
+
| `replyMode` | `"post" \| "streaming" \| "streaming-v2" \| "static"` | no | `"streaming-v2"` | `LARK_REPLY_MODE` |
|
|
96
92
|
| `streamPatchIntervalMs` | `number` | no | `1000` | — |
|
|
97
93
|
| `streamCreateThresholdMs` | `number` | no | `400` | — |
|
|
98
94
|
| `dedupTtlMs` | `number` | no | `1_800_000` (30 min) | — |
|
|
@@ -119,15 +115,15 @@ Or via env: `LARK_BASE_URL=https://open.larksuite.com`.
|
|
|
119
115
|
|
|
120
116
|
## Reply modes
|
|
121
117
|
|
|
122
|
-
- **`
|
|
123
|
-
- **`streaming`**:
|
|
124
|
-
- **`
|
|
118
|
+
- **`streaming-v2`** (default): the channel creates an interactive card on the first delta and live-patches it through Feishu's CardKit v2 (`schema: "2.0"` + `streaming_mode`). Best live UX this channel ships. Card text renders smaller than native chat messages — Feishu treats cards as "structured content".
|
|
119
|
+
- **`streaming`**: same live-patch UX as `streaming-v2` but on the older v1 card schema. Slightly smaller font than v2. Opt in only if you have a specific reason to avoid CardKit v2.
|
|
120
|
+
- **`post`**: the channel waits for `message.completed` and delivers the reply as a `msg_type: "post"` rich-text message. **Renders at native chat-message size** with full markdown support (bold, links, code, `<font>` color tags). No live streaming — the user sees the reply only when the turn completes.
|
|
125
121
|
- **`static`**: same wait-for-completion delivery as `post`, but uses an interactive card instead of a post. Useful if you need card features (buttons, multi-column layout) and don't mind the smaller text.
|
|
126
122
|
|
|
127
123
|
Tune the streaming throttle with `streamPatchIntervalMs` (lower = smoother, more API calls).
|
|
128
124
|
|
|
129
125
|
```bash
|
|
130
|
-
LARK_REPLY_MODE=
|
|
126
|
+
LARK_REPLY_MODE=post # opt into native-size markdown replies (no streaming)
|
|
131
127
|
```
|
|
132
128
|
|
|
133
129
|
## Continuation tokens & threading
|
|
@@ -209,24 +205,29 @@ See [`examples/README.md`](./examples/README.md) for a complete walkthrough. The
|
|
|
209
205
|
|
|
210
206
|
## Production deploy
|
|
211
207
|
|
|
212
|
-
|
|
208
|
+
Both transport modes are supported in production — pick the one that fits your deployment topology.
|
|
209
|
+
|
|
210
|
+
- **`long-connection`** (default, WebSocket): the channel opens an outbound WS to Feishu, so **no public URL is needed**. Best fit for single-instance deployments (one container, one process). The WSClient singleton guard only dedupes within a single process — running N replicas means N independent WebSockets with every event delivered to all of them, so this mode does **not** work behind a multi-replica load balancer.
|
|
211
|
+
- **`webhook`** (HTTP callback): Feishu POSTs events to your public `/lark/webhook`. The load balancer routes each event to one replica, so it **scales horizontally**. Requires a publicly reachable URL.
|
|
212
|
+
|
|
213
|
+
To opt into webhook:
|
|
213
214
|
|
|
214
215
|
```ts
|
|
215
216
|
// agent/channels/lark.ts
|
|
216
217
|
export default createLarkChannel({
|
|
217
218
|
// ... credentials ...
|
|
218
|
-
mode: "webhook",
|
|
219
|
+
mode: "webhook",
|
|
219
220
|
});
|
|
220
221
|
```
|
|
221
222
|
|
|
222
|
-
In the Feishu console,
|
|
223
|
+
In the Feishu console, set **Event Subscription** to **HTTP callback**, URL = your deployed agent's `/lark/webhook`. Then:
|
|
223
224
|
|
|
224
225
|
```bash
|
|
225
226
|
eve build
|
|
226
227
|
eve deploy # or: eve start on a server with a public URL
|
|
227
228
|
```
|
|
228
229
|
|
|
229
|
-
Everything else (signing, AES,
|
|
230
|
+
Everything else (signing, AES, streaming, ask_question) works the same in both modes. Dedup is in-process either way — see the [Serverless caveat](#security-model) for the multi-instance implication.
|
|
230
231
|
|
|
231
232
|
Test layout:
|
|
232
233
|
|
package/README.zh-CN.md
CHANGED
|
@@ -31,13 +31,11 @@
|
|
|
31
31
|
### 不在 v1 范围内
|
|
32
32
|
|
|
33
33
|
以下功能**未实现**——需要的话请提 issue:
|
|
34
|
-
-
|
|
34
|
+
- 图片 / 文件 / 音频以外的非文本入站:sticker / share_chat / share_user / 交互卡片(ack-and-skip)。音频入站在配置了 `asrProvider` 时会转写;没配置则同样是 ack-and-skip。
|
|
35
35
|
- 多账号配置
|
|
36
36
|
- 用户级 OAuth(`user_access_token` device flow)
|
|
37
37
|
- 飞书 API 工具(docs / bitable / calendar / tasks / drive)
|
|
38
|
-
|
|
39
|
-
> `ask_question` 的卡片按钮**已实现**(0.3.0+)。下面列表中剩下的「Card action buttons」指的是 agent 自己生成的完全自定义的卡片 schema。
|
|
40
|
-
- Card action buttons(agent 自定义的交互表单)
|
|
38
|
+
- agent 自渲染的完全自定义卡片 schema(交互表单——`ask_question` 的卡片按钮已在 0.3.0+ 发出,这里指的是超出这个范围的)
|
|
41
39
|
|
|
42
40
|
## 快速开始
|
|
43
41
|
|
|
@@ -74,7 +72,7 @@ eve dev
|
|
|
74
72
|
4. 订阅 `im.message.receive_v1`。
|
|
75
73
|
5. 把 bot 拉进群或直接私聊。
|
|
76
74
|
|
|
77
|
-
|
|
75
|
+
两种传输模式在生产环境都可以用,选哪个取决于你的部署拓扑。详见[生产部署](#生产部署)。
|
|
78
76
|
|
|
79
77
|
## 配置参考
|
|
80
78
|
|
|
@@ -91,7 +89,7 @@ eve dev
|
|
|
91
89
|
| `mode` | `"long-connection" \| "webhook"` | 否 | `"long-connection"` | `LARK_MODE` |
|
|
92
90
|
| `port` | `number` | 否 | `$PORT` 或 `2000` | `PORT` |
|
|
93
91
|
| `webhookPath` | `string` | 否 | `/lark/webhook` | — |
|
|
94
|
-
| `replyMode` | `"post" \| "streaming" \| "static"` | 否 | `"
|
|
92
|
+
| `replyMode` | `"post" \| "streaming" \| "streaming-v2" \| "static"` | 否 | `"streaming-v2"` | `LARK_REPLY_MODE` |
|
|
95
93
|
| `streamPatchIntervalMs` | `number` | 否 | `1000` | — |
|
|
96
94
|
| `streamCreateThresholdMs` | `number` | 否 | `400` | — |
|
|
97
95
|
| `dedupTtlMs` | `number` | 否 | `1_800_000`(30 分钟) | — |
|
|
@@ -118,14 +116,15 @@ createLarkChannel({
|
|
|
118
116
|
|
|
119
117
|
## 回复模式
|
|
120
118
|
|
|
121
|
-
- **`
|
|
122
|
-
- **`streaming
|
|
119
|
+
- **`streaming-v2`**(默认):channel 在第一个 delta 时创建交互卡片,通过飞书 CardKit v2(`schema: "2.0"` + `streaming_mode`)实时 patch。**是这个 channel 能提供的最好的实时 UX**。卡片文字比原生消息字号小(飞书把卡片当作「结构化内容」)。
|
|
120
|
+
- **`streaming`**:和 `streaming-v2` 一样的实时 patch UX,但走老的 v1 卡片 schema,字号比 v2 略小。仅在你有特定原因想避开 CardKit v2 时才选。
|
|
121
|
+
- **`post`**:channel 等 `message.completed`,把回复作为 `msg_type: "post"` 富文本消息发出。**渲染为原生聊天消息大小**,完整支持 markdown(粗体、链接、代码、`<font>` 颜色 tag)。代价:不能流式——用户在 turn 完成时才看到回复。
|
|
123
122
|
- **`static`**:和 `post` 一样等完成再发,但用交互卡片而非 post。适合需要卡片特性(按钮、多列布局)且不在乎字号小的场景。
|
|
124
123
|
|
|
125
124
|
流式节流通过 `streamPatchIntervalMs` 调整(值越小越平滑,但 API 调用越多)。
|
|
126
125
|
|
|
127
126
|
```bash
|
|
128
|
-
LARK_REPLY_MODE=
|
|
127
|
+
LARK_REPLY_MODE=post # 切到原生字号 + markdown(无流式)
|
|
129
128
|
```
|
|
130
129
|
|
|
131
130
|
## Continuation token 与线程
|
|
@@ -208,24 +207,29 @@ pnpm build # tsup build → dist/
|
|
|
208
207
|
|
|
209
208
|
## 生产部署
|
|
210
209
|
|
|
211
|
-
|
|
210
|
+
两种传输模式在生产环境都支持——根据你的部署拓扑选择。
|
|
211
|
+
|
|
212
|
+
- **`long-connection`**(默认,WebSocket):channel 主动向飞书发起出站 WS 连接,**不需要公网 URL**。适合单实例部署(一个容器、一个进程)。WSClient 单例守卫只在单个进程内去重——跑 N 个副本就会有 N 条独立的 WebSocket,每个事件被投递到所有副本,所以这个模式**不**适用于多副本负载均衡场景。
|
|
213
|
+
- **`webhook`**(HTTP 回调):飞书把事件 POST 到你部署的 agent 的公网 `/lark/webhook`。负载均衡把每个事件路由到一个副本,**可以水平扩展**。需要有公网可达的 URL。
|
|
214
|
+
|
|
215
|
+
切到 webhook:
|
|
212
216
|
|
|
213
217
|
```ts
|
|
214
218
|
// agent/channels/lark.ts
|
|
215
219
|
export default createLarkChannel({
|
|
216
220
|
// ... 凭据 ...
|
|
217
|
-
mode: "webhook",
|
|
221
|
+
mode: "webhook",
|
|
218
222
|
});
|
|
219
223
|
```
|
|
220
224
|
|
|
221
|
-
|
|
225
|
+
在飞书后台,把**事件订阅**设为 **HTTP 回调**,URL 设为你部署的 agent 的 `/lark/webhook`。然后:
|
|
222
226
|
|
|
223
227
|
```bash
|
|
224
228
|
eve build
|
|
225
229
|
eve deploy # 或:在有公网 URL 的服务器上跑 eve start
|
|
226
230
|
```
|
|
227
231
|
|
|
228
|
-
其他逻辑(签名、AES
|
|
232
|
+
其他逻辑(签名、AES、流式、ask_question)在两种模式下都一样。去重在两种模式下都是进程内的——多实例场景的影响见[安全模型](#安全模型)里的 serverless 说明。
|
|
229
233
|
|
|
230
234
|
测试目录:
|
|
231
235
|
|