- 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.
Playground completions (chat streaming via ``fetchChunkedData``)
and the raw ``fetch()`` calls for image / audio generation skip
umi's ``request`` pipeline and so miss the request interceptor in
``request.extensions.ts`` that pins tenant context. Higress
receives those calls without ``X-Organization-Id`` and the auth
callback falls back to the user's USER-principal id rather than
their active Org, which makes Playground usage invisible from
Org-scoped Usage views even after the backend learned to backfill
``consumer_principal_id``.
Centralise the lookup in ``tenantHeaders()`` next to
``fetchChunkedData`` so both streaming helpers and the four
``fetch()``-direct entry points in ``playground/apis/index.ts``
(image / TTS) attach the header with the same precedence as the
umi interceptor (``createScopeOrgOverride`` first,
``currentOrganizationId`` second). Returns an empty object when
no active org context is set, leaving requests unchanged.
The Usage page gated cross-user features (default ``scope=all``,
the user filter, the per-user breakdown dimension) on
``currentUser.is_admin`` alone. The backend's
``_can_use_all_scope`` already grants the same surface to Org
owners — the page just never asked. Result: a non-admin Org owner
landed on ``scope=self`` with no user filter and no per-user
group-by, even though the API would have happily served them the
org-wide picture.
Switch the three sites to ``useAccess().canSeeOrgAdmin``, which
already encodes "platform admin OR owner of the selected
(non-Personal) Org". One predicate, no new helper.
Sites:
- ``index.tsx``: ``initialScope`` defaults to ``all`` for managers.
- ``filter-bar.tsx``: the user filter + nested API-key cascader
surface (vs the flat API-key picker for members).
- ``daily-usage.tsx``: the ``user`` group-by option in the chart.
The Usage page's chart fetch (``fetchTimeSeriesData``) spread
``chartFilters`` plus dates and filters, but never forwarded
``commonFilters.scope`` — so it implicitly fell back to the
backend's ``scope=all`` default. The three breakdown tables
(``apikeys-table``, ``models-table``, ``users-table``) all pass
``scope`` explicitly, which produced an inconsistent picture on
the same page: an Org owner viewing a model granted from another
Org saw the date chart render empty while the tables underneath
showed identical usage rows.
Forward ``currentSelectedFilters.scope`` alongside the rest of the
common filters so the chart and the tables ask the backend the
same question.
Lets enterprise plugins contribute per-route columns and a global
mount point on the Usage page's Models tab. Mirrors the existing
modelRoutes pattern: `usage.modelsExtraColumns` for cells,
`<PluginExtraFields name="UsageModelsPageGlobal" />` for the
page-level data lifecycle (receives the visible route ids so a
plugin can bulk-fetch per-row data in one call).
Tracks the gpustack identity-consolidation effort: the unified
``principals`` table's URL-safe identifier column was renamed
``slug`` → ``name`` (with the legacy display ``name`` → ``display_name``).
The enterprise plugin's persisted org caches (``organizationList``,
``allOrganizations`` in localStorage) now write ``name`` instead of
``slug`` on each Organization row.
``getCurrentOrgNamespace`` reads those caches to compose the k8s
namespace (``gpustack-{name}``) for GPU-instance / storage CRDs.
Updated to read ``item.name`` so namespace resolution stays in sync
with what the enterprise plugin writes — otherwise every gpu-service
write would fall through to ``gpustack-default`` even when the user
has an Org context.
Stale ``slug`` references in surrounding comments also retitled to
``name`` to avoid divergence between code and prose. The namespace
format itself (``gpustack-{...}``) is unchanged — only the column it
sources is.
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.
Align with gpustack backend commits 7b57cd3b (add route dimension to
usage breakdown) and 51fd25c8 (use model_route_id as models_called):
* group_by, filters, and BreakdownItem now use the `route` dimension;
`models` filter cascader is replaced with a flat `routes` selector
(routes have no provider/cluster grouping).
* Tab / group_by option / column header keep the user-facing "模型 / Model"
wording — only the underlying data dimension changed.
* Drop cluster_name / provider_type columns from the breakdown table;
drop api_keys_used column per design.
* Fix pre-existing excel export bug in use-export-table — string
dataIndex was lodash-joined char-by-char ("input_tokens" →
"i_n_p_u_t..."), array dataIndex was used as a flat key against nested
rows. Rebuilt around buildSheetMeta that emits a stable field key plus
a formatMap using _.get(row, path) for nested values. Sheet name kept
as `models` to match the visible column label.