diff --git a/apps/cli/src/commands/self/index.ts b/apps/cli/src/commands/self/index.ts index 0a08a792..649bd754 100644 --- a/apps/cli/src/commands/self/index.ts +++ b/apps/cli/src/commands/self/index.ts @@ -1,6 +1,6 @@ import { command, flag, subcommands } from 'cmd-ts'; import packageJson from '../../../package.json' with { type: 'json' }; -import { detectPackageManager, performSelfUpdate } from '../../self-update.js'; +import { detectPackageManager, fetchLatestVersion, performSelfUpdate } from '../../self-update.js'; // Re-export for existing tests export { detectPackageManagerFromPath } from '../../self-update.js'; @@ -29,6 +29,17 @@ const updateCommand = command({ const currentVersion = packageJson.version; console.log(`Current version: ${currentVersion}`); + console.log('Checking for updates...'); + + const latestVersion = await fetchLatestVersion(); + if (latestVersion && latestVersion === currentVersion) { + console.log(`Already up to date (${currentVersion}).`); + return; + } + + if (latestVersion) { + console.log(`Update available: ${currentVersion} → ${latestVersion}`); + } console.log(`Updating agentv using ${pm}...\n`); const result = await performSelfUpdate({ pm, currentVersion }); diff --git a/apps/cli/src/self-update.ts b/apps/cli/src/self-update.ts index a7409d74..e2720496 100644 --- a/apps/cli/src/self-update.ts +++ b/apps/cli/src/self-update.ts @@ -16,6 +16,9 @@ */ import { spawn } from 'node:child_process'; +import { get } from 'node:https'; + +const NPM_REGISTRY_URL = 'https://registry.npmjs.org/agentv/latest'; /** * Detect package manager from the script path. @@ -47,6 +50,39 @@ function runCommand(cmd: string, args: string[]): Promise<{ exitCode: number; st }); } +/** + * Fetch the latest published version of agentv from the npm registry. + * Returns null on network errors or timeouts (best-effort). + */ +export function fetchLatestVersion(): Promise { + return new Promise((resolve) => { + const req = get(NPM_REGISTRY_URL, { timeout: 5000 }, (res) => { + if (res.statusCode !== 200) { + res.resume(); + resolve(null); + return; + } + let body = ''; + res.on('data', (chunk: Buffer) => { + body += chunk.toString(); + }); + res.on('end', () => { + try { + const version = JSON.parse(body).version; + resolve(typeof version === 'string' ? version : null); + } catch { + resolve(null); + } + }); + }); + req.on('error', () => resolve(null)); + req.on('timeout', () => { + req.destroy(); + resolve(null); + }); + }); +} + function getInstallArgs(pm: 'bun' | 'npm', versionSpec: string): string[] { const pkg = `agentv@${versionSpec}`; return pm === 'npm' ? ['install', '-g', pkg] : ['add', '-g', pkg];