cc-x10ded 3.0.16 โ 3.0.17
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/package.json +1 -1
- package/src/commands/doctor.ts +84 -30
- package/src/commands/setup.ts +16 -5
- package/src/core/shell.ts +47 -0
- package/src/index.ts +34 -18
package/package.json
CHANGED
package/src/commands/doctor.ts
CHANGED
|
@@ -3,71 +3,125 @@ import { ShellIntegrator } from "../core/shell";
|
|
|
3
3
|
import { ConfigManager } from "../core/config";
|
|
4
4
|
import * as pc from "picocolors";
|
|
5
5
|
import { existsSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { homedir } from "os";
|
|
6
8
|
|
|
7
9
|
export async function doctorCommand() {
|
|
8
10
|
intro(pc.bgBlue(pc.white(" ccx Doctor ๐ฉบ ")));
|
|
9
11
|
|
|
10
12
|
const s = spinner();
|
|
11
13
|
const issues: string[] = [];
|
|
14
|
+
const warnings: string[] = [];
|
|
12
15
|
const checks: string[] = [];
|
|
16
|
+
const home = homedir();
|
|
13
17
|
|
|
14
|
-
// 1. Check
|
|
18
|
+
// 1. Check for old/shadowing binaries
|
|
19
|
+
s.start("Checking for conflicting binaries...");
|
|
20
|
+
const oldLocations = [
|
|
21
|
+
join(home, ".local", "bin", "ccx"),
|
|
22
|
+
join(home, ".npm-global", "bin", "ccx"),
|
|
23
|
+
join(home, "bin", "ccx"),
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const foundOld: string[] = [];
|
|
27
|
+
for (const loc of oldLocations) {
|
|
28
|
+
if (existsSync(loc)) foundOld.push(loc);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (foundOld.length > 0) {
|
|
32
|
+
issues.push("โ Old ccx binaries found that may shadow the new one:");
|
|
33
|
+
foundOld.forEach(p => issues.push(` ${p}`));
|
|
34
|
+
issues.push(" ๐ Run 'ccx update' to remove them automatically");
|
|
35
|
+
} else {
|
|
36
|
+
checks.push("โ
No conflicting binaries");
|
|
37
|
+
}
|
|
38
|
+
s.stop("Binary check complete");
|
|
39
|
+
|
|
40
|
+
// 2. Check PATH priority
|
|
41
|
+
s.start("Checking PATH configuration...");
|
|
42
|
+
const shellInt = new ShellIntegrator();
|
|
43
|
+
|
|
44
|
+
if (!shellInt.isBunBinFirst()) {
|
|
45
|
+
warnings.push("โ ๏ธ ~/.bun/bin is not first in PATH");
|
|
46
|
+
warnings.push(" This may cause the wrong ccx to run.");
|
|
47
|
+
warnings.push(' ๐ Add to TOP of your shell config: export PATH="$HOME/.bun/bin:$PATH"');
|
|
48
|
+
} else {
|
|
49
|
+
checks.push("โ
PATH is correctly configured");
|
|
50
|
+
}
|
|
51
|
+
s.stop("PATH check complete");
|
|
52
|
+
|
|
53
|
+
// 3. Check Config
|
|
15
54
|
s.start("Checking configuration...");
|
|
16
55
|
const configManager = new ConfigManager();
|
|
17
56
|
const config = await configManager.read();
|
|
18
|
-
|
|
57
|
+
|
|
19
58
|
if (!config.zaiApiKey && !config.minimaxApiKey && Object.keys(config.providers).length === 0) {
|
|
20
|
-
|
|
59
|
+
issues.push("โ No API keys configured. Run 'ccx setup'.");
|
|
21
60
|
} else {
|
|
22
|
-
|
|
61
|
+
const keys = [];
|
|
62
|
+
if (config.zaiApiKey) keys.push("Z.AI");
|
|
63
|
+
if (config.minimaxApiKey) keys.push("Minimax");
|
|
64
|
+
if (config.providers.openai?.apiKey) keys.push("OpenAI");
|
|
65
|
+
if (config.providers.gemini?.apiKey) keys.push("Gemini");
|
|
66
|
+
checks.push(`โ
API keys configured: ${keys.join(", ")}`);
|
|
23
67
|
}
|
|
24
68
|
s.stop("Configuration check complete");
|
|
25
69
|
|
|
26
|
-
//
|
|
70
|
+
// 4. Check Claude Binary
|
|
27
71
|
s.start("Checking Claude Code installation...");
|
|
28
|
-
const shellInt = new ShellIntegrator();
|
|
29
72
|
const claudePath = await shellInt.findClaudeBinary();
|
|
30
|
-
|
|
73
|
+
|
|
31
74
|
if (claudePath) {
|
|
32
|
-
|
|
75
|
+
checks.push(`โ
Claude binary: ${claudePath}`);
|
|
33
76
|
} else {
|
|
34
|
-
|
|
35
|
-
|
|
77
|
+
issues.push("โ 'claude' command not found.");
|
|
78
|
+
issues.push(" ๐ Run: npm install -g @anthropic-ai/claude-code");
|
|
36
79
|
}
|
|
37
80
|
s.stop("Claude check complete");
|
|
38
81
|
|
|
39
|
-
//
|
|
82
|
+
// 5. Check Shell Integration
|
|
40
83
|
s.start("Checking shell integration...");
|
|
41
84
|
const shell = shellInt.detectShell();
|
|
42
85
|
const profile = shellInt.getProfilePath(shell);
|
|
43
|
-
|
|
86
|
+
|
|
44
87
|
if (shell === "unknown") {
|
|
45
|
-
|
|
88
|
+
warnings.push("โ ๏ธ Could not detect shell type.");
|
|
46
89
|
} else {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
90
|
+
checks.push(`โ
Shell: ${shell}`);
|
|
91
|
+
if (profile && existsSync(profile)) {
|
|
92
|
+
const content = await Bun.file(profile).text();
|
|
93
|
+
if (content.includes("claude-glm-wrapper")) {
|
|
94
|
+
// Check if using old bunx-based aliases
|
|
95
|
+
if (content.includes("bunx cc-x10ded")) {
|
|
96
|
+
warnings.push("โ ๏ธ Old bunx-based aliases detected");
|
|
97
|
+
warnings.push(" ๐ Run 'ccx update' to migrate to faster direct aliases");
|
|
98
|
+
} else {
|
|
99
|
+
checks.push("โ
Aliases installed (new format)");
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
warnings.push(`โ ๏ธ Aliases missing. Run 'ccx setup' to install.`);
|
|
55
103
|
}
|
|
104
|
+
}
|
|
56
105
|
}
|
|
57
106
|
s.stop("Shell check complete");
|
|
58
107
|
|
|
59
|
-
//
|
|
60
|
-
// We won't actually bind, just check if we can
|
|
61
|
-
|
|
108
|
+
// Report
|
|
62
109
|
console.log("\n" + pc.bold("Diagnostic Report:"));
|
|
63
110
|
checks.forEach(c => console.log(c));
|
|
64
|
-
|
|
65
|
-
|
|
111
|
+
|
|
112
|
+
if (warnings.length > 0) {
|
|
113
|
+
console.log("");
|
|
114
|
+
warnings.forEach(w => console.log(pc.yellow(w)));
|
|
115
|
+
}
|
|
116
|
+
|
|
66
117
|
if (issues.length > 0) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
118
|
+
console.log("");
|
|
119
|
+
issues.forEach(i => console.log(pc.red(i)));
|
|
120
|
+
outro(pc.red("Issues found. Please resolve them above."));
|
|
121
|
+
process.exit(1);
|
|
122
|
+
} else if (warnings.length > 0) {
|
|
123
|
+
outro(pc.yellow("Some warnings. ccx should work, but consider fixing them."));
|
|
70
124
|
} else {
|
|
71
|
-
|
|
125
|
+
outro(pc.green("All systems operational! ๐"));
|
|
72
126
|
}
|
|
73
127
|
}
|
package/src/commands/setup.ts
CHANGED
|
@@ -88,21 +88,32 @@ export async function setupCommand() {
|
|
|
88
88
|
if (mmKey) config.minimaxApiKey = mmKey as string;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
// 4.
|
|
91
|
+
// 4. Clean up old binaries and install ccx globally
|
|
92
92
|
const s2 = spinner();
|
|
93
|
-
s2.start("
|
|
93
|
+
s2.start("Cleaning up old installations...");
|
|
94
|
+
|
|
95
|
+
// Remove old binaries that might shadow the new one
|
|
96
|
+
const removed = await shellInt.cleanupOldBinaries();
|
|
97
|
+
if (removed.length > 0) {
|
|
98
|
+
s2.stop(pc.yellow(`Removed ${removed.length} old ccx binary(s)`));
|
|
99
|
+
} else {
|
|
100
|
+
s2.stop("No old binaries found");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const s3 = spinner();
|
|
104
|
+
s3.start("Installing ccx globally...");
|
|
94
105
|
try {
|
|
95
106
|
const proc = spawn(["bun", "install", "-g", "cc-x10ded@latest"], {
|
|
96
107
|
stdio: ["ignore", "ignore", "ignore"]
|
|
97
108
|
});
|
|
98
109
|
await proc.exited;
|
|
99
110
|
if (proc.exitCode === 0) {
|
|
100
|
-
|
|
111
|
+
s3.stop(pc.green("ccx installed globally!"));
|
|
101
112
|
} else {
|
|
102
|
-
|
|
113
|
+
s3.stop(pc.yellow("Global install may have failed. You can still use: bunx cc-x10ded"));
|
|
103
114
|
}
|
|
104
115
|
} catch {
|
|
105
|
-
|
|
116
|
+
s3.stop(pc.yellow("Could not install globally (bun not found?). Use: bunx cc-x10ded"));
|
|
106
117
|
}
|
|
107
118
|
|
|
108
119
|
// 5. Shell Config
|
package/src/core/shell.ts
CHANGED
|
@@ -180,6 +180,53 @@ Function ccm { ccx --model=MiniMax-M2.1 @args }`;
|
|
|
180
180
|
return await this.installAliases(shell);
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Remove old ccx binaries from common locations that might shadow the bun global
|
|
185
|
+
*/
|
|
186
|
+
async cleanupOldBinaries(): Promise<string[]> {
|
|
187
|
+
const removed: string[] = [];
|
|
188
|
+
const oldLocations = [
|
|
189
|
+
join(this.home, ".local", "bin", "ccx"),
|
|
190
|
+
join(this.home, ".npm-global", "bin", "ccx"),
|
|
191
|
+
join(this.home, "bin", "ccx"),
|
|
192
|
+
"/usr/local/bin/ccx",
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
for (const loc of oldLocations) {
|
|
196
|
+
if (existsSync(loc)) {
|
|
197
|
+
try {
|
|
198
|
+
const { unlinkSync } = await import("fs");
|
|
199
|
+
unlinkSync(loc);
|
|
200
|
+
removed.push(loc);
|
|
201
|
+
} catch {
|
|
202
|
+
// Ignore permission errors
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return removed;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Check if bun bin is properly prioritized in PATH
|
|
212
|
+
*/
|
|
213
|
+
isBunBinFirst(): boolean {
|
|
214
|
+
const bunBin = join(this.home, ".bun", "bin");
|
|
215
|
+
const path = process.env.PATH || "";
|
|
216
|
+
const paths = path.split(":");
|
|
217
|
+
|
|
218
|
+
// Check if bun bin comes before other common locations
|
|
219
|
+
const bunIndex = paths.findIndex(p => p.includes(".bun/bin"));
|
|
220
|
+
const localIndex = paths.findIndex(p => p.includes(".local/bin"));
|
|
221
|
+
const npmGlobalIndex = paths.findIndex(p => p.includes(".npm-global/bin"));
|
|
222
|
+
|
|
223
|
+
if (bunIndex === -1) return false;
|
|
224
|
+
if (localIndex !== -1 && localIndex < bunIndex) return false;
|
|
225
|
+
if (npmGlobalIndex !== -1 && npmGlobalIndex < bunIndex) return false;
|
|
226
|
+
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
|
|
183
230
|
/**
|
|
184
231
|
* Hunt for the 'claude' binary in common locations
|
|
185
232
|
*/
|
package/src/index.ts
CHANGED
|
@@ -23,14 +23,26 @@ cli
|
|
|
23
23
|
cli
|
|
24
24
|
.command("update", "Update ccx to the latest version")
|
|
25
25
|
.option("--skip-aliases", "Skip alias installation")
|
|
26
|
-
.
|
|
26
|
+
.option("--skip-cleanup", "Skip removal of old binaries")
|
|
27
|
+
.action(async (options: { skipAliases?: boolean; skipCleanup?: boolean }) => {
|
|
27
28
|
const { spawn } = await import("bun");
|
|
28
29
|
const { ShellIntegrator } = await import("./core/shell");
|
|
29
30
|
const pc = await import("picocolors");
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
const shellInt = new ShellIntegrator();
|
|
33
|
+
const shell = shellInt.detectShell();
|
|
32
34
|
|
|
33
|
-
//
|
|
35
|
+
// 1. Clean up old binaries first
|
|
36
|
+
if (!options.skipCleanup) {
|
|
37
|
+
const removed = await shellInt.cleanupOldBinaries();
|
|
38
|
+
if (removed.length > 0) {
|
|
39
|
+
console.log(pc.default.yellow("๐งน Removed old ccx binaries:"));
|
|
40
|
+
removed.forEach(p => console.log(pc.default.dim(` ${p}`)));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 2. Update via bun global install
|
|
45
|
+
console.log(pc.default.blue("๐ฆ Updating ccx..."));
|
|
34
46
|
const proc = spawn(["bun", "install", "-g", "cc-x10ded@latest"], {
|
|
35
47
|
stdio: ["inherit", "inherit", "inherit"]
|
|
36
48
|
});
|
|
@@ -43,25 +55,29 @@ cli
|
|
|
43
55
|
|
|
44
56
|
console.log(pc.default.green("โ
ccx updated!"));
|
|
45
57
|
|
|
46
|
-
//
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
// 3. Ensure bun bin is in PATH (and prioritized)
|
|
59
|
+
if (shell !== "unknown") {
|
|
60
|
+
await shellInt.ensureBunBinInPath(shell);
|
|
61
|
+
|
|
62
|
+
if (!shellInt.isBunBinFirst()) {
|
|
63
|
+
console.log(pc.default.yellow("โ ๏ธ ~/.bun/bin should be first in PATH for ccx to work correctly."));
|
|
64
|
+
console.log(pc.default.dim(" Add this to the TOP of your shell config:"));
|
|
65
|
+
console.log(pc.default.cyan(' export PATH="$HOME/.bun/bin:$PATH"'));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 4. Reinstall aliases (unless skipped)
|
|
70
|
+
if (!options.skipAliases && shell !== "unknown") {
|
|
71
|
+
const success = await shellInt.installAliases(shell);
|
|
72
|
+
if (success) {
|
|
73
|
+
console.log(pc.default.green("โ
Aliases updated!"));
|
|
61
74
|
}
|
|
62
75
|
}
|
|
63
76
|
|
|
64
77
|
console.log(pc.default.green("\n๐ Update complete!"));
|
|
78
|
+
if (shell !== "unknown") {
|
|
79
|
+
console.log(pc.default.dim(` Run: source ~/.${shell}rc (or restart your terminal)`));
|
|
80
|
+
}
|
|
65
81
|
});
|
|
66
82
|
|
|
67
83
|
cli
|