package main import ( "context" "log" "git.x2erp.com/qdy/go-base/config" "git.x2erp.com/qdy/go-base/container" "git.x2erp.com/qdy/go-base/graceful" "git.x2erp.com/qdy/go-base/logger" "git.x2erp.com/qdy/go-base/sdk/configure" "git.x2erp.com/qdy/go-base/webx" "git.x2erp.com/qdy/go-base/webx/health" "git.x2erp.com/qdy/go-base/webx/router" "git.x2erp.com/qdy/go-db/factory/mongodb" "git.x2erp.com/qdy/go-svc-code/internal/opencode" "git.x2erp.com/qdy/go-svc-code/internal/routes" "git.x2erp.com/qdy/go-svc-code/internal/service/event" "git.x2erp.com/qdy/go-svc-code/internal/service/menu" ) var ( appName = "svc-code" appVersion = "1" ) // 全局变量存储 opencode 进程信息 var ( //opencodeProcess *opencode.Process opencodePort int //opencodeMutex sync.Mutex ) func main() { // 0. 初始化启动日志 logBootFactory := logger.InitBootLog() // 1. 获取配置文件 cfg := config.GetConfig() cfg.SetAppName(appName) cfg.SetAppVersion(appVersion) // 2. 创建关闭容器 ctr := container.NewContainer(cfg) // 注册日志,实现自动关闭 container.Reg(ctr, logBootFactory) // 3. 启用运行日志(需要在启动 opencode 服务之前) container.Create(ctr, logger.InitRuntimeLogger) // 创建mongodb mongoDBFactory := container.Create(ctr, mongodb.CreateFactory) mongoDBFactory.TestConnection() // 创建会话-菜单映射服务 mappingService := menu.NewMappingService(mongoDBFactory) // 确保索引存在 ctx := context.Background() if err := mappingService.EnsureIndexes(ctx); err != nil { log.Printf("警告:创建会话-菜单映射索引失败: %v", err) } else { log.Printf("会话-菜单映射索引确保成功") } // 4. 创建 configure 客户端 configClient, err := configure.NewClient() if err != nil { log.Fatalf("创建 configure 客户端失败: %v", err) } // 5. 创建 opencode 客户端(使用 DirectClient,连接外部 opencode 服务) opencodePort = opencode.DefaultOpenCodePort client, err := opencode.NewDirectClient(opencodePort) if err != nil { log.Fatalf("创建 opencode 客户端失败: %v", err) } log.Printf("opencode 客户端已创建,连接端口: %d", opencodePort) // 启动事件分发器(用于多用户流式对话隔离) dispatcher := event.GetEventDispatcher(client.GetBaseURL(), client.GetPort()) if err := dispatcher.Start(context.Background()); err != nil { log.Printf("警告:事件分发器启动失败(流式功能可能受影响): %v", err) } else { log.Printf("事件分发器已启动") defer dispatcher.Stop() } // 初始化订阅服务单例(暂时注释,使用简单回调方案) // event.InitSubscriptionService(dispatcher, mongoDBFactory) // log.Printf("订阅服务单例已初始化") // 6. 得到 webservice 服务工厂 webxFactory := webx.GetWebServiceFactory() // 7. 建立 httpService 服务 webService, err := webxFactory.CreateService(cfg.GetServiceConfig()) if err != nil { log.Fatalf("创建 HTTP 服务失败: %v", err) } // 8. 建立路由-api routerService := router.NewWebService(webService.GetRouter()) // 注册健康检查-api health.RegisterConsulHealthCheck(routerService) // 9. 注册路由--api registerRoutes(routerService, webService, configClient, client, nil, opencodePort, mappingService) // 9. 注册前端静态文件服务 //registerStaticFiles(webService) // 10. 启动服务 webService.Run() // 11. 启用运行日志 container.Create(ctr, logger.InitRuntimeLogger) // 12. 等待关闭 graceful.WaitForShutdown(cfg.GetServiceConfig().ServiceName, ctr, webService.GetServer()) } // registerRoutes 注册所有 API 路由 func registerRoutes(ws *router.RouterService, webService *webx.WebService, configClient *configure.Client, client opencode.OpenCodeClient, opencodeProcess *opencode.Process, opencodePort int, mappingService *menu.MappingService) { // 认证路由(公开登录接口) routes.RegisterAuthRoutes(ws, configClient) // 会话管理路由 routes.RegisterSessionRoutes(ws, client, mappingService) // 同步对话路由 routes.RegisterPromptSyncRoutes(ws, client) // 流式对话路由(需要直接 HTTP 处理器) routes.RegisterPromptStreamRoutes(ws, webService, client) // 日志流路由(需要直接 HTTP 处理器) routes.RegisterLogStreamRoutes(ws, webService, opencodeProcess, opencodePort) // 会话消息路由 routes.RegisterSessionMessagesRoutes(ws, client) // 菜单路由 routes.RegisterMenuRoutes(ws, mappingService) }