aico-cli 0.1.3 → 0.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/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { J as readAicoConfig, K as updateAicoConfig, N as getTranslation, k as AI_OUTPUT_LANGUAGES, O as inquirer, P as addNumbersToChoices, Q as version, q as backupExistingConfig, r as copyConfigFiles, x as applyAiLanguageDirective, R as configureAiPersonality, C as CLAUDE_DIR, I as I18N, T as isWindows, U as readCcrConfig, V as isCcrInstalled, W as installCcr, X as configureCcrFeature, Y as handleExitPromptError, Z as handleGeneralError, _ as readAicoConfigAsync, $ as COMETIX_COMMANDS, a0 as COMETIX_COMMAND_NAME, a1 as installCometixLine, o as openSettingsJson, b as importRecommendedPermissions, a as importRecommendedEnv, z as readMcpConfig, G as fixWindowsMcpConfig, B as writeMcpConfig, a2 as selectMcpServices, D as backupMcpConfig, M as MCP_SERVICES, F as buildMcpServerConfig, a3 as EscapeKeyPressed, E as mergeMcpServers, a4 as displayBanner, a5 as selectAndInstallWorkflows, a6 as displayBannerWithInfo, i as init, a7 as executeWithEscapeSupport, a8 as checkAndUpdateTools } from './shared/aico-cli.Bev0wEf2.mjs';
4
+ import { J as readAicoConfig, K as updateAicoConfig, N as getTranslation, k as AI_OUTPUT_LANGUAGES, O as inquirer, P as addNumbersToChoices, Q as version, q as backupExistingConfig, r as copyConfigFiles, x as applyAiLanguageDirective, R as configureAiPersonality, C as CLAUDE_DIR, I as I18N, T as isWindows, U as readCcrConfig, V as isCcrInstalled, W as installCcr, X as configureCcrFeature, Y as handleExitPromptError, Z as handleGeneralError, _ as readAicoConfigAsync, $ as COMETIX_COMMANDS, a0 as COMETIX_COMMAND_NAME, a1 as installCometixLine, o as openSettingsJson, b as importRecommendedPermissions, a as importRecommendedEnv, z as readMcpConfig, G as fixWindowsMcpConfig, B as writeMcpConfig, a2 as selectMcpServices, D as backupMcpConfig, M as MCP_SERVICES, F as buildMcpServerConfig, a3 as EscapeKeyPressed, E as mergeMcpServers, a4 as displayBanner, a5 as selectAndInstallWorkflows, a6 as displayBannerWithInfo, i as init, a7 as executeWithEscapeSupport, a8 as checkAndUpdateTools } from './shared/aico-cli.CSeKe20G.mjs';
5
5
  import inquirer$1 from 'inquirer';
6
6
  import { existsSync } from 'node:fs';
7
7
  import { x } from 'tinyexec';
@@ -1125,7 +1125,6 @@ async function handleInitCommand(options) {
1125
1125
  force: options.force,
1126
1126
  skipPrompt: options.skipPrompt,
1127
1127
  configAction: options.configAction,
1128
- apiType: options.apiType,
1129
1128
  apiKey: options.apiKey,
1130
1129
  apiUrl: options.apiUrl,
1131
1130
  mcpServices: options.mcpServices,
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AICO_CONFIG_FILE, k as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, f as ClAUDE_CONFIG_FILE, I as I18N, j as LANG_LABELS, L as LEGACY_AICO_CONFIG_FILE, M as MCP_SERVICES, S as SETTINGS_FILE, h as SUPPORTED_LANGS, H as addCompletedOnboarding, x as applyAiLanguageDirective, q as backupExistingConfig, D as backupMcpConfig, F as buildMcpServerConfig, d as cleanupPermissions, c as commandExists, s as configureApi, r as copyConfigFiles, p as ensureClaudeDir, G as fixWindowsMcpConfig, w as getExistingApiConfig, y as getMcpConfigPath, g as getPlatform, a as importRecommendedEnv, b as importRecommendedPermissions, i as init, n as installClaudeCode, l as isClaudeCodeInstalled, m as mergeAndCleanPermissions, t as mergeConfigs, E as mergeMcpServers, v as mergeSettingsFile, o as openSettingsJson, z as readMcpConfig, u as updateDefaultModel, B as writeMcpConfig } from './shared/aico-cli.Bev0wEf2.mjs';
1
+ export { A as AICO_CONFIG_FILE, k as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, f as ClAUDE_CONFIG_FILE, I as I18N, j as LANG_LABELS, L as LEGACY_AICO_CONFIG_FILE, M as MCP_SERVICES, S as SETTINGS_FILE, h as SUPPORTED_LANGS, H as addCompletedOnboarding, x as applyAiLanguageDirective, q as backupExistingConfig, D as backupMcpConfig, F as buildMcpServerConfig, d as cleanupPermissions, c as commandExists, s as configureApi, r as copyConfigFiles, p as ensureClaudeDir, G as fixWindowsMcpConfig, w as getExistingApiConfig, y as getMcpConfigPath, g as getPlatform, a as importRecommendedEnv, b as importRecommendedPermissions, i as init, n as installClaudeCode, l as isClaudeCodeInstalled, m as mergeAndCleanPermissions, t as mergeConfigs, E as mergeMcpServers, v as mergeSettingsFile, o as openSettingsJson, z as readMcpConfig, u as updateDefaultModel, B as writeMcpConfig } from './shared/aico-cli.CSeKe20G.mjs';
2
2
  import 'ansis';
3
3
  import 'inquirer';
4
4
  import 'node:fs';
@@ -3,18 +3,18 @@ import inquirer$1 from 'inquirer';
3
3
  import { existsSync, mkdirSync, copyFileSync, writeFileSync, readFileSync, readdirSync, statSync } from 'node:fs';
4
4
  import { join, dirname } from 'pathe';
5
5
  import dayjs from 'dayjs';
6
- import { exec as exec$1 } from 'node:child_process';
6
+ import { exec as exec$2 } from 'node:child_process';
7
7
  import { homedir, platform } from 'node:os';
8
8
  import { join as join$1 } from 'node:path';
9
- import { promisify } from 'node:util';
9
+ import { promisify as promisify$1 } from 'node:util';
10
10
  import { fileURLToPath } from 'node:url';
11
- import { exec as exec$2 } from 'child_process';
12
- import { promisify as promisify$1 } from 'util';
11
+ import { exec as exec$1 } from 'child_process';
12
+ import { promisify } from 'util';
13
13
  import ora from 'ora';
14
14
  import { exec } from 'tinyexec';
15
15
  import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
16
16
 
