@88code/byebyecode 1.1.12 → 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 +260 -29
- package/package.json +6 -6
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
|
-
//
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
262
|
+
// 检测是否需要静态链接版本 (glibc < 2.35)
|
|
31
263
|
function shouldUseStaticBinary() {
|
|
32
264
|
try {
|
|
33
|
-
const
|
|
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',
|
|
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/
|
|
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.
|
|
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.
|
|
13
|
-
"@88code/byebyecode-darwin-arm64": "1.1.
|
|
14
|
-
"@88code/byebyecode-linux-x64": "1.1.
|
|
15
|
-
"@88code/byebyecode-linux-x64-musl": "1.1.
|
|
16
|
-
"@88code/byebyecode-win32-x64": "1.1.
|
|
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",
|