From c3971754bf4bd5877d7a57c523b981c09d4fa35d Mon Sep 17 00:00:00 2001 From: Eddie Santos <9561596+eddie-santos@users.noreply.github.com> Date: Tue, 17 Jun 2025 08:24:07 -0700 Subject: Auto-update notifications (#1110) --- packages/cli/src/ui/App.tsx | 9 ++++++ .../cli/src/ui/components/UpdateNotification.tsx | 23 ++++++++++++++ packages/cli/src/ui/utils/updateCheck.ts | 35 ++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 packages/cli/src/ui/components/UpdateNotification.tsx create mode 100644 packages/cli/src/ui/utils/updateCheck.ts (limited to 'packages/cli/src/ui') diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx index 9a4ecbd3..a5317b30 100644 --- a/packages/cli/src/ui/App.tsx +++ b/packages/cli/src/ui/App.tsx @@ -60,6 +60,8 @@ import { import { useGitBranchName } from './hooks/useGitBranchName.js'; import { useTextBuffer } from './components/shared/text-buffer.js'; import * as fs from 'fs'; +import { UpdateNotification } from './components/UpdateNotification.js'; +import { checkForUpdates } from './utils/updateCheck.js'; const CTRL_EXIT_PROMPT_DURATION_MS = 1000; @@ -76,6 +78,12 @@ export const AppWrapper = (props: AppProps) => ( ); const App = ({ config, settings, startupWarnings = [] }: AppProps) => { + const [updateMessage, setUpdateMessage] = useState(null); + + useEffect(() => { + checkForUpdates().then(setUpdateMessage); + }, []); + const { history, addItem, clearItems, loadHistory } = useHistory(); const { consoleMessages, @@ -467,6 +475,7 @@ const App = ({ config, settings, startupWarnings = [] }: AppProps) => {
+ {updateMessage && } , ...history.map((h) => ( ( + + {message} + +); diff --git a/packages/cli/src/ui/utils/updateCheck.ts b/packages/cli/src/ui/utils/updateCheck.ts new file mode 100644 index 00000000..17d30378 --- /dev/null +++ b/packages/cli/src/ui/utils/updateCheck.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import updateNotifier from 'update-notifier'; +import { readPackageUp } from 'read-package-up'; +import process from 'node:process'; + +export async function checkForUpdates(): Promise { + // read-package-up looks for the closest package.json from cwd + const pkgResult = await readPackageUp({ cwd: process.cwd() }); + if (!pkgResult) { + return null; + } + + const { packageJson } = pkgResult; + const notifier = updateNotifier({ + pkg: { + name: packageJson.name, + version: packageJson.version, + }, + // check every time + updateCheckInterval: 0, + // allow notifier to run in scripts + shouldNotifyInNpmScript: true, + }); + + if (notifier.update) { + return `Gemini CLI update available! ${notifier.update.current} → ${notifier.update.latest}\nRun npm install -g ${packageJson.name} to update`; + } + + return null; +} -- cgit v1.2.3