npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kriskwok/dsh-feishu-gateway

v0.2.14

Published

DeepSeek Harness-native Feishu (Lark) gateway: chat with the DSH agent from Feishu via long connection, with persistent sessions, /new, Markdown replies, live streaming progress cards, native Typing reactions, click-to-answer approval / Q&A cards, and pro

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 → 回复。群聊中每个话题(thread)都是独立的 DSH 会话,该话题下的所有对话都保持在同一会话里,直到发 /new
  • 🔁 会话保持 — 每个飞书会话(或群聊话题)对应一个 DSH 会话(agents.resume / agents.create);发 /new(或"另起会话 / 新会话 / 重新开始 / 换个话题")开启全新会话, 群聊话题里发 /new 同样新开一个会话(该话题绑定新的 DSH 会话)。
  • ⌨️ 原生 Typing 指示 — 处理期间机器人在你的消息上加一个 Typing 表情回复 (同 hermes-agent 的飞书网关), 回答未结束就一直显示,失败时换成 CrossMark。默认不再发"思考中…"提示语。
  • 🎞 流式汇报 — 长任务持续汇报:一张实时交互卡片流式显示 agent 的 思考、工具调用、回答草稿reporting.mode: 'stream',默认开启); 设为 reporting.mode: 'final' 则只显示最终结果。
  • 🃏 点击即答卡片 — 权限审批(approval/request,如沙箱提权)与模型的 ask_user_question 工具会渲染成飞书交互卡片:点 ✅ 允许一次 / 🚫 拒绝 或选项按钮即可作答。点击后回调响应会瞬间把卡片替换为已处理态 (按钮移除、显示结果)并弹出 toast 确认。
  • ✍️ Markdown 回复 — 用普通富文本(post)消息的 md 标签:粗体、行内代码、 列表、链接原生渲染,无需卡片
  • 🧩 Web-only 交互围栏降级 — 模型输出的 dsh-ui 交互组件围栏(如 dsh-genui) 只在 Web UI 渲染;飞书渠道会自动降级成一行可读提示(提取标题,注明"请在 Web UI 查看"),不会出现裸 JSON 代码块
  • 🤖 完整 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.domain | feishu | feishu(国内)/ lark(海外) | | feishu.botOpenId | 空 | 可选;@ 识别可自动完成 | | feishu.replyMode | at | 群聊策略:at 仅被 @ 回复 / all 全部回复。每个群聊话题(thread)是独立的 DSH 会话。 | | workspace | /root/Documents/DSH-Workspace | agent 工作目录(会话也会自动挂到对应的 DSH 工作区,在 Web UI 里归入该工作区而非"未分组")。私聊与群聊话题会话都固定在此工作区。 | | hintText | 爸爸,我正在努力处理中…… | 兜底"处理中"文案(仅当 Typing 表情被禁用/不可用时) | | reporting.mode | stream | stream=流式进度卡片;final=只显示最终结果 | | reporting.typingReaction | true | 处理中显示原生 Typing 表情 | | reporting.showReasoning | true | 卡片中流式显示模型思考 | | reporting.showToolCalls | true | 卡片中流式显示工具调用 | | reporting.patchIntervalMs | 1100 | 卡片刷新最小间隔(毫秒);飞书单条消息更新约限 1 次/秒(错误 230020),失败会自动退避 | | reporting.maxBodyChars | 900 | 卡片正文最大渲染长度 | | reporting.failureReaction | CrossMark | 失败时(移除 Typing 后)追加的表情 | | reporting.cardTitleStreaming | 🤖 DSH 处理中… | 处理中卡片标题(黄色头)可自定义 | | reporting.cardTitleDone | 🤖 DSH 处理完成 | 完成卡片标题(绿色头)可自定义 | | interactions.approvalCards | true | 权限审批用可点击卡片回答 | | interactions.userQuestionsCards | true | ask_user_question 用可点击卡片回答 | | interactions.approvalCardDispose | update | 审批卡片点击后:update=回调响应瞬间替换为已处理态(按钮移除+结果+toast);recall=撤回卡片消息(失败自动回退 update;注意飞书会在原位显示"撤回了一条消息"占位) | | newSessionPatterns | /new 及中文短语 | 触发另起会话的正则列表 | | sessionsFile | data/dsh-feishu-sessions.json | 会话映射持久化文件 | | http.port | 0 | 管理 API 端口(0=禁用) | | http.token | 空 | 管理 API Bearer Token |

web profile 下的问答卡片ask_user_question 的作答走唯一的 ctx.userQuestions provider 槽位。网关从不抢占该槽位(否则 Web UI 的 apiProxy 宿主会因 DUPLICATE_PROVIDER 启动失败)——它在服务边界包裹 service.ask 做桥接:飞书会话的提问用飞书卡片作答,其余会话继续走 Web UI provider。权限审批卡片在任何部署下都从飞书作答。独立 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