# @tencent-connect/dsh-qqbot A QQ Bot IM plugin for [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh), driving the dsh agent loop with the QQ messaging platform as the frontend protocol. [中文文档](./README.md) | English ## Architecture ``` QQ User → QQ WebSocket → dsh-im-qqbot → ctx.agents → dsh agent loop → LLM ↑ │ └── session/event ──────────┘ (assistant reply → QQ sendMarkdown) ``` ## Installation ### Method 1: Manual ```bash # Add to a profile npx @deepseek-ai/dsh plugin --profile qqbot add @tencent-connect/dsh-qqbot # Start npx @deepseek-ai/dsh --profile qqbot ``` On first launch, the plugin detects missing credentials and automatically starts the QR flow: a QR code is printed in the terminal → scan it with the QQ mobile app → credentials are saved to the profile, so subsequent launches require no re-scan. QR code scan example > **Note**: Upgrade to `0.4.0` or later for browser-link scanning, which avoids QR code misalignment in some terminals. ### Method 2: Local path ```bash # Build cd /path/to/dsh-qqbot pnpm install && pnpm build # Add to a profile (local path) npx @deepseek-ai/dsh plugin --profile qqbot add /path/to/dsh-qqbot # Start export QQBOT_APPID="yourAppID" QQBOT_SECRET="yourAppSecret" npx @deepseek-ai/dsh --profile qqbot ``` ### Method 3: --patch dev mode ```bash export QQBOT_APPID="yourAppID" QQBOT_SECRET="yourAppSecret" npx @deepseek-ai/dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml ``` ## Configuration | Config | Type | Default | Description | |------|------|--------|------| | `appId` | string | **required** | QQ Bot AppID (or via `QQBOT_APPID` env var) | | `appSecret` | string | **required** | QQ Bot AppSecret (or via `QQBOT_SECRET` env var) | | `provider` | string | `deepseek-official` | LLM provider name | | `model` | string | `deepseek-chat` | Model name | | `preset` | string | - | Agent preset id | | `cwd` | string | `process.cwd()` | Agent working directory | | `requireMention` | boolean | `true` | Whether group messages require @bot to trigger | | `groupPrompt` | string | - | Extra system prompt for group chats | | `directPrompt` | string | - | Extra system prompt for direct chats | | `textChunkLimit` | number | `4500` | Max chars per message | | `sessionIdleTimeout` | number | `1800000` | Session idle timeout (ms), default 30 min | | `debug` | boolean | `false` | Debug mode | ## Built-in Commands | Command | Description | |------|------| | `/new` (aliases `/reset` `/clear`) | Start a new session (clear context) | | `/compact` | Compact session history (replace old records with a summary) | | `/model` | View or switch model | | `/stop` | Abort the current generation | | `/bot-ping` | Connectivity test | | `/bot-version` | View version info | | `/bot-status` | View current session status | | `/bot-help` | View all commands | ## Core Modules ``` src/ ├── index.ts # Cordis plugin entry (async apply) ├── config.ts # Config schema ├── types.ts # Global types ├── setup.ts # Credential binding (QR) ├── transport/ # Transport layer │ ├── inbound.ts # QQ inbound message → agent.followup() │ ├── outbound.ts # session/event → QQ sendMarkdown │ ├── outbound-buffer.ts # Streaming buffer │ └── chunker.ts # Markdown chunking ├── session/ # Session management │ ├── session-manager.ts # QQ peer → Agent mapping │ └── idle-evictor.ts # Idle eviction ├── model/ # Model routing │ ├── model-resolver.ts # Route resolution │ ├── prefs-store.ts # Per-peer preference persistence │ └── settings-reader.ts # settings.yaml read-only ├── shared/ # Shared utilities │ ├── utils.ts # Common helpers │ ├── scope.ts # scope/peer extraction │ └── send-helper.ts # Chunked send ├── commands/ # Slash commands └── typings/ # External module declarations ``` ## Session Routing sessionKey: `qqbot:${appId}:${scope}:${peerId}`, with the SessionId derived deterministically via SHA-256 so sessions survive restarts. Resolution strategy: in-process reuse → persisted resume → fresh create. ## Design Principles - **Pure Cordis plugin** — follows the dsh "Plugins, not loop changes" principle - **Declarative dependencies** — `inject = ['agents']`, no direct coupling to other plugins - **Session isolation** — one independent Agent per QQ direct user / group - **Preset support** — mount presets (toolkits, prompts, etc.) via the `agent-presets` service - **Idle eviction** — auto-dispose Agents on timeout to prevent memory leaks - **Markdown output** — replies sent as Markdown with code-block/table-aware chunking ## Local Development ```bash # Install dependencies pnpm install # Build pnpm build # Dev mode (watch) pnpm dev # Debug via --patch export QQBOT_APPID="xxx" QQBOT_SECRET="xxx" npx @deepseek-ai/dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml ``` ## License [MIT](./LICENSE)