diff --git a/package.json b/package.json index 1862365..ab6ea34 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/cli/commands/update.ts b/src/cli/commands/update.ts index bd49dfe..6f43737 100644 --- a/src/cli/commands/update.ts +++ b/src/cli/commands/update.ts @@ -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 { diff --git a/src/cli/index.ts b/src/cli/index.ts index 3b5b4b9..ba5f692 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -114,7 +114,7 @@ async function runRemote(serverUrl: string, fn: () => Promise): Promise', 'AgentHub server URL (env: AGENTHUB_SERVER)'); program