Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions ui/src/hooks/useApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,17 @@ export async function getRunDetail(runId: string) {
return resp.json()
}

export async function deleteRun(runId: string): Promise<{ ok: boolean; run_id?: string; detail?: string }> {
const resp = await fetch(`/api/benchmark/runs/${encodeURIComponent(runId)}`, {
method: 'DELETE',
})
const data = await resp.json().catch(() => ({}))
if (!resp.ok) {
throw new Error(data.detail || data.error || `delete failed: ${resp.status}`)
}
return data
}

export async function getHFModelDetails(repo: string): Promise<HFModelDetails> {
const resp = await fetch(`/api/models/hf-details?repo=${encodeURIComponent(repo)}`)
return resp.json()
Expand Down
57 changes: 51 additions & 6 deletions ui/src/pages/RunDetailPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react'
import { useParams, useNavigate, Link } from 'react-router-dom'
import ScoreBadge from '../components/ScoreBadge'
import { deleteRun } from '../hooks/useApi'

interface RunDetail {
status?: string
Expand All @@ -27,6 +28,8 @@ export default function RunDetailPage() {
const navigate = useNavigate()
const [data, setData] = useState<RunDetail | null>(null)
const [loading, setLoading] = useState(true)
const [deleting, setDeleting] = useState(false)
const [deleteError, setDeleteError] = useState<string | null>(null)

useEffect(() => {
if (!runId) return
Expand Down Expand Up @@ -107,6 +110,23 @@ export default function RunDetailPage() {
const sm = run.speed_metrics || {}
const machine = run.machine || {}

const handleDelete = async () => {
if (!runId || isRunning) return
const ok = window.confirm(`Delete local run ${runId}? This cannot be undone.`)
if (!ok) return

setDeleting(true)
setDeleteError(null)
try {
await deleteRun(runId)
navigate('/leaderboard')
} catch (err) {
setDeleteError(err instanceof Error ? err.message : 'Failed to delete run')
} finally {
setDeleting(false)
}
}

return (
<div>
{isFailed && (
Expand All @@ -132,6 +152,12 @@ export default function RunDetailPage() {
</div>
)}

{deleteError && (
<div className="card" style={{ padding: 12, marginBottom: 16, borderColor: 'rgba(239,68,68,0.4)', background: 'rgba(239,68,68,0.06)', color: '#ff8888', fontSize: '0.85rem' }}>
{deleteError}
</div>
)}

<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
<div>
<button
Expand All @@ -145,12 +171,31 @@ export default function RunDetailPage() {
Run <code style={{ fontFamily: 'var(--mono)' }}>{runId}</code> · {run.timestamp || '—'} · harness <strong>{run.harness || 'raw'}</strong> · provider <strong>{run.provider || '—'}</strong>
</div>
</div>
<Link
to={`/compare?a=${encodeURIComponent(runId || '')}`}
style={{ background: 'var(--bg-elev)', border: '1px solid var(--border)', color: 'var(--text)', padding: '6px 14px', borderRadius: 6, fontSize: '0.85rem', textDecoration: 'none' }}
>
Compare with…
</Link>
<div style={{ display: 'flex', gap: 8 }}>
<button
onClick={handleDelete}
disabled={isRunning || deleting}
title={isRunning ? 'Cancel active runs before deleting them.' : 'Delete this local run'}
style={{
background: 'rgba(239,68,68,0.08)',
border: '1px solid rgba(239,68,68,0.35)',
color: isRunning ? 'var(--text-dim)' : '#ff9999',
padding: '6px 14px',
borderRadius: 6,
fontSize: '0.85rem',
cursor: isRunning || deleting ? 'not-allowed' : 'pointer',
opacity: isRunning || deleting ? 0.6 : 1,
}}
>
{deleting ? 'Deleting...' : 'Delete'}
</button>
<Link
to={`/compare?a=${encodeURIComponent(runId || '')}`}
style={{ background: 'var(--bg-elev)', border: '1px solid var(--border)', color: 'var(--text)', padding: '6px 14px', borderRadius: 6, fontSize: '0.85rem', textDecoration: 'none' }}
>
Compare with…
</Link>
</div>
</div>

{/* Top-line scores */}
Expand Down
66 changes: 59 additions & 7 deletions ui/src/tabs/LeaderboardTab.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMemo, useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { useRuns } from '../hooks/useApi'
import { deleteRun, useRuns } from '../hooks/useApi'
import ScoreBadge from '../components/ScoreBadge'

// "Full" = at least these quality suites + speed. Coding is optional bonus.
Expand Down Expand Up @@ -71,6 +71,8 @@ export default function LeaderboardTab() {
const [providerFilter, setProviderFilter] = useState<string>('all')
const [harnessFilter, setHarnessFilter] = useState<string>('all')
const [rankMode, setRankMode] = useState<RankMode>('overall')
const [deletingRunId, setDeletingRunId] = useState<string | null>(null)
const [deleteError, setDeleteError] = useState<string | null>(null)

const scoreOf = (r: RunRow): number => {
switch (rankMode) {
Expand Down Expand Up @@ -110,6 +112,22 @@ export default function LeaderboardTab() {
const totalRuns = ranked.length
const filteredPartialCount = ranked.length - ranked.filter(isFullRun).length

const handleDelete = async (run: RunRow) => {
const ok = window.confirm(`Delete local run ${run.id}? This cannot be undone.`)
if (!ok) return

setDeletingRunId(run.id)
setDeleteError(null)
try {
await deleteRun(run.id)
refresh()
} catch (err) {
setDeleteError(err instanceof Error ? err.message : 'Failed to delete run')
} finally {
setDeletingRunId(null)
}
}

return (
<div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16, padding: '8px 0' }}>
Expand Down Expand Up @@ -273,6 +291,21 @@ export default function LeaderboardTab() {
⚠️ {speedAtCapCount} runs have speed score at the 100 ceiling. Switch to "Raw tok/s" to see actual speed differences.
</div>
)}
{deleteError && (
<div
style={{
background: 'rgba(239,68,68,0.08)',
border: '1px solid rgba(239,68,68,0.3)',
color: '#ff8888',
padding: '8px 12px',
borderRadius: 6,
fontSize: '0.78rem',
marginBottom: 12,
}}
>
{deleteError}
</div>
)}

{!loading && filtered.length === 0 && (
<div className="empty-state">
Expand Down Expand Up @@ -362,12 +395,31 @@ export default function LeaderboardTab() {
{run.total_runtime_sec ? `${run.total_runtime_sec.toFixed(1)}s` : '—'}
</td>
<td style={{ ...cellStyle, textAlign: 'center' }} onClick={(e) => e.stopPropagation()}>
<Link
to={`/compare?a=${encodeURIComponent(run.id)}`}
style={{ fontSize: '0.72rem', color: 'var(--accent)', textDecoration: 'none', padding: '4px 8px', border: '1px solid var(--border)', borderRadius: 4 }}
>
Compare
</Link>
<div style={{ display: 'flex', justifyContent: 'center', gap: 6 }}>
<Link
to={`/compare?a=${encodeURIComponent(run.id)}`}
style={{ fontSize: '0.72rem', color: 'var(--accent)', textDecoration: 'none', padding: '4px 8px', border: '1px solid var(--border)', borderRadius: 4 }}
>
Compare
</Link>
<button
onClick={() => handleDelete(run)}
disabled={deletingRunId === run.id}
title="Delete this local run"
style={{
fontSize: '0.72rem',
color: '#ff9999',
background: 'rgba(239,68,68,0.06)',
padding: '4px 8px',
border: '1px solid rgba(239,68,68,0.35)',
borderRadius: 4,
cursor: deletingRunId === run.id ? 'not-allowed' : 'pointer',
opacity: deletingRunId === run.id ? 0.6 : 1,
}}
>
{deletingRunId === run.id ? 'Deleting...' : 'Delete'}
</button>
</div>
</td>
</tr>
)
Expand Down