fix(update): harden auto-update — fire agenthub update directly on tick

The old auto path checked `HEAD..origin/branch` right after kicking off a
background fetch, so it read a stale origin ref and only fired on the SECOND
invocation (and never if the agent sat in one long-running `work`).

Now: when AGENTHUB_AUTO_UPDATE is set, a throttled tick (≤1h) spawns
`agenthub update` directly in the background. update does its OWN fresh fetch
+ reset + build and no-ops when current — so it self-heals on the FIRST
invocation, no stale-ref lag. Notify-only path (no flag) unchanged.

Removed the now-unused cooldown const. 122/122 green. Bump 0.6.0 -> 0.6.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
chahinebrini 2026-06-28 00:29:59 +02:00
parent 78bbebf435
commit b5f75c6c65
3 changed files with 24 additions and 21 deletions

View File

@ -1,6 +1,6 @@
{
"name": "agenthub",
"version": "0.6.0",
"version": "0.6.1",
"description": "Local coordination layer for AI coding agents",
"type": "module",
"main": "./dist/index.js",

View File

@ -5,11 +5,10 @@ import { dirname, join, parse } from 'node:path';
import { homedir } from 'node:os';
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
// In auto-update mode we refresh more often so a freshly pushed version is
// picked up within the hour, and we cool down between background updates so we
// never spawn a second reset+build while one is still running.
// In auto-update mode we run an actual background `agenthub update` at most this
// often (it self-no-ops when current), so a freshly pushed version is picked up
// within the hour without spawning competing reset+builds.
const AUTO_CHECK_INTERVAL_MS = 60 * 60 * 1000;
const AUTO_UPDATE_COOLDOWN_MS = 10 * 60 * 1000;
/** Opt-in: set AGENTHUB_AUTO_UPDATE=1 to self-update in the background. */
function autoUpdateEnabled(): boolean {
@ -180,11 +179,26 @@ export function maybeNotifyUpdate(rootOverride?: string): void {
if (!root || !existsSync(join(root, '.git'))) return;
const branch = currentBranch(root);
const auto = autoUpdateEnabled();
// Auto-update: on a throttled tick, fire `agenthub update` directly in the
// background. It does its OWN fresh fetch + reset + build and no-ops when
// already current — so it self-heals on the FIRST invocation. (The old
// path checked a possibly-stale origin ref, so it lagged a fetch cycle and
// took two invocations to ever fire.)
if (autoUpdateEnabled()) {
const stamp = stampPath('last-auto-update');
if (Date.now() - readStamp(stamp) > AUTO_CHECK_INTERVAL_MS) {
writeStamp(stamp);
process.stderr.write('\n🔄 AgentHub: checking for updates in the background…\n\n');
spawnBackgroundUpdate(root);
}
return;
}
// Notify-only: throttled background fetch keeps the behind-count fresh,
// then a one-line hint if the install is behind.
const stamp = stampPath('last-update-check');
const interval = auto ? AUTO_CHECK_INTERVAL_MS : CHECK_INTERVAL_MS;
if (Date.now() - readStamp(stamp) > interval) {
if (Date.now() - readStamp(stamp) > CHECK_INTERVAL_MS) {
writeStamp(stamp);
try {
spawn('git', ['fetch', '--quiet', 'origin', branch], { cwd: root, detached: true, stdio: 'ignore' }).unref();
@ -199,18 +213,7 @@ export function maybeNotifyUpdate(rootOverride?: string): void {
} catch {
return;
}
if (behind === '0') return;
if (auto) {
// Only one background update per cooldown window — a second command while
// the reset+build is in flight must not spawn a competing update.
const autoStamp = stampPath('last-auto-update');
if (Date.now() - readStamp(autoStamp) > AUTO_UPDATE_COOLDOWN_MS) {
writeStamp(autoStamp);
process.stderr.write(`\n🔄 AgentHub: updating in background (${behind} commit(s) behind)…\n\n`);
spawnBackgroundUpdate(root);
}
} else {
if (behind !== '0') {
process.stderr.write(`\n🔄 A newer AgentHub is available (${behind} commit(s) behind). Run \`agenthub update\`.\n\n`);
}
} catch {

View File

@ -114,7 +114,7 @@ async function runRemote(serverUrl: string, fn: () => Promise<void>): Promise<vo
export function createProgram(cwd: string): Command {
const program = new Command('agenthub')
.description('Local coordination layer for AI coding agents')
.version('0.6.0')
.version('0.6.1')
.option('--server <url>', 'AgentHub server URL (env: AGENTHUB_SERVER)');
program