| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- package agentmcp
- import (
- "context"
- "fmt"
- "os"
- "path/filepath"
- "github.com/spf13/viper"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
- "fwh-toolbox-server/cache"
- "fwh-toolbox-server/config"
- "fwh-toolbox-server/database"
- "fwh-toolbox-server/logger"
- "fwh-toolbox-server/repositories"
- )
- // Settings fwh-agent-mcp 自身的运行配置(AGENT_MCP_*),与主服务读取同一份 .env。
- type Settings struct {
- Token string // AGENT_MCP_TOKEN:Bearer 令牌,必填
- Listen string // AGENT_MCP_LISTEN:默认 127.0.0.1:8091
- MaxConcurrency int // AGENT_MCP_MAX_CONCURRENCY:默认 8
- LogPath string // AGENT_MCP_LOG_PATH:默认 /var/log/fwh-agent-mcp/agent-mcp.log
- }
- // LoadSettings 读取 AGENT_MCP_*:先读 .env / config.env(与 config.LoadConfig 相同的查找顺序),环境变量优先。
- func LoadSettings() Settings {
- v := viper.New()
- v.SetDefault("AGENT_MCP_LISTEN", "127.0.0.1:8091")
- v.SetDefault("AGENT_MCP_MAX_CONCURRENCY", 8)
- v.SetDefault("AGENT_MCP_LOG_PATH", "/var/log/fwh-agent-mcp/agent-mcp.log")
- for _, p := range []string{"./.env", "./config.env"} {
- v.SetConfigFile(p)
- v.SetConfigType("env")
- if err := v.ReadInConfig(); err == nil {
- break
- }
- }
- v.AutomaticEnv()
- return Settings{
- Token: v.GetString("AGENT_MCP_TOKEN"),
- Listen: v.GetString("AGENT_MCP_LISTEN"),
- MaxConcurrency: v.GetInt("AGENT_MCP_MAX_CONCURRENCY"),
- LogPath: v.GetString("AGENT_MCP_LOG_PATH"),
- }
- }
- // InitLogger 初始化日志:写入独立的日志文件;目录不可写时退回 stderr。
- // 同时设置 zap 全局 logger 与 logger 包变量(database 等模块直接引用 logger.Sugar)。
- func InitLogger(path string) *zap.Logger {
- outputs := []string{"stderr"}
- if path != "" {
- if err := os.MkdirAll(filepath.Dir(path), 0o755); err == nil {
- outputs = []string{path}
- } else {
- fmt.Fprintf(os.Stderr, "[fwh-agent-mcp] 创建日志目录失败,改为输出到 stderr: %v\n", err)
- }
- }
- cfg := zap.Config{
- Level: zap.NewAtomicLevelAt(zap.InfoLevel),
- Encoding: "json",
- EncoderConfig: zapcore.EncoderConfig{
- TimeKey: "ts",
- LevelKey: "level",
- NameKey: "logger",
- CallerKey: "caller",
- MessageKey: "msg",
- StacktraceKey: "stacktrace",
- LineEnding: zapcore.DefaultLineEnding,
- EncodeLevel: zapcore.LowercaseLevelEncoder,
- EncodeTime: zapcore.ISO8601TimeEncoder,
- EncodeDuration: zapcore.SecondsDurationEncoder,
- EncodeCaller: zapcore.ShortCallerEncoder,
- },
- OutputPaths: outputs,
- ErrorOutputPaths: outputs,
- }
- l, err := cfg.Build(zap.AddStacktrace(zap.ErrorLevel))
- if err != nil {
- fmt.Fprintf(os.Stderr, "[fwh-agent-mcp] logger 初始化失败: %v\n", err)
- l = zap.NewNop()
- }
- zap.ReplaceGlobals(l)
- logger.Log = l
- logger.Sugar = l.Sugar()
- logger.Std = zap.NewStdLog(l)
- return l
- }
- // InitInfra 加载主服务配置并初始化工具用到的基础设施:数据库、Redis、FWH 生产/测试 API、Plane。
- func InitInfra() error {
- cfg, err := config.LoadConfig()
- if err != nil {
- return fmt.Errorf("加载配置失败: %w", err)
- }
- if err := database.Init(&cfg.App); err != nil {
- return fmt.Errorf("数据库初始化失败: %w", err)
- }
- cache.Init(cfg.App.RedisAddr)
- if err := repositories.Init(context.Background()); err != nil {
- return fmt.Errorf("Repository 初始化失败: %w", err)
- }
- repositories.FwhHttpInit(&cfg.FwhApi)
- repositories.FwhTestHttpInit(&cfg.FwhTestApi)
- // 必须用 InitPlane(含 Feedback 专用实例 repositories.Plane),否则 feedback_create 会空指针
- repositories.InitPlane(&cfg.PlaneWebApi)
- return nil
- }
|