cc-wechat 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/patch.js +94 -9
- package/dist/patch.js.map +1 -1
- package/package.json +1 -1
- package/packages/cc-channel-patch/index.mjs +112 -7
- package/packages/cc-channel-patch/package.json +1 -1
- package/src/patch.ts +95 -10
package/dist/patch.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { homedir } from 'node:os';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
10
11
|
// 补丁定义:[特征字符串, 替换字符串, 说明]
|
|
11
12
|
const PATCHES = [
|
|
12
13
|
// 1. Channels feature flag 云控
|
|
@@ -28,27 +29,110 @@ const PATCHES = [
|
|
|
28
29
|
'UI noAuth display check',
|
|
29
30
|
],
|
|
30
31
|
];
|
|
31
|
-
/** 查找 claude
|
|
32
|
+
/** 查找 claude 可执行文件路径 */
|
|
32
33
|
function findClaudeExe() {
|
|
34
|
+
const home = homedir();
|
|
35
|
+
// 1. which/where(最可靠)
|
|
36
|
+
try {
|
|
37
|
+
const cmd = process.platform === 'win32' ? 'where claude 2>nul' : 'which claude 2>/dev/null';
|
|
38
|
+
const p = execSync(cmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim().split('\n')[0].trim();
|
|
39
|
+
if (p && fs.existsSync(p))
|
|
40
|
+
return p;
|
|
41
|
+
}
|
|
42
|
+
catch { /* ignore */ }
|
|
43
|
+
// 2. 常见安装路径
|
|
33
44
|
const candidates = [
|
|
34
|
-
path.join(
|
|
35
|
-
path.join(
|
|
36
|
-
|
|
37
|
-
path.join(
|
|
45
|
+
path.join(home, '.local', 'bin', 'claude.exe'),
|
|
46
|
+
path.join(home, '.local', 'bin', 'claude'),
|
|
47
|
+
path.join(home, 'AppData', 'Roaming', 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
|
|
48
|
+
path.join(home, 'AppData', 'Roaming', 'npm', 'claude.cmd'),
|
|
49
|
+
path.join(home, 'scoop', 'shims', 'claude.exe'),
|
|
50
|
+
path.join('C:', 'ProgramData', 'chocolatey', 'bin', 'claude.exe'),
|
|
51
|
+
path.join('C:', 'Program Files', 'Claude Code', 'claude.exe'),
|
|
52
|
+
path.join('C:', 'Program Files (x86)', 'Claude Code', 'claude.exe'),
|
|
53
|
+
path.join(home, 'AppData', 'Local', 'Programs', 'claude-code', 'claude.exe'),
|
|
54
|
+
path.join(home, 'AppData', 'Local', 'claude-code', 'claude.exe'),
|
|
55
|
+
path.join(home, 'AppData', 'Local', 'AnthropicClaude', 'claude.exe'),
|
|
56
|
+
'/usr/local/bin/claude',
|
|
57
|
+
'/opt/homebrew/bin/claude',
|
|
58
|
+
'/usr/bin/claude',
|
|
59
|
+
'/snap/bin/claude',
|
|
38
60
|
];
|
|
39
61
|
for (const p of candidates) {
|
|
40
62
|
if (fs.existsSync(p))
|
|
41
63
|
return p;
|
|
42
64
|
}
|
|
65
|
+
// 3. npm global prefix 动态查找
|
|
66
|
+
try {
|
|
67
|
+
const prefix = execSync('npm config get prefix', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
68
|
+
if (prefix) {
|
|
69
|
+
for (const c of [path.join(prefix, 'claude.cmd'), path.join(prefix, 'claude'), path.join(prefix, 'bin', 'claude')]) {
|
|
70
|
+
if (fs.existsSync(c))
|
|
71
|
+
return c;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch { /* ignore */ }
|
|
76
|
+
// 4. PATH 逐目录搜索(兜底)
|
|
77
|
+
const pathDirs = (process.env.PATH || '').split(process.platform === 'win32' ? ';' : ':');
|
|
78
|
+
const exeNames = process.platform === 'win32' ? ['claude.exe', 'claude.cmd'] : ['claude'];
|
|
79
|
+
for (const dir of pathDirs) {
|
|
80
|
+
for (const name of exeNames) {
|
|
81
|
+
const p = path.join(dir, name);
|
|
82
|
+
if (fs.existsSync(p))
|
|
83
|
+
return p;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
43
86
|
return null;
|
|
44
87
|
}
|
|
88
|
+
/** 从 wrapper/cmd 解析到真正包含代码的文件(exe 或 cli.js) */
|
|
89
|
+
function resolvePatchTarget(claudePath) {
|
|
90
|
+
const ext = path.extname(claudePath).toLowerCase();
|
|
91
|
+
const dir = path.dirname(claudePath);
|
|
92
|
+
// exe 或大文件(>1MB)→ 直接 patch
|
|
93
|
+
if (ext === '.exe')
|
|
94
|
+
return claudePath;
|
|
95
|
+
const stat = fs.statSync(claudePath);
|
|
96
|
+
if (stat.size > 1_000_000)
|
|
97
|
+
return claudePath;
|
|
98
|
+
// .cmd / 小文件 → npm wrapper,查找 cli.js
|
|
99
|
+
const cliJs = path.join(dir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
|
|
100
|
+
if (fs.existsSync(cliJs))
|
|
101
|
+
return cliJs;
|
|
102
|
+
// 读 .cmd 内容提取路径
|
|
103
|
+
if (ext === '.cmd') {
|
|
104
|
+
try {
|
|
105
|
+
const content = fs.readFileSync(claudePath, 'utf-8');
|
|
106
|
+
const match = content.match(/node_modules[\\/]@anthropic-ai[\\/]claude-code[\\/]cli\.js/);
|
|
107
|
+
if (match) {
|
|
108
|
+
const resolved = path.join(dir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
|
|
109
|
+
if (fs.existsSync(resolved))
|
|
110
|
+
return resolved;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch { /* ignore */ }
|
|
114
|
+
}
|
|
115
|
+
// symlink → resolve
|
|
116
|
+
try {
|
|
117
|
+
const realPath = fs.realpathSync(claudePath);
|
|
118
|
+
if (realPath !== claudePath)
|
|
119
|
+
return resolvePatchTarget(realPath);
|
|
120
|
+
}
|
|
121
|
+
catch { /* ignore */ }
|
|
122
|
+
return claudePath;
|
|
123
|
+
}
|
|
45
124
|
function patch() {
|
|
46
125
|
console.log('\n cc-wechat patch — Claude Code Channels 补丁\n');
|
|
47
|
-
const
|
|
48
|
-
if (!
|
|
126
|
+
const claudePath = findClaudeExe();
|
|
127
|
+
if (!claudePath) {
|
|
49
128
|
console.error(' 找不到 Claude Code。请确认已安装。');
|
|
50
129
|
process.exit(1);
|
|
51
130
|
}
|
|
131
|
+
const exePath = resolvePatchTarget(claudePath);
|
|
132
|
+
if (exePath !== claudePath) {
|
|
133
|
+
console.log(` 查找: ${claudePath}`);
|
|
134
|
+
console.log(` 解析: ${exePath}`);
|
|
135
|
+
}
|
|
52
136
|
console.log(` 目标: ${exePath}`);
|
|
53
137
|
// 读取二进制
|
|
54
138
|
const buf = fs.readFileSync(exePath);
|
|
@@ -128,11 +212,12 @@ function patch() {
|
|
|
128
212
|
}
|
|
129
213
|
function unpatch() {
|
|
130
214
|
console.log('\n cc-wechat unpatch — 恢复原始 Claude Code\n');
|
|
131
|
-
const
|
|
132
|
-
if (!
|
|
215
|
+
const claudePath = findClaudeExe();
|
|
216
|
+
if (!claudePath) {
|
|
133
217
|
console.error(' 找不到 Claude Code。');
|
|
134
218
|
process.exit(1);
|
|
135
219
|
}
|
|
220
|
+
const exePath = resolvePatchTarget(claudePath);
|
|
136
221
|
const backupPath = exePath + '.bak';
|
|
137
222
|
if (!fs.existsSync(backupPath)) {
|
|
138
223
|
console.error(` 未找到备份文件 ${backupPath}`);
|
package/dist/patch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,0BAA0B;AAC1B,MAAM,OAAO,GAAoC;IAC/C,8BAA8B;IAC9B;QACE,8CAA8C;QAC9C,8CAA8C;QAC9C,sCAAsC;KACvC;IACD,sBAAsB;IACtB;QACE,wBAAwB;QACxB,wBAAwB;QACxB,gCAAgC;KACjC;IACD,oBAAoB;IACpB;QACE,2BAA2B;QAC3B,2BAA2B;QAC3B,yBAAyB;KAC1B;CACF,CAAC;AAEF,wBAAwB;AACxB,SAAS,aAAa;IACpB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,sBAAsB;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,0BAA0B,CAAC;QAC7F,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7G,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAExB,YAAY;IACZ,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,CAAC;QACtG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,CAAC;QAC1D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,CAAC;QACjE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,qBAAqB,EAAE,aAAa,EAAE,YAAY,CAAC;QACnE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,CAAC;QAC5E,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,CAAC;QAChE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE,YAAY,CAAC;QACpE,uBAAuB;QACvB,0BAA0B;QAC1B,iBAAiB;QACjB,kBAAkB;KACnB,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,4BAA4B;IAC5B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,uBAAuB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAChH,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;gBACnH,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;oBAAE,OAAO,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAExB,oBAAoB;IACpB,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC1F,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1F,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC/B,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+CAA+C;AAC/C,SAAS,kBAAkB,CAAC,UAAkB;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAErC,2BAA2B;IAC3B,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC;IACtC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACrC,IAAI,IAAI,CAAC,IAAI,GAAG,SAAS;QAAE,OAAO,UAAU,CAAC;IAE7C,qCAAqC;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IACvF,IAAI,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,gBAAgB;IAChB,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC1F,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;gBAC1F,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;oBAAE,OAAO,QAAQ,CAAC;YAC/C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,oBAAoB;IACpB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,QAAQ,KAAK,UAAU;YAAE,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAExB,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,KAAK;IACZ,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAE/D,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;IAEhC,QAAQ;IACR,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,cAAc,GAAG,CAAC,CAAC;IAEvB,KAAK,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACpD,IAAI,QAAQ,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,EAAE,CAAC;YAC3C,OAAO,CAAC,KAAK,CAAC,UAAU,IAAI,YAAY,QAAQ,CAAC,MAAM,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;YACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE1C,WAAW;QACX,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,YAAY,GAAG,CAAC,CAAC;QAErB,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACtC,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,MAAM;YACtB,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACxB,KAAK,EAAE,CAAC;YACR,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;QAChB,CAAC;QAED,iBAAiB;QACjB,GAAG,GAAG,CAAC,CAAC;QACR,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,MAAM;YACtB,YAAY,EAAE,CAAC;YACf,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;QAChB,CAAC;QAED,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,KAAK,KAAK,OAAO,CAAC,CAAC;YAChD,YAAY,IAAI,KAAK,CAAC;QACxB,CAAC;aAAM,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,WAAW,YAAY,KAAK,CAAC,CAAC;YAC3D,cAAc,IAAI,YAAY,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,wBAAwB,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,IAAI,YAAY,KAAK,CAAC,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IAED,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,KAAK;IACL,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,mBAAmB,UAAU,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,iBAAiB;IACjB,MAAM,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;IACrC,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAE/B,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAE9C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,IAAI,aAAa,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,YAAY,IAAI,WAAW,CAAC,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,MAAM,OAAO,OAAO,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,MAAM,OAAO,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,aAAa,UAAU,SAAS,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,OAAO;IACd,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAE/C,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,aAAa,UAAU,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;IACrC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAE9C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,IAAI,iBAAiB,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,YAAY,IAAI,WAAW,CAAC,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,MAAM,OAAO,WAAW,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,MAAM,OAAO,KAAK,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED,KAAK;AACL,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;IAC3C,OAAO,EAAE,CAAC;AACZ,CAAC;KAAM,CAAC;IACN,KAAK,EAAE,CAAC;AACV,CAAC"}
|
package/package.json
CHANGED
|
@@ -39,40 +39,143 @@ const PATCHES = [
|
|
|
39
39
|
// ─── 查找 claude 可执行文件 ──────────────────────────────
|
|
40
40
|
|
|
41
41
|
function findClaude() {
|
|
42
|
-
// 1. which/where
|
|
42
|
+
// 1. which/where 查找(最可靠,覆盖所有自定义安装路径)
|
|
43
43
|
try {
|
|
44
|
-
const
|
|
44
|
+
const cmd = process.platform === 'win32' ? 'where claude 2>nul' : 'which claude 2>/dev/null';
|
|
45
|
+
const p = execSync(cmd, {
|
|
45
46
|
encoding: 'utf-8',
|
|
46
47
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
47
48
|
}).trim().split('\n')[0].trim();
|
|
48
49
|
if (p && fs.existsSync(p)) return p;
|
|
49
50
|
} catch { /* ignore */ }
|
|
50
51
|
|
|
51
|
-
// 2.
|
|
52
|
+
// 2. 常见安装路径(覆盖各种安装方式)
|
|
52
53
|
const home = homedir();
|
|
53
54
|
const candidates = [
|
|
55
|
+
// Claude Code native installer(默认)
|
|
54
56
|
path.join(home, '.local', 'bin', 'claude.exe'),
|
|
55
57
|
path.join(home, '.local', 'bin', 'claude'),
|
|
58
|
+
// npm 全局安装
|
|
56
59
|
path.join(home, 'AppData', 'Roaming', 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
|
|
60
|
+
path.join(home, 'AppData', 'Roaming', 'npm', 'claude.cmd'),
|
|
61
|
+
// scoop / chocolatey / winget 等 Windows 包管理器
|
|
62
|
+
path.join(home, 'scoop', 'shims', 'claude.exe'),
|
|
63
|
+
path.join('C:', 'ProgramData', 'chocolatey', 'bin', 'claude.exe'),
|
|
64
|
+
// Program Files
|
|
65
|
+
path.join('C:', 'Program Files', 'Claude Code', 'claude.exe'),
|
|
66
|
+
path.join('C:', 'Program Files (x86)', 'Claude Code', 'claude.exe'),
|
|
67
|
+
// AppData 常见路径
|
|
68
|
+
path.join(home, 'AppData', 'Local', 'Programs', 'claude-code', 'claude.exe'),
|
|
69
|
+
path.join(home, 'AppData', 'Local', 'claude-code', 'claude.exe'),
|
|
70
|
+
path.join(home, 'AppData', 'Local', 'AnthropicClaude', 'claude.exe'),
|
|
71
|
+
// macOS
|
|
57
72
|
'/usr/local/bin/claude',
|
|
73
|
+
'/opt/homebrew/bin/claude',
|
|
74
|
+
path.join(home, '.nvm', 'versions', 'node'), // 标记,下面特殊处理
|
|
75
|
+
// Linux
|
|
76
|
+
'/usr/bin/claude',
|
|
77
|
+
'/snap/bin/claude',
|
|
58
78
|
];
|
|
79
|
+
|
|
59
80
|
for (const c of candidates) {
|
|
60
81
|
if (fs.existsSync(c)) return c;
|
|
61
82
|
}
|
|
83
|
+
|
|
84
|
+
// 3. npm global prefix 动态查找(覆盖自定义 npm prefix)
|
|
85
|
+
try {
|
|
86
|
+
const prefix = execSync('npm config get prefix', {
|
|
87
|
+
encoding: 'utf-8',
|
|
88
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
89
|
+
}).trim();
|
|
90
|
+
if (prefix) {
|
|
91
|
+
const npmCandidates = [
|
|
92
|
+
path.join(prefix, 'claude.cmd'),
|
|
93
|
+
path.join(prefix, 'claude'),
|
|
94
|
+
path.join(prefix, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
|
|
95
|
+
path.join(prefix, 'bin', 'claude'),
|
|
96
|
+
];
|
|
97
|
+
for (const c of npmCandidates) {
|
|
98
|
+
if (fs.existsSync(c)) return c;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
} catch { /* ignore */ }
|
|
102
|
+
|
|
103
|
+
// 4. PATH 环境变量逐目录搜索(兜底)
|
|
104
|
+
const pathDirs = (process.env.PATH || '').split(process.platform === 'win32' ? ';' : ':');
|
|
105
|
+
const exeNames = process.platform === 'win32' ? ['claude.exe', 'claude.cmd'] : ['claude'];
|
|
106
|
+
for (const dir of pathDirs) {
|
|
107
|
+
for (const name of exeNames) {
|
|
108
|
+
const p = path.join(dir, name);
|
|
109
|
+
if (fs.existsSync(p)) return p;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
62
113
|
return null;
|
|
63
114
|
}
|
|
64
115
|
|
|
116
|
+
// ─── 解析到真正的可 patch 文件 ─────────────────────────────
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* findClaude() 可能返回 .cmd wrapper 或符号链接。
|
|
120
|
+
* 此函数解析到真正包含代码的文件(exe 二进制或 cli.js)。
|
|
121
|
+
* 对于 npm 全局安装的 CC,.cmd 旁边有 node_modules/@anthropic-ai/claude-code/cli.js
|
|
122
|
+
*/
|
|
123
|
+
function resolvePatchTarget(claudePath) {
|
|
124
|
+
const ext = path.extname(claudePath).toLowerCase();
|
|
125
|
+
const dir = path.dirname(claudePath);
|
|
126
|
+
|
|
127
|
+
// 如果已经是 .exe 或大文件(>1MB),直接 patch
|
|
128
|
+
if (ext === '.exe') return claudePath;
|
|
129
|
+
const stat = fs.statSync(claudePath);
|
|
130
|
+
if (stat.size > 1_000_000) return claudePath;
|
|
131
|
+
|
|
132
|
+
// .cmd / 小文件 → 是 npm wrapper,查找真正的 cli.js
|
|
133
|
+
// 策略 1:同目录下 node_modules/@anthropic-ai/claude-code/cli.js
|
|
134
|
+
const cliJs = path.join(dir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
|
|
135
|
+
if (fs.existsSync(cliJs)) return cliJs;
|
|
136
|
+
|
|
137
|
+
// 策略 2:读取 .cmd 内容,提取实际路径
|
|
138
|
+
if (ext === '.cmd') {
|
|
139
|
+
try {
|
|
140
|
+
const content = fs.readFileSync(claudePath, 'utf-8');
|
|
141
|
+
// npm .cmd 格式:@IF EXIST "%~dp0\node.exe" (...) ELSE (... "%~dp0\node_modules\@anthropic-ai\claude-code\cli.js" ...)
|
|
142
|
+
const match = content.match(/node_modules[\\/]@anthropic-ai[\\/]claude-code[\\/]cli\.js/);
|
|
143
|
+
if (match) {
|
|
144
|
+
const resolved = path.join(dir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
|
|
145
|
+
if (fs.existsSync(resolved)) return resolved;
|
|
146
|
+
}
|
|
147
|
+
} catch { /* ignore */ }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 策略 3:如果是 symlink,resolve 到真实路径
|
|
151
|
+
try {
|
|
152
|
+
const realPath = fs.realpathSync(claudePath);
|
|
153
|
+
if (realPath !== claudePath) {
|
|
154
|
+
return resolvePatchTarget(realPath);
|
|
155
|
+
}
|
|
156
|
+
} catch { /* ignore */ }
|
|
157
|
+
|
|
158
|
+
// 兜底:原路径
|
|
159
|
+
return claudePath;
|
|
160
|
+
}
|
|
161
|
+
|
|
65
162
|
// ─── patch ──────────────────────────────────────────────
|
|
66
163
|
|
|
67
164
|
function patch() {
|
|
68
165
|
console.log('\n cc-channel-patch — 启用 Claude Code Channels\n');
|
|
69
166
|
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
167
|
+
const claudePath = findClaude();
|
|
168
|
+
if (!claudePath) {
|
|
72
169
|
console.error(' 找不到 Claude Code 可执行文件。');
|
|
73
170
|
console.error(' 请确认已安装 Claude Code 并在 PATH 中。\n');
|
|
74
171
|
process.exit(1);
|
|
75
172
|
}
|
|
173
|
+
|
|
174
|
+
const exePath = resolvePatchTarget(claudePath);
|
|
175
|
+
console.log(` 查找: ${claudePath}`);
|
|
176
|
+
if (exePath !== claudePath) {
|
|
177
|
+
console.log(` 解析: ${exePath}`);
|
|
178
|
+
}
|
|
76
179
|
console.log(` 目标: ${exePath}`);
|
|
77
180
|
|
|
78
181
|
const buf = fs.readFileSync(exePath);
|
|
@@ -172,12 +275,14 @@ function patch() {
|
|
|
172
275
|
function unpatch() {
|
|
173
276
|
console.log('\n cc-channel-patch unpatch — 恢复原始 Claude Code\n');
|
|
174
277
|
|
|
175
|
-
const
|
|
176
|
-
if (!
|
|
278
|
+
const claudePath = findClaude();
|
|
279
|
+
if (!claudePath) {
|
|
177
280
|
console.error(' 找不到 Claude Code。\n');
|
|
178
281
|
process.exit(1);
|
|
179
282
|
}
|
|
180
283
|
|
|
284
|
+
const exePath = resolvePatchTarget(claudePath);
|
|
285
|
+
|
|
181
286
|
const backupPath = exePath + '.bak';
|
|
182
287
|
if (!fs.existsSync(backupPath)) {
|
|
183
288
|
console.error(` 未找到备份文件: ${backupPath}`);
|
package/src/patch.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import fs from 'node:fs';
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { homedir } from 'node:os';
|
|
11
|
+
import { execSync } from 'node:child_process';
|
|
11
12
|
|
|
12
13
|
// 补丁定义:[特征字符串, 替换字符串, 说明]
|
|
13
14
|
const PATCHES: Array<[string, string, string]> = [
|
|
@@ -31,29 +32,111 @@ const PATCHES: Array<[string, string, string]> = [
|
|
|
31
32
|
],
|
|
32
33
|
];
|
|
33
34
|
|
|
34
|
-
/** 查找 claude
|
|
35
|
+
/** 查找 claude 可执行文件路径 */
|
|
35
36
|
function findClaudeExe(): string | null {
|
|
37
|
+
const home = homedir();
|
|
38
|
+
|
|
39
|
+
// 1. which/where(最可靠)
|
|
40
|
+
try {
|
|
41
|
+
const cmd = process.platform === 'win32' ? 'where claude 2>nul' : 'which claude 2>/dev/null';
|
|
42
|
+
const p = execSync(cmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim().split('\n')[0].trim();
|
|
43
|
+
if (p && fs.existsSync(p)) return p;
|
|
44
|
+
} catch { /* ignore */ }
|
|
45
|
+
|
|
46
|
+
// 2. 常见安装路径
|
|
36
47
|
const candidates = [
|
|
37
|
-
path.join(
|
|
38
|
-
path.join(
|
|
39
|
-
|
|
40
|
-
path.join(
|
|
48
|
+
path.join(home, '.local', 'bin', 'claude.exe'),
|
|
49
|
+
path.join(home, '.local', 'bin', 'claude'),
|
|
50
|
+
path.join(home, 'AppData', 'Roaming', 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
|
|
51
|
+
path.join(home, 'AppData', 'Roaming', 'npm', 'claude.cmd'),
|
|
52
|
+
path.join(home, 'scoop', 'shims', 'claude.exe'),
|
|
53
|
+
path.join('C:', 'ProgramData', 'chocolatey', 'bin', 'claude.exe'),
|
|
54
|
+
path.join('C:', 'Program Files', 'Claude Code', 'claude.exe'),
|
|
55
|
+
path.join('C:', 'Program Files (x86)', 'Claude Code', 'claude.exe'),
|
|
56
|
+
path.join(home, 'AppData', 'Local', 'Programs', 'claude-code', 'claude.exe'),
|
|
57
|
+
path.join(home, 'AppData', 'Local', 'claude-code', 'claude.exe'),
|
|
58
|
+
path.join(home, 'AppData', 'Local', 'AnthropicClaude', 'claude.exe'),
|
|
59
|
+
'/usr/local/bin/claude',
|
|
60
|
+
'/opt/homebrew/bin/claude',
|
|
61
|
+
'/usr/bin/claude',
|
|
62
|
+
'/snap/bin/claude',
|
|
41
63
|
];
|
|
42
|
-
|
|
43
64
|
for (const p of candidates) {
|
|
44
65
|
if (fs.existsSync(p)) return p;
|
|
45
66
|
}
|
|
67
|
+
|
|
68
|
+
// 3. npm global prefix 动态查找
|
|
69
|
+
try {
|
|
70
|
+
const prefix = execSync('npm config get prefix', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
71
|
+
if (prefix) {
|
|
72
|
+
for (const c of [path.join(prefix, 'claude.cmd'), path.join(prefix, 'claude'), path.join(prefix, 'bin', 'claude')]) {
|
|
73
|
+
if (fs.existsSync(c)) return c;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
} catch { /* ignore */ }
|
|
77
|
+
|
|
78
|
+
// 4. PATH 逐目录搜索(兜底)
|
|
79
|
+
const pathDirs = (process.env.PATH || '').split(process.platform === 'win32' ? ';' : ':');
|
|
80
|
+
const exeNames = process.platform === 'win32' ? ['claude.exe', 'claude.cmd'] : ['claude'];
|
|
81
|
+
for (const dir of pathDirs) {
|
|
82
|
+
for (const name of exeNames) {
|
|
83
|
+
const p = path.join(dir, name);
|
|
84
|
+
if (fs.existsSync(p)) return p;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
46
88
|
return null;
|
|
47
89
|
}
|
|
48
90
|
|
|
91
|
+
/** 从 wrapper/cmd 解析到真正包含代码的文件(exe 或 cli.js) */
|
|
92
|
+
function resolvePatchTarget(claudePath: string): string {
|
|
93
|
+
const ext = path.extname(claudePath).toLowerCase();
|
|
94
|
+
const dir = path.dirname(claudePath);
|
|
95
|
+
|
|
96
|
+
// exe 或大文件(>1MB)→ 直接 patch
|
|
97
|
+
if (ext === '.exe') return claudePath;
|
|
98
|
+
const stat = fs.statSync(claudePath);
|
|
99
|
+
if (stat.size > 1_000_000) return claudePath;
|
|
100
|
+
|
|
101
|
+
// .cmd / 小文件 → npm wrapper,查找 cli.js
|
|
102
|
+
const cliJs = path.join(dir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
|
|
103
|
+
if (fs.existsSync(cliJs)) return cliJs;
|
|
104
|
+
|
|
105
|
+
// 读 .cmd 内容提取路径
|
|
106
|
+
if (ext === '.cmd') {
|
|
107
|
+
try {
|
|
108
|
+
const content = fs.readFileSync(claudePath, 'utf-8');
|
|
109
|
+
const match = content.match(/node_modules[\\/]@anthropic-ai[\\/]claude-code[\\/]cli\.js/);
|
|
110
|
+
if (match) {
|
|
111
|
+
const resolved = path.join(dir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
|
|
112
|
+
if (fs.existsSync(resolved)) return resolved;
|
|
113
|
+
}
|
|
114
|
+
} catch { /* ignore */ }
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// symlink → resolve
|
|
118
|
+
try {
|
|
119
|
+
const realPath = fs.realpathSync(claudePath);
|
|
120
|
+
if (realPath !== claudePath) return resolvePatchTarget(realPath);
|
|
121
|
+
} catch { /* ignore */ }
|
|
122
|
+
|
|
123
|
+
return claudePath;
|
|
124
|
+
}
|
|
125
|
+
|
|
49
126
|
function patch(): void {
|
|
50
127
|
console.log('\n cc-wechat patch — Claude Code Channels 补丁\n');
|
|
51
128
|
|
|
52
|
-
const
|
|
53
|
-
if (!
|
|
129
|
+
const claudePath = findClaudeExe();
|
|
130
|
+
if (!claudePath) {
|
|
54
131
|
console.error(' 找不到 Claude Code。请确认已安装。');
|
|
55
132
|
process.exit(1);
|
|
56
133
|
}
|
|
134
|
+
|
|
135
|
+
const exePath = resolvePatchTarget(claudePath);
|
|
136
|
+
if (exePath !== claudePath) {
|
|
137
|
+
console.log(` 查找: ${claudePath}`);
|
|
138
|
+
console.log(` 解析: ${exePath}`);
|
|
139
|
+
}
|
|
57
140
|
console.log(` 目标: ${exePath}`);
|
|
58
141
|
|
|
59
142
|
// 读取二进制
|
|
@@ -144,12 +227,14 @@ function patch(): void {
|
|
|
144
227
|
function unpatch(): void {
|
|
145
228
|
console.log('\n cc-wechat unpatch — 恢复原始 Claude Code\n');
|
|
146
229
|
|
|
147
|
-
const
|
|
148
|
-
if (!
|
|
230
|
+
const claudePath = findClaudeExe();
|
|
231
|
+
if (!claudePath) {
|
|
149
232
|
console.error(' 找不到 Claude Code。');
|
|
150
233
|
process.exit(1);
|
|
151
234
|
}
|
|
152
235
|
|
|
236
|
+
const exePath = resolvePatchTarget(claudePath);
|
|
237
|
+
|
|
153
238
|
const backupPath = exePath + '.bak';
|
|
154
239
|
if (!fs.existsSync(backupPath)) {
|
|
155
240
|
console.error(` 未找到备份文件 ${backupPath}`);
|