@aster110/cc2wechat 2.0.0 → 3.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.
- package/dist/auth.js +3 -1
- package/dist/auth.js.map +1 -1
- package/dist/daemon.js +13 -163
- package/dist/daemon.js.map +1 -1
- package/dist/handlers/pipe.d.ts +3 -0
- package/dist/handlers/pipe.js +47 -0
- package/dist/handlers/pipe.js.map +1 -0
- package/dist/handlers/terminal.d.ts +3 -0
- package/dist/handlers/terminal.js +95 -0
- package/dist/handlers/terminal.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +31 -0
- package/dist/utils.js.map +1 -0
- package/package.json +1 -1
- package/src/auth.ts +3 -1
- package/src/daemon.ts +14 -171
- package/src/handlers/pipe.ts +56 -0
- package/src/handlers/terminal.ts +104 -0
- package/src/utils.ts +30 -0
package/dist/auth.js
CHANGED
|
@@ -138,7 +138,9 @@ function buildQRPage(qrUrl) {
|
|
|
138
138
|
</html>`;
|
|
139
139
|
}
|
|
140
140
|
function openBrowser(url) {
|
|
141
|
-
const cmd = process.platform === 'darwin' ? 'open'
|
|
141
|
+
const cmd = process.platform === 'darwin' ? 'open'
|
|
142
|
+
: process.platform === 'win32' ? 'start'
|
|
143
|
+
: 'xdg-open';
|
|
142
144
|
exec(`${cmd} ${url}`, () => { });
|
|
143
145
|
}
|
|
144
146
|
/**
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon.js
CHANGED
|
@@ -1,126 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { execSync } from 'node:child_process';
|
|
3
|
-
import { createHash } from 'node:crypto';
|
|
4
2
|
import fs from 'node:fs';
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const replyCli = path.join(__dirname, 'reply-cli.js');
|
|
9
3
|
import { loginWithQRWeb } from './auth.js';
|
|
10
4
|
import { getActiveAccount, saveAccount, loadSyncBuf, saveSyncBuf } from './store.js';
|
|
11
|
-
import { getUpdates,
|
|
12
|
-
import {
|
|
5
|
+
import { getUpdates, sendTyping, getConfig } from './wechat-api.js';
|
|
6
|
+
import { extractText } from './utils.js';
|
|
7
|
+
import { handleMessageTerminal } from './handlers/terminal.js';
|
|
8
|
+
import { handleMessagePipe } from './handlers/pipe.js';
|
|
13
9
|
// ---------------------------------------------------------------------------
|
|
14
10
|
// Constants
|
|
15
11
|
// ---------------------------------------------------------------------------
|
|
12
|
+
const IS_MACOS = process.platform === 'darwin';
|
|
16
13
|
const SESSION_EXPIRED_ERRCODE = -14;
|
|
17
14
|
const MAX_CONSECUTIVE_FAILURES = 3;
|
|
18
15
|
const BACKOFF_DELAY_MS = 30_000;
|
|
19
16
|
const RETRY_DELAY_MS = 2_000;
|
|
20
17
|
const SESSION_PAUSE_MS = 5 * 60_000;
|
|
21
|
-
const MAX_CHUNK_LENGTH = 3900;
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
// Helpers
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
function userIdToSessionUUID(userId) {
|
|
26
|
-
const hash = createHash('md5').update(`cc2wechat:${userId}`).digest('hex');
|
|
27
|
-
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
|
|
28
|
-
}
|
|
29
|
-
function extractText(msg) {
|
|
30
|
-
const parts = [];
|
|
31
|
-
for (const item of msg.item_list ?? []) {
|
|
32
|
-
if (item.type === MessageItemType.TEXT && item.text_item?.text) {
|
|
33
|
-
parts.push(item.text_item.text);
|
|
34
|
-
}
|
|
35
|
-
else if (item.type === MessageItemType.IMAGE) {
|
|
36
|
-
parts.push('[Image]');
|
|
37
|
-
}
|
|
38
|
-
else if (item.type === MessageItemType.VOICE && item.voice_item?.text) {
|
|
39
|
-
parts.push(`[Voice] ${item.voice_item.text}`);
|
|
40
|
-
}
|
|
41
|
-
else if (item.type === MessageItemType.FILE && item.file_item?.file_name) {
|
|
42
|
-
parts.push(`[File: ${item.file_item.file_name}]`);
|
|
43
|
-
}
|
|
44
|
-
else if (item.type === MessageItemType.VIDEO) {
|
|
45
|
-
parts.push('[Video]');
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return parts.join('\n') || '[Empty message]';
|
|
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();
|
|
70
|
-
}
|
|
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;
|
|
89
|
-
}
|
|
90
|
-
chunks.push(remaining.slice(0, breakAt));
|
|
91
|
-
remaining = remaining.slice(breakAt).trimStart();
|
|
92
|
-
}
|
|
93
|
-
return chunks;
|
|
94
|
-
}
|
|
95
18
|
function sleep(ms) {
|
|
96
19
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
97
20
|
}
|
|
98
21
|
// ---------------------------------------------------------------------------
|
|
99
|
-
// Core message handler
|
|
22
|
+
// Core message handler — routes to platform-specific handler
|
|
100
23
|
// ---------------------------------------------------------------------------
|
|
101
24
|
async function handleMessage(msg, account) {
|
|
102
25
|
const text = extractText(msg);
|
|
103
26
|
const userId = msg.from_user_id ?? '';
|
|
104
27
|
const contextToken = msg.context_token ?? '';
|
|
105
|
-
const sessionId = userIdToSessionUUID(userId);
|
|
106
28
|
console.log(`[cc2wechat] <- ${userId.slice(0, 10)}...: ${text.slice(0, 50)}`);
|
|
107
|
-
|
|
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({
|
|
29
|
+
// Write context for reply-cli
|
|
30
|
+
fs.writeFileSync('/tmp/cc2wechat-context.json', JSON.stringify({
|
|
124
31
|
token: account.token,
|
|
125
32
|
baseUrl: account.baseUrl,
|
|
126
33
|
userId,
|
|
@@ -136,68 +43,11 @@ IMPORTANT: You are running in non-interactive mode. Do NOT use Agent Teams (Team
|
|
|
136
43
|
catch {
|
|
137
44
|
// non-critical
|
|
138
45
|
}
|
|
139
|
-
|
|
140
|
-
|
|
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();
|
|
46
|
+
if (IS_MACOS) {
|
|
47
|
+
await handleMessageTerminal(msg, account);
|
|
145
48
|
}
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
}
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
result = execErr.stdout?.trim() || `Error: ${stderr}`;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
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}`);
|
|
176
|
-
try {
|
|
177
|
-
await uploadAndSendMedia({
|
|
178
|
-
token: account.token,
|
|
179
|
-
toUser: userId,
|
|
180
|
-
contextToken,
|
|
181
|
-
filePath,
|
|
182
|
-
baseUrl: account.baseUrl,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
catch (err) {
|
|
186
|
-
const sendErr = err;
|
|
187
|
-
console.error(`[cc2wechat] Failed to send file: ${sendErr.message ?? 'unknown'}`);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
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(() => { });
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
catch {
|
|
200
|
-
// non-critical
|
|
49
|
+
else {
|
|
50
|
+
await handleMessagePipe(msg, account);
|
|
201
51
|
}
|
|
202
52
|
}
|
|
203
53
|
// ---------------------------------------------------------------------------
|
|
@@ -271,7 +121,7 @@ async function pollLoop(account) {
|
|
|
271
121
|
// Main
|
|
272
122
|
// ---------------------------------------------------------------------------
|
|
273
123
|
async function main() {
|
|
274
|
-
console.log('\n cc2wechat
|
|
124
|
+
console.log('\n cc2wechat v3 — Interactive Terminal Mode\n');
|
|
275
125
|
let account = getActiveAccount();
|
|
276
126
|
if (!account) {
|
|
277
127
|
console.log(' No saved credentials. Starting login...');
|
package/dist/daemon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { extractText, userIdToSessionUUID } from '../utils.js';
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const replyCli = path.join(__dirname, '..', 'reply-cli.js');
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Pipe mode message handler (Windows/Linux)
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
export async function handleMessagePipe(msg, account) {
|
|
11
|
+
const text = extractText(msg);
|
|
12
|
+
const userId = msg.from_user_id ?? '';
|
|
13
|
+
const sessionId = userIdToSessionUUID(userId);
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
console.log(`[cc2wechat] -> pipe mode: ${text.slice(0, 30)}...`);
|
|
16
|
+
const prompt = JSON.stringify(text);
|
|
17
|
+
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`);
|
|
18
|
+
let result;
|
|
19
|
+
try {
|
|
20
|
+
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();
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
const execErr = err;
|
|
24
|
+
if (!execErr.stdout?.trim()) {
|
|
25
|
+
try {
|
|
26
|
+
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();
|
|
27
|
+
}
|
|
28
|
+
catch (err2) {
|
|
29
|
+
const execErr2 = err2;
|
|
30
|
+
result = execErr2.stdout?.trim() || `Error: ${execErr2.message ?? 'unknown'}`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
result = execErr.stdout.trim();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Auto-send text reply
|
|
38
|
+
const { sendMessage: sendMsg } = await import('../wechat-api.js');
|
|
39
|
+
const plain = result.replace(/```[^\n]*\n?([\s\S]*?)```/g, (_, c) => c.trim())
|
|
40
|
+
.replace(/\*\*(.+?)\*\*/g, '$1').replace(/^#{1,6}\s+/gm, '').trim();
|
|
41
|
+
const chunks = plain.length <= 3900 ? [plain] : [plain.slice(0, 3900), plain.slice(3900)];
|
|
42
|
+
for (const chunk of chunks) {
|
|
43
|
+
await sendMsg(account.token, userId, chunk, msg.context_token ?? '', account.baseUrl);
|
|
44
|
+
}
|
|
45
|
+
console.log(`[cc2wechat] -> replied (${chunks.length} chunk)`);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=pipe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipe.js","sourceRoot":"","sources":["../../src/handlers/pipe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { extractText, userIdToSessionUUID, sleep } from '../utils.js';
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// iTerm Tab Management
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Maintain tab state per WeChat user
|
|
8
|
+
const userTabs = new Map(); // userId -> tabName
|
|
9
|
+
// Track tab IDs - persisted to file so it survives daemon restart
|
|
10
|
+
const TAB_REGISTRY_PATH = '/tmp/cc2wechat-tabs.json';
|
|
11
|
+
const tabSessionIds = new Map(); // tabName -> iTerm window id
|
|
12
|
+
// Load persisted tab registry on startup
|
|
13
|
+
try {
|
|
14
|
+
if (fs.existsSync(TAB_REGISTRY_PATH)) {
|
|
15
|
+
const data = JSON.parse(fs.readFileSync(TAB_REGISTRY_PATH, 'utf-8'));
|
|
16
|
+
for (const [k, v] of Object.entries(data)) {
|
|
17
|
+
tabSessionIds.set(k, v);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch { }
|
|
22
|
+
function saveTabRegistry() {
|
|
23
|
+
fs.writeFileSync(TAB_REGISTRY_PATH, JSON.stringify(Object.fromEntries(tabSessionIds)));
|
|
24
|
+
}
|
|
25
|
+
function tabExists(tabName) {
|
|
26
|
+
const windowId = tabSessionIds.get(tabName);
|
|
27
|
+
if (!windowId)
|
|
28
|
+
return false;
|
|
29
|
+
try {
|
|
30
|
+
const result = execSync(`osascript -e '
|
|
31
|
+
tell application "iTerm2"
|
|
32
|
+
try
|
|
33
|
+
set w to (first window whose id is ${windowId})
|
|
34
|
+
return "found"
|
|
35
|
+
on error
|
|
36
|
+
return "not_found"
|
|
37
|
+
end try
|
|
38
|
+
end tell
|
|
39
|
+
'`, { encoding: 'utf-8' }).trim();
|
|
40
|
+
return result === 'found';
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function createTabAndStartCC(tabName, ccSessionId, cwd) {
|
|
47
|
+
// Create NEW WINDOW and capture window ID (same approach as cc-mesh)
|
|
48
|
+
const windowId = execSync(`osascript -e '
|
|
49
|
+
tell application "iTerm2"
|
|
50
|
+
set w to (create window with default profile)
|
|
51
|
+
tell current session of w
|
|
52
|
+
write text "cd ${cwd} && claude --resume ${ccSessionId} --dangerously-skip-permissions"
|
|
53
|
+
end tell
|
|
54
|
+
return id of w
|
|
55
|
+
end tell
|
|
56
|
+
'`, { encoding: 'utf-8' }).trim();
|
|
57
|
+
tabSessionIds.set(tabName, windowId);
|
|
58
|
+
saveTabRegistry();
|
|
59
|
+
console.log(`[cc2wechat] window created: ${tabName} -> window id: ${windowId}`);
|
|
60
|
+
}
|
|
61
|
+
function injectMessage(tabName, message) {
|
|
62
|
+
const windowId = tabSessionIds.get(tabName);
|
|
63
|
+
if (!windowId)
|
|
64
|
+
return;
|
|
65
|
+
const escaped = message.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
66
|
+
execSync(`osascript -e '
|
|
67
|
+
tell application "iTerm2"
|
|
68
|
+
tell current session of (first window whose id is ${windowId})
|
|
69
|
+
write text "${escaped}"
|
|
70
|
+
end tell
|
|
71
|
+
end tell
|
|
72
|
+
'`);
|
|
73
|
+
}
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Terminal mode message handler
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
export async function handleMessageTerminal(msg, account) {
|
|
78
|
+
const text = extractText(msg);
|
|
79
|
+
const userId = msg.from_user_id ?? '';
|
|
80
|
+
const sessionId = userIdToSessionUUID(userId);
|
|
81
|
+
const tabName = `wechat-${userId.slice(0, 8)}`;
|
|
82
|
+
const cwd = process.cwd();
|
|
83
|
+
if (tabExists(tabName)) {
|
|
84
|
+
console.log(`[cc2wechat] -> inject to existing window: ${tabName}`);
|
|
85
|
+
injectMessage(tabName, `[微信] ${text}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.log(`[cc2wechat] -> creating window: ${tabName} (session: ${sessionId})`);
|
|
89
|
+
createTabAndStartCC(tabName, sessionId, cwd);
|
|
90
|
+
await sleep(5000);
|
|
91
|
+
injectMessage(tabName, `[微信] ${text}`);
|
|
92
|
+
}
|
|
93
|
+
userTabs.set(userId, tabName);
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/handlers/terminal.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { MessageItemType } from './types.js';
|
|
3
|
+
export function userIdToSessionUUID(userId) {
|
|
4
|
+
const hash = createHash('md5').update(`cc2wechat:${userId}`).digest('hex');
|
|
5
|
+
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
|
|
6
|
+
}
|
|
7
|
+
export function extractText(msg) {
|
|
8
|
+
const parts = [];
|
|
9
|
+
for (const item of msg.item_list ?? []) {
|
|
10
|
+
if (item.type === MessageItemType.TEXT && item.text_item?.text) {
|
|
11
|
+
parts.push(item.text_item.text);
|
|
12
|
+
}
|
|
13
|
+
else if (item.type === MessageItemType.IMAGE) {
|
|
14
|
+
parts.push('[Image]');
|
|
15
|
+
}
|
|
16
|
+
else if (item.type === MessageItemType.VOICE && item.voice_item?.text) {
|
|
17
|
+
parts.push(`[Voice] ${item.voice_item.text}`);
|
|
18
|
+
}
|
|
19
|
+
else if (item.type === MessageItemType.FILE && item.file_item?.file_name) {
|
|
20
|
+
parts.push(`[File: ${item.file_item.file_name}]`);
|
|
21
|
+
}
|
|
22
|
+
else if (item.type === MessageItemType.VIDEO) {
|
|
23
|
+
parts.push('[Video]');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return parts.join('\n') || '[Empty message]';
|
|
27
|
+
}
|
|
28
|
+
export function sleep(ms) {
|
|
29
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,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,MAAM,UAAU,WAAW,CAAC,GAAkB;IAC5C,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,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
package/package.json
CHANGED
package/src/auth.ts
CHANGED
|
@@ -155,7 +155,9 @@ function buildQRPage(qrUrl: string): string {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
function openBrowser(url: string): void {
|
|
158
|
-
const cmd = process.platform === 'darwin' ? 'open'
|
|
158
|
+
const cmd = process.platform === 'darwin' ? 'open'
|
|
159
|
+
: process.platform === 'win32' ? 'start'
|
|
160
|
+
: 'xdg-open';
|
|
159
161
|
exec(`${cmd} ${url}`, () => {});
|
|
160
162
|
}
|
|
161
163
|
|
package/src/daemon.ts
CHANGED
|
@@ -1,139 +1,45 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { execSync } from 'node:child_process';
|
|
4
|
-
import { createHash } from 'node:crypto';
|
|
5
3
|
import fs from 'node:fs';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
import { fileURLToPath } from 'node:url';
|
|
8
|
-
|
|
9
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
const replyCli = path.join(__dirname, 'reply-cli.js');
|
|
11
4
|
|
|
12
5
|
import { loginWithQRWeb } from './auth.js';
|
|
13
6
|
import { getActiveAccount, saveAccount, loadSyncBuf, saveSyncBuf } from './store.js';
|
|
14
|
-
import { getUpdates,
|
|
7
|
+
import { getUpdates, sendTyping, getConfig } from './wechat-api.js';
|
|
15
8
|
import type { WeixinMessage } from './types.js';
|
|
16
|
-
import { MessageItemType } from './types.js';
|
|
17
9
|
import type { AccountData } from './store.js';
|
|
10
|
+
import { extractText } from './utils.js';
|
|
11
|
+
import { handleMessageTerminal } from './handlers/terminal.js';
|
|
12
|
+
import { handleMessagePipe } from './handlers/pipe.js';
|
|
18
13
|
|
|
19
14
|
// ---------------------------------------------------------------------------
|
|
20
15
|
// Constants
|
|
21
16
|
// ---------------------------------------------------------------------------
|
|
22
17
|
|
|
18
|
+
const IS_MACOS = process.platform === 'darwin';
|
|
19
|
+
|
|
23
20
|
const SESSION_EXPIRED_ERRCODE = -14;
|
|
24
21
|
const MAX_CONSECUTIVE_FAILURES = 3;
|
|
25
22
|
const BACKOFF_DELAY_MS = 30_000;
|
|
26
23
|
const RETRY_DELAY_MS = 2_000;
|
|
27
24
|
const SESSION_PAUSE_MS = 5 * 60_000;
|
|
28
|
-
const MAX_CHUNK_LENGTH = 3900;
|
|
29
|
-
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
|
-
// Helpers
|
|
32
|
-
// ---------------------------------------------------------------------------
|
|
33
|
-
|
|
34
|
-
function userIdToSessionUUID(userId: string): string {
|
|
35
|
-
const hash = createHash('md5').update(`cc2wechat:${userId}`).digest('hex');
|
|
36
|
-
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function extractText(msg: WeixinMessage): string {
|
|
40
|
-
const parts: string[] = [];
|
|
41
|
-
for (const item of msg.item_list ?? []) {
|
|
42
|
-
if (item.type === MessageItemType.TEXT && item.text_item?.text) {
|
|
43
|
-
parts.push(item.text_item.text);
|
|
44
|
-
} else if (item.type === MessageItemType.IMAGE) {
|
|
45
|
-
parts.push('[Image]');
|
|
46
|
-
} else if (item.type === MessageItemType.VOICE && item.voice_item?.text) {
|
|
47
|
-
parts.push(`[Voice] ${item.voice_item.text}`);
|
|
48
|
-
} else if (item.type === MessageItemType.FILE && item.file_item?.file_name) {
|
|
49
|
-
parts.push(`[File: ${item.file_item.file_name}]`);
|
|
50
|
-
} else if (item.type === MessageItemType.VIDEO) {
|
|
51
|
-
parts.push('[Video]');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return parts.join('\n') || '[Empty message]';
|
|
55
|
-
}
|
|
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();
|
|
77
|
-
}
|
|
78
|
-
|
|
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;
|
|
96
|
-
}
|
|
97
|
-
chunks.push(remaining.slice(0, breakAt));
|
|
98
|
-
remaining = remaining.slice(breakAt).trimStart();
|
|
99
|
-
}
|
|
100
|
-
return chunks;
|
|
101
|
-
}
|
|
102
25
|
|
|
103
26
|
function sleep(ms: number): Promise<void> {
|
|
104
27
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
105
28
|
}
|
|
106
29
|
|
|
107
30
|
// ---------------------------------------------------------------------------
|
|
108
|
-
// Core message handler
|
|
31
|
+
// Core message handler — routes to platform-specific handler
|
|
109
32
|
// ---------------------------------------------------------------------------
|
|
110
33
|
|
|
111
34
|
async function handleMessage(msg: WeixinMessage, account: AccountData): Promise<void> {
|
|
112
35
|
const text = extractText(msg);
|
|
113
36
|
const userId = msg.from_user_id ?? '';
|
|
114
37
|
const contextToken = msg.context_token ?? '';
|
|
115
|
-
const sessionId = userIdToSessionUUID(userId);
|
|
116
38
|
|
|
117
39
|
console.log(`[cc2wechat] <- ${userId.slice(0, 10)}...: ${text.slice(0, 50)}`);
|
|
118
40
|
|
|
119
|
-
|
|
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({
|
|
41
|
+
// Write context for reply-cli
|
|
42
|
+
fs.writeFileSync('/tmp/cc2wechat-context.json', JSON.stringify({
|
|
137
43
|
token: account.token,
|
|
138
44
|
baseUrl: account.baseUrl,
|
|
139
45
|
userId,
|
|
@@ -150,73 +56,10 @@ IMPORTANT: You are running in non-interactive mode. Do NOT use Agent Teams (Team
|
|
|
150
56
|
// non-critical
|
|
151
57
|
}
|
|
152
58
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
}
|
|
176
|
-
} else {
|
|
177
|
-
result = execErr.stdout?.trim() || `Error: ${stderr}`;
|
|
178
|
-
}
|
|
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}`);
|
|
196
|
-
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'}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
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(() => {});
|
|
217
|
-
}
|
|
218
|
-
} catch {
|
|
219
|
-
// non-critical
|
|
59
|
+
if (IS_MACOS) {
|
|
60
|
+
await handleMessageTerminal(msg, account);
|
|
61
|
+
} else {
|
|
62
|
+
await handleMessagePipe(msg, account);
|
|
220
63
|
}
|
|
221
64
|
}
|
|
222
65
|
|
|
@@ -309,7 +152,7 @@ async function pollLoop(account: AccountData): Promise<void> {
|
|
|
309
152
|
// ---------------------------------------------------------------------------
|
|
310
153
|
|
|
311
154
|
async function main(): Promise<void> {
|
|
312
|
-
console.log('\n cc2wechat
|
|
155
|
+
console.log('\n cc2wechat v3 — Interactive Terminal Mode\n');
|
|
313
156
|
|
|
314
157
|
let account = getActiveAccount();
|
|
315
158
|
if (!account) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
import type { WeixinMessage } from '../types.js';
|
|
6
|
+
import type { AccountData } from '../store.js';
|
|
7
|
+
import { extractText, userIdToSessionUUID } from '../utils.js';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const replyCli = path.join(__dirname, '..', 'reply-cli.js');
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Pipe mode message handler (Windows/Linux)
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
export async function handleMessagePipe(msg: WeixinMessage, account: AccountData): Promise<void> {
|
|
17
|
+
const text = extractText(msg);
|
|
18
|
+
const userId = msg.from_user_id ?? '';
|
|
19
|
+
const sessionId = userIdToSessionUUID(userId);
|
|
20
|
+
const cwd = process.cwd();
|
|
21
|
+
|
|
22
|
+
console.log(`[cc2wechat] -> pipe mode: ${text.slice(0, 30)}...`);
|
|
23
|
+
const prompt = JSON.stringify(text);
|
|
24
|
+
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`);
|
|
25
|
+
let result: string;
|
|
26
|
+
try {
|
|
27
|
+
result = execSync(
|
|
28
|
+
`claude -p ${prompt} --resume ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${systemPrompt}`,
|
|
29
|
+
{ encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd },
|
|
30
|
+
).trim();
|
|
31
|
+
} catch (err: unknown) {
|
|
32
|
+
const execErr = err as { stdout?: string; stderr?: string; message?: string };
|
|
33
|
+
if (!execErr.stdout?.trim()) {
|
|
34
|
+
try {
|
|
35
|
+
result = execSync(
|
|
36
|
+
`claude -p ${prompt} --session-id ${sessionId} --output-format text --permission-mode bypassPermissions --system-prompt ${systemPrompt}`,
|
|
37
|
+
{ encoding: 'utf-8', timeout: 120_000, maxBuffer: 10 * 1024 * 1024, cwd },
|
|
38
|
+
).trim();
|
|
39
|
+
} catch (err2: unknown) {
|
|
40
|
+
const execErr2 = err2 as { stdout?: string; message?: string };
|
|
41
|
+
result = execErr2.stdout?.trim() || `Error: ${execErr2.message ?? 'unknown'}`;
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
result = execErr.stdout.trim();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Auto-send text reply
|
|
48
|
+
const { sendMessage: sendMsg } = await import('../wechat-api.js');
|
|
49
|
+
const plain = result.replace(/```[^\n]*\n?([\s\S]*?)```/g, (_, c: string) => c.trim())
|
|
50
|
+
.replace(/\*\*(.+?)\*\*/g, '$1').replace(/^#{1,6}\s+/gm, '').trim();
|
|
51
|
+
const chunks = plain.length <= 3900 ? [plain] : [plain.slice(0, 3900), plain.slice(3900)];
|
|
52
|
+
for (const chunk of chunks) {
|
|
53
|
+
await sendMsg(account.token, userId, chunk, msg.context_token ?? '', account.baseUrl);
|
|
54
|
+
}
|
|
55
|
+
console.log(`[cc2wechat] -> replied (${chunks.length} chunk)`);
|
|
56
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
|
|
4
|
+
import type { WeixinMessage } from '../types.js';
|
|
5
|
+
import type { AccountData } from '../store.js';
|
|
6
|
+
import { getConfig, sendTyping } from '../wechat-api.js';
|
|
7
|
+
import { extractText, userIdToSessionUUID, sleep } from '../utils.js';
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// iTerm Tab Management
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
// Maintain tab state per WeChat user
|
|
14
|
+
const userTabs = new Map<string, string>(); // userId -> tabName
|
|
15
|
+
|
|
16
|
+
// Track tab IDs - persisted to file so it survives daemon restart
|
|
17
|
+
const TAB_REGISTRY_PATH = '/tmp/cc2wechat-tabs.json';
|
|
18
|
+
const tabSessionIds = new Map<string, string>(); // tabName -> iTerm window id
|
|
19
|
+
|
|
20
|
+
// Load persisted tab registry on startup
|
|
21
|
+
try {
|
|
22
|
+
if (fs.existsSync(TAB_REGISTRY_PATH)) {
|
|
23
|
+
const data = JSON.parse(fs.readFileSync(TAB_REGISTRY_PATH, 'utf-8'));
|
|
24
|
+
for (const [k, v] of Object.entries(data)) {
|
|
25
|
+
tabSessionIds.set(k, v as string);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch {}
|
|
29
|
+
|
|
30
|
+
function saveTabRegistry(): void {
|
|
31
|
+
fs.writeFileSync(TAB_REGISTRY_PATH, JSON.stringify(Object.fromEntries(tabSessionIds)));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function tabExists(tabName: string): boolean {
|
|
35
|
+
const windowId = tabSessionIds.get(tabName);
|
|
36
|
+
if (!windowId) return false;
|
|
37
|
+
try {
|
|
38
|
+
const result = execSync(`osascript -e '
|
|
39
|
+
tell application "iTerm2"
|
|
40
|
+
try
|
|
41
|
+
set w to (first window whose id is ${windowId})
|
|
42
|
+
return "found"
|
|
43
|
+
on error
|
|
44
|
+
return "not_found"
|
|
45
|
+
end try
|
|
46
|
+
end tell
|
|
47
|
+
'`, { encoding: 'utf-8' }).trim();
|
|
48
|
+
return result === 'found';
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function createTabAndStartCC(tabName: string, ccSessionId: string, cwd: string): void {
|
|
55
|
+
// Create NEW WINDOW and capture window ID (same approach as cc-mesh)
|
|
56
|
+
const windowId = execSync(`osascript -e '
|
|
57
|
+
tell application "iTerm2"
|
|
58
|
+
set w to (create window with default profile)
|
|
59
|
+
tell current session of w
|
|
60
|
+
write text "cd ${cwd} && claude --resume ${ccSessionId} --dangerously-skip-permissions"
|
|
61
|
+
end tell
|
|
62
|
+
return id of w
|
|
63
|
+
end tell
|
|
64
|
+
'`, { encoding: 'utf-8' }).trim();
|
|
65
|
+
tabSessionIds.set(tabName, windowId);
|
|
66
|
+
saveTabRegistry();
|
|
67
|
+
console.log(`[cc2wechat] window created: ${tabName} -> window id: ${windowId}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function injectMessage(tabName: string, message: string): void {
|
|
71
|
+
const windowId = tabSessionIds.get(tabName);
|
|
72
|
+
if (!windowId) return;
|
|
73
|
+
const escaped = message.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
|
|
74
|
+
execSync(`osascript -e '
|
|
75
|
+
tell application "iTerm2"
|
|
76
|
+
tell current session of (first window whose id is ${windowId})
|
|
77
|
+
write text "${escaped}"
|
|
78
|
+
end tell
|
|
79
|
+
end tell
|
|
80
|
+
'`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// Terminal mode message handler
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
export async function handleMessageTerminal(msg: WeixinMessage, account: AccountData): Promise<void> {
|
|
88
|
+
const text = extractText(msg);
|
|
89
|
+
const userId = msg.from_user_id ?? '';
|
|
90
|
+
const sessionId = userIdToSessionUUID(userId);
|
|
91
|
+
const tabName = `wechat-${userId.slice(0, 8)}`;
|
|
92
|
+
const cwd = process.cwd();
|
|
93
|
+
|
|
94
|
+
if (tabExists(tabName)) {
|
|
95
|
+
console.log(`[cc2wechat] -> inject to existing window: ${tabName}`);
|
|
96
|
+
injectMessage(tabName, `[微信] ${text}`);
|
|
97
|
+
} else {
|
|
98
|
+
console.log(`[cc2wechat] -> creating window: ${tabName} (session: ${sessionId})`);
|
|
99
|
+
createTabAndStartCC(tabName, sessionId, cwd);
|
|
100
|
+
await sleep(5000);
|
|
101
|
+
injectMessage(tabName, `[微信] ${text}`);
|
|
102
|
+
}
|
|
103
|
+
userTabs.set(userId, tabName);
|
|
104
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import type { WeixinMessage } from './types.js';
|
|
3
|
+
import { MessageItemType } from './types.js';
|
|
4
|
+
|
|
5
|
+
export function userIdToSessionUUID(userId: string): string {
|
|
6
|
+
const hash = createHash('md5').update(`cc2wechat:${userId}`).digest('hex');
|
|
7
|
+
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function extractText(msg: WeixinMessage): string {
|
|
11
|
+
const parts: string[] = [];
|
|
12
|
+
for (const item of msg.item_list ?? []) {
|
|
13
|
+
if (item.type === MessageItemType.TEXT && item.text_item?.text) {
|
|
14
|
+
parts.push(item.text_item.text);
|
|
15
|
+
} else if (item.type === MessageItemType.IMAGE) {
|
|
16
|
+
parts.push('[Image]');
|
|
17
|
+
} else if (item.type === MessageItemType.VOICE && item.voice_item?.text) {
|
|
18
|
+
parts.push(`[Voice] ${item.voice_item.text}`);
|
|
19
|
+
} else if (item.type === MessageItemType.FILE && item.file_item?.file_name) {
|
|
20
|
+
parts.push(`[File: ${item.file_item.file_name}]`);
|
|
21
|
+
} else if (item.type === MessageItemType.VIDEO) {
|
|
22
|
+
parts.push('[Video]');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return parts.join('\n') || '[Empty message]';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function sleep(ms: number): Promise<void> {
|
|
29
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
30
|
+
}
|