{{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}}{{.Addr}}{{if .Unreachable}} {{t "mirror.did_not_answer"}}{{end}}
{{template "nav" .Nav}}{{.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}}| {{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. */}}
{{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}}{{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}}{{if .Of}}{{th "explore.adapters_for" .Of}} {{t "explore.all_adapters"}}{{else}}{{th "explore.adapters_any"}}{{end}} {{t "explore.adapters_note"}}
{{else}}{{t "explore.registry_err" .RegistryErr}}
{{end}} {{if not .Repo}}{{with .Explore}} {{if .Rows}}| {{t "explore.col.repo"}} | {{t "explore.col.size"}} | {{t "explore.col.arch"}} | {{t "explore.col.context"}} | {{t "explore.col.downloads"}} | {{t "explore.col.likes"}} | {{t "explore.col.updated"}} |
|---|---|---|---|---|---|---|
{{.ID}}
{{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}} | {{compact .Downloads}} | {{compact .Likes}} | {{.Updated}} |
{{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 eq .Tab "fetch"}}{{t "mirror.fetch.intro"}}
{{t "mirror.fetch.note"}}
{{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}} |
{{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}} {{end}} |
{{t "card.weights_note"}}
{{th "card.pinned_note" .Repo.ShortRevision}}
{{else}}{{t "card.no_weights" .Repo.ID}}
{{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}}{{t "mirror.detail.not_in_catalog"}} {{if $row.Serve}}{{else}}{{th "mirror.detail.use_serve"}}{{end}}
{{end}} {{range .D.Models}}{{.}}
{{end}} {{if .Replicas}}| {{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}} |
{{if eq .Mode "ondemand"}}{{t "mirror.detail.none_running_ondemand"}}{{else}}{{t "mirror.detail.none_running"}}{{end}}
{{end}} {{if .Headroom}}
{{.RoomText}}
{{with .PreemptText}}
{{.}}{{end}}
| {{t "mirror.adapters.asked_as"}} | {{t "mirror.adapters.file"}} | {{t "mirror.adapters.scale"}} | |
|---|---|---|---|
{{.Name}} |
{{.Source}} | {{.EffectiveScale}} |
{{t "mirror.adapters.none"}}
{{end}} {{if .AdapterChoices}}{{$m := .}} {{else}}{{t "mirror.adapters.no_choice"}}
{{end}}{{t "mirror.detail.declared"}}
{{else}} {{end}}