17
- const version = "0.1.3";
17
+ const version = "0.1.4";
18
18
 
19
19
  const common$1 = {
20
20
  // Basic
@@ -358,6 +358,14 @@ const ccrMessages$1 = {
358
358
  ccrInstallSuccess: "Claude Code Router \u5B89\u88C5\u6210\u529F",
359
359
  ccrInstallFailed: "\u5B89\u88C5 Claude Code Router \u5931\u8D25",
360
360
  ccrAlreadyInstalled: "Claude Code Router \u5DF2\u5B89\u88C5",
361
+ // Additional status messages
362
+ checkingInstallation: "\u6B63\u5728\u68C0\u67E5 CCR \u5B89\u88C5...",
363
+ ccrNotInstalled: "CCR \u672A\u5B89\u88C5",
364
+ ccrInstalledWrongPackage: "CCR \u5DF2\u5B89\u88C5\u4F46\u5305/\u7248\u672C\u4E0D\u5339\u914D",
365
+ installationStarting: "\u6B63\u5728\u5F00\u59CB CCR \u5B89\u88C5...",
366
+ installationSuccess: "CCR \u5B89\u88C5\u5B8C\u6210",
367
+ startingCcrService: "\u6B63\u5728\u542F\u52A8 CCR \u670D\u52A1...",
368
+ ccrServiceStarted: "CCR \u670D\u52A1\u5DF2\u542F\u52A8",
361
369
  // Configuration
362
370
  configureCcr: "\u542F\u52A8\u672C\u5730\u4E2A\u4EBA\u914D\u7F6E",
363
371
  useCcrProxy: "\u4F7F\u7528 CCR \u4EE3\u7406",
@@ -482,6 +490,7 @@ const zhCN = {
482
490
  errors: errors$1,
483
491
  tools: tools$1,
484
492
  ccr: ccrMessages$1,
493
+ updater: {},
485
494
  cometix: cometixMessages$1
486
495
  };
487
496
 
@@ -827,6 +836,14 @@ const ccrMessages = {
827
836
  ccrInstallSuccess: "Claude Code Router installed successfully",
828
837
  ccrInstallFailed: "Failed to install Claude Code Router",
829
838
  ccrAlreadyInstalled: "Claude Code Router is already installed",
839
+ // Additional status messages
840
+ checkingInstallation: "Checking CCR installation...",
841
+ ccrNotInstalled: "CCR is not installed",
842
+ ccrInstalledWrongPackage: "CCR is installed but has an unexpected package/version",
843
+ installationStarting: "Starting CCR installation...",
844
+ installationSuccess: "CCR installation completed",
845
+ startingCcrService: "Starting CCR service...",
846
+ ccrServiceStarted: "CCR service started",
830
847
  // Configuration
831
848
  configureCcr: "Configure Model Proxy (CCR)",
832
849
  useCcrProxy: "Use CCR Proxy",
@@ -951,6 +968,7 @@ const en = {
951
968
  errors,
952
969
  tools,
953
970
  ccr: ccrMessages,
971
+ updater: {},
954
972
  cometix: cometixMessages
955
973
  };
956
974
 
@@ -1976,277 +1994,6 @@ function getFallbackPresets() {
1976
1994
  ];
1977
1995
  }
1978
1996
 
1979
- const execAsync$4 = promisify(exec$1);
1980
- const CCR_CONFIG_DIR = join$1(homedir(), ".claude-code-router");
1981
- const CCR_CONFIG_FILE = join$1(CCR_CONFIG_DIR, "config.json");
1982
- const CCR_BACKUP_DIR = CCR_CONFIG_DIR;
1983
- function ensureCcrConfigDir() {
1984
- if (!existsSync(CCR_CONFIG_DIR)) {
1985
- mkdirSync(CCR_CONFIG_DIR, { recursive: true });
1986
- }
1987
- }
1988
- function backupCcrConfig(scriptLang) {
1989
- const i18n = getTranslation(scriptLang);
1990
- try {
1991
- if (!existsSync(CCR_CONFIG_FILE)) {
1992
- return null;
1993
- }
1994
- const timestamp = dayjs().format("YYYY-MM-DDTHH-mm-ss-SSS") + "Z";
1995
- const backupFileName = `config.json.${timestamp}.bak`;
1996
- const backupPath = join$1(CCR_BACKUP_DIR, backupFileName);
1997
- console.log(ansis.cyan(`${i18n.ccr.backupCcrConfig}`));
1998
- copyFileSync(CCR_CONFIG_FILE, backupPath);
1999
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrBackupSuccess.replace("{path}", backupPath)}`));
2000
- return backupPath;
2001
- } catch (error) {
2002
- console.error(ansis.red(`${i18n.ccr.ccrBackupFailed}:`), error.message);
2003
- return null;
2004
- }
2005
- }
2006
- function readCcrConfig() {
2007
- if (!existsSync(CCR_CONFIG_FILE)) {
2008
- return null;
2009
- }
2010
- return readJsonConfig(CCR_CONFIG_FILE);
2011
- }
2012
- function writeCcrConfig(config) {
2013
- ensureCcrConfigDir();
2014
- writeJsonConfig(CCR_CONFIG_FILE, config);
2015
- }
2016
- async function configureCcrProxy(ccrConfig) {
2017
- const settings = readJsonConfig(SETTINGS_FILE) || {};
2018
- const host = ccrConfig.HOST || "127.0.0.1";
2019
- const port = ccrConfig.PORT || 3456;
2020
- const apiKey = ccrConfig.APIKEY || "sk-aico-x-ccr";
2021
- if (!settings.env) {
2022
- settings.env = {};
2023
- }
2024
- settings.env.ANTHROPIC_BASE_URL = `http://${host}:${port}`;
2025
- settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
2026
- writeJsonConfig(SETTINGS_FILE, settings);
2027
- }
2028
- async function selectCcrPreset(scriptLang) {
2029
- const i18n = getTranslation(scriptLang);
2030
- console.log(ansis.cyan(`${i18n.ccr.fetchingPresets}`));
2031
- const presets = await fetchProviderPresets();
2032
- if (!presets || presets.length === 0) {
2033
- console.log(ansis.yellow(`${i18n.ccr.noPresetsAvailable}`));
2034
- return null;
2035
- }
2036
- try {
2037
- const choices = [
2038
- {
2039
- name: `1. ${i18n.ccr.skipOption}`,
2040
- value: "skip"
2041
- },
2042
- ...presets.map((p, index) => ({
2043
- name: `${index + 2}. ${p.name}`,
2044
- value: p
2045
- }))
2046
- ];
2047
- const { preset } = await inquirer$1.prompt({
2048
- type: "list",
2049
- name: "preset",
2050
- message: i18n.ccr.selectCcrPreset,
2051
- choices
2052
- });
2053
- return preset;
2054
- } catch (error) {
2055
- if (error.name === "ExitPromptError") {
2056
- console.log(ansis.yellow(i18n.common.cancelled));
2057
- return null;
2058
- }
2059
- throw error;
2060
- }
2061
- }
2062
- async function configureCcrWithPreset(preset, scriptLang) {
2063
- const i18n = getTranslation(scriptLang);
2064
- const provider = {
2065
- name: preset.name,
2066
- // Use the original name from JSON
2067
- api_base_url: preset.baseURL || "",
2068
- api_key: "",
2069
- models: preset.models
2070
- };
2071
- if (preset.transformer) {
2072
- provider.transformer = preset.transformer;
2073
- }
2074
- if (preset.requiresApiKey) {
2075
- try {
2076
- const { apiKey } = await inquirer$1.prompt({
2077
- type: "input",
2078
- name: "apiKey",
2079
- message: i18n.ccr.enterApiKeyForProvider.replace("{provider}", preset.name),
2080
- validate: (value) => !!value || i18n.api.keyRequired
2081
- });
2082
- provider.api_key = apiKey;
2083
- } catch (error) {
2084
- if (error.name === "ExitPromptError") {
2085
- throw error;
2086
- }
2087
- throw error;
2088
- }
2089
- } else {
2090
- provider.api_key = "sk-free";
2091
- }
2092
- let defaultModel = preset.models[0];
2093
- if (preset.models.length > 1) {
2094
- try {
2095
- const { model } = await inquirer$1.prompt({
2096
- type: "list",
2097
- name: "model",
2098
- message: i18n.ccr.selectDefaultModelForProvider.replace("{provider}", preset.name),
2099
- choices: preset.models.map((m, index) => ({
2100
- name: `${index + 1}. ${m}`,
2101
- value: m
2102
- }))
2103
- });
2104
- defaultModel = model;
2105
- } catch (error) {
2106
- if (error.name === "ExitPromptError") {
2107
- throw error;
2108
- }
2109
- throw error;
2110
- }
2111
- }
2112
- const router = {
2113
- default: `${preset.name},${defaultModel}`,
2114
- // Use the original name
2115
- background: `${preset.name},${defaultModel}`,
2116
- think: `${preset.name},${defaultModel}`,
2117
- longContext: `${preset.name},${defaultModel}`,
2118
- longContextThreshold: 6e4,
2119
- webSearch: `${preset.name},${defaultModel}`
2120
- };
2121
- const config = {
2122
- LOG: true,
2123
- CLAUDE_PATH: "",
2124
- HOST: "127.0.0.1",
2125
- PORT: 3456,
2126
- APIKEY: "sk-aico-x-ccr",
2127
- API_TIMEOUT_MS: "600000",
2128
- PROXY_URL: "",
2129
- transformers: [],
2130
- Providers: [provider],
2131
- Router: router
2132
- };
2133
- return config;
2134
- }
2135
- async function restartAndCheckCcrStatus(scriptLang) {
2136
- const i18n = getTranslation(scriptLang);
2137
- try {
2138
- console.log(ansis.cyan(`${i18n.ccr.restartingCcr}`));
2139
- await execAsync$4("ccr restart");
2140
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrRestartSuccess}`));
2141
- console.log(ansis.cyan(`${i18n.ccr.checkingCcrStatus}`));
2142
- const { stdout } = await execAsync$4("ccr status");
2143
- console.log(ansis.gray(stdout));
2144
- } catch (error) {
2145
- console.error(ansis.red(`${i18n.ccr.ccrRestartFailed}:`), error.message || error);
2146
- if (process.env.DEBUG) {
2147
- console.error("Full error:", error);
2148
- }
2149
- }
2150
- }
2151
- function showConfigurationTips(scriptLang, apiKey) {
2152
- const i18n = getTranslation(scriptLang);
2153
- console.log(ansis.bold.cyan(`
2154
- \u{1F4CC} ${i18n.ccr.configTips}:`));
2155
- console.log(ansis.blue(` \u2022 ${i18n.ccr.advancedConfigTip}`));
2156
- console.log(ansis.blue(` \u2022 ${i18n.ccr.manualConfigTip}`));
2157
- console.log(ansis.bold.yellow(` \u2022 ${i18n.ccr.useClaudeCommand}`));
2158
- if (apiKey) {
2159
- console.log(ansis.bold.green(` \u2022 ${i18n.ccr.ccrUiApiKey || "CCR UI API Key"}: ${apiKey}`));
2160
- console.log(ansis.gray(` ${i18n.ccr.ccrUiApiKeyHint || "Use this API key to login to CCR UI"}`));
2161
- }
2162
- console.log("");
2163
- }
2164
- function createDefaultCcrConfig() {
2165
- return {
2166
- LOG: false,
2167
- CLAUDE_PATH: "",
2168
- HOST: "127.0.0.1",
2169
- PORT: 3456,
2170
- APIKEY: "sk-aico-x-ccr",
2171
- API_TIMEOUT_MS: "600000",
2172
- PROXY_URL: "",
2173
- transformers: [],
2174
- Providers: [],
2175
- // Empty providers array - user configures in UI
2176
- Router: {}
2177
- // Empty router configuration - user configures in UI
2178
- };
2179
- }
2180
- async function setupCcrConfiguration(scriptLang) {
2181
- const i18n = getTranslation(scriptLang);
2182
- try {
2183
- const existingConfig = readCcrConfig();
2184
- if (existingConfig) {
2185
- console.log(ansis.blue(`\u2139 ${i18n.ccr.existingCcrConfig}`));
2186
- let shouldBackupAndReconfigure = false;
2187
- try {
2188
- const result = await inquirer$1.prompt({
2189
- type: "confirm",
2190
- name: "overwrite",
2191
- message: i18n.ccr.overwriteCcrConfig,
2192
- default: false
2193
- });
2194
- shouldBackupAndReconfigure = result.overwrite;
2195
- } catch (error) {
2196
- if (error.name === "ExitPromptError") {
2197
- console.log(ansis.yellow(i18n.common.cancelled));
2198
- return false;
2199
- }
2200
- throw error;
2201
- }
2202
- if (!shouldBackupAndReconfigure) {
2203
- console.log(ansis.yellow(`${i18n.ccr.keepingExistingConfig}`));
2204
- await configureCcrProxy(existingConfig);
2205
- return true;
2206
- }
2207
- backupCcrConfig(scriptLang);
2208
- }
2209
- const preset = await selectCcrPreset(scriptLang);
2210
- if (!preset) {
2211
- return false;
2212
- }
2213
- let config;
2214
- if (preset === "skip") {
2215
- console.log(ansis.yellow(`${i18n.ccr.skipConfiguring}`));
2216
- config = createDefaultCcrConfig();
2217
- } else {
2218
- config = await configureCcrWithPreset(preset, scriptLang);
2219
- }
2220
- writeCcrConfig(config);
2221
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrConfigSuccess}`));
2222
- await configureCcrProxy(config);
2223
- console.log(ansis.green(`\u2714 ${i18n.ccr.proxyConfigSuccess}`));
2224
- await restartAndCheckCcrStatus(scriptLang);
2225
- showConfigurationTips(scriptLang, config.APIKEY);
2226
- try {
2227
- addCompletedOnboarding();
2228
- } catch (error) {
2229
- console.error(ansis.red(i18n.configuration.failedToSetOnboarding), error);
2230
- }
2231
- return true;
2232
- } catch (error) {
2233
- if (error.name === "ExitPromptError") {
2234
- console.log(ansis.yellow(i18n.common.cancelled));
2235
- return false;
2236
- }
2237
- console.error(ansis.red(`${i18n.ccr.ccrConfigFailed}:`), error);
2238
- return false;
2239
- }
2240
- }
2241
- async function configureCcrFeature(scriptLang) {
2242
- const i18n = getTranslation(scriptLang);
2243
- const backupDir = backupExistingConfig();
2244
- if (backupDir) {
2245
- console.log(ansis.gray(`\u2714 ${i18n.configuration.backupSuccess}: ${backupDir}`));
2246
- }
2247
- await setupCcrConfiguration(scriptLang);
2248
- }
2249
-
2250
1997
  function format(template, replacements) {
2251
1998
  return template.replace(/\{(\w+)\}/g, (match, key) => {
2252
1999
  return replacements[key] || match;
@@ -4959,15 +4706,15 @@ function requireSemver () {
4959
4706
  var semverExports = requireSemver();
4960
4707
  const semver = /*@__PURE__*/getDefaultExportFromCjs(semverExports);
4961
4708
 
4962
- const execAsync$3 = promisify$1(exec$2);
4709
+ const execAsync$4 = promisify(exec$1);
4963
4710
  async function getInstalledVersion(command) {
4964
4711
  try {
4965
4712
  let stdout;
4966
4713
  try {
4967
- const result = await execAsync$3(`${command} -v`);
4714
+ const result = await execAsync$4(`${command} -v`);
4968
4715
  stdout = result.stdout;
4969
4716
  } catch {
4970
- const result = await execAsync$3(`${command} --version`);
4717
+ const result = await execAsync$4(`${command} --version`);
4971
4718
  stdout = result.stdout;
4972
4719
  }
4973
4720
  const versionMatch = stdout.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
@@ -4978,7 +4725,7 @@ async function getInstalledVersion(command) {
4978
4725
  }
4979
4726
  async function getLatestVersion(packageName) {
4980
4727
  try {
4981
- const { stdout } = await execAsync$3(`npm view ${packageName} version`);
4728
+ const { stdout } = await execAsync$4(`npm view ${packageName} version`);
4982
4729
  return stdout.trim();
4983
4730
  } catch {
4984
4731
  return null;
@@ -5024,7 +4771,7 @@ async function checkCometixLineVersion() {
5024
4771
  };
5025
4772
  }
5026
4773
 
5027
- const execAsync$2 = promisify$1(exec$2);
4774
+ const execAsync$3 = promisify(exec$1);
5028
4775
  async function updateCcr(scriptLang, force = false) {
5029
4776
  const i18n = getTranslation(scriptLang);
5030
4777
  const spinner = ora(i18n.updater.checkingVersion).start();
@@ -5057,7 +4804,7 @@ async function updateCcr(scriptLang, force = false) {
5057
4804
  }
5058
4805
  const updateSpinner = ora(format(i18n.updater.updating, { tool: "CCR" })).start();
5059
4806
  try {
5060
- await execAsync$2("npm update -g @musistudio/claude-code-router");
4807
+ await execAsync$3("npm update -g @musistudio/claude-code-router");
5061
4808
  updateSpinner.succeed(format(i18n.updater.updateSuccess, { tool: "CCR" }));
5062
4809
  return true;
5063
4810
  } catch (error) {
@@ -5101,143 +4848,455 @@ async function updateClaudeCode(scriptLang, force = false) {
5101
4848
  console.log(ansis.gray(i18n.updater.updateSkipped));
5102
4849
  return true;
5103
4850
  }
5104
- const updateSpinner = ora(format(i18n.updater.updating, { tool: "Claude Code" })).start();
4851
+ const updateSpinner = ora(format(i18n.updater.updating, { tool: "Claude Code" })).start();
4852
+ try {
4853
+ await execAsync$3("npm update -g @anthropic-ai/claude-code");
4854
+ updateSpinner.succeed(format(i18n.updater.updateSuccess, { tool: "Claude Code" }));
4855
+ return true;
4856
+ } catch (error) {
4857
+ updateSpinner.fail(format(i18n.updater.updateFailed, { tool: "Claude Code" }));
4858
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
4859
+ return false;
4860
+ }
4861
+ } catch (error) {
4862
+ spinner.fail(i18n.updater.checkFailed);
4863
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
4864
+ return false;
4865
+ }
4866
+ }
4867
+ async function updateCometixLine(scriptLang, force = false) {
4868
+ const i18n = getTranslation(scriptLang);
4869
+ const spinner = ora(i18n.updater.checkingVersion).start();
4870
+ try {
4871
+ const { installed, currentVersion, latestVersion, needsUpdate } = await checkCometixLineVersion();
4872
+ spinner.stop();
4873
+ if (!installed) {
4874
+ console.log(ansis.yellow(i18n.updater.cometixLineNotInstalled));
4875
+ return false;
4876
+ }
4877
+ if (!needsUpdate && !force) {
4878
+ console.log(ansis.green(format(i18n.updater.cometixLineUpToDate, { version: currentVersion || "" })));
4879
+ return true;
4880
+ }
4881
+ if (!latestVersion) {
4882
+ console.log(ansis.yellow(i18n.updater.cannotCheckVersion));
4883
+ return false;
4884
+ }
4885
+ console.log(ansis.cyan(format(i18n.updater.currentVersion, { version: currentVersion || "" })));
4886
+ console.log(ansis.cyan(format(i18n.updater.latestVersion, { version: latestVersion })));
4887
+ const { confirm } = await inquirer$1.prompt({
4888
+ type: "confirm",
4889
+ name: "confirm",
4890
+ message: format(i18n.updater.confirmUpdate, { tool: "CCometixLine" }),
4891
+ default: true
4892
+ });
4893
+ if (!confirm) {
4894
+ console.log(ansis.gray(i18n.updater.updateSkipped));
4895
+ return true;
4896
+ }
4897
+ const updateSpinner = ora(format(i18n.updater.updating, { tool: "CCometixLine" })).start();
4898
+ try {
4899
+ await execAsync$3("cargo install ccometix");
4900
+ updateSpinner.succeed(format(i18n.updater.updateSuccess, { tool: "CCometixLine" }));
4901
+ return true;
4902
+ } catch (error) {
4903
+ updateSpinner.fail(format(i18n.updater.updateFailed, { tool: "CCometixLine" }));
4904
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
4905
+ return false;
4906
+ }
4907
+ } catch (error) {
4908
+ spinner.fail(i18n.updater.checkFailed);
4909
+ console.error(ansis.red(error instanceof Error ? error.message : String(error)));
4910
+ return false;
4911
+ }
4912
+ }
4913
+ async function checkAndUpdateTools(scriptLang) {
4914
+ const i18n = getTranslation(scriptLang);
4915
+ console.log(ansis.bold.cyan(`
4916
+ \u{1F50D} ${i18n.updater.checkingTools}
4917
+ `));
4918
+ await updateCcr(scriptLang);
4919
+ console.log();
4920
+ await updateClaudeCode(scriptLang);
4921
+ console.log();
4922
+ await updateCometixLine(scriptLang);
4923
+ }
4924
+
4925
+ const execAsync$2 = promisify$1(exec$2);
4926
+ async function isCcrInstalled() {
4927
+ let commandExists = false;
4928
+ try {
4929
+ const ccrCommand = isWindows() ? "npx ccr version" : "ccr version";
4930
+ await execAsync$2(ccrCommand);
4931
+ commandExists = true;
4932
+ } catch {
4933
+ try {
4934
+ const whichCommand = isWindows() ? "where ccr" : "which ccr";
4935
+ await execAsync$2(whichCommand);
4936
+ commandExists = true;
4937
+ } catch {
4938
+ commandExists = false;
4939
+ }
4940
+ }
4941
+ let hasCorrectPackage = false;
4942
+ try {
4943
+ await execAsync$2("npm list -g @musistudio/claude-code-router");
4944
+ hasCorrectPackage = true;
4945
+ } catch {
4946
+ hasCorrectPackage = false;
4947
+ }
4948
+ return {
4949
+ isInstalled: commandExists,
4950
+ hasCorrectPackage
4951
+ };
4952
+ }
4953
+ async function installCcr(scriptLang) {
4954
+ const i18n = getTranslation(scriptLang);
4955
+ const { isInstalled, hasCorrectPackage } = await isCcrInstalled();
4956
+ if (hasCorrectPackage) {
4957
+ console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
4958
+ await updateCcr(scriptLang);
4959
+ return;
4960
+ }
4961
+ if (isInstalled && !hasCorrectPackage) {
4962
+ try {
4963
+ await execAsync$2("npm list -g claude-code-router");
4964
+ console.log(ansis.yellow(`\u26A0 ${i18n.ccr.detectedIncorrectPackage}`));
4965
+ try {
4966
+ await execAsync$2("npm uninstall -g claude-code-router");
4967
+ console.log(ansis.green(`\u2714 ${i18n.ccr.uninstalledIncorrectPackage}`));
4968
+ } catch (uninstallError) {
4969
+ console.log(ansis.yellow(`\u26A0 ${i18n.ccr.failedToUninstallIncorrectPackage}`));
4970
+ }
4971
+ } catch {
4972
+ }
4973
+ }
4974
+ console.log(ansis.cyan(`\u{1F4E6} ${i18n.ccr.installingCcr}`));
4975
+ try {
4976
+ await execAsync$2("npm install -g @musistudio/claude-code-router --force");
4977
+ console.log(ansis.green(`\u2714 ${i18n.ccr.ccrInstallSuccess}`));
4978
+ } catch (error) {
4979
+ if (error.message?.includes("EEXIST")) {
4980
+ console.log(ansis.yellow(`\u26A0 ${i18n.ccr.ccrAlreadyInstalled}`));
4981
+ await updateCcr(scriptLang);
4982
+ return;
4983
+ }
4984
+ console.error(ansis.red(`\u2716 ${i18n.ccr.ccrInstallFailed}`));
4985
+ throw error;
4986
+ }
4987
+ }
4988
+ async function startCcrService(scriptLang) {
4989
+ const lang = scriptLang || "zh-CN";
4990
+ const i18n = getTranslation(lang);
4991
+ try {
4992
+ const ccrCommand = isWindows() ? "npx ccr" : "ccr";
4993
+ exec$2(ccrCommand, (error) => {
4994
+ if (error) {
4995
+ console.error(ansis.red(`${i18n.ccr.failedToStartCcrService}:`), error);
4996
+ }
4997
+ });
4998
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
4999
+ } catch (error) {
5000
+ console.error(ansis.red(`${i18n.ccr.errorStartingCcrService}:`), error);
5001
+ }
5002
+ }
5003
+
5004
+ const execAsync$1 = promisify$1(exec$2);
5005
+ const CCR_CONFIG_DIR = join$1(homedir(), ".claude-code-router");
5006
+ const CCR_CONFIG_FILE = join$1(CCR_CONFIG_DIR, "config.json");
5007
+ const CCR_BACKUP_DIR = CCR_CONFIG_DIR;
5008
+ function ensureCcrConfigDir() {
5009
+ if (!existsSync(CCR_CONFIG_DIR)) {
5010
+ mkdirSync(CCR_CONFIG_DIR, { recursive: true });
5011
+ }
5012
+ }
5013
+ function backupCcrConfig(scriptLang) {
5014
+ const i18n = getTranslation(scriptLang);
5015
+ try {
5016
+ if (!existsSync(CCR_CONFIG_FILE)) {
5017
+ return null;
5018
+ }
5019
+ const timestamp = dayjs().format("YYYY-MM-DDTHH-mm-ss-SSS") + "Z";
5020
+ const backupFileName = `config.json.${timestamp}.bak`;
5021
+ const backupPath = join$1(CCR_BACKUP_DIR, backupFileName);
5022
+ console.log(ansis.cyan(`${i18n.ccr.backupCcrConfig}`));
5023
+ copyFileSync(CCR_CONFIG_FILE, backupPath);
5024
+ console.log(ansis.green(`\u2714 ${i18n.ccr.ccrBackupSuccess.replace("{path}", backupPath)}`));
5025
+ return backupPath;
5026
+ } catch (error) {
5027
+ console.error(ansis.red(`${i18n.ccr.ccrBackupFailed}:`), error.message);
5028
+ return null;
5029
+ }
5030
+ }
5031
+ function readCcrConfig() {
5032
+ if (!existsSync(CCR_CONFIG_FILE)) {
5033
+ return null;
5034
+ }
5035
+ return readJsonConfig(CCR_CONFIG_FILE);
5036
+ }
5037
+ function writeCcrConfig(config) {
5038
+ ensureCcrConfigDir();
5039
+ writeJsonConfig(CCR_CONFIG_FILE, config);
5040
+ }
5041
+ async function configureCcrProxy(ccrConfig) {
5042
+ const settings = readJsonConfig(SETTINGS_FILE) || {};
5043
+ const host = ccrConfig.HOST || "127.0.0.1";
5044
+ const port = ccrConfig.PORT || 3456;
5045
+ const apiKey = ccrConfig.APIKEY || "sk-aico-x-ccr";
5046
+ if (!settings.env) {
5047
+ settings.env = {};
5048
+ }
5049
+ settings.env.ANTHROPIC_BASE_URL = `http://${host}:${port}`;
5050
+ settings.env.ANTHROPIC_AUTH_TOKEN = apiKey;
5051
+ writeJsonConfig(SETTINGS_FILE, settings);
5052
+ }
5053
+ async function selectCcrPreset(scriptLang) {
5054
+ const i18n = getTranslation(scriptLang);
5055
+ console.log(ansis.cyan(`${i18n.ccr.fetchingPresets}`));
5056
+ const presets = await fetchProviderPresets();
5057
+ if (!presets || presets.length === 0) {
5058
+ console.log(ansis.yellow(`${i18n.ccr.noPresetsAvailable}`));
5059
+ return null;
5060
+ }
5061
+ try {
5062
+ const choices = [
5063
+ {
5064
+ name: `1. ${i18n.ccr.skipOption}`,
5065
+ value: "skip"
5066
+ },
5067
+ ...presets.map((p, index) => ({
5068
+ name: `${index + 2}. ${p.name}`,
5069
+ value: p
5070
+ }))
5071
+ ];
5072
+ const { preset } = await inquirer$1.prompt({
5073
+ type: "list",
5074
+ name: "preset",
5075
+ message: i18n.ccr.selectCcrPreset,
5076
+ choices
5077
+ });
5078
+ return preset;
5079
+ } catch (error) {
5080
+ if (error.name === "ExitPromptError") {
5081
+ console.log(ansis.yellow(i18n.common.cancelled));
5082
+ return null;
5083
+ }
5084
+ throw error;
5085
+ }
5086
+ }
5087
+ async function configureCcrWithPreset(preset, scriptLang) {
5088
+ const i18n = getTranslation(scriptLang);
5089
+ const provider = {
5090
+ name: preset.name,
5091
+ // Use the original name from JSON
5092
+ api_base_url: preset.baseURL || "",
5093
+ api_key: "",
5094
+ models: preset.models
5095
+ };
5096
+ if (preset.transformer) {
5097
+ provider.transformer = preset.transformer;
5098
+ }
5099
+ if (preset.requiresApiKey) {
5100
+ try {
5101
+ const { apiKey } = await inquirer$1.prompt({
5102
+ type: "input",
5103
+ name: "apiKey",
5104
+ message: i18n.ccr.enterApiKeyForProvider.replace("{provider}", preset.name),
5105
+ validate: (value) => !!value || i18n.api.keyRequired
5106
+ });
5107
+ provider.api_key = apiKey;
5108
+ } catch (error) {
5109
+ if (error.name === "ExitPromptError") {
5110
+ throw error;
5111
+ }
5112
+ throw error;
5113
+ }
5114
+ } else {
5115
+ provider.api_key = "sk-free";
5116
+ }
5117
+ let defaultModel = preset.models[0];
5118
+ if (preset.models.length > 1) {
5105
5119
  try {
5106
- await execAsync$2("npm update -g @anthropic-ai/claude-code");
5107
- updateSpinner.succeed(format(i18n.updater.updateSuccess, { tool: "Claude Code" }));
5108
- return true;
5120
+ const { model } = await inquirer$1.prompt({
5121
+ type: "list",
5122
+ name: "model",
5123
+ message: i18n.ccr.selectDefaultModelForProvider.replace("{provider}", preset.name),
5124
+ choices: preset.models.map((m, index) => ({
5125
+ name: `${index + 1}. ${m}`,
5126
+ value: m
5127
+ }))
5128
+ });
5129
+ defaultModel = model;
5109
5130
  } catch (error) {
5110
- updateSpinner.fail(format(i18n.updater.updateFailed, { tool: "Claude Code" }));
5111
- console.error(ansis.red(error instanceof Error ? error.message : String(error)));
5112
- return false;
5131
+ if (error.name === "ExitPromptError") {
5132
+ throw error;
5133
+ }
5134
+ throw error;
5113
5135
  }
5114
- } catch (error) {
5115
- spinner.fail(i18n.updater.checkFailed);
5116
- console.error(ansis.red(error instanceof Error ? error.message : String(error)));
5117
- return false;
5118
5136
  }
5137
+ const router = {
5138
+ default: `${preset.name},${defaultModel}`,
5139
+ // Use the original name
5140
+ background: `${preset.name},${defaultModel}`,
5141
+ think: `${preset.name},${defaultModel}`,
5142
+ longContext: `${preset.name},${defaultModel}`,
5143
+ longContextThreshold: 6e4,
5144
+ webSearch: `${preset.name},${defaultModel}`
5145
+ };
5146
+ const config = {
5147
+ LOG: true,
5148
+ CLAUDE_PATH: "",
5149
+ HOST: "127.0.0.1",
5150
+ PORT: 3456,
5151
+ APIKEY: "sk-aico-x-ccr",
5152
+ API_TIMEOUT_MS: "600000",
5153
+ PROXY_URL: "",
5154
+ transformers: [],
5155
+ Providers: [provider],
5156
+ Router: router
5157
+ };
5158
+ return config;
5119
5159
  }
5120
- async function updateCometixLine(scriptLang, force = false) {
5160
+ async function restartAndCheckCcrStatus(scriptLang) {
5121
5161
  const i18n = getTranslation(scriptLang);
5122
- const spinner = ora(i18n.updater.checkingVersion).start();
5123
5162
  try {
5124
- const { installed, currentVersion, latestVersion, needsUpdate } = await checkCometixLineVersion();
5125
- spinner.stop();
5126
- if (!installed) {
5127
- console.log(ansis.yellow(i18n.updater.cometixLineNotInstalled));
5128
- return false;
5129
- }
5130
- if (!needsUpdate && !force) {
5131
- console.log(ansis.green(format(i18n.updater.cometixLineUpToDate, { version: currentVersion || "" })));
5132
- return true;
5133
- }
5134
- if (!latestVersion) {
5135
- console.log(ansis.yellow(i18n.updater.cannotCheckVersion));
5136
- return false;
5137
- }
5138
- console.log(ansis.cyan(format(i18n.updater.currentVersion, { version: currentVersion || "" })));
5139
- console.log(ansis.cyan(format(i18n.updater.latestVersion, { version: latestVersion })));
5140
- const { confirm } = await inquirer$1.prompt({
5141
- type: "confirm",
5142
- name: "confirm",
5143
- message: format(i18n.updater.confirmUpdate, { tool: "CCometixLine" }),
5144
- default: true
5145
- });
5146
- if (!confirm) {
5147
- console.log(ansis.gray(i18n.updater.updateSkipped));
5148
- return true;
5149
- }
5150
- const updateSpinner = ora(format(i18n.updater.updating, { tool: "CCometixLine" })).start();
5151
- try {
5152
- await execAsync$2("cargo install ccometix");
5153
- updateSpinner.succeed(format(i18n.updater.updateSuccess, { tool: "CCometixLine" }));
5154
- return true;
5155
- } catch (error) {
5156
- updateSpinner.fail(format(i18n.updater.updateFailed, { tool: "CCometixLine" }));
5157
- console.error(ansis.red(error instanceof Error ? error.message : String(error)));
5158
- return false;
5159
- }
5163
+ console.log(ansis.cyan(`${i18n.ccr.restartingCcr}`));
5164
+ await execAsync$1("ccr restart", { encoding: "buffer", maxBuffer: 10 * 1024 * 1024 });
5165
+ console.log(ansis.green(`\u2714 ${i18n.ccr.ccrRestartSuccess}`));
5166
+ console.log(ansis.cyan(`${i18n.ccr.checkingCcrStatus}`));
5167
+ const { stdout } = await execAsync$1("ccr status", { encoding: "buffer", maxBuffer: 10 * 1024 * 1024 });
5168
+ const statusOut = Buffer.isBuffer(stdout) ? stdout.toString("utf8").replace(/\0/g, "") : String(stdout);
5169
+ console.log(ansis.gray(statusOut));
5160
5170
  } catch (error) {
5161
- spinner.fail(i18n.updater.checkFailed);
5162
- console.error(ansis.red(error instanceof Error ? error.message : String(error)));
5163
- return false;
5171
+ console.error(ansis.red(`${i18n.ccr.ccrRestartFailed}:`), error);
5164
5172
  }
5165
5173
  }
5166
- async function checkAndUpdateTools(scriptLang) {
5174
+ function showConfigurationTips(scriptLang, apiKey) {
5167
5175
  const i18n = getTranslation(scriptLang);
5168
5176
  console.log(ansis.bold.cyan(`
5169
- \u{1F50D} ${i18n.updater.checkingTools}
5170
- `));
5171
- await updateCcr(scriptLang);
5172
- console.log();
5173
- await updateClaudeCode(scriptLang);
5174
- console.log();
5175
- await updateCometixLine(scriptLang);
5176
- }
5177
-
5178
- const execAsync$1 = promisify(exec$1);
5179
- async function isCcrInstalled() {
5180
- let commandExists = false;
5181
- try {
5182
- const ccrCommand = isWindows() ? "npx ccr version" : "ccr version";
5183
- await execAsync$1(ccrCommand);
5184
- commandExists = true;
5185
- } catch {
5186
- try {
5187
- const whichCommand = isWindows() ? "where ccr" : "which ccr";
5188
- await execAsync$1(whichCommand);
5189
- commandExists = true;
5190
- } catch {
5191
- commandExists = false;
5192
- }
5193
- }
5194
- let hasCorrectPackage = false;
5195
- try {
5196
- await execAsync$1("npm list -g @musistudio/claude-code-router");
5197
- hasCorrectPackage = true;
5198
- } catch {
5199
- hasCorrectPackage = false;
5177
+ \u{1F4CC} ${i18n.ccr.configTips}:`));
5178
+ console.log(ansis.blue(` \u2022 ${i18n.ccr.advancedConfigTip}`));
5179
+ console.log(ansis.blue(` \u2022 ${i18n.ccr.manualConfigTip}`));
5180
+ console.log(ansis.bold.yellow(` \u2022 ${i18n.ccr.useClaudeCommand}`));
5181
+ if (apiKey) {
5182
+ console.log(ansis.bold.green(` \u2022 ${i18n.ccr.ccrUiApiKey || "CCR UI API Key"}: ${apiKey}`));
5183
+ console.log(ansis.gray(` ${i18n.ccr.ccrUiApiKeyHint || "Use this API key to login to CCR UI"}`));
5200
5184
  }
5185
+ console.log("");
5186
+ }
5187
+ function createDefaultCcrConfig() {
5201
5188
  return {
5202
- isInstalled: commandExists,
5203
- hasCorrectPackage
5189
+ LOG: false,
5190
+ CLAUDE_PATH: "",
5191
+ HOST: "127.0.0.1",
5192
+ PORT: 3456,
5193
+ APIKEY: "sk-aico-x-ccr",
5194
+ API_TIMEOUT_MS: "600000",
5195
+ PROXY_URL: "",
5196
+ transformers: [],
5197
+ Providers: [],
5198
+ // Empty providers array - user configures in UI
5199
+ Router: {}
5200
+ // Empty router configuration - user configures in UI
5204
5201
  };
5205
5202
  }
5206
- async function installCcr(scriptLang) {
5203
+ async function setupCcrConfiguration(scriptLang) {
5207
5204
  const i18n = getTranslation(scriptLang);
5208
- const { isInstalled, hasCorrectPackage } = await isCcrInstalled();
5209
- if (hasCorrectPackage) {
5210
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
5211
- await updateCcr(scriptLang);
5212
- return;
5213
- }
5214
- if (isInstalled && !hasCorrectPackage) {
5215
- try {
5216
- await execAsync$1("npm list -g claude-code-router");
5217
- console.log(ansis.yellow(`\u26A0 ${i18n.ccr.detectedIncorrectPackage}`));
5205
+ try {
5206
+ const existingConfig = readCcrConfig();
5207
+ if (existingConfig) {
5208
+ console.log(ansis.blue(`\u2139 ${i18n.ccr.existingCcrConfig}`));
5209
+ let shouldBackupAndReconfigure = false;
5218
5210
  try {
5219
- await execAsync$1("npm uninstall -g claude-code-router");
5220
- console.log(ansis.green(`\u2714 ${i18n.ccr.uninstalledIncorrectPackage}`));
5221
- } catch (uninstallError) {
5222
- console.log(ansis.yellow(`\u26A0 ${i18n.ccr.failedToUninstallIncorrectPackage}`));
5211
+ const result = await inquirer$1.prompt({
5212
+ type: "confirm",
5213
+ name: "overwrite",
5214
+ message: i18n.ccr.overwriteCcrConfig,
5215
+ default: false
5216
+ });
5217
+ shouldBackupAndReconfigure = result.overwrite;
5218
+ } catch (error) {
5219
+ if (error.name === "ExitPromptError") {
5220
+ console.log(ansis.yellow(i18n.common.cancelled));
5221
+ return false;
5222
+ }
5223
+ throw error;
5223
5224
  }
5224
- } catch {
5225
+ if (!shouldBackupAndReconfigure) {
5226
+ console.log(ansis.yellow(`${i18n.ccr.keepingExistingConfig}`));
5227
+ await configureCcrProxy(existingConfig);
5228
+ return true;
5229
+ }
5230
+ backupCcrConfig(scriptLang);
5225
5231
  }
5226
- }
5227
- console.log(ansis.cyan(`\u{1F4E6} ${i18n.ccr.installingCcr}`));
5228
- try {
5229
- await execAsync$1("npm install -g @musistudio/claude-code-router --force");
5230
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrInstallSuccess}`));
5232
+ const preset = await selectCcrPreset(scriptLang);
5233
+ if (!preset) {
5234
+ return false;
5235
+ }
5236
+ let config;
5237
+ if (preset === "skip") {
5238
+ console.log(ansis.yellow(`${i18n.ccr.skipConfiguring}`));
5239
+ config = createDefaultCcrConfig();
5240
+ } else {
5241
+ config = await configureCcrWithPreset(preset, scriptLang);
5242
+ }
5243
+ writeCcrConfig(config);
5244
+ console.log(ansis.green(`\u2714 ${i18n.ccr.ccrConfigSuccess}`));
5245
+ await configureCcrProxy(config);
5246
+ console.log(ansis.green(`\u2714 ${i18n.ccr.proxyConfigSuccess}`));
5247
+ try {
5248
+ console.log(ansis.cyan(i18n.ccr.checkingInstallation || "Checking CCR installation..."));
5249
+ const { isInstalled, hasCorrectPackage } = await isCcrInstalled();
5250
+ if (isInstalled && hasCorrectPackage) {
5251
+ console.log(ansis.green(i18n.ccr.ccrAlreadyInstalled || "\u2714 CCR is already installed and up to date."));
5252
+ } else if (isInstalled && !hasCorrectPackage) {
5253
+ console.log(ansis.yellow(i18n.ccr.ccrInstalledWrongPackage || "\u26A0 CCR is installed but has an unexpected package/version. Will reinstall."));
5254
+ } else {
5255
+ console.log(ansis.yellow(i18n.ccr.ccrNotInstalled || "\u2716 CCR is not installed."));
5256
+ }
5257
+ if (!isInstalled || !hasCorrectPackage) {
5258
+ console.log(ansis.cyan(i18n.ccr.installingCcr || "Installing CCR..."));
5259
+ try {
5260
+ console.log(ansis.cyan(i18n.ccr.installationStarting || "Starting CCR installation..."));
5261
+ await installCcr(scriptLang);
5262
+ console.log(ansis.green(i18n.ccr.installationSuccess || "\u2714 CCR installation completed."));
5263
+ console.log(ansis.cyan(i18n.ccr.startingCcrService || "Starting CCR service..."));
5264
+ await startCcrService(scriptLang);
5265
+ console.log(ansis.green(i18n.ccr.ccrServiceStarted || "\u2714 CCR service started."));
5266
+ } catch (installError) {
5267
+ console.error(ansis.red(`${i18n.ccr.ccrInstallFailed}:`), installError);
5268
+ return false;
5269
+ }
5270
+ }
5271
+ } catch (checkError) {
5272
+ console.error(ansis.red(`${i18n.ccr.ccrInstallCheckFailed || i18n.ccr.ccrInstallFailed}:`), checkError);
5273
+ return false;
5274
+ }
5275
+ await restartAndCheckCcrStatus(scriptLang);
5276
+ showConfigurationTips(scriptLang, config.APIKEY);
5277
+ try {
5278
+ addCompletedOnboarding();
5279
+ } catch (error) {
5280
+ console.error(ansis.red(i18n.configuration.failedToSetOnboarding), error);
5281
+ }
5282
+ return true;
5231
5283
  } catch (error) {
5232
- if (error.message?.includes("EEXIST")) {
5233
- console.log(ansis.yellow(`\u26A0 ${i18n.ccr.ccrAlreadyInstalled}`));
5234
- await updateCcr(scriptLang);
5235
- return;
5284
+ if (error.name === "ExitPromptError") {
5285
+ console.log(ansis.yellow(i18n.common.cancelled));
5286
+ return false;
5236
5287
  }
5237
- console.error(ansis.red(`\u2716 ${i18n.ccr.ccrInstallFailed}`));
5238
- throw error;
5288
+ console.error(ansis.red(`${i18n.ccr.ccrConfigFailed}:`), error);
5289
+ return false;
5239
5290
  }
5240
5291
  }
5292
+ async function configureCcrFeature(scriptLang) {
5293
+ const i18n = getTranslation(scriptLang);
5294
+ const backupDir = backupExistingConfig();
5295
+ if (backupDir) {
5296
+ console.log(ansis.gray(`\u2714 ${i18n.configuration.backupSuccess}: ${backupDir}`));
5297
+ }
5298
+ await setupCcrConfiguration(scriptLang);
5299
+ }
5241
5300
 
5242
5301
  const COMETIX_PACKAGE_NAME = "@cometix/ccline";
5243
5302
  const COMETIX_COMMAND_NAME = "ccline";
@@ -5283,7 +5342,7 @@ function hasCCometixLineConfig() {
5283
5342
  }
5284
5343
  }
5285
5344
 
5286
- const execAsync = promisify(exec$1);
5345
+ const execAsync = promisify$1(exec$2);
5287
5346
  async function isCometixLineInstalled() {
5288
5347
  try {
5289
5348
  await execAsync(COMETIX_COMMANDS.CHECK_INSTALL);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aico-cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "packageManager": "pnpm@9.15.9",
5
5
  "description": "AI CLI",
6
6
  "repository": {