feat(FN-2663): add cached update-check setting, APIs, and banner

- Add global updateCheckEnabled setting to core schema/types and wire dashboard command to cache update checks in the CLI
- Implement dashboard server update-check cache module plus REST routes for status and refresh behavior
- Add dashboard client hook, legacy API helpers, and UpdateAvailableBanner UI to show cached CLI update notices
- Cover update-check server routes, hook behavior, banner rendering, and route registration with focused tests
- Document update-check configuration and API behavior in architecture and settings reference docs
This commit is contained in:
Fusion
2026-04-27 01:40:07 -07:00
committed by gsxdsm
parent 90a28dfe23
commit e80850e7c9
18 changed files with 827 additions and 0 deletions

View File

@@ -46,6 +46,7 @@ import {
resolveClaudeCliExtensionPaths,
setCachedClaudeCliResolution,
} from "./claude-cli-extension.js";
import { getCachedUpdateStatus, isUpdateCheckEnabled } from "../update-cache.js";
import { resolveSelfExtension } from "./self-extension.js";
import { DashboardTUI, DashboardLogSink, isTTYAvailable, type SystemInfo, type GitStatus, type GitCommit, type GitCommitDetail, type GitBranch, type GitWorktree, type FileEntry, type FileReadResult, type TaskStep as TUITaskStep, type TaskLogEntry as TUITaskLogEntry, type TaskDetailData, type TaskEvent } from "./dashboard-tui/index.js";
@@ -1812,6 +1813,30 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
? `${baseUrl}/?token=${encodeURIComponent(dashboardAuthToken)}`
: baseUrl;
const updateMessage = await (async (): Promise<string | null> => {
try {
const updateCheckEnabled = await Promise.race<boolean>([
isUpdateCheckEnabled(),
new Promise<boolean>((resolve) => {
setTimeout(() => resolve(false), 3_000);
}),
]);
if (!updateCheckEnabled) {
return null;
}
const cachedUpdate = getCachedUpdateStatus();
if (!cachedUpdate?.updateAvailable) {
return null;
}
return `⬆ Update available: v${cachedUpdate.latestVersion} (current: v${cachedUpdate.currentVersion})`;
} catch {
return null;
}
})();
// ── TTY Mode: Set system info on TUI ───────────────────────────────
//
// In TTY mode, we populate the TUI System panel instead of printing
@@ -2290,6 +2315,9 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
tui.log("AI engine paused");
}
tui.log("File watcher active");
if (updateMessage) {
tui.log(updateMessage);
}
} else {
// ── Non-TTY Mode: Print plain-text banner ───────────────────────────
//
@@ -2320,6 +2348,9 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
console.log(` • cron: scheduled task execution`);
}
console.log(` File watcher: ✓ active`);
if (updateMessage) {
console.log(` ${updateMessage}`);
}
console.log(` Press Ctrl+C to stop`);
console.log();
}