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:
parent
78bbebf435
commit
b5f75c6c65
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agenthub",
|
"name": "agenthub",
|
||||||
"version": "0.6.0",
|
"version": "0.6.1",
|
||||||
"description": "Local coordination layer for AI coding agents",
|
"description": "Local coordination layer for AI coding agents",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
|
|||||||
@ -5,11 +5,10 @@ import { dirname, join, parse } from 'node:path';
|
|||||||
import { homedir } from 'node:os';
|
import { homedir } from 'node:os';
|
||||||
|
|
||||||
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
||||||
// In auto-update mode we refresh more often so a freshly pushed version is
|
// In auto-update mode we run an actual background `agenthub update` at most this
|
||||||
// picked up within the hour, and we cool down between background updates so we
|
// often (it self-no-ops when current), so a freshly pushed version is picked up
|
||||||
// never spawn a second reset+build while one is still running.
|
// within the hour without spawning competing reset+builds.
|
||||||
const AUTO_CHECK_INTERVAL_MS = 60 * 60 * 1000;
|
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. */
|
/** Opt-in: set AGENTHUB_AUTO_UPDATE=1 to self-update in the background. */
|
||||||
function autoUpdateEnabled(): boolean {
|
function autoUpdateEnabled(): boolean {
|
||||||
@ -180,11 +179,26 @@ export function maybeNotifyUpdate(rootOverride?: string): void {
|
|||||||
if (!root || !existsSync(join(root, '.git'))) return;
|
if (!root || !existsSync(join(root, '.git'))) return;
|
||||||
|
|
||||||
const branch = currentBranch(root);
|
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 stamp = stampPath('last-update-check');
|
||||||
const interval = auto ? AUTO_CHECK_INTERVAL_MS : CHECK_INTERVAL_MS;
|
if (Date.now() - readStamp(stamp) > CHECK_INTERVAL_MS) {
|
||||||
if (Date.now() - readStamp(stamp) > interval) {
|
|
||||||
writeStamp(stamp);
|
writeStamp(stamp);
|
||||||
try {
|
try {
|
||||||
spawn('git', ['fetch', '--quiet', 'origin', branch], { cwd: root, detached: true, stdio: 'ignore' }).unref();
|
spawn('git', ['fetch', '--quiet', 'origin', branch], { cwd: root, detached: true, stdio: 'ignore' }).unref();
|
||||||
@ -199,18 +213,7 @@ export function maybeNotifyUpdate(rootOverride?: string): void {
|
|||||||
} catch {
|
} catch {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (behind === '0') return;
|
if (behind !== '0') {
|
||||||
|
|
||||||
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 {
|
|
||||||
process.stderr.write(`\n🔄 A newer AgentHub is available (${behind} commit(s) behind). Run \`agenthub update\`.\n\n`);
|
process.stderr.write(`\n🔄 A newer AgentHub is available (${behind} commit(s) behind). Run \`agenthub update\`.\n\n`);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@ -114,7 +114,7 @@ async function runRemote(serverUrl: string, fn: () => Promise<void>): Promise<vo
|
|||||||
export function createProgram(cwd: string): Command {
|
export function createProgram(cwd: string): Command {
|
||||||
const program = new Command('agenthub')
|
const program = new Command('agenthub')
|
||||||
.description('Local coordination layer for AI coding agents')
|
.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)');
|
.option('--server <url>', 'AgentHub server URL (env: AGENTHUB_SERVER)');
|
||||||
|
|
||||||
program
|
program
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user