import React, { useState, useEffect } from "react";
import { api, fmt } from "../../api/client";
import { useStorySimulation } from "../../hooks/useStorySimulation";
import { TrainingTabV2 } from "./TrainingTabV2";
// --- Timeline Tab -------------------------------------------------------------
const PHASE_LABELS = {
early: { label: "Early Phase", color: "indigo", icon: "flag", desc: "Agent explores the environment and initial decisions are made." },
middle: { label: "Mid-Phase", color: "amber", icon: "timeline", desc: "Policy adapts as patterns emerge in the backlog." },
late: { label: "Final Phase", color: "violet", icon: "sports_score", desc: "Agent converges toward optimal resolution strategy." },
};
function TimelineTab({ tasks }) {
const {
taskId, setTaskId, maxSteps, setMaxSteps,
agentMode,
policyName, setPolicyName,
modelPath, setModelPath,
modelType, setModelType,
availablePolicies,
availableModels,
configError,
running, starting, currentStep,
kpis, timeline, resources, journeyStats,
startSimulation, stopSimulation,
} = useStorySimulation({ defaultTask: tasks[0] || "district_backlog_easy" });
const isIdle = !starting && !running;
const startBlocked = agentMode === "trained_rl" && !modelPath;
const progressPct = maxSteps > 0 ? Math.min(100, Math.round((currentStep / maxSteps) * 100)) : 0;
const fmt2 = (n) => new Intl.NumberFormat().format(n ?? 0);
const fmtDelta = (n) => { const v = Number(n ?? 0); return v > 0 ? `+${v.toFixed(1)}` : v.toFixed(1); };
// Local string buffer so the user can freely type without the field snapping back
const [stepsInput, setStepsInput] = useState(String(maxSteps));
// Keep buffer in sync if maxSteps changes from outside
React.useEffect(() => { setStepsInput(String(maxSteps)); }, [maxSteps]);
// Build phase-annotated timeline: insert phase dividers between phase changes
const annotatedTimeline = [];
let lastPhase = null;
let phaseStats = { drop: 0, keys: 0 };
for (let i = 0; i < timeline.length; i++) {
const ev = timeline[i];
const ph = ev.phase;
if (ph && ph !== lastPhase) {
if (lastPhase && PHASE_LABELS[lastPhase]) {
// We reached the end of the previous (newer) phase in the chronological timeline,
// so insert its summary before starting the older phase.
annotatedTimeline.push({
_summary: true,
phase: lastPhase,
stats: { ...phaseStats },
key: `sum-${lastPhase}-${i}`,
});
}
if (PHASE_LABELS[ph]) {
annotatedTimeline.push({ _divider: true, phase: ph, key: `div-${ph}-${i}` });
}
lastPhase = ph;
phaseStats = { drop: 0, keys: 0 };
}
if (ev.key) phaseStats.keys += 1;
if (ev.backlogDelta) phaseStats.drop += ev.backlogDelta;
annotatedTimeline.push(ev);
}
// Handle the very last (oldest) phase summary at the bottom of the list
if (lastPhase && PHASE_LABELS[lastPhase] && timeline.length > 0) {
annotatedTimeline.push({
_summary: true,
phase: lastPhase,
stats: { ...phaseStats },
key: `sum-${lastPhase}-end`,
});
}
return (
{/* --- Controls bar --- */}
Scenario
setTaskId(e.target.value)}
disabled={!isIdle}
className="appearance-none bg-slate-800 border border-white/10 text-sm font-medium px-3 py-1.5 rounded-lg text-indigo-300 focus:outline-none focus:border-indigo-500 cursor-pointer"
>
{tasks.length > 0
? tasks.map((t) => {t.replace(/_/g, " ").toUpperCase()} )
: Loading... }
Steps
setStepsInput(e.target.value)}
onBlur={() => {
const v = parseInt(stepsInput, 10);
const clamped = isNaN(v) ? 40 : Math.min(100, Math.max(10, v));
setMaxSteps(clamped);
setStepsInput(String(clamped));
}}
onKeyDown={(e) => {
if (e.key === "Enter") e.currentTarget.blur();
}}
className="w-20 bg-slate-800 border border-white/10 text-sm font-medium px-3 py-1.5 rounded-lg text-indigo-300 focus:outline-none focus:border-indigo-500 text-center"
/>
{agentMode === "baseline_policy" && (
Policy
setPolicyName(e.target.value)}
disabled={!isIdle}
className="appearance-none bg-slate-800 border border-white/10 text-sm font-medium px-3 py-1.5 rounded-lg text-indigo-300 focus:outline-none focus:border-indigo-500 cursor-pointer"
>
{(availablePolicies.length > 0 ? availablePolicies : ["backlog_clearance"]).map((p) => (
{String(p).replace(/_/g, " ")}
))}
)}
{agentMode === "trained_rl" && (
<>
Model
{
const selected = availableModels.find((m) => m.path === e.target.value);
setModelPath(e.target.value);
if (selected?.model_type) setModelType(selected.model_type);
}}
disabled={!isIdle}
className="max-w-[260px] appearance-none bg-slate-800 border border-white/10 text-sm font-medium px-3 py-1.5 rounded-lg text-indigo-300 focus:outline-none focus:border-indigo-500 cursor-pointer"
>
{(availableModels.length > 0
? availableModels
: [{ label: "No model found", path: "", model_type: "maskable" }]
).map((m) => (
{m.label || m.path || "Unknown model"}
))}
Type
setModelType(e.target.value)}
disabled={!isIdle}
className="appearance-none bg-slate-800 border border-white/10 text-sm font-medium px-3 py-1.5 rounded-lg text-indigo-300 focus:outline-none focus:border-indigo-500 cursor-pointer"
>
Maskable PPO
Recurrent PPO
>
)}
{starting ? "Initializing..." : running ? "Stop Simulation" : "Start Auto-Resolution"}
{configError && (
{configError}
)}
{startBlocked && !configError && (
Select an available RL model checkpoint before starting `trained_rl` mode.
)}
{/* --- Progress bar (only visible while running) --- */}
{(running || currentStep > 0) && (
{running ? "Simulation In Progress" : journeyStats ? "Episode Complete" : "Stopped"}
Step {currentStep} / {maxSteps} - {progressPct}%
{running && (
Agent is making decisions...
)}
)}
{/* --- Journey Summary (Before -> After) - appears after episode completes --- */}
{journeyStats && (
auto_graph
Journey Summary - Start to End Transformation
{[
{
label: "Backlog Change",
before: journeyStats.initialBacklog,
after: journeyStats.finalBacklog,
suffix: " cases",
goodWhenDown: true,
},
{
label: "SLA Breaches",
before: journeyStats.initialSla,
after: journeyStats.finalSla,
suffix: "",
goodWhenDown: true,
},
{
label: "Steps Taken",
before: null,
after: journeyStats.totalSteps,
suffix: "",
goodWhenDown: false,
singleValue: true,
},
{
label: "Final Score",
before: journeyStats.finalScore != null ? "No Agent (0.0%)" : "N/A",
after: journeyStats.finalScore != null ? `${(journeyStats.finalScore * 100).toFixed(1)}%` : "N/A",
suffix: "",
goodWhenDown: false,
isScore: true,
isBaselineCmp: true,
},
].map((stat) => {
const delta = stat.singleValue ? null : stat.isBaselineCmp ? (journeyStats.finalScore * 100) : stat.after - stat.before;
const trend =
delta === null
? "none"
: delta === 0
? "stable"
: stat.goodWhenDown
? (delta < 0 ? "improving" : "worsening")
: (delta > 0 ? "improving" : "worsening");
const direction =
delta === null || delta === 0
? "stable"
: stat.goodWhenDown
? (delta < 0 ? "down" : "up")
: (delta > 0 ? "up" : "down");
const directionIcon =
direction === "up"
? "north"
: direction === "down"
? "south"
: "horizontal_rule";
const trendClass =
trend === "improving"
? "text-emerald-400"
: trend === "worsening"
? "text-rose-400"
: "text-slate-300";
return (
{stat.label}
{stat.singleValue ? (
{stat.after}{stat.suffix}
) : (
{stat.isBaselineCmp ? "Baseline" : stat.before}{stat.suffix}
arrow_forward
{stat.after}{stat.suffix}
)}
{delta !== null && (
{directionIcon}
{Number(Math.abs(delta).toFixed(2))} {trend === "stable" ? "no change" : trend}
)}
{stat.label === "Backlog Change" && journeyStats.backlogImprovement !== 0 && (
{journeyStats.backlogImprovement > 0 ? `${journeyStats.backlogImprovement}% cleared` : `${Math.abs(journeyStats.backlogImprovement)}% grew`}
)}
);
})}
)}
{/* --- KPI Row --- */}
{[
{ label: "Total Backlog", value: fmt2(kpis.backlog), delta: kpis.backlogDelta, accent: "rose", icon: "inbox" },
{ label: "SLA Breaches", value: fmt2(kpis.slaBreaches), delta: kpis.slaDelta, accent: "amber", icon: "timer_off" },
{ label: "Fairness Gap", value: `${(Number(kpis.fairness) * 100).toFixed(1)}%`, delta: kpis.fairnessDelta, accent: "emerald", icon: "balance" },
].map((kpi) => {
const delta = Number(kpi.delta ?? 0);
const trend = delta < 0 ? "down" : delta > 0 ? "up" : "stable";
const trendIcon = trend === "up" ? "north" : trend === "down" ? "south" : "horizontal_rule";
const badgeClass =
trend === "down"
? "bg-emerald-500/20 text-emerald-400"
: trend === "up"
? "bg-rose-500/20 text-rose-400"
: "bg-slate-500/20 text-slate-300";
return (
{kpi.icon}
{kpi.label}
{trendIcon}
{fmtDelta(delta)}
{kpi.value}
{trend === "down" ? "Trend improving" : trend === "stable" ? "Stable" : "Trend worsening"}
);
})}
{/* --- Story Timeline + Queue Monitors --- */}
{/* Story Timeline */}
auto_stories Story Timeline
{timeline.length > 1 && (
{timeline.filter(e => e.key).length} key moments
)}
{timeline.length === 0 ? (
play_circle
Select a scenario, set the number of steps, and press{" "}
Start Auto-Resolution to begin.
) : (
{annotatedTimeline.map((ev, idx) => {
// Phase divider
if (ev._divider) {
const ph = PHASE_LABELS[ev.phase];
return (
{ph.icon}
{ph.label}
- {ph.desc}
);
}
// Phase summary block
if (ev._summary) {
const drop = Math.abs(ev.stats.drop || 0);
const isDrop = (ev.stats.drop || 0) < 0;
return (
Phase Backlog Move
0 ? "text-rose-400" : "text-slate-300"}`}>
{isDrop ? "down " : ev.stats.drop > 0 ? "up " : ""}{drop} cases
Key Decisions
{ev.stats.keys}
);
}
const color = ev.type === "error" ? "rose" : ev.type === "warning" ? "amber" : ev.type === "success" ? "emerald" : "indigo";
return (
{ev.icon}
{ev.time}
{ev.outcomeLabel && (
{ev.outcomeLabel}
)}
{ev.key && (
KEY MOMENT
)}
{ev._count > 1 && (
x{ev._count}
)}
{ev.title}
{ev.isHugeImpact && High Impact }
{ev.isHighReward && Hot }
{ev.desc}
{ev.reason && (
Agent Reasoning: {ev.reason}
)}
{ev.impact !== 0 && (
{Number(ev.impact) >= 0 ? "+" : ""}{Number(ev.impact).toFixed(2)}
)}
);
})}
)}
{/* Live Queue Monitors */}
monitor_heart Live Queue Monitors
{resources.length === 0 ? (
sensors
Awaiting live telemetry...
) : (
{resources.map((res, i) => {
const color = res.percentage > 85 ? "rose" : res.percentage > 60 ? "amber" : "emerald";
const tone = color === "rose"
? {
text: "text-rose-400",
bar: "bg-rose-500",
}
: color === "amber"
? {
text: "text-amber-400",
bar: "bg-amber-500",
}
: {
text: "text-emerald-400",
bar: "bg-emerald-500",
};
return (
{res.name}
{res.activeCases} active
{res.percentage > 85 && (
OVERLOADED
)}
);
})}
)}
{/* Reward cumulative tracker - shown after first step */}
{currentStep > 0 && (
Impact Summary
Steps Elapsed
{currentStep}
Key Moments
{timeline.filter((e) => e.key).length}
)}
);
}
// --- Resources Tab ------------------------------------------------------------
function BenchmarkResults({ results }) {
const COLORS = { backlog_clearance: "#6366f1", urgent_first: "#10b981", oldest_first: "#f59e0b" };
const sorted = [...results.agent_results].sort((a, b) => b.average_score - a.average_score);
const winner = sorted[0];
const maxScore = Math.max(...results.agent_results.map((a) => a.average_score), 0.001);
const chartH = 140;
return (
{/* Winner callout */}
emoji_events
BEST PERFORMING POLICY
{winner.agent_policy.replace(/_/g, " ")}
Avg score{" "}{(winner.average_score * 100).toFixed(1)}%
{" | "}Range {(winner.min_score * 100).toFixed(0)}%-{(winner.max_score * 100).toFixed(0)}%
psychology Agent Intelligence
This policy performed best by maintaining fewer SLA breaches relative to its peers while securing steady backlog reduction across critical queues.
{/* Bar chart */}
Average Grader Score by Policy
{sorted.map((agent) => {
const pct = agent.average_score / maxScore;
const barH = Math.max(Math.round(pct * chartH), 6);
const color = COLORS[agent.agent_policy] || "#6366f1";
const isWinner = agent.agent_policy === winner.agent_policy;
return (
{(agent.average_score * 100).toFixed(1)}%
{agent.agent_policy.replace(/_/g, " ")}
{agent.runs.length} runs
);
})}
{/* Multi-metric comparison bars */}
Metric Comparison
{[
{
label: "Score (higher is better)",
vals: results.agent_results.map((a) => ({ key: a.agent_policy, v: a.average_score, display: `${(a.average_score * 100).toFixed(1)}%` })),
higherGood: true,
},
{
label: "Avg Completed Cases (higher is better)",
vals: results.agent_results.map((a) => {
const avg = a.runs.reduce((s, r) => s + (r.completed ?? 0), 0) / Math.max(a.runs.length, 1);
return { key: a.agent_policy, v: avg, display: avg.toFixed(1) };
}),
higherGood: true,
},
{
label: "Avg Remaining Backlog (lower is better)",
vals: results.agent_results.map((a) => {
const avg = a.runs.reduce((s, r) => s + (r.backlog ?? 0), 0) / Math.max(a.runs.length, 1);
return { key: a.agent_policy, v: avg, display: avg.toFixed(1) };
}),
higherGood: false,
},
].map(({ label, vals, higherGood }) => {
const maxVal = Math.max(...vals.map((v) => v.v), 0.001);
const best = higherGood
? vals.reduce((a, b) => (b.v > a.v ? b : a))
: vals.reduce((a, b) => (b.v < a.v ? b : a));
return (
{label}
{vals.map((v) => {
const pct = Math.round((v.v / maxVal) * 100);
const color = (COLORS)[v.key] || "#6366f1";
return (
{v.key.replace(/_/g, " ")}
{v.key === best.key && Top }
{v.display}
);
})}
);
})}
{/* Raw episode table */}
All Episodes - Raw Data
Policy
Run #
Score
Reward
Completed
Backlog
Steps
{results.agent_results.flatMap((agent) =>
agent.runs.map((run) => (
{agent.agent_policy.replace(/_/g, " ")}
#{run.run_index}
{(run.score * 100).toFixed(1)}%
{run.reward_sum?.toFixed(2) ?? "-"}
{run.completed ?? "-"}
{run.backlog ?? "-"}
{run.steps ?? "-"}
))
)}
);
}
function ResourcesTab({ tasks }) {
const [benchTask, setBenchTask] = useState(tasks[0] || "district_backlog_easy");
const [loading, setLoading] = useState(false);
const [results, setResults] = useState(null);
const [error, setError] = useState("");
const runBenchmark = async () => {
setLoading(true);
setError("");
setResults(null);
try {
const data = await api("/benchmark", {
method: "POST",
body: JSON.stringify({
task_id: benchTask,
agent_policies: ["backlog_clearance", "urgent_first", "oldest_first"],
runs: 3,
max_steps: 60,
}),
});
setResults(data);
} catch (e) {
setError(e.message);
} finally {
setLoading(false);
}
};
return (
leaderboard Policy Benchmark Comparison
Run all three baseline policies on the same scenario and compare their grader scores,
completed cases, and remaining backlogs side-by-side with visual charts.
setBenchTask(e.target.value)}
className="appearance-none bg-slate-800 border border-white/10 text-sm font-medium px-3 py-1.5 rounded-lg text-indigo-300 focus:outline-none focus:border-indigo-500"
>
{tasks.map((t) => (
{t.replace(/_/g, " ").toUpperCase()}
))}
{loading ? "Simulating 9 episodes..." : "Run Benchmark"}
{error && (
{error}
)}
{loading && (
Running 3 policies x 3 episodes each - takes ~20 seconds.
)}
{results &&
}
);
}
// --- Library Tab --------------------------------------------------------------
function LibraryTab({ tasks }) {
const [compliance, setCompliance] = useState(null);
const [workflows, setWorkflows] = useState(null);
const [selected, setSelected] = useState(null);
useEffect(() => {
api("/openenv_compliance").then(setCompliance).catch(() => {});
api("/workflows/components").then(setWorkflows).catch(() => {});
}, []);
const taskDetails = {
district_backlog_easy: { diff: "Easy", desc: "Single-service district queue focused on income certificate flow.", services: 1 },
mixed_urgency_medium: { diff: "Medium", desc: "Income, land, passport, driving license, and Aadhaar workloads with mixed urgency.", services: 5 },
cross_department_hard: { diff: "Hard", desc: "Five-service crisis mode with high arrivals, fairness pressure, and event shocks.", services: 5 },
};
const systemTabGuide = [
{
id: "timeline",
title: "Simulation (Timeline Tab)",
icon: "timeline",
summary: "Runs live step-by-step environment simulation and shows queue movement, KPI changes, and decision timeline in real time.",
userFlow: "Choose scenario, steps, and model/policy, then start auto-resolution.",
outputs: "Live backlog, SLA, fairness, key moments, queue pressure bars, and impact summary.",
endpoints: ["/simulation/live/start", "/simulation/live/step", "/simulation/live/{run_id}/stop", "/tasks", "/agents", "/rl_models", "/rl/models"],
},
{
id: "training",
title: "Training Tab",
icon: "fitness_center",
summary: "Controls RL training jobs and tracks how the policy improves over timesteps.",
userFlow: "Start/stop a training job and monitor live checkpoints and job history.",
outputs: "Active job state, progress, reward/score checkpoints, sequential narrative feed, and OpenEnv contract replay results.",
endpoints: ["/training_jobs", "/training_jobs/list", "/training_jobs/{job_id}", "/training_jobs/{job_id}/stop", "/reset", "/step", "/state", "/grade"],
},
{
id: "analytics",
title: "Analytics Tab",
icon: "analytics",
summary: "Shows endpoint-fed system analytics from historical simulation, jobs, models, sessions, and compliance health.",
userFlow: "Open the tab; metrics auto-refresh from backend every few seconds.",
outputs: "Task distributions, mode splits, training status mix, endpoint health, model inventory, and run history tables.",
endpoints: ["/history/simulations", "/history/comparisons", "/training_jobs", "/rl_models", "/rl/models", "/tasks", "/agents", "/sessions", "/actions/schema", "/openenv_compliance", "/workflows/components"],
},
{
id: "resources",
title: "Resources Tab (Benchmark)",
icon: "leaderboard",
summary: "Compares baseline policies on the same task to identify which strategy performs best.",
userFlow: "Select a scenario and run benchmark.",
outputs: "Winner policy card, score bars, metric comparison bars, and raw run-level benchmark table.",
endpoints: ["/compare_agents"],
},
{
id: "library",
title: "Library Tab",
icon: "menu_book",
summary: "Acts as the complete system overview and reference center for tasks, compliance, and workflow availability.",
userFlow: "Explore scenarios, inspect OpenEnv checks, and verify available workflow components.",
outputs: "Task cards with difficulty/service counts, compliance checklist, and component readiness matrix.",
endpoints: ["/tasks", "/openenv_compliance", "/workflows/components"],
},
];
return (
hub Complete System Overview
This section explains how each product tab works, what backend APIs power it, and what outputs users can expect.
Use it as a quick guide for judges and reviewers.
{systemTabGuide.map((tab) => (
{tab.icon}
{tab.title}
{tab.summary}
User flow: {tab.userFlow}
Outputs: {tab.outputs}
{tab.endpoints.map((ep) => (
{ep}
))}
))}
menu_book Scenario Library
{tasks.map((t) => {
const info = taskDetails[t] || { diff: "-", desc: "Custom scenario.", services: "-" };
const diffColor = info.diff === "Easy" ? "emerald" : info.diff === "Medium" ? "amber" : "rose";
const isSelected = selected === t;
return (
setSelected(isSelected ? null : t)}
className={`text-left bg-slate-900/70 border rounded-xl p-5 transition-all hover:border-indigo-500/40 ${isSelected ? "border-indigo-500/60 shadow-[0_0_20px_rgba(99,102,241,0.15)]" : "border-white/5"}`}
>
{info.diff.toUpperCase()}
{isSelected ? "expand_less" : "expand_more"}
{t.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())}
{info.desc}
{isSelected && (
Services {info.services}
Difficulty {info.diff}
Task ID {t}
)}
);
})}
{compliance && (
verified OpenEnv Compliance Status
{compliance.items?.map((item) => (
{item.status === "pass" ? "check_circle" : item.status === "fail" ? "cancel" : "help"}
{item.label}
{item.detail}
))}
)}
{workflows && (
account_tree Workflow Components
{workflows.components?.map((c) => (
{c.available ? "check_box" : "check_box_outline_blank"}
{c.component}
{c.description}
{c.command && (
{c.command}
)}
))}
)}
);
}
// --- Analytics Tab ------------------------------------------------------------
function AnalyticsTab() {
const [history, setHistory] = useState([]);
const [rlModels, setRlModels] = useState([]);
const [rlModelsV2, setRlModelsV2] = useState([]);
const [trainingJobs, setTrainingJobs] = useState([]);
const [tasksList, setTasksList] = useState([]);
const [agentsList, setAgentsList] = useState([]);
const [sessionsInfo, setSessionsInfo] = useState({ active_sessions: 0, session_ids: [] });
const [actionsSchema, setActionsSchema] = useState({});
const [complianceInfo, setComplianceInfo] = useState({ items: [] });
const [workflowInfo, setWorkflowInfo] = useState({ components: [] });
const [comparisonsInfo, setComparisonsInfo] = useState({ comparisons: [] });
const [endpointHealth, setEndpointHealth] = useState([]);
const [loadingHistory, setLoadingHistory] = useState(true);
const [loadingAll, setLoadingAll] = useState(true);
useEffect(() => {
let cancelled = false;
const load = async () => {
setLoadingHistory(true);
setLoadingAll(true);
try {
const [
historyRes,
rlRes,
rlResV2,
jobsRes,
tasksRes,
agentsRes,
sessionsRes,
actionsRes,
complianceRes,
workflowsRes,
comparisonsRes,
] = await Promise.allSettled([
api("/history/simulations?limit=80"),
api("/rl_models"),
api("/rl/models"),
api("/training_jobs"),
api("/tasks"),
api("/agents"),
api("/sessions"),
api("/actions/schema"),
api("/openenv_compliance"),
api("/workflows/components"),
api("/history/comparisons?limit=30"),
]);
if (cancelled) return;
const checks = [
{ key: "history", label: "History", ok: historyRes.status === "fulfilled" },
{ key: "rl_models", label: "RL Models", ok: rlRes.status === "fulfilled" },
{ key: "rl_models_v2", label: "RL Models V2", ok: rlResV2.status === "fulfilled" },
{ key: "training_jobs", label: "Training Jobs", ok: jobsRes.status === "fulfilled" },
{ key: "tasks", label: "Tasks", ok: tasksRes.status === "fulfilled" },
{ key: "agents", label: "Agents", ok: agentsRes.status === "fulfilled" },
{ key: "sessions", label: "Sessions", ok: sessionsRes.status === "fulfilled" },
{ key: "actions_schema", label: "Action Schema", ok: actionsRes.status === "fulfilled" },
{ key: "openenv_compliance", label: "Compliance", ok: complianceRes.status === "fulfilled" },
{ key: "workflow_components", label: "Workflow Components", ok: workflowsRes.status === "fulfilled" },
{ key: "comparison_history", label: "Comparison History", ok: comparisonsRes.status === "fulfilled" },
];
setEndpointHealth(checks);
setHistory(historyRes.status === "fulfilled" ? (historyRes.value?.runs || []) : []);
setRlModels(rlRes.status === "fulfilled" ? (rlRes.value?.models || []) : []);
setRlModelsV2(rlResV2.status === "fulfilled" ? (Array.isArray(rlResV2.value) ? rlResV2.value : []) : []);
setTrainingJobs(jobsRes.status === "fulfilled" ? (jobsRes.value?.jobs || []) : []);
setTasksList(tasksRes.status === "fulfilled" ? (tasksRes.value?.tasks || []) : []);
setAgentsList(agentsRes.status === "fulfilled" ? (Array.isArray(agentsRes.value) ? agentsRes.value : []) : []);
setSessionsInfo(sessionsRes.status === "fulfilled" ? (sessionsRes.value || { active_sessions: 0, session_ids: [] }) : { active_sessions: 0, session_ids: [] });
setActionsSchema(actionsRes.status === "fulfilled" ? (actionsRes.value || {}) : {});
setComplianceInfo(complianceRes.status === "fulfilled" ? (complianceRes.value || { items: [] }) : { items: [] });
setWorkflowInfo(workflowsRes.status === "fulfilled" ? (workflowsRes.value || { components: [] }) : { components: [] });
setComparisonsInfo(comparisonsRes.status === "fulfilled" ? (comparisonsRes.value || { comparisons: [] }) : { comparisons: [] });
} finally {
if (!cancelled) {
setLoadingHistory(false);
setLoadingAll(false);
}
}
};
load();
const timer = setInterval(load, 8000);
return () => {
cancelled = true;
clearInterval(timer);
};
}, []);
const byTask = history.reduce((acc, run) => {
const t = run.task_id || "unknown";
if (!acc[t]) acc[t] = [];
acc[t].push(run);
return acc;
}, {});
const getRunScore = (run) => {
const value = run?.score ?? run?.payload?.score;
const num = Number(value);
return Number.isFinite(num) ? num : null;
};
const getRunReward = (run) => {
const value = run?.total_reward ?? run?.payload?.total_reward;
const num = Number(value);
return Number.isFinite(num) ? num : null;
};
const getJobProgress = (job) => {
const p = Number(job?.progress);
if (Number.isFinite(p)) return Math.max(0, Math.min(1, p));
const ts = Number(job?.latest_metrics?.total_timesteps);
const total = Number(job?.timesteps);
if (Number.isFinite(ts) && Number.isFinite(total) && total > 0) {
return Math.max(0, Math.min(1, ts / total));
}
return 0;
};
const scoreData = history.map(getRunScore).filter((v) => v != null);
const avgScore = scoreData.length ? scoreData.reduce((s, v) => s + v, 0) / scoreData.length : null;
const runningJobs = trainingJobs.filter((j) => String(j?.status || "").toLowerCase() === "running").length;
const endpointCoverage = endpointHealth.length
? endpointHealth.filter((x) => x.ok).length / endpointHealth.length
: null;
const timelineTaskRows = Object.entries(byTask)
.map(([label, runs]) => ({ label, value: runs.length }))
.sort((a, b) => b.value - a.value);
const timelineModeRows = Object.entries(
history.reduce((acc, run) => {
const mode = String(run?.agent_mode || "unknown");
acc[mode] = (acc[mode] || 0) + 1;
return acc;
}, {})
).map(([label, value]) => ({ label, value }));
const trainingStatusRows = Object.entries(
trainingJobs.reduce((acc, job) => {
const status = String(job?.status || "unknown").toLowerCase();
acc[status] = (acc[status] || 0) + 1;
return acc;
}, {})
).map(([label, value]) => ({ label, value }));
const trainingPhaseRows = [1, 2].map((phase) => {
const rows = trainingJobs.filter((job) => Number(job?.phase || 0) === phase);
const avgProgress = rows.length
? rows.reduce((sum, job) => sum + getJobProgress(job), 0) / rows.length
: 0;
return {
label: `Phase ${phase}`,
value: Number((avgProgress * 100).toFixed(1)),
jobs: rows.length,
};
});
const compliancePass = Array.isArray(complianceInfo?.items)
? complianceInfo.items.filter((x) => x?.status === "pass").length
: 0;
const complianceFail = Array.isArray(complianceInfo?.items)
? complianceInfo.items.filter((x) => x?.status === "fail").length
: 0;
const complianceUnknown = Array.isArray(complianceInfo?.items)
? complianceInfo.items.filter((x) => x?.status !== "pass" && x?.status !== "fail").length
: 0;
const systemMetricRows = [
{ label: "Tasks", value: tasksList.length },
{ label: "Agents", value: agentsList.length },
{ label: "Action Types", value: Number(actionsSchema?.total_action_types || 0) },
{ label: "Active Sessions", value: Number(sessionsInfo?.active_sessions || 0) },
{ label: "RL Models V1", value: rlModels.filter((m) => m.exists).length },
{ label: "RL Models V2", value: rlModelsV2.filter((m) => m.exists).length },
{
label: "Workflow Components",
value: Array.isArray(workflowInfo?.components)
? workflowInfo.components.filter((x) => x?.available).length
: 0,
},
{ label: "Comparisons", value: Array.isArray(comparisonsInfo?.comparisons) ? comparisonsInfo.comparisons.length : 0 },
];
const buildConicGradient = (rows, palette) => {
const total = rows.reduce((sum, row) => sum + Number(row?.value || 0), 0);
if (total <= 0) return null;
let cursor = 0;
const segments = [];
rows.forEach((row, idx) => {
const value = Number(row?.value || 0);
if (value <= 0) return;
const delta = (value / total) * 100;
const start = cursor;
const end = cursor + delta;
segments.push(`${palette[idx % palette.length]} ${start.toFixed(2)}% ${end.toFixed(2)}%`);
cursor = end;
});
if (cursor < 100) {
segments.push(`#1e293b ${cursor.toFixed(2)}% 100%`);
}
return `conic-gradient(${segments.join(", ")})`;
};
const timelineModeGradient = buildConicGradient(
timelineModeRows,
["#22d3ee", "#a78bfa", "#f59e0b", "#34d399", "#f472b6"]
);
const trainingStatusGradient = buildConicGradient(
trainingStatusRows,
["#22c55e", "#eab308", "#6366f1", "#ef4444", "#64748b"]
);
const complianceGradient = buildConicGradient(
[
{ label: "pass", value: compliancePass },
{ label: "fail", value: complianceFail },
{ label: "unknown", value: complianceUnknown },
],
["#22c55e", "#ef4444", "#f59e0b"]
);
const renderBars = (rows, color = "bg-indigo-500") => {
const maxVal = Math.max(...rows.map((r) => Number(r?.value || 0)), 1);
return (
{rows.map((row) => {
const widthPct = Math.max(0, Math.min(100, (Number(row.value || 0) / maxVal) * 100));
return (
{row.label.replace(/_/g, " ")}
{Number(row.value || 0)}
);
})}
);
};
return (
{[
{ label: "Total Runs", value: history.length, icon: "play_circle", color: "indigo" },
{ label: "Avg Score", value: avgScore != null ? `${(avgScore * 100).toFixed(1)}%` : "—", icon: "grade", color: "emerald" },
{ label: "Running Jobs", value: runningJobs, icon: "settings_slow_motion", color: "violet" },
{ label: "Endpoint Coverage", value: endpointCoverage != null ? `${(endpointCoverage * 100).toFixed(0)}%` : "—", icon: "hub", color: "amber" },
].map((s) => (
{s.icon}
{s.label}
{s.value}
))}
{!loadingHistory && (
bar_chart Timeline Metric: Runs by Task
{timelineTaskRows.length === 0 ? (
No timeline history yet.
) : renderBars(timelineTaskRows, "bg-cyan-500")}
pie_chart Timeline Metric: Agent Mode Mix
{timelineModeGradient ? (
{timelineModeRows.map((row, idx) => (
))}
) : (
No timeline mode data yet.
)}
)}
{!loadingAll && (
stacked_bar_chart Training Metric: Job Status Mix
{trainingStatusGradient ? (
{trainingStatusRows.map((row, idx) => (
))}
) : (
No training jobs available yet.
)}
dataset Training Metric: Phase Progress (%)
{trainingPhaseRows.map((row) => (
{row.label}
{row.value.toFixed(1)}% · {row.jobs} jobs
))}
)}
{!loadingAll && (
analytics System Metric: Endpoint-fed Counts
{renderBars(systemMetricRows, "bg-cyan-500")}
policy
System Metric: Compliance + Endpoint Health
Pass {compliancePass}
Fail {complianceFail}
Unknown {complianceUnknown}
Endpoint Health
{endpointHealth.map((row) => (
{row.label}
))}
)}
history Simulation Run History
{loadingHistory ? (
) : history.length === 0 ? (
No simulation history yet. Run a simulation on the Timeline tab first.
) : (
Run ID
Task
Agent Mode
Status
Score
Reward
{history.map((run) => {
const score = getRunScore(run);
const reward = getRunReward(run);
const status = run.status || "completed";
const statusColor = status === "completed" ? "emerald" : status === "running" ? "amber" : "slate";
return (
{run.run_id?.slice(0, 8)}…
{run.task_id?.replace(/_/g, " ")}
{run.agent_mode}
{status}
{score != null ? `${(score * 100).toFixed(1)}%` : "—"}
{reward != null ? reward.toFixed(2) : "—"}
);
})}
)}
model_training Trained RL Model Checkpoints
{rlModels.length === 0 && rlModelsV2.length === 0 ? (
No trained models found. Train a model via the RL pipeline first.
) : (
[...rlModels, ...rlModelsV2.map((m) => ({
label: m.model_path ? String(m.model_path).split(/[\\/]/).pop() : "unnamed",
path: m.model_path ? `${m.model_path}.zip` : "",
exists: Boolean(m.exists),
model_type: Number(m.phase) === 2 ? "phase2" : "phase1",
}))].map((m) => (
{m.exists ? "check_circle" : "radio_button_unchecked"}
{m.label}
{m.path?.split("\\").pop() || m.path?.split("/").pop()}
Type: {m.model_type}
{!m.exists &&
Not yet trained
}
))
)}
{Object.keys(byTask).length > 0 && (
bar_chart Score by Scenario
{Object.entries(byTask).map(([task, runs]) => {
const scores = runs.map((r) => r.score ?? r.payload?.score).filter((s) => s != null);
const avg = scores.length ? scores.reduce((a, b) => a + b, 0) / scores.length : null;
const avgPct = avg != null ? Number((avg * 100).toFixed(1)) : 0;
return (
{task.replace(/_/g, " ")}
{runs.length} runs · avg {avg != null ? `${avgPct}%` : "—"}
);
})}
)}
);
}
function TrainingTab({ tasks }) {
return ;
}
const TABS = [
{ id: "timeline", label: "Timeline", icon: "timeline" },
{ id: "training", label: "Training", icon: "fitness_center" },
{ id: "resources", label: "Resources", icon: "leaderboard" },
{ id: "library", label: "Overview", icon: "menu_book" },
{ id: "analytics", label: "Analytics", icon: "analytics" },
];
export function Dashboard({ tasks = [] }) {
const [activeTab, setActiveTab] = useState("library");
return (
OPEN ENV
{TABS.map((tab) => (
setActiveTab(tab.id)}
className={`flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-semibold transition-all duration-200 ${
activeTab === tab.id
? "bg-indigo-600/30 text-indigo-300 border border-indigo-500/30"
: "text-slate-400 hover:text-white hover:bg-white/5"
}`}
>
{tab.icon}
{tab.label}
))}
Gov Workflow RL | OpenEnv v2.0
{TABS.map((tab) => (
setActiveTab(tab.id)}
className={`flex-1 py-2 text-xs font-bold rounded-lg transition-all ${activeTab === tab.id ? "bg-indigo-600 text-white" : "text-slate-400"}`}
>
{tab.label}
))}
{activeTab === "timeline" &&
Oversight Dashboard Watch the AI agent resolve a government workflow backlog in real time - step by step, decision by decision.
}
{activeTab === "training" &&
Reinforcement Learning Visualize policy convergence and reward trends as the agent continuously improves.
}
{activeTab === "resources" &&
Policy Benchmark Compare all three baseline policies head-to-head on identical scenarios to see which strategy wins.
}
{activeTab === "library" &&
Overview Explore system behavior, task configurations, OpenEnv compliance status, and workflow architecture.
}
{activeTab === "analytics" &&
Performance Analytics Review historical simulation runs, trained model checkpoints, and reward improvement evidence.
}
{activeTab === "timeline" && }
{activeTab === "training" && }
{activeTab === "resources" && }
{activeTab === "library" && }
{activeTab === "analytics" && }
);
}