73 lines
3.0 KiB
TypeScript
73 lines
3.0 KiB
TypeScript
import { getRuntimeStartGuard, getRuntimeStateLabel, getRuntimeStatusTone } from "../runtime-utils";
|
|
import type { RuntimeSnapshot } from "../types";
|
|
import "./RuntimeStatusCard.css";
|
|
|
|
function summarizePath(path: string | null): string {
|
|
if (!path) return "No model selected";
|
|
const segments = path.split(/[\\/]/).filter(Boolean);
|
|
return segments[segments.length - 1] || path;
|
|
}
|
|
|
|
interface Props {
|
|
snapshot: RuntimeSnapshot;
|
|
loading: boolean;
|
|
busy: boolean;
|
|
onOpenSettings: () => void;
|
|
onStart: () => void;
|
|
onStop: () => void;
|
|
}
|
|
|
|
export default function RuntimeStatusCard({ snapshot, loading, busy, onOpenSettings, onStart, onStop }: Props) {
|
|
const tone = getRuntimeStatusTone(snapshot);
|
|
const isLocal = snapshot.config.connection_mode === "local";
|
|
const startGuard = getRuntimeStartGuard(snapshot);
|
|
const needsSetup = isLocal && !snapshot.process_running && !startGuard.canStart;
|
|
const primaryAction = needsSetup ? onOpenSettings : isLocal && !snapshot.process_running ? onStart : onStop;
|
|
const primaryLabel = needsSetup ? "Set up" : isLocal && !snapshot.process_running ? "Start" : "Stop";
|
|
const primaryDisabled = busy || (isLocal && snapshot.process_running && snapshot.status === "stopping");
|
|
|
|
return (
|
|
<section className={`runtime-card runtime-card-${tone}`} aria-label="Runtime manager summary">
|
|
<div className="runtime-card-header">
|
|
<div>
|
|
<div className="runtime-card-kicker">Runtime Manager</div>
|
|
<div className="runtime-card-title">{loading ? "Loading runtime" : getRuntimeStateLabel(snapshot)}</div>
|
|
</div>
|
|
<span className={`runtime-card-mode runtime-card-mode-${snapshot.config.connection_mode}`}>
|
|
{snapshot.config.connection_mode === "local" ? "Local" : "Remote"}
|
|
</span>
|
|
</div>
|
|
|
|
<p className="runtime-card-copy">
|
|
{snapshot.config.connection_mode === "local"
|
|
? `Managed endpoint ${snapshot.resolved_url}`
|
|
: snapshot.config.server_url || "Configure a remote API endpoint"}
|
|
</p>
|
|
|
|
<div className="runtime-card-meta" aria-label="Runtime details">
|
|
<span>{isLocal ? summarizePath(snapshot.config.model_path) : "External provider"}</span>
|
|
<span>{snapshot.config.start_policy === "on_app_launch" ? "Auto-start" : "Manual start"}</span>
|
|
</div>
|
|
|
|
{needsSetup && <div className="runtime-card-note">{startGuard.reason}</div>}
|
|
|
|
{snapshot.last_error && (
|
|
<div className="runtime-card-error" role="status">
|
|
{snapshot.last_error.message}
|
|
</div>
|
|
)}
|
|
|
|
<div className="runtime-card-actions">
|
|
<button className="runtime-card-btn runtime-card-btn-secondary" onClick={onOpenSettings} type="button">
|
|
Manage
|
|
</button>
|
|
{snapshot.config.connection_mode === "local" && (
|
|
<button className="runtime-card-btn runtime-card-btn-primary" onClick={primaryAction} type="button" disabled={primaryDisabled}>
|
|
{busy ? "Working..." : primaryLabel}
|
|
</button>
|
|
)}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|