diff --git a/.continue/mcpServers/new-mcp-server.yaml b/.continue/mcpServers/new-mcp-server.yaml new file mode 100644 index 0000000..0e32aa6 --- /dev/null +++ b/.continue/mcpServers/new-mcp-server.yaml @@ -0,0 +1,10 @@ +name: New MCP server +version: 0.0.1 +schema: v1 +mcpServers: + - name: New MCP server + command: npx + args: + - -y + - + env: {} diff --git a/app/app.go b/app/app.go index 7403d63..ad5b379 100755 --- a/app/app.go +++ b/app/app.go @@ -33,6 +33,8 @@ func LoadBuiltInMiddlewares(app *config.AppConfig) { } } + + func Location(c *fiber.Ctx) (string, error) { ip := IP(c) _, err := Http.GeoIP.GetLocation(ip) diff --git a/pkg/services/ia.service.go b/pkg/services/ia.service.go new file mode 100644 index 0000000..b7ea73f --- /dev/null +++ b/pkg/services/ia.service.go @@ -0,0 +1,68 @@ +package services + +import ( + "bufio" + "bytes" + "encoding/json" + "net/http" +) + +// DataIa estructura para el request a Ollama +type DataIa struct { + Prompt string `json:"prompt"` + Model string `json:"model"` + Stream bool `json:"stream"` +} + +// respuestaOllama estructura para parsear la respuesta de Ollama +type respuestaOllama struct { + Response string `json:"response"` + Done bool `json:"done"` +} + +// GenerateTextoStream lee respuesta de Ollama en tiempo real y devuelve canal +func GenerateTextoStream(data DataIa) (<-chan string, error) { + out := make(chan string) + + // Convertir datos a JSON + jsonData, err := json.Marshal(data) + if err != nil { + return nil, err + } + + // Crear request con cabecera personalizada + req, err := http.NewRequest("POST", "http://72.60.24.97:8080/ollama/api/generate", bytes.NewBuffer(jsonData)) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", "Bearer sk-43804e00f5294200ad1e599550fbee4f") + + // Ejecutar request + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return nil, err + } + + // Procesar en goroutine + go func() { + defer resp.Body.Close() + defer close(out) + + scanner := bufio.NewScanner(resp.Body) + for scanner.Scan() { + var msg respuestaOllama + if err := json.Unmarshal(scanner.Bytes(), &msg); err == nil { + if msg.Response != "" { + out <- msg.Response + } + if msg.Done { + break + } + } + } + }() + + return out, nil +} diff --git a/resources/views/auth/login.html b/resources/views/auth/login.html index dd80594..415b3de 100755 --- a/resources/views/auth/login.html +++ b/resources/views/auth/login.html @@ -1,82 +1,9 @@ -
-
- Logo de la empresa +
+
+
-
-
- - - -
+
+
-

Bienvenido

- -
- - - - -
-
- - - - -
- - - -
- - \ No newline at end of file + + diff --git a/resources/views/hosting-user.html b/resources/views/hosting-user.html new file mode 100644 index 0000000..76bdec8 --- /dev/null +++ b/resources/views/hosting-user.html @@ -0,0 +1,590 @@ +
+
+ Cargando... +
+ +
+
+
+

Lista de servidores

+

Gestión de servidores.

+
+ +
+ +
+ +
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + +
NombreIP ServidorSOVencimientoRamNucleoDiscoUltimo pingProveedorTipo servidor
+
+ +
+ + + +
+
+ + +
+
+

Ver servidor

+ +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+
+
+ +
+
+

Editar servidor

+ +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +

+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+ +
+
+

Añadir servidor

+ +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +

+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+ +
+
+

Confirmar Eliminación

+ +

¿Estás seguro de que deseas eliminar este registro?

+ + +
+ + +
+
+
+
+ + \ No newline at end of file diff --git a/rest/controllers/api/ia_controller.go b/rest/controllers/api/ia_controller.go new file mode 100644 index 0000000..7c7d574 --- /dev/null +++ b/rest/controllers/api/ia_controller.go @@ -0,0 +1,85 @@ +package controllers + +import ( + "bufio" + "bytes" + "encoding/json" + "fmt" + "net/http" + + "github.com/gofiber/fiber/v2" +) + +type DataIa struct { + Prompt string `json:"prompt"` + Model string `json:"model"` + Stream bool `json:"stream"` +} + +type respuestaOllama struct { + Response string `json:"response"` + Done bool `json:"done"` +} + +func GeneraTextoStream(c *fiber.Ctx) error { + var data DataIa + if err := c.BodyParser(&data); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Datos inválidos"}) + } + + // Forzar stream = true + data.Stream = true + + jsonData, err := json.Marshal(data) + if err != nil { + return err + } + + req, err := http.NewRequest("POST", "http://72.60.24.97:8080/ollama/api/generate", bytes.NewBuffer(jsonData)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", "Bearer sk-43804e00f5294200ad1e599550fbee4f") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return err + } + + // Configurar headers para streaming + c.Set("Content-Type", "text/plain; charset=utf-8") + c.Set("Cache-Control", "no-cache") + c.Set("Connection", "keep-alive") + + c.Context().SetBodyStreamWriter(func(w *bufio.Writer) { + defer resp.Body.Close() + + scanner := bufio.NewScanner(resp.Body) + + for scanner.Scan() { + line := scanner.Bytes() + if len(line) == 0 { + continue + } + + var msg respuestaOllama + if err := json.Unmarshal(line, &msg); err != nil { + continue + } + + if msg.Response != "" { + fmt.Fprint(w, msg.Response) + w.Flush() // <-- envía inmediatamente + } + + if msg.Done { + break + } + } + }) + + return nil +} + diff --git a/rest/controllers/auth_controller.go b/rest/controllers/auth_controller.go index fae9d8a..d360e51 100755 --- a/rest/controllers/auth_controller.go +++ b/rest/controllers/auth_controller.go @@ -3,6 +3,8 @@ package controllers import ( "time" + "net/url" + "github.com/gofiber/fiber/v2" //nolint:goimports "github.com/gofiber/fiber/v2/middleware/session" "github.com/sujit-baniya/fiber-boilerplate/app" @@ -19,30 +21,21 @@ func LoginGet(c *fiber.Ctx) error { func LoginPost(c *fiber.Ctx) error { // Verificar si falta la contraseña if c.Locals("missing_password") == true { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ - "status": "missing", - "message": "no_password", - }) + return c.Redirect("/update-credentials") // Redirige directamente } // Obtener el usuario desde el contexto user := c.Locals("user").(*models.Users) // Intentar realizar el login - _, err := auth.Login(c, user.ID, app.Http.Token.AppJwtSecret) //nolint:wsl + _, err := auth.Login(c, user.ID, app.Http.Token.AppJwtSecret) if err != nil { - // Si ocurre un error, devolverlo en formato JSON - return c.JSON(fiber.Map{ - "status": "error", - "message": err.Error(), - }) + // Si hay error, podrías mandar de nuevo al login con mensaje + return c.Redirect("/login?error=" + url.QueryEscape(err.Error())) } - // Si todo está bien, devolver éxito y el token JWT - return c.JSON(fiber.Map{ - "status": "success", - "message": "Login exitoso", - }) + // Si todo está bien, redirige al inicio de la app + return c.Redirect("/app/servidor") } var store = session.New() diff --git a/rest/routes/api.go b/rest/routes/api.go index e643d0e..892185f 100755 --- a/rest/routes/api.go +++ b/rest/routes/api.go @@ -23,6 +23,7 @@ func v1AuthRoutes(api fiber.Router) { api.Post("/dlocal/payment/crear-pago", apiControllers.CreatePago) api.Post("/rapyd/wallet/create", apiControllers.MakeWallet) api.Post("/generate-url-qr", apiControllers.CreateUrlQr) + api.Post("/ia/ollama-generate", apiControllers.GeneraTextoStream) } func v1Routes(api fiber.Router) {