myclaude-code 8.8.13 → 8.8.14

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.
@@ -56,7 +56,7 @@ function buildHelpText() {
56
56
  ' /provider matrix',
57
57
  ' /provider repair',
58
58
  ' /provider use kimi',
59
- ' /provider gpt54-main',
59
+ ' /provider <saved-profile-name>',
60
60
  ' /provider clear',
61
61
  ].join('\n')
62
62
  }
@@ -5,7 +5,7 @@ import { dirname, join } from 'node:path'
5
5
  import { createInterface } from 'node:readline/promises'
6
6
  import { stdin, stdout } from 'node:process'
7
7
 
8
- const APP_VERSION = '8.8.13'
8
+ const APP_VERSION = '8.8.14'
9
9
  const CURRENT_PROVIDER_PROFILE_ID = '__current_provider__'
10
10
  const SUPPORTED_LANGUAGES = new Set(['en', 'zh'])
11
11
  const PROVIDER_CAPABILITY_CACHE_TTL_MS = 60 * 60 * 1000
@@ -208,6 +208,48 @@ export const DEFAULT_PROVIDER_ROUTE_DIAGNOSTIC_MODELS = [
208
208
  'gpt-5.3-codex-spark',
209
209
  ]
210
210
 
211
+ const ANSI_RESET = '\u001b[0m'
212
+ const ANSI_BOLD = '\u001b[1m'
213
+ const ANSI_DIM = '\u001b[2m'
214
+ const ANSI_CYAN = '\u001b[36m'
215
+ const ANSI_GREEN = '\u001b[32m'
216
+ const ANSI_YELLOW = '\u001b[33m'
217
+ const ANSI_RED = '\u001b[31m'
218
+
219
+ function isAnsiEnabled() {
220
+ return stdout.isTTY && process.env.NO_COLOR !== '1' && process.env.TERM !== 'dumb'
221
+ }
222
+
223
+ function paint(value, ...codes) {
224
+ const text = String(value || '')
225
+ if (!text || !isAnsiEnabled()) return text
226
+ return `${codes.join('')}${text}${ANSI_RESET}`
227
+ }
228
+
229
+ function accent(value) {
230
+ return paint(value, ANSI_BOLD, ANSI_CYAN)
231
+ }
232
+
233
+ function strong(value) {
234
+ return paint(value, ANSI_BOLD)
235
+ }
236
+
237
+ function subtle(value) {
238
+ return paint(value, ANSI_DIM)
239
+ }
240
+
241
+ function positive(value) {
242
+ return paint(value, ANSI_GREEN)
243
+ }
244
+
245
+ function caution(value) {
246
+ return paint(value, ANSI_YELLOW)
247
+ }
248
+
249
+ function danger(value) {
250
+ return paint(value, ANSI_RED)
251
+ }
252
+
211
253
  function getClaudeConfigHomeDir() {
212
254
  return process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude')
213
255
  }
