feat: add download features to llm models

This commit is contained in:
2026-04-20 22:50:16 +02:00
parent 351dd3b608
commit 6274b4a0b8
11 changed files with 910 additions and 237 deletions

View File

@ -1,6 +1,7 @@
package handlers
import (
"context"
"fmt"
"net/http"
@ -330,6 +331,118 @@ func (h *Handler) GetDefaultSystemPrompt(c *gin.Context) {
httputil.OK(c, gin.H{"prompt": ai.DefaultSystemPrompt})
}
// ── AI Roles ───────────────────────────────────────────────────────────────
func (h *Handler) GetAIRoles(c *gin.Context) {
roles := []string{"summary", "report", "filter"}
resp := gin.H{}
for _, role := range roles {
providerID, _ := h.repo.GetSetting("ai_role_" + role + "_provider")
model, _ := h.repo.GetSetting("ai_role_" + role + "_model")
resp[role] = gin.H{"provider_id": providerID, "model": model}
}
httputil.OK(c, resp)
}
type updateAIRoleRequest struct {
ProviderID string `json:"provider_id"`
Model string `json:"model"`
}
func (h *Handler) UpdateAIRole(c *gin.Context) {
role := c.Param("role")
if role != "summary" && role != "report" && role != "filter" {
httputil.BadRequest(c, fmt.Errorf("invalid role: must be summary, report, or filter"))
return
}
var req updateAIRoleRequest
if err := c.ShouldBindJSON(&req); err != nil {
httputil.BadRequest(c, err)
return
}
if err := h.repo.SetRoleProvider(role, req.ProviderID, req.Model); err != nil {
httputil.InternalError(c, err)
return
}
httputil.OK(c, gin.H{"ok": true})
}
// ── Ollama Model Management ────────────────────────────────────────────────
func (h *Handler) getOllamaManager() (*ai.OllamaProvider, error) {
providers, err := h.repo.ListAIProviders()
if err != nil {
return nil, err
}
endpoint := ""
for _, p := range providers {
if p.Name == "ollama" {
endpoint = p.Endpoint
break
}
}
if endpoint == "" {
endpoint = "http://ollama:11434"
}
return ai.NewOllamaManager(endpoint), nil
}
func (h *Handler) ListOllamaModels(c *gin.Context) {
mgr, err := h.getOllamaManager()
if err != nil {
httputil.InternalError(c, err)
return
}
models, err := mgr.ListModelsDetailed(c.Request.Context())
if err != nil {
httputil.InternalError(c, err)
return
}
if models == nil {
models = []ai.OllamaModelInfo{}
}
httputil.OK(c, models)
}
type pullModelRequest struct {
Name string `json:"name" binding:"required"`
}
func (h *Handler) PullOllamaModel(c *gin.Context) {
var req pullModelRequest
if err := c.ShouldBindJSON(&req); err != nil {
httputil.BadRequest(c, err)
return
}
mgr, err := h.getOllamaManager()
if err != nil {
httputil.InternalError(c, err)
return
}
go func() {
if err := mgr.PullModel(context.Background(), req.Name); err != nil {
fmt.Printf("[ollama] pull %s failed: %v\n", req.Name, err)
} else {
fmt.Printf("[ollama] pull %s completed\n", req.Name)
}
}()
c.JSON(202, gin.H{"ok": true, "message": "pull started"})
}
func (h *Handler) DeleteOllamaModel(c *gin.Context) {
name := c.Param("name")
mgr, err := h.getOllamaManager()
if err != nil {
httputil.InternalError(c, err)
return
}
if err := mgr.DeleteModel(c.Request.Context(), name); err != nil {
httputil.InternalError(c, err)
return
}
httputil.NoContent(c)
}
// ── Admin Users ────────────────────────────────────────────────────────────
func (h *Handler) ListUsers(c *gin.Context) {