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
package/bin/mcp-server.js
CHANGED
|
@@ -1,122 +1,122 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* AgentVibes MCP Server Launcher (Cross-Platform)
|
|
5
|
-
*
|
|
6
|
-
* This Node.js script replaces the bash wrapper to work on Windows, macOS, and Linux.
|
|
7
|
-
* It auto-installs Python dependencies and launches the Python MCP server.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { spawn } from 'child_process';
|
|
11
|
-
import { fileURLToPath } from 'url';
|
|
12
|
-
import { dirname, join } from 'path';
|
|
13
|
-
import { existsSync } from 'fs';
|
|
14
|
-
import { platform } from 'os';
|
|
15
|
-
|
|
16
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
-
const __dirname = dirname(__filename);
|
|
18
|
-
|
|
19
|
-
// Package root is one level up from bin/
|
|
20
|
-
const PACKAGE_ROOT = join(__dirname, '..');
|
|
21
|
-
const MCP_SERVER = join(PACKAGE_ROOT, 'mcp-server', 'server.py');
|
|
22
|
-
const INSTALL_DEPS = join(PACKAGE_ROOT, 'mcp-server', 'install-deps.js');
|
|
23
|
-
|
|
24
|
-
// Check if Python MCP server exists
|
|
25
|
-
if (!existsSync(MCP_SERVER)) {
|
|
26
|
-
console.error(`❌ Error: MCP server not found at ${MCP_SERVER}`);
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Function to find available Python command
|
|
31
|
-
async function findPythonCommand() {
|
|
32
|
-
const commands = platform() === 'win32' ? ['python', 'py', 'python3'] : ['python3', 'python'];
|
|
33
|
-
|
|
34
|
-
for (const cmd of commands) {
|
|
35
|
-
try {
|
|
36
|
-
const checkCmd = platform() === 'win32' ? 'where' : 'which';
|
|
37
|
-
const proc = spawn(checkCmd, [cmd], { stdio: 'ignore' });
|
|
38
|
-
const exists = await new Promise((resolve) => {
|
|
39
|
-
proc.on('close', (code) => resolve(code === 0));
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
if (exists) {
|
|
43
|
-
return cmd;
|
|
44
|
-
}
|
|
45
|
-
} catch (err) {
|
|
46
|
-
// Try next command
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Function to check if Python module is installed
|
|
54
|
-
function checkPythonModule(pythonCmd, moduleName) {
|
|
55
|
-
return new Promise((resolve) => {
|
|
56
|
-
const proc = spawn(pythonCmd, ['-c', `import ${moduleName}`], { stdio: 'ignore' });
|
|
57
|
-
proc.on('close', (code) => resolve(code === 0));
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Main setup and launch function
|
|
62
|
-
async function main() {
|
|
63
|
-
// Silent mode - no output to avoid breaking MCP JSON protocol
|
|
64
|
-
|
|
65
|
-
// Find Python command
|
|
66
|
-
const pythonCmd = await findPythonCommand();
|
|
67
|
-
if (!pythonCmd) {
|
|
68
|
-
console.error('ERROR: Python 3 not found. Install from https://python.org and restart Claude Desktop.');
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Check if MCP Python package is installed
|
|
73
|
-
const hasMCP = await checkPythonModule(pythonCmd, 'mcp');
|
|
74
|
-
if (!hasMCP) {
|
|
75
|
-
// Try to install MCP package directly
|
|
76
|
-
try {
|
|
77
|
-
const installCmd = `${pythonCmd} -m pip install --user mcp`;
|
|
78
|
-
const installProc = spawn(pythonCmd, ['-m', 'pip', 'install', '--user', 'mcp'], {
|
|
79
|
-
stdio: 'pipe',
|
|
80
|
-
shell: false
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
await new Promise((resolve, reject) => {
|
|
84
|
-
installProc.on('close', (code) => {
|
|
85
|
-
if (code === 0) {
|
|
86
|
-
resolve();
|
|
87
|
-
} else {
|
|
88
|
-
console.error('ERROR: Failed to install Python mcp package. Run: pip install mcp');
|
|
89
|
-
reject(new Error('Dependency installation failed'));
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
} catch (err) {
|
|
94
|
-
console.error('ERROR: Failed to install Python mcp package. Run: pip install mcp');
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Launch the Python MCP server
|
|
100
|
-
const serverProc = spawn(pythonCmd, [MCP_SERVER], {
|
|
101
|
-
stdio: 'inherit',
|
|
102
|
-
env: process.env
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
serverProc.on('error', (err) => {
|
|
106
|
-
console.error('❌ Failed to start MCP server:', err.message);
|
|
107
|
-
process.exit(1);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
serverProc.on('close', (code) => {
|
|
111
|
-
process.exit(code || 0);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// Handle termination signals
|
|
115
|
-
process.on('SIGINT', () => serverProc.kill('SIGINT'));
|
|
116
|
-
process.on('SIGTERM', () => serverProc.kill('SIGTERM'));
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
main().catch((err) => {
|
|
120
|
-
console.error('❌ Error:', err.message);
|
|
121
|
-
process.exit(1);
|
|
122
|
-
});
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AgentVibes MCP Server Launcher (Cross-Platform)
|
|
5
|
+
*
|
|
6
|
+
* This Node.js script replaces the bash wrapper to work on Windows, macOS, and Linux.
|
|
7
|
+
* It auto-installs Python dependencies and launches the Python MCP server.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { spawn } from 'child_process';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import { dirname, join } from 'path';
|
|
13
|
+
import { existsSync } from 'fs';
|
|
14
|
+
import { platform } from 'os';
|
|
15
|
+
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
|
|
19
|
+
// Package root is one level up from bin/
|
|
20
|
+
const PACKAGE_ROOT = join(__dirname, '..');
|
|
21
|
+
const MCP_SERVER = join(PACKAGE_ROOT, 'mcp-server', 'server.py');
|
|
22
|
+
const INSTALL_DEPS = join(PACKAGE_ROOT, 'mcp-server', 'install-deps.js');
|
|
23
|
+
|
|
24
|
+
// Check if Python MCP server exists
|
|
25
|
+
if (!existsSync(MCP_SERVER)) {
|
|
26
|
+
console.error(`❌ Error: MCP server not found at ${MCP_SERVER}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Function to find available Python command
|
|
31
|
+
async function findPythonCommand() {
|
|
32
|
+
const commands = platform() === 'win32' ? ['python', 'py', 'python3'] : ['python3', 'python'];
|
|
33
|
+
|
|
34
|
+
for (const cmd of commands) {
|
|
35
|
+
try {
|
|
36
|
+
const checkCmd = platform() === 'win32' ? 'where' : 'which';
|
|
37
|
+
const proc = spawn(checkCmd, [cmd], { stdio: 'ignore' });
|
|
38
|
+
const exists = await new Promise((resolve) => {
|
|
39
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (exists) {
|
|
43
|
+
return cmd;
|
|
44
|
+
}
|
|
45
|
+
} catch (err) {
|
|
46
|
+
// Try next command
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Function to check if Python module is installed
|
|
54
|
+
function checkPythonModule(pythonCmd, moduleName) {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
const proc = spawn(pythonCmd, ['-c', `import ${moduleName}`], { stdio: 'ignore' });
|
|
57
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Main setup and launch function
|
|
62
|
+
async function main() {
|
|
63
|
+
// Silent mode - no output to avoid breaking MCP JSON protocol
|
|
64
|
+
|
|
65
|
+
// Find Python command
|
|
66
|
+
const pythonCmd = await findPythonCommand();
|
|
67
|
+
if (!pythonCmd) {
|
|
68
|
+
console.error('ERROR: Python 3 not found. Install from https://python.org and restart Claude Desktop.');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check if MCP Python package is installed
|
|
73
|
+
const hasMCP = await checkPythonModule(pythonCmd, 'mcp');
|
|
74
|
+
if (!hasMCP) {
|
|
75
|
+
// Try to install MCP package directly
|
|
76
|
+
try {
|
|
77
|
+
const installCmd = `${pythonCmd} -m pip install --user mcp`;
|
|
78
|
+
const installProc = spawn(pythonCmd, ['-m', 'pip', 'install', '--user', 'mcp'], {
|
|
79
|
+
stdio: 'pipe',
|
|
80
|
+
shell: false
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await new Promise((resolve, reject) => {
|
|
84
|
+
installProc.on('close', (code) => {
|
|
85
|
+
if (code === 0) {
|
|
86
|
+
resolve();
|
|
87
|
+
} else {
|
|
88
|
+
console.error('ERROR: Failed to install Python mcp package. Run: pip install mcp');
|
|
89
|
+
reject(new Error('Dependency installation failed'));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
} catch (err) {
|
|
94
|
+
console.error('ERROR: Failed to install Python mcp package. Run: pip install mcp');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Launch the Python MCP server
|
|
100
|
+
const serverProc = spawn(pythonCmd, [MCP_SERVER], {
|
|
101
|
+
stdio: 'inherit',
|
|
102
|
+
env: process.env
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
serverProc.on('error', (err) => {
|
|
106
|
+
console.error('❌ Failed to start MCP server:', err.message);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
serverProc.on('close', (code) => {
|
|
111
|
+
process.exit(code || 0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Handle termination signals
|
|
115
|
+
process.on('SIGINT', () => serverProc.kill('SIGINT'));
|
|
116
|
+
process.on('SIGTERM', () => serverProc.kill('SIGTERM'));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
main().catch((err) => {
|
|
120
|
+
console.error('❌ Error:', err.message);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
});
|
package/bin/mcp-server.sh
CHANGED
|
@@ -72,7 +72,7 @@ if ! python3 -c "import mcp" 2>/dev/null; then
|
|
|
72
72
|
print_section "📦 Installing Python MCP Package"
|
|
73
73
|
echo "Installing 'mcp' package to enable Claude Desktop integration..." >&2
|
|
74
74
|
|
|
75
|
-
if python3 -m pip install --user mcp --quiet 2
|
|
75
|
+
if python3 -m pip install --user mcp --quiet >&2; then
|
|
76
76
|
echo "✅ Python MCP package installed successfully!" >&2
|
|
77
77
|
else
|
|
78
78
|
echo "❌ Failed to auto-install MCP package" >&2
|
|
@@ -86,9 +86,10 @@ else
|
|
|
86
86
|
echo "✅ Python MCP package already installed" >&2
|
|
87
87
|
fi
|
|
88
88
|
|
|
89
|
-
# Check provider
|
|
89
|
+
# Check provider — ElevenLabs was removed from the product; Piper (free,
|
|
90
|
+
# offline) is the only provider this wrapper does auto-setup for.
|
|
90
91
|
PROVIDER_FILE="$PACKAGE_ROOT/.claude/tts-provider.txt"
|
|
91
|
-
PROVIDER="
|
|
92
|
+
PROVIDER="piper" # Default
|
|
92
93
|
|
|
93
94
|
if [ -f "$PROVIDER_FILE" ]; then
|
|
94
95
|
PROVIDER=$(cat "$PROVIDER_FILE" | tr -d '[:space:]')
|
|
@@ -104,7 +105,7 @@ if [ "$PROVIDER" = "piper" ]; then
|
|
|
104
105
|
print_section "📦 Installing pipx"
|
|
105
106
|
echo "pipx is needed to install Piper TTS..." >&2
|
|
106
107
|
|
|
107
|
-
if python3 -m pip install --user pipx --quiet 2
|
|
108
|
+
if python3 -m pip install --user pipx --quiet >&2; then
|
|
108
109
|
# Add pipx to PATH for this session
|
|
109
110
|
export PATH="$HOME/.local/bin:$PATH"
|
|
110
111
|
|
|
@@ -137,7 +138,7 @@ if [ "$PROVIDER" = "piper" ]; then
|
|
|
137
138
|
print_section "📦 Installing Piper TTS"
|
|
138
139
|
echo "Installing Piper TTS (free, offline voice synthesis)..." >&2
|
|
139
140
|
|
|
140
|
-
if pipx install piper-tts --quiet 2
|
|
141
|
+
if pipx install piper-tts --quiet >&2; then
|
|
141
142
|
echo "✅ Piper TTS installed successfully!" >&2
|
|
142
143
|
|
|
143
144
|
# Add pipx bin to PATH
|
|
@@ -181,20 +182,6 @@ if [ "$PROVIDER" = "piper" ]; then
|
|
|
181
182
|
fi
|
|
182
183
|
fi
|
|
183
184
|
fi
|
|
184
|
-
elif [ "$PROVIDER" = "elevenlabs" ]; then
|
|
185
|
-
# Check for ElevenLabs API key
|
|
186
|
-
if [ -z "$ELEVENLABS_API_KEY" ]; then
|
|
187
|
-
echo "⚠️ ElevenLabs selected but ELEVENLABS_API_KEY not set" >&2
|
|
188
|
-
echo "" >&2
|
|
189
|
-
echo "📖 Set your API key:" >&2
|
|
190
|
-
echo " export ELEVENLABS_API_KEY='your-key-here'" >&2
|
|
191
|
-
echo "" >&2
|
|
192
|
-
echo "💡 Or switch to Piper TTS (free):" >&2
|
|
193
|
-
echo " echo 'piper' > $PACKAGE_ROOT/.claude/tts-provider.txt" >&2
|
|
194
|
-
echo "" >&2
|
|
195
|
-
else
|
|
196
|
-
echo "✅ ElevenLabs API key configured" >&2
|
|
197
|
-
fi
|
|
198
185
|
fi
|
|
199
186
|
|
|
200
187
|
# All checks passed, run the MCP server
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* File: bin/resolve-utterance.js
|
|
4
|
+
*
|
|
5
|
+
* CLI bridge between the pure Node utterance resolver and the bash/PowerShell/
|
|
6
|
+
* Python player scripts (Story AVI-S8.5, Stage 2). Reads all config once via the
|
|
7
|
+
* loader, resolves the plan, and prints it as one line of JSON on stdout.
|
|
8
|
+
*
|
|
9
|
+
* Players call this ONCE and execute the returned plan verbatim — they no longer
|
|
10
|
+
* read config or make precedence decisions themselves.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* resolve-utterance.js --text "hello" [--llm claude-code] [--voice af_bella]
|
|
14
|
+
* [--voice-source user-explicit] [--project-dir /path] [--personality pirate]
|
|
15
|
+
*
|
|
16
|
+
* Output (stdout):
|
|
17
|
+
* default / --format json : a single JSON object (the UtterancePlan).
|
|
18
|
+
* --format sh : safe `AV_<FIELD>=<single-quoted>` lines a POSIX
|
|
19
|
+
* shell can `eval`. Booleans emit 'true'/'false';
|
|
20
|
+
* nested music/ssh fields flatten to AV_MUSIC_*,
|
|
21
|
+
* AV_SSH_*. This is how bash/zsh players consume the
|
|
22
|
+
* plan without a JSON parser.
|
|
23
|
+
* Nothing else is printed to stdout so callers can parse it directly;
|
|
24
|
+
* diagnostics go to stderr. Exit codes: 0 = plan emitted; 2 = the resolved plan
|
|
25
|
+
* failed validation (a loud failure — never emit a silently-wrong plan).
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
'use strict';
|
|
29
|
+
|
|
30
|
+
import os from 'node:os';
|
|
31
|
+
import { gatherInputs } from '../src/services/utterance-loader.js';
|
|
32
|
+
import { resolveUtterance, validatePlan } from '../src/services/utterance-resolver.js';
|
|
33
|
+
|
|
34
|
+
/** Minimal --flag value parser (no external deps; players pass simple flags). */
|
|
35
|
+
// Flags that take a value. For these we ALWAYS consume the next token as the
|
|
36
|
+
// value — even if it starts with "--" (a message like "-- shipping now" must not
|
|
37
|
+
// be misread as an absent value and turned into boolean true, which would make
|
|
38
|
+
// TTS literally speak "true"). Anything else is treated as a boolean flag.
|
|
39
|
+
const VALUE_FLAGS = new Set([
|
|
40
|
+
'text', 'voice', 'voiceSource', 'llm', 'personality',
|
|
41
|
+
'projectDir', 'packageRoot', 'format', 'language',
|
|
42
|
+
]);
|
|
43
|
+
function parseArgs(argv) {
|
|
44
|
+
const out = {};
|
|
45
|
+
for (let i = 0; i < argv.length; i++) {
|
|
46
|
+
const a = argv[i];
|
|
47
|
+
if (!a.startsWith('--')) continue;
|
|
48
|
+
const key = a.slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
49
|
+
if (VALUE_FLAGS.has(key)) {
|
|
50
|
+
out[key] = (i + 1 < argv.length) ? argv[++i] : '';
|
|
51
|
+
} else {
|
|
52
|
+
out[key] = true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function main() {
|
|
59
|
+
const args = parseArgs(process.argv.slice(2));
|
|
60
|
+
const ctx = {
|
|
61
|
+
text: args.text ?? '',
|
|
62
|
+
voice: args.voice,
|
|
63
|
+
voiceSource: args.voiceSource,
|
|
64
|
+
llm: args.llm,
|
|
65
|
+
personality: args.personality,
|
|
66
|
+
projectDir: args.projectDir,
|
|
67
|
+
packageRoot: args.packageRoot,
|
|
68
|
+
homeDir: os.homedir(),
|
|
69
|
+
cwd: process.cwd(),
|
|
70
|
+
env: process.env,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
let plan;
|
|
74
|
+
try {
|
|
75
|
+
const inputs = gatherInputs(ctx);
|
|
76
|
+
plan = resolveUtterance(inputs);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
process.stderr.write(`resolve-utterance: failed to resolve plan: ${err.message}\n`);
|
|
79
|
+
process.exit(2);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const problems = validatePlan(plan);
|
|
83
|
+
if (problems.length) {
|
|
84
|
+
// Fail loud — a malformed plan must never be executed (silent-wrong audio).
|
|
85
|
+
process.stderr.write(`resolve-utterance: invalid plan: ${problems.join('; ')}\n`);
|
|
86
|
+
process.exit(2);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (args.format === 'sh') {
|
|
90
|
+
process.stdout.write(toShell(plan));
|
|
91
|
+
} else {
|
|
92
|
+
process.stdout.write(JSON.stringify(plan) + '\n');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Single-quote a value for safe POSIX-shell eval (wrap, escaping embedded quotes). */
|
|
97
|
+
function shq(v) {
|
|
98
|
+
return `'${String(v).replace(/'/g, `'\\''`)}'`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Flatten a plan into `AV_<FIELD>=<quoted>` lines for `eval` in a shell player. */
|
|
102
|
+
function toShell(plan) {
|
|
103
|
+
const b = (x) => (x ? 'true' : 'false');
|
|
104
|
+
const m = plan.music || {};
|
|
105
|
+
const s = plan.sshTarget || {};
|
|
106
|
+
const lines = [
|
|
107
|
+
`AV_TEXT=${shq(plan.text ?? '')}`,
|
|
108
|
+
`AV_VOICE=${shq(plan.voice ?? '')}`,
|
|
109
|
+
`AV_VOICE_IS_OVERRIDE=${b(plan.voiceIsOverride)}`,
|
|
110
|
+
`AV_ENGINE=${shq(plan.engine ?? '')}`,
|
|
111
|
+
`AV_TRANSPORT=${shq(plan.transport ?? 'local')}`,
|
|
112
|
+
`AV_VOICE_MODEL=${shq(plan.voiceModel ?? '')}`,
|
|
113
|
+
`AV_SPEAKER_ID=${shq(plan.speakerId ?? '')}`,
|
|
114
|
+
`AV_PERSONALITY=${shq(plan.personality ?? '')}`,
|
|
115
|
+
`AV_LANGUAGE=${shq(plan.language ?? '')}`,
|
|
116
|
+
`AV_PRETEXT=${shq(plan.pretext ?? '')}`,
|
|
117
|
+
`AV_SPEED=${shq(plan.speed ?? '')}`,
|
|
118
|
+
`AV_REVERB=${shq(plan.reverb ?? 'off')}`,
|
|
119
|
+
`AV_EFFECTS=${shq(plan.effects ?? '')}`,
|
|
120
|
+
`AV_MUSIC_ENABLED=${b(m.enabled)}`,
|
|
121
|
+
`AV_MUSIC_TRACK=${shq(m.track ?? '')}`,
|
|
122
|
+
`AV_MUSIC_VOLUME=${shq(m.volume ?? '')}`,
|
|
123
|
+
`AV_MUTE=${b(plan.mute)}`,
|
|
124
|
+
`AV_RDP_MODE=${b(plan.rdpMode)}`,
|
|
125
|
+
`AV_NO_PLAYBACK=${b(plan.noPlayback)}`,
|
|
126
|
+
`AV_TEST_MODE=${b(plan.testMode)}`,
|
|
127
|
+
`AV_LLM_KEY=${shq(plan.llmKey ?? '')}`,
|
|
128
|
+
`AV_PROJECT_DIR=${shq(plan.projectDir ?? '')}`,
|
|
129
|
+
`AV_SSH_HOST=${shq(s.host ?? '')}`,
|
|
130
|
+
`AV_SSH_PORT=${shq(s.port ?? '')}`,
|
|
131
|
+
`AV_SSH_PASS_PORT_FLAG=${b(s.passPortFlag)}`,
|
|
132
|
+
`AV_SSH_KEY=${shq(s.key ?? '')}`,
|
|
133
|
+
];
|
|
134
|
+
return lines.join('\n') + '\n';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
main();
|
package/bin/test-bmad-pr
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# AgentVibes BMAD PR Testing Command
|
|
4
|
-
# Quick command to test BMAD PRs with AgentVibes integration
|
|
5
|
-
#
|
|
6
|
-
# Usage:
|
|
7
|
-
# npx agentvibes test-bmad-pr [PR_NUMBER]
|
|
8
|
-
# npx agentvibes test-bmad-pr 934
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
set -e
|
|
12
|
-
|
|
13
|
-
# Colors
|
|
14
|
-
GREEN='\033[0;32m'
|
|
15
|
-
BLUE='\033[0;34m'
|
|
16
|
-
YELLOW='\033[1;33m'
|
|
17
|
-
CYAN='\033[0;36m'
|
|
18
|
-
NC='\033[0m' # No Color
|
|
19
|
-
|
|
20
|
-
# Default PR number
|
|
21
|
-
PR_NUMBER="${1:-934}"
|
|
22
|
-
|
|
23
|
-
clear
|
|
24
|
-
|
|
25
|
-
echo ""
|
|
26
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
27
|
-
echo -e "${CYAN}🎙️ AgentVibes BMAD PR Testing Tool${NC}"
|
|
28
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
29
|
-
echo ""
|
|
30
|
-
echo -e "${BLUE}Testing PR #${PR_NUMBER}${NC}"
|
|
31
|
-
echo ""
|
|
32
|
-
echo -e "${YELLOW}This will download and run the automated test script for${NC}"
|
|
33
|
-
echo -e "${YELLOW}BMAD's AgentVibes integration with multi-agent party mode.${NC}"
|
|
34
|
-
echo ""
|
|
35
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
36
|
-
echo ""
|
|
37
|
-
|
|
38
|
-
# Create temp directory for the script
|
|
39
|
-
TEMP_DIR=$(mktemp -d)
|
|
40
|
-
SCRIPT_PATH="$TEMP_DIR/test-bmad-pr.sh"
|
|
41
|
-
|
|
42
|
-
echo -e "${BLUE}📥 Downloading test script...${NC}"
|
|
43
|
-
|
|
44
|
-
# Download the test script from the PR branch
|
|
45
|
-
SCRIPT_URL="https://raw.githubusercontent.com/paulpreibisch/BMAD-METHOD/feature/agentvibes-tts-integration/test-bmad-pr.sh"
|
|
46
|
-
|
|
47
|
-
if curl -fsSL "$SCRIPT_URL" -o "$SCRIPT_PATH"; then
|
|
48
|
-
chmod +x "$SCRIPT_PATH"
|
|
49
|
-
echo -e "${GREEN}✓ Test script downloaded${NC}"
|
|
50
|
-
echo ""
|
|
51
|
-
|
|
52
|
-
# Run the test script
|
|
53
|
-
exec "$SCRIPT_PATH"
|
|
54
|
-
else
|
|
55
|
-
echo -e "${YELLOW}⚠ Could not download test script from PR branch${NC}"
|
|
56
|
-
echo ""
|
|
57
|
-
echo "Trying alternative: Official BMAD repository..."
|
|
58
|
-
echo ""
|
|
59
|
-
|
|
60
|
-
# Fallback to official repo
|
|
61
|
-
SCRIPT_URL="https://raw.githubusercontent.com/bmad-code-org/BMAD-METHOD/refs/pull/${PR_NUMBER}/merge/test-bmad-pr.sh"
|
|
62
|
-
|
|
63
|
-
if curl -fsSL "$SCRIPT_URL" -o "$SCRIPT_PATH"; then
|
|
64
|
-
chmod +x "$SCRIPT_PATH"
|
|
65
|
-
echo -e "${GREEN}✓ Test script downloaded${NC}"
|
|
66
|
-
echo ""
|
|
67
|
-
exec "$SCRIPT_PATH"
|
|
68
|
-
else
|
|
69
|
-
echo -e "${YELLOW}⚠ Could not download test script${NC}"
|
|
70
|
-
echo ""
|
|
71
|
-
echo "Please try manual testing:"
|
|
72
|
-
echo -e "${GREEN}git clone https://github.com/bmad-code-org/BMAD-METHOD.git${NC}"
|
|
73
|
-
echo -e "${GREEN}cd BMAD-METHOD${NC}"
|
|
74
|
-
echo -e "${GREEN}git fetch origin pull/${PR_NUMBER}/head:test-pr-${PR_NUMBER}${NC}"
|
|
75
|
-
echo -e "${GREEN}git checkout test-pr-${PR_NUMBER}${NC}"
|
|
76
|
-
echo ""
|
|
77
|
-
exit 1
|
|
78
|
-
fi
|
|
79
|
-
fi
|
|
2
|
+
#
|
|
3
|
+
# AgentVibes BMAD PR Testing Command
|
|
4
|
+
# Quick command to test BMAD PRs with AgentVibes integration
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# npx agentvibes test-bmad-pr [PR_NUMBER]
|
|
8
|
+
# npx agentvibes test-bmad-pr 934
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
set -e
|
|
12
|
+
|
|
13
|
+
# Colors
|
|
14
|
+
GREEN='\033[0;32m'
|
|
15
|
+
BLUE='\033[0;34m'
|
|
16
|
+
YELLOW='\033[1;33m'
|
|
17
|
+
CYAN='\033[0;36m'
|
|
18
|
+
NC='\033[0m' # No Color
|
|
19
|
+
|
|
20
|
+
# Default PR number
|
|
21
|
+
PR_NUMBER="${1:-934}"
|
|
22
|
+
|
|
23
|
+
clear
|
|
24
|
+
|
|
25
|
+
echo ""
|
|
26
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
27
|
+
echo -e "${CYAN}🎙️ AgentVibes BMAD PR Testing Tool${NC}"
|
|
28
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
29
|
+
echo ""
|
|
30
|
+
echo -e "${BLUE}Testing PR #${PR_NUMBER}${NC}"
|
|
31
|
+
echo ""
|
|
32
|
+
echo -e "${YELLOW}This will download and run the automated test script for${NC}"
|
|
33
|
+
echo -e "${YELLOW}BMAD's AgentVibes integration with multi-agent party mode.${NC}"
|
|
34
|
+
echo ""
|
|
35
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
36
|
+
echo ""
|
|
37
|
+
|
|
38
|
+
# Create temp directory for the script
|
|
39
|
+
TEMP_DIR=$(mktemp -d)
|
|
40
|
+
SCRIPT_PATH="$TEMP_DIR/test-bmad-pr.sh"
|
|
41
|
+
|
|
42
|
+
echo -e "${BLUE}📥 Downloading test script...${NC}"
|
|
43
|
+
|
|
44
|
+
# Download the test script from the PR branch
|
|
45
|
+
SCRIPT_URL="https://raw.githubusercontent.com/paulpreibisch/BMAD-METHOD/feature/agentvibes-tts-integration/test-bmad-pr.sh"
|
|
46
|
+
|
|
47
|
+
if curl -fsSL "$SCRIPT_URL" -o "$SCRIPT_PATH"; then
|
|
48
|
+
chmod +x "$SCRIPT_PATH"
|
|
49
|
+
echo -e "${GREEN}✓ Test script downloaded${NC}"
|
|
50
|
+
echo ""
|
|
51
|
+
|
|
52
|
+
# Run the test script
|
|
53
|
+
exec "$SCRIPT_PATH"
|
|
54
|
+
else
|
|
55
|
+
echo -e "${YELLOW}⚠ Could not download test script from PR branch${NC}"
|
|
56
|
+
echo ""
|
|
57
|
+
echo "Trying alternative: Official BMAD repository..."
|
|
58
|
+
echo ""
|
|
59
|
+
|
|
60
|
+
# Fallback to official repo
|
|
61
|
+
SCRIPT_URL="https://raw.githubusercontent.com/bmad-code-org/BMAD-METHOD/refs/pull/${PR_NUMBER}/merge/test-bmad-pr.sh"
|
|
62
|
+
|
|
63
|
+
if curl -fsSL "$SCRIPT_URL" -o "$SCRIPT_PATH"; then
|
|
64
|
+
chmod +x "$SCRIPT_PATH"
|
|
65
|
+
echo -e "${GREEN}✓ Test script downloaded${NC}"
|
|
66
|
+
echo ""
|
|
67
|
+
exec "$SCRIPT_PATH"
|
|
68
|
+
else
|
|
69
|
+
echo -e "${YELLOW}⚠ Could not download test script${NC}"
|
|
70
|
+
echo ""
|
|
71
|
+
echo "Please try manual testing:"
|
|
72
|
+
echo -e "${GREEN}git clone https://github.com/bmad-code-org/BMAD-METHOD.git${NC}"
|
|
73
|
+
echo -e "${GREEN}cd BMAD-METHOD${NC}"
|
|
74
|
+
echo -e "${GREEN}git fetch origin pull/${PR_NUMBER}/head:test-pr-${PR_NUMBER}${NC}"
|
|
75
|
+
echo -e "${GREEN}git checkout test-pr-${PR_NUMBER}${NC}"
|
|
76
|
+
echo ""
|
|
77
|
+
exit 1
|
|
78
|
+
fi
|
|
79
|
+
fi
|