DeepSeek Harness Plugin

john-walks-slow/dsh-im-humanize

Stars ★ 0 Category Notifications & Integrations Added 2026-09-20

Humanized fork of @xmanrui/dsh-im (base 4.21.2): humanized message delivery with send-delay and typing two-phase, message_break + streaming coexistence, status reactions, reply quotes, per-bot humanize overrides, and a no_reply reclaim tool — across WeChat, Feishu, DingTalk, WeCom, QQ, Telegram, Slack and WhatsApp channels.

Install

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

dsh plugin --profile web add github:john-walks-slow/dsh-im-humanize

Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).

README



Introduction

Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest, or entering existing bot credentials, and let the local Harness connect outward to a public AI Office. One plugin and one settings entry manage nine multi-bot IM channels and the AI Office Connector.

This fork: humanized messaging

This repository is a fork of xmanrui/dsh-im focused on humanized messaging for role-play immersion. It keeps every upstream feature and adds settings configured in the Humanization settings section under Settings → IM bots → General settings; all humanization settings can additionally be overridden per bot on each channel's bot card:

At a glance: all differences from upstream

Change Default Description
Streaming replies streaming on When off, sends the complete reply at once instead of pushing output word by word
Message breaks message_break off Registers a no-op tool; the model calls it to split long replies into multiple messages
New message behavior onNewMessage interrupt interrupt / queue / steer; upstream only has queue
Status emoji reactions statusReaction on When off, the six channels send no processing/success/failure emoji
Reply quotes replyQuote on When off, Telegram/Discord/WhatsApp replies carry no quote header
Progress hints progressStatus on When off, no "Processing…/Using tool…/Gathering results…" placeholder or interim progress bubbles; streaming text still streams word by word
Send delay sendDelay off Two-phase read delay + segment gap, with activity boost
Typing indicator typingIndicator burst off / continuous / burst
QQ messageBreak scoping fix Fixes an upstream messageBreakHandler scope defect
QQ typing session rewrite Bridge-managed 55s/50s session replaces the dead SDK middleware
Delay-window double-reply fix Superseded turns are silently cancelled, no double reply

Upstream sync note: this branch is a long-lived fork and keeps merging updates from xmanrui/dsh-im upstream, staying fully compatible when features get merged. Message breaks, the streaming toggle, the send delay, and the typing indicator depend on this fork's extension of the Harness reply tracker (HarnessReplyTracker) and channel bridges and are not available in the upstream repository.

  • Streaming replies (streaming, on by default): when disabled, model output is no longer pushed progressively; the complete reply is sent at once when the turn finishes, closer to real human reply pacing. Can be enabled alongside message breaks.

  • Message breaks (message_break, off by default): the plugin registers a no-op tool named message_break (it executes nothing; it only marks a break point inside the reply). When the model calls it deliberately in a long reply to "take a breath", the plugin sends the text accumulated before the break as a separate message and then continues with the following segments, so one answer becomes several messages that read like someone typing line by line. Natural spots are between the thinking/tool progress and the final answer, between paragraphs of long answers, and at topic transitions; at most 20 segments per turn, and whitespace-only segments are skipped.

  • New message behavior (onNewMessage, interrupt by default): what happens when the user sends a new message while the model is still generating:

    • Interrupt & resend (interrupt): cancels the current turn and immediately re-asks with the new message;
    • Queue & wait (queue): processes the new message after the current turn finishes (upstream default);
    • Inject as steering (steer): does not interrupt the generation; the new message text is injected as a steering instruction for the current turn, and the model weaves it into the tail of its answer.

    When the turn is waiting for user interaction (question/approval pending, verification, etc.), the message is always queued so the interaction flow is never disturbed by new input.

  • Status emoji reactions (statusReaction, on by default): the bot marks task status with emoji reactions on the user's message (processing/success/failure — 👀 → 👍/👎 on Telegram, for example). Turn it off to send no reactions at all; replies still deliver. Applies to Telegram, Discord, WhatsApp, Slack, Feishu, and DingTalk.

  • Reply quotes (replyQuote, on by default): the bot quotes the user's message when replying (the quote header at the top of a reply). Turn it off and replies go out as plain messages. Only affects the quote style on Telegram, Discord, and WhatsApp; topic routing (Telegram topics, Discord threads, Slack threads, Feishu reply-in-thread) and conversation grouping are unaffected.

  • Progress hints (progressStatus, on by default): show interim status bubbles while processing (e.g. "Processing…", "Using tool…", "Gathering results…"). Turn it off to send no placeholder or interim progress text — replies arrive directly while streaming text still appears word by word. When message_break is also on, turning this off additionally skips the placeholder stream entirely (segments are sent directly, removing the duplicate top bubble). Applies to all chat channels; QQ/WeChat already have no interim progress, and AI Office job progress is unaffected (core product UX).

