- Accueil
- Plugins
- Intégrations et accès distant
- dsh-lark-plus
dsh-lark-plus
anfruj/dsh-lark-plus
Passerelle entre DeepSeek Harness et Feishu/Lark : elle propose le chat, les cartes, les approbations, un tableau de tâches, des objectifs et des plannings dans Feishu, ainsi qu’une transcription vocale entièrement locale (hors ligne) avec une barre de lecture dans la Web GUI.
Installer
dsh plugin --profile web add github:anfruj/dsh-lark-plusREADME
🪶 dsh-lark-plus
DeepSeek Harness × 飞书/Lark 双向桥接
私聊 / 群聊 · 卡片按钮 · 审批与提问回传 · 任务板 · goal · 定时任务
外加:全程本机的语音转文字 + 网页端播放条
中文
DeepSeek Harness × 飞书/Lark 双向桥接插件:把 DSH 智能体装进飞书——扫码建应用、30 秒上线,在飞书里对话、点卡片、回审批、跑任务、看任务板。在此基础上还带了一条全程本机的语音链路:飞书里按住说话,音频在本机由 SenseVoice 转成文字,并可直接在 DSH 网页端回放——音频不出本机、不调任何云端语音 API。
本仓库是
dsh-lark-link的 fork(MIT,原作者及贡献者版权保留)。桥接部分沿用上游实现,语音链路为新增。详见文末归属与许可。
🌟 桥接能力(沿用上游)
- 零门槛:
/lark setup扫码即建飞书应用,不用手搓开放平台、不用配回调、不用公网服务器 - 零丢失:出站 Outbox + 入站 WAL 双持久化,进程崩溃 / 插件热更 / dsh 重启后消息与回答都补得回来
- 零学习成本:切换类命令都是单选卡片,点一下即生效;DSH 原生命令直接用
- 真 Agent:不是聊天机器人——bash / 文件 / 子代理 / 工作流全套工具,飞书里跑完整 Harness
✨ 特性
| 能力 | 说明 |
|---|---|
| 🎙 本地语音转写 | 飞书发语音 → 本机 SenseVoice 转文字(见上文);音频原文件始终保留 |
| 🎯 一键认证 | /lark setup 扫码创建飞书应用(自动订阅消息事件 + 群聊全量 + 表情权限 + 用户基本信息),30 秒上线;也支持 DSH_LARK_APP_ID/SECRET 手动通道 |
| 🧠 多模式 Agent | 标准 / PTC / 极简 / Cordis preset + 你在 GUI 自建的 preset,飞书发 /mode 出单选卡片即切 |
| 🎛 权限分级 | 只读 / 工作区写 / Full access 三种权限,/permission 卡片即切 |
| 🎨 卡片化命令 | /mode /permission /model 全是单选按钮卡片——点一下即切换 |
| 💬 意图确认转发 | 模型提问(ask_user_question)→ 飞书意图确认卡片,答完模型继续 |
| 😊 表情回执 | 收到消息随机表情;回复完成 / 命令完成打 DONE ✅ |
| 💪 出站零丢失 | 持久 Outbox(JSONL + at-least-once + 幂等键 + 分航道并行 + 周期清理) |
| 🆕 入站请求补发 | Agent 处理到一半插件/dsh 崩溃,重启后自动重新触发该消息 |
| 🛡 连接自愈 | probe 驱动受控重连 + 配额熔断 + 断连补偿;环境代理自动规避 |
| 🔀 命令三级分流 | 桥特有命令桥处理;DSH 注册命令原生执行;其余原样注入 Agent |
| 📎 入站多媒体 | 飞书图片 → 视觉模型看图;文件 → 有界文本提取;语音 → 本地转写 |
| 📤 出站多媒体 | 模型经 lark_plus_send_local_file 主动回传本地图片/文件 |
| 🩺 一键诊断 | /doctor → ZIP 诊断包(含当前会话 session log + 脱敏配置) |
| ✍️ Markdown 渲染 | 回复自动检测 markdown → CardKit 卡片渲染,纯文本走文本消息 |
| 🌊 可选流式输出 | /lark-config streaming.enabled=true 热开流式卡片(默认关,省流量) |
| 🖥 复用 DSH Web GUI | 桥 Agent = 原生 DSH session,聊天/工具卡/设置全由 GUI 呈现 |
| 👥 访问控制 | allowlist 白名单;groupPolicy 群聊触发策略;denyList 命令前缀拒绝兜底 |
🚀 快速开始
前置:Node.js ≥ 24,已安装 DeepSeek Harness。语音功能另需 ffmpeg(见上文)。
安装(DSH 官方 bundle 机制,产物已随仓库提交,不执行构建脚本):
# 从 npm 安装(推荐,已发布 0.1.0)
dsh plugin --profile <你的档> add dsh-lark-plus
# 从 GitHub 仓库安装(跟进尚未发版的提交用这条)
dsh plugin --profile <你的档> add github:AnFRuJ/dsh-lark-plus
# 或本地目录(源码开发时)
dsh plugin --profile <你的档> add link:/path/to/dsh-lark-plus
装完在 DSH 输入框执行一次扫码上线:
/lark setup # 手机飞书扫码,自动创建应用并写入凭据
/lark start # 建立长连接
/lark status # 查看连接/会话/补发计数
之后在飞书里直接发文字、图片、文件,或按住说话发语音。
桌面版 DSH 的
desktop档由 Electron 独占,CLI 会拒绝;那种情况请走 GUI 侧边栏「插件」页添加同一条地址。
🎙 附加能力:本地离线语音转文字(+ 网页端回放)
它是怎么工作的
飞书语音(OGG/Opus)
↓ 下载(本机 → 飞书 API,唯一的网络请求)
↓ 原文件落盘保留 ← 你随时能在飞书回听,agent 也能复读同一份文件
↓ ffmpeg 转 16 kHz 单声道 WAV
↓ SenseVoice(sherpa-onnx,CPU 推理)
文字 → 作为这条消息的正文交给智能体
- 引擎:SenseVoice(int8,中/英/日/韩/粤 + 自动标点),通过
sherpa-onnx-node在本机 CPU 上跑。 - 音频去向:只有一次联网 —— 下载约 228 MB 的模型。下载不在插件装载时触发(安装 / 激活 / 启动永远秒级):第一次收到语音消息、或在侧栏面板点「下载模型」、或调用
POST /dsh-voice-local/v1/model/download时才开始。之后完全离线。 - 失败不丢消息:模型没下好、ffmpeg 缺失、解码失败时,音频照样落盘,正文留空并把原因写进日志。同一条语音永远不会因为转写失败而消失。
- 可关:配置里
voice.enabled: false就只保留音频、不做转写。 - 可回放:DSH Web UI 里每条语音正文下面直接有一条播放条(宿主只读路由
GET /plugins/lark-plus/audio?name=…,支持 Range),不用回飞书重听;原始附件卡片会被隐藏,一屏只剩「文字 + 播放条」。
前置条件
| 依赖 | 说明 |
|---|---|
| ffmpeg | 必须。飞书语音是 OGG/Opus,模型只吃 16 kHz WAV。默认按 PATH 查找,也认 voice.ffmpegPath / DSH_VOICE_FFMPEG。 |
| 模型 | 装载时不会下载;首次需要转写时(或手动点「下载模型」/ 调 POST /dsh-voice-local/v1/model/download)才下到 $DSH_HOME/voice/sensevoice/(默认 ~/.dsh/voice/sensevoice/),与 dsh-voice-local 共用同一目录——装过那个插件、或已手动放置模型,都不会重复下载。可用 voice.sha256 / voice.modelSha256 / voice.tokensSha256 做完整性校验。 |
手动放置模型(内网 / 下载慢时):解压官方归档,保证目录里有 model.int8.onnx 和 tokens.txt 即可:
mkdir -p ~/.dsh/voice/sensevoice
# 官方:https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/
# sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
tar -xjf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2 \
--strip-components=1 -C ~/.dsh/voice/sensevoice
配置
# cordis.patch.yml(profile 的 patch 层)
- id: lark-plus
config:
voice:
enabled: true
modelDir: '' # 空 = $DSH_HOME/voice/sensevoice
ffmpegPath: '' # 空 = 自动探测
modelUrl: '' # 主下载源覆盖
mirrors: '' # 逗号分隔,优先于内置镜像(hf-mirror / ghfast)
sha256: '' # 可选:模型归档 tar.bz2 的 SHA-256
modelSha256: '' # 可选:model.int8.onnx 的 SHA-256(直连文件源)
tokensSha256: '' # 可选:tokens.txt 的 SHA-256
timeoutMs: 600000 # 可选:单次下载尝试上限(默认 10 分钟);慢源失败即换下一个
ffmpegTimeoutMs: 60000
本地转写接口
语音链路把转写能力也开成了本机路由(可直接被其他工具复用;只服务本机):
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /dsh-voice-local/v1/health | 引擎 / 模型 / ffmpeg / 下载状态 |
GET | /dsh-voice-local/v1/model/status | 模型文件与下载进度 |
POST | /dsh-voice-local/v1/model/download | 触发后台模型下载 |
POST | /dsh-voice-local/v1/transcribe | body = 16 kHz 单声道 PCM16 WAV,返回 { ok, text } |
自测
npm run test:voice # 真实模型 + 真实 ffmpeg;资产缺失时自动 skip
npm run check # tsc --noEmit
📖 完整文档
下面保留上游的中文文档(命令、卡片、诊断、配置项等),其中的命令名已同步为 /lark。
⌨️ 命令
DSH 侧(GUI 或终端)
/lark setup 扫码一键建应用(或 DSH_LARK_APP_ID/SECRET 手动通道)
/lark start|stop|restart|status 桥接生命周期与全链路健康
/lark uninstall-clean 清除凭据与状态目录
飞书侧(卡片化单选,无需记忆拼写)
| 类别 | 命令 | 行为 |
|---|---|---|
| 选择类 | /mode /permission /model | 单选按钮卡片,点选即切换(动态感知自建 preset 与提供商) |
| 目标类 | /goal [目标|pause|resume|clear] | 启动长任务自主执行 / 暂停 / 恢复 / 清除当前目标 |
| 状态类 | /status /sessions /help | 全链路健康(含 Outbox/补发计数)/ 会话列表 / 帮助卡片 |
| 会话类 | /new /resume [序号|id] /stop /workspace <路径> | 新会话 / 极简恢复历史会话 / 停当前任务 / 切工作区 |
| 诊断 | /doctor | ZIP 诊断包(session log + 配置 + ISSUE.md) |
| 热改 | /lark-config key=value | 热改配置(如 groupPolicy=open、agentPreset=standard、streaming.enabled=true) |
| DSH 命令 | /compact 等 | 原生执行,结果回飞书 |
| 多媒体 | 发图片/文件 | 图片→视觉模型;文件→文本提取 |
| 意图确认 | 模型提问 | 自动转飞书意图确认卡片,选项或输入作答 |
命令无拦截、无门禁:一切
/消息要么桥处理,要么原样交 DSH——绝不静默丢弃。skill 无前缀,直接说任务即可。
⚙️ 常用配置(/lark-config 热改,立即生效并持久化)
| 配置键 | 默认 | 说明 |
|---|---|---|
groupPolicy | open | 群聊触发策略:open(免 @ 全触发)/ mention / keywords / reply |
groupKeywords | ["lark","bot"] | keywords 模式下的触发词 |
agentPreset | ptc | Agent preset(shipped:standard/ptc/minimal/cordis,或 GUI 自建 id;历史别名 code 会自动映射为 ptc) |
permissionMode | danger-full-access | 权限:read-only / workspace-write / danger-full-access |
streaming.enabled | false | CardKit 流式卡片(开=逐字打印) |
reactions.enabled | true | 表情回执 |
allowlist | [] | open_id 白名单,空 = 所有人可对话 |
denyList | [] | 命令前缀拒绝兜底 |
workspaceRoot | `` | 桥会话工作区根目录(空 = process.cwd()) |
attachments.retentionHours | 168 | 入站图片/文件的保留时长(小时,默认 7 天;0 = 永久保留)。默认存系统临时目录,到期自动清扫 |
attachments.dir | `` | 入站媒体根目录覆盖(空 = 系统 tmpdir;重启生效) |
凭据(appId/appSecret)存放在 DSH credentials 服务,不进配置文件;
/lark setup扫码自动写入。
🩺 遇到问题?
- 飞书发
/doctor,得到 ZIP 诊断包(完整 session log + 脱敏配置 + ISSUE.md 模板) - 把诊断包贴给任意 AI(或在 GitHub Issue 中发出来),即可快速定位
/status可随时看连接 / Outbox / 补发 / 会话全链路健康
🛠 开发者
npm run dev:link # 链接本地 DSH checkout(类型检查/测试需要)
npm run check # tsc --noEmit
npm test # 264 项单元 + 集成测试
npm run build # tsdown → dist/(宿主 ESM + client bundle)
npm pack # 产出可分发 tarball
架构:桥 = Cordis 插件(dsh.bundle 格式),分层清晰:
host(SDK 适配/认证)→ inbound(传输/群触发/断连补偿/Inbound WAL)→ application(命令路由/消息编排/诊断)→ outbound(Outbox/事件转发/卡片)→ sessions(每会话 Agent 管理)。
CI(GitHub Actions):push/PR 自动跑类型检查 + 264 项测试 + 构建;发布 npm 走 tag release 的 Publish workflow。
📄 许可
MIT — 自由使用、修改、分发。
本项目为社区插件,与 DeepSeek、飞书或 Lark 无隶属关系。
English
DeepSeek Harness × Feishu/Lark bridge — put your DSH agent inside Feishu. Scan a QR code and go live in 30 seconds; chat from anywhere. Plus fully local voice transcription and a play bar in the Web GUI.
🌟 Why dsh-lark-plus
- Zero setup friction: QR-scan app creation — no Open Platform fiddling, no callback URL, no public server
- Zero message loss: durable Outbox (outbound) + Inbound WAL — crashes, hot reloads, and dsh restarts all recover
- Zero learning curve: every toggle is a single-select card; native DSH commands (
/goal/compact…) just work - A real agent: full tool belt (bash / files / subagents / workflows) driven from Feishu
✨ Features
| Capability | Description |
|---|---|
| 🎯 One-click auth | /lark setup scans a QR to create the Feishu app (auto-subscribes message events + group-all + reactions). 30-second onboarding; manual DSH_LARK_APP_ID/SECRET channel also supported |
| 🧠 Multi-mode Agent | Standard / Code / Minimal / Cordis presets + your custom GUI presets; /mode shows a single-select card — tap to switch (default Code: multi-step tools in one shot) |
| 🎛 Permission tiers | Read-only / workspace-write / Full access; /permission card switches instantly (Full access by default) |
| 🎨 Card-based commands | /mode /permission /model are all single-select button cards — tap, no typing; models grouped by provider |
| 💬 Intent confirmation | Model questions (ask_user_question) land as Feishu intent-confirmation cards (option buttons + multi-select dropdown + custom text); answer and the agent resumes |
| 😊 Reaction receipts | Random "got it" reaction on inbound; DONE ✅ on completion (only Feishu-validated emojis) |
| 💪 Outbound zero-loss | Persistent Outbox (JSONL + at-least-once + idempotency + per-lane parallel + failure quarantine + periodic prune), resumes after kill/restart; bridge command replies ride the Outbox too |
| 🆕 Inbound request replay | If the agent dies / plugin reloads / dsh restarts MID-TURN, the interrupted user message is auto re-triggered on boot (no more silently dropped requests) — durable Inbound WAL + boot reconciliation + attempt/time caps; /status shows the pending-replay count |
| 🛡 Self-healing connection | Probe-driven controlled reconnect + QuotaGovernor circuit breaker (auto-unblocks and reconnects after the quota window) + missed-message compensation; auto-avoids proxy env |
| 🔀 3-tier command routing | Bridge commands → bridge; DSH commands → native; /goal, unknown /xxx, plain text → injected verbatim (no gates). Skills need no prefix — just describe the task |
| 📎 Inbound media | Feishu images → visual model (attachment-backed); files → bounded text extraction |
| 📤 Outbound media | Model sends local files/images via lark_plus_send_local_file (workspace whitelist + size/format checks) |
| 🩺 One-click diagnostics | /doctor → ZIP bundle (full DSH session log + sanitized config + ISSUE.md) back to the chat |
| ✍️ Markdown rendering | Replies auto-render as CardKit cards (headings/lists/code/tables); plain text stays plain |
| 🌊 Optional streaming | /lark-config streaming.enabled=true hot-enables CardKit schema 2.0 streaming cards (off by default, saves traffic) |
| 🆕 Goal-driven long tasks | /goal <objective> launches autonomous long-running task loops directly from Feishu; /goal pause / resume / clear manage execution via clean natural conversation |
| 🆕 Session management | /new opens a fresh session; /resume clean-restores a historical session (button/index/id-prefix, resolves true titles, fixes cross-restart session collision); /workspace <path> switches; per-session isolated configuration |
| 🖥 Reuses DSH Web GUI | Bridge agents are native DSH sessions; conversations auto-group under their workspace; the web panel shows live Outbox/replay counters |
| 👥 Access control | allowlist restricts inbound to specific open_ids; groupPolicy (open / mention / keywords / reply); denyList command-prefix deny |
| 🔓 Full access by default | Sandbox full access + never-ask approvals |
🚀 Quickstart
Prerequisites: Node.js ≥ 24 and DeepSeek Harness installed (npm i -g @deepseek-ai/dsh).
dsh plugin --profile web add dsh-lark-plus@latest --ignore-scripts
dsh web
/lark setup # scan QR (30s)
/lark start
Open Feishu, find your bot, send anything — reaction receipt + full reply = end-to-end. Group chats need no @-mention.
Install variants: local tarball (npm pack, then dsh plugin --profile web add ./dsh-lark-plus-<version>.tgz --ignore-scripts) or GitHub source (github:amlyczz/dsh-lark-plus, requires build approval). Upgrade with dsh plugin --profile web update dsh-lark-plus --latest --ignore-scripts.
Updating after each release
Don't rely on @latest: it resolves the mirror's dist-tags.latest label — npmmirror-style mirrors can serve a stale tag (version metadata synced, tag still pointing at an older release), so pnpm sees Already up to date even though a newer version exists. The tag is what the mirror says; the version number is what you say.
# 1. See the real version list, bypassing tags:
npm view dsh-lark-plus versions --registry https://registry.npmjs.org
# 2. Install by explicit version (most reliable):
dsh plugin --profile web add dsh-lark-plus@<new-version> --ignore-scripts
# 3. Or force the official registry with @latest:
dsh plugin --profile web add dsh-lark-plus@latest --ignore-scripts --registry https://registry.npmjs.org
Suspicious Already up to date? Run dsh plugin --profile web outdated first — if it also shows the old version, the mirror tag is stale; use an explicit version. Restart dsh web after installing.
⌨️ Commands (Feishu side)
- Selectors (single-select cards):
/mode/permission/model - Goals:
/goal [objective|pause|resume|clear](autonomous tasks / pause / resume / clear) - Status:
/status/sessions/help - Sessions:
/new/resume [index|id]/stop/workspace <path> - Diagnostics:
/doctor(ZIP with session log) - Hot reload:
/lark-config key=value - DSH commands run natively:
/compact… - Media: send images/files to the bot
- Intent confirmations auto-arrive as cards
⚙️ Configuration (/lark-config, hot-reloaded & persisted)
| Key | Default | Meaning |
|---|---|---|
groupPolicy | open | group trigger: open / mention / keywords / reply |
agentPreset | ptc | agent preset (standard/ptc/minimal/cordis or custom; legacy alias code maps to ptc) |
permissionMode | danger-full-access | read-only / workspace-write / danger-full-access |
streaming.enabled | false | CardKit streaming cards |
reactions.enabled | true | reaction receipts |
allowlist | [] | open_id allowlist (empty = everyone) |
denyList | [] | command-prefix deny |
workspaceRoot | `` | workspace root for bridge sessions |
attachments.retentionHours | 168 | retention (hours) for inbound images/files (default 7 days; 0 = keep forever). Stored under the OS temp dir and swept by age |
attachments.dir | `` | inbound media root override (empty = OS tmpdir; applies after reload) |
Credentials (appId/appSecret) live in the DSH credentials service, never in config files.
🩺 Troubleshooting
Send /doctor in Feishu — you get a ZIP with the full session log, sanitized config, and an ISSUE.md template. Hand it to any AI (or open a GitHub Issue). /status shows live connection / Outbox / replay health.
🛠 Development
npm run dev:link && npm run check && npm test && npm run build
264 unit + integration tests. GitHub Actions CI runs typecheck + tests + build on every push/PR; npm publishing rides the release-tagged Publish workflow.
Architecture (Cordis plugin, dsh.bundle format):
host (SDK adapter/auth) → inbound (transport/group policy/compensation/Inbound WAL) → application (command routing/orchestration/diagnostics) → outbound (Outbox/event forwarding/cards) → sessions (per-chat agent management).
📄 License
MIT — free to use, modify, and distribute.
This is a community plugin, not affiliated with DeepSeek, Feishu, or Lark.
归属与许可
- 本项目基于
dsh-lark-link(MIT License,Copyright (c) 2026 dsh-lark-link contributors)二次开发,保留了原项目的全部版权与许可声明(见LICENSE)。 - 新增部分:本地离线语音转写链路(
src/voice/、消息链路的audio分支、本机转写路由)以及相应的测试。 - 语音引擎 SenseVoice 与运行时 sherpa-onnx 由各自作者以 Apache-2.0 许可发布;模型文件不随本仓库分发,首次使用时从官方发布页下载。
- 本仓库以 MIT License 发布,见 LICENSE。
Plugins associés
dsh-web (dsh-ssh)
zhu1090093659/dsh-web
dsh-web (dsh-remote-web-ui)
zhu1090093659/dsh-web
dsh-web-ui (dsh-ssh)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-remote-web-ui)
zhu1090093659/dsh-web-ui