Files
gemini-cli/packages/cli/src/ui/hooks/useExtensionUpdates.ts
Jacob MacDonald a0c8e3bf2b Re-request consent if necessary when updating extensions (#9517)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-09-25 17:57:59 +00:00

96 lines
2.9 KiB
TypeScript

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
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 type { UseHistoryManagerReturn } from './useHistoryManager.js';
import { MessageType } from '../types.js';
import {
checkForAllExtensionUpdates,
updateExtension,
} from '../../config/extensions/update.js';
import { requestConsentInteractive } from '../../config/extension.js';
export const useExtensionUpdates = (
extensions: GeminiCLIExtension[],
addItem: UseHistoryManagerReturn['addItem'],
cwd: string,
) => {
const [extensionsUpdateState, setExtensionsUpdateState] = useState(
new Map<string, ExtensionUpdateState>(),
);
useMemo(() => {
const checkUpdates = async () => {
const updateState = await checkForAllExtensionUpdates(
extensions,
extensionsUpdateState,
setExtensionsUpdateState,
);
for (const extension of extensions) {
const prevState = extensionsUpdateState.get(extension.name);
const currentState = updateState.get(extension.name);
if (
prevState === currentState ||
currentState !== ExtensionUpdateState.UPDATE_AVAILABLE
) {
continue;
}
if (extension.installMetadata?.autoUpdate) {
updateExtension(
extension,
cwd,
(description) => requestConsentInteractive(description, addItem),
currentState,
(newState) => {
setExtensionsUpdateState((prev) => {
const finalState = new Map(prev);
finalState.set(extension.name, newState);
return finalState;
});
},
)
.then((result) => {
if (!result) return;
addItem(
{
type: MessageType.INFO,
text: `Extension "${extension.name}" successfully updated: ${result.originalVersion}${result.updatedVersion}.`,
},
Date.now(),
);
})
.catch((error) => {
console.error(
`Error updating extension "${extension.name}": ${getErrorMessage(error)}.`,
);
});
} else {
addItem(
{
type: MessageType.INFO,
text: `Extension ${extension.name} has an update available, run "/extensions update ${extension.name}" to install it.`,
},
Date.now(),
);
}
}
};
checkUpdates();
}, [
extensions,
extensionsUpdateState,
setExtensionsUpdateState,
addItem,
cwd,
]);
return {
extensionsUpdateState,
setExtensionsUpdateState,
};
};