cc-x10ded 3.0.15 โ†’ 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-x10ded",
3
- "version": "3.0.15",
3
+ "version": "3.0.17",
4
4
  "description": "Extend Claude Code with custom OpenAI-compatible model providers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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 Config
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
- issues.push("โŒ No API keys configured. Run 'ccx setup'.");
59
+ issues.push("โŒ No API keys configured. Run 'ccx setup'.");
21
60
  } else {
22
- checks.push("โœ… Configuration loaded");
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
- // 2. Check Claude Binary
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
- checks.push(`โœ… Claude binary found: ${claudePath}`);
75
+ checks.push(`โœ… Claude binary: ${claudePath}`);
33
76
  } else {
34
- issues.push("โŒ 'claude' command not found in common locations.");
35
- issues.push(" ๐Ÿ‘‰ Suggestion: Run 'npm install -g @anthropic-ai/claude-code'");
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
- // 3. Check Shell Integration
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
- issues.push("โš ๏ธ Could not detect shell type.");
88
+ warnings.push("โš ๏ธ Could not detect shell type.");
46
89
  } else {
47
- checks.push(`โœ… Shell detected: ${shell}`);
48
- if (profile && existsSync(profile)) {
49
- const content = await Bun.file(profile).text();
50
- if (content.includes("ccx")) {
51
- checks.push("โœ… Aliases found in profile");
52
- } else {
53
- issues.push(`โš ๏ธ Aliases missing in ${profile}. Run 'ccx setup'.`);
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
- // 4. Check Network/Proxy (Port 17870)
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
- console.log("");
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
- issues.forEach(i => console.log(i));
68
- outro(pc.yellow("Issues found. Please resolve them above."));
69
- process.exit(1);
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
- outro(pc.green("All systems operational! ๐Ÿš€"));
125
+ outro(pc.green("All systems operational! ๐Ÿš€"));
72
126
  }
73
127
  }
@@ -88,21 +88,32 @@ export async function setupCommand() {
88
88
  if (mmKey) config.minimaxApiKey = mmKey as string;
89
89
  }
90
90
 
91
- // 4. Install ccx globally
91
+ // 4. Clean up old binaries and install ccx globally
92
92
  const s2 = spinner();
93
- s2.start("Installing ccx globally...");
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
- s2.stop(pc.green("ccx installed globally!"));
111
+ s3.stop(pc.green("ccx installed globally!"));
101
112
  } else {
102
- s2.stop(pc.yellow("Global install may have failed. You can still use: bunx cc-x10ded"));
113
+ s3.stop(pc.yellow("Global install may have failed. You can still use: bunx cc-x10ded"));
103
114
  }
104
115
  } catch {
105
- s2.stop(pc.yellow("Could not install globally (bun not found?). Use: bunx cc-x10ded"));
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
@@ -22,15 +22,27 @@ cli
22
22
 
23
23
  cli
24
24
  .command("update", "Update ccx to the latest version")
25
- .option("--migrate-aliases", "Also migrate old bunx-based aliases to new format")
26
- .action(async (options: { migrateAliases?: boolean }) => {
25
+ .option("--skip-aliases", "Skip alias installation")
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
- console.log(pc.default.blue("Updating ccx..."));
32
+ const shellInt = new ShellIntegrator();
33
+ const shell = shellInt.detectShell();
32
34
 
33
- // Update via bun global install
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,19 +55,29 @@ cli
43
55
 
44
56
  console.log(pc.default.green("โœ… ccx updated!"));
45
57
 
46
- // Migrate aliases
47
- const shellInt = new ShellIntegrator();
48
- const shell = shellInt.detectShell();
49
-
58
+ // 3. Ensure bun bin is in PATH (and prioritized)
50
59
  if (shell !== "unknown") {
51
- const migrated = await shellInt.migrateAliases(shell);
52
- if (migrated) {
53
- console.log(pc.default.green("โœ… Aliases migrated to new format!"));
54
- console.log(pc.default.dim(` Run: source ~/.${shell}rc (or restart your terminal)`));
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!"));
55
74
  }
56
75
  }
57
76
 
58
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
+ }
59
81
  });
60
82
 
61
83
  cli