mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 12:54:07 -07:00
feat(settings): rename negative settings to positive naming (disable* -> enable*) (#14142)
Co-authored-by: jacob314 <jacob314@gmail.com>
This commit is contained in:
+25
-25
@@ -26,7 +26,7 @@ they appear in the UI.
|
|||||||
| ------------------------------- | ---------------------------------- | ------------------------------------------------------------- | ------- |
|
| ------------------------------- | ---------------------------------- | ------------------------------------------------------------- | ------- |
|
||||||
| Preview Features (e.g., models) | `general.previewFeatures` | Enable preview features (e.g., preview models). | `false` |
|
| Preview Features (e.g., models) | `general.previewFeatures` | Enable preview features (e.g., preview models). | `false` |
|
||||||
| Vim Mode | `general.vimMode` | Enable Vim keybindings | `false` |
|
| Vim Mode | `general.vimMode` | Enable Vim keybindings | `false` |
|
||||||
| Disable Auto Update | `general.disableAutoUpdate` | Disable automatic updates | `false` |
|
| Enable Auto Update | `general.enableAutoUpdate` | Enable automatic updates. | `true` |
|
||||||
| Enable Prompt Completion | `general.enablePromptCompletion` | Enable AI-powered prompt completion suggestions while typing. | `false` |
|
| Enable Prompt Completion | `general.enablePromptCompletion` | Enable AI-powered prompt completion suggestions while typing. | `false` |
|
||||||
| Debug Keystroke Logging | `general.debugKeystrokeLogging` | Enable debug logging of keystrokes to the console. | `false` |
|
| Debug Keystroke Logging | `general.debugKeystrokeLogging` | Enable debug logging of keystrokes to the console. | `false` |
|
||||||
| Enable Session Cleanup | `general.sessionRetention.enabled` | Enable automatic session cleanup | `false` |
|
| Enable Session Cleanup | `general.sessionRetention.enabled` | Enable automatic session cleanup | `false` |
|
||||||
@@ -39,29 +39,29 @@ they appear in the UI.
|
|||||||
|
|
||||||
### UI
|
### UI
|
||||||
|
|
||||||
| UI Label | Setting | Description | Default |
|
| UI Label | Setting | Description | Default |
|
||||||
| ------------------------------ | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
| ------------------------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||||
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
|
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
|
||||||
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
|
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
|
||||||
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
|
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
|
||||||
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
|
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
|
||||||
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
|
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
|
||||||
| Hide Banner | `ui.hideBanner` | Hide the application banner | `false` |
|
| Hide Banner | `ui.hideBanner` | Hide the application banner | `false` |
|
||||||
| Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` |
|
| Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` |
|
||||||
| Hide CWD | `ui.footer.hideCWD` | Hide the current working directory path in the footer. | `false` |
|
| Hide CWD | `ui.footer.hideCWD` | Hide the current working directory path in the footer. | `false` |
|
||||||
| Hide Sandbox Status | `ui.footer.hideSandboxStatus` | Hide the sandbox status indicator in the footer. | `false` |
|
| Hide Sandbox Status | `ui.footer.hideSandboxStatus` | Hide the sandbox status indicator in the footer. | `false` |
|
||||||
| Hide Model Info | `ui.footer.hideModelInfo` | Hide the model name and context usage in the footer. | `false` |
|
| Hide Model Info | `ui.footer.hideModelInfo` | Hide the model name and context usage in the footer. | `false` |
|
||||||
| Hide Context Window Percentage | `ui.footer.hideContextPercentage` | Hides the context window remaining percentage. | `true` |
|
| Hide Context Window Percentage | `ui.footer.hideContextPercentage` | Hides the context window remaining percentage. | `true` |
|
||||||
| Hide Footer | `ui.hideFooter` | Hide the footer from the UI | `false` |
|
| Hide Footer | `ui.hideFooter` | Hide the footer from the UI | `false` |
|
||||||
| Show Memory Usage | `ui.showMemoryUsage` | Display memory usage information in the UI | `false` |
|
| Show Memory Usage | `ui.showMemoryUsage` | Display memory usage information in the UI | `false` |
|
||||||
| Show Line Numbers | `ui.showLineNumbers` | Show line numbers in the chat. | `true` |
|
| Show Line Numbers | `ui.showLineNumbers` | Show line numbers in the chat. | `true` |
|
||||||
| Show Citations | `ui.showCitations` | Show citations for generated text in the chat. | `false` |
|
| Show Citations | `ui.showCitations` | Show citations for generated text in the chat. | `false` |
|
||||||
| Show Model Info In Chat | `ui.showModelInfoInChat` | Show the model name in the chat for each model turn. | `false` |
|
| Show Model Info In Chat | `ui.showModelInfoInChat` | Show the model name in the chat for each model turn. | `false` |
|
||||||
| Use Full Width | `ui.useFullWidth` | Use the entire width of the terminal for output. | `true` |
|
| Use Full Width | `ui.useFullWidth` | Use the entire width of the terminal for output. | `true` |
|
||||||
| Use Alternate Screen Buffer | `ui.useAlternateBuffer` | Use an alternate screen buffer for the UI, preserving shell history. | `false` |
|
| Use Alternate Screen Buffer | `ui.useAlternateBuffer` | Use an alternate screen buffer for the UI, preserving shell history. | `false` |
|
||||||
| Incremental Rendering | `ui.incrementalRendering` | Enable incremental rendering for the UI. This option will reduce flickering but may cause rendering artifacts. Only supported when useAlternateBuffer is enabled. | `true` |
|
| Incremental Rendering | `ui.incrementalRendering` | Enable incremental rendering for the UI. This option will reduce flickering but may cause rendering artifacts. Only supported when useAlternateBuffer is enabled. | `true` |
|
||||||
| Disable Loading Phrases | `ui.accessibility.disableLoadingPhrases` | Disable loading phrases for accessibility | `false` |
|
| Enable Loading Phrases | `ui.accessibility.enableLoadingPhrases` | Enable loading phrases during operations. | `true` |
|
||||||
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
|
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
|
||||||
|
|
||||||
### IDE
|
### IDE
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ they appear in the UI.
|
|||||||
| Respect .gitignore | `context.fileFiltering.respectGitIgnore` | Respect .gitignore files when searching. | `true` |
|
| Respect .gitignore | `context.fileFiltering.respectGitIgnore` | Respect .gitignore files when searching. | `true` |
|
||||||
| Respect .geminiignore | `context.fileFiltering.respectGeminiIgnore` | Respect .geminiignore files when searching. | `true` |
|
| Respect .geminiignore | `context.fileFiltering.respectGeminiIgnore` | Respect .geminiignore files when searching. | `true` |
|
||||||
| Enable Recursive File Search | `context.fileFiltering.enableRecursiveFileSearch` | Enable recursive file search functionality when completing @ references in the prompt. | `true` |
|
| Enable Recursive File Search | `context.fileFiltering.enableRecursiveFileSearch` | Enable recursive file search functionality when completing @ references in the prompt. | `true` |
|
||||||
| Disable Fuzzy Search | `context.fileFiltering.disableFuzzySearch` | Disable fuzzy search when searching for files. | `false` |
|
| Enable Fuzzy Search | `context.fileFiltering.enableFuzzySearch` | Enable fuzzy search when searching for files. | `true` |
|
||||||
|
|
||||||
### Tools
|
### Tools
|
||||||
|
|
||||||
|
|||||||
@@ -110,13 +110,13 @@ their corresponding top-level category object in your `settings.json` file.
|
|||||||
- **Description:** Enable Vim keybindings
|
- **Description:** Enable Vim keybindings
|
||||||
- **Default:** `false`
|
- **Default:** `false`
|
||||||
|
|
||||||
- **`general.disableAutoUpdate`** (boolean):
|
- **`general.enableAutoUpdate`** (boolean):
|
||||||
- **Description:** Disable automatic updates
|
- **Description:** Enable automatic updates.
|
||||||
- **Default:** `false`
|
- **Default:** `true`
|
||||||
|
|
||||||
- **`general.disableUpdateNag`** (boolean):
|
- **`general.enableAutoUpdateNotification`** (boolean):
|
||||||
- **Description:** Disable update notification prompts.
|
- **Description:** Enable update notification prompts.
|
||||||
- **Default:** `false`
|
- **Default:** `true`
|
||||||
|
|
||||||
- **`general.checkpointing.enabled`** (boolean):
|
- **`general.checkpointing.enabled`** (boolean):
|
||||||
- **Description:** Enable session checkpointing for recovery
|
- **Description:** Enable session checkpointing for recovery
|
||||||
@@ -266,9 +266,9 @@ their corresponding top-level category object in your `settings.json` file.
|
|||||||
provided, the CLI cycles through these instead of the defaults.
|
provided, the CLI cycles through these instead of the defaults.
|
||||||
- **Default:** `[]`
|
- **Default:** `[]`
|
||||||
|
|
||||||
- **`ui.accessibility.disableLoadingPhrases`** (boolean):
|
- **`ui.accessibility.enableLoadingPhrases`** (boolean):
|
||||||
- **Description:** Disable loading phrases for accessibility
|
- **Description:** Enable loading phrases during operations.
|
||||||
- **Default:** `false`
|
- **Default:** `true`
|
||||||
- **Requires restart:** Yes
|
- **Requires restart:** Yes
|
||||||
|
|
||||||
- **`ui.accessibility.screenReader`** (boolean):
|
- **`ui.accessibility.screenReader`** (boolean):
|
||||||
@@ -607,9 +607,9 @@ their corresponding top-level category object in your `settings.json` file.
|
|||||||
- **Default:** `true`
|
- **Default:** `true`
|
||||||
- **Requires restart:** Yes
|
- **Requires restart:** Yes
|
||||||
|
|
||||||
- **`context.fileFiltering.disableFuzzySearch`** (boolean):
|
- **`context.fileFiltering.enableFuzzySearch`** (boolean):
|
||||||
- **Description:** Disable fuzzy search when searching for files.
|
- **Description:** Enable fuzzy search when searching for files.
|
||||||
- **Default:** `false`
|
- **Default:** `true`
|
||||||
- **Requires restart:** Yes
|
- **Requires restart:** Yes
|
||||||
|
|
||||||
#### `tools`
|
#### `tools`
|
||||||
|
|||||||
@@ -2193,13 +2193,13 @@ describe('loadCliConfig fileFiltering', () => {
|
|||||||
value: boolean;
|
value: boolean;
|
||||||
}> = [
|
}> = [
|
||||||
{
|
{
|
||||||
property: 'disableFuzzySearch',
|
property: 'enableFuzzySearch',
|
||||||
getter: (c) => c.getFileFilteringDisableFuzzySearch(),
|
getter: (c) => c.getFileFilteringEnableFuzzySearch(),
|
||||||
value: true,
|
value: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
property: 'disableFuzzySearch',
|
property: 'enableFuzzySearch',
|
||||||
getter: (c) => c.getFileFilteringDisableFuzzySearch(),
|
getter: (c) => c.getFileFilteringEnableFuzzySearch(),
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ vi.mock('./settingsSchema.js', async (importOriginal) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// NOW import everything else, including the (now effectively re-exported) settings.js
|
// NOW import everything else, including the (now effectively re-exported) settings.js
|
||||||
import * as pathActual from 'node:path'; // Restored for MOCK_WORKSPACE_SETTINGS_PATH
|
import * as path from 'node:path'; // Restored for MOCK_WORKSPACE_SETTINGS_PATH
|
||||||
import {
|
import {
|
||||||
describe,
|
describe,
|
||||||
it,
|
it,
|
||||||
@@ -69,6 +69,10 @@ import {
|
|||||||
saveSettings,
|
saveSettings,
|
||||||
type SettingsFile,
|
type SettingsFile,
|
||||||
getDefaultsFromSchema,
|
getDefaultsFromSchema,
|
||||||
|
loadEnvironment,
|
||||||
|
migrateDeprecatedSettings,
|
||||||
|
SettingScope,
|
||||||
|
LoadedSettings,
|
||||||
} from './settings.js';
|
} from './settings.js';
|
||||||
import { FatalConfigError, GEMINI_DIR } from '@google/gemini-cli-core';
|
import { FatalConfigError, GEMINI_DIR } from '@google/gemini-cli-core';
|
||||||
import { updateSettingsFilePreservingFormat } from '../utils/commentJson.js';
|
import { updateSettingsFilePreservingFormat } from '../utils/commentJson.js';
|
||||||
@@ -80,7 +84,7 @@ import {
|
|||||||
|
|
||||||
const MOCK_WORKSPACE_DIR = '/mock/workspace';
|
const MOCK_WORKSPACE_DIR = '/mock/workspace';
|
||||||
// Use the (mocked) GEMINI_DIR for consistency
|
// Use the (mocked) GEMINI_DIR for consistency
|
||||||
const MOCK_WORKSPACE_SETTINGS_PATH = pathActual.join(
|
const MOCK_WORKSPACE_SETTINGS_PATH = path.join(
|
||||||
MOCK_WORKSPACE_DIR,
|
MOCK_WORKSPACE_DIR,
|
||||||
GEMINI_DIR,
|
GEMINI_DIR,
|
||||||
'settings.json',
|
'settings.json',
|
||||||
@@ -1602,6 +1606,363 @@ describe('Settings Loading and Merging', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('with workspace trust', () => {
|
||||||
|
it('should merge workspace settings when workspace is trusted', () => {
|
||||||
|
(mockFsExistsSync as Mock).mockReturnValue(true);
|
||||||
|
const userSettingsContent = {
|
||||||
|
ui: { theme: 'dark' },
|
||||||
|
tools: { sandbox: false },
|
||||||
|
};
|
||||||
|
const workspaceSettingsContent = {
|
||||||
|
tools: { sandbox: true },
|
||||||
|
context: { fileName: 'WORKSPACE.md' },
|
||||||
|
};
|
||||||
|
|
||||||
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(userSettingsContent);
|
||||||
|
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(workspaceSettingsContent);
|
||||||
|
return '{}';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
|
expect(settings.merged.tools?.sandbox).toBe(true);
|
||||||
|
expect(settings.merged.context?.fileName).toBe('WORKSPACE.md');
|
||||||
|
expect(settings.merged.ui?.theme).toBe('dark');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT merge workspace settings when workspace is not trusted', () => {
|
||||||
|
vi.mocked(isWorkspaceTrusted).mockReturnValue({
|
||||||
|
isTrusted: false,
|
||||||
|
source: 'file',
|
||||||
|
});
|
||||||
|
(mockFsExistsSync as Mock).mockReturnValue(true);
|
||||||
|
const userSettingsContent = {
|
||||||
|
ui: { theme: 'dark' },
|
||||||
|
tools: { sandbox: false },
|
||||||
|
context: { fileName: 'USER.md' },
|
||||||
|
};
|
||||||
|
const workspaceSettingsContent = {
|
||||||
|
tools: { sandbox: true },
|
||||||
|
context: { fileName: 'WORKSPACE.md' },
|
||||||
|
};
|
||||||
|
|
||||||
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(userSettingsContent);
|
||||||
|
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(workspaceSettingsContent);
|
||||||
|
return '{}';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
|
|
||||||
|
expect(settings.merged.tools?.sandbox).toBe(false); // User setting
|
||||||
|
expect(settings.merged.context?.fileName).toBe('USER.md'); // User setting
|
||||||
|
expect(settings.merged.ui?.theme).toBe('dark'); // User setting
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('loadEnvironment', () => {
|
||||||
|
function setup({
|
||||||
|
isFolderTrustEnabled = true,
|
||||||
|
isWorkspaceTrustedValue = true,
|
||||||
|
}) {
|
||||||
|
delete process.env['TESTTEST']; // reset
|
||||||
|
const geminiEnvPath = path.resolve(path.join(GEMINI_DIR, '.env'));
|
||||||
|
|
||||||
|
vi.mocked(isWorkspaceTrusted).mockReturnValue({
|
||||||
|
isTrusted: isWorkspaceTrustedValue,
|
||||||
|
source: 'file',
|
||||||
|
});
|
||||||
|
(mockFsExistsSync as Mock).mockImplementation((p: fs.PathLike) =>
|
||||||
|
[USER_SETTINGS_PATH, geminiEnvPath].includes(p.toString()),
|
||||||
|
);
|
||||||
|
const userSettingsContent: Settings = {
|
||||||
|
ui: {
|
||||||
|
theme: 'dark',
|
||||||
|
},
|
||||||
|
security: {
|
||||||
|
folderTrust: {
|
||||||
|
enabled: isFolderTrustEnabled,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
fileName: 'USER_CONTEXT.md',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(userSettingsContent);
|
||||||
|
if (p === geminiEnvPath) return 'TESTTEST=1234';
|
||||||
|
return '{}';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('sets environment variables from .env files', () => {
|
||||||
|
setup({ isFolderTrustEnabled: false, isWorkspaceTrustedValue: true });
|
||||||
|
loadEnvironment(loadSettings(MOCK_WORKSPACE_DIR).merged);
|
||||||
|
|
||||||
|
expect(process.env['TESTTEST']).toEqual('1234');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not load env files from untrusted spaces', () => {
|
||||||
|
setup({ isFolderTrustEnabled: true, isWorkspaceTrustedValue: false });
|
||||||
|
loadEnvironment(loadSettings(MOCK_WORKSPACE_DIR).merged);
|
||||||
|
|
||||||
|
expect(process.env['TESTTEST']).not.toEqual('1234');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('migrateDeprecatedSettings', () => {
|
||||||
|
let mockFsExistsSync: Mock;
|
||||||
|
let mockFsReadFileSync: Mock;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.resetAllMocks();
|
||||||
|
mockFsExistsSync = vi.mocked(fs.existsSync);
|
||||||
|
mockFsExistsSync.mockReturnValue(true);
|
||||||
|
mockFsReadFileSync = vi.mocked(fs.readFileSync);
|
||||||
|
mockFsReadFileSync.mockReturnValue('{}');
|
||||||
|
vi.mocked(isWorkspaceTrusted).mockReturnValue({
|
||||||
|
isTrusted: true,
|
||||||
|
source: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not do anything if there are no deprecated settings', () => {
|
||||||
|
const userSettingsContent = {
|
||||||
|
extensions: {
|
||||||
|
enabled: ['user-ext-1'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const workspaceSettingsContent = {
|
||||||
|
someOtherSetting: 'value',
|
||||||
|
};
|
||||||
|
|
||||||
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(userSettingsContent);
|
||||||
|
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(workspaceSettingsContent);
|
||||||
|
return '{}';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const setValueSpy = vi.spyOn(LoadedSettings.prototype, 'setValue');
|
||||||
|
const loadedSettings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
|
setValueSpy.mockClear();
|
||||||
|
|
||||||
|
migrateDeprecatedSettings(loadedSettings, true);
|
||||||
|
|
||||||
|
expect(setValueSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should migrate general.disableAutoUpdate to general.enableAutoUpdate with inverted value', () => {
|
||||||
|
const userSettingsContent = {
|
||||||
|
general: {
|
||||||
|
disableAutoUpdate: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(userSettingsContent);
|
||||||
|
return '{}';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const setValueSpy = vi.spyOn(LoadedSettings.prototype, 'setValue');
|
||||||
|
const loadedSettings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
|
|
||||||
|
migrateDeprecatedSettings(loadedSettings, true);
|
||||||
|
|
||||||
|
// Should set new value to false (inverted from true)
|
||||||
|
expect(setValueSpy).toHaveBeenCalledWith(
|
||||||
|
SettingScope.User,
|
||||||
|
'general',
|
||||||
|
expect.objectContaining({ enableAutoUpdate: false }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should migrate all 4 inverted boolean settings', () => {
|
||||||
|
const userSettingsContent = {
|
||||||
|
general: {
|
||||||
|
disableAutoUpdate: false,
|
||||||
|
disableUpdateNag: true,
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
fileFiltering: {
|
||||||
|
disableFuzzySearch: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ui: {
|
||||||
|
accessibility: {
|
||||||
|
disableLoadingPhrases: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(userSettingsContent);
|
||||||
|
return '{}';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const setValueSpy = vi.spyOn(LoadedSettings.prototype, 'setValue');
|
||||||
|
const loadedSettings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
|
|
||||||
|
migrateDeprecatedSettings(loadedSettings, true);
|
||||||
|
|
||||||
|
// Check that general settings were migrated with inverted values
|
||||||
|
expect(setValueSpy).toHaveBeenCalledWith(
|
||||||
|
SettingScope.User,
|
||||||
|
'general',
|
||||||
|
expect.objectContaining({ enableAutoUpdate: true }),
|
||||||
|
);
|
||||||
|
expect(setValueSpy).toHaveBeenCalledWith(
|
||||||
|
SettingScope.User,
|
||||||
|
'general',
|
||||||
|
expect.objectContaining({ enableAutoUpdateNotification: false }),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check context.fileFiltering was migrated
|
||||||
|
expect(setValueSpy).toHaveBeenCalledWith(
|
||||||
|
SettingScope.User,
|
||||||
|
'context',
|
||||||
|
expect.objectContaining({
|
||||||
|
fileFiltering: expect.objectContaining({ enableFuzzySearch: true }),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check ui.accessibility was migrated
|
||||||
|
expect(setValueSpy).toHaveBeenCalledWith(
|
||||||
|
SettingScope.User,
|
||||||
|
'ui',
|
||||||
|
expect.objectContaining({
|
||||||
|
accessibility: expect.objectContaining({
|
||||||
|
enableLoadingPhrases: false,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prioritize new settings over deprecated ones and respect removeDeprecated flag', () => {
|
||||||
|
const userSettingsContent = {
|
||||||
|
general: {
|
||||||
|
disableAutoUpdate: true,
|
||||||
|
enableAutoUpdate: true, // Trust this (true) over disableAutoUpdate (true -> false)
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
fileFiltering: {
|
||||||
|
disableFuzzySearch: false,
|
||||||
|
enableFuzzySearch: false, // Trust this (false) over disableFuzzySearch (false -> true)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadedSettings = new LoadedSettings(
|
||||||
|
{
|
||||||
|
path: getSystemSettingsPath(),
|
||||||
|
settings: {},
|
||||||
|
originalSettings: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: getSystemDefaultsPath(),
|
||||||
|
settings: {},
|
||||||
|
originalSettings: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: USER_SETTINGS_PATH,
|
||||||
|
settings: userSettingsContent as unknown as Settings,
|
||||||
|
originalSettings: userSettingsContent as unknown as Settings,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: MOCK_WORKSPACE_SETTINGS_PATH,
|
||||||
|
settings: {},
|
||||||
|
originalSettings: {},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
|
||||||
|
|
||||||
|
// 1. removeDeprecated = false (default)
|
||||||
|
migrateDeprecatedSettings(loadedSettings);
|
||||||
|
|
||||||
|
// Should still have old settings
|
||||||
|
expect(
|
||||||
|
loadedSettings.forScope(SettingScope.User).settings.general,
|
||||||
|
).toHaveProperty('disableAutoUpdate');
|
||||||
|
expect(
|
||||||
|
(
|
||||||
|
loadedSettings.forScope(SettingScope.User).settings.context as {
|
||||||
|
fileFiltering: { disableFuzzySearch: boolean };
|
||||||
|
}
|
||||||
|
).fileFiltering,
|
||||||
|
).toHaveProperty('disableFuzzySearch');
|
||||||
|
|
||||||
|
// 2. removeDeprecated = true
|
||||||
|
migrateDeprecatedSettings(loadedSettings, true);
|
||||||
|
|
||||||
|
// Should remove disableAutoUpdate and trust enableAutoUpdate: true
|
||||||
|
expect(setValueSpy).toHaveBeenCalledWith(SettingScope.User, 'general', {
|
||||||
|
enableAutoUpdate: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Should remove disableFuzzySearch and trust enableFuzzySearch: false
|
||||||
|
expect(setValueSpy).toHaveBeenCalledWith(SettingScope.User, 'context', {
|
||||||
|
fileFiltering: { enableFuzzySearch: false },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should trigger migration automatically during loadSettings', () => {
|
||||||
|
mockFsExistsSync.mockImplementation(
|
||||||
|
(p: fs.PathLike) => p === USER_SETTINGS_PATH,
|
||||||
|
);
|
||||||
|
const userSettingsContent = {
|
||||||
|
general: {
|
||||||
|
disableAutoUpdate: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
return JSON.stringify(userSettingsContent);
|
||||||
|
return '{}';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
|
|
||||||
|
// Verify it was migrated in the merged settings
|
||||||
|
expect(settings.merged.general?.enableAutoUpdate).toBe(false);
|
||||||
|
|
||||||
|
// Verify it was saved back to disk (via setValue calling updateSettingsFilePreservingFormat)
|
||||||
|
expect(updateSettingsFilePreservingFormat).toHaveBeenCalledWith(
|
||||||
|
USER_SETTINGS_PATH,
|
||||||
|
expect.objectContaining({
|
||||||
|
general: expect.objectContaining({ enableAutoUpdate: false }),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('saveSettings', () => {
|
describe('saveSettings', () => {
|
||||||
it('should save settings using updateSettingsFilePreservingFormat', () => {
|
it('should save settings using updateSettingsFilePreservingFormat', () => {
|
||||||
const mockUpdateSettings = vi.mocked(updateSettingsFilePreservingFormat);
|
const mockUpdateSettings = vi.mocked(updateSettingsFilePreservingFormat);
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export interface SummarizeToolOutputSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AccessibilitySettings {
|
export interface AccessibilitySettings {
|
||||||
disableLoadingPhrases?: boolean;
|
enableLoadingPhrases?: boolean;
|
||||||
screenReader?: boolean;
|
screenReader?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +613,7 @@ export function loadSettings(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LoadedSettings(
|
const loadedSettings = new LoadedSettings(
|
||||||
{
|
{
|
||||||
path: systemSettingsPath,
|
path: systemSettingsPath,
|
||||||
settings: systemSettings,
|
settings: systemSettings,
|
||||||
@@ -641,6 +641,171 @@ export function loadSettings(
|
|||||||
isTrusted,
|
isTrusted,
|
||||||
settingsErrors,
|
settingsErrors,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Automatically migrate deprecated settings when loading.
|
||||||
|
migrateDeprecatedSettings(loadedSettings);
|
||||||
|
|
||||||
|
return loadedSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrates deprecated settings to their new counterparts.
|
||||||
|
*
|
||||||
|
* TODO: After a couple of weeks (around early Feb 2026), we should start removing
|
||||||
|
* the deprecated settings from the settings files by default.
|
||||||
|
*
|
||||||
|
* @returns true if any changes were made and need to be saved.
|
||||||
|
*/
|
||||||
|
export function migrateDeprecatedSettings(
|
||||||
|
loadedSettings: LoadedSettings,
|
||||||
|
removeDeprecated = false,
|
||||||
|
): boolean {
|
||||||
|
let anyModified = false;
|
||||||
|
const processScope = (scope: LoadableSettingScope) => {
|
||||||
|
const settings = loadedSettings.forScope(scope).settings;
|
||||||
|
|
||||||
|
// Migrate inverted boolean settings (disableX -> enableX)
|
||||||
|
// These settings were renamed and their boolean logic inverted
|
||||||
|
const generalSettings = settings.general as
|
||||||
|
| Record<string, unknown>
|
||||||
|
| undefined;
|
||||||
|
const uiSettings = settings.ui as Record<string, unknown> | undefined;
|
||||||
|
const contextSettings = settings.context as
|
||||||
|
| Record<string, unknown>
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
// Migrate general settings (disableAutoUpdate, disableUpdateNag)
|
||||||
|
if (generalSettings) {
|
||||||
|
const newGeneral: Record<string, unknown> = { ...generalSettings };
|
||||||
|
let modified = false;
|
||||||
|
|
||||||
|
if (typeof newGeneral['disableAutoUpdate'] === 'boolean') {
|
||||||
|
if (typeof newGeneral['enableAutoUpdate'] === 'boolean') {
|
||||||
|
// Both exist, trust the new one
|
||||||
|
if (removeDeprecated) {
|
||||||
|
delete newGeneral['disableAutoUpdate'];
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const oldValue = newGeneral['disableAutoUpdate'];
|
||||||
|
newGeneral['enableAutoUpdate'] = !oldValue;
|
||||||
|
if (removeDeprecated) {
|
||||||
|
delete newGeneral['disableAutoUpdate'];
|
||||||
|
}
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof newGeneral['disableUpdateNag'] === 'boolean') {
|
||||||
|
if (typeof newGeneral['enableAutoUpdateNotification'] === 'boolean') {
|
||||||
|
// Both exist, trust the new one
|
||||||
|
if (removeDeprecated) {
|
||||||
|
delete newGeneral['disableUpdateNag'];
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const oldValue = newGeneral['disableUpdateNag'];
|
||||||
|
newGeneral['enableAutoUpdateNotification'] = !oldValue;
|
||||||
|
if (removeDeprecated) {
|
||||||
|
delete newGeneral['disableUpdateNag'];
|
||||||
|
}
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modified) {
|
||||||
|
loadedSettings.setValue(scope, 'general', newGeneral);
|
||||||
|
anyModified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrate ui settings
|
||||||
|
if (uiSettings) {
|
||||||
|
const newUi: Record<string, unknown> = { ...uiSettings };
|
||||||
|
let modified = false;
|
||||||
|
|
||||||
|
// Migrate ui.accessibility.disableLoadingPhrases -> ui.accessibility.enableLoadingPhrases
|
||||||
|
const accessibilitySettings = newUi['accessibility'] as
|
||||||
|
| Record<string, unknown>
|
||||||
|
| undefined;
|
||||||
|
if (
|
||||||
|
accessibilitySettings &&
|
||||||
|
typeof accessibilitySettings['disableLoadingPhrases'] === 'boolean'
|
||||||
|
) {
|
||||||
|
const newAccessibility: Record<string, unknown> = {
|
||||||
|
...accessibilitySettings,
|
||||||
|
};
|
||||||
|
if (
|
||||||
|
typeof accessibilitySettings['enableLoadingPhrases'] === 'boolean'
|
||||||
|
) {
|
||||||
|
// Both exist, trust the new one
|
||||||
|
if (removeDeprecated) {
|
||||||
|
delete newAccessibility['disableLoadingPhrases'];
|
||||||
|
newUi['accessibility'] = newAccessibility;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const oldValue = accessibilitySettings['disableLoadingPhrases'];
|
||||||
|
newAccessibility['enableLoadingPhrases'] = !oldValue;
|
||||||
|
if (removeDeprecated) {
|
||||||
|
delete newAccessibility['disableLoadingPhrases'];
|
||||||
|
}
|
||||||
|
newUi['accessibility'] = newAccessibility;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modified) {
|
||||||
|
loadedSettings.setValue(scope, 'ui', newUi);
|
||||||
|
anyModified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrate context settings
|
||||||
|
if (contextSettings) {
|
||||||
|
const newContext: Record<string, unknown> = { ...contextSettings };
|
||||||
|
let modified = false;
|
||||||
|
|
||||||
|
// Migrate context.fileFiltering.disableFuzzySearch -> context.fileFiltering.enableFuzzySearch
|
||||||
|
const fileFilteringSettings = newContext['fileFiltering'] as
|
||||||
|
| Record<string, unknown>
|
||||||
|
| undefined;
|
||||||
|
if (
|
||||||
|
fileFilteringSettings &&
|
||||||
|
typeof fileFilteringSettings['disableFuzzySearch'] === 'boolean'
|
||||||
|
) {
|
||||||
|
const newFileFiltering: Record<string, unknown> = {
|
||||||
|
...fileFilteringSettings,
|
||||||
|
};
|
||||||
|
if (typeof fileFilteringSettings['enableFuzzySearch'] === 'boolean') {
|
||||||
|
// Both exist, trust the new one
|
||||||
|
if (removeDeprecated) {
|
||||||
|
delete newFileFiltering['disableFuzzySearch'];
|
||||||
|
newContext['fileFiltering'] = newFileFiltering;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const oldValue = fileFilteringSettings['disableFuzzySearch'];
|
||||||
|
newFileFiltering['enableFuzzySearch'] = !oldValue;
|
||||||
|
if (removeDeprecated) {
|
||||||
|
delete newFileFiltering['disableFuzzySearch'];
|
||||||
|
}
|
||||||
|
newContext['fileFiltering'] = newFileFiltering;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modified) {
|
||||||
|
loadedSettings.setValue(scope, 'context', newContext);
|
||||||
|
anyModified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
processScope(SettingScope.User);
|
||||||
|
processScope(SettingScope.Workspace);
|
||||||
|
|
||||||
|
return anyModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function saveSettings(settingsFile: SettingsFile): void {
|
export function saveSettings(settingsFile: SettingsFile): void {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ describe('SettingsSchema', () => {
|
|||||||
).toBeDefined();
|
).toBeDefined();
|
||||||
expect(
|
expect(
|
||||||
getSettingsSchema().ui?.properties?.accessibility.properties
|
getSettingsSchema().ui?.properties?.accessibility.properties
|
||||||
?.disableLoadingPhrases.type,
|
?.enableLoadingPhrases.type,
|
||||||
).toBe('boolean');
|
).toBe('boolean');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ describe('SettingsSchema', () => {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
getSettingsSchema().general.properties.disableAutoUpdate.showInDialog,
|
getSettingsSchema().general.properties.enableAutoUpdate.showInDialog,
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
expect(
|
expect(
|
||||||
getSettingsSchema().ui.properties.hideWindowTitle.showInDialog,
|
getSettingsSchema().ui.properties.hideWindowTitle.showInDialog,
|
||||||
|
|||||||
@@ -191,22 +191,22 @@ const SETTINGS_SCHEMA = {
|
|||||||
description: 'Enable Vim keybindings',
|
description: 'Enable Vim keybindings',
|
||||||
showInDialog: true,
|
showInDialog: true,
|
||||||
},
|
},
|
||||||
disableAutoUpdate: {
|
enableAutoUpdate: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
label: 'Disable Auto Update',
|
label: 'Enable Auto Update',
|
||||||
category: 'General',
|
category: 'General',
|
||||||
requiresRestart: false,
|
requiresRestart: false,
|
||||||
default: false,
|
default: true,
|
||||||
description: 'Disable automatic updates',
|
description: 'Enable automatic updates.',
|
||||||
showInDialog: true,
|
showInDialog: true,
|
||||||
},
|
},
|
||||||
disableUpdateNag: {
|
enableAutoUpdateNotification: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
label: 'Disable Update Nag',
|
label: 'Enable Auto Update Notification',
|
||||||
category: 'General',
|
category: 'General',
|
||||||
requiresRestart: false,
|
requiresRestart: false,
|
||||||
default: false,
|
default: true,
|
||||||
description: 'Disable update notification prompts.',
|
description: 'Enable update notification prompts.',
|
||||||
showInDialog: false,
|
showInDialog: false,
|
||||||
},
|
},
|
||||||
checkpointing: {
|
checkpointing: {
|
||||||
@@ -577,13 +577,13 @@ const SETTINGS_SCHEMA = {
|
|||||||
description: 'Accessibility settings.',
|
description: 'Accessibility settings.',
|
||||||
showInDialog: false,
|
showInDialog: false,
|
||||||
properties: {
|
properties: {
|
||||||
disableLoadingPhrases: {
|
enableLoadingPhrases: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
label: 'Disable Loading Phrases',
|
label: 'Enable Loading Phrases',
|
||||||
category: 'UI',
|
category: 'UI',
|
||||||
requiresRestart: true,
|
requiresRestart: true,
|
||||||
default: false,
|
default: true,
|
||||||
description: 'Disable loading phrases for accessibility',
|
description: 'Enable loading phrases during operations.',
|
||||||
showInDialog: true,
|
showInDialog: true,
|
||||||
},
|
},
|
||||||
screenReader: {
|
screenReader: {
|
||||||
@@ -914,13 +914,13 @@ const SETTINGS_SCHEMA = {
|
|||||||
`,
|
`,
|
||||||
showInDialog: true,
|
showInDialog: true,
|
||||||
},
|
},
|
||||||
disableFuzzySearch: {
|
enableFuzzySearch: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
label: 'Disable Fuzzy Search',
|
label: 'Enable Fuzzy Search',
|
||||||
category: 'Context',
|
category: 'Context',
|
||||||
requiresRestart: true,
|
requiresRestart: true,
|
||||||
default: false,
|
default: true,
|
||||||
description: 'Disable fuzzy search when searching for files.',
|
description: 'Enable fuzzy search when searching for files.',
|
||||||
showInDialog: true,
|
showInDialog: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ describe('Composer', () => {
|
|||||||
thought: { subject: 'Hidden', description: 'Should not show' },
|
thought: { subject: 'Hidden', description: 'Should not show' },
|
||||||
});
|
});
|
||||||
const config = createMockConfig({
|
const config = createMockConfig({
|
||||||
getAccessibility: vi.fn(() => ({ disableLoadingPhrases: true })),
|
getAccessibility: vi.fn(() => ({ enableLoadingPhrases: false })),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { lastFrame } = renderComposer(uiState, undefined, config);
|
const { lastFrame } = renderComposer(uiState, undefined, config);
|
||||||
|
|||||||
@@ -58,12 +58,12 @@ export const Composer = () => {
|
|||||||
<LoadingIndicator
|
<LoadingIndicator
|
||||||
thought={
|
thought={
|
||||||
uiState.streamingState === StreamingState.WaitingForConfirmation ||
|
uiState.streamingState === StreamingState.WaitingForConfirmation ||
|
||||||
config.getAccessibility()?.disableLoadingPhrases
|
config.getAccessibility()?.enableLoadingPhrases === false
|
||||||
? undefined
|
? undefined
|
||||||
: uiState.thought
|
: uiState.thought
|
||||||
}
|
}
|
||||||
currentLoadingPhrase={
|
currentLoadingPhrase={
|
||||||
config.getAccessibility()?.disableLoadingPhrases
|
config.getAccessibility()?.enableLoadingPhrases === false
|
||||||
? undefined
|
? undefined
|
||||||
: uiState.currentLoadingPhrase
|
: uiState.currentLoadingPhrase
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -320,9 +320,9 @@ describe('SettingsDialog', () => {
|
|||||||
// 'general.vimMode' has description 'Enable Vim keybindings' in settingsSchema.ts
|
// 'general.vimMode' has description 'Enable Vim keybindings' in settingsSchema.ts
|
||||||
expect(output).toContain('Vim Mode');
|
expect(output).toContain('Vim Mode');
|
||||||
expect(output).toContain('Enable Vim keybindings');
|
expect(output).toContain('Enable Vim keybindings');
|
||||||
// 'general.disableAutoUpdate' has description 'Disable automatic updates'
|
// 'general.enableAutoUpdate' has description 'Enable automatic updates.'
|
||||||
expect(output).toContain('Disable Auto Update');
|
expect(output).toContain('Enable Auto Update');
|
||||||
expect(output).toContain('Disable automatic updates');
|
expect(output).toContain('Enable automatic updates.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ describe('SettingsDialog', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(lastFrame()).toContain('Disable Auto Update');
|
expect(lastFrame()).toContain('Enable Auto Update');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Navigate up
|
// Navigate up
|
||||||
@@ -1236,7 +1236,7 @@ describe('SettingsDialog', () => {
|
|||||||
expect(lastFrame()).toContain('nonexistentsetting');
|
expect(lastFrame()).toContain('nonexistentsetting');
|
||||||
expect(lastFrame()).toContain('');
|
expect(lastFrame()).toContain('');
|
||||||
expect(lastFrame()).not.toContain('Vim Mode'); // Should not contain any settings
|
expect(lastFrame()).not.toContain('Vim Mode'); // Should not contain any settings
|
||||||
expect(lastFrame()).not.toContain('Disable Auto Update'); // Should not contain any settings
|
expect(lastFrame()).not.toContain('Enable Auto Update'); // Should not contain any settings
|
||||||
});
|
});
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
@@ -1263,7 +1263,7 @@ describe('SettingsDialog', () => {
|
|||||||
userSettings: {
|
userSettings: {
|
||||||
general: {
|
general: {
|
||||||
vimMode: true,
|
vimMode: true,
|
||||||
disableAutoUpdate: true,
|
enableAutoUpdate: false,
|
||||||
debugKeystrokeLogging: true,
|
debugKeystrokeLogging: true,
|
||||||
enablePromptCompletion: true,
|
enablePromptCompletion: true,
|
||||||
},
|
},
|
||||||
@@ -1274,7 +1274,7 @@ describe('SettingsDialog', () => {
|
|||||||
showLineNumbers: true,
|
showLineNumbers: true,
|
||||||
showCitations: true,
|
showCitations: true,
|
||||||
accessibility: {
|
accessibility: {
|
||||||
disableLoadingPhrases: true,
|
enableLoadingPhrases: false,
|
||||||
screenReader: true,
|
screenReader: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1287,7 +1287,7 @@ describe('SettingsDialog', () => {
|
|||||||
respectGitIgnore: true,
|
respectGitIgnore: true,
|
||||||
respectGeminiIgnore: true,
|
respectGeminiIgnore: true,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
@@ -1310,7 +1310,7 @@ describe('SettingsDialog', () => {
|
|||||||
userSettings: {
|
userSettings: {
|
||||||
general: {
|
general: {
|
||||||
vimMode: false,
|
vimMode: false,
|
||||||
disableAutoUpdate: true,
|
enableAutoUpdate: false,
|
||||||
},
|
},
|
||||||
ui: {
|
ui: {
|
||||||
showMemoryUsage: true,
|
showMemoryUsage: true,
|
||||||
@@ -1348,7 +1348,7 @@ describe('SettingsDialog', () => {
|
|||||||
userSettings: {
|
userSettings: {
|
||||||
ui: {
|
ui: {
|
||||||
accessibility: {
|
accessibility: {
|
||||||
disableLoadingPhrases: true,
|
enableLoadingPhrases: false,
|
||||||
screenReader: true,
|
screenReader: true,
|
||||||
},
|
},
|
||||||
showMemoryUsage: true,
|
showMemoryUsage: true,
|
||||||
@@ -1370,7 +1370,7 @@ describe('SettingsDialog', () => {
|
|||||||
respectGitIgnore: false,
|
respectGitIgnore: false,
|
||||||
respectGeminiIgnore: true,
|
respectGeminiIgnore: true,
|
||||||
enableRecursiveFileSearch: false,
|
enableRecursiveFileSearch: false,
|
||||||
disableFuzzySearch: true,
|
enableFuzzySearch: false,
|
||||||
},
|
},
|
||||||
loadMemoryFromIncludeDirectories: true,
|
loadMemoryFromIncludeDirectories: true,
|
||||||
discoveryMaxDirs: 100,
|
discoveryMaxDirs: 100,
|
||||||
@@ -1409,7 +1409,7 @@ describe('SettingsDialog', () => {
|
|||||||
userSettings: {
|
userSettings: {
|
||||||
general: {
|
general: {
|
||||||
vimMode: false,
|
vimMode: false,
|
||||||
disableAutoUpdate: false,
|
enableAutoUpdate: true,
|
||||||
debugKeystrokeLogging: false,
|
debugKeystrokeLogging: false,
|
||||||
enablePromptCompletion: false,
|
enablePromptCompletion: false,
|
||||||
},
|
},
|
||||||
@@ -1420,7 +1420,7 @@ describe('SettingsDialog', () => {
|
|||||||
showLineNumbers: false,
|
showLineNumbers: false,
|
||||||
showCitations: false,
|
showCitations: false,
|
||||||
accessibility: {
|
accessibility: {
|
||||||
disableLoadingPhrases: false,
|
enableLoadingPhrases: true,
|
||||||
screenReader: false,
|
screenReader: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1433,7 +1433,7 @@ describe('SettingsDialog', () => {
|
|||||||
respectGitIgnore: false,
|
respectGitIgnore: false,
|
||||||
respectGeminiIgnore: false,
|
respectGeminiIgnore: false,
|
||||||
enableRecursiveFileSearch: false,
|
enableRecursiveFileSearch: false,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ exports[`SettingsDialog > Initial Rendering > should render settings list with v
|
|||||||
│ Vim Mode false │
|
│ Vim Mode false │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update false │
|
│ Enable Auto Update true │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion false │
|
│ Enable Prompt Completion false │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
@@ -62,8 +62,8 @@ exports[`SettingsDialog > Snapshot Tests > should render 'accessibility settings
|
|||||||
│ Vim Mode true* │
|
│ Vim Mode true* │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update false │
|
│ Enable Auto Update true │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion false │
|
│ Enable Prompt Completion false │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
@@ -108,8 +108,8 @@ exports[`SettingsDialog > Snapshot Tests > should render 'all boolean settings d
|
|||||||
│ Vim Mode false* │
|
│ Vim Mode false* │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update false* │
|
│ Enable Auto Update true* │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion false* │
|
│ Enable Prompt Completion false* │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
@@ -154,8 +154,8 @@ exports[`SettingsDialog > Snapshot Tests > should render 'default state' correct
|
|||||||
│ Vim Mode false │
|
│ Vim Mode false │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update false │
|
│ Enable Auto Update true │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion false │
|
│ Enable Prompt Completion false │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
@@ -200,8 +200,8 @@ exports[`SettingsDialog > Snapshot Tests > should render 'file filtering setting
|
|||||||
│ Vim Mode false │
|
│ Vim Mode false │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update false │
|
│ Enable Auto Update true │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion false │
|
│ Enable Prompt Completion false │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
@@ -246,8 +246,8 @@ exports[`SettingsDialog > Snapshot Tests > should render 'focused on scope selec
|
|||||||
│ Vim Mode false │
|
│ Vim Mode false │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update false │
|
│ Enable Auto Update true │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion false │
|
│ Enable Prompt Completion false │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
@@ -292,8 +292,8 @@ exports[`SettingsDialog > Snapshot Tests > should render 'mixed boolean and numb
|
|||||||
│ Vim Mode false* │
|
│ Vim Mode false* │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update true* │
|
│ Enable Auto Update false* │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion false │
|
│ Enable Prompt Completion false │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
@@ -338,8 +338,8 @@ exports[`SettingsDialog > Snapshot Tests > should render 'tools and security set
|
|||||||
│ Vim Mode false │
|
│ Vim Mode false │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update false │
|
│ Enable Auto Update true │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion false │
|
│ Enable Prompt Completion false │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
@@ -384,8 +384,8 @@ exports[`SettingsDialog > Snapshot Tests > should render 'various boolean settin
|
|||||||
│ Vim Mode true* │
|
│ Vim Mode true* │
|
||||||
│ Enable Vim keybindings │
|
│ Enable Vim keybindings │
|
||||||
│ │
|
│ │
|
||||||
│ Disable Auto Update true* │
|
│ Enable Auto Update false* │
|
||||||
│ Disable automatic updates │
|
│ Enable automatic updates. │
|
||||||
│ │
|
│ │
|
||||||
│ Enable Prompt Completion true* │
|
│ Enable Prompt Completion true* │
|
||||||
│ Enable AI-powered prompt completion suggestions while typing. │
|
│ Enable AI-powered prompt completion suggestions while typing. │
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ describe('useAtCompletion', () => {
|
|||||||
respectGeminiIgnore: true,
|
respectGeminiIgnore: true,
|
||||||
})),
|
})),
|
||||||
getEnableRecursiveFileSearch: () => true,
|
getEnableRecursiveFileSearch: () => true,
|
||||||
getFileFilteringDisableFuzzySearch: () => false,
|
getFileFilteringEnableFuzzySearch: () => true,
|
||||||
getResourceRegistry: vi.fn().mockReturnValue({
|
getResourceRegistry: vi.fn().mockReturnValue({
|
||||||
getAllResources: () => [],
|
getAllResources: () => [],
|
||||||
}),
|
}),
|
||||||
@@ -153,7 +153,7 @@ describe('useAtCompletion', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
|
|
||||||
@@ -276,7 +276,7 @@ describe('useAtCompletion', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
await realFileSearch.initialize();
|
await realFileSearch.initialize();
|
||||||
|
|
||||||
@@ -558,7 +558,7 @@ describe('useAtCompletion', () => {
|
|||||||
respectGitIgnore: true,
|
respectGitIgnore: true,
|
||||||
respectGeminiIgnore: true,
|
respectGeminiIgnore: true,
|
||||||
})),
|
})),
|
||||||
getFileFilteringDisableFuzzySearch: () => false,
|
getFileFilteringEnableFuzzySearch: () => true,
|
||||||
} as unknown as Config;
|
} as unknown as Config;
|
||||||
|
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
|
|||||||
@@ -258,8 +258,8 @@ export function useAtCompletion(props: UseAtCompletionProps): void {
|
|||||||
cacheTtl: 30, // 30 seconds
|
cacheTtl: 30, // 30 seconds
|
||||||
enableRecursiveFileSearch:
|
enableRecursiveFileSearch:
|
||||||
config?.getEnableRecursiveFileSearch() ?? true,
|
config?.getEnableRecursiveFileSearch() ?? true,
|
||||||
disableFuzzySearch:
|
enableFuzzySearch:
|
||||||
config?.getFileFilteringDisableFuzzySearch() ?? false,
|
config?.getFileFilteringEnableFuzzySearch() ?? true,
|
||||||
maxFiles: config?.getFileFilteringOptions()?.maxFileCount,
|
maxFiles: config?.getFileFilteringOptions()?.maxFileCount,
|
||||||
});
|
});
|
||||||
await searcher.initialize();
|
await searcher.initialize();
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ describe('useAtCompletion with Agents', () => {
|
|||||||
})),
|
})),
|
||||||
getEnableRecursiveFileSearch: () => true,
|
getEnableRecursiveFileSearch: () => true,
|
||||||
getFileFilteringDisableFuzzySearch: () => false,
|
getFileFilteringDisableFuzzySearch: () => false,
|
||||||
|
getFileFilteringEnableFuzzySearch: () => true,
|
||||||
|
getAgentsSettings: () => ({}),
|
||||||
getResourceRegistry: vi.fn().mockReturnValue({
|
getResourceRegistry: vi.fn().mockReturnValue({
|
||||||
getAllResources: () => [],
|
getAllResources: () => [],
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ describe('checkForUpdates', () => {
|
|||||||
mockSettings = {
|
mockSettings = {
|
||||||
merged: {
|
merged: {
|
||||||
general: {
|
general: {
|
||||||
disableUpdateNag: false,
|
enableAutoUpdateNotification: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as LoadedSettings;
|
} as LoadedSettings;
|
||||||
@@ -45,8 +45,8 @@ describe('checkForUpdates', () => {
|
|||||||
vi.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return null if disableUpdateNag is true', async () => {
|
it('should return null if enableAutoUpdateNotification is false', async () => {
|
||||||
mockSettings.merged.general.disableUpdateNag = true;
|
mockSettings.merged.general.enableAutoUpdateNotification = false;
|
||||||
const result = await checkForUpdates(mockSettings);
|
const result = await checkForUpdates(mockSettings);
|
||||||
expect(result).toBeNull();
|
expect(result).toBeNull();
|
||||||
expect(getPackageJson).not.toHaveBeenCalled();
|
expect(getPackageJson).not.toHaveBeenCalled();
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export async function checkForUpdates(
|
|||||||
settings: LoadedSettings,
|
settings: LoadedSettings,
|
||||||
): Promise<UpdateObject | null> {
|
): Promise<UpdateObject | null> {
|
||||||
try {
|
try {
|
||||||
if (settings.merged.general.disableUpdateNag) {
|
if (!settings.merged.general.enableAutoUpdateNotification) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Skip update check when running from source (development mode)
|
// Skip update check when running from source (development mode)
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import EventEmitter from 'node:events';
|
|||||||
import type { ChildProcess } from 'node:child_process';
|
import type { ChildProcess } from 'node:child_process';
|
||||||
import { handleAutoUpdate, setUpdateHandler } from './handleAutoUpdate.js';
|
import { handleAutoUpdate, setUpdateHandler } from './handleAutoUpdate.js';
|
||||||
import { MessageType } from '../ui/types.js';
|
import { MessageType } from '../ui/types.js';
|
||||||
import { mergeSettings } from '../config/settings.js';
|
|
||||||
|
|
||||||
vi.mock('./installationInfo.js', async () => {
|
vi.mock('./installationInfo.js', async () => {
|
||||||
const actual = await vi.importActual('./installationInfo.js');
|
const actual = await vi.importActual('./installationInfo.js');
|
||||||
@@ -50,9 +49,16 @@ describe('handleAutoUpdate', () => {
|
|||||||
message: 'An update is available!',
|
message: 'An update is available!',
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultMergedSettings = mergeSettings({}, {}, {}, {}, true);
|
|
||||||
mockSettings = {
|
mockSettings = {
|
||||||
merged: defaultMergedSettings,
|
merged: {
|
||||||
|
general: {
|
||||||
|
enableAutoUpdate: true,
|
||||||
|
enableAutoUpdateNotification: true,
|
||||||
|
},
|
||||||
|
tools: {
|
||||||
|
sandbox: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
} as LoadedSettings;
|
} as LoadedSettings;
|
||||||
|
|
||||||
mockChildProcess = Object.assign(new EventEmitter(), {
|
mockChildProcess = Object.assign(new EventEmitter(), {
|
||||||
@@ -79,8 +85,8 @@ describe('handleAutoUpdate', () => {
|
|||||||
expect(mockSpawn).not.toHaveBeenCalled();
|
expect(mockSpawn).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should do nothing if update nag is disabled', () => {
|
it('should do nothing if update prompts are disabled', () => {
|
||||||
mockSettings.merged.general.disableUpdateNag = true;
|
mockSettings.merged.general.enableAutoUpdateNotification = false;
|
||||||
handleAutoUpdate(mockUpdateInfo, mockSettings, '/root', mockSpawn);
|
handleAutoUpdate(mockUpdateInfo, mockSettings, '/root', mockSpawn);
|
||||||
expect(mockGetInstallationInfo).not.toHaveBeenCalled();
|
expect(mockGetInstallationInfo).not.toHaveBeenCalled();
|
||||||
expect(updateEventEmitter.emit).not.toHaveBeenCalled();
|
expect(updateEventEmitter.emit).not.toHaveBeenCalled();
|
||||||
@@ -88,7 +94,7 @@ describe('handleAutoUpdate', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should emit "update-received" but not update if auto-updates are disabled', () => {
|
it('should emit "update-received" but not update if auto-updates are disabled', () => {
|
||||||
mockSettings.merged.general.disableAutoUpdate = true;
|
mockSettings.merged.general.enableAutoUpdate = false;
|
||||||
mockGetInstallationInfo.mockReturnValue({
|
mockGetInstallationInfo.mockReturnValue({
|
||||||
updateCommand: 'npm i -g @google/gemini-cli@latest',
|
updateCommand: 'npm i -g @google/gemini-cli@latest',
|
||||||
updateMessage: 'Please update manually.',
|
updateMessage: 'Please update manually.',
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ export function handleAutoUpdate(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.merged.general.disableUpdateNag) {
|
if (!settings.merged.general.enableAutoUpdateNotification) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const installationInfo = getInstallationInfo(
|
const installationInfo = getInstallationInfo(
|
||||||
projectRoot,
|
projectRoot,
|
||||||
settings.merged.general.disableAutoUpdate,
|
settings.merged.general.enableAutoUpdate,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -58,7 +58,7 @@ export function handleAutoUpdate(
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
!installationInfo.updateCommand ||
|
!installationInfo.updateCommand ||
|
||||||
settings.merged.general.disableAutoUpdate
|
!settings.merged.general.enableAutoUpdate
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ describe('getInstallationInfo', () => {
|
|||||||
|
|
||||||
it('should return UNKNOWN when cliPath is not available', () => {
|
it('should return UNKNOWN when cliPath is not available', () => {
|
||||||
process.argv[1] = '';
|
process.argv[1] = '';
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
expect(info.packageManager).toBe(PackageManager.UNKNOWN);
|
expect(info.packageManager).toBe(PackageManager.UNKNOWN);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ describe('getInstallationInfo', () => {
|
|||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.UNKNOWN);
|
expect(info.packageManager).toBe(PackageManager.UNKNOWN);
|
||||||
expect(debugLogger.log).toHaveBeenCalledWith(error);
|
expect(debugLogger.log).toHaveBeenCalledWith(error);
|
||||||
@@ -84,7 +84,7 @@ describe('getInstallationInfo', () => {
|
|||||||
);
|
);
|
||||||
mockedIsGitRepository.mockReturnValue(true);
|
mockedIsGitRepository.mockReturnValue(true);
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.UNKNOWN);
|
expect(info.packageManager).toBe(PackageManager.UNKNOWN);
|
||||||
expect(info.isGlobal).toBe(false);
|
expect(info.isGlobal).toBe(false);
|
||||||
@@ -98,7 +98,7 @@ describe('getInstallationInfo', () => {
|
|||||||
process.argv[1] = npxPath;
|
process.argv[1] = npxPath;
|
||||||
mockedRealPathSync.mockReturnValue(npxPath);
|
mockedRealPathSync.mockReturnValue(npxPath);
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.NPX);
|
expect(info.packageManager).toBe(PackageManager.NPX);
|
||||||
expect(info.isGlobal).toBe(false);
|
expect(info.isGlobal).toBe(false);
|
||||||
@@ -110,7 +110,7 @@ describe('getInstallationInfo', () => {
|
|||||||
process.argv[1] = pnpxPath;
|
process.argv[1] = pnpxPath;
|
||||||
mockedRealPathSync.mockReturnValue(pnpxPath);
|
mockedRealPathSync.mockReturnValue(pnpxPath);
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.PNPX);
|
expect(info.packageManager).toBe(PackageManager.PNPX);
|
||||||
expect(info.isGlobal).toBe(false);
|
expect(info.isGlobal).toBe(false);
|
||||||
@@ -125,7 +125,7 @@ describe('getInstallationInfo', () => {
|
|||||||
throw new Error('Command failed');
|
throw new Error('Command failed');
|
||||||
});
|
});
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.BUNX);
|
expect(info.packageManager).toBe(PackageManager.BUNX);
|
||||||
expect(info.isGlobal).toBe(false);
|
expect(info.isGlobal).toBe(false);
|
||||||
@@ -141,7 +141,7 @@ describe('getInstallationInfo', () => {
|
|||||||
mockedRealPathSync.mockReturnValue(cliPath);
|
mockedRealPathSync.mockReturnValue(cliPath);
|
||||||
mockedExecSync.mockReturnValue(Buffer.from('gemini-cli')); // Simulate successful command
|
mockedExecSync.mockReturnValue(Buffer.from('gemini-cli')); // Simulate successful command
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(mockedExecSync).toHaveBeenCalledWith(
|
expect(mockedExecSync).toHaveBeenCalledWith(
|
||||||
'brew list -1 | grep -q "^gemini-cli$"',
|
'brew list -1 | grep -q "^gemini-cli$"',
|
||||||
@@ -165,7 +165,7 @@ describe('getInstallationInfo', () => {
|
|||||||
throw new Error('Command failed');
|
throw new Error('Command failed');
|
||||||
});
|
});
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(mockedExecSync).toHaveBeenCalledWith(
|
expect(mockedExecSync).toHaveBeenCalledWith(
|
||||||
'brew list -1 | grep -q "^gemini-cli$"',
|
'brew list -1 | grep -q "^gemini-cli$"',
|
||||||
@@ -184,13 +184,15 @@ describe('getInstallationInfo', () => {
|
|||||||
throw new Error('Command failed');
|
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.packageManager).toBe(PackageManager.PNPM);
|
||||||
expect(info.isGlobal).toBe(true);
|
expect(info.isGlobal).toBe(true);
|
||||||
expect(info.updateCommand).toBe('pnpm add -g @google/gemini-cli@latest');
|
expect(info.updateCommand).toBe('pnpm add -g @google/gemini-cli@latest');
|
||||||
expect(info.updateMessage).toContain('Attempting to automatically update');
|
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');
|
expect(infoDisabled.updateMessage).toContain('Please run pnpm add');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -202,7 +204,8 @@ describe('getInstallationInfo', () => {
|
|||||||
throw new Error('Command failed');
|
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.packageManager).toBe(PackageManager.YARN);
|
||||||
expect(info.isGlobal).toBe(true);
|
expect(info.isGlobal).toBe(true);
|
||||||
expect(info.updateCommand).toBe(
|
expect(info.updateCommand).toBe(
|
||||||
@@ -210,7 +213,8 @@ describe('getInstallationInfo', () => {
|
|||||||
);
|
);
|
||||||
expect(info.updateMessage).toContain('Attempting to automatically update');
|
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');
|
expect(infoDisabled.updateMessage).toContain('Please run yarn global add');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -222,13 +226,15 @@ describe('getInstallationInfo', () => {
|
|||||||
throw new Error('Command failed');
|
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.packageManager).toBe(PackageManager.BUN);
|
||||||
expect(info.isGlobal).toBe(true);
|
expect(info.isGlobal).toBe(true);
|
||||||
expect(info.updateCommand).toBe('bun add -g @google/gemini-cli@latest');
|
expect(info.updateCommand).toBe('bun add -g @google/gemini-cli@latest');
|
||||||
expect(info.updateMessage).toContain('Attempting to automatically update');
|
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');
|
expect(infoDisabled.updateMessage).toContain('Please run bun add');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -243,7 +249,7 @@ describe('getInstallationInfo', () => {
|
|||||||
(p) => p === path.join(projectRoot, 'yarn.lock'),
|
(p) => p === path.join(projectRoot, 'yarn.lock'),
|
||||||
);
|
);
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.YARN);
|
expect(info.packageManager).toBe(PackageManager.YARN);
|
||||||
expect(info.isGlobal).toBe(false);
|
expect(info.isGlobal).toBe(false);
|
||||||
@@ -261,7 +267,7 @@ describe('getInstallationInfo', () => {
|
|||||||
(p) => p === path.join(projectRoot, 'pnpm-lock.yaml'),
|
(p) => p === path.join(projectRoot, 'pnpm-lock.yaml'),
|
||||||
);
|
);
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.PNPM);
|
expect(info.packageManager).toBe(PackageManager.PNPM);
|
||||||
expect(info.isGlobal).toBe(false);
|
expect(info.isGlobal).toBe(false);
|
||||||
@@ -278,7 +284,7 @@ describe('getInstallationInfo', () => {
|
|||||||
(p) => p === path.join(projectRoot, 'bun.lockb'),
|
(p) => p === path.join(projectRoot, 'bun.lockb'),
|
||||||
);
|
);
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.BUN);
|
expect(info.packageManager).toBe(PackageManager.BUN);
|
||||||
expect(info.isGlobal).toBe(false);
|
expect(info.isGlobal).toBe(false);
|
||||||
@@ -293,7 +299,7 @@ describe('getInstallationInfo', () => {
|
|||||||
});
|
});
|
||||||
mockedExistsSync.mockReturnValue(false); // No lockfiles
|
mockedExistsSync.mockReturnValue(false); // No lockfiles
|
||||||
|
|
||||||
const info = getInstallationInfo(projectRoot, false);
|
const info = getInstallationInfo(projectRoot, true);
|
||||||
|
|
||||||
expect(info.packageManager).toBe(PackageManager.NPM);
|
expect(info.packageManager).toBe(PackageManager.NPM);
|
||||||
expect(info.isGlobal).toBe(false);
|
expect(info.isGlobal).toBe(false);
|
||||||
@@ -307,13 +313,15 @@ describe('getInstallationInfo', () => {
|
|||||||
throw new Error('Command failed');
|
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.packageManager).toBe(PackageManager.NPM);
|
||||||
expect(info.isGlobal).toBe(true);
|
expect(info.isGlobal).toBe(true);
|
||||||
expect(info.updateCommand).toBe('npm install -g @google/gemini-cli@latest');
|
expect(info.updateCommand).toBe('npm install -g @google/gemini-cli@latest');
|
||||||
expect(info.updateMessage).toContain('Attempting to automatically update');
|
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');
|
expect(infoDisabled.updateMessage).toContain('Please run npm install');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export interface InstallationInfo {
|
|||||||
|
|
||||||
export function getInstallationInfo(
|
export function getInstallationInfo(
|
||||||
projectRoot: string,
|
projectRoot: string,
|
||||||
isAutoUpdateDisabled: boolean,
|
isAutoUpdateEnabled: boolean,
|
||||||
): InstallationInfo {
|
): InstallationInfo {
|
||||||
const cliPath = process.argv[1];
|
const cliPath = process.argv[1];
|
||||||
if (!cliPath) {
|
if (!cliPath) {
|
||||||
@@ -103,9 +103,9 @@ export function getInstallationInfo(
|
|||||||
packageManager: PackageManager.PNPM,
|
packageManager: PackageManager.PNPM,
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
updateCommand,
|
updateCommand,
|
||||||
updateMessage: isAutoUpdateDisabled
|
updateMessage: isAutoUpdateEnabled
|
||||||
? `Please run ${updateCommand} to update`
|
? 'Installed with pnpm. Attempting to automatically update now...'
|
||||||
: 'Installed with pnpm. Attempting to automatically update now...',
|
: `Please run ${updateCommand} to update`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,9 +116,9 @@ export function getInstallationInfo(
|
|||||||
packageManager: PackageManager.YARN,
|
packageManager: PackageManager.YARN,
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
updateCommand,
|
updateCommand,
|
||||||
updateMessage: isAutoUpdateDisabled
|
updateMessage: isAutoUpdateEnabled
|
||||||
? `Please run ${updateCommand} to update`
|
? 'Installed with yarn. Attempting to automatically update now...'
|
||||||
: 'Installed with yarn. Attempting to automatically update now...',
|
: `Please run ${updateCommand} to update`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,9 +136,9 @@ export function getInstallationInfo(
|
|||||||
packageManager: PackageManager.BUN,
|
packageManager: PackageManager.BUN,
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
updateCommand,
|
updateCommand,
|
||||||
updateMessage: isAutoUpdateDisabled
|
updateMessage: isAutoUpdateEnabled
|
||||||
? `Please run ${updateCommand} to update`
|
? 'Installed with bun. Attempting to automatically update now...'
|
||||||
: 'Installed with bun. Attempting to automatically update now...',
|
: `Please run ${updateCommand} to update`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,9 +169,9 @@ export function getInstallationInfo(
|
|||||||
packageManager: PackageManager.NPM,
|
packageManager: PackageManager.NPM,
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
updateCommand,
|
updateCommand,
|
||||||
updateMessage: isAutoUpdateDisabled
|
updateMessage: isAutoUpdateEnabled
|
||||||
? `Please run ${updateCommand} to update`
|
? 'Installed with npm. Attempting to automatically update now...'
|
||||||
: 'Installed with npm. Attempting to automatically update now...',
|
: `Please run ${updateCommand} to update`,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
debugLogger.log(error);
|
debugLogger.log(error);
|
||||||
|
|||||||
@@ -120,13 +120,13 @@ describe('SettingsUtils', () => {
|
|||||||
description: 'Accessibility settings.',
|
description: 'Accessibility settings.',
|
||||||
showInDialog: false,
|
showInDialog: false,
|
||||||
properties: {
|
properties: {
|
||||||
disableLoadingPhrases: {
|
enableLoadingPhrases: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
label: 'Disable Loading Phrases',
|
label: 'Enable Loading Phrases',
|
||||||
category: 'UI',
|
category: 'UI',
|
||||||
requiresRestart: true,
|
requiresRestart: true,
|
||||||
default: false,
|
default: true,
|
||||||
description: 'Disable loading phrases for accessibility',
|
description: 'Enable loading phrases during operations.',
|
||||||
showInDialog: true,
|
showInDialog: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -284,18 +284,18 @@ describe('SettingsUtils', () => {
|
|||||||
|
|
||||||
it('should handle nested settings correctly', () => {
|
it('should handle nested settings correctly', () => {
|
||||||
const settings = makeMockSettings({
|
const settings = makeMockSettings({
|
||||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
ui: { accessibility: { enableLoadingPhrases: false } },
|
||||||
});
|
});
|
||||||
const mergedSettings = makeMockSettings({
|
const mergedSettings = makeMockSettings({
|
||||||
ui: { accessibility: { disableLoadingPhrases: false } },
|
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||||
});
|
});
|
||||||
|
|
||||||
const value = getEffectiveValue(
|
const value = getEffectiveValue(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
settings,
|
settings,
|
||||||
mergedSettings,
|
mergedSettings,
|
||||||
);
|
);
|
||||||
expect(value).toBe(true);
|
expect(value).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return undefined for invalid settings', () => {
|
it('should return undefined for invalid settings', () => {
|
||||||
@@ -315,7 +315,7 @@ describe('SettingsUtils', () => {
|
|||||||
it('should return all setting keys', () => {
|
it('should return all setting keys', () => {
|
||||||
const keys = getAllSettingKeys();
|
const keys = getAllSettingKeys();
|
||||||
expect(keys).toContain('test');
|
expect(keys).toContain('test');
|
||||||
expect(keys).toContain('ui.accessibility.disableLoadingPhrases');
|
expect(keys).toContain('ui.accessibility.enableLoadingPhrases');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -342,9 +342,9 @@ describe('SettingsUtils', () => {
|
|||||||
describe('isValidSettingKey', () => {
|
describe('isValidSettingKey', () => {
|
||||||
it('should return true for valid setting keys', () => {
|
it('should return true for valid setting keys', () => {
|
||||||
expect(isValidSettingKey('ui.requiresRestart')).toBe(true);
|
expect(isValidSettingKey('ui.requiresRestart')).toBe(true);
|
||||||
expect(
|
expect(isValidSettingKey('ui.accessibility.enableLoadingPhrases')).toBe(
|
||||||
isValidSettingKey('ui.accessibility.disableLoadingPhrases'),
|
true,
|
||||||
).toBe(true);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false for invalid setting keys', () => {
|
it('should return false for invalid setting keys', () => {
|
||||||
@@ -357,7 +357,7 @@ describe('SettingsUtils', () => {
|
|||||||
it('should return correct category for valid settings', () => {
|
it('should return correct category for valid settings', () => {
|
||||||
expect(getSettingCategory('ui.requiresRestart')).toBe('UI');
|
expect(getSettingCategory('ui.requiresRestart')).toBe('UI');
|
||||||
expect(
|
expect(
|
||||||
getSettingCategory('ui.accessibility.disableLoadingPhrases'),
|
getSettingCategory('ui.accessibility.enableLoadingPhrases'),
|
||||||
).toBe('UI');
|
).toBe('UI');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -391,7 +391,7 @@ describe('SettingsUtils', () => {
|
|||||||
const uiSettings = categories['UI'];
|
const uiSettings = categories['UI'];
|
||||||
const uiKeys = uiSettings.map((s) => s.key);
|
const uiKeys = uiSettings.map((s) => s.key);
|
||||||
expect(uiKeys).toContain('ui.requiresRestart');
|
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
|
expect(uiKeys).not.toContain('ui.theme'); // This is now marked false
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -421,7 +421,7 @@ describe('SettingsUtils', () => {
|
|||||||
|
|
||||||
const keys = booleanSettings.map((s) => s.key);
|
const keys = booleanSettings.map((s) => s.key);
|
||||||
expect(keys).toContain('ui.requiresRestart');
|
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('privacy.usageStatisticsEnabled');
|
||||||
expect(keys).not.toContain('security.auth.selectedType'); // Advanced setting
|
expect(keys).not.toContain('security.auth.selectedType'); // Advanced setting
|
||||||
expect(keys).not.toContain('security.auth.useExternal'); // Advanced setting
|
expect(keys).not.toContain('security.auth.useExternal'); // Advanced setting
|
||||||
@@ -454,7 +454,7 @@ describe('SettingsUtils', () => {
|
|||||||
expect(dialogKeys).toContain('ui.requiresRestart');
|
expect(dialogKeys).toContain('ui.requiresRestart');
|
||||||
|
|
||||||
// Should include nested settings marked for dialog
|
// 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
|
// Should NOT include settings marked as hidden
|
||||||
expect(dialogKeys).not.toContain('ui.theme'); // Hidden
|
expect(dialogKeys).not.toContain('ui.theme'); // Hidden
|
||||||
@@ -601,14 +601,14 @@ describe('SettingsUtils', () => {
|
|||||||
it('should return true when value differs from default', () => {
|
it('should return true when value differs from default', () => {
|
||||||
expect(isSettingModified('ui.requiresRestart', true)).toBe(true);
|
expect(isSettingModified('ui.requiresRestart', true)).toBe(true);
|
||||||
expect(
|
expect(
|
||||||
isSettingModified('ui.accessibility.disableLoadingPhrases', true),
|
isSettingModified('ui.accessibility.enableLoadingPhrases', false),
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false when value matches default', () => {
|
it('should return false when value matches default', () => {
|
||||||
expect(isSettingModified('ui.requiresRestart', false)).toBe(false);
|
expect(isSettingModified('ui.requiresRestart', false)).toBe(false);
|
||||||
expect(
|
expect(
|
||||||
isSettingModified('ui.accessibility.disableLoadingPhrases', false),
|
isSettingModified('ui.accessibility.enableLoadingPhrases', true),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -628,11 +628,11 @@ describe('SettingsUtils', () => {
|
|||||||
|
|
||||||
it('should return true for nested settings that exist', () => {
|
it('should return true for nested settings that exist', () => {
|
||||||
const settings = makeMockSettings({
|
const settings = makeMockSettings({
|
||||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
settingExistsInScope(
|
settingExistsInScope(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
settings,
|
settings,
|
||||||
),
|
),
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
@@ -642,7 +642,7 @@ describe('SettingsUtils', () => {
|
|||||||
const settings = makeMockSettings({});
|
const settings = makeMockSettings({});
|
||||||
expect(
|
expect(
|
||||||
settingExistsInScope(
|
settingExistsInScope(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
settings,
|
settings,
|
||||||
),
|
),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
@@ -652,7 +652,7 @@ describe('SettingsUtils', () => {
|
|||||||
const settings = makeMockSettings({ ui: { accessibility: {} } });
|
const settings = makeMockSettings({ ui: { accessibility: {} } });
|
||||||
expect(
|
expect(
|
||||||
settingExistsInScope(
|
settingExistsInScope(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
settings,
|
settings,
|
||||||
),
|
),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
@@ -674,25 +674,25 @@ describe('SettingsUtils', () => {
|
|||||||
it('should set nested setting value', () => {
|
it('should set nested setting value', () => {
|
||||||
const pendingSettings = makeMockSettings({});
|
const pendingSettings = makeMockSettings({});
|
||||||
const result = setPendingSettingValue(
|
const result = setPendingSettingValue(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
true,
|
true,
|
||||||
pendingSettings,
|
pendingSettings,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.ui?.accessibility?.disableLoadingPhrases).toBe(true);
|
expect(result.ui?.accessibility?.enableLoadingPhrases).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should preserve existing nested settings', () => {
|
it('should preserve existing nested settings', () => {
|
||||||
const pendingSettings = makeMockSettings({
|
const pendingSettings = makeMockSettings({
|
||||||
ui: { accessibility: { disableLoadingPhrases: false } },
|
ui: { accessibility: { enableLoadingPhrases: false } },
|
||||||
});
|
});
|
||||||
const result = setPendingSettingValue(
|
const result = setPendingSettingValue(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
true,
|
true,
|
||||||
pendingSettings,
|
pendingSettings,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.ui?.accessibility?.disableLoadingPhrases).toBe(true);
|
expect(result.ui?.accessibility?.enableLoadingPhrases).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not mutate original settings', () => {
|
it('should not mutate original settings', () => {
|
||||||
@@ -1029,7 +1029,7 @@ describe('SettingsUtils', () => {
|
|||||||
const settings = makeMockSettings({}); // nested setting doesn't exist
|
const settings = makeMockSettings({}); // nested setting doesn't exist
|
||||||
|
|
||||||
const result = isDefaultValue(
|
const result = isDefaultValue(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
settings,
|
settings,
|
||||||
);
|
);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
@@ -1037,11 +1037,11 @@ describe('SettingsUtils', () => {
|
|||||||
|
|
||||||
it('should return false when nested setting exists in scope', () => {
|
it('should return false when nested setting exists in scope', () => {
|
||||||
const settings = makeMockSettings({
|
const settings = makeMockSettings({
|
||||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||||
}); // nested setting exists
|
}); // nested setting exists
|
||||||
|
|
||||||
const result = isDefaultValue(
|
const result = isDefaultValue(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
settings,
|
settings,
|
||||||
);
|
);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
@@ -1079,14 +1079,14 @@ describe('SettingsUtils', () => {
|
|||||||
|
|
||||||
it('should return false for nested settings that exist in scope', () => {
|
it('should return false for nested settings that exist in scope', () => {
|
||||||
const settings = makeMockSettings({
|
const settings = makeMockSettings({
|
||||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||||
});
|
});
|
||||||
const mergedSettings = makeMockSettings({
|
const mergedSettings = makeMockSettings({
|
||||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = isValueInherited(
|
const result = isValueInherited(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
settings,
|
settings,
|
||||||
mergedSettings,
|
mergedSettings,
|
||||||
);
|
);
|
||||||
@@ -1096,11 +1096,11 @@ describe('SettingsUtils', () => {
|
|||||||
it('should return true for nested settings that do not exist in scope', () => {
|
it('should return true for nested settings that do not exist in scope', () => {
|
||||||
const settings = makeMockSettings({});
|
const settings = makeMockSettings({});
|
||||||
const mergedSettings = makeMockSettings({
|
const mergedSettings = makeMockSettings({
|
||||||
ui: { accessibility: { disableLoadingPhrases: true } },
|
ui: { accessibility: { enableLoadingPhrases: true } },
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = isValueInherited(
|
const result = isValueInherited(
|
||||||
'ui.accessibility.disableLoadingPhrases',
|
'ui.accessibility.enableLoadingPhrases',
|
||||||
settings,
|
settings,
|
||||||
mergedSettings,
|
mergedSettings,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ import type { AgentDefinition } from '../agents/types.js';
|
|||||||
import { fetchAdminControls } from '../code_assist/admin/admin_controls.js';
|
import { fetchAdminControls } from '../code_assist/admin/admin_controls.js';
|
||||||
|
|
||||||
export interface AccessibilitySettings {
|
export interface AccessibilitySettings {
|
||||||
disableLoadingPhrases?: boolean;
|
enableLoadingPhrases?: boolean;
|
||||||
screenReader?: boolean;
|
screenReader?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ export interface ConfigParameters {
|
|||||||
respectGitIgnore?: boolean;
|
respectGitIgnore?: boolean;
|
||||||
respectGeminiIgnore?: boolean;
|
respectGeminiIgnore?: boolean;
|
||||||
enableRecursiveFileSearch?: boolean;
|
enableRecursiveFileSearch?: boolean;
|
||||||
disableFuzzySearch?: boolean;
|
enableFuzzySearch?: boolean;
|
||||||
maxFileCount?: number;
|
maxFileCount?: number;
|
||||||
searchTimeout?: number;
|
searchTimeout?: number;
|
||||||
};
|
};
|
||||||
@@ -444,7 +444,7 @@ export class Config {
|
|||||||
respectGitIgnore: boolean;
|
respectGitIgnore: boolean;
|
||||||
respectGeminiIgnore: boolean;
|
respectGeminiIgnore: boolean;
|
||||||
enableRecursiveFileSearch: boolean;
|
enableRecursiveFileSearch: boolean;
|
||||||
disableFuzzySearch: boolean;
|
enableFuzzySearch: boolean;
|
||||||
maxFileCount: number;
|
maxFileCount: number;
|
||||||
searchTimeout: number;
|
searchTimeout: number;
|
||||||
};
|
};
|
||||||
@@ -598,7 +598,7 @@ export class Config {
|
|||||||
DEFAULT_FILE_FILTERING_OPTIONS.respectGeminiIgnore,
|
DEFAULT_FILE_FILTERING_OPTIONS.respectGeminiIgnore,
|
||||||
enableRecursiveFileSearch:
|
enableRecursiveFileSearch:
|
||||||
params.fileFiltering?.enableRecursiveFileSearch ?? true,
|
params.fileFiltering?.enableRecursiveFileSearch ?? true,
|
||||||
disableFuzzySearch: params.fileFiltering?.disableFuzzySearch ?? false,
|
enableFuzzySearch: params.fileFiltering?.enableFuzzySearch ?? true,
|
||||||
maxFileCount:
|
maxFileCount:
|
||||||
params.fileFiltering?.maxFileCount ??
|
params.fileFiltering?.maxFileCount ??
|
||||||
DEFAULT_FILE_FILTERING_OPTIONS.maxFileCount ??
|
DEFAULT_FILE_FILTERING_OPTIONS.maxFileCount ??
|
||||||
@@ -1402,8 +1402,8 @@ export class Config {
|
|||||||
return this.fileFiltering.enableRecursiveFileSearch;
|
return this.fileFiltering.enableRecursiveFileSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFileFilteringDisableFuzzySearch(): boolean {
|
getFileFilteringEnableFuzzySearch(): boolean {
|
||||||
return this.fileFiltering.disableFuzzySearch;
|
return this.fileFiltering.enableFuzzySearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFileFilteringRespectGitIgnore(): boolean {
|
getFileFilteringRespectGitIgnore(): boolean {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -59,7 +59,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -87,7 +87,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -116,7 +116,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -149,7 +149,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -173,7 +173,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -208,7 +208,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -238,7 +238,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -268,7 +268,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Expect no errors to be thrown during initialization
|
// Expect no errors to be thrown during initialization
|
||||||
@@ -295,7 +295,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -321,7 +321,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -330,7 +330,7 @@ describe('FileSearch', () => {
|
|||||||
expect(results).toEqual(['src/style.css']);
|
expect(results).toEqual(['src/style.css']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not use fzf for fuzzy matching when disableFuzzySearch is true', async () => {
|
it('should not use fzf for fuzzy matching when enableFuzzySearch is false', async () => {
|
||||||
tmpDir = await createTmpDir({
|
tmpDir = await createTmpDir({
|
||||||
src: {
|
src: {
|
||||||
'file1.js': '',
|
'file1.js': '',
|
||||||
@@ -347,7 +347,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: true,
|
enableFuzzySearch: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -356,7 +356,7 @@ describe('FileSearch', () => {
|
|||||||
expect(results).toEqual(['src/flexible.js']);
|
expect(results).toEqual(['src/flexible.js']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use fzf for fuzzy matching when disableFuzzySearch is false', async () => {
|
it('should use fzf for fuzzy matching when enableFuzzySearch is true', async () => {
|
||||||
tmpDir = await createTmpDir({
|
tmpDir = await createTmpDir({
|
||||||
src: {
|
src: {
|
||||||
'file1.js': '',
|
'file1.js': '',
|
||||||
@@ -373,7 +373,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -397,7 +397,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -428,7 +428,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(fileSearch.search('')).rejects.toThrow(
|
await expect(fileSearch.search('')).rejects.toThrow(
|
||||||
@@ -450,7 +450,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -473,7 +473,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -497,7 +497,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -524,7 +524,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -561,7 +561,7 @@ describe('FileSearch', () => {
|
|||||||
cache: true, // Enable caching for this test
|
cache: true, // Enable caching for this test
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -601,7 +601,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -645,7 +645,7 @@ describe('FileSearch', () => {
|
|||||||
cache: true, // Ensure caching is enabled
|
cache: true, // Ensure caching is enabled
|
||||||
cacheTtl: 10000,
|
cacheTtl: 10000,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -683,7 +683,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: true,
|
enableRecursiveFileSearch: true,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -713,7 +713,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: false,
|
enableRecursiveFileSearch: false,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -738,7 +738,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: false,
|
enableRecursiveFileSearch: false,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -763,7 +763,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: false,
|
enableRecursiveFileSearch: false,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
@@ -786,7 +786,7 @@ describe('FileSearch', () => {
|
|||||||
cache: false,
|
cache: false,
|
||||||
cacheTtl: 0,
|
cacheTtl: 0,
|
||||||
enableRecursiveFileSearch: false,
|
enableRecursiveFileSearch: false,
|
||||||
disableFuzzySearch: false,
|
enableFuzzySearch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
await fileSearch.initialize();
|
await fileSearch.initialize();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export interface FileSearchOptions {
|
|||||||
cache: boolean;
|
cache: boolean;
|
||||||
cacheTtl: number;
|
cacheTtl: number;
|
||||||
enableRecursiveFileSearch: boolean;
|
enableRecursiveFileSearch: boolean;
|
||||||
disableFuzzySearch: boolean;
|
enableFuzzySearch: boolean;
|
||||||
maxDepth?: number;
|
maxDepth?: number;
|
||||||
maxFiles?: number;
|
maxFiles?: number;
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ class RecursiveFileSearch implements FileSearch {
|
|||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
if (
|
if (
|
||||||
!this.resultCache ||
|
!this.resultCache ||
|
||||||
(!this.fzf && !this.options.disableFuzzySearch) ||
|
(!this.fzf && this.options.enableFuzzySearch) ||
|
||||||
!this.ignore
|
!this.ignore
|
||||||
) {
|
) {
|
||||||
throw new Error('Engine not initialized. Call initialize() first.');
|
throw new Error('Engine not initialized. Call initialize() first.');
|
||||||
@@ -183,7 +183,7 @@ class RecursiveFileSearch implements FileSearch {
|
|||||||
|
|
||||||
private buildResultCache(): void {
|
private buildResultCache(): void {
|
||||||
this.resultCache = new ResultCache(this.allFiles);
|
this.resultCache = new ResultCache(this.allFiles);
|
||||||
if (!this.options.disableFuzzySearch) {
|
if (this.options.enableFuzzySearch) {
|
||||||
// The v1 algorithm is much faster since it only looks at the first
|
// The v1 algorithm is much faster since it only looks at the first
|
||||||
// occurrence of the pattern. We use it for search spaces that have >20k
|
// occurrence of the pattern. We use it for search spaces that have >20k
|
||||||
// files, because the v2 algorithm is just too slow in those cases.
|
// files, because the v2 algorithm is just too slow in those cases.
|
||||||
|
|||||||
@@ -49,18 +49,18 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"disableAutoUpdate": {
|
"enableAutoUpdate": {
|
||||||
"title": "Disable Auto Update",
|
"title": "Enable Auto Update",
|
||||||
"description": "Disable automatic updates",
|
"description": "Enable automatic updates.",
|
||||||
"markdownDescription": "Disable automatic updates\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `false`",
|
"markdownDescription": "Enable automatic updates.\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `true`",
|
||||||
"default": false,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"disableUpdateNag": {
|
"enableAutoUpdateNotification": {
|
||||||
"title": "Disable Update Nag",
|
"title": "Enable Auto Update Notification",
|
||||||
"description": "Disable update notification prompts.",
|
"description": "Enable update notification prompts.",
|
||||||
"markdownDescription": "Disable update notification prompts.\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `false`",
|
"markdownDescription": "Enable update notification prompts.\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `true`",
|
||||||
"default": false,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"checkpointing": {
|
"checkpointing": {
|
||||||
@@ -340,11 +340,11 @@
|
|||||||
"default": {},
|
"default": {},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"disableLoadingPhrases": {
|
"enableLoadingPhrases": {
|
||||||
"title": "Disable Loading Phrases",
|
"title": "Enable Loading Phrases",
|
||||||
"description": "Disable loading phrases for accessibility",
|
"description": "Enable loading phrases during operations.",
|
||||||
"markdownDescription": "Disable loading phrases for accessibility\n\n- Category: `UI`\n- Requires restart: `yes`\n- Default: `false`",
|
"markdownDescription": "Enable loading phrases during operations.\n\n- Category: `UI`\n- Requires restart: `yes`\n- Default: `true`",
|
||||||
"default": false,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"screenReader": {
|
"screenReader": {
|
||||||
@@ -1017,11 +1017,11 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"disableFuzzySearch": {
|
"enableFuzzySearch": {
|
||||||
"title": "Disable Fuzzy Search",
|
"title": "Enable Fuzzy Search",
|
||||||
"description": "Disable fuzzy search when searching for files.",
|
"description": "Enable fuzzy search when searching for files.",
|
||||||
"markdownDescription": "Disable fuzzy search when searching for files.\n\n- Category: `Context`\n- Requires restart: `yes`\n- Default: `false`",
|
"markdownDescription": "Enable fuzzy search when searching for files.\n\n- Category: `Context`\n- Requires restart: `yes`\n- Default: `true`",
|
||||||
"default": false,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user