Rename the api-keys list column from User Name to Creator for clarity and reorder it to sit immediately before the Created column. Add the common.table.creator locale key across all supported languages.
Surface the top-level system_default_container_registry as a dedicated
input (both Docker and K8s), coerce blank to null, and drop its
redundant worker_config YAML hint.
Align the Kubernetes cluster create/edit page with the backend's
promotion of operator/K8s knobs out of worker_config and the removal
of gpuVendorOverrides.
- k8s_options: drop gpuVendorOverrides; add operatorImage, namespace,
and gpuInstanceOptions (presence = GPU instances enabled, carrying an
optional gpuInstancesAccessStaticAddress).
- Add a top-level system_default_container_registry to the cluster type
(promoted out of worker_config on the backend).
- Group all k8s_options fields into a new top-level "K8s Deployment
Options" collapsible section (sibling of Advanced, rendered above it),
with namespace first followed by volume mounts, image credentials,
node selector, operator image, and GPU instances.
- Drive the GPU instances toggle from local state instead of
Form.useWatch (an unregistered nested path never re-rendered, leaving
the switch unresponsive); use antd's borderless Switch and keep the
label/switch grouped together. Namespace gains a gpustack-system
placeholder.
- Remove the gpuVendorOverrides validation from the form and the stale
operator_image / namespace / gpu_instances_access_static_address hints
from the worker_config YAML template and JSON schema.
- Add-worker GPU picker: always allow multi-select for K8s clusters
(runtime node selectors are now auto-derived), dropping the
override-gating, cluster fetch, and single-only hint.
- Update locales (en/zh/ja/ru/tr) for the removed and added keys.
Two follow-ups to the GPU Service gating:
- In Personal-Org view the access extension was stripping
canSeeAdmin/canSeeOrgAdmin but leaving canSeeGpuService at its
admin-shortcut value, so platform admins switched into Personal
still saw the menu even though Personal scope can't host a K8s
cluster. Mirror the probe result through sessionStorage so the
extension can fall back to the strict cluster-availability signal
in that branch.
- The empty-state CTA now reads 'Add a Kubernetes Cluster' and, on
click, opens the cluster-create flow with Kubernetes preselected
via clusterSession.providerHint. ClusterCreate consumes the hint
on mount: it seeds extraData.provider and starts at the configure
step instead of the provider catalog, so the user lands one click
closer to the form they actually need.
GPU Service today only schedules on Kubernetes clusters; Docker / cloud
clusters can't host the CRDs. Without any awareness of that, Org
members whose Org has no K8s cluster (and no cluster_access grant on
one) saw a menu they couldn't use and a form that bottomed out with
backend errors.
Two changes lock the UX down:
- Boot probes the caller's cluster list once and stashes
hasKubernetesCluster in initialState. A new canSeeGpuService
predicate gates the menu — admins and Org owners always see it
(they can add the cluster); everyone else only sees it when a
reachable K8s cluster actually exists.
- The instances page filters its own cluster list to Kubernetes
before deciding what to show. With nothing reachable we render the
Deployments-style 'No clusters available. Add a Kubernetes cluster
to get started.' empty state and hide the create-instance CTA;
admins and Org owners additionally get the 'Add cluster' button
that jumps to cluster management.
- New k8s_pod_spec form sections (image credentials, node selector,
gpu vendor overrides) under k8s_options, replacing the legacy flat
k8s_volume_mounts list. UI keys aligned to the backend wire shape
(snake_case k8s_options + camelCase inside).
- System default container registry is pre-filled into the first image
credential when creating a new cluster; empty username/password are
coerced to null on submit to match the Optional[str] backend schema.
- Register cluster flow supports multi-runtime selection gated by the
cluster's gpuVendorOverrides: non-override vendors stay single-select
with an inline hint; multi-add only opens once an override vendor is
picked, and non-override cards become disabled in that state.
- Manifest URL emits multiple ?runtime= params; check-env step combines
per-vendor commands; downstream steps are disabled when no vendor is
selected.
- Pre-validate gpuVendorOverrides at save time (non-empty selector, no
duplicates across vendors, no key clash with base nodeSelector) so
the user sees the error before hitting the manifest endpoint.
- Misc: dark-mode background of the k8s_pod_spec / volume mount titles
no longer clashes with the drawer; cluster Steps no longer leaks the
internal showModules/showForms props to the DOM.
Merge the two "by Model" pies (Token Usage + API Requests) into one
dual-pie card with a shared right-side vertical legend and per-donut
center totals, drop the standalone API-Key Top 10 chart, and put the
combined chart side-by-side with the User Top 10 ranking in one row
with the same 16/8 column ratio used by the System Load section above.
* New component usage-charts/usage-by-model.tsx owns both metric queries
(group_by=['date','route']), aggregates a shared route→color map so
the legend toggles both donuts together, and renders two pies at
centers ('20%','50%') and ('60%','50%') with radius ['50%','70%'].
* new-usage.tsx no longer mounts ApiRequestsByModel / TokenUsageByModel
/ TopTokenUsageByApiKey; layout collapses to two columns sized
(lg=24 xl=16) and (lg=24 xl=8).
* Delete unused token-usage-by-model.tsx, api-requests-by-model.tsx,
top-token-usage-by-api-key.tsx, and the use-top-token-usage-by-api-key
hook.
* Strip the now-unreferenced dashboard.tokenUsageByModel /
apiRequestsByModel / topTokenUsageByApiKey locale keys across 5
locales, add the new dashboard.usageByModel title; locale parity
check passes.
Align dashboard with the route dimension introduced in the previous
commit:
* Token Usage / API Requests pie charts query the breakdown API with
`group_by: ['date', 'route']` and aggregate via the new `route`
dimension in `buildUsageLabel`. Visible chart titles keep the existing
"by Model" wording — only the underlying data dim changed.
* Overview "Models" card label switched to `dashboard.deployments`
("部署" / "Deployments"), and the Active Models table heading to
`dashboard.activeDeployments`. These reflect the underlying entity
(model deployments) more accurately now that routes are the
user-facing model concept.
* Drop 11 unused dashboard locale keys (`dashboard.title`,
`dashboard.models`, `dashboard.allocategpus`, `dashboard.instances`,
`dashboard.disk`, `dashboard.diskutilization`, `dashboard.apirequest`,
`dashboard.activeModels`, `dashboard.activeUsers`,
`dashboard.activeModels.name`, `dashboard.runninginstances`) — no
remaining references in `src/` after the rename. Locale parity check
passes.