feat(config): Daemon-Port server.port mit Env-Override TALK_PORT (Default 7800)
This commit is contained in:
1 parent
3b44605234
commit
716f6b2fc9
2 files changed
+94
-3
No files matched your search
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
)
|
)
|
||||||
@@ -16,13 +17,21 @@ const (
|
|||||||
SinkNull = "null"
|
SinkNull = "null"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DefaultServerPort ist der Default-Port des Daemon-HTTP-Servers auf
|
||||||
|
// 127.0.0.1 (Task-04-Brief: „Port Default 7800").
|
||||||
|
const DefaultServerPort = 7800
|
||||||
|
|
||||||
// Config ist der effektiv geladene Konfigurations-Stand von talk. Task 02
|
// Config ist der effektiv geladene Konfigurations-Stand von talk. Task 02
|
||||||
// führt audio.sink; Task 03 ergänzt den Provider-Pin, Provider-Endpunkte
|
// führt audio.sink; Task 03 ergänzt den Provider-Pin, Provider-Endpunkte
|
||||||
// und das Voice-Mapping; spätere Tasks ergänzen weitere Felder (server,
|
// und das Voice-Mapping; Task 04 den Daemon-Port (server.port, TALK_PORT);
|
||||||
// queue …), ohne die Auflösungsreihenfolge zu ändern.
|
// spätere Tasks ergänzen weitere Felder (queue …), ohne die Auflösungs-
|
||||||
|
// reihenfolge zu ändern.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Audio Audio `toml:"audio"`
|
Audio Audio `toml:"audio"`
|
||||||
|
|
||||||
|
// Server steuert den Daemon-HTTP-Server (talkd) auf 127.0.0.1.
|
||||||
|
Server Server `toml:"server"`
|
||||||
|
|
||||||
// Provider pinnt die Kette auf genau einen Provider (z. B.
|
// Provider pinnt die Kette auf genau einen Provider (z. B.
|
||||||
// `provider = "elevenlabs"`); leer = komplette Default-Kette
|
// `provider = "elevenlabs"`); leer = komplette Default-Kette
|
||||||
// (elevenlabs → openai → edge → osbuiltin). Das CLI-Flag --provider
|
// (elevenlabs → openai → edge → osbuiltin). Das CLI-Flag --provider
|
||||||
@@ -48,6 +57,14 @@ type Audio struct {
|
|||||||
Sink string `toml:"sink"`
|
Sink string `toml:"sink"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Server sind die Netz-Einstellungen des Daemons (nur Loopback; Binding
|
||||||
|
// auf 127.0.0.1 macht cmd/talkd, die Config liefert nur den Port).
|
||||||
|
type Server struct {
|
||||||
|
// Port des Daemon-HTTP-Servers auf 127.0.0.1 — config
|
||||||
|
// `[server] port = 7800`, Env-Override TALK_PORT, Default 7800.
|
||||||
|
Port int `toml:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
// ProviderSettings sind die per Provider konfigurierbaren Endpunkte und
|
// ProviderSettings sind die per Provider konfigurierbaren Endpunkte und
|
||||||
// Modelle (TOML `[providers.<name>]`). Leer = eingebaute Defaults; die
|
// Modelle (TOML `[providers.<name>]`). Leer = eingebaute Defaults; die
|
||||||
// Env-Overrides TALK_ELEVENLABS_ENDPOINT / TALK_OPENAI_ENDPOINT /
|
// Env-Overrides TALK_ELEVENLABS_ENDPOINT / TALK_OPENAI_ENDPOINT /
|
||||||
@@ -62,7 +79,10 @@ type ProviderSettings struct {
|
|||||||
// Defaults liefert die eingebaute Default-Konfiguration (unterste Schicht
|
// Defaults liefert die eingebaute Default-Konfiguration (unterste Schicht
|
||||||
// der Auflösung).
|
// der Auflösung).
|
||||||
func Defaults() Config {
|
func Defaults() Config {
|
||||||
return Config{Audio: Audio{Sink: SinkOto}}
|
return Config{
|
||||||
|
Audio: Audio{Sink: SinkOto},
|
||||||
|
Server: Server{Port: DefaultServerPort},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options steuert Load. Alle Felder sind injizierbar, damit die Unit-Tests
|
// Options steuert Load. Alle Felder sind injizierbar, damit die Unit-Tests
|
||||||
@@ -116,6 +136,13 @@ func applyEnv(cfg Config, getenv func(string) string) (Config, error) {
|
|||||||
if v := getenv("TALK_PROVIDER"); v != "" {
|
if v := getenv("TALK_PROVIDER"); v != "" {
|
||||||
cfg.Provider = v
|
cfg.Provider = v
|
||||||
}
|
}
|
||||||
|
if v := getenv("TALK_PORT"); v != "" {
|
||||||
|
port, err := strconv.Atoi(v)
|
||||||
|
if err != nil || port < 1 || port > 65535 {
|
||||||
|
return cfg, fmt.Errorf("TALK_PORT: ungültiger Wert %q (1–65535)", v)
|
||||||
|
}
|
||||||
|
cfg.Server.Port = port
|
||||||
|
}
|
||||||
switch cfg.Audio.Sink {
|
switch cfg.Audio.Sink {
|
||||||
case SinkOto, SinkNull:
|
case SinkOto, SinkNull:
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
|
|||||||
@@ -288,3 +288,67 @@ de = "de-DE-KatjaNeural"
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestLoadServerPort deckt die Task-04-Felder ab: Daemon-Port per Defaults
|
||||||
|
// (7800), TOML [server] port, Env-Override TALK_PORT samt Validierung.
|
||||||
|
func TestLoadServerPort(t *testing.T) {
|
||||||
|
writeTOML := func(t *testing.T, content string) string {
|
||||||
|
t.Helper()
|
||||||
|
path := filepath.Join(t.TempDir(), "config.toml")
|
||||||
|
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("Default 7800", func(t *testing.T) {
|
||||||
|
cfg, err := Load(Options{
|
||||||
|
File: filepath.Join(t.TempDir(), "gibt-es-nicht.toml"),
|
||||||
|
Getenv: env(nil),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Load: %v", err)
|
||||||
|
}
|
||||||
|
if cfg.Server.Port != DefaultServerPort {
|
||||||
|
t.Errorf("Server.Port = %d, want Default %d", cfg.Server.Port, DefaultServerPort)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("TOML überschreibt Default", func(t *testing.T) {
|
||||||
|
cfg, err := Load(Options{
|
||||||
|
File: writeTOML(t, "[server]\nport = 7999\n"),
|
||||||
|
Getenv: env(nil),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Load: %v", err)
|
||||||
|
}
|
||||||
|
if cfg.Server.Port != 7999 {
|
||||||
|
t.Errorf("Server.Port = %d, want 7999 aus TOML", cfg.Server.Port)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("TALK_PORT schlägt Datei", func(t *testing.T) {
|
||||||
|
cfg, err := Load(Options{
|
||||||
|
File: writeTOML(t, "[server]\nport = 7999\n"),
|
||||||
|
Getenv: env(map[string]string{"TALK_PORT": "7912"}),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Load: %v", err)
|
||||||
|
}
|
||||||
|
if cfg.Server.Port != 7912 {
|
||||||
|
t.Errorf("Server.Port = %d, want Env-Override 7912", cfg.Server.Port)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ungültiger TALK_PORT-Wert ist klarer Fehler", func(t *testing.T) {
|
||||||
|
for _, bad := range []string{"null", "0", "-1", "70000"} {
|
||||||
|
_, err := Load(Options{
|
||||||
|
File: filepath.Join(t.TempDir(), "gibt-es-nicht.toml"),
|
||||||
|
Getenv: env(map[string]string{"TALK_PORT": bad}),
|
||||||
|
})
|
||||||
|
if err == nil || !strings.Contains(err.Error(), "TALK_PORT") {
|
||||||
|
t.Fatalf("TALK_PORT=%q: Fehler = %v, will klaren TALK_PORT-Fehler", bad, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in new issue
Block a user