Send delay (two-phase model)

The send delay splits the human feel into two phases matching the real gaps in human messaging:

  1. Read delay (readDelay, phase 1): after a message arrives, the bot stays silent for a while before it starts processing — as if it only noticed the message later. No typing indicator and no read receipt appear during this silence. The duration is random within minMs–maxMs, plus two optional terms:

    • Length reading term (charsPerSecond): longer user messages take longer to "read" (character count divided by a reading speed);
    • Activity boost (activityBoost): right after a quick exchange the bot "replies in seconds", and the delay recedes toward the full range as the conversation goes idle — for fastWindowMs (default 1 min) after the previous turn ends, use fastReplyMs (default ~1 s) directly; ramp linearly back to the read-delay floor by minWindowMs (default 2 min); past fullWindowMs (default 5 min) return to the full random range. The first message is never accelerated.

    The total is capped by maxTotalMs; channels without a typing-status API (DingTalk, WeCom, Feishu, Slack, …) cap the read delay at 5 seconds. DingTalk segment gaps are additionally floored at 3 seconds (webhook rate limit).

  2. Segment gap (segmentGap, part of phase 2): the "typing the next message" pause between message-break or streamed segments, likewise random within minMs–maxMs with an optional per-segment length term.

Supersede semantics: if a new message arrives (interrupt mode) or /stop runs while the read delay is ticking, the old turn is silently cancelled — no generation, no send, no "processing failed" notice, no double reply — and the new message takes over immediately. In queue mode messages are processed one by one and their delays accumulate (each one is "read" in turn).

The send delay is off by default (enabled=false), in which case behavior matches upstream exactly, apart from the supersede fix above. The settings panel exposes the full parameter face: read-delay min/max, reading speed (chars/sec), per-turn cap, activity boost (fast reply plus the fast/floor/full recovery windows), segment gap and segment typing speed, folded advanced burst-rhythm fields (on/off durations in ms), plus exploration presets (Lightly human / Slow-paced / Immersive role-play / Instant reply) that fill every field at once. The config file (~/.dsh/integrations/dsh-im/humanize.json) exposes the same parameters. Each bot can override any humanization setting on its channel card's "Humanization" panel (streaming, message break, status reaction, reply quote, on-new-message behavior, typing indicator, burst rhythm, send delay): each setting can be set to "follow global" or a custom value; only customized settings are saved, while the rest continue to track the global default.

Typing indicator (typingIndicator)

How "typing…" is displayed once processing starts, in three modes:

  • Off: no typing indicator at all;
  • Continuous: shown continuously while processing;
  • Bursty (default): flickers on and off like a real person — a few seconds on, a second or two dark, then on again — avoiding the bot-like endless glow. The on/off rhythm (typingBurst ranges) is tunable in the config file.

Channel capabilities: Telegram / Discord / WhatsApp (composing presence) support all three modes; WeChat fetches and keeps alive an input ticket once the read delay ends; QQ supports direct chats only (the group API does not exist) and now uses a bridge-managed typing session (55 s display / 50 s renewal) instead of the dead SDK middleware relied on upstream; DingTalk, WeCom, Feishu, and Slack have no typing API and ignore this setting. The indicator pauses while an interaction (question/approval) is pending and always goes dark when the turn ends (including /stop and failures).

Bug fixes (upstream defects)

The following issues exist in upstream xmanrui/dsh-im v4.13.0 and are fixed in this fork:

  • QQ bridge messageBreakHandler scoping bug: in upstream, any successful turn with message_break enabled threw a ReferenceError and misreported a task failure (also the root cause behind 4 baseline test failures). This fork fixes the scoping so message_break works correctly on QQ.
  • Double replies for turns superseded during the delay window: when a new message (interrupt) or /stop arrives while the read delay is ticking, the old turn is silently cancelled — no generation, no send, no "processing failed" notice, no double reply — and the new message takes over immediately. Superseded batch inputs are retained for /send retry. Upstream's queue mode was unaffected; this fix covers interrupt mode.

Configuration migration

  • readDelay.idleBoostreadDelay.activityBoost (semantic inversion): the early "idle boost" (the longer the idle, the slower the reply) is semantically inverted and replaced by "activity boost" (fast replies right after a quick exchange). A stored idleBoost key is ignored on load and falls back to the new defaults; if you had tuned the idle boost, re-configure the activity boost in the settings panel.

Interface

IM bot settings page

Built-in channels

Channel Setup Messaging and replies
Feishu Create a bot by QR code, or bind one with App ID + App Secret Persistent connection for incoming messages; streaming cards show thinking, tool progress, and replies
WeChat Scan a QR code to bind a WeChat bot Tencent iLink long polling; shows a typing indicator while Harness works, then sends the final reply in 1,800-character chunks
DingTalk Create a bot by QR code, or bind one with Client ID + Client Secret DingTalk Stream connection; streaming replies through AI Cards
WeCom Create an intelligent bot by QR code, or bind one with Bot ID + Secret Official WebSocket connection; native thinking state, tool progress, and streaming replies
QQ Create a bot with mobile QQ QR scanning, or bind one with AppID + AppSecret WebSocket connection; private chats show typing and receive one Markdown reply, while mentioned group chats receive only the final answer
Slack Create an app from the bundled App Manifest, then enter a Bot Token (xoxb-) and App Token (xapp-) Socket Mode connection; direct DM replies, mention-only channel replies, and preferred native streaming API
Telegram Enter a Bot Token generated by @BotFather Bot API long polling; DMs work by default and groups respond to mentions or replies, while each bot can optionally enable a private-DM allowlist; private chats stream through a Rich Message Draft and persist one rich final, groups and Topics finalize their placeholder in place, and unsupported Rich delivery falls back to ordinary text
Discord Enter a Bot Token generated in the Developer Portal Gateway v10 connection; direct DM replies; the first mention in a server text or announcement channel creates a native Thread, where follow-up messages no longer need to mention the bot; replies stream through message edits
WhatsApp Scan a QR code with mobile WhatsApp to link a device WhatsApp Web connection; self-chat only by default, with optional selected-contact and open-response modes; read receipt and typing indicator, with tool progress and incremental answers shown by editing one message at one-second intervals; long replies split automatically and failed edits fall back to a complete text reply

Other IM platforms can be added through the same channel-adapter structure.

All nine built-in channels can send JPEG, PNG, and WebP images, plus GIFs sent as image files, with optional captions to Harness. Each image is limited to 5 MB, and images in one message are limited to 20 MB in total. Downloading images or files from Feishu user messages requires the im:message:readonly tenant scope, shown on the confirmation page as Read direct and group messages; Feishu currently offers no narrower image-only scope for that download endpoint. Apps created through the built-in QR flow request it by default; for existing or manually connected apps, click Complete permissions on the IM Bot settings page and scan the QR code to incrementally add that scope, im:resource for uploading bot-sent images or files, application:app_slash_command:read / write for the native command panel, and the card callback.

