Xining Li
Deploy snapshot: causal-gate + flash-offer tasks (textbook/ omitted, binary PDF rejected by HF's plain-git push policy)
6ec7f56
Raw History Blame Contribute Delete
5.97 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Beat the agent — WebTask Arena</title>
<style>
* { box-sizing: border-box; margin: 0; }
body { font-family: system-ui, -apple-system, sans-serif; background: #12141a;
color: #ebeef5; }
.wrap { max-width: 1060px; margin: 0 auto; padding: 28px 24px 56px; }
a.back { color: #7ea2ff; text-decoration: none; font-size: 14px; }
h1 { font-size: 26px; margin: 10px 0 4px; }
.sub { color: #969eaa; font-size: 14.5px; }
.bar { display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
margin: 16px 0; }
select, input[type=number] { font: inherit; font-size: 14px; background: #1a1d26;
color: #ebeef5; border: 1px solid #2a2f3c; border-radius: 8px; padding: 7px 10px; }
input[type=number] { width: 82px; }
label.flag { font-size: 13.5px; color: #cdd3de; display: flex; gap: 5px; align-items: center; }
button { font: inherit; font-size: 14px; font-weight: 600; padding: 8px 16px;
border-radius: 8px; border: none; cursor: pointer; }
#start { background: #2456d6; color: #fff; }
#grade { background: #16a34a; color: #fff; display: none; }
.instruction { background: #1a1d26; border: 1px solid #2a2f3c; border-radius: 10px;
padding: 12px 16px; font-size: 15px; color: #ebeef5; display: none; }
iframe { width: 100%; height: 640px; border: 1px solid #2a2f3c; border-radius: 10px;
background: #f4f5f7; margin-top: 14px; display: none; }
.result { margin-top: 14px; display: none; gap: 16px;
display: none; grid-template-columns: 1fr 1fr; }
@media (max-width: 760px) { .result { grid-template-columns: 1fr; } }
.panel { background: #1a1d26; border: 1px solid #2a2f3c; border-radius: 10px;
padding: 16px; }
.panel h3 { font-size: 12px; text-transform: uppercase; letter-spacing: 1px;
color: #969eaa; margin-bottom: 6px; }
.verdict { font-size: 24px; font-weight: 800; }
.pass { color: #4ade80; } .fail { color: #ff7b72; }
.subgoal { font-size: 13.5px; margin-top: 4px; }
.note { font-size: 12.5px; color: #969eaa; margin-top: 8px; }
</style>
</head>
<body>
<div class="wrap">
<a class="back" href="/">&larr; WebTask Arena</a>
<h1>Beat the agent</h1>
<div class="sub">You get the same seeded instruction the model got. Do the task,
then let the oracle grade you — subgoal by subgoal.</div>
<div class="bar">
<select id="task">
{% for task_id, task_title in tasks %}
<option value="{{ task_id }}">{{ task_id }}</option>
{% endfor %}
</select>
<input type="number" id="seed" value="0" min="0" max="9999" title="seed">
<label class="flag"><input type="checkbox" id="latency"> slow loading</label>
<label class="flag"><input type="checkbox" id="shift"> layout shift</label>
<button id="start">Start episode</button>
<button id="grade">I'm done — grade me</button>
</div>
<div class="instruction" id="instruction"></div>
<iframe id="frame" title="task"></iframe>
<div class="result" id="result">
<div class="panel">
<h3>You</h3>
<div class="verdict" id="youVerdict"></div>
<div id="youSubgoals"></div>
</div>
<div class="panel">
<h3 id="agentTitle">Agent</h3>
<div class="verdict" id="agentVerdict"></div>
<div id="agentSubgoals"></div>
<div class="note" id="agentNote"></div>
</div>
</div>
</div>
<script>
const AGENT_RESULTS = {{ agent_results_json | safe }};
const $ = id => document.getElementById(id);
const sid = 'p-' + Math.random().toString(36).slice(2, 12);
let current = null;
function subgoalHtml(subgoals) {
return Object.entries(subgoals)
.map(([k, v]) => `<div class="subgoal"><span class="${v ? 'pass' : 'fail'}">${v ? '✓' : '✗'}</span> ${k}</div>`)
.join('');
}
$('start').addEventListener('click', async () => {
const task = $('task').value;
const body = {
seed: Number($('seed').value) || 0,
latency_ms: $('latency').checked ? 800 : 0,
layout_shift: $('shift').checked,
};
const r = await fetch(`/api/${task}/reset?sid=${sid}`, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const data = await r.json();
current = task;
$('instruction').textContent = data.instruction;
$('instruction').style.display = 'block';
$('frame').src = `/task/${task}?sid=${sid}&t=${Date.now()}`;
$('frame').style.display = 'block';
$('grade').style.display = 'inline-block';
$('result').style.display = 'none';
});
$('grade').addEventListener('click', async () => {
if (!current) return;
const r = await fetch(`/api/${current}/verify?sid=${sid}`);
const v = await r.json();
$('youVerdict').textContent = v.success ? 'PASS' : 'FAIL';
$('youVerdict').className = 'verdict ' + (v.success ? 'pass' : 'fail');
$('youSubgoals').innerHTML = subgoalHtml(v.subgoals);
const agent = AGENT_RESULTS.find(e => e.task === current);
if (agent) {
$('agentTitle').textContent = agent.agent || 'Agent';
$('agentVerdict').textContent = agent.success ? 'PASS' : 'FAIL';
$('agentVerdict').className = 'verdict ' + (agent.success ? 'pass' : 'fail');
$('agentSubgoals').innerHTML = subgoalHtml(agent.subgoals);
$('agentNote').textContent = (agent.seed !== (Number($('seed').value) || 0))
? `Agent result recorded on seed ${agent.seed}; you played seed ${$('seed').value}.`
: `Same seed (${agent.seed}) — a direct comparison. Watch its run in the replay player.`;
} else {
$('agentVerdict').textContent = '—';
$('agentNote').textContent = 'No recorded agent run for this task yet.';
}
$('result').style.display = 'grid';
$('result').scrollIntoView({ behavior: 'smooth' });
});
</script>
</body>
</html>