DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

0x0101010 /

0x0101010/dsh-feishu

Verified

Feishu (Lark) long-connection channel plugin for DeepSeek Harness (dsh) — zero npm dependencies

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@a10b87e7

dsh-feishu

中文 | English

A Feishu (Lark) long-connection channel plugin for DeepSeek Harness (dsh): bridges a dsh agent to a Feishu bot, so you can dispatch tasks, receive results, and approve permissions right in chat.

Zero npm dependencies — built on Node >= 22's native WebSocket plus a hand-written protobuf Frame codec (field numbers match the official oapi-sdk-go WS module). The whole plugin is a single index.js.

Features

  • WebSocket long connection: uses Feishu's official WebSocket callback (callback/ws/endpoint) — no public IP, no port forwarding, no callback server needed
  • One agent per chat: each conversation gets an isolated context; idle sessions are recycled automatically (default 30 min)
  • Approvals as interactive cards: dsh approval requests become Feishu card buttons (✅ allow / ❌ deny); click or reply y/n; the card updates in place once handled
  • Mid-turn steering: send a message while a task is running and it's injected into the current turn at the next step boundary — no interruption; /stop is the hard interrupt
  • Mode switching: /mode switches agent presets (minimal / standard / PTC / creative), orthogonal to permission presets
  • Command bridge: all dsh built-in commands (/permission /plan /compact /goal /export …) work in chat
  • Auto-reconnect (5s after close), heartbeat keepalive, event ack (prevents Feishu redelivery), seq-based dedup after resume

Requirements

  • Node >= 22 (native WebSocket; developed on 23)
  • A working dsh deployment (npx @deepseek-ai/dsh)
  • A Feishu Open Platform app (a self-built enterprise app is fine) with:
    • Events & Callbacks → long-connection (WebSocket) mode
    • Bot capability enabled
    • Scopes: im:message (send/receive), etc.

Install

npx @deepseek-ai/dsh plugin --profile feishu add /path/to/dsh-feishu

Credentials never go into config files — they come from environment variables (put them in the profile's .env, or global ~/.dsh/.env):

FEISHU_APP_ID=cli_xxxxxxxx
FEISHU_APP_SECRET=xxxxxxxx
# optional: agent working directory
DSH_FEISHU_CWD=/your/workspace

Verify the composed config and start:

npx @deepseek-ai/dsh --profile feishu --dump-config   # verify
npx @deepseek-ai/dsh --profile feishu                  # start

Configuration (cordis.patch.yml)

Key Default Description
appId required Feishu App ID (FEISHU_APP_ID)
appSecret required Feishu App Secret (FEISHU_APP_SECRET)
domain https://open.feishu.cn API domain; use https://open.larksuite.com for the international version
cwd process.cwd() Agent working directory
allowUsers [] open_id allowlist; empty = no restriction — set this in production
allowChats [] chat_id allowlist; empty = no restriction
sessionTimeoutMs 1800000 Idle session recycle timeout
defaultMode standard Default agent preset for new sessions
modeAliases see patch Mode aliases (defaults include Chinese aliases)

Security note: when allowUsers/allowChats are empty, anyone who can talk to the bot can drive your agent (executing tasks on your machine). Configure them before sharing publicly.

Slash commands

Native commands (handled by this plugin)

Command Args Behavior
/new — Dispose the current session: context cleared, agent destroyed, next message gets a brand-new agent. Use after /mode on a session with history, or to start a fresh task.
/mode — List all agent presets with descriptions and mark the current one (✅). Also shows whether any preset is broken (e.g. code needs a host runtime not present in the base bundle).
/mode <preset> id or alias Switch the chat's agent preset: minimal (极简) / standard (标准) / code (ptc) / cordis (创造). Blank session → takes effect immediately. Session with history → the choice is recorded (📌) and applies after /new (presets lock at agent creation). Unknown names list the valid ids.
/status — Current model (provider/model), active mode, chat id, agent status (running/idle), minutes since last activity, idle-recycle countdown, pending-approval indicator.
/stop — Hard-interrupt the running turn: cancels in-flight work and clears any queued inputs. If nothing is running, replies "agent idle".
/help — Built-in help text.

Approval answers (not slash commands)

When an approval card is pending, a bare y = allow, n = deny (case-insensitive). Clicking the card buttons does the same; the card is updated in place either way.

Bridged dsh commands

Everything else starting with / is forwarded to dsh's command service, so all built-in commands work in chat. Common ones:

Command Behavior
/permission Show the current permission preset
/permission <preset> Switch: read-only (files read-only, no approval needed) / workspace-write (workspace writable, out-of-bounds needs approval — default) / danger-full-access (full access, no approval)
/plan Toggle plan mode: agent plans first, executes after you approve
/compact Compress session history to reclaim context
/goal Set/view a long-running task goal
/export Export the session log
/feedback Record feedback

Unknown commands reply with the full list of what's available.

Plain messages (no slash)

  • Task running → the message is steered into the current turn: acknowledged with 📌, takes effect at the next step boundary, task keeps running. Use /stop to abort instead.
  • Agent idle → starts a new turn as usual.

In group chats, @mention the bot to trigger any of the above.

Development

node test.mjs    # offline unit tests: protobuf codec roundtrip + config validation
node debug.mjs   # debug frame encoding bytes

test.mjs extracts the pure-function blocks from index.js and roundtrips them — no dsh startup, no real credentials needed.

Protocol notes

Feishu WebSocket long-connection protocol (from larksuite/oapi-sdk-go v3 ws module):

  1. POST /callback/ws/endpoint (body carries AppID/AppSecret) returns a WS URL + PingInterval
  2. Binary frames = protobuf Frame: 1=SeqID 2=LogID 3=service 4=method(0 control/1 data) 5=headers 8=payload
  3. Heartbeat: send method=0 + headers[{type:ping}] every PingInterval
  4. Data frames have header type=event; payload is event JSON (core: im.message.receive_v1)
  5. Every event must be acked (original headers + biz_rt + {"code":200}) or Feishu will redeliver

The codec is hand-written at the top of index.js (encodeFrame/decodeFrame) — no protobufjs dependency.

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit a10b87e7a142

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout