@ai-config-plaza/acp-cli 1.0.9 → 1.0.11

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 📖 简介
6
6
 
7
- ACP CLI 是一个专为简化 AI 编程工具配置而设计的命令行工具。通过统一的配置标准,帮助开发者快速初始化和配置 AI 工具(如 VS Code、Cursor、Codex、Claude Code 等)。
7
+ ACP CLI 是一个专为简化 AI 编程工具配置而设计的命令行工具。通过统一的配置标准,帮助开发者快速初始化和配置 AI 工具(如 VS Code、Cursor、Codex、Claude Code、CodeBuddy、Qoder 等)。
8
8
 
9
9
  ### 核心特性
10
10
 
@@ -134,12 +134,14 @@ acp apply
134
134
 
135
135
  不同 AI IDE 的配置文件输出路径:
136
136
 
137
- | IDE | Prompts 路径 | Agents 文件 | MCP 配置 |
138
- | ----------- | -------------------- | ------------- | ----------------------- |
139
- | VS Code | `.github/prompts/` | `AGENTS.md` | `.vscode/mcp.json` |
140
- | Cursor | `.cursor/commands/` | `AGENTS.md` | `.cursor/mcp.json` |
141
- | Codex | `~/.codex/prompts/` | `AGENTS.md` | `.codex/config.toml` |
142
- | Claude Code | `.claude/commands/` | `AGENTS.md` | `.mcp.json` |
137
+ | IDE | Prompts 路径 | Agents 文件 | MCP 配置 | Skills 路径 |
138
+ | ----------- | -------------------- | ------------- | ----------------------- | -------------------- |
139
+ | VS Code | `.github/prompts/` | `AGENTS.md` | `.vscode/mcp.json` | `.github/skills/` |
140
+ | Cursor | `.cursor/commands/` | `AGENTS.md` | `.cursor/mcp.json` | `.cursor/skills/` |
141
+ | Codex | `~/.codex/prompts/` | `AGENTS.md` | `.codex/config.toml` | `.codex/skills/` |
142
+ | Claude Code | `.claude/commands/` | `AGENTS.md` | `.mcp.json` | `.claude/skills/` |
143
+ | CodeBuddy | `.codebuddy/commands/` | `AGENTS.md` | 不支持 | `.codebuddy/skills/` |
144
+ | Qoder | `.qoder/commands/` | `AGENTS.md` | `.mcp.json` | `qoder/skills/` |
143
145
 
144
146
  ### 文件格式
145
147
 
@@ -167,7 +169,7 @@ acp login
167
169
 
168
170
  **选项**:
169
171
  - `-t, --type <type>`:资源类型(目前仅支持 `solution`)
170
- - `-i, --ide <ide>`:AI IDE 类型(`vscode`|`cursor`|`codex`|`claude-code`)
172
+ - `-i, --ide <ide>`:AI IDE 类型(`vscode`|`cursor`|`codex`|`claude-code`|`codebuddy`|`qoder`)
171
173
  - `-d, --dir <path>`:目标目录(默认为当前目录)
172
174
 
173
175
  **示例**:
package/dist/index.js CHANGED
@@ -205,7 +205,9 @@ var zhCN = {
205
205
  vscode: "VS Code",
206
206
  cursor: "Cursor",
207
207
  codex: "Codex",
208
- claudeCode: "Claude Code"
208
+ claudeCode: "Claude Code",
209
+ codeBuddy: "CodeBuddy",
210
+ qoder: "Qoder"
209
211
  }
210
212
  },
211
213
  // locale 命令
@@ -328,7 +330,9 @@ var enUS = {
328
330
  vscode: "VS Code",
329
331
  cursor: "Cursor",
330
332
  codex: "Codex",
331
- claudeCode: "Claude Code"
333
+ claudeCode: "Claude Code",
334
+ codeBuddy: "CodeBuddy",
335
+ qoder: "Qoder"
332
336
  }
333
337
  },
334
338
  // locale command
