fix(lab): restore semantic overlay in M4.7
This commit is contained in:
@@ -360,27 +360,65 @@ function parseResult(value: unknown): E47SemanticSlamResult {
|
||||
}
|
||||
|
||||
export async function fetchE47SemanticSlamResult({
|
||||
resultId: requestedResultId,
|
||||
fetcher = fetch,
|
||||
signal,
|
||||
}: {
|
||||
resultId?: string;
|
||||
fetcher?: LaboratoryFetch;
|
||||
signal?: AbortSignal;
|
||||
} = {}): Promise<E47SemanticSlamResult | null> {
|
||||
const response = await fetcher("/api/v1/laboratory/e47-semantic-slam/results?limit=1", {
|
||||
headers: { Accept: "application/json" },
|
||||
signal,
|
||||
});
|
||||
if (requestedResultId !== undefined) resultId(requestedResultId);
|
||||
let response = await fetcher(
|
||||
requestedResultId === undefined
|
||||
? "/api/v1/laboratory/e47-semantic-slam/results?limit=1"
|
||||
: `/api/v1/laboratory/e47-semantic-slam/results/${requestedResultId}`,
|
||||
{ headers: { Accept: "application/json" }, signal },
|
||||
);
|
||||
let catalogFallback = false;
|
||||
if (requestedResultId !== undefined && response.status === 404) {
|
||||
response = await fetcher("/api/v1/laboratory/e47-semantic-slam/results?limit=10", {
|
||||
headers: { Accept: "application/json" },
|
||||
signal,
|
||||
});
|
||||
catalogFallback = true;
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new E47SemanticSlamContractError(`E47 LAB недоступен: HTTP ${response.status}.`);
|
||||
}
|
||||
const payload = object(await response.json(), "E47 catalog");
|
||||
exact(
|
||||
payload.schema_version,
|
||||
"missioncore.e47-semantic-slam-catalog/v1",
|
||||
"E47 catalog schema",
|
||||
);
|
||||
const items = array(payload.items, "E47 catalog items");
|
||||
return items.length ? parseResult(items[0]) : null;
|
||||
const payload = await response.json();
|
||||
if (requestedResultId === undefined || catalogFallback) {
|
||||
const catalog = object(payload, "E47 catalog");
|
||||
exact(
|
||||
catalog.schema_version,
|
||||
"missioncore.e47-semantic-slam-catalog/v1",
|
||||
"E47 catalog schema",
|
||||
);
|
||||
const items = array(catalog.items, "E47 catalog items");
|
||||
if (!items.length) return null;
|
||||
const selected = requestedResultId === undefined
|
||||
? items[0]
|
||||
: items.find((candidate) => (
|
||||
typeof candidate === "object"
|
||||
&& candidate !== null
|
||||
&& (candidate as Record<string, unknown>).result_id === requestedResultId
|
||||
));
|
||||
if (selected === undefined) {
|
||||
throw new E47SemanticSlamContractError(
|
||||
"E47 requested result: точный semantic-result отсутствует в каталоге.",
|
||||
);
|
||||
}
|
||||
const parsed = parseResult(selected);
|
||||
if (requestedResultId !== undefined && parsed.resultId !== requestedResultId) {
|
||||
throw new E47SemanticSlamContractError("E47 requested result: нарушена идентичность.");
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
const parsed = parseResult(payload);
|
||||
if (parsed.resultId !== requestedResultId) {
|
||||
throw new E47SemanticSlamContractError("E47 requested result: нарушена идентичность.");
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function parseFrame(
|
||||
|
||||
@@ -6,6 +6,10 @@ import {
|
||||
fetchM4ThreatReplayResult,
|
||||
type M4ThreatReplayResult,
|
||||
} from "./m4ReplayThreat";
|
||||
import {
|
||||
fetchE47SemanticSlamResult,
|
||||
type E47SemanticSlamResult,
|
||||
} from "./e47SemanticSlam";
|
||||
|
||||
export interface M47ReferenceGraphLabResult {
|
||||
resultId: string;
|
||||
@@ -41,6 +45,7 @@ export interface M47ReferenceGraphLabResult {
|
||||
>>;
|
||||
limitations: readonly string[];
|
||||
visual: M4ThreatReplayResult;
|
||||
semantic: E47SemanticSlamResult;
|
||||
}
|
||||
|
||||
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
||||
@@ -154,7 +159,7 @@ export async function fetchM47ReferenceGraphLab({
|
||||
const report = evidence.rawReport;
|
||||
exact(
|
||||
report.schema_version,
|
||||
"missioncore.reference-perception-graph-lab-report/v1",
|
||||
"missioncore.reference-perception-graph-lab-report/v2",
|
||||
"M4.7 report schema",
|
||||
);
|
||||
exact(report.result_id, resultId, "M4.7 report result");
|
||||
@@ -176,6 +181,16 @@ export async function fetchM47ReferenceGraphLab({
|
||||
true,
|
||||
"M4.7 visual evidence",
|
||||
);
|
||||
exact(
|
||||
visualEvidence.camera_semantic_overlay_available,
|
||||
true,
|
||||
"M4.7 camera semantic overlay",
|
||||
);
|
||||
exact(
|
||||
visualEvidence.semantic_binding,
|
||||
"exact-sequence-and-session-time",
|
||||
"M4.7 semantic binding",
|
||||
);
|
||||
const linkedVisualResultId = text(
|
||||
visualEvidence.linked_result_id,
|
||||
"M4.7 linked visual result",
|
||||
@@ -193,6 +208,31 @@ export async function fetchM47ReferenceGraphLab({
|
||||
"M4.7 visual binding: сервер вернул другой replay result.",
|
||||
);
|
||||
}
|
||||
const semanticResultId = text(
|
||||
visualEvidence.semantic_result_id,
|
||||
"M4.7 linked semantic result",
|
||||
);
|
||||
if (!/^e47-semantic-slam-[a-f0-9]{64}$/.test(semanticResultId)) {
|
||||
throw new M47ReferenceGraphContractError(
|
||||
"M4.7 semantic binding: нарушена идентичность.",
|
||||
);
|
||||
}
|
||||
const semantic = await fetchE47SemanticSlamResult({
|
||||
resultId: semanticResultId,
|
||||
fetcher,
|
||||
signal,
|
||||
});
|
||||
if (
|
||||
!semantic
|
||||
|| semantic.resultId !== semanticResultId
|
||||
|| semantic.baseM4ResultId !== linkedVisualResultId
|
||||
|| semantic.metrics.frames.total !== 4489
|
||||
|| semantic.metrics.frames.maskAvailable !== 4489
|
||||
) {
|
||||
throw new M47ReferenceGraphContractError(
|
||||
"M4.7 semantic binding: сервер вернул несвязанный semantic-result.",
|
||||
);
|
||||
}
|
||||
const graphResultId = text(source.graph_result_id, "M4.7 graph result");
|
||||
if (!/^m47-reference-graph-[a-f0-9]{64}$/.test(graphResultId)) {
|
||||
throw new M47ReferenceGraphContractError("M4.7 graph result: нарушена идентичность.");
|
||||
@@ -219,5 +259,6 @@ export async function fetchM47ReferenceGraphLab({
|
||||
queueHighWatermarks: queueWatermarks(metrics.queue_high_watermarks),
|
||||
limitations: stringArray(report.limitations, "M4.7 limitations"),
|
||||
visual,
|
||||
semantic,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user