{{define "admin_mirror"}} {{/* Only while something is downloading, and not while a form is being filled in: pages.js holds the reload off then. */}} {{if .RefreshSec}}{{end}} {{t "mirror.title"}} · llmgw

{{t "mirror.heading"}}

{{.Addr}}{{if .Unreachable}} {{t "mirror.did_not_answer"}}{{end}}

{{template "nav" .Nav}}
{{/* Links rather than a script's panels: each tab has an address, the back button works, and only the one shown asks anything of the registry. */}} {{if .Error}}

{{.Error}}

{{end}} {{if .Message}}

{{.Message}}

{{end}} {{if eq .Tab "held"}} {{if .Unreachable}} {{/* Said outright rather than shown as an empty table. A mirror holding nothing and a mirror that is not there look the same in a list of zero rows, and they call for opposite responses. */}}

{{th "mirror.unreachable" .Addr}}

{{else}}
{{if .Rows}} {{range .Groups}}{{$grouped := gt .Models 1}} {{if $grouped}} {{end}} {{range .Rows}}{{$row0 := .}} {{if .Err}}{{end}} {{with .Detail}}{{end}} {{with .Serve}} {{end}} {{end}} {{end}}
{{t "mirror.col.model"}}{{t "mirror.col.files"}}{{t "mirror.col.size"}}{{t "mirror.col.runs"}}
{{.Family}} {{tn "mirror.group.models" .Models (bytes .Bytes)}} {{if .Fetching}}{{t "mirror.state.fetching"}}{{end}} {{if .Failed}}{{t "mirror.state.failed"}}{{end}} {{if .InUse}}{{t "mirror.group.in_use"}}{{end}}
{{if eq (printf "%s" .State) "present"}}{{.Model}} {{else}}{{.Model}}{{end}} {{.Version}} {{if eq .Kind "adapter"}}{{t "mirror.adapter"}}{{end}} {{if gt .Files 1}}{{tn "mirror.files" .Files}}{{else}}{{.File}}{{end}} {{if eq (printf "%s" .State) "fetching"}} {{if .HasPercent}}{{t "mirror.percent_of" .Percent (bytes .BytesTotal)}} {{else}}{{/* No total came from upstream, so no percentage is invented — a bar that guesses its own end and then stops moving is worse than a number that only goes up. */}} {{t "mirror.so_far" (bytes .BytesDone)}}{{end}} {{else if eq (printf "%s" .State) "failed"}}— {{else}}{{bytes .BytesDone}}{{end}} {{if eq (printf "%s" .State) "fetching"}}{{t "mirror.state.fetching"}} {{else if eq (printf "%s" .State) "failed"}}{{t "mirror.state.failed"}} {{else if .UsedBy}}{{$row := .}}{{range .UsedBy}}
{{/* Named only when the catalog calls it something other than the mirror does; otherwise it is the model column again. */}} {{if ne .Name $row.Model}}{{t "mirror.use.as" .Name}}{{end}} {{if .Declared}} {{- t "mirror.use.yaml" (t (print "mirror.mode." .Mode))}} {{else}} {{/* Submitted on change: the choice is the action, and a second click to confirm it would only be a way to forget to. */}}
{{/* The button is in the catalogue: what a noscript holds is read as text, not markup. */}}
{{end}} {{if .Fleet}} {{- if .Parked}}{{t "mirror.use.parked"}} {{- else if and (eq .Wanted 0) (eq .Ready 0)}}{{t "mirror.use.none_running"}} {{- else}}{{.Ready}}/{{.Wanted}}{{if .Starting}} +{{.Starting}}{{end}}{{end}} {{- if .Unplaceable}} · {{t "mirror.use.no_room"}}{{end}} {{- with .Nodes}} · {{range $i, $n := .}}{{if $i}}, {{end}}{{$n.Short}}{{end}}{{end}}{{end}}
{{end}} {{else}}{{t "mirror.not_served"}}{{end}}
{{if eq (printf "%s" .State) "failed"}} {{/* Retry, not remove. A fetch that failed left nothing on disk, so the remove would come back "the mirror holds nothing for this" — a button whose only outcome is a confusing error. Starting the same download again is what somebody looking at a failed row wants, and the mirror allows it: only a download still running is refused. */}}
{{else if eq (printf "%s" .State) "present"}} {{if and $.HasCatalog (not .UsedBy)}}{{if .Serve}}{{t "mirror.close"}} {{else}}{{t "mirror.serve"}}{{end}}{{end}}
{{end}}
{{.Err}}
{{template "mirror_held_detail" dict "D" . "Row" $row0 "CSRF" $.CSRF}}
{{if .Refusal}} {{/* Offered and then failing at placement is worse than not offered at all. */}}

