dsh-qqbot

70Stars11Forks9Issues1Watchers

Connect a QQ bot to DeepSeek Harness: mention @bot in private or group chats to chat, send files, and call tools. Scan QR code to bind QQ credentials, with independent sessions spawned per message.

Machine-auditedInstall commandRepo verifieddsh-plugin topicLicenseREADMEAI wiki
Language
TypeScript
License
MIT
Branch
main
dshdsh-pluginqqbot

Install

$ dsh plugin --profile web add github:tencent-connect/dsh-qqbot

Run the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial

Install via your agent

Install the DeepSeek Harness plugin tencent-connect/dsh-qqbot for me: review the repository at https://github.com/tencent-connect/dsh-qqbot.git first, then run the install command and verify the plugin loads successfully.

Paste this instruction to the DSH Web GUI assistant — it will install and verify for you.

One-Sentence Overview

dsh-qqbot connects a QQ bot to DeepSeek Harness: turning the QQ messaging platform into a frontend channel for dsh agents. Just @ the bot in private or group chats to converse, send files, and invoke agent tools. Scan a QR code on first launch to bind QQ credentials; each chat window holds its own independent session.

Core Capabilities

  • Private & Group Chat: Private chats always respond; group chats trigger only when @bot by default, with an option to disable the gate and respond to all messages
  • QR Code Credential Binding: On first launch, the terminal prints a QR code; scan it with QQ mobile to obtain AppID/AppSecret and automatically write to profile
  • Attachment Handling: Images include size descriptions automatically; voice messages are transcribed to text; file attachments are downloaded locally and the model is prompted to read them via path
  • Markdown Streaming Replies: Private chats push replies paragraph by paragraph (streaming) by default; group chats send entire paragraphs at once due to QQ protocol limitations; long replies are split by code block/table awareness
  • Independent Sessions: Each QQ user/group maps to a dsh agent; sessions are persisted via SHA-256 derived sessionIds and can be restored after restart
  • Built-in Slash Commands + Access Control: /new /compact /model /stop plus /bot-ping /bot-version /bot-status /bot-help, with openid/groupOpenid whitelist support to allow or disable private and group chats

Technical Implementation

  • Language: TypeScript (ESM, tsconfig compiles to dist/, main points to dist/index.js)
  • Key Dependencies: @tencent-connect/qqbot-nodejs (QQ OpenAPI + WebSocket client + middleware chain), @tencent-connect/qqbot-connector (QR code binding), js-yaml (cordis.patch.yml read/write)
  • Architecture Pattern: Pure Cordis plugin, inject = ['agents']; entry apply() runs credential guidance then calls bootstrapGateway() to assemble SDK middleware chain (error handling → filtering → access control → group history buffer → @ gate → cleaning → rate limiting → slash commands → concurrent serialization → input state → quoting → attachments → envelope), and routes dsh outbound events back to QQ via ctx.on('session/event', ...)
  • Entry File: src/index.ts (Cordis plugin entry, includes credential guidance); gateway assembly in src/gateway/bootstrap.ts

Use Cases

Ideal for users who want to interact with DeepSeek Harness via QQ: ask questions in QQ daily, let the agent read files, write code, or run commands—no need to open the web console. Can also serve as a team assistant in QQ groups, with each person's conversation context isolated from others. Resources are automatically released after 30 minutes of inactivity.

Prerequisites and Compatibility

DependencyMinimum VersionDescription
DeepSeek Harness0.1.0-rc.6+peerDependencies locks @deepseek-ai/dsh-agent / dsh-llm / dsh-session / cordis / schemastery all to 0.1.0-rc.6 / 4.0.1 / 3.18.1 or above
QQ Bot CredentialsAppID + AppSecret required; can be obtained via QR scan or manually injected via QQBOT_APPID / QQBOT_SECRET environment variables
Node.jsNot declaredNo engines field in package.json; devDependencies include @types/node ^26.2.0, actual runtime requires Node 18+ supporting built-in APIs like fetch, AbortSignal.timeout, node:dns/promises
PlatformmacOS / Windows / LinuxQR scan guidance auto-switches to set syntax on Windows (src/setup.ts:186), other platforms use export; no other platform-specific branches in code
Native ModulesNoneOnly depends on built-in modules like node:crypto / node:fs / node:path / node:dns, no native bindings like node-pty / sqlite

Installation

dsh plugin --profile web add github:tencent-connect/dsh-qqbot

Configuration Options

The plugin declares fields via Schemastery Schema (src/config.ts:56); the "Description" column in the table below is in plain language. Default values work for normal scenarios after installation; regular users don't need to adjust.

