yingclaw 1.3.0 → 1.4.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/bin/cli.js +64 -35
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -119,8 +119,10 @@ program
|
|
|
119
119
|
choices: [
|
|
120
120
|
{ name: '有梯子 / 海外网络(走官方)', value: 'vpn' },
|
|
121
121
|
{ name: '国内网络 / 没有梯子(走镜像)', value: 'cn' },
|
|
122
|
+
{ name: chalk.dim('↩ 返回主菜单'), value: '__BACK__' },
|
|
122
123
|
],
|
|
123
124
|
});
|
|
125
|
+
if (network === '__BACK__') return;
|
|
124
126
|
|
|
125
127
|
const cmd = network === 'vpn'
|
|
126
128
|
? 'npm install -g @anthropic-ai/claude-code'
|
|
@@ -183,42 +185,61 @@ program
|
|
|
183
185
|
if (!overwrite) return;
|
|
184
186
|
}
|
|
185
187
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
188
|
+
let providerKey, provider, apiKey, model;
|
|
189
|
+
let step = 'provider';
|
|
190
|
+
|
|
191
|
+
while (true) {
|
|
192
|
+
if (step === 'provider') {
|
|
193
|
+
providerKey = await select({
|
|
194
|
+
message: chalk.cyan('选择 AI 厂商'),
|
|
195
|
+
choices: [
|
|
196
|
+
...Object.entries(PROVIDERS).map(([value, p]) => ({ name: p.name, value })),
|
|
197
|
+
{ name: chalk.dim('↩ 返回主菜单'), value: '__BACK__' },
|
|
198
|
+
],
|
|
199
|
+
});
|
|
200
|
+
if (providerKey === '__BACK__') return;
|
|
201
|
+
provider = PROVIDERS[providerKey];
|
|
202
|
+
step = 'apikey';
|
|
203
|
+
} else if (step === 'apikey') {
|
|
204
|
+
const k = await input({
|
|
205
|
+
message: chalk.cyan(`${provider.name} API Key(输入 b 返回上一步)`),
|
|
206
|
+
transformer: (v) => v && v !== 'b' ? chalk.dim('•'.repeat(v.length)) : v,
|
|
207
|
+
validate: (v) => v.trim().length > 0 ? true : 'API Key 不能为空',
|
|
208
|
+
});
|
|
209
|
+
if (k.trim() === 'b') { step = 'provider'; continue; }
|
|
210
|
+
apiKey = k.trim();
|
|
211
|
+
step = 'model';
|
|
212
|
+
} else if (step === 'model') {
|
|
213
|
+
const fetchSpinner = ora('正在获取可用模型...').start();
|
|
214
|
+
const onlineModels = await fetchModels(providerKey, apiKey);
|
|
215
|
+
let modelChoices;
|
|
216
|
+
if (onlineModels && onlineModels.length > 0) {
|
|
217
|
+
fetchSpinner.succeed(chalk.green(`已获取 ${onlineModels.length} 个可用模型`));
|
|
218
|
+
modelChoices = onlineModels.map(id => ({ name: id, value: id }));
|
|
219
|
+
} else {
|
|
220
|
+
fetchSpinner.warn(chalk.yellow('无法获取在线列表,使用内置默认列表'));
|
|
221
|
+
modelChoices = provider.models;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const m = await select({
|
|
225
|
+
message: chalk.cyan('选择模型'),
|
|
226
|
+
choices: [
|
|
227
|
+
...modelChoices,
|
|
228
|
+
{ name: chalk.dim('↩ 返回上一步(重新输入 Key)'), value: '__BACK__' },
|
|
229
|
+
],
|
|
230
|
+
});
|
|
231
|
+
if (m === '__BACK__') { step = 'apikey'; continue; }
|
|
232
|
+
model = m;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
209
235
|
}
|
|
210
236
|
|
|
211
|
-
const model = await select({
|
|
212
|
-
message: chalk.cyan('选择模型'),
|
|
213
|
-
choices: modelChoices,
|
|
214
|
-
});
|
|
215
|
-
|
|
216
237
|
const spinner = ora('写入配置...').start();
|
|
217
238
|
let result, file;
|
|
218
239
|
try {
|
|
219
|
-
const
|
|
220
|
-
saveConfig(
|
|
221
|
-
({ result, file } = writeEnvToZshrc(provider.baseUrl, apiKey
|
|
240
|
+
const cfg = { provider: providerKey, model, apiKey, baseUrl: provider.baseUrl };
|
|
241
|
+
saveConfig(cfg);
|
|
242
|
+
({ result, file } = writeEnvToZshrc(provider.baseUrl, apiKey));
|
|
222
243
|
spinner.succeed(chalk.green(result === 'updated' ? `环境变量已更新 → ${file}` : `环境变量已写入 → ${file}`));
|
|
223
244
|
} catch (e) {
|
|
224
245
|
spinner.fail(chalk.red(`写入失败: ${e.message}`));
|
|
@@ -229,7 +250,7 @@ program
|
|
|
229
250
|
console.log(boxen(
|
|
230
251
|
chalk.bold('配置完成!\n\n') +
|
|
231
252
|
chalk.dim('ANTHROPIC_BASE_URL ') + chalk.cyan(provider.baseUrl) + '\n' +
|
|
232
|
-
chalk.dim('ANTHROPIC_API_KEY ') + chalk.cyan(apiKey.
|
|
253
|
+
chalk.dim('ANTHROPIC_API_KEY ') + chalk.cyan(apiKey.slice(0, 10) + '...') + '\n\n' +
|
|
233
254
|
chalk.white('下次直接输入 ') + chalk.cyan.bold('claude') + chalk.white(' 即可使用'),
|
|
234
255
|
{ padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'green', margin: { top: 1, bottom: 1 } }
|
|
235
256
|
));
|
|
@@ -240,7 +261,7 @@ program
|
|
|
240
261
|
|
|
241
262
|
spawn('claude', [], {
|
|
242
263
|
stdio: 'inherit',
|
|
243
|
-
env: { ...process.env, ANTHROPIC_BASE_URL: provider.baseUrl, ANTHROPIC_API_KEY: apiKey
|
|
264
|
+
env: { ...process.env, ANTHROPIC_BASE_URL: provider.baseUrl, ANTHROPIC_API_KEY: apiKey },
|
|
244
265
|
}).on('error', () => {
|
|
245
266
|
console.log(chalk.yellow('\nClaude Code 未找到,请先运行: claw install-claude'));
|
|
246
267
|
});
|
|
@@ -263,8 +284,12 @@ program
|
|
|
263
284
|
|
|
264
285
|
const providerKey = await select({
|
|
265
286
|
message: chalk.cyan('选择 AI 厂商'),
|
|
266
|
-
choices:
|
|
287
|
+
choices: [
|
|
288
|
+
...Object.entries(PROVIDERS).map(([value, p]) => ({ name: p.name, value })),
|
|
289
|
+
{ name: chalk.dim('↩ 返回主菜单'), value: '__BACK__' },
|
|
290
|
+
],
|
|
267
291
|
});
|
|
292
|
+
if (providerKey === '__BACK__') return;
|
|
268
293
|
|
|
269
294
|
const provider = PROVIDERS[providerKey];
|
|
270
295
|
|
|
@@ -296,8 +321,12 @@ program
|
|
|
296
321
|
|
|
297
322
|
const model = await select({
|
|
298
323
|
message: chalk.cyan('选择模型'),
|
|
299
|
-
choices:
|
|
324
|
+
choices: [
|
|
325
|
+
...modelChoices,
|
|
326
|
+
{ name: chalk.dim('↩ 返回主菜单'), value: '__BACK__' },
|
|
327
|
+
],
|
|
300
328
|
});
|
|
329
|
+
if (model === '__BACK__') return;
|
|
301
330
|
|
|
302
331
|
const spinner = ora('切换中...').start();
|
|
303
332
|
const newConfig = { ...config, provider: providerKey, model, baseUrl: provider.baseUrl, apiKey };
|