feat(self-update): live progress during install/build so it doesn't look hung

The updater wrote the status once per phase, so the minute-plus npm install and
build steps left the UI frozen on a single label. Add:

- a heartbeat in scripts/self-update.sh (run_step wrapper) that refreshes
  update-status.json every ~3s during the install/build steps with the latest
  output line; full output is still mirrored to the update log.
- a frontend (settings-ui.js) that, during non-terminal phases, shows the live
  status message plus a ticking total-elapsed counter instead of only the static
  phase label.

Takes effect when updating FROM a build that contains it — the detached runner
script (staged from scripts/self-update.sh) and the polling frontend are both
the from-version's copies.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arkon
2026-06-09 03:36:39 +02:00
co-authored by Claude Opus 4.8
parent e82e38e68d
commit d95b4c597c
2 changed files with 44 additions and 6 deletions
+11 -1
View File
@@ -606,7 +606,17 @@ Object.assign(CodemanApp.prototype, {
return;
}
if (!terminal.has(data.phase)) {
this._setUpdateProgress(`↻ ${escapeHtml(this._updatePhaseText(data.phase))}`);
// Prefer the live status message — the updater's heartbeat enriches it with
// the latest npm/build output line so a slow step doesn't look frozen — and
// fall back to the static phase label. Append total elapsed so the counter
// keeps ticking between heartbeats: a clear "still working" signal.
const label = (data.message && data.message.trim()) ? data.message.trim() : this._updatePhaseText(data.phase);
let elapsed = '';
if (data.startedAt) {
const secs = Math.max(0, Math.round((Date.now() - data.startedAt) / 1000));
elapsed = ` <span style="color:var(--text-secondary)">· ${secs}s</span>`;
}
this._setUpdateProgress(`<span class="tunnel-spinner"></span> ${escapeHtml(label)}${elapsed}`);
return;
}
this._stopUpdatePolling();