ccjk 2.3.0 → 2.3.2
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/chunks/auto-bootstrap.mjs +358 -0
- package/dist/chunks/menu.mjs +46 -40
- package/dist/chunks/package.mjs +1 -1
- package/dist/chunks/silent-updater.mjs +396 -0
- package/dist/cli.mjs +12 -0
- package/package.json +1 -1
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { randomUUID, createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { release, platform, type, homedir, hostname } from 'node:os';
|
|
4
|
+
import { join } from 'pathe';
|
|
5
|
+
import { CCJK_CONFIG_DIR } from './constants.mjs';
|
|
6
|
+
import './index2.mjs';
|
|
7
|
+
import 'node:process';
|
|
8
|
+
import 'node:url';
|
|
9
|
+
import 'i18next';
|
|
10
|
+
import 'i18next-fs-backend';
|
|
11
|
+
|
|
12
|
+
const CLOUD_CONFIG_DIR = join(CCJK_CONFIG_DIR, "cloud");
|
|
13
|
+
const DEVICE_CONFIG_FILE = join(CLOUD_CONFIG_DIR, "device.json");
|
|
14
|
+
const CLOUD_STATE_FILE = join(CLOUD_CONFIG_DIR, "state.json");
|
|
15
|
+
const CLOUD_API_ENDPOINT = "https://api.ccjk.dev/v1";
|
|
16
|
+
const AUTO_SYNC_INTERVAL = 30 * 60 * 1e3;
|
|
17
|
+
const AUTO_UPGRADE_CHECK_INTERVAL = 6 * 60 * 60 * 1e3;
|
|
18
|
+
function generateDeviceFingerprint() {
|
|
19
|
+
const data = [
|
|
20
|
+
platform(),
|
|
21
|
+
type(),
|
|
22
|
+
homedir().split("/").length.toString(),
|
|
23
|
+
// 只用路径深度,不用实际路径
|
|
24
|
+
hostname().length.toString()
|
|
25
|
+
// 只用主机名长度,不用实际名称
|
|
26
|
+
].join("|");
|
|
27
|
+
return createHash("sha256").update(data).digest("hex").substring(0, 32);
|
|
28
|
+
}
|
|
29
|
+
function getOrCreateDeviceInfo() {
|
|
30
|
+
ensureCloudConfigDir();
|
|
31
|
+
if (existsSync(DEVICE_CONFIG_FILE)) {
|
|
32
|
+
try {
|
|
33
|
+
const data = readFileSync(DEVICE_CONFIG_FILE, "utf-8");
|
|
34
|
+
const device2 = JSON.parse(data);
|
|
35
|
+
device2.lastActiveAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
36
|
+
writeFileSync(DEVICE_CONFIG_FILE, JSON.stringify(device2, null, 2));
|
|
37
|
+
return device2;
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const device = {
|
|
42
|
+
deviceId: randomUUID(),
|
|
43
|
+
fingerprint: generateDeviceFingerprint(),
|
|
44
|
+
registeredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45
|
+
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
46
|
+
osType: platform(),
|
|
47
|
+
osVersion: release(),
|
|
48
|
+
ccjkVersion: getCcjkVersion()
|
|
49
|
+
};
|
|
50
|
+
writeFileSync(DEVICE_CONFIG_FILE, JSON.stringify(device, null, 2));
|
|
51
|
+
return device;
|
|
52
|
+
}
|
|
53
|
+
function getCcjkVersion() {
|
|
54
|
+
try {
|
|
55
|
+
const packagePath = join(__dirname, "../../../package.json");
|
|
56
|
+
if (existsSync(packagePath)) {
|
|
57
|
+
const pkg = JSON.parse(readFileSync(packagePath, "utf-8"));
|
|
58
|
+
return pkg.version || "unknown";
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
return "unknown";
|
|
63
|
+
}
|
|
64
|
+
function ensureCloudConfigDir() {
|
|
65
|
+
if (!existsSync(CLOUD_CONFIG_DIR)) {
|
|
66
|
+
mkdirSync(CLOUD_CONFIG_DIR, { recursive: true });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function getCloudState() {
|
|
70
|
+
ensureCloudConfigDir();
|
|
71
|
+
if (existsSync(CLOUD_STATE_FILE)) {
|
|
72
|
+
try {
|
|
73
|
+
const data = readFileSync(CLOUD_STATE_FILE, "utf-8");
|
|
74
|
+
return JSON.parse(data);
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
initialized: false,
|
|
80
|
+
autoSyncEnabled: true,
|
|
81
|
+
silentUpgradeEnabled: true,
|
|
82
|
+
lastSyncAt: null,
|
|
83
|
+
lastUpgradeCheckAt: null,
|
|
84
|
+
lastUpgradedAt: null,
|
|
85
|
+
syncStats: {
|
|
86
|
+
totalSyncs: 0,
|
|
87
|
+
successfulSyncs: 0,
|
|
88
|
+
failedSyncs: 0
|
|
89
|
+
},
|
|
90
|
+
upgradeStats: {
|
|
91
|
+
totalChecks: 0,
|
|
92
|
+
upgradesApplied: 0,
|
|
93
|
+
upgradesFailed: 0
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function saveCloudState(state) {
|
|
98
|
+
ensureCloudConfigDir();
|
|
99
|
+
writeFileSync(CLOUD_STATE_FILE, JSON.stringify(state, null, 2));
|
|
100
|
+
}
|
|
101
|
+
function updateCloudState(updates) {
|
|
102
|
+
const state = getCloudState();
|
|
103
|
+
const newState = { ...state, ...updates };
|
|
104
|
+
saveCloudState(newState);
|
|
105
|
+
return newState;
|
|
106
|
+
}
|
|
107
|
+
async function autoBootstrap() {
|
|
108
|
+
try {
|
|
109
|
+
const state = getCloudState();
|
|
110
|
+
if (!state.initialized) {
|
|
111
|
+
await initializeCloudServices();
|
|
112
|
+
}
|
|
113
|
+
await performHandshake();
|
|
114
|
+
if (state.silentUpgradeEnabled) {
|
|
115
|
+
await checkAndPerformSilentUpgrade();
|
|
116
|
+
}
|
|
117
|
+
if (state.autoSyncEnabled) {
|
|
118
|
+
await performAutoSync();
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function initializeCloudServices() {
|
|
124
|
+
const device = getOrCreateDeviceInfo();
|
|
125
|
+
updateCloudState({
|
|
126
|
+
initialized: true,
|
|
127
|
+
autoSyncEnabled: true,
|
|
128
|
+
silentUpgradeEnabled: true
|
|
129
|
+
});
|
|
130
|
+
try {
|
|
131
|
+
await registerDevice(device);
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function registerDevice(device) {
|
|
136
|
+
const controller = new AbortController();
|
|
137
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
138
|
+
try {
|
|
139
|
+
await fetch(`${CLOUD_API_ENDPOINT}/devices/register`, {
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: {
|
|
142
|
+
"Content-Type": "application/json",
|
|
143
|
+
"User-Agent": `CCJK/${device.ccjkVersion}`
|
|
144
|
+
},
|
|
145
|
+
body: JSON.stringify({
|
|
146
|
+
deviceId: device.deviceId,
|
|
147
|
+
fingerprint: device.fingerprint,
|
|
148
|
+
osType: device.osType,
|
|
149
|
+
osVersion: device.osVersion,
|
|
150
|
+
ccjkVersion: device.ccjkVersion
|
|
151
|
+
}),
|
|
152
|
+
signal: controller.signal
|
|
153
|
+
});
|
|
154
|
+
} finally {
|
|
155
|
+
clearTimeout(timeoutId);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async function performHandshake() {
|
|
159
|
+
const device = getOrCreateDeviceInfo();
|
|
160
|
+
const controller = new AbortController();
|
|
161
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
162
|
+
try {
|
|
163
|
+
const response = await fetch(`${CLOUD_API_ENDPOINT}/handshake`, {
|
|
164
|
+
method: "POST",
|
|
165
|
+
headers: {
|
|
166
|
+
"Content-Type": "application/json",
|
|
167
|
+
"User-Agent": `CCJK/${device.ccjkVersion}`,
|
|
168
|
+
"X-Device-ID": device.deviceId
|
|
169
|
+
},
|
|
170
|
+
body: JSON.stringify({
|
|
171
|
+
deviceId: device.deviceId,
|
|
172
|
+
ccjkVersion: device.ccjkVersion
|
|
173
|
+
}),
|
|
174
|
+
signal: controller.signal
|
|
175
|
+
});
|
|
176
|
+
if (response.ok) {
|
|
177
|
+
return await response.json();
|
|
178
|
+
}
|
|
179
|
+
} catch {
|
|
180
|
+
} finally {
|
|
181
|
+
clearTimeout(timeoutId);
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
async function checkAndPerformSilentUpgrade() {
|
|
186
|
+
const state = getCloudState();
|
|
187
|
+
const now = Date.now();
|
|
188
|
+
if (state.lastUpgradeCheckAt) {
|
|
189
|
+
const lastCheck = new Date(state.lastUpgradeCheckAt).getTime();
|
|
190
|
+
if (now - lastCheck < AUTO_UPGRADE_CHECK_INTERVAL) {
|
|
191
|
+
return { success: true, upgraded: false };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
updateCloudState({
|
|
195
|
+
lastUpgradeCheckAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
196
|
+
upgradeStats: {
|
|
197
|
+
...state.upgradeStats,
|
|
198
|
+
totalChecks: state.upgradeStats.totalChecks + 1
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
try {
|
|
202
|
+
const updateInfo = await checkForUpdates();
|
|
203
|
+
if (updateInfo.hasUpdate) {
|
|
204
|
+
const result = await performSilentUpgrade(updateInfo.latestVersion);
|
|
205
|
+
if (result.success && result.upgraded) {
|
|
206
|
+
updateCloudState({
|
|
207
|
+
lastUpgradedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
208
|
+
upgradeStats: {
|
|
209
|
+
...getCloudState().upgradeStats,
|
|
210
|
+
upgradesApplied: getCloudState().upgradeStats.upgradesApplied + 1
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
return { success: true, upgraded: false };
|
|
217
|
+
} catch (error) {
|
|
218
|
+
updateCloudState({
|
|
219
|
+
upgradeStats: {
|
|
220
|
+
...getCloudState().upgradeStats,
|
|
221
|
+
upgradesFailed: getCloudState().upgradeStats.upgradesFailed + 1
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
return {
|
|
225
|
+
success: false,
|
|
226
|
+
upgraded: false,
|
|
227
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async function checkForUpdates() {
|
|
232
|
+
const currentVersion = getCcjkVersion();
|
|
233
|
+
const controller = new AbortController();
|
|
234
|
+
const timeoutId = setTimeout(() => controller.abort(), 1e4);
|
|
235
|
+
try {
|
|
236
|
+
const response = await fetch("https://registry.npmjs.org/ccjk/latest", {
|
|
237
|
+
signal: controller.signal
|
|
238
|
+
});
|
|
239
|
+
if (response.ok) {
|
|
240
|
+
const data = await response.json();
|
|
241
|
+
const latestVersion = data.version;
|
|
242
|
+
return {
|
|
243
|
+
hasUpdate: isNewerVersion(latestVersion, currentVersion),
|
|
244
|
+
latestVersion,
|
|
245
|
+
currentVersion
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
} catch {
|
|
249
|
+
} finally {
|
|
250
|
+
clearTimeout(timeoutId);
|
|
251
|
+
}
|
|
252
|
+
return { hasUpdate: false, latestVersion: currentVersion, currentVersion };
|
|
253
|
+
}
|
|
254
|
+
function isNewerVersion(latest, current) {
|
|
255
|
+
const latestParts = latest.split(".").map(Number);
|
|
256
|
+
const currentParts = current.split(".").map(Number);
|
|
257
|
+
for (let i = 0; i < 3; i++) {
|
|
258
|
+
const l = latestParts[i] || 0;
|
|
259
|
+
const c = currentParts[i] || 0;
|
|
260
|
+
if (l > c)
|
|
261
|
+
return true;
|
|
262
|
+
if (l < c)
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
async function performSilentUpgrade(targetVersion) {
|
|
268
|
+
const currentVersion = getCcjkVersion();
|
|
269
|
+
try {
|
|
270
|
+
const { exec } = await import('tinyexec');
|
|
271
|
+
const result = await exec("npm", ["update", "-g", "ccjk"], {
|
|
272
|
+
timeout: 6e4
|
|
273
|
+
// 60 秒超时
|
|
274
|
+
});
|
|
275
|
+
if (result.exitCode === 0) {
|
|
276
|
+
return {
|
|
277
|
+
success: true,
|
|
278
|
+
upgraded: true,
|
|
279
|
+
fromVersion: currentVersion,
|
|
280
|
+
toVersion: targetVersion
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
success: false,
|
|
285
|
+
upgraded: false,
|
|
286
|
+
error: result.stderr || "Upgrade failed"
|
|
287
|
+
};
|
|
288
|
+
} catch (error) {
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
upgraded: false,
|
|
292
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async function performAutoSync() {
|
|
297
|
+
const state = getCloudState();
|
|
298
|
+
const now = Date.now();
|
|
299
|
+
if (state.lastSyncAt) {
|
|
300
|
+
const lastSync = new Date(state.lastSyncAt).getTime();
|
|
301
|
+
if (now - lastSync < AUTO_SYNC_INTERVAL) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
await syncToCloud();
|
|
307
|
+
updateCloudState({
|
|
308
|
+
lastSyncAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
309
|
+
syncStats: {
|
|
310
|
+
...state.syncStats,
|
|
311
|
+
totalSyncs: state.syncStats.totalSyncs + 1,
|
|
312
|
+
successfulSyncs: state.syncStats.successfulSyncs + 1
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
} catch {
|
|
316
|
+
updateCloudState({
|
|
317
|
+
syncStats: {
|
|
318
|
+
...state.syncStats,
|
|
319
|
+
totalSyncs: state.syncStats.totalSyncs + 1,
|
|
320
|
+
failedSyncs: state.syncStats.failedSyncs + 1
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async function syncToCloud() {
|
|
326
|
+
const device = getOrCreateDeviceInfo();
|
|
327
|
+
const controller = new AbortController();
|
|
328
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
329
|
+
try {
|
|
330
|
+
const syncData = await collectSyncData();
|
|
331
|
+
await fetch(`${CLOUD_API_ENDPOINT}/sync`, {
|
|
332
|
+
method: "POST",
|
|
333
|
+
headers: {
|
|
334
|
+
"Content-Type": "application/json",
|
|
335
|
+
"User-Agent": `CCJK/${device.ccjkVersion}`,
|
|
336
|
+
"X-Device-ID": device.deviceId
|
|
337
|
+
},
|
|
338
|
+
body: JSON.stringify(syncData),
|
|
339
|
+
signal: controller.signal
|
|
340
|
+
});
|
|
341
|
+
} finally {
|
|
342
|
+
clearTimeout(timeoutId);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
async function collectSyncData() {
|
|
346
|
+
const device = getOrCreateDeviceInfo();
|
|
347
|
+
return {
|
|
348
|
+
deviceId: device.deviceId,
|
|
349
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
350
|
+
// 只同步匿名化的使用统计
|
|
351
|
+
stats: {
|
|
352
|
+
osType: device.osType,
|
|
353
|
+
ccjkVersion: device.ccjkVersion
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export { AUTO_SYNC_INTERVAL, AUTO_UPGRADE_CHECK_INTERVAL, CLOUD_API_ENDPOINT, CLOUD_CONFIG_DIR, CLOUD_STATE_FILE, DEVICE_CONFIG_FILE, autoBootstrap, autoBootstrap as bootstrap, checkAndPerformSilentUpgrade as checkUpgrade, getCloudState, getOrCreateDeviceInfo, saveCloudState, performAutoSync as sync, updateCloudState };
|
package/dist/chunks/menu.mjs
CHANGED
|
@@ -3031,47 +3031,38 @@ async function showMoreFeaturesMenu() {
|
|
|
3031
3031
|
console.log("");
|
|
3032
3032
|
console.log(` ${ansis.yellow(i18n.t("menu:moreMenu.config"))}`);
|
|
3033
3033
|
console.log(
|
|
3034
|
-
` ${ansis.cyan("7.")} ${i18n.t("menu:configCenter.
|
|
3034
|
+
` ${ansis.cyan("7.")} ${i18n.t("menu:configCenter.memory")} ${ansis.gray(`- ${i18n.t("menu:configCenter.memoryDesc")}`)}`
|
|
3035
3035
|
);
|
|
3036
3036
|
console.log(
|
|
3037
|
-
` ${ansis.cyan("8.")} ${i18n.t("menu:configCenter.
|
|
3037
|
+
` ${ansis.cyan("8.")} ${i18n.t("menu:configCenter.permission")} ${ansis.gray(`- ${i18n.t("menu:configCenter.permissionDesc")}`)}`
|
|
3038
3038
|
);
|
|
3039
3039
|
console.log(
|
|
3040
|
-
` ${ansis.cyan("9.")} ${i18n.t("menu:configCenter.
|
|
3040
|
+
` ${ansis.cyan("9.")} ${i18n.t("menu:configCenter.configSwitch")} ${ansis.gray(`- ${i18n.t("menu:configCenter.configSwitchDesc")}`)}`
|
|
3041
3041
|
);
|
|
3042
3042
|
console.log(
|
|
3043
|
-
` ${ansis.cyan("10.")} ${i18n.t("menu:configCenter.
|
|
3044
|
-
);
|
|
3045
|
-
console.log(
|
|
3046
|
-
` ${ansis.cyan("11.")} ${i18n.t("menu:configCenter.permission")} ${ansis.gray(`- ${i18n.t("menu:configCenter.permissionDesc")}`)}`
|
|
3047
|
-
);
|
|
3048
|
-
console.log(
|
|
3049
|
-
` ${ansis.cyan("12.")} ${i18n.t("menu:configCenter.configSwitch")} ${ansis.gray(`- ${i18n.t("menu:configCenter.configSwitchDesc")}`)}`
|
|
3050
|
-
);
|
|
3051
|
-
console.log(
|
|
3052
|
-
` ${ansis.cyan("13.")} ${i18n.t("menu:configCenter.context")} ${ansis.gray(`- ${i18n.t("menu:configCenter.contextDesc")}`)}`
|
|
3043
|
+
` ${ansis.cyan("10.")} ${i18n.t("menu:configCenter.context")} ${ansis.gray(`- ${i18n.t("menu:configCenter.contextDesc")}`)}`
|
|
3053
3044
|
);
|
|
3054
3045
|
console.log("");
|
|
3055
3046
|
console.log(` ${ansis.yellow(i18n.t("menu:moreMenu.system"))}`);
|
|
3056
3047
|
console.log(
|
|
3057
|
-
` ${ansis.cyan("
|
|
3048
|
+
` ${ansis.cyan("11.")} ${i18n.t("menu:menuOptions.changeLanguage").split(" / ")[0]} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.changeLanguage")}`)}`
|
|
3058
3049
|
);
|
|
3059
3050
|
console.log(
|
|
3060
|
-
` ${ansis.cyan("
|
|
3051
|
+
` ${ansis.cyan("12.")} ${i18n.t("menu:menuOptions.switchCodeTool")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.switchCodeTool")}`)}`
|
|
3061
3052
|
);
|
|
3062
3053
|
console.log(
|
|
3063
|
-
` ${ansis.cyan("
|
|
3054
|
+
` ${ansis.cyan("13.")} ${i18n.t("menu:categorizedMenu.diagnostics")} ${ansis.gray(`- ${i18n.t("menu:categorizedMenu.diagnosticsDesc")}`)}`
|
|
3064
3055
|
);
|
|
3065
3056
|
console.log(
|
|
3066
|
-
` ${ansis.cyan("
|
|
3057
|
+
` ${ansis.cyan("14.")} ${i18n.t("menu:categorizedMenu.workspace")} ${ansis.gray(`- ${i18n.t("menu:categorizedMenu.workspaceDesc")}`)}`
|
|
3067
3058
|
);
|
|
3068
3059
|
console.log(
|
|
3069
|
-
` ${ansis.cyan("
|
|
3060
|
+
` ${ansis.cyan("15.")} ${i18n.t("menu:menuOptions.uninstall")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.uninstall")}`)}`
|
|
3070
3061
|
);
|
|
3071
3062
|
console.log("");
|
|
3072
3063
|
console.log(` ${ansis.cyan("0.")} ${i18n.t("common:back")}`);
|
|
3073
3064
|
console.log("");
|
|
3074
|
-
const validChoices = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"
|
|
3065
|
+
const validChoices = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"];
|
|
3075
3066
|
const { choice } = await inquirer.prompt({
|
|
3076
3067
|
type: "input",
|
|
3077
3068
|
name: "choice",
|
|
@@ -3104,44 +3095,35 @@ async function showMoreFeaturesMenu() {
|
|
|
3104
3095
|
case "6":
|
|
3105
3096
|
await showMarketplaceMenu();
|
|
3106
3097
|
break;
|
|
3107
|
-
// Config
|
|
3098
|
+
// Config (API/MCP/Model removed - now on main menu)
|
|
3108
3099
|
case "7":
|
|
3109
|
-
await configureApiFeature();
|
|
3110
|
-
break;
|
|
3111
|
-
case "8":
|
|
3112
|
-
await configureMcpFeature();
|
|
3113
|
-
break;
|
|
3114
|
-
case "9":
|
|
3115
|
-
await configureDefaultModelFeature();
|
|
3116
|
-
break;
|
|
3117
|
-
case "10":
|
|
3118
3100
|
await configureAiMemoryFeature();
|
|
3119
3101
|
break;
|
|
3120
|
-
case "
|
|
3102
|
+
case "8":
|
|
3121
3103
|
await configureEnvPermissionFeature();
|
|
3122
3104
|
break;
|
|
3123
|
-
case "
|
|
3105
|
+
case "9":
|
|
3124
3106
|
await showConfigSwitchMenu();
|
|
3125
3107
|
break;
|
|
3126
|
-
case "
|
|
3108
|
+
case "10":
|
|
3127
3109
|
await showContextMenu();
|
|
3128
3110
|
break;
|
|
3129
3111
|
// System
|
|
3130
|
-
case "
|
|
3112
|
+
case "11": {
|
|
3131
3113
|
const currentLang = i18n.language;
|
|
3132
3114
|
await changeScriptLanguageFeature(currentLang);
|
|
3133
3115
|
break;
|
|
3134
3116
|
}
|
|
3135
|
-
case "
|
|
3117
|
+
case "12":
|
|
3136
3118
|
await handleCodeToolSwitch("claude-code");
|
|
3137
3119
|
break;
|
|
3138
|
-
case "
|
|
3120
|
+
case "13":
|
|
3139
3121
|
await doctor();
|
|
3140
3122
|
break;
|
|
3141
|
-
case "
|
|
3123
|
+
case "14":
|
|
3142
3124
|
await workspaceDiagnostics();
|
|
3143
3125
|
break;
|
|
3144
|
-
case "
|
|
3126
|
+
case "15":
|
|
3145
3127
|
await uninstall();
|
|
3146
3128
|
break;
|
|
3147
3129
|
}
|
|
@@ -3149,6 +3131,7 @@ async function showMoreFeaturesMenu() {
|
|
|
3149
3131
|
async function showCategorizedMenu() {
|
|
3150
3132
|
console.log(ansis.cyan(i18n.t("menu:oneClick.title")));
|
|
3151
3133
|
console.log("");
|
|
3134
|
+
console.log(` ${ansis.yellow(i18n.t("menu:menuSections.quickStart"))}`);
|
|
3152
3135
|
console.log(
|
|
3153
3136
|
` ${ansis.cyan("1.")} ${i18n.t("menu:oneClick.setup")} ${ansis.gray(`- ${i18n.t("menu:oneClick.setupDesc")}`)}`
|
|
3154
3137
|
);
|
|
@@ -3162,9 +3145,20 @@ async function showCategorizedMenu() {
|
|
|
3162
3145
|
` ${ansis.cyan("4.")} ${i18n.t("menu:oneClick.notify")} ${ansis.gray(`- ${i18n.t("menu:oneClick.notifyDesc")}`)}`
|
|
3163
3146
|
);
|
|
3164
3147
|
console.log("");
|
|
3148
|
+
console.log(` ${ansis.yellow(i18n.t("menu:menuSections.configCenter"))}`);
|
|
3149
|
+
console.log(
|
|
3150
|
+
` ${ansis.cyan("5.")} ${i18n.t("menu:configCenter.api")} ${ansis.gray(`- ${i18n.t("menu:configCenter.apiDesc")}`)}`
|
|
3151
|
+
);
|
|
3152
|
+
console.log(
|
|
3153
|
+
` ${ansis.cyan("6.")} ${i18n.t("menu:configCenter.mcp")} ${ansis.gray(`- ${i18n.t("menu:configCenter.mcpDesc")}`)}`
|
|
3154
|
+
);
|
|
3155
|
+
console.log(
|
|
3156
|
+
` ${ansis.cyan("7.")} ${i18n.t("menu:configCenter.model")} ${ansis.gray(`- ${i18n.t("menu:configCenter.modelDesc")}`)}`
|
|
3157
|
+
);
|
|
3158
|
+
console.log("");
|
|
3165
3159
|
console.log(` ${ansis.dim("\u2500".repeat(50))}`);
|
|
3166
3160
|
console.log(
|
|
3167
|
-
` ${ansis.cyan("
|
|
3161
|
+
` ${ansis.cyan("8.")} ${i18n.t("menu:oneClick.more")} \u2192 ${ansis.gray(i18n.t("menu:oneClick.moreDesc"))}`
|
|
3168
3162
|
);
|
|
3169
3163
|
console.log("");
|
|
3170
3164
|
console.log(
|
|
@@ -3176,7 +3170,7 @@ async function showCategorizedMenu() {
|
|
|
3176
3170
|
name: "choice",
|
|
3177
3171
|
message: i18n.t("common:enterChoice"),
|
|
3178
3172
|
validate: (value) => {
|
|
3179
|
-
const valid = ["1", "2", "3", "4", "5", "0", "q", "Q"];
|
|
3173
|
+
const valid = ["1", "2", "3", "4", "5", "6", "7", "8", "0", "q", "Q"];
|
|
3180
3174
|
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
3181
3175
|
}
|
|
3182
3176
|
});
|
|
@@ -3202,8 +3196,20 @@ async function showCategorizedMenu() {
|
|
|
3202
3196
|
case "4":
|
|
3203
3197
|
await notificationCommand();
|
|
3204
3198
|
break;
|
|
3205
|
-
//
|
|
3199
|
+
// API Config (Important Setting)
|
|
3206
3200
|
case "5":
|
|
3201
|
+
await configureApiFeature();
|
|
3202
|
+
break;
|
|
3203
|
+
// MCP Config (Important Setting)
|
|
3204
|
+
case "6":
|
|
3205
|
+
await configureMcpFeature();
|
|
3206
|
+
break;
|
|
3207
|
+
// Default Model (Important Setting)
|
|
3208
|
+
case "7":
|
|
3209
|
+
await configureDefaultModelFeature();
|
|
3210
|
+
break;
|
|
3211
|
+
// More features submenu
|
|
3212
|
+
case "8":
|
|
3207
3213
|
printSeparator();
|
|
3208
3214
|
await showMoreFeaturesMenu();
|
|
3209
3215
|
return void 0;
|
package/dist/chunks/package.mjs
CHANGED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, appendFileSync, unlinkSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { platform } from 'node:os';
|
|
3
|
+
import process__default from 'node:process';
|
|
4
|
+
import { join } from 'pathe';
|
|
5
|
+
import { CCJK_CONFIG_DIR } from './constants.mjs';
|
|
6
|
+
import { getCloudState, updateCloudState } from './auto-bootstrap.mjs';
|
|
7
|
+
import './index2.mjs';
|
|
8
|
+
import 'node:url';
|
|
9
|
+
import 'i18next';
|
|
10
|
+
import 'i18next-fs-backend';
|
|
11
|
+
import 'node:crypto';
|
|
12
|
+
|
|
13
|
+
const UPGRADE_LOG_DIR = join(CCJK_CONFIG_DIR, "cloud", "logs");
|
|
14
|
+
const UPGRADE_LOG_FILE = join(UPGRADE_LOG_DIR, "upgrades.log");
|
|
15
|
+
const UPGRADE_LOCK_FILE = join(CCJK_CONFIG_DIR, "cloud", ".upgrade.lock");
|
|
16
|
+
const UPGRADE_CHECK_INTERVAL = 6 * 60 * 60 * 1e3;
|
|
17
|
+
const UPGRADE_TIMEOUT = 5 * 60 * 1e3;
|
|
18
|
+
async function checkAllToolVersions() {
|
|
19
|
+
const results = [];
|
|
20
|
+
const [ccjk, claudeCode, ccr] = await Promise.all([
|
|
21
|
+
checkCcjkVersion(),
|
|
22
|
+
checkClaudeCodeVersion(),
|
|
23
|
+
checkCcrVersion()
|
|
24
|
+
]);
|
|
25
|
+
results.push(ccjk, claudeCode, ccr);
|
|
26
|
+
return results;
|
|
27
|
+
}
|
|
28
|
+
async function checkCcjkVersion() {
|
|
29
|
+
try {
|
|
30
|
+
const currentVersion = getCurrentCcjkVersion();
|
|
31
|
+
const latestVersion = await fetchLatestNpmVersion("ccjk");
|
|
32
|
+
return {
|
|
33
|
+
tool: "ccjk",
|
|
34
|
+
installed: true,
|
|
35
|
+
currentVersion,
|
|
36
|
+
latestVersion,
|
|
37
|
+
needsUpdate: latestVersion ? isNewerVersion(latestVersion, currentVersion) : false,
|
|
38
|
+
installMethod: "npm"
|
|
39
|
+
};
|
|
40
|
+
} catch {
|
|
41
|
+
return {
|
|
42
|
+
tool: "ccjk",
|
|
43
|
+
installed: true,
|
|
44
|
+
currentVersion: getCurrentCcjkVersion(),
|
|
45
|
+
latestVersion: null,
|
|
46
|
+
needsUpdate: false,
|
|
47
|
+
installMethod: "npm"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function checkClaudeCodeVersion() {
|
|
52
|
+
try {
|
|
53
|
+
const { exec } = await import('tinyexec');
|
|
54
|
+
const result = await exec("claude", ["--version"], { timeout: 5e3 });
|
|
55
|
+
if (result.exitCode !== 0) {
|
|
56
|
+
return {
|
|
57
|
+
tool: "claude-code",
|
|
58
|
+
installed: false,
|
|
59
|
+
currentVersion: null,
|
|
60
|
+
latestVersion: null,
|
|
61
|
+
needsUpdate: false,
|
|
62
|
+
installMethod: "unknown"
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const currentVersion = result.stdout.trim().replace(/^v/, "");
|
|
66
|
+
const latestVersion = await fetchLatestNpmVersion("@anthropic-ai/claude-code");
|
|
67
|
+
const installMethod = await detectClaudeCodeInstallMethod();
|
|
68
|
+
return {
|
|
69
|
+
tool: "claude-code",
|
|
70
|
+
installed: true,
|
|
71
|
+
currentVersion,
|
|
72
|
+
latestVersion,
|
|
73
|
+
needsUpdate: latestVersion ? isNewerVersion(latestVersion, currentVersion) : false,
|
|
74
|
+
installMethod
|
|
75
|
+
};
|
|
76
|
+
} catch {
|
|
77
|
+
return {
|
|
78
|
+
tool: "claude-code",
|
|
79
|
+
installed: false,
|
|
80
|
+
currentVersion: null,
|
|
81
|
+
latestVersion: null,
|
|
82
|
+
needsUpdate: false,
|
|
83
|
+
installMethod: "unknown"
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function checkCcrVersion() {
|
|
88
|
+
try {
|
|
89
|
+
const { exec } = await import('tinyexec');
|
|
90
|
+
const result = await exec("ccr", ["--version"], { timeout: 5e3 });
|
|
91
|
+
if (result.exitCode !== 0) {
|
|
92
|
+
return {
|
|
93
|
+
tool: "ccr",
|
|
94
|
+
installed: false,
|
|
95
|
+
currentVersion: null,
|
|
96
|
+
latestVersion: null,
|
|
97
|
+
needsUpdate: false,
|
|
98
|
+
installMethod: "unknown"
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const currentVersion = result.stdout.trim().replace(/^v/, "");
|
|
102
|
+
const latestVersion = await fetchLatestNpmVersion("@musistudio/claude-code-router");
|
|
103
|
+
return {
|
|
104
|
+
tool: "ccr",
|
|
105
|
+
installed: true,
|
|
106
|
+
currentVersion,
|
|
107
|
+
latestVersion,
|
|
108
|
+
needsUpdate: latestVersion ? isNewerVersion(latestVersion, currentVersion) : false,
|
|
109
|
+
installMethod: "npm"
|
|
110
|
+
};
|
|
111
|
+
} catch {
|
|
112
|
+
return {
|
|
113
|
+
tool: "ccr",
|
|
114
|
+
installed: false,
|
|
115
|
+
currentVersion: null,
|
|
116
|
+
latestVersion: null,
|
|
117
|
+
needsUpdate: false,
|
|
118
|
+
installMethod: "unknown"
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function getCurrentCcjkVersion() {
|
|
123
|
+
try {
|
|
124
|
+
const packagePath = join(__dirname, "../../../package.json");
|
|
125
|
+
if (existsSync(packagePath)) {
|
|
126
|
+
const pkg = JSON.parse(readFileSync(packagePath, "utf-8"));
|
|
127
|
+
return pkg.version || "unknown";
|
|
128
|
+
}
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
return "unknown";
|
|
132
|
+
}
|
|
133
|
+
async function fetchLatestNpmVersion(packageName) {
|
|
134
|
+
const controller = new AbortController();
|
|
135
|
+
const timeoutId = setTimeout(() => controller.abort(), 1e4);
|
|
136
|
+
try {
|
|
137
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
|
|
138
|
+
signal: controller.signal
|
|
139
|
+
});
|
|
140
|
+
if (response.ok) {
|
|
141
|
+
const data = await response.json();
|
|
142
|
+
return data.version;
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
} finally {
|
|
146
|
+
clearTimeout(timeoutId);
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
async function detectClaudeCodeInstallMethod() {
|
|
151
|
+
try {
|
|
152
|
+
const { exec } = await import('tinyexec');
|
|
153
|
+
if (platform() === "darwin") {
|
|
154
|
+
const brewResult = await exec("brew", ["list", "--cask", "claude-code"], { timeout: 5e3 });
|
|
155
|
+
if (brewResult.exitCode === 0) {
|
|
156
|
+
return "homebrew";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const npmResult = await exec("npm", ["list", "-g", "@anthropic-ai/claude-code"], { timeout: 5e3 });
|
|
160
|
+
if (npmResult.exitCode === 0 && npmResult.stdout.includes("@anthropic-ai/claude-code")) {
|
|
161
|
+
return "npm";
|
|
162
|
+
}
|
|
163
|
+
return "curl";
|
|
164
|
+
} catch {
|
|
165
|
+
return "unknown";
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function isNewerVersion(latest, current) {
|
|
169
|
+
if (!latest || !current || current === "unknown")
|
|
170
|
+
return false;
|
|
171
|
+
const latestParts = latest.split(".").map(Number);
|
|
172
|
+
const currentParts = current.split(".").map(Number);
|
|
173
|
+
for (let i = 0; i < 3; i++) {
|
|
174
|
+
const l = latestParts[i] || 0;
|
|
175
|
+
const c = currentParts[i] || 0;
|
|
176
|
+
if (l > c)
|
|
177
|
+
return true;
|
|
178
|
+
if (l < c)
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
async function performSilentUpgradeAll() {
|
|
184
|
+
const startTime = Date.now();
|
|
185
|
+
const results = [];
|
|
186
|
+
if (isUpgradeLocked()) {
|
|
187
|
+
return {
|
|
188
|
+
success: false,
|
|
189
|
+
results: [],
|
|
190
|
+
totalDuration: 0,
|
|
191
|
+
upgradedCount: 0,
|
|
192
|
+
failedCount: 0
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
createUpgradeLock();
|
|
197
|
+
const versions = await checkAllToolVersions();
|
|
198
|
+
const toolsToUpgrade = versions.filter((v) => v.needsUpdate && v.installed);
|
|
199
|
+
for (const tool of toolsToUpgrade) {
|
|
200
|
+
const result = await upgradeTool(tool);
|
|
201
|
+
results.push(result);
|
|
202
|
+
logUpgrade({
|
|
203
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
204
|
+
tool: tool.tool,
|
|
205
|
+
fromVersion: tool.currentVersion || "unknown",
|
|
206
|
+
toVersion: tool.latestVersion || "unknown",
|
|
207
|
+
success: result.success,
|
|
208
|
+
error: result.error,
|
|
209
|
+
duration: result.duration
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
const totalDuration = Date.now() - startTime;
|
|
213
|
+
const upgradedCount = results.filter((r) => r.upgraded).length;
|
|
214
|
+
const failedCount = results.filter((r) => !r.success).length;
|
|
215
|
+
const state = getCloudState();
|
|
216
|
+
updateCloudState({
|
|
217
|
+
lastUpgradeCheckAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
218
|
+
upgradeStats: {
|
|
219
|
+
totalChecks: state.upgradeStats.totalChecks + 1,
|
|
220
|
+
upgradesApplied: state.upgradeStats.upgradesApplied + upgradedCount,
|
|
221
|
+
upgradesFailed: state.upgradeStats.upgradesFailed + failedCount
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
return {
|
|
225
|
+
success: failedCount === 0,
|
|
226
|
+
results,
|
|
227
|
+
totalDuration,
|
|
228
|
+
upgradedCount,
|
|
229
|
+
failedCount
|
|
230
|
+
};
|
|
231
|
+
} finally {
|
|
232
|
+
releaseUpgradeLock();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async function upgradeTool(info) {
|
|
236
|
+
const startTime = Date.now();
|
|
237
|
+
try {
|
|
238
|
+
switch (info.tool) {
|
|
239
|
+
case "ccjk":
|
|
240
|
+
return await upgradeCcjk(info, startTime);
|
|
241
|
+
case "claude-code":
|
|
242
|
+
return await upgradeClaudeCode(info, startTime);
|
|
243
|
+
case "ccr":
|
|
244
|
+
return await upgradeCcr(info, startTime);
|
|
245
|
+
default:
|
|
246
|
+
return {
|
|
247
|
+
tool: info.tool,
|
|
248
|
+
success: false,
|
|
249
|
+
upgraded: false,
|
|
250
|
+
error: "Unknown tool",
|
|
251
|
+
duration: Date.now() - startTime
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
} catch (error) {
|
|
255
|
+
return {
|
|
256
|
+
tool: info.tool,
|
|
257
|
+
success: false,
|
|
258
|
+
upgraded: false,
|
|
259
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
260
|
+
duration: Date.now() - startTime
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
async function upgradeCcjk(info, startTime) {
|
|
265
|
+
const { exec } = await import('tinyexec');
|
|
266
|
+
const result = await exec("npm", ["update", "-g", "ccjk"], {
|
|
267
|
+
timeout: UPGRADE_TIMEOUT
|
|
268
|
+
});
|
|
269
|
+
return {
|
|
270
|
+
tool: "ccjk",
|
|
271
|
+
success: result.exitCode === 0,
|
|
272
|
+
upgraded: result.exitCode === 0,
|
|
273
|
+
fromVersion: info.currentVersion || void 0,
|
|
274
|
+
toVersion: info.latestVersion || void 0,
|
|
275
|
+
error: result.exitCode !== 0 ? result.stderr : void 0,
|
|
276
|
+
duration: Date.now() - startTime
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
async function upgradeClaudeCode(info, startTime) {
|
|
280
|
+
const { exec } = await import('tinyexec');
|
|
281
|
+
let result;
|
|
282
|
+
switch (info.installMethod) {
|
|
283
|
+
case "homebrew":
|
|
284
|
+
result = await exec("brew", ["upgrade", "--cask", "claude-code"], {
|
|
285
|
+
timeout: UPGRADE_TIMEOUT
|
|
286
|
+
});
|
|
287
|
+
break;
|
|
288
|
+
case "npm":
|
|
289
|
+
result = await exec("npm", ["update", "-g", "@anthropic-ai/claude-code"], {
|
|
290
|
+
timeout: UPGRADE_TIMEOUT
|
|
291
|
+
});
|
|
292
|
+
break;
|
|
293
|
+
case "curl":
|
|
294
|
+
default:
|
|
295
|
+
result = await exec("claude", ["update"], {
|
|
296
|
+
timeout: UPGRADE_TIMEOUT
|
|
297
|
+
});
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
tool: "claude-code",
|
|
302
|
+
success: result.exitCode === 0,
|
|
303
|
+
upgraded: result.exitCode === 0,
|
|
304
|
+
fromVersion: info.currentVersion || void 0,
|
|
305
|
+
toVersion: info.latestVersion || void 0,
|
|
306
|
+
error: result.exitCode !== 0 ? result.stderr : void 0,
|
|
307
|
+
duration: Date.now() - startTime
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
async function upgradeCcr(info, startTime) {
|
|
311
|
+
const { exec } = await import('tinyexec');
|
|
312
|
+
const result = await exec("npm", ["update", "-g", "@musistudio/claude-code-router"], {
|
|
313
|
+
timeout: UPGRADE_TIMEOUT
|
|
314
|
+
});
|
|
315
|
+
return {
|
|
316
|
+
tool: "ccr",
|
|
317
|
+
success: result.exitCode === 0,
|
|
318
|
+
upgraded: result.exitCode === 0,
|
|
319
|
+
fromVersion: info.currentVersion || void 0,
|
|
320
|
+
toVersion: info.latestVersion || void 0,
|
|
321
|
+
error: result.exitCode !== 0 ? result.stderr : void 0,
|
|
322
|
+
duration: Date.now() - startTime
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function isUpgradeLocked() {
|
|
326
|
+
if (!existsSync(UPGRADE_LOCK_FILE)) {
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
try {
|
|
330
|
+
const lockData = JSON.parse(readFileSync(UPGRADE_LOCK_FILE, "utf-8"));
|
|
331
|
+
const lockTime = new Date(lockData.timestamp).getTime();
|
|
332
|
+
const now = Date.now();
|
|
333
|
+
if (now - lockTime > 10 * 60 * 1e3) {
|
|
334
|
+
releaseUpgradeLock();
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
return true;
|
|
338
|
+
} catch {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function createUpgradeLock() {
|
|
343
|
+
ensureLogDir();
|
|
344
|
+
writeFileSync(UPGRADE_LOCK_FILE, JSON.stringify({
|
|
345
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
346
|
+
pid: process__default.pid
|
|
347
|
+
}));
|
|
348
|
+
}
|
|
349
|
+
function releaseUpgradeLock() {
|
|
350
|
+
try {
|
|
351
|
+
if (existsSync(UPGRADE_LOCK_FILE)) {
|
|
352
|
+
unlinkSync(UPGRADE_LOCK_FILE);
|
|
353
|
+
}
|
|
354
|
+
} catch {
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
function ensureLogDir() {
|
|
358
|
+
if (!existsSync(UPGRADE_LOG_DIR)) {
|
|
359
|
+
mkdirSync(UPGRADE_LOG_DIR, { recursive: true });
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function logUpgrade(entry) {
|
|
363
|
+
ensureLogDir();
|
|
364
|
+
const logLine = [
|
|
365
|
+
entry.timestamp,
|
|
366
|
+
entry.tool,
|
|
367
|
+
entry.fromVersion,
|
|
368
|
+
"->",
|
|
369
|
+
entry.toVersion,
|
|
370
|
+
entry.success ? "SUCCESS" : "FAILED",
|
|
371
|
+
entry.error || "",
|
|
372
|
+
`${entry.duration}ms`
|
|
373
|
+
].join(" | ");
|
|
374
|
+
appendFileSync(UPGRADE_LOG_FILE, `${logLine}
|
|
375
|
+
`);
|
|
376
|
+
}
|
|
377
|
+
function shouldCheckForUpgrades() {
|
|
378
|
+
const state = getCloudState();
|
|
379
|
+
if (!state.silentUpgradeEnabled) {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
if (!state.lastUpgradeCheckAt) {
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
const lastCheck = new Date(state.lastUpgradeCheckAt).getTime();
|
|
386
|
+
const now = Date.now();
|
|
387
|
+
return now - lastCheck >= UPGRADE_CHECK_INTERVAL;
|
|
388
|
+
}
|
|
389
|
+
async function checkAndUpgradeIfNeeded() {
|
|
390
|
+
if (!shouldCheckForUpgrades()) {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
return performSilentUpgradeAll();
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export { UPGRADE_CHECK_INTERVAL, UPGRADE_LOCK_FILE, UPGRADE_LOG_DIR, UPGRADE_LOG_FILE, UPGRADE_TIMEOUT, checkAndUpgradeIfNeeded as autoUpgrade, checkAllToolVersions, checkAndUpgradeIfNeeded, checkAllToolVersions as checkVersions, performSilentUpgradeAll, shouldCheckForUpgrades, performSilentUpgradeAll as upgradeAll };
|
package/dist/cli.mjs
CHANGED
|
@@ -877,10 +877,22 @@ function customizeHelpLazy(_sections, version) {
|
|
|
877
877
|
return newSections;
|
|
878
878
|
}
|
|
879
879
|
async function runLazyCli() {
|
|
880
|
+
bootstrapCloudServices();
|
|
880
881
|
const cac = (await import('cac')).default;
|
|
881
882
|
const cli = cac("ccjk");
|
|
882
883
|
await setupCommandsLazy(cli);
|
|
883
884
|
cli.parse();
|
|
884
885
|
}
|
|
886
|
+
function bootstrapCloudServices() {
|
|
887
|
+
setImmediate(async () => {
|
|
888
|
+
try {
|
|
889
|
+
const { autoBootstrap } = await import('./chunks/auto-bootstrap.mjs');
|
|
890
|
+
await autoBootstrap();
|
|
891
|
+
const { autoUpgrade } = await import('./chunks/silent-updater.mjs');
|
|
892
|
+
await autoUpgrade();
|
|
893
|
+
} catch {
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
}
|
|
885
897
|
|
|
886
898
|
runLazyCli().catch(console.error);
|
package/package.json
CHANGED