feat(handler,cmd): 实现阶段 5 HTTP 服务 — 处理器、入口程序、配置文件
This commit is contained in:
@@ -1,5 +1,111 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"ai-agent-scaffold-go/internal/config"
|
||||
"ai-agent-scaffold-go/internal/handler"
|
||||
"ai-agent-scaffold-go/internal/model"
|
||||
"ai-agent-scaffold-go/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/joho/godotenv"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// TODO: 实现启动逻辑
|
||||
envPath := flag.String("env", ".env", "path to dotenv file (empty to skip)")
|
||||
configPath := flag.String("config", "configs/application.yaml", "path to application.yaml")
|
||||
flag.Parse()
|
||||
|
||||
// 1. 加载 .env 文件
|
||||
loadDotenv(*envPath)
|
||||
|
||||
// 2. 加载应用配置
|
||||
appCfg, err := config.LoadApplication(*configPath)
|
||||
if err != nil {
|
||||
log.Fatalf("load config: %v", err)
|
||||
}
|
||||
|
||||
// 3. 初始化日志
|
||||
logger, _ := zap.NewProduction()
|
||||
if appCfg.App.Env == "local" || appCfg.App.Env == "dev" {
|
||||
logger, _ = zap.NewDevelopment()
|
||||
}
|
||||
defer logger.Sync()
|
||||
|
||||
// 4. 组装 Agent
|
||||
registry := model.NewInMemoryAgentRegistry()
|
||||
sessions := model.NewInMemorySessionStore()
|
||||
|
||||
timeout, _ := appCfg.LLM.RequestTimeoutDuration()
|
||||
agents, err := service.LoadAndAssemble(context.Background(), appCfg.Agent.ConfigPaths, timeout)
|
||||
if err != nil {
|
||||
logger.Fatal("assemble agents failed", zap.Error(err))
|
||||
}
|
||||
for _, agent := range agents {
|
||||
if err := registry.Register(agent); err != nil {
|
||||
logger.Fatal("register agent failed", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
chatService := service.NewChatService(registry, sessions)
|
||||
|
||||
// 5. 配置 HTTP 路由
|
||||
router := gin.Default()
|
||||
router.Use(corsMiddleware())
|
||||
router.GET("/healthz", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{"status": "ok"})
|
||||
})
|
||||
handler.RegisterRoutes(router, chatService)
|
||||
|
||||
// 6. 启动服务
|
||||
addr := appCfg.Server.Addr
|
||||
logger.Info("server starting", zap.String("addr", addr), zap.Int("agents", len(agents)))
|
||||
if err := router.Run(addr); err != nil {
|
||||
logger.Fatal("server stopped", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
// corsMiddleware 跨域中间件
|
||||
func corsMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
origin := c.GetHeader("Origin")
|
||||
if origin != "" {
|
||||
c.Header("Access-Control-Allow-Origin", origin)
|
||||
c.Header("Vary", "Origin")
|
||||
} else {
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
}
|
||||
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||||
c.Header("Access-Control-Allow-Credentials", "true")
|
||||
if c.Request.Method == "OPTIONS" {
|
||||
c.AbortWithStatus(204)
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// loadDotenv 加载 dotenv 文件,已有环境变量不会被覆盖
|
||||
func loadDotenv(path string) {
|
||||
if path == "" {
|
||||
return
|
||||
}
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
pairs, err := godotenv.Read(path)
|
||||
if err != nil {
|
||||
log.Fatalf("read dotenv: %v", err)
|
||||
}
|
||||
for key, value := range pairs {
|
||||
if _, exists := os.LookupEnv(key); !exists {
|
||||
os.Setenv(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user