Metadata-Version: 2.5
Name: feishu-chat-bridge
Version: 0.1.0
Summary: 极简飞书聊天桥:长连接收消息,交给你的 chat_backend 生成回复,再发回飞书
Project-URL: Homepage, https://github.com/jwker/feishu-chat-bridge
Project-URL: Repository, https://github.com/jwker/feishu-chat-bridge
Author: jwker
License-Expression: MIT
License-File: LICENSE
Keywords: agent,bot,bridge,chat,feishu,lark,llm,websocket
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Communications :: Chat
Requires-Python: >=3.10
Requires-Dist: lark-oapi>=1.7.0
Description-Content-Type: text/markdown

# feishu-chat-bridge

> 极简飞书聊天桥:用**长连接(WebSocket)**收飞书消息,交给你的 `chat_backend` 生成回复,再发回飞书。

[![PyPI version](https://img.shields.io/pypi/v/feishu-chat-bridge.svg?cacheSeconds=300)](https://pypi.org/project/feishu-chat-bridge/)
[![Python versions](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://github.com/jwker/feishu-chat-bridge/blob/main/pyproject.toml)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/jwker/feishu-chat-bridge/blob/main/LICENSE)
[![PyPI downloads](https://img.shields.io/pypi/dm/feishu-chat-bridge.svg?cacheSeconds=3600)](https://pypi.org/project/feishu-chat-bridge/)

[![飞书](https://img.shields.io/badge/飞书-聊天桥-blue.svg)](https://open.feishu.cn)
[![Lark](https://img.shields.io/badge/Lark-国际版-blue.svg)](https://open.larksuite.com)
[![Agent](https://img.shields.io/badge/Agent-可接入-green.svg)](https://github.com/jwker/feishu-chat-bridge)
[![LLM](https://img.shields.io/badge/LLM-可接入-green.svg)](https://github.com/jwker/feishu-chat-bridge)

一个零业务逻辑的飞书机器人传输层。你只需要实现**一个函数** `(open_id, text) -> reply`,就能把飞书接进任意系统 —— 接 agent、接 LLM、接规则引擎、接 webhook,都可以。


## 特性

- ✅ 长连接(WebSocket)接收消息,本地开发无需公网
- ✅ 断线自动重连
- ✅ "思考中"emoji(挂 `Typing` reaction,回复后自动摘除)
- ✅ `chat_backend` 支持同步和 async 两种写法
- ✅ 零业务逻辑:不解析命令、不认识用户、不管 agent —— 全都交给宿主
- ✅ 单个 Python 包,依赖仅 `lark-oapi`

## 架构

```
飞书用户 ⇄ 飞书服务器 ⇄(长连接 WebSocket)⇄ feishu-chat-bridge
                                              │
                    收到消息 → chat_backend(open_id, text) → reply
                                              │
                    回复通过飞书发消息 API 发回用户
```

插件只做"收"和"发";"怎么把消息变成回复"由宿主的 `chat_backend` 决定。

## 安装

```bash
pip install feishu-chat-bridge
# 或
uv add feishu-chat-bridge
```

## 快速开始

```python
from feishu_chat_bridge import FeishuBot, FeishuConfig


def chat_backend(open_id: str, text: str) -> str:
    """唯一的对接点:(open_id, 消息文本) -> 回复文本。"""
    # 这里可以调你的 agent / LLM / 任何逻辑
    return f"你说了「{text}」"


bot = FeishuBot(
    FeishuConfig(app_id="cli_xxx", app_secret="xxx"),
    chat_backend=chat_backend,
)
bot.start()   # 非阻塞:内部起后台线程建长连接,调用后保持进程存活即可
```

完整可运行示例见 [examples/minimal.py](https://github.com/jwker/feishu-chat-bridge/blob/main/examples/minimal.py)。

## chat_backend 接口

```python
# 同步写法
def chat_backend(open_id: str, text: str) -> str: ...

# 异步写法(插件自动识别并等待)
async def chat_backend(open_id: str, text: str) -> str: ...
```

| 参数 | 说明 |
|---|---|
| `open_id` | 飞书用户的 open_id(谁发的消息) |
| `text` | 用户发送的文本内容 |
| 返回值 | 要回给用户的文本(返回空字符串/None 时,回「（空）」) |

> 插件不知道你的业务:用户是谁、路由到哪个 agent、要不要命令解析,全在 `chat_backend` 内部自己处理。`open_id` 就是插件能给你的唯一身份信息。

## 配置说明

```python
FeishuConfig(
    app_id="cli_xxx",              # 必填:飞书自建应用 App ID
    app_secret="xxx",              # 必填:飞书自建应用 App Secret
    domain="https://open.feishu.cn",  # 国内版;国际版(Lark)用 https://open.larksuite.com
    log_level="INFO",              # DEBUG / INFO / WARNING / ERROR
    max_workers=2,                 # chat_backend 是同步阻塞时,处理消息的线程池大小
    enable_typing_emoji=True,      # 是否挂"思考中"emoji
)
```

## 飞书侧前置配置

在 [飞书开放平台](https://open.feishu.cn) 创建自建应用:

1. **应用能力** → 开启**机器人**
2. **权限管理**添加:`im:message`(接收消息)、`im:message:send_as_bot`(发消息)
3. **事件与回调 → 事件订阅**:
   - 订阅方式选 **长连接(WebSocket)** ⚠️(选 webhook 则 ws 客户端连不上,这是最常见的坑)
   - 订阅事件 **`im.message.receive_v1`**
4. **版本管理与发布** → 创建版本并发布

## 部署注意

- **不要加 `--workers N` 多 worker**(多 worker 会开多条长连接,一条消息会被随机一个收到)
- 进程内使用请把 `bot.start()` 放进**应用生命周期**(如 FastAPI 的 `lifespan`),不要在 import 时启动
- 长连接断线 SDK 会自动重连;确认线程存活可看 `bot.alive`

## 常见问题

**连不上 / 收不到消息?**
大概率事件订阅方式选成了 webhook,改成**长连接(WebSocket)**。

**报 `This event loop is already running`?**
插件内部已自动处理(lark-oapi 的 ws 客户端会复用主事件循环,插件给它换了专属 loop)。如果在自己写的环境里遇到,确认 `bot.start()` 不是在事件循环内直接调用。

**"思考中"emoji 没生效?**
`emoji_type` 必须是 `Typing`(PascalCase),插件已内置正确值;若飞书返回 `231001`,多半是应用权限或版本未发布。

**想支持群消息 / 卡片消息?**
目前 MVP 只处理单聊文本消息,群消息直接忽略。可在 `MessageHandler._handle` 里扩展。

## 开发

```bash
git clone https://github.com/jwker/feishu-chat-bridge
cd feishu-chat-bridge
uv sync
python examples/minimal.py
```

## License

[MIT](LICENSE)
