편집자 노트

kriskwok/dsh-feishu-gateway

DeepSeek Harness Feishu gateway plugin: chat with your DSH agent from Feishu (persistent sessions, /new, Markdown replies, proactive push)

이것은 DeepSeek Harness(DSH) 플러그인입니다. 이 사이트는 GitHub README, 설치 정보, 유지보수 상태, 공개 보안 시그널을 모아 보여줍니다.

dsh-feishu-gateway

npm version License: MIT GitHub stars

English | 中文

飞书(Feishu/Lark)里与你的 DeepSeek Harness(DSH) agent 对话。

这是一个 DSH 插件 bundle:挂载飞书长连接监听器,每条飞书消息路由到稳定的 DSH 会话 (通过 agents 服务的 resume 恢复,多轮对话保持在同一个会话),agent 的答复以 Markdown 富文本(post 消息的 md 标签)回复。支持 /new 开启全新会话、 原生 Typing 表情处理中指示、长任务的流式进度卡片、权限审批与 ask_user_question点击即答卡片、以及主动推送。

功能

  • 💬 完整对话 — 飞书私聊 / 群聊 @机器人 → DSH agent → 回复
  • 🔁 会话保持 — 每个飞书会话对应一个 DSH 会话(agents.resume / agents.create); 发 /new(或"另起会话 / 新会话 / 重新开始 / 换个话题")开启全新会话
  • ⌨️ 原生 Typing 指示 — 处理期间机器人在你的消息上加一个 Typing 表情回复 (同 hermes-agent 的飞书网关), 回答未结束就一直显示,失败时换成 CrossMark。默认不再发"思考中…"提示语。
  • 🎞 流式汇报 — 长任务持续汇报:一张实时交互卡片流式显示 agent 的 思考、工具调用、回答草稿reporting.mode: 'stream',默认开启); 设为 reporting.mode: 'final' 则只显示最终结果。
  • 🃏 点击即答卡片 — 权限审批(approval/request,如沙箱提权)与模型的 ask_user_question 工具会渲染成飞书交互卡片:点 ✅ 允许一次 / 🚫 拒绝 或选项按钮即可作答。点击后回调响应会瞬间把卡片替换为已处理态 (按钮移除、显示结果)并弹出 toast 确认。
  • ✍️ Markdown 回复 — 用普通富文本(post)消息的 md 标签:粗体、行内代码、 列表、链接原生渲染,无需卡片
  • 🤖 完整 agent 能力 — DSH agent 自带模型与工具(bash、文件、子代理…),完全自主
  • 📨 主动推送 — 可选管理 HTTP API(/api/push),随时向用户/群推送文本、Markdown、卡片
  • 🔌 无需公网 — 飞书长连接,不需要回调地址
  • 🗂 持久化 — 飞书↔DSH 会话映射重启不丢

环境要求

  • 已安装并构建的 DeepSeek Harness(dsh CLI),并配置好 DEEPSEEK_API_KEY (agent 直接使用 DSH 当前模型,无需另配)
  • 一个飞书开放平台企业自建应用,已开启机器人能力(见下)

飞书应用配置

  1. 飞书开放平台 → 创建企业自建应用
  2. 开启机器人能力。
  3. 开通权限:im:messageim:message:send_as_bot(如需读取消息内容再加 im:message:send_as_bot:readonly),然后创建版本并发布。
  4. 事件与回调 → 选择使用长连接接收事件,订阅 im.message.receive_v1(无需公网)。 审批/问答卡片的按钮点击card.action.trigger)也走同一条长连接,无需回调地址。
  5. 在飞书客户端搜索应用名,添加机器人为联系人。

Typing 表情与卡片按钮依赖机器人在会话内有消息交互权限(im:message)。 若表情接口被拒,网关会自动退回发送 hintText 提示语。

安装(作为 DSH 插件)

前提:本包已发布到 npm,且 dsh 命令可用。

推荐把网关挂载到 web profile:与 DSH Web UI 同进程运行,启动 Web UI 即同时启动飞书网关,两者共用同一个 DSH agent。也可以用独立 profile 运行 (见文末「备选」)。

方式一(推荐):挂载到 web profile

web profile 是 DSH 的默认图形界面 profile(dsh --profile web)。

  1. 编辑 ~/.dsh/profiles/web/package.json,加入依赖与 bundle:
{
  "name": "dsh-profile-web",
  "private": true,
  "dependencies": {
    "@kriskwok/dsh-feishu-gateway": "^0.2.0"
  },
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "@kriskwok/dsh-feishu-gateway"
      ]
    }
  }
}
  1. 在 web profile 目录安装依赖:
cd ~/.dsh/profiles/web && pnpm install
  1. 编辑 ~/.dsh/profiles/web/cordis.patch.yml,填入飞书应用凭据:
- id: feishu-gateway
  config:
    feishu:
      appId: cli_xxxxxxxxxxxxxxxx
      appSecret: xxxxxxxxxxxxxxxxxxxxxxxx
    http:
      port: 3100      # 可选管理 API
      token: your-token
  1. 启动(或重启)web profile:
dsh --profile web

也可以直接运行本仓库的一键脚本:./scripts/create-profile.sh (默认挂载到 web profile;--standalone 则创建独立 feishu profile)。

备选:独立 feishu profile

