@aster110/cc2wechat 2.0.0 → 3.0.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/dist/daemon.js CHANGED
@@ -6,9 +6,10 @@ import path from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
8
  const replyCli = path.join(__dirname, 'reply-cli.js');
9
+ const IS_MACOS = process.platform === 'darwin';
9
10
  import { loginWithQRWeb } from './auth.js';
10
11
  import { getActiveAccount, saveAccount, loadSyncBuf, saveSyncBuf } from './store.js';
11
- import { getUpdates, sendMessage, sendTyping, getConfig, uploadAndSendMedia } from './wechat-api.js';
12
+ import { getUpdates, sendTyping, getConfig } from './wechat-api.js';
12
13
  import { MessageItemType } from './types.js';
13
14
  // ---------------------------------------------------------------------------
14
15
  // Constants
@@ -18,7 +19,6 @@ const MAX_CONSECUTIVE_FAILURES = 3;
18
19
  const BACKOFF_DELAY_MS = 30_000;
19
20
  const RETRY_DELAY_MS = 2_000;
20
21
  const SESSION_PAUSE_MS = 5 * 60_000;
21
- const MAX_CHUNK_LENGTH = 3900;
22
22
  // ---------------------------------------------------------------------------
23
23
  // Helpers
24
24
  // ---------------------------------------------------------------------------
@@ -47,53 +47,78 @@ function extractText(msg) {
47
47
  }
48
48
  return parts.join('\n') || '[Empty message]';
49
49
  }
50
- function stripMarkdown(text) {
51
- let result = text;
52
- // Code blocks: strip fences, keep content
53
- result = result.replace(/```[^\n]*\n?([\s\S]*?)```/g, (_, code) => code.trim());
54
- // Images: remove
55
- result = result.replace(/!\[[^\]]*\]\([^)]*\)/g, '');
56
- // Links: keep display text
57
- result = result.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1');
58
- // Bold/italic
59
- result = result.replace(/\*\*(.+?)\*\*/g, '$1');
60
- result = result.replace(/\*(.+?)\*/g, '$1');
61
- result = result.replace(/__(.+?)__/g, '$1');
62
- result = result.replace(/_(.+?)_/g, '$1');
63
- // Headings
64
- result = result.replace(/^#{1,6}\s+/gm, '');
65
- // Horizontal rules
66
- result = result.replace(/^[-*_]{3,}$/gm, '');
67
- // Blockquotes
68
- result = result.replace(/^>\s?/gm, '');
69
- return result.trim();
50
+ function sleep(ms) {
51
+ return new Promise((resolve) => setTimeout(resolve, ms));
70
52
  }
71
- function chunkText(text) {
72
- if (text.length <= MAX_CHUNK_LENGTH)
73
- return [text];
74
- const chunks = [];
75
- let remaining = text;
76
- while (remaining.length > 0) {
77
- if (remaining.length <= MAX_CHUNK_LENGTH) {
78
- chunks.push(remaining);
79
- break;
80
- }
81
- // Try to break at newline
82
- let breakAt = remaining.lastIndexOf('\n', MAX_CHUNK_LENGTH);
83
- if (breakAt < MAX_CHUNK_LENGTH * 0.5) {
84
- // No good newline break, try space
85
- breakAt = remaining.lastIndexOf(' ', MAX_CHUNK_LENGTH);
86
- }
87
- if (breakAt < MAX_CHUNK_LENGTH * 0.3) {
88
- breakAt = MAX_CHUNK_LENGTH;
53
+ // ---------------------------------------------------------------------------
54
+ // iTerm Tab Management
55
+ // ---------------------------------------------------------------------------
56
+ // Maintain tab state per WeChat user
57
+ const userTabs = new Map(); // userId -> tabName
58
+ // Track tab IDs - persisted to file so it survives daemon restart
59
+ const TAB_REGISTRY_PATH = '/tmp/cc2wechat-tabs.json';
60
+ const tabSessionIds = new Map(); // tabName -> iTerm session id
61
+ // Load persisted tab registry on startup
62
+ try {
63
+ if (fs.existsSync(TAB_REGISTRY_PATH)) {
64
+ const data = JSON.parse(fs.readFileSync(TAB_REGISTRY_PATH, 'utf-8'));
65
+ for (const [k, v] of Object.entries(data)) {
66
+ tabSessionIds.set(k, v);
89
67
  }
90
- chunks.push(remaining.slice(0, breakAt));
91
- remaining = remaining.slice(breakAt).trimStart();
92
68
  }
93
- return chunks;
94
69
  }
95
- function sleep(ms) {
96
- return new Promise((resolve) => setTimeout(resolve, ms));
70
+ catch { }
71
+ function saveTabRegistry() {
72
+ fs.writeFileSync(TAB_REGISTRY_PATH, JSON.stringify(Object.fromEntries(tabSessionIds)));
73
+ }
74
+ function tabExists(tabName) {
75
+ const windowId = tabSessionIds.get(tabName);
76
+ if (!windowId)
77
+ return false;
78
+ try {
79
+ const result = execSync(`osascript -e '
80
+ tell application "iTerm2"
81
+ try
82
+ set w to (first window whose id is ${windowId})
83
+ return "found"
84
+ on error
85
+ return "not_found"
86
+ end try
87
+ end tell
88
+ '`, { encoding: 'utf-8' }).trim();
89
+ return result === 'found';
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ }
95
+ function createTabAndStartCC(tabName, ccSessionId, cwd) {
96
+ // Create NEW WINDOW and capture window ID (same approach as cc-mesh)
97
+ const windowId = execSync(`osascript -e '
98
+ tell application "iTerm2"
99
+ set w to (create window with default profile)
100
+ tell current session of w
101
+ write text "cd ${cwd} && claude --resume ${ccSessionId} --dangerously-skip-permissions"
102
+ end tell
103
+ return id of w
104
+ end tell
105
+ '`, { encoding: 'utf-8' }).trim();
106
+ tabSessionIds.set(tabName, windowId);
107
+ saveTabRegistry();
108
+ console.log(`[cc2wechat] window created: ${tabName} -> window id: ${windowId}`);
109
+ }
110
+ function injectMessage(tabName, message) {
111
+ const windowId = tabSessionIds.get(tabName);
112
+ if (!windowId)
113
+ return;
114
+ const escaped = message.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
115
+ execSync(`osascript -e '
116
+ tell application "iTerm2"
117
+ tell current session of (first window whose id is ${windowId})
118
+ write text "${escaped}"
119
+ end tell
120
+ end tell
121
+ '`);
97
122
  }
98
123
  // ---------------------------------------------------------------------------
99
124
  // Core message handler
@@ -103,24 +128,11 @@ async function handleMessage(msg, account) {
103
128
  const userId = msg.from_user_id ?? '';
104
129
  const contextToken = msg.context_token ?? '';
105
130
  const sessionId = userIdToSessionUUID(userId);
131
+ const tabName = `wechat-${userId.slice(0, 8)}`;
132
+ const cwd = process.cwd();
106
133
  console.log(`[cc2wechat] <- ${userId.slice(0, 10)}...: ${text.slice(0, 50)}`);
107
- const systemPrompt = `You are responding to a WeChat message. Keep replies concise (under 500 chars when possible).
108
-
109
- You have these WeChat commands available via Bash:
110
- - Send image/file to user: node ${replyCli} --image /absolute/path/to/file
111
- - Send text message mid-process: node ${replyCli} --text "processing..."
112
-
113
- When user asks for screenshots, files, or images:
114
- 1. Create/save the file (e.g. screencapture -x /tmp/screenshot.png)
115
- 2. Send it: node ${replyCli} --image /tmp/screenshot.png
116
- 3. Confirm in your response
117
-
118
- Your final text response will also be sent to WeChat automatically.
119
-
120
- IMPORTANT: You are running in non-interactive mode. Do NOT use Agent Teams (TeamCreate/TaskCreate). Handle all tasks yourself sequentially.`;
121
- // Write context for cc2wechat-reply CLI
122
- const contextPath = '/tmp/cc2wechat-context.json';
123
- fs.writeFileSync(contextPath, JSON.stringify({
134
+ // Write context for reply-cli
135
+ fs.writeFileSync('/tmp/cc2wechat-context.json', JSON.stringify({
124
136
  token: account.token,
125
137
  baseUrl: account.baseUrl,
126
138
  userId,
@@ -136,68 +148,53 @@ IMPORTANT: You are running in non-interactive mode. Do NOT use Agent Teams (Team
136
148
  catch {
137
149
  // non-critical
138
150
  }
139
- // Call claude -p (try resume first, fallback to new session)
140
- let result;
141
- const prompt = JSON.stringify(text);
142
- try {
143
- // Try resuming existing session
144
- result = execSync(`claude -p ${prompt} --resume ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${JSON.stringify(systemPrompt)}`, { encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd: process.cwd() }).trim();
145
- }
146
- catch (err) {
147
- const execErr = err;
148
- const stderr = execErr.stderr ?? execErr.message ?? '';
149
- // If session not found, create new one
150
- if (stderr.includes('session') || stderr.includes('resume') || !execErr.stdout?.trim()) {
151
- try {
152
- result = execSync(`claude -p ${prompt} --session-id ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${JSON.stringify(systemPrompt)}`, { encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd: process.cwd() }).trim();
153
- }
154
- catch (err2) {
155
- const execErr2 = err2;
156
- result = execErr2.stdout?.trim() || `Error: ${execErr2.message ?? 'unknown'}`;
157
- }
151
+ if (IS_MACOS) {
152
+ // v3: Interactive Terminal Mode (macOS + iTerm2)
153
+ if (tabExists(tabName)) {
154
+ console.log(`[cc2wechat] -> inject to existing window: ${tabName}`);
155
+ injectMessage(tabName, `[微信] ${text}`);
158
156
  }
159
157
  else {
160
- result = execErr.stdout?.trim() || `Error: ${stderr}`;
158
+ console.log(`[cc2wechat] -> creating window: ${tabName} (session: ${sessionId})`);
159
+ createTabAndStartCC(tabName, sessionId, cwd);
160
+ await sleep(5000);
161
+ injectMessage(tabName, `[微信] ${text}`);
161
162
  }
163
+ userTabs.set(userId, tabName);
162
164
  }
163
- console.log(`[cc2wechat] -> ${result.slice(0, 100)}...`);
164
- // Strip markdown + chunk + send text
165
- const plainText = stripMarkdown(result);
166
- const chunks = chunkText(plainText);
167
- for (const chunk of chunks) {
168
- await sendMessage(account.token, userId, chunk, contextToken, account.baseUrl);
169
- }
170
- // Detect file paths in output, auto-send
171
- const fileMatch = result.match(/\/(tmp|Users|home)[\w/._-]+\.(png|jpg|jpeg|gif|mp4|pdf|zip)/gi);
172
- if (fileMatch) {
173
- for (const filePath of fileMatch) {
174
- if (fs.existsSync(filePath)) {
175
- console.log(`[cc2wechat] Sending file: ${filePath}`);
165
+ else {
166
+ // v2: Pipe Mode fallback (Windows/Linux)
167
+ console.log(`[cc2wechat] -> pipe mode: ${text.slice(0, 30)}...`);
168
+ const prompt = JSON.stringify(text);
169
+ const systemPrompt = JSON.stringify(`You are responding to a WeChat message. Keep replies concise. Use this to reply: node ${replyCli} --text "reply" or node ${replyCli} --image /path/to/file`);
170
+ let result;
171
+ try {
172
+ result = execSync(`claude -p ${prompt} --resume ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${systemPrompt}`, { encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd }).trim();
173
+ }
174
+ catch (err) {
175
+ const execErr = err;
176
+ if (!execErr.stdout?.trim()) {
176
177
  try {
177
- await uploadAndSendMedia({
178
- token: account.token,
179
- toUser: userId,
180
- contextToken,
181
- filePath,
182
- baseUrl: account.baseUrl,
183
- });
178
+ result = execSync(`claude -p ${prompt} --session-id ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${systemPrompt}`, { encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd }).trim();
184
179
  }
185
- catch (err) {
186
- const sendErr = err;
187
- console.error(`[cc2wechat] Failed to send file: ${sendErr.message ?? 'unknown'}`);
180
+ catch (err2) {
181
+ const execErr2 = err2;
182
+ result = execErr2.stdout?.trim() || `Error: ${execErr2.message ?? 'unknown'}`;
188
183
  }
189
184
  }
185
+ else {
186
+ result = execErr.stdout.trim();
187
+ }
190
188
  }
191
- }
192
- // Cancel typing
193
- try {
194
- const cfg = await getConfig(account.token, userId, contextToken, account.baseUrl);
195
- if (cfg.typing_ticket) {
196
- await sendTyping(account.token, userId, cfg.typing_ticket, 2, account.baseUrl).catch(() => { });
189
+ // Auto-send text reply
190
+ const { sendMessage: sendMsg } = await import('./wechat-api.js');
191
+ const plain = result.replace(/```[^\n]*\n?([\s\S]*?)```/g, (_, c) => c.trim())
192
+ .replace(/\*\*(.+?)\*\*/g, '$1').replace(/^#{1,6}\s+/gm, '').trim();
193
+ const chunks = plain.length <= 3900 ? [plain] : [plain.slice(0, 3900), plain.slice(3900)];
194
+ for (const chunk of chunks) {
195
+ await sendMsg(account.token, userId, chunk, contextToken, account.baseUrl);
197
196
  }
198
- }
199
- catch {
200
- // non-critical
197
+ console.log(`[cc2wechat] -> replied (${chunks.length} chunk)`);
201
198
  }
202
199
  }
203
200
  // ---------------------------------------------------------------------------
@@ -271,7 +268,7 @@ async function pollLoop(account) {
271
268
  // Main
272
269
  // ---------------------------------------------------------------------------
273
270
  async function main() {
274
- console.log('\n cc2wechat v2Pipe Mode\n');
271
+ console.log('\n cc2wechat v3Interactive Terminal Mode\n');
275
272
  let account = getActiveAccount();
276
273
  if (!account) {
277
274
  console.log(' No saved credentials. Starting login...');
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErG,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAM,uBAAuB,GAAG,CAAC,EAAE,CAAC;AACpC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AACnC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,MAAM,cAAc,GAAG,KAAK,CAAC;AAC7B,MAAM,gBAAgB,GAAG,CAAC,GAAG,MAAM,CAAC;AACpC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,mBAAmB,CAAC,MAAc;IACzC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3E,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;AACvH,CAAC;AAED,SAAS,WAAW,CAAC,GAAkB;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;YAC/D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,KAAK,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC;YACxE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC;YAC3E,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,KAAK,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC;AAC/C,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,0CAA0C;IAC1C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACxF,iBAAiB;IACjB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;IACrD,2BAA2B;IAC3B,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;IACxD,cAAc;IACd,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAChD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAC1C,WAAW;IACX,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAC5C,mBAAmB;IACnB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAC7C,cAAc;IACd,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACvC,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,IAAI,CAAC,MAAM,IAAI,gBAAgB;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,SAAS,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC;YACzC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACvB,MAAM;QACR,CAAC;QACD,0BAA0B;QAC1B,IAAI,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAC5D,IAAI,OAAO,GAAG,gBAAgB,GAAG,GAAG,EAAE,CAAC;YACrC,mCAAmC;YACnC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,OAAO,GAAG,gBAAgB,GAAG,GAAG,EAAE,CAAC;YACrC,OAAO,GAAG,gBAAgB,CAAC;QAC7B,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACzC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E,KAAK,UAAU,aAAa,CAAC,GAAkB,EAAE,OAAoB;IACnE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;IACtC,MAAM,YAAY,GAAG,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;IAC7C,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAE9C,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAE9E,MAAM,YAAY,GAAG;;;kCAGW,QAAQ;wCACF,QAAQ;;;;mBAI7B,QAAQ;;;;;4IAKiH,CAAC;IAE3I,wCAAwC;IACxC,MAAM,WAAW,GAAG,6BAA6B,CAAC;IAClD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC;QAC3C,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM;QACN,YAAY;KACb,CAAC,CAAC,CAAC;IAEJ,wBAAwB;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAClF,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;YACtB,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,6DAA6D;IAC7D,IAAI,MAAc,CAAC;IACnB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,gCAAgC;QAChC,MAAM,GAAG,QAAQ,CACf,aAAa,MAAM,aAAa,SAAS,6EAA6E,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,EACpJ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CACzF,CAAC,IAAI,EAAE,CAAC;IACX,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAA6D,CAAC;QAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QACvD,uCAAuC;QACvC,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;YACvF,IAAI,CAAC;gBACH,MAAM,GAAG,QAAQ,CACf,aAAa,MAAM,iBAAiB,SAAS,6EAA6E,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,EACxJ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CACzF,CAAC,IAAI,EAAE,CAAC;YACX,CAAC;YAAC,OAAO,IAAa,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,IAA6C,CAAC;gBAC/D,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,UAAU,QAAQ,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC;YAChF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,UAAU,MAAM,EAAE,CAAC;QACxD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IAEzD,qCAAqC;IACrC,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACjF,CAAC;IAED,yCAAyC;IACzC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;IAChG,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,CAAC,6BAA6B,QAAQ,EAAE,CAAC,CAAC;gBACrD,IAAI,CAAC;oBACH,MAAM,kBAAkB,CAAC;wBACvB,KAAK,EAAE,OAAO,CAAC,KAAK;wBACpB,MAAM,EAAE,MAAM;wBACd,YAAY;wBACZ,QAAQ;wBACR,OAAO,EAAE,OAAO,CAAC,OAAO;qBACzB,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,GAAY,EAAE,CAAC;oBACtB,MAAM,OAAO,GAAG,GAA2B,CAAC;oBAC5C,OAAO,CAAC,KAAK,CAAC,oCAAoC,OAAO,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC;gBACpF,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,gBAAgB;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAClF,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;YACtB,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,KAAK,UAAU,QAAQ,CAAC,OAAoB;IAC1C,IAAI,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAC5B,IAAI,aAAa,GAAG,MAAM,CAAC;IAE3B,OAAO,CAAC,GAAG,CAAC,2CAA2C,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAE5E,iDAAiD;IACjD,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YAElF,wCAAwC;YACxC,IAAI,IAAI,CAAC,sBAAsB,IAAI,IAAI,IAAI,IAAI,CAAC,sBAAsB,GAAG,CAAC,EAAE,CAAC;gBAC3E,aAAa,GAAG,IAAI,CAAC,sBAAsB,CAAC;YAC9C,CAAC;YAED,uBAAuB;YACvB,MAAM,UAAU,GACd,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;gBAC1C,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC;YAErD,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,gBAAgB,GACpB,IAAI,CAAC,OAAO,KAAK,uBAAuB,IAAI,IAAI,CAAC,GAAG,KAAK,uBAAuB,CAAC;gBAEnF,IAAI,gBAAgB,EAAE,CAAC;oBACrB,OAAO,CAAC,GAAG,CACT,wCAAwC,uBAAuB,cAAc,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,MAAM,CACxH,CAAC;oBACF,mBAAmB,GAAG,CAAC,CAAC;oBACxB,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAC;oBAC9B,SAAS;gBACX,CAAC;gBAED,mBAAmB,EAAE,CAAC;gBACtB,OAAO,CAAC,KAAK,CACX,qCAAqC,IAAI,CAAC,GAAG,YAAY,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,MAAM,IAAI,EAAE,KAAK,mBAAmB,IAAI,wBAAwB,GAAG,CACzJ,CAAC;gBACF,IAAI,mBAAmB,IAAI,wBAAwB,EAAE,CAAC;oBACpD,mBAAmB,GAAG,CAAC,CAAC;oBACxB,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAC;gBAChC,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC,cAAc,CAAC,CAAC;gBAC9B,CAAC;gBACD,SAAS;YACX,CAAC;YAED,mBAAmB,GAAG,CAAC,CAAC;YAExB,gBAAgB;YAChB,IAAI,IAAI,CAAC,eAAe,IAAI,IAAI,IAAI,IAAI,CAAC,eAAe,KAAK,EAAE,EAAE,CAAC;gBAChE,WAAW,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;gBACrD,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC;YAC7B,CAAC;YAED,mBAAmB;YACnB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YAC7B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,kDAAkD;gBAClD,IAAI,GAAG,CAAC,YAAY,KAAK,CAAC;oBAAE,SAAS;gBAErC,4DAA4D;gBAC5D,MAAM,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CACX,2BAA2B,mBAAmB,IAAI,wBAAwB,MAAM,MAAM,CAAC,GAAG,CAAC,EAAE,CAC9F,CAAC;YACF,IAAI,mBAAmB,IAAI,wBAAwB,EAAE,CAAC;gBACpD,mBAAmB,GAAG,CAAC,CAAC;gBACxB,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,CAAC,cAAc,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,OAAO;AACP,8EAA8E;AAE9E,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAE9C,IAAI,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;QACtC,WAAW,CAAC;YACV,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;YAClE,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAClC,CAAC,CAAC;QACH,OAAO,GAAG,gBAAgB,EAAG,CAAC;IAChC,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IAEpD,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,UAAU,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aster110/cc2wechat",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "WeChat channel for Claude Code — chat with Claude Code from WeChat via iLink Bot API",
5
5
  "type": "module",
6
6
  "bin": {
package/src/daemon.ts CHANGED
@@ -8,10 +8,11 @@ import { fileURLToPath } from 'node:url';
8
8
 
9
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
10
  const replyCli = path.join(__dirname, 'reply-cli.js');
11
+ const IS_MACOS = process.platform === 'darwin';
11
12
 
12
13
  import { loginWithQRWeb } from './auth.js';
13
14
  import { getActiveAccount, saveAccount, loadSyncBuf, saveSyncBuf } from './store.js';
14
- import { getUpdates, sendMessage, sendTyping, getConfig, uploadAndSendMedia } from './wechat-api.js';
15
+ import { getUpdates, sendTyping, getConfig } from './wechat-api.js';
15
16
  import type { WeixinMessage } from './types.js';
16
17
  import { MessageItemType } from './types.js';
17
18
  import type { AccountData } from './store.js';
@@ -25,7 +26,6 @@ const MAX_CONSECUTIVE_FAILURES = 3;
25
26
  const BACKOFF_DELAY_MS = 30_000;
26
27
  const RETRY_DELAY_MS = 2_000;
27
28
  const SESSION_PAUSE_MS = 5 * 60_000;
28
- const MAX_CHUNK_LENGTH = 3900;
29
29
 
30
30
  // ---------------------------------------------------------------------------
31
31
  // Helpers
@@ -54,54 +54,82 @@ function extractText(msg: WeixinMessage): string {
54
54
  return parts.join('\n') || '[Empty message]';
55
55
  }
56
56
 
57
- function stripMarkdown(text: string): string {
58
- let result = text;
59
- // Code blocks: strip fences, keep content
60
- result = result.replace(/```[^\n]*\n?([\s\S]*?)```/g, (_, code: string) => code.trim());
61
- // Images: remove
62
- result = result.replace(/!\[[^\]]*\]\([^)]*\)/g, '');
63
- // Links: keep display text
64
- result = result.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1');
65
- // Bold/italic
66
- result = result.replace(/\*\*(.+?)\*\*/g, '$1');
67
- result = result.replace(/\*(.+?)\*/g, '$1');
68
- result = result.replace(/__(.+?)__/g, '$1');
69
- result = result.replace(/_(.+?)_/g, '$1');
70
- // Headings
71
- result = result.replace(/^#{1,6}\s+/gm, '');
72
- // Horizontal rules
73
- result = result.replace(/^[-*_]{3,}$/gm, '');
74
- // Blockquotes
75
- result = result.replace(/^>\s?/gm, '');
76
- return result.trim();
57
+ function sleep(ms: number): Promise<void> {
58
+ return new Promise((resolve) => setTimeout(resolve, ms));
77
59
  }
78
60
 
79
- function chunkText(text: string): string[] {
80
- if (text.length <= MAX_CHUNK_LENGTH) return [text];
81
- const chunks: string[] = [];
82
- let remaining = text;
83
- while (remaining.length > 0) {
84
- if (remaining.length <= MAX_CHUNK_LENGTH) {
85
- chunks.push(remaining);
86
- break;
87
- }
88
- // Try to break at newline
89
- let breakAt = remaining.lastIndexOf('\n', MAX_CHUNK_LENGTH);
90
- if (breakAt < MAX_CHUNK_LENGTH * 0.5) {
91
- // No good newline break, try space
92
- breakAt = remaining.lastIndexOf(' ', MAX_CHUNK_LENGTH);
93
- }
94
- if (breakAt < MAX_CHUNK_LENGTH * 0.3) {
95
- breakAt = MAX_CHUNK_LENGTH;
61
+ // ---------------------------------------------------------------------------
62
+ // iTerm Tab Management
63
+ // ---------------------------------------------------------------------------
64
+
65
+ // Maintain tab state per WeChat user
66
+ const userTabs = new Map<string, string>(); // userId -> tabName
67
+
68
+ // Track tab IDs - persisted to file so it survives daemon restart
69
+ const TAB_REGISTRY_PATH = '/tmp/cc2wechat-tabs.json';
70
+ const tabSessionIds = new Map<string, string>(); // tabName -> iTerm session id
71
+
72
+ // Load persisted tab registry on startup
73
+ try {
74
+ if (fs.existsSync(TAB_REGISTRY_PATH)) {
75
+ const data = JSON.parse(fs.readFileSync(TAB_REGISTRY_PATH, 'utf-8'));
76
+ for (const [k, v] of Object.entries(data)) {
77
+ tabSessionIds.set(k, v as string);
96
78
  }
97
- chunks.push(remaining.slice(0, breakAt));
98
- remaining = remaining.slice(breakAt).trimStart();
99
79
  }
100
- return chunks;
80
+ } catch {}
81
+
82
+ function saveTabRegistry(): void {
83
+ fs.writeFileSync(TAB_REGISTRY_PATH, JSON.stringify(Object.fromEntries(tabSessionIds)));
84
+ }
85
+
86
+ function tabExists(tabName: string): boolean {
87
+ const windowId = tabSessionIds.get(tabName);
88
+ if (!windowId) return false;
89
+ try {
90
+ const result = execSync(`osascript -e '
91
+ tell application "iTerm2"
92
+ try
93
+ set w to (first window whose id is ${windowId})
94
+ return "found"
95
+ on error
96
+ return "not_found"
97
+ end try
98
+ end tell
99
+ '`, { encoding: 'utf-8' }).trim();
100
+ return result === 'found';
101
+ } catch {
102
+ return false;
103
+ }
101
104
  }
102
105
 
103
- function sleep(ms: number): Promise<void> {
104
- return new Promise((resolve) => setTimeout(resolve, ms));
106
+ function createTabAndStartCC(tabName: string, ccSessionId: string, cwd: string): void {
107
+ // Create NEW WINDOW and capture window ID (same approach as cc-mesh)
108
+ const windowId = execSync(`osascript -e '
109
+ tell application "iTerm2"
110
+ set w to (create window with default profile)
111
+ tell current session of w
112
+ write text "cd ${cwd} && claude --resume ${ccSessionId} --dangerously-skip-permissions"
113
+ end tell
114
+ return id of w
115
+ end tell
116
+ '`, { encoding: 'utf-8' }).trim();
117
+ tabSessionIds.set(tabName, windowId);
118
+ saveTabRegistry();
119
+ console.log(`[cc2wechat] window created: ${tabName} -> window id: ${windowId}`);
120
+ }
121
+
122
+ function injectMessage(tabName: string, message: string): void {
123
+ const windowId = tabSessionIds.get(tabName);
124
+ if (!windowId) return;
125
+ const escaped = message.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
126
+ execSync(`osascript -e '
127
+ tell application "iTerm2"
128
+ tell current session of (first window whose id is ${windowId})
129
+ write text "${escaped}"
130
+ end tell
131
+ end tell
132
+ '`);
105
133
  }
106
134
 
107
135
  // ---------------------------------------------------------------------------
@@ -113,27 +141,13 @@ async function handleMessage(msg: WeixinMessage, account: AccountData): Promise<
113
141
  const userId = msg.from_user_id ?? '';
114
142
  const contextToken = msg.context_token ?? '';
115
143
  const sessionId = userIdToSessionUUID(userId);
144
+ const tabName = `wechat-${userId.slice(0, 8)}`;
145
+ const cwd = process.cwd();
116
146
 
117
147
  console.log(`[cc2wechat] <- ${userId.slice(0, 10)}...: ${text.slice(0, 50)}`);
118
148
 
119
- const systemPrompt = `You are responding to a WeChat message. Keep replies concise (under 500 chars when possible).
120
-
121
- You have these WeChat commands available via Bash:
122
- - Send image/file to user: node ${replyCli} --image /absolute/path/to/file
123
- - Send text message mid-process: node ${replyCli} --text "processing..."
124
-
125
- When user asks for screenshots, files, or images:
126
- 1. Create/save the file (e.g. screencapture -x /tmp/screenshot.png)
127
- 2. Send it: node ${replyCli} --image /tmp/screenshot.png
128
- 3. Confirm in your response
129
-
130
- Your final text response will also be sent to WeChat automatically.
131
-
132
- IMPORTANT: You are running in non-interactive mode. Do NOT use Agent Teams (TeamCreate/TaskCreate). Handle all tasks yourself sequentially.`;
133
-
134
- // Write context for cc2wechat-reply CLI
135
- const contextPath = '/tmp/cc2wechat-context.json';
136
- fs.writeFileSync(contextPath, JSON.stringify({
149
+ // Write context for reply-cli
150
+ fs.writeFileSync('/tmp/cc2wechat-context.json', JSON.stringify({
137
151
  token: account.token,
138
152
  baseUrl: account.baseUrl,
139
153
  userId,
@@ -150,73 +164,54 @@ IMPORTANT: You are running in non-interactive mode. Do NOT use Agent Teams (Team
150
164
  // non-critical
151
165
  }
152
166
 
153
- // Call claude -p (try resume first, fallback to new session)
154
- let result: string;
155
- const prompt = JSON.stringify(text);
156
- try {
157
- // Try resuming existing session
158
- result = execSync(
159
- `claude -p ${prompt} --resume ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${JSON.stringify(systemPrompt)}`,
160
- { encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd: process.cwd() },
161
- ).trim();
162
- } catch (err: unknown) {
163
- const execErr = err as { stdout?: string; stderr?: string; message?: string };
164
- const stderr = execErr.stderr ?? execErr.message ?? '';
165
- // If session not found, create new one
166
- if (stderr.includes('session') || stderr.includes('resume') || !execErr.stdout?.trim()) {
167
- try {
168
- result = execSync(
169
- `claude -p ${prompt} --session-id ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${JSON.stringify(systemPrompt)}`,
170
- { encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd: process.cwd() },
171
- ).trim();
172
- } catch (err2: unknown) {
173
- const execErr2 = err2 as { stdout?: string; message?: string };
174
- result = execErr2.stdout?.trim() || `Error: ${execErr2.message ?? 'unknown'}`;
175
- }
167
+ if (IS_MACOS) {
168
+ // v3: Interactive Terminal Mode (macOS + iTerm2)
169
+ if (tabExists(tabName)) {
170
+ console.log(`[cc2wechat] -> inject to existing window: ${tabName}`);
171
+ injectMessage(tabName, `[微信] ${text}`);
176
172
  } else {
177
- result = execErr.stdout?.trim() || `Error: ${stderr}`;
173
+ console.log(`[cc2wechat] -> creating window: ${tabName} (session: ${sessionId})`);
174
+ createTabAndStartCC(tabName, sessionId, cwd);
175
+ await sleep(5000);
176
+ injectMessage(tabName, `[微信] ${text}`);
178
177
  }
179
- }
180
-
181
- console.log(`[cc2wechat] -> ${result.slice(0, 100)}...`);
182
-
183
- // Strip markdown + chunk + send text
184
- const plainText = stripMarkdown(result);
185
- const chunks = chunkText(plainText);
186
- for (const chunk of chunks) {
187
- await sendMessage(account.token, userId, chunk, contextToken, account.baseUrl);
188
- }
189
-
190
- // Detect file paths in output, auto-send
191
- const fileMatch = result.match(/\/(tmp|Users|home)[\w/._-]+\.(png|jpg|jpeg|gif|mp4|pdf|zip)/gi);
192
- if (fileMatch) {
193
- for (const filePath of fileMatch) {
194
- if (fs.existsSync(filePath)) {
195
- console.log(`[cc2wechat] Sending file: ${filePath}`);
178
+ userTabs.set(userId, tabName);
179
+ } else {
180
+ // v2: Pipe Mode fallback (Windows/Linux)
181
+ console.log(`[cc2wechat] -> pipe mode: ${text.slice(0, 30)}...`);
182
+ const prompt = JSON.stringify(text);
183
+ const systemPrompt = JSON.stringify(`You are responding to a WeChat message. Keep replies concise. Use this to reply: node ${replyCli} --text "reply" or node ${replyCli} --image /path/to/file`);
184
+ let result: string;
185
+ try {
186
+ result = execSync(
187
+ `claude -p ${prompt} --resume ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${systemPrompt}`,
188
+ { encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd },
189
+ ).trim();
190
+ } catch (err: unknown) {
191
+ const execErr = err as { stdout?: string; stderr?: string; message?: string };
192
+ if (!execErr.stdout?.trim()) {
196
193
  try {
197
- await uploadAndSendMedia({
198
- token: account.token,
199
- toUser: userId,
200
- contextToken,
201
- filePath,
202
- baseUrl: account.baseUrl,
203
- });
204
- } catch (err: unknown) {
205
- const sendErr = err as { message?: string };
206
- console.error(`[cc2wechat] Failed to send file: ${sendErr.message ?? 'unknown'}`);
194
+ result = execSync(
195
+ `claude -p ${prompt} --session-id ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${systemPrompt}`,
196
+ { encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd },
197
+ ).trim();
198
+ } catch (err2: unknown) {
199
+ const execErr2 = err2 as { stdout?: string; message?: string };
200
+ result = execErr2.stdout?.trim() || `Error: ${execErr2.message ?? 'unknown'}`;
207
201
  }
202
+ } else {
203
+ result = execErr.stdout.trim();
208
204
  }
209
205
  }
210
- }
211
-
212
- // Cancel typing
213
- try {
214
- const cfg = await getConfig(account.token, userId, contextToken, account.baseUrl);
215
- if (cfg.typing_ticket) {
216
- await sendTyping(account.token, userId, cfg.typing_ticket, 2, account.baseUrl).catch(() => {});
206
+ // Auto-send text reply
207
+ const { sendMessage: sendMsg } = await import('./wechat-api.js');
208
+ const plain = result.replace(/```[^\n]*\n?([\s\S]*?)```/g, (_, c: string) => c.trim())
209
+ .replace(/\*\*(.+?)\*\*/g, '$1').replace(/^#{1,6}\s+/gm, '').trim();
210
+ const chunks = plain.length <= 3900 ? [plain] : [plain.slice(0, 3900), plain.slice(3900)];
211
+ for (const chunk of chunks) {
212
+ await sendMsg(account.token, userId, chunk, contextToken, account.baseUrl);
217
213
  }
218
- } catch {
219
- // non-critical
214
+ console.log(`[cc2wechat] -> replied (${chunks.length} chunk)`);
220
215
  }
221
216
  }
222
217
 
@@ -309,7 +304,7 @@ async function pollLoop(account: AccountData): Promise<void> {
309
304
  // ---------------------------------------------------------------------------
310
305
 
311
306
  async function main(): Promise<void> {
312
- console.log('\n cc2wechat v2Pipe Mode\n');
307
+ console.log('\n cc2wechat v3Interactive Terminal Mode\n');
313
308
 
314
309
  let account = getActiveAccount();
315
310
  if (!account) {