From de222b8b1ded6c6dc68883196a7f01953fa92e02 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 12 Aug 2026 20:51:47 -0500 Subject: [PATCH] fix: el crawler de uMind acepta texto plano/Markdown, no solo HTML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CrawlearSitio rechazaba cualquier Content-Type que no contuviera "text/html", así que una URL como base-conocimiento.md (text/plain, pensada explícitamente para que la consuma una IA) fallaba con "no se pudo extraer texto de ninguna página" pese a tener contenido perfectamente válido. Ahora acepta text/plain, text/markdown, o cualquier URL terminada en .md, usando el body tal cual sin pasarlo por el parser de HTML. Co-Authored-By: Claude Sonnet 5 --- pkg/services/umind_ingest_service.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/pkg/services/umind_ingest_service.go b/pkg/services/umind_ingest_service.go index 172629a..4d19f92 100644 --- a/pkg/services/umind_ingest_service.go +++ b/pkg/services/umind_ingest_service.go @@ -2,6 +2,7 @@ package services import ( "fmt" + "io" "log" "net/http" "net/url" @@ -45,8 +46,27 @@ func crawlearPagina(pageURL string) (*paginaCrawleada, error) { return nil, fmt.Errorf("%s respondió %d", pageURL, resp.StatusCode) } ct := resp.Header.Get("Content-Type") - if ct != "" && !strings.Contains(ct, "text/html") { - return nil, fmt.Errorf("%s no es HTML (%s)", pageURL, ct) + esHTML := ct == "" || strings.Contains(ct, "text/html") + // Además de HTML, se acepta texto plano/Markdown servido tal cual — es un + // patrón cada vez más común (ej. este mismo caso: un .md pensado para que + // lo consuma una IA, sin ruido de HTML que limpiar). + esTexto := strings.Contains(ct, "text/plain") || strings.Contains(ct, "text/markdown") || + strings.HasSuffix(strings.ToLower(strings.Split(pageURL, "?")[0]), ".md") + if !esHTML && !esTexto { + return nil, fmt.Errorf("%s no es HTML ni texto plano (%s)", pageURL, ct) + } + + if !esHTML { + body, err := io.ReadAll(io.LimitReader(resp.Body, 2*1024*1024)) + if err != nil { + return nil, fmt.Errorf("no se pudo leer %s: %w", pageURL, err) + } + pagina := &paginaCrawleada{URL: pageURL, Texto: normalizarEspacios(string(body))} + primeraLinea := strings.TrimSpace(strings.SplitN(string(body), "\n", 2)[0]) + if strings.HasPrefix(primeraLinea, "#") { + pagina.Titulo = strings.TrimSpace(strings.TrimLeft(primeraLinea, "# ")) + } + return pagina, nil } base, err := url.Parse(pageURL)