agentvibes 5.6.0 → 5.6.2
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 -38
- package/.claude/config/audio-effects.cfg +1 -1
- package/.claude/config/background-music-enabled.txt +1 -1
- package/.claude/config/background-music-position.txt +6 -6
- package/.claude/github-star-reminder.txt +1 -1
- package/.claude/hooks/play-tts-ssh-remote.sh +119 -42
- package/.claude/hooks/play-tts-windows-receiver.sh +31 -0
- package/.claude/hooks/stop.sh +2 -27
- package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -108
- package/.claude/hooks-windows/play-tts.ps1 +58 -8
- package/.claude/piper-voices-dir.txt +1 -1
- package/.clawdbot/skill/README.md +326 -0
- package/.mcp.json +17 -27
- package/README.md +15 -2
- package/RELEASE_NOTES.md +64 -0
- package/bin/agent-vibes +39 -39
- package/package.json +1 -1
- package/src/bmad-detector.js +71 -71
- 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 +476 -476
- package/src/console/brand-colors.js +13 -13
- package/src/console/constants/personalities.js +44 -44
- package/src/console/modals/modal-overlay.js +247 -247
- package/src/console/navigation.js +5 -1
- package/src/console/tabs/agents-tab.js +5 -5
- package/src/console/tabs/help-tab.js +314 -314
- package/src/console/tabs/readme-tab.js +272 -272
- package/src/console/tabs/setup-tab.js +32 -17
- package/src/console/tabs/voices-tab.js +2 -2
- package/src/console/widgets/destroy-list.js +25 -25
- package/src/console/widgets/notice.js +55 -55
- package/src/console/widgets/personality-picker.js +213 -213
- package/src/console/widgets/reverb-picker.js +97 -97
- package/src/console/widgets/track-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/services/agent-voice-store.js +420 -423
- package/src/services/config-service.js +264 -264
- package/src/services/language-service.js +47 -47
- package/src/services/llm-provider-service.js +11 -4
- package/src/services/navigation-service.js +34 -10
- package/src/services/provider-service.js +143 -143
- 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 +194 -194
- package/src/utils/music-file-validator.js +285 -285
- package/src/utils/preview-list-prompt.js +136 -136
- package/src/utils/secure-music-storage.js +412 -412
- package/.agentvibes/LITE-MODE.md +0 -236
- package/.agentvibes/README.md +0 -136
- package/.agentvibes/backup/session-start-tts.sh.20251210_212814 +0 -141
- package/.agentvibes/backups/agents/analyst_20260204_144958.md +0 -78
- package/.agentvibes/backups/agents/architect_20260204_144958.md +0 -72
- package/.agentvibes/backups/agents/dev_20260204_144958.md +0 -74
- package/.agentvibes/backups/agents/pm_20260204_144958.md +0 -72
- package/.agentvibes/backups/agents/quick-flow-solo-dev_20260204_144958.md +0 -64
- package/.agentvibes/backups/agents/sm_20260204_144958.md +0 -87
- package/.agentvibes/backups/agents/tea_20260204_144958.md +0 -79
- package/.agentvibes/backups/agents/tech-writer_20260204_144958.md +0 -82
- package/.agentvibes/backups/agents/ux-designer_20260204_144958.md +0 -80
- package/.agentvibes/config/README-personality-defaults.md +0 -162
- package/.agentvibes/config/agentvibes.json +0 -1
- package/.agentvibes/config/mode.txt +0 -1
- package/.agentvibes/config/personality-voice-defaults.default.json +0 -21
- package/.agentvibes/config/save-audio.txt +0 -1
- package/.agentvibes/config/voice-metadata.json +0 -160
- package/.agentvibes/hooks/help.sh +0 -191
- package/.agentvibes/hooks/post-tool-use-lite.sh +0 -111
- package/.agentvibes/hooks/save-audio-manager.sh +0 -162
- package/.agentvibes/hooks/session-start-full-optimized.sh +0 -102
- package/.agentvibes/hooks/session-start-full.sh +0 -142
- package/.agentvibes/hooks/session-start-lite-v2.sh +0 -34
- package/.agentvibes/hooks/session-start-lite.sh +0 -29
- package/.agentvibes/hooks/stop-lite.sh +0 -115
- package/.agentvibes/hooks/switch-mode.sh +0 -215
- package/.agentvibes/output-styles/audio-summary.md +0 -30
- package/.claude/audio/voice-samples/piper/alan.wav +0 -0
- package/.claude/audio/voice-samples/piper/amy.wav +0 -0
- package/.claude/audio/voice-samples/piper/charlotte.wav +0 -0
- package/.claude/audio/voice-samples/piper/joe.wav +0 -0
- package/.claude/audio/voice-samples/piper/john.wav +0 -0
- package/.claude/audio/voice-samples/piper/katherine.wav +0 -0
- package/.claude/audio/voice-samples/piper/kristin.wav +0 -0
- package/.claude/audio/voice-samples/piper/linda.wav +0 -0
- package/.claude/audio/voice-samples/piper/marcus.wav +0 -0
- package/.claude/audio/voice-samples/piper/ryan.wav +0 -0
- package/.claude/hooks/post-response.sh +0 -41
- package/bin/ensure-soprano-running.sh +0 -43
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom Inquirer List Prompt with Spacebar Preview
|
|
3
|
-
* Uses wrapper approach with readline keypress events
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import readline from 'node:readline';
|
|
7
|
-
import { execSync } from 'node:child_process';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Wrapper for inquirer list prompt that adds spacebar preview
|
|
11
|
-
* @param {Object} inquirer - Inquirer instance
|
|
12
|
-
* @param {Object} config - Prompt configuration
|
|
13
|
-
* @param {Function} config.onPreview - Callback for preview (receives selected value)
|
|
14
|
-
* @returns {Promise} Inquirer prompt promise
|
|
15
|
-
*/
|
|
16
|
-
export async function createPreviewListPrompt(inquirer, config) {
|
|
17
|
-
const { onPreview, ...promptConfig } = config;
|
|
18
|
-
|
|
19
|
-
// Set up keypress listener
|
|
20
|
-
let keypressListener = null;
|
|
21
|
-
|
|
22
|
-
// Track playing state
|
|
23
|
-
let currentlyPlaying = null;
|
|
24
|
-
let audioProcess = null;
|
|
25
|
-
|
|
26
|
-
// Initialize currentSelection to match the default value
|
|
27
|
-
let currentSelection = 0;
|
|
28
|
-
if (promptConfig.default) {
|
|
29
|
-
const defaultIndex = promptConfig.choices.findIndex(c => c.value === promptConfig.default);
|
|
30
|
-
if (defaultIndex !== -1) {
|
|
31
|
-
currentSelection = defaultIndex;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Function to stop currently playing audio
|
|
36
|
-
const stopAudio = () => {
|
|
37
|
-
// Kill the specific process if we have it
|
|
38
|
-
// SECURITY: Only kill our own process, never use pkill which affects all users
|
|
39
|
-
if (audioProcess) {
|
|
40
|
-
try {
|
|
41
|
-
audioProcess.kill('SIGKILL');
|
|
42
|
-
audioProcess = null;
|
|
43
|
-
} catch (e) {
|
|
44
|
-
// Process might have already finished or already killed
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
currentlyPlaying = null;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
if (onPreview && process.stdin.isTTY) {
|
|
52
|
-
readline.emitKeypressEvents(process.stdin);
|
|
53
|
-
// SECURITY: Wrap in try-catch to prevent terminal corruption on error
|
|
54
|
-
try {
|
|
55
|
-
if (process.stdin.setRawMode) {
|
|
56
|
-
process.stdin.setRawMode(true);
|
|
57
|
-
}
|
|
58
|
-
} catch (e) {
|
|
59
|
-
// Failed to set raw mode, continue without it
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
keypressListener = async (str, key) => {
|
|
63
|
-
// Track current selection based on arrow keys
|
|
64
|
-
if (key && key.name === 'down') {
|
|
65
|
-
currentSelection = Math.min(currentSelection + 1, promptConfig.choices.length - 1);
|
|
66
|
-
} else if (key && key.name === 'up') {
|
|
67
|
-
currentSelection = Math.max(currentSelection - 1, 0);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (key && key.name === 'space') {
|
|
71
|
-
// Get the current item (don't filter - use actual index)
|
|
72
|
-
const currentChoice = promptConfig.choices[currentSelection];
|
|
73
|
-
|
|
74
|
-
// Only preview if it's a valid choice (not separator, not special item)
|
|
75
|
-
if (currentChoice && currentChoice.value && !currentChoice.value.startsWith('__')) {
|
|
76
|
-
|
|
77
|
-
// Toggle: if same voice pressed twice, stop it
|
|
78
|
-
if (currentlyPlaying === currentChoice.value) {
|
|
79
|
-
stopAudio();
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// CRITICAL: Stop previous voice BEFORE starting new one
|
|
84
|
-
if (currentlyPlaying) {
|
|
85
|
-
stopAudio();
|
|
86
|
-
// Small delay to ensure kill takes effect
|
|
87
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
currentlyPlaying = currentChoice.value;
|
|
91
|
-
|
|
92
|
-
// Call onPreview and store process handle immediately
|
|
93
|
-
try {
|
|
94
|
-
const result = await onPreview(currentChoice.value);
|
|
95
|
-
// Store the process handle - onPreview should return the spawn() result
|
|
96
|
-
audioProcess = result;
|
|
97
|
-
} catch (err) {
|
|
98
|
-
console.error(`[Preview] Error playing sample:`, err.message);
|
|
99
|
-
currentlyPlaying = null;
|
|
100
|
-
audioProcess = null;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
process.stdin.on('keypress', keypressListener);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
// Run the standard list prompt
|
|
111
|
-
const result = await inquirer.prompt([{
|
|
112
|
-
...promptConfig,
|
|
113
|
-
type: 'list'
|
|
114
|
-
}]);
|
|
115
|
-
|
|
116
|
-
return result;
|
|
117
|
-
} finally {
|
|
118
|
-
// Stop any playing audio
|
|
119
|
-
stopAudio();
|
|
120
|
-
|
|
121
|
-
// Clean up keypress listener
|
|
122
|
-
if (keypressListener) {
|
|
123
|
-
process.stdin.removeListener('keypress', keypressListener);
|
|
124
|
-
// SECURITY: Wrap in try-catch to ensure cleanup always completes
|
|
125
|
-
try {
|
|
126
|
-
if (process.stdin.setRawMode) {
|
|
127
|
-
process.stdin.setRawMode(false);
|
|
128
|
-
}
|
|
129
|
-
} catch (e) {
|
|
130
|
-
// Failed to restore raw mode, but we're exiting anyway
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export default createPreviewListPrompt;
|
|
1
|
+
/**
|
|
2
|
+
* Custom Inquirer List Prompt with Spacebar Preview
|
|
3
|
+
* Uses wrapper approach with readline keypress events
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import readline from 'node:readline';
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Wrapper for inquirer list prompt that adds spacebar preview
|
|
11
|
+
* @param {Object} inquirer - Inquirer instance
|
|
12
|
+
* @param {Object} config - Prompt configuration
|
|
13
|
+
* @param {Function} config.onPreview - Callback for preview (receives selected value)
|
|
14
|
+
* @returns {Promise} Inquirer prompt promise
|
|
15
|
+
*/
|
|
16
|
+
export async function createPreviewListPrompt(inquirer, config) {
|
|
17
|
+
const { onPreview, ...promptConfig } = config;
|
|
18
|
+
|
|
19
|
+
// Set up keypress listener
|
|
20
|
+
let keypressListener = null;
|
|
21
|
+
|
|
22
|
+
// Track playing state
|
|
23
|
+
let currentlyPlaying = null;
|
|
24
|
+
let audioProcess = null;
|
|
25
|
+
|
|
26
|
+
// Initialize currentSelection to match the default value
|
|
27
|
+
let currentSelection = 0;
|
|
28
|
+
if (promptConfig.default) {
|
|
29
|
+
const defaultIndex = promptConfig.choices.findIndex(c => c.value === promptConfig.default);
|
|
30
|
+
if (defaultIndex !== -1) {
|
|
31
|
+
currentSelection = defaultIndex;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Function to stop currently playing audio
|
|
36
|
+
const stopAudio = () => {
|
|
37
|
+
// Kill the specific process if we have it
|
|
38
|
+
// SECURITY: Only kill our own process, never use pkill which affects all users
|
|
39
|
+
if (audioProcess) {
|
|
40
|
+
try {
|
|
41
|
+
audioProcess.kill('SIGKILL');
|
|
42
|
+
audioProcess = null;
|
|
43
|
+
} catch (e) {
|
|
44
|
+
// Process might have already finished or already killed
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
currentlyPlaying = null;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if (onPreview && process.stdin.isTTY) {
|
|
52
|
+
readline.emitKeypressEvents(process.stdin);
|
|
53
|
+
// SECURITY: Wrap in try-catch to prevent terminal corruption on error
|
|
54
|
+
try {
|
|
55
|
+
if (process.stdin.setRawMode) {
|
|
56
|
+
process.stdin.setRawMode(true);
|
|
57
|
+
}
|
|
58
|
+
} catch (e) {
|
|
59
|
+
// Failed to set raw mode, continue without it
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
keypressListener = async (str, key) => {
|
|
63
|
+
// Track current selection based on arrow keys
|
|
64
|
+
if (key && key.name === 'down') {
|
|
65
|
+
currentSelection = Math.min(currentSelection + 1, promptConfig.choices.length - 1);
|
|
66
|
+
} else if (key && key.name === 'up') {
|
|
67
|
+
currentSelection = Math.max(currentSelection - 1, 0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (key && key.name === 'space') {
|
|
71
|
+
// Get the current item (don't filter - use actual index)
|
|
72
|
+
const currentChoice = promptConfig.choices[currentSelection];
|
|
73
|
+
|
|
74
|
+
// Only preview if it's a valid choice (not separator, not special item)
|
|
75
|
+
if (currentChoice && currentChoice.value && !currentChoice.value.startsWith('__')) {
|
|
76
|
+
|
|
77
|
+
// Toggle: if same voice pressed twice, stop it
|
|
78
|
+
if (currentlyPlaying === currentChoice.value) {
|
|
79
|
+
stopAudio();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// CRITICAL: Stop previous voice BEFORE starting new one
|
|
84
|
+
if (currentlyPlaying) {
|
|
85
|
+
stopAudio();
|
|
86
|
+
// Small delay to ensure kill takes effect
|
|
87
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
currentlyPlaying = currentChoice.value;
|
|
91
|
+
|
|
92
|
+
// Call onPreview and store process handle immediately
|
|
93
|
+
try {
|
|
94
|
+
const result = await onPreview(currentChoice.value);
|
|
95
|
+
// Store the process handle - onPreview should return the spawn() result
|
|
96
|
+
audioProcess = result;
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.error(`[Preview] Error playing sample:`, err.message);
|
|
99
|
+
currentlyPlaying = null;
|
|
100
|
+
audioProcess = null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
process.stdin.on('keypress', keypressListener);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
// Run the standard list prompt
|
|
111
|
+
const result = await inquirer.prompt([{
|
|
112
|
+
...promptConfig,
|
|
113
|
+
type: 'list'
|
|
114
|
+
}]);
|
|
115
|
+
|
|
116
|
+
return result;
|
|
117
|
+
} finally {
|
|
118
|
+
// Stop any playing audio
|
|
119
|
+
stopAudio();
|
|
120
|
+
|
|
121
|
+
// Clean up keypress listener
|
|
122
|
+
if (keypressListener) {
|
|
123
|
+
process.stdin.removeListener('keypress', keypressListener);
|
|
124
|
+
// SECURITY: Wrap in try-catch to ensure cleanup always completes
|
|
125
|
+
try {
|
|
126
|
+
if (process.stdin.setRawMode) {
|
|
127
|
+
process.stdin.setRawMode(false);
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
// Failed to restore raw mode, but we're exiting anyway
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export default createPreviewListPrompt;
|