claude-ai-switcher 1.1.4
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/AGENTS.md +265 -0
- package/ARCHITECTURE.md +162 -0
- package/CLAUDE.md +267 -0
- package/LICENSE +21 -0
- package/QWEN.md +429 -0
- package/README.md +833 -0
- package/dist/clients/claude-code.d.ts +92 -0
- package/dist/clients/claude-code.d.ts.map +1 -0
- package/dist/clients/claude-code.js +312 -0
- package/dist/clients/claude-code.js.map +1 -0
- package/dist/clients/opencode.d.ts +71 -0
- package/dist/clients/opencode.d.ts.map +1 -0
- package/dist/clients/opencode.js +604 -0
- package/dist/clients/opencode.js.map +1 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +122 -0
- package/dist/config.js.map +1 -0
- package/dist/display.d.ts +51 -0
- package/dist/display.d.ts.map +1 -0
- package/dist/display.js +118 -0
- package/dist/display.js.map +1 -0
- package/dist/hooks/index.d.ts +60 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +223 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/token-tracker.js +280 -0
- package/dist/hooks/visual-enhancements.js +364 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1091 -0
- package/dist/index.js.map +1 -0
- package/dist/models.d.ts +34 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +343 -0
- package/dist/models.js.map +1 -0
- package/dist/providers/alibaba.d.ts +25 -0
- package/dist/providers/alibaba.d.ts.map +1 -0
- package/dist/providers/alibaba.js +37 -0
- package/dist/providers/alibaba.js.map +1 -0
- package/dist/providers/anthropic.d.ts +14 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +19 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +44 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +156 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/glm.d.ts +25 -0
- package/dist/providers/glm.d.ts.map +1 -0
- package/dist/providers/glm.js +89 -0
- package/dist/providers/glm.js.map +1 -0
- package/dist/providers/ollama.d.ts +48 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +174 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openrouter.d.ts +24 -0
- package/dist/providers/openrouter.d.ts.map +1 -0
- package/dist/providers/openrouter.js +36 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/verify.d.ts +24 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +262 -0
- package/dist/verify.js.map +1 -0
- package/package.json +57 -0
- package/scripts/copy-hooks.js +15 -0
- package/src/clients/claude-code.ts +340 -0
- package/src/clients/opencode.ts +618 -0
- package/src/config.ts +101 -0
- package/src/display.ts +151 -0
- package/src/hooks/index.ts +208 -0
- package/src/hooks/token-tracker.js +280 -0
- package/src/hooks/visual-enhancements.js +364 -0
- package/src/index.ts +1263 -0
- package/src/models.ts +366 -0
- package/src/providers/alibaba.ts +43 -0
- package/src/providers/anthropic.ts +23 -0
- package/src/providers/gemini.ts +136 -0
- package/src/providers/glm.ts +60 -0
- package/src/providers/ollama.ts +146 -0
- package/src/providers/openrouter.ts +42 -0
- package/src/verify.ts +258 -0
- package/tsconfig.json +19 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1091 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Claude AI Switcher
|
|
5
|
+
*
|
|
6
|
+
* Switch between AI providers (Anthropic, GLM, Alibaba Qwen) for Claude Code.
|
|
7
|
+
* Also provides helper commands to add/remove Alibaba Coding Plan provider for OpenCode.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
43
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
|
+
};
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
const commander_1 = require("commander");
|
|
47
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
48
|
+
const readline = __importStar(require("readline"));
|
|
49
|
+
const fs = __importStar(require("fs-extra"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const models_1 = require("./models");
|
|
52
|
+
const claude_code_1 = require("./clients/claude-code");
|
|
53
|
+
const opencode_1 = require("./clients/opencode");
|
|
54
|
+
const config_1 = require("./config");
|
|
55
|
+
const display_1 = require("./display");
|
|
56
|
+
const glm_1 = require("./providers/glm");
|
|
57
|
+
const ollama_1 = require("./providers/ollama");
|
|
58
|
+
const gemini_1 = require("./providers/gemini");
|
|
59
|
+
const verify_1 = require("./verify");
|
|
60
|
+
const index_1 = require("./hooks/index");
|
|
61
|
+
// Read version from package.json at runtime so `claude-switch --version` never drifts.
|
|
62
|
+
// package.json lives outside src/rootDir, so resolve it relative to this compiled file.
|
|
63
|
+
const pkgVersion = fs.readJsonSync(path.join(__dirname, "..", "package.json")).version;
|
|
64
|
+
const program = new commander_1.Command();
|
|
65
|
+
program
|
|
66
|
+
.name("claude-switch")
|
|
67
|
+
.description("Switch between AI providers for Claude Code. Also provides OpenCode helper commands.")
|
|
68
|
+
.version(pkgVersion);
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Helpers
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
async function promptApiKey(provider, helpUrl) {
|
|
73
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
74
|
+
console.log(chalk_1.default.yellow(`\n⚠ ${provider} API Key not found`));
|
|
75
|
+
console.log(chalk_1.default.dim(` Get your API key from: ${helpUrl}`));
|
|
76
|
+
console.log();
|
|
77
|
+
const answer = await new Promise((resolve) => {
|
|
78
|
+
rl.question(`Enter your ${provider} API Key: `, resolve);
|
|
79
|
+
});
|
|
80
|
+
rl.close();
|
|
81
|
+
if (!answer.trim()) {
|
|
82
|
+
(0, display_1.displayError)("API Key is required");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
return answer.trim();
|
|
86
|
+
}
|
|
87
|
+
function buildTierMap(defaultMap, opts) {
|
|
88
|
+
return {
|
|
89
|
+
opus: opts.opus || defaultMap.opus,
|
|
90
|
+
sonnet: opts.sonnet || defaultMap.sonnet,
|
|
91
|
+
haiku: opts.haiku || defaultMap.haiku
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function displayTierMap(tierMap) {
|
|
95
|
+
console.log(chalk_1.default.dim(" Claude model aliases:"));
|
|
96
|
+
console.log(chalk_1.default.dim(` ANTHROPIC_DEFAULT_OPUS_MODEL → ${tierMap.opus}`));
|
|
97
|
+
console.log(chalk_1.default.dim(` ANTHROPIC_DEFAULT_SONNET_MODEL → ${tierMap.sonnet}`));
|
|
98
|
+
console.log(chalk_1.default.dim(` ANTHROPIC_DEFAULT_HAIKU_MODEL → ${tierMap.haiku}`));
|
|
99
|
+
}
|
|
100
|
+
function addTierOptions(cmd) {
|
|
101
|
+
return cmd
|
|
102
|
+
.option("--opus <model>", "Override opus tier model alias")
|
|
103
|
+
.option("--sonnet <model>", "Override sonnet tier model alias")
|
|
104
|
+
.option("--haiku <model>", "Override haiku tier model alias");
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Provider switch implementations (Claude Code)
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
async function switchAnthropic() {
|
|
110
|
+
await (0, claude_code_1.configureAnthropic)();
|
|
111
|
+
(0, display_1.displaySuccess)("Switched to Anthropic (default)");
|
|
112
|
+
console.log(chalk_1.default.dim(" Provider: Anthropic"));
|
|
113
|
+
console.log(chalk_1.default.dim(" Using native Claude models"));
|
|
114
|
+
console.log();
|
|
115
|
+
}
|
|
116
|
+
async function switchAlibaba(model, tierOpts) {
|
|
117
|
+
const selectedModel = model || "qwen3.7-plus";
|
|
118
|
+
let apiKey = await (0, config_1.getApiKey)("alibaba");
|
|
119
|
+
if (!apiKey) {
|
|
120
|
+
apiKey = await promptApiKey("Alibaba", "https://modelstudio.console.alibabacloud.com/");
|
|
121
|
+
await (0, config_1.setApiKey)("alibaba", apiKey);
|
|
122
|
+
}
|
|
123
|
+
const alibabaModels = (0, models_1.getModels)("alibaba");
|
|
124
|
+
const validModel = alibabaModels.find((m) => m.id === selectedModel);
|
|
125
|
+
if (!validModel) {
|
|
126
|
+
(0, display_1.displayError)(`Invalid model: ${selectedModel}`);
|
|
127
|
+
console.log(chalk_1.default.dim(" Valid models: ") + alibabaModels.map((m) => m.id).join(", "));
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
const tierMap = buildTierMap((0, models_1.getAlibabaTierMap)(selectedModel), tierOpts);
|
|
131
|
+
await (0, claude_code_1.configureAlibaba)(apiKey, selectedModel, tierMap);
|
|
132
|
+
console.log(chalk_1.default.green(`\n✓ Switched to: Alibaba Coding Plan`));
|
|
133
|
+
console.log(chalk_1.default.dim("─".repeat(60)));
|
|
134
|
+
console.log(` ${chalk_1.default.cyan.bold("Model:")} ${chalk_1.default.white(validModel.name)}`);
|
|
135
|
+
console.log(` ${chalk_1.default.cyan.bold("Context:")} ${chalk_1.default.yellow((0, models_1.formatContext)(validModel.contextWindow))}`);
|
|
136
|
+
console.log(` ${chalk_1.default.cyan.bold("Endpoint:")} ${chalk_1.default.dim("https://coding-intl.dashscope.aliyuncs.com/apps/anthropic")}`);
|
|
137
|
+
console.log(` ${chalk_1.default.cyan.bold("Capabilities:")} ${chalk_1.default.gray(validModel.capabilities.join(", "))}`);
|
|
138
|
+
console.log(chalk_1.default.dim(` ${validModel.description}`));
|
|
139
|
+
console.log();
|
|
140
|
+
displayTierMap(tierMap);
|
|
141
|
+
console.log();
|
|
142
|
+
}
|
|
143
|
+
async function switchGLM(tierOpts) {
|
|
144
|
+
const hasCodingHelper = await (0, glm_1.isCodingHelperInstalled)();
|
|
145
|
+
if (!hasCodingHelper) {
|
|
146
|
+
(0, display_1.displayWarning)("coding-helper not found");
|
|
147
|
+
console.log(chalk_1.default.dim(" Install with: npm install -g @z_ai/coding-helper"));
|
|
148
|
+
console.log(chalk_1.default.dim(" Then run: coding-helper auth"));
|
|
149
|
+
console.log();
|
|
150
|
+
}
|
|
151
|
+
const tierMap = buildTierMap(models_1.GLM_DEFAULT_TIER_MAP, tierOpts);
|
|
152
|
+
await (0, claude_code_1.configureGLM)(tierMap);
|
|
153
|
+
if (hasCodingHelper) {
|
|
154
|
+
const result = await (0, glm_1.reloadGLMConfig)();
|
|
155
|
+
if (!result.success) {
|
|
156
|
+
(0, display_1.displayWarning)("coding-helper reload failed, but local config updated");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
(0, display_1.displaySuccess)("Switched to GLM/Z.AI");
|
|
160
|
+
console.log(chalk_1.default.dim(" Provider: GLM/Z.AI"));
|
|
161
|
+
if (hasCodingHelper)
|
|
162
|
+
console.log(chalk_1.default.dim(" Managed by: coding-helper"));
|
|
163
|
+
console.log();
|
|
164
|
+
displayTierMap(tierMap);
|
|
165
|
+
console.log();
|
|
166
|
+
}
|
|
167
|
+
async function switchOpenRouter(model, tierOpts) {
|
|
168
|
+
const selectedModel = model || "qwen/qwen3.6-plus:free";
|
|
169
|
+
let apiKey = await (0, config_1.getApiKey)("openrouter");
|
|
170
|
+
if (!apiKey) {
|
|
171
|
+
apiKey = await promptApiKey("OpenRouter", "https://openrouter.ai/settings/keys");
|
|
172
|
+
await (0, config_1.setApiKey)("openrouter", apiKey);
|
|
173
|
+
}
|
|
174
|
+
const openrouterModels = (0, models_1.getModels)("openrouter");
|
|
175
|
+
const validModel = openrouterModels.find((m) => m.id === selectedModel);
|
|
176
|
+
if (!validModel) {
|
|
177
|
+
(0, display_1.displayError)(`Invalid model: ${selectedModel}`);
|
|
178
|
+
console.log(chalk_1.default.dim(" Valid models: ") + openrouterModels.map((m) => m.id).join(", "));
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
const tierMap = buildTierMap(models_1.OPENROUTER_DEFAULT_TIER_MAP, tierOpts);
|
|
182
|
+
await (0, claude_code_1.configureOpenRouter)(apiKey, selectedModel, tierMap);
|
|
183
|
+
console.log(chalk_1.default.green(`\n✓ Switched to: OpenRouter`));
|
|
184
|
+
console.log(chalk_1.default.dim("─".repeat(60)));
|
|
185
|
+
console.log(` ${chalk_1.default.cyan.bold("Model:")} ${chalk_1.default.white(validModel.name)}`);
|
|
186
|
+
console.log(` ${chalk_1.default.cyan.bold("Context:")} ${chalk_1.default.yellow((0, models_1.formatContext)(validModel.contextWindow))}`);
|
|
187
|
+
console.log(` ${chalk_1.default.cyan.bold("Endpoint:")} ${chalk_1.default.dim("https://openrouter.ai/api/v1")}`);
|
|
188
|
+
console.log(` ${chalk_1.default.cyan.bold("Capabilities:")} ${chalk_1.default.gray(validModel.capabilities.join(", "))}`);
|
|
189
|
+
console.log(chalk_1.default.dim(` ${validModel.description}`));
|
|
190
|
+
console.log();
|
|
191
|
+
displayTierMap(tierMap);
|
|
192
|
+
console.log();
|
|
193
|
+
}
|
|
194
|
+
async function switchOllama(model, tierOpts) {
|
|
195
|
+
// Pre-flight: check litellm
|
|
196
|
+
const hasLitellm = await (0, ollama_1.isLitellmInstalled)();
|
|
197
|
+
if (!hasLitellm) {
|
|
198
|
+
(0, display_1.displayError)("LiteLLM is required for Ollama support");
|
|
199
|
+
console.log(chalk_1.default.dim(" Install with: pip install 'litellm[proxy]'"));
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
// Pre-flight: check ollama
|
|
203
|
+
const hasOllama = await (0, ollama_1.isOllamaInstalled)();
|
|
204
|
+
if (!hasOllama) {
|
|
205
|
+
(0, display_1.displayError)("Ollama is not installed");
|
|
206
|
+
console.log(chalk_1.default.dim(" Install from: https://ollama.com"));
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
// Check if Ollama is running
|
|
210
|
+
const ollamaRunning = await (0, ollama_1.isOllamaRunning)();
|
|
211
|
+
if (!ollamaRunning) {
|
|
212
|
+
(0, display_1.displayError)("Ollama is not running");
|
|
213
|
+
console.log(chalk_1.default.dim(" Start with: ollama serve"));
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
const selectedModel = model || "deepseek-r1:latest";
|
|
217
|
+
const validModel = (0, ollama_1.findModel)(selectedModel);
|
|
218
|
+
if (!validModel) {
|
|
219
|
+
const ollamaModels = (0, models_1.getModels)("ollama");
|
|
220
|
+
(0, display_1.displayError)(`Invalid model: ${selectedModel}`);
|
|
221
|
+
console.log(chalk_1.default.dim(" Valid models: ") + ollamaModels.map((m) => m.id).join(", "));
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
// Start LiteLLM proxy
|
|
225
|
+
const proxyResult = await (0, ollama_1.startLitellmProxy)(selectedModel);
|
|
226
|
+
if (!proxyResult.success) {
|
|
227
|
+
(0, display_1.displayError)(`Failed to start LiteLLM proxy: ${proxyResult.error}`);
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
const tierMap = buildTierMap(models_1.OLLAMA_DEFAULT_TIER_MAP, tierOpts);
|
|
231
|
+
await (0, claude_code_1.configureOllama)(selectedModel, tierMap);
|
|
232
|
+
console.log(chalk_1.default.green(`\n✓ Switched to: Ollama (Local)`));
|
|
233
|
+
console.log(chalk_1.default.dim("─".repeat(60)));
|
|
234
|
+
console.log(` ${chalk_1.default.cyan.bold("Model:")} ${chalk_1.default.white(validModel.name)}`);
|
|
235
|
+
console.log(` ${chalk_1.default.cyan.bold("Context:")} ${chalk_1.default.yellow((0, models_1.formatContext)(validModel.contextWindow))}`);
|
|
236
|
+
console.log(` ${chalk_1.default.cyan.bold("Endpoint:")} ${chalk_1.default.dim("http://localhost:4000 (LiteLLM proxy)")}`);
|
|
237
|
+
console.log(` ${chalk_1.default.cyan.bold("Capabilities:")} ${chalk_1.default.gray(validModel.capabilities.join(", "))}`);
|
|
238
|
+
console.log(chalk_1.default.dim(` ${validModel.description}`));
|
|
239
|
+
console.log();
|
|
240
|
+
displayTierMap(tierMap);
|
|
241
|
+
console.log();
|
|
242
|
+
}
|
|
243
|
+
async function switchGemini(model, tierOpts) {
|
|
244
|
+
// Pre-flight: check litellm
|
|
245
|
+
const hasLitellm = await (0, gemini_1.isLitellmInstalled)();
|
|
246
|
+
if (!hasLitellm) {
|
|
247
|
+
(0, display_1.displayError)("LiteLLM is required for Gemini support");
|
|
248
|
+
console.log(chalk_1.default.dim(" Install with: pip install 'litellm[proxy]'"));
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
const selectedModel = model || "gemini-2.5-pro";
|
|
252
|
+
const validModel = (0, gemini_1.findModel)(selectedModel);
|
|
253
|
+
if (!validModel) {
|
|
254
|
+
const geminiModels = (0, models_1.getModels)("gemini");
|
|
255
|
+
(0, display_1.displayError)(`Invalid model: ${selectedModel}`);
|
|
256
|
+
console.log(chalk_1.default.dim(" Valid models: ") + geminiModels.map((m) => m.id).join(", "));
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
// Get API key
|
|
260
|
+
let apiKey = await (0, config_1.getApiKey)("gemini");
|
|
261
|
+
if (!apiKey) {
|
|
262
|
+
apiKey = await promptApiKey("Gemini", "https://aistudio.google.com/apikey");
|
|
263
|
+
await (0, config_1.setApiKey)("gemini", apiKey);
|
|
264
|
+
}
|
|
265
|
+
// Start LiteLLM proxy
|
|
266
|
+
const proxyResult = await (0, gemini_1.startGeminiLitellmProxy)(apiKey, selectedModel);
|
|
267
|
+
if (!proxyResult.success) {
|
|
268
|
+
(0, display_1.displayError)(`Failed to start LiteLLM proxy: ${proxyResult.error}`);
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
271
|
+
const tierMap = buildTierMap(models_1.GEMINI_DEFAULT_TIER_MAP, tierOpts);
|
|
272
|
+
await (0, claude_code_1.configureGemini)(apiKey, selectedModel, tierMap);
|
|
273
|
+
console.log(chalk_1.default.green(`\n✓ Switched to: Gemini (Google)`));
|
|
274
|
+
console.log(chalk_1.default.dim("─".repeat(60)));
|
|
275
|
+
console.log(` ${chalk_1.default.cyan.bold("Model:")} ${chalk_1.default.white(validModel.name)}`);
|
|
276
|
+
console.log(` ${chalk_1.default.cyan.bold("Context:")} ${chalk_1.default.yellow((0, models_1.formatContext)(validModel.contextWindow))}`);
|
|
277
|
+
console.log(` ${chalk_1.default.cyan.bold("Endpoint:")} ${chalk_1.default.dim("http://localhost:4001 (LiteLLM proxy)")}`);
|
|
278
|
+
console.log(` ${chalk_1.default.cyan.bold("Capabilities:")} ${chalk_1.default.gray(validModel.capabilities.join(", "))}`);
|
|
279
|
+
console.log(chalk_1.default.dim(` ${validModel.description}`));
|
|
280
|
+
console.log();
|
|
281
|
+
displayTierMap(tierMap);
|
|
282
|
+
console.log();
|
|
283
|
+
}
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
// Top-level commands — Claude Code only
|
|
286
|
+
// ---------------------------------------------------------------------------
|
|
287
|
+
addTierOptions(program
|
|
288
|
+
.command("alibaba [model]")
|
|
289
|
+
.description("Switch Claude Code to Alibaba Coding Plan")).action(async (model, options) => {
|
|
290
|
+
try {
|
|
291
|
+
await switchAlibaba(model, options);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to Alibaba");
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
program
|
|
299
|
+
.command("anthropic")
|
|
300
|
+
.description("Switch Claude Code to Anthropic (default)")
|
|
301
|
+
.action(async () => {
|
|
302
|
+
try {
|
|
303
|
+
await switchAnthropic();
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to Anthropic");
|
|
307
|
+
process.exit(1);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
addTierOptions(program
|
|
311
|
+
.command("glm")
|
|
312
|
+
.description("Switch Claude Code to GLM/Z.AI (requires @z_ai/coding-helper)")).action(async (options) => {
|
|
313
|
+
try {
|
|
314
|
+
await switchGLM(options);
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to GLM");
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
addTierOptions(program
|
|
322
|
+
.command("openrouter [model]")
|
|
323
|
+
.description("Switch Claude Code to OpenRouter")).action(async (model, options) => {
|
|
324
|
+
try {
|
|
325
|
+
await switchOpenRouter(model, options);
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to OpenRouter");
|
|
329
|
+
process.exit(1);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
addTierOptions(program
|
|
333
|
+
.command("ollama [model]")
|
|
334
|
+
.description("Switch Claude Code to Ollama (local models, requires LiteLLM proxy)")).action(async (model, options) => {
|
|
335
|
+
try {
|
|
336
|
+
await switchOllama(model, options);
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to Ollama");
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
addTierOptions(program
|
|
344
|
+
.command("gemini [model]")
|
|
345
|
+
.description("Switch Claude Code to Gemini (Google, requires LiteLLM proxy)")).action(async (model, options) => {
|
|
346
|
+
try {
|
|
347
|
+
await switchGemini(model, options);
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to Gemini");
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// `claude` subcommand — explicit Claude Code targeting
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
const claudeCmd = program
|
|
358
|
+
.command("claude")
|
|
359
|
+
.description("Configure Claude Code (explicit targeting)");
|
|
360
|
+
claudeCmd
|
|
361
|
+
.command("anthropic")
|
|
362
|
+
.description("Switch Claude Code to Anthropic (default)")
|
|
363
|
+
.action(async () => {
|
|
364
|
+
try {
|
|
365
|
+
await switchAnthropic();
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to Anthropic");
|
|
369
|
+
process.exit(1);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
addTierOptions(claudeCmd
|
|
373
|
+
.command("alibaba [model]")
|
|
374
|
+
.description("Switch Claude Code to Alibaba Coding Plan")).action(async (model, options) => {
|
|
375
|
+
try {
|
|
376
|
+
await switchAlibaba(model, options);
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to Alibaba");
|
|
380
|
+
process.exit(1);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
addTierOptions(claudeCmd
|
|
384
|
+
.command("glm")
|
|
385
|
+
.description("Switch Claude Code to GLM/Z.AI (requires @z_ai/coding-helper)")).action(async (options) => {
|
|
386
|
+
try {
|
|
387
|
+
await switchGLM(options);
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to GLM");
|
|
391
|
+
process.exit(1);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
addTierOptions(claudeCmd
|
|
395
|
+
.command("openrouter [model]")
|
|
396
|
+
.description("Switch Claude Code to OpenRouter")).action(async (model, options) => {
|
|
397
|
+
try {
|
|
398
|
+
await switchOpenRouter(model, options);
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to OpenRouter");
|
|
402
|
+
process.exit(1);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
addTierOptions(claudeCmd
|
|
406
|
+
.command("ollama [model]")
|
|
407
|
+
.description("Switch Claude Code to Ollama (local models, requires LiteLLM proxy)")).action(async (model, options) => {
|
|
408
|
+
try {
|
|
409
|
+
await switchOllama(model, options);
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to Ollama");
|
|
413
|
+
process.exit(1);
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
addTierOptions(claudeCmd
|
|
417
|
+
.command("gemini [model]")
|
|
418
|
+
.description("Switch Claude Code to Gemini (Google, requires LiteLLM proxy)")).action(async (model, options) => {
|
|
419
|
+
try {
|
|
420
|
+
await switchGemini(model, options);
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to switch to Gemini");
|
|
424
|
+
process.exit(1);
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
// ---------------------------------------------------------------------------
|
|
428
|
+
// `opencode` subcommand — OpenCode helper commands
|
|
429
|
+
// ---------------------------------------------------------------------------
|
|
430
|
+
const opencodeCmd = program
|
|
431
|
+
.command("opencode")
|
|
432
|
+
.description("OpenCode helper commands");
|
|
433
|
+
const opencodeAddCmd = opencodeCmd
|
|
434
|
+
.command("add")
|
|
435
|
+
.description("Add a provider to OpenCode");
|
|
436
|
+
opencodeAddCmd
|
|
437
|
+
.command("alibaba")
|
|
438
|
+
.description("Add Alibaba Coding Plan provider to OpenCode")
|
|
439
|
+
.action(async () => {
|
|
440
|
+
try {
|
|
441
|
+
let apiKey = await (0, config_1.getApiKey)("alibaba");
|
|
442
|
+
if (!apiKey) {
|
|
443
|
+
apiKey = await promptApiKey("Alibaba", "https://modelstudio.console.alibabacloud.com/");
|
|
444
|
+
await (0, config_1.setApiKey)("alibaba", apiKey);
|
|
445
|
+
}
|
|
446
|
+
await (0, opencode_1.configureAlibaba)(apiKey);
|
|
447
|
+
(0, display_1.displaySuccess)("Added Alibaba Coding Plan provider to OpenCode");
|
|
448
|
+
console.log(chalk_1.default.dim(" Config: ~/.config/opencode/opencode.json"));
|
|
449
|
+
console.log(chalk_1.default.dim(" Provider: bailian-coding-plan"));
|
|
450
|
+
console.log(chalk_1.default.dim(" Models: qwen3.7-plus, qwen3.6-plus, qwen3-max-2026-01-23, qwen3-coder-next, qwen3-coder-plus, MiniMax-M2.5, glm-5, glm-4.7, kimi-k2.5"));
|
|
451
|
+
console.log();
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to add Alibaba provider");
|
|
455
|
+
process.exit(1);
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
opencodeAddCmd
|
|
459
|
+
.command("openrouter")
|
|
460
|
+
.description("Add OpenRouter provider to OpenCode")
|
|
461
|
+
.action(async () => {
|
|
462
|
+
try {
|
|
463
|
+
let apiKey = await (0, config_1.getApiKey)("openrouter");
|
|
464
|
+
if (!apiKey) {
|
|
465
|
+
apiKey = await promptApiKey("OpenRouter", "https://openrouter.ai/settings/keys");
|
|
466
|
+
await (0, config_1.setApiKey)("openrouter", apiKey);
|
|
467
|
+
}
|
|
468
|
+
await (0, opencode_1.configureOpenRouter)(apiKey);
|
|
469
|
+
(0, display_1.displaySuccess)("Added OpenRouter provider to OpenCode");
|
|
470
|
+
console.log(chalk_1.default.dim(" Config: ~/.config/opencode/opencode.json"));
|
|
471
|
+
console.log(chalk_1.default.dim(" Provider: openrouter"));
|
|
472
|
+
console.log(chalk_1.default.dim(" Models: qwen/qwen3.6-plus:free, openrouter/free"));
|
|
473
|
+
console.log();
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to add OpenRouter provider");
|
|
477
|
+
process.exit(1);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
opencodeAddCmd
|
|
481
|
+
.command("ollama")
|
|
482
|
+
.description("Add Ollama provider to OpenCode (requires LiteLLM proxy)")
|
|
483
|
+
.action(async () => {
|
|
484
|
+
try {
|
|
485
|
+
await (0, opencode_1.configureOllama)();
|
|
486
|
+
(0, display_1.displaySuccess)("Added Ollama provider to OpenCode");
|
|
487
|
+
console.log(chalk_1.default.dim(" Config: ~/.config/opencode/opencode.json"));
|
|
488
|
+
console.log(chalk_1.default.dim(" Provider: ollama"));
|
|
489
|
+
console.log(chalk_1.default.dim(" Models: deepseek-r1:latest, qwen2.5-coder:latest, llama3.1:latest, codellama:latest"));
|
|
490
|
+
console.log(chalk_1.default.yellow(" Note: Requires LiteLLM proxy running on port 4000"));
|
|
491
|
+
console.log();
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to add Ollama provider");
|
|
495
|
+
process.exit(1);
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
opencodeAddCmd
|
|
499
|
+
.command("gemini")
|
|
500
|
+
.description("Add Gemini provider to OpenCode (requires LiteLLM proxy)")
|
|
501
|
+
.action(async () => {
|
|
502
|
+
try {
|
|
503
|
+
let apiKey = await (0, config_1.getApiKey)("gemini");
|
|
504
|
+
if (!apiKey) {
|
|
505
|
+
apiKey = await promptApiKey("Gemini", "https://aistudio.google.com/apikey");
|
|
506
|
+
await (0, config_1.setApiKey)("gemini", apiKey);
|
|
507
|
+
}
|
|
508
|
+
await (0, opencode_1.configureGemini)(apiKey);
|
|
509
|
+
(0, display_1.displaySuccess)("Added Gemini provider to OpenCode");
|
|
510
|
+
console.log(chalk_1.default.dim(" Config: ~/.config/opencode/opencode.json"));
|
|
511
|
+
console.log(chalk_1.default.dim(" Provider: gemini"));
|
|
512
|
+
console.log(chalk_1.default.dim(" Models: gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite"));
|
|
513
|
+
console.log(chalk_1.default.yellow(" Note: Requires LiteLLM proxy running on port 4001"));
|
|
514
|
+
console.log();
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to add Gemini provider");
|
|
518
|
+
process.exit(1);
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
opencodeAddCmd
|
|
522
|
+
.command("glm")
|
|
523
|
+
.description("Add GLM/Z.AI provider to OpenCode (requires @z_ai/coding-helper)")
|
|
524
|
+
.action(async () => {
|
|
525
|
+
try {
|
|
526
|
+
// Check coding-helper
|
|
527
|
+
const hasCodingHelper = await (0, glm_1.isCodingHelperInstalled)();
|
|
528
|
+
if (!hasCodingHelper) {
|
|
529
|
+
(0, display_1.displayWarning)("coding-helper not found");
|
|
530
|
+
console.log(chalk_1.default.dim(" Install with: npm install -g @z_ai/coding-helper"));
|
|
531
|
+
console.log(chalk_1.default.dim(" Then run: coding-helper auth"));
|
|
532
|
+
console.log();
|
|
533
|
+
}
|
|
534
|
+
// Read GLM auth from Claude settings (set by coding-helper auth reload claude)
|
|
535
|
+
const claudeSettings = await (0, claude_code_1.readClaudeSettings)();
|
|
536
|
+
let baseURL = claudeSettings.env?.["ANTHROPIC_BASE_URL"] || "";
|
|
537
|
+
let apiKey = claudeSettings.env?.["ANTHROPIC_AUTH_TOKEN"] || "";
|
|
538
|
+
if (!baseURL || !baseURL.includes(".z.ai")) {
|
|
539
|
+
(0, display_1.displayWarning)("GLM not configured in Claude Code yet");
|
|
540
|
+
console.log(chalk_1.default.dim(" Run 'claude-switch glm' first to set up coding-helper auth"));
|
|
541
|
+
console.log();
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
await (0, opencode_1.configureGLM)(baseURL, apiKey);
|
|
545
|
+
(0, display_1.displaySuccess)("Added GLM/Z.AI provider to OpenCode");
|
|
546
|
+
console.log(chalk_1.default.dim(" Config: ~/.config/opencode/opencode.json"));
|
|
547
|
+
console.log(chalk_1.default.dim(" Provider: glm"));
|
|
548
|
+
console.log(chalk_1.default.dim(" Models: glm-5.1, glm-5v-turbo, glm-5-turbo, glm-4.7, glm-4.7-flash"));
|
|
549
|
+
if (hasCodingHelper)
|
|
550
|
+
console.log(chalk_1.default.dim(" Managed by: coding-helper"));
|
|
551
|
+
console.log();
|
|
552
|
+
}
|
|
553
|
+
catch (error) {
|
|
554
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to add GLM provider");
|
|
555
|
+
process.exit(1);
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
const opencodeRemoveCmd = opencodeCmd
|
|
559
|
+
.command("remove")
|
|
560
|
+
.description("Remove a provider from OpenCode");
|
|
561
|
+
opencodeRemoveCmd
|
|
562
|
+
.command("alibaba")
|
|
563
|
+
.description("Remove Alibaba Coding Plan provider from OpenCode")
|
|
564
|
+
.action(async () => {
|
|
565
|
+
try {
|
|
566
|
+
const { removeProvider } = await Promise.resolve().then(() => __importStar(require("./clients/opencode")));
|
|
567
|
+
await removeProvider("bailian-coding-plan");
|
|
568
|
+
(0, display_1.displaySuccess)("Removed Alibaba Coding Plan provider from OpenCode");
|
|
569
|
+
console.log(chalk_1.default.dim(" Other providers remain unchanged"));
|
|
570
|
+
console.log();
|
|
571
|
+
}
|
|
572
|
+
catch (error) {
|
|
573
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to remove Alibaba provider");
|
|
574
|
+
process.exit(1);
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
opencodeRemoveCmd
|
|
578
|
+
.command("openrouter")
|
|
579
|
+
.description("Remove OpenRouter provider from OpenCode")
|
|
580
|
+
.action(async () => {
|
|
581
|
+
try {
|
|
582
|
+
const { removeProvider } = await Promise.resolve().then(() => __importStar(require("./clients/opencode")));
|
|
583
|
+
await removeProvider("openrouter");
|
|
584
|
+
(0, display_1.displaySuccess)("Removed OpenRouter provider from OpenCode");
|
|
585
|
+
console.log(chalk_1.default.dim(" Other providers remain unchanged"));
|
|
586
|
+
console.log();
|
|
587
|
+
}
|
|
588
|
+
catch (error) {
|
|
589
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to remove OpenRouter provider");
|
|
590
|
+
process.exit(1);
|
|
591
|
+
}
|
|
592
|
+
});
|
|
593
|
+
opencodeRemoveCmd
|
|
594
|
+
.command("ollama")
|
|
595
|
+
.description("Remove Ollama provider from OpenCode")
|
|
596
|
+
.action(async () => {
|
|
597
|
+
try {
|
|
598
|
+
const { removeProvider } = await Promise.resolve().then(() => __importStar(require("./clients/opencode")));
|
|
599
|
+
await removeProvider("ollama");
|
|
600
|
+
(0, display_1.displaySuccess)("Removed Ollama provider from OpenCode");
|
|
601
|
+
console.log(chalk_1.default.dim(" Other providers remain unchanged"));
|
|
602
|
+
console.log();
|
|
603
|
+
}
|
|
604
|
+
catch (error) {
|
|
605
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to remove Ollama provider");
|
|
606
|
+
process.exit(1);
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
opencodeRemoveCmd
|
|
610
|
+
.command("gemini")
|
|
611
|
+
.description("Remove Gemini provider from OpenCode")
|
|
612
|
+
.action(async () => {
|
|
613
|
+
try {
|
|
614
|
+
const { removeProvider } = await Promise.resolve().then(() => __importStar(require("./clients/opencode")));
|
|
615
|
+
await removeProvider("gemini");
|
|
616
|
+
(0, display_1.displaySuccess)("Removed Gemini provider from OpenCode");
|
|
617
|
+
console.log(chalk_1.default.dim(" Other providers remain unchanged"));
|
|
618
|
+
console.log();
|
|
619
|
+
}
|
|
620
|
+
catch (error) {
|
|
621
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to remove Gemini provider");
|
|
622
|
+
process.exit(1);
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
opencodeRemoveCmd
|
|
626
|
+
.command("glm")
|
|
627
|
+
.description("Remove GLM/Z.AI provider from OpenCode")
|
|
628
|
+
.action(async () => {
|
|
629
|
+
try {
|
|
630
|
+
const { removeProvider } = await Promise.resolve().then(() => __importStar(require("./clients/opencode")));
|
|
631
|
+
await removeProvider("glm");
|
|
632
|
+
(0, display_1.displaySuccess)("Removed GLM/Z.AI provider from OpenCode");
|
|
633
|
+
console.log(chalk_1.default.dim(" Other providers remain unchanged"));
|
|
634
|
+
console.log();
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to remove GLM provider");
|
|
638
|
+
process.exit(1);
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
// ---------------------------------------------------------------------------
|
|
642
|
+
// Info commands
|
|
643
|
+
// ---------------------------------------------------------------------------
|
|
644
|
+
program
|
|
645
|
+
.command("status")
|
|
646
|
+
.description("Show current config and verify API keys")
|
|
647
|
+
.action(async () => {
|
|
648
|
+
try {
|
|
649
|
+
// ── Current Configuration ──
|
|
650
|
+
console.log(chalk_1.default.green("\n=== Claude AI Switcher Status ===\n"));
|
|
651
|
+
// Claude Code
|
|
652
|
+
console.log(chalk_1.default.cyan.bold(" Claude Code:"));
|
|
653
|
+
if ((0, claude_code_1.claudeSettingsExists)()) {
|
|
654
|
+
const claudeProvider = await (0, claude_code_1.getCurrentProvider)();
|
|
655
|
+
if (claudeProvider) {
|
|
656
|
+
console.log(` Provider: ${chalk_1.default.white(claudeProvider.provider)}`);
|
|
657
|
+
if (claudeProvider.model)
|
|
658
|
+
console.log(` Model: ${chalk_1.default.white(claudeProvider.model)}`);
|
|
659
|
+
if (claudeProvider.endpoint)
|
|
660
|
+
console.log(` Endpoint: ${chalk_1.default.dim(claudeProvider.endpoint)}`);
|
|
661
|
+
if (claudeProvider.tierMap?.opus) {
|
|
662
|
+
console.log(chalk_1.default.dim(" Aliases:"));
|
|
663
|
+
console.log(chalk_1.default.dim(` opus → ${claudeProvider.tierMap.opus}`));
|
|
664
|
+
console.log(chalk_1.default.dim(` sonnet → ${claudeProvider.tierMap.sonnet}`));
|
|
665
|
+
console.log(chalk_1.default.dim(` haiku → ${claudeProvider.tierMap.haiku}`));
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
console.log(chalk_1.default.dim(" Unable to read configuration"));
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
else {
|
|
673
|
+
console.log(chalk_1.default.dim(" Not configured (using defaults)"));
|
|
674
|
+
}
|
|
675
|
+
console.log();
|
|
676
|
+
// OpenCode
|
|
677
|
+
console.log(chalk_1.default.cyan.bold(" OpenCode:"));
|
|
678
|
+
if ((0, opencode_1.opencodeSettingsExists)()) {
|
|
679
|
+
const opencodeProvider = await (0, opencode_1.getCurrentProvider)();
|
|
680
|
+
if (opencodeProvider) {
|
|
681
|
+
console.log(` Provider: ${chalk_1.default.white(opencodeProvider.provider)}`);
|
|
682
|
+
if (opencodeProvider.model)
|
|
683
|
+
console.log(` Model: ${chalk_1.default.white(opencodeProvider.model)}`);
|
|
684
|
+
if (opencodeProvider.endpoint)
|
|
685
|
+
console.log(` Endpoint: ${chalk_1.default.dim(opencodeProvider.endpoint)}`);
|
|
686
|
+
}
|
|
687
|
+
else {
|
|
688
|
+
console.log(chalk_1.default.dim(" Unable to read configuration"));
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
console.log(chalk_1.default.dim(" Not installed"));
|
|
693
|
+
}
|
|
694
|
+
// ── API Key Verification ──
|
|
695
|
+
console.log();
|
|
696
|
+
console.log(chalk_1.default.cyan.bold(" API Key Verification:"));
|
|
697
|
+
console.log(chalk_1.default.dim("─".repeat(50)));
|
|
698
|
+
const alibabaKey = await (0, config_1.getApiKey)("alibaba");
|
|
699
|
+
const openrouterKey = await (0, config_1.getApiKey)("openrouter");
|
|
700
|
+
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
701
|
+
const geminiKey = await (0, config_1.getApiKey)("gemini");
|
|
702
|
+
// Show spinner while verifying
|
|
703
|
+
const ora = (await Promise.resolve().then(() => __importStar(require("ora")))).default;
|
|
704
|
+
const spinner = ora("Verifying API keys...").start();
|
|
705
|
+
const results = await (0, verify_1.verifyAllKeys)({
|
|
706
|
+
alibaba: alibabaKey,
|
|
707
|
+
openrouter: openrouterKey,
|
|
708
|
+
anthropic: anthropicKey,
|
|
709
|
+
checkGLM: true,
|
|
710
|
+
checkOllama: true,
|
|
711
|
+
gemini: geminiKey
|
|
712
|
+
});
|
|
713
|
+
spinner.stop();
|
|
714
|
+
for (const result of results) {
|
|
715
|
+
const label = result.provider.padEnd(12);
|
|
716
|
+
let icon;
|
|
717
|
+
let detail = result.message || "";
|
|
718
|
+
switch (result.status) {
|
|
719
|
+
case "ok":
|
|
720
|
+
icon = chalk_1.default.green("✓");
|
|
721
|
+
break;
|
|
722
|
+
case "invalid":
|
|
723
|
+
icon = chalk_1.default.red("✗");
|
|
724
|
+
break;
|
|
725
|
+
case "missing":
|
|
726
|
+
icon = chalk_1.default.dim("○");
|
|
727
|
+
detail = "No key configured";
|
|
728
|
+
break;
|
|
729
|
+
case "error":
|
|
730
|
+
icon = chalk_1.default.yellow("⚠");
|
|
731
|
+
break;
|
|
732
|
+
default:
|
|
733
|
+
icon = chalk_1.default.dim("–");
|
|
734
|
+
detail = "Skipped";
|
|
735
|
+
}
|
|
736
|
+
// Show masked key if available
|
|
737
|
+
let keyDisplay = "";
|
|
738
|
+
if (result.provider === "alibaba" && alibabaKey) {
|
|
739
|
+
keyDisplay = chalk_1.default.dim(` (${(0, verify_1.maskKey)(alibabaKey)})`);
|
|
740
|
+
}
|
|
741
|
+
else if (result.provider === "openrouter" && openrouterKey) {
|
|
742
|
+
keyDisplay = chalk_1.default.dim(` (${(0, verify_1.maskKey)(openrouterKey)})`);
|
|
743
|
+
}
|
|
744
|
+
else if (result.provider === "anthropic" && anthropicKey) {
|
|
745
|
+
keyDisplay = chalk_1.default.dim(` (${(0, verify_1.maskKey)(anthropicKey)})`);
|
|
746
|
+
}
|
|
747
|
+
else if (result.provider === "gemini" && geminiKey) {
|
|
748
|
+
keyDisplay = chalk_1.default.dim(` (${(0, verify_1.maskKey)(geminiKey)})`);
|
|
749
|
+
}
|
|
750
|
+
console.log(` ${icon} ${chalk_1.default.white(label)} ${chalk_1.default.gray(detail)}${keyDisplay}`);
|
|
751
|
+
}
|
|
752
|
+
console.log(chalk_1.default.dim("─".repeat(50)));
|
|
753
|
+
console.log();
|
|
754
|
+
}
|
|
755
|
+
catch (error) {
|
|
756
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to get status");
|
|
757
|
+
process.exit(1);
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
program
|
|
761
|
+
.command("current")
|
|
762
|
+
.description("Show current provider and model for both clients")
|
|
763
|
+
.action(async () => {
|
|
764
|
+
try {
|
|
765
|
+
console.log(chalk_1.default.green("\nCurrent Configuration:\n"));
|
|
766
|
+
console.log(chalk_1.default.cyan.bold(" Claude Code:"));
|
|
767
|
+
if ((0, claude_code_1.claudeSettingsExists)()) {
|
|
768
|
+
const claudeProvider = await (0, claude_code_1.getCurrentProvider)();
|
|
769
|
+
if (claudeProvider) {
|
|
770
|
+
console.log(` Provider: ${chalk_1.default.white(claudeProvider.provider)}`);
|
|
771
|
+
if (claudeProvider.model)
|
|
772
|
+
console.log(` Model: ${chalk_1.default.white(claudeProvider.model)}`);
|
|
773
|
+
if (claudeProvider.endpoint)
|
|
774
|
+
console.log(` Endpoint: ${chalk_1.default.dim(claudeProvider.endpoint)}`);
|
|
775
|
+
if (claudeProvider.tierMap?.opus) {
|
|
776
|
+
console.log(chalk_1.default.dim(" Model aliases:"));
|
|
777
|
+
console.log(chalk_1.default.dim(` opus → ${claudeProvider.tierMap.opus}`));
|
|
778
|
+
console.log(chalk_1.default.dim(` sonnet → ${claudeProvider.tierMap.sonnet}`));
|
|
779
|
+
console.log(chalk_1.default.dim(` haiku → ${claudeProvider.tierMap.haiku}`));
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
console.log(chalk_1.default.dim(" Unable to read configuration"));
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
console.log(chalk_1.default.dim(" Not configured (using defaults)"));
|
|
788
|
+
}
|
|
789
|
+
console.log();
|
|
790
|
+
console.log(chalk_1.default.cyan.bold(" OpenCode:"));
|
|
791
|
+
if ((0, opencode_1.opencodeSettingsExists)()) {
|
|
792
|
+
const opencodeProvider = await (0, opencode_1.getCurrentProvider)();
|
|
793
|
+
if (opencodeProvider) {
|
|
794
|
+
console.log(` Provider: ${chalk_1.default.white(opencodeProvider.provider)}`);
|
|
795
|
+
if (opencodeProvider.model)
|
|
796
|
+
console.log(` Model: ${chalk_1.default.white(opencodeProvider.model)}`);
|
|
797
|
+
if (opencodeProvider.endpoint)
|
|
798
|
+
console.log(` Endpoint: ${chalk_1.default.dim(opencodeProvider.endpoint)}`);
|
|
799
|
+
}
|
|
800
|
+
else {
|
|
801
|
+
console.log(chalk_1.default.dim(" Unable to read configuration"));
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
else {
|
|
805
|
+
console.log(chalk_1.default.dim(" Not configured (using defaults)"));
|
|
806
|
+
}
|
|
807
|
+
console.log();
|
|
808
|
+
}
|
|
809
|
+
catch (error) {
|
|
810
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to get current provider");
|
|
811
|
+
process.exit(1);
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
program
|
|
815
|
+
.command("list")
|
|
816
|
+
.description("List all providers and their models")
|
|
817
|
+
.action(() => {
|
|
818
|
+
const providerList = Object.values(models_1.providers).map((p) => ({
|
|
819
|
+
id: p.id,
|
|
820
|
+
name: p.name,
|
|
821
|
+
endpoint: p.endpoint,
|
|
822
|
+
modelCount: p.models.length
|
|
823
|
+
}));
|
|
824
|
+
(0, display_1.displayProviders)(providerList);
|
|
825
|
+
for (const provider of Object.values(models_1.providers)) {
|
|
826
|
+
(0, display_1.displayModels)(provider.name, provider.models);
|
|
827
|
+
}
|
|
828
|
+
});
|
|
829
|
+
program
|
|
830
|
+
.command("models [provider]")
|
|
831
|
+
.description("Show models for a specific provider")
|
|
832
|
+
.action((providerName) => {
|
|
833
|
+
if (!providerName) {
|
|
834
|
+
(0, display_1.displayError)("Please specify a provider: anthropic, alibaba, openrouter, glm, ollama, or gemini");
|
|
835
|
+
console.log(chalk_1.default.dim(" Example: claude-switch models alibaba"));
|
|
836
|
+
process.exit(1);
|
|
837
|
+
}
|
|
838
|
+
const provider = models_1.providers[providerName.toLowerCase()];
|
|
839
|
+
if (!provider) {
|
|
840
|
+
(0, display_1.displayError)(`Unknown provider: ${providerName}`);
|
|
841
|
+
console.log(chalk_1.default.dim(" Valid providers: ") + Object.keys(models_1.providers).join(", "));
|
|
842
|
+
process.exit(1);
|
|
843
|
+
}
|
|
844
|
+
(0, display_1.displayModels)(provider.name, provider.models);
|
|
845
|
+
});
|
|
846
|
+
program
|
|
847
|
+
.command("key <provider> [apikey]")
|
|
848
|
+
.description("Set or show API key for a provider")
|
|
849
|
+
.action(async (provider, apikey) => {
|
|
850
|
+
try {
|
|
851
|
+
if (!apikey) {
|
|
852
|
+
const hasKey = await (0, config_1.hasApiKey)(provider);
|
|
853
|
+
if (hasKey) {
|
|
854
|
+
(0, display_1.displaySuccess)(`API key is set for ${provider}`);
|
|
855
|
+
}
|
|
856
|
+
else {
|
|
857
|
+
(0, display_1.displayWarning)(`No API key set for ${provider}`);
|
|
858
|
+
console.log(chalk_1.default.dim(" Set with: claude-switch key " + provider + " <your-key>"));
|
|
859
|
+
}
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
await (0, config_1.setApiKey)(provider, apikey);
|
|
863
|
+
(0, display_1.displaySuccess)(`API key set for ${provider}`);
|
|
864
|
+
}
|
|
865
|
+
catch (error) {
|
|
866
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to manage API key");
|
|
867
|
+
process.exit(1);
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
program
|
|
871
|
+
.command("setup")
|
|
872
|
+
.description("Interactive setup wizard")
|
|
873
|
+
.action(async () => {
|
|
874
|
+
try {
|
|
875
|
+
console.log(chalk_1.default.green("\n=== Claude AI Switcher Setup ===\n"));
|
|
876
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
877
|
+
const hasAlibabaKey = await (0, config_1.hasApiKey)("alibaba");
|
|
878
|
+
if (!hasAlibabaKey) {
|
|
879
|
+
console.log(chalk_1.default.yellow("Alibaba Coding Plan Setup"));
|
|
880
|
+
console.log(chalk_1.default.dim(" Get your API key from: https://modelstudio.console.alibabacloud.com/"));
|
|
881
|
+
console.log();
|
|
882
|
+
const answer = await new Promise((resolve) => {
|
|
883
|
+
rl.question("Enter your Alibaba API Key (or press Enter to skip): ", resolve);
|
|
884
|
+
});
|
|
885
|
+
if (answer.trim()) {
|
|
886
|
+
await (0, config_1.setApiKey)("alibaba", answer.trim());
|
|
887
|
+
(0, display_1.displaySuccess)("Alibaba API key saved");
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
const hasOpenRouterKey = await (0, config_1.hasApiKey)("openrouter");
|
|
891
|
+
if (!hasOpenRouterKey) {
|
|
892
|
+
console.log(chalk_1.default.yellow("\nOpenRouter Setup"));
|
|
893
|
+
console.log(chalk_1.default.dim(" Get your API key from: https://openrouter.ai/settings/keys"));
|
|
894
|
+
console.log();
|
|
895
|
+
const answer = await new Promise((resolve) => {
|
|
896
|
+
rl.question("Enter your OpenRouter API Key (or press Enter to skip): ", resolve);
|
|
897
|
+
});
|
|
898
|
+
if (answer.trim()) {
|
|
899
|
+
await (0, config_1.setApiKey)("openrouter", answer.trim());
|
|
900
|
+
(0, display_1.displaySuccess)("OpenRouter API key saved");
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
const hasGeminiKey = await (0, config_1.hasApiKey)("gemini");
|
|
904
|
+
if (!hasGeminiKey) {
|
|
905
|
+
console.log(chalk_1.default.yellow("\nGemini Setup"));
|
|
906
|
+
console.log(chalk_1.default.dim(" Get your API key from: https://aistudio.google.com/apikey"));
|
|
907
|
+
console.log();
|
|
908
|
+
const answer = await new Promise((resolve) => {
|
|
909
|
+
rl.question("Enter your Gemini API Key (or press Enter to skip): ", resolve);
|
|
910
|
+
});
|
|
911
|
+
if (answer.trim()) {
|
|
912
|
+
await (0, config_1.setApiKey)("gemini", answer.trim());
|
|
913
|
+
(0, display_1.displaySuccess)("Gemini API key saved");
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
rl.close();
|
|
917
|
+
console.log(chalk_1.default.green("\n✓ Setup complete!\n"));
|
|
918
|
+
console.log("Available commands:");
|
|
919
|
+
console.log(chalk_1.default.dim(" claude-switch alibaba [model] - Switch Claude Code to Alibaba"));
|
|
920
|
+
console.log(chalk_1.default.dim(" claude-switch anthropic - Switch Claude Code to Anthropic"));
|
|
921
|
+
console.log(chalk_1.default.dim(" claude-switch glm - Switch Claude Code to GLM/Z.AI"));
|
|
922
|
+
console.log(chalk_1.default.dim(" claude-switch openrouter [model] - Switch Claude Code to OpenRouter"));
|
|
923
|
+
console.log(chalk_1.default.dim(" claude-switch ollama [model] - Switch Claude Code to Ollama"));
|
|
924
|
+
console.log(chalk_1.default.dim(" claude-switch gemini [model] - Switch Claude Code to Gemini"));
|
|
925
|
+
console.log(chalk_1.default.dim(" claude-switch claude alibaba - Explicit Claude Code targeting"));
|
|
926
|
+
console.log(chalk_1.default.dim(" claude-switch opencode add alibaba - Add Alibaba provider to OpenCode"));
|
|
927
|
+
console.log(chalk_1.default.dim(" claude-switch opencode add openrouter - Add OpenRouter provider to OpenCode"));
|
|
928
|
+
console.log(chalk_1.default.dim(" claude-switch opencode add ollama - Add Ollama provider to OpenCode"));
|
|
929
|
+
console.log(chalk_1.default.dim(" claude-switch opencode add gemini - Add Gemini provider to OpenCode"));
|
|
930
|
+
console.log(chalk_1.default.dim(" claude-switch opencode add glm - Add GLM/Z.AI provider to OpenCode"));
|
|
931
|
+
console.log(chalk_1.default.dim(" claude-switch opencode remove alibaba - Remove Alibaba from OpenCode"));
|
|
932
|
+
console.log(chalk_1.default.dim(" claude-switch opencode remove openrouter - Remove OpenRouter from OpenCode"));
|
|
933
|
+
console.log(chalk_1.default.dim(" claude-switch opencode remove ollama - Remove Ollama from OpenCode"));
|
|
934
|
+
console.log(chalk_1.default.dim(" claude-switch opencode remove gemini - Remove Gemini from OpenCode"));
|
|
935
|
+
console.log(chalk_1.default.dim(" claude-switch opencode remove glm - Remove GLM/Z.AI from OpenCode"));
|
|
936
|
+
console.log(chalk_1.default.dim(" claude-switch openrouter --opus <model> - Custom model aliases"));
|
|
937
|
+
console.log(chalk_1.default.dim(" claude-switch list - List all providers"));
|
|
938
|
+
console.log(chalk_1.default.dim(" claude-switch status - Show current config + verify API keys"));
|
|
939
|
+
console.log(chalk_1.default.dim(" claude-switch current - Show current config"));
|
|
940
|
+
console.log(chalk_1.default.dim(" claude-switch hooks install - Install token tracking & visual enhancements"));
|
|
941
|
+
console.log(chalk_1.default.dim(" claude-switch hooks status - Show token usage and visual status"));
|
|
942
|
+
console.log();
|
|
943
|
+
}
|
|
944
|
+
catch (error) {
|
|
945
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Setup failed");
|
|
946
|
+
process.exit(1);
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
// ---------------------------------------------------------------------------
|
|
950
|
+
// Hooks commands - Token tracking and visual enhancements
|
|
951
|
+
// ---------------------------------------------------------------------------
|
|
952
|
+
const hooksCmd = program
|
|
953
|
+
.command("hooks")
|
|
954
|
+
.description("Manage Claude Code hooks (token tracking, visual enhancements)");
|
|
955
|
+
hooksCmd
|
|
956
|
+
.command("install")
|
|
957
|
+
.description("Install all visual enhancements and token tracking")
|
|
958
|
+
.action(async () => {
|
|
959
|
+
try {
|
|
960
|
+
const ora = await Promise.resolve().then(() => __importStar(require("ora"))).catch(() => null);
|
|
961
|
+
const spinner = ora ? ora.default("Installing hooks...").start() : null;
|
|
962
|
+
await (0, index_1.installAllHooks)();
|
|
963
|
+
spinner?.stop();
|
|
964
|
+
console.log(chalk_1.default.green("\n✓ Hooks installed successfully!\n"));
|
|
965
|
+
console.log(chalk_1.default.cyan.bold(" Installed:"));
|
|
966
|
+
console.log(chalk_1.default.dim(" • Token Tracker (~/.claude/token-tracker.js)"));
|
|
967
|
+
console.log(chalk_1.default.dim(" • Visual Enhancements (~/.claude/visual-enhancements.js)"));
|
|
968
|
+
console.log();
|
|
969
|
+
console.log(chalk_1.default.yellow(" Usage:"));
|
|
970
|
+
console.log(chalk_1.default.dim(" • Token usage is tracked automatically"));
|
|
971
|
+
console.log(chalk_1.default.dim(" • Run 'claude-switch hooks status' to see current usage"));
|
|
972
|
+
console.log(chalk_1.default.dim(" • Run 'claude-switch hooks reset' to reset counters"));
|
|
973
|
+
console.log();
|
|
974
|
+
}
|
|
975
|
+
catch (error) {
|
|
976
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to install hooks");
|
|
977
|
+
process.exit(1);
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
hooksCmd
|
|
981
|
+
.command("install-token")
|
|
982
|
+
.description("Install only token tracker")
|
|
983
|
+
.action(async () => {
|
|
984
|
+
try {
|
|
985
|
+
await (0, index_1.installTokenTracker)();
|
|
986
|
+
(0, display_1.displaySuccess)("Token tracker installed");
|
|
987
|
+
console.log(chalk_1.default.dim(" Location: ~/.claude/token-tracker.js"));
|
|
988
|
+
console.log();
|
|
989
|
+
}
|
|
990
|
+
catch (error) {
|
|
991
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to install token tracker");
|
|
992
|
+
process.exit(1);
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
hooksCmd
|
|
996
|
+
.command("install-visual")
|
|
997
|
+
.description("Install only visual enhancements")
|
|
998
|
+
.action(async () => {
|
|
999
|
+
try {
|
|
1000
|
+
await (0, index_1.installVisualEnhancements)();
|
|
1001
|
+
(0, display_1.displaySuccess)("Visual enhancements installed");
|
|
1002
|
+
console.log(chalk_1.default.dim(" Location: ~/.claude/visual-enhancements.js"));
|
|
1003
|
+
console.log();
|
|
1004
|
+
}
|
|
1005
|
+
catch (error) {
|
|
1006
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to install visual enhancements");
|
|
1007
|
+
process.exit(1);
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
hooksCmd
|
|
1011
|
+
.command("status")
|
|
1012
|
+
.description("Show token usage and visual status")
|
|
1013
|
+
.action(async () => {
|
|
1014
|
+
try {
|
|
1015
|
+
const installed = await (0, index_1.areHooksInstalled)();
|
|
1016
|
+
console.log(chalk_1.default.green("\n=== Hooks Status ===\n"));
|
|
1017
|
+
console.log(` Token Tracker: ${installed.tokenTracking ? chalk_1.default.green("✓ Installed") : chalk_1.default.red("Not installed")}`);
|
|
1018
|
+
console.log(` Visual Enhancements: ${installed.visualEnhancements ? chalk_1.default.green("✓ Installed") : chalk_1.default.red("Not installed")}`);
|
|
1019
|
+
console.log();
|
|
1020
|
+
if (installed.tokenTracking) {
|
|
1021
|
+
await (0, index_1.showTokenStatus)();
|
|
1022
|
+
}
|
|
1023
|
+
if (installed.visualEnhancements) {
|
|
1024
|
+
await (0, index_1.showVisualStatus)();
|
|
1025
|
+
}
|
|
1026
|
+
if (!installed.tokenTracking && !installed.visualEnhancements) {
|
|
1027
|
+
console.log(chalk_1.default.yellow(" Run 'claude-switch hooks install' to install hooks"));
|
|
1028
|
+
console.log();
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
catch (error) {
|
|
1032
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to get hooks status");
|
|
1033
|
+
process.exit(1);
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
hooksCmd
|
|
1037
|
+
.command("reset")
|
|
1038
|
+
.description("Reset token usage counters")
|
|
1039
|
+
.action(async () => {
|
|
1040
|
+
try {
|
|
1041
|
+
await (0, index_1.resetTokenUsage)();
|
|
1042
|
+
}
|
|
1043
|
+
catch (error) {
|
|
1044
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to reset token usage");
|
|
1045
|
+
process.exit(1);
|
|
1046
|
+
}
|
|
1047
|
+
});
|
|
1048
|
+
hooksCmd
|
|
1049
|
+
.command("remove")
|
|
1050
|
+
.description("Remove all hooks")
|
|
1051
|
+
.action(async () => {
|
|
1052
|
+
try {
|
|
1053
|
+
await (0, index_1.removeAllHooks)();
|
|
1054
|
+
(0, display_1.displaySuccess)("All hooks removed");
|
|
1055
|
+
console.log();
|
|
1056
|
+
}
|
|
1057
|
+
catch (error) {
|
|
1058
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to remove hooks");
|
|
1059
|
+
process.exit(1);
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
hooksCmd
|
|
1063
|
+
.command("remove-token")
|
|
1064
|
+
.description("Remove token tracker")
|
|
1065
|
+
.action(async () => {
|
|
1066
|
+
try {
|
|
1067
|
+
await (0, index_1.removeTokenTracker)();
|
|
1068
|
+
(0, display_1.displaySuccess)("Token tracker removed");
|
|
1069
|
+
console.log();
|
|
1070
|
+
}
|
|
1071
|
+
catch (error) {
|
|
1072
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to remove token tracker");
|
|
1073
|
+
process.exit(1);
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
hooksCmd
|
|
1077
|
+
.command("remove-visual")
|
|
1078
|
+
.description("Remove visual enhancements")
|
|
1079
|
+
.action(async () => {
|
|
1080
|
+
try {
|
|
1081
|
+
await (0, index_1.removeVisualEnhancements)();
|
|
1082
|
+
(0, display_1.displaySuccess)("Visual enhancements removed");
|
|
1083
|
+
console.log();
|
|
1084
|
+
}
|
|
1085
|
+
catch (error) {
|
|
1086
|
+
(0, display_1.displayError)(error instanceof Error ? error.message : "Failed to remove visual enhancements");
|
|
1087
|
+
process.exit(1);
|
|
1088
|
+
}
|
|
1089
|
+
});
|
|
1090
|
+
program.parse();
|
|
1091
|
+
//# sourceMappingURL=index.js.map
|