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 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.exe 路径 */
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(homedir(), '.local', 'bin', 'claude.exe'),
35
- path.join(homedir(), '.local', 'bin', 'claude'),
36
- // npm 全局安装
37
- path.join(homedir(), 'AppData', 'Roaming', 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
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 exePath = findClaudeExe();
48
- if (!exePath) {
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 exePath = findClaudeExe();
132
- if (!exePath) {
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":"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"}
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-wechat",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "WeChat channel for Claude Code via iLink Bot API",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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 p = execSync(process.platform === 'win32' ? 'where claude' : 'which claude', {
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 exePath = findClaude();
71
- if (!exePath) {
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 exePath = findClaude();
176
- if (!exePath) {
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}`);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-channel-patch",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "One-command patch to enable Claude Code Channels (bypasses tengu_harbor feature flag)",
5
5
  "type": "module",
6
6
  "bin": {
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.exe 路径 */
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(homedir(), '.local', 'bin', 'claude.exe'),
38
- path.join(homedir(), '.local', 'bin', 'claude'),
39
- // npm 全局安装
40
- path.join(homedir(), 'AppData', 'Roaming', 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
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 exePath = findClaudeExe();
53
- if (!exePath) {
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 exePath = findClaudeExe();
148
- if (!exePath) {
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}`);