@@ -806,7 +810,7 @@ async function applySolution(solution, options) {
806
810
  \u2728 \u89E3\u51B3\u65B9\u6848 ${chalk3.cyan(solution.name)} \u5E94\u7528\u6210\u529F\uFF01`);
807
811
  }
808
812
  async function applyAgentConfig(content, relativePath, targetDir) {
809
- const filePath = path3.join(targetDir, relativePath);
813
+ const filePath = path3.isAbsolute(relativePath) ? relativePath : path3.join(targetDir, relativePath);
810
814
  logger.step(`\u5199\u5165 Agent \u914D\u7F6E: ${chalk3.gray(relativePath)}`);
811
815
  const exists = await fs3.pathExists(filePath);
812
816
  if (exists) {
@@ -828,7 +832,7 @@ async function applyAgentConfig(content, relativePath, targetDir) {
828
832
  logger.success(`\u5DF2\u5199\u5165: ${relativePath}`);
829
833
  }
830
834
  async function applyPrompts(prompts, promptsDir, targetDir) {
831
- const fullPromptsDir = path3.join(targetDir, promptsDir);
835
+ const fullPromptsDir = path3.isAbsolute(promptsDir) ? promptsDir : path3.join(targetDir, promptsDir);
832
836
  logger.step(`\u5199\u5165 ${prompts.length} \u4E2A Prompt \u914D\u7F6E\u5230: ${chalk3.gray(promptsDir)}`);
833
837
  await fs3.ensureDir(fullPromptsDir);
834
838
  for (const prompt of prompts) {
@@ -858,7 +862,7 @@ async function applyMcpConfigs(mcpConfigs, mcpFile, targetDir) {
858
862
  logger.warning("\u6682\u4E0D\u652F\u6301 CodeBuddy \u7684 MCP \u914D\u7F6E\u5199\u5165");
859
863
  return;
860
864
  }
861
- const filePath = path3.join(targetDir, mcpFile);
865
+ const filePath = path3.isAbsolute(mcpFile) ? mcpFile : path3.join(targetDir, mcpFile);
862
866
  logger.step(`\u5199\u5165 MCP \u914D\u7F6E: ${chalk3.gray(mcpFile)}`);
863
867
  const mcpServers = {};
864
868
  for (const mcpConfig of mcpConfigs) {
@@ -930,7 +934,7 @@ function convertMcpToToml(mcpServers) {
930
934
  return tomlContent;
931
935
  }
932
936
  async function applySkills(skills, skillsDir, targetDir) {
933
- const fullSkillsDir = path3.join(targetDir, skillsDir);
937
+ const fullSkillsDir = path3.isAbsolute(skillsDir) ? skillsDir : path3.join(targetDir, skillsDir);
934
938
  logger.step(`\u5199\u5165 ${skills.length} \u4E2A Skill \u914D\u7F6E\u5230: ${chalk3.gray(skillsDir)}`);
935
939
  await fs3.ensureDir(fullSkillsDir);
936
940
  for (const skill of skills) {
@@ -1000,7 +1004,7 @@ function sanitizeFileName(name) {
1000
1004
  }
1001
1005
 
1002
1006
  // src/commands/apply.ts
1003
- var applyCommand = new Command2("apply").description("\u62C9\u53D6\u5E76\u5E94\u7528\u914D\u7F6E\u5230\u672C\u5730\u9879\u76EE / Fetch and apply configurations to local project").option("-t, --type <type>", "\u8D44\u6E90\u7C7B\u578B (solution|agent|prompt|mcp) / Resource type", "solution").option("-i, --ide <ide>", "AI IDE \u7C7B\u578B / AI IDE type (vscode|cursor|codex|claude-code)").option("-d, --dir <path>", "\u76EE\u6807\u76EE\u5F55 / Target directory", process.cwd()).action(async (options) => {
1007
+ var applyCommand = new Command2("apply").description("\u62C9\u53D6\u5E76\u5E94\u7528\u914D\u7F6E\u5230\u672C\u5730\u9879\u76EE / Fetch and apply configurations to local project").option("-t, --type <type>", "\u8D44\u6E90\u7C7B\u578B (solution|agent|prompt|mcp) / Resource type", "solution").option("-i, --ide <ide>", "AI IDE \u7C7B\u578B / AI IDE type (vscode|cursor|codex|claude-code|codebuddy|qoder)").option("-d, --dir <path>", "\u76EE\u6807\u76EE\u5F55 / Target directory", process.cwd()).action(async (options) => {
1004
1008
  try {
1005
1009
  if (!await isLoggedIn()) {
1006
1010
  throw new CLIError(
@@ -1153,7 +1157,9 @@ async function selectIde() {
1153
1157
  { name: chalk4.cyan(await t("apply.ideTypes.vscode")), value: "vscode" },
1154
1158
  { name: chalk4.cyan(await t("apply.ideTypes.cursor")), value: "cursor" },
1155
1159
  { name: chalk4.cyan(await t("apply.ideTypes.codex")), value: "codex" },
1156
- { name: chalk4.cyan(await t("apply.ideTypes.claudeCode")), value: "claude-code" }
1160
+ { name: chalk4.cyan(await t("apply.ideTypes.claudeCode")), value: "claude-code" },
1161
+ { name: chalk4.cyan(await t("apply.ideTypes.codeBuddy")), value: "codebuddy" },
1162
+ { name: chalk4.cyan(await t("apply.ideTypes.qoder")), value: "qoder" }
1157
1163
  ],
1158
1164
  default: "vscode"
1159
1165
  }
@@ -1214,7 +1220,7 @@ import chalk6 from "chalk";
1214
1220
  import ora2 from "ora";
1215
1221
  import axios2 from "axios";
1216
1222
  import { spawnSync } from "child_process";
1217
- var currentVersion = true ? "1.0.9" : "0.0.0-dev";
1223
+ var currentVersion = true ? "1.0.11" : "0.0.0-dev";
1218
1224
  var packageName = "@ai-config-plaza/acp-cli";
1219
1225
  function getAvailablePkgManagers() {
1220
1226
  const managers = ["pnpm", "npm", "yarn"];
@@ -1317,7 +1323,7 @@ var updateCommand = new Command4("update").description("\u66F4\u65B0 ACP CLI \u5
1317
1323
  });
1318
1324
 
1319
1325
  // src/index.ts
1320
- var version = true ? "1.0.9" : "0.0.0-dev";
1326
+ var version = true ? "1.0.11" : "0.0.0-dev";
1321
1327
  async function main() {
1322
1328
  const program = new Command5();
1323
1329
  program.name("acp").description(
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/config/token.ts","../src/utils/logger.ts","../src/config/locale.ts","../src/i18n/zh-CN.ts","../src/i18n/en-US.ts","../src/i18n/index.ts","../src/commands/apply.ts","../src/api/client.ts","../src/utils/pagination.ts","../src/apply/writer.ts","../src/utils/ide-mapper.ts","../src/commands/locale.ts","../src/commands/update.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { Command } from 'commander'\r\nimport chalk from 'chalk'\r\nimport { loginCommand } from './commands/login.js'\r\nimport { applyCommand } from './commands/apply.js'\r\nimport { localeCommand } from './commands/locale.js'\r\nimport { updateCommand } from './commands/update.js'\r\nimport { handleError } from './utils/logger.js'\r\nimport { t } from './i18n/index.js'\r\n\r\n/**\r\n * ACP CLI 主入口\r\n */\r\n\r\n// 版本号在构建时注入\r\n// @ts-ignore - 构建时通过 tsup define 注入\r\nconst version = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0-dev'\r\n\r\nasync function main() {\r\n const program = new Command()\r\n\r\n program\r\n .name('acp')\r\n .description(\r\n chalk.gray(await t('cli.description'))\r\n )\r\n .version(version, '-v, --version', await t('cli.version'))\r\n .helpOption('-h, --help', await t('cli.help'))\r\n\r\n // 注册命令\r\n program.addCommand(loginCommand)\r\n program.addCommand(applyCommand)\r\n program.addCommand(localeCommand)\r\n program.addCommand(updateCommand)\r\n\r\n // 自定义帮助显示\r\n program.on('--help', async () => {\r\n console.log(chalk.bold('\\n' + await t('cli.exampleTitle') + '\\n'))\r\n console.log(chalk.gray(' $ acp login'))\r\n console.log(chalk.gray(' $ acp apply'))\r\n console.log(chalk.gray(' $ acp apply --ide vscode --dir ./my-project'))\r\n console.log(chalk.gray(' $ acp locale'))\r\n console.log(chalk.gray(' $ acp update'))\r\n console.log()\r\n })\r\n\r\n // 解析命令\r\n try {\r\n await program.parseAsync(process.argv)\r\n } catch (error) {\r\n await handleError(error)\r\n process.exit(1)\r\n }\r\n}\r\n\r\nmain()\r\n","import { Command } from 'commander'\r\nimport inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport { saveToken, getToken, initDefaultConfig } from '../config/token.js'\r\nimport { logger } from '../utils/logger.js'\r\nimport { t } from '../i18n/index.js'\r\n\r\n/**\r\n * acp login 命令\r\n * 提示用户输入 CLI Token 并保存\r\n */\r\n\r\nexport const loginCommand = new Command('login')\r\n .description('登录 ACP CLI,保存访问令牌 / Login to ACP CLI and save access token')\r\n .action(async () => {\r\n try {\r\n logger.title(await t('login.title'))\r\n\r\n // 初始化默认配置(首次使用时)\r\n await initDefaultConfig()\r\n\r\n // 检查是否已有 token\r\n const existingToken = await getToken()\r\n if (existingToken) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: await t('login.alreadyLoggedIn'),\r\n default: false\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.info(await t('login.cancelled'))\r\n return\r\n }\r\n }\r\n\r\n // 提示输入 token\r\n const { token } = await inquirer.prompt([\r\n {\r\n type: 'password',\r\n name: 'token',\r\n message: await t('login.inputToken'),\r\n validate: async (input: string) => {\r\n if (!input.trim()) {\r\n return await t('login.tokenEmpty')\r\n }\r\n if (input.trim().length < 10) {\r\n return await t('login.tokenInvalid')\r\n }\r\n return true\r\n },\r\n mask: '*'\r\n }\r\n ])\r\n\r\n // 保存 token\r\n await saveToken(token)\r\n\r\n logger.success(await t('login.success'))\r\n console.log(chalk.gray('\\n' + await t('login.hint') + '\\n'))\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error(`${await t('login.failed')}: ${error.message}`)\r\n }\r\n process.exit(1)\r\n }\r\n })\r\n","import fs from 'fs-extra'\r\nimport path from 'path'\r\nimport os from 'os'\r\n\r\n/**\r\n * Token 和 BASE_URL 配置管理\r\n * 优先级: 环境变量 > ~/.acp/ 配置文件\r\n */\r\n\r\nconst TOKEN_ENV_KEY = 'ACP_CLI_TOKEN'\r\nconst BASE_URL_ENV_KEY = 'ACP_CLI_BASE_URL'\r\nconst DEFAULT_BASE_URL = 'https://api.ai-config-plaza.com'\r\n\r\nconst CONFIG_DIR = path.join(os.homedir(), '.acp')\r\nconst TOKEN_FILE = path.join(CONFIG_DIR, 'token')\r\nconst BASE_URL_FILE = path.join(CONFIG_DIR, 'base-url')\r\n\r\n/**\r\n * 读取 CLI Token\r\n */\r\nexport async function getToken(): Promise<string | null> {\r\n // 1. 优先读取环境变量\r\n const envToken = process.env[TOKEN_ENV_KEY]\r\n if (envToken?.trim()) {\r\n return envToken.trim()\r\n }\r\n\r\n // 2. 读取本地配置文件\r\n try {\r\n if (await fs.pathExists(TOKEN_FILE)) {\r\n const token = await fs.readFile(TOKEN_FILE, 'utf-8')\r\n return token.trim() || null\r\n }\r\n } catch (error) {\r\n // 读取失败返回 null\r\n }\r\n\r\n return null\r\n}\r\n\r\n/**\r\n * 保存 CLI Token 到本地配置文件\r\n */\r\nexport async function saveToken(token: string): Promise<void> {\r\n if (!token?.trim()) {\r\n throw new Error('Token 不能为空')\r\n }\r\n\r\n // 确保配置目录存在\r\n await fs.ensureDir(CONFIG_DIR)\r\n\r\n // 写入 token 文件\r\n await fs.writeFile(TOKEN_FILE, token.trim(), 'utf-8')\r\n}\r\n\r\n/**\r\n * 删除本地 Token\r\n */\r\nexport async function removeToken(): Promise<void> {\r\n if (await fs.pathExists(TOKEN_FILE)) {\r\n await fs.remove(TOKEN_FILE)\r\n }\r\n}\r\n\r\n/**\r\n * 检查是否已登录\r\n */\r\nexport async function isLoggedIn(): Promise<boolean> {\r\n const token = await getToken()\r\n return token !== null && token.length > 0\r\n}\r\n\r\n/**\r\n * 读取 BASE_URL\r\n */\r\nexport async function getBaseUrl(): Promise<string> {\r\n // 1. 优先读取环境变量\r\n const envBaseUrl = process.env[BASE_URL_ENV_KEY]\r\n if (envBaseUrl?.trim()) {\r\n return envBaseUrl.trim()\r\n }\r\n\r\n // 2. 读取本地配置文件\r\n try {\r\n if (await fs.pathExists(BASE_URL_FILE)) {\r\n const baseUrl = await fs.readFile(BASE_URL_FILE, 'utf-8')\r\n if (baseUrl.trim()) {\r\n return baseUrl.trim()\r\n }\r\n }\r\n } catch (error) {\r\n // 读取失败,使用默认值\r\n }\r\n\r\n // 3. 返回默认值\r\n return DEFAULT_BASE_URL\r\n}\r\n\r\n/**\r\n * 保存 BASE_URL 到本地配置文件\r\n */\r\nexport async function saveBaseUrl(baseUrl: string): Promise<void> {\r\n if (!baseUrl?.trim()) {\r\n throw new Error('BASE_URL 不能为空')\r\n }\r\n\r\n // 验证 URL 格式\r\n try {\r\n new URL(baseUrl.trim())\r\n } catch {\r\n throw new Error('BASE_URL 格式不正确,请输入有效的 URL')\r\n }\r\n\r\n // 确保配置目录存在\r\n await fs.ensureDir(CONFIG_DIR)\r\n\r\n // 写入 base-url 文件\r\n await fs.writeFile(BASE_URL_FILE, baseUrl.trim(), 'utf-8')\r\n}\r\n\r\n/**\r\n * 删除本地 BASE_URL\r\n */\r\nexport async function removeBaseUrl(): Promise<void> {\r\n if (await fs.pathExists(BASE_URL_FILE)) {\r\n await fs.remove(BASE_URL_FILE)\r\n }\r\n}\r\n\r\n/**\r\n * 初始化默认配置(首次使用时)\r\n */\r\nexport async function initDefaultConfig(): Promise<void> {\r\n await fs.ensureDir(CONFIG_DIR)\r\n\r\n // 如果 BASE_URL 不存在,初始化默认值\r\n if (!(await fs.pathExists(BASE_URL_FILE))) {\r\n await saveBaseUrl(DEFAULT_BASE_URL)\r\n }\r\n}\r\n","import chalk from 'chalk'\r\nimport { t } from '../i18n/index.js'\r\n\r\n/**\r\n * 日志工具 - 提供统一的终端输出格式\r\n */\r\n\r\n// 使用 Unicode 符号代替 figures\r\nconst symbols = {\r\n info: 'ℹ',\r\n tick: '✓',\r\n warning: '⚠',\r\n cross: '✖',\r\n arrowRight: '→'\r\n}\r\n\r\nexport const logger = {\r\n /**\r\n * 普通信息\r\n */\r\n info: (message: string) => {\r\n console.log(chalk.blue(symbols.info) + ' ' + message)\r\n },\r\n\r\n /**\r\n * 成功信息\r\n */\r\n success: (message: string) => {\r\n console.log(chalk.green(symbols.tick) + ' ' + chalk.green(message))\r\n },\r\n\r\n /**\r\n * 警告信息\r\n */\r\n warning: (message: string) => {\r\n console.log(chalk.yellow(symbols.warning) + ' ' + chalk.yellow(message))\r\n },\r\n\r\n /**\r\n * 错误信息\r\n */\r\n error: (message: string) => {\r\n console.error(chalk.red(symbols.cross) + ' ' + chalk.red(message))\r\n },\r\n\r\n /**\r\n * 步骤信息\r\n */\r\n step: (message: string) => {\r\n console.log(chalk.cyan(symbols.arrowRight) + ' ' + chalk.gray(message))\r\n },\r\n\r\n /**\r\n * 标题\r\n */\r\n title: (message: string) => {\r\n console.log('\\n' + chalk.bold.underline(message) + '\\n')\r\n },\r\n\r\n /**\r\n * 普通文本(无图标)\r\n */\r\n log: (message: string) => {\r\n console.log(message)\r\n }\r\n}\r\n\r\n/**\r\n * 自定义 CLI 错误类\r\n */\r\nexport class CLIError extends Error {\r\n constructor(\r\n message: string,\r\n public code?: string,\r\n public suggestions?: string[]\r\n ) {\r\n super(message)\r\n this.name = 'CLIError'\r\n }\r\n}\r\n\r\n/**\r\n * 错误处理函数\r\n */\r\nexport async function handleError(error: unknown): Promise<void> {\r\n console.error()\r\n\r\n if (error instanceof CLIError) {\r\n logger.error(error.message)\r\n\r\n if (error.code) {\r\n const errorCodeText = await t('error.errorCode')\r\n console.log(chalk.gray(`${errorCodeText} ${error.code}`))\r\n }\r\n\r\n if (error.suggestions?.length) {\r\n const suggestionsText = await t('error.suggestions')\r\n console.log(chalk.yellow.bold(`\\n${suggestionsText}\\n`))\r\n error.suggestions.forEach((suggestion, index) => {\r\n console.log(chalk.gray(` ${index + 1}. ${suggestion}`))\r\n })\r\n }\r\n } else if (error instanceof Error) {\r\n logger.error(error.message)\r\n\r\n if (process.env.DEBUG) {\r\n console.log(chalk.gray('\\n' + error.stack))\r\n }\r\n } else {\r\n logger.error(await t('error.unknownError'))\r\n }\r\n\r\n const needHelpText = await t('error.needHelp')\r\n console.log(\r\n chalk.gray(`\\n${needHelpText} `) +\r\n chalk.blue.underline('https://github.com/AIConfigPlaza/acp-cli')\r\n )\r\n console.log()\r\n}\r\n","import fs from 'fs-extra'\r\nimport path from 'path'\r\nimport os from 'os'\r\n\r\n/**\r\n * 语言配置管理\r\n * 支持的语言: zh-CN (中文), en-US (英文)\r\n */\r\n\r\nexport type Locale = 'zh-CN' | 'en-US'\r\n\r\nconst LOCALE_ENV_KEY = 'ACP_CLI_LOCALE'\r\nconst DEFAULT_LOCALE: Locale = 'zh-CN'\r\n\r\nconst CONFIG_DIR = path.join(os.homedir(), '.acp')\r\nconst LOCALE_FILE = path.join(CONFIG_DIR, 'locale')\r\n\r\n/**\r\n * 读取当前语言配置\r\n */\r\nexport async function getLocale(): Promise<Locale> {\r\n // 1. 优先读取环境变量\r\n const envLocale = process.env[LOCALE_ENV_KEY]\r\n if (envLocale && isValidLocale(envLocale)) {\r\n return envLocale as Locale\r\n }\r\n\r\n // 2. 读取本地配置文件\r\n try {\r\n if (await fs.pathExists(LOCALE_FILE)) {\r\n const locale = (await fs.readFile(LOCALE_FILE, 'utf-8')).trim()\r\n if (isValidLocale(locale)) {\r\n return locale as Locale\r\n }\r\n }\r\n } catch (error) {\r\n // 读取失败使用默认值\r\n }\r\n\r\n // 3. 返回默认语言\r\n return DEFAULT_LOCALE\r\n}\r\n\r\n/**\r\n * 保存语言配置到本地文件\r\n */\r\nexport async function saveLocale(locale: Locale): Promise<void> {\r\n if (!isValidLocale(locale)) {\r\n throw new Error(`不支持的语言: ${locale}`)\r\n }\r\n\r\n // 确保配置目录存在\r\n await fs.ensureDir(CONFIG_DIR)\r\n\r\n // 保存语言配置\r\n await fs.writeFile(LOCALE_FILE, locale, 'utf-8')\r\n}\r\n\r\n/**\r\n * 验证语言代码是否有效\r\n */\r\nfunction isValidLocale(locale: string): boolean {\r\n return locale === 'zh-CN' || locale === 'en-US'\r\n}\r\n\r\n/**\r\n * 获取所有支持的语言列表\r\n */\r\nexport function getSupportedLocales(): Locale[] {\r\n return ['zh-CN', 'en-US']\r\n}\r\n\r\n/**\r\n * 获取语言显示名称\r\n */\r\nexport function getLocaleName(locale: Locale): string {\r\n const names: Record<Locale, string> = {\r\n 'zh-CN': '简体中文',\r\n 'en-US': 'English'\r\n }\r\n return names[locale]\r\n}\r\n","/**\r\n * 中文语言包\r\n */\r\n\r\nexport const zhCN = {\r\n // 通用\r\n common: {\r\n confirm: '确认',\r\n cancel: '取消',\r\n yes: '是',\r\n no: '否',\r\n success: '成功',\r\n failed: '失败',\r\n error: '错误',\r\n warning: '警告',\r\n info: '提示'\r\n },\r\n\r\n // CLI 主程序\r\n cli: {\r\n name: 'acp',\r\n description: 'AI-Config-Plaza CLI - 统一 AI 编程工具配置管理',\r\n version: '显示版本号',\r\n help: '显示帮助信息',\r\n exampleTitle: '示例:'\r\n },\r\n\r\n // login 命令\r\n login: {\r\n command: 'login',\r\n description: '登录 ACP CLI,保存访问令牌',\r\n title: '🔐 ACP CLI 登录',\r\n alreadyLoggedIn: '检测到已登录,是否重新登录?',\r\n cancelled: '已取消登录',\r\n inputToken: '请输入 CLI Token:',\r\n tokenEmpty: 'Token 不能为空',\r\n tokenInvalid: 'Token 格式不正确(至少 10 个字符)',\r\n success: '登录成功!Token 已保存到 ~/.acp/token',\r\n hint: '提示: 现在可以使用 acp apply 命令拉取配置',\r\n failed: '登录失败'\r\n },\r\n\r\n // apply 命令\r\n apply: {\r\n command: 'apply',\r\n description: '拉取并应用配置到本地项目',\r\n title: '🚀 ACP 配置应用',\r\n optionType: '资源类型 (solution|agent|prompt|mcp)',\r\n optionIde: 'AI IDE 类型 (vscode|cursor|codex|claude-code)',\r\n optionDir: '目标目录',\r\n notLoggedIn: '未登录,请先执行 acp login',\r\n loginFirst: '运行 acp login 命令登录',\r\n selectResourceType: '请选择资源类型:',\r\n resourceTypes: {\r\n solution: '解决方案 (Solution)',\r\n agent: 'Agent 配置 (暂不支持)',\r\n prompt: 'Prompt (暂不支持)',\r\n mcp: 'MCP 配置 (暂不支持)'\r\n },\r\n notSupported: '暂不支持独立应用 agent/prompt/mcp,请使用 solution 类型',\r\n noSelection: '未选择任何配置',\r\n selectIde: '请选择 AI IDE 类型:',\r\n applied: '配置已应用到:',\r\n searchPlaceholder: '搜索解决方案(输入名称或描述)',\r\n noResults: '没有找到解决方案',\r\n loadingMore: '加载更多...',\r\n noMore: '没有更多了',\r\n selected: '已选择',\r\n selectSolution: '请选择一个解决方案:',\r\n fetching: '正在获取解决方案列表...',\r\n fetchSuccess: '获取到 {count} 个解决方案',\r\n noSolutions: '暂无可用的解决方案',\r\n searchPrompt: '搜索解决方案 (按名称搜索,留空显示全部):',\r\n noMatch: '未找到匹配的解决方案',\r\n selectSolutionPage: '选择解决方案 (第 {current}/{total} 页):',\r\n nextPage: '>>> 下一页',\r\n prevPage: '<<< 上一页',\r\n cancel: '取消',\r\n fetchingDetail: '正在获取解决方案详情...',\r\n fetchDetailFailed: '获取解决方案失败',\r\n ideTypes: {\r\n vscode: 'VS Code',\r\n cursor: 'Cursor',\r\n codex: 'Codex',\r\n claudeCode: 'Claude Code'\r\n }\r\n },\r\n\r\n // locale 命令\r\n locale: {\r\n command: 'locale',\r\n description: '切换 CLI 语言',\r\n title: '🌐 语言设置',\r\n current: '当前语言',\r\n selectLanguage: '请选择语言:',\r\n success: '语言已切换为',\r\n failed: '语言切换失败',\r\n restartHint: '提示: 已生效,新命令将使用所选语言'\r\n },\r\n\r\n // update 命令\r\n update: {\r\n command: 'update',\r\n description: '更新 ACP CLI 到最新版本',\r\n title: '⬆️ CLI 自更新',\r\n currentVersion: '当前版本',\r\n latestVersion: '最新版本',\r\n alreadyLatest: '已是最新版本,无需更新',\r\n checkingLatest: '正在检查最新版本...',\r\n fetchFailed: '获取最新版本失败',\r\n selectTarget: '请选择更新目标:',\r\n targets: {\r\n global: '全局 (推荐)',\r\n local: '本地项目'\r\n },\r\n noPkgManager: '未检测到可用的包管理器 (pnpm/npm/yarn)',\r\n selectPkgManager: '请选择包管理器:',\r\n executing: '正在使用 {manager} 执行更新...',\r\n success: '更新成功!',\r\n failed: '更新失败',\r\n verifyHint: '提示: 运行 acp -v 查看当前版本'\r\n },\r\n\r\n // 错误处理\r\n error: {\r\n errorCode: '错误代码:',\r\n suggestions: '💡 建议:',\r\n needHelp: '需要帮助? 访问:',\r\n unknownError: '未知错误'\r\n }\r\n}\r\n","/**\r\n * English Language Pack\r\n */\r\n\r\nexport const enUS = {\r\n // Common\r\n common: {\r\n confirm: 'Confirm',\r\n cancel: 'Cancel',\r\n yes: 'Yes',\r\n no: 'No',\r\n success: 'Success',\r\n failed: 'Failed',\r\n error: 'Error',\r\n warning: 'Warning',\r\n info: 'Info'\r\n },\r\n\r\n // CLI Main\r\n cli: {\r\n name: 'acp',\r\n description: 'AI-Config-Plaza CLI - Unified AI Programming Tool Configuration Management',\r\n version: 'Show version number',\r\n help: 'Show help information',\r\n exampleTitle: 'Examples:'\r\n },\r\n\r\n // login command\r\n login: {\r\n command: 'login',\r\n description: 'Login to ACP CLI and save access token',\r\n title: '🔐 ACP CLI Login',\r\n alreadyLoggedIn: 'Already logged in. Do you want to login again?',\r\n cancelled: 'Login cancelled',\r\n inputToken: 'Please enter CLI Token:',\r\n tokenEmpty: 'Token cannot be empty',\r\n tokenInvalid: 'Invalid token format (at least 10 characters)',\r\n success: 'Login successful! Token saved to ~/.acp/token',\r\n hint: 'Tip: You can now use acp apply command to fetch configurations',\r\n failed: 'Login failed'\r\n },\r\n\r\n // apply command\r\n apply: {\r\n command: 'apply',\r\n description: 'Fetch and apply configurations to local project',\r\n title: '🚀 ACP Configuration Apply',\r\n optionType: 'Resource type (solution|agent|prompt|mcp)',\r\n optionIde: 'AI IDE type (vscode|cursor|codex|claude-code)',\r\n optionDir: 'Target directory',\r\n notLoggedIn: 'Not logged in. Please run acp login first',\r\n loginFirst: 'Run acp login command to login',\r\n selectResourceType: 'Please select resource type:',\r\n resourceTypes: {\r\n solution: 'Solution',\r\n agent: 'Agent Configuration (Not supported yet)',\r\n prompt: 'Prompt (Not supported yet)',\r\n mcp: 'MCP Configuration (Not supported yet)'\r\n },\r\n notSupported: 'Standalone application of agent/prompt/mcp is not supported yet. Please use solution type',\r\n noSelection: 'No configuration selected',\r\n selectIde: 'Please select AI IDE type:',\r\n applied: 'Configuration applied to:',\r\n searchPlaceholder: 'Search solutions (enter name or description)',\r\n noResults: 'No solutions found',\r\n loadingMore: 'Loading more...',\r\n noMore: 'No more items',\r\n selected: 'Selected',\r\n selectSolution: 'Please select a solution:',\r\n fetching: 'Fetching solution list...',\r\n fetchSuccess: 'Fetched {count} solutions',\r\n noSolutions: 'No solutions available',\r\n searchPrompt: 'Search solutions (search by name, leave empty to show all):',\r\n noMatch: 'No matching solutions found',\r\n selectSolutionPage: 'Select solution (Page {current}/{total}):',\r\n nextPage: '>>> Next Page',\r\n prevPage: '<<< Previous Page',\r\n cancel: 'Cancel',\r\n fetchingDetail: 'Fetching solution details...',\r\n fetchDetailFailed: 'Failed to fetch solutions',\r\n ideTypes: {\r\n vscode: 'VS Code',\r\n cursor: 'Cursor',\r\n codex: 'Codex',\r\n claudeCode: 'Claude Code'\r\n }\r\n },\r\n\r\n // locale command\r\n locale: {\r\n command: 'locale',\r\n description: 'Switch CLI language',\r\n title: '🌐 Language Settings',\r\n current: 'Current Language',\r\n selectLanguage: 'Please select language:',\r\n success: 'Language switched to',\r\n failed: 'Failed to switch language',\r\n restartHint: 'Tip: Changes take effect immediately for new commands'\r\n },\r\n\r\n // update command\r\n update: {\r\n command: 'update',\r\n description: 'Update ACP CLI to latest version',\r\n title: '⬆️ CLI Self Update',\r\n currentVersion: 'Current Version',\r\n latestVersion: 'Latest Version',\r\n alreadyLatest: 'Already up to date',\r\n checkingLatest: 'Checking latest version...',\r\n fetchFailed: 'Failed to fetch latest version',\r\n selectTarget: 'Select update target:',\r\n targets: {\r\n global: 'Global (Recommended)',\r\n local: 'Local Project'\r\n },\r\n noPkgManager: 'No available package manager detected (pnpm/npm/yarn)',\r\n selectPkgManager: 'Select a package manager:',\r\n executing: 'Executing update with {manager}...',\r\n success: 'Update successful!',\r\n failed: 'Update failed',\r\n verifyHint: 'Tip: Run acp -v to verify current version'\r\n },\r\n\r\n // Error handling\r\n error: {\r\n errorCode: 'Error Code:',\r\n suggestions: '💡 Suggestions:',\r\n needHelp: 'Need help? Visit:',\r\n unknownError: 'Unknown error'\r\n }\r\n}\r\n","import { getLocale, type Locale } from '../config/locale.js'\r\nimport { zhCN } from './zh-CN.js'\r\nimport { enUS } from './en-US.js'\r\n\r\n/**\r\n * 国际化工具 - 提供多语言支持\r\n */\r\n\r\n// 语言包映射\r\nconst messages: Record<Locale, typeof zhCN> = {\r\n 'zh-CN': zhCN,\r\n 'en-US': enUS\r\n}\r\n\r\n// 当前语言缓存\r\nlet currentLocale: Locale | null = null\r\nlet currentMessages: typeof zhCN | null = null\r\n\r\n/**\r\n * 初始化 i18n\r\n */\r\nasync function initI18n(): Promise<void> {\r\n if (!currentLocale) {\r\n currentLocale = await getLocale()\r\n currentMessages = messages[currentLocale]\r\n }\r\n}\r\n\r\n/**\r\n * 翻译函数 - 根据键路径获取翻译文本\r\n * @param key - 翻译键,支持点分隔的路径,如 'login.title'\r\n * @param params - 替换参数对象\r\n * @returns 翻译后的文本\r\n */\r\nexport async function t(key: string, params?: Record<string, string | number>): Promise<string> {\r\n await initI18n()\r\n\r\n // 通过点分隔的路径获取嵌套值\r\n const keys = key.split('.')\r\n let value: any = currentMessages\r\n\r\n for (const k of keys) {\r\n if (value && typeof value === 'object' && k in value) {\r\n value = value[k]\r\n } else {\r\n // 如果找不到翻译,返回 key 本身\r\n return key\r\n }\r\n }\r\n\r\n // 如果不是字符串,返回 key\r\n if (typeof value !== 'string') {\r\n return key\r\n }\r\n\r\n // 替换参数\r\n if (params) {\r\n return value.replace(/\\{(\\w+)\\}/g, (match, paramKey) => {\r\n return paramKey in params ? String(params[paramKey]) : match\r\n })\r\n }\r\n\r\n return value\r\n}\r\n\r\n/**\r\n * 同步翻译函数(需要先初始化)\r\n * @param key - 翻译键\r\n * @param params - 替换参数对象\r\n * @returns 翻译后的文本\r\n */\r\nexport function tSync(key: string, params?: Record<string, string | number>): string {\r\n if (!currentMessages) {\r\n // 如果未初始化,返回 key\r\n return key\r\n }\r\n\r\n const keys = key.split('.')\r\n let value: any = currentMessages\r\n\r\n for (const k of keys) {\r\n if (value && typeof value === 'object' && k in value) {\r\n value = value[k]\r\n } else {\r\n return key\r\n }\r\n }\r\n\r\n if (typeof value !== 'string') {\r\n return key\r\n }\r\n\r\n if (params) {\r\n return value.replace(/\\{(\\w+)\\}/g, (match, paramKey) => {\r\n return paramKey in params ? String(params[paramKey]) : match\r\n })\r\n }\r\n\r\n return value\r\n}\r\n\r\n/**\r\n * 获取当前语言\r\n */\r\nexport async function getCurrentLocale(): Promise<Locale> {\r\n await initI18n()\r\n return currentLocale!\r\n}\r\n\r\n/**\r\n * 重新加载语言配置(切换语言后调用)\r\n */\r\nexport async function reloadLocale(): Promise<void> {\r\n currentLocale = null\r\n currentMessages = null\r\n await initI18n()\r\n}\r\n\r\n/**\r\n * 获取完整的语言包(用于类型提示)\r\n */\r\nexport function getMessages() {\r\n return currentMessages || zhCN\r\n}\r\n","import { Command } from 'commander'\r\nimport inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport ora from 'ora'\r\nimport { apiClient } from '../api/client.js'\r\nimport { logger, CLIError } from '../utils/logger.js'\r\nimport { isLoggedIn } from '../config/token.js'\r\nimport { type AiIdeType } from '../utils/ide-mapper.js'\r\nimport { searchByName, paginate } from '../utils/pagination.js'\r\nimport { applySolution } from '../apply/writer.js'\r\nimport type { Solution } from '../types/index.js'\r\nimport { t } from '../i18n/index.js'\r\n\r\n/**\r\n * acp apply 命令\r\n * 拉取并应用配置到本地项目\r\n */\r\n\r\ntype ResourceType = 'solution' | 'agent' | 'prompt' | 'mcp'\r\n\r\nexport const applyCommand = new Command('apply')\r\n .description('拉取并应用配置到本地项目 / Fetch and apply configurations to local project')\r\n .option('-t, --type <type>', '资源类型 (solution|agent|prompt|mcp) / Resource type', 'solution')\r\n .option('-i, --ide <ide>', 'AI IDE 类型 / AI IDE type (vscode|cursor|codex|claude-code)')\r\n .option('-d, --dir <path>', '目标目录 / Target directory', process.cwd())\r\n .action(async (options) => {\r\n try {\r\n // 检查登录状态\r\n if (!(await isLoggedIn())) {\r\n throw new CLIError(\r\n await t('apply.notLoggedIn'),\r\n 'NOT_LOGGED_IN',\r\n [await t('apply.loginFirst')]\r\n )\r\n }\r\n\r\n logger.title(await t('apply.title'))\r\n\r\n // 1. 选择资源类型\r\n const resourceType = await selectResourceType(options.type)\r\n\r\n // 2. 根据类型拉取并选择资源\r\n let selectedSolution: Solution | null = null\r\n\r\n if (resourceType === 'solution') {\r\n selectedSolution = await fetchAndSelectSolution()\r\n } else {\r\n throw new CLIError(await t('apply.notSupported'))\r\n }\r\n\r\n if (!selectedSolution) {\r\n logger.info(await t('apply.noSelection'))\r\n return\r\n }\r\n\r\n // 3. 选择 IDE 类型\r\n const ide = options.ide || (await selectIde())\r\n\r\n // 4. 应用配置\r\n await applySolution(selectedSolution, {\r\n ide: ide as AiIdeType,\r\n targetDir: options.dir\r\n })\r\n\r\n const appliedMsg = await t('apply.applied')\r\n console.log(chalk.gray(`\\n${appliedMsg} ${chalk.cyan(options.dir)}\\n`))\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error(error.message)\r\n }\r\n process.exit(1)\r\n }\r\n })\r\n\r\n/**\r\n * 选择资源类型\r\n */\r\nasync function selectResourceType(defaultType?: string): Promise<ResourceType> {\r\n if (defaultType && ['solution', 'agent', 'prompt', 'mcp'].includes(defaultType)) {\r\n return defaultType as ResourceType\r\n }\r\n\r\n const { type } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'type',\r\n message: await t('apply.selectResourceType'),\r\n choices: [\r\n { name: chalk.cyan(await t('apply.resourceTypes.solution')), value: 'solution' },\r\n { name: chalk.gray(await t('apply.resourceTypes.agent')), value: 'agent', disabled: true },\r\n { name: chalk.gray(await t('apply.resourceTypes.prompt')), value: 'prompt', disabled: true },\r\n { name: chalk.gray(await t('apply.resourceTypes.mcp')), value: 'mcp', disabled: true }\r\n ],\r\n default: 'solution'\r\n }\r\n ])\r\n\r\n return type\r\n}\r\n\r\n/**\r\n * 拉取并选择解决方案\r\n */\r\nasync function fetchAndSelectSolution(): Promise<Solution | null> {\r\n const spinner = ora(await t('apply.fetching')).start()\r\n\r\n try {\r\n // 1. 拉取解决方案列表\r\n const response = await apiClient.getSolutions()\r\n spinner.stop()\r\n\r\n if (!response.data || response.data.length === 0) {\r\n logger.warning(await t('apply.noSolutions'))\r\n return null\r\n }\r\n\r\n logger.success(await t('apply.fetchSuccess', { count: response.data.length }))\r\n\r\n // 2. 搜索过滤\r\n const { searchQuery } = await inquirer.prompt([\r\n {\r\n type: 'input',\r\n name: 'searchQuery',\r\n message: await t('apply.searchPrompt'),\r\n default: ''\r\n }\r\n ])\r\n\r\n let filteredSolutions = searchByName(response.data, searchQuery)\r\n\r\n if (filteredSolutions.length === 0) {\r\n logger.warning(await t('apply.noMatch'))\r\n return null\r\n }\r\n\r\n // 3. 分页显示\r\n const PAGE_SIZE = 20\r\n let currentPage = 1\r\n let selectedSolution: Solution | null = null\r\n\r\n while (!selectedSolution) {\r\n const paginatedResult = paginate(filteredSolutions, {\r\n page: currentPage,\r\n pageSize: PAGE_SIZE\r\n })\r\n\r\n // 构建选择列表\r\n const choices = paginatedResult.items.map((solution) => ({\r\n name: `${chalk.cyan(solution.name)} ${chalk.yellow(`@${solution.author.username}`)} - ${chalk.gray(solution.description)}`,\r\n value: solution.id,\r\n short: solution.name\r\n }))\r\n\r\n // 添加分页控制选项\r\n if (paginatedResult.hasNext) {\r\n choices.push({\r\n name: chalk.yellow(await t('apply.nextPage')),\r\n value: '__NEXT_PAGE__',\r\n short: await t('apply.nextPage')\r\n })\r\n }\r\n\r\n if (paginatedResult.hasPrev) {\r\n choices.unshift({\r\n name: chalk.yellow(await t('apply.prevPage')),\r\n value: '__PREV_PAGE__',\r\n short: await t('apply.prevPage')\r\n })\r\n }\r\n\r\n choices.push({\r\n name: chalk.red(await t('apply.cancel')),\r\n value: '__CANCEL__',\r\n short: await t('apply.cancel')\r\n })\r\n\r\n const { selected } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'selected',\r\n message: await t('apply.selectSolutionPage', { \r\n current: currentPage, \r\n total: paginatedResult.totalPages \r\n }),\r\n choices,\r\n pageSize: 15\r\n }\r\n ])\r\n\r\n if (selected === '__CANCEL__') {\r\n return null\r\n } else if (selected === '__NEXT_PAGE__') {\r\n currentPage++\r\n } else if (selected === '__PREV_PAGE__') {\r\n currentPage--\r\n } else {\r\n // 获取详情\r\n const detailSpinner = ora(await t('apply.fetchingDetail')).start()\r\n const detailResponse = await apiClient.getSolutionById(selected)\r\n detailSpinner.stop()\r\n\r\n selectedSolution = detailResponse.data\r\n }\r\n }\r\n\r\n return selectedSolution\r\n } catch (error) {\r\n spinner.fail(await t('apply.fetchDetailFailed'))\r\n throw error\r\n }\r\n}\r\n\r\n/**\r\n * 选择 IDE 类型\r\n */\r\nasync function selectIde(): Promise<AiIdeType> {\r\n const { ide } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'ide',\r\n message: await t('apply.selectIde'),\r\n choices: [\r\n { name: chalk.cyan(await t('apply.ideTypes.vscode')), value: 'vscode' },\r\n { name: chalk.cyan(await t('apply.ideTypes.cursor')), value: 'cursor' },\r\n { name: chalk.cyan(await t('apply.ideTypes.codex')), value: 'codex' },\r\n { name: chalk.cyan(await t('apply.ideTypes.claudeCode')), value: 'claude-code' }\r\n ],\r\n default: 'vscode'\r\n }\r\n ])\r\n\r\n return ide\r\n}\r\n","import axios, { AxiosInstance, AxiosError } from 'axios'\r\nimport { getToken, getBaseUrl } from '../config/token.js'\r\nimport type {\r\n ApiResponse,\r\n Solution,\r\n AgentConfig,\r\n Prompt,\r\n McpConfig\r\n} from '../types/index.js'\r\n\r\n/**\r\n * API 客户端封装\r\n */\r\n\r\nclass ApiClient {\r\n private client: AxiosInstance\r\n private baseUrlPromise: Promise<string>\r\n\r\n constructor() {\r\n // 异步获取 BASE_URL\r\n this.baseUrlPromise = getBaseUrl()\r\n\r\n this.client = axios.create({\r\n timeout: 30000,\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n })\r\n\r\n // 请求拦截器:自动添加 token 和 baseURL\r\n this.client.interceptors.request.use(async (config) => {\r\n // 设置 baseURL\r\n if (!config.baseURL) {\r\n config.baseURL = await this.baseUrlPromise\r\n }\r\n\r\n // 添加 token\r\n const token = await getToken()\r\n if (token) {\r\n config.headers['X-CLI-TOKEN'] = token\r\n }\r\n return config\r\n })\r\n\r\n // 响应拦截器:统一错误处理\r\n this.client.interceptors.response.use(\r\n (response) => response,\r\n (error: AxiosError) => {\r\n if (error.response) {\r\n const status = error.response.status\r\n const message = (error.response.data as any)?.message || error.message\r\n\r\n if (status === 401) {\r\n throw new Error('认证失败,请先执行 acp login 登录')\r\n } else if (status === 403) {\r\n throw new Error('权限不足,请检查 token 是否有效')\r\n } else if (status === 404) {\r\n throw new Error('请求的资源不存在')\r\n } else if (status >= 500) {\r\n throw new Error(`服务器错误 (${status}): ${message}`)\r\n } else {\r\n throw new Error(`请求失败 (${status}): ${message}`)\r\n }\r\n } else if (error.request) {\r\n throw new Error('网络错误,请检查网络连接')\r\n } else {\r\n throw new Error(`请求配置错误: ${error.message}`)\r\n }\r\n }\r\n )\r\n }\r\n\r\n /**\r\n * 获取解决方案列表\r\n */\r\n async getSolutions(aiTool?: string): Promise<ApiResponse<Solution[]>> {\r\n const params = aiTool ? { aiTool } : {}\r\n const response = await this.client.get<ApiResponse<Solution[]>>(\r\n '/api/cli/solutions',\r\n { params }\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取解决方案详情\r\n */\r\n async getSolutionById(id: string): Promise<ApiResponse<Solution>> {\r\n const response = await this.client.get<ApiResponse<Solution>>(\r\n `/api/cli/solutions/${id}`\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 Agent 配置列表\r\n */\r\n async getAgents(): Promise<ApiResponse<AgentConfig[]>> {\r\n const response = await this.client.get<ApiResponse<AgentConfig[]>>(\r\n '/api/cli/agents'\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 Agent 配置详情\r\n */\r\n async getAgentById(id: string): Promise<ApiResponse<AgentConfig>> {\r\n const response = await this.client.get<ApiResponse<AgentConfig>>(\r\n `/api/cli/agents/${id}`\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 Prompt 列表\r\n */\r\n async getPrompts(): Promise<ApiResponse<Prompt[]>> {\r\n const response = await this.client.get<ApiResponse<Prompt[]>>(\r\n '/api/cli/prompts'\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 Prompt 详情\r\n */\r\n async getPromptById(id: string): Promise<ApiResponse<Prompt>> {\r\n const response = await this.client.get<ApiResponse<Prompt>>(\r\n `/api/cli/prompts/${id}`\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 MCP 配置列表\r\n */\r\n async getMcps(): Promise<ApiResponse<McpConfig[]>> {\r\n const response = await this.client.get<ApiResponse<McpConfig[]>>(\r\n '/api/cli/mcps'\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 MCP 配置详情\r\n */\r\n async getMcpById(id: string): Promise<ApiResponse<McpConfig>> {\r\n const response = await this.client.get<ApiResponse<McpConfig>>(\r\n `/api/cli/mcps/${id}`\r\n )\r\n return response.data\r\n }\r\n}\r\n\r\n// 导出单例\r\nexport const apiClient = new ApiClient()\r\n","/**\r\n * 分页工具函数\r\n */\r\n\r\nexport interface PaginationOptions {\r\n page: number\r\n pageSize: number\r\n}\r\n\r\nexport interface PaginationResult<T> {\r\n items: T[]\r\n total: number\r\n page: number\r\n pageSize: number\r\n totalPages: number\r\n hasNext: boolean\r\n hasPrev: boolean\r\n}\r\n\r\n/**\r\n * 对数组进行分页\r\n */\r\nexport function paginate<T>(\r\n items: T[],\r\n options: PaginationOptions\r\n): PaginationResult<T> {\r\n const { page, pageSize } = options\r\n const total = items.length\r\n const totalPages = Math.ceil(total / pageSize)\r\n const startIndex = (page - 1) * pageSize\r\n const endIndex = startIndex + pageSize\r\n\r\n return {\r\n items: items.slice(startIndex, endIndex),\r\n total,\r\n page,\r\n pageSize,\r\n totalPages,\r\n hasNext: page < totalPages,\r\n hasPrev: page > 1\r\n }\r\n}\r\n\r\n/**\r\n * 按名称搜索(不区分大小写)\r\n */\r\nexport function searchByName<T extends { name: string }>(\r\n items: T[],\r\n query: string\r\n): T[] {\r\n if (!query.trim()) {\r\n return items\r\n }\r\n\r\n const lowerQuery = query.toLowerCase().trim()\r\n return items.filter((item) =>\r\n item.name.toLowerCase().includes(lowerQuery)\r\n )\r\n}\r\n","import fs from 'fs-extra'\r\nimport path from 'path'\r\nimport chalk from 'chalk'\r\nimport inquirer from 'inquirer'\r\nimport { logger } from '../utils/logger.js'\r\nimport { getIdePathMapping, type AiIdeType } from '../utils/ide-mapper.js'\r\nimport type { Solution, Prompt, McpConfig, Skill } from '../types/index.js'\r\n\r\n/**\r\n * 配置应用模块 - 将远程配置写入本地文件\r\n */\r\n\r\nexport interface ApplyOptions {\r\n ide: AiIdeType\r\n targetDir: string\r\n}\r\n\r\n/**\r\n * 应用解决方案配置\r\n */\r\nexport async function applySolution(\r\n solution: Solution,\r\n options: ApplyOptions\r\n): Promise<void> {\r\n const { ide, targetDir } = options\r\n const pathMapping = getIdePathMapping(ide)\r\n\r\n logger.title(`📦 应用解决方案: ${chalk.cyan(solution.name)}`)\r\n\r\n // 1. 应用 Agent 配置\r\n if (solution.agentConfig) {\r\n await applyAgentConfig(\r\n solution.agentConfig.content,\r\n pathMapping.agents,\r\n targetDir\r\n )\r\n }\r\n\r\n // 2. 应用 Prompts\r\n if (solution.customPrompts?.length) {\r\n await applyPrompts(\r\n solution.customPrompts,\r\n pathMapping.prompts,\r\n targetDir\r\n )\r\n }\r\n\r\n // 3. 应用 MCP 配置\r\n if (solution.mcpConfigs?.length) {\r\n await applyMcpConfigs(\r\n solution.mcpConfigs,\r\n pathMapping.mcp,\r\n targetDir\r\n )\r\n }\r\n\r\n // 4. 应用 Skills\r\n if (solution.skills?.length) {\r\n await applySkills(\r\n solution.skills,\r\n pathMapping.skills,\r\n targetDir\r\n )\r\n }\r\n\r\n logger.success(`\\n✨ 解决方案 ${chalk.cyan(solution.name)} 应用成功!`)\r\n}\r\n\r\n/**\r\n * 应用 Agent 配置\r\n */\r\nexport async function applyAgentConfig(\r\n content: string,\r\n relativePath: string,\r\n targetDir: string\r\n): Promise<void> {\r\n const filePath = path.join(targetDir, relativePath)\r\n\r\n logger.step(`写入 Agent 配置: ${chalk.gray(relativePath)}`)\r\n\r\n // 检查文件是否存在\r\n const exists = await fs.pathExists(filePath)\r\n if (exists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `文件 ${chalk.cyan(relativePath)} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${relativePath}`)\r\n return\r\n }\r\n }\r\n\r\n // 写入文件\r\n await fs.ensureDir(path.dirname(filePath))\r\n await fs.writeFile(filePath, content, 'utf-8')\r\n\r\n logger.success(`已写入: ${relativePath}`)\r\n}\r\n\r\n/**\r\n * 应用 Prompts\r\n */\r\nexport async function applyPrompts(\r\n prompts: Prompt[],\r\n promptsDir: string,\r\n targetDir: string\r\n): Promise<void> {\r\n const fullPromptsDir = path.join(targetDir, promptsDir)\r\n\r\n logger.step(`写入 ${prompts.length} 个 Prompt 配置到: ${chalk.gray(promptsDir)}`)\r\n\r\n // 确保目录存在\r\n await fs.ensureDir(fullPromptsDir)\r\n\r\n for (const prompt of prompts) {\r\n // 生成文件名(清理特殊字符)\r\n const fileName = sanitizeFileName(prompt.name) + '.prompt.md'\r\n const filePath = path.join(fullPromptsDir, fileName)\r\n\r\n // 检查是否存在\r\n const exists = await fs.pathExists(filePath)\r\n if (exists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `Prompt ${chalk.cyan(fileName)} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${fileName}`)\r\n continue\r\n }\r\n }\r\n\r\n // 写入内容\r\n await fs.writeFile(filePath, prompt.content, 'utf-8')\r\n logger.success(`已写入: ${path.join(promptsDir, fileName)}`)\r\n }\r\n}\r\n\r\n/**\r\n * 应用 MCP 配置\r\n */\r\nexport async function applyMcpConfigs(\r\n mcpConfigs: McpConfig[],\r\n mcpFile: string,\r\n targetDir: string\r\n): Promise<void> {\r\n // 检查是否为 CodeBuddy IDE(不支持 MCP 配置)\r\n if (!mcpFile || mcpFile === '') {\r\n logger.warning('暂不支持 CodeBuddy 的 MCP 配置写入')\r\n return\r\n }\r\n\r\n const filePath = path.join(targetDir, mcpFile)\r\n\r\n logger.step(`写入 MCP 配置: ${chalk.gray(mcpFile)}`)\r\n\r\n // 构造 mcpServers 结构\r\n const mcpServers: Record<string, any> = {}\r\n\r\n for (const mcpConfig of mcpConfigs) {\r\n try {\r\n const config = JSON.parse(mcpConfig.configJson)\r\n // 使用 MCP 配置的名称作为 key\r\n mcpServers[mcpConfig.name] = config\r\n } catch (error) {\r\n logger.warning(`MCP 配置 ${mcpConfig.name} 格式错误,已跳过`)\r\n }\r\n }\r\n\r\n // 检查文件是否存在\r\n const exists = await fs.pathExists(filePath)\r\n if (exists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `文件 ${chalk.cyan(mcpFile)} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${mcpFile}`)\r\n return\r\n }\r\n }\r\n\r\n // 写入文件\r\n await fs.ensureDir(path.dirname(filePath))\r\n\r\n // 根据文件扩展名和路径决定输出格式\r\n if (mcpFile.endsWith('.toml')) {\r\n // Codex 使用 TOML 格式\r\n const tomlContent = convertMcpToToml(mcpServers)\r\n await fs.writeFile(filePath, tomlContent, 'utf-8')\r\n } else {\r\n // JSON 格式\r\n let mergedConfig: Record<string, any>\r\n \r\n // VS Code 使用 \"servers\",其他 IDE 使用 \"mcpServers\"\r\n if (mcpFile.includes('.vscode')) {\r\n mergedConfig = {\r\n servers: mcpServers\r\n }\r\n } else {\r\n mergedConfig = {\r\n mcpServers\r\n }\r\n }\r\n \r\n await fs.writeFile(filePath, JSON.stringify(mergedConfig, null, 2), 'utf-8')\r\n }\r\n\r\n logger.success(`已写入: ${mcpFile}`)\r\n}\r\n\r\n/**\r\n * 将 MCP 配置转换为 TOML 格式(用于 Codex)\r\n */\r\nfunction convertMcpToToml(mcpServers: Record<string, any>): string {\r\n let tomlContent = ''\r\n\r\n for (const [serverName, config] of Object.entries(mcpServers)) {\r\n tomlContent += `[mcp_servers.${serverName}]\\n`\r\n \r\n // 写入 command\r\n if (config.command) {\r\n tomlContent += `command = ${JSON.stringify(config.command)}\\n`\r\n }\r\n\r\n // 写入 args\r\n if (config.args && Array.isArray(config.args)) {\r\n const argsStr = config.args.map((arg: string) => JSON.stringify(arg)).join(', ')\r\n tomlContent += `args = [${argsStr}]\\n`\r\n }\r\n\r\n // 写入 env\r\n if (config.env && typeof config.env === 'object') {\r\n const envEntries = Object.entries(config.env)\r\n if (envEntries.length > 0) {\r\n const envStr = envEntries\r\n .map(([key, value]) => `${key} = ${JSON.stringify(value)}`)\r\n .join(', ')\r\n tomlContent += `env = { ${envStr} }\\n`\r\n }\r\n }\r\n\r\n tomlContent += '\\n'\r\n }\r\n\r\n return tomlContent\r\n}\r\n\r\n/**\r\n * 应用 Skills\r\n */\r\nexport async function applySkills(\r\n skills: Skill[],\r\n skillsDir: string,\r\n targetDir: string\r\n): Promise<void> {\r\n const fullSkillsDir = path.join(targetDir, skillsDir)\r\n\r\n logger.step(`写入 ${skills.length} 个 Skill 配置到: ${chalk.gray(skillsDir)}`)\r\n\r\n // 确保目录存在\r\n await fs.ensureDir(fullSkillsDir)\r\n\r\n for (const skill of skills) {\r\n // 生成目录名(清理特殊字符)\r\n const skillDirName = sanitizeSkillName(skill.name)\r\n const skillDirPath = path.join(fullSkillsDir, skillDirName)\r\n\r\n logger.step(`处理 Skill: ${chalk.cyan(skill.name)}`)\r\n\r\n // 检查目录是否存在\r\n const dirExists = await fs.pathExists(skillDirPath)\r\n if (dirExists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `Skill 目录 ${chalk.cyan(skillDirName)} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${skillDirName}`)\r\n continue\r\n }\r\n }\r\n\r\n // 确保目录存在\r\n await fs.ensureDir(skillDirPath)\r\n\r\n // 1. 创建 SKILL.md 文件\r\n const skillMdPath = path.join(skillDirPath, 'SKILL.md')\r\n await fs.writeFile(skillMdPath, skill.skillMarkdown, 'utf-8')\r\n logger.success(`已写入: ${path.join(skillsDir, skillDirName, 'SKILL.md')}`)\r\n\r\n // 2. 处理 SkillResources\r\n if (skill.skillResources && skill.skillResources.length > 0) {\r\n for (const resource of skill.skillResources) {\r\n // 确保相对路径安全(防止路径遍历攻击)\r\n const safeRelativePath = sanitizePath(resource.relativePath)\r\n const resourceFilePath = path.join(skillDirPath, safeRelativePath, resource.fileName)\r\n\r\n // 检查文件是否存在\r\n const fileExists = await fs.pathExists(resourceFilePath)\r\n if (fileExists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `文件 ${chalk.cyan(path.join(skillDirName, safeRelativePath))} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${path.join(skillDirName, safeRelativePath)}`)\r\n continue\r\n }\r\n }\r\n\r\n // 确保父目录存在\r\n await fs.ensureDir(path.dirname(resourceFilePath))\r\n\r\n // 写入文件内容\r\n await fs.writeFile(resourceFilePath, resource.fileContent, 'utf-8')\r\n logger.success(`已写入: ${path.join(skillsDir, skillDirName, safeRelativePath)}`)\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 清理 skill 名称,用于创建目录名\r\n */\r\nfunction sanitizeSkillName(name: string): string {\r\n return name\r\n .replace(/[<>:\"/\\\\|?*]/g, '-') // 替换非法字符\r\n .replace(/\\s+/g, '-') // 空格转连字符\r\n .replace(/-+/g, '-') // 多个连字符合并\r\n .replace(/^-+|-+$/g, '') // 移除首尾连字符\r\n .toLowerCase()\r\n}\r\n\r\n/**\r\n * 清理路径,防止路径遍历攻击\r\n */\r\nfunction sanitizePath(relativePath: string): string {\r\n // 移除路径遍历攻击(如 ../, ..\\, 等)\r\n let safePath = relativePath\r\n .replace(/\\.\\./g, '') // 移除 ..\r\n .replace(/^[/\\\\]+/, '') // 移除开头的 / 或 \\\r\n .replace(/[/\\\\]+/g, path.sep) // 统一路径分隔符\r\n\r\n // 确保路径是相对路径,不包含绝对路径\r\n if (path.isAbsolute(safePath)) {\r\n safePath = path.relative('/', safePath)\r\n }\r\n\r\n // 移除 Windows 驱动器号(如 C:)\r\n if (safePath.match(/^[A-Za-z]:/)) {\r\n safePath = safePath.substring(2)\r\n }\r\n\r\n return safePath\r\n}\r\n\r\n/**\r\n * 清理文件名中的特殊字符\r\n */\r\nfunction sanitizeFileName(name: string): string {\r\n return name\r\n .replace(/[<>:\"/\\\\|?*]/g, '-') // 替换非法字符\r\n .replace(/\\s+/g, '-') // 空格转连字符\r\n .replace(/-+/g, '-') // 多个连字符合并\r\n .toLowerCase()\r\n}\r\n","import { homedir } from 'os'\r\nimport type { AiIdeType, IdePathMapping } from '../types/index.js'\r\n\r\n// 重新导出类型\r\nexport type { AiIdeType, IdePathMapping }\r\n\r\n/**\r\n * AI IDE 路径映射配置\r\n * 定义不同 IDE 的配置文件输出路径\r\n */\r\n\r\nexport const IDE_PATH_MAPPINGS: Record<AiIdeType, IdePathMapping> = {\r\n vscode: {\r\n prompts: '.github/prompts',\r\n agents: 'AGENTS.md',\r\n mcp: '.vscode/mcp.json',\r\n skills: '.github/skills'\r\n },\r\n cursor: {\r\n prompts: '.cursor/commands',\r\n agents: 'AGENTS.md',\r\n mcp: '.cursor/mcp.json',\r\n skills: '.cursor/skills'\r\n },\r\n codex: {\r\n prompts: '~/.codex/prompts',\r\n agents: 'AGENTS.md',\r\n mcp: '.codex/config.toml',\r\n skills: '.codex/skills'\r\n },\r\n 'claude-code': {\r\n prompts: '.claude/commands',\r\n agents: 'AGENTS.md',\r\n mcp: '.mcp.json',\r\n skills: '.claude/skills'\r\n },\r\n codebuddy: {\r\n prompts: '.codebuddy/commands',\r\n agents: 'AGENTS.md',\r\n mcp: '.mcp.json',\r\n skills: '.codebuddy/skills'\r\n },\r\n qoder: {\r\n prompts: '.qoder/commands',\r\n agents: 'AGENTS.md',\r\n mcp: '.mcp.json',\r\n skills: 'qoder/skills'\r\n }\r\n}\r\n\r\n/**\r\n * 展开路径中的 ~ 为用户主目录\r\n */\r\nfunction expandPath(path: string): string {\r\n if (path.startsWith('~')) {\r\n return path.replace('~', homedir())\r\n }\r\n return path\r\n}\r\n\r\n/**\r\n * 获取 IDE 路径映射\r\n */\r\nexport function getIdePathMapping(ide: AiIdeType): IdePathMapping {\r\n const mapping = IDE_PATH_MAPPINGS[ide]\r\n return {\r\n prompts: expandPath(mapping.prompts),\r\n agents: expandPath(mapping.agents),\r\n mcp: expandPath(mapping.mcp),\r\n skills: expandPath(mapping.skills)\r\n }\r\n}\r\n\r\n/**\r\n * 获取所有支持的 IDE 列表\r\n */\r\nexport function getSupportedIdes(): AiIdeType[] {\r\n return Object.keys(IDE_PATH_MAPPINGS) as AiIdeType[]\r\n}\r\n\r\n/**\r\n * 验证 IDE 类型是否支持\r\n */\r\nexport function isValidIde(ide: string): ide is AiIdeType {\r\n return ide in IDE_PATH_MAPPINGS\r\n}\r\n","import { Command } from 'commander'\r\nimport inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport { getLocale, saveLocale, getSupportedLocales, getLocaleName, type Locale } from '../config/locale.js'\r\nimport { t } from '../i18n/index.js'\r\nimport { logger } from '../utils/logger.js'\r\n\r\n/**\r\n * acp locale 命令\r\n * 切换 CLI 语言\r\n */\r\n\r\nexport const localeCommand = new Command('locale')\r\n .description('切换 CLI 语言 / Switch CLI language')\r\n .action(async () => {\r\n try {\r\n // 获取当前语言\r\n const currentLocale = await getLocale()\r\n \r\n // 显示标题\r\n const title = await t('locale.title')\r\n logger.title(title)\r\n\r\n // 显示当前语言\r\n const currentText = await t('locale.current')\r\n console.log(chalk.gray(`${currentText}: `) + chalk.cyan(getLocaleName(currentLocale)))\r\n console.log()\r\n\r\n // 选择新语言\r\n const supportedLocales = getSupportedLocales()\r\n const selectText = await t('locale.selectLanguage')\r\n \r\n const { newLocale } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'newLocale',\r\n message: selectText,\r\n choices: supportedLocales.map(locale => ({\r\n name: locale === currentLocale \r\n ? chalk.cyan(`${getLocaleName(locale)} (当前 / Current)`)\r\n : getLocaleName(locale),\r\n value: locale\r\n })),\r\n default: currentLocale\r\n }\r\n ])\r\n\r\n // 如果选择的是当前语言,则不做任何操作\r\n if (newLocale === currentLocale) {\r\n logger.info(`${await t('locale.current')}: ${getLocaleName(currentLocale)}`)\r\n return\r\n }\r\n\r\n // 保存新语言\r\n await saveLocale(newLocale as Locale)\r\n\r\n // 显示成功消息(使用新语言)\r\n // 注意:这里需要手动构造消息,因为 t() 函数还在使用旧语言缓存\r\n if (newLocale === 'zh-CN') {\r\n logger.success(`语言已切换为 ${getLocaleName(newLocale)}`)\r\n console.log(chalk.gray('\\n提示: 已生效,新命令将使用所选语言\\n'))\r\n } else {\r\n logger.success(`Language switched to ${getLocaleName(newLocale)}`)\r\n console.log(chalk.gray('\\nTip: Changes take effect immediately for new commands\\n'))\r\n }\r\n\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error(`${await t('locale.failed')}: ${error.message}`)\r\n }\r\n process.exit(1)\r\n }\r\n })\r\n","import { Command } from 'commander'\r\nimport inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport ora from 'ora'\r\nimport axios from 'axios'\r\nimport { spawnSync } from 'child_process'\r\nimport { logger, CLIError } from '../utils/logger.js'\r\nimport { t } from '../i18n/index.js'\r\n\r\n/**\r\n * acp update 命令\r\n * 检查并更新 ACP CLI 到最新版本\r\n */\r\n\r\n// 版本号在构建时注入\r\n// @ts-ignore - 构建时通过 tsup define 注入\r\nconst currentVersion = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0-dev'\r\nconst packageName = '@ai-config-plaza/acp-cli'\r\n\r\ntype UpdateTarget = 'global' | 'local'\r\n\r\nfunction getAvailablePkgManagers(): string[] {\r\n const managers = ['pnpm', 'npm', 'yarn']\r\n const available: string[] = []\r\n for (const m of managers) {\r\n const res = spawnSync(m, ['--version'], { stdio: 'pipe', shell: true })\r\n if (res.status === 0) available.push(m)\r\n }\r\n return available\r\n}\r\n\r\nfunction runUpdate(target: UpdateTarget, manager: string): number {\r\n const isGlobal = target === 'global'\r\n let args: string[] = []\r\n\r\n if (manager === 'pnpm') {\r\n args = isGlobal\r\n ? ['add', '-g', `${packageName}@latest`]\r\n : ['add', `${packageName}@latest`]\r\n } else if (manager === 'npm') {\r\n args = isGlobal\r\n ? ['install', '-g', `${packageName}@latest`]\r\n : ['install', `${packageName}@latest`, '--save']\r\n } else if (manager === 'yarn') {\r\n args = isGlobal\r\n ? ['global', 'add', `${packageName}@latest`]\r\n : ['add', `${packageName}@latest`]\r\n } else {\r\n return 1\r\n }\r\n\r\n const execSpinner = ora().start()\r\n execSpinner.text = manager + ' ' + args.join(' ')\r\n\r\n const res = spawnSync(manager, args, { stdio: 'inherit', shell: true })\r\n execSpinner.stop()\r\n return res.status ?? 1\r\n}\r\n\r\nexport const updateCommand = new Command('update')\r\n .description('更新 ACP CLI 到最新版本 / Update ACP CLI to latest version')\r\n .option('-t, --target <target>', '更新目标 (global|local) / Update target', 'global')\r\n .action(async (options) => {\r\n try {\r\n logger.title(await t('update.title'))\r\n\r\n // 显示当前版本\r\n logger.info(`${await t('update.currentVersion')}: ${chalk.cyan(currentVersion)}`)\r\n\r\n // 查询 npm 最新版本\r\n const spinner = ora(await t('update.checkingLatest')).start()\r\n let latestVersion = ''\r\n try {\r\n const resp = await axios.get(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`)\r\n latestVersion = resp.data?.version || ''\r\n } catch (e) {\r\n spinner.fail(await t('update.fetchFailed'))\r\n throw new CLIError(await t('update.fetchFailed'), 'FETCH_LATEST_FAILED')\r\n }\r\n\r\n spinner.stop()\r\n if (!latestVersion) {\r\n throw new CLIError(await t('update.fetchFailed'), 'LATEST_EMPTY')\r\n }\r\n\r\n logger.info(`${await t('update.latestVersion')}: ${chalk.cyan(latestVersion)}`)\r\n\r\n if (currentVersion === latestVersion) {\r\n logger.success(await t('update.alreadyLatest'))\r\n return\r\n }\r\n\r\n // 选择更新目标\r\n const target: UpdateTarget = ['global', 'local'].includes(options.target)\r\n ? options.target\r\n : (await (async () => {\r\n const { targetSel } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'targetSel',\r\n message: await t('update.selectTarget'),\r\n choices: [\r\n { name: await t('update.targets.global'), value: 'global' },\r\n { name: await t('update.targets.local'), value: 'local' }\r\n ],\r\n default: 'global'\r\n }\r\n ])\r\n return targetSel as UpdateTarget\r\n })())\r\n\r\n // 检测包管理器\r\n const managers = getAvailablePkgManagers()\r\n if (managers.length === 0) {\r\n throw new CLIError(await t('update.noPkgManager'), 'NO_PKG_MANAGER', [\r\n '安装 pnpm 或 npm 后重试',\r\n 'https://pnpm.io/installation'\r\n ])\r\n }\r\n\r\n let manager = managers[0]\r\n if (managers.length > 1) {\r\n const { pm } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'pm',\r\n message: await t('update.selectPkgManager'),\r\n choices: managers.map(m => ({ name: m, value: m })),\r\n default: manager\r\n }\r\n ])\r\n manager = pm\r\n }\r\n\r\n logger.step(await t('update.executing', { manager }))\r\n const code = runUpdate(target, manager)\r\n if (code === 0) {\r\n logger.success(await t('update.success'))\r\n logger.info(await t('update.verifyHint'))\r\n } else {\r\n throw new CLIError(await t('update.failed'), 'UPDATE_FAILED')\r\n }\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error(error.message)\r\n }\r\n process.exit(1)\r\n }\r\n })\r\n"],"mappings":"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","names":["Command","chalk","chalk","fs","path","os","CONFIG_DIR","chalk","Command","inquirer","chalk","fs","path","chalk","inquirer","path","chalk","path","fs","inquirer","Command","chalk","inquirer","Command","inquirer","chalk","Command","currentLocale","chalk","inquirer","Command","inquirer","chalk","ora","axios","ora","Command","chalk","axios","inquirer","Command","chalk"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/config/token.ts","../src/utils/logger.ts","../src/config/locale.ts","../src/i18n/zh-CN.ts","../src/i18n/en-US.ts","../src/i18n/index.ts","../src/commands/apply.ts","../src/api/client.ts","../src/utils/pagination.ts","../src/apply/writer.ts","../src/utils/ide-mapper.ts","../src/commands/locale.ts","../src/commands/update.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { Command } from 'commander'\r\nimport chalk from 'chalk'\r\nimport { loginCommand } from './commands/login.js'\r\nimport { applyCommand } from './commands/apply.js'\r\nimport { localeCommand } from './commands/locale.js'\r\nimport { updateCommand } from './commands/update.js'\r\nimport { handleError } from './utils/logger.js'\r\nimport { t } from './i18n/index.js'\r\n\r\n/**\r\n * ACP CLI 主入口\r\n */\r\n\r\n// 版本号在构建时注入\r\n// @ts-ignore - 构建时通过 tsup define 注入\r\nconst version = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0-dev'\r\n\r\nasync function main() {\r\n const program = new Command()\r\n\r\n program\r\n .name('acp')\r\n .description(\r\n chalk.gray(await t('cli.description'))\r\n )\r\n .version(version, '-v, --version', await t('cli.version'))\r\n .helpOption('-h, --help', await t('cli.help'))\r\n\r\n // 注册命令\r\n program.addCommand(loginCommand)\r\n program.addCommand(applyCommand)\r\n program.addCommand(localeCommand)\r\n program.addCommand(updateCommand)\r\n\r\n // 自定义帮助显示\r\n program.on('--help', async () => {\r\n console.log(chalk.bold('\\n' + await t('cli.exampleTitle') + '\\n'))\r\n console.log(chalk.gray(' $ acp login'))\r\n console.log(chalk.gray(' $ acp apply'))\r\n console.log(chalk.gray(' $ acp apply --ide vscode --dir ./my-project'))\r\n console.log(chalk.gray(' $ acp locale'))\r\n console.log(chalk.gray(' $ acp update'))\r\n console.log()\r\n })\r\n\r\n // 解析命令\r\n try {\r\n await program.parseAsync(process.argv)\r\n } catch (error) {\r\n await handleError(error)\r\n process.exit(1)\r\n }\r\n}\r\n\r\nmain()\r\n","import { Command } from 'commander'\r\nimport inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport { saveToken, getToken, initDefaultConfig } from '../config/token.js'\r\nimport { logger } from '../utils/logger.js'\r\nimport { t } from '../i18n/index.js'\r\n\r\n/**\r\n * acp login 命令\r\n * 提示用户输入 CLI Token 并保存\r\n */\r\n\r\nexport const loginCommand = new Command('login')\r\n .description('登录 ACP CLI,保存访问令牌 / Login to ACP CLI and save access token')\r\n .action(async () => {\r\n try {\r\n logger.title(await t('login.title'))\r\n\r\n // 初始化默认配置(首次使用时)\r\n await initDefaultConfig()\r\n\r\n // 检查是否已有 token\r\n const existingToken = await getToken()\r\n if (existingToken) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: await t('login.alreadyLoggedIn'),\r\n default: false\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.info(await t('login.cancelled'))\r\n return\r\n }\r\n }\r\n\r\n // 提示输入 token\r\n const { token } = await inquirer.prompt([\r\n {\r\n type: 'password',\r\n name: 'token',\r\n message: await t('login.inputToken'),\r\n validate: async (input: string) => {\r\n if (!input.trim()) {\r\n return await t('login.tokenEmpty')\r\n }\r\n if (input.trim().length < 10) {\r\n return await t('login.tokenInvalid')\r\n }\r\n return true\r\n },\r\n mask: '*'\r\n }\r\n ])\r\n\r\n // 保存 token\r\n await saveToken(token)\r\n\r\n logger.success(await t('login.success'))\r\n console.log(chalk.gray('\\n' + await t('login.hint') + '\\n'))\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error(`${await t('login.failed')}: ${error.message}`)\r\n }\r\n process.exit(1)\r\n }\r\n })\r\n","import fs from 'fs-extra'\r\nimport path from 'path'\r\nimport os from 'os'\r\n\r\n/**\r\n * Token 和 BASE_URL 配置管理\r\n * 优先级: 环境变量 > ~/.acp/ 配置文件\r\n */\r\n\r\nconst TOKEN_ENV_KEY = 'ACP_CLI_TOKEN'\r\nconst BASE_URL_ENV_KEY = 'ACP_CLI_BASE_URL'\r\nconst DEFAULT_BASE_URL = 'https://api.ai-config-plaza.com'\r\n\r\nconst CONFIG_DIR = path.join(os.homedir(), '.acp')\r\nconst TOKEN_FILE = path.join(CONFIG_DIR, 'token')\r\nconst BASE_URL_FILE = path.join(CONFIG_DIR, 'base-url')\r\n\r\n/**\r\n * 读取 CLI Token\r\n */\r\nexport async function getToken(): Promise<string | null> {\r\n // 1. 优先读取环境变量\r\n const envToken = process.env[TOKEN_ENV_KEY]\r\n if (envToken?.trim()) {\r\n return envToken.trim()\r\n }\r\n\r\n // 2. 读取本地配置文件\r\n try {\r\n if (await fs.pathExists(TOKEN_FILE)) {\r\n const token = await fs.readFile(TOKEN_FILE, 'utf-8')\r\n return token.trim() || null\r\n }\r\n } catch (error) {\r\n // 读取失败返回 null\r\n }\r\n\r\n return null\r\n}\r\n\r\n/**\r\n * 保存 CLI Token 到本地配置文件\r\n */\r\nexport async function saveToken(token: string): Promise<void> {\r\n if (!token?.trim()) {\r\n throw new Error('Token 不能为空')\r\n }\r\n\r\n // 确保配置目录存在\r\n await fs.ensureDir(CONFIG_DIR)\r\n\r\n // 写入 token 文件\r\n await fs.writeFile(TOKEN_FILE, token.trim(), 'utf-8')\r\n}\r\n\r\n/**\r\n * 删除本地 Token\r\n */\r\nexport async function removeToken(): Promise<void> {\r\n if (await fs.pathExists(TOKEN_FILE)) {\r\n await fs.remove(TOKEN_FILE)\r\n }\r\n}\r\n\r\n/**\r\n * 检查是否已登录\r\n */\r\nexport async function isLoggedIn(): Promise<boolean> {\r\n const token = await getToken()\r\n return token !== null && token.length > 0\r\n}\r\n\r\n/**\r\n * 读取 BASE_URL\r\n */\r\nexport async function getBaseUrl(): Promise<string> {\r\n // 1. 优先读取环境变量\r\n const envBaseUrl = process.env[BASE_URL_ENV_KEY]\r\n if (envBaseUrl?.trim()) {\r\n return envBaseUrl.trim()\r\n }\r\n\r\n // 2. 读取本地配置文件\r\n try {\r\n if (await fs.pathExists(BASE_URL_FILE)) {\r\n const baseUrl = await fs.readFile(BASE_URL_FILE, 'utf-8')\r\n if (baseUrl.trim()) {\r\n return baseUrl.trim()\r\n }\r\n }\r\n } catch (error) {\r\n // 读取失败,使用默认值\r\n }\r\n\r\n // 3. 返回默认值\r\n return DEFAULT_BASE_URL\r\n}\r\n\r\n/**\r\n * 保存 BASE_URL 到本地配置文件\r\n */\r\nexport async function saveBaseUrl(baseUrl: string): Promise<void> {\r\n if (!baseUrl?.trim()) {\r\n throw new Error('BASE_URL 不能为空')\r\n }\r\n\r\n // 验证 URL 格式\r\n try {\r\n new URL(baseUrl.trim())\r\n } catch {\r\n throw new Error('BASE_URL 格式不正确,请输入有效的 URL')\r\n }\r\n\r\n // 确保配置目录存在\r\n await fs.ensureDir(CONFIG_DIR)\r\n\r\n // 写入 base-url 文件\r\n await fs.writeFile(BASE_URL_FILE, baseUrl.trim(), 'utf-8')\r\n}\r\n\r\n/**\r\n * 删除本地 BASE_URL\r\n */\r\nexport async function removeBaseUrl(): Promise<void> {\r\n if (await fs.pathExists(BASE_URL_FILE)) {\r\n await fs.remove(BASE_URL_FILE)\r\n }\r\n}\r\n\r\n/**\r\n * 初始化默认配置(首次使用时)\r\n */\r\nexport async function initDefaultConfig(): Promise<void> {\r\n await fs.ensureDir(CONFIG_DIR)\r\n\r\n // 如果 BASE_URL 不存在,初始化默认值\r\n if (!(await fs.pathExists(BASE_URL_FILE))) {\r\n await saveBaseUrl(DEFAULT_BASE_URL)\r\n }\r\n}\r\n","import chalk from 'chalk'\r\nimport { t } from '../i18n/index.js'\r\n\r\n/**\r\n * 日志工具 - 提供统一的终端输出格式\r\n */\r\n\r\n// 使用 Unicode 符号代替 figures\r\nconst symbols = {\r\n info: 'ℹ',\r\n tick: '✓',\r\n warning: '⚠',\r\n cross: '✖',\r\n arrowRight: '→'\r\n}\r\n\r\nexport const logger = {\r\n /**\r\n * 普通信息\r\n */\r\n info: (message: string) => {\r\n console.log(chalk.blue(symbols.info) + ' ' + message)\r\n },\r\n\r\n /**\r\n * 成功信息\r\n */\r\n success: (message: string) => {\r\n console.log(chalk.green(symbols.tick) + ' ' + chalk.green(message))\r\n },\r\n\r\n /**\r\n * 警告信息\r\n */\r\n warning: (message: string) => {\r\n console.log(chalk.yellow(symbols.warning) + ' ' + chalk.yellow(message))\r\n },\r\n\r\n /**\r\n * 错误信息\r\n */\r\n error: (message: string) => {\r\n console.error(chalk.red(symbols.cross) + ' ' + chalk.red(message))\r\n },\r\n\r\n /**\r\n * 步骤信息\r\n */\r\n step: (message: string) => {\r\n console.log(chalk.cyan(symbols.arrowRight) + ' ' + chalk.gray(message))\r\n },\r\n\r\n /**\r\n * 标题\r\n */\r\n title: (message: string) => {\r\n console.log('\\n' + chalk.bold.underline(message) + '\\n')\r\n },\r\n\r\n /**\r\n * 普通文本(无图标)\r\n */\r\n log: (message: string) => {\r\n console.log(message)\r\n }\r\n}\r\n\r\n/**\r\n * 自定义 CLI 错误类\r\n */\r\nexport class CLIError extends Error {\r\n constructor(\r\n message: string,\r\n public code?: string,\r\n public suggestions?: string[]\r\n ) {\r\n super(message)\r\n this.name = 'CLIError'\r\n }\r\n}\r\n\r\n/**\r\n * 错误处理函数\r\n */\r\nexport async function handleError(error: unknown): Promise<void> {\r\n console.error()\r\n\r\n if (error instanceof CLIError) {\r\n logger.error(error.message)\r\n\r\n if (error.code) {\r\n const errorCodeText = await t('error.errorCode')\r\n console.log(chalk.gray(`${errorCodeText} ${error.code}`))\r\n }\r\n\r\n if (error.suggestions?.length) {\r\n const suggestionsText = await t('error.suggestions')\r\n console.log(chalk.yellow.bold(`\\n${suggestionsText}\\n`))\r\n error.suggestions.forEach((suggestion, index) => {\r\n console.log(chalk.gray(` ${index + 1}. ${suggestion}`))\r\n })\r\n }\r\n } else if (error instanceof Error) {\r\n logger.error(error.message)\r\n\r\n if (process.env.DEBUG) {\r\n console.log(chalk.gray('\\n' + error.stack))\r\n }\r\n } else {\r\n logger.error(await t('error.unknownError'))\r\n }\r\n\r\n const needHelpText = await t('error.needHelp')\r\n console.log(\r\n chalk.gray(`\\n${needHelpText} `) +\r\n chalk.blue.underline('https://github.com/AIConfigPlaza/acp-cli')\r\n )\r\n console.log()\r\n}\r\n","import fs from 'fs-extra'\r\nimport path from 'path'\r\nimport os from 'os'\r\n\r\n/**\r\n * 语言配置管理\r\n * 支持的语言: zh-CN (中文), en-US (英文)\r\n */\r\n\r\nexport type Locale = 'zh-CN' | 'en-US'\r\n\r\nconst LOCALE_ENV_KEY = 'ACP_CLI_LOCALE'\r\nconst DEFAULT_LOCALE: Locale = 'zh-CN'\r\n\r\nconst CONFIG_DIR = path.join(os.homedir(), '.acp')\r\nconst LOCALE_FILE = path.join(CONFIG_DIR, 'locale')\r\n\r\n/**\r\n * 读取当前语言配置\r\n */\r\nexport async function getLocale(): Promise<Locale> {\r\n // 1. 优先读取环境变量\r\n const envLocale = process.env[LOCALE_ENV_KEY]\r\n if (envLocale && isValidLocale(envLocale)) {\r\n return envLocale as Locale\r\n }\r\n\r\n // 2. 读取本地配置文件\r\n try {\r\n if (await fs.pathExists(LOCALE_FILE)) {\r\n const locale = (await fs.readFile(LOCALE_FILE, 'utf-8')).trim()\r\n if (isValidLocale(locale)) {\r\n return locale as Locale\r\n }\r\n }\r\n } catch (error) {\r\n // 读取失败使用默认值\r\n }\r\n\r\n // 3. 返回默认语言\r\n return DEFAULT_LOCALE\r\n}\r\n\r\n/**\r\n * 保存语言配置到本地文件\r\n */\r\nexport async function saveLocale(locale: Locale): Promise<void> {\r\n if (!isValidLocale(locale)) {\r\n throw new Error(`不支持的语言: ${locale}`)\r\n }\r\n\r\n // 确保配置目录存在\r\n await fs.ensureDir(CONFIG_DIR)\r\n\r\n // 保存语言配置\r\n await fs.writeFile(LOCALE_FILE, locale, 'utf-8')\r\n}\r\n\r\n/**\r\n * 验证语言代码是否有效\r\n */\r\nfunction isValidLocale(locale: string): boolean {\r\n return locale === 'zh-CN' || locale === 'en-US'\r\n}\r\n\r\n/**\r\n * 获取所有支持的语言列表\r\n */\r\nexport function getSupportedLocales(): Locale[] {\r\n return ['zh-CN', 'en-US']\r\n}\r\n\r\n/**\r\n * 获取语言显示名称\r\n */\r\nexport function getLocaleName(locale: Locale): string {\r\n const names: Record<Locale, string> = {\r\n 'zh-CN': '简体中文',\r\n 'en-US': 'English'\r\n }\r\n return names[locale]\r\n}\r\n","/**\r\n * 中文语言包\r\n */\r\n\r\nexport const zhCN = {\r\n // 通用\r\n common: {\r\n confirm: '确认',\r\n cancel: '取消',\r\n yes: '是',\r\n no: '否',\r\n success: '成功',\r\n failed: '失败',\r\n error: '错误',\r\n warning: '警告',\r\n info: '提示'\r\n },\r\n\r\n // CLI 主程序\r\n cli: {\r\n name: 'acp',\r\n description: 'AI-Config-Plaza CLI - 统一 AI 编程工具配置管理',\r\n version: '显示版本号',\r\n help: '显示帮助信息',\r\n exampleTitle: '示例:'\r\n },\r\n\r\n // login 命令\r\n login: {\r\n command: 'login',\r\n description: '登录 ACP CLI,保存访问令牌',\r\n title: '🔐 ACP CLI 登录',\r\n alreadyLoggedIn: '检测到已登录,是否重新登录?',\r\n cancelled: '已取消登录',\r\n inputToken: '请输入 CLI Token:',\r\n tokenEmpty: 'Token 不能为空',\r\n tokenInvalid: 'Token 格式不正确(至少 10 个字符)',\r\n success: '登录成功!Token 已保存到 ~/.acp/token',\r\n hint: '提示: 现在可以使用 acp apply 命令拉取配置',\r\n failed: '登录失败'\r\n },\r\n\r\n // apply 命令\r\n apply: {\r\n command: 'apply',\r\n description: '拉取并应用配置到本地项目',\r\n title: '🚀 ACP 配置应用',\r\n optionType: '资源类型 (solution|agent|prompt|mcp)',\r\n optionIde: 'AI IDE 类型 (vscode|cursor|codex|claude-code)',\r\n optionDir: '目标目录',\r\n notLoggedIn: '未登录,请先执行 acp login',\r\n loginFirst: '运行 acp login 命令登录',\r\n selectResourceType: '请选择资源类型:',\r\n resourceTypes: {\r\n solution: '解决方案 (Solution)',\r\n agent: 'Agent 配置 (暂不支持)',\r\n prompt: 'Prompt (暂不支持)',\r\n mcp: 'MCP 配置 (暂不支持)'\r\n },\r\n notSupported: '暂不支持独立应用 agent/prompt/mcp,请使用 solution 类型',\r\n noSelection: '未选择任何配置',\r\n selectIde: '请选择 AI IDE 类型:',\r\n applied: '配置已应用到:',\r\n searchPlaceholder: '搜索解决方案(输入名称或描述)',\r\n noResults: '没有找到解决方案',\r\n loadingMore: '加载更多...',\r\n noMore: '没有更多了',\r\n selected: '已选择',\r\n selectSolution: '请选择一个解决方案:',\r\n fetching: '正在获取解决方案列表...',\r\n fetchSuccess: '获取到 {count} 个解决方案',\r\n noSolutions: '暂无可用的解决方案',\r\n searchPrompt: '搜索解决方案 (按名称搜索,留空显示全部):',\r\n noMatch: '未找到匹配的解决方案',\r\n selectSolutionPage: '选择解决方案 (第 {current}/{total} 页):',\r\n nextPage: '>>> 下一页',\r\n prevPage: '<<< 上一页',\r\n cancel: '取消',\r\n fetchingDetail: '正在获取解决方案详情...',\r\n fetchDetailFailed: '获取解决方案失败',\r\n ideTypes: {\r\n vscode: 'VS Code',\r\n cursor: 'Cursor',\r\n codex: 'Codex',\r\n claudeCode: 'Claude Code',\r\n codeBuddy: 'CodeBuddy',\r\n qoder: 'Qoder'\r\n }\r\n },\r\n\r\n // locale 命令\r\n locale: {\r\n command: 'locale',\r\n description: '切换 CLI 语言',\r\n title: '🌐 语言设置',\r\n current: '当前语言',\r\n selectLanguage: '请选择语言:',\r\n success: '语言已切换为',\r\n failed: '语言切换失败',\r\n restartHint: '提示: 已生效,新命令将使用所选语言'\r\n },\r\n\r\n // update 命令\r\n update: {\r\n command: 'update',\r\n description: '更新 ACP CLI 到最新版本',\r\n title: '⬆️ CLI 自更新',\r\n currentVersion: '当前版本',\r\n latestVersion: '最新版本',\r\n alreadyLatest: '已是最新版本,无需更新',\r\n checkingLatest: '正在检查最新版本...',\r\n fetchFailed: '获取最新版本失败',\r\n selectTarget: '请选择更新目标:',\r\n targets: {\r\n global: '全局 (推荐)',\r\n local: '本地项目'\r\n },\r\n noPkgManager: '未检测到可用的包管理器 (pnpm/npm/yarn)',\r\n selectPkgManager: '请选择包管理器:',\r\n executing: '正在使用 {manager} 执行更新...',\r\n success: '更新成功!',\r\n failed: '更新失败',\r\n verifyHint: '提示: 运行 acp -v 查看当前版本'\r\n },\r\n\r\n // 错误处理\r\n error: {\r\n errorCode: '错误代码:',\r\n suggestions: '💡 建议:',\r\n needHelp: '需要帮助? 访问:',\r\n unknownError: '未知错误'\r\n }\r\n}\r\n","/**\r\n * English Language Pack\r\n */\r\n\r\nexport const enUS = {\r\n // Common\r\n common: {\r\n confirm: 'Confirm',\r\n cancel: 'Cancel',\r\n yes: 'Yes',\r\n no: 'No',\r\n success: 'Success',\r\n failed: 'Failed',\r\n error: 'Error',\r\n warning: 'Warning',\r\n info: 'Info'\r\n },\r\n\r\n // CLI Main\r\n cli: {\r\n name: 'acp',\r\n description: 'AI-Config-Plaza CLI - Unified AI Programming Tool Configuration Management',\r\n version: 'Show version number',\r\n help: 'Show help information',\r\n exampleTitle: 'Examples:'\r\n },\r\n\r\n // login command\r\n login: {\r\n command: 'login',\r\n description: 'Login to ACP CLI and save access token',\r\n title: '🔐 ACP CLI Login',\r\n alreadyLoggedIn: 'Already logged in. Do you want to login again?',\r\n cancelled: 'Login cancelled',\r\n inputToken: 'Please enter CLI Token:',\r\n tokenEmpty: 'Token cannot be empty',\r\n tokenInvalid: 'Invalid token format (at least 10 characters)',\r\n success: 'Login successful! Token saved to ~/.acp/token',\r\n hint: 'Tip: You can now use acp apply command to fetch configurations',\r\n failed: 'Login failed'\r\n },\r\n\r\n // apply command\r\n apply: {\r\n command: 'apply',\r\n description: 'Fetch and apply configurations to local project',\r\n title: '🚀 ACP Configuration Apply',\r\n optionType: 'Resource type (solution|agent|prompt|mcp)',\r\n optionIde: 'AI IDE type (vscode|cursor|codex|claude-code)',\r\n optionDir: 'Target directory',\r\n notLoggedIn: 'Not logged in. Please run acp login first',\r\n loginFirst: 'Run acp login command to login',\r\n selectResourceType: 'Please select resource type:',\r\n resourceTypes: {\r\n solution: 'Solution',\r\n agent: 'Agent Configuration (Not supported yet)',\r\n prompt: 'Prompt (Not supported yet)',\r\n mcp: 'MCP Configuration (Not supported yet)'\r\n },\r\n notSupported: 'Standalone application of agent/prompt/mcp is not supported yet. Please use solution type',\r\n noSelection: 'No configuration selected',\r\n selectIde: 'Please select AI IDE type:',\r\n applied: 'Configuration applied to:',\r\n searchPlaceholder: 'Search solutions (enter name or description)',\r\n noResults: 'No solutions found',\r\n loadingMore: 'Loading more...',\r\n noMore: 'No more items',\r\n selected: 'Selected',\r\n selectSolution: 'Please select a solution:',\r\n fetching: 'Fetching solution list...',\r\n fetchSuccess: 'Fetched {count} solutions',\r\n noSolutions: 'No solutions available',\r\n searchPrompt: 'Search solutions (search by name, leave empty to show all):',\r\n noMatch: 'No matching solutions found',\r\n selectSolutionPage: 'Select solution (Page {current}/{total}):',\r\n nextPage: '>>> Next Page',\r\n prevPage: '<<< Previous Page',\r\n cancel: 'Cancel',\r\n fetchingDetail: 'Fetching solution details...',\r\n fetchDetailFailed: 'Failed to fetch solutions',\r\n ideTypes: {\r\n vscode: 'VS Code',\r\n cursor: 'Cursor',\r\n codex: 'Codex',\r\n claudeCode: 'Claude Code',\r\n codeBuddy: 'CodeBuddy',\r\n qoder: 'Qoder'\r\n }\r\n },\r\n\r\n // locale command\r\n locale: {\r\n command: 'locale',\r\n description: 'Switch CLI language',\r\n title: '🌐 Language Settings',\r\n current: 'Current Language',\r\n selectLanguage: 'Please select language:',\r\n success: 'Language switched to',\r\n failed: 'Failed to switch language',\r\n restartHint: 'Tip: Changes take effect immediately for new commands'\r\n },\r\n\r\n // update command\r\n update: {\r\n command: 'update',\r\n description: 'Update ACP CLI to latest version',\r\n title: '⬆️ CLI Self Update',\r\n currentVersion: 'Current Version',\r\n latestVersion: 'Latest Version',\r\n alreadyLatest: 'Already up to date',\r\n checkingLatest: 'Checking latest version...',\r\n fetchFailed: 'Failed to fetch latest version',\r\n selectTarget: 'Select update target:',\r\n targets: {\r\n global: 'Global (Recommended)',\r\n local: 'Local Project'\r\n },\r\n noPkgManager: 'No available package manager detected (pnpm/npm/yarn)',\r\n selectPkgManager: 'Select a package manager:',\r\n executing: 'Executing update with {manager}...',\r\n success: 'Update successful!',\r\n failed: 'Update failed',\r\n verifyHint: 'Tip: Run acp -v to verify current version'\r\n },\r\n\r\n // Error handling\r\n error: {\r\n errorCode: 'Error Code:',\r\n suggestions: '💡 Suggestions:',\r\n needHelp: 'Need help? Visit:',\r\n unknownError: 'Unknown error'\r\n }\r\n}\r\n","import { getLocale, type Locale } from '../config/locale.js'\r\nimport { zhCN } from './zh-CN.js'\r\nimport { enUS } from './en-US.js'\r\n\r\n/**\r\n * 国际化工具 - 提供多语言支持\r\n */\r\n\r\n// 语言包映射\r\nconst messages: Record<Locale, typeof zhCN> = {\r\n 'zh-CN': zhCN,\r\n 'en-US': enUS\r\n}\r\n\r\n// 当前语言缓存\r\nlet currentLocale: Locale | null = null\r\nlet currentMessages: typeof zhCN | null = null\r\n\r\n/**\r\n * 初始化 i18n\r\n */\r\nasync function initI18n(): Promise<void> {\r\n if (!currentLocale) {\r\n currentLocale = await getLocale()\r\n currentMessages = messages[currentLocale]\r\n }\r\n}\r\n\r\n/**\r\n * 翻译函数 - 根据键路径获取翻译文本\r\n * @param key - 翻译键,支持点分隔的路径,如 'login.title'\r\n * @param params - 替换参数对象\r\n * @returns 翻译后的文本\r\n */\r\nexport async function t(key: string, params?: Record<string, string | number>): Promise<string> {\r\n await initI18n()\r\n\r\n // 通过点分隔的路径获取嵌套值\r\n const keys = key.split('.')\r\n let value: any = currentMessages\r\n\r\n for (const k of keys) {\r\n if (value && typeof value === 'object' && k in value) {\r\n value = value[k]\r\n } else {\r\n // 如果找不到翻译,返回 key 本身\r\n return key\r\n }\r\n }\r\n\r\n // 如果不是字符串,返回 key\r\n if (typeof value !== 'string') {\r\n return key\r\n }\r\n\r\n // 替换参数\r\n if (params) {\r\n return value.replace(/\\{(\\w+)\\}/g, (match, paramKey) => {\r\n return paramKey in params ? String(params[paramKey]) : match\r\n })\r\n }\r\n\r\n return value\r\n}\r\n\r\n/**\r\n * 同步翻译函数(需要先初始化)\r\n * @param key - 翻译键\r\n * @param params - 替换参数对象\r\n * @returns 翻译后的文本\r\n */\r\nexport function tSync(key: string, params?: Record<string, string | number>): string {\r\n if (!currentMessages) {\r\n // 如果未初始化,返回 key\r\n return key\r\n }\r\n\r\n const keys = key.split('.')\r\n let value: any = currentMessages\r\n\r\n for (const k of keys) {\r\n if (value && typeof value === 'object' && k in value) {\r\n value = value[k]\r\n } else {\r\n return key\r\n }\r\n }\r\n\r\n if (typeof value !== 'string') {\r\n return key\r\n }\r\n\r\n if (params) {\r\n return value.replace(/\\{(\\w+)\\}/g, (match, paramKey) => {\r\n return paramKey in params ? String(params[paramKey]) : match\r\n })\r\n }\r\n\r\n return value\r\n}\r\n\r\n/**\r\n * 获取当前语言\r\n */\r\nexport async function getCurrentLocale(): Promise<Locale> {\r\n await initI18n()\r\n return currentLocale!\r\n}\r\n\r\n/**\r\n * 重新加载语言配置(切换语言后调用)\r\n */\r\nexport async function reloadLocale(): Promise<void> {\r\n currentLocale = null\r\n currentMessages = null\r\n await initI18n()\r\n}\r\n\r\n/**\r\n * 获取完整的语言包(用于类型提示)\r\n */\r\nexport function getMessages() {\r\n return currentMessages || zhCN\r\n}\r\n","import { Command } from 'commander'\r\nimport inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport ora from 'ora'\r\nimport { apiClient } from '../api/client.js'\r\nimport { logger, CLIError } from '../utils/logger.js'\r\nimport { isLoggedIn } from '../config/token.js'\r\nimport { type AiIdeType } from '../utils/ide-mapper.js'\r\nimport { searchByName, paginate } from '../utils/pagination.js'\r\nimport { applySolution } from '../apply/writer.js'\r\nimport type { Solution } from '../types/index.js'\r\nimport { t } from '../i18n/index.js'\r\n\r\n/**\r\n * acp apply 命令\r\n * 拉取并应用配置到本地项目\r\n */\r\n\r\ntype ResourceType = 'solution' | 'agent' | 'prompt' | 'mcp'\r\n\r\nexport const applyCommand = new Command('apply')\r\n .description('拉取并应用配置到本地项目 / Fetch and apply configurations to local project')\r\n .option('-t, --type <type>', '资源类型 (solution|agent|prompt|mcp) / Resource type', 'solution')\r\n .option('-i, --ide <ide>', 'AI IDE 类型 / AI IDE type (vscode|cursor|codex|claude-code|codebuddy|qoder)')\r\n .option('-d, --dir <path>', '目标目录 / Target directory', process.cwd())\r\n .action(async (options) => {\r\n try {\r\n // 检查登录状态\r\n if (!(await isLoggedIn())) {\r\n throw new CLIError(\r\n await t('apply.notLoggedIn'),\r\n 'NOT_LOGGED_IN',\r\n [await t('apply.loginFirst')]\r\n )\r\n }\r\n\r\n logger.title(await t('apply.title'))\r\n\r\n // 1. 选择资源类型\r\n const resourceType = await selectResourceType(options.type)\r\n\r\n // 2. 根据类型拉取并选择资源\r\n let selectedSolution: Solution | null = null\r\n\r\n if (resourceType === 'solution') {\r\n selectedSolution = await fetchAndSelectSolution()\r\n } else {\r\n throw new CLIError(await t('apply.notSupported'))\r\n }\r\n\r\n if (!selectedSolution) {\r\n logger.info(await t('apply.noSelection'))\r\n return\r\n }\r\n\r\n // 3. 选择 IDE 类型\r\n const ide = options.ide || (await selectIde())\r\n\r\n // 4. 应用配置\r\n await applySolution(selectedSolution, {\r\n ide: ide as AiIdeType,\r\n targetDir: options.dir\r\n })\r\n\r\n const appliedMsg = await t('apply.applied')\r\n console.log(chalk.gray(`\\n${appliedMsg} ${chalk.cyan(options.dir)}\\n`))\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error(error.message)\r\n }\r\n process.exit(1)\r\n }\r\n })\r\n\r\n/**\r\n * 选择资源类型\r\n */\r\nasync function selectResourceType(defaultType?: string): Promise<ResourceType> {\r\n if (defaultType && ['solution', 'agent', 'prompt', 'mcp'].includes(defaultType)) {\r\n return defaultType as ResourceType\r\n }\r\n\r\n const { type } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'type',\r\n message: await t('apply.selectResourceType'),\r\n choices: [\r\n { name: chalk.cyan(await t('apply.resourceTypes.solution')), value: 'solution' },\r\n { name: chalk.gray(await t('apply.resourceTypes.agent')), value: 'agent', disabled: true },\r\n { name: chalk.gray(await t('apply.resourceTypes.prompt')), value: 'prompt', disabled: true },\r\n { name: chalk.gray(await t('apply.resourceTypes.mcp')), value: 'mcp', disabled: true }\r\n ],\r\n default: 'solution'\r\n }\r\n ])\r\n\r\n return type\r\n}\r\n\r\n/**\r\n * 拉取并选择解决方案\r\n */\r\nasync function fetchAndSelectSolution(): Promise<Solution | null> {\r\n const spinner = ora(await t('apply.fetching')).start()\r\n\r\n try {\r\n // 1. 拉取解决方案列表\r\n const response = await apiClient.getSolutions()\r\n spinner.stop()\r\n\r\n if (!response.data || response.data.length === 0) {\r\n logger.warning(await t('apply.noSolutions'))\r\n return null\r\n }\r\n\r\n logger.success(await t('apply.fetchSuccess', { count: response.data.length }))\r\n\r\n // 2. 搜索过滤\r\n const { searchQuery } = await inquirer.prompt([\r\n {\r\n type: 'input',\r\n name: 'searchQuery',\r\n message: await t('apply.searchPrompt'),\r\n default: ''\r\n }\r\n ])\r\n\r\n let filteredSolutions = searchByName(response.data, searchQuery)\r\n\r\n if (filteredSolutions.length === 0) {\r\n logger.warning(await t('apply.noMatch'))\r\n return null\r\n }\r\n\r\n // 3. 分页显示\r\n const PAGE_SIZE = 20\r\n let currentPage = 1\r\n let selectedSolution: Solution | null = null\r\n\r\n while (!selectedSolution) {\r\n const paginatedResult = paginate(filteredSolutions, {\r\n page: currentPage,\r\n pageSize: PAGE_SIZE\r\n })\r\n\r\n // 构建选择列表\r\n const choices = paginatedResult.items.map((solution) => ({\r\n name: `${chalk.cyan(solution.name)} ${chalk.yellow(`@${solution.author.username}`)} - ${chalk.gray(solution.description)}`,\r\n value: solution.id,\r\n short: solution.name\r\n }))\r\n\r\n // 添加分页控制选项\r\n if (paginatedResult.hasNext) {\r\n choices.push({\r\n name: chalk.yellow(await t('apply.nextPage')),\r\n value: '__NEXT_PAGE__',\r\n short: await t('apply.nextPage')\r\n })\r\n }\r\n\r\n if (paginatedResult.hasPrev) {\r\n choices.unshift({\r\n name: chalk.yellow(await t('apply.prevPage')),\r\n value: '__PREV_PAGE__',\r\n short: await t('apply.prevPage')\r\n })\r\n }\r\n\r\n choices.push({\r\n name: chalk.red(await t('apply.cancel')),\r\n value: '__CANCEL__',\r\n short: await t('apply.cancel')\r\n })\r\n\r\n const { selected } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'selected',\r\n message: await t('apply.selectSolutionPage', { \r\n current: currentPage, \r\n total: paginatedResult.totalPages \r\n }),\r\n choices,\r\n pageSize: 15\r\n }\r\n ])\r\n\r\n if (selected === '__CANCEL__') {\r\n return null\r\n } else if (selected === '__NEXT_PAGE__') {\r\n currentPage++\r\n } else if (selected === '__PREV_PAGE__') {\r\n currentPage--\r\n } else {\r\n // 获取详情\r\n const detailSpinner = ora(await t('apply.fetchingDetail')).start()\r\n const detailResponse = await apiClient.getSolutionById(selected)\r\n detailSpinner.stop()\r\n\r\n selectedSolution = detailResponse.data\r\n }\r\n }\r\n\r\n return selectedSolution\r\n } catch (error) {\r\n spinner.fail(await t('apply.fetchDetailFailed'))\r\n throw error\r\n }\r\n}\r\n\r\n/**\r\n * 选择 IDE 类型\r\n */\r\nasync function selectIde(): Promise<AiIdeType> {\r\n const { ide } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'ide',\r\n message: await t('apply.selectIde'),\r\n choices: [\r\n { name: chalk.cyan(await t('apply.ideTypes.vscode')), value: 'vscode' },\r\n { name: chalk.cyan(await t('apply.ideTypes.cursor')), value: 'cursor' },\r\n { name: chalk.cyan(await t('apply.ideTypes.codex')), value: 'codex' },\r\n { name: chalk.cyan(await t('apply.ideTypes.claudeCode')), value: 'claude-code' },\r\n { name: chalk.cyan(await t('apply.ideTypes.codeBuddy')), value: 'codebuddy' },\r\n { name: chalk.cyan(await t('apply.ideTypes.qoder')), value: 'qoder' }\r\n ],\r\n default: 'vscode'\r\n }\r\n ])\r\n\r\n return ide\r\n}\r\n","import axios, { AxiosInstance, AxiosError } from 'axios'\r\nimport { getToken, getBaseUrl } from '../config/token.js'\r\nimport type {\r\n ApiResponse,\r\n Solution,\r\n AgentConfig,\r\n Prompt,\r\n McpConfig\r\n} from '../types/index.js'\r\n\r\n/**\r\n * API 客户端封装\r\n */\r\n\r\nclass ApiClient {\r\n private client: AxiosInstance\r\n private baseUrlPromise: Promise<string>\r\n\r\n constructor() {\r\n // 异步获取 BASE_URL\r\n this.baseUrlPromise = getBaseUrl()\r\n\r\n this.client = axios.create({\r\n timeout: 30000,\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n })\r\n\r\n // 请求拦截器:自动添加 token 和 baseURL\r\n this.client.interceptors.request.use(async (config) => {\r\n // 设置 baseURL\r\n if (!config.baseURL) {\r\n config.baseURL = await this.baseUrlPromise\r\n }\r\n\r\n // 添加 token\r\n const token = await getToken()\r\n if (token) {\r\n config.headers['X-CLI-TOKEN'] = token\r\n }\r\n return config\r\n })\r\n\r\n // 响应拦截器:统一错误处理\r\n this.client.interceptors.response.use(\r\n (response) => response,\r\n (error: AxiosError) => {\r\n if (error.response) {\r\n const status = error.response.status\r\n const message = (error.response.data as any)?.message || error.message\r\n\r\n if (status === 401) {\r\n throw new Error('认证失败,请先执行 acp login 登录')\r\n } else if (status === 403) {\r\n throw new Error('权限不足,请检查 token 是否有效')\r\n } else if (status === 404) {\r\n throw new Error('请求的资源不存在')\r\n } else if (status >= 500) {\r\n throw new Error(`服务器错误 (${status}): ${message}`)\r\n } else {\r\n throw new Error(`请求失败 (${status}): ${message}`)\r\n }\r\n } else if (error.request) {\r\n throw new Error('网络错误,请检查网络连接')\r\n } else {\r\n throw new Error(`请求配置错误: ${error.message}`)\r\n }\r\n }\r\n )\r\n }\r\n\r\n /**\r\n * 获取解决方案列表\r\n */\r\n async getSolutions(aiTool?: string): Promise<ApiResponse<Solution[]>> {\r\n const params = aiTool ? { aiTool } : {}\r\n const response = await this.client.get<ApiResponse<Solution[]>>(\r\n '/api/cli/solutions',\r\n { params }\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取解决方案详情\r\n */\r\n async getSolutionById(id: string): Promise<ApiResponse<Solution>> {\r\n const response = await this.client.get<ApiResponse<Solution>>(\r\n `/api/cli/solutions/${id}`\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 Agent 配置列表\r\n */\r\n async getAgents(): Promise<ApiResponse<AgentConfig[]>> {\r\n const response = await this.client.get<ApiResponse<AgentConfig[]>>(\r\n '/api/cli/agents'\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 Agent 配置详情\r\n */\r\n async getAgentById(id: string): Promise<ApiResponse<AgentConfig>> {\r\n const response = await this.client.get<ApiResponse<AgentConfig>>(\r\n `/api/cli/agents/${id}`\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 Prompt 列表\r\n */\r\n async getPrompts(): Promise<ApiResponse<Prompt[]>> {\r\n const response = await this.client.get<ApiResponse<Prompt[]>>(\r\n '/api/cli/prompts'\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 Prompt 详情\r\n */\r\n async getPromptById(id: string): Promise<ApiResponse<Prompt>> {\r\n const response = await this.client.get<ApiResponse<Prompt>>(\r\n `/api/cli/prompts/${id}`\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 MCP 配置列表\r\n */\r\n async getMcps(): Promise<ApiResponse<McpConfig[]>> {\r\n const response = await this.client.get<ApiResponse<McpConfig[]>>(\r\n '/api/cli/mcps'\r\n )\r\n return response.data\r\n }\r\n\r\n /**\r\n * 获取 MCP 配置详情\r\n */\r\n async getMcpById(id: string): Promise<ApiResponse<McpConfig>> {\r\n const response = await this.client.get<ApiResponse<McpConfig>>(\r\n `/api/cli/mcps/${id}`\r\n )\r\n return response.data\r\n }\r\n}\r\n\r\n// 导出单例\r\nexport const apiClient = new ApiClient()\r\n","/**\r\n * 分页工具函数\r\n */\r\n\r\nexport interface PaginationOptions {\r\n page: number\r\n pageSize: number\r\n}\r\n\r\nexport interface PaginationResult<T> {\r\n items: T[]\r\n total: number\r\n page: number\r\n pageSize: number\r\n totalPages: number\r\n hasNext: boolean\r\n hasPrev: boolean\r\n}\r\n\r\n/**\r\n * 对数组进行分页\r\n */\r\nexport function paginate<T>(\r\n items: T[],\r\n options: PaginationOptions\r\n): PaginationResult<T> {\r\n const { page, pageSize } = options\r\n const total = items.length\r\n const totalPages = Math.ceil(total / pageSize)\r\n const startIndex = (page - 1) * pageSize\r\n const endIndex = startIndex + pageSize\r\n\r\n return {\r\n items: items.slice(startIndex, endIndex),\r\n total,\r\n page,\r\n pageSize,\r\n totalPages,\r\n hasNext: page < totalPages,\r\n hasPrev: page > 1\r\n }\r\n}\r\n\r\n/**\r\n * 按名称搜索(不区分大小写)\r\n */\r\nexport function searchByName<T extends { name: string }>(\r\n items: T[],\r\n query: string\r\n): T[] {\r\n if (!query.trim()) {\r\n return items\r\n }\r\n\r\n const lowerQuery = query.toLowerCase().trim()\r\n return items.filter((item) =>\r\n item.name.toLowerCase().includes(lowerQuery)\r\n )\r\n}\r\n","import fs from 'fs-extra'\r\nimport path from 'path'\r\nimport chalk from 'chalk'\r\nimport inquirer from 'inquirer'\r\nimport { logger } from '../utils/logger.js'\r\nimport { getIdePathMapping, type AiIdeType } from '../utils/ide-mapper.js'\r\nimport type { Solution, Prompt, McpConfig, Skill } from '../types/index.js'\r\n\r\n/**\r\n * 配置应用模块 - 将远程配置写入本地文件\r\n */\r\n\r\nexport interface ApplyOptions {\r\n ide: AiIdeType\r\n targetDir: string\r\n}\r\n\r\n/**\r\n * 应用解决方案配置\r\n */\r\nexport async function applySolution(\r\n solution: Solution,\r\n options: ApplyOptions\r\n): Promise<void> {\r\n const { ide, targetDir } = options\r\n const pathMapping = getIdePathMapping(ide)\r\n\r\n logger.title(`📦 应用解决方案: ${chalk.cyan(solution.name)}`)\r\n\r\n // 1. 应用 Agent 配置\r\n if (solution.agentConfig) {\r\n await applyAgentConfig(\r\n solution.agentConfig.content,\r\n pathMapping.agents,\r\n targetDir\r\n )\r\n }\r\n\r\n // 2. 应用 Prompts\r\n if (solution.customPrompts?.length) {\r\n await applyPrompts(\r\n solution.customPrompts,\r\n pathMapping.prompts,\r\n targetDir\r\n )\r\n }\r\n\r\n // 3. 应用 MCP 配置\r\n if (solution.mcpConfigs?.length) {\r\n await applyMcpConfigs(\r\n solution.mcpConfigs,\r\n pathMapping.mcp,\r\n targetDir\r\n )\r\n }\r\n\r\n // 4. 应用 Skills\r\n if (solution.skills?.length) {\r\n await applySkills(\r\n solution.skills,\r\n pathMapping.skills,\r\n targetDir\r\n )\r\n }\r\n\r\n logger.success(`\\n✨ 解决方案 ${chalk.cyan(solution.name)} 应用成功!`)\r\n}\r\n\r\n/**\r\n * 应用 Agent 配置\r\n */\r\nexport async function applyAgentConfig(\r\n content: string,\r\n relativePath: string,\r\n targetDir: string\r\n): Promise<void> {\r\n // 如果 relativePath 是绝对路径,直接使用;否则拼接 targetDir\r\n const filePath = path.isAbsolute(relativePath) \r\n ? relativePath \r\n : path.join(targetDir, relativePath)\r\n\r\n logger.step(`写入 Agent 配置: ${chalk.gray(relativePath)}`)\r\n\r\n // 检查文件是否存在\r\n const exists = await fs.pathExists(filePath)\r\n if (exists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `文件 ${chalk.cyan(relativePath)} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${relativePath}`)\r\n return\r\n }\r\n }\r\n\r\n // 写入文件\r\n await fs.ensureDir(path.dirname(filePath))\r\n await fs.writeFile(filePath, content, 'utf-8')\r\n\r\n logger.success(`已写入: ${relativePath}`)\r\n}\r\n\r\n/**\r\n * 应用 Prompts\r\n */\r\nexport async function applyPrompts(\r\n prompts: Prompt[],\r\n promptsDir: string,\r\n targetDir: string\r\n): Promise<void> {\r\n // 如果 promptsDir 是绝对路径,直接使用;否则拼接 targetDir\r\n const fullPromptsDir = path.isAbsolute(promptsDir) \r\n ? promptsDir \r\n : path.join(targetDir, promptsDir)\r\n\r\n logger.step(`写入 ${prompts.length} 个 Prompt 配置到: ${chalk.gray(promptsDir)}`)\r\n\r\n // 确保目录存在\r\n await fs.ensureDir(fullPromptsDir)\r\n\r\n for (const prompt of prompts) {\r\n // 生成文件名(清理特殊字符)\r\n const fileName = sanitizeFileName(prompt.name) + '.prompt.md'\r\n const filePath = path.join(fullPromptsDir, fileName)\r\n\r\n // 检查是否存在\r\n const exists = await fs.pathExists(filePath)\r\n if (exists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `Prompt ${chalk.cyan(fileName)} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${fileName}`)\r\n continue\r\n }\r\n }\r\n\r\n // 写入内容\r\n await fs.writeFile(filePath, prompt.content, 'utf-8')\r\n logger.success(`已写入: ${path.join(promptsDir, fileName)}`)\r\n }\r\n}\r\n\r\n/**\r\n * 应用 MCP 配置\r\n */\r\nexport async function applyMcpConfigs(\r\n mcpConfigs: McpConfig[],\r\n mcpFile: string,\r\n targetDir: string\r\n): Promise<void> {\r\n // 检查是否为 CodeBuddy IDE(不支持 MCP 配置)\r\n if (!mcpFile || mcpFile === '') {\r\n logger.warning('暂不支持 CodeBuddy 的 MCP 配置写入')\r\n return\r\n }\r\n\r\n // 如果 mcpFile 是绝对路径,直接使用;否则拼接 targetDir\r\n const filePath = path.isAbsolute(mcpFile) \r\n ? mcpFile \r\n : path.join(targetDir, mcpFile)\r\n\r\n logger.step(`写入 MCP 配置: ${chalk.gray(mcpFile)}`)\r\n\r\n // 构造 mcpServers 结构\r\n const mcpServers: Record<string, any> = {}\r\n\r\n for (const mcpConfig of mcpConfigs) {\r\n try {\r\n const config = JSON.parse(mcpConfig.configJson)\r\n // 使用 MCP 配置的名称作为 key\r\n mcpServers[mcpConfig.name] = config\r\n } catch (error) {\r\n logger.warning(`MCP 配置 ${mcpConfig.name} 格式错误,已跳过`)\r\n }\r\n }\r\n\r\n // 检查文件是否存在\r\n const exists = await fs.pathExists(filePath)\r\n if (exists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `文件 ${chalk.cyan(mcpFile)} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${mcpFile}`)\r\n return\r\n }\r\n }\r\n\r\n // 写入文件\r\n await fs.ensureDir(path.dirname(filePath))\r\n\r\n // 根据文件扩展名和路径决定输出格式\r\n if (mcpFile.endsWith('.toml')) {\r\n // Codex 使用 TOML 格式\r\n const tomlContent = convertMcpToToml(mcpServers)\r\n await fs.writeFile(filePath, tomlContent, 'utf-8')\r\n } else {\r\n // JSON 格式\r\n let mergedConfig: Record<string, any>\r\n \r\n // VS Code 使用 \"servers\",其他 IDE 使用 \"mcpServers\"\r\n if (mcpFile.includes('.vscode')) {\r\n mergedConfig = {\r\n servers: mcpServers\r\n }\r\n } else {\r\n mergedConfig = {\r\n mcpServers\r\n }\r\n }\r\n \r\n await fs.writeFile(filePath, JSON.stringify(mergedConfig, null, 2), 'utf-8')\r\n }\r\n\r\n logger.success(`已写入: ${mcpFile}`)\r\n}\r\n\r\n/**\r\n * 将 MCP 配置转换为 TOML 格式(用于 Codex)\r\n */\r\nfunction convertMcpToToml(mcpServers: Record<string, any>): string {\r\n let tomlContent = ''\r\n\r\n for (const [serverName, config] of Object.entries(mcpServers)) {\r\n tomlContent += `[mcp_servers.${serverName}]\\n`\r\n \r\n // 写入 command\r\n if (config.command) {\r\n tomlContent += `command = ${JSON.stringify(config.command)}\\n`\r\n }\r\n\r\n // 写入 args\r\n if (config.args && Array.isArray(config.args)) {\r\n const argsStr = config.args.map((arg: string) => JSON.stringify(arg)).join(', ')\r\n tomlContent += `args = [${argsStr}]\\n`\r\n }\r\n\r\n // 写入 env\r\n if (config.env && typeof config.env === 'object') {\r\n const envEntries = Object.entries(config.env)\r\n if (envEntries.length > 0) {\r\n const envStr = envEntries\r\n .map(([key, value]) => `${key} = ${JSON.stringify(value)}`)\r\n .join(', ')\r\n tomlContent += `env = { ${envStr} }\\n`\r\n }\r\n }\r\n\r\n tomlContent += '\\n'\r\n }\r\n\r\n return tomlContent\r\n}\r\n\r\n/**\r\n * 应用 Skills\r\n */\r\nexport async function applySkills(\r\n skills: Skill[],\r\n skillsDir: string,\r\n targetDir: string\r\n): Promise<void> {\r\n // 如果 skillsDir 是绝对路径,直接使用;否则拼接 targetDir\r\n const fullSkillsDir = path.isAbsolute(skillsDir) \r\n ? skillsDir \r\n : path.join(targetDir, skillsDir)\r\n\r\n logger.step(`写入 ${skills.length} 个 Skill 配置到: ${chalk.gray(skillsDir)}`)\r\n\r\n // 确保目录存在\r\n await fs.ensureDir(fullSkillsDir)\r\n\r\n for (const skill of skills) {\r\n // 生成目录名(清理特殊字符)\r\n const skillDirName = sanitizeSkillName(skill.name)\r\n const skillDirPath = path.join(fullSkillsDir, skillDirName)\r\n\r\n logger.step(`处理 Skill: ${chalk.cyan(skill.name)}`)\r\n\r\n // 检查目录是否存在\r\n const dirExists = await fs.pathExists(skillDirPath)\r\n if (dirExists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `Skill 目录 ${chalk.cyan(skillDirName)} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${skillDirName}`)\r\n continue\r\n }\r\n }\r\n\r\n // 确保目录存在\r\n await fs.ensureDir(skillDirPath)\r\n\r\n // 1. 创建 SKILL.md 文件\r\n const skillMdPath = path.join(skillDirPath, 'SKILL.md')\r\n await fs.writeFile(skillMdPath, skill.skillMarkdown, 'utf-8')\r\n logger.success(`已写入: ${path.join(skillsDir, skillDirName, 'SKILL.md')}`)\r\n\r\n // 2. 处理 SkillResources\r\n if (skill.skillResources && skill.skillResources.length > 0) {\r\n for (const resource of skill.skillResources) {\r\n // 确保相对路径安全(防止路径遍历攻击)\r\n const safeRelativePath = sanitizePath(resource.relativePath)\r\n const resourceFilePath = path.join(skillDirPath, safeRelativePath, resource.fileName)\r\n\r\n // 检查文件是否存在\r\n const fileExists = await fs.pathExists(resourceFilePath)\r\n if (fileExists) {\r\n const { overwrite } = await inquirer.prompt([\r\n {\r\n type: 'confirm',\r\n name: 'overwrite',\r\n message: `文件 ${chalk.cyan(path.join(skillDirName, safeRelativePath))} 已存在,是否覆盖?`,\r\n default: true\r\n }\r\n ])\r\n\r\n if (!overwrite) {\r\n logger.warning(`跳过: ${path.join(skillDirName, safeRelativePath)}`)\r\n continue\r\n }\r\n }\r\n\r\n // 确保父目录存在\r\n await fs.ensureDir(path.dirname(resourceFilePath))\r\n\r\n // 写入文件内容\r\n await fs.writeFile(resourceFilePath, resource.fileContent, 'utf-8')\r\n logger.success(`已写入: ${path.join(skillsDir, skillDirName, safeRelativePath)}`)\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 清理 skill 名称,用于创建目录名\r\n */\r\nfunction sanitizeSkillName(name: string): string {\r\n return name\r\n .replace(/[<>:\"/\\\\|?*]/g, '-') // 替换非法字符\r\n .replace(/\\s+/g, '-') // 空格转连字符\r\n .replace(/-+/g, '-') // 多个连字符合并\r\n .replace(/^-+|-+$/g, '') // 移除首尾连字符\r\n .toLowerCase()\r\n}\r\n\r\n/**\r\n * 清理路径,防止路径遍历攻击\r\n */\r\nfunction sanitizePath(relativePath: string): string {\r\n // 移除路径遍历攻击(如 ../, ..\\, 等)\r\n let safePath = relativePath\r\n .replace(/\\.\\./g, '') // 移除 ..\r\n .replace(/^[/\\\\]+/, '') // 移除开头的 / 或 \\\r\n .replace(/[/\\\\]+/g, path.sep) // 统一路径分隔符\r\n\r\n // 确保路径是相对路径,不包含绝对路径\r\n if (path.isAbsolute(safePath)) {\r\n safePath = path.relative('/', safePath)\r\n }\r\n\r\n // 移除 Windows 驱动器号(如 C:)\r\n if (safePath.match(/^[A-Za-z]:/)) {\r\n safePath = safePath.substring(2)\r\n }\r\n\r\n return safePath\r\n}\r\n\r\n/**\r\n * 清理文件名中的特殊字符\r\n */\r\nfunction sanitizeFileName(name: string): string {\r\n return name\r\n .replace(/[<>:\"/\\\\|?*]/g, '-') // 替换非法字符\r\n .replace(/\\s+/g, '-') // 空格转连字符\r\n .replace(/-+/g, '-') // 多个连字符合并\r\n .toLowerCase()\r\n}\r\n","import { homedir } from 'os'\r\nimport type { AiIdeType, IdePathMapping } from '../types/index.js'\r\n\r\n// 重新导出类型\r\nexport type { AiIdeType, IdePathMapping }\r\n\r\n/**\r\n * AI IDE 路径映射配置\r\n * 定义不同 IDE 的配置文件输出路径\r\n */\r\n\r\nexport const IDE_PATH_MAPPINGS: Record<AiIdeType, IdePathMapping> = {\r\n vscode: {\r\n prompts: '.github/prompts',\r\n agents: 'AGENTS.md',\r\n mcp: '.vscode/mcp.json',\r\n skills: '.github/skills'\r\n },\r\n cursor: {\r\n prompts: '.cursor/commands',\r\n agents: 'AGENTS.md',\r\n mcp: '.cursor/mcp.json',\r\n skills: '.cursor/skills'\r\n },\r\n codex: {\r\n prompts: '~/.codex/prompts',\r\n agents: 'AGENTS.md',\r\n mcp: '.codex/config.toml',\r\n skills: '.codex/skills'\r\n },\r\n 'claude-code': {\r\n prompts: '.claude/commands',\r\n agents: 'AGENTS.md',\r\n mcp: '.mcp.json',\r\n skills: '.claude/skills'\r\n },\r\n codebuddy: {\r\n prompts: '.codebuddy/commands',\r\n agents: 'AGENTS.md',\r\n mcp: '.mcp.json',\r\n skills: '.codebuddy/skills'\r\n },\r\n qoder: {\r\n prompts: '.qoder/commands',\r\n agents: 'AGENTS.md',\r\n mcp: '.mcp.json',\r\n skills: 'qoder/skills'\r\n }\r\n}\r\n\r\n/**\r\n * 展开路径中的 ~ 为用户主目录\r\n */\r\nfunction expandPath(path: string): string {\r\n if (path.startsWith('~')) {\r\n return path.replace('~', homedir())\r\n }\r\n return path\r\n}\r\n\r\n/**\r\n * 获取 IDE 路径映射\r\n */\r\nexport function getIdePathMapping(ide: AiIdeType): IdePathMapping {\r\n const mapping = IDE_PATH_MAPPINGS[ide]\r\n return {\r\n prompts: expandPath(mapping.prompts),\r\n agents: expandPath(mapping.agents),\r\n mcp: expandPath(mapping.mcp),\r\n skills: expandPath(mapping.skills)\r\n }\r\n}\r\n\r\n/**\r\n * 获取所有支持的 IDE 列表\r\n */\r\nexport function getSupportedIdes(): AiIdeType[] {\r\n return Object.keys(IDE_PATH_MAPPINGS) as AiIdeType[]\r\n}\r\n\r\n/**\r\n * 验证 IDE 类型是否支持\r\n */\r\nexport function isValidIde(ide: string): ide is AiIdeType {\r\n return ide in IDE_PATH_MAPPINGS\r\n}\r\n","import { Command } from 'commander'\r\nimport inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport { getLocale, saveLocale, getSupportedLocales, getLocaleName, type Locale } from '../config/locale.js'\r\nimport { t } from '../i18n/index.js'\r\nimport { logger } from '../utils/logger.js'\r\n\r\n/**\r\n * acp locale 命令\r\n * 切换 CLI 语言\r\n */\r\n\r\nexport const localeCommand = new Command('locale')\r\n .description('切换 CLI 语言 / Switch CLI language')\r\n .action(async () => {\r\n try {\r\n // 获取当前语言\r\n const currentLocale = await getLocale()\r\n \r\n // 显示标题\r\n const title = await t('locale.title')\r\n logger.title(title)\r\n\r\n // 显示当前语言\r\n const currentText = await t('locale.current')\r\n console.log(chalk.gray(`${currentText}: `) + chalk.cyan(getLocaleName(currentLocale)))\r\n console.log()\r\n\r\n // 选择新语言\r\n const supportedLocales = getSupportedLocales()\r\n const selectText = await t('locale.selectLanguage')\r\n \r\n const { newLocale } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'newLocale',\r\n message: selectText,\r\n choices: supportedLocales.map(locale => ({\r\n name: locale === currentLocale \r\n ? chalk.cyan(`${getLocaleName(locale)} (当前 / Current)`)\r\n : getLocaleName(locale),\r\n value: locale\r\n })),\r\n default: currentLocale\r\n }\r\n ])\r\n\r\n // 如果选择的是当前语言,则不做任何操作\r\n if (newLocale === currentLocale) {\r\n logger.info(`${await t('locale.current')}: ${getLocaleName(currentLocale)}`)\r\n return\r\n }\r\n\r\n // 保存新语言\r\n await saveLocale(newLocale as Locale)\r\n\r\n // 显示成功消息(使用新语言)\r\n // 注意:这里需要手动构造消息,因为 t() 函数还在使用旧语言缓存\r\n if (newLocale === 'zh-CN') {\r\n logger.success(`语言已切换为 ${getLocaleName(newLocale)}`)\r\n console.log(chalk.gray('\\n提示: 已生效,新命令将使用所选语言\\n'))\r\n } else {\r\n logger.success(`Language switched to ${getLocaleName(newLocale)}`)\r\n console.log(chalk.gray('\\nTip: Changes take effect immediately for new commands\\n'))\r\n }\r\n\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error(`${await t('locale.failed')}: ${error.message}`)\r\n }\r\n process.exit(1)\r\n }\r\n })\r\n","import { Command } from 'commander'\r\nimport inquirer from 'inquirer'\r\nimport chalk from 'chalk'\r\nimport ora from 'ora'\r\nimport axios from 'axios'\r\nimport { spawnSync } from 'child_process'\r\nimport { logger, CLIError } from '../utils/logger.js'\r\nimport { t } from '../i18n/index.js'\r\n\r\n/**\r\n * acp update 命令\r\n * 检查并更新 ACP CLI 到最新版本\r\n */\r\n\r\n// 版本号在构建时注入\r\n// @ts-ignore - 构建时通过 tsup define 注入\r\nconst currentVersion = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0-dev'\r\nconst packageName = '@ai-config-plaza/acp-cli'\r\n\r\ntype UpdateTarget = 'global' | 'local'\r\n\r\nfunction getAvailablePkgManagers(): string[] {\r\n const managers = ['pnpm', 'npm', 'yarn']\r\n const available: string[] = []\r\n for (const m of managers) {\r\n const res = spawnSync(m, ['--version'], { stdio: 'pipe', shell: true })\r\n if (res.status === 0) available.push(m)\r\n }\r\n return available\r\n}\r\n\r\nfunction runUpdate(target: UpdateTarget, manager: string): number {\r\n const isGlobal = target === 'global'\r\n let args: string[] = []\r\n\r\n if (manager === 'pnpm') {\r\n args = isGlobal\r\n ? ['add', '-g', `${packageName}@latest`]\r\n : ['add', `${packageName}@latest`]\r\n } else if (manager === 'npm') {\r\n args = isGlobal\r\n ? ['install', '-g', `${packageName}@latest`]\r\n : ['install', `${packageName}@latest`, '--save']\r\n } else if (manager === 'yarn') {\r\n args = isGlobal\r\n ? ['global', 'add', `${packageName}@latest`]\r\n : ['add', `${packageName}@latest`]\r\n } else {\r\n return 1\r\n }\r\n\r\n const execSpinner = ora().start()\r\n execSpinner.text = manager + ' ' + args.join(' ')\r\n\r\n const res = spawnSync(manager, args, { stdio: 'inherit', shell: true })\r\n execSpinner.stop()\r\n return res.status ?? 1\r\n}\r\n\r\nexport const updateCommand = new Command('update')\r\n .description('更新 ACP CLI 到最新版本 / Update ACP CLI to latest version')\r\n .option('-t, --target <target>', '更新目标 (global|local) / Update target', 'global')\r\n .action(async (options) => {\r\n try {\r\n logger.title(await t('update.title'))\r\n\r\n // 显示当前版本\r\n logger.info(`${await t('update.currentVersion')}: ${chalk.cyan(currentVersion)}`)\r\n\r\n // 查询 npm 最新版本\r\n const spinner = ora(await t('update.checkingLatest')).start()\r\n let latestVersion = ''\r\n try {\r\n const resp = await axios.get(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`)\r\n latestVersion = resp.data?.version || ''\r\n } catch (e) {\r\n spinner.fail(await t('update.fetchFailed'))\r\n throw new CLIError(await t('update.fetchFailed'), 'FETCH_LATEST_FAILED')\r\n }\r\n\r\n spinner.stop()\r\n if (!latestVersion) {\r\n throw new CLIError(await t('update.fetchFailed'), 'LATEST_EMPTY')\r\n }\r\n\r\n logger.info(`${await t('update.latestVersion')}: ${chalk.cyan(latestVersion)}`)\r\n\r\n if (currentVersion === latestVersion) {\r\n logger.success(await t('update.alreadyLatest'))\r\n return\r\n }\r\n\r\n // 选择更新目标\r\n const target: UpdateTarget = ['global', 'local'].includes(options.target)\r\n ? options.target\r\n : (await (async () => {\r\n const { targetSel } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'targetSel',\r\n message: await t('update.selectTarget'),\r\n choices: [\r\n { name: await t('update.targets.global'), value: 'global' },\r\n { name: await t('update.targets.local'), value: 'local' }\r\n ],\r\n default: 'global'\r\n }\r\n ])\r\n return targetSel as UpdateTarget\r\n })())\r\n\r\n // 检测包管理器\r\n const managers = getAvailablePkgManagers()\r\n if (managers.length === 0) {\r\n throw new CLIError(await t('update.noPkgManager'), 'NO_PKG_MANAGER', [\r\n '安装 pnpm 或 npm 后重试',\r\n 'https://pnpm.io/installation'\r\n ])\r\n }\r\n\r\n let manager = managers[0]\r\n if (managers.length > 1) {\r\n const { pm } = await inquirer.prompt([\r\n {\r\n type: 'list',\r\n name: 'pm',\r\n message: await t('update.selectPkgManager'),\r\n choices: managers.map(m => ({ name: m, value: m })),\r\n default: manager\r\n }\r\n ])\r\n manager = pm\r\n }\r\n\r\n logger.step(await t('update.executing', { manager }))\r\n const code = runUpdate(target, manager)\r\n if (code === 0) {\r\n logger.success(await t('update.success'))\r\n logger.info(await t('update.verifyHint'))\r\n } else {\r\n throw new CLIError(await t('update.failed'), 'UPDATE_FAILED')\r\n }\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n logger.error(error.message)\r\n }\r\n process.exit(1)\r\n }\r\n })\r\n"],"mappings":"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","names":["Command","chalk","chalk","fs","path","os","CONFIG_DIR","chalk","Command","inquirer","chalk","fs","path","chalk","inquirer","path","chalk","path","fs","inquirer","Command","chalk","inquirer","Command","inquirer","chalk","Command","currentLocale","chalk","inquirer","Command","inquirer","chalk","ora","axios","ora","Command","chalk","axios","inquirer","Command","chalk"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-config-plaza/acp-cli",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "AI-Config-Plaza CLI 工具 - 统一 AI 编程工具配置管理",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",