{{t "serve.refusal" .Refusal}}

{{else}} {{if .Warning}}

{{.Warning}}.

{{end}}
{{if .StrataFamily}} {{end}}

{{th "serve.serving" .Source .Engine}} {{if .Files}}{{t "serve.whole_version" .Files}}{{end}}

{{if .StrataFamily}}

{{t "serve.strata" .StrataFamily .StrataSize}}

{{end}}
{{/* Reaches clients through /v1/models, which for most of them is the only view of what this gateway serves. Nine names and nothing to choose between them is a choice made by guesswork. */}}
{{if ne .Engine "strata"}}{{end}}
{{/* Where it runs is a choice with consequences, so it is a choice: the GPU classes the fleet has, and the CPU for llama.cpp. A profile name field stood here once, and reading as though naming a profile "gpu" would put it on one, it put GGUF models on the CPU of GPU clusters. */}}
{{if ne .Engine "strata"}}{{end}} {{if eq .Engine "llamacpp"}}{{end}}
{{if .FreeGPUs}}{{end}}

{{t "serve.pool_note"}}

{{t "serve.memory_note" .MemoryBasis}}

{{end}}

{{th "mirror.copy_note"}}

{{else}}

{{if .HasRegistry}}{{th "mirror.empty_explore"}}{{else}}{{th "mirror.empty"}}{{end}}

{{end}}
{{end}} {{end}} {{if and (eq .Tab "explore") .HasRegistry}} {{if not .Repo}}{{with .Explore}} {{if eq .View "adapters"}}

{{if .Of}}{{th "explore.adapters_for" .Of}} {{t "explore.all_adapters"}}{{else}}{{th "explore.adapters_any"}}{{end}} {{t "explore.adapters_note"}}

{{else}}
{{end}} {{end}} {{end}} {{if .RegistryErr}} {{/* Its own line, not the page's error: the registry is somebody else's server and it being down says nothing about the mirror, which is what this page is for and has to keep working when Hugging Face does not. */}}

{{t "explore.registry_err" .RegistryErr}}

{{end}} {{if not .Repo}}{{with .Explore}} {{with .Fit}}

{{.}}

{{end}} {{if .Rows}} {{range .Rows}}{{end}}
{{t "explore.col.repo"}}{{t "explore.col.size"}}{{t "explore.col.arch"}}{{t "explore.col.context"}} {{t "explore.col.gpu"}} {{t "explore.col.cpu"}} {{t "explore.col.downloads"}}{{t "explore.col.likes"}}{{t "explore.col.updated"}}
{{if .New}}{{t "explore.new"}}{{end}}{{if .Gated.Is}}{{t "explore.gated"}}{{end}} {{if or .BaseModel .License}}{{with .BaseModel}}{{t "explore.from" .}}{{end}}{{if and .BaseModel .License}} · {{end}}{{.License}}{{end}} {{.ParamsLabel}} {{if .Architecture}}{{.Architecture}}{{if .Verdict.Checked}}{{if .Verdict.Servable}} ✓{{else}} ✗{{end}}{{end}}{{else}}—{{end}} {{.ContextLabel}} {{if .GPUSpeed}}{{.GPUSpeed}}{{else}}—{{end}} {{if .CPUSpeed}}{{.CPUSpeed}}{{else}}—{{end}} {{compact .Downloads}} {{compact .Likes}} {{.Updated}}
{{if .Hidden}}

{{tn "explore.hidden" .Hidden}} {{t "explore.untick"}}

