@ai-config-plaza/acp-cli 1.0.10 → 1.0.12
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 +287 -287
- package/bin/acp.js +13 -13
- package/dist/index.js +37 -7
- package/dist/index.js.map +1 -1
- package/package.json +69 -69
package/README.md
CHANGED
|
@@ -1,287 +1,287 @@
|
|
|
1
|
-
# ACP CLI
|
|
2
|
-
|
|
3
|
-
**AI-Config-Plaza CLI** - 统一 AI 编程工具配置管理工具
|
|
4
|
-
|
|
5
|
-
## 📖 简介
|
|
6
|
-
|
|
7
|
-
ACP CLI 是一个专为简化 AI 编程工具配置而设计的命令行工具。通过统一的配置标准,帮助开发者快速初始化和配置 AI 工具(如 VS Code、Cursor、Codex、Claude Code、CodeBuddy、Qoder 等)。
|
|
8
|
-
|
|
9
|
-
### 核心特性
|
|
10
|
-
|
|
11
|
-
- 🔐 **统一认证**:通过 CLI Token 统一管理 API 访问权限
|
|
12
|
-
- 📦 **一键应用**:快速拉取并应用配置到本地项目
|
|
13
|
-
- 🔍 **智能搜索**:支持按名称搜索和分页浏览配置
|
|
14
|
-
- 🎨 **多 IDE 支持**:自动适配不同 AI IDE 的配置路径
|
|
15
|
-
- 🌐 **多语言支持**:支持中文和英文界面切换
|
|
16
|
-
- ✨ **友好交互**:清晰的终端提示和进度反馈
|
|
17
|
-
|
|
18
|
-
## 🚀 快速开始
|
|
19
|
-
|
|
20
|
-
### 安装
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
# 使用 npm
|
|
24
|
-
npm install -g @ai-config-plaza/acp-cli
|
|
25
|
-
|
|
26
|
-
# 使用 pnpm
|
|
27
|
-
pnpm add -g @ai-config-plaza/acp-cli
|
|
28
|
-
|
|
29
|
-
│ │ ├── locale.ts # 语言切换命令
|
|
30
|
-
│ │ └── update.ts # 自更新命令
|
|
31
|
-
yarn global add @ai-config-plaza/acp-cli
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### 本地开发
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# 克隆仓库
|
|
38
|
-
git clone https://github.com/AIConfigPlaza/acp.git
|
|
39
|
-
cd acp/cli
|
|
40
|
-
|
|
41
|
-
# 安装依赖
|
|
42
|
-
pnpm install
|
|
43
|
-
|
|
44
|
-
# 本地构建
|
|
45
|
-
pnpm build
|
|
46
|
-
|
|
47
|
-
# 链接到全局(用于本地测试)
|
|
48
|
-
npm link
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## 📋 使用指南
|
|
52
|
-
|
|
53
|
-
### 1. 登录
|
|
54
|
-
|
|
55
|
-
首次使用需要登录并保存 CLI Token:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
acp login
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
系统会提示输入 CLI Token,Token 将保存在用户主目录 `~/.acp/token` 中。
|
|
62
|
-
|
|
63
|
-
### 2. 应用配置
|
|
64
|
-
|
|
65
|
-
拉取并应用配置到本地项目:
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
# 在当前目录应用配置
|
|
69
|
-
|
|
70
|
-
### `acp update`
|
|
71
|
-
|
|
72
|
-
更新 ACP CLI 到最新版本。
|
|
73
|
-
|
|
74
|
-
**选项**:
|
|
75
|
-
- `-t, --target <target>`:更新目标(`global` 全局,`local` 本地项目;默认 `global`)
|
|
76
|
-
|
|
77
|
-
**示例**:
|
|
78
|
-
```bash
|
|
79
|
-
# 全局更新(推荐)
|
|
80
|
-
acp update
|
|
81
|
-
|
|
82
|
-
# 指定本地更新
|
|
83
|
-
acp update --target local
|
|
84
|
-
```
|
|
85
|
-
# 指定 IDE 类型
|
|
86
|
-
acp apply --ide vscode
|
|
87
|
-
|
|
88
|
-
# 指定目标目录
|
|
89
|
-
acp apply --dir ./my-project
|
|
90
|
-
|
|
91
|
-
# 完整示例
|
|
92
|
-
acp apply --ide cursor --dir ~/projects/my-app
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### 3. 交互流程
|
|
96
|
-
|
|
97
|
-
执行 `acp apply` 后,CLI 会引导你完成以下步骤:
|
|
98
|
-
|
|
99
|
-
1. **选择资源类型**:目前支持 Solution(解决方案)
|
|
100
|
-
2. **搜索配置**:输入关键词搜索,或留空显示全部
|
|
101
|
-
3. **分页浏览**:每页显示 20 条记录,支持上下翻页
|
|
102
|
-
4. **选择配置**:从列表中选择需要的配置
|
|
103
|
-
5. **选择 IDE**:选择目标 AI IDE 类型
|
|
104
|
-
6. **确认覆盖**:如果文件已存在,会提示是否覆盖
|
|
105
|
-
|
|
106
|
-
### 4. 切换语言
|
|
107
|
-
|
|
108
|
-
ACP CLI 支持中文和英文界面:
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
# 打开语言设置
|
|
112
|
-
acp locale
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
或通过环境变量临时设置:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
# Windows PowerShell
|
|
119
|
-
$env:ACP_CLI_LOCALE = "en-US"
|
|
120
|
-
acp apply
|
|
121
|
-
|
|
122
|
-
# Linux/macOS
|
|
123
|
-
export ACP_CLI_LOCALE=en-US
|
|
124
|
-
acp apply
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
支持的语言代码:
|
|
128
|
-
- `zh-CN`:简体中文(默认)
|
|
129
|
-
- `en-US`:English
|
|
130
|
-
|
|
131
|
-
详细文档:[多语言支持文档](docs/i18n.md)
|
|
132
|
-
|
|
133
|
-
## 📁 配置输出路径
|
|
134
|
-
|
|
135
|
-
不同 AI IDE 的配置文件输出路径:
|
|
136
|
-
|
|
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/` |
|
|
145
|
-
|
|
146
|
-
### 文件格式
|
|
147
|
-
|
|
148
|
-
- **Prompts**:输出为 `*.prompt.md` 格式的 Markdown 文件
|
|
149
|
-
- **Agents**:输出为项目根目录的 `AGENTS.md` 文件
|
|
150
|
-
- **MCP 配置**:
|
|
151
|
-
- VS Code: JSON 格式(`servers` 结构)在 `.vscode/mcp.json`
|
|
152
|
-
- Cursor/Claude Code: JSON 格式(`mcpServers` 结构)
|
|
153
|
-
- Codex: TOML 格式(`[mcp_servers.xxx]` 结构)在 `.codex/config.toml`
|
|
154
|
-
|
|
155
|
-
## 🔧 命令参考
|
|
156
|
-
|
|
157
|
-
### `acp login`
|
|
158
|
-
|
|
159
|
-
登录并保存 CLI Token。
|
|
160
|
-
|
|
161
|
-
**示例**:
|
|
162
|
-
```bash
|
|
163
|
-
acp login
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### `acp apply`
|
|
167
|
-
|
|
168
|
-
拉取并应用配置到本地项目。
|
|
169
|
-
|
|
170
|
-
**选项**:
|
|
171
|
-
- `-t, --type <type>`:资源类型(目前仅支持 `solution`)
|
|
172
|
-
- `-i, --ide <ide>`:AI IDE 类型(`vscode`|`cursor`|`codex`|`claude-code`|`codebuddy`|`qoder`)
|
|
173
|
-
- `-d, --dir <path>`:目标目录(默认为当前目录)
|
|
174
|
-
|
|
175
|
-
**示例**:
|
|
176
|
-
```bash
|
|
177
|
-
# 基本用法
|
|
178
|
-
acp apply
|
|
179
|
-
|
|
180
|
-
# 指定 IDE
|
|
181
|
-
acp apply --ide cursor
|
|
182
|
-
|
|
183
|
-
# 指定目录
|
|
184
|
-
acp apply --dir ~/my-project
|
|
185
|
-
|
|
186
|
-
# 完整命令
|
|
187
|
-
acp apply --type solution --ide vscode --dir ./project
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### `acp locale`
|
|
191
|
-
|
|
192
|
-
切换 CLI 界面语言。
|
|
193
|
-
|
|
194
|
-
**示例**:
|
|
195
|
-
```bash
|
|
196
|
-
# 打开语言选择菜单
|
|
197
|
-
acp locale
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
**支持的语言**:
|
|
201
|
-
- `zh-CN`:简体中文
|
|
202
|
-
- `en-US`:English
|
|
203
|
-
|
|
204
|
-
## 🛠️ 开发
|
|
205
|
-
|
|
206
|
-
### 项目结构
|
|
207
|
-
|
|
208
|
-
```
|
|
209
|
-
acp/cli/
|
|
210
|
-
├── bin/ # 可执行文件入口
|
|
211
|
-
│ └── acp.js
|
|
212
|
-
├── src/
|
|
213
|
-
│ ├── commands/ # 命令实现
|
|
214
|
-
│ │ ├── login.ts # 登录命令
|
|
215
|
-
│ │ ├── apply.ts # 应用配置命令
|
|
216
|
-
│ │ └── locale.ts # 语言切换命令
|
|
217
|
-
│ ├── api/ # API 客户端
|
|
218
|
-
│ │ └── client.ts
|
|
219
|
-
│ ├── config/ # 配置管理
|
|
220
|
-
│ │ ├── token.ts # Token 存储
|
|
221
|
-
│ │ └── locale.ts # 语言配置
|
|
222
|
-
│ ├── i18n/ # 国际化
|
|
223
|
-
│ │ ├── index.ts # i18n 工具函数
|
|
224
|
-
│ │ ├── zh-CN.ts # 中文语言包
|
|
225
|
-
│ │ └── en-US.ts # 英文语言包
|
|
226
|
-
│ ├── apply/ # 配置应用
|
|
227
|
-
│ │ └── writer.ts # 文件写入逻辑
|
|
228
|
-
│ ├── utils/ # 工具函数
|
|
229
|
-
│ │ ├── logger.ts # 日志工具
|
|
230
|
-
│ │ ├── ide-mapper.ts # IDE 路径映射
|
|
231
|
-
│ │ └── pagination.ts # 分页工具
|
|
232
|
-
│ ├── types/ # 类型定义
|
|
233
|
-
│ │ └── index.ts
|
|
234
|
-
│ └── index.ts # 主入口
|
|
235
|
-
├── docs/ # 文档
|
|
236
|
-
│ └── i18n.md # 多语言支持文档
|
|
237
|
-
├── package.json
|
|
238
|
-
├── tsconfig.json
|
|
239
|
-
├── tsup.config.ts
|
|
240
|
-
└── README.md
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
### 技术栈
|
|
244
|
-
|
|
245
|
-
- **运行时**:Node.js 18+
|
|
246
|
-
- **语言**:TypeScript 5.x
|
|
247
|
-
- **命令解析**:Commander.js
|
|
248
|
-
- **交互提示**:Inquirer.js
|
|
249
|
-
- **HTTP 客户端**:Axios
|
|
250
|
-
- **终端样式**:Chalk
|
|
251
|
-
- **进度动画**:Ora
|
|
252
|
-
- **文件操作**:fs-extra
|
|
253
|
-
- **构建工具**:tsup
|
|
254
|
-
|
|
255
|
-
### 开发命令
|
|
256
|
-
|
|
257
|
-
```bash
|
|
258
|
-
# 安装依赖
|
|
259
|
-
pnpm install
|
|
260
|
-
|
|
261
|
-
# 开发模式(使用 tsx 直接运行)
|
|
262
|
-
pnpm dev
|
|
263
|
-
|
|
264
|
-
# 构建生产版本
|
|
265
|
-
pnpm build
|
|
266
|
-
|
|
267
|
-
# 类型检查
|
|
268
|
-
pnpm typecheck
|
|
269
|
-
|
|
270
|
-
# 运行测试
|
|
271
|
-
pnpm test
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
## 🌐 API 服务
|
|
275
|
-
|
|
276
|
-
ACP CLI 连接到 ACP 平台的后端 API 服务:
|
|
277
|
-
- **认证方式**:通过 `X-CLI-TOKEN` HTTP Header 携带 Token
|
|
278
|
-
|
|
279
|
-
## 🐛 问题反馈
|
|
280
|
-
|
|
281
|
-
遇到问题?请提交 Issue:
|
|
282
|
-
|
|
283
|
-
- GitHub Issues: https://github.com/AIConfigPlaza/acp/issues
|
|
284
|
-
-
|
|
285
|
-
---
|
|
286
|
-
|
|
287
|
-
**Made with ❤️ by AIConfigPlaza Team**
|
|
1
|
+
# ACP CLI
|
|
2
|
+
|
|
3
|
+
**AI-Config-Plaza CLI** - 统一 AI 编程工具配置管理工具
|
|
4
|
+
|
|
5
|
+
## 📖 简介
|
|
6
|
+
|
|
7
|
+
ACP CLI 是一个专为简化 AI 编程工具配置而设计的命令行工具。通过统一的配置标准,帮助开发者快速初始化和配置 AI 工具(如 VS Code、Cursor、Codex、Claude Code、CodeBuddy、Qoder 等)。
|
|
8
|
+
|
|
9
|
+
### 核心特性
|
|
10
|
+
|
|
11
|
+
- 🔐 **统一认证**:通过 CLI Token 统一管理 API 访问权限
|
|
12
|
+
- 📦 **一键应用**:快速拉取并应用配置到本地项目
|
|
13
|
+
- 🔍 **智能搜索**:支持按名称搜索和分页浏览配置
|
|
14
|
+
- 🎨 **多 IDE 支持**:自动适配不同 AI IDE 的配置路径
|
|
15
|
+
- 🌐 **多语言支持**:支持中文和英文界面切换
|
|
16
|
+
- ✨ **友好交互**:清晰的终端提示和进度反馈
|
|
17
|
+
|
|
18
|
+
## 🚀 快速开始
|
|
19
|
+
|
|
20
|
+
### 安装
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# 使用 npm
|
|
24
|
+
npm install -g @ai-config-plaza/acp-cli
|
|
25
|
+
|
|
26
|
+
# 使用 pnpm
|
|
27
|
+
pnpm add -g @ai-config-plaza/acp-cli
|
|
28
|
+
|
|
29
|
+
│ │ ├── locale.ts # 语言切换命令
|
|
30
|
+
│ │ └── update.ts # 自更新命令
|
|
31
|
+
yarn global add @ai-config-plaza/acp-cli
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 本地开发
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# 克隆仓库
|
|
38
|
+
git clone https://github.com/AIConfigPlaza/acp.git
|
|
39
|
+
cd acp/cli
|
|
40
|
+
|
|
41
|
+
# 安装依赖
|
|
42
|
+
pnpm install
|
|
43
|
+
|
|
44
|
+
# 本地构建
|
|
45
|
+
pnpm build
|
|
46
|
+
|
|
47
|
+
# 链接到全局(用于本地测试)
|
|
48
|
+
npm link
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 📋 使用指南
|
|
52
|
+
|
|
53
|
+
### 1. 登录
|
|
54
|
+
|
|
55
|
+
首次使用需要登录并保存 CLI Token:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
acp login
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
系统会提示输入 CLI Token,Token 将保存在用户主目录 `~/.acp/token` 中。
|
|
62
|
+
|
|
63
|
+
### 2. 应用配置
|
|
64
|
+
|
|
65
|
+
拉取并应用配置到本地项目:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# 在当前目录应用配置
|
|
69
|
+
|
|
70
|
+
### `acp update`
|
|
71
|
+
|
|
72
|
+
更新 ACP CLI 到最新版本。
|
|
73
|
+
|
|
74
|
+
**选项**:
|
|
75
|
+
- `-t, --target <target>`:更新目标(`global` 全局,`local` 本地项目;默认 `global`)
|
|
76
|
+
|
|
77
|
+
**示例**:
|
|
78
|
+
```bash
|
|
79
|
+
# 全局更新(推荐)
|
|
80
|
+
acp update
|
|
81
|
+
|
|
82
|
+
# 指定本地更新
|
|
83
|
+
acp update --target local
|
|
84
|
+
```
|
|
85
|
+
# 指定 IDE 类型
|
|
86
|
+
acp apply --ide vscode
|
|
87
|
+
|
|
88
|
+
# 指定目标目录
|
|
89
|
+
acp apply --dir ./my-project
|
|
90
|
+
|
|
91
|
+
# 完整示例
|
|
92
|
+
acp apply --ide cursor --dir ~/projects/my-app
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 3. 交互流程
|
|
96
|
+
|
|
97
|
+
执行 `acp apply` 后,CLI 会引导你完成以下步骤:
|
|
98
|
+
|
|
99
|
+
1. **选择资源类型**:目前支持 Solution(解决方案)
|
|
100
|
+
2. **搜索配置**:输入关键词搜索,或留空显示全部
|
|
101
|
+
3. **分页浏览**:每页显示 20 条记录,支持上下翻页
|
|
102
|
+
4. **选择配置**:从列表中选择需要的配置
|
|
103
|
+
5. **选择 IDE**:选择目标 AI IDE 类型
|
|
104
|
+
6. **确认覆盖**:如果文件已存在,会提示是否覆盖
|
|
105
|
+
|
|
106
|
+
### 4. 切换语言
|
|
107
|
+
|
|
108
|
+
ACP CLI 支持中文和英文界面:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# 打开语言设置
|
|
112
|
+
acp locale
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
或通过环境变量临时设置:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Windows PowerShell
|
|
119
|
+
$env:ACP_CLI_LOCALE = "en-US"
|
|
120
|
+
acp apply
|
|
121
|
+
|
|
122
|
+
# Linux/macOS
|
|
123
|
+
export ACP_CLI_LOCALE=en-US
|
|
124
|
+
acp apply
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
支持的语言代码:
|
|
128
|
+
- `zh-CN`:简体中文(默认)
|
|
129
|
+
- `en-US`:English
|
|
130
|
+
|
|
131
|
+
详细文档:[多语言支持文档](docs/i18n.md)
|
|
132
|
+
|
|
133
|
+
## 📁 配置输出路径
|
|
134
|
+
|
|
135
|
+
不同 AI IDE 的配置文件输出路径:
|
|
136
|
+
|
|
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/` |
|
|
145
|
+
|
|
146
|
+
### 文件格式
|
|
147
|
+
|
|
148
|
+
- **Prompts**:输出为 `*.prompt.md` 格式的 Markdown 文件
|
|
149
|
+
- **Agents**:输出为项目根目录的 `AGENTS.md` 文件
|
|
150
|
+
- **MCP 配置**:
|
|
151
|
+
- VS Code: JSON 格式(`servers` 结构)在 `.vscode/mcp.json`
|
|
152
|
+
- Cursor/Claude Code: JSON 格式(`mcpServers` 结构)
|
|
153
|
+
- Codex: TOML 格式(`[mcp_servers.xxx]` 结构)在 `.codex/config.toml`
|
|
154
|
+
|
|
155
|
+
## 🔧 命令参考
|
|
156
|
+
|
|
157
|
+
### `acp login`
|
|
158
|
+
|
|
159
|
+
登录并保存 CLI Token。
|
|
160
|
+
|
|
161
|
+
**示例**:
|
|
162
|
+
```bash
|
|
163
|
+
acp login
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### `acp apply`
|
|
167
|
+
|
|
168
|
+
拉取并应用配置到本地项目。
|
|
169
|
+
|
|
170
|
+
**选项**:
|
|
171
|
+
- `-t, --type <type>`:资源类型(目前仅支持 `solution`)
|
|
172
|
+
- `-i, --ide <ide>`:AI IDE 类型(`vscode`|`cursor`|`codex`|`claude-code`|`codebuddy`|`qoder`)
|
|
173
|
+
- `-d, --dir <path>`:目标目录(默认为当前目录)
|
|
174
|
+
|
|
175
|
+
**示例**:
|
|
176
|
+
```bash
|
|
177
|
+
# 基本用法
|
|
178
|
+
acp apply
|
|
179
|
+
|
|
180
|
+
# 指定 IDE
|
|
181
|
+
acp apply --ide cursor
|
|
182
|
+
|
|
183
|
+
# 指定目录
|
|
184
|
+
acp apply --dir ~/my-project
|
|
185
|
+
|
|
186
|
+
# 完整命令
|
|
187
|
+
acp apply --type solution --ide vscode --dir ./project
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### `acp locale`
|
|
191
|
+
|
|
192
|
+
切换 CLI 界面语言。
|
|
193
|
+
|
|
194
|
+
**示例**:
|
|
195
|
+
```bash
|
|
196
|
+
# 打开语言选择菜单
|
|
197
|
+
acp locale
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**支持的语言**:
|
|
201
|
+
- `zh-CN`:简体中文
|
|
202
|
+
- `en-US`:English
|
|
203
|
+
|
|
204
|
+
## 🛠️ 开发
|
|
205
|
+
|
|
206
|
+
### 项目结构
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
acp/cli/
|
|
210
|
+
├── bin/ # 可执行文件入口
|
|
211
|
+
│ └── acp.js
|
|
212
|
+
├── src/
|
|
213
|
+
│ ├── commands/ # 命令实现
|
|
214
|
+
│ │ ├── login.ts # 登录命令
|
|
215
|
+
│ │ ├── apply.ts # 应用配置命令
|
|
216
|
+
│ │ └── locale.ts # 语言切换命令
|
|
217
|
+
│ ├── api/ # API 客户端
|
|
218
|
+
│ │ └── client.ts
|
|
219
|
+
│ ├── config/ # 配置管理
|
|
220
|
+
│ │ ├── token.ts # Token 存储
|
|
221
|
+
│ │ └── locale.ts # 语言配置
|
|
222
|
+
│ ├── i18n/ # 国际化
|
|
223
|
+
│ │ ├── index.ts # i18n 工具函数
|
|
224
|
+
│ │ ├── zh-CN.ts # 中文语言包
|
|
225
|
+
│ │ └── en-US.ts # 英文语言包
|
|
226
|
+
│ ├── apply/ # 配置应用
|
|
227
|
+
│ │ └── writer.ts # 文件写入逻辑
|
|
228
|
+
│ ├── utils/ # 工具函数
|
|
229
|
+
│ │ ├── logger.ts # 日志工具
|
|
230
|
+
│ │ ├── ide-mapper.ts # IDE 路径映射
|
|
231
|
+
│ │ └── pagination.ts # 分页工具
|
|
232
|
+
│ ├── types/ # 类型定义
|
|
233
|
+
│ │ └── index.ts
|
|
234
|
+
│ └── index.ts # 主入口
|
|
235
|
+
├── docs/ # 文档
|
|
236
|
+
│ └── i18n.md # 多语言支持文档
|
|
237
|
+
├── package.json
|
|
238
|
+
├── tsconfig.json
|
|
239
|
+
├── tsup.config.ts
|
|
240
|
+
└── README.md
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 技术栈
|
|
244
|
+
|
|
245
|
+
- **运行时**:Node.js 18+
|
|
246
|
+
- **语言**:TypeScript 5.x
|
|
247
|
+
- **命令解析**:Commander.js
|
|
248
|
+
- **交互提示**:Inquirer.js
|
|
249
|
+
- **HTTP 客户端**:Axios
|
|
250
|
+
- **终端样式**:Chalk
|
|
251
|
+
- **进度动画**:Ora
|
|
252
|
+
- **文件操作**:fs-extra
|
|
253
|
+
- **构建工具**:tsup
|
|
254
|
+
|
|
255
|
+
### 开发命令
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# 安装依赖
|
|
259
|
+
pnpm install
|
|
260
|
+
|
|
261
|
+
# 开发模式(使用 tsx 直接运行)
|
|
262
|
+
pnpm dev
|
|
263
|
+
|
|
264
|
+
# 构建生产版本
|
|
265
|
+
pnpm build
|
|
266
|
+
|
|
267
|
+
# 类型检查
|
|
268
|
+
pnpm typecheck
|
|
269
|
+
|
|
270
|
+
# 运行测试
|
|
271
|
+
pnpm test
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## 🌐 API 服务
|
|
275
|
+
|
|
276
|
+
ACP CLI 连接到 ACP 平台的后端 API 服务:
|
|
277
|
+
- **认证方式**:通过 `X-CLI-TOKEN` HTTP Header 携带 Token
|
|
278
|
+
|
|
279
|
+
## 🐛 问题反馈
|
|
280
|
+
|
|
281
|
+
遇到问题?请提交 Issue:
|
|
282
|
+
|
|
283
|
+
- GitHub Issues: https://github.com/AIConfigPlaza/acp/issues
|
|
284
|
+
-
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
**Made with ❤️ by AIConfigPlaza Team**
|
package/bin/acp.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ACP CLI 入口文件
|
|
5
|
-
* 负责加载并执行主程序
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import('../dist/index.js').catch((error) => {
|
|
9
|
-
console.error('启动 ACP CLI 失败:', error.message)
|
|
10
|
-
console.error('')
|
|
11
|
-
console.error('请确保已执行构建命令: pnpm build')
|
|
12
|
-
process.exit(1)
|
|
13
|
-
})
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ACP CLI 入口文件
|
|
5
|
+
* 负责加载并执行主程序
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import('../dist/index.js').catch((error) => {
|
|
9
|
+
console.error('启动 ACP CLI 失败:', error.message)
|
|
10
|
+
console.error('')
|
|
11
|
+
console.error('请确保已执行构建命令: pnpm build')
|
|
12
|
+
process.exit(1)
|
|
13
|
+
})
|
package/dist/index.js
CHANGED
|
@@ -681,6 +681,15 @@ var ApiClient = class {
|
|
|
681
681
|
);
|
|
682
682
|
return response.data;
|
|
683
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* 下载二进制资源
|
|
686
|
+
*/
|
|
687
|
+
async downloadBinary(url) {
|
|
688
|
+
const response = await this.client.get(url, {
|
|
689
|
+
responseType: "arraybuffer"
|
|
690
|
+
});
|
|
691
|
+
return Buffer.from(response.data);
|
|
692
|
+
}
|
|
684
693
|
};
|
|
685
694
|
var apiClient = new ApiClient();
|
|
686
695
|
|
|
@@ -810,7 +819,7 @@ async function applySolution(solution, options) {
|
|
|
810
819
|
\u2728 \u89E3\u51B3\u65B9\u6848 ${chalk3.cyan(solution.name)} \u5E94\u7528\u6210\u529F\uFF01`);
|
|
811
820
|
}
|
|
812
821
|
async function applyAgentConfig(content, relativePath, targetDir) {
|
|
813
|
-
const filePath = path3.join(targetDir, relativePath);
|
|
822
|
+
const filePath = path3.isAbsolute(relativePath) ? relativePath : path3.join(targetDir, relativePath);
|
|
814
823
|
logger.step(`\u5199\u5165 Agent \u914D\u7F6E: ${chalk3.gray(relativePath)}`);
|
|
815
824
|
const exists = await fs3.pathExists(filePath);
|
|
816
825
|
if (exists) {
|
|
@@ -832,7 +841,7 @@ async function applyAgentConfig(content, relativePath, targetDir) {
|
|
|
832
841
|
logger.success(`\u5DF2\u5199\u5165: ${relativePath}`);
|
|
833
842
|
}
|
|
834
843
|
async function applyPrompts(prompts, promptsDir, targetDir) {
|
|
835
|
-
const fullPromptsDir = path3.join(targetDir, promptsDir);
|
|
844
|
+
const fullPromptsDir = path3.isAbsolute(promptsDir) ? promptsDir : path3.join(targetDir, promptsDir);
|
|
836
845
|
logger.step(`\u5199\u5165 ${prompts.length} \u4E2A Prompt \u914D\u7F6E\u5230: ${chalk3.gray(promptsDir)}`);
|
|
837
846
|
await fs3.ensureDir(fullPromptsDir);
|
|
838
847
|
for (const prompt of prompts) {
|
|
@@ -862,7 +871,7 @@ async function applyMcpConfigs(mcpConfigs, mcpFile, targetDir) {
|
|
|
862
871
|
logger.warning("\u6682\u4E0D\u652F\u6301 CodeBuddy \u7684 MCP \u914D\u7F6E\u5199\u5165");
|
|
863
872
|
return;
|
|
864
873
|
}
|
|
865
|
-
const filePath = path3.join(targetDir, mcpFile);
|
|
874
|
+
const filePath = path3.isAbsolute(mcpFile) ? mcpFile : path3.join(targetDir, mcpFile);
|
|
866
875
|
logger.step(`\u5199\u5165 MCP \u914D\u7F6E: ${chalk3.gray(mcpFile)}`);
|
|
867
876
|
const mcpServers = {};
|
|
868
877
|
for (const mcpConfig of mcpConfigs) {
|
|
@@ -934,7 +943,7 @@ function convertMcpToToml(mcpServers) {
|
|
|
934
943
|
return tomlContent;
|
|
935
944
|
}
|
|
936
945
|
async function applySkills(skills, skillsDir, targetDir) {
|
|
937
|
-
const fullSkillsDir = path3.join(targetDir, skillsDir);
|
|
946
|
+
const fullSkillsDir = path3.isAbsolute(skillsDir) ? skillsDir : path3.join(targetDir, skillsDir);
|
|
938
947
|
logger.step(`\u5199\u5165 ${skills.length} \u4E2A Skill \u914D\u7F6E\u5230: ${chalk3.gray(skillsDir)}`);
|
|
939
948
|
await fs3.ensureDir(fullSkillsDir);
|
|
940
949
|
for (const skill of skills) {
|
|
@@ -980,12 +989,33 @@ async function applySkills(skills, skillsDir, targetDir) {
|
|
|
980
989
|
}
|
|
981
990
|
}
|
|
982
991
|
await fs3.ensureDir(path3.dirname(resourceFilePath));
|
|
983
|
-
await
|
|
992
|
+
const resourceContent = await resolveSkillResourceContent(resource);
|
|
993
|
+
if (Buffer.isBuffer(resourceContent)) {
|
|
994
|
+
await fs3.writeFile(resourceFilePath, resourceContent);
|
|
995
|
+
} else {
|
|
996
|
+
await fs3.writeFile(resourceFilePath, resourceContent, "utf-8");
|
|
997
|
+
}
|
|
984
998
|
logger.success(`\u5DF2\u5199\u5165: ${path3.join(skillsDir, skillDirName, safeRelativePath)}`);
|
|
985
999
|
}
|
|
986
1000
|
}
|
|
987
1001
|
}
|
|
988
1002
|
}
|
|
1003
|
+
async function resolveSkillResourceContent(resource) {
|
|
1004
|
+
if (resource.isBinary) {
|
|
1005
|
+
if (!resource.downloadUrl) {
|
|
1006
|
+
throw new Error(`Skill \u8D44\u6E90 ${resource.fileName} \u7F3A\u5C11 downloadUrl\uFF0C\u65E0\u6CD5\u4E0B\u8F7D\u4E8C\u8FDB\u5236\u5185\u5BB9`);
|
|
1007
|
+
}
|
|
1008
|
+
return apiClient.downloadBinary(resource.downloadUrl);
|
|
1009
|
+
}
|
|
1010
|
+
if (typeof resource.fileContent === "string") {
|
|
1011
|
+
return resource.fileContent;
|
|
1012
|
+
}
|
|
1013
|
+
if (resource.downloadUrl) {
|
|
1014
|
+
const bytes = await apiClient.downloadBinary(resource.downloadUrl);
|
|
1015
|
+
return bytes.toString("utf-8");
|
|
1016
|
+
}
|
|
1017
|
+
throw new Error(`Skill \u8D44\u6E90 ${resource.fileName} \u7F3A\u5C11\u53EF\u5199\u5165\u5185\u5BB9`);
|
|
1018
|
+
}
|
|
989
1019
|
function sanitizeSkillName(name) {
|
|
990
1020
|
return name.replace(/[<>:"/\\|?*]/g, "-").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
991
1021
|
}
|
|
@@ -1220,7 +1250,7 @@ import chalk6 from "chalk";
|
|
|
1220
1250
|
import ora2 from "ora";
|
|
1221
1251
|
import axios2 from "axios";
|
|
1222
1252
|
import { spawnSync } from "child_process";
|
|
1223
|
-
var currentVersion = true ? "1.0.
|
|
1253
|
+
var currentVersion = true ? "1.0.12" : "0.0.0-dev";
|
|
1224
1254
|
var packageName = "@ai-config-plaza/acp-cli";
|
|
1225
1255
|
function getAvailablePkgManagers() {
|
|
1226
1256
|
const managers = ["pnpm", "npm", "yarn"];
|
|
@@ -1323,7 +1353,7 @@ var updateCommand = new Command4("update").description("\u66F4\u65B0 ACP CLI \u5
|
|
|
1323
1353
|
});
|
|
1324
1354
|
|
|
1325
1355
|
// src/index.ts
|
|
1326
|
-
var version = true ? "1.0.
|
|
1356
|
+
var version = true ? "1.0.12" : "0.0.0-dev";
|
|
1327
1357
|
async function main() {
|
|
1328
1358
|
const program = new Command5();
|
|
1329
1359
|
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 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 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\n\nimport { Command } from 'commander'\nimport chalk from 'chalk'\nimport { loginCommand } from './commands/login.js'\nimport { applyCommand } from './commands/apply.js'\nimport { localeCommand } from './commands/locale.js'\nimport { updateCommand } from './commands/update.js'\nimport { handleError } from './utils/logger.js'\nimport { t } from './i18n/index.js'\n\n/**\n * ACP CLI 主入口\n */\n\n// 版本号在构建时注入\n// @ts-ignore - 构建时通过 tsup define 注入\nconst version = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0-dev'\n\nasync function main() {\n const program = new Command()\n\n program\n .name('acp')\n .description(\n chalk.gray(await t('cli.description'))\n )\n .version(version, '-v, --version', await t('cli.version'))\n .helpOption('-h, --help', await t('cli.help'))\n\n // 注册命令\n program.addCommand(loginCommand)\n program.addCommand(applyCommand)\n program.addCommand(localeCommand)\n program.addCommand(updateCommand)\n\n // 自定义帮助显示\n program.on('--help', async () => {\n console.log(chalk.bold('\\n' + await t('cli.exampleTitle') + '\\n'))\n console.log(chalk.gray(' $ acp login'))\n console.log(chalk.gray(' $ acp apply'))\n console.log(chalk.gray(' $ acp apply --ide vscode --dir ./my-project'))\n console.log(chalk.gray(' $ acp locale'))\n console.log(chalk.gray(' $ acp update'))\n console.log()\n })\n\n // 解析命令\n try {\n await program.parseAsync(process.argv)\n } catch (error) {\n await handleError(error)\n process.exit(1)\n }\n}\n\nmain()\n","import { Command } from 'commander'\nimport inquirer from 'inquirer'\nimport chalk from 'chalk'\nimport { saveToken, getToken, initDefaultConfig } from '../config/token.js'\nimport { logger } from '../utils/logger.js'\nimport { t } from '../i18n/index.js'\n\n/**\n * acp login 命令\n * 提示用户输入 CLI Token 并保存\n */\n\nexport const loginCommand = new Command('login')\n .description('登录 ACP CLI,保存访问令牌 / Login to ACP CLI and save access token')\n .action(async () => {\n try {\n logger.title(await t('login.title'))\n\n // 初始化默认配置(首次使用时)\n await initDefaultConfig()\n\n // 检查是否已有 token\n const existingToken = await getToken()\n if (existingToken) {\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: await t('login.alreadyLoggedIn'),\n default: false\n }\n ])\n\n if (!overwrite) {\n logger.info(await t('login.cancelled'))\n return\n }\n }\n\n // 提示输入 token\n const { token } = await inquirer.prompt([\n {\n type: 'password',\n name: 'token',\n message: await t('login.inputToken'),\n validate: async (input: string) => {\n if (!input.trim()) {\n return await t('login.tokenEmpty')\n }\n if (input.trim().length < 10) {\n return await t('login.tokenInvalid')\n }\n return true\n },\n mask: '*'\n }\n ])\n\n // 保存 token\n await saveToken(token)\n\n logger.success(await t('login.success'))\n console.log(chalk.gray('\\n' + await t('login.hint') + '\\n'))\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`${await t('login.failed')}: ${error.message}`)\n }\n process.exit(1)\n }\n })\n","import fs from 'fs-extra'\nimport path from 'path'\nimport os from 'os'\n\n/**\n * Token 和 BASE_URL 配置管理\n * 优先级: 环境变量 > ~/.acp/ 配置文件\n */\n\nconst TOKEN_ENV_KEY = 'ACP_CLI_TOKEN'\nconst BASE_URL_ENV_KEY = 'ACP_CLI_BASE_URL'\nconst DEFAULT_BASE_URL = 'https://api.ai-config-plaza.com'\n\nconst CONFIG_DIR = path.join(os.homedir(), '.acp')\nconst TOKEN_FILE = path.join(CONFIG_DIR, 'token')\nconst BASE_URL_FILE = path.join(CONFIG_DIR, 'base-url')\n\n/**\n * 读取 CLI Token\n */\nexport async function getToken(): Promise<string | null> {\n // 1. 优先读取环境变量\n const envToken = process.env[TOKEN_ENV_KEY]\n if (envToken?.trim()) {\n return envToken.trim()\n }\n\n // 2. 读取本地配置文件\n try {\n if (await fs.pathExists(TOKEN_FILE)) {\n const token = await fs.readFile(TOKEN_FILE, 'utf-8')\n return token.trim() || null\n }\n } catch (error) {\n // 读取失败返回 null\n }\n\n return null\n}\n\n/**\n * 保存 CLI Token 到本地配置文件\n */\nexport async function saveToken(token: string): Promise<void> {\n if (!token?.trim()) {\n throw new Error('Token 不能为空')\n }\n\n // 确保配置目录存在\n await fs.ensureDir(CONFIG_DIR)\n\n // 写入 token 文件\n await fs.writeFile(TOKEN_FILE, token.trim(), 'utf-8')\n}\n\n/**\n * 删除本地 Token\n */\nexport async function removeToken(): Promise<void> {\n if (await fs.pathExists(TOKEN_FILE)) {\n await fs.remove(TOKEN_FILE)\n }\n}\n\n/**\n * 检查是否已登录\n */\nexport async function isLoggedIn(): Promise<boolean> {\n const token = await getToken()\n return token !== null && token.length > 0\n}\n\n/**\n * 读取 BASE_URL\n */\nexport async function getBaseUrl(): Promise<string> {\n // 1. 优先读取环境变量\n const envBaseUrl = process.env[BASE_URL_ENV_KEY]\n if (envBaseUrl?.trim()) {\n return envBaseUrl.trim()\n }\n\n // 2. 读取本地配置文件\n try {\n if (await fs.pathExists(BASE_URL_FILE)) {\n const baseUrl = await fs.readFile(BASE_URL_FILE, 'utf-8')\n if (baseUrl.trim()) {\n return baseUrl.trim()\n }\n }\n } catch (error) {\n // 读取失败,使用默认值\n }\n\n // 3. 返回默认值\n return DEFAULT_BASE_URL\n}\n\n/**\n * 保存 BASE_URL 到本地配置文件\n */\nexport async function saveBaseUrl(baseUrl: string): Promise<void> {\n if (!baseUrl?.trim()) {\n throw new Error('BASE_URL 不能为空')\n }\n\n // 验证 URL 格式\n try {\n new URL(baseUrl.trim())\n } catch {\n throw new Error('BASE_URL 格式不正确,请输入有效的 URL')\n }\n\n // 确保配置目录存在\n await fs.ensureDir(CONFIG_DIR)\n\n // 写入 base-url 文件\n await fs.writeFile(BASE_URL_FILE, baseUrl.trim(), 'utf-8')\n}\n\n/**\n * 删除本地 BASE_URL\n */\nexport async function removeBaseUrl(): Promise<void> {\n if (await fs.pathExists(BASE_URL_FILE)) {\n await fs.remove(BASE_URL_FILE)\n }\n}\n\n/**\n * 初始化默认配置(首次使用时)\n */\nexport async function initDefaultConfig(): Promise<void> {\n await fs.ensureDir(CONFIG_DIR)\n\n // 如果 BASE_URL 不存在,初始化默认值\n if (!(await fs.pathExists(BASE_URL_FILE))) {\n await saveBaseUrl(DEFAULT_BASE_URL)\n }\n}\n","import chalk from 'chalk'\nimport { t } from '../i18n/index.js'\n\n/**\n * 日志工具 - 提供统一的终端输出格式\n */\n\n// 使用 Unicode 符号代替 figures\nconst symbols = {\n info: 'ℹ',\n tick: '✓',\n warning: '⚠',\n cross: '✖',\n arrowRight: '→'\n}\n\nexport const logger = {\n /**\n * 普通信息\n */\n info: (message: string) => {\n console.log(chalk.blue(symbols.info) + ' ' + message)\n },\n\n /**\n * 成功信息\n */\n success: (message: string) => {\n console.log(chalk.green(symbols.tick) + ' ' + chalk.green(message))\n },\n\n /**\n * 警告信息\n */\n warning: (message: string) => {\n console.log(chalk.yellow(symbols.warning) + ' ' + chalk.yellow(message))\n },\n\n /**\n * 错误信息\n */\n error: (message: string) => {\n console.error(chalk.red(symbols.cross) + ' ' + chalk.red(message))\n },\n\n /**\n * 步骤信息\n */\n step: (message: string) => {\n console.log(chalk.cyan(symbols.arrowRight) + ' ' + chalk.gray(message))\n },\n\n /**\n * 标题\n */\n title: (message: string) => {\n console.log('\\n' + chalk.bold.underline(message) + '\\n')\n },\n\n /**\n * 普通文本(无图标)\n */\n log: (message: string) => {\n console.log(message)\n }\n}\n\n/**\n * 自定义 CLI 错误类\n */\nexport class CLIError extends Error {\n constructor(\n message: string,\n public code?: string,\n public suggestions?: string[]\n ) {\n super(message)\n this.name = 'CLIError'\n }\n}\n\n/**\n * 错误处理函数\n */\nexport async function handleError(error: unknown): Promise<void> {\n console.error()\n\n if (error instanceof CLIError) {\n logger.error(error.message)\n\n if (error.code) {\n const errorCodeText = await t('error.errorCode')\n console.log(chalk.gray(`${errorCodeText} ${error.code}`))\n }\n\n if (error.suggestions?.length) {\n const suggestionsText = await t('error.suggestions')\n console.log(chalk.yellow.bold(`\\n${suggestionsText}\\n`))\n error.suggestions.forEach((suggestion, index) => {\n console.log(chalk.gray(` ${index + 1}. ${suggestion}`))\n })\n }\n } else if (error instanceof Error) {\n logger.error(error.message)\n\n if (process.env.DEBUG) {\n console.log(chalk.gray('\\n' + error.stack))\n }\n } else {\n logger.error(await t('error.unknownError'))\n }\n\n const needHelpText = await t('error.needHelp')\n console.log(\n chalk.gray(`\\n${needHelpText} `) +\n chalk.blue.underline('https://github.com/AIConfigPlaza/acp-cli')\n )\n console.log()\n}\n","import fs from 'fs-extra'\nimport path from 'path'\nimport os from 'os'\n\n/**\n * 语言配置管理\n * 支持的语言: zh-CN (中文), en-US (英文)\n */\n\nexport type Locale = 'zh-CN' | 'en-US'\n\nconst LOCALE_ENV_KEY = 'ACP_CLI_LOCALE'\nconst DEFAULT_LOCALE: Locale = 'zh-CN'\n\nconst CONFIG_DIR = path.join(os.homedir(), '.acp')\nconst LOCALE_FILE = path.join(CONFIG_DIR, 'locale')\n\n/**\n * 读取当前语言配置\n */\nexport async function getLocale(): Promise<Locale> {\n // 1. 优先读取环境变量\n const envLocale = process.env[LOCALE_ENV_KEY]\n if (envLocale && isValidLocale(envLocale)) {\n return envLocale as Locale\n }\n\n // 2. 读取本地配置文件\n try {\n if (await fs.pathExists(LOCALE_FILE)) {\n const locale = (await fs.readFile(LOCALE_FILE, 'utf-8')).trim()\n if (isValidLocale(locale)) {\n return locale as Locale\n }\n }\n } catch (error) {\n // 读取失败使用默认值\n }\n\n // 3. 返回默认语言\n return DEFAULT_LOCALE\n}\n\n/**\n * 保存语言配置到本地文件\n */\nexport async function saveLocale(locale: Locale): Promise<void> {\n if (!isValidLocale(locale)) {\n throw new Error(`不支持的语言: ${locale}`)\n }\n\n // 确保配置目录存在\n await fs.ensureDir(CONFIG_DIR)\n\n // 保存语言配置\n await fs.writeFile(LOCALE_FILE, locale, 'utf-8')\n}\n\n/**\n * 验证语言代码是否有效\n */\nfunction isValidLocale(locale: string): boolean {\n return locale === 'zh-CN' || locale === 'en-US'\n}\n\n/**\n * 获取所有支持的语言列表\n */\nexport function getSupportedLocales(): Locale[] {\n return ['zh-CN', 'en-US']\n}\n\n/**\n * 获取语言显示名称\n */\nexport function getLocaleName(locale: Locale): string {\n const names: Record<Locale, string> = {\n 'zh-CN': '简体中文',\n 'en-US': 'English'\n }\n return names[locale]\n}\n","/**\n * 中文语言包\n */\n\nexport const zhCN = {\n // 通用\n common: {\n confirm: '确认',\n cancel: '取消',\n yes: '是',\n no: '否',\n success: '成功',\n failed: '失败',\n error: '错误',\n warning: '警告',\n info: '提示'\n },\n\n // CLI 主程序\n cli: {\n name: 'acp',\n description: 'AI-Config-Plaza CLI - 统一 AI 编程工具配置管理',\n version: '显示版本号',\n help: '显示帮助信息',\n exampleTitle: '示例:'\n },\n\n // login 命令\n login: {\n command: 'login',\n description: '登录 ACP CLI,保存访问令牌',\n title: '🔐 ACP CLI 登录',\n alreadyLoggedIn: '检测到已登录,是否重新登录?',\n cancelled: '已取消登录',\n inputToken: '请输入 CLI Token:',\n tokenEmpty: 'Token 不能为空',\n tokenInvalid: 'Token 格式不正确(至少 10 个字符)',\n success: '登录成功!Token 已保存到 ~/.acp/token',\n hint: '提示: 现在可以使用 acp apply 命令拉取配置',\n failed: '登录失败'\n },\n\n // apply 命令\n apply: {\n command: 'apply',\n description: '拉取并应用配置到本地项目',\n title: '🚀 ACP 配置应用',\n optionType: '资源类型 (solution|agent|prompt|mcp)',\n optionIde: 'AI IDE 类型 (vscode|cursor|codex|claude-code)',\n optionDir: '目标目录',\n notLoggedIn: '未登录,请先执行 acp login',\n loginFirst: '运行 acp login 命令登录',\n selectResourceType: '请选择资源类型:',\n resourceTypes: {\n solution: '解决方案 (Solution)',\n agent: 'Agent 配置 (暂不支持)',\n prompt: 'Prompt (暂不支持)',\n mcp: 'MCP 配置 (暂不支持)'\n },\n notSupported: '暂不支持独立应用 agent/prompt/mcp,请使用 solution 类型',\n noSelection: '未选择任何配置',\n selectIde: '请选择 AI IDE 类型:',\n applied: '配置已应用到:',\n searchPlaceholder: '搜索解决方案(输入名称或描述)',\n noResults: '没有找到解决方案',\n loadingMore: '加载更多...',\n noMore: '没有更多了',\n selected: '已选择',\n selectSolution: '请选择一个解决方案:',\n fetching: '正在获取解决方案列表...',\n fetchSuccess: '获取到 {count} 个解决方案',\n noSolutions: '暂无可用的解决方案',\n searchPrompt: '搜索解决方案 (按名称搜索,留空显示全部):',\n noMatch: '未找到匹配的解决方案',\n selectSolutionPage: '选择解决方案 (第 {current}/{total} 页):',\n nextPage: '>>> 下一页',\n prevPage: '<<< 上一页',\n cancel: '取消',\n fetchingDetail: '正在获取解决方案详情...',\n fetchDetailFailed: '获取解决方案失败',\n ideTypes: {\n vscode: 'VS Code',\n cursor: 'Cursor',\n codex: 'Codex',\n claudeCode: 'Claude Code',\n codeBuddy: 'CodeBuddy',\n qoder: 'Qoder'\n }\n },\n\n // locale 命令\n locale: {\n command: 'locale',\n description: '切换 CLI 语言',\n title: '🌐 语言设置',\n current: '当前语言',\n selectLanguage: '请选择语言:',\n success: '语言已切换为',\n failed: '语言切换失败',\n restartHint: '提示: 已生效,新命令将使用所选语言'\n },\n\n // update 命令\n update: {\n command: 'update',\n description: '更新 ACP CLI 到最新版本',\n title: '⬆️ CLI 自更新',\n currentVersion: '当前版本',\n latestVersion: '最新版本',\n alreadyLatest: '已是最新版本,无需更新',\n checkingLatest: '正在检查最新版本...',\n fetchFailed: '获取最新版本失败',\n selectTarget: '请选择更新目标:',\n targets: {\n global: '全局 (推荐)',\n local: '本地项目'\n },\n noPkgManager: '未检测到可用的包管理器 (pnpm/npm/yarn)',\n selectPkgManager: '请选择包管理器:',\n executing: '正在使用 {manager} 执行更新...',\n success: '更新成功!',\n failed: '更新失败',\n verifyHint: '提示: 运行 acp -v 查看当前版本'\n },\n\n // 错误处理\n error: {\n errorCode: '错误代码:',\n suggestions: '💡 建议:',\n needHelp: '需要帮助? 访问:',\n unknownError: '未知错误'\n }\n}\n","/**\n * English Language Pack\n */\n\nexport const enUS = {\n // Common\n common: {\n confirm: 'Confirm',\n cancel: 'Cancel',\n yes: 'Yes',\n no: 'No',\n success: 'Success',\n failed: 'Failed',\n error: 'Error',\n warning: 'Warning',\n info: 'Info'\n },\n\n // CLI Main\n cli: {\n name: 'acp',\n description: 'AI-Config-Plaza CLI - Unified AI Programming Tool Configuration Management',\n version: 'Show version number',\n help: 'Show help information',\n exampleTitle: 'Examples:'\n },\n\n // login command\n login: {\n command: 'login',\n description: 'Login to ACP CLI and save access token',\n title: '🔐 ACP CLI Login',\n alreadyLoggedIn: 'Already logged in. Do you want to login again?',\n cancelled: 'Login cancelled',\n inputToken: 'Please enter CLI Token:',\n tokenEmpty: 'Token cannot be empty',\n tokenInvalid: 'Invalid token format (at least 10 characters)',\n success: 'Login successful! Token saved to ~/.acp/token',\n hint: 'Tip: You can now use acp apply command to fetch configurations',\n failed: 'Login failed'\n },\n\n // apply command\n apply: {\n command: 'apply',\n description: 'Fetch and apply configurations to local project',\n title: '🚀 ACP Configuration Apply',\n optionType: 'Resource type (solution|agent|prompt|mcp)',\n optionIde: 'AI IDE type (vscode|cursor|codex|claude-code)',\n optionDir: 'Target directory',\n notLoggedIn: 'Not logged in. Please run acp login first',\n loginFirst: 'Run acp login command to login',\n selectResourceType: 'Please select resource type:',\n resourceTypes: {\n solution: 'Solution',\n agent: 'Agent Configuration (Not supported yet)',\n prompt: 'Prompt (Not supported yet)',\n mcp: 'MCP Configuration (Not supported yet)'\n },\n notSupported: 'Standalone application of agent/prompt/mcp is not supported yet. Please use solution type',\n noSelection: 'No configuration selected',\n selectIde: 'Please select AI IDE type:',\n applied: 'Configuration applied to:',\n searchPlaceholder: 'Search solutions (enter name or description)',\n noResults: 'No solutions found',\n loadingMore: 'Loading more...',\n noMore: 'No more items',\n selected: 'Selected',\n selectSolution: 'Please select a solution:',\n fetching: 'Fetching solution list...',\n fetchSuccess: 'Fetched {count} solutions',\n noSolutions: 'No solutions available',\n searchPrompt: 'Search solutions (search by name, leave empty to show all):',\n noMatch: 'No matching solutions found',\n selectSolutionPage: 'Select solution (Page {current}/{total}):',\n nextPage: '>>> Next Page',\n prevPage: '<<< Previous Page',\n cancel: 'Cancel',\n fetchingDetail: 'Fetching solution details...',\n fetchDetailFailed: 'Failed to fetch solutions',\n ideTypes: {\n vscode: 'VS Code',\n cursor: 'Cursor',\n codex: 'Codex',\n claudeCode: 'Claude Code',\n codeBuddy: 'CodeBuddy',\n qoder: 'Qoder'\n }\n },\n\n // locale command\n locale: {\n command: 'locale',\n description: 'Switch CLI language',\n title: '🌐 Language Settings',\n current: 'Current Language',\n selectLanguage: 'Please select language:',\n success: 'Language switched to',\n failed: 'Failed to switch language',\n restartHint: 'Tip: Changes take effect immediately for new commands'\n },\n\n // update command\n update: {\n command: 'update',\n description: 'Update ACP CLI to latest version',\n title: '⬆️ CLI Self Update',\n currentVersion: 'Current Version',\n latestVersion: 'Latest Version',\n alreadyLatest: 'Already up to date',\n checkingLatest: 'Checking latest version...',\n fetchFailed: 'Failed to fetch latest version',\n selectTarget: 'Select update target:',\n targets: {\n global: 'Global (Recommended)',\n local: 'Local Project'\n },\n noPkgManager: 'No available package manager detected (pnpm/npm/yarn)',\n selectPkgManager: 'Select a package manager:',\n executing: 'Executing update with {manager}...',\n success: 'Update successful!',\n failed: 'Update failed',\n verifyHint: 'Tip: Run acp -v to verify current version'\n },\n\n // Error handling\n error: {\n errorCode: 'Error Code:',\n suggestions: '💡 Suggestions:',\n needHelp: 'Need help? Visit:',\n unknownError: 'Unknown error'\n }\n}\n","import { getLocale, type Locale } from '../config/locale.js'\nimport { zhCN } from './zh-CN.js'\nimport { enUS } from './en-US.js'\n\n/**\n * 国际化工具 - 提供多语言支持\n */\n\n// 语言包映射\nconst messages: Record<Locale, typeof zhCN> = {\n 'zh-CN': zhCN,\n 'en-US': enUS\n}\n\n// 当前语言缓存\nlet currentLocale: Locale | null = null\nlet currentMessages: typeof zhCN | null = null\n\n/**\n * 初始化 i18n\n */\nasync function initI18n(): Promise<void> {\n if (!currentLocale) {\n currentLocale = await getLocale()\n currentMessages = messages[currentLocale]\n }\n}\n\n/**\n * 翻译函数 - 根据键路径获取翻译文本\n * @param key - 翻译键,支持点分隔的路径,如 'login.title'\n * @param params - 替换参数对象\n * @returns 翻译后的文本\n */\nexport async function t(key: string, params?: Record<string, string | number>): Promise<string> {\n await initI18n()\n\n // 通过点分隔的路径获取嵌套值\n const keys = key.split('.')\n let value: any = currentMessages\n\n for (const k of keys) {\n if (value && typeof value === 'object' && k in value) {\n value = value[k]\n } else {\n // 如果找不到翻译,返回 key 本身\n return key\n }\n }\n\n // 如果不是字符串,返回 key\n if (typeof value !== 'string') {\n return key\n }\n\n // 替换参数\n if (params) {\n return value.replace(/\\{(\\w+)\\}/g, (match, paramKey) => {\n return paramKey in params ? String(params[paramKey]) : match\n })\n }\n\n return value\n}\n\n/**\n * 同步翻译函数(需要先初始化)\n * @param key - 翻译键\n * @param params - 替换参数对象\n * @returns 翻译后的文本\n */\nexport function tSync(key: string, params?: Record<string, string | number>): string {\n if (!currentMessages) {\n // 如果未初始化,返回 key\n return key\n }\n\n const keys = key.split('.')\n let value: any = currentMessages\n\n for (const k of keys) {\n if (value && typeof value === 'object' && k in value) {\n value = value[k]\n } else {\n return key\n }\n }\n\n if (typeof value !== 'string') {\n return key\n }\n\n if (params) {\n return value.replace(/\\{(\\w+)\\}/g, (match, paramKey) => {\n return paramKey in params ? String(params[paramKey]) : match\n })\n }\n\n return value\n}\n\n/**\n * 获取当前语言\n */\nexport async function getCurrentLocale(): Promise<Locale> {\n await initI18n()\n return currentLocale!\n}\n\n/**\n * 重新加载语言配置(切换语言后调用)\n */\nexport async function reloadLocale(): Promise<void> {\n currentLocale = null\n currentMessages = null\n await initI18n()\n}\n\n/**\n * 获取完整的语言包(用于类型提示)\n */\nexport function getMessages() {\n return currentMessages || zhCN\n}\n","import { Command } from 'commander'\nimport inquirer from 'inquirer'\nimport chalk from 'chalk'\nimport ora from 'ora'\nimport { apiClient } from '../api/client.js'\nimport { logger, CLIError } from '../utils/logger.js'\nimport { isLoggedIn } from '../config/token.js'\nimport { type AiIdeType } from '../utils/ide-mapper.js'\nimport { searchByName, paginate } from '../utils/pagination.js'\nimport { applySolution } from '../apply/writer.js'\nimport type { Solution } from '../types/index.js'\nimport { t } from '../i18n/index.js'\n\n/**\n * acp apply 命令\n * 拉取并应用配置到本地项目\n */\n\ntype ResourceType = 'solution' | 'agent' | 'prompt' | 'mcp'\n\nexport const applyCommand = new Command('apply')\n .description('拉取并应用配置到本地项目 / Fetch and apply configurations to local project')\n .option('-t, --type <type>', '资源类型 (solution|agent|prompt|mcp) / Resource type', 'solution')\n .option('-i, --ide <ide>', 'AI IDE 类型 / AI IDE type (vscode|cursor|codex|claude-code|codebuddy|qoder)')\n .option('-d, --dir <path>', '目标目录 / Target directory', process.cwd())\n .action(async (options) => {\n try {\n // 检查登录状态\n if (!(await isLoggedIn())) {\n throw new CLIError(\n await t('apply.notLoggedIn'),\n 'NOT_LOGGED_IN',\n [await t('apply.loginFirst')]\n )\n }\n\n logger.title(await t('apply.title'))\n\n // 1. 选择资源类型\n const resourceType = await selectResourceType(options.type)\n\n // 2. 根据类型拉取并选择资源\n let selectedSolution: Solution | null = null\n\n if (resourceType === 'solution') {\n selectedSolution = await fetchAndSelectSolution()\n } else {\n throw new CLIError(await t('apply.notSupported'))\n }\n\n if (!selectedSolution) {\n logger.info(await t('apply.noSelection'))\n return\n }\n\n // 3. 选择 IDE 类型\n const ide = options.ide || (await selectIde())\n\n // 4. 应用配置\n await applySolution(selectedSolution, {\n ide: ide as AiIdeType,\n targetDir: options.dir\n })\n\n const appliedMsg = await t('apply.applied')\n console.log(chalk.gray(`\\n${appliedMsg} ${chalk.cyan(options.dir)}\\n`))\n } catch (error) {\n if (error instanceof Error) {\n logger.error(error.message)\n }\n process.exit(1)\n }\n })\n\n/**\n * 选择资源类型\n */\nasync function selectResourceType(defaultType?: string): Promise<ResourceType> {\n if (defaultType && ['solution', 'agent', 'prompt', 'mcp'].includes(defaultType)) {\n return defaultType as ResourceType\n }\n\n const { type } = await inquirer.prompt([\n {\n type: 'list',\n name: 'type',\n message: await t('apply.selectResourceType'),\n choices: [\n { name: chalk.cyan(await t('apply.resourceTypes.solution')), value: 'solution' },\n { name: chalk.gray(await t('apply.resourceTypes.agent')), value: 'agent', disabled: true },\n { name: chalk.gray(await t('apply.resourceTypes.prompt')), value: 'prompt', disabled: true },\n { name: chalk.gray(await t('apply.resourceTypes.mcp')), value: 'mcp', disabled: true }\n ],\n default: 'solution'\n }\n ])\n\n return type\n}\n\n/**\n * 拉取并选择解决方案\n */\nasync function fetchAndSelectSolution(): Promise<Solution | null> {\n const spinner = ora(await t('apply.fetching')).start()\n\n try {\n // 1. 拉取解决方案列表\n const response = await apiClient.getSolutions()\n spinner.stop()\n\n if (!response.data || response.data.length === 0) {\n logger.warning(await t('apply.noSolutions'))\n return null\n }\n\n logger.success(await t('apply.fetchSuccess', { count: response.data.length }))\n\n // 2. 搜索过滤\n const { searchQuery } = await inquirer.prompt([\n {\n type: 'input',\n name: 'searchQuery',\n message: await t('apply.searchPrompt'),\n default: ''\n }\n ])\n\n let filteredSolutions = searchByName(response.data, searchQuery)\n\n if (filteredSolutions.length === 0) {\n logger.warning(await t('apply.noMatch'))\n return null\n }\n\n // 3. 分页显示\n const PAGE_SIZE = 20\n let currentPage = 1\n let selectedSolution: Solution | null = null\n\n while (!selectedSolution) {\n const paginatedResult = paginate(filteredSolutions, {\n page: currentPage,\n pageSize: PAGE_SIZE\n })\n\n // 构建选择列表\n const choices = paginatedResult.items.map((solution) => ({\n name: `${chalk.cyan(solution.name)} ${chalk.yellow(`@${solution.author.username}`)} - ${chalk.gray(solution.description)}`,\n value: solution.id,\n short: solution.name\n }))\n\n // 添加分页控制选项\n if (paginatedResult.hasNext) {\n choices.push({\n name: chalk.yellow(await t('apply.nextPage')),\n value: '__NEXT_PAGE__',\n short: await t('apply.nextPage')\n })\n }\n\n if (paginatedResult.hasPrev) {\n choices.unshift({\n name: chalk.yellow(await t('apply.prevPage')),\n value: '__PREV_PAGE__',\n short: await t('apply.prevPage')\n })\n }\n\n choices.push({\n name: chalk.red(await t('apply.cancel')),\n value: '__CANCEL__',\n short: await t('apply.cancel')\n })\n\n const { selected } = await inquirer.prompt([\n {\n type: 'list',\n name: 'selected',\n message: await t('apply.selectSolutionPage', { \n current: currentPage, \n total: paginatedResult.totalPages \n }),\n choices,\n pageSize: 15\n }\n ])\n\n if (selected === '__CANCEL__') {\n return null\n } else if (selected === '__NEXT_PAGE__') {\n currentPage++\n } else if (selected === '__PREV_PAGE__') {\n currentPage--\n } else {\n // 获取详情\n const detailSpinner = ora(await t('apply.fetchingDetail')).start()\n const detailResponse = await apiClient.getSolutionById(selected)\n detailSpinner.stop()\n\n selectedSolution = detailResponse.data\n }\n }\n\n return selectedSolution\n } catch (error) {\n spinner.fail(await t('apply.fetchDetailFailed'))\n throw error\n }\n}\n\n/**\n * 选择 IDE 类型\n */\nasync function selectIde(): Promise<AiIdeType> {\n const { ide } = await inquirer.prompt([\n {\n type: 'list',\n name: 'ide',\n message: await t('apply.selectIde'),\n choices: [\n { name: chalk.cyan(await t('apply.ideTypes.vscode')), value: 'vscode' },\n { name: chalk.cyan(await t('apply.ideTypes.cursor')), value: 'cursor' },\n { name: chalk.cyan(await t('apply.ideTypes.codex')), value: 'codex' },\n { name: chalk.cyan(await t('apply.ideTypes.claudeCode')), value: 'claude-code' },\n { name: chalk.cyan(await t('apply.ideTypes.codeBuddy')), value: 'codebuddy' },\n { name: chalk.cyan(await t('apply.ideTypes.qoder')), value: 'qoder' }\n ],\n default: 'vscode'\n }\n ])\n\n return ide\n}\n","import axios, { AxiosInstance, AxiosError } from 'axios'\nimport { getToken, getBaseUrl } from '../config/token.js'\nimport type {\n ApiResponse,\n Solution,\n AgentConfig,\n Prompt,\n McpConfig\n} from '../types/index.js'\n\n/**\n * API 客户端封装\n */\n\nclass ApiClient {\n private client: AxiosInstance\n private baseUrlPromise: Promise<string>\n\n constructor() {\n // 异步获取 BASE_URL\n this.baseUrlPromise = getBaseUrl()\n\n this.client = axios.create({\n timeout: 30000,\n headers: {\n 'Content-Type': 'application/json'\n }\n })\n\n // 请求拦截器:自动添加 token 和 baseURL\n this.client.interceptors.request.use(async (config) => {\n // 设置 baseURL\n if (!config.baseURL) {\n config.baseURL = await this.baseUrlPromise\n }\n\n // 添加 token\n const token = await getToken()\n if (token) {\n config.headers['X-CLI-TOKEN'] = token\n }\n return config\n })\n\n // 响应拦截器:统一错误处理\n this.client.interceptors.response.use(\n (response) => response,\n (error: AxiosError) => {\n if (error.response) {\n const status = error.response.status\n const message = (error.response.data as any)?.message || error.message\n\n if (status === 401) {\n throw new Error('认证失败,请先执行 acp login 登录')\n } else if (status === 403) {\n throw new Error('权限不足,请检查 token 是否有效')\n } else if (status === 404) {\n throw new Error('请求的资源不存在')\n } else if (status >= 500) {\n throw new Error(`服务器错误 (${status}): ${message}`)\n } else {\n throw new Error(`请求失败 (${status}): ${message}`)\n }\n } else if (error.request) {\n throw new Error('网络错误,请检查网络连接')\n } else {\n throw new Error(`请求配置错误: ${error.message}`)\n }\n }\n )\n }\n\n /**\n * 获取解决方案列表\n */\n async getSolutions(aiTool?: string): Promise<ApiResponse<Solution[]>> {\n const params = aiTool ? { aiTool } : {}\n const response = await this.client.get<ApiResponse<Solution[]>>(\n '/api/cli/solutions',\n { params }\n )\n return response.data\n }\n\n /**\n * 获取解决方案详情\n */\n async getSolutionById(id: string): Promise<ApiResponse<Solution>> {\n const response = await this.client.get<ApiResponse<Solution>>(\n `/api/cli/solutions/${id}`\n )\n return response.data\n }\n\n /**\n * 获取 Agent 配置列表\n */\n async getAgents(): Promise<ApiResponse<AgentConfig[]>> {\n const response = await this.client.get<ApiResponse<AgentConfig[]>>(\n '/api/cli/agents'\n )\n return response.data\n }\n\n /**\n * 获取 Agent 配置详情\n */\n async getAgentById(id: string): Promise<ApiResponse<AgentConfig>> {\n const response = await this.client.get<ApiResponse<AgentConfig>>(\n `/api/cli/agents/${id}`\n )\n return response.data\n }\n\n /**\n * 获取 Prompt 列表\n */\n async getPrompts(): Promise<ApiResponse<Prompt[]>> {\n const response = await this.client.get<ApiResponse<Prompt[]>>(\n '/api/cli/prompts'\n )\n return response.data\n }\n\n /**\n * 获取 Prompt 详情\n */\n async getPromptById(id: string): Promise<ApiResponse<Prompt>> {\n const response = await this.client.get<ApiResponse<Prompt>>(\n `/api/cli/prompts/${id}`\n )\n return response.data\n }\n\n /**\n * 获取 MCP 配置列表\n */\n async getMcps(): Promise<ApiResponse<McpConfig[]>> {\n const response = await this.client.get<ApiResponse<McpConfig[]>>(\n '/api/cli/mcps'\n )\n return response.data\n }\n\n /**\n * 获取 MCP 配置详情\n */\n async getMcpById(id: string): Promise<ApiResponse<McpConfig>> {\n const response = await this.client.get<ApiResponse<McpConfig>>(\n `/api/cli/mcps/${id}`\n )\n return response.data\n }\n\n /**\n * 下载二进制资源\n */\n async downloadBinary(url: string): Promise<Buffer> {\n const response = await this.client.get<ArrayBuffer>(url, {\n responseType: 'arraybuffer'\n })\n\n return Buffer.from(response.data)\n }\n}\n\n// 导出单例\nexport const apiClient = new ApiClient()\n","/**\n * 分页工具函数\n */\n\nexport interface PaginationOptions {\n page: number\n pageSize: number\n}\n\nexport interface PaginationResult<T> {\n items: T[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n hasNext: boolean\n hasPrev: boolean\n}\n\n/**\n * 对数组进行分页\n */\nexport function paginate<T>(\n items: T[],\n options: PaginationOptions\n): PaginationResult<T> {\n const { page, pageSize } = options\n const total = items.length\n const totalPages = Math.ceil(total / pageSize)\n const startIndex = (page - 1) * pageSize\n const endIndex = startIndex + pageSize\n\n return {\n items: items.slice(startIndex, endIndex),\n total,\n page,\n pageSize,\n totalPages,\n hasNext: page < totalPages,\n hasPrev: page > 1\n }\n}\n\n/**\n * 按名称搜索(不区分大小写)\n */\nexport function searchByName<T extends { name: string }>(\n items: T[],\n query: string\n): T[] {\n if (!query.trim()) {\n return items\n }\n\n const lowerQuery = query.toLowerCase().trim()\n return items.filter((item) =>\n item.name.toLowerCase().includes(lowerQuery)\n )\n}\n","import fs from 'fs-extra'\nimport path from 'path'\nimport chalk from 'chalk'\nimport inquirer from 'inquirer'\nimport { logger } from '../utils/logger.js'\nimport { apiClient } from '../api/client.js'\nimport { getIdePathMapping, type AiIdeType } from '../utils/ide-mapper.js'\nimport type { Solution, Prompt, McpConfig, Skill, SkillResource } from '../types/index.js'\n\n/**\n * 配置应用模块 - 将远程配置写入本地文件\n */\n\nexport interface ApplyOptions {\n ide: AiIdeType\n targetDir: string\n}\n\n/**\n * 应用解决方案配置\n */\nexport async function applySolution(\n solution: Solution,\n options: ApplyOptions\n): Promise<void> {\n const { ide, targetDir } = options\n const pathMapping = getIdePathMapping(ide)\n\n logger.title(`📦 应用解决方案: ${chalk.cyan(solution.name)}`)\n\n // 1. 应用 Agent 配置\n if (solution.agentConfig) {\n await applyAgentConfig(\n solution.agentConfig.content,\n pathMapping.agents,\n targetDir\n )\n }\n\n // 2. 应用 Prompts\n if (solution.customPrompts?.length) {\n await applyPrompts(\n solution.customPrompts,\n pathMapping.prompts,\n targetDir\n )\n }\n\n // 3. 应用 MCP 配置\n if (solution.mcpConfigs?.length) {\n await applyMcpConfigs(\n solution.mcpConfigs,\n pathMapping.mcp,\n targetDir\n )\n }\n\n // 4. 应用 Skills\n if (solution.skills?.length) {\n await applySkills(\n solution.skills,\n pathMapping.skills,\n targetDir\n )\n }\n\n logger.success(`\\n✨ 解决方案 ${chalk.cyan(solution.name)} 应用成功!`)\n}\n\n/**\n * 应用 Agent 配置\n */\nexport async function applyAgentConfig(\n content: string,\n relativePath: string,\n targetDir: string\n): Promise<void> {\n // 如果 relativePath 是绝对路径,直接使用;否则拼接 targetDir\n const filePath = path.isAbsolute(relativePath) \n ? relativePath \n : path.join(targetDir, relativePath)\n\n logger.step(`写入 Agent 配置: ${chalk.gray(relativePath)}`)\n\n // 检查文件是否存在\n const exists = await fs.pathExists(filePath)\n if (exists) {\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: `文件 ${chalk.cyan(relativePath)} 已存在,是否覆盖?`,\n default: true\n }\n ])\n\n if (!overwrite) {\n logger.warning(`跳过: ${relativePath}`)\n return\n }\n }\n\n // 写入文件\n await fs.ensureDir(path.dirname(filePath))\n await fs.writeFile(filePath, content, 'utf-8')\n\n logger.success(`已写入: ${relativePath}`)\n}\n\n/**\n * 应用 Prompts\n */\nexport async function applyPrompts(\n prompts: Prompt[],\n promptsDir: string,\n targetDir: string\n): Promise<void> {\n // 如果 promptsDir 是绝对路径,直接使用;否则拼接 targetDir\n const fullPromptsDir = path.isAbsolute(promptsDir) \n ? promptsDir \n : path.join(targetDir, promptsDir)\n\n logger.step(`写入 ${prompts.length} 个 Prompt 配置到: ${chalk.gray(promptsDir)}`)\n\n // 确保目录存在\n await fs.ensureDir(fullPromptsDir)\n\n for (const prompt of prompts) {\n // 生成文件名(清理特殊字符)\n const fileName = sanitizeFileName(prompt.name) + '.prompt.md'\n const filePath = path.join(fullPromptsDir, fileName)\n\n // 检查是否存在\n const exists = await fs.pathExists(filePath)\n if (exists) {\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: `Prompt ${chalk.cyan(fileName)} 已存在,是否覆盖?`,\n default: true\n }\n ])\n\n if (!overwrite) {\n logger.warning(`跳过: ${fileName}`)\n continue\n }\n }\n\n // 写入内容\n await fs.writeFile(filePath, prompt.content, 'utf-8')\n logger.success(`已写入: ${path.join(promptsDir, fileName)}`)\n }\n}\n\n/**\n * 应用 MCP 配置\n */\nexport async function applyMcpConfigs(\n mcpConfigs: McpConfig[],\n mcpFile: string,\n targetDir: string\n): Promise<void> {\n // 检查是否为 CodeBuddy IDE(不支持 MCP 配置)\n if (!mcpFile || mcpFile === '') {\n logger.warning('暂不支持 CodeBuddy 的 MCP 配置写入')\n return\n }\n\n // 如果 mcpFile 是绝对路径,直接使用;否则拼接 targetDir\n const filePath = path.isAbsolute(mcpFile) \n ? mcpFile \n : path.join(targetDir, mcpFile)\n\n logger.step(`写入 MCP 配置: ${chalk.gray(mcpFile)}`)\n\n // 构造 mcpServers 结构\n const mcpServers: Record<string, any> = {}\n\n for (const mcpConfig of mcpConfigs) {\n try {\n const config = JSON.parse(mcpConfig.configJson)\n // 使用 MCP 配置的名称作为 key\n mcpServers[mcpConfig.name] = config\n } catch (error) {\n logger.warning(`MCP 配置 ${mcpConfig.name} 格式错误,已跳过`)\n }\n }\n\n // 检查文件是否存在\n const exists = await fs.pathExists(filePath)\n if (exists) {\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: `文件 ${chalk.cyan(mcpFile)} 已存在,是否覆盖?`,\n default: true\n }\n ])\n\n if (!overwrite) {\n logger.warning(`跳过: ${mcpFile}`)\n return\n }\n }\n\n // 写入文件\n await fs.ensureDir(path.dirname(filePath))\n\n // 根据文件扩展名和路径决定输出格式\n if (mcpFile.endsWith('.toml')) {\n // Codex 使用 TOML 格式\n const tomlContent = convertMcpToToml(mcpServers)\n await fs.writeFile(filePath, tomlContent, 'utf-8')\n } else {\n // JSON 格式\n let mergedConfig: Record<string, any>\n \n // VS Code 使用 \"servers\",其他 IDE 使用 \"mcpServers\"\n if (mcpFile.includes('.vscode')) {\n mergedConfig = {\n servers: mcpServers\n }\n } else {\n mergedConfig = {\n mcpServers\n }\n }\n \n await fs.writeFile(filePath, JSON.stringify(mergedConfig, null, 2), 'utf-8')\n }\n\n logger.success(`已写入: ${mcpFile}`)\n}\n\n/**\n * 将 MCP 配置转换为 TOML 格式(用于 Codex)\n */\nfunction convertMcpToToml(mcpServers: Record<string, any>): string {\n let tomlContent = ''\n\n for (const [serverName, config] of Object.entries(mcpServers)) {\n tomlContent += `[mcp_servers.${serverName}]\\n`\n \n // 写入 command\n if (config.command) {\n tomlContent += `command = ${JSON.stringify(config.command)}\\n`\n }\n\n // 写入 args\n if (config.args && Array.isArray(config.args)) {\n const argsStr = config.args.map((arg: string) => JSON.stringify(arg)).join(', ')\n tomlContent += `args = [${argsStr}]\\n`\n }\n\n // 写入 env\n if (config.env && typeof config.env === 'object') {\n const envEntries = Object.entries(config.env)\n if (envEntries.length > 0) {\n const envStr = envEntries\n .map(([key, value]) => `${key} = ${JSON.stringify(value)}`)\n .join(', ')\n tomlContent += `env = { ${envStr} }\\n`\n }\n }\n\n tomlContent += '\\n'\n }\n\n return tomlContent\n}\n\n/**\n * 应用 Skills\n */\nexport async function applySkills(\n skills: Skill[],\n skillsDir: string,\n targetDir: string\n): Promise<void> {\n // 如果 skillsDir 是绝对路径,直接使用;否则拼接 targetDir\n const fullSkillsDir = path.isAbsolute(skillsDir) \n ? skillsDir \n : path.join(targetDir, skillsDir)\n\n logger.step(`写入 ${skills.length} 个 Skill 配置到: ${chalk.gray(skillsDir)}`)\n\n // 确保目录存在\n await fs.ensureDir(fullSkillsDir)\n\n for (const skill of skills) {\n // 生成目录名(清理特殊字符)\n const skillDirName = sanitizeSkillName(skill.name)\n const skillDirPath = path.join(fullSkillsDir, skillDirName)\n\n logger.step(`处理 Skill: ${chalk.cyan(skill.name)}`)\n\n // 检查目录是否存在\n const dirExists = await fs.pathExists(skillDirPath)\n if (dirExists) {\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: `Skill 目录 ${chalk.cyan(skillDirName)} 已存在,是否覆盖?`,\n default: true\n }\n ])\n\n if (!overwrite) {\n logger.warning(`跳过: ${skillDirName}`)\n continue\n }\n }\n\n // 确保目录存在\n await fs.ensureDir(skillDirPath)\n\n // 1. 创建 SKILL.md 文件\n const skillMdPath = path.join(skillDirPath, 'SKILL.md')\n await fs.writeFile(skillMdPath, skill.skillMarkdown, 'utf-8')\n logger.success(`已写入: ${path.join(skillsDir, skillDirName, 'SKILL.md')}`)\n\n // 2. 处理 SkillResources\n if (skill.skillResources && skill.skillResources.length > 0) {\n for (const resource of skill.skillResources) {\n // 确保相对路径安全(防止路径遍历攻击)\n const safeRelativePath = sanitizePath(resource.relativePath)\n const resourceFilePath = path.join(skillDirPath, safeRelativePath, resource.fileName)\n\n // 检查文件是否存在\n const fileExists = await fs.pathExists(resourceFilePath)\n if (fileExists) {\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: `文件 ${chalk.cyan(path.join(skillDirName, safeRelativePath))} 已存在,是否覆盖?`,\n default: true\n }\n ])\n\n if (!overwrite) {\n logger.warning(`跳过: ${path.join(skillDirName, safeRelativePath)}`)\n continue\n }\n }\n\n // 确保父目录存在\n await fs.ensureDir(path.dirname(resourceFilePath))\n\n // 写入文件内容\n const resourceContent = await resolveSkillResourceContent(resource)\n if (Buffer.isBuffer(resourceContent)) {\n await fs.writeFile(resourceFilePath, resourceContent)\n } else {\n await fs.writeFile(resourceFilePath, resourceContent, 'utf-8')\n }\n logger.success(`已写入: ${path.join(skillsDir, skillDirName, safeRelativePath)}`)\n }\n }\n }\n}\n\nasync function resolveSkillResourceContent(resource: SkillResource): Promise<string | Buffer> {\n if (resource.isBinary) {\n if (!resource.downloadUrl) {\n throw new Error(`Skill 资源 ${resource.fileName} 缺少 downloadUrl,无法下载二进制内容`)\n }\n\n return apiClient.downloadBinary(resource.downloadUrl)\n }\n\n if (typeof resource.fileContent === 'string') {\n return resource.fileContent\n }\n\n if (resource.downloadUrl) {\n const bytes = await apiClient.downloadBinary(resource.downloadUrl)\n return bytes.toString('utf-8')\n }\n\n throw new Error(`Skill 资源 ${resource.fileName} 缺少可写入内容`)\n}\n\n/**\n * 清理 skill 名称,用于创建目录名\n */\nfunction sanitizeSkillName(name: string): string {\n return name\n .replace(/[<>:\"/\\\\|?*]/g, '-') // 替换非法字符\n .replace(/\\s+/g, '-') // 空格转连字符\n .replace(/-+/g, '-') // 多个连字符合并\n .replace(/^-+|-+$/g, '') // 移除首尾连字符\n .toLowerCase()\n}\n\n/**\n * 清理路径,防止路径遍历攻击\n */\nfunction sanitizePath(relativePath: string): string {\n // 移除路径遍历攻击(如 ../, ..\\, 等)\n let safePath = relativePath\n .replace(/\\.\\./g, '') // 移除 ..\n .replace(/^[/\\\\]+/, '') // 移除开头的 / 或 \\\n .replace(/[/\\\\]+/g, path.sep) // 统一路径分隔符\n\n // 确保路径是相对路径,不包含绝对路径\n if (path.isAbsolute(safePath)) {\n safePath = path.relative('/', safePath)\n }\n\n // 移除 Windows 驱动器号(如 C:)\n if (safePath.match(/^[A-Za-z]:/)) {\n safePath = safePath.substring(2)\n }\n\n return safePath\n}\n\n/**\n * 清理文件名中的特殊字符\n */\nfunction sanitizeFileName(name: string): string {\n return name\n .replace(/[<>:\"/\\\\|?*]/g, '-') // 替换非法字符\n .replace(/\\s+/g, '-') // 空格转连字符\n .replace(/-+/g, '-') // 多个连字符合并\n .toLowerCase()\n}\n","import { homedir } from 'os'\nimport type { AiIdeType, IdePathMapping } from '../types/index.js'\n\n// 重新导出类型\nexport type { AiIdeType, IdePathMapping }\n\n/**\n * AI IDE 路径映射配置\n * 定义不同 IDE 的配置文件输出路径\n */\n\nexport const IDE_PATH_MAPPINGS: Record<AiIdeType, IdePathMapping> = {\n vscode: {\n prompts: '.github/prompts',\n agents: 'AGENTS.md',\n mcp: '.vscode/mcp.json',\n skills: '.github/skills'\n },\n cursor: {\n prompts: '.cursor/commands',\n agents: 'AGENTS.md',\n mcp: '.cursor/mcp.json',\n skills: '.cursor/skills'\n },\n codex: {\n prompts: '~/.codex/prompts',\n agents: 'AGENTS.md',\n mcp: '.codex/config.toml',\n skills: '.codex/skills'\n },\n 'claude-code': {\n prompts: '.claude/commands',\n agents: 'AGENTS.md',\n mcp: '.mcp.json',\n skills: '.claude/skills'\n },\n codebuddy: {\n prompts: '.codebuddy/commands',\n agents: 'AGENTS.md',\n mcp: '.mcp.json',\n skills: '.codebuddy/skills'\n },\n qoder: {\n prompts: '.qoder/commands',\n agents: 'AGENTS.md',\n mcp: '.mcp.json',\n skills: 'qoder/skills'\n }\n}\n\n/**\n * 展开路径中的 ~ 为用户主目录\n */\nfunction expandPath(path: string): string {\n if (path.startsWith('~')) {\n return path.replace('~', homedir())\n }\n return path\n}\n\n/**\n * 获取 IDE 路径映射\n */\nexport function getIdePathMapping(ide: AiIdeType): IdePathMapping {\n const mapping = IDE_PATH_MAPPINGS[ide]\n return {\n prompts: expandPath(mapping.prompts),\n agents: expandPath(mapping.agents),\n mcp: expandPath(mapping.mcp),\n skills: expandPath(mapping.skills)\n }\n}\n\n/**\n * 获取所有支持的 IDE 列表\n */\nexport function getSupportedIdes(): AiIdeType[] {\n return Object.keys(IDE_PATH_MAPPINGS) as AiIdeType[]\n}\n\n/**\n * 验证 IDE 类型是否支持\n */\nexport function isValidIde(ide: string): ide is AiIdeType {\n return ide in IDE_PATH_MAPPINGS\n}\n","import { Command } from 'commander'\nimport inquirer from 'inquirer'\nimport chalk from 'chalk'\nimport { getLocale, saveLocale, getSupportedLocales, getLocaleName, type Locale } from '../config/locale.js'\nimport { t } from '../i18n/index.js'\nimport { logger } from '../utils/logger.js'\n\n/**\n * acp locale 命令\n * 切换 CLI 语言\n */\n\nexport const localeCommand = new Command('locale')\n .description('切换 CLI 语言 / Switch CLI language')\n .action(async () => {\n try {\n // 获取当前语言\n const currentLocale = await getLocale()\n \n // 显示标题\n const title = await t('locale.title')\n logger.title(title)\n\n // 显示当前语言\n const currentText = await t('locale.current')\n console.log(chalk.gray(`${currentText}: `) + chalk.cyan(getLocaleName(currentLocale)))\n console.log()\n\n // 选择新语言\n const supportedLocales = getSupportedLocales()\n const selectText = await t('locale.selectLanguage')\n \n const { newLocale } = await inquirer.prompt([\n {\n type: 'list',\n name: 'newLocale',\n message: selectText,\n choices: supportedLocales.map(locale => ({\n name: locale === currentLocale \n ? chalk.cyan(`${getLocaleName(locale)} (当前 / Current)`)\n : getLocaleName(locale),\n value: locale\n })),\n default: currentLocale\n }\n ])\n\n // 如果选择的是当前语言,则不做任何操作\n if (newLocale === currentLocale) {\n logger.info(`${await t('locale.current')}: ${getLocaleName(currentLocale)}`)\n return\n }\n\n // 保存新语言\n await saveLocale(newLocale as Locale)\n\n // 显示成功消息(使用新语言)\n // 注意:这里需要手动构造消息,因为 t() 函数还在使用旧语言缓存\n if (newLocale === 'zh-CN') {\n logger.success(`语言已切换为 ${getLocaleName(newLocale)}`)\n console.log(chalk.gray('\\n提示: 已生效,新命令将使用所选语言\\n'))\n } else {\n logger.success(`Language switched to ${getLocaleName(newLocale)}`)\n console.log(chalk.gray('\\nTip: Changes take effect immediately for new commands\\n'))\n }\n\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`${await t('locale.failed')}: ${error.message}`)\n }\n process.exit(1)\n }\n })\n","import { Command } from 'commander'\nimport inquirer from 'inquirer'\nimport chalk from 'chalk'\nimport ora from 'ora'\nimport axios from 'axios'\nimport { spawnSync } from 'child_process'\nimport { logger, CLIError } from '../utils/logger.js'\nimport { t } from '../i18n/index.js'\n\n/**\n * acp update 命令\n * 检查并更新 ACP CLI 到最新版本\n */\n\n// 版本号在构建时注入\n// @ts-ignore - 构建时通过 tsup define 注入\nconst currentVersion = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0-dev'\nconst packageName = '@ai-config-plaza/acp-cli'\n\ntype UpdateTarget = 'global' | 'local'\n\nfunction getAvailablePkgManagers(): string[] {\n const managers = ['pnpm', 'npm', 'yarn']\n const available: string[] = []\n for (const m of managers) {\n const res = spawnSync(m, ['--version'], { stdio: 'pipe', shell: true })\n if (res.status === 0) available.push(m)\n }\n return available\n}\n\nfunction runUpdate(target: UpdateTarget, manager: string): number {\n const isGlobal = target === 'global'\n let args: string[] = []\n\n if (manager === 'pnpm') {\n args = isGlobal\n ? ['add', '-g', `${packageName}@latest`]\n : ['add', `${packageName}@latest`]\n } else if (manager === 'npm') {\n args = isGlobal\n ? ['install', '-g', `${packageName}@latest`]\n : ['install', `${packageName}@latest`, '--save']\n } else if (manager === 'yarn') {\n args = isGlobal\n ? ['global', 'add', `${packageName}@latest`]\n : ['add', `${packageName}@latest`]\n } else {\n return 1\n }\n\n const execSpinner = ora().start()\n execSpinner.text = manager + ' ' + args.join(' ')\n\n const res = spawnSync(manager, args, { stdio: 'inherit', shell: true })\n execSpinner.stop()\n return res.status ?? 1\n}\n\nexport const updateCommand = new Command('update')\n .description('更新 ACP CLI 到最新版本 / Update ACP CLI to latest version')\n .option('-t, --target <target>', '更新目标 (global|local) / Update target', 'global')\n .action(async (options) => {\n try {\n logger.title(await t('update.title'))\n\n // 显示当前版本\n logger.info(`${await t('update.currentVersion')}: ${chalk.cyan(currentVersion)}`)\n\n // 查询 npm 最新版本\n const spinner = ora(await t('update.checkingLatest')).start()\n let latestVersion = ''\n try {\n const resp = await axios.get(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`)\n latestVersion = resp.data?.version || ''\n } catch (e) {\n spinner.fail(await t('update.fetchFailed'))\n throw new CLIError(await t('update.fetchFailed'), 'FETCH_LATEST_FAILED')\n }\n\n spinner.stop()\n if (!latestVersion) {\n throw new CLIError(await t('update.fetchFailed'), 'LATEST_EMPTY')\n }\n\n logger.info(`${await t('update.latestVersion')}: ${chalk.cyan(latestVersion)}`)\n\n if (currentVersion === latestVersion) {\n logger.success(await t('update.alreadyLatest'))\n return\n }\n\n // 选择更新目标\n const target: UpdateTarget = ['global', 'local'].includes(options.target)\n ? options.target\n : (await (async () => {\n const { targetSel } = await inquirer.prompt([\n {\n type: 'list',\n name: 'targetSel',\n message: await t('update.selectTarget'),\n choices: [\n { name: await t('update.targets.global'), value: 'global' },\n { name: await t('update.targets.local'), value: 'local' }\n ],\n default: 'global'\n }\n ])\n return targetSel as UpdateTarget\n })())\n\n // 检测包管理器\n const managers = getAvailablePkgManagers()\n if (managers.length === 0) {\n throw new CLIError(await t('update.noPkgManager'), 'NO_PKG_MANAGER', [\n '安装 pnpm 或 npm 后重试',\n 'https://pnpm.io/installation'\n ])\n }\n\n let manager = managers[0]\n if (managers.length > 1) {\n const { pm } = await inquirer.prompt([\n {\n type: 'list',\n name: 'pm',\n message: await t('update.selectPkgManager'),\n choices: managers.map(m => ({ name: m, value: m })),\n default: manager\n }\n ])\n manager = pm\n }\n\n logger.step(await t('update.executing', { manager }))\n const code = runUpdate(target, manager)\n if (code === 0) {\n logger.success(await t('update.success'))\n logger.info(await t('update.verifyHint'))\n } else {\n throw new CLIError(await t('update.failed'), 'UPDATE_FAILED')\n }\n } catch (error) {\n if (error instanceof Error) {\n logger.error(error.message)\n }\n process.exit(1)\n }\n })\n"],"mappings":";;;AAEA,SAAS,WAAAA,gBAAe;AACxB,OAAOC,YAAW;;;ACHlB,SAAS,eAAe;AACxB,OAAO,cAAc;AACrB,OAAOC,YAAW;;;ACFlB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAOf,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAEzB,IAAM,aAAa,KAAK,KAAK,GAAG,QAAQ,GAAG,MAAM;AACjD,IAAM,aAAa,KAAK,KAAK,YAAY,OAAO;AAChD,IAAM,gBAAgB,KAAK,KAAK,YAAY,UAAU;AAKtD,eAAsB,WAAmC;AAEvD,QAAM,WAAW,QAAQ,IAAI,aAAa;AAC1C,MAAI,UAAU,KAAK,GAAG;AACpB,WAAO,SAAS,KAAK;AAAA,EACvB;AAGA,MAAI;AACF,QAAI,MAAM,GAAG,WAAW,UAAU,GAAG;AACnC,YAAM,QAAQ,MAAM,GAAG,SAAS,YAAY,OAAO;AACnD,aAAO,MAAM,KAAK,KAAK;AAAA,IACzB;AAAA,EACF,SAAS,OAAO;AAAA,EAEhB;AAEA,SAAO;AACT;AAKA,eAAsB,UAAU,OAA8B;AAC5D,MAAI,CAAC,OAAO,KAAK,GAAG;AAClB,UAAM,IAAI,MAAM,gCAAY;AAAA,EAC9B;AAGA,QAAM,GAAG,UAAU,UAAU;AAG7B,QAAM,GAAG,UAAU,YAAY,MAAM,KAAK,GAAG,OAAO;AACtD;AAcA,eAAsB,aAA+B;AACnD,QAAM,QAAQ,MAAM,SAAS;AAC7B,SAAO,UAAU,QAAQ,MAAM,SAAS;AAC1C;AAKA,eAAsB,aAA8B;AAElD,QAAM,aAAa,QAAQ,IAAI,gBAAgB;AAC/C,MAAI,YAAY,KAAK,GAAG;AACtB,WAAO,WAAW,KAAK;AAAA,EACzB;AAGA,MAAI;AACF,QAAI,MAAM,GAAG,WAAW,aAAa,GAAG;AACtC,YAAM,UAAU,MAAM,GAAG,SAAS,eAAe,OAAO;AACxD,UAAI,QAAQ,KAAK,GAAG;AAClB,eAAO,QAAQ,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAAA,EAEhB;AAGA,SAAO;AACT;AAKA,eAAsB,YAAY,SAAgC;AAChE,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,UAAM,IAAI,MAAM,mCAAe;AAAA,EACjC;AAGA,MAAI;AACF,QAAI,IAAI,QAAQ,KAAK,CAAC;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI,MAAM,uFAA2B;AAAA,EAC7C;AAGA,QAAM,GAAG,UAAU,UAAU;AAG7B,QAAM,GAAG,UAAU,eAAe,QAAQ,KAAK,GAAG,OAAO;AAC3D;AAcA,eAAsB,oBAAmC;AACvD,QAAM,GAAG,UAAU,UAAU;AAG7B,MAAI,CAAE,MAAM,GAAG,WAAW,aAAa,GAAI;AACzC,UAAM,YAAY,gBAAgB;AAAA,EACpC;AACF;;;AC3IA,OAAO,WAAW;;;ACAlB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AASf,IAAM,iBAAiB;AACvB,IAAM,iBAAyB;AAE/B,IAAMC,cAAaF,MAAK,KAAKC,IAAG,QAAQ,GAAG,MAAM;AACjD,IAAM,cAAcD,MAAK,KAAKE,aAAY,QAAQ;AAKlD,eAAsB,YAA6B;AAEjD,QAAM,YAAY,QAAQ,IAAI,cAAc;AAC5C,MAAI,aAAa,cAAc,SAAS,GAAG;AACzC,WAAO;AAAA,EACT;AAGA,MAAI;AACF,QAAI,MAAMH,IAAG,WAAW,WAAW,GAAG;AACpC,YAAM,UAAU,MAAMA,IAAG,SAAS,aAAa,OAAO,GAAG,KAAK;AAC9D,UAAI,cAAc,MAAM,GAAG;AACzB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAAA,EAEhB;AAGA,SAAO;AACT;AAKA,eAAsB,WAAW,QAA+B;AAC9D,MAAI,CAAC,cAAc,MAAM,GAAG;AAC1B,UAAM,IAAI,MAAM,yCAAW,MAAM,EAAE;AAAA,EACrC;AAGA,QAAMA,IAAG,UAAUG,WAAU;AAG7B,QAAMH,IAAG,UAAU,aAAa,QAAQ,OAAO;AACjD;AAKA,SAAS,cAAc,QAAyB;AAC9C,SAAO,WAAW,WAAW,WAAW;AAC1C;AAKO,SAAS,sBAAgC;AAC9C,SAAO,CAAC,SAAS,OAAO;AAC1B;AAKO,SAAS,cAAc,QAAwB;AACpD,QAAM,QAAgC;AAAA,IACpC,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACA,SAAO,MAAM,MAAM;AACrB;;;AC7EO,IAAM,OAAO;AAAA;AAAA,EAElB,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AAAA;AAAA,EAGA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAGA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,eAAe;AAAA,MACb,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,KAAK;AAAA,IACP;AAAA,IACA,cAAc;AAAA,IACd,aAAa;AAAA,IACb,WAAW;AAAA,IACX,SAAS;AAAA,IACT,mBAAmB;AAAA,IACnB,WAAW;AAAA,IACX,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,cAAc;AAAA,IACd,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,IACT,oBAAoB;AAAA,IACpB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,UAAU;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAAA;AAAA,EAGA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AAAA,IACA,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AAAA;AAAA,EAGA,OAAO;AAAA,IACL,WAAW;AAAA,IACX,aAAa;AAAA,IACb,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AACF;;;AChIO,IAAM,OAAO;AAAA;AAAA,EAElB,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AAAA;AAAA,EAGA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA;AAAA,EAGA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,eAAe;AAAA,MACb,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,KAAK;AAAA,IACP;AAAA,IACA,cAAc;AAAA,IACd,aAAa;AAAA,IACb,WAAW;AAAA,IACX,SAAS;AAAA,IACT,mBAAmB;AAAA,IACnB,WAAW;AAAA,IACX,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,cAAc;AAAA,IACd,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,IACT,oBAAoB;AAAA,IACpB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,UAAU;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAAA;AAAA,EAGA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AAAA,IACA,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AAAA;AAAA,EAGA,OAAO;AAAA,IACL,WAAW;AAAA,IACX,aAAa;AAAA,IACb,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AACF;;;AC3HA,IAAM,WAAwC;AAAA,EAC5C,SAAS;AAAA,EACT,SAAS;AACX;AAGA,IAAI,gBAA+B;AACnC,IAAI,kBAAsC;AAK1C,eAAe,WAA0B;AACvC,MAAI,CAAC,eAAe;AAClB,oBAAgB,MAAM,UAAU;AAChC,sBAAkB,SAAS,aAAa;AAAA,EAC1C;AACF;AAQA,eAAsB,EAAE,KAAa,QAA2D;AAC9F,QAAM,SAAS;AAGf,QAAM,OAAO,IAAI,MAAM,GAAG;AAC1B,MAAI,QAAa;AAEjB,aAAW,KAAK,MAAM;AACpB,QAAI,SAAS,OAAO,UAAU,YAAY,KAAK,OAAO;AACpD,cAAQ,MAAM,CAAC;AAAA,IACjB,OAAO;AAEL,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ;AACV,WAAO,MAAM,QAAQ,cAAc,CAAC,OAAO,aAAa;AACtD,aAAO,YAAY,SAAS,OAAO,OAAO,QAAQ,CAAC,IAAI;AAAA,IACzD,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AJvDA,IAAM,UAAU;AAAA,EACd,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AACd;AAEO,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA,EAIpB,MAAM,CAAC,YAAoB;AACzB,YAAQ,IAAI,MAAM,KAAK,QAAQ,IAAI,IAAI,MAAM,OAAO;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,CAAC,YAAoB;AAC5B,YAAQ,IAAI,MAAM,MAAM,QAAQ,IAAI,IAAI,MAAM,MAAM,MAAM,OAAO,CAAC;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,CAAC,YAAoB;AAC5B,YAAQ,IAAI,MAAM,OAAO,QAAQ,OAAO,IAAI,MAAM,MAAM,OAAO,OAAO,CAAC;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,CAAC,YAAoB;AAC1B,YAAQ,MAAM,MAAM,IAAI,QAAQ,KAAK,IAAI,MAAM,MAAM,IAAI,OAAO,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,CAAC,YAAoB;AACzB,YAAQ,IAAI,MAAM,KAAK,QAAQ,UAAU,IAAI,MAAM,MAAM,KAAK,OAAO,CAAC;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,CAAC,YAAoB;AAC1B,YAAQ,IAAI,OAAO,MAAM,KAAK,UAAU,OAAO,IAAI,IAAI;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,CAAC,YAAoB;AACxB,YAAQ,IAAI,OAAO;AAAA,EACrB;AACF;AAKO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC,YACE,SACO,MACA,aACP;AACA,UAAM,OAAO;AAHN;AACA;AAGP,SAAK,OAAO;AAAA,EACd;AACF;AAKA,eAAsB,YAAY,OAA+B;AAC/D,UAAQ,MAAM;AAEd,MAAI,iBAAiB,UAAU;AAC7B,WAAO,MAAM,MAAM,OAAO;AAE1B,QAAI,MAAM,MAAM;AACd,YAAM,gBAAgB,MAAM,EAAE,iBAAiB;AAC/C,cAAQ,IAAI,MAAM,KAAK,GAAG,aAAa,IAAI,MAAM,IAAI,EAAE,CAAC;AAAA,IAC1D;AAEA,QAAI,MAAM,aAAa,QAAQ;AAC7B,YAAM,kBAAkB,MAAM,EAAE,mBAAmB;AACnD,cAAQ,IAAI,MAAM,OAAO,KAAK;AAAA,EAAK,eAAe;AAAA,CAAI,CAAC;AACvD,YAAM,YAAY,QAAQ,CAAC,YAAY,UAAU;AAC/C,gBAAQ,IAAI,MAAM,KAAK,KAAK,QAAQ,CAAC,KAAK,UAAU,EAAE,CAAC;AAAA,MACzD,CAAC;AAAA,IACH;AAAA,EACF,WAAW,iBAAiB,OAAO;AACjC,WAAO,MAAM,MAAM,OAAO;AAE1B,QAAI,QAAQ,IAAI,OAAO;AACrB,cAAQ,IAAI,MAAM,KAAK,OAAO,MAAM,KAAK,CAAC;AAAA,IAC5C;AAAA,EACF,OAAO;AACL,WAAO,MAAM,MAAM,EAAE,oBAAoB,CAAC;AAAA,EAC5C;AAEA,QAAM,eAAe,MAAM,EAAE,gBAAgB;AAC7C,UAAQ;AAAA,IACN,MAAM,KAAK;AAAA,EAAK,YAAY,GAAG,IAC7B,MAAM,KAAK,UAAU,0CAA0C;AAAA,EACnE;AACA,UAAQ,IAAI;AACd;;;AF1GO,IAAM,eAAe,IAAI,QAAQ,OAAO,EAC5C,YAAY,yGAA4D,EACxE,OAAO,YAAY;AAClB,MAAI;AACF,WAAO,MAAM,MAAM,EAAE,aAAa,CAAC;AAGnC,UAAM,kBAAkB;AAGxB,UAAM,gBAAgB,MAAM,SAAS;AACrC,QAAI,eAAe;AACjB,YAAM,EAAE,UAAU,IAAI,MAAM,SAAS,OAAO;AAAA,QAC1C;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,MAAM,EAAE,uBAAuB;AAAA,UACxC,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAED,UAAI,CAAC,WAAW;AACd,eAAO,KAAK,MAAM,EAAE,iBAAiB,CAAC;AACtC;AAAA,MACF;AAAA,IACF;AAGA,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,OAAO;AAAA,MACtC;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,MAAM,EAAE,kBAAkB;AAAA,QACnC,UAAU,OAAO,UAAkB;AACjC,cAAI,CAAC,MAAM,KAAK,GAAG;AACjB,mBAAO,MAAM,EAAE,kBAAkB;AAAA,UACnC;AACA,cAAI,MAAM,KAAK,EAAE,SAAS,IAAI;AAC5B,mBAAO,MAAM,EAAE,oBAAoB;AAAA,UACrC;AACA,iBAAO;AAAA,QACT;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAGD,UAAM,UAAU,KAAK;AAErB,WAAO,QAAQ,MAAM,EAAE,eAAe,CAAC;AACvC,YAAQ,IAAII,OAAM,KAAK,OAAO,MAAM,EAAE,YAAY,IAAI,IAAI,CAAC;AAAA,EAC7D,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,aAAO,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,KAAK,MAAM,OAAO,EAAE;AAAA,IAC7D;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;;;AOrEH,SAAS,WAAAC,gBAAe;AACxB,OAAOC,eAAc;AACrB,OAAOC,YAAW;AAClB,OAAO,SAAS;;;ACHhB,OAAO,WAA0C;AAcjD,IAAM,YAAN,MAAgB;AAAA,EACN;AAAA,EACA;AAAA,EAER,cAAc;AAEZ,SAAK,iBAAiB,WAAW;AAEjC,SAAK,SAAS,MAAM,OAAO;AAAA,MACzB,SAAS;AAAA,MACT,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,IACF,CAAC;AAGD,SAAK,OAAO,aAAa,QAAQ,IAAI,OAAO,WAAW;AAErD,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO,UAAU,MAAM,KAAK;AAAA,MAC9B;AAGA,YAAM,QAAQ,MAAM,SAAS;AAC7B,UAAI,OAAO;AACT,eAAO,QAAQ,aAAa,IAAI;AAAA,MAClC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,SAAK,OAAO,aAAa,SAAS;AAAA,MAChC,CAAC,aAAa;AAAA,MACd,CAAC,UAAsB;AACrB,YAAI,MAAM,UAAU;AAClB,gBAAM,SAAS,MAAM,SAAS;AAC9B,gBAAM,UAAW,MAAM,SAAS,MAAc,WAAW,MAAM;AAE/D,cAAI,WAAW,KAAK;AAClB,kBAAM,IAAI,MAAM,+EAAwB;AAAA,UAC1C,WAAW,WAAW,KAAK;AACzB,kBAAM,IAAI,MAAM,iFAAqB;AAAA,UACvC,WAAW,WAAW,KAAK;AACzB,kBAAM,IAAI,MAAM,kDAAU;AAAA,UAC5B,WAAW,UAAU,KAAK;AACxB,kBAAM,IAAI,MAAM,mCAAU,MAAM,MAAM,OAAO,EAAE;AAAA,UACjD,OAAO;AACL,kBAAM,IAAI,MAAM,6BAAS,MAAM,MAAM,OAAO,EAAE;AAAA,UAChD;AAAA,QACF,WAAW,MAAM,SAAS;AACxB,gBAAM,IAAI,MAAM,0EAAc;AAAA,QAChC,OAAO;AACL,gBAAM,IAAI,MAAM,yCAAW,MAAM,OAAO,EAAE;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,QAAmD;AACpE,UAAM,SAAS,SAAS,EAAE,OAAO,IAAI,CAAC;AACtC,UAAM,WAAW,MAAM,KAAK,OAAO;AAAA,MACjC;AAAA,MACA,EAAE,OAAO;AAAA,IACX;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,IAA4C;AAChE,UAAM,WAAW,MAAM,KAAK,OAAO;AAAA,MACjC,sBAAsB,EAAE;AAAA,IAC1B;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAiD;AACrD,UAAM,WAAW,MAAM,KAAK,OAAO;AAAA,MACjC;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,IAA+C;AAChE,UAAM,WAAW,MAAM,KAAK,OAAO;AAAA,MACjC,mBAAmB,EAAE;AAAA,IACvB;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAA6C;AACjD,UAAM,WAAW,MAAM,KAAK,OAAO;AAAA,MACjC;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,IAA0C;AAC5D,UAAM,WAAW,MAAM,KAAK,OAAO;AAAA,MACjC,oBAAoB,EAAE;AAAA,IACxB;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAA6C;AACjD,UAAM,WAAW,MAAM,KAAK,OAAO;AAAA,MACjC;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,IAA6C;AAC5D,UAAM,WAAW,MAAM,KAAK,OAAO;AAAA,MACjC,iBAAiB,EAAE;AAAA,IACrB;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,KAA8B;AACjD,UAAM,WAAW,MAAM,KAAK,OAAO,IAAiB,KAAK;AAAA,MACvD,cAAc;AAAA,IAChB,CAAC;AAED,WAAO,OAAO,KAAK,SAAS,IAAI;AAAA,EAClC;AACF;AAGO,IAAM,YAAY,IAAI,UAAU;;;ACjJhC,SAAS,SACd,OACA,SACqB;AACrB,QAAM,EAAE,MAAM,SAAS,IAAI;AAC3B,QAAM,QAAQ,MAAM;AACpB,QAAM,aAAa,KAAK,KAAK,QAAQ,QAAQ;AAC7C,QAAM,cAAc,OAAO,KAAK;AAChC,QAAM,WAAW,aAAa;AAE9B,SAAO;AAAA,IACL,OAAO,MAAM,MAAM,YAAY,QAAQ;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,OAAO;AAAA,IAChB,SAAS,OAAO;AAAA,EAClB;AACF;AAKO,SAAS,aACd,OACA,OACK;AACL,MAAI,CAAC,MAAM,KAAK,GAAG;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,YAAY,EAAE,KAAK;AAC5C,SAAO,MAAM;AAAA,IAAO,CAAC,SACnB,KAAK,KAAK,YAAY,EAAE,SAAS,UAAU;AAAA,EAC7C;AACF;;;AC1DA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAOC,YAAW;AAClB,OAAOC,eAAc;;;ACHrB,SAAS,eAAe;AAWjB,IAAM,oBAAuD;AAAA,EAClE,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,WAAW;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AACF;AAKA,SAAS,WAAWC,OAAsB;AACxC,MAAIA,MAAK,WAAW,GAAG,GAAG;AACxB,WAAOA,MAAK,QAAQ,KAAK,QAAQ,CAAC;AAAA,EACpC;AACA,SAAOA;AACT;AAKO,SAAS,kBAAkB,KAAgC;AAChE,QAAM,UAAU,kBAAkB,GAAG;AACrC,SAAO;AAAA,IACL,SAAS,WAAW,QAAQ,OAAO;AAAA,IACnC,QAAQ,WAAW,QAAQ,MAAM;AAAA,IACjC,KAAK,WAAW,QAAQ,GAAG;AAAA,IAC3B,QAAQ,WAAW,QAAQ,MAAM;AAAA,EACnC;AACF;;;ADlDA,eAAsB,cACpB,UACA,SACe;AACf,QAAM,EAAE,KAAK,UAAU,IAAI;AAC3B,QAAM,cAAc,kBAAkB,GAAG;AAEzC,SAAO,MAAM,mDAAcC,OAAM,KAAK,SAAS,IAAI,CAAC,EAAE;AAGtD,MAAI,SAAS,aAAa;AACxB,UAAM;AAAA,MACJ,SAAS,YAAY;AAAA,MACrB,YAAY;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,eAAe,QAAQ;AAClC,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,YAAY,QAAQ;AAC/B,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,QAAQ,QAAQ;AAC3B,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ;AAAA,kCAAYA,OAAM,KAAK,SAAS,IAAI,CAAC,iCAAQ;AAC9D;AAKA,eAAsB,iBACpB,SACA,cACA,WACe;AAEf,QAAM,WAAWC,MAAK,WAAW,YAAY,IACzC,eACAA,MAAK,KAAK,WAAW,YAAY;AAErC,SAAO,KAAK,oCAAgBD,OAAM,KAAK,YAAY,CAAC,EAAE;AAGtD,QAAM,SAAS,MAAME,IAAG,WAAW,QAAQ;AAC3C,MAAI,QAAQ;AACV,UAAM,EAAE,UAAU,IAAI,MAAMC,UAAS,OAAO;AAAA,MAC1C;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,gBAAMH,OAAM,KAAK,YAAY,CAAC;AAAA,QACvC,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAED,QAAI,CAAC,WAAW;AACd,aAAO,QAAQ,iBAAO,YAAY,EAAE;AACpC;AAAA,IACF;AAAA,EACF;AAGA,QAAME,IAAG,UAAUD,MAAK,QAAQ,QAAQ,CAAC;AACzC,QAAMC,IAAG,UAAU,UAAU,SAAS,OAAO;AAE7C,SAAO,QAAQ,uBAAQ,YAAY,EAAE;AACvC;AAKA,eAAsB,aACpB,SACA,YACA,WACe;AAEf,QAAM,iBAAiBD,MAAK,WAAW,UAAU,IAC7C,aACAA,MAAK,KAAK,WAAW,UAAU;AAEnC,SAAO,KAAK,gBAAM,QAAQ,MAAM,sCAAkBD,OAAM,KAAK,UAAU,CAAC,EAAE;AAG1E,QAAME,IAAG,UAAU,cAAc;AAEjC,aAAW,UAAU,SAAS;AAE5B,UAAM,WAAW,iBAAiB,OAAO,IAAI,IAAI;AACjD,UAAM,WAAWD,MAAK,KAAK,gBAAgB,QAAQ;AAGnD,UAAM,SAAS,MAAMC,IAAG,WAAW,QAAQ;AAC3C,QAAI,QAAQ;AACV,YAAM,EAAE,UAAU,IAAI,MAAMC,UAAS,OAAO;AAAA,QAC1C;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,UAAUH,OAAM,KAAK,QAAQ,CAAC;AAAA,UACvC,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAED,UAAI,CAAC,WAAW;AACd,eAAO,QAAQ,iBAAO,QAAQ,EAAE;AAChC;AAAA,MACF;AAAA,IACF;AAGA,UAAME,IAAG,UAAU,UAAU,OAAO,SAAS,OAAO;AACpD,WAAO,QAAQ,uBAAQD,MAAK,KAAK,YAAY,QAAQ,CAAC,EAAE;AAAA,EAC1D;AACF;AAKA,eAAsB,gBACpB,YACA,SACA,WACe;AAEf,MAAI,CAAC,WAAW,YAAY,IAAI;AAC9B,WAAO,QAAQ,wEAA2B;AAC1C;AAAA,EACF;AAGA,QAAM,WAAWA,MAAK,WAAW,OAAO,IACpC,UACAA,MAAK,KAAK,WAAW,OAAO;AAEhC,SAAO,KAAK,kCAAcD,OAAM,KAAK,OAAO,CAAC,EAAE;AAG/C,QAAM,aAAkC,CAAC;AAEzC,aAAW,aAAa,YAAY;AAClC,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,UAAU,UAAU;AAE9C,iBAAW,UAAU,IAAI,IAAI;AAAA,IAC/B,SAAS,OAAO;AACd,aAAO,QAAQ,oBAAU,UAAU,IAAI,mDAAW;AAAA,IACpD;AAAA,EACF;AAGA,QAAM,SAAS,MAAME,IAAG,WAAW,QAAQ;AAC3C,MAAI,QAAQ;AACV,UAAM,EAAE,UAAU,IAAI,MAAMC,UAAS,OAAO;AAAA,MAC1C;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,gBAAMH,OAAM,KAAK,OAAO,CAAC;AAAA,QAClC,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAED,QAAI,CAAC,WAAW;AACd,aAAO,QAAQ,iBAAO,OAAO,EAAE;AAC/B;AAAA,IACF;AAAA,EACF;AAGA,QAAME,IAAG,UAAUD,MAAK,QAAQ,QAAQ,CAAC;AAGzC,MAAI,QAAQ,SAAS,OAAO,GAAG;AAE7B,UAAM,cAAc,iBAAiB,UAAU;AAC/C,UAAMC,IAAG,UAAU,UAAU,aAAa,OAAO;AAAA,EACnD,OAAO;AAEL,QAAI;AAGJ,QAAI,QAAQ,SAAS,SAAS,GAAG;AAC/B,qBAAe;AAAA,QACb,SAAS;AAAA,MACX;AAAA,IACF,OAAO;AACL,qBAAe;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,UAAMA,IAAG,UAAU,UAAU,KAAK,UAAU,cAAc,MAAM,CAAC,GAAG,OAAO;AAAA,EAC7E;AAEA,SAAO,QAAQ,uBAAQ,OAAO,EAAE;AAClC;AAKA,SAAS,iBAAiB,YAAyC;AACjE,MAAI,cAAc;AAElB,aAAW,CAAC,YAAY,MAAM,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC7D,mBAAe,gBAAgB,UAAU;AAAA;AAGzC,QAAI,OAAO,SAAS;AAClB,qBAAe,aAAa,KAAK,UAAU,OAAO,OAAO,CAAC;AAAA;AAAA,IAC5D;AAGA,QAAI,OAAO,QAAQ,MAAM,QAAQ,OAAO,IAAI,GAAG;AAC7C,YAAM,UAAU,OAAO,KAAK,IAAI,CAAC,QAAgB,KAAK,UAAU,GAAG,CAAC,EAAE,KAAK,IAAI;AAC/E,qBAAe,WAAW,OAAO;AAAA;AAAA,IACnC;AAGA,QAAI,OAAO,OAAO,OAAO,OAAO,QAAQ,UAAU;AAChD,YAAM,aAAa,OAAO,QAAQ,OAAO,GAAG;AAC5C,UAAI,WAAW,SAAS,GAAG;AACzB,cAAM,SAAS,WACZ,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,MAAM,KAAK,UAAU,KAAK,CAAC,EAAE,EACzD,KAAK,IAAI;AACZ,uBAAe,WAAW,MAAM;AAAA;AAAA,MAClC;AAAA,IACF;AAEA,mBAAe;AAAA,EACjB;AAEA,SAAO;AACT;AAKA,eAAsB,YACpB,QACA,WACA,WACe;AAEf,QAAM,gBAAgBD,MAAK,WAAW,SAAS,IAC3C,YACAA,MAAK,KAAK,WAAW,SAAS;AAElC,SAAO,KAAK,gBAAM,OAAO,MAAM,qCAAiBD,OAAM,KAAK,SAAS,CAAC,EAAE;AAGvE,QAAME,IAAG,UAAU,aAAa;AAEhC,aAAW,SAAS,QAAQ;AAE1B,UAAM,eAAe,kBAAkB,MAAM,IAAI;AACjD,UAAM,eAAeD,MAAK,KAAK,eAAe,YAAY;AAE1D,WAAO,KAAK,uBAAaD,OAAM,KAAK,MAAM,IAAI,CAAC,EAAE;AAGjD,UAAM,YAAY,MAAME,IAAG,WAAW,YAAY;AAClD,QAAI,WAAW;AACb,YAAM,EAAE,UAAU,IAAI,MAAMC,UAAS,OAAO;AAAA,QAC1C;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,sBAAYH,OAAM,KAAK,YAAY,CAAC;AAAA,UAC7C,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAED,UAAI,CAAC,WAAW;AACd,eAAO,QAAQ,iBAAO,YAAY,EAAE;AACpC;AAAA,MACF;AAAA,IACF;AAGA,UAAME,IAAG,UAAU,YAAY;AAG/B,UAAM,cAAcD,MAAK,KAAK,cAAc,UAAU;AACtD,UAAMC,IAAG,UAAU,aAAa,MAAM,eAAe,OAAO;AAC5D,WAAO,QAAQ,uBAAQD,MAAK,KAAK,WAAW,cAAc,UAAU,CAAC,EAAE;AAGvE,QAAI,MAAM,kBAAkB,MAAM,eAAe,SAAS,GAAG;AAC3D,iBAAW,YAAY,MAAM,gBAAgB;AAE3C,cAAM,mBAAmB,aAAa,SAAS,YAAY;AAC3D,cAAM,mBAAmBA,MAAK,KAAK,cAAc,kBAAkB,SAAS,QAAQ;AAGpF,cAAM,aAAa,MAAMC,IAAG,WAAW,gBAAgB;AACvD,YAAI,YAAY;AACd,gBAAM,EAAE,UAAU,IAAI,MAAMC,UAAS,OAAO;AAAA,YAC1C;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS,gBAAMH,OAAM,KAAKC,MAAK,KAAK,cAAc,gBAAgB,CAAC,CAAC;AAAA,cACpE,SAAS;AAAA,YACX;AAAA,UACF,CAAC;AAED,cAAI,CAAC,WAAW;AACd,mBAAO,QAAQ,iBAAOA,MAAK,KAAK,cAAc,gBAAgB,CAAC,EAAE;AACjE;AAAA,UACF;AAAA,QACF;AAGA,cAAMC,IAAG,UAAUD,MAAK,QAAQ,gBAAgB,CAAC;AAGjD,cAAM,kBAAkB,MAAM,4BAA4B,QAAQ;AAClE,YAAI,OAAO,SAAS,eAAe,GAAG;AACpC,gBAAMC,IAAG,UAAU,kBAAkB,eAAe;AAAA,QACtD,OAAO;AACL,gBAAMA,IAAG,UAAU,kBAAkB,iBAAiB,OAAO;AAAA,QAC/D;AACA,eAAO,QAAQ,uBAAQD,MAAK,KAAK,WAAW,cAAc,gBAAgB,CAAC,EAAE;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,4BAA4B,UAAmD;AAC5F,MAAI,SAAS,UAAU;AACrB,QAAI,CAAC,SAAS,aAAa;AACzB,YAAM,IAAI,MAAM,sBAAY,SAAS,QAAQ,uFAA2B;AAAA,IAC1E;AAEA,WAAO,UAAU,eAAe,SAAS,WAAW;AAAA,EACtD;AAEA,MAAI,OAAO,SAAS,gBAAgB,UAAU;AAC5C,WAAO,SAAS;AAAA,EAClB;AAEA,MAAI,SAAS,aAAa;AACxB,UAAM,QAAQ,MAAM,UAAU,eAAe,SAAS,WAAW;AACjE,WAAO,MAAM,SAAS,OAAO;AAAA,EAC/B;AAEA,QAAM,IAAI,MAAM,sBAAY,SAAS,QAAQ,6CAAU;AACzD;AAKA,SAAS,kBAAkB,MAAsB;AAC/C,SAAO,KACJ,QAAQ,iBAAiB,GAAG,EAC5B,QAAQ,QAAQ,GAAG,EACnB,QAAQ,OAAO,GAAG,EAClB,QAAQ,YAAY,EAAE,EACtB,YAAY;AACjB;AAKA,SAAS,aAAa,cAA8B;AAElD,MAAI,WAAW,aACZ,QAAQ,SAAS,EAAE,EACnB,QAAQ,WAAW,EAAE,EACrB,QAAQ,WAAWA,MAAK,GAAG;AAG9B,MAAIA,MAAK,WAAW,QAAQ,GAAG;AAC7B,eAAWA,MAAK,SAAS,KAAK,QAAQ;AAAA,EACxC;AAGA,MAAI,SAAS,MAAM,YAAY,GAAG;AAChC,eAAW,SAAS,UAAU,CAAC;AAAA,EACjC;AAEA,SAAO;AACT;AAKA,SAAS,iBAAiB,MAAsB;AAC9C,SAAO,KACJ,QAAQ,iBAAiB,GAAG,EAC5B,QAAQ,QAAQ,GAAG,EACnB,QAAQ,OAAO,GAAG,EAClB,YAAY;AACjB;;;AH3ZO,IAAM,eAAe,IAAIG,SAAQ,OAAO,EAC5C,YAAY,4HAAgE,EAC5E,OAAO,qBAAqB,wEAAoD,UAAU,EAC1F,OAAO,mBAAmB,qFAA2E,EACrG,OAAO,oBAAoB,+CAA2B,QAAQ,IAAI,CAAC,EACnE,OAAO,OAAO,YAAY;AACzB,MAAI;AAEF,QAAI,CAAE,MAAM,WAAW,GAAI;AACzB,YAAM,IAAI;AAAA,QACR,MAAM,EAAE,mBAAmB;AAAA,QAC3B;AAAA,QACA,CAAC,MAAM,EAAE,kBAAkB,CAAC;AAAA,MAC9B;AAAA,IACF;AAEA,WAAO,MAAM,MAAM,EAAE,aAAa,CAAC;AAGnC,UAAM,eAAe,MAAM,mBAAmB,QAAQ,IAAI;AAG1D,QAAI,mBAAoC;AAExC,QAAI,iBAAiB,YAAY;AAC/B,yBAAmB,MAAM,uBAAuB;AAAA,IAClD,OAAO;AACL,YAAM,IAAI,SAAS,MAAM,EAAE,oBAAoB,CAAC;AAAA,IAClD;AAEA,QAAI,CAAC,kBAAkB;AACrB,aAAO,KAAK,MAAM,EAAE,mBAAmB,CAAC;AACxC;AAAA,IACF;AAGA,UAAM,MAAM,QAAQ,OAAQ,MAAM,UAAU;AAG5C,UAAM,cAAc,kBAAkB;AAAA,MACpC;AAAA,MACA,WAAW,QAAQ;AAAA,IACrB,CAAC;AAED,UAAM,aAAa,MAAM,EAAE,eAAe;AAC1C,YAAQ,IAAIC,OAAM,KAAK;AAAA,EAAK,UAAU,IAAIA,OAAM,KAAK,QAAQ,GAAG,CAAC;AAAA,CAAI,CAAC;AAAA,EACxE,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,aAAO,MAAM,MAAM,OAAO;AAAA,IAC5B;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAKH,eAAe,mBAAmB,aAA6C;AAC7E,MAAI,eAAe,CAAC,YAAY,SAAS,UAAU,KAAK,EAAE,SAAS,WAAW,GAAG;AAC/E,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,KAAK,IAAI,MAAMC,UAAS,OAAO;AAAA,IACrC;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,MAAM,EAAE,0BAA0B;AAAA,MAC3C,SAAS;AAAA,QACP,EAAE,MAAMD,OAAM,KAAK,MAAM,EAAE,8BAA8B,CAAC,GAAG,OAAO,WAAW;AAAA,QAC/E,EAAE,MAAMA,OAAM,KAAK,MAAM,EAAE,2BAA2B,CAAC,GAAG,OAAO,SAAS,UAAU,KAAK;AAAA,QACzF,EAAE,MAAMA,OAAM,KAAK,MAAM,EAAE,4BAA4B,CAAC,GAAG,OAAO,UAAU,UAAU,KAAK;AAAA,QAC3F,EAAE,MAAMA,OAAM,KAAK,MAAM,EAAE,yBAAyB,CAAC,GAAG,OAAO,OAAO,UAAU,KAAK;AAAA,MACvF;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAKA,eAAe,yBAAmD;AAChE,QAAM,UAAU,IAAI,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM;AAErD,MAAI;AAEF,UAAM,WAAW,MAAM,UAAU,aAAa;AAC9C,YAAQ,KAAK;AAEb,QAAI,CAAC,SAAS,QAAQ,SAAS,KAAK,WAAW,GAAG;AAChD,aAAO,QAAQ,MAAM,EAAE,mBAAmB,CAAC;AAC3C,aAAO;AAAA,IACT;AAEA,WAAO,QAAQ,MAAM,EAAE,sBAAsB,EAAE,OAAO,SAAS,KAAK,OAAO,CAAC,CAAC;AAG7E,UAAM,EAAE,YAAY,IAAI,MAAMC,UAAS,OAAO;AAAA,MAC5C;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,MAAM,EAAE,oBAAoB;AAAA,QACrC,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAED,QAAI,oBAAoB,aAAa,SAAS,MAAM,WAAW;AAE/D,QAAI,kBAAkB,WAAW,GAAG;AAClC,aAAO,QAAQ,MAAM,EAAE,eAAe,CAAC;AACvC,aAAO;AAAA,IACT;AAGA,UAAM,YAAY;AAClB,QAAI,cAAc;AAClB,QAAI,mBAAoC;AAExC,WAAO,CAAC,kBAAkB;AACxB,YAAM,kBAAkB,SAAS,mBAAmB;AAAA,QAClD,MAAM;AAAA,QACN,UAAU;AAAA,MACZ,CAAC;AAGD,YAAM,UAAU,gBAAgB,MAAM,IAAI,CAAC,cAAc;AAAA,QACvD,MAAM,GAAGD,OAAM,KAAK,SAAS,IAAI,CAAC,IAAIA,OAAM,OAAO,IAAI,SAAS,OAAO,QAAQ,EAAE,CAAC,MAAMA,OAAM,KAAK,SAAS,WAAW,CAAC;AAAA,QACxH,OAAO,SAAS;AAAA,QAChB,OAAO,SAAS;AAAA,MAClB,EAAE;AAGF,UAAI,gBAAgB,SAAS;AAC3B,gBAAQ,KAAK;AAAA,UACX,MAAMA,OAAM,OAAO,MAAM,EAAE,gBAAgB,CAAC;AAAA,UAC5C,OAAO;AAAA,UACP,OAAO,MAAM,EAAE,gBAAgB;AAAA,QACjC,CAAC;AAAA,MACH;AAEA,UAAI,gBAAgB,SAAS;AAC3B,gBAAQ,QAAQ;AAAA,UACd,MAAMA,OAAM,OAAO,MAAM,EAAE,gBAAgB,CAAC;AAAA,UAC5C,OAAO;AAAA,UACP,OAAO,MAAM,EAAE,gBAAgB;AAAA,QACjC,CAAC;AAAA,MACH;AAEA,cAAQ,KAAK;AAAA,QACX,MAAMA,OAAM,IAAI,MAAM,EAAE,cAAc,CAAC;AAAA,QACvC,OAAO;AAAA,QACP,OAAO,MAAM,EAAE,cAAc;AAAA,MAC/B,CAAC;AAED,YAAM,EAAE,SAAS,IAAI,MAAMC,UAAS,OAAO;AAAA,QACzC;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,MAAM,EAAE,4BAA4B;AAAA,YAC3C,SAAS;AAAA,YACT,OAAO,gBAAgB;AAAA,UACzB,CAAC;AAAA,UACD;AAAA,UACA,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAED,UAAI,aAAa,cAAc;AAC7B,eAAO;AAAA,MACT,WAAW,aAAa,iBAAiB;AACvC;AAAA,MACF,WAAW,aAAa,iBAAiB;AACvC;AAAA,MACF,OAAO;AAEL,cAAM,gBAAgB,IAAI,MAAM,EAAE,sBAAsB,CAAC,EAAE,MAAM;AACjE,cAAM,iBAAiB,MAAM,UAAU,gBAAgB,QAAQ;AAC/D,sBAAc,KAAK;AAEnB,2BAAmB,eAAe;AAAA,MACpC;AAAA,IACF;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,KAAK,MAAM,EAAE,yBAAyB,CAAC;AAC/C,UAAM;AAAA,EACR;AACF;AAKA,eAAe,YAAgC;AAC7C,QAAM,EAAE,IAAI,IAAI,MAAMA,UAAS,OAAO;AAAA,IACpC;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,MAAM,EAAE,iBAAiB;AAAA,MAClC,SAAS;AAAA,QACP,EAAE,MAAMD,OAAM,KAAK,MAAM,EAAE,uBAAuB,CAAC,GAAG,OAAO,SAAS;AAAA,QACtE,EAAE,MAAMA,OAAM,KAAK,MAAM,EAAE,uBAAuB,CAAC,GAAG,OAAO,SAAS;AAAA,QACtE,EAAE,MAAMA,OAAM,KAAK,MAAM,EAAE,sBAAsB,CAAC,GAAG,OAAO,QAAQ;AAAA,QACpE,EAAE,MAAMA,OAAM,KAAK,MAAM,EAAE,2BAA2B,CAAC,GAAG,OAAO,cAAc;AAAA,QAC/E,EAAE,MAAMA,OAAM,KAAK,MAAM,EAAE,0BAA0B,CAAC,GAAG,OAAO,YAAY;AAAA,QAC5E,EAAE,MAAMA,OAAM,KAAK,MAAM,EAAE,sBAAsB,CAAC,GAAG,OAAO,QAAQ;AAAA,MACtE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;AK1OA,SAAS,WAAAE,gBAAe;AACxB,OAAOC,eAAc;AACrB,OAAOC,YAAW;AAUX,IAAM,gBAAgB,IAAIC,SAAQ,QAAQ,EAC9C,YAAY,qDAAiC,EAC7C,OAAO,YAAY;AAClB,MAAI;AAEF,UAAMC,iBAAgB,MAAM,UAAU;AAGtC,UAAM,QAAQ,MAAM,EAAE,cAAc;AACpC,WAAO,MAAM,KAAK;AAGlB,UAAM,cAAc,MAAM,EAAE,gBAAgB;AAC5C,YAAQ,IAAIC,OAAM,KAAK,GAAG,WAAW,IAAI,IAAIA,OAAM,KAAK,cAAcD,cAAa,CAAC,CAAC;AACrF,YAAQ,IAAI;AAGZ,UAAM,mBAAmB,oBAAoB;AAC7C,UAAM,aAAa,MAAM,EAAE,uBAAuB;AAElD,UAAM,EAAE,UAAU,IAAI,MAAME,UAAS,OAAO;AAAA,MAC1C;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS,iBAAiB,IAAI,aAAW;AAAA,UACvC,MAAM,WAAWF,iBACbC,OAAM,KAAK,GAAG,cAAc,MAAM,CAAC,2BAAiB,IACpD,cAAc,MAAM;AAAA,UACxB,OAAO;AAAA,QACT,EAAE;AAAA,QACF,SAASD;AAAA,MACX;AAAA,IACF,CAAC;AAGD,QAAI,cAAcA,gBAAe;AAC/B,aAAO,KAAK,GAAG,MAAM,EAAE,gBAAgB,CAAC,KAAK,cAAcA,cAAa,CAAC,EAAE;AAC3E;AAAA,IACF;AAGA,UAAM,WAAW,SAAmB;AAIpC,QAAI,cAAc,SAAS;AACzB,aAAO,QAAQ,wCAAU,cAAc,SAAS,CAAC,EAAE;AACnD,cAAQ,IAAIC,OAAM,KAAK,wGAAwB,CAAC;AAAA,IAClD,OAAO;AACL,aAAO,QAAQ,wBAAwB,cAAc,SAAS,CAAC,EAAE;AACjE,cAAQ,IAAIA,OAAM,KAAK,2DAA2D,CAAC;AAAA,IACrF;AAAA,EAEF,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,aAAO,MAAM,GAAG,MAAM,EAAE,eAAe,CAAC,KAAK,MAAM,OAAO,EAAE;AAAA,IAC9D;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;;;ACxEH,SAAS,WAAAE,gBAAe;AACxB,OAAOC,eAAc;AACrB,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAChB,OAAOC,YAAW;AAClB,SAAS,iBAAiB;AAW1B,IAAM,iBAAiB,OAAqC,WAAc;AAC1E,IAAM,cAAc;AAIpB,SAAS,0BAAoC;AAC3C,QAAM,WAAW,CAAC,QAAQ,OAAO,MAAM;AACvC,QAAM,YAAsB,CAAC;AAC7B,aAAW,KAAK,UAAU;AACxB,UAAM,MAAM,UAAU,GAAG,CAAC,WAAW,GAAG,EAAE,OAAO,QAAQ,OAAO,KAAK,CAAC;AACtE,QAAI,IAAI,WAAW,EAAG,WAAU,KAAK,CAAC;AAAA,EACxC;AACA,SAAO;AACT;AAEA,SAAS,UAAU,QAAsB,SAAyB;AAChE,QAAM,WAAW,WAAW;AAC5B,MAAI,OAAiB,CAAC;AAEtB,MAAI,YAAY,QAAQ;AACtB,WAAO,WACH,CAAC,OAAO,MAAM,GAAG,WAAW,SAAS,IACrC,CAAC,OAAO,GAAG,WAAW,SAAS;AAAA,EACrC,WAAW,YAAY,OAAO;AAC5B,WAAO,WACH,CAAC,WAAW,MAAM,GAAG,WAAW,SAAS,IACzC,CAAC,WAAW,GAAG,WAAW,WAAW,QAAQ;AAAA,EACnD,WAAW,YAAY,QAAQ;AAC7B,WAAO,WACH,CAAC,UAAU,OAAO,GAAG,WAAW,SAAS,IACzC,CAAC,OAAO,GAAG,WAAW,SAAS;AAAA,EACrC,OAAO;AACL,WAAO;AAAA,EACT;AAEA,QAAM,cAAcC,KAAI,EAAE,MAAM;AAChC,cAAY,OAAO,UAAU,MAAM,KAAK,KAAK,GAAG;AAEhD,QAAM,MAAM,UAAU,SAAS,MAAM,EAAE,OAAO,WAAW,OAAO,KAAK,CAAC;AACtE,cAAY,KAAK;AACjB,SAAO,IAAI,UAAU;AACvB;AAEO,IAAM,gBAAgB,IAAIC,SAAQ,QAAQ,EAC9C,YAAY,wFAAqD,EACjE,OAAO,yBAAyB,2DAAuC,QAAQ,EAC/E,OAAO,OAAO,YAAY;AACzB,MAAI;AACF,WAAO,MAAM,MAAM,EAAE,cAAc,CAAC;AAGpC,WAAO,KAAK,GAAG,MAAM,EAAE,uBAAuB,CAAC,KAAKC,OAAM,KAAK,cAAc,CAAC,EAAE;AAGhF,UAAM,UAAUF,KAAI,MAAM,EAAE,uBAAuB,CAAC,EAAE,MAAM;AAC5D,QAAI,gBAAgB;AACpB,QAAI;AACF,YAAM,OAAO,MAAMG,OAAM,IAAI,8BAA8B,mBAAmB,WAAW,CAAC,SAAS;AACnG,sBAAgB,KAAK,MAAM,WAAW;AAAA,IACxC,SAAS,GAAG;AACV,cAAQ,KAAK,MAAM,EAAE,oBAAoB,CAAC;AAC1C,YAAM,IAAI,SAAS,MAAM,EAAE,oBAAoB,GAAG,qBAAqB;AAAA,IACzE;AAEA,YAAQ,KAAK;AACb,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI,SAAS,MAAM,EAAE,oBAAoB,GAAG,cAAc;AAAA,IAClE;AAEA,WAAO,KAAK,GAAG,MAAM,EAAE,sBAAsB,CAAC,KAAKD,OAAM,KAAK,aAAa,CAAC,EAAE;AAE9E,QAAI,mBAAmB,eAAe;AACpC,aAAO,QAAQ,MAAM,EAAE,sBAAsB,CAAC;AAC9C;AAAA,IACF;AAGA,UAAM,SAAuB,CAAC,UAAU,OAAO,EAAE,SAAS,QAAQ,MAAM,IACpE,QAAQ,SACP,OAAO,YAAY;AAClB,YAAM,EAAE,UAAU,IAAI,MAAME,UAAS,OAAO;AAAA,QAC1C;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,MAAM,EAAE,qBAAqB;AAAA,UACtC,SAAS;AAAA,YACP,EAAE,MAAM,MAAM,EAAE,uBAAuB,GAAG,OAAO,SAAS;AAAA,YAC1D,EAAE,MAAM,MAAM,EAAE,sBAAsB,GAAG,OAAO,QAAQ;AAAA,UAC1D;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT,GAAG;AAGP,UAAM,WAAW,wBAAwB;AACzC,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI,SAAS,MAAM,EAAE,qBAAqB,GAAG,kBAAkB;AAAA,QACnE;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,UAAU,SAAS,CAAC;AACxB,QAAI,SAAS,SAAS,GAAG;AACvB,YAAM,EAAE,GAAG,IAAI,MAAMA,UAAS,OAAO;AAAA,QACnC;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,MAAM,EAAE,yBAAyB;AAAA,UAC1C,SAAS,SAAS,IAAI,QAAM,EAAE,MAAM,GAAG,OAAO,EAAE,EAAE;AAAA,UAClD,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AACD,gBAAU;AAAA,IACZ;AAEA,WAAO,KAAK,MAAM,EAAE,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AACpD,UAAM,OAAO,UAAU,QAAQ,OAAO;AACtC,QAAI,SAAS,GAAG;AACd,aAAO,QAAQ,MAAM,EAAE,gBAAgB,CAAC;AACxC,aAAO,KAAK,MAAM,EAAE,mBAAmB,CAAC;AAAA,IAC1C,OAAO;AACL,YAAM,IAAI,SAAS,MAAM,EAAE,eAAe,GAAG,eAAe;AAAA,IAC9D;AAAA,EACF,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,aAAO,MAAM,MAAM,OAAO;AAAA,IAC5B;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;;;AdnIH,IAAM,UAAU,OAAqC,WAAc;AAEnE,eAAe,OAAO;AACpB,QAAM,UAAU,IAAIC,SAAQ;AAE5B,UACG,KAAK,KAAK,EACV;AAAA,IACCC,OAAM,KAAK,MAAM,EAAE,iBAAiB,CAAC;AAAA,EACvC,EACC,QAAQ,SAAS,iBAAiB,MAAM,EAAE,aAAa,CAAC,EACxD,WAAW,cAAc,MAAM,EAAE,UAAU,CAAC;AAG/C,UAAQ,WAAW,YAAY;AAC/B,UAAQ,WAAW,YAAY;AAC/B,UAAQ,WAAW,aAAa;AAChC,UAAQ,WAAW,aAAa;AAGhC,UAAQ,GAAG,UAAU,YAAY;AAC/B,YAAQ,IAAIA,OAAM,KAAK,OAAO,MAAM,EAAE,kBAAkB,IAAI,IAAI,CAAC;AACjE,YAAQ,IAAIA,OAAM,KAAK,eAAe,CAAC;AACvC,YAAQ,IAAIA,OAAM,KAAK,eAAe,CAAC;AACvC,YAAQ,IAAIA,OAAM,KAAK,+CAA+C,CAAC;AACvE,YAAQ,IAAIA,OAAM,KAAK,gBAAgB,CAAC;AACxC,YAAQ,IAAIA,OAAM,KAAK,gBAAgB,CAAC;AACxC,YAAQ,IAAI;AAAA,EACd,CAAC;AAGD,MAAI;AACF,UAAM,QAAQ,WAAW,QAAQ,IAAI;AAAA,EACvC,SAAS,OAAO;AACd,UAAM,YAAY,KAAK;AACvB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK;","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,69 +1,69 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ai-config-plaza/acp-cli",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "AI-Config-Plaza CLI 工具 - 统一 AI 编程工具配置管理",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"acp": "
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"bin",
|
|
13
|
-
"dist",
|
|
14
|
-
"README.md",
|
|
15
|
-
"LICENSE"
|
|
16
|
-
],
|
|
17
|
-
"repository": {
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/AIConfigPlaza/acp-cli.git"
|
|
20
|
-
},
|
|
21
|
-
"bugs": {
|
|
22
|
-
"url": "https://github.com/AIConfigPlaza/acp-cli/issues"
|
|
23
|
-
},
|
|
24
|
-
"homepage": "https://github.com/AIConfigPlaza/acp-cli#readme",
|
|
25
|
-
"publishConfig": {
|
|
26
|
-
"access": "public",
|
|
27
|
-
"registry": "https://registry.npmjs.org/"
|
|
28
|
-
},
|
|
29
|
-
"scripts": {
|
|
30
|
-
"dev": "tsx src/index.ts",
|
|
31
|
-
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
32
|
-
"start": "node bin/acp.js",
|
|
33
|
-
"typecheck": "tsc --noEmit",
|
|
34
|
-
"lint": "eslint .",
|
|
35
|
-
"test": "vitest",
|
|
36
|
-
"prepublishOnly": "
|
|
37
|
-
},
|
|
38
|
-
"keywords": [
|
|
39
|
-
"cli",
|
|
40
|
-
"ai",
|
|
41
|
-
"config",
|
|
42
|
-
"scaffolding",
|
|
43
|
-
"mcp",
|
|
44
|
-
"prompt"
|
|
45
|
-
],
|
|
46
|
-
"author": "AIConfigPlaza",
|
|
47
|
-
"license": "MIT",
|
|
48
|
-
"engines": {
|
|
49
|
-
"node": ">=18.0.0"
|
|
50
|
-
},
|
|
51
|
-
"dependencies": {
|
|
52
|
-
"commander": "^12.1.0",
|
|
53
|
-
"inquirer": "^10.2.2",
|
|
54
|
-
"axios": "^1.7.7",
|
|
55
|
-
"chalk": "^5.3.0",
|
|
56
|
-
"ora": "^8.1.0",
|
|
57
|
-
"fs-extra": "^11.2.0",
|
|
58
|
-
"cosmiconfig": "^9.0.0"
|
|
59
|
-
},
|
|
60
|
-
"devDependencies": {
|
|
61
|
-
"@types/fs-extra": "^11.0.4",
|
|
62
|
-
"@types/inquirer": "^9.0.7",
|
|
63
|
-
"@types/node": "^22.8.4",
|
|
64
|
-
"tsup": "^8.3.0",
|
|
65
|
-
"tsx": "^4.19.1",
|
|
66
|
-
"typescript": "^5.6.3",
|
|
67
|
-
"vitest": "^2.1.3"
|
|
68
|
-
}
|
|
69
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-config-plaza/acp-cli",
|
|
3
|
+
"version": "1.0.12",
|
|
4
|
+
"description": "AI-Config-Plaza CLI 工具 - 统一 AI 编程工具配置管理",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"acp": "bin/acp.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"bin",
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/AIConfigPlaza/acp-cli.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/AIConfigPlaza/acp-cli/issues"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/AIConfigPlaza/acp-cli#readme",
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public",
|
|
27
|
+
"registry": "https://registry.npmjs.org/"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"dev": "tsx src/index.ts",
|
|
31
|
+
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
32
|
+
"start": "node bin/acp.js",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"lint": "eslint .",
|
|
35
|
+
"test": "vitest",
|
|
36
|
+
"prepublishOnly": "npm run build && npm run typecheck"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"cli",
|
|
40
|
+
"ai",
|
|
41
|
+
"config",
|
|
42
|
+
"scaffolding",
|
|
43
|
+
"mcp",
|
|
44
|
+
"prompt"
|
|
45
|
+
],
|
|
46
|
+
"author": "AIConfigPlaza",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=18.0.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"commander": "^12.1.0",
|
|
53
|
+
"inquirer": "^10.2.2",
|
|
54
|
+
"axios": "^1.7.7",
|
|
55
|
+
"chalk": "^5.3.0",
|
|
56
|
+
"ora": "^8.1.0",
|
|
57
|
+
"fs-extra": "^11.2.0",
|
|
58
|
+
"cosmiconfig": "^9.0.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/fs-extra": "^11.0.4",
|
|
62
|
+
"@types/inquirer": "^9.0.7",
|
|
63
|
+
"@types/node": "^22.8.4",
|
|
64
|
+
"tsup": "^8.3.0",
|
|
65
|
+
"tsx": "^4.19.1",
|
|
66
|
+
"typescript": "^5.6.3",
|
|
67
|
+
"vitest": "^2.1.3"
|
|
68
|
+
}
|
|
69
|
+
}
|