mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-15 05:29:28 +00:00
feat(webui): rate badges, refresh labels, anchor links
Providers tab (Feature A): a new ProviderRateBadge component renders each provider's day-window success rate (attempts-failures)/attempts — always shown when attempts>0 (100% muted, <99% amber via the chart palette's --color-chart-tokens-out token, <90% destructive, reusing the Badge component's existing secondary/outline/destructive idioms rather than inventing a new variant), a distinct "no traffic" badge when attempts=0, and the live minute-window count in its title attribute. The same component renders beside a ModelChip inside a provider's accordion, but only when that model is degraded (<99% with attempts>0) so a long, healthy model list stays uncluttered. The math and its threshold constants live in lib/provider-rate.ts, unit-tested directly (vitest's node environment needs no component mount). Feature B: a provider's "refreshed ..." label (lib/format.ts's new refreshLabel) now reads "discovery off" when DiscoveryEnabled is false, "pending" when it is true but lastRefresh is still unset, and otherwise the unchanged relative-time text — replacing the misleading "refreshed never" a discovery-disabled provider showed before. Feature C: composables/useTabHash syncs App.vue's active tab to the URL hash (#providers/#usage/#charts/#targets, matching the existing TabsTrigger values) with no router dependency. On load it reads the current hash (falling back to "providers" for an absent or invalid one); on tab change it writes the hash back via history.replaceState (no scroll jump, no new history entry per click); a hashchange listener handles back/forward and hand-edited URLs. hashToTab/tabToHash are exported as pure functions so the mapping is unit-tested directly, independent of window/history/location — every DOM touch inside useTabHash itself is guarded behind one hasWindow check so the module still imports cleanly under vitest's node test environment. AuthGate never reads or writes the hash, so a tab named in the URL survives the unauthenticated -> authenticated transition unchanged.
This commit is contained in:
@@ -12,6 +12,19 @@ export interface LimitsConfig {
|
||||
costPerMonthUSD?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* One upstream model's current-window attempt/failure counters within its
|
||||
* provider (admin.go: adminModelRateView) — Feature A, v0.22 per-model
|
||||
* success-rate breakdown. Field shape matches AdminProviderView's own
|
||||
* attempts/failures counters below, just scoped to one model.
|
||||
*/
|
||||
export interface AdminModelRateView {
|
||||
attemptsDay: number
|
||||
failuresDay: number
|
||||
attemptsMinute: number
|
||||
failuresMinute: number
|
||||
}
|
||||
|
||||
export interface AdminProviderView {
|
||||
name: string
|
||||
type: string
|
||||
@@ -21,6 +34,27 @@ export interface AdminProviderView {
|
||||
/** Sorted explicit∪discovered model ids (admin.go: adminProviderView.Models) — always an array, never omitted, even when empty. */
|
||||
models: string[]
|
||||
modelCount: number
|
||||
/**
|
||||
* discoveryEnabled mirrors the provider's own configured Discovery flag
|
||||
* (admin.go: adminProviderView.DiscoveryEnabled — Feature B, v0.22): the
|
||||
* Providers tab uses it to tell "discovery is off" apart from "discovery
|
||||
* is on but has not refreshed yet", both of which otherwise show the same
|
||||
* zero lastRefresh.
|
||||
*/
|
||||
discoveryEnabled: boolean
|
||||
/**
|
||||
* attemptsDay/failuresDay/attemptsMinute/failuresMinute are this
|
||||
* provider's current-window upstream-attempt counters (admin.go:
|
||||
* adminProviderView's identically-named fields — Feature A, v0.22). See
|
||||
* lib/provider-rate.ts for the success-rate math and badge-tier
|
||||
* thresholds built on top of these.
|
||||
*/
|
||||
attemptsDay: number
|
||||
failuresDay: number
|
||||
attemptsMinute: number
|
||||
failuresMinute: number
|
||||
/** Per-model breakdown of the counters above, keyed by upstream model id — always present (possibly empty), never omitted. */
|
||||
modelRates: Record<string, AdminModelRateView>
|
||||
}
|
||||
|
||||
export interface AdminRedisView {
|
||||
|
||||
Reference in New Issue
Block a user