pokertools-arena 0.4.4 → 0.4.5
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/README.md +1 -1
- package/dist/app.js +26 -1
- package/dist/pokertools-arena.html +26 -1
- package/docs/diagnostics/SUMMARY.md +1 -1
- package/docs/diagnostics/summary.json +1 -1
- package/docs/releases/RELEASE_NOTES.md +10 -0
- package/package.json +1 -1
- package/src/app.js +28 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
| **Package** | `npx pokertools-arena` |
|
|
18
18
|
| **Runtime** | Node.js ≥ 24 for tooling; any modern browser for the app |
|
|
19
19
|
|
|
20
|
-
> **Current release: 0.4.
|
|
20
|
+
> **Current release: 0.4.5.** A maintenance release on top of the 0.4.0 methodology work: modal tooltips float above overflow, the launcher starts exactly once when its default port is busy, real-API diagnostics skip cleanly when repository secrets are absent, the Decision sanity suite attributes results to the correct model, seat editors show the model-derived name, close buttons use centered SVG icons, decision logs no longer repeat the typed-decision caption, and Stop immediately freezes the clock and table effects.
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
package/dist/app.js
CHANGED
|
@@ -115700,6 +115700,16 @@ function showActionToast(text, type = "") {
|
|
|
115700
115700
|
function seatEl(playerId) {
|
|
115701
115701
|
return $(`.seat[data-player-id="${CSS.escape(String(playerId))}"]`, els.seatsLayer);
|
|
115702
115702
|
}
|
|
115703
|
+
function stopTableEffects() {
|
|
115704
|
+
clearTimeout(showActionToast.timer);
|
|
115705
|
+
els.actionToast?.classList.add("hidden");
|
|
115706
|
+
els.pokerTable?.classList.remove("action-message-visible");
|
|
115707
|
+
els.fxLayer?.replaceChildren();
|
|
115708
|
+
for (const el of $$(".seat.fold-flash, .seat.check-flash")) {
|
|
115709
|
+
el.classList.remove("fold-flash");
|
|
115710
|
+
el.classList.remove("check-flash");
|
|
115711
|
+
}
|
|
115712
|
+
}
|
|
115703
115713
|
function animateNewHand(s) {
|
|
115704
115714
|
if (!animationsAllowed()) return;
|
|
115705
115715
|
requestAnimationFrame(() => {
|
|
@@ -115727,6 +115737,12 @@ function animateBoardCards(previousCount, currentCount) {
|
|
|
115727
115737
|
}
|
|
115728
115738
|
function processVisualEffects(s) {
|
|
115729
115739
|
const events = s?.events || [];
|
|
115740
|
+
if (["STOPPED", "ERROR"].includes(s?.status)) {
|
|
115741
|
+
if (events.length) lastProcessedEventId = events.at(-1).id;
|
|
115742
|
+
lastVisualState = s;
|
|
115743
|
+
stopTableEffects();
|
|
115744
|
+
return;
|
|
115745
|
+
}
|
|
115730
115746
|
if (!animationsAllowed()) {
|
|
115731
115747
|
if (events.length) lastProcessedEventId = events.at(-1).id;
|
|
115732
115748
|
lastVisualState = s;
|
|
@@ -117353,6 +117369,10 @@ function championBadgeHtml() {
|
|
|
117353
117369
|
return '<span class="champion-badge" role="img" aria-label="Tournament champion"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6.6 2.6h10.8v4.7a5.4 5.4 0 0 1-10.8 0V2.6Z"/><path d="M10.7 12.4h2.6V15h-2.6z"/><path d="M7.2 15h9.6v2.1H7.2z"/><path d="M5.6 18.2h12.8v2.3H5.6z"/></svg></span>';
|
|
117354
117370
|
}
|
|
117355
117371
|
function renderDecision(s) {
|
|
117372
|
+
if (["STOPPED", "ERROR"].includes(s?.status)) {
|
|
117373
|
+
stopClock();
|
|
117374
|
+
return;
|
|
117375
|
+
}
|
|
117356
117376
|
const d = s?.currentDecision;
|
|
117357
117377
|
const last = latestDecisionEvent(s);
|
|
117358
117378
|
const shouldShowCard = Boolean(d || last || seatAssignments.filter(Boolean).length);
|
|
@@ -118269,7 +118289,12 @@ els.pauseBtn.addEventListener("click", () => {
|
|
|
118269
118289
|
if (!director) return;
|
|
118270
118290
|
currentState?.status === "PAUSED" ? director.resume() : director.pause();
|
|
118271
118291
|
});
|
|
118272
|
-
els.stopBtn.addEventListener("click", () =>
|
|
118292
|
+
els.stopBtn.addEventListener("click", () => {
|
|
118293
|
+
if (!director) return;
|
|
118294
|
+
stopClock();
|
|
118295
|
+
stopTableEffects();
|
|
118296
|
+
director.stop();
|
|
118297
|
+
});
|
|
118273
118298
|
els.exportBtn.addEventListener("click", () => {
|
|
118274
118299
|
if (!director?.events?.length) return;
|
|
118275
118300
|
downloadText(`${director.config?.id || "pokertools-arena"}.jsonl`, director.exportJsonl());
|
|
@@ -118375,6 +118375,16 @@ function showActionToast(text, type = "") {
|
|
|
118375
118375
|
function seatEl(playerId) {
|
|
118376
118376
|
return $(`.seat[data-player-id="${CSS.escape(String(playerId))}"]`, els.seatsLayer);
|
|
118377
118377
|
}
|
|
118378
|
+
function stopTableEffects() {
|
|
118379
|
+
clearTimeout(showActionToast.timer);
|
|
118380
|
+
els.actionToast?.classList.add("hidden");
|
|
118381
|
+
els.pokerTable?.classList.remove("action-message-visible");
|
|
118382
|
+
els.fxLayer?.replaceChildren();
|
|
118383
|
+
for (const el of $$(".seat.fold-flash, .seat.check-flash")) {
|
|
118384
|
+
el.classList.remove("fold-flash");
|
|
118385
|
+
el.classList.remove("check-flash");
|
|
118386
|
+
}
|
|
118387
|
+
}
|
|
118378
118388
|
function animateNewHand(s) {
|
|
118379
118389
|
if (!animationsAllowed()) return;
|
|
118380
118390
|
requestAnimationFrame(() => {
|
|
@@ -118402,6 +118412,12 @@ function animateBoardCards(previousCount, currentCount) {
|
|
|
118402
118412
|
}
|
|
118403
118413
|
function processVisualEffects(s) {
|
|
118404
118414
|
const events = s?.events || [];
|
|
118415
|
+
if (["STOPPED", "ERROR"].includes(s?.status)) {
|
|
118416
|
+
if (events.length) lastProcessedEventId = events.at(-1).id;
|
|
118417
|
+
lastVisualState = s;
|
|
118418
|
+
stopTableEffects();
|
|
118419
|
+
return;
|
|
118420
|
+
}
|
|
118405
118421
|
if (!animationsAllowed()) {
|
|
118406
118422
|
if (events.length) lastProcessedEventId = events.at(-1).id;
|
|
118407
118423
|
lastVisualState = s;
|
|
@@ -120028,6 +120044,10 @@ function championBadgeHtml() {
|
|
|
120028
120044
|
return '<span class="champion-badge" role="img" aria-label="Tournament champion"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6.6 2.6h10.8v4.7a5.4 5.4 0 0 1-10.8 0V2.6Z"/><path d="M10.7 12.4h2.6V15h-2.6z"/><path d="M7.2 15h9.6v2.1H7.2z"/><path d="M5.6 18.2h12.8v2.3H5.6z"/></svg></span>';
|
|
120029
120045
|
}
|
|
120030
120046
|
function renderDecision(s) {
|
|
120047
|
+
if (["STOPPED", "ERROR"].includes(s?.status)) {
|
|
120048
|
+
stopClock();
|
|
120049
|
+
return;
|
|
120050
|
+
}
|
|
120031
120051
|
const d = s?.currentDecision;
|
|
120032
120052
|
const last = latestDecisionEvent(s);
|
|
120033
120053
|
const shouldShowCard = Boolean(d || last || seatAssignments.filter(Boolean).length);
|
|
@@ -120944,7 +120964,12 @@ els.pauseBtn.addEventListener("click", () => {
|
|
|
120944
120964
|
if (!director) return;
|
|
120945
120965
|
currentState?.status === "PAUSED" ? director.resume() : director.pause();
|
|
120946
120966
|
});
|
|
120947
|
-
els.stopBtn.addEventListener("click", () =>
|
|
120967
|
+
els.stopBtn.addEventListener("click", () => {
|
|
120968
|
+
if (!director) return;
|
|
120969
|
+
stopClock();
|
|
120970
|
+
stopTableEffects();
|
|
120971
|
+
director.stop();
|
|
120972
|
+
});
|
|
120948
120973
|
els.exportBtn.addEventListener("click", () => {
|
|
120949
120974
|
if (!director?.events?.length) return;
|
|
120950
120975
|
downloadText(`${director.config?.id || "pokertools-arena"}.jsonl`, director.exportJsonl());
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Release notes
|
|
2
2
|
|
|
3
|
+
## 0.4.5 — Maintenance
|
|
4
|
+
|
|
5
|
+
- **Stop now freezes the display.** Stopping a tournament clears the decision
|
|
6
|
+
clock and cancels every table effect still in flight (chip flies, action
|
|
7
|
+
toast, fold/check flashes and their pending timers). Previously the turn ring
|
|
8
|
+
and clock kept counting and queued animations finished after the run had
|
|
9
|
+
stopped, because the last broadcast still carried `currentDecision` and the
|
|
10
|
+
effects queue was never drained. `renderDecision` and `processVisualEffects`
|
|
11
|
+
now hard-stop on `STOPPED`/`ERROR`.
|
|
12
|
+
|
|
3
13
|
## 0.4.4 — Maintenance
|
|
4
14
|
|
|
5
15
|
- **Cleaner decision logs.** Removed the repeated spectator caption ("This
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pokertools-arena",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Browser-first AI poker benchmark powered by @pokertools/engine with generic OpenAI-compatible endpoints, optional OpenRouter/Jev Decisions routing, deterministic hierarchical decisions, paired fixed-state methodology, and reproducible reporting.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/app.js
CHANGED
|
@@ -142,6 +142,17 @@ function showActionToast(text, type = '') {
|
|
|
142
142
|
}, 1550);
|
|
143
143
|
}
|
|
144
144
|
function seatEl(playerId) { return $(`.seat[data-player-id="${CSS.escape(String(playerId))}"]`, els.seatsLayer); }
|
|
145
|
+
// Cancel every effect the table may still have in flight: chip flies, toast,
|
|
146
|
+
// fold/check flashes and their pending timeouts. Called when a run stops so the
|
|
147
|
+
// display freezes instead of finishing queued animations.
|
|
148
|
+
function stopTableEffects() {
|
|
149
|
+
clearTimeout(showActionToast.timer);
|
|
150
|
+
els.actionToast?.classList.add('hidden');
|
|
151
|
+
els.pokerTable?.classList.remove('action-message-visible');
|
|
152
|
+
els.fxLayer?.replaceChildren();
|
|
153
|
+
for (const el of $$('.seat.fold-flash, .seat.check-flash'))
|
|
154
|
+
{ el.classList.remove('fold-flash'); el.classList.remove('check-flash'); }
|
|
155
|
+
}
|
|
145
156
|
function animateNewHand(s) {
|
|
146
157
|
if (!animationsAllowed()) return;
|
|
147
158
|
requestAnimationFrame(() => {
|
|
@@ -169,6 +180,15 @@ function animateBoardCards(previousCount, currentCount) {
|
|
|
169
180
|
}
|
|
170
181
|
function processVisualEffects(s) {
|
|
171
182
|
const events = s?.events || [];
|
|
183
|
+
// Once a run is stopped (or errored) no further effects may be scheduled.
|
|
184
|
+
// Without this, already-live chip flies, flashes and sounds continued after
|
|
185
|
+
// Stop, and an in-flight broadcast could replay the last decision's effects.
|
|
186
|
+
if (['STOPPED', 'ERROR'].includes(s?.status)) {
|
|
187
|
+
if (events.length) lastProcessedEventId = events.at(-1).id;
|
|
188
|
+
lastVisualState = s;
|
|
189
|
+
stopTableEffects();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
172
192
|
if (!animationsAllowed()) {
|
|
173
193
|
if (events.length) lastProcessedEventId = events.at(-1).id;
|
|
174
194
|
lastVisualState = s;
|
|
@@ -1569,6 +1589,9 @@ function championBadgeHtml() {
|
|
|
1569
1589
|
+ '</svg></span>';
|
|
1570
1590
|
}
|
|
1571
1591
|
function renderDecision(s) {
|
|
1592
|
+
// A stopped/errored run must not keep a live clock. stop() clears
|
|
1593
|
+
// currentDecision, but the last broadcast can still carry it, so guard here.
|
|
1594
|
+
if (['STOPPED', 'ERROR'].includes(s?.status)) { stopClock(); return; }
|
|
1572
1595
|
const d = s?.currentDecision;
|
|
1573
1596
|
const last = latestDecisionEvent(s);
|
|
1574
1597
|
const shouldShowCard = Boolean(d || last || seatAssignments.filter(Boolean).length);
|
|
@@ -2326,7 +2349,11 @@ els.setupBtn.addEventListener('click', openSetup);
|
|
|
2326
2349
|
els.closeSetup.addEventListener('click', () => els.setupDialog.close());
|
|
2327
2350
|
els.addConnectionBtn.addEventListener('click', () => addConnectionRow({ name: `API ${els.connectionsEditor.children.length + 1}`, kind: 'openai', baseUrl: 'https://api.openai.com/v1' }));
|
|
2328
2351
|
els.pauseBtn.addEventListener('click', () => { if (!director) return; currentState?.status === 'PAUSED' ? director.resume() : director.pause(); });
|
|
2329
|
-
els.stopBtn.addEventListener('click', () =>
|
|
2352
|
+
els.stopBtn.addEventListener('click', () => {
|
|
2353
|
+
if (!director) return;
|
|
2354
|
+
stopClock(); stopTableEffects();
|
|
2355
|
+
director.stop();
|
|
2356
|
+
});
|
|
2330
2357
|
els.exportBtn.addEventListener('click', () => { if (!director?.events?.length) return; downloadText(`${director.config?.id || 'pokertools-arena'}.jsonl`, director.exportJsonl()); });
|
|
2331
2358
|
els.seatsBtn.addEventListener('click', () => {
|
|
2332
2359
|
if (director && ['RUNNING', 'PAUSED'].includes(director.status)) return;
|