[extensions] Add extensions update command (#6878)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
christine betts
2025-08-25 19:41:15 +00:00
committed by GitHub
parent 41ece1a8b7
commit f32a54fefc
4 changed files with 174 additions and 4 deletions

View File

@@ -39,6 +39,11 @@ export interface ExtensionInstallMetadata {
type: 'git' | 'local';
}
export interface ExtensionUpdateInfo {
originalVersion: string;
updatedVersion: string;
}
export class ExtensionStorage {
private readonly extensionName: string;
@@ -321,7 +326,7 @@ export async function installExtension(
)
) {
throw new Error(
`Error: Extension "${newExtensionName}" is already installed. Please uninstall it first.`,
`Extension "${newExtensionName}" is already installed. Please uninstall it first.`,
);
}
@@ -346,7 +351,7 @@ export async function uninstallExtension(extensionName: string): Promise<void> {
(installed) => installed.config.name === extensionName,
)
) {
throw new Error(`Error: Extension "${extensionName}" not found.`);
throw new Error(`Extension "${extensionName}" not found.`);
}
const storage = new ExtensionStorage(extensionName);
return await fs.promises.rm(storage.getExtensionDir(), {
@@ -381,3 +386,45 @@ export function toOutputString(extension: Extension): string {
}
return output;
}
export async function updateExtension(
extensionName: string,
): Promise<ExtensionUpdateInfo | undefined> {
const installedExtensions = loadUserExtensions();
const extension = installedExtensions.find(
(installed) => installed.config.name === extensionName,
);
if (!extension) {
throw new Error(
`Extension "${extensionName}" not found. Run gemini extensions list to see available extensions.`,
);
}
if (!extension.installMetadata) {
throw new Error(
`Extension cannot be updated because it is missing the .gemini-extension.install.json file. To update manually, uninstall and then reinstall the updated version.`,
);
}
const originalVersion = extension.config.version;
const tempDir = await ExtensionStorage.createTmpDir();
try {
await copyExtension(extension.path, tempDir);
await uninstallExtension(extensionName);
await installExtension(extension.installMetadata);
const updatedExtension = loadExtension(extension.path);
if (!updatedExtension) {
throw new Error('Updated extension not found after installation.');
}
const updatedVersion = updatedExtension.config.version;
return {
originalVersion,
updatedVersion,
};
} catch (e) {
console.error(`Error updating extension, rolling back. ${e}`);
await copyExtension(tempDir, extension.path);
throw e;
} finally {
await fs.promises.rm(tempDir, { recursive: true, force: true });
}
}