fix: tolerate missing hosted system metrics

This commit is contained in:
velixio
2026-08-18 13:30:50 +05:30
parent e6f4c766f5
commit b6ee314ff2
4 changed files with 47 additions and 20 deletions
+1
View File
@@ -26,6 +26,7 @@ the frozen-backend fallback mirror it for their toolchains.
- Every engine now has its own guide — 21 new pages under docs/engines plus an index covering all 16 TTS and 11 ASR engines, linked from both READMEs (#1556)
### Fixed
- Hosted Studio no longer crashes when system information omits desktop-only RAM, CPU, or VRAM metrics
- The crash-isolated ASR sidecar and its download preflight now agree on which model to load — setting the shared faster-whisper model variable applies to both variants instead of the sidecar quietly using a different one (#1556)
- "Ready" now requires the deep health probe (a working database-backed route), not just the identity probe — a backend whose install broke underneath can no longer be announced up while every real request fails (#1548)
- Supervisor restarts after repeat crashes now back off (immediate, then 5s, then 15s) instead of respawning back-to-back, so a tight crash loop can't burn the whole restart budget in seconds (#1548)
+12 -1
View File
@@ -155,6 +155,11 @@ export default function Header({
// only re-renders the header chrome, not the whole App tree.
const sysQuery = useSysinfo();
const sysStats = sysQuery.data ?? null;
const hasRamStats =
Number.isFinite(sysStats?.ram) && Number.isFinite(sysStats?.total_ram);
const hasCpuStats = Number.isFinite(sysStats?.cpu);
const hasVramStats = Number.isFinite(sysStats?.vram);
const hasLiveStats = hasRamStats || hasCpuStats || hasVramStats;
// Default OFF chrome shouldn't double as a resource monitor. Power users
// flip this on via Settings Performance. Idle/Ready/Loading badge +
// Flush button stay visible regardless (action-relevant).
@@ -327,16 +332,21 @@ export default function Header({
/>
{sysStats && (
<div className="flex items-center gap-[10px] [font-family:var(--chrome-font-mono)] text-[10.5px] text-[var(--chrome-fg-dim)] bg-transparent h-[var(--chrome-pill-h)] whitespace-nowrap shrink overflow-hidden tabular-nums slashed-zero max-[851px]:hidden!">
{showLiveStats && (
{showLiveStats && hasLiveStats && (
<>
{hasRamStats && (
<span className="max-[1081px]:hidden">
<b className="text-[var(--chrome-fg-muted)] font-semibold">RAM</b>{' '}
{sysStats.ram.toFixed(1)}/{sysStats.total_ram.toFixed(0)}G
</span>
)}
{hasCpuStats && (
<span className="max-[1081px]:hidden">
<b className="text-[var(--chrome-fg-muted)] font-semibold">CPU</b>{' '}
{sysStats.cpu.toFixed(0)}%
</span>
)}
{hasVramStats && (
<span
className="[border-left:1px_solid_var(--chrome-border)] pl-[6px]"
aria-label={`VRAM usage: ${sysStats.vram.toFixed(1)} gigabytes`}
@@ -348,6 +358,7 @@ export default function Header({
</b>{' '}
{sysStats.vram.toFixed(1)}G
</span>
)}
</>
)}
{/* Where the next job runs. Renders nothing until at least one
+14 -1
View File
@@ -13,6 +13,8 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import React from 'react';
import Header from '../components/Header';
import { queryKeys } from '../api/hooks';
import { useAppStore } from '../store';
const windowActions = vi.hoisted(() => ({
minimize: vi.fn(async () => {}),
@@ -24,11 +26,13 @@ vi.mock('@tauri-apps/api/window', () => ({ getCurrentWindow: () => windowActions
afterEach(() => {
delete window.__TAURI_INTERNALS__;
useAppStore.setState({ showHeaderLiveStats: false });
vi.clearAllMocks();
});
function renderHeader(props) {
function renderHeader(props, sysinfo) {
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
if (sysinfo) qc.setQueryData(queryKeys.sysinfo, sysinfo);
return render(
<QueryClientProvider client={qc}>
<Header mode="dub" setMode={() => {}} modelStatus="idle" {...props} />
@@ -37,6 +41,15 @@ function renderHeader(props) {
}
describe('Header — rail mode (default)', () => {
it('treats resource metrics as optional on hosted backends', () => {
useAppStore.setState({ showHeaderLiveStats: true });
expect(() => renderHeader({}, { platform: 'web' })).not.toThrow();
expect(screen.queryByText('RAM')).toBeNull();
expect(screen.queryByText('CPU')).toBeNull();
expect(screen.queryByText('VRAM')).toBeNull();
});
it('keeps the breadcrumb and wordmark, and renders no tab strip', () => {
const { container } = renderHeader({});
expect(container.querySelector('.tabstrip')).toBeNull();
+2
View File
@@ -39,6 +39,8 @@ _REF_REQUIRED_SECTIONS = {"Added", "Fixed"}
# work with no issue or PR to point at). Match is by substring; keep this list
# short and delete entries once they ship in a tagged release.
_REF_ALLOWLIST = (
# owner-directed hosted Studio integration fix, no issue or PR
"Hosted Studio no longer crashes",
# owner commit 7036e101 — first-run consent prompt, committed straight to main
"First-run consent question for the existing opt-in analytics",
# owner commits ce842737 + dc766baf — Colab notebook, committed straight to main