import { useState, type FormEvent } from "react";
import { Link } from "react-router";
import { api, ApiError, type Debt, type Endpoint, type Evidence } from "../api";
import { fmtDate } from "../hooks";
import { Badge, ErrorBox, JsonTree, Td } from "./ui";
export function EvidenceList({ evidence }: { evidence: Evidence[] }) {
if (!evidence.length) return
No machine evidence recorded yet.
;
return (
{[...evidence].reverse().map((e) => (
{e.kind} {fmtDate(e.created_at)} · {e.created_by ?? "system"}
{e.command &&
command: {e.command}
}
{e.output_excerpt &&
{e.output_excerpt} }
{e.output_hash &&
output sha256 {e.output_hash}
}
{Object.keys(e.details ?? {}).length > 0 &&
}
))}
);
}
export function DebtTable({ debt, onChange }: { debt: Debt[]; onChange?: () => void }) {
const [err, setErr] = useState(null);
if (!debt.length) return No knowledge debt.
;
const patch = async (id: string, status: string) => { setErr(null); try { await api(`debt/${id}`, { method: "PATCH", body: { status } }); onChange?.(); } catch (e) { setErr(e as ApiError); } };
return (
Severity Kind Subject Description Remediation Status Created
{debt.map((d) => (
{d.kind}
{d.description} {d.remediation ?? "—"}
{onChange ? patch(d.id, e.target.value)}>{["open", "in_progress", "resolved", "accepted"].map((s) => {s} )} : }
{fmtDate(d.created_at)}
))}
);
}
export function SubjectLink({ type, id, label }: { type: string; id: string; label?: string }) {
const to = type === "akp" ? `/akps/${id}` : type === "api" ? `/apis/${id}` : type === "execution" ? `/executions/${id}` : type === "version" ? `/versions/${id}` : type === "dataset" ? `/datasets/${id}` : null;
const text = label ?? `${type} ${id.slice(0, 8)}`;
return to ? {text} : {text} ;
}
export function LifecycleButtons({ allowed, onTransition }: { allowed: string[]; onTransition: (to: string, reason: string) => Promise }) {
const [err, setErr] = useState(null); const [busy, setBusy] = useState(null); const [reason, setReason] = useState("");
if (!allowed.length) return no transitions available ;
return (
);
}
/** Execute form for one endpoint: query + path params → POST /execute. */
export function ExecuteForm({ endpoint, apiId, packageId, projects }: { endpoint: Endpoint; apiId?: string; packageId?: string; projects: { slug: string; name: string }[] }) {
const [vals, setVals] = useState>(() => Object.fromEntries(endpoint.parameters.filter((p) => p.example !== undefined && p.example !== null).map((p) => [p.name, String(p.example)])));
const [project, setProject] = useState("default"); const [purpose, setPurpose] = useState("");
const [res, setRes] = useState | null>(null); const [err, setErr] = useState(null); const [busy, setBusy] = useState(false);
const submit = async (e: FormEvent) => {
e.preventDefault(); setBusy(true); setErr(null); setRes(null);
const path_params: Record = {}, query: Record = {};
for (const p of endpoint.parameters) { const v = vals[p.name]; if (v === undefined || v === "") continue; (p.in === "path" ? path_params : query)[p.name] = v; }
try { setRes(await api("execute", { body: { project_id: project, api_id: packageId ? undefined : apiId, package_id: packageId, endpoint_id: endpoint.id, operation_id: endpoint.operation_id, method: endpoint.method === "MCP" ? "GET" : endpoint.method, path_params, query, purpose, caller: "ui" } })); }
catch (ex) { const e = ex as ApiError; setErr(e); const p = e.payload as { execution?: Record } | undefined; if (p?.execution) setRes(p.execution); }
finally { setBusy(false); }
};
const ex = res as { id?: string; state?: string; status_code?: number; duration_ms?: number; response_hash?: string; policy_decision?: { decision: string; reasons: string[] } } | null;
return (
);
}
export function EndpointRow({ e, apiId, packageId, projects }: { e: Endpoint; apiId?: string; packageId?: string; projects: { slug: string; name: string }[] }) {
return (
{e.method} {e.path} {e.operation_id} {e.inferred && } {e.summary && — {e.summary} }
Parameters {e.parameters.length ?
Name In Req Schema Description {e.parameters.map((p) => {p.name}{p.in} {p.required ? "yes" : ""} {p.schema?.type ? String(p.schema.type) : "—"}{p.description} )}
:
none }
{Object.keys(e.pagination ?? {}).length > 0 && <>
Pagination >}
Execute
Response schema {e.response_schema ?
:
not documented }
{e.request_schema ? <>
Request schema > : null}
endpoint page →
);
}