agentvibes 5.7.4 → 5.7.6
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/install-manifest.json +115 -111
- package/.claude/config/audio-effects.cfg +1 -1
- package/.claude/config/background-music-position.txt +1 -1
- package/.claude/github-star-reminder.txt +1 -1
- package/.claude/hooks/play-tts-ssh-remote.sh +50 -10
- package/.claude/hooks/play-tts.sh +2 -2
- package/README.md +15 -3
- package/RELEASE_NOTES.md +67 -0
- package/mcp-server/WINDOWS_SETUP.md +1 -1
- package/mcp-server/docs/troubleshooting-audio.md +1 -1
- package/package.json +1 -1
- package/src/console/app.js +7 -0
- package/src/console/audio-env.js +19 -0
- package/src/console/tabs/agents-tab.js +64 -10
- package/src/console/tabs/music-tab.js +4 -4
- package/src/console/tabs/settings-tab.js +75 -1
- package/src/console/tabs/setup-tab.js +94 -28
- package/src/console/tabs/voices-tab.js +51 -33
- package/src/installer.js +15 -1
- package/src/services/llm-provider-service.js +4 -4
- package/templates/agentvibes-receiver.sh +139 -66
|
@@ -78,7 +78,7 @@ const COLORS = {
|
|
|
78
78
|
noticeFg: 'white',
|
|
79
79
|
btnBg: 'blue',
|
|
80
80
|
btnFg: 'white',
|
|
81
|
-
btnFocusBg: '
|
|
81
|
+
btnFocusBg: '#2e7d32',
|
|
82
82
|
removeBg: 'red',
|
|
83
83
|
removeFocusBg: 'magenta',
|
|
84
84
|
cfgBg: 'green',
|
|
@@ -354,7 +354,7 @@ export function createSetupTab(screen, services) {
|
|
|
354
354
|
content: ' Install ', tags: true, mouse: true, keys: true, hidden: true,
|
|
355
355
|
style: {
|
|
356
356
|
fg: COLORS.btnFg, bg: COLORS.btnBg,
|
|
357
|
-
focus: { fg: '
|
|
357
|
+
focus: { fg: 'white', bg: COLORS.btnFocusBg },
|
|
358
358
|
},
|
|
359
359
|
});
|
|
360
360
|
|
|
@@ -534,7 +534,7 @@ export function createSetupTab(screen, services) {
|
|
|
534
534
|
style: {
|
|
535
535
|
fg: COLORS.btnFg,
|
|
536
536
|
bg: COLORS.btnBg,
|
|
537
|
-
focus: { fg: '
|
|
537
|
+
focus: { fg: 'white', bg: COLORS.btnFocusBg },
|
|
538
538
|
},
|
|
539
539
|
});
|
|
540
540
|
|
|
@@ -870,10 +870,12 @@ export function createSetupTab(screen, services) {
|
|
|
870
870
|
padding: { left: 1, right: 1 },
|
|
871
871
|
style: {
|
|
872
872
|
bg: 'blue', fg: 'white',
|
|
873
|
-
focus: { bg: '
|
|
874
|
-
hover: { bg: '
|
|
873
|
+
focus: { bg: '#2e7d32', fg: 'white', bold: true },
|
|
874
|
+
hover: { bg: '#2e7d32', fg: 'white', bold: true },
|
|
875
875
|
},
|
|
876
876
|
});
|
|
877
|
+
btn.on('focus', () => { btn.style.bg = '#2e7d32'; btn.style.fg = 'white'; screen.render(); });
|
|
878
|
+
btn.on('blur', () => { btn.style.bg = 'blue'; btn.style.fg = 'white'; screen.render(); });
|
|
877
879
|
btn.key(['enter', 'space'], () => onClick());
|
|
878
880
|
btn.on('click', () => onClick());
|
|
879
881
|
return btn;
|
|
@@ -1115,7 +1117,7 @@ export function createSetupTab(screen, services) {
|
|
|
1115
1117
|
style: {
|
|
1116
1118
|
fg: COLORS.labelFg, bg: COLORS.contentBg,
|
|
1117
1119
|
border: { fg: 'cyan' },
|
|
1118
|
-
selected: { bg: 'blue', fg: '
|
|
1120
|
+
selected: { bg: 'blue', fg: 'black', bold: true },
|
|
1119
1121
|
},
|
|
1120
1122
|
});
|
|
1121
1123
|
picker.setFront();
|
|
@@ -1154,7 +1156,7 @@ export function createSetupTab(screen, services) {
|
|
|
1154
1156
|
style: {
|
|
1155
1157
|
fg: COLORS.labelFg, bg: COLORS.contentBg,
|
|
1156
1158
|
border: { fg: 'cyan' },
|
|
1157
|
-
selected: { bg: 'blue', fg: '
|
|
1159
|
+
selected: { bg: 'blue', fg: 'black', bold: true },
|
|
1158
1160
|
},
|
|
1159
1161
|
});
|
|
1160
1162
|
picker.setFront();
|
|
@@ -1268,7 +1270,7 @@ export function createSetupTab(screen, services) {
|
|
|
1268
1270
|
style: {
|
|
1269
1271
|
fg: COLORS.labelFg, bg: COLORS.contentBg,
|
|
1270
1272
|
border: { fg: 'cyan' },
|
|
1271
|
-
selected: { bg: 'blue', fg: '
|
|
1273
|
+
selected: { bg: 'blue', fg: 'black', bold: true },
|
|
1272
1274
|
},
|
|
1273
1275
|
});
|
|
1274
1276
|
picker.setFront();
|
|
@@ -1326,7 +1328,7 @@ export function createSetupTab(screen, services) {
|
|
|
1326
1328
|
style: {
|
|
1327
1329
|
fg: COLORS.labelFg, bg: COLORS.contentBg,
|
|
1328
1330
|
border: { fg: 'cyan' },
|
|
1329
|
-
selected: { bg: 'blue', fg: '
|
|
1331
|
+
selected: { bg: 'blue', fg: 'black', bold: true },
|
|
1330
1332
|
},
|
|
1331
1333
|
});
|
|
1332
1334
|
picker.setFront();
|
|
@@ -1364,7 +1366,7 @@ export function createSetupTab(screen, services) {
|
|
|
1364
1366
|
style: {
|
|
1365
1367
|
fg: COLORS.labelFg, bg: COLORS.contentBg,
|
|
1366
1368
|
border: { fg: 'cyan' },
|
|
1367
|
-
selected: { bg: 'blue', fg: '
|
|
1369
|
+
selected: { bg: 'blue', fg: 'black', bold: true },
|
|
1368
1370
|
},
|
|
1369
1371
|
});
|
|
1370
1372
|
picker.setFront();
|
|
@@ -1400,7 +1402,7 @@ export function createSetupTab(screen, services) {
|
|
|
1400
1402
|
style: {
|
|
1401
1403
|
fg: COLORS.labelFg, bg: COLORS.contentBg,
|
|
1402
1404
|
border: { fg: 'cyan' },
|
|
1403
|
-
selected: { bg: 'blue', fg: '
|
|
1405
|
+
selected: { bg: 'blue', fg: 'black', bold: true },
|
|
1404
1406
|
},
|
|
1405
1407
|
});
|
|
1406
1408
|
picker.setFront();
|
|
@@ -1501,10 +1503,12 @@ export function createSetupTab(screen, services) {
|
|
|
1501
1503
|
padding: { left: 1, right: 1 },
|
|
1502
1504
|
style: {
|
|
1503
1505
|
bg: 'blue', fg: 'white',
|
|
1504
|
-
focus: { bg: '
|
|
1505
|
-
hover: { bg: '
|
|
1506
|
+
focus: { bg: '#2e7d32', fg: 'white', bold: true },
|
|
1507
|
+
hover: { bg: '#2e7d32', fg: 'white', bold: true },
|
|
1506
1508
|
},
|
|
1507
1509
|
});
|
|
1510
|
+
btn.on('focus', () => { btn.style.bg = '#2e7d32'; btn.style.fg = 'white'; screen.render(); });
|
|
1511
|
+
btn.on('blur', () => { btn.style.bg = 'blue'; btn.style.fg = 'white'; screen.render(); });
|
|
1508
1512
|
btn.key(['enter', 'space'], () => onClick());
|
|
1509
1513
|
btn.on('click', () => onClick());
|
|
1510
1514
|
return btn;
|
|
@@ -1618,11 +1622,15 @@ export function createSetupTab(screen, services) {
|
|
|
1618
1622
|
let _closed = false;
|
|
1619
1623
|
navigationService?.openModal(null, _closeModal);
|
|
1620
1624
|
|
|
1625
|
+
const _folderName = path.basename(targetDir);
|
|
1626
|
+
const _folderPretext = _folderName
|
|
1627
|
+
? _folderName.charAt(0).toUpperCase() + _folderName.slice(1) + ' here'
|
|
1628
|
+
: '';
|
|
1621
1629
|
const defaultPretext = {
|
|
1622
|
-
'claude-code':
|
|
1623
|
-
'copilot':
|
|
1624
|
-
'codex':
|
|
1625
|
-
'default':
|
|
1630
|
+
'claude-code': _folderPretext,
|
|
1631
|
+
'copilot': _folderPretext,
|
|
1632
|
+
'codex': _folderPretext,
|
|
1633
|
+
'default': _folderPretext,
|
|
1626
1634
|
};
|
|
1627
1635
|
|
|
1628
1636
|
// Read global defaults for display
|
|
@@ -1747,10 +1755,12 @@ export function createSetupTab(screen, services) {
|
|
|
1747
1755
|
style: {
|
|
1748
1756
|
bg: 'blue',
|
|
1749
1757
|
fg: 'white',
|
|
1750
|
-
focus: { bg: '
|
|
1751
|
-
hover: { bg: '
|
|
1758
|
+
focus: { bg: '#2e7d32', fg: 'white', bold: true },
|
|
1759
|
+
hover: { bg: '#2e7d32', fg: 'white', bold: true },
|
|
1752
1760
|
},
|
|
1753
1761
|
});
|
|
1762
|
+
btn.on('focus', () => { btn.style.bg = '#2e7d32'; btn.style.fg = 'white'; screen.render(); });
|
|
1763
|
+
btn.on('blur', () => { btn.style.bg = 'blue'; btn.style.fg = 'white'; screen.render(); });
|
|
1754
1764
|
btn.key(['enter', 'space'], () => onClick());
|
|
1755
1765
|
btn.on('click', () => onClick());
|
|
1756
1766
|
return btn;
|
|
@@ -2172,7 +2182,7 @@ export function createSetupTab(screen, services) {
|
|
|
2172
2182
|
style: {
|
|
2173
2183
|
fg: COLORS.labelFg, bg: COLORS.contentBg,
|
|
2174
2184
|
border: { fg: 'blue' },
|
|
2175
|
-
selected: { bg: 'green', fg: '
|
|
2185
|
+
selected: { bg: 'green', fg: 'black', bold: true },
|
|
2176
2186
|
item: { fg: COLORS.labelFg },
|
|
2177
2187
|
},
|
|
2178
2188
|
});
|
|
@@ -2431,8 +2441,6 @@ export function createSetupTab(screen, services) {
|
|
|
2431
2441
|
const inputBox = blessed.textbox({
|
|
2432
2442
|
parent: editModal, top: 3, left: 2, right: 2, height: 3,
|
|
2433
2443
|
border: { type: 'line' },
|
|
2434
|
-
inputOnFocus: true,
|
|
2435
|
-
value: draft.pretext,
|
|
2436
2444
|
style: {
|
|
2437
2445
|
fg: 'white', bg: 'black',
|
|
2438
2446
|
border: { fg: 'blue' },
|
|
@@ -2440,21 +2448,79 @@ export function createSetupTab(screen, services) {
|
|
|
2440
2448
|
},
|
|
2441
2449
|
});
|
|
2442
2450
|
|
|
2451
|
+
let _editClosed = false;
|
|
2452
|
+
let _cursor = (draft.pretext || '').length;
|
|
2453
|
+
inputBox.value = draft.pretext || '';
|
|
2454
|
+
|
|
2455
|
+
function _renderPretext() {
|
|
2456
|
+
const val = inputBox.value;
|
|
2457
|
+
const lpos = inputBox._getCoords();
|
|
2458
|
+
if (!lpos) { screen.render(); return; }
|
|
2459
|
+
const contentWidth = Math.max(1, (lpos.xl - lpos.xi) - inputBox.iwidth);
|
|
2460
|
+
const start = _cursor > contentWidth - 1 ? _cursor - contentWidth + 1 : 0;
|
|
2461
|
+
inputBox.setContent(val.slice(start));
|
|
2462
|
+
screen.render();
|
|
2463
|
+
screen.program.cup(lpos.yi + inputBox.itop, lpos.xi + inputBox.ileft + (_cursor - start));
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2466
|
+
const _prevGrabKeys = screen.grabKeys;
|
|
2443
2467
|
function _closeEdit(save) {
|
|
2468
|
+
if (_editClosed) return;
|
|
2469
|
+
_editClosed = true;
|
|
2470
|
+
inputBox.removeAllListeners('keypress');
|
|
2471
|
+
screen.grabKeys = _prevGrabKeys;
|
|
2472
|
+
screen.program.hideCursor();
|
|
2444
2473
|
if (save) {
|
|
2445
|
-
|
|
2446
|
-
draft.pretext = val;
|
|
2474
|
+
draft.pretext = (inputBox.value || '').trim().slice(0, 200);
|
|
2447
2475
|
}
|
|
2448
2476
|
destroyList(editModal, screen);
|
|
2449
2477
|
onDone();
|
|
2450
2478
|
}
|
|
2451
2479
|
|
|
2452
|
-
|
|
2453
|
-
|
|
2480
|
+
// Guard: if editModal is destroyed externally without _closeEdit being called,
|
|
2481
|
+
// restore grab state so TUI stays responsive.
|
|
2482
|
+
editModal.once('destroy', () => {
|
|
2483
|
+
if (!_editClosed) {
|
|
2484
|
+
_editClosed = true;
|
|
2485
|
+
inputBox.removeAllListeners('keypress');
|
|
2486
|
+
screen.grabKeys = _prevGrabKeys;
|
|
2487
|
+
screen.program.hideCursor();
|
|
2488
|
+
}
|
|
2489
|
+
});
|
|
2454
2490
|
|
|
2491
|
+
screen.grabKeys = true;
|
|
2455
2492
|
inputBox.focus();
|
|
2456
|
-
|
|
2457
|
-
screen.
|
|
2493
|
+
screen.render(); // Layout pass so _getCoords() returns valid coords on first _renderPretext
|
|
2494
|
+
screen.program.showCursor();
|
|
2495
|
+
_renderPretext();
|
|
2496
|
+
|
|
2497
|
+
inputBox.on('keypress', function(ch, key) {
|
|
2498
|
+
if (_editClosed) return;
|
|
2499
|
+
const val = inputBox.value;
|
|
2500
|
+
if (key.name === 'enter') { _closeEdit(true); return; }
|
|
2501
|
+
if (key.name === 'escape') { _closeEdit(false); return; }
|
|
2502
|
+
if (key.name === 'home' || (key.ctrl && key.name === 'a')) {
|
|
2503
|
+
_cursor = 0;
|
|
2504
|
+
} else if (key.name === 'end' || (key.ctrl && key.name === 'e')) {
|
|
2505
|
+
_cursor = val.length;
|
|
2506
|
+
} else if (key.name === 'left') {
|
|
2507
|
+
if (_cursor > 0) _cursor--; else return;
|
|
2508
|
+
} else if (key.name === 'right') {
|
|
2509
|
+
if (_cursor < val.length) _cursor++; else return;
|
|
2510
|
+
} else if (key.name === 'backspace') {
|
|
2511
|
+
if (_cursor > 0) { inputBox.value = val.slice(0, _cursor - 1) + val.slice(_cursor); _cursor--; }
|
|
2512
|
+
else return;
|
|
2513
|
+
} else if (key.name === 'delete') {
|
|
2514
|
+
if (_cursor < val.length) { inputBox.value = val.slice(0, _cursor) + val.slice(_cursor + 1); }
|
|
2515
|
+
else return;
|
|
2516
|
+
} else if (ch && !key.ctrl && !key.meta && !/^[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]$/.test(ch)) {
|
|
2517
|
+
inputBox.value = val.slice(0, _cursor) + ch + val.slice(_cursor);
|
|
2518
|
+
_cursor++;
|
|
2519
|
+
} else {
|
|
2520
|
+
return;
|
|
2521
|
+
}
|
|
2522
|
+
_renderPretext();
|
|
2523
|
+
});
|
|
2458
2524
|
}
|
|
2459
2525
|
|
|
2460
2526
|
// ── Saved toast ───────────────────────────────────────────────────────────
|
|
@@ -13,7 +13,7 @@ import path from 'node:path';
|
|
|
13
13
|
import os from 'node:os';
|
|
14
14
|
import { spawn } from 'node:child_process';
|
|
15
15
|
import { fileURLToPath } from 'node:url';
|
|
16
|
-
import { buildAudioEnv, detectWavPlayer } from '../audio-env.js';
|
|
16
|
+
import { buildAudioEnv, detectWavPlayer, getAllWavPlayers } from '../audio-env.js';
|
|
17
17
|
import { SURNAME_POOL, uniquifyVoiceName } from '../../utils/voice-names.js';
|
|
18
18
|
|
|
19
19
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -1022,9 +1022,9 @@ export function createVoicesTab(screen, services) {
|
|
|
1022
1022
|
return;
|
|
1023
1023
|
}
|
|
1024
1024
|
|
|
1025
|
-
// Play the synthesized wav
|
|
1026
|
-
const
|
|
1027
|
-
if (
|
|
1025
|
+
// Play the synthesized wav — try each installed player until one succeeds
|
|
1026
|
+
const _wavPlayers = getAllWavPlayers(_spawnEnv);
|
|
1027
|
+
if (_wavPlayers.length === 0) {
|
|
1028
1028
|
_playingVoiceId = null;
|
|
1029
1029
|
_playingProcess = null;
|
|
1030
1030
|
previewLine.setContent(`{red-fg}No audio player found. Install ffmpeg.{/red-fg}`);
|
|
@@ -1033,44 +1033,62 @@ export function createVoicesTab(screen, services) {
|
|
|
1033
1033
|
try { fs.unlinkSync(tempWav); } catch {}
|
|
1034
1034
|
return;
|
|
1035
1035
|
}
|
|
1036
|
-
|
|
1037
|
-
stdio: 'ignore',
|
|
1038
|
-
detached: !isWindows,
|
|
1039
|
-
windowsHide: true,
|
|
1040
|
-
env: _spawnEnv,
|
|
1041
|
-
});
|
|
1036
|
+
|
|
1042
1037
|
// Race note: _playingVoiceId could change between piper exit and here
|
|
1043
1038
|
// if the user stops playback. Re-check before assigning to avoid orphan.
|
|
1044
1039
|
if (_playingVoiceId !== voiceId) { try { fs.unlinkSync(tempWav); } catch {} return; }
|
|
1045
|
-
_playingProcess = playProc;
|
|
1046
1040
|
|
|
1047
1041
|
previewLine.setContent(`{${COLORS.activeFg}-fg}♪ Playing: ${voiceId} (Enter/Space to stop){/${COLORS.activeFg}-fg}`);
|
|
1048
1042
|
screen.render();
|
|
1049
1043
|
|
|
1050
|
-
|
|
1051
|
-
if (
|
|
1044
|
+
function _tryNextPlayer(remainingPlayers) {
|
|
1045
|
+
if (!remainingPlayers.length) {
|
|
1052
1046
|
_playingVoiceId = null;
|
|
1053
1047
|
_playingProcess = null;
|
|
1048
|
+
previewLine.setContent(`{red-fg}♪ Audio playback failed (no audio device?) — check your provider in Setup{/red-fg}`);
|
|
1049
|
+
screen.render();
|
|
1050
|
+
setTimeout(() => { if (!_closed) { previewLine.setContent(_listFocused ? HINT_TEXT : ''); screen.render(); } }, 5000);
|
|
1051
|
+
try { fs.unlinkSync(tempWav); } catch {}
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
const [wavP, ...rest] = remainingPlayers;
|
|
1055
|
+
const playProc = spawn(wavP.bin, wavP.args(tempWav), {
|
|
1056
|
+
stdio: 'ignore',
|
|
1057
|
+
detached: !isWindows,
|
|
1058
|
+
windowsHide: true,
|
|
1059
|
+
env: _spawnEnv,
|
|
1060
|
+
});
|
|
1061
|
+
if (_playingVoiceId !== voiceId) {
|
|
1062
|
+
try { playProc.kill(); } catch {}
|
|
1063
|
+
try { fs.unlinkSync(tempWav); } catch {}
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
_playingProcess = playProc;
|
|
1067
|
+
|
|
1068
|
+
playProc.on('exit', (code) => {
|
|
1069
|
+
if (_playingVoiceId !== voiceId) {
|
|
1070
|
+
try { fs.unlinkSync(tempWav); } catch {}
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1054
1073
|
if (code !== 0) {
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
setTimeout(() => { if (!_closed) { previewLine.setContent(_listFocused ? HINT_TEXT : ''); screen.render(); } }, 5000);
|
|
1074
|
+
// This player failed — try the next one
|
|
1075
|
+
_tryNextPlayer(rest);
|
|
1058
1076
|
} else {
|
|
1077
|
+
_playingVoiceId = null;
|
|
1078
|
+
_playingProcess = null;
|
|
1059
1079
|
previewLine.setContent(_listFocused ? HINT_TEXT : '');
|
|
1060
|
-
refreshDisplay();
|
|
1080
|
+
refreshDisplay();
|
|
1081
|
+
try { fs.unlinkSync(tempWav); } catch {}
|
|
1061
1082
|
}
|
|
1062
|
-
}
|
|
1063
|
-
try { fs.unlinkSync(tempWav); } catch {}
|
|
1064
|
-
});
|
|
1083
|
+
});
|
|
1065
1084
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
});
|
|
1085
|
+
playProc.on('error', () => {
|
|
1086
|
+
if (_playingVoiceId !== voiceId) { try { fs.unlinkSync(tempWav); } catch {} return; }
|
|
1087
|
+
_tryNextPlayer(rest);
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
_tryNextPlayer(_wavPlayers);
|
|
1074
1092
|
});
|
|
1075
1093
|
|
|
1076
1094
|
piper.on('error', () => {
|
|
@@ -1122,7 +1140,7 @@ export function createVoicesTab(screen, services) {
|
|
|
1122
1140
|
padding: { left: 1, right: 1 },
|
|
1123
1141
|
style: {
|
|
1124
1142
|
bg: COLORS.btnDefault,
|
|
1125
|
-
fg: 'white',
|
|
1143
|
+
fg: 'bright-white',
|
|
1126
1144
|
focus: { bg: COLORS.btnFocus, fg: COLORS.btnFocusFg, bold: true },
|
|
1127
1145
|
hover: { bg: COLORS.btnFocus, fg: COLORS.btnFocusFg, bold: true },
|
|
1128
1146
|
},
|
|
@@ -1136,7 +1154,7 @@ export function createVoicesTab(screen, services) {
|
|
|
1136
1154
|
});
|
|
1137
1155
|
btn.on('blur', () => {
|
|
1138
1156
|
btn.style.bg = COLORS.btnDefault;
|
|
1139
|
-
btn.style.fg = 'white';
|
|
1157
|
+
btn.style.fg = 'bright-white';
|
|
1140
1158
|
const raw = btn.content.replace(/[►◄]/g, '').trim();
|
|
1141
1159
|
btn.setContent(raw);
|
|
1142
1160
|
screen.render();
|
|
@@ -1306,7 +1324,7 @@ export function createVoicesTab(screen, services) {
|
|
|
1306
1324
|
padding: { left: 1, right: 1 },
|
|
1307
1325
|
style: {
|
|
1308
1326
|
bg,
|
|
1309
|
-
fg: 'white',
|
|
1327
|
+
fg: 'bright-white',
|
|
1310
1328
|
focus: { bg: COLORS.btnFocus, fg: COLORS.btnFocusFg, bold: true },
|
|
1311
1329
|
hover: { bg: COLORS.btnFocus, fg: COLORS.btnFocusFg, bold: true },
|
|
1312
1330
|
},
|
|
@@ -1341,7 +1359,7 @@ export function createVoicesTab(screen, services) {
|
|
|
1341
1359
|
padding: { left: 1, right: 1 },
|
|
1342
1360
|
style: {
|
|
1343
1361
|
bg: '#e65100',
|
|
1344
|
-
fg: 'white',
|
|
1362
|
+
fg: 'bright-white',
|
|
1345
1363
|
focus: { bg: COLORS.btnFocus, fg: COLORS.btnFocusFg, bold: true },
|
|
1346
1364
|
hover: { bg: COLORS.btnFocus, fg: COLORS.btnFocusFg, bold: true },
|
|
1347
1365
|
},
|
|
@@ -1550,7 +1568,7 @@ export function createVoicesTab(screen, services) {
|
|
|
1550
1568
|
padding: { left: 1, right: 1 },
|
|
1551
1569
|
style: {
|
|
1552
1570
|
bg,
|
|
1553
|
-
fg: 'white',
|
|
1571
|
+
fg: 'bright-white',
|
|
1554
1572
|
focus: { bg: COLORS.btnFocus, fg: COLORS.btnFocusFg, bold: true },
|
|
1555
1573
|
hover: { bg: COLORS.btnFocus, fg: COLORS.btnFocusFg, bold: true },
|
|
1556
1574
|
},
|
package/src/installer.js
CHANGED
|
@@ -74,6 +74,7 @@ import { promptForCustomMusic } from './installer/music-file-input.js';
|
|
|
74
74
|
import { createPreviewListPrompt } from './utils/preview-list-prompt.js';
|
|
75
75
|
import { selectLanguage } from './installer/language-screen.js';
|
|
76
76
|
import { t } from './i18n/strings.js';
|
|
77
|
+
import { seedAllLlmDefaultsSync } from './services/llm-provider-service.js';
|
|
77
78
|
|
|
78
79
|
const __filename = fileURLToPath(import.meta.url);
|
|
79
80
|
const __dirname = path.dirname(__filename);
|
|
@@ -1248,12 +1249,20 @@ async function collectConfiguration(options = {}) {
|
|
|
1248
1249
|
config.provider = process.platform === 'darwin' ? 'macos' : 'piper';
|
|
1249
1250
|
config.defaultVoice = process.platform === 'darwin' ? 'Samantha' : 'en_US-ryan-high';
|
|
1250
1251
|
}
|
|
1251
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
1252
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
1252
1253
|
config.piperPath = path.join(homeDir, '.claude', 'piper-voices');
|
|
1253
1254
|
// AI agent / non-interactive defaults: no reverb, no background music, no hermes
|
|
1254
1255
|
config.reverb = 'none';
|
|
1255
1256
|
config.backgroundMusic = { enabled: false, track: 'agentvibes_soft_flamenco_loop.mp3' };
|
|
1256
1257
|
config.hermes = { enabled: false };
|
|
1258
|
+
// Use folder name as project identity when no existing pretext is set
|
|
1259
|
+
if (!config.pretext) {
|
|
1260
|
+
const folderName = path.basename(process.cwd());
|
|
1261
|
+
// Guard empty basename (e.g. process.cwd() === '/' in some Docker containers)
|
|
1262
|
+
if (folderName) {
|
|
1263
|
+
config.pretext = folderName.charAt(0).toUpperCase() + folderName.slice(1) + ' here';
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1257
1266
|
return config;
|
|
1258
1267
|
}
|
|
1259
1268
|
|
|
@@ -5761,6 +5770,11 @@ Troubleshooting:
|
|
|
5761
5770
|
}
|
|
5762
5771
|
// Do NOT unlink tts-pretext.txt when blank — user may have set it via MCP or manually.
|
|
5763
5772
|
|
|
5773
|
+
// Seed project-level llm: rows with empty pretext so global ~/.claude/config/audio-effects.cfg
|
|
5774
|
+
// "Claude Code here" rows don't override tts-pretext.txt (play-tts.sh stops searching when it
|
|
5775
|
+
// finds a row with a voice, then falls through to tts-pretext.txt for the pretext).
|
|
5776
|
+
seedAllLlmDefaultsSync(targetDir);
|
|
5777
|
+
|
|
5764
5778
|
// Apply reverb setting
|
|
5765
5779
|
const selectedReverb = userConfig.reverb;
|
|
5766
5780
|
if (selectedReverb && selectedReverb !== 'off') {
|
|
@@ -59,7 +59,7 @@ const DEFAULT_LLM_CONFIGS = {
|
|
|
59
59
|
bgTrack: 'agent_vibes_chillwave_v2_loop.mp3',
|
|
60
60
|
bgVolume: '0.15',
|
|
61
61
|
voice: 'en_US-lessac-high',
|
|
62
|
-
pretext: '
|
|
62
|
+
pretext: '',
|
|
63
63
|
ttsEngine: 'piper',
|
|
64
64
|
},
|
|
65
65
|
copilot: {
|
|
@@ -67,7 +67,7 @@ const DEFAULT_LLM_CONFIGS = {
|
|
|
67
67
|
bgTrack: 'agent_vibes_bossa_nova_v2_loop.mp3',
|
|
68
68
|
bgVolume: '0.15',
|
|
69
69
|
voice: 'en_US-libritts-high::Anna-11',
|
|
70
|
-
pretext: '
|
|
70
|
+
pretext: '',
|
|
71
71
|
ttsEngine: 'piper',
|
|
72
72
|
},
|
|
73
73
|
codex: {
|
|
@@ -78,7 +78,7 @@ const DEFAULT_LLM_CONFIGS = {
|
|
|
78
78
|
// Windows Piper installs (loads the model, exits with no output).
|
|
79
79
|
// lessac-high works reliably, so use it as the default for codex.
|
|
80
80
|
voice: 'en_US-lessac-high',
|
|
81
|
-
pretext: '
|
|
81
|
+
pretext: '',
|
|
82
82
|
ttsEngine: 'piper',
|
|
83
83
|
},
|
|
84
84
|
hermes: {
|
|
@@ -86,7 +86,7 @@ const DEFAULT_LLM_CONFIGS = {
|
|
|
86
86
|
bgTrack: 'agent_vibes_bachata_v1_loop.mp3',
|
|
87
87
|
bgVolume: '0.15',
|
|
88
88
|
voice: 'en_US-libritts-high::Leo-8',
|
|
89
|
-
pretext: '
|
|
89
|
+
pretext: '',
|
|
90
90
|
ttsEngine: 'piper',
|
|
91
91
|
},
|
|
92
92
|
};
|