Fix Vitest suite and wire cloud/AWS dashboard API helpers.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Adds missing client methods, VPC seeder badges, hospice strain UI, and uiHelp drift keys so server/web builds and all 849 Vitest tests pass.
This commit is contained in:
AetherForge
2026-06-07 11:03:35 -07:00
parent 35c3271f20
commit c3a9cda7d5
27 changed files with 941 additions and 95 deletions

View File

@@ -13,7 +13,7 @@ import {
formatClearanceElevation,
} from '../../help/clearance';
import { useWebSocket } from '../../hooks/useWebSocket';
import type { Agent, StrainCard } from '../../types';
import type { Agent, StrainCard, StrainHospiceRecord } from '../../types';
import { HelpTip } from '../HelpTip';
import JoinLaneBadge from './JoinLaneBadge';
import LotlTierBadge from './LotlTierBadge';
@@ -78,6 +78,7 @@ export default function AccessDepthPanel({ agent, diagnostics }: Props) {
const [serverPolicy, setServerPolicy] = useState(parseAccessDepthServerPolicy({}));
const [elevationFlash, setElevationFlash] = useState<string | null>(null);
const [strainCards, setStrainCards] = useState<StrainCard[]>([]);
const [hospiceStrains, setHospiceStrains] = useState<Set<string>>(new Set());
const [strainPlayBusy, setStrainPlayBusy] = useState<string | null>(null);
const flashTimerRef = useRef<number | null>(null);
@@ -141,6 +142,23 @@ export default function AccessDepthPanel({ agent, diagnostics }: Props) {
};
}, [agent.id]);
useEffect(() => {
let cancelled = false;
api
.listStrainHospice()
.then((rows: StrainHospiceRecord[]) => {
if (!cancelled) {
setHospiceStrains(new Set(rows.map((r: StrainHospiceRecord) => r.strain_id.trim().toLowerCase())));
}
})
.catch(() => {
if (!cancelled) setHospiceStrains(new Set());
});
return () => {
cancelled = true;
};
}, []);
useEffect(() => {
if (!latestMessage) return;
if (latestMessage.type === 'strain_card' || latestMessage.type === 'strain_card_played') {
@@ -154,8 +172,13 @@ export default function AccessDepthPanel({ agent, diagnostics }: Props) {
}
}, [latestMessage, agent.id]);
const strainInHospice = (strain?: string) => {
const id = strain?.trim().toLowerCase().replace(/^#/, '') ?? '';
return id !== '' && hospiceStrains.has(id);
};
const playStrainCard = async (card: StrainCard) => {
if (strainPlayBusy) return;
if (strainPlayBusy || strainInHospice(card.spread_strain)) return;
setStrainPlayBusy(card.id);
try {
await api.playStrainCard({ agent_id: agent.id, card_id: card.id });
@@ -232,6 +255,11 @@ export default function AccessDepthPanel({ agent, diagnostics }: Props) {
) : (
<div className="access-depth-muted">No join lane yet</div>
)}
{strainInHospice(agent.spread_strain) && (
<div className="access-depth-hospice-note access-depth-muted">
strain in hospice museum read-only lineage
</div>
)}
{(agent.parent_agent_id || agent.spread_generation || agent.spread_strain) && (
<div className="access-depth-lineage" data-strain={agent.spread_strain?.replace(/^#/, '') ?? ''}>
lineage gen {agent.spread_generation ?? 0}
@@ -266,13 +294,24 @@ export default function AccessDepthPanel({ agent, diagnostics }: Props) {
) : null}
<span className="access-depth-strain-card-title">
strain · {card.persona}
{strainInHospice(card.spread_strain) ? (
<span className="access-depth-tag access-depth-tag--skip"> hospice</span>
) : null}
</span>
<button
type="button"
className="access-depth-strain-play"
disabled={agent.status !== 'online' || strainPlayBusy === card.id}
disabled={
agent.status !== 'online' ||
strainPlayBusy === card.id ||
strainInHospice(card.spread_strain)
}
onClick={() => playStrainCard(card)}
title={`Play ${card.source_agent_name} lineage preset`}
title={
strainInHospice(card.spread_strain)
? 'Strain retired to hospice'
: `Play ${card.source_agent_name} lineage preset`
}
>
{strainPlayBusy === card.id ? '…' : 'play'}
</button>