dsh-im
xmanrui
通过扫码或机器人凭据把IM机器人接入DeepSeek Harness(支持飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord和WhatsApp)。 Connect IM bots to DeepSeek Harness via QR code or credentials (9 channels).
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:addozhang/dsh-discord
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
A Discord-first adapter for DeepSeek Harness: run DSH sessions from your Discord guild — mention the bot with a task, a thread opens, the answer streams in, and approvals and questions arrive as buttons you can answer from your phone.
No extra process: the adapter is a DSH plugin that mounts straight onto your dsh web profile. Session state stays in DSH; durable bindings live in the profile's storage domain.
@bot <task> in a bound channel anchors a thread (your message becomes the first post), creates the DSH session, and submits the prompt at most once. Follow-ups inside the thread queue without a mention. Attached images ride along: they are downloaded from the Discord CDN within strict size/host bounds and submitted as image parts for multimodal models./steer, /stop, and /queue list|remove with turn-ownership checks; /project bind|list|info and /session resume for guild↔workspace binding and history; /guild forget for operator cleanup./model show reads the session's live model directory; /model select walks an interactive provider → model → reasoning cascade, or applies a typed provider/model directly. Open to any authorized member by default; restrictable to Host operators./permission show / set read and switch the session's permission preset (bundled sandbox + approval tiers) through the Host's own /permission command path, inheriting its journal audit pair; danger-full-access requires a button confirmation.allowed_mentions on every request, plus byte-level neutralization of the wire body. DSH submission is at-most-once with unknown-preserving reconciliation — an ambiguous delivery is never blindly resent. Bindings survive restarts, and the READY sweep rebuilds deleted category/control channels while treating a deleted workspace channel as user intent (the mapping retires; the workspace stays bindable).^22.19.0 || >=24Two channels ship in parallel, each pinned to the dsh host surface it was verified against. Pick the adapter and the dsh CLI from the same row:
| Channel | Adapter | dsh CLI | Install |
|---|---|---|---|
| next (0.2.0 line) | >=0.6.0-rc.1 — npm next |
0.2.0-rc.2 — npm latest/next |
dsh plugin --profile web add @addozhang/dsh-discord@next |
| stable (0.1.7 line) | 0.5.0 — npm latest |
0.1.7-rc.1 — npm next |
dsh plugin --profile web add @addozhang/dsh-discord |
0.6.x carries runtime dependencies (dsh-storage-domain/dsh-credentials) pinned to the dsh 0.2.0 line — on a 0.1.7 host the exact-version compatibility gate disables them (the storageDomain service never arrives and the plugin stays inactive); adapter 0.5.0 is disabled on a 0.2.0 host symmetrically. Adapter >=0.5.0-rc.4 (including 0.5.0) speaks the 0.1.7 profile-backed settings forms and controller services and will not load on older hosts (the startup probe refuses with one actionable diagnostic); 0.5.0-rc.1–rc.3 target dsh 0.1.6-alpha; adapter 0.4.x talks to the former apiProxy surface, which 0.1.6-alpha removed — it remains the pairing for the dsh 0.1.5 stable line, reachable by exact version (e.g. @addozhang/dsh-discord@0.4.0). A mismatched pair fails at startup.npm install -g @deepseek-ai/dsh@latest (0.2.0-rc.2, pairs with adapter 0.6.0-rc.1) or npm install -g @deepseek-ai/dsh@next (0.1.7-rc.1, pairs with adapter 0.5.0).next release, the @next spec can resolve to a stale cached version. If the installed copy looks old, install by exact version instead (e.g. @addozhang/dsh-discord@0.5.0-rc.4) and verify the version field inside the profile's node_modules.Install with the dsh CLI — it installs the package into the profile and registers the bundle for you. The stable channel is shown below; for the next channel use the @next command from the Versions table (up / rm take the same spec):
dsh plugin --profile web add @addozhang/dsh-discord
Then restart dsh web and refresh the browser. dsh plugin reconciles the profile's bundle list for you — nothing to edit by hand.
Upgrade and removal use the same command:
dsh plugin --profile web up @addozhang/dsh-discord # upgrade; the bundle list reconciles again
dsh plugin --profile web rm @addozhang/dsh-discord # remove; run /guild forget first to clean adapter records
If you manage a profile without the CLI, the manual equivalent is to add the package with pnpm inside the profile directory and list it in dsh.profile.bundles yourself:
{
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@addozhang/dsh-discord"] } }
}
All keys live in the dsh-discord settings namespace and can be set either from the settings card or by editing the profile's user settings (settings.yaml):
| Key | Default | Meaning |
|---|---|---|
enabled |
false |
Adapter master switch; the card's Connect starts it once a token is stored. |
allowedGuildIds |
[] |
Guild allowlist. Anything outside is ignored with zero adapter or DSH calls. |
memberUserIds / memberRoleIds |
[] |
Member-level authorization inside an allowed guild. |
administratorUserIds / administratorRoleIds |
[] |
Workspace-administrator level (/project bind). |
deniedUserIds / deniedRoleIds |
[] |
Deny entries; they win over every grant above. |
hostOperatorUserIds |
[] |
Host operators (/guild forget; /model select when modelSelectOperatorOnly is enabled). |
modelSelectOperatorOnly |
false |
Restrict /model select to Host operators (settings.yaml only; the card does not expose it). Default false: any authorized member may switch, and the switch still updates the Host default. |
permissionSelectOperatorOnly |
true |
Restrict /permission set to Host operators (settings.yaml only). Default true — stricter than /model because danger-full-access disables both sandbox and approval; loosen to let any authorized member switch. |
defaultVerbosity |
essential-tools |
Tool-activity row granularity: text-only, essential-tools, or full-tools. |
language |
auto |
Bot-visible copy language: auto follows the DSH language preference (non-Chinese renders English), or pin zh/en. |
streamUpdateIntervalMs |
800 |
Coalescing budget for stream edits (250–10000). |
typingIntervalMs |
7000 |
Typing-indicator heartbeat (1000–30000). |
approvalTimeoutMs |
600000 |
Approval ask deadline (30000–86400000); overdue asks auto-reject. |
questionTimeoutMs |
1800000 |
Question ask deadline (30000–86400000); expiry cancels the owning turn. |
threadAutoArchiveMinutes |
1440 |
Task-thread auto-archive: 60, 1440, 4320, or 10080. |
dsh-discord:
allowedGuildIds: ["1517134847850709032"]
language: auto
The settings card exposes the three high-frequency fields (guild allowlist, auto-archive, language) plus the connection and token surface; every other key is fully supported through settings.yaml. An invalid stored section preserves the last known-good configuration.
/model select works for any authorized member by default (single-user deployments). To restrict it to Host operators, add their IDs under hostOperatorUserIds and set modelSelectOperatorOnly: true in settings.yaml. /guild forget always requires a Host operator.| Command | Where | What |
|---|---|---|
/project bind |
any channel | bind the guild to a workspace (admin; provisions the home channel) |
/project list / info |
any channel | list workspaces / inspect this channel's binding |
/queue list, /queue remove |
session thread | inspect and trim the pending queue |
/steer, /stop |
session thread | steer or cancel the running turn (owner only) |
/model show / select |
session thread | show the live model directory; select without arguments walks the interactive provider → model → reasoning cascade (any authorized member by default) |
/session resume |
project channel | pick one of this workspace's past sessions (autocomplete: title and age, newest first) and resume it into a new thread of this channel; blank, already-bound, subagent, and archived sessions are never offered. The thread renders the session's history — answers and tool summaries plus the user's inputs as quoted echo lines (plugin/system injections are never echoed). After an adapter restart, threads catch up only what they missed: a persisted render watermark suppresses already-delivered history, and bound sessions re-subscribe on reconnect so turns prompted from the web UI still land in their thread |
/guild forget |
any channel | operator-only removal of adapter records |
/permission show / set |
session thread | read or switch the session's permission preset (view only / workspace edit / full access — bundled sandbox + approval tiers, catalog read live from the Host). set danger-full-access asks for a button confirmation first; presets autocomplete; Host operators only by default (permissionSelectOperatorOnly can loosen it). Every switch — from Discord or the web UI — renders one system line in the thread |
inject: ['sessionController', 'workspaceController', 'sessionQuery', 'webServer', 'credentials', 'settings', 'storageDomain', 'connection', 'commands', 'permissionPresets']) that mounts the Discord Gateway, command surface, stream renderer, and the settings card onto the DSH web profile.DSH_DISCORD_BOT_TOKEN ref over the plugin management channel, then triggers the start chain. Disconnect keeps the credential; an empty reconnect uses it.resolve() because the Host's describe() misses env-sourced values — a connected adapter never reads as unconfigured.DSH_DISCORD_TRACE=1 before booting to emit mux frames, drop points, and delivery outcomes to stderr (default silent). It exists because the Host wires no plugin log exporter and exposes no log-level switch at this surface — logger.debug output is unobservable — and should be dropped once the Host grows one./preset, /skill, and /host stay deregistered — their control modules are implemented and unit-tested and return when the router wires them (the /preset thread-context guard rides along).pnpm install --ignore-scripts
pnpm test # 729 tests incl. gateway/REST twin E2E
pnpm typecheck
pnpm lint
pnpm build # lib + client bundle
To try a local build in a profile:
pnpm pack --pack-destination /tmp
dsh plugin --profile <your-profile> add file:/tmp/addozhang-dsh-discord-<version>.tgz
dsh plugin anchors relative path specs to the invoking directory, so from a checkout that has run pnpm build, dsh plugin --profile <your-profile> add ../fiber works too. Re-run pack + add to refresh the installed copy, then restart dsh web.
Releases are tagged (npm version <level> && git push --follow-tags) and published by GitHub Actions via npm trusted publishing (OIDC) — no publish token is stored anywhere. The implementation follows the OpenSpec change at openspec/changes/build-discord-native-adapter/ (design, capability specs, verification checklist, review reports).
MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: discord、discord-bot。