Usability-Schicht für Nutzer, die kein Terminal-Handbuch lesen wollen: - `talk doctor`: eine Zeile je Prüfpunkt mit klarem Satz, was Sache ist und was zu tun wäre — Config (kaputt → ✘, die übrigen Prüfungen laufen mit Defaults weiter), Daemon (läuft / startet beim nächsten Sprechbefehl / fremder Dienst auf dem Port → ✘ mit Port-Hinweis), Audio (oto-Kontext wirklich initialisieren; null → ⚠), jede Provider-Stufe (Key-Env-Name, Endpunkt, Default-Stimme; OS-Stimme nennt den gefundenen Mechanismus), Mute (an → ⚠ mit unmute-Hinweis), Gesetze inkl. gerade aktiver Ruhezeit. --probe macht echte Synthese-Proben, --json liefert die Liste. Exit 0 ohne ✘. Windows-Konsolen bekommen [OK]/[WARN]/[FAIL]. - `talk test`: Testsatz direkt über den Sprech-Kern (nicht über den Daemon), nennt die Stufe, die wirklich gesprochen hat, Synthese- und Wiedergabezeit; Mute/Ruhezeit gelten bewusst nicht, Mute wird genannt. - `talk voices`: kuratierter Katalog mit Namen (ElevenLabs-Premade, OpenAI, Edge-Neural de/en-Locales) als Tabelle, „*“ = effektive Default-Stimme (Config vor Repo-Default), Config-IDs außerhalb des Katalogs als eigene Zeile, Filter --provider/--lang, --json. - `talk setup`: wenige Fragen statt Bubble Tea — Keys nur als Hinweis (ohne Key läuft die Edge-Stimme), Stimme je Sprache aus dem Katalog mit Probehören, Ruhezeit; schreibt die config.toml zusammengeführt mit bestehenden Werten (.bak), spricht einen Testsatz. q bricht ab, bevor etwas geschrieben wird; ohne Terminal keine Fragen, nur die wirksame Konfiguration. Unterbau: provider.Catalog/VoiceName/DefaultVoice, Chain.SpeakOutcome (Stufe, Bytes, Zeiten) durch speak.Engine bis in Daemon-Log und test, audio.Check (oto-Initialisierung ohne Ton), config.Path, OSBuiltin.Describe. README: Abschnitt „Erste Schritte“. Tests: voices-Zeilen (Default-Markierung, Config-Override, Filter, JSON), doctor (ohne Daemon, Mute/Key via JSON, fremder Dienst → Exit 1, kaputte Config → ✘ aber vollständiger Bericht), test (fake espeak), setup (stdin-Antworten → config.toml-Inhalt, Merge mit .bak, Abbruch schreibt nichts, Pipe stellt keine Fragen), Prozessgrenze: doctor/--probe/voices/ test gegen echten Daemon. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
67 lines
2.0 KiB
Go
67 lines
2.0 KiB
Go
package config
|
|
|
|
import (
|
|
"errors"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
// fileName ist der Name der Config-Datei im Config-Verzeichnis.
|
|
const fileName = "config.toml"
|
|
|
|
// ErrNoHome meldet, dass das Heimatverzeichnis nicht bestimmt werden kann
|
|
// (keine HOME- bzw. APPDATA-Umgebungsvariable).
|
|
var ErrNoHome = errors.New("Config-Verzeichnis nicht bestimmbar (HOME bzw. APPDATA fehlt)")
|
|
|
|
// Dir liefert das platform-native Config-Verzeichnis von talk auf dem
|
|
// aktuellen System: Linux ~/.config/talk (respektive $XDG_CONFIG_HOME/talk),
|
|
// macOS ~/Library/Application Support/talk, Windows %APPDATA%\talk.
|
|
func Dir(getenv func(string) string) (string, error) {
|
|
return dirFor(runtime.GOOS, getenv)
|
|
}
|
|
|
|
// dirFor ist die testbare Plattformlogik hinter Dir: goos wird als
|
|
// Parameter übergeben, damit die Pfade für alle Betriebssysteme vom
|
|
// Dev-Host aus tischgesteuert geprüft werden können.
|
|
//
|
|
// XDG_CONFIG_HOME wird nur berücksichtigt, wenn es einen absoluten Pfad
|
|
// enthält (XDG-Spezifikation); relative Werte werden ignoriert.
|
|
func dirFor(goos string, getenv func(string) string) (string, error) {
|
|
if getenv == nil {
|
|
return "", ErrNoHome
|
|
}
|
|
switch goos {
|
|
case "windows":
|
|
appdata := getenv("APPDATA")
|
|
if appdata == "" {
|
|
return "", ErrNoHome
|
|
}
|
|
return filepath.Join(appdata, "talk"), nil
|
|
case "darwin":
|
|
home := getenv("HOME")
|
|
if home == "" {
|
|
return "", ErrNoHome
|
|
}
|
|
return filepath.Join(home, "Library", "Application Support", "talk"), nil
|
|
default: // linux und sonstige unixartige Systeme
|
|
if xdg := getenv("XDG_CONFIG_HOME"); xdg != "" && filepath.IsAbs(xdg) {
|
|
return filepath.Join(xdg, "talk"), nil
|
|
}
|
|
home := getenv("HOME")
|
|
if home == "" {
|
|
return "", ErrNoHome
|
|
}
|
|
return filepath.Join(home, ".config", "talk"), nil
|
|
}
|
|
}
|
|
|
|
// Path liefert den vollständigen Pfad der config.toml im platform-nativen
|
|
// Config-Verzeichnis (Diagnose, Setup-Wizard).
|
|
func Path(getenv func(string) string) (string, error) {
|
|
dir, err := Dir(getenv)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return filepath.Join(dir, fileName), nil
|
|
}
|