mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-30 04:30:48 +00:00
Merge branch 'main' into mingholy/fix/acp-model-list
This commit is contained in:
commit
a31699ed73
351 changed files with 20743 additions and 5801 deletions
|
|
@ -65,7 +65,7 @@ describe('handleAutoUpdate', () => {
|
|||
mockSettings = {
|
||||
merged: {
|
||||
general: {
|
||||
disableAutoUpdate: false,
|
||||
enableAutoUpdate: true,
|
||||
},
|
||||
},
|
||||
} as LoadedSettings;
|
||||
|
|
@ -94,32 +94,29 @@ describe('handleAutoUpdate', () => {
|
|||
expect(mockSpawn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should do nothing if update nag is disabled', () => {
|
||||
mockSettings.merged.general!.disableUpdateNag = true;
|
||||
handleAutoUpdate(mockUpdateInfo, mockSettings, '/root', mockSpawn);
|
||||
expect(mockGetInstallationInfo).not.toHaveBeenCalled();
|
||||
expect(mockUpdateEventEmitter.emit).not.toHaveBeenCalled();
|
||||
expect(mockSpawn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should emit "update-received" but not update if auto-updates are disabled', () => {
|
||||
mockSettings.merged.general!.disableAutoUpdate = true;
|
||||
it('should show manual update message when enableAutoUpdate is false', () => {
|
||||
// When enableAutoUpdate is false, gemini.tsx won't call checkForUpdates(),
|
||||
// but if handleAutoUpdate is still called, it should show a manual update message.
|
||||
mockSettings.merged.general!.enableAutoUpdate = false;
|
||||
mockGetInstallationInfo.mockReturnValue({
|
||||
updateCommand: 'npm i -g @qwen-code/qwen-code@latest',
|
||||
updateMessage: 'Please update manually.',
|
||||
updateMessage:
|
||||
'Please run npm i -g @qwen-code/qwen-code@latest to update',
|
||||
isGlobal: true,
|
||||
packageManager: PackageManager.NPM,
|
||||
});
|
||||
|
||||
handleAutoUpdate(mockUpdateInfo, mockSettings, '/root', mockSpawn);
|
||||
|
||||
expect(mockUpdateEventEmitter.emit).toHaveBeenCalledTimes(1);
|
||||
// Should still emit update-received with manual update message
|
||||
expect(mockUpdateEventEmitter.emit).toHaveBeenCalledWith(
|
||||
'update-received',
|
||||
{
|
||||
message: 'An update is available!\nPlease update manually.',
|
||||
message:
|
||||
'An update is available!\nPlease run npm i -g @qwen-code/qwen-code@latest to update',
|
||||
},
|
||||
);
|
||||
// Should NOT spawn update when enableAutoUpdate is false
|
||||
expect(mockSpawn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@ export function handleAutoUpdate(
|
|||
return;
|
||||
}
|
||||
|
||||
if (settings.merged.general?.disableUpdateNag) {
|
||||
return;
|
||||
}
|
||||
// enableAutoUpdate is checked in gemini.tsx before calling this function,
|
||||
// so if we get here, auto-update is enabled (or undefined, which defaults to enabled).
|
||||
const isAutoUpdateEnabled =
|
||||
settings.merged.general?.enableAutoUpdate !== false;
|
||||
|
||||
const installationInfo = getInstallationInfo(
|
||||
projectRoot,
|
||||
settings.merged.general?.disableAutoUpdate ?? false,
|
||||
isAutoUpdateEnabled,
|
||||
);
|
||||
|
||||
let combinedMessage = info.message;
|
||||
|
|
@ -42,10 +43,8 @@ export function handleAutoUpdate(
|
|||
message: combinedMessage,
|
||||
});
|
||||
|
||||
if (
|
||||
!installationInfo.updateCommand ||
|
||||
settings.merged.general?.disableAutoUpdate
|
||||
) {
|
||||
// Don't automatically run the update if auto-update is disabled or no update command
|
||||
if (!installationInfo.updateCommand || !isAutoUpdateEnabled) {
|
||||
return;
|
||||
}
|
||||
const isNightly = info.update.latest.includes('nightly');
|
||||
|
|
|
|||
|
|
@ -178,13 +178,15 @@ describe('getInstallationInfo', () => {
|
|||
throw new Error('Command failed');
|
||||
});
|
||||
|
||||
const info = getInstallationInfo(projectRoot, false);
|
||||
// isAutoUpdateEnabled = true -> "Attempting to automatically update"
|
||||
const info = getInstallationInfo(projectRoot, true);
|
||||
expect(info.packageManager).toBe(PackageManager.PNPM);
|
||||
expect(info.isGlobal).toBe(true);
|
||||
expect(info.updateCommand).toBe('pnpm add -g @qwen-code/qwen-code@latest');
|
||||
expect(info.updateMessage).toContain('Attempting to automatically update');
|
||||
|
||||
const infoDisabled = getInstallationInfo(projectRoot, true);
|
||||
// isAutoUpdateEnabled = false -> "Please run..."
|
||||
const infoDisabled = getInstallationInfo(projectRoot, false);
|
||||
expect(infoDisabled.updateMessage).toContain('Please run pnpm add');
|
||||
});
|
||||
|
||||
|
|
@ -196,7 +198,8 @@ describe('getInstallationInfo', () => {
|
|||
throw new Error('Command failed');
|
||||
});
|
||||
|
||||
const info = getInstallationInfo(projectRoot, false);
|
||||
// isAutoUpdateEnabled = true -> "Attempting to automatically update"
|
||||
const info = getInstallationInfo(projectRoot, true);
|
||||
expect(info.packageManager).toBe(PackageManager.YARN);
|
||||
expect(info.isGlobal).toBe(true);
|
||||
expect(info.updateCommand).toBe(
|
||||
|
|
@ -204,7 +207,8 @@ describe('getInstallationInfo', () => {
|
|||
);
|
||||
expect(info.updateMessage).toContain('Attempting to automatically update');
|
||||
|
||||
const infoDisabled = getInstallationInfo(projectRoot, true);
|
||||
// isAutoUpdateEnabled = false -> "Please run..."
|
||||
const infoDisabled = getInstallationInfo(projectRoot, false);
|
||||
expect(infoDisabled.updateMessage).toContain('Please run yarn global add');
|
||||
});
|
||||
|
||||
|
|
@ -216,13 +220,15 @@ describe('getInstallationInfo', () => {
|
|||
throw new Error('Command failed');
|
||||
});
|
||||
|
||||
const info = getInstallationInfo(projectRoot, false);
|
||||
// isAutoUpdateEnabled = true -> "Attempting to automatically update"
|
||||
const info = getInstallationInfo(projectRoot, true);
|
||||
expect(info.packageManager).toBe(PackageManager.BUN);
|
||||
expect(info.isGlobal).toBe(true);
|
||||
expect(info.updateCommand).toBe('bun add -g @qwen-code/qwen-code@latest');
|
||||
expect(info.updateMessage).toContain('Attempting to automatically update');
|
||||
|
||||
const infoDisabled = getInstallationInfo(projectRoot, true);
|
||||
// isAutoUpdateEnabled = false -> "Please run..."
|
||||
const infoDisabled = getInstallationInfo(projectRoot, false);
|
||||
expect(infoDisabled.updateMessage).toContain('Please run bun add');
|
||||
});
|
||||
|
||||
|
|
@ -301,7 +307,8 @@ describe('getInstallationInfo', () => {
|
|||
throw new Error('Command failed');
|
||||
});
|
||||
|
||||
const info = getInstallationInfo(projectRoot, false);
|
||||
// isAutoUpdateEnabled = true -> "Attempting to automatically update"
|
||||
const info = getInstallationInfo(projectRoot, true);
|
||||
expect(info.packageManager).toBe(PackageManager.NPM);
|
||||
expect(info.isGlobal).toBe(true);
|
||||
expect(info.updateCommand).toBe(
|
||||
|
|
@ -309,7 +316,8 @@ describe('getInstallationInfo', () => {
|
|||
);
|
||||
expect(info.updateMessage).toContain('Attempting to automatically update');
|
||||
|
||||
const infoDisabled = getInstallationInfo(projectRoot, true);
|
||||
// isAutoUpdateEnabled = false -> "Please run..."
|
||||
const infoDisabled = getInstallationInfo(projectRoot, false);
|
||||
expect(infoDisabled.updateMessage).toContain('Please run npm install');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export interface InstallationInfo {
|
|||
|
||||
export function getInstallationInfo(
|
||||
projectRoot: string,
|
||||
isAutoUpdateDisabled: boolean,
|
||||
isAutoUpdateEnabled: boolean,
|
||||
): InstallationInfo {
|
||||
const cliPath = process.argv[1];
|
||||
if (!cliPath) {
|
||||
|
|
@ -99,9 +99,9 @@ export function getInstallationInfo(
|
|||
packageManager: PackageManager.PNPM,
|
||||
isGlobal: true,
|
||||
updateCommand,
|
||||
updateMessage: isAutoUpdateDisabled
|
||||
? `Please run ${updateCommand} to update`
|
||||
: 'Installed with pnpm. Attempting to automatically update now...',
|
||||
updateMessage: isAutoUpdateEnabled
|
||||
? 'Installed with pnpm. Attempting to automatically update now...'
|
||||
: `Please run ${updateCommand} to update`,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -112,9 +112,9 @@ export function getInstallationInfo(
|
|||
packageManager: PackageManager.YARN,
|
||||
isGlobal: true,
|
||||
updateCommand,
|
||||
updateMessage: isAutoUpdateDisabled
|
||||
? `Please run ${updateCommand} to update`
|
||||
: 'Installed with yarn. Attempting to automatically update now...',
|
||||
updateMessage: isAutoUpdateEnabled
|
||||
? 'Installed with yarn. Attempting to automatically update now...'
|
||||
: `Please run ${updateCommand} to update`,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -132,9 +132,9 @@ export function getInstallationInfo(
|
|||
packageManager: PackageManager.BUN,
|
||||
isGlobal: true,
|
||||
updateCommand,
|
||||
updateMessage: isAutoUpdateDisabled
|
||||
? `Please run ${updateCommand} to update`
|
||||
: 'Installed with bun. Attempting to automatically update now...',
|
||||
updateMessage: isAutoUpdateEnabled
|
||||
? 'Installed with bun. Attempting to automatically update now...'
|
||||
: `Please run ${updateCommand} to update`,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -165,9 +165,9 @@ export function getInstallationInfo(
|
|||
packageManager: PackageManager.NPM,
|
||||
isGlobal: true,
|
||||
updateCommand,
|
||||
updateMessage: isAutoUpdateDisabled
|
||||
? `Please run ${updateCommand} to update`
|
||||
: 'Installed with npm. Attempting to automatically update now...',
|
||||
updateMessage: isAutoUpdateEnabled
|
||||
? 'Installed with npm. Attempting to automatically update now...'
|
||||
: `Please run ${updateCommand} to update`,
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ describe('SettingsUtils', () => {
|
|||
description: 'Accessibility settings.',
|
||||
showInDialog: false,
|
||||
properties: {
|
||||
disableLoadingPhrases: {
|
||||
enableLoadingPhrases: {
|
||||
type: 'boolean',
|
||||
label: 'Disable Loading Phrases',
|
||||
category: 'UI',
|
||||
|
|
@ -285,14 +285,14 @@ describe('SettingsUtils', () => {
|
|||
|
||||
it('should handle nested settings correctly', () => {
|
||||
const settings = makeMockSettings({
|
||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
||||
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||
});
|
||||
const mergedSettings = makeMockSettings({
|
||||
ui: { accessibility: { disableLoadingPhrases: false } },
|
||||
ui: { accessibility: { enableLoadingPhrases: false } },
|
||||
});
|
||||
|
||||
const value = getEffectiveValue(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
settings,
|
||||
mergedSettings,
|
||||
);
|
||||
|
|
@ -316,7 +316,7 @@ describe('SettingsUtils', () => {
|
|||
it('should return all setting keys', () => {
|
||||
const keys = getAllSettingKeys();
|
||||
expect(keys).toContain('test');
|
||||
expect(keys).toContain('ui.accessibility.disableLoadingPhrases');
|
||||
expect(keys).toContain('ui.accessibility.enableLoadingPhrases');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -343,9 +343,9 @@ describe('SettingsUtils', () => {
|
|||
describe('isValidSettingKey', () => {
|
||||
it('should return true for valid setting keys', () => {
|
||||
expect(isValidSettingKey('ui.requiresRestart')).toBe(true);
|
||||
expect(
|
||||
isValidSettingKey('ui.accessibility.disableLoadingPhrases'),
|
||||
).toBe(true);
|
||||
expect(isValidSettingKey('ui.accessibility.enableLoadingPhrases')).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return false for invalid setting keys', () => {
|
||||
|
|
@ -358,7 +358,7 @@ describe('SettingsUtils', () => {
|
|||
it('should return correct category for valid settings', () => {
|
||||
expect(getSettingCategory('ui.requiresRestart')).toBe('UI');
|
||||
expect(
|
||||
getSettingCategory('ui.accessibility.disableLoadingPhrases'),
|
||||
getSettingCategory('ui.accessibility.enableLoadingPhrases'),
|
||||
).toBe('UI');
|
||||
});
|
||||
|
||||
|
|
@ -392,7 +392,7 @@ describe('SettingsUtils', () => {
|
|||
const uiSettings = categories['UI'];
|
||||
const uiKeys = uiSettings.map((s) => s.key);
|
||||
expect(uiKeys).toContain('ui.requiresRestart');
|
||||
expect(uiKeys).toContain('ui.accessibility.disableLoadingPhrases');
|
||||
expect(uiKeys).toContain('ui.accessibility.enableLoadingPhrases');
|
||||
expect(uiKeys).not.toContain('ui.theme'); // This is now marked false
|
||||
});
|
||||
|
||||
|
|
@ -422,7 +422,7 @@ describe('SettingsUtils', () => {
|
|||
|
||||
const keys = booleanSettings.map((s) => s.key);
|
||||
expect(keys).toContain('ui.requiresRestart');
|
||||
expect(keys).toContain('ui.accessibility.disableLoadingPhrases');
|
||||
expect(keys).toContain('ui.accessibility.enableLoadingPhrases');
|
||||
expect(keys).not.toContain('privacy.usageStatisticsEnabled');
|
||||
expect(keys).not.toContain('security.auth.selectedType'); // Advanced setting
|
||||
expect(keys).not.toContain('security.auth.useExternal'); // Advanced setting
|
||||
|
|
@ -455,7 +455,7 @@ describe('SettingsUtils', () => {
|
|||
expect(dialogKeys).toContain('ui.requiresRestart');
|
||||
|
||||
// Should include nested settings marked for dialog
|
||||
expect(dialogKeys).toContain('ui.accessibility.disableLoadingPhrases');
|
||||
expect(dialogKeys).toContain('ui.accessibility.enableLoadingPhrases');
|
||||
|
||||
// Should NOT include settings marked as hidden
|
||||
expect(dialogKeys).not.toContain('ui.theme'); // Hidden
|
||||
|
|
@ -602,14 +602,14 @@ describe('SettingsUtils', () => {
|
|||
it('should return true when value differs from default', () => {
|
||||
expect(isSettingModified('ui.requiresRestart', true)).toBe(true);
|
||||
expect(
|
||||
isSettingModified('ui.accessibility.disableLoadingPhrases', true),
|
||||
isSettingModified('ui.accessibility.enableLoadingPhrases', true),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when value matches default', () => {
|
||||
expect(isSettingModified('ui.requiresRestart', false)).toBe(false);
|
||||
expect(
|
||||
isSettingModified('ui.accessibility.disableLoadingPhrases', false),
|
||||
isSettingModified('ui.accessibility.enableLoadingPhrases', false),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -629,11 +629,11 @@ describe('SettingsUtils', () => {
|
|||
|
||||
it('should return true for nested settings that exist', () => {
|
||||
const settings = makeMockSettings({
|
||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
||||
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||
});
|
||||
expect(
|
||||
settingExistsInScope(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
settings,
|
||||
),
|
||||
).toBe(true);
|
||||
|
|
@ -643,7 +643,7 @@ describe('SettingsUtils', () => {
|
|||
const settings = makeMockSettings({});
|
||||
expect(
|
||||
settingExistsInScope(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
settings,
|
||||
),
|
||||
).toBe(false);
|
||||
|
|
@ -653,7 +653,7 @@ describe('SettingsUtils', () => {
|
|||
const settings = makeMockSettings({ ui: { accessibility: {} } });
|
||||
expect(
|
||||
settingExistsInScope(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
settings,
|
||||
),
|
||||
).toBe(false);
|
||||
|
|
@ -675,25 +675,25 @@ describe('SettingsUtils', () => {
|
|||
it('should set nested setting value', () => {
|
||||
const pendingSettings = makeMockSettings({});
|
||||
const result = setPendingSettingValue(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
true,
|
||||
pendingSettings,
|
||||
);
|
||||
|
||||
expect(result.ui?.accessibility?.disableLoadingPhrases).toBe(true);
|
||||
expect(result.ui?.accessibility?.enableLoadingPhrases).toBe(true);
|
||||
});
|
||||
|
||||
it('should preserve existing nested settings', () => {
|
||||
const pendingSettings = makeMockSettings({
|
||||
ui: { accessibility: { disableLoadingPhrases: false } },
|
||||
ui: { accessibility: { enableLoadingPhrases: false } },
|
||||
});
|
||||
const result = setPendingSettingValue(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
true,
|
||||
pendingSettings,
|
||||
);
|
||||
|
||||
expect(result.ui?.accessibility?.disableLoadingPhrases).toBe(true);
|
||||
expect(result.ui?.accessibility?.enableLoadingPhrases).toBe(true);
|
||||
});
|
||||
|
||||
it('should not mutate original settings', () => {
|
||||
|
|
@ -1030,7 +1030,7 @@ describe('SettingsUtils', () => {
|
|||
const settings = makeMockSettings({}); // nested setting doesn't exist
|
||||
|
||||
const result = isDefaultValue(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
settings,
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
|
|
@ -1038,11 +1038,11 @@ describe('SettingsUtils', () => {
|
|||
|
||||
it('should return false when nested setting exists in scope', () => {
|
||||
const settings = makeMockSettings({
|
||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
||||
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||
}); // nested setting exists
|
||||
|
||||
const result = isDefaultValue(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
settings,
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -1080,14 +1080,14 @@ describe('SettingsUtils', () => {
|
|||
|
||||
it('should return false for nested settings that exist in scope', () => {
|
||||
const settings = makeMockSettings({
|
||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
||||
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||
});
|
||||
const mergedSettings = makeMockSettings({
|
||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
||||
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||
});
|
||||
|
||||
const result = isValueInherited(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
settings,
|
||||
mergedSettings,
|
||||
);
|
||||
|
|
@ -1097,11 +1097,11 @@ describe('SettingsUtils', () => {
|
|||
it('should return true for nested settings that do not exist in scope', () => {
|
||||
const settings = makeMockSettings({});
|
||||
const mergedSettings = makeMockSettings({
|
||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
||||
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||
});
|
||||
|
||||
const result = isValueInherited(
|
||||
'ui.accessibility.disableLoadingPhrases',
|
||||
'ui.accessibility.enableLoadingPhrases',
|
||||
settings,
|
||||
mergedSettings,
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue