maven: embedder config validation + docs (task 1)

- Tests: all-three-set → ok; one-missing → error; nil → ok
- Log message on HashEmbedder fallback in voice.go
- Document floor mode in START.md

Co-Authored-By: opencode <opencode@anthropic.com>
This commit is contained in:
kami
2026-07-06 04:02:32 +04:00
parent 311c5cb1cd
commit b778f0bbec
3 changed files with 46 additions and 0 deletions
+2
View File
@@ -58,6 +58,8 @@ Config path: `~/.config/maven/mavend.json`. Full example with all options:
}
```
Omit the `embedder` block entirely to use the deterministic HashEmbedder floor (no ML, no ONNX runtime dependency). Useful for testing or low-resource setups.
## mavsttd — STT worker (optional, remote whisper.cpp)
Requires `LD_LIBRARY_PATH` to include deps/lib (for libwhisper.so, libggml-vulkan.so).
+1
View File
@@ -156,6 +156,7 @@ func wireVoice(cfg *config.Config, coreAPI ipc.CoreAPI, phr phraser.Phraser) (*v
log.Printf("voice: onnx embedder loaded (%d dim)", onnx.Dim())
emb = onnx
} else {
log.Printf("voice: embedder not configured, using HashEmbedder floor")
emb = router.NewHashEmbedder(1024)
}
w.embedder = emb
+43
View File
@@ -82,6 +82,49 @@ func TestVoiceEnabledWithBindOK(t *testing.T) {
}
}
func TestEmbedderAllPathsSetOK(t *testing.T) {
p := writeConfig(t, `{
"voice": {
"enabled": true, "bind": "127.0.0.1:9100",
"embedder": {
"model_path": "m.onnx",
"tokenizer_path": "t.json",
"lib_path": "l.so"
}
}
}`)
if _, err := Load(p); err != nil {
t.Fatalf("Load: %v", err)
}
}
func TestEmbedderPartialConfigRejected(t *testing.T) {
tests := []struct {
name string
json string
}{
{"missing model_path", `{"voice":{"enabled":true,"bind":"127.0.0.1:9100","embedder":{"tokenizer_path":"t.json","lib_path":"l.so"}}}`},
{"missing tokenizer_path", `{"voice":{"enabled":true,"bind":"127.0.0.1:9100","embedder":{"model_path":"m.onnx","lib_path":"l.so"}}}`},
{"missing lib_path", `{"voice":{"enabled":true,"bind":"127.0.0.1:9100","embedder":{"model_path":"m.onnx","tokenizer_path":"t.json"}}}`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := writeConfig(t, tt.json)
if _, err := Load(p); err == nil {
t.Fatal("Load succeeded for partial embedder; want error")
}
})
}
}
func TestEmbedderNilOK(t *testing.T) {
// voice block without embedder → ok (HashEmbedder floor)
p := writeConfig(t, `{"voice":{"enabled":true,"bind":"127.0.0.1:9100"}}`)
if _, err := Load(p); err != nil {
t.Fatalf("Load: %v", err)
}
}
func TestVoicePresentDisabledOK(t *testing.T) {
// voice block present but not enabled — acceptable (the listener stays
// down; the routing table's ChannelVoice selections drop).