@vibeapi/api-helper 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -17
- package/dist/commands/auth.js +1 -119
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/config.js +1 -130
- package/dist/commands/doctor.js +1 -105
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/index.js +1 -5
- package/dist/commands/lang.js +1 -28
- package/dist/index.js +1 -10
- package/dist/lib/api-validator.js +1 -79
- package/dist/lib/claude-code-manager.js +1 -269
- package/dist/lib/claude-code-manager.js.map +1 -1
- package/dist/lib/command.js +1 -175
- package/dist/lib/config.d.ts +1 -6
- package/dist/lib/config.js +1 -233
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/i18n.js +1 -149
- package/dist/lib/model-registry.d.ts +20 -0
- package/dist/lib/model-registry.js +1 -0
- package/dist/lib/model-registry.js.map +1 -0
- package/dist/lib/opencode-manager.js +1 -134
- package/dist/lib/settings-template.d.ts +6 -0
- package/dist/lib/settings-template.js +1 -0
- package/dist/lib/settings-template.js.map +1 -0
- package/dist/lib/tool-manager.js +1 -280
- package/dist/lib/tool-manager.js.map +1 -1
- package/dist/lib/wizard.d.ts +3 -3
- package/dist/lib/wizard.js +1 -625
- package/dist/lib/wizard.js.map +1 -1
- package/dist/locales/en_US.json +9 -7
- package/dist/locales/zh_CN.json +8 -6
- package/dist/models.json +44 -0
- package/dist/settings-template.json +12 -0
- package/dist/utils/logger.js +1 -202
- package/dist/utils/string-width.js +1 -131
- package/models.json +44 -0
- package/package.json +75 -73
- package/settings-template.json +12 -0
package/dist/lib/wizard.js
CHANGED
|
@@ -1,625 +1 @@
|
|
|
1
|
-
import inquirer from 'inquirer';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import ora from 'ora';
|
|
4
|
-
import { configManager, DEFAULT_MODELS } from './config.js';
|
|
5
|
-
import { toolManager, SUPPORTED_TOOLS } from './tool-manager.js';
|
|
6
|
-
import { claudeCodeManager } from './claude-code-manager.js';
|
|
7
|
-
import { i18n } from './i18n.js';
|
|
8
|
-
import { createBorderLine, createContentLine } from '../utils/string-width.js';
|
|
9
|
-
import { validateApiKey } from './api-validator.js';
|
|
10
|
-
// 主题色
|
|
11
|
-
const THEME_COLOR = '#FF8700';
|
|
12
|
-
const theme = chalk.hex(THEME_COLOR);
|
|
13
|
-
export class Wizard {
|
|
14
|
-
static instance;
|
|
15
|
-
BOX_WIDTH = 63;
|
|
16
|
-
apiKeyValid = false; // 添加 API Key 验证状态
|
|
17
|
-
constructor() { }
|
|
18
|
-
static getInstance() {
|
|
19
|
-
if (!Wizard.instance) {
|
|
20
|
-
Wizard.instance = new Wizard();
|
|
21
|
-
}
|
|
22
|
-
return Wizard.instance;
|
|
23
|
-
}
|
|
24
|
-
createBox(title) {
|
|
25
|
-
console.log(theme.bold('\n' + createBorderLine('╔', '╗', '═', this.BOX_WIDTH)));
|
|
26
|
-
console.log(theme.bold(createContentLine(title, '║', '║', this.BOX_WIDTH, 'center')));
|
|
27
|
-
console.log(theme.bold(createBorderLine('╚', '╝', '═', this.BOX_WIDTH)));
|
|
28
|
-
console.log('');
|
|
29
|
-
}
|
|
30
|
-
showOperationHints() {
|
|
31
|
-
const hints = [
|
|
32
|
-
chalk.gray(i18n.t('wizard.hint_navigate')),
|
|
33
|
-
chalk.gray(i18n.t('wizard.hint_confirm'))
|
|
34
|
-
];
|
|
35
|
-
console.log(chalk.gray('💡 ') + hints.join(chalk.gray(' | ')) + '\n');
|
|
36
|
-
}
|
|
37
|
-
async promptWithHints(questions) {
|
|
38
|
-
this.showOperationHints();
|
|
39
|
-
return inquirer.prompt(questions);
|
|
40
|
-
}
|
|
41
|
-
printBanner() {
|
|
42
|
-
const BANNER_WIDTH = 65;
|
|
43
|
-
const subtitle = i18n.t('wizard.banner_subtitle');
|
|
44
|
-
const subtitleLine = createContentLine(subtitle, '║', '║', BANNER_WIDTH, 'center');
|
|
45
|
-
const emptyLine = createContentLine('', '║', '║', BANNER_WIDTH, 'center');
|
|
46
|
-
const titleLine = createContentLine('API Helper v0.0.14', '║', '║', BANNER_WIDTH, 'center');
|
|
47
|
-
const asciiLines = [
|
|
48
|
-
' ▄▀▄ █▀▄ █ █▄█ ██▀ █ █▀▄ ██▀ █▀▄ ',
|
|
49
|
-
' █▀█ █▀ █ █ █ █▄▄ █▄▄ █▀ █▄▄ █▀▄ '
|
|
50
|
-
].map(line => createContentLine(line, '║', '║', BANNER_WIDTH, 'center'));
|
|
51
|
-
const bannerLines = [
|
|
52
|
-
createBorderLine('╔', '╗', '═', BANNER_WIDTH),
|
|
53
|
-
emptyLine,
|
|
54
|
-
...asciiLines,
|
|
55
|
-
emptyLine,
|
|
56
|
-
titleLine,
|
|
57
|
-
subtitleLine,
|
|
58
|
-
createBorderLine('╚', '╝', '═', BANNER_WIDTH)
|
|
59
|
-
];
|
|
60
|
-
console.log(theme.bold('\n' + bannerLines.join('\n')));
|
|
61
|
-
}
|
|
62
|
-
resetScreen() {
|
|
63
|
-
console.clear();
|
|
64
|
-
this.printBanner();
|
|
65
|
-
}
|
|
66
|
-
async runFirstTimeSetup() {
|
|
67
|
-
this.resetScreen();
|
|
68
|
-
console.log(theme.bold('\n' + i18n.t('wizard.welcome')));
|
|
69
|
-
console.log(chalk.gray(i18n.t('wizard.privacy_note') + '\n'));
|
|
70
|
-
// 1. 先配置语言
|
|
71
|
-
await this.configLanguage();
|
|
72
|
-
// 2. 必须先验证 API Key
|
|
73
|
-
await this.configApiKey();
|
|
74
|
-
// 3. 验证 API Key 后才能配置模型和工具
|
|
75
|
-
const apiKey = configManager.getApiKey();
|
|
76
|
-
if (!apiKey) {
|
|
77
|
-
console.log(chalk.red('\n' + i18n.t('wizard.api_key_required')));
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
// 4. 配置模型
|
|
81
|
-
await this.configModels();
|
|
82
|
-
// 5. 配置工具
|
|
83
|
-
await this.selectAndConfigureTool();
|
|
84
|
-
}
|
|
85
|
-
async configLanguage() {
|
|
86
|
-
while (true) {
|
|
87
|
-
this.resetScreen();
|
|
88
|
-
this.createBox(i18n.t('wizard.select_language'));
|
|
89
|
-
const currentLanguage = i18n.getLocale();
|
|
90
|
-
const { language } = await this.promptWithHints([
|
|
91
|
-
{
|
|
92
|
-
type: 'list',
|
|
93
|
-
name: 'language',
|
|
94
|
-
message: '✨ ' + i18n.t('wizard.select_language'),
|
|
95
|
-
choices: [
|
|
96
|
-
{ name: '[EN] English' + (currentLanguage === 'en_US' ? chalk.green(' ✓ (' + i18n.t('wizard.current_active') + ')') : ''), value: 'en_US' },
|
|
97
|
-
{ name: '[CN] 中文' + (currentLanguage === 'zh_CN' ? chalk.green(' ✓ (' + i18n.t('wizard.current_active') + ')') : ''), value: 'zh_CN' },
|
|
98
|
-
new inquirer.Separator(),
|
|
99
|
-
{ name: '<- ' + i18n.t('wizard.nav_return'), value: 'back' },
|
|
100
|
-
{ name: 'x ' + i18n.t('wizard.nav_exit'), value: 'exit' }
|
|
101
|
-
],
|
|
102
|
-
default: 'zh_CN'
|
|
103
|
-
}
|
|
104
|
-
]);
|
|
105
|
-
if (language === 'exit') {
|
|
106
|
-
console.log(chalk.green('\n👋 ' + i18n.t('wizard.goodbye_message')));
|
|
107
|
-
process.exit(0);
|
|
108
|
-
}
|
|
109
|
-
else if (language === 'back') {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
configManager.setLang(language);
|
|
113
|
-
i18n.setLocale(language);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
async configModels() {
|
|
118
|
-
// 确保 API Key 已配置
|
|
119
|
-
const apiKey = configManager.getApiKey();
|
|
120
|
-
if (!apiKey) {
|
|
121
|
-
console.log(chalk.red('\n' + i18n.t('wizard.api_key_required')));
|
|
122
|
-
await inquirer.prompt([{ type: 'input', name: 'continue', message: i18n.t('wizard.press_enter') }]);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
while (true) {
|
|
126
|
-
this.resetScreen();
|
|
127
|
-
this.createBox(i18n.t('wizard.config_models'));
|
|
128
|
-
const { modelChoice } = await this.promptWithHints([{
|
|
129
|
-
type: 'list',
|
|
130
|
-
name: 'modelChoice',
|
|
131
|
-
message: i18n.t('wizard.select_model_config'),
|
|
132
|
-
choices: [
|
|
133
|
-
{ name: 'MiniMax-M2.5', value: 'MiniMax-M2.5' },
|
|
134
|
-
{ name: 'MiniMax-M2.7', value: 'MiniMax-M2.7' },
|
|
135
|
-
{ name: 'GPT-5.4', value: 'gpt-5.4' },
|
|
136
|
-
{ name: 'Kimi-K2.5', value: 'kimi-k2.5' },
|
|
137
|
-
{ name: 'Qwen3.5-Plus', value: 'qwen3.5-plus' },
|
|
138
|
-
{ name: 'GLM-5.1', value: 'glm-5.1' },
|
|
139
|
-
new inquirer.Separator(),
|
|
140
|
-
{ name: i18n.t('wizard.use_default_models'), value: 'default' },
|
|
141
|
-
{ name: i18n.t('wizard.use_custom_models'), value: 'custom' },
|
|
142
|
-
{ name: i18n.t('wizard.custom_model_input'), value: 'custom_input' },
|
|
143
|
-
new inquirer.Separator(),
|
|
144
|
-
{ name: '<- ' + i18n.t('wizard.nav_return'), value: 'back' },
|
|
145
|
-
{ name: 'x ' + i18n.t('wizard.nav_exit'), value: 'exit' }
|
|
146
|
-
]
|
|
147
|
-
}]);
|
|
148
|
-
if (modelChoice === 'exit') {
|
|
149
|
-
console.log(chalk.green('\n👋 ' + i18n.t('wizard.goodbye_message')));
|
|
150
|
-
process.exit(0);
|
|
151
|
-
}
|
|
152
|
-
else if (modelChoice === 'back') {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
else if (modelChoice === 'default') {
|
|
156
|
-
configManager.setModels(DEFAULT_MODELS);
|
|
157
|
-
console.log(chalk.green('\n✓ ' + i18n.t('wizard.models_saved')));
|
|
158
|
-
await this.promptLoadAfterModelConfig();
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
else if (modelChoice === 'custom') {
|
|
162
|
-
// 自定义每个模型
|
|
163
|
-
const models = await inquirer.prompt([
|
|
164
|
-
{
|
|
165
|
-
type: 'input',
|
|
166
|
-
name: 'haiku',
|
|
167
|
-
message: i18n.t('wizard.model_haiku') + ':',
|
|
168
|
-
default: DEFAULT_MODELS.haiku
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
type: 'input',
|
|
172
|
-
name: 'sonnet',
|
|
173
|
-
message: i18n.t('wizard.model_sonnet') + ':',
|
|
174
|
-
default: DEFAULT_MODELS.sonnet
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
type: 'input',
|
|
178
|
-
name: 'opus',
|
|
179
|
-
message: i18n.t('wizard.model_opus') + ':',
|
|
180
|
-
default: DEFAULT_MODELS.opus
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
type: 'input',
|
|
184
|
-
name: 'reasoning',
|
|
185
|
-
message: i18n.t('wizard.model_reasoning') + ':',
|
|
186
|
-
default: DEFAULT_MODELS.reasoning
|
|
187
|
-
}
|
|
188
|
-
]);
|
|
189
|
-
configManager.setModels(models);
|
|
190
|
-
console.log(chalk.green('\n✓ ' + i18n.t('wizard.models_saved')));
|
|
191
|
-
await this.promptLoadAfterModelConfig();
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
else if (modelChoice === 'custom_input') {
|
|
195
|
-
// 自定义输入一个模型
|
|
196
|
-
const { customModel } = await inquirer.prompt([
|
|
197
|
-
{
|
|
198
|
-
type: 'input',
|
|
199
|
-
name: 'customModel',
|
|
200
|
-
message: i18n.t('wizard.input_custom_model'),
|
|
201
|
-
default: DEFAULT_MODELS.sonnet
|
|
202
|
-
}
|
|
203
|
-
]);
|
|
204
|
-
const models = {
|
|
205
|
-
haiku: customModel,
|
|
206
|
-
sonnet: customModel,
|
|
207
|
-
opus: customModel,
|
|
208
|
-
reasoning: customModel
|
|
209
|
-
};
|
|
210
|
-
configManager.setModels(models);
|
|
211
|
-
console.log(chalk.green('\n✓ ' + i18n.t('wizard.models_saved')));
|
|
212
|
-
await this.promptLoadAfterModelConfig();
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
// 选择了预设模型(MiniMax、GPT、Kimi、Qwen)
|
|
217
|
-
const models = {
|
|
218
|
-
haiku: modelChoice,
|
|
219
|
-
sonnet: modelChoice,
|
|
220
|
-
opus: modelChoice,
|
|
221
|
-
reasoning: modelChoice
|
|
222
|
-
};
|
|
223
|
-
configManager.setModels(models);
|
|
224
|
-
console.log(chalk.green('\n✓ ' + i18n.t('wizard.models_saved')));
|
|
225
|
-
await this.promptLoadAfterModelConfig();
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
async promptLoadAfterModelConfig() {
|
|
231
|
-
const { shouldLoad } = await inquirer.prompt([{
|
|
232
|
-
type: 'list',
|
|
233
|
-
name: 'shouldLoad',
|
|
234
|
-
message: i18n.t('wizard.load_config_now'),
|
|
235
|
-
choices: [
|
|
236
|
-
{ name: i18n.t('wizard.load_config_yes'), value: true },
|
|
237
|
-
{ name: i18n.t('wizard.load_config_later'), value: false }
|
|
238
|
-
]
|
|
239
|
-
}]);
|
|
240
|
-
if (shouldLoad) {
|
|
241
|
-
await this.selectAndConfigureTool();
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
async configApiKey() {
|
|
245
|
-
while (true) {
|
|
246
|
-
this.resetScreen();
|
|
247
|
-
this.createBox(i18n.t('wizard.input_api_key'));
|
|
248
|
-
// 直接进入输入,不需要额外的选择菜单
|
|
249
|
-
console.log(chalk.gray('\n💡 ' + i18n.t('wizard.api_key_input_hint')));
|
|
250
|
-
console.log(chalk.gray(' ' + i18n.t('wizard.api_key_get_hint', { url: 'https://www.vibeapi.cn/console/token' })));
|
|
251
|
-
console.log();
|
|
252
|
-
const { apiKey } = await inquirer.prompt([
|
|
253
|
-
{
|
|
254
|
-
type: 'password',
|
|
255
|
-
name: 'apiKey',
|
|
256
|
-
message: i18n.t('wizard.input_your_api_key'),
|
|
257
|
-
mask: '*'
|
|
258
|
-
}
|
|
259
|
-
]);
|
|
260
|
-
if (!apiKey || apiKey.trim() === '') {
|
|
261
|
-
const { action } = await inquirer.prompt([{
|
|
262
|
-
type: 'list',
|
|
263
|
-
name: 'action',
|
|
264
|
-
message: i18n.t('wizard.select_action'),
|
|
265
|
-
choices: [
|
|
266
|
-
{ name: i18n.t('wizard.retry_input'), value: 'retry' },
|
|
267
|
-
{ name: '<- ' + i18n.t('wizard.nav_return'), value: 'back' }
|
|
268
|
-
]
|
|
269
|
-
}]);
|
|
270
|
-
if (action === 'back') {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
continue;
|
|
274
|
-
}
|
|
275
|
-
const spinner = ora(i18n.t('wizard.validating_api_key')).start();
|
|
276
|
-
const result = await validateApiKey(apiKey.trim());
|
|
277
|
-
spinner.stop();
|
|
278
|
-
if (result.valid) {
|
|
279
|
-
configManager.setApiKey(apiKey.trim());
|
|
280
|
-
this.apiKeyValid = true; // 更新验证状态
|
|
281
|
-
console.log(chalk.green('\n✓ ' + i18n.t('wizard.api_key_valid')));
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
this.apiKeyValid = false; // 更新验证状态
|
|
286
|
-
if (result.error === 'invalid_api_key') {
|
|
287
|
-
console.log(chalk.red('\n✗ ' + i18n.t('wizard.api_key_invalid')));
|
|
288
|
-
}
|
|
289
|
-
else {
|
|
290
|
-
console.log(chalk.red('\n✗ ' + i18n.t('wizard.api_key_network_error')));
|
|
291
|
-
}
|
|
292
|
-
const { action } = await inquirer.prompt([{
|
|
293
|
-
type: 'list',
|
|
294
|
-
name: 'action',
|
|
295
|
-
message: i18n.t('wizard.select_action'),
|
|
296
|
-
choices: [
|
|
297
|
-
{ name: i18n.t('wizard.retry_input'), value: 'retry' },
|
|
298
|
-
{ name: '<- ' + i18n.t('wizard.nav_return'), value: 'back' }
|
|
299
|
-
]
|
|
300
|
-
}]);
|
|
301
|
-
if (action === 'back') {
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
async selectAndConfigureTool() {
|
|
308
|
-
while (true) {
|
|
309
|
-
this.resetScreen();
|
|
310
|
-
this.createBox(i18n.t('wizard.select_tool'));
|
|
311
|
-
const { tool } = await this.promptWithHints([
|
|
312
|
-
{
|
|
313
|
-
type: 'list',
|
|
314
|
-
name: 'tool',
|
|
315
|
-
message: '🛠️ ' + i18n.t('wizard.select_tool'),
|
|
316
|
-
choices: [
|
|
317
|
-
{ name: 'Claude Code', value: 'claude-code' },
|
|
318
|
-
{ name: 'OpenCode', value: 'opencode' },
|
|
319
|
-
new inquirer.Separator(),
|
|
320
|
-
{ name: '<- ' + i18n.t('wizard.nav_return'), value: 'back' },
|
|
321
|
-
{ name: 'x ' + i18n.t('wizard.nav_exit'), value: 'exit' }
|
|
322
|
-
]
|
|
323
|
-
}
|
|
324
|
-
]);
|
|
325
|
-
if (tool === 'exit') {
|
|
326
|
-
console.log(chalk.green('\n👋 ' + i18n.t('wizard.goodbye_message')));
|
|
327
|
-
process.exit(0);
|
|
328
|
-
}
|
|
329
|
-
else if (tool === 'back') {
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
await this.configureTool(tool);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
async configureTool(toolName) {
|
|
336
|
-
const toolInfo = SUPPORTED_TOOLS[toolName];
|
|
337
|
-
if (!toolInfo)
|
|
338
|
-
return;
|
|
339
|
-
const isInstalled = toolManager.isToolInstalled(toolName);
|
|
340
|
-
if (!isInstalled) {
|
|
341
|
-
console.log(chalk.yellow('\n' + i18n.t('wizard.tool_not_installed', { tool: toolInfo.displayName })));
|
|
342
|
-
const { install } = await inquirer.prompt([{
|
|
343
|
-
type: 'confirm',
|
|
344
|
-
name: 'install',
|
|
345
|
-
message: i18n.t('wizard.install_tool_confirm'),
|
|
346
|
-
default: true
|
|
347
|
-
}]);
|
|
348
|
-
if (install) {
|
|
349
|
-
try {
|
|
350
|
-
await toolManager.installTool(toolName);
|
|
351
|
-
}
|
|
352
|
-
catch (error) {
|
|
353
|
-
console.log(chalk.red(i18n.t('wizard.install_failed')));
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
else {
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
await this.showToolMenu(toolName);
|
|
362
|
-
}
|
|
363
|
-
async showToolMenu(toolName) {
|
|
364
|
-
while (true) {
|
|
365
|
-
this.resetScreen();
|
|
366
|
-
const toolInfo = SUPPORTED_TOOLS[toolName];
|
|
367
|
-
if (!toolInfo)
|
|
368
|
-
return;
|
|
369
|
-
this.createBox(toolInfo.displayName + ' ' + i18n.t('wizard.menu_title'));
|
|
370
|
-
const { action } = await this.promptWithHints([
|
|
371
|
-
{
|
|
372
|
-
type: 'list',
|
|
373
|
-
name: 'action',
|
|
374
|
-
message: '⚙️ ' + i18n.t('wizard.select_action'),
|
|
375
|
-
choices: [
|
|
376
|
-
{ name: '📥 ' + i18n.t('wizard.action_load_config', { tool: toolInfo.displayName }), value: 'load' },
|
|
377
|
-
{ name: '📤 ' + i18n.t('wizard.action_unload_config', { tool: toolInfo.displayName }), value: 'unload' },
|
|
378
|
-
new inquirer.Separator(),
|
|
379
|
-
{ name: '<- ' + i18n.t('wizard.nav_return'), value: 'back' },
|
|
380
|
-
{ name: 'x ' + i18n.t('wizard.nav_exit'), value: 'exit' }
|
|
381
|
-
]
|
|
382
|
-
}
|
|
383
|
-
]);
|
|
384
|
-
if (action === 'exit') {
|
|
385
|
-
console.log(chalk.green('\n👋 ' + i18n.t('wizard.goodbye_message')));
|
|
386
|
-
process.exit(0);
|
|
387
|
-
}
|
|
388
|
-
else if (action === 'back') {
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
else if (action === 'load') {
|
|
392
|
-
await this.loadConfig(toolName);
|
|
393
|
-
}
|
|
394
|
-
else if (action === 'unload') {
|
|
395
|
-
await this.unloadConfig(toolName);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
async loadConfig(toolName) {
|
|
400
|
-
const apiKey = configManager.getApiKey();
|
|
401
|
-
const models = configManager.getModels();
|
|
402
|
-
if (!apiKey) {
|
|
403
|
-
console.log(chalk.red('\n' + i18n.t('wizard.api_key_required')));
|
|
404
|
-
console.log(chalk.yellow(i18n.t('wizard.please_config_api_key_first')));
|
|
405
|
-
await inquirer.prompt([{ type: 'input', name: 'continue', message: i18n.t('wizard.press_enter') }]);
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
// 再次验证 API Key 是否有效
|
|
409
|
-
const spinner = ora(i18n.t('wizard.validating_api_key')).start();
|
|
410
|
-
const result = await validateApiKey(apiKey);
|
|
411
|
-
if (!result.valid) {
|
|
412
|
-
spinner.fail(i18n.t('wizard.api_key_invalid'));
|
|
413
|
-
console.log(chalk.red('\n' + i18n.t('wizard.please_reconfig_api_key')));
|
|
414
|
-
await inquirer.prompt([{ type: 'input', name: 'continue', message: i18n.t('wizard.press_enter') }]);
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
spinner.text = i18n.t('wizard.loading_config');
|
|
418
|
-
try {
|
|
419
|
-
toolManager.loadPrivateConfig(toolName, apiKey, models);
|
|
420
|
-
spinner.succeed(i18n.t('wizard.config_loaded', { tool: SUPPORTED_TOOLS[toolName]?.displayName || toolName }));
|
|
421
|
-
// 提供选择:退出或继续配置
|
|
422
|
-
const { nextAction } = await inquirer.prompt([{
|
|
423
|
-
type: 'list',
|
|
424
|
-
name: 'nextAction',
|
|
425
|
-
message: i18n.t('wizard.what_next'),
|
|
426
|
-
choices: [
|
|
427
|
-
{ name: i18n.t('wizard.exit_and_start'), value: 'exit' },
|
|
428
|
-
{ name: i18n.t('wizard.continue_config'), value: 'continue' }
|
|
429
|
-
]
|
|
430
|
-
}]);
|
|
431
|
-
if (nextAction === 'exit') {
|
|
432
|
-
console.log(chalk.green('\n👋 ' + i18n.t('wizard.goodbye_message')));
|
|
433
|
-
process.exit(0);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
catch (error) {
|
|
437
|
-
spinner.fail(i18n.t('wizard.config_failed'));
|
|
438
|
-
console.log(chalk.red(error instanceof Error ? error.message : String(error)));
|
|
439
|
-
await inquirer.prompt([{ type: 'input', name: 'continue', message: i18n.t('wizard.press_enter') }]);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
async unloadConfig(toolName) {
|
|
443
|
-
const { confirm } = await inquirer.prompt([
|
|
444
|
-
{
|
|
445
|
-
type: 'confirm',
|
|
446
|
-
name: 'confirm',
|
|
447
|
-
message: i18n.t('wizard.confirm_unload_config', { tool: SUPPORTED_TOOLS[toolName]?.displayName || toolName }),
|
|
448
|
-
default: false
|
|
449
|
-
}
|
|
450
|
-
]);
|
|
451
|
-
if (!confirm)
|
|
452
|
-
return;
|
|
453
|
-
const spinner = ora(i18n.t('wizard.unloading_config')).start();
|
|
454
|
-
try {
|
|
455
|
-
toolManager.unloadPrivateConfig(toolName);
|
|
456
|
-
spinner.succeed(i18n.t('wizard.config_unloaded'));
|
|
457
|
-
// 提供选择:退出或继续配置
|
|
458
|
-
const { nextAction } = await inquirer.prompt([{
|
|
459
|
-
type: 'list',
|
|
460
|
-
name: 'nextAction',
|
|
461
|
-
message: i18n.t('wizard.what_next'),
|
|
462
|
-
choices: [
|
|
463
|
-
{ name: i18n.t('wizard.exit_and_start'), value: 'exit' },
|
|
464
|
-
{ name: i18n.t('wizard.continue_config'), value: 'continue' }
|
|
465
|
-
]
|
|
466
|
-
}]);
|
|
467
|
-
if (nextAction === 'exit') {
|
|
468
|
-
console.log(chalk.green('\n👋 ' + i18n.t('wizard.goodbye_message')));
|
|
469
|
-
process.exit(0);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
catch (error) {
|
|
473
|
-
spinner.fail(i18n.t('wizard.config_unload_failed'));
|
|
474
|
-
console.log(chalk.red(error instanceof Error ? error.message : String(error)));
|
|
475
|
-
await inquirer.prompt([{ type: 'input', name: 'continue', message: i18n.t('wizard.press_enter') }]);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
async run() {
|
|
479
|
-
const config = configManager.getConfig();
|
|
480
|
-
// 初始化时验证 API Key
|
|
481
|
-
if (config.api_key) {
|
|
482
|
-
const result = await validateApiKey(config.api_key);
|
|
483
|
-
this.apiKeyValid = result.valid;
|
|
484
|
-
}
|
|
485
|
-
else {
|
|
486
|
-
this.apiKeyValid = false;
|
|
487
|
-
}
|
|
488
|
-
if (!config.api_key || !this.apiKeyValid) {
|
|
489
|
-
await this.runFirstTimeSetup();
|
|
490
|
-
}
|
|
491
|
-
else {
|
|
492
|
-
await this.showMainMenu();
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
async showMainMenu() {
|
|
496
|
-
while (true) {
|
|
497
|
-
this.resetScreen();
|
|
498
|
-
this.createBox(i18n.t('wizard.main_menu_title'));
|
|
499
|
-
// 构建菜单选项
|
|
500
|
-
const choices = [];
|
|
501
|
-
// 只有 API Key 有效时才显示编码工具和模型配置
|
|
502
|
-
if (this.apiKeyValid) {
|
|
503
|
-
choices.push({ name: '🛠️ ' + i18n.t('wizard.menu_config_tool'), value: 'tools' });
|
|
504
|
-
choices.push({ name: '⚙️ ' + i18n.t('wizard.menu_config_models'), value: 'models' });
|
|
505
|
-
choices.push(new inquirer.Separator());
|
|
506
|
-
}
|
|
507
|
-
choices.push({ name: '🔑 ' + i18n.t('wizard.menu_config_api_key'), value: 'apikey' });
|
|
508
|
-
choices.push({ name: '🌐 ' + i18n.t('wizard.menu_config_language'), value: 'language' });
|
|
509
|
-
choices.push({ name: '🧪 ' + i18n.t('wizard.menu_experimental_features'), value: 'experimental' });
|
|
510
|
-
choices.push(new inquirer.Separator());
|
|
511
|
-
choices.push({ name: 'x ' + i18n.t('wizard.nav_exit'), value: 'exit' });
|
|
512
|
-
const { action } = await this.promptWithHints([
|
|
513
|
-
{
|
|
514
|
-
type: 'list',
|
|
515
|
-
name: 'action',
|
|
516
|
-
message: i18n.t('wizard.select_operation'),
|
|
517
|
-
choices: choices
|
|
518
|
-
}
|
|
519
|
-
]);
|
|
520
|
-
if (action === 'exit') {
|
|
521
|
-
console.log(chalk.green('\n👋 ' + i18n.t('wizard.goodbye_message')));
|
|
522
|
-
process.exit(0);
|
|
523
|
-
}
|
|
524
|
-
else if (action === 'language') {
|
|
525
|
-
await this.configLanguage();
|
|
526
|
-
}
|
|
527
|
-
else if (action === 'apikey') {
|
|
528
|
-
await this.configApiKey();
|
|
529
|
-
// 配置完 API Key 后重新验证
|
|
530
|
-
const apiKey = configManager.getApiKey();
|
|
531
|
-
if (apiKey) {
|
|
532
|
-
const result = await validateApiKey(apiKey);
|
|
533
|
-
this.apiKeyValid = result.valid;
|
|
534
|
-
// 如果 API Key 有效,直接进入模型配置
|
|
535
|
-
if (this.apiKeyValid) {
|
|
536
|
-
await this.configModels();
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
else {
|
|
540
|
-
this.apiKeyValid = false;
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
else if (action === 'models') {
|
|
544
|
-
await this.configModels();
|
|
545
|
-
}
|
|
546
|
-
else if (action === 'tools') {
|
|
547
|
-
await this.selectAndConfigureTool();
|
|
548
|
-
}
|
|
549
|
-
else if (action === 'experimental') {
|
|
550
|
-
await this.configExperimentalFeatures();
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
async configExperimentalFeatures() {
|
|
555
|
-
while (true) {
|
|
556
|
-
this.resetScreen();
|
|
557
|
-
this.createBox(i18n.t('wizard.experimental_features_title'));
|
|
558
|
-
// Check current status
|
|
559
|
-
const agentTeamsEnabled = claudeCodeManager.getExperimentalFeature('CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS') === '1';
|
|
560
|
-
const { action } = await this.promptWithHints([
|
|
561
|
-
{
|
|
562
|
-
type: 'list',
|
|
563
|
-
name: 'action',
|
|
564
|
-
message: i18n.t('wizard.select_experimental_feature'),
|
|
565
|
-
choices: [
|
|
566
|
-
{
|
|
567
|
-
name: '🤖 Agent Teams' + (agentTeamsEnabled ? chalk.green(' ✓ (' + i18n.t('wizard.enabled') + ')') : chalk.gray(' (' + i18n.t('wizard.disabled') + ')')),
|
|
568
|
-
value: 'agent-teams'
|
|
569
|
-
},
|
|
570
|
-
new inquirer.Separator(),
|
|
571
|
-
{ name: '<- ' + i18n.t('wizard.nav_return'), value: 'back' },
|
|
572
|
-
{ name: 'x ' + i18n.t('wizard.nav_exit'), value: 'exit' }
|
|
573
|
-
]
|
|
574
|
-
}
|
|
575
|
-
]);
|
|
576
|
-
if (action === 'exit') {
|
|
577
|
-
console.log(chalk.green('\n👋 ' + i18n.t('wizard.goodbye_message')));
|
|
578
|
-
process.exit(0);
|
|
579
|
-
}
|
|
580
|
-
else if (action === 'back') {
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
else if (action === 'agent-teams') {
|
|
584
|
-
await this.toggleAgentTeams();
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
async toggleAgentTeams() {
|
|
589
|
-
const isEnabled = claudeCodeManager.getExperimentalFeature('CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS') === '1';
|
|
590
|
-
const { action } = await inquirer.prompt([
|
|
591
|
-
{
|
|
592
|
-
type: 'list',
|
|
593
|
-
name: 'action',
|
|
594
|
-
message: i18n.t('wizard.agent_teams_current_status') + ': ' + (isEnabled ? chalk.green(i18n.t('wizard.enabled')) : chalk.gray(i18n.t('wizard.disabled'))),
|
|
595
|
-
choices: [
|
|
596
|
-
{ name: i18n.t('wizard.enable'), value: 'enable' },
|
|
597
|
-
{ name: i18n.t('wizard.disable'), value: 'disable' },
|
|
598
|
-
new inquirer.Separator(),
|
|
599
|
-
{ name: '<- ' + i18n.t('wizard.nav_return'), value: 'back' }
|
|
600
|
-
]
|
|
601
|
-
}
|
|
602
|
-
]);
|
|
603
|
-
if (action === 'back')
|
|
604
|
-
return;
|
|
605
|
-
const spinner = ora(i18n.t('wizard.updating_settings')).start();
|
|
606
|
-
try {
|
|
607
|
-
if (action === 'enable') {
|
|
608
|
-
claudeCodeManager.setExperimentalFeature('CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS', '1');
|
|
609
|
-
spinner.succeed(chalk.green('✓ ' + i18n.t('wizard.agent_teams_enabled')));
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
claudeCodeManager.removeExperimentalFeature('CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS');
|
|
613
|
-
spinner.succeed(chalk.green('✓ ' + i18n.t('wizard.agent_teams_disabled')));
|
|
614
|
-
}
|
|
615
|
-
await inquirer.prompt([{ type: 'input', name: 'continue', message: i18n.t('wizard.press_enter') }]);
|
|
616
|
-
}
|
|
617
|
-
catch (error) {
|
|
618
|
-
spinner.fail(i18n.t('wizard.update_failed'));
|
|
619
|
-
console.log(chalk.red(error instanceof Error ? error.message : String(error)));
|
|
620
|
-
await inquirer.prompt([{ type: 'input', name: 'continue', message: i18n.t('wizard.press_enter') }]);
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
export const wizard = Wizard.getInstance();
|
|
625
|
-
//# sourceMappingURL=wizard.js.map
|
|
1
|
+
import e from"inquirer";import t from"chalk";import a from"ora";import{configManager as i,DEFAULT_MODELS as o}from"./config.js";import{getPresets as n,resolvePreset as r}from"./model-registry.js";import{toolManager as s,SUPPORTED_TOOLS as l}from"./tool-manager.js";import{i18n as c}from"./i18n.js";import{createBorderLine as d,createContentLine as p}from"../utils/string-width.js";import{validateApiKey as m}from"./api-validator.js";import{readFileSync as g}from"fs";import{dirname as u,join as w}from"path";import{fileURLToPath as _}from"url";const y=u(_(import.meta.url)),h=t.hex("#FF8700");export class Wizard{static instance;BOX_WIDTH=63;apiKeyValid=!1;constructor(){}static getInstance(){return Wizard.instance||(Wizard.instance=new Wizard),Wizard.instance}createBox(e){console.log(h.bold("\n"+d("╔","╗","═",this.BOX_WIDTH))),console.log(h.bold(p(e,"║","║",this.BOX_WIDTH,"center"))),console.log(h.bold(d("╚","╝","═",this.BOX_WIDTH))),console.log("")}showOperationHints(){const e=[t.gray(c.t("wizard.hint_navigate")),t.gray(c.t("wizard.hint_confirm"))];console.log(t.gray("💡 ")+e.join(t.gray(" | "))+"\n")}async promptWithHints(t){this.showOperationHints();const a=t.map(e=>"list"!==e.type||e.pageSize?e:{...e,pageSize:20});return e.prompt(a)}printBanner(){const e=65,t=c.t("wizard.banner_subtitle"),a=p(t,"║","║",e,"center"),i=p("","║","║",e,"center"),o=p(`API Helper v${function(){try{return JSON.parse(g(w(y,"..","..","package.json"),"utf-8")).version}catch{return"0.0.0"}}()}`,"║","║",e,"center"),n=[" ▄▀▄ █▀▄ █ █▄█ ██▀ █ █▀▄ ██▀ █▀▄ "," █▀█ █▀ █ █ █ █▄▄ █▄▄ █▀ █▄▄ █▀▄ "].map(t=>p(t,"║","║",e,"center")),r=[d("╔","╗","═",e),i,...n,i,o,a,d("╚","╝","═",e)];console.log(h.bold("\n"+r.join("\n")))}resetScreen(){console.clear(),this.printBanner()}async runFirstTimeSetup(){this.resetScreen(),console.log(h.bold("\n"+c.t("wizard.welcome"))),console.log(t.gray(c.t("wizard.privacy_note")+"\n")),await this.configLanguage(),await this.configApiKey(),i.getApiKey()?(await this.configModels({skipLoadPrompt:!0}),await this.selectAndConfigureTool()):console.log(t.red("\n"+c.t("wizard.api_key_required")))}async configLanguage(){for(;;){this.resetScreen(),this.createBox(c.t("wizard.select_language"));const a=c.getLocale(),{language:o}=await this.promptWithHints([{type:"list",name:"language",message:"✨ "+c.t("wizard.select_language"),choices:[{name:"[EN] English"+("en_US"===a?t.green(" ✓ ("+c.t("wizard.current_active")+")"):""),value:"en_US"},{name:"[CN] 中文"+("zh_CN"===a?t.green(" ✓ ("+c.t("wizard.current_active")+")"):""),value:"zh_CN"},new e.Separator,{name:"<- "+c.t("wizard.nav_return"),value:"back"},{name:"x "+c.t("wizard.nav_exit"),value:"exit"}],default:"zh_CN"}]);if("exit"===o)console.log(t.green("\n👋 "+c.t("wizard.goodbye_message"))),process.exit(0);else if("back"===o)return;return i.setLang(o),void c.setLocale(o)}}async configModels(a){if(!i.getApiKey())return console.log(t.red("\n"+c.t("wizard.api_key_required"))),void await e.prompt([{type:"input",name:"continue",message:c.t("wizard.press_enter")}]);for(;;){this.resetScreen(),this.createBox(c.t("wizard.config_models"));const s=n(),l=s.filter(e=>e.recommended),d=s.filter(e=>!e.recommended),p=e=>{const a=e.models?t.gray(` [H:${e.models.haiku} S:${e.models.sonnet} O:${e.models.opus}]`):"";return{name:e.name+a,value:{type:"preset",preset:e}}},m=[];l.length>0&&(m.push(new e.Separator(t.hex("#FF8700")("── "+c.t("wizard.recommended")+" ──"))),m.push(...l.map(p))),d.length>0&&(m.push(new e.Separator(t.gray("── "+c.t("wizard.other_models")+" ──"))),m.push(...d.map(p))),m.push(new e.Separator),m.push({name:"✏️ "+c.t("wizard.custom_model_input"),value:{type:"custom_input"}}),m.push(new e.Separator),m.push({name:"<- "+c.t("wizard.nav_return"),value:{type:"back"}}),m.push({name:"x "+c.t("wizard.nav_exit"),value:{type:"exit"}});const{modelChoice:g}=await this.promptWithHints([{type:"list",name:"modelChoice",message:c.t("wizard.select_model_config"),choices:m}]);if("exit"===g.type)console.log(t.green("\n👋 "+c.t("wizard.goodbye_message"))),process.exit(0);else{if("back"===g.type)return;if("custom_input"===g.type){const{customModel:n}=await e.prompt([{type:"input",name:"customModel",message:c.t("wizard.input_custom_model"),default:o.sonnet}]),r={haiku:n,sonnet:n,opus:n,reasoning:n};return i.setModels(r),console.log(t.green("\n✓ "+c.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}if("preset"===g.type){const e=r(g.preset);return i.setModels(e),console.log(t.green("\n✓ "+c.t("wizard.models_saved"))),void(a?.skipLoadPrompt||await this.promptLoadAfterModelConfig())}}}}async promptLoadAfterModelConfig(){const{shouldLoad:t}=await e.prompt([{type:"list",name:"shouldLoad",message:c.t("wizard.load_config_now"),choices:[{name:c.t("wizard.load_config_yes"),value:!0},{name:c.t("wizard.load_config_later"),value:!1}]}]);t&&await this.selectAndConfigureTool()}async configApiKey(){for(;;){this.resetScreen(),this.createBox(c.t("wizard.input_api_key")),console.log(t.gray("\n💡 "+c.t("wizard.api_key_input_hint"))),console.log(t.gray(" "+c.t("wizard.api_key_get_hint",{url:"https://www.vibeapi.cn/console/token"}))),console.log();const{apiKey:o}=await e.prompt([{type:"password",name:"apiKey",message:c.t("wizard.input_your_api_key"),mask:"*"}]);if(!o||""===o.trim()){const{action:t}=await e.prompt([{type:"list",name:"action",message:c.t("wizard.select_action"),choices:[{name:c.t("wizard.retry_input"),value:"retry"},{name:"<- "+c.t("wizard.nav_return"),value:"back"}]}]);if("back"===t)return;continue}const n=a(c.t("wizard.validating_api_key")).start(),r=await m(o.trim());if(n.stop(),r.valid)return i.setApiKey(o.trim()),this.apiKeyValid=!0,void console.log(t.green("\n✓ "+c.t("wizard.api_key_valid")));{this.apiKeyValid=!1,"invalid_api_key"===r.error?console.log(t.red("\n✗ "+c.t("wizard.api_key_invalid"))):console.log(t.red("\n✗ "+c.t("wizard.api_key_network_error")));const{action:a}=await e.prompt([{type:"list",name:"action",message:c.t("wizard.select_action"),choices:[{name:c.t("wizard.retry_input"),value:"retry"},{name:"<- "+c.t("wizard.nav_return"),value:"back"}]}]);if("back"===a)return}}}async selectAndConfigureTool(){for(;;){this.resetScreen(),this.createBox(c.t("wizard.select_tool"));const{tool:a}=await this.promptWithHints([{type:"list",name:"tool",message:"🛠️ "+c.t("wizard.select_tool"),choices:[{name:"Claude Code",value:"claude-code"},{name:"OpenCode",value:"opencode"},new e.Separator,{name:"<- "+c.t("wizard.nav_return"),value:"back"},{name:"x "+c.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===a)console.log(t.green("\n👋 "+c.t("wizard.goodbye_message"))),process.exit(0);else if("back"===a)return;await this.configureTool(a)}}async configureTool(a){const i=l[a];if(i){if(!s.isToolInstalled(a)){console.log(t.yellow("\n"+c.t("wizard.tool_not_installed",{tool:i.displayName})));const{install:o}=await e.prompt([{type:"confirm",name:"install",message:c.t("wizard.install_tool_confirm"),default:!0}]);if(!o)return;try{await s.installTool(a)}catch(e){return void console.log(t.red(c.t("wizard.install_failed")))}}await this.showToolMenu(a)}}async showToolMenu(a){for(;;){this.resetScreen();const i=l[a];if(!i)return;this.createBox(i.displayName+" "+c.t("wizard.menu_title"));const{action:o}=await this.promptWithHints([{type:"list",name:"action",message:"⚙️ "+c.t("wizard.select_action"),choices:[{name:"📥 "+c.t("wizard.action_load_config",{tool:i.displayName}),value:"load"},{name:"📤 "+c.t("wizard.action_unload_config",{tool:i.displayName}),value:"unload"},new e.Separator,{name:"<- "+c.t("wizard.nav_return"),value:"back"},{name:"x "+c.t("wizard.nav_exit"),value:"exit"}]}]);if("exit"===o)console.log(t.green("\n👋 "+c.t("wizard.goodbye_message"))),process.exit(0);else{if("back"===o)return;"load"===o?await this.loadConfig(a):"unload"===o&&await this.unloadConfig(a)}}}async loadConfig(o){const n=i.getApiKey(),r=i.getModels();if(!n)return console.log(t.red("\n"+c.t("wizard.api_key_required"))),console.log(t.yellow(c.t("wizard.please_config_api_key_first"))),void await e.prompt([{type:"input",name:"continue",message:c.t("wizard.press_enter")}]);if(!this.apiKeyValid){const i=a(c.t("wizard.validating_api_key")).start();if(!(await m(n)).valid)return i.fail(c.t("wizard.api_key_invalid")),console.log(t.red("\n"+c.t("wizard.please_reconfig_api_key"))),void await e.prompt([{type:"input",name:"continue",message:c.t("wizard.press_enter")}]);this.apiKeyValid=!0,i.stop()}const d=a(c.t("wizard.loading_config")).start();try{s.loadPrivateConfig(o,n,r),d.succeed(c.t("wizard.config_loaded",{tool:l[o]?.displayName||o}));const{nextAction:a}=await e.prompt([{type:"list",name:"nextAction",message:c.t("wizard.what_next"),choices:[{name:c.t("wizard.exit_and_start"),value:"exit"},{name:c.t("wizard.continue_config"),value:"continue"}]}]);"exit"===a&&(console.log(t.green("\n👋 "+c.t("wizard.goodbye_message"))),process.exit(0))}catch(a){d.fail(c.t("wizard.config_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:c.t("wizard.press_enter")}])}}async unloadConfig(i){const{confirm:o}=await e.prompt([{type:"confirm",name:"confirm",message:c.t("wizard.confirm_unload_config",{tool:l[i]?.displayName||i}),default:!1}]);if(!o)return;const n=a(c.t("wizard.unloading_config")).start();try{s.unloadPrivateConfig(i),n.succeed(c.t("wizard.config_unloaded"));const{nextAction:a}=await e.prompt([{type:"list",name:"nextAction",message:c.t("wizard.what_next"),choices:[{name:c.t("wizard.exit_and_start"),value:"exit"},{name:c.t("wizard.continue_config"),value:"continue"}]}]);"exit"===a&&(console.log(t.green("\n👋 "+c.t("wizard.goodbye_message"))),process.exit(0))}catch(a){n.fail(c.t("wizard.config_unload_failed")),console.log(t.red(a instanceof Error?a.message:String(a))),await e.prompt([{type:"input",name:"continue",message:c.t("wizard.press_enter")}])}}async run(){const e=i.getConfig();if(e.api_key){const t=await m(e.api_key);this.apiKeyValid=t.valid}else this.apiKeyValid=!1;e.api_key&&this.apiKeyValid?await this.showMainMenu():await this.runFirstTimeSetup()}async showMainMenu(){for(;;){this.resetScreen();const a=i.getApiKey()||"",s=a.length>4?"sk-****"+a.slice(-4):"****",l=i.getModels(),d=l.opus||l.sonnet||"N/A";console.log(t.gray(` 🔑 API Key: ${s}`)+t.green(" ✓")),console.log(t.gray(` 🤖 ${c.t("wizard.current_model")}: ${d}`)),console.log("");const p=n(),g=p.filter(e=>e.recommended),u=p.filter(e=>!e.recommended),w=e=>{const a=e.models?t.gray(` [H:${e.models.haiku} S:${e.models.sonnet} O:${e.models.opus}]`):"";return{name:e.name+a,value:{type:"preset",preset:e}}},_=[];g.length>0&&(_.push(new e.Separator(t.hex("#FF8700")("── "+c.t("wizard.recommended")+" ──"))),_.push(...g.map(w))),u.length>0&&(_.push(new e.Separator(t.gray("── "+c.t("wizard.other_models")+" ──"))),_.push(...u.map(w))),_.push(new e.Separator),_.push({name:"✏️ "+c.t("wizard.custom_model_input"),value:{type:"custom_input"}}),_.push({name:"🛠️ "+c.t("wizard.menu_load_to_tool"),value:{type:"load_tool"}}),_.push(new e.Separator(t.gray("── "+c.t("wizard.settings")+" ──"))),_.push({name:"🔑 "+c.t("wizard.menu_change_api_key"),value:{type:"apikey"}}),_.push({name:"🌐 "+c.t("wizard.menu_config_language"),value:{type:"language"}}),_.push(new e.Separator),_.push({name:"x "+c.t("wizard.nav_exit"),value:{type:"exit"}});const{action:y}=await this.promptWithHints([{type:"list",name:"action",message:c.t("wizard.select_model_config"),choices:_}]);if("exit"===y.type)console.log(t.green("\n👋 "+c.t("wizard.goodbye_message"))),process.exit(0);else if("preset"===y.type){const e=r(y.preset);i.setModels(e),console.log(t.green("\n✓ "+c.t("wizard.models_saved"))),await this.promptLoadAfterModelConfig()}else if("custom_input"===y.type){const{customModel:a}=await e.prompt([{type:"input",name:"customModel",message:c.t("wizard.input_custom_model"),default:o.sonnet}]);i.setModels({haiku:a,sonnet:a,opus:a,reasoning:a}),console.log(t.green("\n✓ "+c.t("wizard.models_saved"))),await this.promptLoadAfterModelConfig()}else if("load_tool"===y.type)await this.selectAndConfigureTool();else if("apikey"===y.type){await this.configApiKey();const e=i.getApiKey();if(e){const t=await m(e);this.apiKeyValid=t.valid}else this.apiKeyValid=!1}else"language"===y.type&&await this.configLanguage()}}}export const wizard=Wizard.getInstance();
|