agentvibes 5.11.2 → 5.12.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/.claude/config/audio-effects.cfg +1 -1
- package/.claude/config/audio-effects.cfg.bak-kokoro +7 -0
- 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 +117 -7
- package/.claude/hooks/play-tts-termux-ssh.sh +1 -1
- package/.claude/hooks/play-tts.sh +106 -13
- 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/tts-watcher.ps1 +55 -0
- package/.claude/hooks-windows/voice-manager-windows.ps1 +101 -1
- package/README.md +11 -6
- package/RELEASE_NOTES.md +67 -0
- package/bin/mcp-server.sh +6 -19
- package/bin/resolve-utterance.js +137 -0
- package/mcp-server/server.py +280 -99
- package/mcp-server/test_mcp_correctness.py +486 -0
- package/mcp-server/test_windows_script_parity.py +341 -336
- package/package.json +3 -2
- package/setup-windows.ps1 +867 -815
- package/src/console/app.js +14 -11
- package/src/console/footer-config.js +0 -4
- package/src/console/navigation.js +0 -1
- package/src/console/tabs/agents-tab.js +96 -11
- package/src/console/tabs/music-tab.js +108 -3
- package/src/console/tabs/placeholder-tab.js +0 -2
- package/src/console/tabs/settings-tab.js +41 -2
- package/src/console/tabs/setup-tab.js +34 -6
- package/src/console/tabs/voices-tab.js +19 -9
- 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.js +205 -15
- package/src/services/config-service.js +264 -264
- package/src/services/llm-provider-service.js +7 -7
- package/src/services/navigation-service.js +1 -1
- package/src/services/utterance-loader.js +280 -0
- package/src/services/utterance-resolver.js +526 -0
- package/templates/agentvibes-receiver.sh +74 -12
- package/voice-assignments.json +8245 -0
|
@@ -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();
|