feat(cli): replace loading phrases boolean with enum setting (#19347)

This commit is contained in:
Dmitry Lyalin
2026-02-19 13:43:12 -05:00
committed by GitHub
parent 09b623fbd7
commit 372f41eab8
16 changed files with 260 additions and 70 deletions
+79
View File
@@ -2032,6 +2032,85 @@ describe('Settings Loading and Merging', () => {
}),
}),
);
// Check that enableLoadingPhrases: false was further migrated to loadingPhrases: 'off'
expect(setValueSpy).toHaveBeenCalledWith(
SettingScope.User,
'ui',
expect.objectContaining({
loadingPhrases: 'off',
}),
);
});
it('should migrate enableLoadingPhrases: false to loadingPhrases: off', () => {
const userSettingsContent = {
ui: {
accessibility: {
enableLoadingPhrases: false,
},
},
};
const loadedSettings = createMockSettings(userSettingsContent);
const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
migrateDeprecatedSettings(loadedSettings);
expect(setValueSpy).toHaveBeenCalledWith(
SettingScope.User,
'ui',
expect.objectContaining({
loadingPhrases: 'off',
}),
);
});
it('should not migrate enableLoadingPhrases: true to loadingPhrases', () => {
const userSettingsContent = {
ui: {
accessibility: {
enableLoadingPhrases: true,
},
},
};
const loadedSettings = createMockSettings(userSettingsContent);
const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
migrateDeprecatedSettings(loadedSettings);
// Should not set loadingPhrases when enableLoadingPhrases is true
const uiCalls = setValueSpy.mock.calls.filter((call) => call[1] === 'ui');
for (const call of uiCalls) {
const uiValue = call[2] as Record<string, unknown>;
expect(uiValue).not.toHaveProperty('loadingPhrases');
}
});
it('should not overwrite existing loadingPhrases during migration', () => {
const userSettingsContent = {
ui: {
loadingPhrases: 'witty',
accessibility: {
enableLoadingPhrases: false,
},
},
};
const loadedSettings = createMockSettings(userSettingsContent);
const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
migrateDeprecatedSettings(loadedSettings);
// Should not overwrite existing loadingPhrases
const uiCalls = setValueSpy.mock.calls.filter((call) => call[1] === 'ui');
for (const call of uiCalls) {
const uiValue = call[2] as Record<string, unknown>;
if (uiValue['loadingPhrases'] !== undefined) {
expect(uiValue['loadingPhrases']).toBe('witty');
}
}
});
it('should prioritize new settings over deprecated ones and respect removeDeprecated flag', () => {
+19
View File
@@ -165,7 +165,10 @@ export interface SummarizeToolOutputSettings {
tokenBudget?: number;
}
export type LoadingPhrasesMode = 'tips' | 'witty' | 'all' | 'off';
export interface AccessibilitySettings {
/** @deprecated Use ui.loadingPhrases instead. */
enableLoadingPhrases?: boolean;
screenReader?: boolean;
}
@@ -928,6 +931,22 @@ export function migrateDeprecatedSettings(
anyModified = true;
}
}
// Migrate enableLoadingPhrases: false → loadingPhrases: 'off'
const enableLP = newAccessibility['enableLoadingPhrases'];
if (
typeof enableLP === 'boolean' &&
newUi['loadingPhrases'] === undefined
) {
if (!enableLP) {
newUi['loadingPhrases'] = 'off';
loadedSettings.setValue(scope, 'ui', newUi);
if (!settingsFile.readOnly) {
anyModified = true;
}
}
foundDeprecated.push('ui.accessibility.enableLoadingPhrases');
}
}
}
@@ -83,6 +83,19 @@ describe('SettingsSchema', () => {
).toBe('boolean');
});
it('should have loadingPhrases enum property', () => {
const definition = getSettingsSchema().ui?.properties?.loadingPhrases;
expect(definition).toBeDefined();
expect(definition?.type).toBe('enum');
expect(definition?.default).toBe('tips');
expect(definition?.options?.map((o) => o.value)).toEqual([
'tips',
'witty',
'all',
'off',
]);
});
it('should have checkpointing nested properties', () => {
expect(
getSettingsSchema().general?.properties?.checkpointing.properties
+19 -2
View File
@@ -672,6 +672,22 @@ const SETTINGS_SCHEMA = {
description: 'Show the spinner during operations.',
showInDialog: true,
},
loadingPhrases: {
type: 'enum',
label: 'Loading Phrases',
category: 'UI',
requiresRestart: false,
default: 'tips',
description:
'What to show while the model is working: tips, witty comments, both, or nothing.',
showInDialog: true,
options: [
{ value: 'tips', label: 'Tips' },
{ value: 'witty', label: 'Witty' },
{ value: 'all', label: 'All' },
{ value: 'off', label: 'Off' },
],
},
customWittyPhrases: {
type: 'array',
label: 'Custom Witty Phrases',
@@ -700,8 +716,9 @@ const SETTINGS_SCHEMA = {
category: 'UI',
requiresRestart: true,
default: true,
description: 'Enable loading phrases during operations.',
showInDialog: true,
description:
'@deprecated Use ui.loadingPhrases instead. Enable loading phrases during operations.',
showInDialog: false,
},
screenReader: {
type: 'boolean',