Report measured usage costs and link completed runs to the annotation viewer
Browse files- frontend/src/main.tsx +11 -3
- frontend/src/style.css +6 -0
- server.py +3 -1
frontend/src/main.tsx
CHANGED
|
@@ -117,6 +117,8 @@ type Progress = {
|
|
| 117 |
expected: number;
|
| 118 |
completed: number;
|
| 119 |
failed: number;
|
|
|
|
|
|
|
| 120 |
usage: {
|
| 121 |
measured_inference_usd?: number;
|
| 122 |
successful_calls?: number;
|
|
@@ -1435,11 +1437,15 @@ function App() {
|
|
| 1435 |
<code>{j.id.slice(0, 8)}</code>
|
| 1436 |
</p>
|
| 1437 |
</div>
|
| 1438 |
-
<span
|
|
|
|
|
|
|
| 1439 |
{!terminal.has(j.stage) && (
|
| 1440 |
<LoaderCircle size={12} className="spin" />
|
| 1441 |
)}
|
| 1442 |
-
{j.
|
|
|
|
|
|
|
| 1443 |
</span>
|
| 1444 |
</div>
|
| 1445 |
{progress[j.id] && (
|
|
@@ -1456,7 +1462,9 @@ function App() {
|
|
| 1456 |
value={progress[j.id].completed}
|
| 1457 |
/>
|
| 1458 |
<small>
|
| 1459 |
-
{progress[j.id].failed}
|
|
|
|
|
|
|
| 1460 |
measured inference{" "}
|
| 1461 |
{money(
|
| 1462 |
progress[j.id].usage.measured_inference_usd || 0,
|
|
|
|
| 117 |
expected: number;
|
| 118 |
completed: number;
|
| 119 |
failed: number;
|
| 120 |
+
stopped?: number;
|
| 121 |
+
pending?: number;
|
| 122 |
usage: {
|
| 123 |
measured_inference_usd?: number;
|
| 124 |
successful_calls?: number;
|
|
|
|
| 1437 |
<code>{j.id.slice(0, 8)}</code>
|
| 1438 |
</p>
|
| 1439 |
</div>
|
| 1440 |
+
<span
|
| 1441 |
+
className={`job-status ${progress[j.id]?.status === "partial" ? "partial" : j.stage.toLowerCase()}`}
|
| 1442 |
+
>
|
| 1443 |
{!terminal.has(j.stage) && (
|
| 1444 |
<LoaderCircle size={12} className="spin" />
|
| 1445 |
)}
|
| 1446 |
+
{progress[j.id]?.status === "partial"
|
| 1447 |
+
? "Partial"
|
| 1448 |
+
: j.stage.toLowerCase()}
|
| 1449 |
</span>
|
| 1450 |
</div>
|
| 1451 |
{progress[j.id] && (
|
|
|
|
| 1462 |
value={progress[j.id].completed}
|
| 1463 |
/>
|
| 1464 |
<small>
|
| 1465 |
+
{progress[j.id].failed} failed ·{" "}
|
| 1466 |
+
{progress[j.id].stopped || 0} stopped ·{" "}
|
| 1467 |
+
{progress[j.id].pending || 0} not processed ·
|
| 1468 |
measured inference{" "}
|
| 1469 |
{money(
|
| 1470 |
progress[j.id].usage.measured_inference_usd || 0,
|
frontend/src/style.css
CHANGED
|
@@ -2559,3 +2559,9 @@ footer > span {
|
|
| 2559 |
gap: 8px;
|
| 2560 |
}
|
| 2561 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2559 |
gap: 8px;
|
| 2560 |
}
|
| 2561 |
}
|
| 2562 |
+
|
| 2563 |
+
.job-status.partial {
|
| 2564 |
+
background: var(--accent-fill);
|
| 2565 |
+
color: var(--fg-soft);
|
| 2566 |
+
border-color: var(--line);
|
| 2567 |
+
}
|
server.py
CHANGED
|
@@ -402,7 +402,9 @@ def progress(job_id: str, request: Request):
|
|
| 402 |
else report["status"],
|
| 403 |
"expected": report["expected_episodes"],
|
| 404 |
"completed": sum(e["status"] == "completed" for e in episodes),
|
| 405 |
-
"failed": sum(e["status"]
|
|
|
|
|
|
|
| 406 |
"usage": report.get("usage", {}),
|
| 407 |
"cost": usage_costs(job, report),
|
| 408 |
"annotation_url": annotation_url(report),
|
|
|
|
| 402 |
else report["status"],
|
| 403 |
"expected": report["expected_episodes"],
|
| 404 |
"completed": sum(e["status"] == "completed" for e in episodes),
|
| 405 |
+
"failed": sum(e["status"] == "failed" for e in episodes),
|
| 406 |
+
"stopped": sum(e["status"] in {"time_stopped", "budget_stopped"} for e in episodes),
|
| 407 |
+
"pending": max(0, report["expected_episodes"] - len(episodes)),
|
| 408 |
"usage": report.get("usage", {}),
|
| 409 |
"cost": usage_costs(job, report),
|
| 410 |
"annotation_url": annotation_url(report),
|