- 将 wechat_official_account 重命名为 weixin_public_account,符合中文命名规范 - 新增 DOCX 文档生成技能、聊天历史、请求 ID 中间件 - 增强工作流、热点服务、文章服务等模块功能 - 前端同步重命名组件和 API - 新增架构文档 AR13/AR14、专员文档更新 - 补充测试用例(seed_specialists_test, db_migration_test) Co-Authored-AI: yes
106 lines
3.0 KiB
Go
106 lines
3.0 KiB
Go
package main
|
||
|
||
import (
|
||
"log"
|
||
"os"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
|
||
"eai_agentplatform/backend/internal/api"
|
||
"eai_agentplatform/backend/internal/auth"
|
||
"eai_agentplatform/backend/internal/config"
|
||
"eai_agentplatform/backend/internal/dal"
|
||
"eai_agentplatform/backend/internal/model"
|
||
specialistseeding "eai_agentplatform/backend/internal/specialists/seeding"
|
||
"eai_agentplatform/backend/internal/store"
|
||
)
|
||
|
||
func main() {
|
||
// 交付维护子命令(不进服务主流程)
|
||
if len(os.Args) > 1 {
|
||
switch os.Args[1] {
|
||
case "-reset-admin":
|
||
resetAdmin(os.Args[2:])
|
||
return
|
||
case "-backup":
|
||
backupOnce()
|
||
return
|
||
}
|
||
}
|
||
|
||
cfg := config.Load()
|
||
|
||
// 启动前校验 AI 路由配置:若 ai_config.json 不可解析或默认路由无效,
|
||
// 立刻失败而不是等用户聊天时才爆"AI 模型不可用"。
|
||
if err := config.ValidateAIConfig(); err != nil {
|
||
log.Fatalf("AI 路由配置校验失败(请检查 config/ai_config.json): %v", err)
|
||
}
|
||
|
||
db, err := store.Init(cfg.DBPath)
|
||
if err != nil {
|
||
log.Fatalf("数据库初始化失败: %v", err)
|
||
}
|
||
dal.SetDB(db)
|
||
if err := store.SeedDefaults(); err != nil {
|
||
log.Fatalf("种子数据初始化失败: %v", err)
|
||
}
|
||
if err := specialistseeding.SeedSpecialists(store.DB); err != nil {
|
||
log.Fatalf("专员目录种子初始化失败: %v", err)
|
||
}
|
||
|
||
config.StartAIRouteHealthLoop(30 * time.Minute)
|
||
|
||
// 定期备份:SQLite 是单文件且无外部副本,坏一份就是全丢。
|
||
// 失败只在日志里报,绝不因此拦下服务。
|
||
if cfg.BackupEnabled {
|
||
store.StartBackupLoop(store.DB, cfg.DBPath, cfg.BackupDir, cfg.BackupKeep, cfg.BackupIntervalHours)
|
||
}
|
||
|
||
r := gin.Default()
|
||
|
||
api.RegisterRoutes(r, cfg)
|
||
|
||
log.Printf("eai_agentplatform 后端启动,端口 :%s", cfg.Port)
|
||
if err := r.Run(":" + cfg.Port); err != nil {
|
||
log.Fatalf("启动失败: %v", err)
|
||
}
|
||
}
|
||
|
||
// backupOnce 手工备份一次后退出:eai_agentplatform-server -backup
|
||
// 用于升级/迁移/交付前留一份手边的副本,比等定期那份更让人放心。
|
||
func backupOnce() {
|
||
cfg := config.Load()
|
||
db, err := store.Init(cfg.DBPath)
|
||
if err != nil {
|
||
log.Fatalf("数据库初始化失败: %v", err)
|
||
}
|
||
dal.SetDB(db)
|
||
path, err := store.Backup(store.DB, cfg.BackupDir, cfg.BackupKeep, time.Now())
|
||
if err != nil {
|
||
log.Fatalf("备份失败: %v", err)
|
||
}
|
||
log.Printf("[OK] 已备份到 %s", path)
|
||
}
|
||
|
||
// resetAdmin 交付前重置管理员密码:eai_agentplatform-server -reset-admin <新密码>
|
||
func resetAdmin(args []string) {
|
||
if len(args) < 1 || args[0] == "" {
|
||
log.Fatal("用法: eai_agentplatform-server -reset-admin <新密码>")
|
||
}
|
||
cfg := config.Load()
|
||
db, err := store.Init(cfg.DBPath)
|
||
if err != nil {
|
||
log.Fatalf("数据库初始化失败: %v", err)
|
||
}
|
||
dal.SetDB(db)
|
||
hash, err := auth.HashPassword(args[0])
|
||
if err != nil {
|
||
log.Fatalf("密码加密失败: %v", err)
|
||
}
|
||
if err := store.DB.Model(&model.User{}).Where("username = ?", "admin").Update("password_hash", hash).Error; err != nil {
|
||
log.Fatalf("重置密码失败: %v", err)
|
||
}
|
||
log.Println("[OK] 管理员密码已重置")
|
||
}
|