transitions-refine 0.3.20 → 0.3.21
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/package.json +1 -1
- package/server/relay.mjs +13 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "transitions-refine",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.21",
|
|
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": {
|
package/server/relay.mjs
CHANGED
|
@@ -138,13 +138,6 @@ const PENDING_TIMEOUT_MS = Number(process.env.REFINE_PENDING_TIMEOUT_MS) || 1200
|
|
|
138
138
|
// to stop (it returns {stop:true} from /jobs/next). 0 disables. Only the chat
|
|
139
139
|
// loop is affected — a wired REFINE_AGENT_CMD never polls /jobs/next.
|
|
140
140
|
const POLLER_IDLE_STOP_MS = Number(process.env.REFINE_POLLER_IDLE_STOP_MS) || 600000;
|
|
141
|
-
// While the Stop latch is held, a genuinely new `/refine live` session can resume
|
|
142
|
-
// itself implicitly: only after polling has been *quiet* this long (the old loop
|
|
143
|
-
// actually died) do we treat the next poll as a fresh session and auto-resume.
|
|
144
|
-
// Must exceed a looping agent's poll gap, so an agent that ignores Stop and keeps
|
|
145
|
-
// polling can never clear the latch — it just keeps getting {stop:true}. (An
|
|
146
|
-
// updated agent also resumes explicitly via POST /poller/start, no wait needed.)
|
|
147
|
-
const STOP_QUIET_MS = Number(process.env.REFINE_STOP_QUIET_MS) || 15000;
|
|
148
141
|
|
|
149
142
|
/** @type {Map<string, Job>} */
|
|
150
143
|
const jobs = new Map();
|
|
@@ -160,9 +153,6 @@ let lastPollAt = 0;
|
|
|
160
153
|
// re-polls — can never silently revive the session. This is what makes the
|
|
161
154
|
// panel's Stop button stick instead of flipping "Live" back on seconds later.
|
|
162
155
|
let pollerStopped = false;
|
|
163
|
-
// When did a poll last arrive *while latched*? Used to detect that the old loop
|
|
164
|
-
// went quiet so a genuinely new session (or re-run) can auto-resume.
|
|
165
|
-
let lastStoppedPollAt = 0;
|
|
166
156
|
const pollerActive = () => !pollerStopped && now() - lastPollAt < POLLER_TTL_MS;
|
|
167
157
|
const llmAvailable = () => Boolean(agentCmd()) || pollerActive();
|
|
168
158
|
|
|
@@ -740,21 +730,15 @@ const server = createServer(async (req, res) => {
|
|
|
740
730
|
|
|
741
731
|
// GET /jobs/next — long-poll claimed by a `/refine live` agent (LLM jobs).
|
|
742
732
|
if (method === "GET" && path === "/jobs/next") {
|
|
743
|
-
// Stopped latch: a Stop was issued and not yet resumed.
|
|
744
|
-
//
|
|
745
|
-
// /poller/start
|
|
746
|
-
//
|
|
747
|
-
//
|
|
733
|
+
// Stopped latch: a Stop was issued and not yet resumed. STICKY — every poll
|
|
734
|
+
// gets {stop:true} and the poller reports inactive until an explicit
|
|
735
|
+
// POST /poller/start (a fresh `/refine live` / loop announcing itself) or a
|
|
736
|
+
// relay restart. We deliberately do NOT auto-resume on a quiet gap: a stubborn
|
|
737
|
+
// agent's straggler poll arriving seconds later would be misread as a new
|
|
738
|
+
// session and flip the panel back to "Live" — which is exactly the bug where
|
|
739
|
+
// Stop "didn't stick". A pending job still wins so we never drop real work.
|
|
748
740
|
if (pollerStopped && !nextPendingLlm()) {
|
|
749
|
-
|
|
750
|
-
// Quiet gap → the previous loop is gone. This poll is a fresh session.
|
|
751
|
-
pollerStopped = false;
|
|
752
|
-
lastStoppedPollAt = 0;
|
|
753
|
-
// fall through to normal handling below (counts as live again)
|
|
754
|
-
} else {
|
|
755
|
-
lastStoppedPollAt = now(); // a poller is still hammering us → hold the latch
|
|
756
|
-
return send(res, 200, { stop: true });
|
|
757
|
-
}
|
|
741
|
+
return send(res, 200, { stop: true });
|
|
758
742
|
}
|
|
759
743
|
lastPollAt = now();
|
|
760
744
|
if (!lastJobAt) lastJobAt = now(); // seed idle window on the loop's first poll
|
|
@@ -762,8 +746,7 @@ const server = createServer(async (req, res) => {
|
|
|
762
746
|
// loop to exit. A pending job always wins so we never drop real work.
|
|
763
747
|
if ((stopRequested || (POLLER_IDLE_STOP_MS && now() - lastJobAt >= POLLER_IDLE_STOP_MS)) && !nextPendingLlm()) {
|
|
764
748
|
stopRequested = false;
|
|
765
|
-
pollerStopped = true; // latch until /poller/start
|
|
766
|
-
lastStoppedPollAt = 0;
|
|
749
|
+
pollerStopped = true; // latch until an explicit /poller/start
|
|
767
750
|
lastJobAt = 0;
|
|
768
751
|
lastPollAt = 0; // loop is exiting → report it inactive immediately on /health
|
|
769
752
|
return send(res, 200, { stop: true });
|
|
@@ -773,8 +756,7 @@ const server = createServer(async (req, res) => {
|
|
|
773
756
|
if (res.writableEnded) return;
|
|
774
757
|
if (stopRequested && !nextPendingLlm()) {
|
|
775
758
|
stopRequested = false;
|
|
776
|
-
pollerStopped = true; // latch until /poller/start
|
|
777
|
-
lastStoppedPollAt = 0;
|
|
759
|
+
pollerStopped = true; // latch until an explicit /poller/start
|
|
778
760
|
lastJobAt = 0;
|
|
779
761
|
lastPollAt = 0; // loop is exiting → report it inactive immediately on /health
|
|
780
762
|
return send(res, 200, { stop: true });
|
|
@@ -797,8 +779,7 @@ const server = createServer(async (req, res) => {
|
|
|
797
779
|
if (method === "POST" && path === "/poller/stop") {
|
|
798
780
|
const wasActive = now() - lastPollAt < POLLER_TTL_MS;
|
|
799
781
|
stopRequested = true;
|
|
800
|
-
pollerStopped = true; // latch: stays stopped until /poller/start
|
|
801
|
-
lastStoppedPollAt = 0;
|
|
782
|
+
pollerStopped = true; // latch: stays stopped until an explicit /poller/start
|
|
802
783
|
lastPollAt = 0; // report inactive immediately; a straggler poll won't revive it
|
|
803
784
|
return send(res, 200, { ok: true, stopping: wasActive });
|
|
804
785
|
}
|
|
@@ -822,11 +803,10 @@ const server = createServer(async (req, res) => {
|
|
|
822
803
|
|
|
823
804
|
// POST /poller/start — a fresh `/refine live` agent (or loop) announces itself
|
|
824
805
|
// and clears the Stop latch so its polls count as live again. Without this an
|
|
825
|
-
// explicit re-run
|
|
826
|
-
// startup, before the first GET /jobs/next.
|
|
806
|
+
// explicit re-run couldn't resume at all (the sticky latch tells every poll to
|
|
807
|
+
// stop). Call it once at loop startup, before the first GET /jobs/next.
|
|
827
808
|
if (method === "POST" && path === "/poller/start") {
|
|
828
809
|
pollerStopped = false;
|
|
829
|
-
lastStoppedPollAt = 0;
|
|
830
810
|
stopRequested = false;
|
|
831
811
|
lastJobAt = now();
|
|
832
812
|
lastPollAt = now();
|