@wangxiaoerqqq/ccs 2.0.0
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/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/README.md +287 -0
- package/dist/commands/current.d.ts +2 -0
- package/dist/commands/current.d.ts.map +1 -0
- package/dist/commands/current.js +29 -0
- package/dist/commands/current.js.map +1 -0
- package/dist/commands/edit.d.ts +2 -0
- package/dist/commands/edit.d.ts.map +1 -0
- package/dist/commands/edit.js +21 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +47 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +31 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/models.d.ts +2 -0
- package/dist/commands/models.d.ts.map +1 -0
- package/dist/commands/models.js +44 -0
- package/dist/commands/models.js.map +1 -0
- package/dist/commands/set-key.d.ts +2 -0
- package/dist/commands/set-key.d.ts.map +1 -0
- package/dist/commands/set-key.js +51 -0
- package/dist/commands/set-key.js.map +1 -0
- package/dist/commands/switch.d.ts +3 -0
- package/dist/commands/switch.d.ts.map +1 -0
- package/dist/commands/switch.js +83 -0
- package/dist/commands/switch.js.map +1 -0
- package/dist/config/crypto.d.ts +5 -0
- package/dist/config/crypto.d.ts.map +1 -0
- package/dist/config/crypto.js +89 -0
- package/dist/config/crypto.js.map +1 -0
- package/dist/config/manager.d.ts +28 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +188 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/defaults.d.ts +22 -0
- package/dist/providers/defaults.d.ts.map +1 -0
- package/dist/providers/defaults.js +160 -0
- package/dist/providers/defaults.js.map +1 -0
- package/dist/providers/registry.d.ts +20 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +81 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +51 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/platform.d.ts +11 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +50 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/reload.d.ts +4 -0
- package/dist/utils/reload.d.ts.map +1 -0
- package/dist/utils/reload.js +51 -0
- package/dist/utils/reload.js.map +1 -0
- package/package.json +64 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2024-03-25
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release
|
|
13
|
+
- CLI commands:
|
|
14
|
+
- `ccs init` - Initialize configuration
|
|
15
|
+
- `ccs <provider> [model]` - Switch provider and model
|
|
16
|
+
- `ccs model <model>` - Switch model only
|
|
17
|
+
- `ccs set-key <provider> [api-key]` - Set API key
|
|
18
|
+
- `ccs list` / `ccs ls` - List all providers and models
|
|
19
|
+
- `ccs current` - Show current configuration
|
|
20
|
+
- `ccs models [provider]` - List models for a provider
|
|
21
|
+
- `ccs edit` - Open config file for editing
|
|
22
|
+
- `ccs reload` - Send reload signal to Claude Code
|
|
23
|
+
- Supported providers:
|
|
24
|
+
- 阿里百炼 (Aliyun) - Qwen series models
|
|
25
|
+
- 智谱 GLM (Zhipu) - GLM-4/5 series models
|
|
26
|
+
- 火山引擎豆包 (Volc) - Doubao series models
|
|
27
|
+
- DeepSeek - Chat and Reasoner models
|
|
28
|
+
- Moonshot Kimi - Kimi series models
|
|
29
|
+
- MiniMax - abab series models
|
|
30
|
+
- Anthropic - Claude series models
|
|
31
|
+
- Features:
|
|
32
|
+
- Encrypted API key storage using AES-256-CBC
|
|
33
|
+
- Cross-platform support (macOS, Linux, Windows)
|
|
34
|
+
- Hot reload via SIGHUP signal
|
|
35
|
+
- Dynamic provider commands (e.g., `ccs aliyun`, `ccs zhipu`)
|
|
36
|
+
- Machine-specific encryption keys
|
|
37
|
+
|
|
38
|
+
### Security
|
|
39
|
+
|
|
40
|
+
- API keys are encrypted with AES-256-CBC before storage
|
|
41
|
+
- Encryption keys are derived from machine-specific identifiers
|
|
42
|
+
- Secrets file has restricted permissions (0600)
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Future Plans
|
|
47
|
+
|
|
48
|
+
- [ ] Auto-detect rate limit status
|
|
49
|
+
- [ ] Support for more providers via community contributions
|
|
50
|
+
- [ ] API for programmatic access
|
|
51
|
+
- [ ] VS Code extension integration
|
|
52
|
+
- [ ] Configuration sync across devices
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 genzhen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# CCS - Claude Code Switcher
|
|
2
|
+
|
|
3
|
+
一个极简风格的 CLI 工具,用于在 Claude Code 中即时切换 AI 提供商和模型。
|
|
4
|
+
|
|
5
|
+
## 功能特点
|
|
6
|
+
|
|
7
|
+
- **快速切换**: 一条命令即可切换提供商和模型
|
|
8
|
+
- **多提供商支持**: 支持阿里百炼、智谱 GLM、DeepSeek、火山引擎、MiniMax、美团 LongCat 等主流 AI 平台
|
|
9
|
+
- **灵活配置**: 支持提供商和模型两级 env 配置,模型代号与真实模型名分离
|
|
10
|
+
- **安全存储**: API 密钥加密存储在本地
|
|
11
|
+
- **热加载**: 自动发送重载信号,无需重启 Claude Code
|
|
12
|
+
- **跨平台**: 支持 macOS、Linux、Windows
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
ZFfbvTh3Yu
|
|
16
|
+
```bash
|
|
17
|
+
# npm
|
|
18
|
+
npm install -g ccs
|
|
19
|
+
|
|
20
|
+
# 或使用 pnpm
|
|
21
|
+
pnpm add -g ccs
|
|
22
|
+
|
|
23
|
+
# 或使用 yarn
|
|
24
|
+
yarn global add ccs
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 快速开始
|
|
28
|
+
|
|
29
|
+
### 1. 初始化配置
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
ccs init
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
这将引导你设置各个平台的 API 密钥。
|
|
36
|
+
|
|
37
|
+
### 2. 切换提供商
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# 切换到阿里百炼(使用默认模型)
|
|
41
|
+
ccs aliyun
|
|
42
|
+
|
|
43
|
+
# 切换到智谱 GLM 并指定模型
|
|
44
|
+
ccs zhipu glm-5.1
|
|
45
|
+
|
|
46
|
+
# 切换到 DeepSeek
|
|
47
|
+
ccs deepseek
|
|
48
|
+
|
|
49
|
+
# 仅切换模型(保持当前提供商)
|
|
50
|
+
ccs model qwen-max
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. 查看状态
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# 列出所有提供商和模型
|
|
57
|
+
ccs list
|
|
58
|
+
|
|
59
|
+
# 查看当前配置
|
|
60
|
+
ccs current
|
|
61
|
+
|
|
62
|
+
# 查看特定提供商的模型列表
|
|
63
|
+
ccs models zhipu
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 支持的提供商
|
|
67
|
+
|
|
68
|
+
| 提供商 | 命令 | 默认模型 |
|
|
69
|
+
|--------|------|----------|
|
|
70
|
+
| 阿里百炼 | `ccs aliyun` | qwen-turbo |
|
|
71
|
+
| 智谱 GLM | `ccs zhipu` | glm-5.1 |
|
|
72
|
+
| 火山引擎豆包 | `ccs volc` | doubao-pro-32k |
|
|
73
|
+
| DeepSeek | `ccs deepseek` | v4pro |
|
|
74
|
+
| Moonshot Kimi | `ccs moonshot` | kimi-k2.6 |
|
|
75
|
+
| MiniMax | `ccs minimax` | m3 |
|
|
76
|
+
| Anthropic 官方 | `ccs anthropic` | claude-sonnet-4-6 |
|
|
77
|
+
| 美团官方 | `ccs longcat` | longcat-2-preview |
|
|
78
|
+
|
|
79
|
+
## 命令参考
|
|
80
|
+
|
|
81
|
+
### `ccs init`
|
|
82
|
+
|
|
83
|
+
初始化 CCS 配置,交互式引导设置 API 密钥。
|
|
84
|
+
|
|
85
|
+
### `ccs <provider> [model]`
|
|
86
|
+
|
|
87
|
+
切换到指定提供商和模型。
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
ccs aliyun # 切换到阿里百炼(默认模型)
|
|
91
|
+
ccs zhipu glm-5.1 # 切换到智谱 GLM 的 glm-5.1 模型
|
|
92
|
+
ccs minimax m3 # 切换到 MiniMax-M3
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### `ccs model <model>`
|
|
96
|
+
|
|
97
|
+
仅切换模型,保持当前提供商不变。
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
ccs model qwen-max # 切换到 qwen-max 模型
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### `ccs set-key <provider> [api-key]`
|
|
104
|
+
|
|
105
|
+
设置提供商的 API 密钥。
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
ccs set-key zhipu # 交互式输入
|
|
109
|
+
ccs set-key aliyun sk-xxx # 直接设置
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `ccs list` / `ccs ls`
|
|
113
|
+
|
|
114
|
+
列出所有可用的提供商和模型,含模型代号和真实 API 模型名。
|
|
115
|
+
|
|
116
|
+
### `ccs current`
|
|
117
|
+
|
|
118
|
+
显示当前的提供商和模型配置。当代号与真实模型名不同时,额外显示 Real model 行。
|
|
119
|
+
|
|
120
|
+
### `ccs models [provider]`
|
|
121
|
+
|
|
122
|
+
列出提供商的所有可用模型。
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
ccs models # 当前提供商的模型
|
|
126
|
+
ccs models zhipu # 智谱 GLM 的所有模型
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### `ccs edit`
|
|
130
|
+
|
|
131
|
+
打开提供商配置文件进行编辑。
|
|
132
|
+
|
|
133
|
+
### `ccs reload`
|
|
134
|
+
|
|
135
|
+
发送重载信号到 Claude Code 进程。
|
|
136
|
+
|
|
137
|
+
## 配置文件
|
|
138
|
+
|
|
139
|
+
配置文件存储位置:
|
|
140
|
+
|
|
141
|
+
| 平台 | 配置目录 |
|
|
142
|
+
|------|----------|
|
|
143
|
+
| macOS/Linux | `~/.config/ccs/` |
|
|
144
|
+
| Windows | `%APPDATA%\ccs\` |
|
|
145
|
+
|
|
146
|
+
### 文件说明
|
|
147
|
+
|
|
148
|
+
- `providers.json` - 提供商和模型配置
|
|
149
|
+
- `current.json` - 当前选择的提供商和模型
|
|
150
|
+
- `secrets.enc` - 加密存储的 API 密钥
|
|
151
|
+
- `.key` - 本地加密密钥(请勿分享)
|
|
152
|
+
|
|
153
|
+
### providers.json 结构
|
|
154
|
+
|
|
155
|
+
每个提供商可以配置两级 `env`:
|
|
156
|
+
|
|
157
|
+
- **provider 级 env**:所有模型共享的基础环境变量(如 `ANTHROPIC_BASE_URL`)
|
|
158
|
+
- **model 级 env**:覆盖或追加模型专属的环境变量(如 `ENDPOINT_ID`)
|
|
159
|
+
|
|
160
|
+
模型的 `model` 字段为真实 API 模型名,而 key 为用户使用的友好代号:
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"moonshot": {
|
|
165
|
+
"name": "Moonshot Kimi",
|
|
166
|
+
"env": {
|
|
167
|
+
"ANTHROPIC_BASE_URL": "https://api.moonshot.cn/v1"
|
|
168
|
+
},
|
|
169
|
+
"models": {
|
|
170
|
+
"kimi-8k": {
|
|
171
|
+
"name": "Kimi 8K",
|
|
172
|
+
"model": "moonshot-v1-8k",
|
|
173
|
+
"default": true
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
上例中用户使用 `ccs moonshot kimi-8k`,实际写入 `ANTHROPIC_MODEL` 的值为 `moonshot-v1-8k`。
|
|
181
|
+
|
|
182
|
+
模型也可配置 `env` 字段覆盖 provider 级的同名变量(`undefined` 值会被跳过不覆盖):
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"deepseek": {
|
|
187
|
+
"name": "DeepSeek",
|
|
188
|
+
"env": {
|
|
189
|
+
"ANTHROPIC_BASE_URL": "https://api.deepseek.com/anthropic",
|
|
190
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL": "deepseek-v4-pro"
|
|
191
|
+
},
|
|
192
|
+
"models": {
|
|
193
|
+
"deepseek-v4-flash": {
|
|
194
|
+
"name": "DeepSeek V4 Flash",
|
|
195
|
+
"model": "deepseek-v4-flash",
|
|
196
|
+
"env": {
|
|
197
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL": "deepseek-v4-flash"
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
切换 `deepseek-v4-flash` 时,`ANTHROPIC_DEFAULT_OPUS_MODEL` 会被覆盖为 `deepseek-v4-flash`。
|
|
206
|
+
|
|
207
|
+
### 添加自定义提供商
|
|
208
|
+
|
|
209
|
+
编辑 `~/.config/ccs/providers.json`:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"my-provider": {
|
|
214
|
+
"name": "我的提供商",
|
|
215
|
+
"env": {
|
|
216
|
+
"ANTHROPIC_BASE_URL": "https://api.example.com/anthropic"
|
|
217
|
+
},
|
|
218
|
+
"models": {
|
|
219
|
+
"model-1": {
|
|
220
|
+
"name": "Model 1",
|
|
221
|
+
"model": "real-model-name-1",
|
|
222
|
+
"default": true
|
|
223
|
+
},
|
|
224
|
+
"model-2": {
|
|
225
|
+
"name": "Model 2",
|
|
226
|
+
"model": "real-model-name-2",
|
|
227
|
+
"env": {
|
|
228
|
+
"CUSTOM_VAR": "model-specific-value"
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## 热加载机制
|
|
237
|
+
|
|
238
|
+
CCS 支持自动重载 Claude Code 配置:
|
|
239
|
+
|
|
240
|
+
1. 切换提供商后,自动检测 Claude Code 进程
|
|
241
|
+
2. 发送 SIGHUP 信号触发重载
|
|
242
|
+
3. 如使用 Shell wrapper,会话自动继续
|
|
243
|
+
|
|
244
|
+
### Shell Wrapper(推荐)
|
|
245
|
+
|
|
246
|
+
创建 `~/bin/claude-wrapper.sh`:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
#!/bin/bash
|
|
250
|
+
while claude "$@"; [ $? -eq 129 ]; do
|
|
251
|
+
set -- -c
|
|
252
|
+
done
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
然后在终端中使用此脚本启动 Claude Code。
|
|
256
|
+
|
|
257
|
+
## 开发
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# 克隆仓库
|
|
261
|
+
git clone https://gitee.com/xiaoerlangqqq/ccs.git
|
|
262
|
+
cd ccs
|
|
263
|
+
|
|
264
|
+
# 安装依赖
|
|
265
|
+
npm install
|
|
266
|
+
|
|
267
|
+
# 构建
|
|
268
|
+
npm run build
|
|
269
|
+
|
|
270
|
+
# 测试
|
|
271
|
+
npm test
|
|
272
|
+
|
|
273
|
+
# 开发模式(监听文件变化)
|
|
274
|
+
npm run dev
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## 许可证
|
|
278
|
+
|
|
279
|
+
MIT License
|
|
280
|
+
|
|
281
|
+
## 贡献
|
|
282
|
+
|
|
283
|
+
欢迎提交 Issue 和 Pull Request!
|
|
284
|
+
|
|
285
|
+
## 相关项目
|
|
286
|
+
|
|
287
|
+
- [Claude Code](https://github.com/anthropics/claude-code) - Anthropic 官方 CLI 工具
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current.d.ts","sourceRoot":"","sources":["../../src/commands/current.ts"],"names":[],"mappings":"AAOA,wBAAgB,cAAc,IAAI,IAAI,CA4BrC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Current command - show current selection
|
|
2
|
+
import { loadCurrent, initConfig } from '../config/manager.js';
|
|
3
|
+
import { getProviderDisplayName, getModelDisplayName, getRealModelName, hasApiKey } from '../providers/registry.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
export function currentCommand() {
|
|
7
|
+
initConfig();
|
|
8
|
+
const current = loadCurrent();
|
|
9
|
+
logger.title('Current Configuration');
|
|
10
|
+
if (!current.provider) {
|
|
11
|
+
logger.warning('No provider selected');
|
|
12
|
+
logger.info('Run "ccs <provider>" to select a provider');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const providerName = getProviderDisplayName(current.provider);
|
|
16
|
+
const modelName = getModelDisplayName(current.provider, current.model);
|
|
17
|
+
const realModel = getRealModelName(current.provider, current.model);
|
|
18
|
+
const keyStatus = hasApiKey(current.provider)
|
|
19
|
+
? chalk.green('✓ API key set')
|
|
20
|
+
: chalk.red('✗ No API key');
|
|
21
|
+
logger.item('Provider', `${providerName} ${chalk.dim(`(${current.provider})`)}`);
|
|
22
|
+
logger.item('Model', `${modelName} ${chalk.dim(`(${current.model})`)}`);
|
|
23
|
+
if (realModel && realModel !== current.model) {
|
|
24
|
+
logger.item('Real model', realModel);
|
|
25
|
+
}
|
|
26
|
+
logger.item('Status', keyStatus);
|
|
27
|
+
console.log();
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=current.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current.js","sourceRoot":"","sources":["../../src/commands/current.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAE3C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACpH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,cAAc;IAC5B,UAAU,EAAE,CAAC;IAEb,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAE9B,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEtC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,sBAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC3C,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC;QAC9B,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAE9B,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,YAAY,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC,CAAC;IACjF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;IACxE,IAAI,SAAS,IAAI,SAAS,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAEjC,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/commands/edit.ts"],"names":[],"mappings":"AAOA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBjD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Edit command - open config file for editing
|
|
2
|
+
import { getProvidersPath, getConfigDir } from '../utils/platform.js';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
import open from 'open';
|
|
5
|
+
export async function editCommand() {
|
|
6
|
+
const providersPath = getProvidersPath();
|
|
7
|
+
const configDir = getConfigDir();
|
|
8
|
+
logger.info(`Config directory: ${configDir}`);
|
|
9
|
+
logger.info(`Providers file: ${providersPath}`);
|
|
10
|
+
// Try to open with default editor
|
|
11
|
+
try {
|
|
12
|
+
await open(providersPath);
|
|
13
|
+
logger.success('Opened providers.json in default editor');
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// Fallback: show instructions
|
|
17
|
+
logger.info('Could not open editor automatically');
|
|
18
|
+
logger.info(`Please edit: ${providersPath}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/commands/edit.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAG9C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,MAAM,CAAC,IAAI,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;IAC9C,MAAM,CAAC,IAAI,CAAC,mBAAmB,aAAa,EAAE,CAAC,CAAC;IAEhD,kCAAkC;IAClC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,MAAM,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;QAC9B,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,gBAAgB,aAAa,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA+CjD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Init command - initialize CCS configuration
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { initConfig, setApiKey, loadSecrets } from '../config/manager.js';
|
|
4
|
+
import { getAvailableProviders } from '../providers/registry.js';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
export async function initCommand() {
|
|
7
|
+
logger.title('CCS Configuration');
|
|
8
|
+
// Initialize config files
|
|
9
|
+
initConfig();
|
|
10
|
+
const providers = getAvailableProviders();
|
|
11
|
+
const secrets = loadSecrets();
|
|
12
|
+
logger.info('Configuration directory created');
|
|
13
|
+
logger.info('Please enter API keys for the providers you want to use:');
|
|
14
|
+
logger.separator();
|
|
15
|
+
for (const [providerId, config] of Object.entries(providers)) {
|
|
16
|
+
const existingKey = secrets[providerId];
|
|
17
|
+
const { setKey } = await inquirer.prompt([
|
|
18
|
+
{
|
|
19
|
+
type: 'confirm',
|
|
20
|
+
name: 'setKey',
|
|
21
|
+
message: `Set API key for ${config.name}?`,
|
|
22
|
+
default: !existingKey
|
|
23
|
+
}
|
|
24
|
+
]);
|
|
25
|
+
if (setKey) {
|
|
26
|
+
const { apiKey } = await inquirer.prompt([
|
|
27
|
+
{
|
|
28
|
+
type: 'password',
|
|
29
|
+
name: 'apiKey',
|
|
30
|
+
message: `Enter API key for ${config.name}:`,
|
|
31
|
+
mask: '*',
|
|
32
|
+
validate: (input) => input.length > 0 || 'API key cannot be empty'
|
|
33
|
+
}
|
|
34
|
+
]);
|
|
35
|
+
setApiKey(providerId, apiKey);
|
|
36
|
+
logger.success(`API key saved for ${config.name}`);
|
|
37
|
+
}
|
|
38
|
+
else if (existingKey) {
|
|
39
|
+
logger.info(`Using existing API key for ${config.name}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
logger.separator();
|
|
43
|
+
logger.success('CCS initialization complete!');
|
|
44
|
+
logger.info('Run "ccs list" to see available providers');
|
|
45
|
+
logger.info('Run "ccs <provider>" to switch to a provider');
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAE9C,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAa,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAElC,0BAA0B;IAC1B,UAAU,EAAE,CAAC;IAEb,MAAM,SAAS,GAAG,qBAAqB,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAE9B,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC/C,MAAM,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;IACxE,MAAM,CAAC,SAAS,EAAE,CAAC;IAEnB,KAAK,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7D,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAExC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACvC;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,mBAAmB,MAAM,CAAC,IAAI,GAAG;gBAC1C,OAAO,EAAE,CAAC,WAAW;aACtB;SACF,CAAC,CAAC;QAEH,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;gBACvC;oBACE,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE,qBAAqB,MAAM,CAAC,IAAI,GAAG;oBAC5C,IAAI,EAAE,GAAG;oBACT,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,yBAAyB;iBAC3E;aACF,CAAC,CAAC;YAEH,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC9B,MAAM,CAAC,OAAO,CAAC,qBAAqB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;aAAM,IAAI,WAAW,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,8BAA8B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,SAAS,EAAE,CAAC;IACnB,MAAM,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC/C,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IACzD,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAOA,wBAAgB,WAAW,IAAI,IAAI,CA+BlC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// List command - list all providers and models
|
|
2
|
+
import { loadProviders, loadCurrent, initConfig } from '../config/manager.js';
|
|
3
|
+
import { hasApiKey } from '../providers/registry.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
export function listCommand() {
|
|
7
|
+
initConfig();
|
|
8
|
+
const providers = loadProviders();
|
|
9
|
+
const current = loadCurrent();
|
|
10
|
+
logger.title('Available Providers');
|
|
11
|
+
for (const [providerId, config] of Object.entries(providers)) {
|
|
12
|
+
const hasKey = hasApiKey(providerId);
|
|
13
|
+
const isCurrent = providerId === current.provider;
|
|
14
|
+
// Provider header
|
|
15
|
+
const status = hasKey ? chalk.green('✓') : chalk.dim('○');
|
|
16
|
+
const currentMarker = isCurrent ? chalk.yellow(' (current)') : '';
|
|
17
|
+
console.log(`${status} ${chalk.bold(config.name)} ${chalk.dim(`(${providerId})`)}${currentMarker}`);
|
|
18
|
+
// Models
|
|
19
|
+
for (const [modelId, modelConfig] of Object.entries(config.models)) {
|
|
20
|
+
const defaultMarker = modelConfig.default ? chalk.dim(' [default]') : '';
|
|
21
|
+
const currentModelMarker = isCurrent && modelId === current.model ? chalk.yellow(' ←') : '';
|
|
22
|
+
const realModel = modelConfig.model !== modelId ? chalk.dim(` → ${modelConfig.model}`) : '';
|
|
23
|
+
console.log(` ${chalk.dim('•')} ${modelConfig.name} ${chalk.dim(`(${modelId})`)}${realModel}${defaultMarker}${currentModelMarker}`);
|
|
24
|
+
}
|
|
25
|
+
console.log();
|
|
26
|
+
}
|
|
27
|
+
logger.separator();
|
|
28
|
+
logger.info('Usage: ccs <provider> [model]');
|
|
29
|
+
logger.info('Example: ccs zhipu glm-5-turbo');
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,WAAW;IACzB,UAAU,EAAE,CAAC;IAEb,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAE9B,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAEpC,KAAK,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,UAAU,KAAK,OAAO,CAAC,QAAQ,CAAC;QAElD,kBAAkB;QAClB,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1D,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,GAAG,aAAa,EAAE,CAAC,CAAC;QAEpG,SAAS;QACT,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzE,MAAM,kBAAkB,GAAG,SAAS,IAAI,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5F,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5F,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,GAAG,SAAS,GAAG,aAAa,GAAG,kBAAkB,EAAE,CAAC,CAAC;QACzI,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,SAAS,EAAE,CAAC;IACnB,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC7C,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"AAeA,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CA6CrD"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Models command - list models for a provider
|
|
2
|
+
import { initConfig, loadProviders } from '../config/manager.js';
|
|
3
|
+
import { providerExists, getProviderModels, getProviderDisplayName, getModelDisplayName, getProviderDefaultModel, getRealModelName } from '../providers/registry.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
export function modelsCommand(provider) {
|
|
7
|
+
initConfig();
|
|
8
|
+
if (!provider) {
|
|
9
|
+
// Show models for all providers
|
|
10
|
+
const allProviders = loadProviders();
|
|
11
|
+
logger.title('Available Models');
|
|
12
|
+
for (const [providerId, config] of Object.entries(allProviders)) {
|
|
13
|
+
console.log(chalk.bold(config.name));
|
|
14
|
+
for (const [modelId, modelConfig] of Object.entries(config.models)) {
|
|
15
|
+
const defaultMarker = modelConfig.default ? chalk.dim(' [default]') : '';
|
|
16
|
+
const realModel = modelConfig.model !== modelId ? chalk.dim(` → ${modelConfig.model}`) : '';
|
|
17
|
+
console.log(` ${modelConfig.name} ${chalk.dim(`(${modelId})`)}${realModel}${defaultMarker}`);
|
|
18
|
+
}
|
|
19
|
+
console.log();
|
|
20
|
+
}
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// Validate provider
|
|
24
|
+
if (!providerExists(provider)) {
|
|
25
|
+
logger.error(`Unknown provider: ${provider}`);
|
|
26
|
+
logger.info('Run "ccs list" to see available providers');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const models = getProviderModels(provider);
|
|
30
|
+
const defaultModel = getProviderDefaultModel(provider);
|
|
31
|
+
const providerName = getProviderDisplayName(provider);
|
|
32
|
+
logger.title(`Models for ${providerName}`);
|
|
33
|
+
for (const modelId of models) {
|
|
34
|
+
const modelName = getModelDisplayName(provider, modelId);
|
|
35
|
+
const realModel = getRealModelName(provider, modelId);
|
|
36
|
+
const isDefault = modelId === defaultModel;
|
|
37
|
+
const defaultMarker = isDefault ? chalk.green(' [default]') : '';
|
|
38
|
+
const realMarker = realModel && realModel !== modelId ? chalk.dim(` → ${realModel}`) : '';
|
|
39
|
+
console.log(` ${modelName} ${chalk.dim(`(${modelId})`)}${realMarker}${defaultMarker}`);
|
|
40
|
+
}
|
|
41
|
+
console.log();
|
|
42
|
+
logger.info(`Usage: ccs ${provider} <model>`);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAE9C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,aAAa,CAAC,QAAiB;IAC7C,UAAU,EAAE,CAAC;IAEb,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,gCAAgC;QAChC,MAAM,YAAY,GAAG,aAAa,EAAE,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAEjC,KAAK,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAA+B,EAAE,CAAC;YAC9F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YACrC,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAA4B,EAAE,CAAC;gBAC9F,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzE,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5F,OAAO,CAAC,GAAG,CAAC,KAAK,WAAW,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,GAAG,SAAS,GAAG,aAAa,EAAE,CAAC,CAAC;YAChG,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;QACD,OAAO;IACT,CAAC;IAED,oBAAoB;IACpB,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAEtD,MAAM,CAAC,KAAK,CAAC,cAAc,YAAY,EAAE,CAAC,CAAC;IAE3C,KAAK,MAAM,OAAO,IAAI,MAAM,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,OAAO,KAAK,YAAY,CAAC;QAC3C,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,MAAM,UAAU,GAAG,SAAS,IAAI,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,GAAG,UAAU,GAAG,aAAa,EAAE,CAAC,CAAC;IAC1F,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,MAAM,CAAC,IAAI,CAAC,cAAc,QAAQ,UAAU,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-key.d.ts","sourceRoot":"","sources":["../../src/commands/set-key.ts"],"names":[],"mappings":"AAOA,wBAAsB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD3F"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Set-key command - set API key for a provider
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { setApiKey, initConfig, loadProviders } from '../config/manager.js';
|
|
4
|
+
import { providerExists, getProviderDisplayName } from '../providers/registry.js';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
export async function setKeyCommand(providerArg, apiKeyArg) {
|
|
7
|
+
initConfig();
|
|
8
|
+
let provider = providerArg;
|
|
9
|
+
// If provider not specified, show interactive prompt
|
|
10
|
+
if (!provider) {
|
|
11
|
+
const providers = loadProviders();
|
|
12
|
+
const { selectedProvider } = await inquirer.prompt([
|
|
13
|
+
{
|
|
14
|
+
type: 'list',
|
|
15
|
+
name: 'selectedProvider',
|
|
16
|
+
message: 'Select provider to set API key:',
|
|
17
|
+
choices: Object.keys(providers).map(p => ({
|
|
18
|
+
name: `${providers[p].name}`,
|
|
19
|
+
value: p
|
|
20
|
+
}))
|
|
21
|
+
}
|
|
22
|
+
]);
|
|
23
|
+
provider = selectedProvider;
|
|
24
|
+
}
|
|
25
|
+
// Validate provider
|
|
26
|
+
if (!provider || !providerExists(provider)) {
|
|
27
|
+
logger.error(`Unknown provider: ${provider || 'undefined'}`);
|
|
28
|
+
logger.info('Run "ccs list" to see available providers');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
let apiKey = apiKeyArg;
|
|
32
|
+
// If API key not provided, prompt for it
|
|
33
|
+
if (!apiKey) {
|
|
34
|
+
const response = await inquirer.prompt([
|
|
35
|
+
{
|
|
36
|
+
type: 'password',
|
|
37
|
+
name: 'apiKey',
|
|
38
|
+
message: `Enter API key for ${getProviderDisplayName(provider)}:`,
|
|
39
|
+
mask: '*',
|
|
40
|
+
validate: (input) => input.length > 0 || 'API key cannot be empty'
|
|
41
|
+
}
|
|
42
|
+
]);
|
|
43
|
+
apiKey = response.apiKey;
|
|
44
|
+
}
|
|
45
|
+
// Save the API key (apiKey is guaranteed to be defined here)
|
|
46
|
+
if (apiKey) {
|
|
47
|
+
setApiKey(provider, apiKey);
|
|
48
|
+
logger.success(`API key saved for ${getProviderDisplayName(provider)}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=set-key.js.map
|