cc-wechat 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 (48) hide show
  1. package/.claude-plugin/plugin.json +6 -0
  2. package/.mcp.json +8 -0
  3. package/.pace/stop-block-count +1 -0
  4. package/LICENSE +21 -0
  5. package/README.md +83 -0
  6. package/dist/auth.d.ts +18 -0
  7. package/dist/auth.js +351 -0
  8. package/dist/auth.js.map +1 -0
  9. package/dist/cdn.d.ts +39 -0
  10. package/dist/cdn.js +228 -0
  11. package/dist/cdn.js.map +1 -0
  12. package/dist/cli.d.ts +5 -0
  13. package/dist/cli.js +127 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/ilink-api.d.ts +33 -0
  16. package/dist/ilink-api.js +206 -0
  17. package/dist/ilink-api.js.map +1 -0
  18. package/dist/patch.d.ts +7 -0
  19. package/dist/patch.js +165 -0
  20. package/dist/patch.js.map +1 -0
  21. package/dist/server.d.ts +6 -0
  22. package/dist/server.js +406 -0
  23. package/dist/server.js.map +1 -0
  24. package/dist/store.d.ts +24 -0
  25. package/dist/store.js +57 -0
  26. package/dist/store.js.map +1 -0
  27. package/dist/text-utils.d.ts +7 -0
  28. package/dist/text-utils.js +56 -0
  29. package/dist/text-utils.js.map +1 -0
  30. package/dist/types.d.ts +98 -0
  31. package/dist/types.js +13 -0
  32. package/dist/types.js.map +1 -0
  33. package/package.json +24 -0
  34. package/packages/cc-channel-patch/README.md +36 -0
  35. package/packages/cc-channel-patch/index.mjs +228 -0
  36. package/packages/cc-channel-patch/package.json +11 -0
  37. package/skills/configure/SKILL.md +32 -0
  38. package/src/auth.ts +400 -0
  39. package/src/cdn.ts +261 -0
  40. package/src/cli.ts +121 -0
  41. package/src/ilink-api.ts +279 -0
  42. package/src/patch.ts +182 -0
  43. package/src/qrcode-terminal.d.ts +10 -0
  44. package/src/server.ts +445 -0
  45. package/src/store.ts +62 -0
  46. package/src/text-utils.ts +56 -0
  47. package/src/types.ts +94 -0
  48. package/tsconfig.json +17 -0
