Add operator user agent and video recorder
This commit is contained in:
@@ -311,6 +311,24 @@ type ValidationAgentPayload = {
|
||||
checks: AgentCheck[];
|
||||
};
|
||||
|
||||
type UserAgentPayload = {
|
||||
available?: boolean;
|
||||
agent: string;
|
||||
passed: boolean;
|
||||
run_id?: string;
|
||||
created_at?: string;
|
||||
dataset?: {
|
||||
name: string;
|
||||
root: string;
|
||||
license: string;
|
||||
counts: { images: number; labels: number; masks: number; annotations: number };
|
||||
pairs: { image_label: number; image_mask: number };
|
||||
yaml: string;
|
||||
};
|
||||
checks?: AgentCheck[];
|
||||
suggestions?: string[];
|
||||
};
|
||||
|
||||
type PageId = "overview" | "datasets" | "training" | "inference" | "results" | "system" | "agents";
|
||||
|
||||
type ModelWeightOption = {
|
||||
@@ -425,11 +443,12 @@ function useData() {
|
||||
const [runtimeReadiness, setRuntimeReadiness] = useState<RuntimeReadinessPayload | null>(null);
|
||||
const [capabilities, setCapabilities] = useState<CapabilityPayload | null>(null);
|
||||
const [agentEvaluation, setAgentEvaluation] = useState<EvaluationAgentPayload | null>(null);
|
||||
const [userAgent, setUserAgent] = useState<UserAgentPayload | null>(null);
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
const [catalogNext, gpusNext, envsNext, readinessNext, capabilitiesNext, jobsNext, resultsNext, curvesNext, weightsNext, datasetsNext, coverageNext, acceptanceNext, realAcceptanceNext, realTrainAcceptanceNext, deepAcceptanceNext, agentEvaluationNext] = await Promise.all([
|
||||
const [catalogNext, gpusNext, envsNext, readinessNext, capabilitiesNext, jobsNext, resultsNext, curvesNext, weightsNext, datasetsNext, coverageNext, acceptanceNext, realAcceptanceNext, realTrainAcceptanceNext, deepAcceptanceNext, agentEvaluationNext, userAgentNext] = await Promise.all([
|
||||
api<Catalog>("/api/catalog"),
|
||||
api<GpuPayload>("/api/system/gpus"),
|
||||
api<CondaEnvPayload>("/api/system/envs"),
|
||||
@@ -445,7 +464,8 @@ function useData() {
|
||||
api<AcceptancePayload>("/api/acceptance/real/latest"),
|
||||
api<AcceptancePayload>("/api/acceptance/real-train/latest"),
|
||||
api<DeepAcceptancePayload>("/api/acceptance/deep/latest"),
|
||||
api<EvaluationAgentPayload>("/api/agents/evaluate")
|
||||
api<EvaluationAgentPayload>("/api/agents/evaluate"),
|
||||
api<UserAgentPayload>("/api/agents/user/latest")
|
||||
]);
|
||||
setCatalog(catalogNext);
|
||||
setGpus(gpusNext);
|
||||
@@ -475,6 +495,7 @@ function useData() {
|
||||
setRealTrainAcceptance(realTrainAcceptanceNext);
|
||||
setDeepAcceptance(deepAcceptanceNext);
|
||||
setAgentEvaluation(agentEvaluationNext);
|
||||
setUserAgent(userAgentNext);
|
||||
setError("");
|
||||
} catch (err) {
|
||||
setError(String(err));
|
||||
@@ -487,7 +508,7 @@ function useData() {
|
||||
return () => window.clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
return { catalog, gpus, condaEnvs, runtimeReadiness, capabilities, agentEvaluation, jobs, results, curves, weightManifest, datasets, datasetValidations, coverage, acceptance, realAcceptance, realTrainAcceptance, deepAcceptance, error, refresh };
|
||||
return { catalog, gpus, condaEnvs, runtimeReadiness, capabilities, agentEvaluation, userAgent, jobs, results, curves, weightManifest, datasets, datasetValidations, coverage, acceptance, realAcceptance, realTrainAcceptance, deepAcceptance, error, refresh };
|
||||
}
|
||||
|
||||
function StatusPill({ status }: { status: string }) {
|
||||
@@ -510,7 +531,7 @@ function JobProgressBar({ progress }: { progress?: JobProgress }) {
|
||||
}
|
||||
|
||||
function App() {
|
||||
const { catalog, gpus, condaEnvs, runtimeReadiness, capabilities, agentEvaluation, jobs, results, curves, weightManifest, datasets, datasetValidations, coverage, acceptance, realAcceptance, realTrainAcceptance, deepAcceptance, error, refresh } = useData();
|
||||
const { catalog, gpus, condaEnvs, runtimeReadiness, capabilities, agentEvaluation, userAgent, jobs, results, curves, weightManifest, datasets, datasetValidations, coverage, acceptance, realAcceptance, realTrainAcceptance, deepAcceptance, error, refresh } = useData();
|
||||
const [page, setPage] = useState<PageId>(pageFromHash);
|
||||
const [taskType, setTaskType] = useState("mock.echo");
|
||||
const [params, setParams] = useState(JSON.stringify(defaultParams["mock.echo"], null, 2));
|
||||
@@ -530,6 +551,7 @@ function App() {
|
||||
const [agentValidation, setAgentValidation] = useState<ValidationAgentPayload | null>(null);
|
||||
const [weightVerification, setWeightVerification] = useState<WeightVerifyPayload | null>(null);
|
||||
const [agentBusy, setAgentBusy] = useState(false);
|
||||
const [userAgentBusy, setUserAgentBusy] = useState(false);
|
||||
const [selectedInferenceWeight, setSelectedInferenceWeight] = useState("");
|
||||
const [inferenceSourcePath, setInferenceSourcePath] = useState("");
|
||||
const [inferenceModelKey, setInferenceModelKey] = useState("YOLO11n-seg");
|
||||
@@ -801,6 +823,16 @@ function App() {
|
||||
}
|
||||
}
|
||||
|
||||
async function runUserAgent() {
|
||||
setUserAgentBusy(true);
|
||||
try {
|
||||
await api<UserAgentPayload>("/api/agents/user", { method: "POST" });
|
||||
await refresh();
|
||||
} finally {
|
||||
setUserAgentBusy(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function createDataset() {
|
||||
setBusy(true);
|
||||
try {
|
||||
@@ -1489,7 +1521,7 @@ function App() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="grid two" id="agents" data-page-section="agents">
|
||||
<section className="grid three" id="agents" data-page-section="agents">
|
||||
<div className="panel agentPanel">
|
||||
<div className="panelHead">
|
||||
<div>
|
||||
@@ -1526,6 +1558,36 @@ function App() {
|
||||
</div>
|
||||
<AgentCheckList checks={agentValidation?.checks ?? []} limit={18} />
|
||||
</div>
|
||||
|
||||
<div className="panel agentPanel userAgentPanel">
|
||||
<div className="panelHead">
|
||||
<div>
|
||||
<p className="eyebrow">User Agent</p>
|
||||
<h2>使用者模拟</h2>
|
||||
</div>
|
||||
<button className="primary secondary" disabled={userAgentBusy} onClick={runUserAgent}>
|
||||
<Boxes size={17} />运行
|
||||
</button>
|
||||
</div>
|
||||
<div className="agentScore">
|
||||
<strong>{userAgent?.available === false ? "New" : userAgent?.passed ? "OK" : "Check"}</strong>
|
||||
<span>{userAgent?.run_id ? `run ${userAgent.run_id}` : "生成合成开源数据并走完整数据集流程"}</span>
|
||||
</div>
|
||||
{userAgent?.dataset && (
|
||||
<div className="userAgentDataset">
|
||||
<div><span>Dataset</span><strong>{userAgent.dataset.name}</strong></div>
|
||||
<div><span>Pairs</span><strong>{userAgent.dataset.pairs.image_label}/{userAgent.dataset.pairs.image_mask}</strong></div>
|
||||
<div><span>Annotations</span><strong>{userAgent.dataset.counts.annotations}</strong></div>
|
||||
<a href={`${API_BASE}/api/artifacts/${userAgent.dataset.yaml}`} target="_blank" rel="noreferrer">dataset.yaml</a>
|
||||
</div>
|
||||
)}
|
||||
<div className="suggestionList">
|
||||
{(userAgent?.suggestions ?? ["等待使用者 agent 运行。"]).slice(0, 3).map((item, index) => (
|
||||
<div key={`${index}-${item}`}>{item}</div>
|
||||
))}
|
||||
</div>
|
||||
<AgentCheckList checks={userAgent?.checks ?? []} limit={10} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="grid four" data-page-section="system">
|
||||
|
||||
@@ -990,6 +990,44 @@ textarea {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.userAgentDataset {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.userAgentDataset div,
|
||||
.userAgentDataset a {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
padding: 9px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--line);
|
||||
background: #101310;
|
||||
color: var(--ink);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.userAgentDataset span,
|
||||
.userAgentDataset strong,
|
||||
.userAgentDataset a {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.userAgentDataset span {
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.userAgentDataset a {
|
||||
color: var(--green);
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.datasetCard {
|
||||
width: 100%;
|
||||
display: block;
|
||||
@@ -1842,7 +1880,8 @@ meter {
|
||||
.pipelineExample,
|
||||
.pipelineSteps,
|
||||
.pipelineStats,
|
||||
.inferencePreview {
|
||||
.inferencePreview,
|
||||
.userAgentDataset {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
@@ -1902,5 +1941,6 @@ meter {
|
||||
.coverageGrid,
|
||||
.taskCheckList { grid-template-columns: 1fr; }
|
||||
.grid.three { grid-template-columns: 1fr; }
|
||||
.shell[data-page="agents"] .grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
.grid.two { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user