Results after a reply timeout

All nine channels share deferred task tracking. After a model reply timeout, the plugin keeps checking the original task and delivers its final text to the original chat or thread. Checks resume after a plugin restart or reconnection. /stop only stops the matching turn submitted by that chat; changing the bound Session prevents old results from being delivered there. No new setting is required, and normal replies keep their existing flow.

Channel permissions and quotas still apply. Definite send failures allow up to three attempts; uncertain delivery is retained without automatic retries to avoid duplicate messages. Recovery covers final text and terminal notices, without replaying questions, approvals, or file-tool calls. See the deferred delivery notes.

Result-file and image delivery

All nine built-in channels can return any file readable by Harness as a native channel attachment. Existing files and files created by the current task can both be sent directly. The capability is available to every connected bot by default, with no switch or per-bot allowlist, while existing text, image, streaming, command, and Session behavior remains unchanged.

After the model calls the file-return tool, the plugin hands the specified file to the channel's native API. Images prefer native image messages; if a channel does not support or definitively rejects image delivery, the plugin falls back to a file attachment, while an uncertain result never triggers a duplicate fallback. The plugin adds no rules for file origin, creation time, workspace boundary, extension, content, count, size, or lifetime; the file only needs to exist and be readable. A channel may still reject delivery according to its own permissions, quota, file capability, or account tier, and the plugin reports that provider result.

Animated GIFs render according to each channel's native capability and differ: Telegram sends .gif via the native animation message (sendAnimation), so the client plays it inline on loop; the WeChat (iLink) protocol only offers image messages and has no separate emoji/animation message type, so a GIF sent as an image shows only the static first frame and cannot animate inline (a protocol-level limit, not something the plugin can fix). Other channels follow whatever their native image message does with GIF. The file name must carry a .gif extension to take the image/animation path; a GIF without the extension is sent as an ordinary file.

Channel Platform requirements
WeChat The current binding protocol and conversation must support native file messages; the WeChat API response determines the actual range.
Feishu Feishu's file-upload API requires a non-empty file no larger than the platform's 30 MB limit. The app needs the im:resource tenant scope (Read and upload images or other files). Apps created through the built-in QR flow request it by default; existing or manually connected apps can add it incrementally through Complete permissions or /repair in a direct chat, followed by any approval Feishu requires. The Feishu developer console currently has no separate im:resource:upload scope.
DingTalk The app needs qyapi_base, and the bot must support file messages. The current OAPI and bot capability determine the accepted formats and sizes.
WeCom The app needs media-upload and file-message capability; the WeCom API response determines the actual range.
QQ The bot needs file-message capability and remains subject to QQ's daily upload quota; the bot reports when the quota is exhausted.
Slack The Bot Token needs files:read, files:write, and reactions:write; the Workspace's current policy determines the actual file-size limit. After changing scopes, re-authorize/reinstall the App and reconnect the bot.
Telegram The bot must be allowed to send documents in the current chat; the Bot API response determines the actual range.
Discord Enable Message Content Intent in the Developer Portal. The bot needs Send Messages, Create Public Threads, Send Messages in Threads, and Read Message History; result-file delivery also requires Attach Files. The current account and server capability determine the actual attachment allowance.
WhatsApp The linked session must support Document Messages; the WhatsApp/Baileys response determines the actual range.

AI Office Connector

Read the AI Office Connector guide

Installation

Install the published stable release from npm (recommended):

dsh plugin --profile web add -w @xmanrui/dsh-im

Restart dsh web, refresh the browser, then open Settings → IM Bot. The top-level IM Bot entry uses order: 21 to follow Agent Presets, and the Plugins page no longer retains the old entry. Upgrading preserves existing bots, credentials, workspaces, Agent Presets, and Session bindings.

