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

View File

@@ -143,17 +143,17 @@ export async function checkForAllExtensionUpdates(
>,
cwd: string = process.cwd(),
): Promise<Map<string, ExtensionUpdateState>> {
let newStates: Map<string, ExtensionUpdateState> = new Map(
extensionsUpdateState,
);
for (const extension of extensions) {
const initialState = extensionsUpdateState.get(extension.name);
if (initialState === undefined) {
if (!extension.installMetadata) {
setExtensionsUpdateState((prev) => {
extensionsUpdateState = new Map(prev);
extensionsUpdateState.set(
extension.name,
ExtensionUpdateState.NOT_UPDATABLE,
);
return extensionsUpdateState;
newStates = new Map(prev);
newStates.set(extension.name, ExtensionUpdateState.NOT_UPDATABLE);
return newStates;
});
continue;
}
@@ -161,14 +161,14 @@ export async function checkForAllExtensionUpdates(
extension,
(updatedState) => {
setExtensionsUpdateState((prev) => {
extensionsUpdateState = new Map(prev);
extensionsUpdateState.set(extension.name, updatedState);
return extensionsUpdateState;
newStates = new Map(prev);
newStates.set(extension.name, updatedState);
return newStates;
});
},
cwd,
);
}
}
return extensionsUpdateState;
return newStates;
}

View File

@@ -143,7 +143,7 @@ describe('useExtensionUpdates', () => {
expect(addItem).toHaveBeenCalledWith(
{
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),
);

View File

@@ -7,7 +7,7 @@
import type { GeminiCLIExtension } from '@google/gemini-cli-core';
import { getErrorMessage } from '../../utils/errors.js';
import { ExtensionUpdateState } from '../state/extensions.js';
import { useMemo, useState } from 'react';
import { useState } from 'react';
import type { UseHistoryManagerReturn } from './useHistoryManager.js';
import { MessageType } from '../types.js';
import {
@@ -24,13 +24,18 @@ export const useExtensionUpdates = (
const [extensionsUpdateState, setExtensionsUpdateState] = useState(
new Map<string, ExtensionUpdateState>(),
);
useMemo(() => {
const checkUpdates = async () => {
const [isChecking, setIsChecking] = useState(false);
(async () => {
if (isChecking) return;
setIsChecking(true);
try {
const updateState = await checkForAllExtensionUpdates(
extensions,
extensionsUpdateState,
setExtensionsUpdateState,
);
let extensionsWithUpdatesCount = 0;
for (const extension of extensions) {
const prevState = extensionsUpdateState.get(extension.name);
const currentState = updateState.get(extension.name);
@@ -70,24 +75,24 @@ export const useExtensionUpdates = (
);
});
} else {
addItem(
{
type: MessageType.INFO,
text: `Extension ${extension.name} has an update available, run "/extensions update ${extension.name}" to install it.`,
},
Date.now(),
);
extensionsWithUpdatesCount++;
}
}
};
checkUpdates();
}, [
extensions,
extensionsUpdateState,
setExtensionsUpdateState,
addItem,
cwd,
]);
if (extensionsWithUpdatesCount > 0) {
const s = extensionsWithUpdatesCount > 1 ? 's' : '';
addItem(
{
type: MessageType.INFO,
text: `You have ${extensionsWithUpdatesCount} extension${s} with an update available, run "/extensions list" for more information.`,
},
Date.now(),
);
}
} finally {
setIsChecking(false);
}
})();
return {
extensionsUpdateState,
setExtensionsUpdateState,