187 lines
4.8 KiB
Go
187 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func registerAdminLLMRoutes(r *gin.RouterGroup, store *store) {
|
|
group := r.Group("/llm")
|
|
{
|
|
group.GET("/messages", handleListLLMMessages(store))
|
|
group.GET("/messages/:id", handleGetLLMMessage(store))
|
|
group.PUT("/messages/:id/status", handleUpdateLLMMessageStatus(store))
|
|
group.DELETE("/messages/:id", handleDeleteLLMMessage(store))
|
|
group.DELETE("/bots/:bot_id/messages", handleDeleteLLMMessagesByBot(store))
|
|
group.POST("/messages/cleanup", handleCleanupDeletedLLMMessages(store))
|
|
}
|
|
}
|
|
|
|
func handleListLLMMessages(store *store) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
opts, ok := parseListOptions(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
var botID uint64
|
|
if botIDStr := c.Query("bot_id"); botIDStr != "" {
|
|
id, err := strconv.ParseUint(botIDStr, 10, 64)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid bot_id"})
|
|
return
|
|
}
|
|
botID = id
|
|
}
|
|
|
|
includeDeleted := c.Query("include_deleted") == "true"
|
|
|
|
rows, total, err := store.ListLLMMessages(opts, botID, includeDeleted)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
items := make([]map[string]any, 0, len(rows))
|
|
for _, row := range rows {
|
|
items = append(items, llmMessageDTO(row))
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"items": items,
|
|
"limit": opts.Limit,
|
|
"offset": opts.Offset,
|
|
"total": total,
|
|
})
|
|
}
|
|
}
|
|
|
|
func handleGetLLMMessage(store *store) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil || id == 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid message id"})
|
|
return
|
|
}
|
|
|
|
record, err := store.GetLLMMessage(id)
|
|
if err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "message not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"item": llmMessageDTO(*record)})
|
|
}
|
|
}
|
|
|
|
func handleUpdateLLMMessageStatus(store *store) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil || id == 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid message id"})
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Status string `json:"status"`
|
|
Error string `json:"error"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
|
|
return
|
|
}
|
|
|
|
// 验证状态值
|
|
validStatus := map[string]bool{
|
|
llmMessageStatusPending: true,
|
|
llmMessageStatusProcessing: true,
|
|
llmMessageStatusProcessed: true,
|
|
llmMessageStatusError: true,
|
|
}
|
|
if !validStatus[req.Status] {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid status value"})
|
|
return
|
|
}
|
|
|
|
if err := store.UpdateLLMMessageStatus(id, req.Status, req.Error); err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "message not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
}
|
|
}
|
|
|
|
func handleDeleteLLMMessage(store *store) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil || id == 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid message id"})
|
|
return
|
|
}
|
|
|
|
if err := store.SoftDeleteLLMMessage(id); err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "message not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
}
|
|
}
|
|
|
|
func handleDeleteLLMMessagesByBot(store *store) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
botID, err := strconv.ParseUint(c.Param("bot_id"), 10, 64)
|
|
if err != nil || botID == 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid bot id"})
|
|
return
|
|
}
|
|
|
|
if err := store.SoftDeleteLLMMessagesByBot(botID); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
}
|
|
}
|
|
|
|
func handleCleanupDeletedLLMMessages(store *store) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
var req struct {
|
|
Days int `json:"days"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
req.Days = 7 // 默认清理 7 天前删除的消息
|
|
}
|
|
if req.Days <= 0 {
|
|
req.Days = 7
|
|
}
|
|
|
|
before := time.Now().AddDate(0, 0, -req.Days)
|
|
count, err := store.CleanupDeletedLLMMessages(before)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"status": "ok", "deleted_count": count})
|
|
}
|
|
}
|