package/dist/patch.js ADDED
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cc-wechat 补丁工具
4
+ * 绕过 Claude Code 的 Channels 云控检查(tengu_harbor feature flag + accessToken auth)
5
+ * 用法:node dist/patch.js 或 npx cc-wechat patch
6
+ */
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ import { homedir } from 'node:os';
10
+ // 补丁定义:[特征字符串, 替换字符串, 说明]
11
+ const PATCHES = [
12
+ // 1. Channels feature flag 云控
13
+ [
14
+ 'function PaH(){return lA("tengu_harbor",!1)}',
15
+ 'function PaH(){return !0 }',
16
+ 'Channels feature flag (tengu_harbor)',
17
+ ],
18
+ // 2. S1_ gate auth 检查
19
+ [
20
+ 'if(!yf()?.accessToken)',
21
+ 'if( false )',
22
+ 'Channel gate accessToken check',
23
+ ],
24
+ // 3. UI 层 noAuth 检查
25
+ [
26
+ 'noAuth:!yf()?.accessToken',
27
+ 'noAuth: false ',
28
+ 'UI noAuth display check',
29
+ ],
30
+ ];
31
+ /** 查找 claude.exe 路径 */
32
+ function findClaudeExe() {
33
+ const candidates = [
34
+ path.join(homedir(), '.local', 'bin', 'claude.exe'),
35
+ path.join(homedir(), '.local', 'bin', 'claude'),
36
+ // npm 全局安装
37
+ path.join(homedir(), 'AppData', 'Roaming', 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
38
+ ];
39
+ for (const p of candidates) {
40
+ if (fs.existsSync(p))
41
+ return p;
42
+ }
43
+ return null;
44
+ }
45
+ function patch() {
46
+ console.log('\n cc-wechat patch — Claude Code Channels 补丁\n');
47
+ const exePath = findClaudeExe();
48
+ if (!exePath) {
49
+ console.error(' 找不到 Claude Code。请确认已安装。');
50
+ process.exit(1);
51
+ }
52
+ console.log(` 目标: ${exePath}`);
53
+ // 读取二进制
54
+ const buf = fs.readFileSync(exePath);
55
+ let totalPatched = 0;
56
+ let alreadyPatched = 0;
57
+ for (const [original, replacement, desc] of PATCHES) {
58
+ if (original.length !== replacement.length) {
59
+ console.error(` 错误: "${desc}" 长度不匹配 (${original.length} vs ${replacement.length})`);
60
+ process.exit(1);
61
+ }
62
+ const origBuf = Buffer.from(original);
63
+ const patchBuf = Buffer.from(replacement);
64
+ // 搜索所有出现位置
65
+ let pos = 0;
66
+ let count = 0;
67
+ let alreadyCount = 0;
68
+ while (true) {
69
+ const idx = buf.indexOf(origBuf, pos);
70
+ if (idx === -1)
71
+ break;
72
+ patchBuf.copy(buf, idx);
73
+ count++;
74
+ pos = idx + 1;
75
+ }
76
+ // 检查是否已经 patch 过
77
+ pos = 0;
78
+ while (true) {
79
+ const idx = buf.indexOf(patchBuf, pos);
80
+ if (idx === -1)
81
+ break;
82
+ alreadyCount++;
83
+ pos = idx + 1;
84
+ }
85
+ if (count > 0) {
86
+ console.log(` [PATCH] ${desc}: ${count} 处已修补`);
87
+ totalPatched += count;
88
+ }
89
+ else if (alreadyCount > 0) {
90
+ console.log(` [SKIP] ${desc}: 已修补过 (${alreadyCount} 处)`);
91
+ alreadyPatched += alreadyCount;
92
+ }
93
+ else {
94
+ console.log(` [WARN] ${desc}: 未找到特征字符串(CC 版本可能已更新)`);
95
+ }
96
+ }
97
+ if (totalPatched === 0 && alreadyPatched > 0) {
98
+ console.log('\n 所有补丁已生效,无需操作。\n');
99
+ return;
100
+ }
101
+ if (totalPatched === 0) {
102
+ console.error('\n 未找到任何可修补的位置。Claude Code 版本可能不兼容。\n');
103
+ process.exit(1);
104
+ }
105
+ // 备份
106
+ const backupPath = exePath + '.bak';
107
+ if (!fs.existsSync(backupPath)) {
108
+ fs.copyFileSync(exePath, backupPath);
109
+ console.log(` [BACKUP] 已备份到 ${backupPath}`);
110
+ }
111
+ // 写入 — 先写临时文件再替换
112
+ const tmpPath = exePath + '.patched';
113
+ fs.writeFileSync(tmpPath, buf);
114
+ console.log(`\n 补丁已写入 ${tmpPath}`);
115
+ console.log(' 请关闭所有 Claude Code 进程后手动替换:\n');
116
+ if (process.platform === 'win32') {
117
+ const dir = path.dirname(exePath);
118
+ const name = path.basename(exePath);
119
+ console.log(` cd ${dir}`);
120
+ console.log(` Move-Item ${name} ${name}.old -Force`);
121
+ console.log(` Move-Item ${name}.patched ${name} -Force\n`);
122
+ }
123
+ else {
124
+ console.log(` mv "${exePath}" "${exePath}.old"`);
125
+ console.log(` mv "${tmpPath}" "${exePath}"\n`);
126
+ }
127
+ console.log(` 恢复方法: 用 ${backupPath} 替换即可\n`);
128
+ }
129
+ function unpatch() {
130
+ console.log('\n cc-wechat unpatch — 恢复原始 Claude Code\n');
131
+ const exePath = findClaudeExe();
132
+ if (!exePath) {
133
+ console.error(' 找不到 Claude Code。');
134
+ process.exit(1);
135
+ }
136
+ const backupPath = exePath + '.bak';
137
+ if (!fs.existsSync(backupPath)) {
138
+ console.error(` 未找到备份文件 ${backupPath}`);
139
+ process.exit(1);
140
+ }
141
+ const tmpPath = exePath + '.restore';
142
+ fs.copyFileSync(backupPath, tmpPath);
143
+ console.log(` 已准备恢复文件 ${tmpPath}`);
144
+ console.log(' 请关闭所有 Claude Code 进程后手动替换:\n');
145
+ if (process.platform === 'win32') {
146
+ const dir = path.dirname(exePath);
147
+ const name = path.basename(exePath);
148
+ console.log(` cd ${dir}`);
149
+ console.log(` Move-Item ${name} ${name}.patched -Force`);
150
+ console.log(` Move-Item ${name}.restore ${name} -Force\n`);
151
+ }
152
+ else {
153
+ console.log(` mv "${exePath}" "${exePath}.patched"`);
154
+ console.log(` mv "${tmpPath}" "${exePath}"\n`);
155
+ }
156
+ }
157
+ // 入口
158
+ const cmd = process.argv[2];
159
+ if (cmd === 'unpatch' || cmd === 'restore') {
160
+ unpatch();
161
+ }
162
+ else {
163
+ patch();
164
+ }
165
+ //# sourceMappingURL=patch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cc-wechat MCP Server 主入口
4
+ * Claude Code Channel 插件 — 微信消息桥接
5
+ */
6
+ export {};
package/dist/server.js ADDED
@@ -0,0 +1,406 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cc-wechat MCP Server 主入口
4
+ * Claude Code Channel 插件 — 微信消息桥接
5
+ */
6
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
7
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
+ import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
9
+ import fs from 'node:fs';
10
+ import { getActiveAccount, saveAccount, loadSyncBuf, saveSyncBuf } from './store.js';
11
+ import { getUpdates, sendMessage, sendTyping, getConfig } from './ilink-api.js';
12
+ import { loginBrowser } from './auth.js';
13
+ import { uploadMedia, downloadMedia } from './cdn.js';
14
+ import { stripMarkdown, chunkText } from './text-utils.js';
15
+ import { MessageItemType } from './types.js';
16
+ // ─── 状态变量 ─────────────────────────────────────────
17
+ let pollingActive = false;
18
+ let pollingAbort = null;
19
+ const typingTicketCache = new Map();
20
+ // ─── Session 过期处理常量 ─────────────────────────────
21
+ const SESSION_EXPIRED_ERRCODE = -14;
22
+ const MAX_SESSION_RETRIES = 3;
23
+ const MAX_CONSECUTIVE_FAILURES = 5;
24
+ const INITIAL_RETRY_DELAY_MS = 2_000;
25
+ const MAX_RETRY_DELAY_MS = 30_000;
26
+ const SESSION_PAUSE_MS = 5 * 60_000;
27
+ // ─── 辅助函数 ─────────────────────────────────────────
28
+ /** 可中断的 sleep */
29
+ function sleep(ms, signal) {
30
+ return new Promise((resolve, reject) => {
31
+ const t = setTimeout(resolve, ms);
32
+ signal?.addEventListener('abort', () => { clearTimeout(t); reject(new Error('aborted')); }, { once: true });
33
+ });
34
+ }
35
+ /** 从消息提取可读文本(异步,支持媒体下载) */
36
+ async function extractText(msg) {
37
+ const parts = [];
38
+ for (const item of msg.item_list ?? []) {
39
+ const t = item.type ?? 0;
40
+ if (t === MessageItemType.TEXT) {
41
+ if (item.text_item?.text)
42
+ parts.push(item.text_item.text);
43
+ }
44
+ else if (t === MessageItemType.IMAGE) {
45
+ let desc = '[图片]';
46
+ if (item.image_item?.media?.encrypt_query_param && item.image_item?.media?.aes_key) {
47
+ try {
48
+ const filePath = await downloadMedia({
49
+ encryptQueryParam: item.image_item.media.encrypt_query_param,
50
+ aesKeyBase64: item.image_item.media.aes_key,
51
+ });
52
+ desc += `\n[附件: ${filePath}]`;
53
+ }
54
+ catch {
55
+ // 下载失败不阻塞消息处理
56
+ }
57
+ }
58
+ parts.push(desc);
59
+ }
60
+ else if (t === MessageItemType.VOICE) {
61
+ parts.push(`[语音] ${item.voice_item?.text ?? ''}`);
62
+ }
63
+ else if (t === MessageItemType.FILE) {
64
+ let desc = `[文件: ${item.file_item?.file_name ?? 'unknown'}]`;
65
+ if (item.file_item?.media?.encrypt_query_param && item.file_item?.media?.aes_key) {
66
+ try {
67
+ const filePath = await downloadMedia({
68
+ encryptQueryParam: item.file_item.media.encrypt_query_param,
69
+ aesKeyBase64: item.file_item.media.aes_key,
70
+ fileName: item.file_item.file_name,
71
+ });
72
+ desc += `\n[附件: ${filePath}]`;
73
+ }
74
+ catch {
75
+ // 下载失败不阻塞消息处理
76
+ }
77
+ }
78
+ parts.push(desc);
79
+ }
80
+ else if (t === MessageItemType.VIDEO) {
81
+ parts.push('[视频]');
82
+ }
83
+ }
84
+ return parts.join('\n') || '[空消息]';
85
+ }
86
+ // ─── MCP Server 创建 ─────────────────────────────────
87
+ const server = new Server({ name: 'wechat-channel', version: '0.1.0' }, {
88
+ capabilities: {
89
+ experimental: { 'claude/channel': {} },
90
+ tools: {},
91
+ },
92
+ instructions: `Messages arrive as <channel source="wechat-channel" user_id="..." context_token="...">.
93
+ Reply using the reply tool. Pass user_id and context_token from the channel tag.
94
+ For media: set media to an absolute local file path to send image/video/file.
95
+ IMPORTANT: Always use the reply tool to respond to WeChat messages. Do not just output text.`,
96
+ });
97
+ // ─── Tools — ListToolsRequestSchema ──────────────────
98
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
99
+ tools: [
100
+ {
101
+ name: 'login',
102
+ description: '扫码登录微信。首次使用或 session 过期后运行。',
103
+ inputSchema: {
104
+ type: 'object',
105
+ properties: {},
106
+ },
107
+ },
108
+ {
109
+ name: 'reply',
110
+ description: '回复微信消息',
111
+ inputSchema: {
112
+ type: 'object',
113
+ properties: {
114
+ user_id: { type: 'string', description: '微信用户 ID(来自消息 meta 的 user_id)' },
115
+ context_token: { type: 'string', description: '会话上下文令牌(来自消息 meta 的 context_token)' },
116
+ content: { type: 'string', description: '回复文本内容' },
117
+ media: { type: 'string', description: '可选:本地文件绝对路径,发送图片/视频/文件' },
118
+ },
119
+ required: ['user_id', 'context_token', 'content'],
120
+ },
121
+ },
122
+ ],
123
+ }));
124
+ // ─── Tools — CallToolRequestSchema ───────────────────
125
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
126
+ const { name, arguments: args } = request.params;
127
+ // ── login tool ──
128
+ if (name === 'login') {
129
+ try {
130
+ const result = await loginBrowser();
131
+ saveAccount({
132
+ token: result.token,
133
+ baseUrl: result.baseUrl ?? '',
134
+ botId: result.accountId,
135
+ savedAt: new Date().toISOString(),
136
+ });
137
+ startPolling();
138
+ return {
139
+ content: [{ type: 'text', text: `登录成功!账号 ID: ${result.accountId}` }],
140
+ };
141
+ }
142
+ catch (err) {
143
+ return {
144
+ content: [{ type: 'text', text: `登录失败: ${String(err)}` }],
145
+ isError: true,
146
+ };
147
+ }
148
+ }
149
+ // ── reply tool ──
150
+ if (name === 'reply') {
151
+ const userId = args?.user_id;
152
+ const contextToken = args?.context_token;
153
+ const content = args?.content;
154
+ const media = args?.media;
155
+ // 验证必填参数
156
+ if (!userId || !contextToken || !content) {
157
+ return {
158
+ content: [{ type: 'text', text: '缺少必填参数: user_id, context_token, content' }],
159
+ isError: true,
160
+ };
161
+ }
162
+ // 验证账号存在
163
+ const account = getActiveAccount();
164
+ if (!account) {
165
+ return {
166
+ content: [{ type: 'text', text: '未登录,请先使用 login 工具扫码登录' }],
167
+ isError: true,
168
+ };
169
+ }
170
+ // 检查媒体文件是否存在
171
+ if (media && !fs.existsSync(media)) {
172
+ return {
173
+ content: [{ type: 'text', text: `媒体文件不存在: ${media}` }],
174
+ isError: true,
175
+ };
176
+ }
177
+ try {
178
+ // 发送 typing 状态(best-effort)
179
+ try {
180
+ let ticket = typingTicketCache.get(userId);
181
+ if (!ticket) {
182
+ const config = await getConfig(account.token, userId, contextToken, account.baseUrl);
183
+ ticket = config.typing_ticket ?? '';
184
+ if (ticket)
185
+ typingTicketCache.set(userId, ticket);
186
+ }
187
+ if (ticket) {
188
+ await sendTyping(account.token, userId, ticket, 1, account.baseUrl);
189
+ }
190
+ }
191
+ catch {
192
+ // typing 失败不阻塞
193
+ }
194
+ // 清理 Markdown 并分段发送
195
+ const plainText = stripMarkdown(content);
196
+ const chunks = chunkText(plainText, 3900);
197
+ for (const chunk of chunks) {
198
+ await sendMessage(account.token, userId, chunk, contextToken, account.baseUrl);
199
+ }
200
+ // 发送媒体文件(如有)
201
+ let mediaError = '';
202
+ if (media) {
203
+ try {
204
+ await uploadMedia({
205
+ token: account.token,
206
+ toUser: userId,
207
+ contextToken,
208
+ filePath: media,
209
+ baseUrl: account.baseUrl,
210
+ });
211
+ }
212
+ catch (err) {
213
+ mediaError = `(媒体发送失败: ${String(err)})`;
214
+ }
215
+ }
216
+ // 停止 typing 状态(best-effort)
217
+ try {
218
+ const ticket = typingTicketCache.get(userId);
219
+ if (ticket) {
220
+ await sendTyping(account.token, userId, ticket, 2, account.baseUrl);
221
+ }
222
+ }
223
+ catch {
224
+ // typing 失败不阻塞
225
+ }
226
+ return {
227
+ content: [{
228
+ type: 'text',
229
+ text: `已发送 ${chunks.length} 段文本${media ? ' + 1 个媒体文件' : ''}${mediaError}`,
230
+ }],
231
+ };
232
+ }
233
+ catch (err) {
234
+ return {
235
+ content: [{ type: 'text', text: `发送失败: ${String(err)}` }],
236
+ isError: true,
237
+ };
238
+ }
239
+ }
240
+ return {
241
+ content: [{ type: 'text', text: `未知工具: ${name}` }],
242
+ isError: true,
243
+ };
244
+ });
245
+ // ─── 轮询循环 ─────────────────────────────────────────
246
+ /** 消息长轮询循环 */
247
+ async function pollLoop(account) {
248
+ let buf = loadSyncBuf();
249
+ let consecutiveFailures = 0;
250
+ let sessionRetries = 0;
251
+ let retryDelay = INITIAL_RETRY_DELAY_MS;
252
+ let nextTimeoutMs;
253
+ while (pollingActive && !pollingAbort?.signal.aborted) {
254
+ try {
255
+ const resp = await getUpdates(account.token, buf, account.baseUrl, nextTimeoutMs);
256
+ // 更新长轮询超时
257
+ if (resp.longpolling_timeout_ms) {
258
+ nextTimeoutMs = resp.longpolling_timeout_ms;
259
+ }
260
+ // 检查 API 错误
261
+ if ((resp.ret !== undefined && resp.ret !== 0) || (resp.errcode !== undefined && resp.errcode !== 0)) {
262
+ const errcode = resp.errcode ?? resp.ret ?? 0;
263
+ if (errcode === SESSION_EXPIRED_ERRCODE) {
264
+ sessionRetries++;
265
+ process.stderr.write(`[wechat-channel] Session 过期 (${sessionRetries}/${MAX_SESSION_RETRIES})\n`);
266
+ if (sessionRetries >= MAX_SESSION_RETRIES) {
267
+ pollingActive = false;
268
+ // 通知 Claude session 过期
269
+ server.notification({
270
+ method: 'notifications/message',
271
+ params: {
272
+ level: 'error',
273
+ data: 'WeChat session expired, please use login tool to reconnect',
274
+ },
275
+ });
276
+ return;
277
+ }
278
+ await sleep(SESSION_PAUSE_MS, pollingAbort?.signal);
279
+ continue;
280
+ }
281
+ // 其他错误
282
+ consecutiveFailures++;
283
+ process.stderr.write(`[wechat-channel] API 错误 errcode=${errcode} errmsg=${resp.errmsg ?? ''} ` +
284
+ `(${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES})\n`);
285
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
286
+ process.stderr.write(`[wechat-channel] 连续失败过多,暂停 ${SESSION_PAUSE_MS / 1000}s\n`);
287
+ await sleep(SESSION_PAUSE_MS, pollingAbort?.signal);
288
+ consecutiveFailures = 0;
289
+ }
290
+ else {
291
+ await sleep(retryDelay, pollingAbort?.signal);
292
+ retryDelay = Math.min(retryDelay * 2, MAX_RETRY_DELAY_MS);
293
+ }
294
+ continue;
295
+ }
296
+ // 成功 → 重置计数器
297
+ consecutiveFailures = 0;
298
+ retryDelay = INITIAL_RETRY_DELAY_MS;
299
+ // 保存 sync buf
300
+ if (resp.get_updates_buf) {
301
+ buf = resp.get_updates_buf;
302
+ saveSyncBuf(buf);
303
+ }
304
+ // 处理消息(仅用户消息 message_type === 1)
305
+ for (const msg of resp.msgs ?? []) {
306
+ if (msg.message_type !== 1)
307
+ continue;
308
+ const fromUser = msg.from_user_id ?? '';
309
+ const contextToken = msg.context_token ?? '';
310
+ // 提取文本
311
+ const text = await extractText(msg);
312
+ // 缓存 typing ticket(best-effort)
313
+ try {
314
+ const config = await getConfig(account.token, fromUser, contextToken, account.baseUrl);
315
+ if (config.typing_ticket) {
316
+ typingTicketCache.set(fromUser, config.typing_ticket);
317
+ }
318
+ }
319
+ catch {
320
+ // 忽略
321
+ }
322
+ // 发送 typing 状态(best-effort)
323
+ try {
324
+ const ticket = typingTicketCache.get(fromUser);
325
+ if (ticket) {
326
+ await sendTyping(account.token, fromUser, ticket, 1, account.baseUrl);
327
+ }
328
+ }
329
+ catch {
330
+ // 忽略
331
+ }
332
+ // 通知 Claude 有新消息
333
+ server.notification({
334
+ method: 'notifications/claude/channel',
335
+ params: {
336
+ content: text,
337
+ meta: {
338
+ source: 'wechat',
339
+ user_id: fromUser,
340
+ context_token: contextToken,
341
+ message_id: String(msg.message_id ?? ''),
342
+ session_id: msg.session_id ?? '',
343
+ },
344
+ },
345
+ });
346
+ }
347
+ }
348
+ catch (err) {
349
+ if (pollingAbort?.signal.aborted)
350
+ return;
351
+ // 网络错误 → 指数退避
352
+ consecutiveFailures++;
353
+ process.stderr.write(`[wechat-channel] 网络错误: ${String(err)} ` +
354
+ `(${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES})\n`);
355
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
356
+ process.stderr.write(`[wechat-channel] 连续失败过多,暂停 ${SESSION_PAUSE_MS / 1000}s\n`);
357
+ await sleep(SESSION_PAUSE_MS, pollingAbort?.signal);
358
+ consecutiveFailures = 0;
359
+ }
360
+ else {
361
+ await sleep(retryDelay, pollingAbort?.signal);
362
+ retryDelay = Math.min(retryDelay * 2, MAX_RETRY_DELAY_MS);
363
+ }
364
+ }
365
+ }
366
+ }
367
+ // ─── 轮询控制 ─────────────────────────────────────────
368
+ /** 启动消息轮询 */
369
+ function startPolling() {
370
+ const account = getActiveAccount();
371
+ if (!account || pollingActive)
372
+ return;
373
+ pollingActive = true;
374
+ pollingAbort = new AbortController();
375
+ pollLoop(account).catch((err) => {
376
+ if (!pollingAbort?.signal.aborted) {
377
+ process.stderr.write(`[wechat-channel] Poll loop crashed: ${String(err)}\n`);
378
+ }
379
+ pollingActive = false;
380
+ });
381
+ }
382
+ /** 停止消息轮询 */
383
+ function stopPolling() {
384
+ pollingActive = false;
385
+ pollingAbort?.abort();
386
+ pollingAbort = null;
387
+ }
388
+ // ─── 主入口 ───────────────────────────────────────────
389
+ async function main() {
390
+ const transport = new StdioServerTransport();
391
+ await server.connect(transport);
392
+ process.stderr.write('[wechat-channel] MCP server started\n');
393
+ const account = getActiveAccount();
394
+ if (account) {
395
+ process.stderr.write(`[wechat-channel] Found saved account: ${account.botId}\n`);
396
+ startPolling();
397
+ }
398
+ else {
399
+ process.stderr.write('[wechat-channel] No saved account. Use the login tool to connect.\n');
400
+ }
401
+ }
402
+ main().catch((err) => {
403
+ process.stderr.write(`[wechat-channel] Fatal: ${String(err)}\n`);
404
+ process.exit(1);
405
+ });
406
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AACnG,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,qDAAqD;AAErD,IAAI,aAAa,GAAG,KAAK,CAAC;AAC1B,IAAI,YAAY,GAA2B,IAAI,CAAC;AAChD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;AAEpD,mDAAmD;AAEnD,MAAM,uBAAuB,GAAG,CAAC,EAAE,CAAC;AACpC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,wBAAwB,GAAG,CAAC,CAAC;AACnC,MAAM,sBAAsB,GAAG,KAAK,CAAC;AACrC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,gBAAgB,GAAG,CAAC,GAAG,MAAM,CAAC;AAEpC,qDAAqD;AAErD,iBAAiB;AACjB,SAAS,KAAK,CAAC,EAAU,EAAE,MAAoB;IAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAClC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9G,CAAC,CAAC,CAAC;AACL,CAAC;AAED,2BAA2B;AAC3B,KAAK,UAAU,WAAW,CAAC,GAAkB;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;QAEzB,IAAI,CAAC,KAAK,eAAe,CAAC,IAAI,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC;aAAM,IAAI,CAAC,KAAK,eAAe,CAAC,KAAK,EAAE,CAAC;YACvC,IAAI,IAAI,GAAG,MAAM,CAAC;YAClB,IAAI,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,mBAAmB,IAAI,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;gBACnF,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC;wBACnC,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,mBAAmB;wBAC5D,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO;qBAC5C,CAAC,CAAC;oBACH,IAAI,IAAI,UAAU,QAAQ,GAAG,CAAC;gBAChC,CAAC;gBAAC,MAAM,CAAC;oBACP,cAAc;gBAChB,CAAC;YACH,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,CAAC,KAAK,eAAe,CAAC,KAAK,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,CAAC,KAAK,eAAe,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,IAAI,GAAG,QAAQ,IAAI,CAAC,SAAS,EAAE,SAAS,IAAI,SAAS,GAAG,CAAC;YAC7D,IAAI,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,mBAAmB,IAAI,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;gBACjF,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC;wBACnC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,mBAAmB;wBAC3D,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO;wBAC1C,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS;qBACnC,CAAC,CAAC;oBACH,IAAI,IAAI,UAAU,QAAQ,GAAG,CAAC;gBAChC,CAAC;gBAAC,MAAM,CAAC;oBACP,cAAc;gBAChB,CAAC;YACH,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,CAAC,KAAK,eAAe,CAAC,KAAK,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC;AACrC,CAAC;AAED,sDAAsD;AAEtD,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,EAC5C;IACE,YAAY,EAAE;QACZ,YAAY,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE;QACtC,KAAK,EAAE,EAAE;KACV;IACD,YAAY,EAAE;;;6FAG2E;CAC1F,CACF,CAAC;AAEF,wDAAwD;AAExD,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,EAAE;QACL;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,6BAA6B;YAC1C,WAAW,EAAE;gBACX,IAAI,EAAE,QAAiB;gBACvB,UAAU,EAAE,EAAE;aACf;SACF;QACD;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,QAAQ;YACrB,WAAW,EAAE;gBACX,IAAI,EAAE,QAAiB;gBACvB,UAAU,EAAE;oBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;oBACxE,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oCAAoC,EAAE;oBACpF,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE;oBAClD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;iBACjE;gBACD,QAAQ,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,SAAS,CAAC;aAClD;SACF;KACF;CACF,CAAC,CAAC,CAAC;AAEJ,wDAAwD;AAExD,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAEjD,mBAAmB;IACnB,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;YACpC,WAAW,CAAC;gBACV,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;gBAC7B,KAAK,EAAE,MAAM,CAAC,SAAS;gBACvB,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aAClC,CAAC,CAAC;YACH,YAAY,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,eAAe,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;aAC9E,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBAClE,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,IAAI,EAAE,OAA6B,CAAC;QACnD,MAAM,YAAY,GAAG,IAAI,EAAE,aAAmC,CAAC;QAC/D,MAAM,OAAO,GAAG,IAAI,EAAE,OAA6B,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,EAAE,KAA2B,CAAC;QAEhD,SAAS;QACT,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,yCAAyC,EAAE,CAAC;gBACrF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,SAAS;QACT,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC;gBACnE,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,aAAa;QACb,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,YAAY,KAAK,EAAE,EAAE,CAAC;gBAC/D,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,4BAA4B;YAC5B,IAAI,CAAC;gBACH,IAAI,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;oBACrF,MAAM,GAAG,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC;oBACpC,IAAI,MAAM;wBAAE,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACpD,CAAC;gBACD,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,eAAe;YACjB,CAAC;YAED,oBAAoB;YACpB,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACjF,CAAC;YAED,aAAa;YACb,IAAI,UAAU,GAAG,EAAE,CAAC;YACpB,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC;oBACH,MAAM,WAAW,CAAC;wBAChB,KAAK,EAAE,OAAO,CAAC,KAAK;wBACpB,MAAM,EAAE,MAAM;wBACd,YAAY;wBACZ,QAAQ,EAAE,KAAK;wBACf,OAAO,EAAE,OAAO,CAAC,OAAO;qBACzB,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,UAAU,GAAG,YAAY,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBAC1C,CAAC;YACH,CAAC;YAED,4BAA4B;YAC5B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC7C,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,eAAe;YACjB,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,OAAO,MAAM,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE;qBAC1E,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBAClE,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,IAAI,EAAE,EAAE,CAAC;QAC3D,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,qDAAqD;AAErD,cAAc;AACd,KAAK,UAAU,QAAQ,CAAC,OAAoB;IAC1C,IAAI,GAAG,GAAG,WAAW,EAAE,CAAC;IACxB,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAC5B,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,UAAU,GAAG,sBAAsB,CAAC;IACxC,IAAI,aAAiC,CAAC;IAEtC,OAAO,aAAa,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QACtD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YAElF,UAAU;YACV,IAAI,IAAI,CAAC,sBAAsB,EAAE,CAAC;gBAChC,aAAa,GAAG,IAAI,CAAC,sBAAsB,CAAC;YAC9C,CAAC;YAED,YAAY;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;gBACrG,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;gBAE9C,IAAI,OAAO,KAAK,uBAAuB,EAAE,CAAC;oBACxC,cAAc,EAAE,CAAC;oBACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,cAAc,IAAI,mBAAmB,KAAK,CAAC,CAAC;oBAEjG,IAAI,cAAc,IAAI,mBAAmB,EAAE,CAAC;wBAC1C,aAAa,GAAG,KAAK,CAAC;wBACtB,uBAAuB;wBACvB,MAAM,CAAC,YAAY,CAAC;4BAClB,MAAM,EAAE,uBAAuB;4BAC/B,MAAM,EAAE;gCACN,KAAK,EAAE,OAAO;gCACd,IAAI,EAAE,4DAA4D;6BACnE;yBACF,CAAC,CAAC;wBACH,OAAO;oBACT,CAAC;oBAED,MAAM,KAAK,CAAC,gBAAgB,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;oBACpD,SAAS;gBACX,CAAC;gBAED,OAAO;gBACP,mBAAmB,EAAE,CAAC;gBACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mCAAmC,OAAO,WAAW,IAAI,CAAC,MAAM,IAAI,EAAE,GAAG;oBACzE,IAAI,mBAAmB,IAAI,wBAAwB,KAAK,CACzD,CAAC;gBAEF,IAAI,mBAAmB,IAAI,wBAAwB,EAAE,CAAC;oBACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,gBAAgB,GAAG,IAAI,KAAK,CAAC,CAAC;oBACjF,MAAM,KAAK,CAAC,gBAAgB,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;oBACpD,mBAAmB,GAAG,CAAC,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;oBAC9C,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,kBAAkB,CAAC,CAAC;gBAC5D,CAAC;gBACD,SAAS;YACX,CAAC;YAED,aAAa;YACb,mBAAmB,GAAG,CAAC,CAAC;YACxB,UAAU,GAAG,sBAAsB,CAAC;YAEpC,cAAc;YACd,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC;gBAC3B,WAAW,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;YAED,iCAAiC;YACjC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;gBAClC,IAAI,GAAG,CAAC,YAAY,KAAK,CAAC;oBAAE,SAAS;gBAErC,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;gBACxC,MAAM,YAAY,GAAG,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;gBAE7C,OAAO;gBACP,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;gBAEpC,gCAAgC;gBAChC,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;oBACvF,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;wBACzB,iBAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;oBACxD,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,KAAK;gBACP,CAAC;gBAED,4BAA4B;gBAC5B,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBAC/C,IAAI,MAAM,EAAE,CAAC;wBACX,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;oBACxE,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,KAAK;gBACP,CAAC;gBAED,iBAAiB;gBACjB,MAAM,CAAC,YAAY,CAAC;oBAClB,MAAM,EAAE,8BAA8B;oBACtC,MAAM,EAAE;wBACN,OAAO,EAAE,IAAI;wBACb,IAAI,EAAE;4BACJ,MAAM,EAAE,QAAQ;4BAChB,OAAO,EAAE,QAAQ;4BACjB,aAAa,EAAE,YAAY;4BAC3B,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;4BACxC,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE;yBACjC;qBACF;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,YAAY,EAAE,MAAM,CAAC,OAAO;gBAAE,OAAO;YAEzC,cAAc;YACd,mBAAmB,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0BAA0B,MAAM,CAAC,GAAG,CAAC,GAAG;gBACxC,IAAI,mBAAmB,IAAI,wBAAwB,KAAK,CACzD,CAAC;YAEF,IAAI,mBAAmB,IAAI,wBAAwB,EAAE,CAAC;gBACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,gBAAgB,GAAG,IAAI,KAAK,CAAC,CAAC;gBACjF,MAAM,KAAK,CAAC,gBAAgB,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;gBACpD,mBAAmB,GAAG,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;gBAC9C,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,kBAAkB,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,qDAAqD;AAErD,aAAa;AACb,SAAS,YAAY;IACnB,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACnC,IAAI,CAAC,OAAO,IAAI,aAAa;QAAE,OAAO;IACtC,aAAa,GAAG,IAAI,CAAC;IACrB,YAAY,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QAC9B,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;YAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/E,CAAC;QACD,aAAa,GAAG,KAAK,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,aAAa;AACb,SAAS,WAAW;IAClB,aAAa,GAAG,KAAK,CAAC;IACtB,YAAY,EAAE,KAAK,EAAE,CAAC;IACtB,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAED,sDAAsD;AAEtD,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAE9D,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACnC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;QACjF,YAAY,EAAE,CAAC;IACjB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * cc-wechat 凭证持久化 — account.json 原子写入 + sync buf
3
+ */
4
+ import type { AccountData } from './types.js';
5
+ /**
6
+ * 获取状态目录路径,不存在则自动创建
7
+ */
8
+ export declare function getStateDir(): string;
9
+ /**
10
+ * 原子写入账号数据(先写 tmp 再 rename)
11
+ */
12
+ export declare function saveAccount(data: AccountData): void;
13
+ /**
14
+ * 读取当前活跃账号,文件不存在返回 null
15
+ */
16
+ export declare function getActiveAccount(): AccountData | null;
17
+ /**
18
+ * 读取 sync buf,不存在返回空字符串
19
+ */
20
+ export declare function loadSyncBuf(): string;
21
+ /**
22
+ * 写入 sync buf
23
+ */
24
+ export declare function saveSyncBuf(buf: string): void;