dsh-qqchat 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +276 -0
- package/README.md +211 -0
- package/client-src/plugin.cts +15 -0
- package/client-src/settings.cts +216 -0
- package/client-src/shared.cts +104 -0
- package/client-src/workspace.cts +164 -0
- package/cordis.patch.yml +7 -0
- package/docs/ARCHITECTURE.en.md +346 -0
- package/docs/ARCHITECTURE.md +411 -0
- package/docs/DEVELOPMENT.md +69 -0
- package/docs/MEDIA_AND_QUOTES.md +644 -0
- package/docs/MEMORY.md +99 -0
- package/docs/MEMORY_CONTEXT.md +254 -0
- package/docs/QUOTES.md +355 -0
- package/docs/README.md +22 -0
- package/docs/SECURITY.md +62 -0
- package/docs/STREAMING.md +347 -0
- package/docs/assets//346/211/253/347/240/201/351/223/276/346/216/245.jpg +0 -0
- package/docs/assets//347/276/244/350/201/212/347/225/214/351/235/242.jpg +0 -0
- package/docs/assets//350/256/260/345/277/206/347/263/273/347/273/237.jpg +0 -0
- package/docs/assets//350/256/276/347/275/256/347/225/214/351/235/242.jpg +0 -0
- package/docs/devlog.md +24 -0
- package/lib/client.js +433 -0
- package/lib/commands/dispatch.d.ts +16 -0
- package/lib/commands/dispatch.js +48 -0
- package/lib/config.d.ts +3 -0
- package/lib/config.js +63 -0
- package/lib/gateway/api.d.ts +30 -0
- package/lib/gateway/api.js +202 -0
- package/lib/gateway/auth.d.ts +35 -0
- package/lib/gateway/auth.js +80 -0
- package/lib/gateway/crypto.d.ts +2 -0
- package/lib/gateway/crypto.js +17 -0
- package/lib/gateway/gateway.d.ts +32 -0
- package/lib/gateway/gateway.js +219 -0
- package/lib/gateway/normalize.d.ts +6 -0
- package/lib/gateway/normalize.js +248 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.js +35 -0
- package/lib/media/image-tool.d.ts +4 -0
- package/lib/media/image-tool.js +62 -0
- package/lib/media/media-tools.d.ts +3 -0
- package/lib/media/media-tools.js +68 -0
- package/lib/media/store.d.ts +14 -0
- package/lib/media/store.js +176 -0
- package/lib/session/agent-bridge.d.ts +56 -0
- package/lib/session/agent-bridge.js +613 -0
- package/lib/session/memory-snapshot.d.ts +23 -0
- package/lib/session/memory-snapshot.js +27 -0
- package/lib/session/runtime.d.ts +41 -0
- package/lib/session/runtime.js +395 -0
- package/lib/shared/augmentations.d.ts +40 -0
- package/lib/shared/augmentations.js +1 -0
- package/lib/shared/logging.d.ts +14 -0
- package/lib/shared/logging.js +41 -0
- package/lib/storage/db.d.ts +82 -0
- package/lib/storage/db.js +669 -0
- package/lib/storage/memory.d.ts +50 -0
- package/lib/storage/memory.js +566 -0
- package/lib/transport/rpc.d.ts +18 -0
- package/lib/transport/rpc.js +318 -0
- package/lib/types.d.ts +416 -0
- package/lib/types.js +1 -0
- package/package.json +115 -0
- package/scripts/wrap-client.mjs +20 -0
- package/src/commands/dispatch.ts +75 -0
- package/src/config.ts +70 -0
- package/src/gateway/api.ts +260 -0
- package/src/gateway/auth.ts +99 -0
- package/src/gateway/crypto.ts +16 -0
- package/src/gateway/gateway.ts +207 -0
- package/src/gateway/normalize.ts +236 -0
- package/src/index.ts +46 -0
- package/src/media/image-tool.ts +62 -0
- package/src/media/media-tools.ts +66 -0
- package/src/media/store.ts +157 -0
- package/src/session/agent-bridge.ts +624 -0
- package/src/session/memory-snapshot.ts +41 -0
- package/src/session/runtime.ts +368 -0
- package/src/shared/augmentations.ts +45 -0
- package/src/shared/logging.ts +36 -0
- package/src/storage/db.ts +760 -0
- package/src/storage/memory.ts +581 -0
- package/src/transport/rpc.ts +316 -0
- package/src/types.ts +456 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.client.json +14 -0
- package/tsconfig.json +23 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Coffeiz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# dsh-qqchat
|
|
4
|
+
|
|
5
|
+
### Bring QQ group and direct chats to DeepSeek Harness
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
<a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT License"></a>
|
|
9
|
+
<img src="https://img.shields.io/badge/DSH-Plugin-6f42c1.svg" alt="DSH Plugin">
|
|
10
|
+
<img src="https://img.shields.io/badge/TypeScript-5.x-3178c6.svg" alt="TypeScript">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p>
|
|
14
|
+
<a href="./README.md">中文</a> ·
|
|
15
|
+
<a href="./docs/ARCHITECTURE.en.md">Architecture</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p><em>Chat in QQ, then view the complete Session, memory and tool activity in DSH Web.</em></p>
|
|
19
|
+
|
|
20
|
+
`dsh-qqchat` is an official QQ Bot plugin for [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness). It maps QQ groups and direct chats to ordinary DSH Sessions and uses DSH's native Conversation, Agent, command and tool surfaces.
|
|
21
|
+
|
|
22
|
+
> This is a Vibe Coding project, so code quality and engineering completeness may need improvement. If you find a problem or have a better implementation idea, please open an [Issue](https://github.com/Coffeiz/dsh-qqchat/issues) or submit a [Pull Request](https://github.com/Coffeiz/dsh-qqchat/pulls).
|
|
23
|
+
|
|
24
|
+
> This uses official QQ Bot authorization. It is not QR login for a personal QQ account.
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
| Feature | What it does | Notes |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| QQ group and direct chat | Receives group and C2C messages | One isolated DSH Session per group or direct peer |
|
|
33
|
+
| QR connection | Binds an official QQ Bot from **Settings -> QQ Chat** | Cancel the binding and scan again when needed |
|
|
34
|
+
| Group receive modes | Auto reply, Mention only or Silent record | Silent record stores messages without waking the Agent |
|
|
35
|
+
| Message formats | Smart, Markdown or Plain compatibility | Group and direct-chat formats are configured separately; groups default to Plain compatibility |
|
|
36
|
+
| Direct-chat streaming | Optionally uses QQ's official streaming message API for private chats | Private chats only; Plain compatibility disables it automatically; some clients may not display streaming |
|
|
37
|
+
| Quotes and mentions | Preserves quoted messages and resolves QQ mentions to display names | Stable IDs remain in metadata |
|
|
38
|
+
| Memory system | Stores group, member and direct-user memory | Can be disabled; disabling does not delete existing memory |
|
|
39
|
+
| Memory reflection | Converts recent daily notes into long-term memory | Runs asynchronously after idle or batch thresholds |
|
|
40
|
+
| Media and file permissions | Separately controls receiving media, reading attachments, and regular tools | Owner and direct chats are unrestricted by default |
|
|
41
|
+
| Tool permissions | Separately controls whether group members may use regular Agent tools | Owner is matched by stable user ID |
|
|
42
|
+
| Native DSH commands | Runs `/compact`, `/goal`, `/plan`, `/qqmodel`, `/qqstatus` and more directly from QQ | Commands do not go through the model; `/qqhelp` lists the full set |
|
|
43
|
+
| Native DSH UI | Uses the normal Session list, Conversation surface and composer styling | QQ Sessions remain ungrouped in DSH |
|
|
44
|
+
| Diagnostics | Shows plugin logs in Settings | Useful for connection and delivery troubleshooting |
|
|
45
|
+
|
|
46
|
+
## How to use
|
|
47
|
+
|
|
48
|
+
<table>
|
|
49
|
+
<tr>
|
|
50
|
+
<td width="50%" valign="top">
|
|
51
|
+
<img src="./docs/assets/扫码链接.jpg" width="100%" alt="QQ Chat QR connection">
|
|
52
|
+
<h3>Scan to connect</h3>
|
|
53
|
+
<p>Open <strong>Settings -> QQ Chat</strong> in DSH Web and scan the generated QR code with QQ to authorize an official Bot. Connection status, QR regeneration and cancellation are all available on the same page.</p>
|
|
54
|
+
</td>
|
|
55
|
+
<td width="50%" valign="top">
|
|
56
|
+
<img src="./docs/assets/设置界面.jpg" width="100%" alt="QQ Chat settings page">
|
|
57
|
+
<h3>Settings and permissions</h3>
|
|
58
|
+
<p>Use the settings page to configure group receive mode, message formats, memory, media and file access, tool permissions and the Owner account.</p>
|
|
59
|
+
</td>
|
|
60
|
+
</tr>
|
|
61
|
+
<tr>
|
|
62
|
+
<td width="50%" valign="top">
|
|
63
|
+
<img src="./docs/assets/群聊界面.jpg" width="100%" alt="QQ group chat in DSH Web">
|
|
64
|
+
<h3>Group and direct chat</h3>
|
|
65
|
+
<p>QQ groups and direct chats connect to the DSH Agent and appear as separate Sessions. Groups support auto reply, mention-only reply and silent recording, as well as quoted messages, username display and mention conversion.</p>
|
|
66
|
+
</td>
|
|
67
|
+
<td width="50%" valign="top">
|
|
68
|
+
<img src="./docs/assets/记忆系统.jpg" width="100%" alt="QQ Chat memory system">
|
|
69
|
+
<h3>Memory system</h3>
|
|
70
|
+
<p>The plugin maintains separate memory for groups, members and direct users. Member memory supports profiles, group nicknames, historical nicknames, behavior patterns and long-term notes; recent messages are organized asynchronously. Memory is refreshed as Session context when needed, and can be disabled without deleting stored data.</p>
|
|
71
|
+
</td>
|
|
72
|
+
</tr>
|
|
73
|
+
</table>
|
|
74
|
+
|
|
75
|
+
### Scan to connect
|
|
76
|
+
|
|
77
|
+
1. Start DSH.
|
|
78
|
+
2. Open **Settings -> QQ Chat**.
|
|
79
|
+
3. Choose **Scan to connect** and scan the QR code with QQ.
|
|
80
|
+
4. Authorize the desired official Bot.
|
|
81
|
+
5. The Gateway starts automatically. Use **Cancel connection** before scanning again if you need to bind another Bot.
|
|
82
|
+
|
|
83
|
+
The Host decrypts and stores the AppSecret in the local plugin database. The temporary QR AES key never travels through the browser Client RPC.
|
|
84
|
+
|
|
85
|
+
### Chat in QQ
|
|
86
|
+
|
|
87
|
+
QQ groups and direct chats appear as normal DSH Sessions. Group messages can be handled automatically, only when the Bot is mentioned, or recorded silently. Quotes are preserved, and `@` mentions are displayed with the resolved username whenever QQ provides one.
|
|
88
|
+
|
|
89
|
+
### Use the memory system
|
|
90
|
+
|
|
91
|
+
The plugin keeps separate memory for groups, members and direct users. Member profiles support typed facts, group nicknames, historical nicknames, patterns, summaries and long-term notes. Daily records use one `## YYYY-MM-DD` heading per day and are asynchronously reflected into long-term memory.
|
|
92
|
+
|
|
93
|
+
Memory is injected through DSH's official runtime-context snapshot mechanism, so a new snapshot replaces the previous one instead of accumulating duplicate full contexts. Memory is enabled by default and can be switched off under **Settings -> QQ Chat -> Memory system**. The setting warns that memory may reduce context-cache hit rate and increase input tokens; disabling it stops injection and background reflection without deleting stored data.
|
|
94
|
+
|
|
95
|
+
## Install
|
|
96
|
+
|
|
97
|
+
### New `qqchat` profile
|
|
98
|
+
|
|
99
|
+
Install the official DSH Web bundle together with the plugin:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx @deepseek-ai/dsh plugin --profile qqchat add @deepseek-ai/dsh-web-app dsh-qqchat
|
|
103
|
+
npx @deepseek-ai/dsh --profile qqchat
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Existing Web profile
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-qqchat
|
|
110
|
+
npx @deepseek-ai/dsh --profile web
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Development branch
|
|
114
|
+
|
|
115
|
+
Before npm publication, install the branch directly from GitHub:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npx @deepseek-ai/dsh plugin --profile qqchat add @deepseek-ai/dsh-web-app "git+ssh://git@github.com/Coffeiz/dsh-qqchat.git#agent/typescript-migration"
|
|
119
|
+
npx @deepseek-ai/dsh --profile qqchat
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Git installs build TypeScript through `prepare`. For local development:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
git clone git@github.com:Coffeiz/dsh-qqchat.git
|
|
126
|
+
cd dsh-qqchat
|
|
127
|
+
npm install
|
|
128
|
+
npm run check
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Group receive modes
|
|
132
|
+
|
|
133
|
+
Configure **Settings -> QQ Chat -> Message reception**:
|
|
134
|
+
|
|
135
|
+
| Mode | Behavior |
|
|
136
|
+
| --- | --- |
|
|
137
|
+
| Auto reply | Every group message can trigger the Agent |
|
|
138
|
+
| Mention only | All messages are stored, but only messages mentioning the Bot trigger a reply |
|
|
139
|
+
| Silent record | Stores messages and memory without actively replying |
|
|
140
|
+
|
|
141
|
+
Groups default to Plain compatibility format. Group and direct-chat formats can be selected independently. Plain compatibility for direct chats automatically disables streaming.
|
|
142
|
+
|
|
143
|
+
## Commands
|
|
144
|
+
|
|
145
|
+
Messages beginning with `/` are handled directly by the command system and are not sent to the model. Native DSH commands keep their original names; QQChat commands use the `qq` prefix. In a group, write `@Bot /help` or `@Bot /qqhelp`.
|
|
146
|
+
|
|
147
|
+
| Command | Purpose |
|
|
148
|
+
| --- | --- |
|
|
149
|
+
| `/qqhelp`, `/qqcommands` | List QQChat and DSH commands |
|
|
150
|
+
| `/qqnew`, `/qqreset`, `/qqclear` | Keep the old Session and start a new one on the next message |
|
|
151
|
+
| `/compact` | Compact older conversation history |
|
|
152
|
+
| `/qqmodel [provider/]model` | Show or switch the current Session model |
|
|
153
|
+
| `/qqstop` | Stop the current generation |
|
|
154
|
+
| `/qqstatus` | Show Session, model and generation status |
|
|
155
|
+
| `/qqping` | Check QQChat connectivity |
|
|
156
|
+
| `/qqversion` | Show the plugin version |
|
|
157
|
+
| `/goal` | Manage a DSH Goal |
|
|
158
|
+
| `/plan` | Enter or leave Plan mode |
|
|
159
|
+
| `/feedback` | Submit feedback |
|
|
160
|
+
| `/permission` | View or switch tool permission presets |
|
|
161
|
+
|
|
162
|
+
### Where `/feedback` goes
|
|
163
|
+
|
|
164
|
+
`/feedback` uses DSH's native feedback mechanism. It does not create a GitHub Issue or send feedback directly to the QQChat authors. By default, feedback is written only to the current DSH Session's local log and does not leave the machine.
|
|
165
|
+
|
|
166
|
+
It is uploaded to a configured OTLP service only when DSH session telemetry is explicitly enabled:
|
|
167
|
+
|
|
168
|
+
| DSH telemetry mode | Destination |
|
|
169
|
+
| --- | --- |
|
|
170
|
+
| `DISABLED` (default) | Local DSH Session only |
|
|
171
|
+
| `FEEDBACK_ONLY` | The current Session log suffix is sent to the configured OTLP service when `/feedback` is recorded |
|
|
172
|
+
| `FULL` | Session events are sent to the configured OTLP service in real time; `/feedback` also records a feedback event |
|
|
173
|
+
|
|
174
|
+
Feedback may include the current Session's conversation, tool arguments, tool results and workspace path. Check your DSH telemetry settings before submitting sensitive information.
|
|
175
|
+
|
|
176
|
+
`/export` is a browser-only DSH Web command and is not available from QQ. Model changes apply independently to each group or direct Session while preserving the existing conversation.
|
|
177
|
+
|
|
178
|
+
## Memory content
|
|
179
|
+
|
|
180
|
+
QQ Chat stores:
|
|
181
|
+
|
|
182
|
+
- Group memory: important events, agreements, topics and relationships.
|
|
183
|
+
- Member memory: profile facts, group nicknames, historical nicknames, behavior patterns and long-term information.
|
|
184
|
+
- Direct-chat memory: long-term information about a direct QQ user.
|
|
185
|
+
|
|
186
|
+
Reflection runs asynchronously after the chat is idle or enough messages have accumulated. The **QQ Memory** action at the top of a QQ Session shows group and member memory. Memory snapshots refresh when a Session starts, the memory context expires, or the Session is compacted; continuous conversation does not repeatedly write the full memory. Enabled memory may reduce context-cache hit rate or increase input tokens, and can be disabled under **Settings -> QQ Chat -> Memory system** without deleting stored data.
|
|
187
|
+
|
|
188
|
+
## Tool permissions
|
|
189
|
+
|
|
190
|
+
When **Group members can use tools** is enabled, group-triggered Agent turns may use the tools exposed by the current preset. When disabled, only the configured Owner stable ID may execute tools; other group members can still chat normally.
|
|
191
|
+
|
|
192
|
+
Owner matching uses a stable QQ user ID, not a nickname.
|
|
193
|
+
|
|
194
|
+
## Message display
|
|
195
|
+
|
|
196
|
+
QQ conversations use DSH's default Conversation UI:
|
|
197
|
+
|
|
198
|
+
- Sender usernames are displayed without exposing stable IDs in the bubble.
|
|
199
|
+
- Own and other people's messages use the native DSH bubble alignment.
|
|
200
|
+
- Quoted messages are displayed.
|
|
201
|
+
- QQ `@` mentions are converted to usernames when available.
|
|
202
|
+
- The DSH Session composer can proactively send messages to QQ.
|
|
203
|
+
|
|
204
|
+
## Notes
|
|
205
|
+
|
|
206
|
+
- An official QQ Bot is required; personal QQ account login is not supported.
|
|
207
|
+
- `0.2.0` is still being refined; test with a dedicated Bot and group first.
|
|
208
|
+
- Rich media, full QQ emoji handling and some complex message formats may require compatibility mode.
|
|
209
|
+
- Uninstalling the plugin does not automatically delete saved chat or memory data.
|
|
210
|
+
|
|
211
|
+
## Settings
|
|
212
|
+
|
|
213
|
+
The Settings page contains configuration only:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
QR authorization and connection
|
|
217
|
+
Group receive mode
|
|
218
|
+
Group and direct-chat reply formats
|
|
219
|
+
Memory system [on/off]
|
|
220
|
+
Media and file permissions and regular tool permissions are independent settings:
|
|
221
|
+
|
|
222
|
+
- **Receive group-member media/files** controls whether images, files, audio, and video are downloaded, stored, and shown in the session.
|
|
223
|
+
- **Allow group members to read media/files** controls whether their Agent turns may call QQChat media tools for the current attachment.
|
|
224
|
+
- **Group members can use tools** controls access to regular Agent tools.
|
|
225
|
+
Owner stable ID
|
|
226
|
+
Diagnostics and logs
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The Settings page does not contain chat lists, transcripts or memory browsing. Those remain in the normal DSH Session and Conversation surfaces.
|
|
230
|
+
|
|
231
|
+
## Persistence and memory scopes
|
|
232
|
+
|
|
233
|
+
The SQLite database is stored at:
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
$DSH_HOME/plugins/dsh-qqchat/qqchat.sqlite
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
SQLite is the source of truth for real QQ history, identities, settings, memory documents and the proactive-message outbox. DSH Sessions store the Agent turns, model output, tools, titles and visible transcript events.
|
|
240
|
+
|
|
241
|
+
Memory scopes are isolated as follows:
|
|
242
|
+
|
|
243
|
+
- **Group:** profile, summary, daily and long-term memory for one QQ group.
|
|
244
|
+
- **Member:** typed profile, pattern, summary, daily and long-term memory for one stable sender.
|
|
245
|
+
- **Direct chat:** uses the member scope for that QQ user.
|
|
246
|
+
|
|
247
|
+
The same stable sender may retain member memory across groups under the same Bot. Group relationships and group-specific facts never cross group scopes. Reflection runs after roughly 120 seconds of inactivity or 20 unreflected messages, and can also compress older daily records after the configured thresholds.
|
|
248
|
+
|
|
249
|
+
## Development
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
npm run typecheck
|
|
253
|
+
npm test
|
|
254
|
+
npm run build
|
|
255
|
+
npm run check
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
The source layout follows feature boundaries:
|
|
259
|
+
|
|
260
|
+
```text
|
|
261
|
+
src/config.ts runtime configuration
|
|
262
|
+
src/gateway/ QQ API, authorization, Gateway and normalization
|
|
263
|
+
src/session/ Agent bridge and QQ runtime
|
|
264
|
+
src/storage/ SQLite and memory engine
|
|
265
|
+
src/transport/ Client RPC
|
|
266
|
+
src/commands/ QQ command dispatch
|
|
267
|
+
src/shared/ shared augmentations and logging
|
|
268
|
+
client-src/ DSH Web Client factory and settings UI
|
|
269
|
+
tests/ automated tests
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
See [docs/ARCHITECTURE.en.md](./docs/ARCHITECTURE.en.md) for the detailed boundaries and data flow.
|
|
273
|
+
|
|
274
|
+
## License
|
|
275
|
+
|
|
276
|
+
This project is released under the [MIT License](./LICENSE).
|
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# dsh-qqchat
|
|
4
|
+
|
|
5
|
+
### 让 QQ 群聊与私聊接入 DeepSeek Harness
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
<a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT License"></a>
|
|
9
|
+
<img src="https://img.shields.io/badge/DSH-Plugin-6f42c1.svg" alt="DSH Plugin">
|
|
10
|
+
<img src="https://img.shields.io/badge/TypeScript-5.x-3178c6.svg" alt="TypeScript">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p>
|
|
14
|
+
<a href="./README.en.md">English</a> ·
|
|
15
|
+
<a href="./docs/DEVELOPMENT.md">开发文档</a> ·
|
|
16
|
+
<a href="./docs/ARCHITECTURE.md">架构说明</a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p><em>dsh-qqchat 是 DeepSeek Harness(DSH)的 QQ 官方 Bot 插件,支持 QQ 群聊、私聊、会话隔离、记忆系统和 DSH 原生命令。</em></p>
|
|
20
|
+
|
|
21
|
+
> 本项目是一个 Vibe Coding 项目,代码质量和工程完整性可能需要改进。如果你发现问题或有更好的实现建议,欢迎提交 [Issue](https://github.com/Coffeiz/dsh-qqchat/issues) 或 [Pull Request](https://github.com/Coffeiz/dsh-qqchat/pulls)。
|
|
22
|
+
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
## 主要功能
|
|
26
|
+
|
|
27
|
+
| 功能 | 说明 | 备注 |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| QQ 群聊与私聊 | 接收 QQ 官方 Bot 的群聊和私聊消息 | 每个群、每个私聊对象对应独立 DSH 会话 |
|
|
30
|
+
| 扫码连接 | 在 **设置 → QQ Chat** 中扫码绑定 QQ Bot | 支持取消连接后重新绑定 |
|
|
31
|
+
| 断线重连 | QQ Gateway 断线后自动恢复连接 | 无需重复扫码 |
|
|
32
|
+
| 群聊回复模式 | 自动回应、@回复、静默记录 | 可在设置页随时切换 |
|
|
33
|
+
| 消息格式兼容 | 智能兼容、Markdown、纯文本兼容 | 群聊和私聊可分别设置;群聊默认纯文本兼容 |
|
|
34
|
+
| 私聊流式回复 | 私聊可选用 QQ 官方流式消息接口逐步更新回复 | 仅适用于私聊;纯文本兼容模式自动关闭;部分客户端可能不可见 |
|
|
35
|
+
| 消息引用与 @ | 支持引用消息和 QQ @消息 | @用户优先显示用户名 |
|
|
36
|
+
| 会话隔离 | QQ 群聊和私聊分别使用独立会话 | 不同群、不同用户的上下文互相隔离 |
|
|
37
|
+
| 记忆系统 | 保存群聊、群成员和私聊用户的独立记忆 | 设置中可关闭;关闭不会删除已有记忆 |
|
|
38
|
+
| 记忆整理 | 自动将近期记录整理为长期记忆 | 后台执行,不阻塞正常回复 |
|
|
39
|
+
| 媒体与文件权限 | 分别控制群成员媒体接收、媒体读取和普通工具使用 | Owner 与私聊默认不受限制 |
|
|
40
|
+
| 工具权限 | 单独控制群成员是否可以使用普通 Agent 工具 | 可指定 Owner,按稳定用户 ID 判断 |
|
|
41
|
+
| DSH / QQChat 命令 | QQ 中直接执行 `/compact`、`/goal`、`/plan`、`/qqmodel`、`/qqstatus` 等命令 | 命令不经过模型;发送 `/qqhelp` 查看完整列表 |
|
|
42
|
+
| DSH 原生界面 | 使用 DSH 默认会话、聊天区和输入框 | 支持从 DSH 主动向 QQ 发送消息 |
|
|
43
|
+
| 日志查看 | 在设置页查看 QQ Chat 运行日志 | 方便排查连接和消息问题 |
|
|
44
|
+
|
|
45
|
+
## 如何使用
|
|
46
|
+
|
|
47
|
+
<table>
|
|
48
|
+
<tr>
|
|
49
|
+
<td width="50%" valign="top">
|
|
50
|
+
<img src="./docs/assets/扫码链接.jpg" width="100%" alt="QQ Chat 扫码连接">
|
|
51
|
+
<h3>扫码连接</h3>
|
|
52
|
+
<p>在 DSH Web 的 <strong>设置 → QQ Chat</strong> 中生成二维码,使用手机 QQ 扫描即可完成官方 Bot 授权。连接状态、重新生成二维码和取消绑定都可以在同一页面完成。</p>
|
|
53
|
+
</td>
|
|
54
|
+
<td width="50%" valign="top">
|
|
55
|
+
<img src="./docs/assets/设置界面.jpg" width="100%" alt="QQ Chat 设置页面">
|
|
56
|
+
<h3>设置与权限</h3>
|
|
57
|
+
<p>在设置页面配置群聊接收方式、消息格式、记忆系统、媒体与文件权限、工具权限以及 Owner。</p>
|
|
58
|
+
</td>
|
|
59
|
+
</tr>
|
|
60
|
+
<tr>
|
|
61
|
+
<td width="50%" valign="top">
|
|
62
|
+
<img src="./docs/assets/群聊界面.jpg" width="100%" alt="QQ 群聊在 DSH Web 中的显示">
|
|
63
|
+
<h3>群聊与私聊</h3>
|
|
64
|
+
<p>QQ 群聊和私聊都会接入 DSH Agent,并在 DSH Web 中以独立 Session 展示。群聊支持自动回应、@回复和静默记录,也支持引用消息、用户名显示和 @用户转换。</p>
|
|
65
|
+
</td>
|
|
66
|
+
<td width="50%" valign="top">
|
|
67
|
+
<img src="./docs/assets/记忆系统.jpg" width="100%" alt="QQ Chat 群聊记忆系统">
|
|
68
|
+
<h3>记忆系统</h3>
|
|
69
|
+
<p>插件会分别维护群聊、群成员和私聊用户的记忆。成员记忆支持资料、群内称呼、历史昵称、行为模式和长期信息;近期消息会在空闲或达到阈值后自动整理。记忆会作为 Session 上下文按需刷新,设置中可以关闭,关闭后不会删除已有数据。</p>
|
|
70
|
+
</td>
|
|
71
|
+
</tr>
|
|
72
|
+
</table>
|
|
73
|
+
|
|
74
|
+
## 安装
|
|
75
|
+
|
|
76
|
+
### 新建一个 QQ Chat profile
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npx @deepseek-ai/dsh plugin --profile qqchat add @deepseek-ai/dsh-web-app dsh-qqchat
|
|
80
|
+
npx @deepseek-ai/dsh --profile qqchat
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 安装到已有的 Web profile
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx @deepseek-ai/dsh plugin --profile web add dsh-qqchat
|
|
87
|
+
npx @deepseek-ai/dsh --profile web
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
当前开发分支也可以直接从 GitHub 安装:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npx @deepseek-ai/dsh plugin --profile qqchat add @deepseek-ai/dsh-web-app "git+ssh://git@github.com/Coffeiz/dsh-qqchat.git#agent/typescript-migration"
|
|
94
|
+
npx @deepseek-ai/dsh --profile qqchat
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 第一次连接 QQ
|
|
98
|
+
|
|
99
|
+
1. 启动 DSH Web。
|
|
100
|
+
2. 打开 **设置 → QQ Chat**。
|
|
101
|
+
3. 点击 **扫码连接**。
|
|
102
|
+
4. 使用手机 QQ 扫描二维码,并选择要授权的官方 Bot。
|
|
103
|
+
5. 授权完成后,QQ Gateway 会自动连接。
|
|
104
|
+
|
|
105
|
+
连接成功后,QQ Chat 的设置和对话会出现在 DSH 中。
|
|
106
|
+
|
|
107
|
+
## 群聊接收方式
|
|
108
|
+
|
|
109
|
+
在 **设置 → QQ Chat → 消息接收** 中可以选择:
|
|
110
|
+
|
|
111
|
+
| 模式 | 行为 |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| 自动回应 | 每条群消息都会交给 Agent,Agent 可以自动回复 |
|
|
114
|
+
| @回复 | 所有消息都会记录,但只有 @Bot 的消息会触发回复 |
|
|
115
|
+
| 静默记录 | 只保存消息和记忆,不主动回复 |
|
|
116
|
+
|
|
117
|
+
群聊默认使用纯文本兼容格式,适合不同 QQ 客户端。私聊和群聊可以分别选择智能兼容、Markdown 或纯文本兼容。私聊使用纯文本兼容时会自动关闭流式传输。
|
|
118
|
+
|
|
119
|
+
## 命令
|
|
120
|
+
|
|
121
|
+
QQ 中以 `/` 开头的消息会交给命令系统处理,不会作为普通消息发送给模型。DSH 原生命令保持原名;QQChat 自有命令使用 `qq` 前缀。群聊中可以发送 `@Bot /help` 或 `@Bot /qqhelp`。
|
|
122
|
+
|
|
123
|
+
| 命令 | 用途 |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| `/qqhelp`、`/qqcommands` | 查看 QQChat 和 DSH 命令 |
|
|
126
|
+
| `/qqnew`、`/qqreset`、`/qqclear` | 保留旧 Session,下一条消息开始新的 QQ Session |
|
|
127
|
+
| `/compact` | 手动压缩较早的会话历史 |
|
|
128
|
+
| `/qqmodel [provider/]model` | 查看或切换当前群聊/私聊的模型 |
|
|
129
|
+
| `/qqstop` | 中止当前生成 |
|
|
130
|
+
| `/qqstatus` | 查看当前 Session、模型和生成状态 |
|
|
131
|
+
| `/qqping` | 测试 QQChat 连通性 |
|
|
132
|
+
| `/qqversion` | 查看 QQChat 版本 |
|
|
133
|
+
| `/goal` | 查看、创建、编辑、暂停、恢复或清除 Goal |
|
|
134
|
+
| `/plan` | 进入或退出 Plan 模式 |
|
|
135
|
+
| `/feedback` | 提交反馈 |
|
|
136
|
+
| `/permission` | 查看或切换工具权限预设 |
|
|
137
|
+
|
|
138
|
+
### `/feedback` 反馈去向
|
|
139
|
+
|
|
140
|
+
`/feedback` 使用 DSH 原生反馈机制,不会自动创建 GitHub Issue,也不会直接发送给 QQChat 作者。默认情况下,反馈只写入当前 DSH Session 的本地日志,不会离开本机。
|
|
141
|
+
|
|
142
|
+
只有在 DSH 显式配置会话遥测时才会上传到配置的 OTLP 服务:
|
|
143
|
+
|
|
144
|
+
| DSH 遥测模式 | 反馈去向 |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `DISABLED`(默认) | 仅保存在本地 Session |
|
|
147
|
+
| `FEEDBACK_ONLY` | 执行 `/feedback` 时,将当前 Session 日志后缀发送到配置的 OTLP 服务 |
|
|
148
|
+
| `FULL` | Session 事件按配置实时发送到 OTLP 服务;`/feedback` 另外记录反馈事件 |
|
|
149
|
+
|
|
150
|
+
反馈可能包含当前 Session 的对话、工具参数、工具结果和工作区路径。提交前请确认 DSH 遥测配置符合你的隐私要求。
|
|
151
|
+
|
|
152
|
+
`/export` 是 DSH Web 的浏览器下载命令,QQ 中会提示暂不支持。模型切换按群聊/私聊分别生效,并保留已有对话上下文。
|
|
153
|
+
|
|
154
|
+
## 记忆内容
|
|
155
|
+
|
|
156
|
+
QQ Chat 会分别保存:
|
|
157
|
+
|
|
158
|
+
- 群聊记忆:群里的重要事件、约定、话题和关系
|
|
159
|
+
- 群成员记忆:成员的资料、群内称呼、历史昵称、行为特点和长期信息
|
|
160
|
+
- 私聊记忆:与某个 QQ 用户的长期对话信息
|
|
161
|
+
|
|
162
|
+
记忆会在聊天空闲或积累到一定数量后异步整理,不会阻塞正常回复。可以从 QQ Session 顶部的 **QQ 记忆** 入口查看群和成员记忆。记忆内容会按需进入 Agent 上下文,启用后可能降低上下文缓存命中率并增加输入 token;可在 **设置 → QQ Chat → 记忆系统** 中关闭。
|
|
163
|
+
|
|
164
|
+
记忆快照会在新 Session、记忆上下文过期或 Session 压缩后刷新,连续对话不会重复写入完整记忆。群级记忆和当前群员记忆分别管理,群持续活跃不会替潜水成员刷新成员记忆。
|
|
165
|
+
|
|
166
|
+
## 工具权限
|
|
167
|
+
|
|
168
|
+
在设置中,媒体与文件权限和普通工具权限分别控制:
|
|
169
|
+
|
|
170
|
+
- **接收群成员媒体/文件**:控制是否下载、存储并在会话中显示群成员发送的图片、文件、音频和视频。
|
|
171
|
+
- **允许群成员读取媒体/文件**:控制群成员触发的 Agent 是否可以调用 QQChat 媒体工具读取当前消息附件。
|
|
172
|
+
- **群成员可用工具**:控制群成员是否可以使用当前 preset 的普通 Agent 工具。
|
|
173
|
+
|
|
174
|
+
关闭媒体接收不会影响普通文字消息;关闭普通工具或媒体读取也不会影响群友正常聊天和获得回复。
|
|
175
|
+
|
|
176
|
+
Owner 使用 QQ 的稳定用户 ID 判断,不根据昵称判断身份。
|
|
177
|
+
|
|
178
|
+
## 消息显示
|
|
179
|
+
|
|
180
|
+
QQ 对话会使用 DSH 的默认聊天界面显示:
|
|
181
|
+
|
|
182
|
+
- 显示发送人用户名
|
|
183
|
+
- 区分自己发送和他人发送的消息
|
|
184
|
+
- 支持消息引用显示
|
|
185
|
+
- 支持 QQ @消息转换为用户名
|
|
186
|
+
- 支持从 DSH 会话输入框主动发送 QQ 消息
|
|
187
|
+
|
|
188
|
+
## 注意事项
|
|
189
|
+
|
|
190
|
+
- 需要 QQ 官方 Bot,不支持个人 QQ 账号登录。
|
|
191
|
+
- `0.2.0` 仍在持续完善,建议先在测试 Bot 和测试群中使用。
|
|
192
|
+
- 富媒体、完整 QQ 表情和部分复杂消息格式可能需要使用兼容模式。
|
|
193
|
+
- 卸载插件不会自动删除已经保存的聊天和记忆数据。
|
|
194
|
+
|
|
195
|
+
## 本地开发
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
npm install
|
|
199
|
+
npm run check
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
更多开发约定和内部说明见:
|
|
203
|
+
|
|
204
|
+
- [开发说明](./docs/DEVELOPMENT.md)
|
|
205
|
+
- [记忆规则](./docs/MEMORY.md)
|
|
206
|
+
- [安全边界](./docs/SECURITY.md)
|
|
207
|
+
- [架构说明](./docs/ARCHITECTURE.md)
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
本项目使用 [MIT License](./LICENSE)。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { installStyles, setQQRpc } from './shared.cjs'
|
|
2
|
+
import type { Ctx } from './shared.cjs'
|
|
3
|
+
import { QQSettings } from './settings.cjs'
|
|
4
|
+
import { QQSessionUtility, QQTranscriptNode, createQQMessageDefinition } from './workspace.cjs'
|
|
5
|
+
|
|
6
|
+
exports.inject = ['slots', 'connection', 'conversationEvents'] as const
|
|
7
|
+
exports.apply = function apply(ctx: Ctx) {
|
|
8
|
+
setQQRpc(ctx.connection.rpc)
|
|
9
|
+
ctx.effect(installStyles, 'dsh-qqchat: client styles')
|
|
10
|
+
ctx.conversationEvents.register(createQQMessageDefinition())
|
|
11
|
+
|
|
12
|
+
ctx.slots.inject('settings.section', () => ctx.slots.register({ name: 'settings.section', id: 'qqchat', order: 35, label: () => 'QQ Chat', inject: () => ({ rpc: ctx.connection.rpc }) }, QQSettings))
|
|
13
|
+
ctx.slots.inject('conversation.chat.node', () => ctx.slots.register({ name: 'conversation.chat.node', key: 'qqchat-message' }, QQTranscriptNode))
|
|
14
|
+
ctx.slots.inject('conversation.session.header.utilities', () => ctx.slots.register({ name: 'conversation.session.header.utilities', id: 'qqchat-memory', order: 30, inject: () => ({ rpc: ctx.connection.rpc }) }, QQSessionUtility))
|
|
15
|
+
}
|