{{end}}

{{t "explore.gated_note"}}

{{else if not $.RegistryErr}}

{{if $.Query}}{{if .Hidden}}{{tn "explore.empty.query_hidden" .Hidden $.Query}}{{else}}{{t "explore.empty.query" $.Query}}{{end}} {{- else}}{{if .Hidden}}{{tn "explore.empty.hidden" .Hidden}}{{else}}{{t "explore.empty.nothing"}}{{end}}{{end}}

{{end}} {{end}}{{end}} {{if .Repo}}{{template "mirror_repo" .}}{{end}} {{end}} {{if and (eq .Tab "strata") .Strata}}

{{t "strata.intro"}}

{{if .Strata.Nodes}}

{{t "strata.nodes" (join .Strata.Nodes)}}

{{else}}

{{th "strata.none"}}

{{end}} {{range .Strata.Families}}

{{.Title}} --family {{.Name}}{{if .Repo}} · {{.Repo}}{{end}}

{{if .FetchesItself}}

{{t "strata.self"}}

{{end}} {{$fam := .}} {{range .Sizes}} {{end}}
{{t "strata.col.size"}}{{t "strata.col.download"}}{{t "strata.col.ram"}}{{t "strata.col.runs"}}
{{.Size}}{{if .NVIDIAOnly}} {{t "strata.nvidia"}}{{end}} {{.DownloadGB}} GB {{.RAMGB}} GB {{if .Fits}}{{.Runs}}{{else}}{{.Runs}}{{end}} {{if and $fam.FetchesItself .Fits}}
{{end}}{{if and $fam.Fetchable .Fits}}
{{end}}
{{end}} {{end}} {{if eq .Tab "fetch"}}

{{t "mirror.fetch.intro"}}

{{t "mirror.fetch.note"}}

{{end}}
{{end}} {{/* One repository: its card and its files. The whole page when opened by address, and the row beneath a listing entry when opened from the list. */}} {{define "mirror_repo"}} {{if not .Inline}}

{{t "card.back"}}

{{.Repo.ID}} {{t "card.at" .Repo.ShortRevision}}

{{end}}

{{if .Inline}}{{th "card.at_code" .Repo.ShortRevision}}{{end}} {{with .Repo.BaseModel}}{{t "card.from"}} {{range $i, $b := .}}{{if $i}}, {{end}}{{$b}}{{end}}{{end}} {{with .Repo.License}}{{t "card.license" .}}{{end}} {{with .Repo.Languages}}{{join .}}{{end}} {{t "card.on_registry"}}

{{if .Card}}
{{t "card.model_card"}}
{{.Card}}
{{end}} {{if .RepoSets}} {{range .RepoSets}}{{end}}
{{t "card.col.what"}}{{t "card.col.size"}}{{t "card.col.checksum"}}
{{.Name}} {{if .Shards}}{{t "card.shards" .Shards}}{{end}} {{with .Companions}}{{t "card.companions" (len .)}}{{end}} {{if eq .Kind "adapter"}}{{t "card.adapter" .Arch}} {{else if eq .Kind "model"}}{{if .Arch}}{{t "card.model_arch" .Arch}}{{else}}{{t "card.model"}}{{end}}{{end}} {{if .GPUSpeed}}{{t "card.gpu_speed" .GPUSpeed .GPULayout}}{{end}} {{if .CPUSpeed}}{{t "card.cpu_speed" .CPUSpeed .CPUNode}}{{end}} {{bytes .Bytes}} {{with .SHA256}}{{slice . 0 12}}{{else}}—{{end}} {{if not .Verdict.Servable}} {{t "card.cannot_serve"}} {{.Verdict.Reason}} {{else}} {{if .Verdict.Architecture}}{{.Verdict.Architecture}}{{if .Verdict.Checked}} ✓{{end}}{{end}}
{{range .Sources}} {{end}}
{{end}}
{{if .PickleHidden}}

{{tn "card.pickle_hidden" .PickleHidden}}

{{end}}

{{t "card.weights_note"}}

{{th "card.pinned_note" .Repo.ShortRevision}}

