@lanbaolu/dsh-wechat-bridge 0.1.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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +152 -0
  3. package/cordis.patch.yml +12 -0
  4. package/docs/feasibility-plan.md +62 -0
  5. package/lib/bridge/commands/handlers.js +155 -0
  6. package/lib/bridge/commands/handlers.js.map +1 -0
  7. package/lib/bridge/commands/router.js +52 -0
  8. package/lib/bridge/commands/router.js.map +1 -0
  9. package/lib/bridge/config.js +40 -0
  10. package/lib/bridge/config.js.map +1 -0
  11. package/lib/bridge/constants.js +14 -0
  12. package/lib/bridge/constants.js.map +1 -0
  13. package/lib/bridge/dsh-client.js +100 -0
  14. package/lib/bridge/dsh-client.js.map +1 -0
  15. package/lib/bridge/logger.js +75 -0
  16. package/lib/bridge/logger.js.map +1 -0
  17. package/lib/bridge/main.js +546 -0
  18. package/lib/bridge/main.js.map +1 -0
  19. package/lib/bridge/pending-queue.js +55 -0
  20. package/lib/bridge/pending-queue.js.map +1 -0
  21. package/lib/bridge/session.js +84 -0
  22. package/lib/bridge/session.js.map +1 -0
  23. package/lib/bridge/store.js +38 -0
  24. package/lib/bridge/store.js.map +1 -0
  25. package/lib/bridge/wechat/accounts.js +50 -0
  26. package/lib/bridge/wechat/accounts.js.map +1 -0
  27. package/lib/bridge/wechat/api.js +197 -0
  28. package/lib/bridge/wechat/api.js.map +1 -0
  29. package/lib/bridge/wechat/cdn.js +45 -0
  30. package/lib/bridge/wechat/cdn.js.map +1 -0
  31. package/lib/bridge/wechat/crypto.js +17 -0
  32. package/lib/bridge/wechat/crypto.js.map +1 -0
  33. package/lib/bridge/wechat/login.js +139 -0
  34. package/lib/bridge/wechat/login.js.map +1 -0
  35. package/lib/bridge/wechat/media.js +138 -0
  36. package/lib/bridge/wechat/media.js.map +1 -0
  37. package/lib/bridge/wechat/monitor.js +104 -0
  38. package/lib/bridge/wechat/monitor.js.map +1 -0
  39. package/lib/bridge/wechat/send.js +172 -0
  40. package/lib/bridge/wechat/send.js.map +1 -0
  41. package/lib/bridge/wechat/sync-buf.js +11 -0
  42. package/lib/bridge/wechat/sync-buf.js.map +1 -0
  43. package/lib/bridge/wechat/types.js +35 -0
  44. package/lib/bridge/wechat/types.js.map +1 -0
  45. package/lib/bridge/wechat/upload.js +111 -0
  46. package/lib/bridge/wechat/upload.js.map +1 -0
  47. package/lib/client/Panel.js +205 -0
  48. package/lib/client/Panel.js.map +1 -0
  49. package/lib/client/index.js +11 -0
  50. package/lib/client/index.js.map +1 -0
  51. package/lib/client.js +376 -0
  52. package/lib/client.js.map +1 -0
  53. package/lib/index.js +828 -0
  54. package/lib/index.js.map +1 -0
  55. package/lib/types/bridge/commands/handlers.d.ts +18 -0
  56. package/lib/types/bridge/commands/router.d.ts +26 -0
  57. package/lib/types/bridge/config.d.ts +7 -0
  58. package/lib/types/bridge/constants.d.ts +10 -0
  59. package/lib/types/bridge/dsh-client.d.ts +39 -0
  60. package/lib/types/bridge/logger.d.ts +13 -0
  61. package/lib/types/bridge/main.d.ts +1 -0
  62. package/lib/types/bridge/pending-queue.d.ts +10 -0
  63. package/lib/types/bridge/session.d.ts +22 -0
  64. package/lib/types/bridge/store.d.ts +11 -0
  65. package/lib/types/bridge/wechat/accounts.d.ts +14 -0
  66. package/lib/types/bridge/wechat/api.d.ts +32 -0
  67. package/lib/types/bridge/wechat/cdn.d.ts +2 -0
  68. package/lib/types/bridge/wechat/crypto.d.ts +4 -0
  69. package/lib/types/bridge/wechat/login.d.ts +31 -0
  70. package/lib/types/bridge/wechat/media.d.ts +20 -0
  71. package/lib/types/bridge/wechat/monitor.d.ts +10 -0
  72. package/lib/types/bridge/wechat/send.d.ts +6 -0
  73. package/lib/types/bridge/wechat/sync-buf.d.ts +2 -0
  74. package/lib/types/bridge/wechat/types.d.ts +135 -0
  75. package/lib/types/bridge/wechat/upload.d.ts +11 -0
  76. package/lib/types/client/Panel.d.ts +3 -0
  77. package/lib/types/client/index.d.ts +9 -0
  78. package/lib/types/index.d.ts +39 -0
  79. package/package.json +92 -0