@@ -273,14 +315,17 @@ function getMessages(language) {
273
315
  apiConfigSubtitle: '配置供应商档案、API URL、凭证和路由角色。',
274
316
  firstRunHint: '检测到首次运行。请先配置一个供应商档案后再启动 myclaude。',
275
317
  normalHint:
276
- 'myclaude 使用直接供应商配置,不需要 Claude Code 官方账号登录。使用 /provider 管理兼容 Anthropic 的供应商或网关档案。',
318
+ '不需要 Claude Code 官方账号登录。myclaude 只判断是否已配置 API 供应商档案;使用 /provider 管理兼容 Anthropic 的供应商或网关档案。',
277
319
  requiredField: '此项为必填。',
278
320
  invalidChoice: '无效选择,请输入列表中的数字。',
279
321
  cancelOption: '取消',
322
+ menuInputHint: '输入编号并按回车。',
323
+ selectionPrompt: '选择',
324
+ valuePrompt: '输入',
280
325
  chooseLanguage: '请选择语言',
281
326
  languageChinese: '中文',
282
327
  languageEnglish: 'English',
283
- chooseAction: '档案',
328
+ chooseAction: '选择 /provider 操作',
284
329
  addProvider: '新增档案',
285
330
  addProviderDesc: '新建一个可复用的供应商档案并立即启用',
286
331
  editProvider: '编辑档案',
@@ -303,15 +348,17 @@ function getMessages(language) {
303
348
  providerName: '档案名称',
304
349
  apiUrl: 'API URL',
305
350
  invalidApiUrl: 'API URL 必须以 http:// 或 https:// 开头',
306
- chooseModelRouting: '路由预设',
351
+ chooseModelRouting: '选择模型路由预设',
352
+ modelRoutingHint: '在这里设置主线程、子代理和快速辅助模型;其余角色会自动跟随。',
307
353
  primaryModel: '主线程模型',
308
354
  subagentModel: '子代理模型',
309
355
  fastHelperModel: '快速辅助模型',
310
- confirmProviderSetup: '检查并启用',
356
+ confirmProviderSetup: '保存前检查',
311
357
  provider: '档案',
312
358
  preset: '供应商预设',
313
359
  auth: '认证方式',
314
360
  modelRouting: '路由预设',
361
+ routingSummary: '模型路由摘要',
315
362
  providerDefault: '供应商默认',
316
363
  inheritFromMain: '继承主线程模型',
317
364
  saveProviderNow: '现在保存并启用这个档案吗?',
@@ -329,14 +376,16 @@ function getMessages(language) {
329
376
  keepUnchanged: '返回',
330
377
  keepUnchangedDesc: '回到档案列表',
331
378
  activeSuffix: ' (当前启用)',
332
- startupPrompt: '请选择启动方式',
333
- startupUseCurrent: '直接使用当前档案',
379
+ startupPrompt: '启动 myclaude',
380
+ startupUseCurrent: '直接进入当前档案',
334
381
  startupUseCurrentDesc: '使用当前供应商档案、API URL、凭证和路由角色启动 myclaude',
335
- startupConfigure: '打开 /provider 配置',
382
+ startupConfigure: '先打开 /provider',
336
383
  startupConfigureDesc: '启动前修改当前档案、API URL、凭证或路由角色',
337
384
  startupExit: '退出',
338
385
  startupExitDesc: '先不进入 myclaude',
339
- currentConfiguration: '当前档案',
386
+ currentConfiguration: '当前启用档案',
387
+ currentConfigurationHint:
388
+ '进入 myclaude 后可用 /provider current、/provider validate、/provider repair 查看、验证或自动修复当前路由。',
340
389
  manualModel: '手动输入模型 ID',
341
390
  manualModelDesc: '直接填写原始模型 ID,例如 gpt-5.4',
342
391
  validatingModels: '正在验证当前供应商与模型路由...',
@@ -368,14 +417,17 @@ function getMessages(language) {
368
417
  firstRunHint:
369
418
  'First run detected. Configure a provider profile before starting myclaude.',
370
419
  normalHint:
371
- 'myclaude uses direct provider setup instead of Claude Code account login. Use /provider to manage Anthropic-compatible provider or gateway profiles.',
420
+ 'No Claude Code login is required. myclaude only checks whether an API provider profile is configured; use /provider to manage Anthropic-compatible provider or gateway profiles.',
372
421
  requiredField: 'This field is required.',
373
422
  invalidChoice: 'Invalid choice. Enter one of the listed numbers.',
374
423
  cancelOption: 'Cancel',
424
+ menuInputHint: 'Enter a number and press Enter.',
425
+ selectionPrompt: 'Selection',
426
+ valuePrompt: 'Value',
375
427
  chooseLanguage: 'Choose language',
376
428
  languageChinese: '中文',
377
429
  languageEnglish: 'English',
378
- chooseAction: 'Profiles',
430
+ chooseAction: 'Choose /provider action',
379
431
  addProvider: 'Add profile',
380
432
  addProviderDesc: 'Create a reusable provider profile and activate it now',
381
433
  editProvider: 'Edit profile',
@@ -398,15 +450,18 @@ function getMessages(language) {
398
450
  providerName: 'Profile name',
399
451
  apiUrl: 'API URL',
400
452
  invalidApiUrl: 'API URL must start with http:// or https://',
401
- chooseModelRouting: 'Routing preset',
453
+ chooseModelRouting: 'Choose model routing preset',
454
+ modelRoutingHint:
455
+ 'Set the main thread, subagent, and fast helper models here. Derived roles update automatically.',
402
456
  primaryModel: 'Main thread model',
403
457
  subagentModel: 'Subagent model',
404
458
  fastHelperModel: 'Fast helper model',
405
- confirmProviderSetup: 'Review and activate',
459
+ confirmProviderSetup: 'Review before save',
406
460
  provider: 'Profile',
407
461
  preset: 'Provider preset',
408
462
  auth: 'Auth',
409
463
  modelRouting: 'Routing preset',
464
+ routingSummary: 'Model routing summary',
410
465
  providerDefault: 'Provider default',
411
466
  inheritFromMain: 'Inherit from main thread',
412
467
  saveProviderNow: 'Save and activate this profile now?',
@@ -424,16 +479,18 @@ function getMessages(language) {
424
479
  keepUnchanged: 'Go back',
425
480
  keepUnchangedDesc: 'Return to the profile list',
426
481
  activeSuffix: ' (active)',
427
- startupPrompt: 'Choose how to start',
428
- startupUseCurrent: 'Use current profile',
482
+ startupPrompt: 'Start myclaude',
483
+ startupUseCurrent: 'Enter chat with current profile',
429
484
  startupUseCurrentDesc:
430
485
  'Start myclaude with the current provider profile, API URL, credential, and routing roles',
431
- startupConfigure: 'Open /provider setup',
486
+ startupConfigure: 'Open /provider before chat',
432
487
  startupConfigureDesc:
433
488
  'Change the active profile, API URL, credential, or routing roles before starting',
434
489
  startupExit: 'Exit',
435
490
  startupExitDesc: 'Do not enter myclaude right now',
436
- currentConfiguration: 'Current profile',
491
+ currentConfiguration: 'Active profile',
492
+ currentConfigurationHint:
493
+ 'Inside myclaude, use /provider current, /provider validate, or /provider repair to inspect, verify, or repair this routing.',
437
494
  manualModel: 'Enter raw model ID',
438
495
  manualModelDesc: 'Type an exact model ID such as gpt-5.4',
439
496
  validatingModels: 'Validating the selected provider and model routing...',
@@ -2987,17 +3044,80 @@ function printLine(value = '') {
2987
3044
  stdout.write(`${value}\n`)
2988
3045
  }
2989
3046
 
3047
+ function printDivider() {
3048
+ printLine(subtle('------------------------------------------------------------'))
3049
+ }
3050
+
3051
+ function printSectionTitle(title) {
3052
+ printLine(accent(title))
3053
+ }
3054
+
3055
+ function renderTone(value, tone) {
3056
+ const text = String(value || '')
3057
+ if (tone === 'positive') return positive(text)
3058
+ if (tone === 'caution') return caution(text)
3059
+ if (tone === 'danger') return danger(text)
3060
+ return text
3061
+ }
3062
+
3063
+ function printKeyValueRows(rows) {
3064
+ for (const row of rows) {
3065
+ printLine(` ${strong(`${row.label}:`)} ${renderTone(row.value, row.tone)}`)
3066
+ }
3067
+ }
3068
+
3069
+ function buildProfileSummaryRows(profile, messages) {
3070
+ return [
3071
+ {
3072
+ label: messages.provider,
3073
+ value: profile.name,
3074
+ tone: 'positive',
3075
+ },
3076
+ {
3077
+ label: messages.apiUrl,
3078
+ value: profile.baseUrl,
3079
+ },
3080
+ {
3081
+ label: getCredentialLabel(profile.authType),
3082
+ value: maskCredential(profile.credential),
3083
+ },
3084
+ {
3085
+ label: messages.primaryModel,
3086
+ value: getModelDisplayValue(
3087
+ profile.modelRouting?.primaryModel,
3088
+ messages.providerDefault,
3089
+ ),
3090
+ },
3091
+ {
3092
+ label: messages.subagentModel,
3093
+ value: getModelDisplayValue(
3094
+ profile.modelRouting?.subagentModel,
3095
+ messages.inheritFromMain,
3096
+ ),
3097
+ },
3098
+ {
3099
+ label: messages.fastHelperModel,
3100
+ value: getModelDisplayValue(
3101
+ profile.modelRouting?.smallFastModel,
3102
+ messages.providerDefault,
3103
+ ),
3104
+ },
3105
+ ]
3106
+ }
3107
+
2990
3108
  function printHeader(reason, language) {
2991
3109
  const messages = getMessages(language)
2992
3110
  printLine()
2993
- printLine(messages.setupTitle)
2994
- printLine(messages.apiConfigTitle)
3111
+ printLine(subtle(`myclaude v${APP_VERSION}`))
3112
+ printLine(accent(`${messages.setupTitle} ${messages.apiConfigTitle}`))
2995
3113
  printLine(messages.apiConfigSubtitle)
3114
+ printLine(subtle(messages.normalHint))
2996
3115
  if (reason === 'first-run') {
2997
- printLine(messages.firstRunHint)
2998
- } else {
2999
- printLine(messages.normalHint)
3116
+ printLine(caution(messages.firstRunHint))
3117
+ } else if (reason === 'startup-validation-failed') {
3118
+ printLine(caution(messages.validationReconfigure))
3000
3119
  }
3120
+ printDivider()
3001
3121
  printLine()
3002
3122
  }
3003
3123
 
@@ -3005,29 +3125,33 @@ function formatCurrentConfigurationSummary(language) {
3005
3125
  const messages = getMessages(language)
3006
3126
  const currentProfile = getResolvedCurrentProviderProfile()
3007
3127
  if (!currentProfile) {
3008
- return []
3128
+ return null
3009
3129
  }
3010
3130
 
3011
- return [
3012
- messages.currentConfiguration,
3013
- `${messages.provider}: ${currentProfile.name}`,
3014
- `${messages.apiUrl}: ${currentProfile.baseUrl}`,
3015
- `${getCredentialLabel(currentProfile.authType)}: ${maskCredential(
3016
- currentProfile.credential,
3017
- )}`,
3018
- `${messages.primaryModel}: ${getModelDisplayValue(
3019
- currentProfile.modelRouting?.primaryModel,
3020
- messages.providerDefault,
3021
- )}`,
3022
- `${messages.subagentModel}: ${getModelDisplayValue(
3023
- currentProfile.modelRouting?.subagentModel,
3024
- messages.inheritFromMain,
3025
- )}`,
3026
- `${messages.fastHelperModel}: ${getModelDisplayValue(
3027
- currentProfile.modelRouting?.smallFastModel,
3028
- messages.providerDefault,
3029
- )}`,
3030
- ]
3131
+ return {
3132
+ title: messages.currentConfiguration,
3133
+ rows: buildProfileSummaryRows(currentProfile, messages),
3134
+ hint: messages.currentConfigurationHint,
3135
+ }
3136
+ }
3137
+
3138
+ function printRoutingSummary(routing, language) {
3139
+ const messages = getMessages(language)
3140
+ printSectionTitle(messages.routingSummary)
3141
+ printKeyValueRows([
3142
+ {
3143
+ label: messages.primaryModel,
3144
+ value: getModelDisplayValue(routing?.primaryModel, messages.providerDefault),
3145
+ },
3146
+ {
3147
+ label: messages.subagentModel,
3148
+ value: getModelDisplayValue(routing?.subagentModel, messages.inheritFromMain),
3149
+ },
3150
+ {
3151
+ label: messages.fastHelperModel,
3152
+ value: getModelDisplayValue(routing?.smallFastModel, messages.providerDefault),
3153
+ },
3154
+ ])
3031
3155
  }
3032
3156
 
3033
3157
  async function askText(
@@ -3039,16 +3163,19 @@ async function askText(
3039
3163
  const messages = getMessages(language)
3040
3164
  while (true) {
3041
3165
  const suffix = initialValue ? ` [${initialValue}]` : ''
3042
- const answer = (await rl.question(`${label}${suffix}: `)).trim()
3166
+ const promptLabel = `${label}${suffix || ''}`
3167
+ const answer = (
3168
+ await rl.question(accent(`${promptLabel} (${messages.valuePrompt}) > `))
3169
+ ).trim()
3043
3170
  const value = answer || initialValue
3044
3171
  if (required && !value) {
3045
- printLine(messages.requiredField)
3172
+ printLine(caution(messages.requiredField))
3046
3173
  continue
3047
3174
  }
3048
3175
  if (validate) {
3049
3176
  const error = validate(value)
3050
3177
  if (error) {
3051
- printLine(error)
3178
+ printLine(danger(error))
3052
3179
  continue
3053
3180
  }
3054
3181
  }
@@ -3064,16 +3191,24 @@ async function askSelect(
3064
3191
  ) {
3065
3192
  const messages = getMessages(language)
3066
3193
  while (true) {
3067
- printLine(title)
3194
+ printSectionTitle(title)
3195
+ printLine(subtle(messages.menuInputHint))
3196
+ printLine()
3068
3197
  for (let index = 0; index < options.length; index += 1) {
3069
3198
  const option = options[index]
3070
- const prefix = `${index + 1}. ${option.label}`
3071
- printLine(option.description ? `${prefix} ${option.description}` : prefix)
3199
+ const prefix = accent(`[${index + 1}]`)
3200
+ printLine(` ${prefix} ${strong(option.label)}`)
3201
+ if (option.description) {
3202
+ printLine(` ${subtle(option.description)}`)
3203
+ }
3072
3204
  }
3073
3205
  if (allowCancel) {
3074
- printLine(`0. ${messages.cancelOption}`)
3206
+ printLine(` ${subtle('[0]')} ${messages.cancelOption}`)
3075
3207
  }
3076
- const answer = (await rl.question('Choose: ')).trim()
3208
+ printLine()
3209
+ const answer = (
3210
+ await rl.question(accent(`${messages.selectionPrompt} > `))
3211
+ ).trim()
3077
3212
  if (allowCancel && (answer === '0' || answer.toLowerCase() === 'q')) {
3078
3213
  return null
3079
3214
  }
@@ -3081,7 +3216,8 @@ async function askSelect(
3081
3216
  if (Number.isInteger(selected) && selected >= 1 && selected <= options.length) {
3082
3217
  return options[selected - 1].value
3083
3218
  }
3084
- printLine(messages.invalidChoice)
3219
+ printLine(danger(messages.invalidChoice))
3220
+ printLine()
3085
3221
  }
3086
3222
  }
3087
3223
 
@@ -3220,6 +3356,9 @@ async function configureProfile(
3220
3356
  }, language)
3221
3357
  draft.providerId = inferProviderPresetId(draft.baseUrl)
3222
3358
 
3359
+ printLine()
3360
+ printLine(subtle(messages.modelRoutingHint))
3361
+ printLine()
3223
3362
  const routingPresetId = await askSelect(
3224
3363
  rl,
3225
3364
  messages.chooseModelRouting,
@@ -3233,6 +3372,9 @@ async function configureProfile(
3233
3372
  if (!routingPresetId) return null
3234
3373
 
3235
3374
  if (routingPresetId === 'custom') {
3375
+ printLine()
3376
+ printLine(subtle(messages.modelRoutingHint))
3377
+ printLine()
3236
3378
  const primaryModel = await askModelChoice(
3237
3379
  rl,
3238
3380
  messages.primaryModel,
@@ -3278,33 +3420,36 @@ async function configureProfile(
3278
3420
  }
3279
3421
 
3280
3422
  printLine()
3281
- printLine(messages.confirmProviderSetup)
3282
- printLine(`${messages.provider}: ${draft.name}`)
3283
- printLine(`${messages.preset}: ${getProviderPreset(draft.providerId).name}`)
3284
- printLine(`${messages.auth}: ${getCredentialLabel(draft.authType)}`)
3285
- printLine(`${messages.apiUrl}: ${draft.baseUrl}`)
3286
- printLine(`${getCredentialLabel(draft.authType)}: ${maskCredential(draft.credential)}`)
3287
- printLine(
3288
- `${messages.modelRouting}: ${getProviderModelRoutingPreset(draft.modelRouting.presetId).name}`,
3289
- )
3290
- printLine(
3291
- `${messages.primaryModel}: ${getModelDisplayValue(
3292
- draft.modelRouting.primaryModel,
3293
- messages.providerDefault,
3294
- )}`,
3295
- )
3296
- printLine(
3297
- `${messages.subagentModel}: ${getModelDisplayValue(
3298
- draft.modelRouting.subagentModel,
3299
- messages.inheritFromMain,
3300
- )}`,
3301
- )
3302
- printLine(
3303
- `${messages.fastHelperModel}: ${getModelDisplayValue(
3304
- draft.modelRouting.smallFastModel,
3305
- messages.providerDefault,
3306
- )}`,
3307
- )
3423
+ printSectionTitle(messages.confirmProviderSetup)
3424
+ printKeyValueRows([
3425
+ {
3426
+ label: messages.provider,
3427
+ value: draft.name,
3428
+ tone: 'positive',
3429
+ },
3430
+ {
3431
+ label: messages.preset,
3432
+ value: getProviderPreset(draft.providerId).name,
3433
+ },
3434
+ {
3435
+ label: messages.auth,
3436
+ value: getCredentialLabel(draft.authType),
3437
+ },
3438
+ {
3439
+ label: messages.apiUrl,
3440
+ value: draft.baseUrl,
3441
+ },
3442
+ {
3443
+ label: getCredentialLabel(draft.authType),
3444
+ value: maskCredential(draft.credential),
3445
+ },
3446
+ {
3447
+ label: messages.modelRouting,
3448
+ value: getProviderModelRoutingPreset(draft.modelRouting.presetId).name,
3449
+ },
3450
+ ])
3451
+ printLine()
3452
+ printRoutingSummary(draft.modelRouting, language)
3308
3453
  printLine()
3309
3454
 
3310
3455
  const saveChoice = await askSelect(rl, messages.saveProviderNow, [
@@ -3515,8 +3660,13 @@ export async function runMyclaudeStartupChooser(options = {}) {
3515
3660
 
3516
3661
  printHeader(options.reason || 'startup', language)
3517
3662
  const summary = formatCurrentConfigurationSummary(language)
3518
- for (const line of summary) {
3519
- printLine(line)
3663
+ if (summary) {
3664
+ printSectionTitle(summary.title)
3665
+ printKeyValueRows(summary.rows)
3666
+ if (summary.hint) {
3667
+ printLine()
3668
+ printLine(subtle(summary.hint))
3669
+ }
3520
3670
  }
3521
3671
  printLine()
3522
3672
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myclaude-code",
3
- "version": "8.8.13",
3
+ "version": "8.8.14",
4
4
  "description": "myclaude: fast-start AI coding CLI with no Claude Code login and quick third-party API setup",
5
5
  "keywords": [
6
6
  "myclaude",