@yemi33/minions 0.1.2051 → 0.1.2052
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/dashboard/js/refresh.js +56 -4
- package/dashboard.js +5 -0
- package/engine.js +11 -0
- package/package.json +1 -1
package/dashboard/js/refresh.js
CHANGED
|
@@ -73,7 +73,7 @@ const RENDER_VERSIONS = {
|
|
|
73
73
|
prd: 1,
|
|
74
74
|
prs: 2,
|
|
75
75
|
archivedPrds: 1,
|
|
76
|
-
engine:
|
|
76
|
+
engine: 3,
|
|
77
77
|
version: 1,
|
|
78
78
|
adoThrottle: 1,
|
|
79
79
|
ghThrottle: 1,
|
|
@@ -147,6 +147,47 @@ function _formatCcDrawerLabel(autoMode) {
|
|
|
147
147
|
return runtimeLabel + (model ? ' (' + model + ')' : '') + '-powered. Full minions context. Enter to send, Shift+Enter for newline.';
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
// W-mpnc4u8c001d9d6c — #engine-quick-stats "Next tick in Xs" countdown.
|
|
151
|
+
//
|
|
152
|
+
// Origin is engine.lastTickAt (stamped by tickInner at the start of every
|
|
153
|
+
// tick, see engine.js) plus engine.tickInterval (server-side config, surfaced
|
|
154
|
+
// via _buildStatusFastState). The chip updates every 1s without re-rendering
|
|
155
|
+
// the surrounding row — mirrors the _tickAgentRuntimes pattern in
|
|
156
|
+
// dashboard/js/render-agents.js. The countdown clamps at 0 and shows "due"
|
|
157
|
+
// when the engine is mid-tick (PR polls etc. can push tick-to-tick wall time
|
|
158
|
+
// past the nominal interval). When the engine isn't running, show "—" so a
|
|
159
|
+
// stale lastTickAt doesn't render a ticking countdown the engine can't honor.
|
|
160
|
+
var _engineCountdown = { lastTickAt: 0, tickInterval: 0, engineState: 'stopped' };
|
|
161
|
+
var _engineNextTickTimer = null;
|
|
162
|
+
|
|
163
|
+
function _formatNextTickText() {
|
|
164
|
+
var state = _engineCountdown.engineState;
|
|
165
|
+
if (state !== 'running' && state !== 'stopping') return '—';
|
|
166
|
+
var last = _engineCountdown.lastTickAt;
|
|
167
|
+
var interval = _engineCountdown.tickInterval;
|
|
168
|
+
if (!last || !interval) return '—';
|
|
169
|
+
var remainingMs = last + interval - Date.now();
|
|
170
|
+
if (remainingMs <= 0) return 'due';
|
|
171
|
+
return Math.ceil(remainingMs / 1000) + 's';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function _updateNextTickChip() {
|
|
175
|
+
var el = document.getElementById('engine-next-tick');
|
|
176
|
+
if (!el) {
|
|
177
|
+
if (_engineNextTickTimer) { clearInterval(_engineNextTickTimer); _engineNextTickTimer = null; }
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
var next = _formatNextTickText();
|
|
181
|
+
if (el.textContent !== next) el.textContent = next;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function _startNextTickTicker() {
|
|
185
|
+
// Idempotent — refresh.js re-runs every 4s and reseats the data on the
|
|
186
|
+
// shared _engineCountdown; we don't want compounding intervals.
|
|
187
|
+
if (_engineNextTickTimer) return;
|
|
188
|
+
_engineNextTickTimer = setInterval(_updateNextTickChip, 1000);
|
|
189
|
+
}
|
|
190
|
+
|
|
150
191
|
function _processStatusUpdate(data) {
|
|
151
192
|
// Detect fresh install — clear stale browser state AND reload so module-scoped
|
|
152
193
|
// JS caches (_sectionCache, _prevCounts, _managedProcessesLastItems,
|
|
@@ -246,10 +287,21 @@ function _processStatusUpdate(data) {
|
|
|
246
287
|
var qs = document.getElementById('engine-quick-stats');
|
|
247
288
|
if (qs && data.engine) {
|
|
248
289
|
var wt = data.engine.worktreeCount != null ? data.engine.worktreeCount : '-';
|
|
249
|
-
var tick = data.engine.tick || '-';
|
|
250
290
|
var pid = data.engine.pid || '-';
|
|
251
|
-
//
|
|
252
|
-
|
|
291
|
+
// W-mpnc4u8c001d9d6c — replace the dead "Tick: -" chip (control.json
|
|
292
|
+
// never carried a `tick` field) with a live "Next tick in Xs" countdown
|
|
293
|
+
// driven by engine.lastTickAt (stamped at the start of every tickInner)
|
|
294
|
+
// and engine.tickInterval (config, surfaced in the status payload).
|
|
295
|
+
// _updateNextTickChip below ticks the inner span every 1s without
|
|
296
|
+
// re-rendering this whole row.
|
|
297
|
+
_engineCountdown.lastTickAt = Number(data.engine.lastTickAt) || 0;
|
|
298
|
+
_engineCountdown.tickInterval = Number(data.engine.tickInterval) || 0;
|
|
299
|
+
_engineCountdown.engineState = data.engine.state || 'stopped';
|
|
300
|
+
// eslint-disable-next-line no-unsanitized/property -- reason: composed from internal engine metrics (pid, lastTickAt/tickInterval, worktreeCount) and a literal id; no user data flows in
|
|
301
|
+
qs.innerHTML = '<span>PID: <b>' + pid + '</b></span>' +
|
|
302
|
+
'<span>Next tick in: <b id="engine-next-tick">' + _formatNextTickText() + '</b></span>' +
|
|
303
|
+
'<span>Worktrees: <b>' + wt + '</b></span>';
|
|
304
|
+
_startNextTickTicker();
|
|
253
305
|
}
|
|
254
306
|
}
|
|
255
307
|
if (_changed('version', data.version)) renderVersionBanner(data.version);
|
package/dashboard.js
CHANGED
|
@@ -1730,6 +1730,11 @@ function _buildStatusFastState() {
|
|
|
1730
1730
|
// possibly-cached payload (false-positive banner regression #2754).
|
|
1731
1731
|
heartbeatAgeMs: engineState.heartbeat ? hbAge : null,
|
|
1732
1732
|
heartbeatStale: !!(engineState.heartbeat && hbAge > ENGINE_HEARTBEAT_STALE_MS),
|
|
1733
|
+
// W-mpnc4u8c001d9d6c — Surface the tick cadence so the client's
|
|
1734
|
+
// #engine-quick-stats "Next tick in Xs" countdown reads the SAME value
|
|
1735
|
+
// the engine actually uses (Settings parity rule). Paired with
|
|
1736
|
+
// control.lastTickAt (above) stamped at the start of every tickInner.
|
|
1737
|
+
tickInterval: Number(CONFIG?.engine?.tickInterval) || shared.ENGINE_DEFAULTS.tickInterval,
|
|
1733
1738
|
},
|
|
1734
1739
|
adoThrottle: ado.getAdoThrottleState(),
|
|
1735
1740
|
ghThrottle: gh.getGhThrottleState(),
|
package/engine.js
CHANGED
|
@@ -6522,6 +6522,17 @@ async function tickInner() {
|
|
|
6522
6522
|
// Per-phase guards inside the rest of tickInner are sub-task -b's scope.
|
|
6523
6523
|
if (_isTickStale(myGeneration)) return;
|
|
6524
6524
|
|
|
6525
|
+
// W-mpnc4u8c001d9d6c — Stamp `lastTickAt` on every tickInner entry so the
|
|
6526
|
+
// dashboard's #engine-quick-stats "Next tick in Xs" countdown has a reliable
|
|
6527
|
+
// anchor (control.json carries no separate tick-counter field). Synchronous
|
|
6528
|
+
// mutator, no awaits inside the lock — mirrors the writer contract used by
|
|
6529
|
+
// engine/cli.js#writeHeartbeatNow. Distinct from control.heartbeat: this
|
|
6530
|
+
// advances once per tick cadence, not on the 15s heartbeat cadence, so the
|
|
6531
|
+
// client can render an accurate "next tick" countdown without coupling to
|
|
6532
|
+
// the staleness signal.
|
|
6533
|
+
try { shared.mutateControl(c => { c.lastTickAt = Date.now(); return c; }); }
|
|
6534
|
+
catch (e) { log('warn', `lastTickAt write: ${e.message}`); }
|
|
6535
|
+
|
|
6525
6536
|
const config = getConfig();
|
|
6526
6537
|
tickCount++;
|
|
6527
6538
|
const now = Date.now();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2052",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|