feat: llms.txt and llms-full.txt, openapi.json, MCP server
This commit is contained in:
1 parent
daba3c04c0
commit
4cff43fefb
25 files changed
+1691
-1
No files matched your search
@@ -0,0 +1,76 @@
|
||||
package llms
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
const (
|
||||
versionPlaceholder = "{{VERSION}}"
|
||||
baseURLPlaceholder = "{{BASE_URL}}"
|
||||
pageSuffix = ".md"
|
||||
cacheControl = "public, max-age=300"
|
||||
notBuiltNotice = "The LLM documentation was not generated for this build. Run `task build:llms`."
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
docs fs.FS
|
||||
version string
|
||||
baseURL string
|
||||
}
|
||||
|
||||
func NewHandler(docs fs.FS, version string, publicURL string) *Handler {
|
||||
return &Handler{
|
||||
docs: docs,
|
||||
version: version,
|
||||
baseURL: strings.TrimRight(publicURL, "/"),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) Register(r chi.Router) {
|
||||
r.Get("/llms.txt", h.serve("llms.txt", "text/plain; charset=utf-8"))
|
||||
r.Get("/llms-full.txt", h.serve("llms-full.txt", "text/plain; charset=utf-8"))
|
||||
r.Get("/openapi.json", h.serve("openapi.json", "application/json"))
|
||||
r.Get("/llms/{page}", h.page)
|
||||
}
|
||||
|
||||
func (h *Handler) page(w http.ResponseWriter, r *http.Request) {
|
||||
name := chi.URLParam(r, "page")
|
||||
if !strings.HasSuffix(name, pageSuffix) || strings.ContainsAny(name, "/\\") {
|
||||
h.notFound(w)
|
||||
return
|
||||
}
|
||||
h.write(w, path.Join("llms", name), "text/markdown; charset=utf-8")
|
||||
}
|
||||
|
||||
func (h *Handler) serve(name string, contentType string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, _ *http.Request) {
|
||||
h.write(w, name, contentType)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) write(w http.ResponseWriter, name string, contentType string) {
|
||||
if h.docs == nil {
|
||||
h.notFound(w)
|
||||
return
|
||||
}
|
||||
raw, err := fs.ReadFile(h.docs, name)
|
||||
if err != nil {
|
||||
h.notFound(w)
|
||||
return
|
||||
}
|
||||
text := strings.NewReplacer(versionPlaceholder, h.version, baseURLPlaceholder, h.baseURL).Replace(string(raw))
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
w.Header().Set("Cache-Control", cacheControl)
|
||||
_, _ = w.Write([]byte(text))
|
||||
}
|
||||
|
||||
func (h *Handler) notFound(w http.ResponseWriter) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, _ = w.Write([]byte(notBuiltNotice))
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"RenewCMS/api/handlers/entry"
|
||||
"RenewCMS/api/handlers/frontend"
|
||||
"RenewCMS/api/handlers/imagevariant"
|
||||
"RenewCMS/api/handlers/llms"
|
||||
"RenewCMS/api/handlers/media"
|
||||
"RenewCMS/api/handlers/settings"
|
||||
"RenewCMS/api/handlers/site"
|
||||
@@ -20,6 +21,7 @@ import (
|
||||
"RenewCMS/api/middleware"
|
||||
"RenewCMS/api/pkg/authtoken"
|
||||
"RenewCMS/internal/infrastructure/config"
|
||||
"RenewCMS/internal/infrastructure/llmdocs"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -493,6 +495,7 @@ func InitRoutes(container *UseCases, settings config.Settings) *chi.Mux {
|
||||
apiRouter.Use(middleware.CrossOriginProtection(settings.PublicURL))
|
||||
apiRouter.Use(chimiddleware.GetHead)
|
||||
apiRouter.Get("/healthz", GetHealth)
|
||||
llms.NewHandler(llmdocs.Docs, settings.Version, settings.PublicURL).Register(apiRouter)
|
||||
apiRouter.Mount("/v1", backend)
|
||||
apiRouter.Mount("/static/uploadedImages", staticimages.NewHandler(container.OpenMediaUseCase, container.ServeVariantUseCase))
|
||||
apiRouter.Mount("/", frontend)
|
||||
|
||||
Reference in new issue
Block a user