aico-cli 0.1.2 → 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.d.mts CHANGED
@@ -1 +1,6 @@
1
1
 
2
+ declare global {
3
+ interface Array<T> {
4
+ findLastIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number;
5
+ }
6
+ }
package/dist/cli.d.ts CHANGED
@@ -1 +1,6 @@
1
1
 
2
+ declare global {
3
+ interface Array<T> {
4
+ findLastIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number;
5
+ }
6
+ }
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 readCcrConfig, U as isCcrInstalled, V as installCcr, W as configureCcrFeature, X as handleExitPromptError, Y as handleGeneralError, Z as readAicoConfigAsync, _ as COMETIX_COMMANDS, $ as COMETIX_COMMAND_NAME, a0 as installCometixLine, o as openSettingsJson, b as importRecommendedPermissions, a as importRecommendedEnv, a1 as isWindows, 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.BM5W68Yb.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';
@@ -116,7 +116,8 @@ async function runCcrUi(scriptLang, apiKey) {
116
116
  `));
117
117
  }
118
118
  try {
119
- const { stdout, stderr } = await execAsync$1("ccr ui");
119
+ const ccrCommand = isWindows() ? "npx ccr ui" : "ccr ui";
120
+ const { stdout, stderr } = await execAsync$1(ccrCommand);
120
121
  if (stdout) console.log(stdout);
121
122
  if (stderr) console.error(ansis.yellow(stderr));
122
123
  console.log(ansis.green(`\u2714 ${i18n.ccr.ccrUiStarted}`));
@@ -130,7 +131,8 @@ async function runCcrStatus(scriptLang) {
130
131
  console.log(ansis.cyan(`
131
132
  \u{1F4CA} ${i18n.ccr.checkingCcrStatus}`));
132
133
  try {
133
- const { stdout, stderr } = await execAsync$1("ccr status");
134
+ const ccrCommand = isWindows() ? "npx ccr status" : "ccr status";
135
+ const { stdout, stderr } = await execAsync$1(ccrCommand);
134
136
  if (stdout) {
135
137
  console.log("\n" + ansis.bold(i18n.ccr.ccrStatusTitle));
136
138
  console.log(stdout);
@@ -146,7 +148,8 @@ async function runCcrRestart(scriptLang) {
146
148
  console.log(ansis.cyan(`
147
149
  \u{1F504} ${i18n.ccr.restartingCcr}`));
148
150
  try {
149
- const { stdout, stderr } = await execAsync$1("ccr restart");
151
+ const ccrCommand = isWindows() ? "npx ccr restart" : "ccr restart";
152
+ const { stdout, stderr } = await execAsync$1(ccrCommand);
150
153
  if (stdout) console.log(stdout);
151
154
  if (stderr) console.error(ansis.yellow(stderr));
152
155
  console.log(ansis.green(`\u2714 ${i18n.ccr.ccrRestarted}`));
@@ -160,7 +163,8 @@ async function runCcrStart(scriptLang) {
160
163
  console.log(ansis.cyan(`
161
164
  \u25B6\uFE0F ${i18n.ccr.startingCcr}`));
162
165
  try {
163
- const { stdout, stderr } = await execAsync$1("ccr start");
166
+ const ccrCommand = isWindows() ? "npx ccr start" : "ccr start";
167
+ const { stdout, stderr } = await execAsync$1(ccrCommand);
164
168
  if (stdout) console.log(stdout);
165
169
  if (stderr) console.error(ansis.yellow(stderr));
166
170
  console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStarted}`));
