first commit

This commit is contained in:
2026-08-14 23:41:57 +08:00
commit 086803a8dd
471 changed files with 91938 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
package server
import (
"fmt"
"net/http"
"path/filepath"
"time"
"agent/internal/agent"
"github.com/gin-gonic/gin"
)
// NewRouter 组装全部路由:静态资源、会话直达、/api/v1 REST、/ws WebSocket。
// 返回 (gin.Engine, *Server)*Server 供 main.go 在托管模式下调用 StartBenchmark 自动触发评测。
func NewRouter(cfg agent.Config, store *agent.SessionStore, dockerCfg *agent.DockerConfigStore, apiCfg *agent.APIConfigStore) (*gin.Engine, *Server) {
s := &Server{
cfg: cfg,
store: store,
agent: agent.NewAgent(cfg, store, dockerCfg, apiCfg),
dockerCfg: dockerCfg,
apiCfg: apiCfg,
}
gin.SetMode(gin.ReleaseMode)
r := gin.New()
r.Use(gin.Recovery(), requestLogger())
staticDir := filepath.Join(cfg.Workspace, "web", "static")
indexFile := filepath.Join(staticDir, "index.html")
r.Static("/static", staticDir)
r.StaticFile("/", indexFile)
// 会话直达:/<sessionId> 返回前端页面,由前端 JS 从路径解析会话 ID
r.GET("/:sessionId", func(c *gin.Context) {
if !sessionIDPattern.MatchString(c.Param("sessionId")) {
c.Status(http.StatusNotFound)
return
}
c.File(indexFile)
})
v1 := r.Group("/api/v1")
v1.GET("/health", s.health)
// 授权相关接口始终放行:前端据此判断是否需要授权 / 提交授权码。
// 其余 API 与 WebSocket 统一挂 authRequired(未启用授权时自动放行)。
auth := v1.Group("/auth")
auth.GET("/status", s.authStatus)
auth.POST("/login", s.authLogin)
authed := v1.Group("")
authed.Use(s.authRequired)
authed.GET("/config", s.config)
authed.GET("/docker/config", s.dockerConfig)
authed.PUT("/docker/config", s.setDockerConfig)
authed.GET("/llm/config", s.llmConfig)
authed.PUT("/llm/config", s.setLLMConfig)
authed.GET("/sessions", s.listSessions)
authed.POST("/sessions", s.createSession)
authed.GET("/sessions/:id", s.getSession)
authed.GET("/sessions/:id/messages", s.sessionMessages)
authed.DELETE("/sessions/:id", s.deleteSession)
authed.DELETE("/sessions/:id/messages", s.clearSession)
authed.GET("/coop/tasks", s.coopTasks)
// WebSocket 实时通道:Agent 流式输出 / 状态 / 协作通知(同样受授权保护)
r.GET("/ws", s.authRequired, s.ws)
return r, s
}
// requestLogger 轻量请求日志中间件:统一 [http] 前缀,便于与 [coop] 等日志区分。
func requestLogger() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
c.Next()
gin.DefaultWriter.Write([]byte(fmt.Sprintf(
"[http] %s | %s %s | %s | %d\n",
time.Now().Format("2006/01/02 15:04:05"),
c.Request.Method,
c.Request.URL.Path,
time.Since(start).Round(time.Millisecond).String(),
c.Writer.Status(),
)))
}
}