Files
meshtastic_mqtt_server/admin_llm_routes.go
T
2026-06-17 20:18:37 +08:00

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})
}
}