{{else}}

{{if .PickleHidden}}{{tn "card.only_pickle" .PickleHidden .Repo.ID}}{{else}}{{t "card.no_weights" .Repo.ID}}{{end}}

{{end}} {{end}} {{/* The card beneath a held version: what runs it, where, and how many. */}} {{define "mirror_held_detail"}}{{$row := .Row}}{{$csrf := .CSRF}}{{$scopes := .D.Scopes}}

{{if gt $row.Files 1}}{{tn "mirror.files" $row.Files}}{{else}}{{$row.File}}{{end}} {{bytes $row.BytesDone}} {{with $row.SHA256}}sha256 {{slice . 0 12}}{{end}} {{$row.URL}}

{{if not .D.Models}}

{{t "mirror.detail.not_in_catalog"}} {{if $row.Serve}}{{else}}{{th "mirror.detail.use_serve"}}{{end}}

{{end}} {{range .D.Models}}

{{.Name}} {{with .View}}{{t "mirror.detail.ready" .Ready .Desired}}{{if ne .Total .Ready}} · {{t "mirror.detail.in_all" .Total}}{{end}} {{if .Parked}}{{t "mirror.use.parked"}}{{else if .Unplaceable}}{{t "mirror.detail.does_not_fit"}}{{end}}{{end}}

{{with .View.Reason}}

{{.}}

{{end}} {{if .Replicas}} {{range .Replicas}}{{$rep := .}}{{range $i, $s := .Nodes}}{{end}}{{end}}
{{t "mirror.replica.col.replica"}}{{t "mirror.replica.col.node"}}{{t "mirror.replica.col.state"}}{{t "mirror.replica.col.age"}}CPU{{t "mirror.replica.col.memory"}}
{{if eq $i 0}}{{$rep.ID}}{{end}} {{$s.Node}}{{if $s.MemoryGB}} {{$s.MemoryGB}} GB{{end}} {{if eq $i 0}}{{$rep.StateText}} {{with $rep.Restart}}{{t "mirror.replica.restart" .}}{{end}}{{end}} {{if eq $i 0}}{{age $rep.Age}}{{end}} {{if $s.CPU}}{{t "mirror.replica.cores" (num $s.CPU 1)}}{{else}}—{{end}} {{if $s.MemBytes}}{{bytes $s.MemBytes}}{{else}}—{{end}}
{{else}}

{{if eq .Mode "ondemand"}}{{t "mirror.detail.none_running_ondemand"}}{{else}}{{t "mirror.detail.none_running"}}{{end}}

{{end}} {{if .Headroom}}

{{.RoomText}} {{with .PreemptText}}
{{.}}{{end}}

{{if and (not .Headroom.Limited) .Headroom.Blocked}}
{{if .Headroom.More}}{{t "mirror.room.why_not_more"}}{{else}}{{t "mirror.room.why_not_another"}}{{end}}
    {{range .Headroom.Blocked}}
  • {{.}}
  • {{end}}
{{end}} {{end}} {{if not .Declared}}{{$mname := .Name}}

{{t "mirror.adapters.heading"}} {{t "mirror.adapters.find"}}

{{if .Adapters}} {{range .Adapters}}{{$a := .}}{{end}}
{{t "mirror.adapters.asked_as"}}{{t "mirror.adapters.file"}}{{t "mirror.adapters.scale"}}
{{.Name}} {{.Source}} {{.EffectiveScale}}
{{else}}

{{t "mirror.adapters.none"}}

{{end}} {{if .AdapterChoices}}{{$m := .}}
{{else}}

{{t "mirror.adapters.no_choice"}}

{{end}}
{{end}} {{if .Declared}}

{{t "mirror.detail.declared"}}

{{else}}
{{if $scopes}}{{$owner := .Owner}}{{end}}

{{if .MostNow}}{{if and .Headroom .Headroom.ByPreempting}}{{t "mirror.form.most_now_preempting" .MostNow}}{{else}}{{t "mirror.form.most_now" .MostNow}}{{end}} {{end}}{{t "mirror.form.note"}}

{{end}}
{{end}}
{{end}}