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.
Files changed (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +276 -0
  3. package/README.md +211 -0
  4. package/client-src/plugin.cts +15 -0
  5. package/client-src/settings.cts +216 -0
  6. package/client-src/shared.cts +104 -0
  7. package/client-src/workspace.cts +164 -0
  8. package/cordis.patch.yml +7 -0
  9. package/docs/ARCHITECTURE.en.md +346 -0
  10. package/docs/ARCHITECTURE.md +411 -0
  11. package/docs/DEVELOPMENT.md +69 -0
  12. package/docs/MEDIA_AND_QUOTES.md +644 -0
  13. package/docs/MEMORY.md +99 -0
  14. package/docs/MEMORY_CONTEXT.md +254 -0
  15. package/docs/QUOTES.md +355 -0
  16. package/docs/README.md +22 -0
  17. package/docs/SECURITY.md +62 -0
  18. package/docs/STREAMING.md +347 -0
  19. package/docs/assets//346/211/253/347/240/201/351/223/276/346/216/245.jpg +0 -0
  20. package/docs/assets//347/276/244/350/201/212/347/225/214/351/235/242.jpg +0 -0
  21. package/docs/assets//350/256/260/345/277/206/347/263/273/347/273/237.jpg +0 -0
  22. package/docs/assets//350/256/276/347/275/256/347/225/214/351/235/242.jpg +0 -0
  23. package/docs/devlog.md +24 -0
  24. package/lib/client.js +433 -0
  25. package/lib/commands/dispatch.d.ts +16 -0
  26. package/lib/commands/dispatch.js +48 -0
  27. package/lib/config.d.ts +3 -0
  28. package/lib/config.js +63 -0
  29. package/lib/gateway/api.d.ts +30 -0
  30. package/lib/gateway/api.js +202 -0
  31. package/lib/gateway/auth.d.ts +35 -0
  32. package/lib/gateway/auth.js +80 -0
  33. package/lib/gateway/crypto.d.ts +2 -0
  34. package/lib/gateway/crypto.js +17 -0
  35. package/lib/gateway/gateway.d.ts +32 -0
  36. package/lib/gateway/gateway.js +219 -0
  37. package/lib/gateway/normalize.d.ts +6 -0
  38. package/lib/gateway/normalize.js +248 -0
  39. package/lib/index.d.ts +14 -0
  40. package/lib/index.js +35 -0
  41. package/lib/media/image-tool.d.ts +4 -0
  42. package/lib/media/image-tool.js +62 -0
  43. package/lib/media/media-tools.d.ts +3 -0
  44. package/lib/media/media-tools.js +68 -0
  45. package/lib/media/store.d.ts +14 -0
  46. package/lib/media/store.js +176 -0
  47. package/lib/session/agent-bridge.d.ts +56 -0
  48. package/lib/session/agent-bridge.js +613 -0
  49. package/lib/session/memory-snapshot.d.ts +23 -0
  50. package/lib/session/memory-snapshot.js +27 -0
  51. package/lib/session/runtime.d.ts +41 -0
  52. package/lib/session/runtime.js +395 -0
  53. package/lib/shared/augmentations.d.ts +40 -0
  54. package/lib/shared/augmentations.js +1 -0
  55. package/lib/shared/logging.d.ts +14 -0
  56. package/lib/shared/logging.js +41 -0
  57. package/lib/storage/db.d.ts +82 -0
  58. package/lib/storage/db.js +669 -0
  59. package/lib/storage/memory.d.ts +50 -0
  60. package/lib/storage/memory.js +566 -0
  61. package/lib/transport/rpc.d.ts +18 -0
  62. package/lib/transport/rpc.js +318 -0
  63. package/lib/types.d.ts +416 -0
  64. package/lib/types.js +1 -0
  65. package/package.json +115 -0
  66. package/scripts/wrap-client.mjs +20 -0
  67. package/src/commands/dispatch.ts +75 -0
  68. package/src/config.ts +70 -0
  69. package/src/gateway/api.ts +260 -0
  70. package/src/gateway/auth.ts +99 -0
  71. package/src/gateway/crypto.ts +16 -0
  72. package/src/gateway/gateway.ts +207 -0
  73. package/src/gateway/normalize.ts +236 -0
  74. package/src/index.ts +46 -0
  75. package/src/media/image-tool.ts +62 -0
  76. package/src/media/media-tools.ts +66 -0
  77. package/src/media/store.ts +157 -0
  78. package/src/session/agent-bridge.ts +624 -0
  79. package/src/session/memory-snapshot.ts +41 -0
  80. package/src/session/runtime.ts +368 -0
  81. package/src/shared/augmentations.ts +45 -0
  82. package/src/shared/logging.ts +36 -0
  83. package/src/storage/db.ts +760 -0
  84. package/src/storage/memory.ts +581 -0
  85. package/src/transport/rpc.ts +316 -0
  86. package/src/types.ts +456 -0
  87. package/tsconfig.build.json +12 -0
  88. package/tsconfig.client.json +14 -0
  89. 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.