ccjk 2.3.1 → 2.4.1
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/README.md +270 -444
- package/README.zh-CN.md +273 -447
- package/dist/chunks/auto-bootstrap.mjs +358 -0
- package/dist/chunks/ccr.mjs +5 -2
- package/dist/chunks/claude-wrapper.mjs +442 -0
- package/dist/chunks/cloud-sync.mjs +29 -0
- package/dist/chunks/constants.mjs +1 -1
- package/dist/chunks/context-manager.mjs +641 -0
- package/dist/chunks/context.mjs +248 -0
- package/dist/chunks/index2.mjs +2 -0
- package/dist/chunks/index3.mjs +19 -19
- package/dist/chunks/init.mjs +18 -8
- package/dist/chunks/marketplace.mjs +6 -2
- package/dist/chunks/mcp.mjs +1 -1
- package/dist/chunks/menu.mjs +3 -3
- package/dist/chunks/notification.mjs +27 -27
- package/dist/chunks/package.mjs +1 -1
- package/dist/chunks/platform.mjs +70 -21
- package/dist/chunks/silent-updater.mjs +396 -0
- package/dist/chunks/skills-sync.mjs +1 -1
- package/dist/chunks/version-checker.mjs +31 -31
- package/dist/cli.mjs +67 -5
- package/dist/i18n/locales/en/context.json +32 -0
- package/dist/i18n/locales/en/marketplace.json +1 -0
- package/dist/i18n/locales/en/mcp.json +12 -1
- package/dist/i18n/locales/en/superpowers.json +46 -0
- package/dist/i18n/locales/zh-CN/context.json +32 -0
- package/dist/i18n/locales/zh-CN/marketplace.json +1 -0
- package/dist/i18n/locales/zh-CN/mcp.json +12 -1
- package/dist/i18n/locales/zh-CN/superpowers.json +46 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/shared/ccjk.QbS8EAOd.mjs +1019 -0
- package/dist/shared/ccjk.RR9TS76h.mjs +698 -0
- package/package.json +4 -1
- package/dist/shared/ccjk.Bi-m3LKY.mjs +0 -357
- package/dist/shared/ccjk.D-RZS4E2.mjs +0 -416
package/dist/chunks/platform.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
2
|
import { homedir, platform } from 'node:os';
|
|
3
3
|
import process__default from 'node:process';
|
|
4
4
|
import { dirname } from 'pathe';
|
|
@@ -14,7 +14,7 @@ function getPlatform() {
|
|
|
14
14
|
return "linux";
|
|
15
15
|
}
|
|
16
16
|
function isTermux() {
|
|
17
|
-
return !!(process__default.env.PREFIX && process__default.env.PREFIX.includes("com.termux")) || !!process__default.env.TERMUX_VERSION ||
|
|
17
|
+
return !!(process__default.env.PREFIX && process__default.env.PREFIX.includes("com.termux")) || !!process__default.env.TERMUX_VERSION || fs.existsSync("/data/data/com.termux/files/usr");
|
|
18
18
|
}
|
|
19
19
|
function getTermuxPrefix() {
|
|
20
20
|
return process__default.env.PREFIX || "/data/data/com.termux/files/usr";
|
|
@@ -26,16 +26,16 @@ function isWSL() {
|
|
|
26
26
|
if (process__default.env.WSL_DISTRO_NAME) {
|
|
27
27
|
return true;
|
|
28
28
|
}
|
|
29
|
-
if (
|
|
29
|
+
if (fs.existsSync("/proc/version")) {
|
|
30
30
|
try {
|
|
31
|
-
const version =
|
|
31
|
+
const version = fs.readFileSync("/proc/version", "utf8");
|
|
32
32
|
if (version.includes("Microsoft") || version.includes("WSL")) {
|
|
33
33
|
return true;
|
|
34
34
|
}
|
|
35
35
|
} catch {
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
if (
|
|
38
|
+
if (fs.existsSync("/mnt/c")) {
|
|
39
39
|
return true;
|
|
40
40
|
}
|
|
41
41
|
return false;
|
|
@@ -44,9 +44,9 @@ function getWSLDistro() {
|
|
|
44
44
|
if (process__default.env.WSL_DISTRO_NAME) {
|
|
45
45
|
return process__default.env.WSL_DISTRO_NAME;
|
|
46
46
|
}
|
|
47
|
-
if (
|
|
47
|
+
if (fs.existsSync("/etc/os-release")) {
|
|
48
48
|
try {
|
|
49
|
-
const osRelease =
|
|
49
|
+
const osRelease = fs.readFileSync("/etc/os-release", "utf8");
|
|
50
50
|
const nameMatch = osRelease.match(/^PRETTY_NAME="(.+)"$/m);
|
|
51
51
|
if (nameMatch) {
|
|
52
52
|
return nameMatch[1];
|
|
@@ -61,9 +61,9 @@ function getWSLInfo() {
|
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
63
|
let version = null;
|
|
64
|
-
if (
|
|
64
|
+
if (fs.existsSync("/proc/version")) {
|
|
65
65
|
try {
|
|
66
|
-
version =
|
|
66
|
+
version = fs.readFileSync("/proc/version", "utf8").trim();
|
|
67
67
|
} catch {
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -140,7 +140,7 @@ function isPathInsideHome(path) {
|
|
|
140
140
|
}
|
|
141
141
|
function canWriteToPath(path) {
|
|
142
142
|
try {
|
|
143
|
-
|
|
143
|
+
fs.accessSync(path, WRITE_CHECK_FLAG);
|
|
144
144
|
return true;
|
|
145
145
|
} catch {
|
|
146
146
|
return false;
|
|
@@ -175,7 +175,7 @@ async function commandExists(command) {
|
|
|
175
175
|
`/data/data/com.termux/files/usr/bin/${command}`
|
|
176
176
|
];
|
|
177
177
|
for (const path of possiblePaths) {
|
|
178
|
-
if (
|
|
178
|
+
if (fs.existsSync(path)) {
|
|
179
179
|
return true;
|
|
180
180
|
}
|
|
181
181
|
}
|
|
@@ -189,14 +189,14 @@ async function commandExists(command) {
|
|
|
189
189
|
`${home}/.local/bin/${command}`
|
|
190
190
|
];
|
|
191
191
|
for (const path of commonPaths) {
|
|
192
|
-
if (
|
|
192
|
+
if (fs.existsSync(path)) {
|
|
193
193
|
return true;
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
if (getPlatform() === "macos") {
|
|
197
197
|
const homebrewPaths = await getHomebrewCommandPaths(command);
|
|
198
198
|
for (const path of homebrewPaths) {
|
|
199
|
-
if (
|
|
199
|
+
if (fs.existsSync(path)) {
|
|
200
200
|
return true;
|
|
201
201
|
}
|
|
202
202
|
}
|
|
@@ -217,9 +217,9 @@ async function getHomebrewCommandPaths(command) {
|
|
|
217
217
|
}
|
|
218
218
|
for (const prefix of homebrewPrefixes) {
|
|
219
219
|
const cellarNodePath = `${prefix}/Cellar/node`;
|
|
220
|
-
if (
|
|
220
|
+
if (fs.existsSync(cellarNodePath)) {
|
|
221
221
|
try {
|
|
222
|
-
const versions =
|
|
222
|
+
const versions = fs.readdirSync(cellarNodePath);
|
|
223
223
|
for (const version of versions) {
|
|
224
224
|
const binPath = `${cellarNodePath}/${version}/bin/${command}`;
|
|
225
225
|
paths.push(binPath);
|
|
@@ -236,9 +236,9 @@ async function getHomebrewCommandPaths(command) {
|
|
|
236
236
|
if (caskName) {
|
|
237
237
|
for (const prefix of homebrewPrefixes) {
|
|
238
238
|
const caskroomPath = `${prefix}/Caskroom/${caskName}`;
|
|
239
|
-
if (
|
|
239
|
+
if (fs.existsSync(caskroomPath)) {
|
|
240
240
|
try {
|
|
241
|
-
const versions =
|
|
241
|
+
const versions = fs.readdirSync(caskroomPath).filter((v) => !v.startsWith("."));
|
|
242
242
|
for (const version of versions) {
|
|
243
243
|
const binPath = `${caskroomPath}/${version}/${command}`;
|
|
244
244
|
paths.push(binPath);
|
|
@@ -267,14 +267,14 @@ async function findCommandPath(command) {
|
|
|
267
267
|
`${home}/.local/bin/${command}`
|
|
268
268
|
];
|
|
269
269
|
for (const path of commonPaths) {
|
|
270
|
-
if (
|
|
270
|
+
if (fs.existsSync(path)) {
|
|
271
271
|
return path;
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
if (getPlatform() === "macos") {
|
|
275
275
|
const homebrewPaths = await getHomebrewCommandPaths(command);
|
|
276
276
|
for (const path of homebrewPaths) {
|
|
277
|
-
if (
|
|
277
|
+
if (fs.existsSync(path)) {
|
|
278
278
|
return path;
|
|
279
279
|
}
|
|
280
280
|
}
|
|
@@ -286,7 +286,56 @@ async function findCommandPath(command) {
|
|
|
286
286
|
`${termuxPrefix}/usr/bin/${command}`
|
|
287
287
|
];
|
|
288
288
|
for (const path of termuxPaths) {
|
|
289
|
-
if (
|
|
289
|
+
if (fs.existsSync(path)) {
|
|
290
|
+
return path;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
async function findRealCommandPath(command) {
|
|
297
|
+
const platform2 = getPlatform();
|
|
298
|
+
if (platform2 !== "windows") {
|
|
299
|
+
try {
|
|
300
|
+
const res = await exec("bash", ["-c", `type -P ${command}`]);
|
|
301
|
+
if (res.exitCode === 0 && res.stdout) {
|
|
302
|
+
const path = res.stdout.trim();
|
|
303
|
+
if (path && fs.existsSync(path)) {
|
|
304
|
+
return path;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
} catch {
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const home = homedir();
|
|
311
|
+
const commonPaths = [
|
|
312
|
+
`/usr/local/bin/${command}`,
|
|
313
|
+
`/opt/homebrew/bin/${command}`,
|
|
314
|
+
`/usr/bin/${command}`,
|
|
315
|
+
`/bin/${command}`,
|
|
316
|
+
`${home}/.local/bin/${command}`
|
|
317
|
+
];
|
|
318
|
+
for (const path of commonPaths) {
|
|
319
|
+
if (fs.existsSync(path)) {
|
|
320
|
+
return path;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (platform2 === "macos") {
|
|
324
|
+
const homebrewPaths = await getHomebrewCommandPaths(command);
|
|
325
|
+
for (const path of homebrewPaths) {
|
|
326
|
+
if (fs.existsSync(path)) {
|
|
327
|
+
return path;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (isTermux()) {
|
|
332
|
+
const termuxPrefix = getTermuxPrefix();
|
|
333
|
+
const termuxPaths = [
|
|
334
|
+
`${termuxPrefix}/bin/${command}`,
|
|
335
|
+
`${termuxPrefix}/usr/bin/${command}`
|
|
336
|
+
];
|
|
337
|
+
for (const path of termuxPaths) {
|
|
338
|
+
if (fs.existsSync(path)) {
|
|
290
339
|
return path;
|
|
291
340
|
}
|
|
292
341
|
}
|
|
@@ -318,4 +367,4 @@ function getRecommendedInstallMethods(codeType) {
|
|
|
318
367
|
return ["npm"];
|
|
319
368
|
}
|
|
320
369
|
|
|
321
|
-
export { commandExists, findCommandPath, getHomebrewCommandPaths, getMcpCommand, getPlatform, getRecommendedInstallMethods, getSystemRoot, getTermuxPrefix, getWSLDistro, getWSLInfo, isTermux, isWSL, isWindows, normalizeTomlPath, shouldUseSudoForGlobalInstall, wrapCommandWithSudo };
|
|
370
|
+
export { commandExists, findCommandPath, findRealCommandPath, getHomebrewCommandPaths, getMcpCommand, getPlatform, getRecommendedInstallMethods, getSystemRoot, getTermuxPrefix, getWSLDistro, getWSLInfo, isTermux, isWSL, isWindows, normalizeTomlPath, shouldUseSudoForGlobalInstall, wrapCommandWithSudo };
|
|
@@ -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 };
|
|
@@ -121,7 +121,7 @@ function extractMetadata(data, filePath) {
|
|
|
121
121
|
return metadata;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
const CLOUD_API_BASE_URL = process__default.env.CCJK_CLOUD_API_URL || "https://api.
|
|
124
|
+
const CLOUD_API_BASE_URL = process__default.env.CCJK_CLOUD_API_URL || "https://api.api.claudehome.cn/v1";
|
|
125
125
|
const SYNC_STATE_FILE = join(CCJK_CONFIG_DIR, "skills-sync-state.json");
|
|
126
126
|
const DEFAULT_TIMEOUT = 3e4;
|
|
127
127
|
function loadSyncState() {
|