agentvibes 5.9.0 → 5.10.1
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 +3 -12
- 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 +4 -5
- package/.claude/config/audio-effects.cfg.sample +52 -52
- 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-cache-utils.sh +0 -0
- package/.claude/hooks/audio-processor.sh +0 -0
- package/.claude/hooks/background-music-manager.sh +0 -0
- package/.claude/hooks/bmad-party-speak.sh +0 -0
- package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
- package/.claude/hooks/bmad-speak.sh +0 -0
- package/.claude/hooks/bmad-tts-injector.sh +0 -0
- package/.claude/hooks/bmad-voice-manager.sh +0 -0
- package/.claude/hooks/clawdbot-receiver-SECURE.sh +0 -0
- package/.claude/hooks/clawdbot-receiver.sh +0 -0
- package/.claude/hooks/clean-audio-cache.sh +0 -0
- package/.claude/hooks/cleanup-cache.sh +0 -0
- package/.claude/hooks/configure-rdp-mode.sh +0 -0
- package/.claude/hooks/download-extra-voices.sh +0 -0
- package/.claude/hooks/effects-manager.sh +0 -0
- package/.claude/hooks/github-star-reminder.sh +0 -0
- package/.claude/hooks/language-manager.sh +0 -0
- package/.claude/hooks/learn-manager.sh +0 -0
- package/.claude/hooks/macos-voice-manager.sh +0 -0
- package/.claude/hooks/migrate-background-music.sh +0 -0
- package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
- package/.claude/hooks/optimize-background-music.sh +0 -0
- package/.claude/hooks/path-resolver.sh +0 -0
- package/.claude/hooks/personality-manager.sh +0 -0
- package/.claude/hooks/piper-download-voices.sh +0 -0
- package/.claude/hooks/piper-installer.sh +0 -0
- package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
- package/.claude/hooks/piper-voice-manager.sh +0 -0
- package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +0 -0
- package/.claude/hooks/play-tts-enhanced.sh +0 -0
- package/.claude/hooks/play-tts-macos.sh +0 -0
- package/.claude/hooks/play-tts-piper.sh +20 -13
- package/.claude/hooks/play-tts-soprano.sh +0 -0
- package/.claude/hooks/play-tts-ssh-remote.sh +0 -0
- package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
- package/.claude/hooks/play-tts-windows-receiver.sh +0 -0
- package/.claude/hooks/play-tts.sh +0 -0
- package/.claude/hooks/prepare-release.sh +0 -0
- package/.claude/hooks/provider-commands.sh +0 -0
- package/.claude/hooks/provider-manager.sh +0 -0
- package/.claude/hooks/replay-target-audio.sh +0 -0
- package/.claude/hooks/requirements.txt +6 -6
- package/.claude/hooks/sentiment-manager.sh +0 -0
- package/.claude/hooks/session-start-tts.sh +0 -0
- package/.claude/hooks/soprano-gradio-synth.py +139 -139
- package/.claude/hooks/speed-manager.sh +0 -0
- package/.claude/hooks/stop-tts.sh +0 -0
- package/.claude/hooks/termux-installer.sh +0 -0
- package/.claude/hooks/translate-manager.sh +0 -0
- package/.claude/hooks/translator.py +237 -237
- package/.claude/hooks/tts-queue-worker.sh +0 -0
- package/.claude/hooks/tts-queue.sh +0 -0
- package/.claude/hooks/verbosity-manager.sh +0 -0
- package/.claude/hooks/voice-manager.sh +6 -0
- package/.claude/hooks-windows/play-tts-windows-piper.ps1 +22 -16
- package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
- package/.claude/verbosity.txt +1 -1
- package/.clawdbot/README.md +105 -105
- package/.mcp.json +19 -6
- package/README.md +1 -1
- package/WINDOWS-SETUP.md +208 -208
- package/bin/agent-vibes +39 -39
- package/bin/agentvibes-voice-browser.js +0 -0
- package/bin/agentvibes.js +0 -0
- package/bin/mcp-server.js +121 -121
- package/bin/mcp-server.sh +0 -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/WINDOWS_SETUP.md +0 -0
- 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/install-deps.js +0 -0
- package/mcp-server/server.py +1807 -1797
- package/mcp-server/test_server.py +0 -0
- package/package.json +2 -2
- 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/commands/install-mcp.js +730 -476
- package/src/console/app.js +3 -3
- package/src/console/brand-colors.js +13 -13
- package/src/console/constants/personalities.js +44 -44
- package/src/console/tabs/agents-tab.js +6 -6
- package/src/console/tabs/help-tab.js +314 -314
- package/src/console/tabs/music-tab.js +1 -1
- package/src/console/tabs/readme-tab.js +272 -272
- package/src/console/tabs/receiver-tab.js +13 -13
- package/src/console/tabs/settings-tab.js +2 -2
- package/src/console/tabs/setup-tab.js +10 -10
- package/src/console/tabs/voices-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/personality-picker.js +2 -2
- package/src/console/widgets/reverb-picker.js +1 -1
- package/src/i18n/de.js +202 -202
- package/src/i18n/es.js +202 -202
- package/src/i18n/fr.js +202 -202
- package/src/i18n/hi.js +202 -202
- package/src/i18n/ja.js +202 -202
- package/src/i18n/ko.js +202 -202
- package/src/i18n/pt.js +202 -202
- package/src/i18n/strings.js +54 -54
- package/src/i18n/zh-CN.js +202 -202
- package/src/installer/language-screen.js +31 -31
- package/src/installer/music-file-input.js +304 -304
- package/src/installer.js +32 -27
- package/src/services/config-service.js +264 -264
- package/src/services/language-service.js +47 -47
- package/src/services/provider-service.js +143 -143
- package/src/services/tts-engine-service.js +2 -2
- package/src/utils/audio-duration-validator.js +298 -298
- 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/list-formatter.js +200 -194
- package/src/utils/music-file-validator.js +285 -285
- package/src/utils/platform-resolver.js +369 -0
- package/src/utils/preview-list-prompt.js +136 -136
- package/src/utils/provider-validator.js +9 -9
- package/src/utils/secure-music-storage.js +412 -412
- package/templates/agentvibes-receiver.sh +231 -231
- package/templates/audio/welcome-music.mp3 +0 -0
- package/.agentvibes/install-manifest.json +0 -330
- 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/reverb-level.txt +0 -1
- package/.claude/config/tts-speech-rate.txt +0 -1
- package/.claude/config/tts-verbosity.txt +0 -1
- package/.claude/hooks/play-tts-agentvibes-receiver.sh +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/src/installer.js
CHANGED
|
@@ -383,14 +383,14 @@ function isPiperInstalled() {
|
|
|
383
383
|
}
|
|
384
384
|
// Also check PATH (e.g. pip-installed piper)
|
|
385
385
|
try {
|
|
386
|
-
execSync('where piper.exe', { stdio: 'pipe', timeout: 3000 });
|
|
386
|
+
execSync('where piper.exe', { stdio: 'pipe', timeout: 3000 }); // NOSONAR
|
|
387
387
|
return true;
|
|
388
388
|
} catch (e) {
|
|
389
389
|
return false;
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
392
|
try {
|
|
393
|
-
execSync('which piper', {
|
|
393
|
+
execSync('which piper', { // NOSONAR
|
|
394
394
|
stdio: 'pipe',
|
|
395
395
|
timeout: 3000
|
|
396
396
|
});
|
|
@@ -406,7 +406,7 @@ function isPiperInstalled() {
|
|
|
406
406
|
*/
|
|
407
407
|
function isSopranoInstalled() {
|
|
408
408
|
try {
|
|
409
|
-
execSync('which soprano-tts || which soprano-webui', {
|
|
409
|
+
execSync('which soprano-tts || which soprano-webui', { // NOSONAR
|
|
410
410
|
stdio: 'pipe',
|
|
411
411
|
timeout: 3000
|
|
412
412
|
});
|
|
@@ -415,7 +415,7 @@ function isSopranoInstalled() {
|
|
|
415
415
|
// On Windows, 'which' may not find Python scripts; try 'py -m pip show' as fallback
|
|
416
416
|
if (isNativeWindows()) {
|
|
417
417
|
try {
|
|
418
|
-
const result = spawnSync('py', ['-m', 'pip', 'show', 'soprano-tts'], {
|
|
418
|
+
const result = spawnSync('py', ['-m', 'pip', 'show', 'soprano-tts'], { // NOSONAR
|
|
419
419
|
encoding: 'utf8',
|
|
420
420
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
421
421
|
timeout: 10000
|
|
@@ -454,7 +454,7 @@ async function playVoiceSample(voiceName, provider) {
|
|
|
454
454
|
// Play using sox/aplay - use spawn for non-blocking playback
|
|
455
455
|
try {
|
|
456
456
|
// Play using aplay directly (no shell interpolation — prevents command injection)
|
|
457
|
-
const player = spawn('aplay', [sampleFile], {
|
|
457
|
+
const player = spawn('aplay', [sampleFile], { // NOSONAR
|
|
458
458
|
detached: false,
|
|
459
459
|
stdio: 'ignore'
|
|
460
460
|
});
|
|
@@ -470,7 +470,7 @@ async function playVoiceSample(voiceName, provider) {
|
|
|
470
470
|
if (isPiperProvider(provider) && isPiperInstalled()) {
|
|
471
471
|
const text = `Hi, I'm ${voiceName.split('-')[1] || 'Piper'}`;
|
|
472
472
|
// Use bash -c with positional args to prevent command injection via text/voiceName
|
|
473
|
-
spawnSync('bash', ['-c', 'echo "$1" | piper --model "$2" --output_raw | aplay -r 22050 -f S16_LE -t raw -', '_', text, voiceName], {
|
|
473
|
+
spawnSync('bash', ['-c', 'echo "$1" | piper --model "$2" --output_raw | aplay -r 22050 -f S16_LE -t raw -', '_', text, voiceName], { // NOSONAR
|
|
474
474
|
stdio: 'inherit',
|
|
475
475
|
timeout: 15000
|
|
476
476
|
});
|
|
@@ -492,7 +492,7 @@ async function playVoiceSample(voiceName, provider) {
|
|
|
492
492
|
fsSync.writeFileSync(tempFile, Buffer.from(audio));
|
|
493
493
|
try {
|
|
494
494
|
// Use spawnSync with argument array to prevent command injection
|
|
495
|
-
spawnSync('aplay', [tempFile], { stdio: 'pipe', timeout: 5000 });
|
|
495
|
+
spawnSync('aplay', [tempFile], { stdio: 'pipe', timeout: 5000 }); // NOSONAR
|
|
496
496
|
} finally {
|
|
497
497
|
fsSync.unlinkSync(tempFile);
|
|
498
498
|
}
|
|
@@ -531,7 +531,7 @@ async function startSopranoServer() {
|
|
|
531
531
|
console.log(chalk.gray('🚀 Starting Soprano TTS server...'));
|
|
532
532
|
|
|
533
533
|
// Start soprano-webui in background
|
|
534
|
-
const sopranoProcess = spawn('soprano-webui', ['--port', '7860'], {
|
|
534
|
+
const sopranoProcess = spawn('soprano-webui', ['--port', '7860'], { // NOSONAR
|
|
535
535
|
detached: true,
|
|
536
536
|
stdio: 'ignore'
|
|
537
537
|
});
|
|
@@ -569,7 +569,7 @@ async function detectSystemCapabilities() {
|
|
|
569
569
|
try {
|
|
570
570
|
// Detect NVIDIA GPU
|
|
571
571
|
try {
|
|
572
|
-
execSync('nvidia-smi --query-gpu=name --format=csv,noheader', {
|
|
572
|
+
execSync('nvidia-smi --query-gpu=name --format=csv,noheader', { // NOSONAR
|
|
573
573
|
stdio: 'pipe',
|
|
574
574
|
timeout: 5000 // 5 second timeout
|
|
575
575
|
});
|
|
@@ -580,7 +580,7 @@ async function detectSystemCapabilities() {
|
|
|
580
580
|
|
|
581
581
|
// Detect total RAM (in MB)
|
|
582
582
|
if (isMacOS) {
|
|
583
|
-
const output = execSync('sysctl hw.memsize', {
|
|
583
|
+
const output = execSync('sysctl hw.memsize', { // NOSONAR
|
|
584
584
|
encoding: 'utf8',
|
|
585
585
|
timeout: 3000 // 3 second timeout
|
|
586
586
|
});
|
|
@@ -594,7 +594,7 @@ async function detectSystemCapabilities() {
|
|
|
594
594
|
}
|
|
595
595
|
totalRAM = Math.floor(bytes / (1024 * 1024));
|
|
596
596
|
} else {
|
|
597
|
-
const output = execSync('cat /proc/meminfo | grep MemTotal', {
|
|
597
|
+
const output = execSync('cat /proc/meminfo | grep MemTotal', { // NOSONAR
|
|
598
598
|
encoding: 'utf8',
|
|
599
599
|
timeout: 3000 // 3 second timeout
|
|
600
600
|
});
|
|
@@ -679,12 +679,12 @@ function checkAudioDevices() {
|
|
|
679
679
|
if (process.platform === 'linux') {
|
|
680
680
|
try {
|
|
681
681
|
// Try aplay first (ALSA)
|
|
682
|
-
execSync('aplay -l 2>/dev/null', { encoding: 'utf8', stdio: 'pipe' });
|
|
682
|
+
execSync('aplay -l 2>/dev/null', { encoding: 'utf8', stdio: 'pipe' }); // NOSONAR
|
|
683
683
|
return true;
|
|
684
684
|
} catch (e) {
|
|
685
685
|
// Try paplay (PulseAudio)
|
|
686
686
|
try {
|
|
687
|
-
execSync('paplay --version 2>/dev/null', { encoding: 'utf8', stdio: 'pipe' });
|
|
687
|
+
execSync('paplay --version 2>/dev/null', { encoding: 'utf8', stdio: 'pipe' }); // NOSONAR
|
|
688
688
|
return true;
|
|
689
689
|
} catch (e2) {
|
|
690
690
|
return false;
|
|
@@ -936,7 +936,7 @@ async function handleSystemDependenciesPage() {
|
|
|
936
936
|
|
|
937
937
|
if (piperInstalled) {
|
|
938
938
|
try {
|
|
939
|
-
const piperPath = execSync('which piper 2>/dev/null', { encoding: 'utf8' }).trim();
|
|
939
|
+
const piperPath = execSync('which piper 2>/dev/null', { encoding: 'utf8' }).trim(); // NOSONAR
|
|
940
940
|
depContent += chalk.green('✓ Piper TTS (offline voice synthesis)\n');
|
|
941
941
|
depContent += chalk.gray(` ${piperPath}\n`);
|
|
942
942
|
} catch (e) {
|
|
@@ -947,9 +947,9 @@ async function handleSystemDependenciesPage() {
|
|
|
947
947
|
try {
|
|
948
948
|
let sopranoPath = '';
|
|
949
949
|
try {
|
|
950
|
-
sopranoPath = execSync('which soprano-tts 2>/dev/null', { encoding: 'utf8' }).trim();
|
|
950
|
+
sopranoPath = execSync('which soprano-tts 2>/dev/null', { encoding: 'utf8' }).trim(); // NOSONAR
|
|
951
951
|
} catch (e) {
|
|
952
|
-
sopranoPath = execSync('which soprano-webui 2>/dev/null', { encoding: 'utf8' }).trim();
|
|
952
|
+
sopranoPath = execSync('which soprano-webui 2>/dev/null', { encoding: 'utf8' }).trim(); // NOSONAR
|
|
953
953
|
}
|
|
954
954
|
depContent += chalk.green('✓ Soprano TTS (premium quality)\n');
|
|
955
955
|
depContent += chalk.gray(` ${sopranoPath}\n`);
|
|
@@ -2244,7 +2244,7 @@ async function collectConfiguration(options = {}) {
|
|
|
2244
2244
|
const content = await fs.readFile(filePath, 'utf-8');
|
|
2245
2245
|
|
|
2246
2246
|
// Extract description from frontmatter
|
|
2247
|
-
const descMatch = content.match(/^description:\s*(.+)$/m);
|
|
2247
|
+
const descMatch = content.match(/^description:\s*(.+)$/m); // NOSONAR
|
|
2248
2248
|
const description = descMatch ? descMatch[1].trim() : '';
|
|
2249
2249
|
|
|
2250
2250
|
personalities.push({
|
|
@@ -2958,7 +2958,7 @@ function getReleaseInfoBoxen() {
|
|
|
2958
2958
|
.replace(/^#{1,6}\s*/, '') // ## headings
|
|
2959
2959
|
.replace(/\*\*([^*]+)\*\*/g, '$1') // **bold**
|
|
2960
2960
|
.replace(/`([^`]+)`/g, '$1') // `code`
|
|
2961
|
-
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); // [text](url)
|
|
2961
|
+
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); // [text](url) // NOSONAR
|
|
2962
2962
|
|
|
2963
2963
|
// Render: heading in cyan, bullets as gray, skip blank/hr lines at end
|
|
2964
2964
|
return sectionLines
|
|
@@ -3007,7 +3007,7 @@ async function playWelcomeDemo(targetDir, spinner, options = {}) {
|
|
|
3007
3007
|
if (isNativeWindows()) {
|
|
3008
3008
|
// Escape single quotes to prevent PowerShell injection (double them per PS escaping rules)
|
|
3009
3009
|
const safeAudioPath = welcomeDemoAudio.replace(/'/g, "''");
|
|
3010
|
-
const audioProcess = spawn('powershell', [
|
|
3010
|
+
const audioProcess = spawn('powershell', [ // NOSONAR
|
|
3011
3011
|
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command',
|
|
3012
3012
|
`(New-Object System.Media.SoundPlayer '${safeAudioPath}').PlaySync()`
|
|
3013
3013
|
], { detached: true, stdio: 'ignore' });
|
|
@@ -3019,15 +3019,15 @@ async function playWelcomeDemo(targetDir, spinner, options = {}) {
|
|
|
3019
3019
|
let audioPlayer = null;
|
|
3020
3020
|
|
|
3021
3021
|
try {
|
|
3022
|
-
execFileSync('which', ['paplay'], { stdio: 'pipe' });
|
|
3022
|
+
execFileSync('which', ['paplay'], { stdio: 'pipe' }); // NOSONAR
|
|
3023
3023
|
audioPlayer = 'paplay';
|
|
3024
3024
|
} catch {
|
|
3025
3025
|
try {
|
|
3026
|
-
execFileSync('which', ['afplay'], { stdio: 'pipe' });
|
|
3026
|
+
execFileSync('which', ['afplay'], { stdio: 'pipe' }); // NOSONAR
|
|
3027
3027
|
audioPlayer = 'afplay';
|
|
3028
3028
|
} catch {
|
|
3029
3029
|
try {
|
|
3030
|
-
execFileSync('which', ['mpv'], { stdio: 'pipe' });
|
|
3030
|
+
execFileSync('which', ['mpv'], { stdio: 'pipe' }); // NOSONAR
|
|
3031
3031
|
audioPlayer = 'mpv';
|
|
3032
3032
|
} catch {}
|
|
3033
3033
|
}
|
|
@@ -4907,7 +4907,7 @@ async function executeMigrationScript(migrationScript, targetDir, spinner) {
|
|
|
4907
4907
|
|
|
4908
4908
|
// Execute migration script using execFileSync to prevent command injection
|
|
4909
4909
|
// Uses top-level import of execFileSync (ESM-compatible, no require())
|
|
4910
|
-
execFileSync('bash', [migrationScript], { cwd: targetDir, stdio: 'pipe' });
|
|
4910
|
+
execFileSync('bash', [migrationScript], { cwd: targetDir, stdio: 'pipe' }); // NOSONAR
|
|
4911
4911
|
|
|
4912
4912
|
spinner.succeed(chalk.green('✓ Configuration migrated to .agentvibes/'));
|
|
4913
4913
|
console.log(chalk.gray(' Old locations: .claude/config/, .claude/plugins/'));
|
|
@@ -5298,7 +5298,7 @@ async function restartWatcherIfInstalled(homeDirOverride) {
|
|
|
5298
5298
|
const { spawnSync, spawn } = require('child_process');
|
|
5299
5299
|
|
|
5300
5300
|
// Kill old watcher — use array args to avoid quoting issues
|
|
5301
|
-
spawnSync('powershell.exe', [
|
|
5301
|
+
spawnSync('powershell.exe', [ // NOSONAR
|
|
5302
5302
|
'-NoProfile', '-Command',
|
|
5303
5303
|
'Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like \'*tts-watcher.ps1*\' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }'
|
|
5304
5304
|
], { stdio: 'ignore', timeout: 8000 });
|
|
@@ -5315,9 +5315,9 @@ async function restartWatcherIfInstalled(homeDirOverride) {
|
|
|
5315
5315
|
// Restart via VBS launcher (hidden, no console flash) or fall back to direct spawn
|
|
5316
5316
|
try {
|
|
5317
5317
|
await fs.access(vbsLauncher);
|
|
5318
|
-
spawnSync('wscript.exe', [vbsLauncher], { stdio: 'ignore' });
|
|
5318
|
+
spawnSync('wscript.exe', [vbsLauncher], { stdio: 'ignore' }); // NOSONAR
|
|
5319
5319
|
} catch {
|
|
5320
|
-
const ps = spawn('powershell.exe', [
|
|
5320
|
+
const ps = spawn('powershell.exe', [ // NOSONAR
|
|
5321
5321
|
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-WindowStyle', 'Hidden', '-File', watcherDest
|
|
5322
5322
|
], { detached: true, stdio: 'ignore' });
|
|
5323
5323
|
ps.unref();
|
|
@@ -5782,7 +5782,7 @@ Troubleshooting:
|
|
|
5782
5782
|
const validReverb = ['light', 'medium', 'heavy', 'cathedral'];
|
|
5783
5783
|
if (validReverb.includes(selectedReverb)) {
|
|
5784
5784
|
try {
|
|
5785
|
-
execFileSync('bash', [effectsManagerPath, 'set-reverb', selectedReverb, 'default'], { stdio: 'pipe' });
|
|
5785
|
+
execFileSync('bash', [effectsManagerPath, 'set-reverb', selectedReverb, 'default'], { stdio: 'pipe' }); // NOSONAR
|
|
5786
5786
|
} catch {
|
|
5787
5787
|
// Reverb setting failed — non-fatal
|
|
5788
5788
|
}
|
|
@@ -6721,4 +6721,9 @@ export {
|
|
|
6721
6721
|
// Manifest utilities (used by tests and external tooling)
|
|
6722
6722
|
getProjectManifestPath, getGlobalManifestPath,
|
|
6723
6723
|
loadManifest, saveManifest, computeFileHash, manifestSafeCopy, removeManifestFiles,
|
|
6724
|
+
// Pure helper functions exported for testing
|
|
6725
|
+
isPiperProvider, supportsEmoji, getPersonalityIcon,
|
|
6726
|
+
detectEnvironment, createPageHeaderFooter, buildNavigationChoices, handleNavigationAction, getPageTitle,
|
|
6727
|
+
getUserShell, showWelcome, getReleaseInfoBoxen, generateActivationInstructions,
|
|
6728
|
+
collectConfiguration,
|
|
6724
6729
|
};
|