UNPKG

zcf

Version:

Zero-Config Code Flow - One-click configuration tool for Code Cli

1,478 lines (1,467 loc) 77.3 kB
#!/usr/bin/env node import cac from 'cac'; import ansis from 'ansis'; import { ak as ensureI18nInitialized, al as i18n, aO as readCcrConfig, aJ as isCcrInstalled, aK as installCcr, aP as configureCcrFeature, ao as promptBoolean, aQ as handleExitPromptError, aR as handleGeneralError, aS as COMETIX_COMMAND_NAME, aT as COMETIX_COMMANDS, aU as installCometixLine, am as addNumbersToChoices, aV as checkAndUpdateTools, aW as runCodexUpdate, aX as resolveCodeType$1, at as readJsonConfig, aY as writeJsonConfig, q as ZCF_CONFIG_FILE, aE as readZcfConfig, D as DEFAULT_CODE_TOOL_TYPE, u as isCodeToolType, aZ as displayBanner, aC as updateZcfConfig, a_ as version, a$ as resolveAiOutputLanguage, b0 as updatePromptOnly, b1 as selectAndInstallWorkflows, b2 as checkClaudeCodeVersionAndPrompt, w as resolveCodeToolType$1, b3 as displayBannerWithInfo, s as CODE_TOOL_BANNERS, b4 as runCodexUninstall, b5 as configureCodexMcp, b6 as configureCodexApi, b7 as runCodexWorkflowImportWithLanguageSelection, b8 as runCodexFullInit, i as init, b9 as switchCodexProvider, ba as listCodexProviders, ay as readCodexConfig, bb as switchToOfficialLogin, bc as switchToProvider, bd as readZcfConfigAsync, be as initI18n, bf as selectScriptLanguage, aD as changeLanguage } from './chunks/simple-config.mjs'; import { existsSync } from 'node:fs'; import { homedir } from 'node:os'; import inquirer from 'inquirer'; import { join } from 'pathe'; import { runCcrStop, runCcrStart, runCcrRestart, runCcrStatus, runCcrUi } from './chunks/commands.mjs'; import { changeScriptLanguageFeature, configureCodexAiMemoryFeature, configureCodexDefaultModelFeature, configureEnvPermissionFeature, configureAiMemoryFeature, configureDefaultModelFeature, configureMcpFeature, configureApiFeature } from './chunks/features.mjs'; import process from 'node:process'; import { x, exec as exec$1 } from 'tinyexec'; import { exec, spawn } from 'node:child_process'; import { promisify } from 'node:util'; import { pathExists } from 'fs-extra'; import { m as moveToTrash } from './shared/zcf.DGjQxTq_.mjs'; import { ClaudeCodeConfigManager } from './chunks/claude-code-config-manager.mjs'; import 'dayjs'; import 'node:url'; import 'inquirer-toggle'; import 'ora'; import 'semver'; import 'smol-toml'; import 'node:fs/promises'; import 'i18next'; import 'i18next-fs-backend'; import 'trash'; function isCcrConfigured() { const CCR_CONFIG_FILE = join(homedir(), ".claude-code-router", "config.json"); if (!existsSync(CCR_CONFIG_FILE)) { return false; } const config = readCcrConfig(); return config !== null; } async function showCcrMenu() { try { ensureI18nInitialized(); console.log(` ${ansis.cyan("\u2550".repeat(50))}`); console.log(ansis.bold.cyan(` ${i18n.t("ccr:ccrMenuTitle")}`)); console.log(`${ansis.cyan("\u2550".repeat(50))} `); console.log(` ${ansis.cyan("1.")} ${i18n.t("ccr:ccrMenuOptions.initCcr")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.initCcr")}`)}`); console.log(` ${ansis.cyan("2.")} ${i18n.t("ccr:ccrMenuOptions.startUi")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.startUi")}`)}`); console.log(` ${ansis.cyan("3.")} ${i18n.t("ccr:ccrMenuOptions.checkStatus")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.checkStatus")}`)}`); console.log(` ${ansis.cyan("4.")} ${i18n.t("ccr:ccrMenuOptions.restart")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.restart")}`)}`); console.log(` ${ansis.cyan("5.")} ${i18n.t("ccr:ccrMenuOptions.start")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.start")}`)}`); console.log(` ${ansis.cyan("6.")} ${i18n.t("ccr:ccrMenuOptions.stop")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.stop")}`)}`); console.log(` ${ansis.yellow("0.")} ${i18n.t("ccr:ccrMenuOptions.back")}`); console.log(""); const { choice } = await inquirer.prompt({ type: "input", name: "choice", message: i18n.t("common:enterChoice"), validate: (value) => { const valid = ["1", "2", "3", "4", "5", "6", "0"]; return valid.includes(value) || i18n.t("common:invalidChoice"); } }); switch (choice) { case "1": { const ccrStatus = await isCcrInstalled(); if (!ccrStatus.hasCorrectPackage) { await installCcr(); } else { console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrAlreadyInstalled")}`)); } await configureCcrFeature(); console.log(ansis.green(` \u2714 ${i18n.t("ccr:ccrSetupComplete")}`)); break; } case "2": if (!isCcrConfigured()) { console.log(ansis.yellow(` \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`)); console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")} `)); } else { const config = readCcrConfig(); await runCcrUi(config?.APIKEY); } break; case "3": if (!isCcrConfigured()) { console.log(ansis.yellow(` \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`)); console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")} `)); } else { await runCcrStatus(); } break; case "4": if (!isCcrConfigured()) { console.log(ansis.yellow(` \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`)); console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")} `)); } else { await runCcrRestart(); } break; case "5": if (!isCcrConfigured()) { console.log(ansis.yellow(` \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`)); console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")} `)); } else { await runCcrStart(); } break; case "6": if (!isCcrConfigured()) { console.log(ansis.yellow(` \u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`)); console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")} `)); } else { await runCcrStop(); } break; case "0": return false; } if (choice !== "0") { console.log(` ${ansis.dim("\u2500".repeat(50))} `); const continueInCcr = await promptBoolean({ message: i18n.t("common:returnToMenu"), defaultValue: true }); if (continueInCcr) { return await showCcrMenu(); } } return false; } catch (error) { if (!handleExitPromptError(error)) { handleGeneralError(error); } return false; } } async function executeCcusage(args = []) { try { const command = "npx"; const commandArgs = ["ccusage@latest", ...args || []]; console.log(ansis.cyan(i18n.t("tools:runningCcusage"))); console.log(ansis.gray(`$ npx ccusage@latest ${(args || []).join(" ")}`)); console.log(""); await x(command, commandArgs, { nodeOptions: { stdio: "inherit" } }); } catch (error) { console.error(ansis.red(i18n.t("tools:ccusageFailed"))); console.error(ansis.yellow(i18n.t("tools:checkNetworkConnection"))); if (process.env.DEBUG) { console.error(ansis.gray(i18n.t("tools:errorDetails")), error); } if (process.env.NODE_ENV !== "test") { process.exit(1); } throw error; } } const execAsync = promisify(exec); async function runCometixPrintConfig() { ensureI18nInitialized(); try { console.log(ansis.blue(`${i18n.t("cometix:printingConfig")}`)); const { stdout } = await execAsync(COMETIX_COMMANDS.PRINT_CONFIG); console.log(stdout); } catch (error) { if (error.message.includes(`command not found: ${COMETIX_COMMAND_NAME}`)) { console.error(ansis.red(`\u2717 ${i18n.t("cometix:commandNotFound")}`)); } else { console.error(ansis.red(`\u2717 ${i18n.t("cometix:printConfigFailed")}: ${error}`)); } throw error; } } async function runCometixTuiConfig() { ensureI18nInitialized(); return new Promise((resolve, reject) => { console.log(ansis.blue(`${i18n.t("cometix:enteringTuiConfig")}`)); const child = spawn(COMETIX_COMMAND_NAME, ["-c"], { stdio: "inherit", // This allows the TUI to interact directly with the terminal shell: true }); child.on("close", (code) => { if (code === 0) { console.log(ansis.green(`\u2713 ${i18n.t("cometix:tuiConfigSuccess")}`)); resolve(); } else { const error = new Error(`${COMETIX_COMMAND_NAME} -c exited with code ${code}`); console.error(ansis.red(`\u2717 ${i18n.t("cometix:tuiConfigFailed")}: ${error.message}`)); reject(error); } }); child.on("error", (error) => { if (error.message.includes(`command not found`) || error.message.includes("ENOENT")) { console.error(ansis.red(`\u2717 ${i18n.t("cometix:commandNotFound")}`)); } else { console.error(ansis.red(`\u2717 ${i18n.t("cometix:tuiConfigFailed")}: ${error.message}`)); } reject(error); }); }); } async function showCometixMenu() { try { ensureI18nInitialized(); console.log(` ${ansis.cyan("\u2550".repeat(50))}`); console.log(ansis.bold.cyan(` ${i18n.t("cometix:cometixMenuTitle")}`)); console.log(`${ansis.cyan("\u2550".repeat(50))} `); console.log(` ${ansis.cyan("1.")} ${i18n.t("cometix:cometixMenuOptions.installOrUpdate")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.installOrUpdate")}`)}`); console.log(` ${ansis.cyan("2.")} ${i18n.t("cometix:cometixMenuOptions.printConfig")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.printConfig")}`)}`); console.log(` ${ansis.cyan("3.")} ${i18n.t("cometix:cometixMenuOptions.customConfig")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.customConfig")}`)}`); console.log(` ${ansis.yellow("0.")} ${i18n.t("cometix:cometixMenuOptions.back")}`); console.log(""); const { choice } = await inquirer.prompt({ type: "input", name: "choice", message: i18n.t("common:enterChoice"), validate: async (value) => { const valid = ["1", "2", "3", "0"]; return valid.includes(value) || i18n.t("common:invalidChoice"); } }); switch (choice) { case "1": await installCometixLine(); break; case "2": await runCometixPrintConfig(); break; case "3": await runCometixTuiConfig(); break; case "0": return false; } if (choice !== "0") { console.log(` ${ansis.dim("\u2500".repeat(50))} `); const continueInCometix = await promptBoolean({ message: i18n.t("common:returnToMenu"), defaultValue: true }); if (continueInCometix) { return await showCometixMenu(); } } return false; } catch (error) { if (!handleExitPromptError(error)) { handleGeneralError(error); } return false; } } async function runCcusageFeature() { ensureI18nInitialized(); console.log(""); console.log(ansis.cyan(i18n.t("menu:menuOptions.ccusage"))); console.log(ansis.gray(`${i18n.t("tools:ccusageDescription")}`)); console.log(""); const choices = [ { name: i18n.t("tools:ccusageModes.daily"), value: "daily" }, { name: i18n.t("tools:ccusageModes.monthly"), value: "monthly" }, { name: i18n.t("tools:ccusageModes.session"), value: "session" }, { name: i18n.t("tools:ccusageModes.blocks"), value: "blocks" }, { name: i18n.t("tools:ccusageModes.custom"), value: "custom" }, { name: i18n.t("common:back"), value: "back" } ]; const { mode } = await inquirer.prompt({ type: "list", name: "mode", message: i18n.t("tools:selectAnalysisMode"), choices: addNumbersToChoices(choices) }); if (mode === "back") { return; } let args = []; if (mode === "custom") { const { customArgs } = await inquirer.prompt({ type: "input", name: "customArgs", message: i18n.t("tools:enterCustomArgs"), default: "" }); if (customArgs === null || customArgs === void 0 || customArgs === "") { args = []; } else { const argsString = String(customArgs).trim(); if (!argsString) { args = []; } else { const argPattern = /"([^"]*)"|'([^']*)'|(\S+)/g; const matches = []; let match = argPattern.exec(argsString); while (match !== null) { const value = match[1] || match[2] || match[3]; if (value) { matches.push(value); } match = argPattern.exec(argsString); } args = matches; } } } else { args = [mode]; } console.log(""); await executeCcusage(args); console.log(""); await inquirer.prompt({ type: "input", name: "continue", message: ansis.gray(i18n.t("tools:pressEnterToContinue")) }); } async function runCcrMenuFeature() { await showCcrMenu(); } async function runCometixMenuFeature() { await showCometixMenu(); } class ToolUpdateScheduler { /** * Update tools based on code type * @param codeType - The code tool type to update * @param skipPrompt - Whether to skip interactive prompts */ async updateByCodeType(codeType, skipPrompt = false) { await ensureI18nInitialized(); switch (codeType) { case "claude-code": await this.updateClaudeCodeTools(skipPrompt); break; case "codex": await this.updateCodexTools(skipPrompt); break; default: throw new Error(`Unsupported code type: ${codeType}`); } } /** * Update Claude Code related tools * @param skipPrompt - Whether to skip interactive prompts */ async updateClaudeCodeTools(skipPrompt) { await checkAndUpdateTools(skipPrompt); } /** * Update Codex tools * @param skipPrompt - Whether to skip interactive prompts */ async updateCodexTools(skipPrompt) { await runCodexUpdate(false, skipPrompt); } } async function checkUpdates(options = {}) { try { const skipPrompt = options.skipPrompt || false; let codeType; try { codeType = await resolveCodeType$1(options.codeType); } catch (err) { const errorMessage = err instanceof Error ? err.message : String(err); console.error(ansis.red(`${errorMessage} Defaulting to "claude-code".`)); codeType = "claude-code"; } const scheduler = new ToolUpdateScheduler(); await scheduler.updateByCodeType(codeType, skipPrompt); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(ansis.red(`${i18n.t("updater:errorCheckingUpdates")} ${errorMessage}`)); process.exit(1); } } class ZcfUninstaller { _lang; // Reserved for future i18n support conflictResolution = /* @__PURE__ */ new Map(); constructor(lang = "en") { this._lang = lang; this.conflictResolution.set("claude-code", ["mcps"]); void this._lang; } /** * 1. Remove outputStyle field from settings.json and output-styles directory */ async removeOutputStyles() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const settingsPath = join(homedir(), ".claude", "settings.json"); const outputStylesPath = join(homedir(), ".claude", "output-styles"); if (await pathExists(settingsPath)) { const settings = readJsonConfig(settingsPath) || {}; if (settings.outputStyle) { delete settings.outputStyle; writeJsonConfig(settingsPath, settings); result.removedConfigs.push("outputStyle field from settings.json"); } } else { result.warnings.push(i18n.t("uninstall:settingsJsonNotFound")); } if (await pathExists(outputStylesPath)) { const trashResult = await moveToTrash(outputStylesPath); if (!trashResult[0]?.success) { result.warnings.push(trashResult[0]?.error || "Failed to move to trash"); } result.removed.push("~/.claude/output-styles/"); } else { result.warnings.push(i18n.t("uninstall:outputStylesDirectoryNotFound")); } result.success = true; } catch (error) { result.errors.push(`Failed to remove output styles: ${error.message}`); } return result; } /** * 2. Remove custom commands directory (commands/zcf/) */ async removeCustomCommands() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const commandsPath = join(homedir(), ".claude", "commands", "zcf"); if (await pathExists(commandsPath)) { const trashResult = await moveToTrash(commandsPath); if (!trashResult[0]?.success) { result.warnings.push(trashResult[0]?.error || "Failed to move to trash"); } result.removed.push("commands/zcf/"); result.success = true; } else { result.warnings.push(i18n.t("uninstall:commandsNotFound")); result.success = true; } } catch (error) { result.errors.push(`Failed to remove custom commands: ${error.message}`); } return result; } /** * 3. Remove custom agents directory (agents/zcf/) */ async removeCustomAgents() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const agentsPath = join(homedir(), ".claude", "agents", "zcf"); if (await pathExists(agentsPath)) { const trashResult = await moveToTrash(agentsPath); if (!trashResult[0]?.success) { result.warnings.push(trashResult[0]?.error || "Failed to move to trash"); } result.removed.push("agents/zcf/"); result.success = true; } else { result.warnings.push(i18n.t("uninstall:agentsNotFound")); result.success = true; } } catch (error) { result.errors.push(`Failed to remove custom agents: ${error.message}`); } return result; } /** * 4. Remove global memory file (CLAUDE.md) */ async removeClaudeMd() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md"); if (await pathExists(claudeMdPath)) { const trashResult = await moveToTrash(claudeMdPath); if (!trashResult[0]?.success) { result.warnings.push(trashResult[0]?.error || "Failed to move to trash"); } result.removed.push("CLAUDE.md"); result.success = true; } else { result.warnings.push(i18n.t("uninstall:claudeMdNotFound")); result.success = true; } } catch (error) { result.errors.push(`Failed to remove CLAUDE.md: ${error.message}`); } return result; } /** * 5. Remove permissions and environment variables */ async removePermissionsAndEnvs() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const settingsPath = join(homedir(), ".claude", "settings.json"); if (await pathExists(settingsPath)) { const settings = readJsonConfig(settingsPath) || {}; let modified = false; if (settings.permissions) { delete settings.permissions; result.removedConfigs.push("permissions configuration"); modified = true; } if (settings.env) { delete settings.env; result.removedConfigs.push("environment variables"); modified = true; } if (modified) { writeJsonConfig(settingsPath, settings); } result.success = true; } else { result.warnings.push(i18n.t("uninstall:settingsJsonNotFound")); result.success = true; } } catch (error) { result.errors.push(`Failed to remove permissions and envs: ${error.message}`); } return result; } /** * 6. Remove MCP servers from .claude.json (mcpServers field only) */ async removeMcps() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const claudeJsonPath = join(homedir(), ".claude.json"); if (await pathExists(claudeJsonPath)) { const config = readJsonConfig(claudeJsonPath) || {}; if (config.mcpServers) { delete config.mcpServers; writeJsonConfig(claudeJsonPath, config); result.removedConfigs.push("mcpServers from .claude.json"); } result.success = true; } else { result.warnings.push(i18n.t("uninstall:claudeJsonNotFound")); result.success = true; } } catch (error) { result.errors.push(`Failed to remove MCP servers: ${error.message}`); } return result; } /** * 7. Uninstall Claude Code Router and remove configuration */ async uninstallCcr() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const ccrPath = join(homedir(), ".claude-code-router"); if (await pathExists(ccrPath)) { const trashResult = await moveToTrash(ccrPath); if (!trashResult[0]?.success) { result.warnings.push(trashResult[0]?.error || "Failed to move to trash"); } result.removed.push(".claude-code-router/"); } try { await exec$1("npm", ["uninstall", "-g", "@musistudio/claude-code-router"]); result.removed.push("@musistudio/claude-code-router package"); result.success = true; } catch (npmError) { if (npmError.message.includes("not found") || npmError.message.includes("not installed")) { result.warnings.push(i18n.t("uninstall:ccrPackageNotFound")); result.success = true; } else { result.errors.push(`Failed to uninstall CCR package: ${npmError.message}`); } } } catch (error) { result.errors.push(`Failed to uninstall CCR: ${error.message}`); } return result; } /** * 8. Uninstall CCometixLine */ async uninstallCcline() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { await exec$1("npm", ["uninstall", "-g", "@cometix/ccline"]); result.removed.push("@cometix/ccline package"); result.success = true; } catch (error) { if (error.message.includes("not found") || error.message.includes("not installed")) { result.warnings.push(i18n.t("uninstall:cclinePackageNotFound")); result.success = true; } else { result.errors.push(`Failed to uninstall CCometixLine: ${error.message}`); } } return result; } /** * 9. Uninstall Claude Code and remove entire .claude.json */ async uninstallClaudeCode() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const claudeJsonPath = join(homedir(), ".claude.json"); if (await pathExists(claudeJsonPath)) { const trashResult = await moveToTrash(claudeJsonPath); if (!trashResult[0]?.success) { result.warnings.push(trashResult[0]?.error || "Failed to move to trash"); } result.removed.push(".claude.json (includes MCP configuration)"); } try { const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.bo; }); const success = await uninstallCodeTool("claude-code"); if (success) { result.removed.push("@anthropic-ai/claude-code"); result.success = true; } else { result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: "" })); } } catch (npmError) { if (npmError.message.includes("not found") || npmError.message.includes("not installed")) { result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound")); result.success = true; } else { result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${npmError.message}` })); } } } catch (error) { result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${error.message}` })); } return result; } /** * 10. Remove backup files */ async removeBackups() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const backupPath = join(homedir(), ".claude", "backup"); if (await pathExists(backupPath)) { const trashResult = await moveToTrash(backupPath); if (!trashResult[0]?.success) { result.warnings.push(trashResult[0]?.error || "Failed to move to trash"); } result.removed.push("backup/"); result.success = true; } else { result.warnings.push(i18n.t("uninstall:backupsNotFound")); result.success = true; } } catch (error) { result.errors.push(`Failed to remove backups: ${error.message}`); } return result; } /** * 11. Remove ZCF preference configuration */ async removeZcfConfig() { const result = { success: false, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const zcfConfigPath = ZCF_CONFIG_FILE; const relativeName = zcfConfigPath.replace(homedir(), "~"); if (await pathExists(zcfConfigPath)) { const trashResult = await moveToTrash(zcfConfigPath); if (!trashResult[0]?.success) { result.warnings.push(trashResult[0]?.error || "Failed to move to trash"); } result.removed.push(relativeName); result.success = true; } else { result.warnings.push(i18n.t("uninstall:zcfConfigNotFound")); result.success = true; } } catch (error) { result.errors.push(`Failed to remove ZCF config: ${error.message}`); } return result; } /** * Complete uninstall - remove all directories and packages */ async completeUninstall() { const result = { success: true, removed: [], removedConfigs: [], errors: [], warnings: [] }; try { const directoriesToRemove = [ { path: join(homedir(), ".claude"), name: "~/.claude/" }, { path: join(homedir(), ".claude.json"), name: "~/.claude.json" }, { path: join(homedir(), ".claude-code-router"), name: "~/.claude-code-router/" } ]; for (const dir of directoriesToRemove) { try { if (await pathExists(dir.path)) { const trashResult = await moveToTrash(dir.path); if (!trashResult[0]?.success) { result.warnings.push(`Failed to move ${dir.name} to trash: ${trashResult[0]?.error || "Unknown error"}`); } result.removed.push(dir.name); } } catch (error) { result.warnings.push(`Failed to remove ${dir.name}: ${error.message}`); } } const packagesToUninstall = [ "@musistudio/claude-code-router", "@cometix/ccline", "@anthropic-ai/claude-code" ]; for (const pkg of packagesToUninstall) { try { await exec$1("npm", ["uninstall", "-g", pkg]); result.removed.push(`${pkg} package`); } catch (error) { if (error.message.includes("not found") || error.message.includes("not installed")) { if (pkg.includes("claude-code-router")) { result.warnings.push(i18n.t("uninstall:ccrPackageNotFound")); } else if (pkg.includes("ccline")) { result.warnings.push(i18n.t("uninstall:cclinePackageNotFound")); } else { result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound")); } } else { result.warnings.push(`Failed to uninstall ${pkg}: ${error.message}`); } } } } catch (error) { result.errors.push(`Complete uninstall failed: ${error.message}`); result.success = false; } return result; } /** * Custom uninstall with conflict resolution */ async customUninstall(selectedItems) { const resolvedItems = this.resolveConflicts(selectedItems); const results = []; for (const item of resolvedItems) { try { const result = await this.executeUninstallItem(item); results.push(result); } catch (error) { results.push({ success: false, removed: [], removedConfigs: [], errors: [`Failed to execute ${item}: ${error.message}`], warnings: [] }); } } return results; } /** * Resolve conflicts between uninstall items */ resolveConflicts(items) { const resolved = [...items]; for (const [primary, conflicts] of this.conflictResolution) { if (resolved.includes(primary)) { conflicts.forEach((conflict) => { const index = resolved.indexOf(conflict); if (index > -1) { resolved.splice(index, 1); } }); } } return resolved; } /** * Execute uninstall for a specific item */ async executeUninstallItem(item) { switch (item) { case "output-styles": return await this.removeOutputStyles(); case "commands": return await this.removeCustomCommands(); case "agents": return await this.removeCustomAgents(); case "claude-md": return await this.removeClaudeMd(); case "permissions-envs": return await this.removePermissionsAndEnvs(); case "mcps": return await this.removeMcps(); case "ccr": return await this.uninstallCcr(); case "ccline": return await this.uninstallCcline(); case "claude-code": return await this.uninstallClaudeCode(); case "backups": return await this.removeBackups(); case "zcf-config": return await this.removeZcfConfig(); default: return { success: false, removed: [], removedConfigs: [], errors: [`Unknown uninstall item: ${item}`], warnings: [] }; } } } async function uninstall(options = {}) { try { ensureI18nInitialized(); let codeType; if (options.codeType) { try { codeType = await resolveCodeType$1(options.codeType); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(ansis.red(`${i18n.t("errors:generalError")} ${errorMessage}`)); const config = readZcfConfig(); codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE; } } else { const config = readZcfConfig(); codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE; } const uninstaller = new ZcfUninstaller(options.lang || "en"); if (codeType === "codex") { const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.bn; }); await runCodexUninstall(); return; } if (options.mode && options.mode !== "interactive") { if (options.mode === "complete") { await executeCompleteUninstall(uninstaller); return; } else if (options.mode === "custom" && options.items) { let items; if (typeof options.items === "string") { items = options.items.split(",").map((item) => item.trim()); } else { items = options.items; } await executeCustomUninstall(uninstaller, items); return; } } await showInteractiveUninstall(uninstaller); } catch (error) { if (!handleExitPromptError(error)) { handleGeneralError(error); } } } async function showInteractiveUninstall(uninstaller) { console.log(ansis.cyan.bold(i18n.t("uninstall:title"))); console.log(""); const { mainChoice } = await inquirer.prompt({ type: "list", name: "mainChoice", message: i18n.t("uninstall:selectMainOption"), choices: addNumbersToChoices([ { name: `${i18n.t("uninstall:completeUninstall")} - ${ansis.gray(i18n.t("uninstall:completeUninstallDesc"))}`, value: "complete", short: i18n.t("uninstall:completeUninstall") }, { name: `${i18n.t("uninstall:customUninstall")} - ${ansis.gray(i18n.t("uninstall:customUninstallDesc"))}`, value: "custom", short: i18n.t("uninstall:customUninstall") } ]) }); if (!mainChoice) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return; } if (mainChoice === "complete") { await executeCompleteUninstall(uninstaller); } else { await showCustomUninstallMenu(uninstaller); } } async function showCustomUninstallMenu(uninstaller) { console.log(""); console.log(ansis.cyan(i18n.t("uninstall:selectCustomItems"))); const { customItems } = await inquirer.prompt({ type: "checkbox", name: "customItems", message: `${i18n.t("uninstall:selectItemsToRemove")} ${i18n.t("common:multiSelectHint")}`, choices: [ { name: i18n.t("uninstall:outputStyles"), value: "output-styles" }, { name: i18n.t("uninstall:commands"), value: "commands" }, { name: i18n.t("uninstall:agents"), value: "agents" }, { name: i18n.t("uninstall:claudeMd"), value: "claude-md" }, { name: i18n.t("uninstall:permissionsEnvs"), value: "permissions-envs" }, { name: i18n.t("uninstall:mcps"), value: "mcps" }, { name: i18n.t("uninstall:ccr"), value: "ccr" }, { name: i18n.t("uninstall:ccline"), value: "ccline" }, { name: i18n.t("uninstall:claudeCode"), value: "claude-code" }, { name: i18n.t("uninstall:backups"), value: "backups" }, { name: i18n.t("uninstall:zcfConfig"), value: "zcf-config" } ], validate: (answers) => { if (answers.length === 0) { return i18n.t("uninstall:selectAtLeastOne"); } return true; } }); if (!customItems || customItems.length === 0) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return; } await executeCustomUninstall(uninstaller, customItems); } async function executeCompleteUninstall(uninstaller) { console.log(""); console.log(ansis.red.bold(i18n.t("uninstall:executingComplete"))); console.log(ansis.yellow(i18n.t("uninstall:completeWarning"))); const confirm = await promptBoolean({ message: i18n.t("uninstall:confirmComplete"), defaultValue: false }); if (!confirm) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return; } console.log(""); console.log(ansis.cyan(i18n.t("uninstall:processingComplete"))); const result = await uninstaller.completeUninstall(); displayUninstallResult("complete", [result]); } async function executeCustomUninstall(uninstaller, items) { console.log(""); console.log(ansis.cyan(i18n.t("uninstall:executingCustom"))); console.log(ansis.gray(i18n.t("uninstall:selectedItems"))); items.forEach((item) => { console.log(` \u2022 ${i18n.t(`uninstall:${item}`)}`); }); const confirm = await promptBoolean({ message: i18n.t("uninstall:confirmCustom"), defaultValue: false }); if (!confirm) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return; } console.log(""); console.log(ansis.cyan(i18n.t("uninstall:processingCustom"))); const results = await uninstaller.customUninstall(items); displayUninstallResult("custom", results); } function displayUninstallResult(mode, results) { console.log(""); console.log(ansis.cyan("\u2500".repeat(50))); let totalSuccess = 0; let totalErrors = 0; let totalWarnings = 0; results.forEach((result) => { if (result.success) { totalSuccess++; } if (result.removed && result.removed.length > 0) { console.log(ansis.green(`\u{1F5D1}\uFE0F ${i18n.t("uninstall:movedToTrash")}:`)); result.removed.forEach((item) => { console.log(ansis.gray(` \u2022 ${item}`)); }); } if (result.removedConfigs && result.removedConfigs.length > 0) { console.log(ansis.green(`\u2714 ${i18n.t("uninstall:removedConfigs")}:`)); result.removedConfigs.forEach((item) => { console.log(ansis.gray(` \u2022 ${item}`)); }); } if (result.errors && result.errors.length > 0) { totalErrors += result.errors.length; console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errors")}:`)); result.errors.forEach((error) => { console.log(ansis.red(` \u2022 ${error}`)); }); } if (result.warnings && result.warnings.length > 0) { totalWarnings += result.warnings.length; console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warnings")}:`)); result.warnings.forEach((warning) => { console.log(ansis.yellow(` \u2022 ${warning}`)); }); } }); const totalRemovedFiles = results.reduce((count, result) => count + (result.removed?.length || 0), 0); const totalRemovedConfigs = results.reduce((count, result) => count + (result.removedConfigs?.length || 0), 0); console.log(""); console.log(ansis.cyan("\u2500".repeat(50))); if (mode === "complete") { if (totalErrors === 0) { console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:completeSuccess")}`)); } else { console.log(ansis.yellow.bold(`\u26A0 ${i18n.t("uninstall:completePartialSuccess")}`)); } } else { if (totalRemovedFiles > 0 && totalRemovedConfigs > 0) { console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessBoth", { fileCount: totalRemovedFiles, configCount: totalRemovedConfigs })}`)); } else if (totalRemovedFiles > 0) { console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessFiles", { count: totalRemovedFiles })}`)); } else if (totalRemovedConfigs > 0) { console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessConfigs", { count: totalRemovedConfigs })}`)); } else { console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccess", { count: totalSuccess })}`)); } if (totalErrors > 0) { console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errorsCount", { count: totalErrors })}`)); } if (totalWarnings > 0) { console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warningsCount", { count: totalWarnings })}`)); } } console.log(""); } function resolveCodeToolType(optionValue, savedValue) { if (optionValue !== void 0) { const resolved = resolveCodeToolType$1(optionValue); if (resolved !== DEFAULT_CODE_TOOL_TYPE || optionValue === DEFAULT_CODE_TOOL_TYPE) { return resolved; } } if (savedValue && isCodeToolType(savedValue)) { return savedValue; } return DEFAULT_CODE_TOOL_TYPE; } async function update(options = {}) { try { if (!options.skipBanner) { displayBanner(i18n.t("cli:banner.updateSubtitle")); } const zcfConfig = readZcfConfig(); const codeToolType = resolveCodeToolType(options.codeType, zcfConfig?.codeToolType); options.codeType = codeToolType; if (codeToolType === "codex") { await runCodexUpdate(); const newPreferredLang = options.configLang || zcfConfig?.preferredLang; if (newPreferredLang) { updateZcfConfig({ version, preferredLang: newPreferredLang, codeToolType }); } else { updateZcfConfig({ version, codeToolType }); } return; } const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.bm; }); const configLang = await resolveTemplateLanguage( options.configLang, // Command line option zcfConfig, options.skipPrompt // Non-interactive mode flag ); const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig, options.skipPrompt); console.log(ansis.cyan(` ${i18n.t("configuration:updatingPrompts")} `)); await updatePromptOnly(aiOutputLang); await selectAndInstallWorkflows(configLang); await checkClaudeCodeVersionAndPrompt(false); updateZcfConfig({ version, templateLang: configLang, // 保存模板语言选择 aiOutputLang, codeToolType }); } catch (error) { if (!handleExitPromptError(error)) { handleGeneralError(error); } } } const CODE_TOOL_LABELS = { "claude-code": "Claude Code", "codex": "Codex" }; function getCurrentCodeTool() { const config = readZcfConfig(); if (config?.codeToolType && isCodeToolType(config.codeToolType)) { return config.codeToolType; } return DEFAULT_CODE_TOOL_TYPE; } function printSeparator() { console.log(` ${ansis.dim("\u2500".repeat(50))} `); } function getCodeToolLabel(codeTool) { return CODE_TOOL_LABELS[codeTool] || codeTool; } async function promptCodeToolSelection(current) { const choices = addNumbersToChoices(Object.entries(CODE_TOOL_LABELS).map(([value, label]) => ({ name: label, value, short: label }))); const { tool } = await inquirer.prompt({ type: "list", name: "tool", message: i18n.t("menu:switchCodeToolPrompt"), default: current, choices }); if (!tool) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return null; } return tool; } async function handleCodeToolSwitch(current) { const newTool = await promptCodeToolSelection(current); if (!newTool || newTool === current) { return false; } updateZcfConfig({ codeToolType: newTool }); console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(newTool) })}`)); return true; } function printOtherToolsSection() { console.log(` --------- ${i18n.t("menu:menuSections.otherTools")} ----------`); console.log( ` ${ansis.cyan("R.")} ${i18n.t("menu:menuOptions.ccrManagement")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccrManagement")}`)}` ); console.log( ` ${ansis.cyan("U.")} ${i18n.t("menu:menuOptions.ccusage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccusage")}`)}` ); console.log( ` ${ansis.cyan("L.")} ${i18n.t("menu:menuOptions.cometixLine")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.cometixLine")}`)}` ); console.log(""); } function printZcfSection(options) { console.log(" ------------ ZCF ------------"); console.log( ` ${ansis.cyan("0.")} ${i18n.t("menu:menuOptions.changeLanguage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.changeLanguage")}`)}` ); console.log( ` ${ansis.cyan("S.")} ${i18n.t("menu:menuOptions.switchCodeTool")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.switchCodeTool")}`)}` ); console.log( ` ${ansis.cyan("-.")} ${options.uninstallOption} ${ansis.gray(`- ${options.uninstallDescription}`)}` ); console.log( ` ${ansis.cyan("+.")} ${options.updateOption} ${ansis.gray(`- ${options.updateDescription}`)}` ); console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.t("menu:menuOptions.exit"))}`); console.log(""); } async function showClaudeCodeMenu() { console.log(ansis.cyan(i18n.t("menu:selectFunction"))); console.log(" -------- Claude Code --------"); console.log( ` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.fullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.fullInit")}`)}` ); console.log( ` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.importWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.importWorkflow")}`)}` ); console.log( ` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.configureApiOrCcr")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureApiOrCcr")}`)}` ); console.log( ` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.configureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureMcp")}`)}` ); console.log( ` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.configureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureModel")}`)}` ); console.log( ` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.configureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureAiMemory")}`)}` ); console.log( ` ${ansis.cyan("7.")} ${i18n.t("menu:menuOptions.configureEnvPermission")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureEnvPermission")}`)}` ); console.log(""); printOtherToolsSection(); printZcfSection({ uninstallOption: i18n.t("menu:menuOptions.uninstall"), uninstallDescription: i18n.t("menu:menuDescriptions.uninstall"), updateOption: i18n.t("menu:menuOptions.checkUpdates"), updateDescription: i18n.t("menu:menuDescriptions.checkUpdates") }); const { choice } = await inquirer.prompt({ type: "input", name: "choice", message: i18n.t("common:enterChoice"), validate: (value) => { const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "l", "L", "0", "-", "+", "s", "S", "q", "Q"]; return valid.includes(value) || i18n.t("common:invalidChoice"); } }); if (!choice) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return "exit"; } const normalized = choice.toLowerCase(); switch (normalized) { case "1": await init({ skipBanner: true }); break; case "2": await update({ skipBanner: true }); break; case "3": await configureApiFeature(); break; case "4": await configureMcpFeature(); break; case "5": await configureDefaultModelFeature(); break; case "6": await configureAiMemoryFeature(); break; case "7": await configureEnvPermissionFeature(); break; case "r": await runCcrMenuFeature(); printSeparator(); return void 0; case "u": await runCcusageFeature(); printSeparator(); return void 0; case "l": await runCometixMenuFeature(); printSeparator(); return void 0; case "0": { const currentLang = i18n.language; await changeScriptLanguageFeature(currentLang); printSeparator(); return void 0; } case "-": await uninstall(); printSeparator(); return void 0; case "+": await checkUpdates(); printSeparator(); return void 0; case "s": { const switched = await handleCodeToolSwitch("claude-code"); if (switched) { return "switch"; } printSeparator(); return void 0; } case "q": console.log(ansis.cyan(i18n.t("common:goodbye"))); return "exit"; default: return void 0; } printSeparator(); const shouldContinue = await promptBoolean({ message: i18n.t("common:returnToMenu"), defaultValue: true }); if (!shouldContinue) { console.log(ansis.cyan(i18n.t("common:goodbye"))); return "exit"; } return void 0; } async function showCodexMenu() { console.log(ansis.cyan(i18n.t("menu:selectFunction"))); console.log(" -------- Codex --------"); console.log( ` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.codexFullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexFullInit")}`)}` ); console.log( ` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.codexImportWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexImportWorkflow")}`)}` ); console.log( ` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.codexConfigureApi")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureApi")}`)}` ); console.log( ` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.codexConfigureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureMcp")}`)}` ); console.log( ` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.codexConfigureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureModel")}`)}` ); console.log( ` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.codexConfigureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureAiMemory")}`)}` ); console.log(""); printZcfSection({ uninstallOption: i18n.t("menu:menuOptions.codexUninstall"), uninstallDescription: i18n.t("menu:menuDescriptions.codexUninstall"), updateOption: i18n.t("menu:menuOptions.codexCheckUpdates"), updateDescription: i18n.t("menu:menuDescriptions.codexCheckUpdates") }); const { choice } = await inquirer.prompt({ type: "input", name: "choice", message: i18n.t("common:enterChoice"), validate: (value) => { const valid = ["1", "2", "3", "4", "5", "6", "0", "-", "+", "s", "S", "q", "Q"]; return valid.includes(value) || i18n.t("common:invalidChoice"); } }); if (!choice) { console.log(ansis.yellow(i18n.t("common:cancelled"))); return "exit"; } const normalized = choice.toLowerCase(); switch (normalized) { case "1": await runCodexFullInit(); break; case "2": await runCodexWorkflowImportWithLanguageSelection(); break; case "3": await configureCodexApi(); break; case "4": await configureCodexMcp(); break; case "5": await configureCodexDefaultModelFeature(); bre