agentvibes 5.11.2 → 5.12.0-alpha.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/.agentvibes/config.json +1 -15
- package/.claude/activation-instructions +54 -54
- package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
- package/.claude/commands/agent-vibes-rdp.md +24 -24
- package/.claude/config/audio-effects.cfg +5 -5
- package/.claude/config/background-music-enabled.txt +1 -1
- package/.claude/docs/TERMUX_SETUP.md +408 -408
- package/.claude/github-star-reminder.txt +1 -1
- package/.claude/hooks/audio-processor.sh +1 -1
- package/.claude/hooks/background-music-manager.sh +2 -1
- package/.claude/hooks/bmad-speak-enhanced.sh +37 -22
- package/.claude/hooks/bmad-speak.sh +26 -8
- package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +1 -1
- package/.claude/hooks/play-tts-kokoro.sh +9 -0
- package/.claude/hooks/play-tts-piper.sh +13 -1
- package/.claude/hooks/play-tts-ssh-remote.sh +78 -5
- package/.claude/hooks/play-tts-termux-ssh.sh +1 -1
- package/.claude/hooks/play-tts.sh +85 -4
- package/.claude/hooks-windows/background-music-manager.ps1 +2 -1
- package/.claude/hooks-windows/play-tts-kokoro.ps1 +14 -0
- package/.claude/hooks-windows/play-tts.ps1 +163 -30
- package/.claude/hooks-windows/voice-manager-windows.ps1 +101 -1
- package/.clawdbot/README.md +105 -105
- package/LICENSE +190 -190
- package/RELEASE_NOTES.md +29 -0
- package/WINDOWS-SETUP.md +208 -208
- package/bin/agent-vibes +39 -39
- package/bin/mcp-server.js +121 -121
- package/bin/mcp-server.sh +6 -19
- package/bin/resolve-utterance.js +137 -0
- package/bin/test-bmad-pr +78 -78
- package/mcp-server/QUICK_START.md +203 -203
- package/mcp-server/README.md +345 -345
- package/mcp-server/examples/claude_desktop_config.json +11 -11
- package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
- package/mcp-server/examples/custom_instructions.md +169 -169
- package/mcp-server/pyproject.toml +52 -52
- package/mcp-server/requirements.txt +2 -2
- package/mcp-server/server.py +280 -99
- package/mcp-server/test_mcp_correctness.py +486 -0
- package/mcp-server/test_server.py +395 -395
- package/mcp-server/test_windows_script_parity.py +341 -336
- package/package.json +3 -2
- package/setup-windows.ps1 +867 -815
- package/src/cli/list-personalities.js +110 -110
- package/src/cli/list-voices.js +114 -114
- package/src/commands/bmad-voices.js +394 -394
- package/src/console/app.js +13 -2
- package/src/console/brand-colors.js +13 -13
- package/src/console/constants/personalities.js +44 -44
- package/src/console/tabs/agents-tab.js +82 -9
- package/src/console/tabs/help-tab.js +314 -314
- package/src/console/tabs/music-tab.js +7 -1
- package/src/console/tabs/readme-tab.js +272 -272
- package/src/console/tabs/settings-tab.js +29 -1
- package/src/console/tabs/setup-tab.js +4 -4
- package/src/console/widgets/destroy-list.js +25 -25
- package/src/console/widgets/notice.js +55 -55
- package/src/console/widgets/track-picker.js +3 -3
- package/src/i18n/de.js +0 -1
- package/src/i18n/en.js +0 -1
- package/src/i18n/es.js +0 -1
- package/src/i18n/fr.js +0 -1
- package/src/i18n/hi.js +0 -1
- package/src/i18n/ja.js +0 -1
- package/src/i18n/ko.js +0 -1
- package/src/i18n/pt.js +0 -1
- package/src/i18n/zh-CN.js +0 -1
- package/src/installer/language-screen.js +31 -31
- package/src/installer/music-file-input.js +304 -304
- package/src/installer.js +205 -15
- package/src/services/config-service.js +264 -264
- package/src/services/language-service.js +47 -47
- package/src/services/llm-provider-service.js +7 -7
- package/src/services/utterance-loader.js +280 -0
- package/src/services/utterance-resolver.js +526 -0
- package/src/utils/audio-format-validator.js +277 -277
- package/src/utils/dependency-checker.js +469 -469
- package/src/utils/file-ownership-verifier.js +358 -358
- package/src/utils/music-file-validator.js +285 -285
- package/src/utils/preview-list-prompt.js +144 -144
- package/src/utils/secure-music-storage.js +412 -412
- package/templates/agentvibes-receiver.sh +74 -12
- package/voice-assignments.json +8245 -0
- package/.agentvibes/install-manifest.json +0 -342
- package/.claude/config/background-music-position.txt +0 -27
- package/.claude/config/background-music-volume.txt +0 -1
- package/.claude/config/background-music.cfg +0 -1
- package/.claude/config/background-music.txt +0 -1
- package/.claude/config/language.txt +0 -1
- package/.claude/config/personality.txt +0 -1
- package/.claude/config/tts-speech-rate.txt +0 -1
- package/.claude/config/tts-verbosity.txt +0 -1
- package/.claude/hooks-windows/audio-cache-utils.ps1.user.bak +0 -119
- package/.claude/hooks-windows/soprano-gradio-synth.py.user.bak +0 -153
- package/.claude/piper-voices-dir.txt +0 -1
- package/.mcp.json +0 -22
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AgentVibes TUI — Shared Widget: Modal Destroy Helper
|
|
3
|
-
*
|
|
4
|
-
* Force-invalidates blessed's olines buffer after destroying a modal widget.
|
|
5
|
-
* Without this, blessed skips repainting cells where lines==olines and the
|
|
6
|
-
* terminal retains stale modal content as ghost artifacts.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Destroy a blessed list/box widget and force full screen repaint.
|
|
11
|
-
*
|
|
12
|
-
* @param {object} widget - blessed widget to destroy
|
|
13
|
-
* @param {object} screen - blessed screen instance
|
|
14
|
-
* @param {Function} [onClose] - optional callback after destruction
|
|
15
|
-
*/
|
|
16
|
-
export function destroyList(widget, screen, onClose) {
|
|
17
|
-
widget.destroy();
|
|
18
|
-
try {
|
|
19
|
-
for (let r = 0; r < screen.height; r++)
|
|
20
|
-
for (let c = 0; c < screen.width; c++)
|
|
21
|
-
if (screen.olines[r]?.[c]) screen.olines[r][c][0] = -1;
|
|
22
|
-
} catch {}
|
|
23
|
-
onClose?.();
|
|
24
|
-
screen.render();
|
|
25
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* AgentVibes TUI — Shared Widget: Modal Destroy Helper
|
|
3
|
+
*
|
|
4
|
+
* Force-invalidates blessed's olines buffer after destroying a modal widget.
|
|
5
|
+
* Without this, blessed skips repainting cells where lines==olines and the
|
|
6
|
+
* terminal retains stale modal content as ghost artifacts.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Destroy a blessed list/box widget and force full screen repaint.
|
|
11
|
+
*
|
|
12
|
+
* @param {object} widget - blessed widget to destroy
|
|
13
|
+
* @param {object} screen - blessed screen instance
|
|
14
|
+
* @param {Function} [onClose] - optional callback after destruction
|
|
15
|
+
*/
|
|
16
|
+
export function destroyList(widget, screen, onClose) {
|
|
17
|
+
widget.destroy();
|
|
18
|
+
try {
|
|
19
|
+
for (let r = 0; r < screen.height; r++)
|
|
20
|
+
for (let c = 0; c < screen.width; c++)
|
|
21
|
+
if (screen.olines[r]?.[c]) screen.olines[r][c][0] = -1;
|
|
22
|
+
} catch {}
|
|
23
|
+
onClose?.();
|
|
24
|
+
screen.render();
|
|
25
|
+
}
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AgentVibes TUI — Shared Widget: Notice Toast
|
|
3
|
-
*
|
|
4
|
-
* Displays a short auto-dismissing notice modal centred on screen.
|
|
5
|
-
* Usable from any tab; no settings-specific state required.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { destroyList } from './destroy-list.js';
|
|
9
|
-
|
|
10
|
-
const IS_TEST = process.env.AGENTVIBES_TEST_MODE === 'true';
|
|
11
|
-
let blessed;
|
|
12
|
-
if (!IS_TEST) {
|
|
13
|
-
const { default: b } = await import('blessed');
|
|
14
|
-
blessed = b;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Show a temporary notice that auto-dismisses after 2.5 seconds.
|
|
19
|
-
*
|
|
20
|
-
* @param {object} screen - blessed screen instance
|
|
21
|
-
* @param {string} message - text to display
|
|
22
|
-
* @param {object} [opts]
|
|
23
|
-
* @param {string} [opts.bg='#0a0e1a'] - background colour
|
|
24
|
-
* @param {string} [opts.fg='#e3f2fd'] - foreground colour
|
|
25
|
-
* @param {string} [opts.borderFg='bright-cyan'] - border colour
|
|
26
|
-
* @param {number} [opts.durationMs=2500] - auto-dismiss delay in ms
|
|
27
|
-
*/
|
|
28
|
-
export function showNotice(screen, message, opts = {}) {
|
|
29
|
-
const bg = opts.bg ?? '#0a0e1a';
|
|
30
|
-
const fg = opts.fg ?? '#e3f2fd';
|
|
31
|
-
const borderFg = opts.borderFg ?? 'bright-cyan';
|
|
32
|
-
const durationMs = opts.durationMs ?? 2500;
|
|
33
|
-
|
|
34
|
-
const width = Math.max(28, message.length + 6);
|
|
35
|
-
const modal = blessed.box({
|
|
36
|
-
parent: screen,
|
|
37
|
-
top: 'center',
|
|
38
|
-
left: 'center',
|
|
39
|
-
width,
|
|
40
|
-
height: 3,
|
|
41
|
-
border: { type: 'line' },
|
|
42
|
-
tags: true,
|
|
43
|
-
content: `{center}${message}{/center}`,
|
|
44
|
-
style: {
|
|
45
|
-
fg,
|
|
46
|
-
bg,
|
|
47
|
-
border: { fg: borderFg },
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
screen.render();
|
|
51
|
-
|
|
52
|
-
setTimeout(() => {
|
|
53
|
-
destroyList(modal, screen);
|
|
54
|
-
}, durationMs);
|
|
55
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* AgentVibes TUI — Shared Widget: Notice Toast
|
|
3
|
+
*
|
|
4
|
+
* Displays a short auto-dismissing notice modal centred on screen.
|
|
5
|
+
* Usable from any tab; no settings-specific state required.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { destroyList } from './destroy-list.js';
|
|
9
|
+
|
|
10
|
+
const IS_TEST = process.env.AGENTVIBES_TEST_MODE === 'true';
|
|
11
|
+
let blessed;
|
|
12
|
+
if (!IS_TEST) {
|
|
13
|
+
const { default: b } = await import('blessed');
|
|
14
|
+
blessed = b;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Show a temporary notice that auto-dismisses after 2.5 seconds.
|
|
19
|
+
*
|
|
20
|
+
* @param {object} screen - blessed screen instance
|
|
21
|
+
* @param {string} message - text to display
|
|
22
|
+
* @param {object} [opts]
|
|
23
|
+
* @param {string} [opts.bg='#0a0e1a'] - background colour
|
|
24
|
+
* @param {string} [opts.fg='#e3f2fd'] - foreground colour
|
|
25
|
+
* @param {string} [opts.borderFg='bright-cyan'] - border colour
|
|
26
|
+
* @param {number} [opts.durationMs=2500] - auto-dismiss delay in ms
|
|
27
|
+
*/
|
|
28
|
+
export function showNotice(screen, message, opts = {}) {
|
|
29
|
+
const bg = opts.bg ?? '#0a0e1a';
|
|
30
|
+
const fg = opts.fg ?? '#e3f2fd';
|
|
31
|
+
const borderFg = opts.borderFg ?? 'bright-cyan';
|
|
32
|
+
const durationMs = opts.durationMs ?? 2500;
|
|
33
|
+
|
|
34
|
+
const width = Math.max(28, message.length + 6);
|
|
35
|
+
const modal = blessed.box({
|
|
36
|
+
parent: screen,
|
|
37
|
+
top: 'center',
|
|
38
|
+
left: 'center',
|
|
39
|
+
width,
|
|
40
|
+
height: 3,
|
|
41
|
+
border: { type: 'line' },
|
|
42
|
+
tags: true,
|
|
43
|
+
content: `{center}${message}{/center}`,
|
|
44
|
+
style: {
|
|
45
|
+
fg,
|
|
46
|
+
bg,
|
|
47
|
+
border: { fg: borderFg },
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
screen.render();
|
|
51
|
+
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
destroyList(modal, screen);
|
|
54
|
+
}, durationMs);
|
|
55
|
+
}
|
|
@@ -33,9 +33,9 @@ const _modalTitle = (text) => ` {${BRAND_PINK}-fg}${text}{/${BRAND_PINK}-fg} `;
|
|
|
33
33
|
* @param {Function} [onClose] - called when modal closes (confirm or cancel)
|
|
34
34
|
*/
|
|
35
35
|
export function openVolumeInput(screen, currentVol, onConfirm, onClose) {
|
|
36
|
-
if (IS_TEST) { onConfirm(currentVol ??
|
|
36
|
+
if (IS_TEST) { onConfirm(currentVol ?? 20); return; }
|
|
37
37
|
let vol = (Number.isFinite(currentVol) && currentVol >= 0 && currentVol <= 100)
|
|
38
|
-
? currentVol :
|
|
38
|
+
? currentVol : 20;
|
|
39
39
|
|
|
40
40
|
const box = blessed.box({
|
|
41
41
|
parent: screen,
|
|
@@ -141,7 +141,7 @@ const BUILT_IN_TRACKS = [
|
|
|
141
141
|
*
|
|
142
142
|
* @param {object} screen - blessed screen
|
|
143
143
|
* @param {string} currentTrack - currently selected track filename
|
|
144
|
-
* @param {number} currentVolume - currently set volume (0-100, default
|
|
144
|
+
* @param {number} currentVolume - currently set volume (0-100, default 20)
|
|
145
145
|
* @param {Function} onSelect - called with (trackFile, volume)
|
|
146
146
|
* @param {Function} [onClose] - called after modal fully closes
|
|
147
147
|
*/
|
package/src/i18n/de.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[Stimme wechseln]",
|
|
144
144
|
voicesFavoriteBtn: "[★ Favorit]",
|
|
145
145
|
voicesDownloadBtn: "[Stimme herunterladen]",
|
|
146
|
-
voicesInstallAllBtn: "[BMAD-Stimmen installieren]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] Vorschau [Enter] Auswählen [*] Favorit",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] Herunterladen und installieren",
|
|
149
148
|
musicRowHint: "[Space] Abspielen [Enter] Auswählen [*] Favorit",
|
package/src/i18n/en.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[Switch Voice]",
|
|
144
144
|
voicesFavoriteBtn: "[+ Thumbs Up]",
|
|
145
145
|
voicesDownloadBtn: "[Download Voice]",
|
|
146
|
-
voicesInstallAllBtn: "[Install BMAD Voices]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] Preview [Enter] Select [+/*] Up [-] Down",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] Download & Install",
|
|
149
148
|
musicRowHint: "[Space] Play [Enter] Select [+/*] Favorite",
|
package/src/i18n/es.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[Cambiar Voz]",
|
|
144
144
|
voicesFavoriteBtn: "[★ Favorito]",
|
|
145
145
|
voicesDownloadBtn: "[Descargar Voz]",
|
|
146
|
-
voicesInstallAllBtn: "[Instalar Voces BMAD]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] Vista previa [Enter] Seleccionar [*] Favorito",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] Descargar e instalar",
|
|
149
148
|
musicRowHint: "[Space] Reproducir [Enter] Seleccionar [*] Favorito",
|
package/src/i18n/fr.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[Changer la voix]",
|
|
144
144
|
voicesFavoriteBtn: "[★ Favori]",
|
|
145
145
|
voicesDownloadBtn: "[Télécharger la voix]",
|
|
146
|
-
voicesInstallAllBtn: "[Installer les voix BMAD]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] Aperçu [Enter] Sélectionner [*] Favori",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] Télécharger et installer",
|
|
149
148
|
musicRowHint: "[Space] Lire [Enter] Sélectionner [*] Favori",
|
package/src/i18n/hi.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[आवाज़ बदलें]",
|
|
144
144
|
voicesFavoriteBtn: "[★ पसंदीदा]",
|
|
145
145
|
voicesDownloadBtn: "[आवाज़ डाउनलोड]",
|
|
146
|
-
voicesInstallAllBtn: "[BMAD आवाज़ें इंस्टॉल करें]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] पूर्वावलोकन [Enter] चुनें [*] पसंदीदा",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] डाउनलोड और इंस्टॉल करें",
|
|
149
148
|
musicRowHint: "[Space] चलाएं [Enter] चुनें [*] पसंदीदा",
|
package/src/i18n/ja.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[音声切り替え]",
|
|
144
144
|
voicesFavoriteBtn: "[★ お気に入り]",
|
|
145
145
|
voicesDownloadBtn: "[音声ダウンロード]",
|
|
146
|
-
voicesInstallAllBtn: "[BMADボイスをインストール]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] プレビュー [Enter] 選択 [*] お気に入り",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] ダウンロードしてインストール",
|
|
149
148
|
musicRowHint: "[Space] 再生 [Enter] 選択 [*] お気に入り",
|
package/src/i18n/ko.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[음성 전환]",
|
|
144
144
|
voicesFavoriteBtn: "[★ 즐겨찾기]",
|
|
145
145
|
voicesDownloadBtn: "[음성 다운로드]",
|
|
146
|
-
voicesInstallAllBtn: "[BMAD 음성 설치]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] 미리보기 [Enter] 선택 [*] 즐겨찾기",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] 다운로드 및 설치",
|
|
149
148
|
musicRowHint: "[Space] 재생 [Enter] 선택 [*] 즐겨찾기",
|
package/src/i18n/pt.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[Trocar Voz]",
|
|
144
144
|
voicesFavoriteBtn: "[★ Favorito]",
|
|
145
145
|
voicesDownloadBtn: "[Baixar Voz]",
|
|
146
|
-
voicesInstallAllBtn: "[Instalar Vozes BMAD]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] Visualizar [Enter] Selecionar [*] Favorito",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] Baixar e instalar",
|
|
149
148
|
musicRowHint: "[Space] Reproduzir [Enter] Selecionar [*] Favorito",
|
package/src/i18n/zh-CN.js
CHANGED
|
@@ -143,7 +143,6 @@ export default {
|
|
|
143
143
|
voicesSwitchBtn: "[切换语音]",
|
|
144
144
|
voicesFavoriteBtn: "[★ 收藏]",
|
|
145
145
|
voicesDownloadBtn: "[下载语音]",
|
|
146
|
-
voicesInstallAllBtn: "[安装BMAD语音]",
|
|
147
146
|
voicesRowHintInstalled: "[Space] 预览 [Enter] 选择 [*] 收藏",
|
|
148
147
|
voicesRowHintUninstalled: "[Enter] 下载并安装",
|
|
149
148
|
musicRowHint: "[Space] 播放 [Enter] 选择 [*] 收藏",
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File: src/installer/language-screen.js
|
|
3
|
-
*
|
|
4
|
-
* Language selection screen for the AgentVibes installer TUI.
|
|
5
|
-
* Presents a list of supported languages and returns the selected code.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import inquirer from 'inquirer';
|
|
9
|
-
import { t, SUPPORTED_LANGUAGES } from '../i18n/strings.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Show the language selection screen and return the chosen language code.
|
|
13
|
-
*
|
|
14
|
-
* @param {string} [currentLang='en'] - Currently active language code (used as default)
|
|
15
|
-
* @returns {Promise<string>} The selected language code (e.g. 'es', 'zh-CN')
|
|
16
|
-
*/
|
|
17
|
-
export async function selectLanguage(currentLang = 'en') {
|
|
18
|
-
const { lang } = await inquirer.prompt([{
|
|
19
|
-
type: 'list',
|
|
20
|
-
name: 'lang',
|
|
21
|
-
message: '🌐 Select Language / Seleccionar Idioma / Choisir la langue / Sprache wählen / Selecionar Idioma / 言語を選択 / भाषा चुनें / 选择语言 / 언어 선택',
|
|
22
|
-
default: currentLang,
|
|
23
|
-
choices: SUPPORTED_LANGUAGES
|
|
24
|
-
}]);
|
|
25
|
-
|
|
26
|
-
console.clear();
|
|
27
|
-
const chosenName = SUPPORTED_LANGUAGES.find(l => l.value === lang)?.name ?? lang;
|
|
28
|
-
console.log(`\u2713 ${t(lang, 'languageApplied')}: ${chosenName}\n`);
|
|
29
|
-
|
|
30
|
-
return lang;
|
|
31
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* File: src/installer/language-screen.js
|
|
3
|
+
*
|
|
4
|
+
* Language selection screen for the AgentVibes installer TUI.
|
|
5
|
+
* Presents a list of supported languages and returns the selected code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import inquirer from 'inquirer';
|
|
9
|
+
import { t, SUPPORTED_LANGUAGES } from '../i18n/strings.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Show the language selection screen and return the chosen language code.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} [currentLang='en'] - Currently active language code (used as default)
|
|
15
|
+
* @returns {Promise<string>} The selected language code (e.g. 'es', 'zh-CN')
|
|
16
|
+
*/
|
|
17
|
+
export async function selectLanguage(currentLang = 'en') {
|
|
18
|
+
const { lang } = await inquirer.prompt([{
|
|
19
|
+
type: 'list',
|
|
20
|
+
name: 'lang',
|
|
21
|
+
message: '🌐 Select Language / Seleccionar Idioma / Choisir la langue / Sprache wählen / Selecionar Idioma / 言語を選択 / भाषा चुनें / 选择语言 / 언어 선택',
|
|
22
|
+
default: currentLang,
|
|
23
|
+
choices: SUPPORTED_LANGUAGES
|
|
24
|
+
}]);
|
|
25
|
+
|
|
26
|
+
console.clear();
|
|
27
|
+
const chosenName = SUPPORTED_LANGUAGES.find(l => l.value === lang)?.name ?? lang;
|
|
28
|
+
console.log(`\u2713 ${t(lang, 'languageApplied')}: ${chosenName}\n`);
|
|
29
|
+
|
|
30
|
+
return lang;
|
|
31
|
+
}
|