mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-22 01:49:33 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5adf044399 | ||
|
|
d95b4c597c |
No files matched your search
@@ -1,5 +1,15 @@
|
|||||||
# aicodeman
|
# aicodeman
|
||||||
|
|
||||||
|
## 0.9.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Self-updater: show live progress during the slow steps so an update no longer looks frozen.
|
||||||
|
- The detached update runner (`scripts/self-update.sh`) now emits a heartbeat every few seconds during `npm install` and `npm run build`, refreshing the update status with the latest output line (full output is still written to the update log).
|
||||||
|
- App Settings → Updates now shows the live status message plus a ticking elapsed-time counter during non-terminal phases, instead of only a static phase label.
|
||||||
|
|
||||||
|
This takes effect when updating _from_ a build that includes it — the detached runner script and the polling UI are both the from-version's copies.
|
||||||
|
|
||||||
## 0.9.5
|
## 0.9.5
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ When user says "COM":
|
|||||||
|
|
||||||
CI runs `npm run check:lockfile` on every push/PR, so lockfile drift fails the build even if the `version-packages` script is bypassed.
|
CI runs `npm run check:lockfile` on every push/PR, so lockfile drift fails the build even if the `version-packages` script is bypassed.
|
||||||
|
|
||||||
**Version**: 0.9.5 (must match `package.json`)
|
**Version**: 0.9.6 (must match `package.json`)
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "aicodeman",
|
"name": "aicodeman",
|
||||||
"version": "0.9.5",
|
"version": "0.9.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "aicodeman",
|
"name": "aicodeman",
|
||||||
"version": "0.9.5",
|
"version": "0.9.6",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aicodeman",
|
"name": "aicodeman",
|
||||||
"version": "0.9.5",
|
"version": "0.9.6",
|
||||||
"description": "The missing control plane for AI coding agents - run 20 autonomous agents with real-time monitoring and session persistence",
|
"description": "The missing control plane for AI coding agents - run 20 autonomous agents with real-time monitoring and session persistence",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|||||||
+33
-5
@@ -93,6 +93,35 @@ write_status() {
|
|||||||
' || echo "[self-update] WARN: status write failed ($phase)"
|
' || echo "[self-update] WARN: status write failed ($phase)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Run a slow step with a heartbeat so the status file (and the UI polling it) keeps
|
||||||
|
# moving instead of looking frozen during npm install / build. Every few seconds it
|
||||||
|
# refreshes the status with the latest output line, and mirrors full output to the
|
||||||
|
# log. Returns the wrapped command's exit code.
|
||||||
|
run_step() {
|
||||||
|
local phase="$1" base="$2"; shift 2
|
||||||
|
local step_log; step_log="$(mktemp "${TMPDIR:-/tmp}/codeman-update.XXXXXX" 2>/dev/null || echo "/tmp/codeman-update.$$")"
|
||||||
|
write_status "$phase" "$base…"
|
||||||
|
echo "[self-update] $phase: $* (output below)"
|
||||||
|
"$@" >"$step_log" 2>&1 &
|
||||||
|
local pid=$! start=$SECONDS last_line=""
|
||||||
|
while kill -0 "$pid" 2>/dev/null; do
|
||||||
|
sleep 3
|
||||||
|
local line
|
||||||
|
line="$(tr -d '\r' <"$step_log" 2>/dev/null | grep -aE '[^[:space:]]' | tail -n 1 | cut -c1-100)"
|
||||||
|
[[ -n "$line" && "$line" != "$last_line" ]] && last_line="$line"
|
||||||
|
if [[ -n "$last_line" ]]; then
|
||||||
|
write_status "$phase" "$base… · $last_line"
|
||||||
|
else
|
||||||
|
write_status "$phase" "$base… (working)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
wait "$pid"; local rc=$?
|
||||||
|
echo "[self-update] $phase finished in $((SECONDS - start))s (rc=$rc)"
|
||||||
|
cat "$step_log" >>"$LOG" 2>/dev/null || true
|
||||||
|
rm -f "$step_log" 2>/dev/null || true
|
||||||
|
return $rc
|
||||||
|
}
|
||||||
|
|
||||||
fail() {
|
fail() {
|
||||||
local msg="$1" err="${2:-}"
|
local msg="$1" err="${2:-}"
|
||||||
echo "[self-update] FAILED: $msg ($err)"
|
echo "[self-update] FAILED: $msg ($err)"
|
||||||
@@ -138,13 +167,12 @@ git fetch --tags --force origin "refs/tags/$TAG:refs/tags/$TAG" 2>/dev/null \
|
|||||||
write_status "checkout" "Checking out $TAG…"
|
write_status "checkout" "Checking out $TAG…"
|
||||||
git -c advice.detachedHead=false checkout --force "$TAG" || rollback_and_fail "Could not check out $TAG"
|
git -c advice.detachedHead=false checkout --force "$TAG" || rollback_and_fail "Could not check out $TAG"
|
||||||
|
|
||||||
# 4) Install dependencies.
|
# 4) Install dependencies (heartbeat keeps the UI live during this slow step).
|
||||||
write_status "installing" "Installing dependencies…"
|
run_step "installing" "Installing dependencies" npm install --no-fund --no-audit \
|
||||||
npm install --no-fund --no-audit || rollback_and_fail "Dependency install failed"
|
|| rollback_and_fail "Dependency install failed"
|
||||||
|
|
||||||
# 5) Build (gate the restart on success — never restart into a torn dist/).
|
# 5) Build (gate the restart on success — never restart into a torn dist/).
|
||||||
write_status "building" "Building…"
|
run_step "building" "Building" npm run build || rollback_and_fail "Build failed"
|
||||||
npm run build || rollback_and_fail "Build failed"
|
|
||||||
|
|
||||||
# 6) Restart the service so the new code loads. Write the terminal pre-restart
|
# 6) Restart the service so the new code loads. Write the terminal pre-restart
|
||||||
# marker FIRST so the freshly-booted server can reconcile it deterministically.
|
# marker FIRST so the freshly-booted server can reconcile it deterministically.
|
||||||
|
|||||||
@@ -606,7 +606,17 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!terminal.has(data.phase)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
this._stopUpdatePolling();
|
this._stopUpdatePolling();
|
||||||
|
|||||||
Reference in new issue
Block a user