package main import ( "bufio" "crypto/rand" "fmt" "os" "strconv" "strings" ) type agentCfg struct { BailianBaseURL string BailianWssBaseURL string BailianKey string TTSModel string TTSVoice string TTSInstruction string VoiceAPIURL string LLMModel string VolcAppKey string // 新版控制台:单凭证 VolcAppID string // 旧版控制台:APP ID + Access Token 两件套 VolcAccessToken string VolcResourceID string } // loadDotEnv 加载简单的 KEY=VALUE / export KEY=VALUE;系统环境变量优先。 func loadDotEnv(path string) error { f, err := os.Open(path) if os.IsNotExist(err) { return nil } if err != nil { return err } defer f.Close() scanner := bufio.NewScanner(f) for lineNo := 1; scanner.Scan(); lineNo++ { line := strings.TrimSpace(strings.TrimPrefix(scanner.Text(), "\ufeff")) if line == "" || strings.HasPrefix(line, "#") { continue } line = strings.TrimSpace(strings.TrimPrefix(line, "export ")) key, value, ok := strings.Cut(line, "=") key, value = strings.TrimSpace(key), strings.TrimSpace(value) if !ok || key == "" { return fmt.Errorf("%s:%d: 无效的 dotenv 配置", path, lineNo) } if len(value) >= 2 && value[0] == value[len(value)-1] { switch value[0] { case '\'': value = value[1 : len(value)-1] case '"': value, err = strconv.Unquote(value) if err != nil { return fmt.Errorf("%s:%d: %w", path, lineNo, err) } } } if _, exists := os.LookupEnv(key); !exists { if err := os.Setenv(key, value); err != nil { return fmt.Errorf("%s:%d: %w", path, lineNo, err) } } } return scanner.Err() } func loadCfg() agentCfg { return agentCfg{ BailianBaseURL: getenv("BAILIAN_BASE_URL", ""), BailianWssBaseURL: getenv("BAILIAN_WSS_BASE_URL", ""), BailianKey: getenv("BAILIAN_API_KEY", ""), TTSModel: getenv("BAILIAN_TTS_MODEL", "cosyvoice-v3.5-plus"), TTSVoice: getenv("BAILIAN_TTS_VOICE", ""), TTSInstruction: getenv("BAILIAN_TTS_INSTRUCTION", ""), VoiceAPIURL: getenv("BAILIAN_VOICE_API_URL", "https://dashscope.aliyuncs.com/api/v1/services/audio/tts/customization"), LLMModel: getenv("BAILIAN_LLM_MODEL", "qwen3.8-flash"), VolcAppKey: getenv("VOLC_ASR_APP_KEY", ""), VolcAppID: getenv("VOLC_ASR_APP_ID", ""), VolcAccessToken: getenv("VOLC_ASR_ACCESS_TOKEN", ""), VolcResourceID: getenv("VOLC_ASR_RESOURCE_ID", "volc.bigasr.sauc.duration"), } } func getenv(k, def string) string { if v := os.Getenv(k); v != "" { return v } return def } func uuid() string { var b [16]byte rand.Read(b[:]) b[6] = (b[6] & 0x0f) | 0x40 b[8] = (b[8] & 0x3f) | 0x80 return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:16]) }