viepilot 2.45.4 → 2.45.5

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 CHANGED
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.45.5] - 2026-04-27
11
+
12
+ ### Enhanced
13
+ - **ENH-078**: `npx viepilot install` now prompts users to select their preferred
14
+ communication language (the language ViePilot uses for banners and AI prompts)
15
+ via keyboard selector or numbered-list fallback; chosen language written to
16
+ `~/.viepilot/config.json → language.communication`; supports 10 languages
17
+ (en, vi, fr, ja, de, es, zh, ko, pt, id); `--yes` mode skips prompt and
18
+ defaults to `en` (ENH-078)
19
+
10
20
  ## [2.45.4] - 2026-04-27
11
21
 
12
22
  ### Fixed
package/bin/viepilot.cjs CHANGED
@@ -17,6 +17,19 @@ const { buildInstallPlan, applyInstallPlan, resolveViepilotPackageRoot } = requi
17
17
  const { adapters: adapterMap } = require(path.join(__dirname, '..', 'lib', 'adapters', 'index.cjs'));
18
18
 
19
19
  // UI target list — keep cursor-agent and cursor-ide as distinct choices for users.
20
+ const LANGUAGES = [
21
+ { id: 'en', label: 'English (en)' },
22
+ { id: 'vi', label: 'Vietnamese — Tiếng Việt (vi)' },
23
+ { id: 'fr', label: 'French — Français (fr)' },
24
+ { id: 'ja', label: 'Japanese — 日本語 (ja)' },
25
+ { id: 'de', label: 'German — Deutsch (de)' },
26
+ { id: 'es', label: 'Spanish — Español (es)' },
27
+ { id: 'zh', label: 'Chinese Simplified — 中文 (zh)' },
28
+ { id: 'ko', label: 'Korean — 한국어 (ko)' },
29
+ { id: 'pt', label: 'Portuguese — Português (pt)' },
30
+ { id: 'id', label: 'Indonesian — Bahasa Indonesia (id)' },
31
+ ];
32
+
20
33
  const TARGETS = [
21
34
  { id: 'claude-code', label: adapterMap['claude-code'].name + ' (default)' },
22
35
  { id: 'cursor-agent', label: 'Cursor Agent' },
@@ -235,6 +248,19 @@ function ask(question) {
235
248
  });
236
249
  }
237
250
 
251
+ async function interactiveLanguageSelection() {
252
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
253
+ console.log('\nSelect communication language (ViePilot banners and prompts):');
254
+ LANGUAGES.forEach((l, idx) => console.log(` ${idx + 1}. ${l.label}`));
255
+ const answer = await ask('Language [1 = English]: ');
256
+ const idx = parseInt(answer, 10);
257
+ const lang = LANGUAGES[Number.isInteger(idx) && idx >= 1 && idx <= LANGUAGES.length ? idx - 1 : 0];
258
+ return lang.id;
259
+ }
260
+ const selected = await runKeyboardSelector(LANGUAGES, 'single', 'Select communication language');
261
+ return (selected && selected[0]) || 'en';
262
+ }
263
+
238
264
  async function interactiveTargetSelection() {
239
265
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
240
266
  console.log('\nSelect install targets (comma-separated numbers):');
@@ -261,7 +287,7 @@ async function interactiveTargetSelection() {
261
287
  * @param {boolean} dryRun
262
288
  * @returns {{ ok: boolean, code: number }}
263
289
  */
264
- function runInstallViaNode(selectedTargets, dryRun) {
290
+ function runInstallViaNode(selectedTargets, dryRun, communicationLang = 'en') {
265
291
  const fallbackRoot = path.join(__dirname, '..');
266
292
  const pkgRoot = resolveViepilotPackageRoot(fallbackRoot) || fallbackRoot;
267
293
  const profile = selectedTargets[0] || 'claude-code';
@@ -269,6 +295,7 @@ function runInstallViaNode(selectedTargets, dryRun) {
269
295
  ...process.env,
270
296
  VIEPILOT_AUTO_YES: '1',
271
297
  VIEPILOT_INSTALL_PROFILE: profile,
298
+ VIEPILOT_COMM_LANG: communicationLang,
272
299
  };
273
300
  const wantPathShim = env.VIEPILOT_ADD_PATH === '1';
274
301
 
@@ -328,8 +355,14 @@ async function installCommand(rawArgs) {
328
355
  }
329
356
  }
330
357
 
358
+ let communicationLang = 'en';
359
+ if (!options.yes) {
360
+ communicationLang = await interactiveLanguageSelection();
361
+ }
362
+
331
363
  console.log(`\nSelected targets: ${selectedTargets.join(', ')}`);
332
- const run = runInstallViaNode(selectedTargets, options.dryRun);
364
+ console.log(`Communication language: ${communicationLang}`);
365
+ const run = runInstallViaNode(selectedTargets, options.dryRun, communicationLang);
333
366
  const results = selectedTargets.map((target) => ({
334
367
  ok: run.ok,
335
368
  target,
@@ -29,6 +29,7 @@ function normalizeInstallEnv(envSource = process.env) {
29
29
  profile: envSource.VIEPILOT_INSTALL_PROFILE || 'claude-code',
30
30
  addPath: envSource.VIEPILOT_ADD_PATH === '1',
31
31
  symlinkSkills: envSource.VIEPILOT_SYMLINK_SKILLS === '1',
32
+ communicationLang: envSource.VIEPILOT_COMM_LANG || 'en',
32
33
  };
33
34
  }
34
35
 
@@ -241,9 +242,10 @@ function buildInstallPlan(packageRoot, envSource = process.env, opts = {}) {
241
242
  });
242
243
  }
243
244
 
244
- // ENH-032: prompt for language config at end of install
245
+ // ENH-032 / ENH-078: write selected communication language; lang chosen interactively in CLI
245
246
  steps.push({
246
247
  kind: 'language_config_prompt',
248
+ communicationLang: env.communicationLang,
247
249
  autoYes: env.autoYes,
248
250
  home,
249
251
  });
@@ -519,13 +521,13 @@ function applyInstallPlan(plan, options = {}) {
519
521
  break;
520
522
  }
521
523
  case 'language_config_prompt': {
524
+ const commLang = step.communicationLang ?? 'en';
522
525
  if (dryRun) {
523
- logs.push(`[dry-run] language_config_prompt: would write ~/.viepilot/config.json with communication=en, document=en`);
526
+ logs.push(`[dry-run] language_config_prompt: would write ~/.viepilot/config.json with communication=${commLang}, document=en`);
524
527
  break;
525
528
  }
526
- // Write defaults; future interactive installer can prompt here
527
- writeConfig({ language: { communication: 'en', document: 'en' } }, step.home);
528
- logs.push(`language_config_prompt: wrote ${step.home}/.viepilot/config.json (communication=en, document=en)`);
529
+ writeConfig({ language: { communication: commLang, document: 'en' } }, step.home);
530
+ logs.push(`language_config_prompt: wrote ${step.home}/.viepilot/config.json (communication=${commLang}, document=en)`);
529
531
  break;
530
532
  }
531
533
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viepilot",
3
- "version": "2.45.4",
3
+ "version": "2.45.5",
4
4
  "description": "**Autonomous Vibe Coding Framework / Bộ khung phát triển tự động có kiểm soát**",
5
5
  "main": "index.js",
6
6
  "bin": {