@@ -0,0 +1,75 @@
1
+ import { mkdirSync, appendFileSync, readdirSync, unlinkSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { DATA_DIR } from "./constants.js";
4
+ const LOG_DIR = join(DATA_DIR, "logs");
5
+ const MAX_LOG_FILES = 30; // Keep at most 30 days of logs
6
+ /** Clean up old log files beyond MAX_LOG_FILES retention. */
7
+ function cleanupOldLogs() {
8
+ try {
9
+ const files = readdirSync(LOG_DIR)
10
+ .filter((f) => f.startsWith("bridge-") && f.endsWith(".log"))
11
+ .sort();
12
+ while (files.length > MAX_LOG_FILES) {
13
+ unlinkSync(join(LOG_DIR, files.shift()));
14
+ }
15
+ }
16
+ catch {
17
+ // Ignore errors during cleanup
18
+ }
19
+ }
20
+ /**
21
+ * Redact sensitive values from a string:
22
+ * - Bearer tokens (Authorization headers)
23
+ * - aes_key values
24
+ * - generic token/secret values in JSON payloads
25
+ */
26
+ export function redact(obj) {
27
+ const raw = typeof obj === "string" ? obj : JSON.stringify(obj);
28
+ if (!raw)
29
+ return raw;
30
+ let safe = raw;
31
+ // Mask Bearer tokens: "Bearer <anything>"
32
+ safe = safe.replace(/Bearer\s+[^\s"\\]+/gi, "Bearer ***");
33
+ // Mask generic token/secret/password/api_key values in JSON
34
+ // Matches both snake_case (bot_token) and camelCase (botToken)
35
+ safe = safe.replace(/"(?:(?:[\w]+_)?[Tt]oken|(?:[\w]+_)?[Ss]ecret|(?:[\w]+_)?[Pp]assword|(?:[\w]+_)?api_key|[Aa]es_[Kk]ey)"\s*:\s*"[^"]*"/gi, (match) => {
36
+ const key = match.match(/"[^"]*"/)?.[0] ?? '""';
37
+ return `${key}: "***"`;
38
+ });
39
+ return safe;
40
+ }
41
+ function ensureLogDir() {
42
+ mkdirSync(LOG_DIR, { recursive: true });
43
+ cleanupOldLogs();
44
+ }
45
+ function getLogFilePath() {
46
+ const now = new Date(Date.now() + 8 * 60 * 60 * 1000);
47
+ const date = now.toISOString().slice(0, 10); // YYYY-MM-DD
48
+ return join(LOG_DIR, `bridge-${date}.log`);
49
+ }
50
+ function writeLogLine(level, message, data) {
51
+ ensureLogDir();
52
+ const ts = new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString();
53
+ const timestamp = ts.replace('Z', '+08:00');
54
+ const parts = [timestamp, level, message];
55
+ if (data !== undefined) {
56
+ parts.push(redact(data));
57
+ }
58
+ const line = parts.join(" ") + "\n";
59
+ appendFileSync(getLogFilePath(), line, "utf-8");
60
+ }
61
+ export const logger = {
62
+ info(message, data) {
63
+ writeLogLine("INFO", message, data);
64
+ },
65
+ warn(message, data) {
66
+ writeLogLine("WARN", message, data);
67
+ },
68
+ error(message, data) {
69
+ writeLogLine("ERROR", message, data);
70
+ },
71
+ debug(message, data) {
72
+ writeLogLine("DEBUG", message, data);
73
+ },
74
+ };
75
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/bridge/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,546 @@
1
+ import { createInterface } from 'node:readline';
2
+ import process from 'node:process';
3
+ import { spawnSync } from 'node:child_process';
4
+ import { join, basename, extname } from 'node:path';
5
+ import { unlinkSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { WeChatApi } from './wechat/api.js';
8
+ import { loadLatestAccount } from './wechat/accounts.js';
9
+ import { startQrLogin, waitForQrScan } from './wechat/login.js';
10
+ import { createMonitor } from './wechat/monitor.js';
11
+ import { createSender } from './wechat/send.js';
12
+ import { downloadImage, extractText, extractFirstImageUrl, extractFirstFileItem, downloadFile } from './wechat/media.js';
13
+ import { createSessionStore } from './session.js';
14
+ import { routeCommand } from './commands/router.js';
15
+ import { loadConfig, saveConfig } from './config.js';
16
+ import { logger } from './logger.js';
17
+ import { DATA_DIR } from './constants.js';
18
+ import { MessageType } from './wechat/types.js';
19
+ import { DshClient } from './dsh-client.js';
20
+ // ---------------------------------------------------------------------------
21
+ // Helpers
22
+ // ---------------------------------------------------------------------------
23
+ const MAX_MESSAGE_LENGTH = 4000;
24
+ /** Extensions eligible for auto-push when detected in DSH's response text. */
25
+ const AUTO_PUSH_EXTENSIONS = new Set([
26
+ '.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.svg', '.ico',
27
+ '.pdf', '.doc', '.docx', '.ppt', '.pptx', '.rtf',
28
+ '.txt', '.md',
29
+ '.csv', '.xlsx', '.xls',
30
+ '.mp3', '.wav', '.m4a', '.mp4', '.mov',
31
+ ]);
32
+ /** Extract local file paths from DSH response text (macOS/Linux/Windows). */
33
+ function extractFilePathsFromText(text, cwd) {
34
+ const paths = [];
35
+ const regex = /(?:\/(?:Users|home|tmp|var|etc)\/[^\s`'"()\[\]{}|<>]+\.\w+|~\/[^\s`'"()\[\]{}|<>]+\.\w+|[A-Za-z]:[\\\/][^\s`'"()\[\]{}|<>]+\.\w+)/g;
36
+ let match;
37
+ while ((match = regex.exec(text)) !== null) {
38
+ const raw = match[0];
39
+ const resolved = raw.startsWith('~')
40
+ ? raw.replace(/^~/, homedir())
41
+ : raw;
42
+ // Also resolve relative paths that are absolute-ish under the cwd.
43
+ paths.push(resolved.startsWith('/') || /^[A-Za-z]:[\\/]/.test(resolved) ? resolved : join(cwd, resolved));
44
+ }
45
+ return paths;
46
+ }
47
+ /** Silence keepalive messages sent when DSH has not produced output for a while. */
48
+ const SILENCE_MESSAGES = [
49
+ '我还在处理中,这个问题有点复杂,请再稍等一下',
50
+ '正在努力干活中,马上就有结果了,请稍等片刻',
51
+ '有点复杂正在处理,再给我一点时间,很快就好',
52
+ '快好了别着急,正在收尾阶段,马上给你回复',
53
+ '还在跑呢,任务量比较大,不过马上就能出结果了',
54
+ '正在处理中,进展顺利,再等一会儿就好',
55
+ ];
56
+ /** Split text into blocks at paragraph boundaries (double newlines). */
57
+ function parseBlocks(text) {
58
+ return text.split(/\n\n+/).filter(block => block.length > 0);
59
+ }
60
+ /** Find a safe split point that won't break markdown formatting. */
61
+ function findSafeSplitPoint(text, maxLen) {
62
+ let idx = text.lastIndexOf('\n', maxLen);
63
+ if (idx >= maxLen * 0.3)
64
+ return idx;
65
+ const sentenceEnd = /[。!?.!?]$/;
66
+ for (let i = maxLen; i >= maxLen * 0.5; i--) {
67
+ if (sentenceEnd.test(text.slice(i - 1, i)))
68
+ return i;
69
+ }
70
+ idx = text.lastIndexOf(' ', maxLen);
71
+ if (idx >= maxLen * 0.3)
72
+ return idx;
73
+ return maxLen;
74
+ }
75
+ /** Fallback: split a single oversized block at safe boundaries. */
76
+ function splitByNewline(text, maxLen) {
77
+ const chunks = [];
78
+ let remaining = text;
79
+ while (remaining.length > 0) {
80
+ if (remaining.length <= maxLen) {
81
+ chunks.push(remaining);
82
+ break;
83
+ }
84
+ const splitIdx = findSafeSplitPoint(remaining, maxLen);
85
+ chunks.push(remaining.slice(0, splitIdx));
86
+ remaining = remaining.slice(splitIdx).replace(/^\n+/, '');
87
+ }
88
+ return chunks;
89
+ }
90
+ /** Split a message into WeChat-safe chunks, preserving paragraphs. */
91
+ function splitMessage(text, maxLen = MAX_MESSAGE_LENGTH) {
92
+ if (text.length <= maxLen)
93
+ return [text];
94
+ const blocks = parseBlocks(text);
95
+ const chunks = [];
96
+ let current = '';
97
+ for (const block of blocks) {
98
+ if (current.length === 0) {
99
+ if (block.length <= maxLen) {
100
+ current = block;
101
+ }
102
+ else {
103
+ chunks.push(...splitByNewline(block, maxLen));
104
+ }
105
+ }
106
+ else if (current.length + 2 + block.length <= maxLen) {
107
+ current += '\n\n' + block;
108
+ }
109
+ else {
110
+ chunks.push(current);
111
+ if (block.length <= maxLen) {
112
+ current = block;
113
+ }
114
+ else {
115
+ chunks.push(...splitByNewline(block, maxLen));
116
+ current = '';
117
+ }
118
+ }
119
+ }
120
+ if (current)
121
+ chunks.push(current);
122
+ return chunks;
123
+ }
124
+ function promptUser(question, defaultValue) {
125
+ return new Promise((resolve) => {
126
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
127
+ const display = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
128
+ rl.question(display, (answer) => {
129
+ rl.close();
130
+ resolve(answer.trim() || defaultValue || '');
131
+ });
132
+ });
133
+ }
134
+ /** Open a file using the platform's default application (cross-platform). */
135
+ function openFile(filePath) {
136
+ const platform = process.platform;
137
+ let cmd;
138
+ let args;
139
+ if (platform === 'darwin') {
140
+ cmd = 'open';
141
+ args = [filePath];
142
+ }
143
+ else if (platform === 'win32') {
144
+ cmd = 'cmd';
145
+ args = ['/c', 'start', '', filePath];
146
+ }
147
+ else {
148
+ cmd = 'xdg-open';
149
+ args = [filePath];
150
+ }
151
+ const result = spawnSync(cmd, args, { stdio: 'ignore' });
152
+ if (result.error) {
153
+ logger.warn('Failed to open file', { cmd, filePath, error: result.error.message });
154
+ }
155
+ }
156
+ function extractTextFromItems(items) {
157
+ return items.map((item) => extractText(item)).filter(Boolean).join('\n');
158
+ }
159
+ // ---------------------------------------------------------------------------
160
+ // Setup
161
+ // ---------------------------------------------------------------------------
162
+ async function runSetup() {
163
+ mkdirSync(DATA_DIR, { recursive: true });
164
+ const QR_PATH = join(DATA_DIR, 'qrcode.png');
165
+ console.log('正在设置 DSH 微信桥接...\n');
166
+ while (true) {
167
+ const { qrcodeUrl, qrcodeId } = await startQrLogin();
168
+ const isHeadlessLinux = process.platform === 'linux'
169
+ && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY;
170
+ if (isHeadlessLinux) {
171
+ try {
172
+ const qrcodeTerminal = await import('qrcode-terminal');
173
+ console.log('请用微信扫描下方二维码:\n');
174
+ qrcodeTerminal.default.generate(qrcodeUrl, { small: true });
175
+ console.log();
176
+ console.log('二维码链接:', qrcodeUrl);
177
+ console.log();
178
+ }
179
+ catch {
180
+ logger.warn('qrcode-terminal not available, falling back to URL');
181
+ console.log('无法在终端显示二维码,请访问链接:');
182
+ console.log(qrcodeUrl);
183
+ console.log();
184
+ }
185
+ }
186
+ else {
187
+ const QRCode = await import('qrcode');
188
+ const pngData = await QRCode.toBuffer(qrcodeUrl, { type: 'png', width: 400, margin: 2 });
189
+ writeFileSync(QR_PATH, pngData);
190
+ openFile(QR_PATH);
191
+ console.log('已打开二维码图片,请用微信扫描:');
192
+ console.log(`图片路径: ${QR_PATH}\n`);
193
+ }
194
+ console.log('等待扫码绑定...');
195
+ try {
196
+ await waitForQrScan(qrcodeId);
197
+ console.log('✅ 绑定成功!');
198
+ break;
199
+ }
200
+ catch (err) {
201
+ if (err.message?.includes('expired')) {
202
+ console.log('⚠️ 二维码已过期,正在刷新...\n');
203
+ continue;
204
+ }
205
+ throw err;
206
+ }
207
+ }
208
+ try {
209
+ unlinkSync(QR_PATH);
210
+ }
211
+ catch {
212
+ logger.warn('Failed to clean up QR image', { path: QR_PATH });
213
+ }
214
+ const workingDir = await promptUser('请输入 DSH 工作目录', join(homedir(), 'Documents', 'DSH'));
215
+ const config = loadConfig();
216
+ config.workingDirectory = workingDir;
217
+ saveConfig(config);
218
+ console.log('绑定完成。可在 DSH 插件面板或命令行执行 wechat_bridge_start 启动服务。');
219
+ }
220
+ // ---------------------------------------------------------------------------
221
+ // Daemon
222
+ // ---------------------------------------------------------------------------
223
+ async function runDaemon() {
224
+ const config = loadConfig();
225
+ const account = loadLatestAccount();
226
+ if (!account) {
227
+ console.error('未找到微信账号,请先运行: node lib/bridge/main.js setup');
228
+ process.exit(1);
229
+ }
230
+ const apiBase = process.env.DSH_BRIDGE_API_BASE;
231
+ const apiToken = process.env.DSH_BRIDGE_API_TOKEN;
232
+ if (!apiBase || !apiToken) {
233
+ console.error('缺少 DSH_BRIDGE_API_BASE / DSH_BRIDGE_API_TOKEN 环境变量(应由 DSH 插件启动时注入)');
234
+ process.exit(1);
235
+ }
236
+ const client = new DshClient(apiBase, apiToken);
237
+ const api = new WeChatApi(account.botToken, account.baseUrl);
238
+ const sessionStore = createSessionStore();
239
+ const session = sessionStore.load(account.accountId);
240
+ if (config.workingDirectory && session.workingDirectory === process.cwd()) {
241
+ session.workingDirectory = config.workingDirectory;
242
+ sessionStore.save(account.accountId, session);
243
+ }
244
+ if (session.state !== 'idle') {
245
+ logger.warn('Resetting stale session state on startup', { state: session.state });
246
+ session.state = 'idle';
247
+ sessionStore.save(account.accountId, session);
248
+ }
249
+ const sender = createSender(api, account.accountId);
250
+ const messageQueue = [];
251
+ let processingQueue = false;
252
+ async function drainQueue() {
253
+ if (processingQueue)
254
+ return;
255
+ processingQueue = true;
256
+ while (messageQueue.length > 0) {
257
+ const msg = messageQueue.shift();
258
+ await handleMessage(msg, account, session, sessionStore, sender, config, client, messageQueue);
259
+ }
260
+ processingQueue = false;
261
+ }
262
+ function handlePriorityCommand(msg) {
263
+ if (msg.message_type !== MessageType.USER || !msg.item_list)
264
+ return false;
265
+ const text = extractTextFromItems(msg.item_list);
266
+ if (!/^\/(?:stop|clear|new)(?:\s|$)/i.test(text))
267
+ return false;
268
+ if (session.state !== 'processing')
269
+ return false;
270
+ messageQueue.length = 0;
271
+ if (/^\/(?:clear|new)(?:\s|$)/i.test(text)) {
272
+ const cleared = sessionStore.clear(account.accountId, session);
273
+ Object.assign(session, cleared);
274
+ }
275
+ else {
276
+ session.state = 'idle';
277
+ sessionStore.save(account.accountId, session);
278
+ }
279
+ if (text.trim().toLowerCase().startsWith('/stop')) {
280
+ client.stop(account.accountId).catch(() => { });
281
+ sender.sendText(msg.from_user_id, msg.context_token ?? '', '⏹ 已停止当前对话,排队中的消息已清空。').catch(() => { });
282
+ }
283
+ else {
284
+ client.clear(account.accountId).catch(() => { });
285
+ sender.sendText(msg.from_user_id, msg.context_token ?? '', '✅ 会话已清除。').catch(() => { });
286
+ }
287
+ return true;
288
+ }
289
+ const callbacks = {
290
+ onMessage: async (msg) => {
291
+ if (handlePriorityCommand(msg))
292
+ return;
293
+ messageQueue.push(msg);
294
+ drainQueue();
295
+ },
296
+ onSessionExpired: () => {
297
+ logger.warn('Session expired, will keep retrying...');
298
+ console.error('⚠️ 微信会话已过期,请重新运行 setup 扫码绑定');
299
+ },
300
+ };
301
+ const monitor = createMonitor(api, callbacks);
302
+ function shutdown() {
303
+ logger.info('Shutting down...');
304
+ monitor.stop();
305
+ process.exit(0);
306
+ }
307
+ process.on('SIGINT', shutdown);
308
+ process.on('SIGTERM', shutdown);
309
+ logger.info('Daemon started', { accountId: account.accountId });
310
+ console.log(`已启动 (账号: ${account.accountId})`);
311
+ await monitor.run();
312
+ }
313
+ // ---------------------------------------------------------------------------
314
+ // Message handling
315
+ // ---------------------------------------------------------------------------
316
+ async function handleMessage(msg, account, session, sessionStore, sender, config, client, messageQueue) {
317
+ if (msg.message_type !== MessageType.USER)
318
+ return;
319
+ if (!msg.from_user_id || !msg.item_list)
320
+ return;
321
+ if (account.userId && msg.from_user_id !== account.userId)
322
+ return;
323
+ const contextToken = msg.context_token ?? '';
324
+ const fromUserId = msg.from_user_id;
325
+ const userText = extractTextFromItems(msg.item_list);
326
+ const imageItem = extractFirstImageUrl(msg.item_list);
327
+ const fileItem = extractFirstFileItem(msg.item_list);
328
+ // While the current turn is running, keep ordinary messages queued and
329
+ // process them after this turn finishes, instead of dropping them.
330
+ if (session.state === 'processing' && !userText.startsWith('/')) {
331
+ messageQueue.push(msg);
332
+ return;
333
+ }
334
+ if (userText.startsWith('/')) {
335
+ const updateSession = (partial) => {
336
+ Object.assign(session, partial);
337
+ sessionStore.save(account.accountId, session);
338
+ };
339
+ const ctx = {
340
+ accountId: account.accountId,
341
+ session,
342
+ updateSession,
343
+ clearSession: () => sessionStore.clear(account.accountId),
344
+ getChatHistoryText: (limit) => sessionStore.getChatHistoryText(session, limit),
345
+ text: userText,
346
+ };
347
+ const result = routeCommand(ctx);
348
+ if (result.handled && result.reply) {
349
+ await sender.sendText(fromUserId, contextToken, result.reply);
350
+ // /clear and /new must also clear the real DSH session (and its persisted
351
+ // id mapping), even when the daemon is idle and not just mid-turn.
352
+ if (/^\/(?:clear|new)(?:\s|$)/i.test(userText.trim())) {
353
+ await client.clear(account.accountId).catch((err) => {
354
+ logger.warn('Failed to clear DSH session from slash command', {
355
+ error: err instanceof Error ? err.message : String(err),
356
+ });
357
+ });
358
+ }
359
+ return;
360
+ }
361
+ if (result.handled && result.sendFile) {
362
+ await sender.sendFile(fromUserId, contextToken, result.sendFile);
363
+ return;
364
+ }
365
+ if (result.handled && result.dshPrompt) {
366
+ await sendToDsh(result.dshPrompt, imageItem, fileItem, fromUserId, contextToken, account, session, sessionStore, sender, config, client);
367
+ return;
368
+ }
369
+ if (result.handled)
370
+ return;
371
+ }
372
+ if (!userText && !imageItem && !fileItem) {
373
+ await sender.sendText(fromUserId, contextToken, '暂不支持此类型消息,请发送文字、语音、图片或文件');
374
+ return;
375
+ }
376
+ await sendToDsh(userText, imageItem, fileItem, fromUserId, contextToken, account, session, sessionStore, sender, config, client);
377
+ }
378
+ async function sendToDsh(userText, imageItem, fileItem, fromUserId, contextToken, account, session, sessionStore, sender, config, client) {
379
+ session.state = 'processing';
380
+ sessionStore.save(account.accountId, session);
381
+ sessionStore.addChatMessage(session, 'user', userText || '(图片/文件)');
382
+ const stopTyping = sender.startTyping(fromUserId, contextToken);
383
+ try {
384
+ // Download media to local paths; DSH can read them from disk.
385
+ const files = [];
386
+ let prompt = userText || '请处理这条消息';
387
+ if (imageItem) {
388
+ const filePath = await downloadImage(imageItem);
389
+ if (filePath) {
390
+ files.push(filePath);
391
+ prompt = userText
392
+ ? `${userText}\n\n用户发送了图片,已保存到: ${filePath}\n请查看这张图片。`
393
+ : `用户发送了图片,已保存到: ${filePath}\n请查看这张图片。`;
394
+ }
395
+ }
396
+ if (fileItem) {
397
+ const filePath = await downloadFile(fileItem);
398
+ if (filePath) {
399
+ files.push(filePath);
400
+ const fileName = fileItem.file_item?.file_name || basename(filePath);
401
+ prompt = userText
402
+ ? `${userText}\n\n用户发送了文件: ${fileName}\n文件已保存到: ${filePath}\n请先读取这个文件再回答。`
403
+ : `用户发送了文件: ${fileName}\n文件已保存到: ${filePath}\n请读取这个文件并总结其内容。`;
404
+ }
405
+ }
406
+ const accepted = await client.prompt({
407
+ text: prompt,
408
+ sessionId: account.accountId,
409
+ cwd: (session.workingDirectory || config.workingDirectory).replace(/^~/, homedir()),
410
+ model: session.model,
411
+ systemPrompt: config.systemPrompt,
412
+ files,
413
+ });
414
+ if (!accepted) {
415
+ await sender.sendText(fromUserId, contextToken, '消息已收到,但 DSH 未接受处理请求。');
416
+ session.state = 'idle';
417
+ sessionStore.save(account.accountId, session);
418
+ return;
419
+ }
420
+ // Stream the assistant response back.
421
+ let finalText = '';
422
+ let flushTimer;
423
+ let keepaliveTimer;
424
+ let pendingSend = '';
425
+ let lastSentTime = Date.now();
426
+ const flush = async (force) => {
427
+ if (!pendingSend)
428
+ return;
429
+ const text = pendingSend;
430
+ pendingSend = '';
431
+ for (const chunk of splitMessage(text)) {
432
+ try {
433
+ await sender.sendText(fromUserId, contextToken, chunk);
434
+ lastSentTime = Date.now();
435
+ }
436
+ catch (err) {
437
+ logger.warn('Flush send failed, will retry on next flush', {
438
+ error: err instanceof Error ? err.message : String(err),
439
+ });
440
+ pendingSend = text + (pendingSend ? '\n\n' + pendingSend : '');
441
+ return;
442
+ }
443
+ }
444
+ };
445
+ flushTimer = setInterval(() => {
446
+ void flush(true).catch(() => { });
447
+ }, 1500);
448
+ // 超时安抚:如果 5 分钟没有产出任何消息,主动告诉用户还在处理。
449
+ const SILENCE_WARNING_MS = 5 * 60 * 1000;
450
+ keepaliveTimer = setInterval(() => {
451
+ if (Date.now() - lastSentTime > SILENCE_WARNING_MS) {
452
+ const msg = SILENCE_MESSAGES[Math.floor(Math.random() * SILENCE_MESSAGES.length)];
453
+ sender.sendText(fromUserId, contextToken, msg).catch(() => { });
454
+ lastSentTime = Date.now();
455
+ }
456
+ }, 2000);
457
+ const controller = new AbortController();
458
+ await client.stream(account.accountId, (event) => {
459
+ switch (event.type) {
460
+ case 'chunk':
461
+ if (event.text) {
462
+ finalText += event.text;
463
+ pendingSend += event.text;
464
+ // Batch streaming chunks into reasonably-sized WeChat messages;
465
+ // flush immediately per-chunk would spam hundreds of tiny messages.
466
+ if (pendingSend.length >= 1200) {
467
+ void flush(false).catch(() => { });
468
+ }
469
+ }
470
+ break;
471
+ case 'status':
472
+ // Optional status updates are currently not pushed to WeChat.
473
+ break;
474
+ case 'error':
475
+ if (event.message) {
476
+ finalText += `\n\n⚠️ ${event.message}`;
477
+ }
478
+ break;
479
+ case 'done':
480
+ // Wait for the next stream tick to flush the remaining buffer.
481
+ break;
482
+ }
483
+ }, controller.signal);
484
+ if (flushTimer)
485
+ clearInterval(flushTimer);
486
+ if (keepaliveTimer)
487
+ clearInterval(keepaliveTimer);
488
+ await flush(true);
489
+ const resultText = finalText.trim();
490
+ if (resultText) {
491
+ sessionStore.addChatMessage(session, 'assistant', resultText);
492
+ if (!resultText.startsWith('⚠️')) {
493
+ // Auto-push deliverable files mentioned in DSH's response.
494
+ const cwd = (session.workingDirectory || config.workingDirectory).replace(/^~/, homedir());
495
+ const detectedPaths = extractFilePathsFromText(resultText, cwd);
496
+ const pushable = detectedPaths.filter(f => {
497
+ const ext = extname(f).toLowerCase();
498
+ return AUTO_PUSH_EXTENSIONS.has(ext) && existsSync(f);
499
+ });
500
+ for (const filePath of pushable) {
501
+ try {
502
+ await sender.sendFile(fromUserId, contextToken, filePath);
503
+ }
504
+ catch (err) {
505
+ logger.warn('Failed to auto-push file', {
506
+ filePath,
507
+ error: err instanceof Error ? err.message : String(err),
508
+ });
509
+ }
510
+ }
511
+ }
512
+ }
513
+ else {
514
+ await sender.sendText(fromUserId, contextToken, 'DSH 无返回内容。');
515
+ }
516
+ }
517
+ catch (err) {
518
+ const errorMsg = err instanceof Error ? err.message : String(err);
519
+ logger.error('Error in sendToDsh', { error: errorMsg });
520
+ await sender.sendText(fromUserId, contextToken, '处理消息时出错,请稍后重试。');
521
+ }
522
+ finally {
523
+ session.state = 'idle';
524
+ sessionStore.save(account.accountId, session);
525
+ stopTyping();
526
+ }
527
+ }
528
+ // ---------------------------------------------------------------------------
529
+ // CLI
530
+ // ---------------------------------------------------------------------------
531
+ const command = process.argv[2];
532
+ if (command === 'setup') {
533
+ runSetup().catch((err) => {
534
+ logger.error('Setup failed', { error: err instanceof Error ? err.message : String(err) });
535
+ console.error('设置失败:', err);
536
+ process.exit(1);
537
+ });
538
+ }
539
+ else {
540
+ runDaemon().catch((err) => {
541
+ logger.error('Daemon start failed', { error: err instanceof Error ? err.message : String(err) });
542
+ console.error('启动失败:', err);
543
+ process.exit(1);
544
+ });
545
+ }
546
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/bridge/main.ts"],"names":[],"mappings":"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"}