@@ -180,7 +184,8 @@ async function runCcrStop(scriptLang) {
180
184
  console.log(ansis.cyan(`
181
185
  \u23F9\uFE0F ${i18n.ccr.stoppingCcr}`));
182
186
  try {
183
- const { stdout, stderr } = await execAsync$1("ccr stop");
187
+ const ccrCommand = isWindows() ? "npx ccr stop" : "ccr stop";
188
+ const { stdout, stderr } = await execAsync$1(ccrCommand);
184
189
  if (stdout) console.log(stdout);
185
190
  if (stderr) console.error(ansis.yellow(stderr));
186
191
  console.log(ansis.green(`\u2714 ${i18n.ccr.ccrStopped}`));
@@ -1120,7 +1125,6 @@ async function handleInitCommand(options) {
1120
1125
  force: options.force,
1121
1126
  skipPrompt: options.skipPrompt,
1122
1127
  configAction: options.configAction,
1123
- apiType: options.apiType,
1124
1128
  apiKey: options.apiKey,
1125
1129
  apiUrl: options.apiUrl,
1126
1130
  mcpServices: options.mcpServices,
@@ -1217,6 +1221,25 @@ function customizeHelp(sections) {
1217
1221
  return sections;
1218
1222
  }
1219
1223
 
1224
+ if (!Array.prototype.findLastIndex) {
1225
+ Array.prototype.findLastIndex = function(predicate, thisArg) {
1226
+ if (this == null) {
1227
+ throw new TypeError("Array.prototype.findLastIndex called on null or undefined");
1228
+ }
1229
+ if (typeof predicate !== "function") {
1230
+ throw new TypeError("predicate must be a function");
1231
+ }
1232
+ const array = Object(this);
1233
+ const length = array.length >>> 0;
1234
+ for (let i = length - 1; i >= 0; i--) {
1235
+ if (predicate.call(thisArg, array[i], i, array)) {
1236
+ return i;
1237
+ }
1238
+ }
1239
+ return -1;
1240
+ };
1241
+ }
1242
+
1220
1243
  async function main() {
1221
1244
  const cli = cac("aico");
1222
1245
  setupCommands(cli);
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.BM5W68Yb.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.2";
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,141 +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
- await execAsync$1("ccr version");
5183
- commandExists = true;
5184
- } catch {
5185
- try {
5186
- await execAsync$1("which ccr");
5187
- commandExists = true;
5188
- } catch {
5189
- commandExists = false;
5190
- }
5191
- }
5192
- let hasCorrectPackage = false;
5193
- try {
5194
- await execAsync$1("npm list -g @musistudio/claude-code-router");
5195
- hasCorrectPackage = true;
5196
- } catch {
5197
- 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"}`));
5198
5184
  }
5185
+ console.log("");
5186
+ }
5187
+ function createDefaultCcrConfig() {
5199
5188
  return {
5200
- isInstalled: commandExists,
5201
- 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
5202
5201
  };
5203
5202
  }
5204
- async function installCcr(scriptLang) {
5203
+ async function setupCcrConfiguration(scriptLang) {
5205
5204
  const i18n = getTranslation(scriptLang);
5206
- const { isInstalled, hasCorrectPackage } = await isCcrInstalled();
5207
- if (hasCorrectPackage) {
5208
- console.log(ansis.green(`\u2714 ${i18n.ccr.ccrAlreadyInstalled}`));
5209
- await updateCcr(scriptLang);
5210
- return;
5211
- }
5212
- if (isInstalled && !hasCorrectPackage) {
5213
- try {
5214
- await execAsync$1("npm list -g claude-code-router");
5215
- 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;
5216
5210
  try {
5217
- await execAsync$1("npm uninstall -g claude-code-router");
5218
- console.log(ansis.green(`\u2714 ${i18n.ccr.uninstalledIncorrectPackage}`));
5219
- } catch (uninstallError) {
5220
- 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;
5221
5224
  }
5222
- } catch {
5225
+ if (!shouldBackupAndReconfigure) {
5226
+ console.log(ansis.yellow(`${i18n.ccr.keepingExistingConfig}`));
5227
+ await configureCcrProxy(existingConfig);
5228
+ return true;
5229
+ }
5230
+ backupCcrConfig(scriptLang);
5223
5231
  }
5224
- }
5225
- console.log(ansis.cyan(`\u{1F4E6} ${i18n.ccr.installingCcr}`));
5226
- try {
5227
- await execAsync$1("npm install -g @musistudio/claude-code-router --force");
5228
- 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;
5229
5283
  } catch (error) {
5230
- if (error.message?.includes("EEXIST")) {
5231
- console.log(ansis.yellow(`\u26A0 ${i18n.ccr.ccrAlreadyInstalled}`));
5232
- await updateCcr(scriptLang);
5233
- return;
5284
+ if (error.name === "ExitPromptError") {
5285
+ console.log(ansis.yellow(i18n.common.cancelled));
5286
+ return false;
5234
5287
  }
5235
- console.error(ansis.red(`\u2716 ${i18n.ccr.ccrInstallFailed}`));
5236
- throw error;
5288
+ console.error(ansis.red(`${i18n.ccr.ccrConfigFailed}:`), error);
5289
+ return false;
5237
5290
  }
5238
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
+ }
5239
5300
 
5240
5301
  const COMETIX_PACKAGE_NAME = "@cometix/ccline";
5241
5302
  const COMETIX_COMMAND_NAME = "ccline";
@@ -5281,7 +5342,7 @@ function hasCCometixLineConfig() {
5281
5342
  }
5282
5343
  }
5283
5344
 
5284
- const execAsync = promisify(exec$1);
5345
+ const execAsync = promisify$1(exec$2);
5285
5346
  async function isCometixLineInstalled() {
5286
5347
  try {
5287
5348
  await execAsync(COMETIX_COMMANDS.CHECK_INSTALL);
@@ -6025,4 +6086,4 @@ async function openSettingsJson() {
6025
6086
  }
6026
6087
  }
6027
6088
 
6028
- export { COMETIX_COMMAND_NAME as $, AICO_CONFIG_FILE as A, writeMcpConfig as B, CLAUDE_DIR as C, backupMcpConfig as D, mergeMcpServers as E, buildMcpServerConfig as F, fixWindowsMcpConfig as G, addCompletedOnboarding as H, I18N as I, readAicoConfig as J, updateAicoConfig as K, LEGACY_AICO_CONFIG_FILE as L, MCP_SERVICES as M, getTranslation as N, inquirer as O, addNumbersToChoices as P, version as Q, configureAiPersonality as R, SETTINGS_FILE as S, readCcrConfig as T, isCcrInstalled as U, installCcr as V, configureCcrFeature as W, handleExitPromptError as X, handleGeneralError as Y, readAicoConfigAsync as Z, COMETIX_COMMANDS as _, importRecommendedEnv as a, installCometixLine as a0, isWindows as a1, selectMcpServices as a2, EscapeKeyPressed as a3, displayBanner as a4, selectAndInstallWorkflows as a5, displayBannerWithInfo as a6, executeWithEscapeSupport as a7, checkAndUpdateTools as a8, importRecommendedPermissions as b, commandExists as c, cleanupPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, SUPPORTED_LANGS as h, init as i, LANG_LABELS as j, AI_OUTPUT_LANGUAGES as k, isClaudeCodeInstalled as l, mergeAndCleanPermissions as m, installClaudeCode as n, openSettingsJson as o, ensureClaudeDir as p, backupExistingConfig as q, copyConfigFiles as r, configureApi as s, mergeConfigs as t, updateDefaultModel as u, mergeSettingsFile as v, getExistingApiConfig as w, applyAiLanguageDirective as x, getMcpConfigPath as y, readMcpConfig as z };
6089
+ export { COMETIX_COMMANDS as $, AICO_CONFIG_FILE as A, writeMcpConfig as B, CLAUDE_DIR as C, backupMcpConfig as D, mergeMcpServers as E, buildMcpServerConfig as F, fixWindowsMcpConfig as G, addCompletedOnboarding as H, I18N as I, readAicoConfig as J, updateAicoConfig as K, LEGACY_AICO_CONFIG_FILE as L, MCP_SERVICES as M, getTranslation as N, inquirer as O, addNumbersToChoices as P, version as Q, configureAiPersonality as R, SETTINGS_FILE as S, isWindows as T, readCcrConfig as U, isCcrInstalled as V, installCcr as W, configureCcrFeature as X, handleExitPromptError as Y, handleGeneralError as Z, readAicoConfigAsync as _, importRecommendedEnv as a, COMETIX_COMMAND_NAME as a0, installCometixLine as a1, selectMcpServices as a2, EscapeKeyPressed as a3, displayBanner as a4, selectAndInstallWorkflows as a5, displayBannerWithInfo as a6, executeWithEscapeSupport as a7, checkAndUpdateTools as a8, importRecommendedPermissions as b, commandExists as c, cleanupPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, SUPPORTED_LANGS as h, init as i, LANG_LABELS as j, AI_OUTPUT_LANGUAGES as k, isClaudeCodeInstalled as l, mergeAndCleanPermissions as m, installClaudeCode as n, openSettingsJson as o, ensureClaudeDir as p, backupExistingConfig as q, copyConfigFiles as r, configureApi as s, mergeConfigs as t, updateDefaultModel as u, mergeSettingsFile as v, getExistingApiConfig as w, applyAiLanguageDirective as x, getMcpConfigPath as y, readMcpConfig as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aico-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "packageManager": "pnpm@9.15.9",
5
5
  "description": "AI CLI",
6
6
  "repository": {
@@ -39,7 +39,7 @@
39
39
  "cac": "^6.7.14",
40
40
  "dayjs": "^1.11.13",
41
41
  "find-up-simple": "^1.0.1",
42
- "inquirer": "^12.9.0",
42
+ "inquirer": "^12.9.3",
43
43
  "ora": "^8.2.0",
44
44
  "pathe": "^2.0.3",
45
45
  "tinyexec": "^1.0.1"