xcisxc29/dsh-qq-plugin

dsh-qq-plugin

仓库尚未提供可用的公开描述。

Uncategorizedai-agentautomationdeepseek-harness

dsh-qq-plugin

Drive the DeepSeek Harness agent on this computer from your phone, in QQ.

It goes through Tencent's official QQ bot platform (api.bot.qq.com, bound by scanning a QR code), so there is no public IP to expose, no reverse proxy, and no third-party protocol client in the middle. Bind once, and it keeps working.

Runs on the current DSH desktop app — developed and tested against DSH 0.2.0-rc.2.

This is the QQ counterpart of dsh-wechat-plugin. It is feature-aligned with it, with a few deliberate departures where the QQ protocol makes the WeChat machinery unnecessary — see Differences from the WeChat version.

中文说明

A QQ chat: the message 「把我电脑上桌面那张 DSH 自画像发过来」 (send me that DSH self-portrait from my desktop), then the file arrives in the chat as an image, followed by 「已发送 ✅ 桌面上的「DSH 自画像.png」(29 KB,PNG)」 (sent — DSH 自画像.png on the desktop, 29 KB, PNG)

Ask for a file in one sentence and it lands on your phone. Say "send me that DSH self-portrait from my desktop" in QQ and the agent finds the file on the computer, sends it back, and confirms with "sent — DSH 自画像.png on the desktop (29 KB, PNG)". The + at the right of the composer is the attachment entry: images, videos, voice and files all go in that way (see Media in both directions).

Features

  • Text both ways. A QQ message becomes a DSH prompt, and the reply comes back to QQ.
  • Images, files and voice in; images, videos and files out. Attachments are saved into the session workspace and handed to the agent; the agent sends files back with send_to_qq. A reply that runs long is turned into a .md file and sent to your phone instead of being cut.
  • One QQ chat, many DSH conversations. /new, /list, /switch, /current, /cancel — or just say "switch to the other one". The list has session folders and sessions as two levels.
  • Pick the model and the reasoning level from your phone too. /model lists the models with each one's reasoning levels; /model 2 and /model 等级 high switch them, effective from the next step.
  • Answer permission prompts and questions from your phone. Approvals are answered with 「允许」/「拒绝」 (allow/deny) or a numbered option; the agent's multiple-choice questions arrive in QQ with numbered options and a digit answers them — being away from the desk does not stall the task.
  • Proactive push. notify_qq lets any session on this machine message you — that is what makes "tell me when it is done" work. It works in practice: a ten-message burst was delivered in full, and the last six of those went out as proactive pushes. (Tencent's rules for unsolicited sends can change and the plugin assumes no quota; anything undelivered is queued and flushed the next time you speak.)
  • Scheduled tasks. Run through the DSH host's own schedule_create / schedule_list / schedule_delete / schedule_update — just say "wake me at 23:12". The plugin does not reimplement what DSH already has; it is only the channel.
  • Settings page under Settings → QQ — nine settings, a native folder picker, and diagnostics.

Install

For the DSH desktop app on a machine that stays on. It needs DSH's workspace, tool and UI services — the standard desktop composition.

DSH desktop@deepseek-ai/dsh-desktop 0.2.0-rc.2 or newer
Phonemobile QQ, to scan one QR code
QQ botnothing to register in advance. The bot application is created by that scan; you do not need an AppID/AppSecret beforehand
Tencent's rulesan uncertified bot is usable only by its administrator — that is, only by you, which is exactly what a personal remote control wants

Open the plugin entry in the sidebar and choose 添加插件 (add plugin). The field takes a package name, a Git URL, a tarball, or a local path.

The name to install is dsh-qq-plugin

The repository and the package share one name, so there is nothing to reconcile — but the -plugin suffix is easy to drop by accident. Copy dsh-qq-plugin rather than typing it. The install command has to match the package name exactly.

From a terminal, that is one line (--profile web works just as well if that is the profile you use):

dsh plugin --profile desktop add dsh-qq-plugin
From npm — nothing to configure
dsh-qq-plugin

Add a version if you need one: dsh-qq-plugin@1.0.5.

From a local checkout — there is no build step to wait for
C:\path\to\dsh-qq

Point it at the directory that holds package.json — the folder is dsh-qq, the package it declares is dsh-qq-plugin.

From a tarball
npm pack
# → dsh-qq-plugin-1.0.5.tgz

Paste the absolute path to that .tgz into 添加插件.

Install from a terminal instead

The app drives pnpm underneath, so the same thing headlessly:

dsh plugin --profile desktop add dsh-qq-plugin
dsh plugin --profile desktop add C:\path\to\dsh-qq

You then have to enable the bundle yourself — which is what 立即启用 does for you — in ~/.dsh/profiles/desktop/package.json:

{
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-qq-plugin"
      ]
    }
  }
}