ConfigTypeDescriptionDefault
appIdstringQQ bot AppID; if left empty, QR scan guidance runs on startupempty (requires QR scan or env var)
appSecretstringQQ bot AppSecret; same as aboveempty
providerstringDefault LLM provider; if empty, inherits host configinherits
modelstringDefault model; if empty, inherits host configinherits
presetstringAssociated agent preset id (toolset, prompt, etc.)none
cwdstringRoot directory for agent command executioncurrent process directory
requireMentionbooleanWhether group chats require @bot to respondtrue
groupPromptstringAdditional content injected into system prompt for group chatsnone
directPromptstringAdditional content injected into system prompt for private chatsnone
textChunkLimitnumberMaximum characters per QQ message (QQ limit ~5000)4500
streamingbooleanWhether private chats enable streaming replies (group chats never stream)true
sessionIdleTimeoutnumberMilliseconds before idle sessions are auto-reclaimed1800000 (30 minutes)
maxQueuenumberMaximum messages queued for the same session20
processingTimeoutMsnumberMilliseconds before a single LLM call auto-terminates120000 (2 minutes)
historyLimitnumberNumber of recent messages included as context when responding in group chats10
access.c2cModestringPrivate chat access mode: open allow all / allowlist whitelist / disabled deny allopen
access.c2cAllowstring arrayPrivate chat whitelist (enter user openid)[]
access.groupModestringGroup chat access mode (same values)open
access.groupAllowstring arrayGroup chat whitelist (enter group openid)[]
showToolResultsbooleanWhether to display successful tool call results (errors always shown)false
debugbooleanEnable debug logs (includes middleware hit details)false

FAQ

Q: What do I need to do on first launch?

A: If AppID/AppSecret is not detected on startup, the plugin prints a QR code in the terminal; scan to complete binding. Credentials are automatically written to the current profile's cordis.patch.yml, no need to scan again next time. When QR code is misaligned, use the browser link output by version 0.4.0+ instead.

Q: Do I need to @bot in group chats for it to respond?

A: requireMention is enabled by default; group chats only trigger responses when @bot. Set to false to respond to any message. Private chats are unaffected by this switch and always respond.

Q: Will conversation context leak between different QQ groups?

A: No. Each QQ private chat user and each QQ group has an independent sessionKey. sessionId is deterministically derived via SHA-256 from qqbot:${appId}:${scope}:${peerId}, restorable after restart. Dialogues between different groups/people are isolated.

Q: Does it support images, voice, and files?

A: Images include size descriptions in context. Voice messages prefer ASR-transcribed text; if the model can't access audio, the original link is attached as fallback. File attachments are automatically downloaded to ${cwd}/.qqbot/${messageId}/ with path prompts, then the model reads them via tools. File downloads include HTTPS + SSRF protection and 20MB size limits.

Q: How to enable streaming replies?

A: Streaming is on by default for private chats (streaming: true), replies push paragraph by paragraph. Group chats never stream due to QQ group message API limitations, only sending entire Markdown blocks. If global streaming is disabled, private chats also switch to sending complete replies at once.

Q: How to switch models?

A: Send /model in chat to list available models (click to switch), or /model provider/model to specify a route. Preferences are persisted per sessionKey to ~/.dsh-qqbot/model-prefs.json, so the same person/group retains settings on next restart.

Q: How to completely reset the current conversation?

A: Send /new (alias /reset, /clear) to discard the current session and start a new one. To preserve context but compress history, send /compact (requires host with compaction service). Long idle sessions over 30 minutes are auto-disposed and restored on next message.

Q: "Credentials not configured" error—now what?

A: QR scanning automatically writes to profile. In dev mode (loading source via cordis.dev.yml), the profile directory can't be located, so the plugin prints export/set environment variable instructions to terminal. For manual configuration, write appId and appSecret to the corresponding plugin entry in the profile's cordis.patch.yml.

Learning Curve

Beginner — scan QR code to bind QQ credentials, start chatting in private messages immediately. Advanced users can adjust group gating, whitelists, Markdown split thresholds, and other parameters as needed.

Known Issues and Limitations

  • Model preferences are persisted per sessionKey to ~/.dsh-qqbot/model-prefs.json; deleting this file resets all preferences. No UI-based batch cleanup currently available.
  • Group chat streaming is always disabled: QQ group message API doesn't support incremental updates, so group chats only send entire Markdown blocks, with single-message limits controlled by textChunkLimit (default 4500).
  • File attachment downloads have 20MB size limits and HTTPS + SSRF protection. When either rule is triggered, download is skipped and only path description is retained; oversized files need to be manually placed in the agent's working directory.
  • Sessions idle for 30 minutes are automatically disposed; the next message triggers a "resume → create" flow. If the host lacks sessions service, resume fails and falls back to creating a brand new session (history lost).
  • Model switching uses fork + rebuild strategy. If sessions.fork service doesn't exist at the lower level, it falls back to disposing old session and creating new one with new model (equivalent to /new, context lost).
  • /compact command requires host to have agent-presets or compaction service loaded; returns "compression capability unavailable" when not loaded.
  • In streaming replies, both assistant/chunk and assistant/message enter the buffer. If turn/end ends abnormally mid-stream,底层错误码 like STREAM_CLOSED are silently ignored (won't appear in user messages).

Listing badge

Listed on deepseek-plugin.org
[![Listed on deepseek-plugin.org](https://img.shields.io/badge/listed_on-deepseek--plugin.org-007EC6)](https://deepseek-plugin.org/plugins/tencent-connect/dsh-qqbot)

Paste this markdown into your GitHub README to link back to this listing. The badge only states the listing — not a security endorsement.

← Back to plugin directory