321 lines
32 KiB
TypeScript
321 lines
32 KiB
TypeScript
import { FormEvent, useCallback, useEffect, useState } from "react";
|
||
import type { ReactNode } from "react";
|
||
import { Activity, CircleGauge, Clock3, KeyRound, Play, RefreshCw, ShieldCheck } from "lucide-react";
|
||
|
||
import { api, ApiError, operatorCredentialReference } from "../lib/api";
|
||
import { SafetyDialog } from "./SafetyDialog";
|
||
import { TabList, TabPanel } from "./TabList";
|
||
import type { TabDescriptor } from "./TabList";
|
||
import type {
|
||
CapabilityDeployment, CapabilityEstate, DeploymentCandidate, GatewayInvokeResponse,
|
||
GatewayRequest, OCRInvokeResponse, PlacementPlan, ProductionApproval, SchedulerBudget, SchedulerPolicy, ServiceClient,
|
||
ServiceClientCreated, SpeechTranscriptionResponse, VisionEmbeddingResponse,
|
||
} from "../types";
|
||
|
||
type View = "overview" | "scheduler" | "requests" | "clients" | "promotion" | "playground";
|
||
const capabilityViews: TabDescriptor<View>[] = [
|
||
{ key: "overview", label: "overview" }, { key: "scheduler", label: "scheduler" },
|
||
{ key: "requests", label: "requests" }, { key: "clients", label: "clients" },
|
||
{ key: "promotion", label: "promotion" }, { key: "playground", label: "playground" },
|
||
];
|
||
|
||
export function CapabilityWorkspace({ onError }: { onError: (message: string | null) => void }) {
|
||
const sessionReference = operatorCredentialReference();
|
||
const sessionActive = Boolean(sessionReference);
|
||
const [view, setView] = useState<View>("overview");
|
||
const [deployments, setDeployments] = useState<CapabilityDeployment[]>([]);
|
||
const [estate, setEstate] = useState<CapabilityEstate[]>([]);
|
||
const [budgets, setBudgets] = useState<SchedulerBudget[]>([]);
|
||
const [candidates, setCandidates] = useState<DeploymentCandidate[]>([]);
|
||
const [requests, setRequests] = useState<GatewayRequest[]>([]);
|
||
const [clients, setClients] = useState<ServiceClient[]>([]);
|
||
const [approvals, setApprovals] = useState<ProductionApproval[]>([]);
|
||
const [plans, setPlans] = useState<PlacementPlan[]>([]);
|
||
const [policy, setPolicy] = useState<SchedulerPolicy | null>(null);
|
||
const [adminToken, setAdminToken] = useState(sessionReference);
|
||
const [adminUnlocked, setAdminUnlocked] = useState(sessionActive);
|
||
const [loading, setLoading] = useState(true);
|
||
|
||
const loadPublic = useCallback(async () => {
|
||
const [nextDeployments, nextBudgets, nextCandidates, nextEstate] = await Promise.all([
|
||
api.capabilityDeployments(), api.scheduler(), api.deploymentCandidates(), api.capabilityEstate(),
|
||
]);
|
||
setDeployments(nextDeployments);
|
||
setBudgets(nextBudgets);
|
||
setCandidates(nextCandidates);
|
||
setEstate(nextEstate);
|
||
}, []);
|
||
|
||
const loadAdmin = useCallback(async (token: string) => {
|
||
if (!token && !sessionActive) return;
|
||
const [nextRequests, nextClients, nextApprovals, nextPlans, nextPolicy] = await Promise.all([
|
||
api.gatewayRequests(token), api.serviceClients(token), api.productionApprovals(token),
|
||
api.placementHistory(token), api.schedulerPolicy(token),
|
||
]);
|
||
setRequests(nextRequests);
|
||
setClients(nextClients);
|
||
setApprovals(nextApprovals);
|
||
setPlans(nextPlans);
|
||
setPolicy(nextPolicy);
|
||
}, [sessionActive]);
|
||
|
||
useEffect(() => {
|
||
Promise.all([loadPublic(), sessionActive ? loadAdmin(sessionReference) : Promise.resolve()])
|
||
.catch((cause: unknown) => onError(errorMessage(cause)))
|
||
.finally(() => setLoading(false));
|
||
}, [loadAdmin, loadPublic, onError, sessionActive, sessionReference]);
|
||
|
||
useEffect(() => {
|
||
const interval = window.setInterval(() => {
|
||
loadPublic().catch((cause: unknown) => onError(errorMessage(cause)));
|
||
if (adminUnlocked) loadAdmin(adminToken).catch((cause: unknown) => onError(errorMessage(cause)));
|
||
}, 5000);
|
||
return () => window.clearInterval(interval);
|
||
}, [adminToken, adminUnlocked, loadAdmin, loadPublic, onError]);
|
||
|
||
const deployment = deployments.find((item) =>
|
||
item.capability === "rag.embedding" && item.contract_version === 1 && item.production && item.status === "stable",
|
||
) ?? deployments.find((item) => item.capability === "rag.embedding" && item.contract_version === 1);
|
||
const refresh = async () => {
|
||
onError(null);
|
||
try { await Promise.all([loadPublic(), loadAdmin(adminToken)]); }
|
||
catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
const authenticateAdmin = async (event: FormEvent) => {
|
||
event.preventDefault(); onError(null);
|
||
try { await loadAdmin(adminToken); setAdminUnlocked(true); }
|
||
catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
if (loading) return <div className="state-card"><span className="state-spinner" />Loading capability serving state…</div>;
|
||
return <div className="capability-stack">
|
||
<section className="capability-hero panel">
|
||
<div><span className="eyebrow">MULTI-CAPABILITY ESTATE</span><h2>{estate.length} governed contracts</h2><p>Capability-first routing across RAG, document, vision and audio · no client-visible model names</p></div>
|
||
<div className="capability-health"><span className={`status-chip ${deployment && ["healthy", "ready_on_demand"].includes(deployment.health_status) ? "active" : "degraded"}`}>{deployment?.health_status ?? "unavailable"}</span><strong>{deployment?.status ?? "not promoted"}</strong></div>
|
||
</section>
|
||
<div className="capability-toolbar">
|
||
<TabList idPrefix="capability" label="Capability operations" className="capability-tabs" tabs={capabilityViews} active={view} onSelect={setView} />
|
||
<button className="icon-action" aria-label="Refresh capability state" onClick={refresh}><RefreshCw size={15} /></button>
|
||
</div>
|
||
<TabPanel idPrefix="capability" active={view} className="capability-tabpanel">
|
||
{view === "overview" ? <CapabilityOverview deployment={deployment} requests={requests} estate={estate} /> : null}
|
||
{view === "scheduler" ? <><SchedulerView budgets={budgets} deployments={deployments} plans={plans} policy={policy} token={adminToken} unlocked={adminUnlocked} onChanged={refresh} onError={onError} /><AdminBoundary unlocked={adminUnlocked} token={adminToken} onToken={setAdminToken} onSubmit={authenticateAdmin}><></></AdminBoundary></> : null}
|
||
{view === "requests" ? <AdminBoundary unlocked={adminUnlocked} token={adminToken} onToken={setAdminToken} onSubmit={authenticateAdmin}><RequestHistory requests={requests} /></AdminBoundary> : null}
|
||
{view === "clients" ? <AdminBoundary unlocked={adminUnlocked} token={adminToken} onToken={setAdminToken} onSubmit={authenticateAdmin}><Clients clients={clients} token={adminToken} onChanged={() => loadAdmin(adminToken)} onError={onError} /></AdminBoundary> : null}
|
||
{view === "promotion" ? <AdminBoundary unlocked={adminUnlocked} token={adminToken} onToken={setAdminToken} onSubmit={authenticateAdmin}><Promotion deployment={deployment} candidates={candidates} approvals={approvals} token={adminToken} onChanged={refresh} onError={onError} /></AdminBoundary> : null}
|
||
{view === "playground" ? <Playground /> : null}
|
||
</TabPanel>
|
||
</div>;
|
||
}
|
||
|
||
function CapabilityOverview({ deployment, requests, estate }: { deployment?: CapabilityDeployment; requests: GatewayRequest[]; estate: CapabilityEstate[] }) {
|
||
if (!estate.length) return <div className="state-card">No capability contracts are registered.</div>;
|
||
const successful = requests.filter((item) => item.status === "completed");
|
||
const warmHits = successful.filter((item) => item.cold === false).length;
|
||
return <>
|
||
<section className="project-grid">{estate.map((item) => <article className="panel project-card" key={`${item.capability}@${item.version}`}><span className="eyebrow">{item.category} · {item.resource_class}</span><h2>{item.capability}@{item.version}</h2><p>{item.purpose}</p><div className="binding-list"><div><span>State</span><strong>{item.operational_state}</strong></div><div><span>Evaluation</span><strong>{item.evaluation_state}</strong></div><div><span>Privacy</span><strong>{item.privacy_class}</strong></div><div><span>Consumers</span><strong>{item.consumers.join(", ") || "none declared"}</strong></div></div></article>)}</section>
|
||
{!deployment ? <div className="state-card">No stable deployment exists. New modality capabilities remain LAB-only.</div> : <>
|
||
<section className="metrics-grid capability-metrics">
|
||
<CapabilityMetric label="Channel" value={deployment.channel} hint={deployment.production ? "Production approved" : "Not production"} />
|
||
<CapabilityMetric label="Residency" value={deployment.residency.state} hint={`${deployment.residency.load_count} measured loads`} />
|
||
<CapabilityMetric label="GPU envelope" value={formatBytes(deployment.resource_envelope.required_vram_bytes)} hint="Measured, not estimated" />
|
||
<CapabilityMetric label="Queue" value={String(Math.max(0, requests.filter((item) => item.status === "queued").length))} hint={`Bounded at ${deployment.max_queue_depth}`} />
|
||
<CapabilityMetric label="Requests" value={String(requests.length)} hint="Bounded visible history" />
|
||
<CapabilityMetric label="Warm hit rate" value={successful.length ? `${Math.round((warmHits / successful.length) * 100)}%` : "No data"} hint="Only completed visible requests" />
|
||
</section>
|
||
<section className="grid-two">
|
||
<article className="panel evidence-list"><div className="panel-header"><div><span className="eyebrow">CONTRACT</span><h2>Backend-authoritative boundary</h2></div><ShieldCheck size={19} /></div><Evidence label="Input modality" value="text"/><Evidence label="Output modality" value="vector"/><Evidence label="Dimension / normalized" value={`${deployment.embedding_space.dimension} / ${deployment.embedding_space.normalized}`}/><Evidence label="Migration" value={deployment.embedding_space.migration_class}/><Evidence label="Retention" value="No request content persisted"/></article>
|
||
<article className="panel evidence-list"><div className="panel-header"><div><span className="eyebrow">RESIDENCY</span><h2>Load-on-demand state</h2></div><Activity size={19} /></div><Evidence label="Policy" value={`${deployment.residency_policy} · ${deployment.keep_warm_seconds}s`}/><Evidence label="State" value={deployment.residency.state}/><Evidence label="Active requests" value={String(deployment.residency.active_requests)}/><Evidence label="Resident since" value={formatTime(deployment.residency.resident_since)}/><Evidence label="Embedding space" value={deployment.embedding_space.id}/></article>
|
||
</section>
|
||
</>}</>;
|
||
}
|
||
|
||
function SchedulerView({ budgets, deployments, plans, policy, token, unlocked, onChanged, onError }: { budgets: SchedulerBudget[]; deployments: CapabilityDeployment[]; plans: PlacementPlan[]; policy: SchedulerPolicy | null; token: string; unlocked: boolean; onChanged: () => Promise<void>; onError: (message: string | null) => void }) {
|
||
const [latest, setLatest] = useState<Record<string, PlacementPlan>>({});
|
||
const [pendingUnload, setPendingUnload] = useState<CapabilityDeployment | null>(null);
|
||
const [unloadAcknowledged, setUnloadAcknowledged] = useState(false);
|
||
const [unloadPending, setUnloadPending] = useState(false);
|
||
const [unloadError, setUnloadError] = useState<string | null>(null);
|
||
const [unloadOutcome, setUnloadOutcome] = useState<string | null>(null);
|
||
if (!budgets.length) return <div className="state-card">No accelerator telemetry is available for scheduling.</div>;
|
||
const simulate = async (deploymentId: string) => {
|
||
try { const plan = await api.dryRunPlacement(deploymentId, "interactive", token); setLatest((current) => ({ ...current, [deploymentId]: plan })); }
|
||
catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
const previewUnload = (deployment: CapabilityDeployment) => {
|
||
setUnloadAcknowledged(false); setUnloadError(null); setUnloadOutcome(null); setPendingUnload(deployment);
|
||
};
|
||
const confirmUnload = async (deployment: CapabilityDeployment) => {
|
||
// Guarded against a replayed handler so one acknowledgement can never evict residency twice.
|
||
if (unloadPending) return;
|
||
setUnloadPending(true); setUnloadError(null);
|
||
try {
|
||
await api.unloadDeployment(deployment.id, token);
|
||
setPendingUnload(null); setUnloadAcknowledged(false);
|
||
setUnloadOutcome(`Residency for ${deployment.capability}@${deployment.contract_version} was unloaded.`);
|
||
await onChanged();
|
||
} catch (cause: unknown) { setUnloadError(errorMessage(cause)); }
|
||
finally { setUnloadPending(false); }
|
||
};
|
||
const changePolicy = async (deployment: CapabilityDeployment, value: string) => {
|
||
try { await api.updateResidencyPolicy(deployment.id, value, token); await onChanged(); }
|
||
catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
const pauseLab = async () => {
|
||
try { await api.updateSchedulerPolicy(!Boolean(policy?.configuration.lab_paused), token); await onChanged(); }
|
||
catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
return <div className="capability-stack"><section className="scheduler-grid">{budgets.map((budget) => {
|
||
const segments = [
|
||
["External / unmanaged", budget.external_vram_bytes], ["Safety reserve", budget.safety_reserve_bytes],
|
||
["ModelForge resident", budget.resident_vram_bytes], ["Active leases", budget.leased_vram_bytes],
|
||
["Schedulable free", budget.schedulable_free_vram_bytes],
|
||
] as const;
|
||
return <article className="panel scheduler-card" key={budget.accelerator_id}><div className="panel-header"><div><span className="eyebrow">GPU SCHEDULING COCKPIT · {budget.node_name}</span><h2>{budget.accelerator_name}</h2></div><span className={`status-chip ${budget.pressure_state === "NORMAL" ? "active" : "degraded"}`}>{budget.pressure_state}</span></div><div className="budget-total"><strong>{formatBytes(budget.total_vram_bytes)}</strong><span>Total VRAM · attribution {budget.attribution_confidence}</span></div><div className="budget-bar" aria-label="GPU capacity distribution">{segments.map(([label, bytes], index) => <span key={label} className={`budget-segment segment-${index}`} style={{ width: `${Math.min(100, (bytes / budget.total_vram_bytes) * 100)}%` }} title={`${label}: ${formatBytes(bytes)}`} />)}</div><div className="budget-legend">{segments.map(([label, bytes]) => <Evidence key={label} label={label} value={formatBytes(bytes)} />)}</div><small>Observed {formatBytes(budget.observed_used_vram_bytes)} · invariant delta {formatBytes(budget.invariant_delta_bytes)} · policy {budget.policy_revision} · telemetry {formatTime(budget.observed_at)}. External usage is observation-only and has no controls.</small></article>;
|
||
})}</section>{unlocked ? <><article className="panel evidence-list"><div className="panel-header"><div><span className="eyebrow">RESIDENCY MAP · WHAT CAN RUN NOW?</span><h2>Managed capability placements</h2></div><button onClick={pauseLab}>{Boolean(policy?.configuration.lab_paused) ? "Resume LAB" : "Pause LAB"}</button></div>{deployments.map((item) => { const plan = latest[item.id]; return <div className="client-row" key={item.id}><div><strong>{item.capability}@{item.contract_version} · {item.residency.state.toUpperCase()}</strong><span>{item.production ? "production" : "lab"} · {formatBytes(item.residency.measured_resident_vram_bytes)} · {item.residency.active_requests} active · cold load {formatMs(item.resource_envelope.cold_load_time_ms)}</span>{plan ? <span>{plan.verdict} · {plan.reason_codes.join(", ")} · after {formatBytes(plan.headroom_after_bytes)}{plan.evictions.length ? ` · evict ${plan.evictions.map((entry) => entry.capability).join(", ")}` : ""}</span> : null}</div><div className="promotion-actions"><button onClick={() => simulate(item.id)}>Dry run</button><select aria-label={`Residency policy for ${item.capability}`} value={item.residency_policy} onChange={(event) => changePolicy(item, event.target.value)}><option value="always_warm">ALWAYS_WARM</option><option value="keep_warm">KEEP_WARM</option><option value="load_on_demand">LOAD_ON_DEMAND</option><option value="lab_only">LAB_ONLY</option></select><button className="danger" disabled={item.residency.active_requests > 0 || item.residency.state === "cold"} onClick={() => previewUnload(item)}>Unload idle</button></div></div>; })}</article><article className="panel evidence-list"><div className="panel-header"><div><span className="eyebrow">PLACEMENT HISTORY</span><h2>Recent bounded decisions</h2></div><CircleGauge size={19}/></div>{plans.slice(0, 20).map((plan) => <Evidence key={plan.id ?? plan.decision_fingerprint} label={`${plan.capability} · ${plan.verdict}`} value={`${plan.reason_codes.join(", ")} · ${formatBytes(plan.headroom_before_bytes)} → ${formatBytes(plan.headroom_after_bytes)} · ${formatTime(plan.created_at)}`}/>)}</article></> : null}
|
||
{unloadOutcome ? <p className="field-success" role="status">{unloadOutcome}</p> : null}
|
||
{pendingUnload ? <SafetyDialog
|
||
idPrefix="residency-unload"
|
||
eyebrow="DESTRUCTIVE ACTION PREVIEW"
|
||
title="Unload idle residency?"
|
||
subject={`${pendingUnload.capability}@${pendingUnload.contract_version}`}
|
||
description="ModelForge will evict this deployment from accelerator memory. Serving is not withdrawn: the next request reloads the model and pays the cold-load cost. Residency is unloaded only while no request is active."
|
||
facts={[
|
||
{ label: "Channel", value: pendingUnload.production ? "production" : "lab" },
|
||
{ label: "Residency state", value: pendingUnload.residency.state },
|
||
{ label: "Active requests", value: String(pendingUnload.residency.active_requests) },
|
||
{ label: "Resident VRAM released", value: formatBytes(pendingUnload.residency.measured_resident_vram_bytes) },
|
||
{ label: "Next cold load", value: formatMs(pendingUnload.resource_envelope.cold_load_time_ms) },
|
||
]}
|
||
acknowledgement="I understand the next request for this capability will pay the cold-load cost."
|
||
confirmLabel="Unload residency"
|
||
acknowledged={unloadAcknowledged}
|
||
onAcknowledgedChange={setUnloadAcknowledged}
|
||
pending={unloadPending}
|
||
errorTitle="Unload blocked"
|
||
error={unloadError}
|
||
closeLabel="Close residency unload preview"
|
||
onCancel={() => setPendingUnload(null)}
|
||
onConfirm={() => void confirmUnload(pendingUnload)}
|
||
/> : null}</div>;
|
||
}
|
||
|
||
function RequestHistory({ requests }: { requests: GatewayRequest[] }) {
|
||
if (!requests.length) return <div className="state-card">No gateway request metadata exists yet. Input text is never displayed or persisted.</div>;
|
||
return <article className="panel table-panel"><div className="panel-header"><div><span className="eyebrow">PRIVACY-PRESERVING HISTORY</span><h2>Gateway requests</h2></div><Clock3 size={19}/></div><div className="operation-table"><div className="table-head"><span>Request</span><span>Client</span><span>State</span><span>Path</span><span>Queue</span><span>Total</span><span>Time</span></div>{requests.map((request) => <div className="table-row" key={request.request_id}><code>{request.request_id.slice(0, 8)}…</code><span>{request.client ?? "rejected identity"}</span><span className={`registry-status ${request.status}`}>{request.failure_code ?? request.status}</span><span>{request.cold == null ? "—" : request.cold ? "cold" : "warm"}</span><span>{formatMs(request.queue_time_ms)}</span><span>{formatMs(request.total_latency_ms)}</span><span>{formatTime(request.created_at)}</span></div>)}</div></article>;
|
||
}
|
||
|
||
function Clients({ clients, token, onChanged, onError }: { clients: ServiceClient[]; token: string; onChanged: () => Promise<void>; onError: (message: string | null) => void }) {
|
||
const [name, setName] = useState("modelforge-m5-acceptance");
|
||
const [rpm, setRpm] = useState(60);
|
||
const [created, setCreated] = useState<ServiceClientCreated | null>(null);
|
||
const submit = async (event: FormEvent) => {
|
||
event.preventDefault(); onError(null);
|
||
try { setCreated(await api.createServiceClient({ name, allowed_capabilities: ["rag.embedding@1"], requests_per_minute: rpm, max_concurrent_requests: 1 }, token)); await onChanged(); }
|
||
catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
const revoke = async (clientId: string) => {
|
||
onError(null);
|
||
try { await api.revokeServiceCredential(clientId, token); await onChanged(); }
|
||
catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
return <section className="grid-two"><form className="panel client-form" onSubmit={submit}><span className="eyebrow">SCOPED IDENTITY</span><h2>Create service client</h2><label>Name<input required pattern="[a-z][a-z0-9-]*" value={name} onChange={(event) => setName(event.target.value)} /></label><label>Requests per minute<input type="number" min="1" max="10000" value={rpm} onChange={(event) => setRpm(Number(event.target.value))} /></label><p>Scope is fixed to <code>rag.embedding@1</code>; concurrency starts conservatively at one.</p><button type="submit"><KeyRound size={15}/>Create one-time credential</button>{created ? <div className="one-time-secret"><strong>Copy this credential now</strong><code>{created.credential}</code><small>Only its hash is stored. It cannot be retrieved again.</small></div> : null}</form><article className="panel evidence-list"><div className="panel-header"><div><span className="eyebrow">CLIENTS</span><h2>Authorized consumers</h2></div><KeyRound size={19}/></div>{clients.length ? clients.map((client) => <div className="client-row" key={client.id}><div><strong>{client.name}</strong><span>{client.allowed_capabilities.join(", ")} · {client.requests_per_minute}/min · last used {formatTime(client.last_used_at)}</span></div><button className="danger" disabled={client.status !== "active"} onClick={() => revoke(client.id)}>{client.status === "active" ? "Revoke" : "Revoked"}</button></div>) : <p>No service clients created.</p>}</article></section>;
|
||
}
|
||
|
||
function Promotion({ deployment, candidates, approvals, token, onChanged, onError }: { deployment?: CapabilityDeployment; candidates: DeploymentCandidate[]; approvals: ProductionApproval[]; token: string; onChanged: () => Promise<void>; onError: (message: string | null) => void }) {
|
||
const candidate = candidates[0];
|
||
const approval = approvals.find((item) => item.deployment_candidate_id === candidate?.id);
|
||
const reviewItems = [
|
||
["exact_revision_reviewed", "Exact upstream revision and resolved commit reviewed"],
|
||
["artifact_hashes_reviewed", "Local artifact SHA-256 digests reviewed"],
|
||
["safetensors_only", "Artifact set contains safetensors only"],
|
||
["remote_code_required", "No remote repository code is required"],
|
||
["pickle_present", "No pickle payload is present"],
|
||
["scanner_evidence_reviewed", "Supply-chain scanner evidence reviewed"],
|
||
["provenance_complete", "Artifact and derivation provenance is complete"],
|
||
["runtime_offline_reviewed", "Offline runtime behavior reviewed"],
|
||
["dependency_provenance_reviewed", "Runtime dependency provenance reviewed"],
|
||
["license_reviewed", "License evidence and production use reviewed"],
|
||
] as const;
|
||
const [reviewed, setReviewed] = useState<Record<string, boolean>>({});
|
||
const [licenseIdentifier, setLicenseIdentifier] = useState("");
|
||
const reviewComplete = reviewItems.every(([key]) => reviewed[key]) && licenseIdentifier.trim().length > 0;
|
||
const evidence = deployment ? [
|
||
["Artifact integrity", "verified"], ["Supply chain", "production approved"],
|
||
["Runtime probe", String(deployment.provenance.runtime_probe_id ?? "bound")],
|
||
["Compatibility", String(deployment.provenance.compatibility_assessment_id ?? "bound")],
|
||
["Resource envelope", `${formatBytes(deployment.resource_envelope.required_vram_bytes)} · ${deployment.resource_envelope.stale ? "stale" : "current"}`],
|
||
["Node eligibility", "production eligible"], ["Capability contract", "rag.embedding@1"],
|
||
["Migration class", deployment.embedding_space.migration_class], ["Production approval", deployment.production_approval_id],
|
||
] : [];
|
||
const approve = async () => {
|
||
if (!candidate) return;
|
||
onError(null);
|
||
try {
|
||
await api.approveProduction(candidate.id, { approved_by: "operator-ui", reason: "Exact production evidence explicitly reviewed and accepted by operator.", supply_chain_review: { exact_revision_reviewed: true, artifact_hashes_reviewed: true, safetensors_only: true, remote_code_required: false, pickle_present: false, scanner_evidence_reviewed: true, provenance_complete: true, runtime_offline_reviewed: true, dependency_provenance_reviewed: true, license_reviewed: true, license_identifier: licenseIdentifier.trim() }, deployment_config: { capability: "rag.embedding@1", max_concurrency: 1 } }, token);
|
||
await onChanged();
|
||
} catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
const promote = async () => {
|
||
if (!candidate || !approval) return;
|
||
onError(null);
|
||
try { await api.promoteCandidate(candidate.id, { production_approval_id: approval.id, residency_policy: "keep_warm", keep_warm_seconds: 900, max_concurrency: 1, max_queue_depth: 16, routing_weight: 100 }, token); await onChanged(); }
|
||
catch (cause: unknown) { onError(errorMessage(cause)); }
|
||
};
|
||
return <article className="panel evidence-list"><div className="panel-header"><div><span className="eyebrow">AUDITED PRODUCTION GATE</span><h2>Promotion evidence</h2></div><ShieldCheck size={20}/></div>{deployment ? evidence.map(([label, value]) => <Evidence key={label} label={label} value={value}/>) : <><p>No stable deployment exists. Promotion remains two explicit, audited actions.</p><Evidence label="LAB_READY candidate" value={candidate?.id ?? "none"}/><Evidence label="Production approval" value={approval?.status ?? "required"}/>{candidate && !approval ? <details className="promotion-review" open><summary>Review the evidence being attested</summary><p>ModelForge records only claims the operator explicitly confirms below. Verify each claim in Registry, Runtime and Evaluation before approval.</p><div className="promotion-checklist">{reviewItems.map(([key, label]) => <label key={key}><input type="checkbox" checked={Boolean(reviewed[key])} onChange={(event) => setReviewed((current) => ({ ...current, [key]: event.target.checked }))}/><span>{label}</span></label>)}</div><label className="license-review">Reviewed license identifier<input value={licenseIdentifier} onChange={(event) => setLicenseIdentifier(event.target.value)} placeholder="For example: Apache-2.0" /></label></details> : null}<div className="promotion-actions"><button onClick={approve} disabled={!candidate || Boolean(approval) || !reviewComplete}>1. Record reviewed approval</button><button onClick={promote} disabled={!candidate || !approval}>2. Promote exact binding</button></div></>}</article>;
|
||
}
|
||
|
||
type ModalityResult = GatewayInvokeResponse | OCRInvokeResponse | VisionEmbeddingResponse | SpeechTranscriptionResponse;
|
||
|
||
async function fileBase64(file: File): Promise<string> {
|
||
const bytes = new Uint8Array(await file.arrayBuffer());
|
||
let binary = "";
|
||
for (const byte of bytes) binary += String.fromCharCode(byte);
|
||
return btoa(binary);
|
||
}
|
||
|
||
function Playground() {
|
||
const [capability, setCapability] = useState<"rag.embedding" | "document.ocr" | "vision.embedding" | "speech.transcription">("rag.embedding");
|
||
const [credential, setCredential] = useState("");
|
||
const [input, setInput] = useState("ModelForge capability gateway test");
|
||
const [file, setFile] = useState<File | null>(null);
|
||
const [result, setResult] = useState<ModalityResult | null>(null);
|
||
const [failure, setFailure] = useState<string | null>(null);
|
||
const [running, setRunning] = useState(false);
|
||
const invoke = async (event: FormEvent) => {
|
||
event.preventDefault(); setFailure(null); setRunning(true);
|
||
try {
|
||
if (capability === "rag.embedding") setResult(await api.invokeEmbedding(input, credential));
|
||
else {
|
||
if (!file) throw new Error("Choose a local fixture first");
|
||
const encoded = await fileBase64(file);
|
||
if (capability === "document.ocr") {
|
||
if (file.type !== "image/png" && file.type !== "image/jpeg") throw new Error("OCR accepts PNG or JPEG");
|
||
setResult(await api.invokeOcr(encoded, file.type, credential));
|
||
} else if (capability === "vision.embedding") {
|
||
if (file.type !== "image/png" && file.type !== "image/jpeg") throw new Error("Vision accepts PNG or JPEG");
|
||
setResult(await api.invokeVisionEmbedding(encoded, file.type, credential));
|
||
} else {
|
||
if (file.type !== "audio/wav" && !file.name.toLowerCase().endsWith(".wav")) throw new Error("Transcription accepts WAV");
|
||
setResult(await api.invokeTranscription(encoded, credential));
|
||
}
|
||
}
|
||
}
|
||
catch (cause: unknown) { setFailure(errorMessage(cause)); }
|
||
finally { setRunning(false); }
|
||
};
|
||
const output = result ? ("data" in result ? `${result.data.length} × ${result.dimension} finite values` : "text" in result ? result.text || "valid empty text" : "typed output") : "";
|
||
return <form className="panel playground" onSubmit={invoke}><div className="panel-header"><div><span className="eyebrow">REAL GATEWAY PATH</span><h2>Capability playground</h2></div><Play size={20}/></div><p>The client selects a capability contract. No model name, path, or runtime engine is accepted here.</p><label>Capability<select value={capability} onChange={(event) => { setCapability(event.target.value as typeof capability); setResult(null); }}><option value="rag.embedding">rag.embedding@1</option><option value="document.ocr">document.ocr@1</option><option value="vision.embedding">vision.embedding@1</option><option value="speech.transcription">speech.transcription@1</option></select></label><label>Service credential<input required type="password" autoComplete="off" value={credential} onChange={(event) => setCredential(event.target.value)} /></label>{capability === "rag.embedding" ? <label>Input text<textarea required maxLength={8192} value={input} onChange={(event) => setInput(event.target.value)} /></label> : <label>{capability === "speech.transcription" ? "WAV audio" : "PNG or JPEG image"}<input required type="file" accept={capability === "speech.transcription" ? ".wav,audio/wav" : "image/png,image/jpeg"} onChange={(event) => setFile(event.target.files?.[0] ?? null)} /></label>}<button disabled={running}>{running ? "Invoking…" : "Invoke capability"}</button>{failure ? <div className="error-banner"><strong>Typed gateway failure</strong><span>{failure}</span></div> : null}{result ? <div className="playground-result"><span className={`registry-status ${result.execution.cold ? "candidate" : "ready"}`}>{result.execution.cold ? "cold" : "warm"}</span><Evidence label="Request ID" value={result.request_id}/><Evidence label="Output" value={output}/>{"embedding_space_id" in result ? <Evidence label="Embedding space" value={result.embedding_space_id}/> : null}<Evidence label="Total / inference" value={`${formatMs(result.execution.timings.total_ms)} / ${formatMs(result.execution.timings.inference_ms)}`}/></div> : null}</form>;
|
||
}
|
||
|
||
function AdminBoundary({ unlocked, token, onToken, onSubmit, children }: { unlocked: boolean; token: string; onToken: (value: string) => void; onSubmit: (event: FormEvent) => Promise<void>; children: ReactNode }) {
|
||
if (unlocked) return <>{children}</>;
|
||
return <form className="panel admin-boundary" onSubmit={onSubmit}><ShieldCheck size={22}/><div><h2>Operator authentication required</h2><p>Administrative data and actions require the operator credential. It remains in browser memory only.</p></div><label htmlFor="capability-operator-key">Operator API key</label><input id="capability-operator-key" name="operator-api-key" required type="password" autoComplete="off" value={token} onChange={(event) => onToken(event.target.value)} /><button type="submit">Unlock operational view</button></form>;
|
||
}
|
||
|
||
function CapabilityMetric({ label, value, hint }: { label: string; value: string; hint: string }) { return <article className="metric-card"><span>{label}</span><strong>{value}</strong><small>{hint}</small></article>; }
|
||
function Evidence({ label, value }: { label: string; value: string }) { return <div className="evidence-row"><span>{label}</span><strong title={value}>{value}</strong></div>; }
|
||
function formatBytes(value: number): string { return `${(value / 1024 ** 3).toFixed(2)} GiB`; }
|
||
function formatMs(value?: number | null): string { return value == null ? "—" : `${value.toFixed(1)} ms`; }
|
||
function formatTime(value?: string | null): string { return value ? new Date(value).toLocaleString() : "never"; }
|
||
function errorMessage(cause: unknown): string { return cause instanceof ApiError ? `${cause.message}${typeof cause.details.failure_code === "string" ? ` (${cause.details.failure_code})` : ""}` : cause instanceof Error ? cause.message : "Capability operation failed"; }
|