Local dsh web and DSH Desktop reuse the current Host's internal services by default: legacy Harness releases use apiProxy, while current releases automatically use the Typert Gateway plus the Session and Workspace controllers. No Harness address or loopback HTTP connection is required. Desktop's compatibility, extended-window, and advanced modes do not require browser access or LAN access to be enabled. An explicit channel harnessBaseUrl is retained only for legacy remote HTTP/WebSocket Harness endpoints; failed internal calls never silently switch to another Host.

To try the latest code before it is published to npm, use the GitHub-source installer instead:

npx -y github:xmanrui/dsh-im install

A GitHub-source installation fetches and builds a Git dependency directly. With pnpm 10 or newer, the profile may first need an allowBuilds entry in pnpm-workspace.yaml. Most users should prefer the stable npm release.

After installation, follow the built-in instructions on each channel page to scan a QR code or enter credentials. Secrets and Tokens are sent only to the local Harness Host and stored through its protected credential provider; status responses and bot lists never return them.

If this machine must use a forward proxy to reach Feishu, set HTTPS_PROXY to a full HTTP proxy URL before starting dsh web (for example, http://proxy:8080; lowercase https_proxy is also supported, with HTTP_PROXY accepted as a fallback), then restart the Host after changing it. Feishu registration and credential verification reuse the SDK's proxy-aware HTTP client, while the message WebSocket explicitly uses that proxy; the WebSocket path does not currently read ALL_PROXY or NO_PROXY.

If this machine cannot reach the Telegram Bot API directly, use Node.js 22.21 or newer and enable Node's environment proxy support before starting dsh web:

NODE_USE_ENV_PROXY=1 \
HTTPS_PROXY=http://proxy:8080 \
HTTP_PROXY=http://proxy:8080 \
NO_PROXY=localhost,127.0.0.1 \
dsh web

Use the proxy URL required by your network and restart the Host after changing it. If Telegram Bot Token binding reports that the Bot API cannot be reached, first check the proxy URL, Node.js version, and NO_PROXY configuration.

Default behavior Description
Bot workspace Each bot stores its workspace independently. New bots start with the Host's current working directory, which can later be changed from the bot card.
Model Every bot in all nine IM channels can choose a model directly below its workspace, or follow the Host default. A change applies only to later new Sessions; send /new and then an ordinary message in the current chat to use it.
Agent Preset Each bot can choose an Agent Preset on its settings card. When none is chosen, new Sessions follow the Host's agent-presets.default. A channel-level config.agentPreset is only the default for later new bots on that channel. Changing the preset never modifies or clears existing Sessions; if the current chat already has a Session, send /new and then a regular message to create one with the new selection.
Context enhancement Open settings from a bot card to enable groups and DMs independently. Both switches default to off, including for existing bots after an upgrade.

Proactive delivery

All nine IM channels can proactively send text through a stable botId + targetId pair. Bot settings support choosing a known conversation or entering a target manually, testing the current route before saving, and copying call parameters. HTTP POST, same-Host plugins, and Connection RPC share the same target configuration and delivery core.

Saved direct-message targets also offer an opt-in Two-way Session sync switch. Once enabled, user text submitted from DSH Web/CLI and the final assistant text in that DM's current Session are mirrored back to the DM; ordinary IM prompts and /steer are not duplicated. The switch follows the current Session across /session, /new, and workspace changes. The first version supports text DMs on the current Host only; groups, Topics, Threads, and explicit remote harnessBaseUrl connections are unavailable.

See the Proactive Delivery Guide (简体中文) for setup steps, native fields for all nine channels, complete call examples, management endpoints, error codes, and troubleshooting.

Context enhancement

Read the context enhancement guide

Access modes

Read the access modes guide

Checking and installing updates

Read the update-checking and installation guide

Bot commands

Command Description
/help Show the commands and usage supported by the bot.
/menu, /m Open the Feishu, DingTalk or Enterprise WeChat interactive menu. DingTalk arranges session, workspace, preset and model dropdowns in two columns; selections apply immediately and update the same card. WeCom requires Apply after selecting and also opens on the daily direct-chat entry event. Menus include new session, stop, compact, status and help buttons.
QQ /menu, /m Open a button and numbered menu for session selection, workspace, mode/preset, model, new session, session list, stop, compact, steering, archived-session visibility, status and help. Lists support pagination; reply with a number when buttons are unavailable. Menus are scoped to the chat and actor and expire after 15 minutes or restart. Ordinary messages exit number selection; questions, approvals and batch input retain priority.
/new Unbind the current chat so its next ordinary message starts a new Harness Session.
/status Check the connection between the current bot and DeepSeek Harness.
/version Show the version of the running dsh-im plugin.
/models List every currently configured model with a number.
/model Show the model and reasoning effort used by the Session bound to this chat.
/model <number or provider/model-id> [reasoning effort ID] Switch the Session model and optionally select an effort supported by the target model.
/reasoninglist, /reasonings Equivalent aliases that list the reasoning efforts supported by the current model.
/reasoning Show the current Session model and reasoning effort.
/reasoning <number or effort ID> Switch the current model's reasoning effort.
/reasoning --default Restore the current model's default reasoning effort.
/presetlist, /presets Equivalent aliases that list the Host's currently available Agent Presets, marking the Host default and this bot's selection.
/preset Show this bot's Agent Preset setting for new Sessions.
/preset <number or Preset ID> Set this bot's Agent Preset; use /preset id:<ID> for a numeric ID.
/preset --default Clear this bot's explicit selection so later new Sessions follow the Host default.
/stop Immediately stop this chat's running task while preserving work that has not started.
/steer <additional instruction> Inject an additional instruction into this chat's running task.
/batch Start batch input in a direct chat and collect up to 10 text messages.
/send Submit the collected messages, in order, as one input.
/cancel Cancel batch input and discard its collected messages.
/repair In a Feishu direct chat, incrementally repair the card callback and permissions required for media and the native Slash Command panel.
/compact Immediately compact older context in the Session bound to the current chat.
/workspace <workspace index or absolute path>, /ws <workspace index or absolute path> Switch the current bot's Harness workspace by /workspacelist index or absolute path.
/workspacelist, /workspaces, /wsl List workspace absolute paths that still exist on the current Harness Host.
/sessionlist [workspace number or absolute path], /sessions [...] Equivalent aliases that list every registered session ID and title in the selected workspace; omit the argument to use the current workspace.
/sessionlist --limit N, /sessions --limit N List the first N sessions in the current workspace's existing order; N must be a positive integer.
/session <Session ID> Bind the current chat to an existing Harness session.
/history [count] Preview recent messages from the bound Session in a direct chat; defaults to 3, capped at 5.
Interactive question Reply with an option number, option label, or custom text; separate multiple choices with commas.
Remote approval Reply with 批准 / 拒绝 / 同意 / 不同意 / yes / no.

Command details

Read the command details

DingTalk menus use a shared template built into the plugin; no template setup is needed for each bot. A menu stays active for 30 minutes. Send /m again after expiry or a Host restart. Maintainers can import assets/dingtalk-menu-template.json into DingTalk's card platform to maintain the template.

Other features

  • Image understanding: all nine built-in channels can send JPEG, PNG, WebP, and GIF files sent as images to Harness, with an optional text description. Each image is limited to 5 MB, and all images in one message are limited to 20 MB in total.
  • Switch workspaces from a bot card: every bot card on the settings page shows its current Harness workspace. Enter an existing absolute directory path directly or open the directory picker. Switching clears only that bot's old chat mappings; it never deletes, empties, or archives old Sessions. Replies already in progress may finish, while later messages use the new workspace.
  • Choose a model from a bot card: every bot card in all nine IM channels offers the Host's available models directly below the workspace, plus an option to follow the default. The selection is stored per bot and used only for later new Sessions; existing Sessions and replies already in progress are unchanged.
  • Choose an Agent Preset from a bot card: every bot card can select one of the Host's existing Agent Presets, or follow the Host default. The change applies only to that bot and only to later new Sessions; existing Sessions and replies already in progress are left unchanged.
  • Check the connection and send a test message: when a bot is online, clicking Check connection verifies the platform connection and sends a “DeepSeek Harness connection test succeeded” message to the bot's most recently remembered direct conversation; WhatsApp uses the account's self-chat. The test neither creates a Harness Session nor invokes the model. The bot must have received at least one direct message before it has a remembered test target; otherwise the page reports that no test conversation is available yet.
  • Retry a connection or remove an integration: when a bot is offline, its card action changes to Retry connection. Use Remove integration when the bot is no longer needed. Each action affects only the selected bot and leaves other bots and channels unchanged.
  • Manage multiple bots independently: a channel can have multiple connected bots. Credentials, connection state, workspace, model, Agent Preset, and chat-to-Session mappings are kept separately for every bot, so card actions do not affect sibling bots.
  • Streaming replies and progress: the plugin uses each platform's available capabilities to show thinking state, tool progress, and incremental answers. Platforms without a native streaming API complete replies through message edits, card updates, or a final message.

Design

  • Registers one top-level IM Bot settings page containing nine IM channels and one AI Office Connector.
  • Maintains the Host, client, and runtime sources for all nine channels and the Office Connector in this repository without external standalone plugins.
  • Follows the DeepSeek Harness language preference and switches the settings UI live between Chinese and English. Bot chat messages follow the Host's language config (Chinese by default; en switches them to English), with Chinese always as the fallback so untranslated text is sent verbatim.
  • Uses logos for WeChat, Feishu, DingTalk, WeCom, QQ, Slack, Telegram, Discord, WhatsApp, and AI Office navigation without enable/disable switches.
  • Keeps RPC endpoints, credentials, connection supervision, and session mappings isolated by IM channel; the Office Connector separately owns Device credentials, Job leases, approval waits, and concurrency limits.
  • Returns only QR codes, the public Slack Manifest, redacted status data, and access modes or allowlist identifiers explicitly saved for the current Telegram or WhatsApp bot. Manually entered secrets and Tokens travel one way to the local Host; no RPC response returns App Secrets, bot_token, DingTalk client_secret, WeCom Secrets, QQ app_secret, Slack Bot/App Tokens, Telegram/Discord Bot Tokens, WhatsApp linked-device keys, AI Office Device Tokens, or other raw user identifiers observed from platform messages.

Local development

npm install
npm run check
node bin/dsh-im.mjs install --source .

npm run check runs unit tests, builds the Host and Client artifacts, and verifies that the published package contains neither credentials nor standalone channel settings-page registrations.

IM management RPCs accept loopback browsers by default. When a Web profile is deliberately served on a trusted LAN, opt the plugin into the Host authorities already trusted by Connection in that profile's cordis.patch.yml:

- id: xmanrui-dsh-im
  config:
    rpcAuthority: trusted-host

trusted-host reuses Harness's Host/Origin fence; it is not user authentication. Anyone who can reach that LAN authority can inspect bot status, scan or submit application credentials, reconnect bots, and remove bots. Enable it only on a trusted network.

Bot chat message language

Bot chat messages are in Chinese by default. To switch them to English, set language: en in the plugin config (also accepts en-US or english), or set the DSH_IM_LANGUAGE=en environment variable:

- id: xmanrui-dsh-im
  config:
    language: en

Without a setting, Chinese is used. Chinese is always the fallback language — any text missing from the English dictionary is sent verbatim in Chinese, so this feature never changes the behavior of existing Chinese users.


Contact

Join the WeCom community group, or reach me by email, WeChat, Xiaohongshu, or WhatsApp.

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →

Community comments

Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.