若不想通过 Web UI 使用,可让网关在独立 profile 中运行:

mkdir -p ~/.dsh/profiles/feishu && cd ~/.dsh/profiles/feishu

cat > package.json <<'EOF'
{
  "name": "dsh-profile-feishu",
  "private": true,
  "dependencies": {
    "@kriskwok/dsh-feishu-gateway": "^0.2.0"
  },
  "dsh": {
    "profile": {
      "bundles": ["@deepseek-ai/dsh-base", "@kriskwok/dsh-feishu-gateway"]
    }
  }
}
EOF

cat > pnpm-workspace.yaml <<'EOF'
packages:
  - .
nodeLinker: hoisted
autoInstallPeers: false
EOF

pnpm install
# 再创建 ~/.dsh/profiles/feishu/cordis.patch.yml 填入应用凭据
dsh --profile feishu

配置项

所有配置都在 feishu-gateway 命名空间下(profile patch 行或 ~/.dsh/settings.yaml):

字段默认说明
feishu.appId飞书应用 App ID(必填)
feishu.appSecret飞书应用 App Secret(必填)
feishu.domainfeishufeishu(国内)/ lark(海外)
feishu.botOpenId可选;@ 识别可自动完成
feishu.replyModeat群聊策略:at 仅被 @ 回复 / all 全部回复
workspace~/Documents/DSH-Workspaceagent 工作目录
hintText爸爸,我正在努力处理中……兜底"处理中"文案(仅当 Typing 表情被禁用/不可用时)
reporting.modestreamstream=流式进度卡片;final=只显示最终结果
reporting.typingReactiontrue处理中显示原生 Typing 表情
reporting.showReasoningtrue卡片中流式显示模型思考
reporting.showToolCallstrue卡片中流式显示工具调用
reporting.patchIntervalMs700卡片刷新最小间隔(毫秒,飞书有限流)
reporting.maxBodyChars900卡片正文最大渲染长度
reporting.failureReactionCrossMark失败时(移除 Typing 后)追加的表情
reporting.cardTitleStreaming🤖 DSH 处理中…处理中卡片标题(黄色头)可自定义
reporting.cardTitleDone🤖 DSH 处理完成完成卡片标题(绿色头)可自定义
interactions.approvalCardstrue权限审批用可点击卡片回答
interactions.userQuestionsCardstrueask_user_question 用可点击卡片回答
interactions.approvalCardDisposeupdate审批卡片点击后:update=回调响应瞬间替换为已处理态(按钮移除+结果+toast);recall=撤回卡片消息(失败自动回退 update;注意飞书会在原位显示"撤回了一条消息"占位)
newSessionPatterns/new 及中文短语触发另起会话的正则列表
sessionsFiledata/dsh-feishu-sessions.json会话映射持久化文件
http.port0管理 API 端口(0=禁用)
http.token管理 API Bearer Token

web profile 下的问答卡片ask_user_question 的作答走唯一的 ctx.userQuestions provider 槽位。当 Web UI 与网关同进程(推荐部署)时该槽位 归 Web UI,因此 ask_user_question 在 Web UI 中作答;而权限审批卡片在任何 部署下都从飞书作答。独立 feishu profile 下,ask_user_question 与审批都在 飞书卡片中作答。

会话共存与自愈

  • 预设编排(有工具!) — 在 preset-roster 部署(如 web profile)下,飞书 agent 会从部署的 agent preset 编排(meta.agentPreset + preset mount), 模型因此拿到工具,而不会把工具调用当成纯文本。
  • 与 Web UI 共存 — 会话单 owner。当 Web UI 打开某会话后,飞书侧通过 agents.get() 接管正在运行的 agent 并驱动同一会话,不再报 "while it is live" / "already exists";两个界面共享同一段对话。
  • wedged 会话自愈 — 进程中途死亡留下永久冲突的会话("already exists")时, 网关自动换一个新 session id,并把飞书会话映射重指向它,继续对话。

管理 HTTP API(可选)

设置 http.port 启用。端点:

  • GET /health — 状态
  • POST /api/push — 主动推送 { "receive_id": "ou_xxx", "receive_id_type": "open_id", "msg_type": "text", "content": "{\"text\":\"hi\"}" }
  • GET /api/sessions — 飞书↔DSH 会话映射概览

开发

pnpm install
pnpm build     # tsc → lib/
pnpm test      # 离线自测

说明:@deepseek-ai/* 运行时由 DSH 宿主提供;本地类型检查从你的 deepseek-harness 检出目录 symlink(见发布检查清单)。

许可

MIT

REPOSITORY SIGNALS

보안 및 설치 증거

이 점수는 공개 저장소 메타데이터와 이 사이트에 등록된 설치 증거에만 기반하며, 코드 보안 감사와 다릅니다.

출처 추적 가능

공개 플러그인 카탈로그에서 왔으며, 공개 GitHub 저장소로 연결됩니다.

라이선스

저장소가 MIT 라이선스를 선언했습니다.

유지보수 활동

최근 180일 내 코드 업데이트가 있습니다.

설치 증거

재현 가능한 정확한 설치 메타데이터가 아직 등록되지 않았습니다. 저장소 설명에 따라 직접 확인하세요.

설치 라이프사이클 스크립트

검사한 패키지 메타데이터에 설치 라이프사이클 스크립트가 선언되지 않았습니다.