Wait for the install to finish, click 立即启用 (enable now), and restart DSH.

Getting started

After restarting DSH, open Settings → QQ and click 开始扫码 (start the QR bind). Scan the code with mobile QQ and confirm on the phone.

The scan is the whole registration. The bot application is created by that scan, so you do not need to register anything on Tencent's open platform first and you do not need an AppID/AppSecret in advance — nor a public IP or a reverse proxy.

The credentials land straight in DSH's credential store — the plugin's own state file records only the AppID, never the AppSecret. The channel connects by itself once bound: send any message to the bot in QQ and you should get a reply.

A QQ chat on a phone: at 22:38 the agent reports that the 13-poem autumn anthology is ready and sends a docx and a pdf; at 22:43 the user asks 「告诉我,我现在电脑时间」 (tell me the computer's current time) and the agent answers 2026-10-13 22:43:28 Tuesday, then asks whether to set a reminder or a scheduled task

That is what it looks like in real use, after installing it: the agent put together a 13-poem anthology on the computer and sent both the docx and the pdf straight to the phone; in the same conversation, "tell me the computer's current time" came back as 2026-10-13 22:43:28 Tuesday, along with an offer to set a reminder.

The computer was locked at that moment — the phone says 22:43 and so does the lock screen:

The computer's lock screen at the same 22:43: across the screen there is only the clock 22:43 and the date 10月13日,星期二, with no taskbar and no windows visible — a city-at-night photo behind them

Locking the screen does not stop the agent, so it keeps working after you walk away while the conversation on your phone carries on. The reverse is also true: locking is exactly what you should do when you leave (see Security).

Usage

Just send a message and it reaches the agent:

你好

What follows is grouped by capability, and each group carries a real screenshot showing what it looks like and what it proves.

Conversation management, from your phone

One QQ chat sits in front of any number of DSH conversations. /list opens this workspace's conversations, ten per screen:

Replying /list in QQ: the agent answers with an 【QQ 会话】会话 (1/1) list of ten rows, every row ending in a six-character id, row 1 marked with ← 当前 (current), and a footer saying there are another 89 conversations in other session folders, plus 「回复编号或行尾 6 位 id 切换。引用这条消息再回编号,可以避免编号过期。」

One shot, four things proved: ten rows per screen, a six-character id at the end of every row (7cee80, 4b55e1…), the current conversation marked ← 当前, and that footer line. The list also tells you there are 89 more conversations in the other session folders.

/list all is the level above — the session folders (across projects and workspaces), each with its conversation count; reply with a number or a name to enter one, and what you get is that folder's conversation list (the screenshot replies 1, so it enters 「QQ 会话」):

Replying /list all in QQ: the agent answers with a 会话夹 (1/1) list — QQ 会话 11 个会话, workplace 62, dsh_wechat 21, texttry 1, dsh_orb 1, browser-sessions 3 — footer 「回复编号或名字进入。」; the user then replies 1 and the agent sends the 【QQ 会话】 conversation list

Entering a folder only moves where you are browsing, not which conversation you are bound to — to actually switch you still pick a conversation inside it.

A bare digit is /switch <digit>: with the list on screen there is no need to type /switch, just reply 2 — and it tells you which one you landed on, short id included, so you can check it against the row you meant:

With the conversation list on screen the user replies with a bare 2, and the agent answers 「已切换到「你好」。4b55e1」 (switched to 「你好」, 4b55e1)

★ Quoting freezes the numbering: long-press the list message and quote it before replying with a number, and the number is read as that screen printed it. Sessions running while you read cannot make you land on the wrong one — the numbering is frozen inside that message. The list footer says so itself: 「引用这条消息再回编号,可以避免编号过期。」

Plain language works too. Here the user sends 「查看所有会话」 (show all conversations) — not a command:

Having earlier replied 2 to switch, the user now sends the plain-language 「查看所有会话」; instead of an error the agent sends the session-folder list plus 「已列出,请看上面的会话列表。回复对应编号即可切换,回复「查看其余」看下一页。」

The agent judges intent rather than matching fixed rules: it recognised "list conversations", listed the session folders, and told you that a number switches and 「查看其余」 turns the page. A switch also reports whether it succeeded or failed.

Type these to control which DSH conversation you are talking to:

CommandWhat it does
/new [title]Start a fresh conversation. Anything after it becomes the title: /new 修复登录 starts a conversation called 「修复登录」
/listGo straight to this workspace's conversations (ten per screen)
/list allList the session folders (workspaces) on this machine, one per line with its conversation count; reply with a number or a name to enter
/switch 3Move to the 3rd row of that screen
/switch e716f0Move by the short id at the end of the row — unrelated to numbering, and it never expires
Reply 「查看其余」Walk down ten rows (both levels, all the way to the end). Numbering runs on across screens (1–10, then 11–20)
Reply 3, a name, or a trailing idNo need to type /switch while the list is on screen
Quote a list message → /switch 3Numbered by that screen; the numbering is frozen inside that message
/modelWhich models there are, and each one's reasoning levels, with the one in use marked
/model 2Switch to the 2nd one; a model name works too
/model 等级 highChange the reasoning level of the current model (the level names are the ones the list prints)
/model 2 等级 highChange the model and the level together
/currentWhich conversation you are in
/cancelStop the task that is running
/helpThis list

Spaces are optional: /switch3, /switch 3 and /switch:3 all work — these commands get typed on a phone keyboard, where a dropped space is normal. A word that merely starts with a command is not one, so /news is not /new.

Numbering expires: sessions run while you are reading the list, so by the time you reply "3" the 3rd row may be someone else. Every row therefore ends with a short id of at most 6 characters — reply with that, or quote that screen's list message and the number is read as that message printed it.

The list has two levels, ten rows per screen: /list opens this workspace's conversations; /list all lists the session folders (workspaces), which you enter by number or name. Both levels walk down ten rows with 「查看其余」, and numbering runs on across screens. When you reach the end it says so instead of inviting you to keep going. Entering a folder only moves where you are browsing, not which conversation you are bound to — to actually switch you still pick a conversation inside it.

Models and reasoning levels

/model lists which models there are (marked 「(当前)」/「(默认)」 — current / default) and each one's reasoning levels. /model <name|number> switches model; /model 等级 high changes only the reasoning level; /model 2 等级 high changes both. A switch takes effect from the next step.

Reasoning levels come from the host adapter. The bundled DeepSeek adapter publishes off / low / high / max (printed as Off / Low / High / Max), and those are the names /model 等级 accepts, case-insensitively. There is no separate Chinese spelling — the level names are the ones the list prints, exactly as the WeChat channel does it.

Plain language works here too — "switch to the other one", "what conversations do I have", "stop". The agent judges the intent rather than matching fixed rules, and a switch tells you whether it succeeded or failed.

Media in both directions: images, video, voice, files

In: send the agent an image / video / voice message / file from your phone. Voice is transcribed server-side and you never see that step. Document attachments (Word, Excel) are readable too.

Here is a photo of a dog sent in, with a single question — "what is this":

The user sends a photo of a small dog into the QQ chat and asks only 「这是什么」 (what is this); the agent answers 「一只小狗的照片 🐶」 and lists the white long coat with a tuft of black on the head and ears looking like a border-collie mix, the big eyes staring at the lens with a very innocent expression, the pale tiled floor with a yellow-bodied orange-beaked duck toy, and notes that the photo is sideways because the phone was held the wrong way round

What is worth noticing is not that it recognised a dog but the two details only someone who really looked at the image could give: the yellow-bodied orange-beaked duck toy, the person's legs at the left edge of the frame, and its unprompted remark that the photo is sideways (the phone was held the wrong way round).

Now a PDF sent in, again with a single question — "what is this":

The user sends 「视觉组预训练文档.pdf」 (387.89KB) into the QQ chat and asks 「这是什么?」; the agent answers that it is a vision-group pre-training / recruitment task document from the Zhuyan team dated September 2026, five pages, exported from MarkText, and summarises it under three headings: environment setup, AI plus engineering discipline, and four traditional OpenCV tasks

Document attachments are read too: it says this is a five-page recruitment task document, exported from MarkText, and summarises it as "Part 1 environment setup / Part 2 using AI plus engineering discipline / Part 3 traditional OpenCV, four tasks".

Out: the agent sends files from this computer to your phone with send_to_qq — images arrive as photos, videos as playable clips, everything else as a file attachment:

The user says 「把我电脑上桌面那张 DSH 自画像发过来」 in QQ; the agent first replies with the filename 「桌面上的 DSH 自画像.png」, then the image itself appears in the chat, and finally it confirms 「已发送 ✅ 桌面上的「DSH 自画像.png」(29 KB,PNG)。」

This is the story the cover image at the top of the page tells, and it is a complete pickup: say which file you mean, the agent finds it on the computer and sends it back, and it confirms with the filename and size so you can see at a glance whether it sent the one you meant.

★ A reply that runs long is turned into a .md file and sent to your phone (4000 characters by default, adjustable; 0 = no limit):

The user says 「把这个 QQ 插件项目 read me 完整读一遍,写一份详细的中文导读」; the agent replies 「dsh-qq-plugin README 中文导读(完整版)」 with a 20.33KB .md attachment and adds that it read the whole 377-line README and sent the guide as a **.md file** because it is easier to read on a phone than a long message

Something that would not fit on one phone screen is far more usable as a file — not truncated, and not split into a dozen messages that flood the chat. The threshold is the settings page's "单条回复字数上限" (per-reply character limit).

Voice: hold to talk on the phone and the agent receives text (transcribed server-side, with nothing extra for you to do):

A three-second voice bubble in the QQ chat, immediately followed by the agent giving tonight's and tomorrow's Beijing weather: tonight clear 8°C, sunset 17:39; tomorrow cloudy with a high of 21°C, sunrise 6:22, plus a warning that the temperature has dropped sharply and the cold index is very high, and a note about Indonesian haze and PSI levels

Under that 3-second voice bubble in the screenshot is a complete weather answer — the middle step, turning speech into text, is invisible on your phone, and does not need to be visible.

Interaction

These three have no screenshots — they are a question and an answer inside the same conversation, so a picture of one would look much like the ones above; prose says it better. This is what arrives on your phone:

  • Permission approvals: when the agent wants to touch your files, a pending request appears in QQ saying what it intends to do. Reply 「允许」 (allow), 「拒绝」 (deny), or a numbered option — all three answer it, and the task carries on. (For such a prompt to appear at all, the permission preset has to be one of the two that can show prompts — see Settings.)
  • Either/or and multiple-choice questions: the agent's question arrives with numbered options, and a single digit answers it.
  • Quoting as context: long-press and quote one of its answers before speaking — for example "expand the second point in this one" — and it knows which answer "this one" is and which point "the second" is.

Proactivity: tell me when it is done

★★ notify_qq: any session on this machine can push a message to you — that is what "tell me when it is done" is built on. On the left is the desktop session doing the work; on the right is what arrives on mobile QQ:

The DSH desktop app: the user asked 「从网上找几篇写秋天的诗歌,写完发我 qq」 (find a few autumn poems online and send them to my QQ when done); the session shows 「已完成,用时 3 分 24 秒」 (done, took 3m24s), the answer explains it searched public web pages, checked each poem and compiled them into a file which it sent to QQ as DOCX and PDF, and below is a table of the 13 poems with number, work and author The same result on mobile QQ: first 「秋天的诗给你整理好了:13 首(唐宋诗词·元曲·清词·济慈《秋颂》),每首附一句品读,来源逐首核对过。文件:秋日诗歌选.docx」, then the docx and pdf attachments, with a line in between explaining that a PDF version was added so it can be opened directly on the phone, with source links on the last page

Note that the two sides are not the same session: the work was done by that desktop session, and the message arrived in the QQ conversation you are bound to. That is exactly why allowCrossSessionNotify is on by default — without it, the session doing the work could not report its own result.

It works in practice: a ten-message burst was delivered in full, and the last six of those went out as proactive pushes. (Tencent's rules for unsolicited sends can change and the plugin assumes no quota; anything undelivered is queued and flushed the next time you speak.)

Scheduled tasks run through the DSH host's own schedule_create / schedule_list / schedule_delete / schedule_update — the plugin does not reimplement what DSH already has, it is only the channel. Plain language is enough:

In the QQ chat the user says 「我去眯一会儿,23:12 叫我」 (I'm going to doze off, wake me at 23:12); the agent answers 「好,定好了 ⏰ **23:12** 喊你(后台定时已启动)。眯着吧,到点我发 QQ 消息叫你 😴」 (done, set for 23:12, the timer is running in the background; doze off, I'll message you on QQ when it is time)

When the time comes it really does push one over (this is a proactive push, not you asking):

A QQ notification on the phone's lock screen: the app icon next to the name Deepseek, reading 「⏰ 23:12 到点了,该起了!」 (it is 23:12, time to get up), with 23:12 in the status bar

"Remind me every morning at 9 what I have to do today", "send me the current time every hour", "show me which scheduled tasks I have" all belong here. Showing them is schedule_list, and so are deleting and changing them.

Reliability

  • A session that is archived or disappears is re-bound automatically, with a line telling you so rather than the message being swallowed: the old conversation was archived → a new one is created to carry on, and you are notified.
  • State writes on Windows have retries and backoff (for the "file is in use" kind of EPERM).
  • Inbound messages with empty content or an unknown frame type leave a log line instead of leaving no trace at all.

Tools the agent can use

ToolWhat it does
send_to_qqSend a file from this machine to the conversation that asked. Images arrive as photos, videos as playable clips, everything else as a file attachment
notify_qqPush to your current QQ conversation from any session. This is what "tell me when it is done" is built on, and it works in practice (a ten-message burst arrived in full; the last six were proactive pushes)
qq_session_controlLook at, switch, create or interrupt conversations; list (or switch) models and their reasoning levels

The qq_ / _qq in those names is deliberate: tool names are unique across the whole host scope, and the WeChat plugin already occupies session_control. Two plugins claiming the same name means whichever registers second fails silently.

Those three come from the plugin. Scheduling is not among them because it does not need the plugin to implement anything: it runs through the DSH host's own schedule_create / schedule_list / schedule_delete / schedule_update, and the plugin's part is