# ๐ dsh-im-gateway
Connect DeepSeek Harness to every chat app you use
Aggregated IM gateway for DeepSeek Harness (dsh) โ drive your coding agents from WeChat, Feishu, Telegram, Discord, QQ and 25+ chat platforms, with unified sessions, remote approvals, interactive questions and one-command setup.
English ยท ็ฎไฝไธญๆ
---
## ๐ธ Screenshots
---
## โก One-command install
Paste any prompt below into dsh (Web GUI chat, `dsh --profile headless "โฆ"`, or a connected IM chat). The agent will install the plugin for you. Restart dsh web once after installing a plugin.
Option A ยท Install from npm (recommended)
```text
Please install the dsh-im-gateway plugin: dsh plugin --profile web add dsh-im-gateway
Tell me when it's done and remind me to restart dsh web.
```
Option B ยท Clone from GitHub
```text
Please install the dsh-im-gateway plugin (the aggregated IM gateway for DeepSeek Harness):
1. Run git clone --depth 1 https://github.com/zhuiyueya/dsh-im-gateway.git /tmp/dsh-im-gateway
2. Run cd /tmp/dsh-im-gateway && npm install && npm run build
3. Run dsh plugin --profile web add /tmp/dsh-im-gateway
4. Report the result; if it asks for a restart, remind me to restart dsh web.
```
Option C ยท Install straight from the git URL
```text
Please install the dsh-im-gateway plugin: dsh plugin --profile web add https://github.com/zhuiyueya/dsh-im-gateway.git
Remind me to restart dsh web when done (first install takes 1โ2 min for dependencies).
```
Option D ยท Local project directory
```text
Please install the local dsh-im-gateway project as a dsh plugin:
1. cd into the project and run npm install && npm run build
2. Run dsh plugin --profile web add
3. Remind me to restart dsh web.
```
---
## ๐ Quick Start
### 1. Install and open Settings
After installation, restart dsh web and open: **Settings โ๏ธ โ ๐ IM Gateway**.
### 2. Connect a channel
- **WeChat / WhatsApp**: click ใConnect (scan)ใ and link the device with the mobile app.
- **Feishu / QQ / DingTalk / WeCom**: click ใScan to connect botใ and scan with the platform app; manual credentials are also supported.
- **Telegram / Discord / Slack and others**: follow the official documentation and credential form shown on the channel card.
No restart is needed after connecting. Status is normalized to: **connected / not connected / connecting / error**. Saved channel configurations auto-reconnect after a dsh restart; WeChat login state is persisted, so it does not need to be scanned again.
> **Disconnect vs Delete config**: temporary disconnect stops the channel but keeps its configuration for automatic recovery; delete config removes the credentials and requires setup again.
### 3. Start using it
Message your bot in any connected chat app:
```text
/help โ available commands
Hi, take a look at my current workspace โ plain chat = drive the agent
```
When `allowAllUsers: false`, an unknown user's first message triggers an authorization request in the Web settings panel. With the default `allowAllUsers: true`, no authorization step is needed.
Agent replies stream back in real time; when approval is needed, reply ใapprove / rejectใ in the chat. The agent can also use `im_send_file` to send workspace files into the chat.
See [`docs/qr-login-matrix.md`](docs/qr-login-matrix.md) for the platform-by-platform QR capability research.
---
## ๐ก Supported Channels
| Channel | Status | Receive mode | Setup |
|---|---|---|---|
| **Telegram** | โ
Full | Bot API long-polling | @BotFather token |
| **Discord** | โ
Full | Gateway WebSocket | Bot token |
| **Slack** | โ
Full | Socket Mode | xoxb- + xapp- token |
| **Feishu / Lark** | โ
Full | Official SDK long-connection | Official QR or App ID + Secret |
| **DingTalk** | โ
Full | Official Stream connection | Official QR or Client ID + Secret |
| **WeCom** | โ
Full | Official intelligent-bot WebSocket | Official QR or Bot ID + Secret |
| **WeChat** | โ
Full* | Tencent official iLink long-polling (device QR) | Official iLink account (dedicated account recommended) |
| **QQ Bot** | โ
Full | Official WebSocket | Official QR or AppID + Secret |
| **LINE** | โ
Full | REST + webhook | Channel token |
| **Matrix** | โ
Full | Client sync | Homeserver + token |
| **Mattermost** | โ
Full | WebSocket + REST | Server URL + token |
| **IRC** | โ
Full | Native socket | Server address |
| **Twitch** | โ
Full | WebSocket IRC | OAuth token |
| **Signal** | โ
Full | signal-cli subprocess | Local signal-cli |
| **Nextcloud Talk** | โ
Full | REST polling | Instance account |
| **Synology Chat** | โ
Full | webhook | Incoming webhook |
| **Zalo** | โ
Full | REST + webhook | OA token |
| **iMessage** | โ
Full* | imsg / osascript | macOS |
| **WhatsApp** | ๐ Dynamic dep | Baileys QR | `npm i @whiskeysockets/baileys` |
| **Nostr** | ๐ Dynamic dep | NIP-04 DM | `npm i @noble/curves` |
| **Teams** | ๐งช Experimental | Bot Framework | Azure registration |
| **Google Chat** | ๐งช Experimental | webhook | Public endpoint |
| **Tlon / Yuanbao / Voice** | ๐งช Skeleton | โ | Infrastructure |
โ
Full = send & receive work ๏ฝ ๐ Dynamic dep = prompts to install SDK if missing ๏ฝ ๐งช Experimental = needs public network or dedicated infrastructure ๏ฝ *WeChat = Tencent's official iLink channel (media + voice-to-text + typing)
---
## โจ Core Features
### ๐ฌ IM Commands
Messages starting with `/` in any connected chat are commands:
| Command | Description |
|---|---|
| `/help` | This help |
| `/status` | Current session (session id / workspace / pending approvals) |
| `/new` ยท `/clear` | Start a brand-new session (per-chat mode) |
| `/workspaces` | List all workspaces |
| `/workspace ` | Switch workspace (takes effect on the next `/new`) |
| `/sessions [all\|path]` | List sessions (default: current workspace; `all` for everything) |
| `/continue ` | Resume an existing session (across channels/workspaces) |
| `/bind ` | Bind a local live session (bound mode) |
| `/unbind` | Unbind (bound mode) |
| `/channels` | Connection status of each channel |
| `/cron list` | List this chat's scheduled tasks |
| `/cron rm ` | Delete a scheduled task |
| `approve` / `reject` | Answer a pending approval (also `yes` / `no` / `ๅๆ`) |
| Plain text | Sent to the agent; trailing `..` means more coming, `!!` submits immediately |
### โ
Remote Approval
When the agent requests a tool approval, the request is pushed to the chat. Reply ใapprove / rejectใ directly; approval replies verify chat and session ownership, and expired requests fall back to the local approval system.
### โ Interactive Questions
When the agent calls `ask_user_question`, its prompt and options are sent to every IM chat bound to that session. Web and IM can both answer; **the first valid answer wins**, and every other channel receives a resolved notice.
| Question type | IM reply format | Example |
|---|---|---|
| Single choice | Option number, exact label, or custom text | `2`, `Full mode`, `Ask me later` |
| Multiple choice | Separate values with commas, Chinese commas, ideographic commas, or semicolons | `1,3`, `Fast;Tests` |
| Free text | Reply with the full answer | `Use dsh-im-gateway as the project name` |
| Multiple questions | One line per question: `question-number: answer` | `1: 2`, then `2: 1,3` on the next line |
The answer window is controlled by `questionTimeoutSecs` and defaults to 600 seconds. When it expires, only the IM wait is removed; the question remains answerable in the Web GUI. Pending questions are isolated by session.
### โฐ Chat-scoped Scheduled Reminders
Scheduled tasks bind to the **chat (`chatId`) rather than the session (`sessionId`)**. Say โremind me to drink water at 9am dailyโ or โevery Monday at 9am generate today's todo listโ; the task continues to work across `/new` and session restarts.
- `/cron list`: list this chat's tasks
- `/cron rm `: delete a task
- Supports one-shot, daily, and weekday schedules
- Supports IANA time zones and DST gap/overlap handling
- State persists across restarts; failed sends are retried
### ๐ฑ Messages and Media
- Mobile multi-part input: `..` means more coming, `!!` submits immediately, bare text merges within a 5-second window, and buffers recover after a crash.
- Long replies are split by each channel's limit, preferring newlines and sentence boundaries, with `(i/n)` numbering.
- WeChat supports images, voice transcription, files, and video; agents can send workspace files with `im_send_file`.
### ๐ก๏ธ Access Control
`allowAllUsers: true` is the default for easy setup. Set it to `false` when access control is needed and manage the channel allowlist. Approval replies always verify session ownership.
---
## ๐ Architecture
```text
IM channels (Telegram / WeChat / Feishu / Discord / โฆ) DSH agent
โ adapter normalizes inbound โฒ
โผ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ChannelAdapter โโโโโโโบโ ImGateway (core) โโโโโโโโ
โ ยท one adapter per channelโ โ ยท session routing โ
โ ยท recv: poll/WebSocket/ โ โ (per-chat) โ
โ webhook โ ImMessage โ โ ยท allowlist & IM cmds โ
โ ยท send: send(chatId, โ โ ยท approval / questions โ
โ text) โ โ ยท split / merge โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ
โฒ
โ session/event ยท assistant/message ยท turn/end
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
```text
user message โ channel adapter โ gateway (allowlist โ merge โ route) โ agent.followup()
agent reply โ gateway (split per channel) โ session/event(assistant/message) โ agent
tool approval โ approval/request โ pushed to chat โ ใapproveใโ allowed-once
```
---
## ๐งช Development
```bash
npm install
npm run build # tsc builds to lib/
npm test # node --test (106 cases)
```
**Adding a new channel takes 4 steps**:
1. Create `src/channels/yourchannel.ts` implementing `ChannelAdapter` (6 methods)
2. Register it in `src/channels/index.ts`
3. Add the config fields in the Config in `src/index.ts`
4. Add a row to the README channel table โจ
```typescript
export function createYourChannel(config, log): ChannelAdapter | undefined {
if (!config.token) return undefined // no credentials โ don't start
return {
id: 'yourchannel', label: 'YourChannel', maxMessageLength: 2000,
start() { /* connect / poll / scan */ },
stop() { /* cleanup */ },
async send(chatId, text) { /* send message */ },
setMessageHandler(h) { /* inbound callback */ },
status() { return 'running' },
}
}
```
---
## ๐ค Contributing
- Bug fixes, new channels and doc improvements are all welcome!
- Please make sure `npm test` passes all 106 cases first
- Add the `dsh-plugin` and `deepseek-harness` topics to the repo to get into the awesome-plugin list
## ๐ License
[MIT](./LICENSE) ยฉ zhuiyueya
---
Made with ๐ for the DeepSeek Harness ecosystem