import type { ReactElement } from "react"; import { useQuery } from "@tanstack/react-query"; import { getSessionDocuments } from "../api/sessions"; import type { SessionDocument } from "../api/types"; import { ArtifactView } from "../viewers/ArtifactView"; import { MarkdownView } from "../viewers/MarkdownView"; import { resolveFileArtifact } from "./gateArtifact"; type ArtifactData = { kind: string; data?: unknown; content?: unknown; [k: string]: unknown }; /** * Body of an artifact-review gate. Most gates embed their content and render via * ArtifactView. A phase-completion gate, however, may carry only a file reference * (e.g. `{ file: "question.md" }`): in that case we fetch the referenced session * document and render its content in full, with the session-relative path as a * quiet trailing line. Anything we cannot resolve falls back to ArtifactView, so * no existing gate regresses. */ export function GateArtifactBody({ artifact, sessionId, }: { artifact: ArtifactData; sessionId?: string; }): ReactElement { const ref = resolveFileArtifact(artifact); if (!sessionId || !ref) return ; return ( } /> ); } function ResolvedDoc({ sessionId, docKey, filename, fallback, }: { sessionId: string; docKey: string; filename: string; fallback: ReactElement; }): ReactElement { const { data: docs, isLoading, isError } = useQuery({ queryKey: ["session-documents", sessionId], queryFn: () => getSessionDocuments(sessionId), }); if (isLoading) return

Loading…

; const doc = docs?.find((d) => d.key === docKey); if (isError || !doc || doc.format !== "markdown") return fallback; return (

sessions/{sessionId}/{filename}

); }