dsh-lark
Feishu/Lark channel for DeepSeek Harness: prefix-created task sessions, thread routing, streaming thinking cards, interactive questions, media delivery, lifecycle notices, runtime policies, web mirror
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 20, 2026
- Updated
- Aug 22, 2026
Introduction
dsh-lark
Feishu/Lark channel for DeepSeek Harness (DSH), built on the deepseek-harness-lark bridge. Adds task-oriented workflows on top of the stock bridge: prefix-created task sessions with thread routing, streaming thinking cards, interactive questions, media delivery, lifecycle notices, runtime policies, and a Web UI mirror.
This is the open-source release of a plugin previously maintained as three separate packages (dsh-lark-tasks + dsh-lark-policies + dsh-lark-mirror), merged into one.
Features
| Area | Description |
|---|---|
| Task sessions | Create a task session from a main-chat prefix: ptc任务: / 标准任务: / 极简任务: / 创造任务: / 任务: (preset mapping configurable). One task = one durable DSH session, managed exactly like web sessions |
| Thread routing | Every message inside a task's thread is delivered to that task's session — no prefix needed inside the thread |
| Streaming cards | While a task runs, thinking is streamed into an interactive card inside the thread (event-driven + per-second heartbeat). Each round gets a fresh card; finished cards freeze at their final state |
| Task reports | The final answer is sent as a separate message in the same thread, with a fixed-format prefix (✅[dsh] [YYYY-MM-DD-任务-N], daily sequence number) |
| Interactive questions | ask_user_question is redirected to Feishu card buttons (with text-reply fallback) instead of an invisible web prompt |
| Media delivery | lark_send_media (image/file/audio/video, ≤30 MB), lark_send_bigfile (>30 MB → cloud drive + link, view permission granted to the sender), lark_create_doc (markdown → Feishu docx) |
| Lifecycle notices | 🔴 shutdown / 🟢 recovery notices delivered to the user's DM (auto-learned or configured) |
| Runtime policies | Exact restartCommandText (default 重启进程) restarts the DSH process; single-turn hard time limit (default 6 h); global Chinese-output prompt section |
| Web mirror | One-way sync of task sessions into the Web GUI: /lark-mirror/* read-only routes + "飞书任务" sidebar panel; task sessions grouped into a "飞书" workspace |
Install
The stock lark-channel from deepseek-harness-lark is disabled and replaced by this plugin. Place the package under a DSH profile (plugins/ or node_modules/), then in cordis.patch.yml:
- id: lark-channel
disabled: true
- insert:
- id: lark
name: dsh-lark
config:
appId: <your feishu app id>
appSecretRef: LARK_APP_SECRET
cwd: !!js process.env.DSH_LARK_CWD ?? process.cwd()
lifecycleChatId: <optional: DM chat id for lifecycle notices>
restartCommandText: 重启进程
turnHardLimitHours: 6
Credentials are resolved through the DSH credential store (appSecretRef names an env var / credential entry — never put the secret in the patch file).
Configuration
The config is the union of the three merged plugins' keys. Highlights:
| Key | Default | Description |
|---|---|---|
appId / appSecretRef | — | Feishu app credentials (required) |
taskPresets | ptc→code, standard→standard, minimal→minimal, creation→cordis | Prefix → agent preset mapping |
taskPermission | danger-full-access | Permission preset pinned on new task sessions ('' disables; Feishu has no interactive approval surface) |
registryPath | ~/.dsh/lark/registry.json | Task registry persistence (override to keep historical data from older layouts) |
reportSymbol / reportIdentity / reportTaskLabel | ✅ / dsh / 任务 | Task report prefix parts |
restartCommandText | 重启进程 | Exact user message that restarts DSH |
turnHardLimitHours | 6 | Single-turn hard cap in hours (0 disables) |
questionEnable / questionTimeoutMs | true / 30 min | Feishu interactive question behavior |
lifecycleChatId | auto-learned | DM chat id for 🔴/🟢 notices |
Known upstream issue
Long markdown/text replies are chunked by the official SDK, and only the first chunk carries replyTo — pages 2+ land in the main chat instead of the thread (affects long task reports). Root cause is in @larksuiteoapi/node-sdk's OutboundSender:
- larksuite/node-sdk#205
- sliverp/DeepSeek-harness-lark#1
Until an upstream fix ships, patch the bundled SDK code in dist/index.js (two lines):
- replyTo: i === 0 ? opts.replyTo : void 0,
+ replyTo: opts.replyTo,
(sendMarkdown and sendText — 2 occurrences; verified in production: all chunked pages stay in the thread, mentions still only on page 1.)
Development
node --check lib/*.js
node test/self-test.mjs
License
MIT