# dsh-lark-bridge [English](README.md) | 中文 一个 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 插件,把 DSH agent 桥接到 [飞书开放平台](https://open.feishu.cn)。提供带自动刷新的鉴权 provider(`tenant_access_token`)、一组出方向 tool(发消息、读云文档、读写多维表格、调飞书智能体),以及可选的 **Phase 2 入方向**:飞书私聊 → 进程内 DSH agent → 回消息。 ## 为什么做 飞书生态有丰富的内容(云文档、多维表格、智能体),AI 编码 agent 经常需要读取和操作它们。本插件把这些 API 转成模型可直接调用的 tool,避免用户手动粘贴内容。 ## 安装 ```sh dsh plugin --profile web add github:<你的用户名>/dsh-lark-bridge ``` 安装后,把 bundle 加到 profile 的 `dsh.profile.bundles`(见 [Bundles](#bundles))。 ## 配置 | Key | 默认值 | 含义 | |---|---|---| | `appId` | 省略 | 飞书 App ID 字面量。优先用 `appIdEnv`,避免密钥进入配置;非空字面量优先。 | | `appSecret` | 省略 | 飞书 App Secret 字面量。优先用 `appSecretEnv`。 | | `appIdEnv` | `FEISHU_APP_ID` | 凭证引用名,每次调用通过 `ctx.credentials` 解析;无该 seam 时从进程环境读。 | | `appSecretEnv` | `FEISHU_APP_SECRET` | 凭证引用名,每次调用解析。 | | `baseURL` | `https://open.feishu.cn/open-apis` | 飞书开放 API 基址。Lark 用 `https://open.larksuite.com/open-apis`。 | | `timeoutMs` | `30000` | 每个 Feishu tool 的协作式超时(ms),由 `dsh-tool-call-timeout-policy` 强制。 | | `enableSendMessage` | `true` | 是否注册 `feishu_send_message`。 | | `enableReadDoc` | `true` | 是否注册 `feishu_read_doc`。 | | `enableBitable` | `true` | 是否注册多维表格读写 tool。 | | `enableCallAgent` | `false` | 是否注册 `feishu_call_agent`(默认关 —— 需配置智能体 id)。 | | `enableInbound` | `false` | 是否启动飞书长连接入方向(私聊 → DSH agent → 回复)。 | | `inboundCwd` | 进程 cwd | 入方向新建 agent 会话的工作目录。 | | `inboundAck` | `true` | 跑 agent 前是否先回一句「收到,正在处理…」。 | ```yaml - id: lark-bridge name: dsh-lark-bridge config: appIdEnv: FEISHU_APP_ID appSecretEnv: FEISHU_APP_SECRET baseURL: https://open.feishu.cn/open-apis ``` `appId` / `appSecret` 带 `role('secret')`,不会出现在任何 `describe()` 响应里。 ## Tools | Tool | 作用 | |---|---| | `feishu_send_message` | 给指定用户/群/email 发文本或卡片消息。 | | `feishu_read_doc` | 读取 docx 文档内容(走 raw_content 接口),返回纯文本。 | | `feishu_list_doc_blocks` | 读取 docx 文档的结构化块,渲染带标题层级。需要结构时用这个。 | | `feishu_list_bitable_tables` | 列出多维表格里的所有表 —— 先用这个查 table_id。 | | `feishu_bitable_list_records` | 列出表的记录(支持 filter/sort)。 | | `feishu_bitable_create_record` | 在表里新增一条记录。 | | `feishu_bitable_update_record` | 更新(覆盖)一条记录的字段。 | | `feishu_bitable_batch_create_records` | 批量新增记录。 | | `feishu_call_agent` | 触发飞书机器人/智能体(通过发消息 @,飞书无直接服务端 bot-run API)。 | | `feishu_aily_start_skill` | 直接调用飞书智能伙伴(Aily)技能。需 `enableAily=true`。 | 每个 tool 的超时预算是 `config.timeoutMs`,挂在 `ToolDefinition.timeoutMs` 上。 ## 入方向(Phase 2 — 仅私聊) `enableInbound: true` 时,插件建立飞书**长连接**,只处理**私聊**(`chat_type === p2p`),群消息暂忽略。 ```text 飞书私聊 → WS 长连接 → ctx.agents create/resume (session-feishu-) → agent.followup + whenIdle → IM API 回消息 ``` ### 飞书应用配置 1. 与出方向共用同一 App ID / Secret 即可。 2. 权限至少:`im:message`、`im:message:send_as_bot`、`im:message.p2p_msg`。 3. 事件订阅:**使用长连接接收事件** + `im.message.receive_v1`。 4. **先启动带本插件的 `dsh web`**,再在开放平台保存长连接。 5. **不要**再对同一应用跑 `feishu-dsh-bridge` 或其他 WS 客户端(会抢长连接)。 ### 说明 - 入方向暂无流式回复,等整轮 agent 跑完再发。 - 若工具审批卡住,可为飞书会话使用更宽松的 permission preset。 - 本仓库 `cordis.patch.yml` 已默认 `enableInbound: true`。 ## Bundles TODO:确认 bundle 契约后声明 `dsh.bundle`。在此之前本插件作为普通依赖安装,见 [已知限制](#已知限制)。 ## 模型体验 ### 模型看到什么 每个启用的 tool 带 JSON-schema 描述的参数集和一行 system-prompt 引导。鉴权 provider 对模型不可见 —— token 每次调用从 config/env 解析,绝不经过模型参数。 ### token 消耗 出方向的飞书 API 调用不直接消耗对话 token。返回给模型的内容随飞书响应大小而变;`feishu_read_doc` 会截断长文档。 ### KV 缓存影响 只追加;新出现的 tool 结果跟在可复用的请求前缀之后,不会使已有 KV 缓存条目失效。 ## 已知限制 - **入方向暂无群聊** —— Phase 2 只接私聊,群 @ 后续再加。 - **入方向无流式回复** —— 等整轮 agent 结束后再发文本。 - **智能体出方向调用是间接的** —— 飞书服务端「直接调智能体」API 有限,`feishu_call_agent` 通过 @ 机器人触发。 - **同一应用只能有一条长连接** —— 入方向开在本插件后,请停掉独立的 `feishu-dsh-bridge`。 ## License MIT