mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
feat: Add auto update functionality (#4686)
This commit is contained in:
139
packages/cli/src/utils/handleAutoUpdate.ts
Normal file
139
packages/cli/src/utils/handleAutoUpdate.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { spawn } from 'node:child_process';
|
||||
import { UpdateObject } from '../ui/utils/updateCheck.js';
|
||||
import { LoadedSettings } from '../config/settings.js';
|
||||
import { getInstallationInfo } from './installationInfo.js';
|
||||
import { updateEventEmitter } from './updateEventEmitter.js';
|
||||
import { HistoryItem, MessageType } from '../ui/types.js';
|
||||
|
||||
export function handleAutoUpdate(
|
||||
info: UpdateObject | null,
|
||||
settings: LoadedSettings,
|
||||
projectRoot: string,
|
||||
) {
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
|
||||
const installationInfo = getInstallationInfo(
|
||||
projectRoot,
|
||||
settings.merged.disableAutoUpdate ?? false,
|
||||
);
|
||||
|
||||
let combinedMessage = info.message;
|
||||
if (installationInfo.updateMessage) {
|
||||
combinedMessage += `\n${installationInfo.updateMessage}`;
|
||||
}
|
||||
|
||||
updateEventEmitter.emit('update-received', {
|
||||
message: combinedMessage,
|
||||
});
|
||||
|
||||
if (!installationInfo.updateCommand || settings.merged.disableAutoUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updateCommand = installationInfo.updateCommand.replace(
|
||||
'@latest',
|
||||
`@${info.update.latest}`,
|
||||
);
|
||||
|
||||
const updateProcess = spawn(updateCommand, { stdio: 'pipe', shell: true });
|
||||
let errorOutput = '';
|
||||
updateProcess.stderr.on('data', (data) => {
|
||||
errorOutput += data.toString();
|
||||
});
|
||||
|
||||
updateProcess.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
updateEventEmitter.emit('update-success', {
|
||||
message:
|
||||
'Update successful! The new version will be used on your next run.',
|
||||
});
|
||||
} else {
|
||||
updateEventEmitter.emit('update-failed', {
|
||||
message: `Automatic update failed. Please try updating manually. (command: ${updateCommand}, stderr: ${errorOutput.trim()})`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
updateProcess.on('error', (err) => {
|
||||
updateEventEmitter.emit('update-failed', {
|
||||
message: `Automatic update failed. Please try updating manually. (error: ${err.message})`,
|
||||
});
|
||||
});
|
||||
return updateProcess;
|
||||
}
|
||||
|
||||
export function setUpdateHandler(
|
||||
addItem: (item: Omit<HistoryItem, 'id'>, timestamp: number) => void,
|
||||
setUpdateInfo: (info: UpdateObject | null) => void,
|
||||
) {
|
||||
let successfullyInstalled = false;
|
||||
const handleUpdateRecieved = (info: UpdateObject) => {
|
||||
setUpdateInfo(info);
|
||||
const savedMessage = info.message;
|
||||
setTimeout(() => {
|
||||
if (!successfullyInstalled) {
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.INFO,
|
||||
text: savedMessage,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
}
|
||||
setUpdateInfo(null);
|
||||
}, 60000);
|
||||
};
|
||||
|
||||
const handleUpdateFailed = () => {
|
||||
setUpdateInfo(null);
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.ERROR,
|
||||
text: `Automatic update failed. Please try updating manually`,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
};
|
||||
|
||||
const handleUpdateSuccess = () => {
|
||||
successfullyInstalled = true;
|
||||
setUpdateInfo(null);
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.INFO,
|
||||
text: `Update successful! The new version will be used on your next run.`,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
};
|
||||
|
||||
const handleUpdateInfo = (data: { message: string }) => {
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.INFO,
|
||||
text: data.message,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
};
|
||||
|
||||
updateEventEmitter.on('update-received', handleUpdateRecieved);
|
||||
updateEventEmitter.on('update-failed', handleUpdateFailed);
|
||||
updateEventEmitter.on('update-success', handleUpdateSuccess);
|
||||
updateEventEmitter.on('update-info', handleUpdateInfo);
|
||||
|
||||
return () => {
|
||||
updateEventEmitter.off('update-received', handleUpdateRecieved);
|
||||
updateEventEmitter.off('update-failed', handleUpdateFailed);
|
||||
updateEventEmitter.off('update-success', handleUpdateSuccess);
|
||||
updateEventEmitter.off('update-info', handleUpdateInfo);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user