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
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
# dsh-qqchat Architecture
|
|
2
|
+
|
|
3
|
+
[中文](./ARCHITECTURE.md)
|
|
4
|
+
|
|
5
|
+
## Core boundary
|
|
6
|
+
|
|
7
|
+
`dsh-qqchat` is an out-of-tree DSH plugin and does not fork DeepSeek Harness.
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
dsh-qqchat
|
|
11
|
+
QQ protocol / auth / identity
|
|
12
|
+
real QQ history
|
|
13
|
+
receive policy
|
|
14
|
+
group + member memory
|
|
15
|
+
tool authority
|
|
16
|
+
proactive sending
|
|
17
|
+
QQ-specific Client presentation
|
|
18
|
+
|
|
19
|
+
DSH
|
|
20
|
+
Agent loop
|
|
21
|
+
Session lifecycle
|
|
22
|
+
model routing
|
|
23
|
+
tools
|
|
24
|
+
Session list
|
|
25
|
+
Conversation shell
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
QQ Chat owns neither a second AgentLoop nor a second chat-navigation system.
|
|
29
|
+
|
|
30
|
+
## Sessions are the navigation unit
|
|
31
|
+
|
|
32
|
+
Each QQ peer maps to one ordinary DSH Session:
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
group -> groups.dsh_session_id
|
|
36
|
+
c2c -> members.dsh_session_id
|
|
37
|
+
|
|
38
|
+
sessionId = qqchat-<uuid>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Titles are persisted through DSH session titles:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
QQ Group · <group name>
|
|
45
|
+
QQ Direct · <nickname>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The Client no longer registers a `sidebar.footer.action` chat picker. QQ Sessions are listed and opened by DSH's normal Session/Workspace Browser.
|
|
49
|
+
|
|
50
|
+
A new silent-only peer would otherwise remain blank because DSH uses `turn/start` to decide whether a Session has begun. The plugin submits one internal `qq-chat-bootstrap` wake and rejects it in `agent/pre-step`. This leaves a durable turn boundary while producing no model step, no LLM call, no QQ output and no model-visible bootstrap content.
|
|
51
|
+
|
|
52
|
+
## Settings boundary
|
|
53
|
+
|
|
54
|
+
`settings.section: qqchat` contains only the control plane:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
QR authorization / connection
|
|
58
|
+
Auto reply / Mention only / Silent record
|
|
59
|
+
reply compatibility format
|
|
60
|
+
memory system [on/off]
|
|
61
|
+
group-member tool permission
|
|
62
|
+
Owner stable ID
|
|
63
|
+
plugin logs
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Settings does not contain chat lists, transcripts or memory browsing.
|
|
67
|
+
|
|
68
|
+
## Conversation boundary
|
|
69
|
+
|
|
70
|
+
QQ Sessions use the main DSH Conversation surface.
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
conversation.chat.node
|
|
74
|
+
qqchat-message # only QQ transcript rows that do not wake the Agent
|
|
75
|
+
|
|
76
|
+
conversation.composer
|
|
77
|
+
QQ Session composer # proactive QQ send, no local Agent turn
|
|
78
|
+
|
|
79
|
+
conversation.session.header.utilities
|
|
80
|
+
QQ Memory
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Agent-triggering QQ messages
|
|
84
|
+
|
|
85
|
+
Messages selected by the receive policy use DSH's native `user/message` path:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
QQ inbound
|
|
89
|
+
-> SQLite
|
|
90
|
+
-> context snapshot
|
|
91
|
+
-> Agent.followup()
|
|
92
|
+
-> user/message
|
|
93
|
+
-> DSH Agent loop
|
|
94
|
+
-> assistant/tool events
|
|
95
|
+
-> QQ API
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The source keeps `kind: user` while adding reliable QQ metadata such as channel, bot id, chat id, sender id, message id and mention state. The same incoming message is therefore not also appended as `qqchat/message`, preventing duplicate transcript rows.
|
|
99
|
+
|
|
100
|
+
### Messages that do not wake the Agent
|
|
101
|
+
|
|
102
|
+
Messages observed in Mention-only or Silent-record modes append the plugin's log-only event:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
qqchat/message
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
It can be rendered by the Client but is not part of the DSH model surface and never wakes the Agent.
|
|
109
|
+
|
|
110
|
+
The plugin no longer replays SQLite history into new DSH Sessions. SQLite remains the complete QQ-world history; DSH persistence records the Session events that actually happened while the plugin was running.
|
|
111
|
+
|
|
112
|
+
## Host / Client
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
DSH Web Client
|
|
116
|
+
|
|
|
117
|
+
| Connection RPC /qqchat
|
|
118
|
+
v
|
|
119
|
+
+--------------------------------------+
|
|
120
|
+
| dsh-qqchat Host |
|
|
121
|
+
| |
|
|
122
|
+
| QQBindService |
|
|
123
|
+
| QQGateway -- QQApiClient |
|
|
124
|
+
| | |
|
|
125
|
+
| v |
|
|
126
|
+
| QQChatRuntime |
|
|
127
|
+
| | | |
|
|
128
|
+
| | +-- QQChatDatabase |
|
|
129
|
+
| | +-- MemoryEngine |
|
|
130
|
+
| | +-- QQChatLogger |
|
|
131
|
+
| v |
|
|
132
|
+
| DshQQBridge |
|
|
133
|
+
+---+----------------------------------+
|
|
134
|
+
v
|
|
135
|
+
DSH Agent / Session / Tools
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Credentials, tokens and temporary QR AES keys stay on the Host side.
|
|
139
|
+
|
|
140
|
+
## Three data planes
|
|
141
|
+
|
|
142
|
+
### QQ world truth
|
|
143
|
+
|
|
144
|
+
SQLite owns:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
accounts
|
|
148
|
+
groups
|
|
149
|
+
members
|
|
150
|
+
group_members
|
|
151
|
+
messages
|
|
152
|
+
memory_documents
|
|
153
|
+
reflection_state
|
|
154
|
+
plugin_settings
|
|
155
|
+
outbox
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### DSH Session/UI plane
|
|
159
|
+
|
|
160
|
+
The Session log owns Agent turns, assistant/tool events, log-only QQ transcript rows, titles and turn boundaries.
|
|
161
|
+
|
|
162
|
+
### Model surface
|
|
163
|
+
|
|
164
|
+
The model receives the normal DSH surface plus context snapshots explicitly injected by the plugin. Full QQ history does not become model history merely because it exists in SQLite or the UI transcript.
|
|
165
|
+
|
|
166
|
+
Memory snapshots use DSH's official `@deepseek-ai/dsh-system-prompt` runtime-context source. DSH's runtime-context projection replaces the previous snapshot when a new one is injected, so a full memory context is not appended as a new ordinary user message on every turn.
|
|
167
|
+
|
|
168
|
+
## Inbound state machine
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
QQ dispatch
|
|
172
|
+
|
|
|
173
|
+
normalize stable identity
|
|
174
|
+
|
|
|
175
|
+
upsert member/group
|
|
176
|
+
|
|
|
177
|
+
insert SQLite message
|
|
178
|
+
|
|
|
179
|
+
receive mode
|
|
180
|
+
+-- silent -----------------> qqchat/message -> stop
|
|
181
|
+
+-- mention + not @ --------> qqchat/message -> stop
|
|
182
|
+
`-- auto / mentioned / c2c
|
|
183
|
+
+-- assemble memory/context
|
|
184
|
+
+-- Agent.followup(user message)
|
|
185
|
+
+-- DSH tools/model loop
|
|
186
|
+
`-- QQ outbound
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Every mode preserves real QQ history and memory input. The receive mode only controls whether a message enters an Agent turn.
|
|
190
|
+
|
|
191
|
+
## Identity
|
|
192
|
+
|
|
193
|
+
Stable sender priority:
|
|
194
|
+
|
|
195
|
+
```text
|
|
196
|
+
author.user_openid
|
|
197
|
+
|| author.member_openid
|
|
198
|
+
|| author.id
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
```text
|
|
202
|
+
senderId -> identity / authority / memory key
|
|
203
|
+
senderName -> display only
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Nicknames are never treated as identity evidence.
|
|
207
|
+
|
|
208
|
+
## Agent context
|
|
209
|
+
|
|
210
|
+
Before a group turn the plugin reconstructs:
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
recent group history
|
|
214
|
+
+ group profile / summary / memory / daily
|
|
215
|
+
+ current member profile / pattern / summary
|
|
216
|
+
+ stable sender and group metadata
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The current QQ text enters as the normal user prompt; reliable identity is retained in source metadata and the injected context snapshot.
|
|
220
|
+
|
|
221
|
+
Group snapshots contain group profile/summary/daily/memory, current member profile/pattern/summary/memory, stable group and sender IDs, and recent group history. Direct-chat snapshots contain the member profile/pattern/summary/daily/memory and the stable sender ID.
|
|
222
|
+
|
|
223
|
+
## Tool authority
|
|
224
|
+
|
|
225
|
+
The plugin uses DSH's official:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
tools/pre-execute
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
During one QQ turn it tracks:
|
|
232
|
+
|
|
233
|
+
```text
|
|
234
|
+
sessionId -> { chatType, senderId }
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Policy:
|
|
238
|
+
|
|
239
|
+
```text
|
|
240
|
+
non-group QQ turn -> allow
|
|
241
|
+
groupMembersCanUseTools == true -> allow
|
|
242
|
+
senderId == ownerUserId -> allow
|
|
243
|
+
otherwise -> deny
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
No Tool Runtime or AgentLoop fork is required.
|
|
247
|
+
|
|
248
|
+
## Memory scope
|
|
249
|
+
|
|
250
|
+
Group:
|
|
251
|
+
|
|
252
|
+
```text
|
|
253
|
+
profile
|
|
254
|
+
summary
|
|
255
|
+
daily
|
|
256
|
+
memory
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Member:
|
|
260
|
+
|
|
261
|
+
```text
|
|
262
|
+
profile
|
|
263
|
+
pattern
|
|
264
|
+
summary
|
|
265
|
+
daily
|
|
266
|
+
memory
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Direct chats use the member scope. Memory injection can be disabled in Settings; disabling it stops context injection and background reflection but does not delete stored documents. The UI warns that enabled memory may reduce context-cache hit rate and increase input tokens.
|
|
270
|
+
|
|
271
|
+
Group scope never crosses groups. Member scope may remain continuous across groups under the same Bot.
|
|
272
|
+
|
|
273
|
+
Reflection is triggered by idle debounce or batch threshold and attributes updates by stable sender id.
|
|
274
|
+
|
|
275
|
+
## Memory UI
|
|
276
|
+
|
|
277
|
+
The `QQ Memory` Session utility shows group profile/summary/memory/daily and a member list. Selecting a member opens that member's profile/pattern/summary. Direct Sessions show the corresponding member profile/pattern/summary. Daily and memory documents are persisted for direct chats even when the current UI presents a smaller member overview.
|
|
278
|
+
|
|
279
|
+
## Proactive sending
|
|
280
|
+
|
|
281
|
+
The QQ Session composer calls `chat/send`:
|
|
282
|
+
|
|
283
|
+
```text
|
|
284
|
+
group -> /v2/groups/.../messages
|
|
285
|
+
c2c -> /v2/users/.../messages
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
This sends directly to QQ and does not create another local Agent prompt. The durable outbox remains independent of a Session being live.
|
|
289
|
+
|
|
290
|
+
## RPC
|
|
291
|
+
|
|
292
|
+
The Host registers the loopback RPC namespace:
|
|
293
|
+
|
|
294
|
+
```text
|
|
295
|
+
/qqchat
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Main endpoints include:
|
|
299
|
+
|
|
300
|
+
```text
|
|
301
|
+
status
|
|
302
|
+
auth/start
|
|
303
|
+
auth/poll
|
|
304
|
+
settings/get
|
|
305
|
+
settings/update
|
|
306
|
+
logs/list
|
|
307
|
+
chat/send
|
|
308
|
+
chat/info
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Legacy chat and group endpoints remain available for compatibility, but the main DSH navigation no longer depends on them.
|
|
312
|
+
|
|
313
|
+
## Persistence boundary
|
|
314
|
+
|
|
315
|
+
```text
|
|
316
|
+
qqchat.sqlite
|
|
317
|
+
QQ real history / identity / memory / settings / outbox
|
|
318
|
+
|
|
319
|
+
DSH Session persistence
|
|
320
|
+
Agent turns / model output / tools / DSH transcript
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Neither layer replaces the other.
|
|
324
|
+
|
|
325
|
+
## TypeScript build
|
|
326
|
+
|
|
327
|
+
```text
|
|
328
|
+
src/config.ts
|
|
329
|
+
src/gateway/ QQ API, authorization, Gateway and normalization
|
|
330
|
+
src/session/ Agent bridge and QQ runtime
|
|
331
|
+
src/storage/ SQLite and memory engine
|
|
332
|
+
src/transport/ Client RPC
|
|
333
|
+
src/commands/ QQ command dispatch
|
|
334
|
+
src/shared/ shared augmentations and logging
|
|
335
|
+
client-src/*.cts
|
|
336
|
+
tests/*.test.ts
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
The Host is built with `tsc`. The Client is compiled to temporary CJS and then wrapped by `scripts/wrap-client.mjs` as a DSH Client factory. `lib/` is generated output rather than source truth.
|
|
340
|
+
|
|
341
|
+
## Development and security documentation
|
|
342
|
+
|
|
343
|
+
- [Development](DEVELOPMENT.md): installation, build, testing, startup and browser verification.
|
|
344
|
+
- [Memory](MEMORY.md): scopes, daily records, reflection and compression contracts.
|
|
345
|
+
- [Security](SECURITY.md): credentials, identity, permissions, logging and isolation.
|
|
346
|
+
- [Development log](devlog.md): investigation notes and design decisions.
|