fix: tolerate missing hosted system metrics
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user