The manual the binary carries, rendered on the client port: a sidebar of the documents in the console's reading order (now one list, llmgw.Manual, for both), heading anchors, links between documents kept in the portal and links to files outside the binary sent to the repository, no script. Public by default; landing.docs_sign_in sends visitors to sign in first. docs/clients.md shows the official OpenAI and Anthropic SDKs against llmgw in Python, TypeScript, Go and curl, with llmgw's headers; the portal's index, the landing page and the account page link to it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
90 lines
2.3 KiB
Go
90 lines
2.3 KiB
Go
// Package llmgw holds what the binary carries besides code: its manual.
|
|
package llmgw
|
|
|
|
import (
|
|
"embed"
|
|
"io/fs"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// Docs is the documentation, read on any machine by `llmgw docs` and the
|
|
// console's manual without a checkout or the internet.
|
|
//
|
|
//go:embed README.md CHANGELOG.md docs/*.md
|
|
var Docs embed.FS
|
|
|
|
// Doc is one page of the manual.
|
|
type Doc struct {
|
|
// Key is what `llmgw docs KEY` takes, and the page's address under /docs/
|
|
// on the gateway.
|
|
Key string
|
|
// Path is the file in Docs.
|
|
Path string
|
|
// Title is the document's first heading.
|
|
Title string
|
|
}
|
|
|
|
// Source is the document's markdown.
|
|
func (d Doc) Source() string {
|
|
b, err := fs.ReadFile(Docs, d.Path)
|
|
if err != nil {
|
|
return "# " + d.Path + "\n\nNot in this build."
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
// docOrder is the documents in the order someone new reads them. Here rather
|
|
// than with either reader, because the console's manual and the gateway's
|
|
// docs portal both list them, and two lists drift.
|
|
var docOrder = []string{"console", "quick-install", "install", "node-onboarding", "onboarding",
|
|
"clients", "guardrails", "choosing-models", "fabrics", "facility-aware-placement", "data",
|
|
"reference", "development"}
|
|
|
|
// Manual is every document, in reading order: those docOrder names, then any
|
|
// other under docs/ alphabetically, so a new one is never missing, then the
|
|
// README and the changes.
|
|
func Manual() []Doc {
|
|
var out []Doc
|
|
seen := map[string]bool{}
|
|
add := func(key, path string) {
|
|
if seen[key] {
|
|
return
|
|
}
|
|
b, err := fs.ReadFile(Docs, path)
|
|
if err != nil {
|
|
return
|
|
}
|
|
seen[key] = true
|
|
out = append(out, Doc{Key: key, Path: path, Title: titleOf(string(b), path)})
|
|
}
|
|
for _, k := range docOrder {
|
|
add(k, "docs/"+k+".md")
|
|
}
|
|
entries, _ := fs.ReadDir(Docs, "docs")
|
|
var rest []string
|
|
for _, e := range entries {
|
|
if strings.HasSuffix(e.Name(), ".md") {
|
|
rest = append(rest, strings.TrimSuffix(e.Name(), ".md"))
|
|
}
|
|
}
|
|
sort.Strings(rest)
|
|
for _, k := range rest {
|
|
add(k, "docs/"+k+".md")
|
|
}
|
|
add("readme", "README.md")
|
|
add("changes", "CHANGELOG.md")
|
|
return out
|
|
}
|
|
|
|
// titleOf is a document's first top-level heading, or its path when it has
|
|
// none.
|
|
func titleOf(src, path string) string {
|
|
for _, l := range strings.Split(src, "\n") {
|
|
if strings.HasPrefix(l, "# ") {
|
|
return strings.TrimSpace(strings.TrimPrefix(l, "# "))
|
|
}
|
|
}
|
|
return path
|
|
}
|