pokertools-arena 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/bin/pokertools-arena.mjs +197 -0
- package/dist/.nojekyll +0 -0
- package/dist/app.js +118427 -0
- package/dist/arena-env.js +2 -0
- package/dist/favicon.svg +4 -0
- package/dist/index.html +382 -0
- package/dist/og-image.png +0 -0
- package/dist/og-image.svg +190 -0
- package/dist/pokertools-arena.html +121106 -0
- package/dist/styles.css +2289 -0
- package/docs/architecture/CONTEXT.md +202 -0
- package/docs/diagnostics/SUMMARY.md +102 -0
- package/docs/diagnostics/summary.json +337 -0
- package/docs/legal/THIRD_PARTY_NOTICES.md +15 -0
- package/docs/releases/RELEASE_NOTES.md +171 -0
- package/docs/verification/0.3.x.md +250 -0
- package/package.json +77 -0
- package/src/app.js +2458 -0
- package/src/assets/favicon.svg +4 -0
- package/src/assets/og-image.png +0 -0
- package/src/assets/og-image.svg +190 -0
- package/src/benchmark/scenarios.js +108 -0
- package/src/env/arena-env.js +2 -0
- package/src/index.html +382 -0
- package/src/lib/decision-core.js +1288 -0
- package/src/shims/crypto.cjs +19 -0
- package/src/styles.css +2289 -0
package/src/index.html
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
6
|
+
<meta name="color-scheme" content="dark" />
|
|
7
|
+
<meta name="theme-color" content="#07090b" />
|
|
8
|
+
<title>pokertools-arena — AI Poker Benchmark</title>
|
|
9
|
+
<meta name="description" content="A browser-first AI poker benchmark. Put Jev and OpenAI-compatible models at the same no-limit Texas Hold'em table, watch every card and decision, and let the tournament run until one model wins." />
|
|
10
|
+
<meta name="author" content="pokertools-arena" />
|
|
11
|
+
<link rel="canonical" href="https://pokertools-arena.github.io/" />
|
|
12
|
+
<link rel="icon" href="./favicon.svg" type="image/svg+xml" />
|
|
13
|
+
|
|
14
|
+
<!-- Open Graph (Facebook, LinkedIn, Discord, Slack, iMessage) -->
|
|
15
|
+
<meta property="og:type" content="website" />
|
|
16
|
+
<meta property="og:site_name" content="pokertools-arena" />
|
|
17
|
+
<meta property="og:locale" content="en_US" />
|
|
18
|
+
<meta property="og:title" content="pokertools-arena — AI Poker Benchmark" />
|
|
19
|
+
<meta property="og:description" content="Frontier models play no-limit Texas Hold'em with identical information and legal actions. Watch every card and decision until one model wins." />
|
|
20
|
+
<meta property="og:url" content="https://pokertools-arena.github.io/" />
|
|
21
|
+
<meta property="og:image" content="https://pokertools-arena.github.io/og-image.png" />
|
|
22
|
+
<meta property="og:image:secure_url" content="https://pokertools-arena.github.io/og-image.png" />
|
|
23
|
+
<meta property="og:image:type" content="image/png" />
|
|
24
|
+
<meta property="og:image:width" content="1200" />
|
|
25
|
+
<meta property="og:image:height" content="630" />
|
|
26
|
+
<meta property="og:image:alt" content="pokertools-arena: a poker table where frontier AI models play Texas Hold'em." />
|
|
27
|
+
|
|
28
|
+
<!-- Twitter / X -->
|
|
29
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
30
|
+
<meta name="twitter:title" content="pokertools-arena — AI Poker Benchmark" />
|
|
31
|
+
<meta name="twitter:description" content="Frontier models play no-limit Texas Hold'em with identical information and legal actions. Watch every card and decision until one model wins." />
|
|
32
|
+
<meta name="twitter:image" content="https://pokertools-arena.github.io/og-image.png" />
|
|
33
|
+
<meta name="twitter:image:alt" content="pokertools-arena: a poker table where frontier AI models play Texas Hold'em." />
|
|
34
|
+
|
|
35
|
+
<!-- Structured data -->
|
|
36
|
+
<script type="application/ld+json">
|
|
37
|
+
{
|
|
38
|
+
"@context": "https://schema.org",
|
|
39
|
+
"@type": "SoftwareApplication",
|
|
40
|
+
"name": "pokertools-arena",
|
|
41
|
+
"alternateName": "AI Poker Benchmark",
|
|
42
|
+
"applicationCategory": "GameApplication",
|
|
43
|
+
"applicationSubCategory": "AI benchmark",
|
|
44
|
+
"operatingSystem": "Web browser",
|
|
45
|
+
"description": "A browser-first AI poker benchmark where Jev and OpenAI-compatible models play no-limit Texas Hold'em with identical canonical information and legal actions.",
|
|
46
|
+
"url": "https://pokertools-arena.github.io/",
|
|
47
|
+
"image": "https://pokertools-arena.github.io/og-image.png",
|
|
48
|
+
"codeRepository": "https://github.com/pokertools-arena/pokertools-arena.github.io",
|
|
49
|
+
"license": "https://opensource.org/licenses/MIT",
|
|
50
|
+
"programmingLanguage": "JavaScript",
|
|
51
|
+
"isAccessibleForFree": true,
|
|
52
|
+
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" }
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<link rel="stylesheet" href="./styles.css" />
|
|
57
|
+
</head>
|
|
58
|
+
<body>
|
|
59
|
+
<div class="app-shell">
|
|
60
|
+
<header class="topbar">
|
|
61
|
+
<div class="brandbar" aria-label="pokertools-arena">
|
|
62
|
+
<div class="brand-mark">♠</div>
|
|
63
|
+
<div class="brand-copy">
|
|
64
|
+
<div class="brand-title">pokertools-arena</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="topbar-actions">
|
|
68
|
+
<button id="startTopBtn" class="button primary top-action" type="button" title="Start tournament"><span class="action-icon">▶</span><span class="action-label">Start</span></button>
|
|
69
|
+
<button id="seatsBtn" class="button ghost top-action" type="button" title="Edit seats"><span class="action-icon">♟</span><span class="action-label">Seats</span></button>
|
|
70
|
+
<button id="setupBtn" class="button ghost top-action" type="button" title="Connections and tournament settings"><span class="action-icon">⚙</span><span class="action-label">Settings</span></button>
|
|
71
|
+
<button id="testsBtn" class="button ghost top-action" type="button" title="Run the 10-spot decision sanity suite"><span class="action-icon">◇</span><span class="action-label">Tests</span></button>
|
|
72
|
+
<button id="soundBtn" class="button ghost top-action sound-button" type="button" aria-pressed="false" title="Enable table sounds"><span class="action-icon">♪</span><span class="action-label">Sound</span></button>
|
|
73
|
+
<button id="recordBtn" class="button ghost top-action record-button" type="button" aria-pressed="false" title="Record only the poker table"><span class="action-icon">●</span><span class="action-label">Record</span></button>
|
|
74
|
+
<button id="exportBtn" class="button ghost top-action" type="button" disabled title="Export tournament log"><span class="action-icon">↓</span><span class="action-label">Log</span></button>
|
|
75
|
+
<button id="pauseBtn" class="button ghost top-action hidden" type="button"><span class="action-icon">Ⅱ</span><span class="action-label">Pause</span></button>
|
|
76
|
+
<button id="stopBtn" class="button danger top-action hidden" type="button"><span class="action-icon">■</span><span class="action-label">Stop</span></button>
|
|
77
|
+
<a id="repoLink" class="button ghost top-action repo-action" href="https://github.com/pokertools-arena/pokertools-arena.github.io" target="_blank" rel="noopener noreferrer" title="View source on GitHub" aria-label="View source on GitHub"><svg class="action-icon repo-icon" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg><span class="action-label">GitHub</span></a>
|
|
78
|
+
</div>
|
|
79
|
+
</header>
|
|
80
|
+
|
|
81
|
+
<main class="workspace">
|
|
82
|
+
<section class="arena-card">
|
|
83
|
+
<div class="arena-head">
|
|
84
|
+
<div class="arena-status"><span id="statusDot" class="status-dot"></span><span id="statusLabel">IDLE</span></div>
|
|
85
|
+
<div id="tournamentMeta" class="mono muted">Seat 2–10 models, then press Start</div>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div id="winnerBanner" class="winner-banner hidden" role="status" aria-live="polite"></div>
|
|
89
|
+
<div id="pokerTable" class="poker-table">
|
|
90
|
+
<div class="felt-ring"></div>
|
|
91
|
+
<div id="fxLayer" class="fx-layer" aria-hidden="true"></div>
|
|
92
|
+
<div id="seatsLayer" class="seats-layer"></div>
|
|
93
|
+
<div class="table-center">
|
|
94
|
+
<div class="table-brand-stage">
|
|
95
|
+
<div class="table-brand" aria-label="pokertools-arena model benchmark table"><span class="table-brand-mark">♠</span><span class="table-brand-copy"><strong>pokertools-arena</strong><small>model benchmark table</small></span></div>
|
|
96
|
+
<div id="actionToast" class="action-toast hidden" aria-live="polite"></div>
|
|
97
|
+
</div>
|
|
98
|
+
<div id="streetLabel" class="street-label">LOBBY</div>
|
|
99
|
+
<div id="board" class="board"></div>
|
|
100
|
+
<div class="table-hud" aria-label="Hand information">
|
|
101
|
+
<div class="hud-pill hud-pot"><span>POT</span><strong id="potValue">0</strong></div>
|
|
102
|
+
<div class="hud-pill"><span>BLINDS</span><strong id="blindsValue">— / —</strong></div>
|
|
103
|
+
<div class="hud-pill"><span>ANTE</span><strong id="anteValue">—</strong></div>
|
|
104
|
+
<div class="hud-pill"><span>HAND</span><strong id="handValue">—</strong></div>
|
|
105
|
+
<div class="hud-pill"><span>LEVEL</span><strong id="levelValue">—</strong></div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</section>
|
|
110
|
+
|
|
111
|
+
<aside class="inspector">
|
|
112
|
+
<div class="tabs">
|
|
113
|
+
<button class="tab active" data-tab="live">Live</button>
|
|
114
|
+
<button class="tab" data-tab="log">Log</button>
|
|
115
|
+
<button class="tab" data-tab="stats">Stats</button>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div id="tab-live" class="tab-panel active">
|
|
119
|
+
<section class="panel-block decision-panel">
|
|
120
|
+
<div id="decisionPanelTitle" class="panel-title">Current decision</div>
|
|
121
|
+
<div id="decisionEmpty" class="empty-state">Configure seats on the table. During play, the active model, clock, and legal actions appear here.</div>
|
|
122
|
+
<div id="decisionCard" class="decision-card hidden">
|
|
123
|
+
<div class="decision-top">
|
|
124
|
+
<div class="decision-identity"><div id="decisionPlayer" class="decision-player">—</div><div id="decisionModel" class="decision-model-line mono">—</div></div>
|
|
125
|
+
<div class="clock-wrap"><span id="decisionPhase" class="decision-phase">IDLE</span><div id="decisionClock" class="decision-clock">—</div><div id="bankClock" class="mono muted tiny">idle</div></div>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="decision-context" aria-label="Decision context">
|
|
128
|
+
<span><small id="decisionLabelHand">Hand</small><b id="decisionHand">—</b></span>
|
|
129
|
+
<span><small id="decisionLabelStreet">Street</small><b id="decisionStreet">—</b></span>
|
|
130
|
+
<span><small id="decisionLabelPosition">Position</small><b id="decisionPosition">—</b></span>
|
|
131
|
+
<span><small id="decisionLabelOptions">Options</small><b id="decisionOptionCount">—</b></span>
|
|
132
|
+
</div>
|
|
133
|
+
<div class="decision-actions-head"><span id="decisionActionLabel">Legal actions</span><span class="mono muted" id="decisionActionHint">Choose one</span></div>
|
|
134
|
+
<div id="legalActions" class="legal-actions"></div>
|
|
135
|
+
</div>
|
|
136
|
+
</section>
|
|
137
|
+
<section class="panel-block"><div class="panel-title">Recent decisions</div><div id="decisionFeed" class="decision-feed"></div></section>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div id="tab-log" class="tab-panel"><section class="panel-block grow"><div class="panel-title">Tournament events</div><div id="eventLog" class="event-log mono"></div></section></div>
|
|
141
|
+
<div id="tab-stats" class="tab-panel"><section class="panel-block grow"><div class="panel-title">Models</div><div id="statsGrid" class="stats-grid"></div></section></div>
|
|
142
|
+
</aside>
|
|
143
|
+
</main>
|
|
144
|
+
|
|
145
|
+
<footer class="site-footer">
|
|
146
|
+
<div class="site-footer-brand">
|
|
147
|
+
<span class="site-footer-mark" aria-hidden="true">♠</span>
|
|
148
|
+
<span>pokertools-arena <span class="site-footer-sep">·</span> <span class="muted">browser-first AI poker benchmark</span></span>
|
|
149
|
+
</div>
|
|
150
|
+
<nav class="site-footer-links" aria-label="Project links">
|
|
151
|
+
<a href="https://github.com/pokertools-arena/pokertools-arena.github.io" target="_blank" rel="noopener noreferrer">
|
|
152
|
+
<svg class="site-footer-icon" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg>
|
|
153
|
+
<span>Source code</span>
|
|
154
|
+
</a>
|
|
155
|
+
<a href="https://github.com/pokertools-arena/pokertools-arena.github.io/issues" target="_blank" rel="noopener noreferrer">Report an issue</a>
|
|
156
|
+
<a href="https://www.npmjs.com/package/pokertools-arena" target="_blank" rel="noopener noreferrer">npm package</a>
|
|
157
|
+
</nav>
|
|
158
|
+
</footer>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<dialog id="setupDialog" class="setup-dialog">
|
|
162
|
+
<form id="setupForm" method="dialog">
|
|
163
|
+
<div class="dialog-head">
|
|
164
|
+
<div class="dialog-title-row">
|
|
165
|
+
<h2>Settings</h2>
|
|
166
|
+
<button class="info-button" type="button" aria-label="About settings" data-tip="API keys stay in this browser tab and are never written to saved configuration or tournament logs.">i</button>
|
|
167
|
+
</div>
|
|
168
|
+
<button id="closeSetup" type="button" class="icon-button" aria-label="Close settings">×</button>
|
|
169
|
+
</div>
|
|
170
|
+
|
|
171
|
+
<div class="dialog-body setup-body">
|
|
172
|
+
<section class="settings-section">
|
|
173
|
+
<div class="section-head compact-section-head">
|
|
174
|
+
<div class="section-title-row"><h3>Connections</h3><button class="info-button" type="button" aria-label="About API connections" data-tip="Use any browser-accessible OpenAI-compatible API. Base URL is always editable. OpenRouter is an optional preset that also enables Jev Decisions routing.">i</button></div>
|
|
175
|
+
<button id="addConnectionBtn" type="button" class="button ghost small-button">+ Add</button>
|
|
176
|
+
</div>
|
|
177
|
+
<div id="connectionsEditor" class="connections-editor"></div>
|
|
178
|
+
</section>
|
|
179
|
+
|
|
180
|
+
<section class="settings-section">
|
|
181
|
+
<div class="section-head compact-section-head">
|
|
182
|
+
<div class="section-title-row"><h3>Tournament</h3><button class="info-button" type="button" aria-label="About tournament settings" data-tip="Blind levels advance after the configured number of hands. Action time is the per-move deadline; time bank is extra reserve per player.">i</button></div>
|
|
183
|
+
<div id="seatSummary" class="seat-summary">0 / 10 seated</div>
|
|
184
|
+
</div>
|
|
185
|
+
<div class="field-grid tournament-fields">
|
|
186
|
+
<label>Starting stack<input name="startingStack" type="number" min="100" value="10000" /></label>
|
|
187
|
+
<label>Small blind<input name="smallBlind" type="number" min="1" value="25" /></label>
|
|
188
|
+
<label>Big blind<input name="bigBlind" type="number" min="2" value="50" /></label>
|
|
189
|
+
<label>Ante<input name="ante" type="number" min="0" value="5" /></label>
|
|
190
|
+
<label>Hands / level<input name="handsPerLevel" type="number" min="1" value="8" /></label>
|
|
191
|
+
<label>Blind multiplier<input name="blindMultiplier" type="number" min="1.1" max="3" step="0.1" value="1.5" /></label>
|
|
192
|
+
<label>Action time (s)<input name="actionSeconds" type="number" min="1" max="120" value="12" /></label>
|
|
193
|
+
<label>Time bank (s)<input name="timeBankSeconds" type="number" min="0" max="600" value="30" /></label>
|
|
194
|
+
<label>Low-time warning (s)<input name="lowTimeSeconds" type="number" min="0" max="600" value="5" /></label>
|
|
195
|
+
<label>Low-time ring fraction<input name="lowTimeFraction" type="number" min="0" max="1" step="0.05" value="0.25" /></label>
|
|
196
|
+
<label>Action delay (ms)<input name="betweenActionsMs" type="number" min="0" max="5000" value="250" /></label>
|
|
197
|
+
<label>Hand delay (ms)<input name="betweenHandsMs" type="number" min="0" max="10000" value="700" /></label>
|
|
198
|
+
</div>
|
|
199
|
+
</section>
|
|
200
|
+
|
|
201
|
+
<section class="settings-section">
|
|
202
|
+
<div class="section-head compact-section-head">
|
|
203
|
+
<div class="section-title-row"><h3>Benchmark</h3><button class="info-button" type="button" aria-label="About benchmark mode" data-tip="Strategy: every model receives a deterministic hero hand classification from code, so the benchmark focuses on poker strategy. Raw cognition: every model receives raw cards and must identify its own hand. This option applies to all seats and cannot be changed per player.">i</button></div>
|
|
204
|
+
</div>
|
|
205
|
+
<div class="field-grid tournament-fields">
|
|
206
|
+
<label>Benchmark mode
|
|
207
|
+
<select name="benchmarkMode">
|
|
208
|
+
<option value="strategy">Strategy (deterministic hero hand)</option>
|
|
209
|
+
<option value="raw">Raw cognition (raw cards)</option>
|
|
210
|
+
</select>
|
|
211
|
+
</label>
|
|
212
|
+
</div>
|
|
213
|
+
<details class="connection-advanced benchmark-advanced">
|
|
214
|
+
<summary>Diagnostics / developer</summary>
|
|
215
|
+
<div class="field-grid tournament-fields">
|
|
216
|
+
<label>Decision architecture
|
|
217
|
+
<select name="decisionArchitecture">
|
|
218
|
+
<option value="hierarchical">Hierarchical (recommended)</option>
|
|
219
|
+
<option value="flat">Flat legacy (diagnostics)</option>
|
|
220
|
+
</select>
|
|
221
|
+
</label>
|
|
222
|
+
<label>Representation
|
|
223
|
+
<select name="representation">
|
|
224
|
+
<option value="canonical_json">Canonical JSON</option>
|
|
225
|
+
<option value="compact_json">Compact JSON</option>
|
|
226
|
+
<option value="markdown">Markdown</option>
|
|
227
|
+
</select>
|
|
228
|
+
</label>
|
|
229
|
+
<label class="checkbox-field"><input name="spectatorExplanations" type="checkbox" /> Spectator explanations (isolated, off the decision clock)</label>
|
|
230
|
+
</div>
|
|
231
|
+
</details>
|
|
232
|
+
</section>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
<div id="setupError" class="setup-error hidden"></div>
|
|
236
|
+
<div class="dialog-footer compact-footer">
|
|
237
|
+
<button id="saveSettingsBtn" type="submit" class="button primary">Save</button>
|
|
238
|
+
</div>
|
|
239
|
+
</form>
|
|
240
|
+
</dialog>
|
|
241
|
+
|
|
242
|
+
<dialog id="seatDialog" class="seat-dialog">
|
|
243
|
+
<form id="seatForm" method="dialog">
|
|
244
|
+
<div class="dialog-head">
|
|
245
|
+
<div class="dialog-title-row">
|
|
246
|
+
<h2 id="seatDialogTitle">Seat 1</h2>
|
|
247
|
+
<button class="info-button" type="button" aria-label="About seat context" data-tip="Each model receives only its own hole cards plus the same canonical public table state, recent public hands, opponent statistics, and legal actions.">i</button>
|
|
248
|
+
</div>
|
|
249
|
+
<button id="closeSeat" type="button" class="icon-button" aria-label="Close seat editor">×</button>
|
|
250
|
+
</div>
|
|
251
|
+
<div class="dialog-body seat-editor-body">
|
|
252
|
+
<div id="seatLockNotice" class="seat-lock-notice hidden">Seat assignments are locked during a tournament.</div>
|
|
253
|
+
<div class="seat-editor-grid">
|
|
254
|
+
<label>Name<input id="seatName" maxlength="40" placeholder="Claude" /></label>
|
|
255
|
+
<label>Connection<select id="seatConnection"></select></label>
|
|
256
|
+
<label class="seat-model-field">
|
|
257
|
+
<span class="field-label-row">Model <button class="info-button inline-info" type="button" aria-label="About model IDs" data-tip="Enter any model ID accepted by the selected endpoint. The refresh button attempts GET /models. OpenRouter also injects Jev Decisions shortcuts.">i</button></span>
|
|
258
|
+
<div class="model-input-wrap"><input id="seatModel" list="seatModelOptions" autocomplete="off" placeholder="model-id" /><button id="refreshModelsBtn" type="button" class="field-icon-button" title="Refresh models" aria-label="Refresh models">↻</button></div>
|
|
259
|
+
<datalist id="seatModelOptions"></datalist>
|
|
260
|
+
<span id="seatModelStatus" class="field-help"></span>
|
|
261
|
+
</label>
|
|
262
|
+
<label>
|
|
263
|
+
<span class="field-label-row">Protocol <button class="info-button inline-info" type="button" aria-label="About protocols" data-tip="Tool call is preferred when supported. JSON Schema is a strict structured-output fallback. Prompt JSON works with older compatible APIs. Jev Decisions is selected automatically for Jev on OpenRouter.">i</button></span>
|
|
264
|
+
<select id="seatProtocol"><option value="tool">Tool call</option><option value="json_schema">JSON Schema</option><option value="plain_json">Prompt JSON</option><option value="jev_decisions">Jev Decisions</option><option value="jev_native">Jev native</option></select>
|
|
265
|
+
</label>
|
|
266
|
+
<label class="seat-provider-field">
|
|
267
|
+
<span class="field-label-row">Provider <button class="info-button inline-info" type="button" aria-label="About provider pinning" data-tip="Optional provider pin for APIs that support routing, such as OpenRouter. Leave blank for automatic routing.">i</button></span>
|
|
268
|
+
<input id="seatProvider" placeholder="auto" />
|
|
269
|
+
</label>
|
|
270
|
+
</div>
|
|
271
|
+
</div>
|
|
272
|
+
<div id="seatError" class="setup-error hidden"></div>
|
|
273
|
+
<div class="dialog-footer compact-footer split-footer">
|
|
274
|
+
<button id="removeSeatBtn" type="button" class="button danger">Clear</button>
|
|
275
|
+
<div class="seat-footer-actions"><button id="cancelSeatBtn" type="button" class="button ghost">Cancel</button><button id="saveSeatBtn" type="submit" class="button primary">Save</button></div>
|
|
276
|
+
</div>
|
|
277
|
+
</form>
|
|
278
|
+
</dialog>
|
|
279
|
+
|
|
280
|
+
<dialog id="testsDialog" class="tests-dialog">
|
|
281
|
+
<div class="tests-shell">
|
|
282
|
+
<div class="dialog-head tests-dialog-head">
|
|
283
|
+
<div>
|
|
284
|
+
<div class="dialog-title-row"><h2>Decision sanity suite</h2><button class="info-button" type="button" aria-label="About decision tests" data-tip="A small comprehension and reliability check. It is intentionally not a GTO solver, Elo score, or tournament-strength ranking.">i</button></div>
|
|
285
|
+
<div class="dialog-subtitle">The same 10 fixed poker spots are sent independently to every seated model.</div>
|
|
286
|
+
</div>
|
|
287
|
+
<button id="closeTests" type="button" class="icon-button" aria-label="Close tests">×</button>
|
|
288
|
+
</div>
|
|
289
|
+
<div class="tests-body">
|
|
290
|
+
<div class="tests-how" aria-label="How the suite works">
|
|
291
|
+
<div class="tests-how-step"><b>1</b><span><strong>Fixed state</strong><small>Each model receives the same cards, board, stacks, history and legal actions.</small></span></div>
|
|
292
|
+
<div class="tests-how-step"><b>2</b><span><strong>One decision</strong><small>Arena calls that seat using its configured protocol: tool, JSON Schema or Jev Decisions.</small></span></div>
|
|
293
|
+
<div class="tests-how-step"><b>3</b><span><strong>Sanity check</strong><small>PASS only means the chosen action type matches the scenario expectation. It is not a poker-strength score.</small></span></div>
|
|
294
|
+
</div>
|
|
295
|
+
<section class="tests-participants-section">
|
|
296
|
+
<div class="tests-section-title"><span>Models under test</span><small>Every configured seat below is tested.</small></div>
|
|
297
|
+
<div id="testsParticipants" class="tests-participants"></div>
|
|
298
|
+
</section>
|
|
299
|
+
<div class="tests-toolbar">
|
|
300
|
+
<div class="tests-run-copy"><div id="testsStatus" class="tests-status">Ready.</div><div id="testsProgressLabel" class="tests-progress-label mono">0 / 0 decisions</div></div>
|
|
301
|
+
<button id="runTestsBtn" class="button primary" type="button">Run all models</button>
|
|
302
|
+
</div>
|
|
303
|
+
<div class="tests-progress" aria-hidden="true"><i id="testsProgressFill"></i></div>
|
|
304
|
+
<div id="testsResults" class="tests-results"></div>
|
|
305
|
+
</div>
|
|
306
|
+
<div class="dialog-footer compact-footer split-footer tests-footer">
|
|
307
|
+
<span class="muted tiny">Tests use real API calls and may incur provider cost.</span><button id="clearTestsBtn" class="button ghost" type="button">Clear results</button>
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
</dialog>
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
<dialog id="replayDialog" class="replay-dialog">
|
|
314
|
+
<div class="replay-shell">
|
|
315
|
+
<div class="dialog-head">
|
|
316
|
+
<div>
|
|
317
|
+
<div class="dialog-title-row"><h2 id="replayTitle">Decision replay</h2><span id="replayBadge" class="replay-badge">HAND —</span></div>
|
|
318
|
+
<div id="replaySubtitle" class="dialog-subtitle">Snapshot captured immediately before the model acted.</div>
|
|
319
|
+
</div>
|
|
320
|
+
<button id="closeReplay" type="button" class="icon-button" aria-label="Close decision replay">×</button>
|
|
321
|
+
</div>
|
|
322
|
+
<div class="dialog-body replay-body">
|
|
323
|
+
<section class="replay-table-wrap">
|
|
324
|
+
<div class="replay-table">
|
|
325
|
+
<div id="replayOpponents" class="replay-opponents"></div>
|
|
326
|
+
<div class="replay-center">
|
|
327
|
+
<div id="replayStreet" class="replay-street">—</div>
|
|
328
|
+
<div id="replayBoard" class="board replay-board"></div>
|
|
329
|
+
<div id="replayPot" class="replay-pot">POT —</div>
|
|
330
|
+
</div>
|
|
331
|
+
<div id="replayHero" class="replay-hero"></div>
|
|
332
|
+
</div>
|
|
333
|
+
</section>
|
|
334
|
+
<section class="replay-details">
|
|
335
|
+
<div id="replaySummary" class="replay-summary"></div>
|
|
336
|
+
<div class="replay-action-block"><span>Chosen action</span><strong id="replayAction">—</strong></div>
|
|
337
|
+
<div id="replayReason" class="replay-reason"></div>
|
|
338
|
+
<details class="replay-history" open><summary>Actions before this decision</summary><div id="replayHistory"></div></details>
|
|
339
|
+
<details class="replay-legal"><summary>Legal actions offered to the model</summary><div id="replayLegal"></div></details>
|
|
340
|
+
</section>
|
|
341
|
+
</div>
|
|
342
|
+
<div class="dialog-footer replay-footer">
|
|
343
|
+
<div class="replay-share-copy">
|
|
344
|
+
<strong>Share this decision</strong>
|
|
345
|
+
<span id="replayShareStatus">Creates a 1080×1350 PNG from this exact replay snapshot.</span>
|
|
346
|
+
</div>
|
|
347
|
+
<div class="replay-share-actions">
|
|
348
|
+
<button id="copyReplayImage" class="button ghost" type="button">Copy image</button>
|
|
349
|
+
<button id="shareReplayImage" class="button ghost hidden" type="button">Share</button>
|
|
350
|
+
<button id="saveReplayImage" class="button primary" type="button">Save PNG</button>
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
</dialog>
|
|
355
|
+
|
|
356
|
+
<template id="connectionRowTemplate">
|
|
357
|
+
<article class="connection-row">
|
|
358
|
+
<div class="connection-card-head">
|
|
359
|
+
<label class="connection-name">Name<input data-field="name" maxlength="32" placeholder="My API" /></label>
|
|
360
|
+
<label class="connection-kind">
|
|
361
|
+
<span class="field-label-row">Preset <button class="info-button inline-info" type="button" aria-label="About connection presets" data-tip="OpenAI-compatible keeps Base URL fully editable. OpenRouter only fills its standard URL and enables OpenRouter-specific routing. TypeSafe uses the native System One endpoint.">i</button></span>
|
|
362
|
+
<select data-field="kind"><option value="openai">OpenAI-compatible</option><option value="openrouter">OpenRouter</option><option value="typesafe">TypeSafe System One</option></select>
|
|
363
|
+
</label>
|
|
364
|
+
<button type="button" class="remove-connection icon-button" title="Remove connection" aria-label="Remove connection">×</button>
|
|
365
|
+
</div>
|
|
366
|
+
<div class="connection-main-grid">
|
|
367
|
+
<label class="connection-url">Base URL<input data-field="baseUrl" spellcheck="false" placeholder="https://api.example.com/v1" /></label>
|
|
368
|
+
<label><span class="field-label-row">API key <button class="info-button inline-info" type="button" aria-label="About API keys" data-tip="Optional for local or unauthenticated OpenAI-compatible endpoints. Required by OpenRouter, OpenAI, and most hosted providers.">i</button></span><input data-field="apiKey" type="password" autocomplete="off" placeholder="optional" /></label>
|
|
369
|
+
<button type="button" class="test-connection button ghost small-button">Test</button>
|
|
370
|
+
</div>
|
|
371
|
+
<div class="connection-status muted tiny" aria-live="polite"></div>
|
|
372
|
+
<details class="connection-advanced">
|
|
373
|
+
<summary>Advanced</summary>
|
|
374
|
+
<label class="connection-headers">Extra headers JSON<input data-field="headers" spellcheck="false" placeholder='{"X-Custom":"value"}' /></label>
|
|
375
|
+
</details>
|
|
376
|
+
</article>
|
|
377
|
+
</template>
|
|
378
|
+
|
|
379
|
+
<script src="./arena-env.js"></script>
|
|
380
|
+
<script type="module" src="./app.js"></script>
|
|
381
|
+
</body>
|
|
382
|
+
</html>
|