Fix duplicate info messages for extension updates (#9760)

This commit is contained in:
Jacob MacDonald
2025-09-25 10:58:43 -07:00
committed by GitHub
parent a0c8e3bf2b
commit defda3a97d
3 changed files with 35 additions and 30 deletions
+10 -10
View File
@@ -143,17 +143,17 @@ export async function checkForAllExtensionUpdates(
>, >,
cwd: string = process.cwd(), cwd: string = process.cwd(),
): Promise<Map<string, ExtensionUpdateState>> { ): Promise<Map<string, ExtensionUpdateState>> {
let newStates: Map<string, ExtensionUpdateState> = new Map(
extensionsUpdateState,
);
for (const extension of extensions) { for (const extension of extensions) {
const initialState = extensionsUpdateState.get(extension.name); const initialState = extensionsUpdateState.get(extension.name);
if (initialState === undefined) { if (initialState === undefined) {
if (!extension.installMetadata) { if (!extension.installMetadata) {
setExtensionsUpdateState((prev) => { setExtensionsUpdateState((prev) => {
extensionsUpdateState = new Map(prev); newStates = new Map(prev);
extensionsUpdateState.set( newStates.set(extension.name, ExtensionUpdateState.NOT_UPDATABLE);
extension.name, return newStates;
ExtensionUpdateState.NOT_UPDATABLE,
);
return extensionsUpdateState;
}); });
continue; continue;
} }
@@ -161,14 +161,14 @@ export async function checkForAllExtensionUpdates(
extension, extension,
(updatedState) => { (updatedState) => {
setExtensionsUpdateState((prev) => { setExtensionsUpdateState((prev) => {
extensionsUpdateState = new Map(prev); newStates = new Map(prev);
extensionsUpdateState.set(extension.name, updatedState); newStates.set(extension.name, updatedState);
return extensionsUpdateState; return newStates;
}); });
}, },
cwd, cwd,
); );
} }
} }
return extensionsUpdateState; return newStates;
} }
@@ -143,7 +143,7 @@ describe('useExtensionUpdates', () => {
expect(addItem).toHaveBeenCalledWith( expect(addItem).toHaveBeenCalledWith(
{ {
type: MessageType.INFO, type: MessageType.INFO,
text: 'Extension test-extension has an update available, run "/extensions update test-extension" to install it.', text: 'You have 1 extension with an update available, run "/extensions list" for more information.',
}, },
expect.any(Number), expect.any(Number),
); );
@@ -7,7 +7,7 @@
import type { GeminiCLIExtension } from '@google/gemini-cli-core'; import type { GeminiCLIExtension } from '@google/gemini-cli-core';
import { getErrorMessage } from '../../utils/errors.js'; import { getErrorMessage } from '../../utils/errors.js';
import { ExtensionUpdateState } from '../state/extensions.js'; import { ExtensionUpdateState } from '../state/extensions.js';
import { useMemo, useState } from 'react'; import { useState } from 'react';
import type { UseHistoryManagerReturn } from './useHistoryManager.js'; import type { UseHistoryManagerReturn } from './useHistoryManager.js';
import { MessageType } from '../types.js'; import { MessageType } from '../types.js';
import { import {
@@ -24,13 +24,18 @@ export const useExtensionUpdates = (
const [extensionsUpdateState, setExtensionsUpdateState] = useState( const [extensionsUpdateState, setExtensionsUpdateState] = useState(
new Map<string, ExtensionUpdateState>(), new Map<string, ExtensionUpdateState>(),
); );
useMemo(() => { const [isChecking, setIsChecking] = useState(false);
const checkUpdates = async () => {
(async () => {
if (isChecking) return;
setIsChecking(true);
try {
const updateState = await checkForAllExtensionUpdates( const updateState = await checkForAllExtensionUpdates(
extensions, extensions,
extensionsUpdateState, extensionsUpdateState,
setExtensionsUpdateState, setExtensionsUpdateState,
); );
let extensionsWithUpdatesCount = 0;
for (const extension of extensions) { for (const extension of extensions) {
const prevState = extensionsUpdateState.get(extension.name); const prevState = extensionsUpdateState.get(extension.name);
const currentState = updateState.get(extension.name); const currentState = updateState.get(extension.name);
@@ -70,24 +75,24 @@ export const useExtensionUpdates = (
); );
}); });
} else { } else {
addItem( extensionsWithUpdatesCount++;
{
type: MessageType.INFO,
text: `Extension ${extension.name} has an update available, run "/extensions update ${extension.name}" to install it.`,
},
Date.now(),
);
} }
} }
}; if (extensionsWithUpdatesCount > 0) {
checkUpdates(); const s = extensionsWithUpdatesCount > 1 ? 's' : '';
}, [ addItem(
extensions, {
extensionsUpdateState, type: MessageType.INFO,
setExtensionsUpdateState, text: `You have ${extensionsWithUpdatesCount} extension${s} with an update available, run "/extensions list" for more information.`,
addItem, },
cwd, Date.now(),
]); );
}
} finally {
setIsChecking(false);
}
})();
return { return {
extensionsUpdateState, extensionsUpdateState,
setExtensionsUpdateState, setExtensionsUpdateState,