package main import ( cryptorand "crypto/rand" "errors" "fmt" "net/url" "os" "strings" ) // ASR-only subset of the reference configuration. No LLM/TTS fields are imported. type agentCfg struct { BailianKey, BailianWssBaseURL string VolcAppKey, VolcAppID, VolcAccessToken, VolcResourceID, VolcWS string } type config struct { bailianKey, bailianBase, funASRKey, funASRBase string volcAppKey, volcAppID, volcToken, volcResourceID, volcWS string } func env(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback } func loadConfig() config { key := os.Getenv("BAILIAN_API_KEY") return config{ bailianKey: key, bailianBase: env("BAILIAN_WS", "wss://dashscope.aliyuncs.com/api-ws/v1/inference/"), funASRKey: env("FUNASR_API_KEY", key), funASRBase: env("FUNASR_WS", "wss://dashscope.aliyuncs.com/api-ws/v1/inference/"), volcAppKey: os.Getenv("VOLC_APP_KEY"), volcAppID: os.Getenv("VOLC_APP_ID"), volcToken: os.Getenv("VOLC_ACCESS_TOKEN"), volcResourceID: env("VOLC_RESOURCE_ID", "volc.bigasr.sauc.duration"), volcWS: env("VOLC_WS", "wss://openspeech.bytedance.com/api/v3/sauc/bigmodel"), } } func validateConfig(token, origin string, cfg config) error { if len(token) < 32 || strings.HasPrefix(token, "CHANGE_ME") { return errors.New("ASR_WEB_TOKEN must be at least 32 characters and not a placeholder") } for _, r := range token { if !(r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' || r == '-' || r == '_') { return errors.New("ASR_WEB_TOKEN must use URL-safe alphanumeric characters") } } if origin != "" { u, err := url.Parse(origin) if err != nil || (u.Scheme != "https" && u.Scheme != "http") || u.Host == "" || u.User != nil || u.Path != "" || u.RawQuery != "" || u.Fragment != "" { return errors.New("PUBLIC_ORIGIN must be an exact http(s) origin without a path") } } for _, endpoint := range []string{cfg.bailianBase, cfg.funASRBase, cfg.volcWS} { u, err := url.Parse(endpoint) if err != nil || u.Scheme != "wss" || u.Host == "" || u.User != nil { return errors.New("provider endpoints must use wss without embedded credentials") } } return nil } func uuid() (string, error) { b := make([]byte, 16) count, err := cryptorand.Read(b) if err != nil || count != len(b) { return "", errors.New("secure random unavailable") } b[6] = b[6]&15 | 64 b[8] = b[8]&63 | 128 return fmt.Sprintf("%x-%x-%x-%x-%x", b[:4], b[4:6], b[6:8], b[8:10], b[10:]), nil }