@88code/byebyecode 1.1.11 → 1.1.13

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/bin/byebyecode.js CHANGED
@@ -1,57 +1,284 @@
1
1
  #!/usr/bin/env node
2
- const { spawnSync } = require('child_process');
2
+ const { spawnSync, execSync } = require('child_process');
3
3
  const path = require('path');
4
4
  const fs = require('fs');
5
5
  const os = require('os');
6
6
 
7
- // 1. Priority: Use ~/.claude/ccline/byebyecode if exists
8
- const claudePath = path.join(
9
- os.homedir(),
10
- '.claude',
11
- 'ccline',
12
- process.platform === 'win32' ? 'byebyecode.exe' : 'byebyecode'
13
- );
14
-
15
- if (fs.existsSync(claudePath)) {
16
- const result = spawnSync(claudePath, process.argv.slice(2), {
17
- stdio: 'inherit',
18
- shell: false
19
- });
20
- process.exit(result.status || 0);
7
+ // ==================== 辅助函数 ====================
8
+
9
+ /**
10
+ * 检查指定 PID 的进程是否仍在运行
11
+ */
12
+ function isProcessRunning(pid) {
13
+ try {
14
+ const platform = process.platform;
15
+
16
+ if (platform === 'win32') {
17
+ const output = execSync(`tasklist /FI "PID eq ${pid}"`, {
18
+ encoding: 'utf8',
19
+ stdio: ['ignore', 'pipe', 'ignore']
20
+ });
21
+ return output.includes(pid.toString());
22
+ } else {
23
+ // Unix-like systems
24
+ const output = execSync(`ps -p ${pid}`, {
25
+ encoding: 'utf8',
26
+ stdio: ['ignore', 'pipe', 'ignore']
27
+ });
28
+ return output.includes(pid.toString());
29
+ }
30
+ } catch (e) {
31
+ return false; // 进程不存在
32
+ }
33
+ }
34
+
35
+ /**
36
+ * 清理过期或无效的锁文件
37
+ */
38
+ function cleanupStaleLock(lockFile) {
39
+ if (!fs.existsSync(lockFile)) return;
40
+
41
+ try {
42
+ const lockData = JSON.parse(fs.readFileSync(lockFile, 'utf8'));
43
+ const age = Date.now() - lockData.timestamp;
44
+ const MAX_LOCK_AGE = 5 * 60 * 1000; // 5 分钟
45
+
46
+ // 如果锁文件超过 5 分钟,或 PID 已不存在,清理锁
47
+ if (age > MAX_LOCK_AGE || !isProcessRunning(lockData.pid)) {
48
+ fs.unlinkSync(lockFile);
49
+ }
50
+ } catch (e) {
51
+ // 锁文件损坏,直接删除
52
+ try {
53
+ fs.unlinkSync(lockFile);
54
+ } catch (err) {
55
+ // Ignore
56
+ }
57
+ }
21
58
  }
22
59
 
23
- // 2. Fallback: Use npm package binary
60
+ // ==================== 启动时检查待更新 ====================
61
+
62
+ /**
63
+ * 在执行二进制前,检查是否有待安装的更新
64
+ * 如果有,执行更新并清理标记文件
65
+ */
66
+ function checkAndInstallPendingUpdate() {
67
+ const configDir = path.join(os.homedir(), '.claude', 'byebyecode');
68
+ const pendingFile = path.join(configDir, '.update_pending');
69
+ const lockFile = path.join(configDir, '.update_lock');
70
+
71
+ // 如果没有待更新文件,直接返回
72
+ if (!fs.existsSync(pendingFile)) {
73
+ return;
74
+ }
75
+
76
+ // 清理过期锁文件
77
+ cleanupStaleLock(lockFile);
78
+
79
+ // 检查是否有其他进程正在更新
80
+ if (fs.existsSync(lockFile)) {
81
+ try {
82
+ const lockData = JSON.parse(fs.readFileSync(lockFile, 'utf8'));
83
+
84
+ // 如果锁文件对应的进程仍在运行,跳过更新
85
+ if (isProcessRunning(lockData.pid)) {
86
+ return;
87
+ }
88
+ } catch (e) {
89
+ // 锁文件损坏,继续尝试更新
90
+ }
91
+ }
92
+
93
+ // 创建锁文件
94
+ try {
95
+ fs.mkdirSync(configDir, { recursive: true });
96
+ fs.writeFileSync(lockFile, JSON.stringify({
97
+ pid: process.pid,
98
+ timestamp: Date.now()
99
+ }));
100
+ } catch (e) {
101
+ // 无法创建锁文件,跳过更新
102
+ return;
103
+ }
104
+
105
+ // 读取待更新信息
106
+ let pendingUpdate;
107
+ try {
108
+ pendingUpdate = JSON.parse(fs.readFileSync(pendingFile, 'utf8'));
109
+ } catch (e) {
110
+ // 文件损坏,清理后退出
111
+ try {
112
+ fs.unlinkSync(pendingFile);
113
+ fs.unlinkSync(lockFile);
114
+ } catch (err) {
115
+ // Ignore
116
+ }
117
+ return;
118
+ }
119
+
120
+ // 执行更新
121
+ console.error('');
122
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
123
+ console.error(`🔄 正在更新 byebyecode 到 v${pendingUpdate.latestVersion}...`);
124
+ console.error(' (这可能需要几秒钟)');
125
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
126
+ console.error('');
127
+
128
+ try {
129
+ execSync('npm install -g @88code/byebyecode@latest', {
130
+ stdio: 'inherit',
131
+ timeout: 120000
132
+ });
133
+
134
+ console.error('');
135
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
136
+ console.error(`✓ 更新成功!已安装 v${pendingUpdate.latestVersion}`);
137
+ console.error(' 正在继续执行...');
138
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
139
+ console.error('');
140
+
141
+ // 清理文件
142
+ try {
143
+ fs.unlinkSync(pendingFile);
144
+
145
+ const noticeFile = path.join(configDir, '.update_notice');
146
+ if (fs.existsSync(noticeFile)) {
147
+ fs.unlinkSync(noticeFile);
148
+ }
149
+ } catch (e) {
150
+ // Ignore cleanup errors
151
+ }
152
+ } catch (error) {
153
+ console.error('');
154
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
155
+ console.error('⚠ 自动更新失败');
156
+ console.error(' 请稍后重试,或手动运行:');
157
+ console.error(' npm update -g @88code/byebyecode');
158
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
159
+ console.error('');
160
+ // 不删除 pending 文件,下次启动时继续尝试
161
+ } finally {
162
+ // 清理锁文件
163
+ try {
164
+ fs.unlinkSync(lockFile);
165
+ } catch (e) {
166
+ // Ignore
167
+ }
168
+ }
169
+ }
170
+
171
+ // ==================== 后台版本检查 ====================
172
+
173
+ /**
174
+ * 检查是否有新版本可用
175
+ * 如果有,创建 .update_pending 文件,不立即更新
176
+ */
177
+ function checkVersionAndNotify() {
178
+ const configDir = path.join(os.homedir(), '.claude', 'byebyecode');
179
+ const versionCheckFile = path.join(configDir, '.last_version_check');
180
+ const pendingFile = path.join(configDir, '.update_pending');
181
+ const noticeFile = path.join(configDir, '.update_notice');
182
+
183
+ try {
184
+ // 频率限制:每小时最多检查一次
185
+ if (fs.existsSync(versionCheckFile)) {
186
+ const lastCheck = parseInt(fs.readFileSync(versionCheckFile, 'utf8'));
187
+ const hoursSinceCheck = (Date.now() - lastCheck) / (1000 * 60 * 60);
188
+
189
+ if (hoursSinceCheck < 1) {
190
+ // 如果已有待更新提示,显示它
191
+ if (fs.existsSync(noticeFile)) {
192
+ const notice = fs.readFileSync(noticeFile, 'utf8');
193
+ console.error(notice);
194
+ }
195
+ return;
196
+ }
197
+ }
198
+
199
+ // 记录检查时间
200
+ fs.mkdirSync(configDir, { recursive: true });
201
+ fs.writeFileSync(versionCheckFile, Date.now().toString());
202
+
203
+ // 获取当前版本
204
+ const packageJsonPath = path.join(__dirname, '..', 'package.json');
205
+ const currentVersion = require(packageJsonPath).version;
206
+
207
+ // 从 npm registry 获取最新版本
208
+ const latestVersion = execSync('npm view @88code/byebyecode version', {
209
+ encoding: 'utf8',
210
+ timeout: 5000,
211
+ stdio: ['ignore', 'pipe', 'ignore']
212
+ }).trim();
213
+
214
+ // 发现新版本
215
+ if (latestVersion && latestVersion !== currentVersion) {
216
+ // 创建待更新文件
217
+ fs.writeFileSync(pendingFile, JSON.stringify({
218
+ currentVersion,
219
+ latestVersion,
220
+ detectedAt: Date.now()
221
+ }));
222
+
223
+ // 创建提示信息
224
+ const notice = `
225
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
226
+ 📦 发现 byebyecode 新版本!
227
+ 当前版本: v${currentVersion}
228
+ 最新版本: v${latestVersion}
229
+
230
+ 💡 更新将在您下次启动 Claude Code 时自动进行
231
+ (或手动运行: npm update -g @88code/byebyecode)
232
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
233
+ `.trim();
234
+
235
+ fs.writeFileSync(noticeFile, notice);
236
+ console.error(notice);
237
+ } else {
238
+ // 没有新版本,清理旧的提示文件
239
+ if (fs.existsSync(pendingFile)) {
240
+ fs.unlinkSync(pendingFile);
241
+ }
242
+ if (fs.existsSync(noticeFile)) {
243
+ fs.unlinkSync(noticeFile);
244
+ }
245
+ }
246
+ } catch (error) {
247
+ // 静默忽略错误(网络问题等)
248
+ }
249
+ }
250
+
251
+ // ==================== 主流程 ====================
252
+
253
+ // 步骤 1: 启动时检查并安装待更新
254
+ checkAndInstallPendingUpdate();
255
+
256
+ // 步骤 2: 确定平台对应的二进制
24
257
  const platform = process.platform;
25
258
  const arch = process.arch;
26
259
 
27
- // Handle special cases
28
260
  let platformKey = `${platform}-${arch}`;
29
261
  if (platform === 'linux') {
30
- // Detect if static linking is needed based on glibc version
262
+ // 检测是否需要静态链接版本 (glibc < 2.35)
31
263
  function shouldUseStaticBinary() {
32
264
  try {
33
- const { execSync } = require('child_process');
34
- const lddOutput = execSync('ldd --version 2>/dev/null || echo ""', {
265
+ const lddOutput = execSync('ldd --version 2>/dev/null || echo ""', {
35
266
  encoding: 'utf8',
36
- timeout: 1000
267
+ timeout: 1000
37
268
  });
38
-
39
- // Parse "ldd (GNU libc) 2.35" format
269
+
40
270
  const match = lddOutput.match(/(?:GNU libc|GLIBC).*?(\d+)\.(\d+)/);
41
271
  if (match) {
42
272
  const major = parseInt(match[1]);
43
273
  const minor = parseInt(match[2]);
44
- // Use static binary if glibc < 2.35
45
274
  return major < 2 || (major === 2 && minor < 35);
46
275
  }
47
276
  } catch (e) {
48
- // If detection fails, default to dynamic binary
49
277
  return false;
50
278
  }
51
-
52
279
  return false;
53
280
  }
54
-
281
+
55
282
  if (shouldUseStaticBinary()) {
56
283
  platformKey = 'linux-x64-musl';
57
284
  }
@@ -63,14 +290,14 @@ const packageMap = {
63
290
  'linux-x64': '@88code/byebyecode-linux-x64',
64
291
  'linux-x64-musl': '@88code/byebyecode-linux-x64-musl',
65
292
  'win32-x64': '@88code/byebyecode-win32-x64',
66
- 'win32-ia32': '@88code/byebyecode-win32-x64', // Use 64-bit for 32-bit systems
293
+ 'win32-ia32': '@88code/byebyecode-win32-x64',
67
294
  };
68
295
 
69
296
  const packageName = packageMap[platformKey];
70
297
  if (!packageName) {
71
298
  console.error(`Error: Unsupported platform ${platformKey}`);
72
299
  console.error('Supported platforms: darwin (x64/arm64), linux (x64), win32 (x64)');
73
- console.error('Please visit https://github.com/Haleclipse/CCometixLine for manual installation');
300
+ console.error('Please visit https://github.com/byebye-code/byebyecode for manual installation');
74
301
  process.exit(1);
75
302
  }
76
303
 
@@ -85,9 +312,13 @@ if (!fs.existsSync(binaryPath)) {
85
312
  process.exit(1);
86
313
  }
87
314
 
315
+ // 步骤 3: 执行二进制
88
316
  const result = spawnSync(binaryPath, process.argv.slice(2), {
89
317
  stdio: 'inherit',
90
318
  shell: false
91
319
  });
92
320
 
321
+ // 步骤 4: 执行完毕后,异步检查版本
322
+ setImmediate(() => checkVersionAndNotify());
323
+
93
324
  process.exit(result.status || 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@88code/byebyecode",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "description": "CCometixLine - High-performance Claude Code StatusLine tool",
5
5
  "bin": {
6
6
  "byebyecode": "./bin/byebyecode.js"
@@ -9,11 +9,11 @@
9
9
  "postinstall": "node scripts/postinstall.js"
10
10
  },
11
11
  "optionalDependencies": {
12
- "@88code/byebyecode-darwin-x64": "1.1.11",
13
- "@88code/byebyecode-darwin-arm64": "1.1.11",
14
- "@88code/byebyecode-linux-x64": "1.1.11",
15
- "@88code/byebyecode-linux-x64-musl": "1.1.11",
16
- "@88code/byebyecode-win32-x64": "1.1.11"
12
+ "@88code/byebyecode-darwin-x64": "1.1.13",
13
+ "@88code/byebyecode-darwin-arm64": "1.1.13",
14
+ "@88code/byebyecode-linux-x64": "1.1.13",
15
+ "@88code/byebyecode-linux-x64-musl": "1.1.13",
16
+ "@88code/byebyecode-win32-x64": "1.1.13"
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
@@ -14,7 +14,7 @@ try {
14
14
  const platform = process.platform;
15
15
  const arch = process.arch;
16
16
  const homeDir = os.homedir();
17
- const claudeDir = path.join(homeDir, '.claude', '88code');
17
+ const claudeDir = path.join(homeDir, '.claude', 'byebyecode');
18
18
 
19
19
  // Create directory
20
20
  fs.mkdirSync(claudeDir, { recursive: true });