transitions-refine 0.3.12 → 0.3.14
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.
|
@@ -54,6 +54,19 @@ The relay reports the agent as "available" for ~120s after your last poll, so
|
|
|
54
54
|
short pauses keep you live. A successful job always resets idle, so an active
|
|
55
55
|
session never backs off.
|
|
56
56
|
|
|
57
|
+
0. **Announce yourself once, before the first poll.** The relay keeps a *sticky*
|
|
58
|
+
Stop latch: after a panel **Stop** (or the idle auto-stop) it answers every
|
|
59
|
+
`GET /jobs/next` with `{"stop": true}` until a new agent explicitly resumes —
|
|
60
|
+
so a stopped session can't silently come back. Clear the latch a single time
|
|
61
|
+
at startup, then begin polling:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
curl -s -X POST http://localhost:7331/poller/start
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Do **not** call this again mid-loop (it would defeat a user's Stop). Only on a
|
|
68
|
+
fresh `/refine live`.
|
|
69
|
+
|
|
57
70
|
1. **Claim the next job (long-poll).** This call blocks up to ~25s, then returns.
|
|
58
71
|
|
|
59
72
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "transitions-refine",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.14",
|
|
4
4
|
"description": "Live, agent-driven Refine panel for CSS/Motion transitions — injects a timeline + Refine UI and runs transitions.dev suggestions via your coding agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -446,6 +446,10 @@ async function pollOnce() {
|
|
|
446
446
|
|
|
447
447
|
async function loop() {
|
|
448
448
|
log(`live refine loop → ${RELAY} (workspace: ${WORKSPACE})`);
|
|
449
|
+
// Announce ourselves so the relay clears any prior Stop latch — otherwise a
|
|
450
|
+
// relay that's still "stopped" from a previous panel Stop would answer our
|
|
451
|
+
// first poll with {stop:true} and we'd exit immediately.
|
|
452
|
+
try { await post("/poller/start", {}); } catch {}
|
|
449
453
|
// eslint-disable-next-line no-constant-condition
|
|
450
454
|
while (true) {
|
|
451
455
|
try {
|
package/server/relay.mjs
CHANGED
|
@@ -99,7 +99,14 @@ const now = () => Date.now();
|
|
|
99
99
|
// When did a `/refine live` agent last poll? Used to know if LLM mode can be
|
|
100
100
|
// served by a live editor agent (vs. needing REFINE_AGENT_CMD).
|
|
101
101
|
let lastPollAt = 0;
|
|
102
|
-
|
|
102
|
+
// Stop latch. Set by POST /poller/stop (and idle auto-stop); cleared ONLY by an
|
|
103
|
+
// explicit POST /poller/start (a fresh `/refine live` / agent loop announcing
|
|
104
|
+
// itself). While latched the poller reports inactive and every GET /jobs/next
|
|
105
|
+
// answers {stop:true}, so a loop that ignores the stop — or keeps polling /
|
|
106
|
+
// re-polls — can never silently revive the session. This is what makes the
|
|
107
|
+
// panel's Stop button stick instead of flipping "Live" back on seconds later.
|
|
108
|
+
let pollerStopped = false;
|
|
109
|
+
const pollerActive = () => !pollerStopped && now() - lastPollAt < POLLER_TTL_MS;
|
|
103
110
|
const llmAvailable = () => Boolean(AGENT_CMD) || pollerActive();
|
|
104
111
|
|
|
105
112
|
// Stop signal for the in-chat `/refine live` loop. Set by POST /poller/stop
|
|
@@ -653,12 +660,19 @@ const server = createServer(async (req, res) => {
|
|
|
653
660
|
|
|
654
661
|
// GET /jobs/next — long-poll claimed by a `/refine live` agent (LLM jobs).
|
|
655
662
|
if (method === "GET" && path === "/jobs/next") {
|
|
663
|
+
// Stopped latch: a Stop was issued and not yet resumed. Keep telling every
|
|
664
|
+
// poller to exit and report inactive (don't touch lastPollAt) until a fresh
|
|
665
|
+
// POST /poller/start. A pending job still wins so we never drop real work.
|
|
666
|
+
if (pollerStopped && !nextPendingLlm()) {
|
|
667
|
+
return send(res, 200, { stop: true });
|
|
668
|
+
}
|
|
656
669
|
lastPollAt = now();
|
|
657
670
|
if (!lastJobAt) lastJobAt = now(); // seed idle window on the loop's first poll
|
|
658
|
-
//
|
|
659
|
-
// A pending job always wins so we never drop real work
|
|
671
|
+
// Idle auto-stop (or a leftover stopRequested) → latch stopped + tell the
|
|
672
|
+
// loop to exit. A pending job always wins so we never drop real work.
|
|
660
673
|
if ((stopRequested || (POLLER_IDLE_STOP_MS && now() - lastJobAt >= POLLER_IDLE_STOP_MS)) && !nextPendingLlm()) {
|
|
661
674
|
stopRequested = false;
|
|
675
|
+
pollerStopped = true; // latch until an explicit /poller/start
|
|
662
676
|
lastJobAt = 0;
|
|
663
677
|
lastPollAt = 0; // loop is exiting → report it inactive immediately on /health
|
|
664
678
|
return send(res, 200, { stop: true });
|
|
@@ -668,6 +682,7 @@ const server = createServer(async (req, res) => {
|
|
|
668
682
|
if (res.writableEnded) return;
|
|
669
683
|
if (stopRequested && !nextPendingLlm()) {
|
|
670
684
|
stopRequested = false;
|
|
685
|
+
pollerStopped = true; // latch until an explicit /poller/start
|
|
671
686
|
lastJobAt = 0;
|
|
672
687
|
lastPollAt = 0; // loop is exiting → report it inactive immediately on /health
|
|
673
688
|
return send(res, 200, { stop: true });
|
|
@@ -688,8 +703,23 @@ const server = createServer(async (req, res) => {
|
|
|
688
703
|
// POST /poller/stop — the panel's "Stop" button. Flags the in-chat loop to
|
|
689
704
|
// exit on its next poll. No-op for a wired REFINE_AGENT_CMD (never polls).
|
|
690
705
|
if (method === "POST" && path === "/poller/stop") {
|
|
706
|
+
const wasActive = now() - lastPollAt < POLLER_TTL_MS;
|
|
691
707
|
stopRequested = true;
|
|
692
|
-
|
|
708
|
+
pollerStopped = true; // latch: stays stopped until POST /poller/start
|
|
709
|
+
lastPollAt = 0; // report inactive immediately; a straggler poll won't revive it
|
|
710
|
+
return send(res, 200, { ok: true, stopping: wasActive });
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// POST /poller/start — a fresh `/refine live` agent (or loop) announces itself
|
|
714
|
+
// and clears the Stop latch so its polls count as live again. Without this an
|
|
715
|
+
// explicit re-run couldn't resume, since a latched relay tells every poll to
|
|
716
|
+
// stop. Call it once at loop startup, before the first GET /jobs/next.
|
|
717
|
+
if (method === "POST" && path === "/poller/start") {
|
|
718
|
+
pollerStopped = false;
|
|
719
|
+
stopRequested = false;
|
|
720
|
+
lastJobAt = now();
|
|
721
|
+
lastPollAt = now();
|
|
722
|
+
return send(res, 200, { ok: true });
|
|
693
723
|
}
|
|
694
724
|
|
|
695
725
|
const m = path.match(/^\/jobs\/([^/]+)(?:\/(status|result|error))?$/);
|