[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80029":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":13,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":30,"readmeContent":31,"aiSummary":32,"trendingCount":16,"starSnapshotCount":16,"syncStatus":33,"lastSyncTime":34,"discoverSource":35},80029,"hermes-lark-streaming","Cheerwhy\u002Fhermes-lark-streaming","Cheerwhy","Hermes 飞书（Feishu\u002FLark）CardKit v2.0 流式卡片插件","",null,"Python",97,13,66,1,0,16,30,39,3.44,"MIT License",false,"main",[25,26,27,28,29],"cardkit","feishu","hermes","lark","streaming","2026-06-12 02:03:57","# Hermes Lark Streaming\n\n[![PyPI](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fpython-%E2%89%A53.11-blue)](https:\u002F\u002Fwww.python.org\u002F)\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-yellow.svg)](LICENSE)\n\n[Hermes](https:\u002F\u002Fgithub.com\u002FNousResearch\u002Fhermes-agent) Gateway 飞书流式卡片插件 — 基于 CardKit v2.0 的进程内流式消息卡片。\n\n灵感来源于 [openclaw-lark](https:\u002F\u002Fgithub.com\u002Flarksuite\u002Fopenclaw-lark) 和 [hermes-feishu-streaming-card](https:\u002F\u002Fgithub.com\u002Fbaileyh8\u002Fhermes-feishu-streaming-card)。\n\n[English](README.en.md)\n\n![](assets\u002Fcover.jpg)\n\n---\n\n## 功能\n\n- **流式输出** — AI 回复实时显示在交互卡片中，打字机效果\n- **流式卡片** — 按事件顺序在单张卡片内动态渲染思考、工具调用、回答内容\n- **思考过程** — 显示模型的推理\u002F思考内容\n- **工具调用** — 实时展示工具调用状态和进度，含标准图标和结果\u002F错误块\n- **CardKit v2.0** — 使用飞书 CardKit 流式 API；卡片创建失败时交回 Hermes Gateway 默认回复\n- **终态卡片** — 完成后展示完整结果，含 token 用量、耗时、上下文信息\n- **消息保护** — 消息被删除\u002F撤回后自动终止更新，避免无效 API 调用\n- **图片解析** — 自动识别 markdown 图片引用，下载上传后替换为飞书 img_key\n- **中断处理** — 处理 `\u002Fstop` 命令和消息打断，展示中断状态卡片并自动开启新会话\n- **Cron 卡片推送** — 定时任务结果以飞书卡片形式推送，保留 Markdown 渲染\n- **后台任务卡片推送** — `\u002Fbackground`（`\u002Fbtw`）任务完成后以卡片形式推送，支持话题内回复\n- **多语言** — 卡片文本（状态、工具面板、思考标签等）内置中英双语，根据飞书客户端语言自动切换\n\n---\n\n## 卡片展示\n\n插件按事件到达顺序在卡片内动态渲染思考、工具调用、回答元素，多轮对话内容按实际顺序展示。\n\n当长对话或工具调用步骤过多导致卡片元素接近飞书 200 上限时，自动拆分为多张卡片：旧卡片封存（数据完整），新卡片继续输出，仅最后一张卡片带页脚。单个工具面板步骤过多时也会按步骤边界拆分。\n\n![](assets\u002Fstreaming.jpg)\n\n---\n\n## 运行要求\n\n- Hermes `>= 0.11.0`（2026.4.23）已安装并配置飞书平台\n- `Python >= 3.11`\n- `lark-oapi >= 1.4.0` — 飞书\u002FLark 官方 Python SDK\n- `PyYAML >= 6.0` — YAML 解析库\n- 飞书应用权限：消息卡片（CardKit）读写、消息发送与回复、图片上传\n\n---\n\n## 安装\n\n> **注意：** Hermes 运行在独立的 Python 虚拟环境中，请使用 Hermes 的 Python 安装插件，否则 gateway 启动后会无法加载。\n\n### AI Agent\n\n让 Agent 读取 README 后按手动步骤操作：\n\n```\ncurl https:\u002F\u002Fraw.githubusercontent.com\u002FCheerwhy\u002Fhermes-lark-streaming\u002Fmain\u002FREADME.md\n```\n\n### 手动安装\n\n> 插件会自动读取 Hermes 的 `HERMES_HOME` 环境变量定位安装路径（默认 `~\u002F.hermes`），非默认路径下无需额外操作。\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002FCheerwhy\u002Fhermes-lark-streaming.git\ncd hermes-lark-streaming\n\n# 安装到 Hermes 的 venv 中，确保 gateway 能加载插件\nHERMES_PYTHON=~\u002F.hermes\u002Fhermes-agent\u002Fvenv\u002Fbin\u002Fpython3\n$HERMES_PYTHON -m pip install -e .\n$HERMES_PYTHON -m hermes_lark_streaming verify   # 验证兼容性\n$HERMES_PYTHON -m hermes_lark_streaming install   # 注入 hook\nhermes gateway restart\n```\n\n---\n\n## 配置\n\n在 `~\u002F.hermes\u002Fconfig.yaml` 中添加：\n\n```yaml\nstreaming:\n  enabled: true\n```\n\n### 凭据\n\n凭据按以下顺序解析：\n\n| 优先级 | 来源 | 变量 |\n|--------|------|------|\n| 1 | 环境变量 | `FEISHU_APP_ID` \u002F `FEISHU_APP_SECRET`（或 `LARK_APP_ID` \u002F `LARK_APP_SECRET`） |\n| 2 | 配置文件 | `~\u002F.hermes\u002Fconfig.yaml` 中的 `feishu` 或 `lark` 区段 |\n\n```env\nFEISHU_APP_ID=cli_xxxxx\nFEISHU_APP_SECRET=xxxxx\n```\n\n### 页脚\n\n通过 `streaming.footer` 自定义完成态卡片的页脚：\n\n```yaml\nstreaming:\n  enabled: true\n  footer:\n    fields:\n      - [status, elapsed, context, model]\n    show_label: false\n```\n\n**字段**（`footer.fields`）：二维数组，每个子数组为一行，字段间用 `·` 连接。\n\n| 字段 | 说明 | 有标签 | 无标签 |\n|------|------|--------|--------|\n| `status` | 完成状态 | `✅ Completed` | `✅ Completed` |\n| `elapsed` | 耗时 | `Elapsed 12.3s` | `12.3s` |\n| `model` | 模型名称 | `deepseek-v4-flash` | `deepseek-v4-flash` |\n| `tokens` | Token 用量 | `↑ 1.2K ↓ 500` | `↑ 1.2K ↓ 500` |\n| `context` | 上下文窗口用量 | `Context 50K\u002F200K (25%)` | `50K\u002F200K (25%)` |\n\n**显示标签**（`footer.show_label`）：是否展示字段标签（如 \"Elapsed\"、\"Context\"）。默认：`false`。\n\n未配置时的默认值：`fields: [[status, elapsed, context, model]]`，`show_label: false`。\n\n### 面板折叠\n\n完成态卡片中，推理面板和工具面板默认折叠。配置 `panel_expanded: true` 可保持展开：\n\n```yaml\nstreaming:\n  enabled: true\n  panel_expanded: true\n```\n\n---\n\n## CLI 命令\n\n```bash\nHERMES_PYTHON=~\u002F.hermes\u002Fhermes-agent\u002Fvenv\u002Fbin\u002Fpython3\n$HERMES_PYTHON -m hermes_lark_streaming verify     # 验证兼容性（不修改文件）\n$HERMES_PYTHON -m hermes_lark_streaming install    # 注入 hook\n$HERMES_PYTHON -m hermes_lark_streaming uninstall  # 移除 hook\n$HERMES_PYTHON -m hermes_lark_streaming restore    # 从备份恢复原始文件\n$HERMES_PYTHON -m hermes_lark_streaming status     # 查看状态\n```\n\n---\n\n## 更新\n\n```bash\ncd hermes-lark-streaming\ngit pull\nHERMES_PYTHON=~\u002F.hermes\u002Fhermes-agent\u002Fvenv\u002Fbin\u002Fpython3\n$HERMES_PYTHON -m pip install -e .\n$HERMES_PYTHON -m hermes_lark_streaming uninstall   # 先移除旧注入\n$HERMES_PYTHON -m hermes_lark_streaming verify\n$HERMES_PYTHON -m hermes_lark_streaming install\nhermes gateway restart\n```\n\n---\n\n## 卸载\n\n```bash\nHERMES_PYTHON=~\u002F.hermes\u002Fhermes-agent\u002Fvenv\u002Fbin\u002Fpython3\n$HERMES_PYTHON -m hermes_lark_streaming uninstall\n$HERMES_PYTHON -m pip uninstall hermes-lark-streaming\n```\n\n---\n\n## 工作原理\n\n插件通过 AST 注入在 `gateway\u002Frun.py` 和 `cron\u002Fscheduler.py` 插入 hook 调用，所有业务逻辑在 `hermes_lark_streaming` 包内完成：\n\n| Hook | 注入位置 | 说明 |\n|------|----------|------|\n| `on_feishu_normalize` | `_handle_message` 中 `source = event.source` 之后 | 修正飞书引用消息的虚假 thread_id |\n| `on_message_started` | `_handle_message_with_agent` 函数体开头 | 创建卡片会话，发送占位卡片 |\n| `on_tool_updated` | `progress_callback` 内部 | 实时展示工具调用状态 |\n| `on_answer_delta` | `_stream_delta_cb` 内部 | 流式更新回答文本 |\n| `on_thinking_delta` | `_interim_assistant_cb` 内部 | 显示思考\u002F推理过程 |\n| `on_reasoning_delta` | `agent.reasoning_config` 赋值之后 | 流式展示模型原生推理 |\n| `on_background_review_message` | `background_review_callback` 赋值处 | 延迟自我进化消息到卡片完成后再发送 |\n| `on_message_aborted` | stale `return None` 之前 | 处理 `\u002Fstop` 中断 |\n| `on_message_interrupted` | `_run_agent` 递归调用前 | 处理消息打断，终止旧卡片并创建新会话 |\n| `on_message_completed_wait` | `return response` 之前 | 等待卡片创建\u002F收尾完成后发送终态卡片，失败时让网关走文本兜底 |\n| `on_cron_deliver` | `_deliver_result` 中 `delivered = False` 之后 | 拦截飞书 Cron 推送，以卡片形式发送 |\n| `on_background_deliver` | `_run_background_task` 中 `extract_images` 之后 | 拦截飞书后台任务推送，以卡片形式回复到原始消息（话题内正确定位） |\n\n**消息处理流程：**\n\n```\n用户发送消息\n  → 创建卡片会话\n  → 流式更新（工具状态、文本增量 — 节流调度）\n  → 图片 URL 异步解析替换\n  → 终态卡片（token\u002F耗时\u002F上下文）\n```\n\n若消息被删除\u002F撤回，UnavailableGuard 自动终止后续更新。\n\n**中断处理：**\n\n- `\u002Fstop` 终止 — 用户主动停止，卡片展示中断状态：\n\n![](assets\u002Fabort.jpg)\n\n- 消息打断 — 用户发送新消息打断正在处理的回复，旧卡片展示中断状态，并自动为新消息创建新的流式卡片：\n\n![](assets\u002Finterrupt.jpg)\n\n**失败处理：**\n\n| 场景 | 处理方式 |\n|------|----------|\n| CardKit 流式 | 100ms 节流更新 |\n| CardKit 创建失败 | Gateway 回退到默认文本回复 |\n| 速率限制 | 跳过当前帧，不切换通道 |\n| 终态卡片失败 | Gateway 回退到默认文本回复 |\n\n---\n\n## 注意事项\n\n- `install` 会修改 `~\u002F.hermes\u002Fhermes-agent\u002Fgateway\u002Frun.py` 和 `cron\u002Fscheduler.py`，自动创建 `.hermes_lark.bak` 备份\n- Hermes 更新后需重新运行 `verify` + `install`\n- 插件与 Hermes 内置飞书适配器互补工作：插件负责流式卡片，内置适配器负责消息收发\n- 仅对飞书平台生效，其他平台不受影响\n\n## 贡献者\n\n感谢以下贡献者的 Issue 和 PR：\n\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FMxin-9527\">\u003Cimg src=\"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F178271393?v=4&s=64\" width=\"48\" height=\"48\" style=\"border-radius:50%\" \u002F>\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fgitteeee\">\u003Cimg src=\"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F128769493?v=4&s=64\" width=\"48\" height=\"48\" style=\"border-radius:50%\" \u002F>\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FBandersnatch0x\">\u003Cimg src=\"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F13325067?v=4&s=64\" width=\"48\" height=\"48\" style=\"border-radius:50%\" \u002F>\u003C\u002Fa>\n\n---\n\n## 许可证\n\n[MIT](LICENSE)\n","Hermes Lark Streaming 是一个基于飞书（Feishu\u002FLark）CardKit v2.0 的流式卡片插件，使用 Python 开发。该项目的核心功能包括实时显示AI回复、动态渲染思考过程和工具调用状态，并支持多语言自动切换。它适用于需要在飞书平台上进行复杂对话交互的场景，如客服系统、智能助手等。通过该插件，用户可以在单张卡片内看到模型的推理过程、工具调用详情以及最终结果，同时具备消息保护和中断处理机制以优化用户体验。此外，还支持定时任务和后台任务的结果推送。此项目遵循MIT许可证，适合已有Hermes Gateway环境并希望增强其飞书集成能力的开发者使用。",2,"2026-06-11 03:58:57","CREATED_QUERY"]