package main import ( "context" "html/template" "net/http" "os" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" ) // TemplateWrapper adapts html/template.Template to TemplateExecutor // (implements Execute(http.ResponseWriter, interface{}) error) type TemplateWrapper struct { Tmpl *template.Template } func (tw *TemplateWrapper) Execute(wr http.ResponseWriter, data interface{}) error { return tw.Tmpl.Execute(wr, data) } func main() { logrus.SetFormatter(&logrus.TextFormatter{FullTimestamp: true}) logrus.SetLevel(logrus.InfoLevel) if err := loadConfig("config.yaml"); err != nil { logrus.Fatalf("Failed to load config.yaml: %v", err) } logrus.Infof("Loaded config: %+v", appConfig) visitDB := NewVisitDB() if err := loadUITemplate("ui.html"); err != nil { logrus.Fatalf("Failed to load ui.html: %v", err) } if err := loadDBEditTemplate("ui_dbedit.html"); err != nil { logrus.Fatalf("Failed to load ui_dbedit.html: %v", err) } if err := loadAdminChatsTemplate("ui_admin_chats.html"); err != nil { logrus.Fatalf("Failed to load ui_admin_chats.html: %v", err) } // Initialize PostgreSQL repository first dsn := buildDefaultDSN() logrus.Info("Connecting to PostgreSQL with DSN: ", dsn) repo, err := NewPGChatRepository(context.Background(), dsn) if err != nil { logrus.WithError(err).Warn("PostgreSQL repository disabled (connection failed)") } else if repo == nil { logrus.Info("PostgreSQL repository not configured (no DSN)") } // defer repo.Close() // optionally enable // Initialize LLM client llmClient := NewLLMClient( os.Getenv("OPENAI_API_KEY"), os.Getenv("OPENAI_BASE_URL"), os.Getenv("OPENAI_MODEL"), repo, ) var llm LLMClientAPI = llmClient // Wrap templates for controller uiTmpl := &TemplateWrapper{Tmpl: uiTemplate} uiDBEditTmpl := &TemplateWrapper{Tmpl: uiDBEditTemplate} uiAdminChatsTmpl := &TemplateWrapper{Tmpl: uiAdminChatsTemplate} // Create controller ctrl := NewController( repo, llm, &visitDB, uiTmpl, uiDBEditTmpl, uiAdminChatsTmpl, ) r := gin.Default() // Routes r.GET("/", ctrl.RootUI) r.GET("/health", ctrl.Health) r.POST("/chat", ctrl.HandleChat) r.GET("/admin", ctrl.AdminUI) r.GET("/db.yaml", ctrl.DownloadDB) // KnowledgeModel endpoints (replaces snapshot) r.POST("/admin/chats/snapshot", ctrl.SaveKnowledgeModel) r.GET("/admin/chats/snapshots", ctrl.ListKnowledgeModels) r.GET("/admin/chats/snapshot/:id", ctrl.GetKnowledgeModel) // Chat interactions and events r.GET("/admin/chats", ctrl.ListChatInteractions) r.GET("/admin/chats/events", ctrl.ListLLMEvents) r.GET("/admin/chats/ui", ctrl.AdminChatsUI) r.Run(":8080") }