Merge pull request 'fix: 修复 deploy 工作流缺少 Node.js 导致 checkout 失败的问题' #72

Merged
huanghaosheng merged 61 commits from develop into main 2026-06-14 14:37:27 +08:00
Showing only changes of commit 63f8cc279d - Show all commits

View File

@@ -22,6 +22,10 @@ import (
"github.com/hhs/camtalk/internal/ws" "github.com/hhs/camtalk/internal/ws"
) )
// Version 通过构建时 -ldflags 注入,如:
// go build -ldflags "-X main.Version=v1.0.0" ./cmd/server
var Version string
var startTime = time.Now() var startTime = time.Now()
func main() { func main() {
@@ -43,7 +47,10 @@ func main() {
// 初始化 Session ManagerMVP 默认内存实现) // 初始化 Session ManagerMVP 默认内存实现)
var sessionMgr session.Manager var sessionMgr session.Manager
// TODO: 当 Redis 配置非空时切换为 RedisManager // TODO: 当 Redis 配置非空时切换为 RedisManager
sessionMgr = session.NewMemoryManager(30*time.Minute, 20) sessionMgr = session.NewMemoryManager(
time.Duration(cfg.Session.TTL)*time.Minute,
cfg.Session.MaxHistory,
)
defer sessionMgr.(*session.MemoryManager).Stop() defer sessionMgr.(*session.MemoryManager).Stop()
// 初始化 AI 服务 // 初始化 AI 服务
@@ -60,27 +67,27 @@ func main() {
var sttService stt.Service var sttService stt.Service
switch strings.ToLower(cfg.AI.STT.Provider) { switch strings.ToLower(cfg.AI.STT.Provider) {
case "mimo", "xiaomi": case "mimo", "xiaomi":
sttService = stt.NewMiMoService(cfg.AI.STT.APIKey, cfg.AI.STT.Model, cfg.AI.STT.Endpoint, logger.Log) sttService = stt.NewMiMoService(cfg.AI.STT.APIKey, cfg.AI.STT.Model, cfg.AI.STT.Endpoint, cfg.AI.STT.Timeout, logger.Log)
logger.Log.Infow("STT service initialized", "provider", "mimo", "model", cfg.AI.STT.Model, "endpoint", cfg.AI.STT.Endpoint) logger.Log.Infow("STT service initialized", "provider", "mimo", "model", cfg.AI.STT.Model, "endpoint", cfg.AI.STT.Endpoint)
default: default:
sttService = stt.NewDeepgramService(cfg.AI.STT.APIKey, cfg.AI.STT.Model, cfg.AI.STT.Endpoint, logger.Log) sttService = stt.NewDeepgramService(cfg.AI.STT.APIKey, cfg.AI.STT.Model, cfg.AI.STT.Endpoint, cfg.AI.STT.Timeout, logger.Log)
logger.Log.Infow("STT service initialized", "provider", "deepgram", "model", cfg.AI.STT.Model) logger.Log.Infow("STT service initialized", "provider", "deepgram", "model", cfg.AI.STT.Model)
} }
llmService := llm.NewOpenAIService(cfg.AI.LLM.APIKey, cfg.AI.LLM.Model, cfg.AI.LLM.Endpoint, cfg.AI.LLM.Timeout, logger.Log) llmService := llm.NewOpenAIService(cfg.AI.LLM.APIKey, cfg.AI.LLM.Model, cfg.AI.LLM.Endpoint, cfg.AI.LLM.Timeout, cfg.AI.LLM.HTTPClientTimeout, logger.Log)
logger.Log.Infow("LLM service initialized", "provider", cfg.AI.LLM.Provider, "model", cfg.AI.LLM.Model, "endpoint", cfg.AI.LLM.Endpoint, "timeout", cfg.AI.LLM.Timeout) logger.Log.Infow("LLM service initialized", "provider", cfg.AI.LLM.Provider, "model", cfg.AI.LLM.Model, "endpoint", cfg.AI.LLM.Endpoint, "timeout", cfg.AI.LLM.Timeout)
var ttsService tts.Service var ttsService tts.Service
switch strings.ToLower(cfg.AI.TTS.Provider) { switch strings.ToLower(cfg.AI.TTS.Provider) {
case "mimo", "xiaomi": case "mimo", "xiaomi":
ttsService = tts.NewMiMoService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Timeout, logger.Log) ttsService = tts.NewMiMoService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Timeout, cfg.AI.TTS.HTTPClientTimeout, logger.Log)
logger.Log.Infow("TTS service initialized", "provider", "mimo", "model", cfg.AI.TTS.Model, "voice", cfg.AI.TTS.Voice, "endpoint", cfg.AI.TTS.Endpoint) logger.Log.Infow("TTS service initialized", "provider", "mimo", "model", cfg.AI.TTS.Model, "voice", cfg.AI.TTS.Voice, "endpoint", cfg.AI.TTS.Endpoint)
default: default:
ttsService = tts.NewOpenAIService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Speed, cfg.AI.TTS.Timeout, logger.Log) ttsService = tts.NewOpenAIService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Speed, cfg.AI.TTS.Timeout, cfg.AI.TTS.HTTPClientTimeout, logger.Log)
logger.Log.Infow("TTS service initialized", "provider", "openai", "model", cfg.AI.TTS.Model, "voice", cfg.AI.TTS.Voice, "speed", cfg.AI.TTS.Speed) logger.Log.Infow("TTS service initialized", "provider", "openai", "model", cfg.AI.TTS.Model, "voice", cfg.AI.TTS.Voice, "speed", cfg.AI.TTS.Speed)
} }
// 初始化 Orchestrator // 初始化 Orchestrator
orch := orchestrator.New(sttService, llmService, ttsService, sessionMgr, cfg.AI.LLM.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Speed) orch := orchestrator.New(sttService, llmService, ttsService, sessionMgr, cfg)
// Gin 模式 // Gin 模式
if cfg.App.Env == "prod" { if cfg.App.Env == "prod" {
@@ -93,7 +100,7 @@ func main() {
// REST API // REST API
apiGroup := r.Group("/api") apiGroup := r.Group("/api")
{ {
apiGroup.GET("/health", healthHandler(sessionMgr)) apiGroup.GET("/health", healthHandler(sessionMgr, cfg))
} }
// Session REST 端点 // Session REST 端点
@@ -101,7 +108,7 @@ func main() {
sessionHandler.RegisterRoutes(apiGroup) sessionHandler.RegisterRoutes(apiGroup)
// WebSocket // WebSocket
r.GET("/ws", ws.ServeWS(sessionMgr, orch)) r.GET("/ws", ws.ServeWS(sessionMgr, orch, cfg))
// HTTP Server // HTTP Server
srv := &http.Server{ srv := &http.Server{
@@ -125,7 +132,7 @@ func main() {
<-ctx.Done() <-ctx.Done()
logger.Log.Info("shutting down...") logger.Log.Info("shutting down...")
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) shutdownCtx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.Server.ShutdownTimeout)*time.Second)
defer cancel() defer cancel()
if err := srv.Shutdown(shutdownCtx); err != nil { if err := srv.Shutdown(shutdownCtx); err != nil {
@@ -135,11 +142,15 @@ func main() {
} }
// healthHandler 健康检查。 // healthHandler 健康检查。
func healthHandler(sessionMgr session.Manager) gin.HandlerFunc { func healthHandler(sessionMgr session.Manager, cfg *config.Config) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
version := Version
if version == "" {
version = cfg.App.Version
}
c.JSON(200, gin.H{ c.JSON(200, gin.H{
"status": "ok", "status": "ok",
"version": "0.1.0", "version": version,
"uptime_seconds": int(time.Since(startTime).Seconds()), "uptime_seconds": int(time.Since(startTime).Seconds()),
"active_sessions": sessionMgr.ActiveCount(), "active_sessions": sessionMgr.ActiveCount(),
}) })