# dsh-qqbot-dafeiyu 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 dsh plugin --profile qqbot add dsh-qqbot-dafeiyu # Start 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. ### Method 2: Local path ```bash # Build cd /path/to/dsh-qqbot pnpm install && pnpm build # Add to a profile (local path) dsh plugin --profile qqbot add /path/to/dsh-qqbot # Start export QQBOT_APPID="yourAppID" QQBOT_SECRET="yourAppSecret" dsh --profile qqbot ``` ### Method 3: --patch dev mode ```bash cd /path/to/deepseek-harness export QQBOT_APPID="yourAppID" QQBOT_SECRET="yourAppSecret" pnpm 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 | |------|------| | `/bot-reset` | Reset the current session (clear context) | | `/bot-model` | View or switch model | | `/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 (inside the dsh monorepo) cd /path/to/deepseek-harness export QQBOT_APPID="xxx" QQBOT_SECRET="xxx" pnpm dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml ``` ## License [MIT](./LICENSE)