summaryrefslogtreecommitdiff
path: root/packages/cli/src/config
diff options
context:
space:
mode:
authorAli Al Jufairi <[email protected]>2025-08-10 09:04:52 +0900
committerGitHub <[email protected]>2025-08-10 00:04:52 +0000
commit8a9a9275440e3681e9be73d741a5aba429ae501f (patch)
treecc2c17101c57d0c34049a6ee390d0f1b9bf38018 /packages/cli/src/config
parentc632ec8b03ac5b459da9ccb041b9fca19252f69b (diff)
feat(ui): add /settings command and UI panel (#4738)
Co-authored-by: Jacob Richman <[email protected]>
Diffstat (limited to 'packages/cli/src/config')
-rw-r--r--packages/cli/src/config/settings.ts91
-rw-r--r--packages/cli/src/config/settingsSchema.test.ts253
-rw-r--r--packages/cli/src/config/settingsSchema.ts516
3 files changed, 773 insertions, 87 deletions
diff --git a/packages/cli/src/config/settings.ts b/packages/cli/src/config/settings.ts
index 3c4270d7..36fd50f1 100644
--- a/packages/cli/src/config/settings.ts
+++ b/packages/cli/src/config/settings.ts
@@ -9,18 +9,15 @@ import * as path from 'path';
import { homedir, platform } from 'os';
import * as dotenv from 'dotenv';
import {
- MCPServerConfig,
GEMINI_CONFIG_DIR as GEMINI_DIR,
getErrorMessage,
- BugCommandSettings,
- ChatCompressionSettings,
- TelemetrySettings,
- AuthType,
} from '@google/gemini-cli-core';
import stripJsonComments from 'strip-json-comments';
import { DefaultLight } from '../ui/themes/default-light.js';
import { DefaultDark } from '../ui/themes/default.js';
-import { CustomTheme } from '../ui/themes/theme.js';
+import { Settings, MemoryImportFormat } from './settingsSchema.js';
+
+export type { Settings, MemoryImportFormat };
export const SETTINGS_DIRECTORY_NAME = '.gemini';
export const USER_SETTINGS_DIR = path.join(homedir(), SETTINGS_DIRECTORY_NAME);
@@ -44,7 +41,7 @@ export function getWorkspaceSettingsPath(workspaceDir: string): string {
return path.join(workspaceDir, SETTINGS_DIRECTORY_NAME, 'settings.json');
}
-export type DnsResolutionOrder = 'ipv4first' | 'verbatim';
+export type { DnsResolutionOrder } from './settingsSchema.js';
export enum SettingScope {
User = 'User',
@@ -64,86 +61,6 @@ export interface AccessibilitySettings {
disableLoadingPhrases?: boolean;
}
-export interface Settings {
- theme?: string;
- customThemes?: Record<string, CustomTheme>;
- selectedAuthType?: AuthType;
- useExternalAuth?: boolean;
- sandbox?: boolean | string;
- coreTools?: string[];
- excludeTools?: string[];
- toolDiscoveryCommand?: string;
- toolCallCommand?: string;
- mcpServerCommand?: string;
- mcpServers?: Record<string, MCPServerConfig>;
- allowMCPServers?: string[];
- excludeMCPServers?: string[];
- showMemoryUsage?: boolean;
- contextFileName?: string | string[];
- accessibility?: AccessibilitySettings;
- telemetry?: TelemetrySettings;
- usageStatisticsEnabled?: boolean;
- preferredEditor?: string;
- bugCommand?: BugCommandSettings;
- checkpointing?: CheckpointingSettings;
- autoConfigureMaxOldSpaceSize?: boolean;
- /** The model name to use (e.g 'gemini-9.0-pro') */
- model?: string;
-
- // Git-aware file filtering settings
- fileFiltering?: {
- respectGitIgnore?: boolean;
- respectGeminiIgnore?: boolean;
- enableRecursiveFileSearch?: boolean;
- };
-
- hideWindowTitle?: boolean;
-
- hideTips?: boolean;
- hideBanner?: boolean;
-
- // Setting for setting maximum number of user/model/tool turns in a session.
- maxSessionTurns?: number;
-
- // A map of tool names to their summarization settings.
- summarizeToolOutput?: Record<string, SummarizeToolOutputSettings>;
-
- vimMode?: boolean;
- memoryImportFormat?: 'tree' | 'flat';
-
- // Flag to be removed post-launch.
- ideModeFeature?: boolean;
- /// IDE mode setting configured via slash command toggle.
- ideMode?: boolean;
-
- // Flag to be removed post-launch.
- folderTrustFeature?: boolean;
- // Setting to track whether Folder trust is enabled.
- folderTrust?: boolean;
-
- // Setting to track if the user has seen the IDE integration nudge.
- hasSeenIdeIntegrationNudge?: boolean;
-
- // Setting for disabling auto-update.
- disableAutoUpdate?: boolean;
-
- // Setting for disabling the update nag message.
- disableUpdateNag?: boolean;
-
- memoryDiscoveryMaxDirs?: number;
-
- // Environment variables to exclude from project .env files
- excludedProjectEnvVars?: string[];
- dnsResolutionOrder?: DnsResolutionOrder;
-
- includeDirectories?: string[];
-
- loadMemoryFromIncludeDirectories?: boolean;
-
- chatCompression?: ChatCompressionSettings;
- showLineNumbers?: boolean;
-}
-
export interface SettingsError {
message: string;
path: string;
diff --git a/packages/cli/src/config/settingsSchema.test.ts b/packages/cli/src/config/settingsSchema.test.ts
new file mode 100644
index 00000000..ab820ee1
--- /dev/null
+++ b/packages/cli/src/config/settingsSchema.test.ts
@@ -0,0 +1,253 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { describe, it, expect } from 'vitest';
+import { SETTINGS_SCHEMA, Settings } from './settingsSchema.js';
+
+describe('SettingsSchema', () => {
+ describe('SETTINGS_SCHEMA', () => {
+ it('should contain all expected top-level settings', () => {
+ const expectedSettings = [
+ 'theme',
+ 'customThemes',
+ 'showMemoryUsage',
+ 'usageStatisticsEnabled',
+ 'autoConfigureMaxOldSpaceSize',
+ 'preferredEditor',
+ 'maxSessionTurns',
+ 'memoryImportFormat',
+ 'memoryDiscoveryMaxDirs',
+ 'contextFileName',
+ 'vimMode',
+ 'ideMode',
+ 'accessibility',
+ 'checkpointing',
+ 'fileFiltering',
+ 'disableAutoUpdate',
+ 'hideWindowTitle',
+ 'hideTips',
+ 'hideBanner',
+ 'selectedAuthType',
+ 'useExternalAuth',
+ 'sandbox',
+ 'coreTools',
+ 'excludeTools',
+ 'toolDiscoveryCommand',
+ 'toolCallCommand',
+ 'mcpServerCommand',
+ 'mcpServers',
+ 'allowMCPServers',
+ 'excludeMCPServers',
+ 'telemetry',
+ 'bugCommand',
+ 'summarizeToolOutput',
+ 'ideModeFeature',
+ 'dnsResolutionOrder',
+ 'excludedProjectEnvVars',
+ 'disableUpdateNag',
+ 'includeDirectories',
+ 'loadMemoryFromIncludeDirectories',
+ 'model',
+ 'hasSeenIdeIntegrationNudge',
+ 'folderTrustFeature',
+ ];
+
+ expectedSettings.forEach((setting) => {
+ expect(
+ SETTINGS_SCHEMA[setting as keyof typeof SETTINGS_SCHEMA],
+ ).toBeDefined();
+ });
+ });
+
+ it('should have correct structure for each setting', () => {
+ Object.entries(SETTINGS_SCHEMA).forEach(([_key, definition]) => {
+ expect(definition).toHaveProperty('type');
+ expect(definition).toHaveProperty('label');
+ expect(definition).toHaveProperty('category');
+ expect(definition).toHaveProperty('requiresRestart');
+ expect(definition).toHaveProperty('default');
+ expect(typeof definition.type).toBe('string');
+ expect(typeof definition.label).toBe('string');
+ expect(typeof definition.category).toBe('string');
+ expect(typeof definition.requiresRestart).toBe('boolean');
+ });
+ });
+
+ it('should have correct nested setting structure', () => {
+ const nestedSettings = [
+ 'accessibility',
+ 'checkpointing',
+ 'fileFiltering',
+ ];
+
+ nestedSettings.forEach((setting) => {
+ const definition = SETTINGS_SCHEMA[
+ setting as keyof typeof SETTINGS_SCHEMA
+ ] as (typeof SETTINGS_SCHEMA)[keyof typeof SETTINGS_SCHEMA] & {
+ properties: unknown;
+ };
+ expect(definition.type).toBe('object');
+ expect(definition.properties).toBeDefined();
+ expect(typeof definition.properties).toBe('object');
+ });
+ });
+
+ it('should have accessibility nested properties', () => {
+ expect(
+ SETTINGS_SCHEMA.accessibility.properties?.disableLoadingPhrases,
+ ).toBeDefined();
+ expect(
+ SETTINGS_SCHEMA.accessibility.properties?.disableLoadingPhrases.type,
+ ).toBe('boolean');
+ });
+
+ it('should have checkpointing nested properties', () => {
+ expect(SETTINGS_SCHEMA.checkpointing.properties?.enabled).toBeDefined();
+ expect(SETTINGS_SCHEMA.checkpointing.properties?.enabled.type).toBe(
+ 'boolean',
+ );
+ });
+
+ it('should have fileFiltering nested properties', () => {
+ expect(
+ SETTINGS_SCHEMA.fileFiltering.properties?.respectGitIgnore,
+ ).toBeDefined();
+ expect(
+ SETTINGS_SCHEMA.fileFiltering.properties?.respectGeminiIgnore,
+ ).toBeDefined();
+ expect(
+ SETTINGS_SCHEMA.fileFiltering.properties?.enableRecursiveFileSearch,
+ ).toBeDefined();
+ });
+
+ it('should have unique categories', () => {
+ const categories = new Set();
+
+ // Collect categories from top-level settings
+ Object.values(SETTINGS_SCHEMA).forEach((definition) => {
+ categories.add(definition.category);
+ // Also collect from nested properties
+ const defWithProps = definition as typeof definition & {
+ properties?: Record<string, unknown>;
+ };
+ if (defWithProps.properties) {
+ Object.values(defWithProps.properties).forEach(
+ (nestedDef: unknown) => {
+ const nestedDefTyped = nestedDef as { category?: string };
+ if (nestedDefTyped.category) {
+ categories.add(nestedDefTyped.category);
+ }
+ },
+ );
+ }
+ });
+
+ expect(categories.size).toBeGreaterThan(0);
+ expect(categories).toContain('General');
+ expect(categories).toContain('UI');
+ expect(categories).toContain('Mode');
+ expect(categories).toContain('Updates');
+ expect(categories).toContain('Accessibility');
+ expect(categories).toContain('Checkpointing');
+ expect(categories).toContain('File Filtering');
+ expect(categories).toContain('Advanced');
+ });
+
+ it('should have consistent default values for boolean settings', () => {
+ const checkBooleanDefaults = (schema: Record<string, unknown>) => {
+ Object.entries(schema).forEach(
+ ([_key, definition]: [string, unknown]) => {
+ const def = definition as {
+ type?: string;
+ default?: unknown;
+ properties?: Record<string, unknown>;
+ };
+ if (def.type === 'boolean') {
+ // Boolean settings can have boolean or undefined defaults (for optional settings)
+ expect(['boolean', 'undefined']).toContain(typeof def.default);
+ }
+ if (def.properties) {
+ checkBooleanDefaults(def.properties);
+ }
+ },
+ );
+ };
+
+ checkBooleanDefaults(SETTINGS_SCHEMA as Record<string, unknown>);
+ });
+
+ it('should have showInDialog property configured', () => {
+ // Check that user-facing settings are marked for dialog display
+ expect(SETTINGS_SCHEMA.showMemoryUsage.showInDialog).toBe(true);
+ expect(SETTINGS_SCHEMA.vimMode.showInDialog).toBe(true);
+ expect(SETTINGS_SCHEMA.ideMode.showInDialog).toBe(true);
+ expect(SETTINGS_SCHEMA.disableAutoUpdate.showInDialog).toBe(true);
+ expect(SETTINGS_SCHEMA.hideWindowTitle.showInDialog).toBe(true);
+ expect(SETTINGS_SCHEMA.hideTips.showInDialog).toBe(true);
+ expect(SETTINGS_SCHEMA.hideBanner.showInDialog).toBe(true);
+ expect(SETTINGS_SCHEMA.usageStatisticsEnabled.showInDialog).toBe(true);
+
+ // Check that advanced settings are hidden from dialog
+ expect(SETTINGS_SCHEMA.selectedAuthType.showInDialog).toBe(false);
+ expect(SETTINGS_SCHEMA.coreTools.showInDialog).toBe(false);
+ expect(SETTINGS_SCHEMA.mcpServers.showInDialog).toBe(false);
+ expect(SETTINGS_SCHEMA.telemetry.showInDialog).toBe(false);
+
+ // Check that some settings are appropriately hidden
+ expect(SETTINGS_SCHEMA.theme.showInDialog).toBe(false); // Changed to false
+ expect(SETTINGS_SCHEMA.customThemes.showInDialog).toBe(false); // Managed via theme editor
+ expect(SETTINGS_SCHEMA.checkpointing.showInDialog).toBe(false); // Experimental feature
+ expect(SETTINGS_SCHEMA.accessibility.showInDialog).toBe(false); // Changed to false
+ expect(SETTINGS_SCHEMA.fileFiltering.showInDialog).toBe(false); // Changed to false
+ expect(SETTINGS_SCHEMA.preferredEditor.showInDialog).toBe(false); // Changed to false
+ expect(SETTINGS_SCHEMA.autoConfigureMaxOldSpaceSize.showInDialog).toBe(
+ true,
+ );
+ });
+
+ it('should infer Settings type correctly', () => {
+ // This test ensures that the Settings type is properly inferred from the schema
+ const settings: Settings = {
+ theme: 'dark',
+ includeDirectories: ['/path/to/dir'],
+ loadMemoryFromIncludeDirectories: true,
+ };
+
+ // TypeScript should not complain about these properties
+ expect(settings.theme).toBe('dark');
+ expect(settings.includeDirectories).toEqual(['/path/to/dir']);
+ expect(settings.loadMemoryFromIncludeDirectories).toBe(true);
+ });
+
+ it('should have includeDirectories setting in schema', () => {
+ expect(SETTINGS_SCHEMA.includeDirectories).toBeDefined();
+ expect(SETTINGS_SCHEMA.includeDirectories.type).toBe('array');
+ expect(SETTINGS_SCHEMA.includeDirectories.category).toBe('General');
+ expect(SETTINGS_SCHEMA.includeDirectories.default).toEqual([]);
+ });
+
+ it('should have loadMemoryFromIncludeDirectories setting in schema', () => {
+ expect(SETTINGS_SCHEMA.loadMemoryFromIncludeDirectories).toBeDefined();
+ expect(SETTINGS_SCHEMA.loadMemoryFromIncludeDirectories.type).toBe(
+ 'boolean',
+ );
+ expect(SETTINGS_SCHEMA.loadMemoryFromIncludeDirectories.category).toBe(
+ 'General',
+ );
+ expect(SETTINGS_SCHEMA.loadMemoryFromIncludeDirectories.default).toBe(
+ false,
+ );
+ });
+
+ it('should have folderTrustFeature setting in schema', () => {
+ expect(SETTINGS_SCHEMA.folderTrustFeature).toBeDefined();
+ expect(SETTINGS_SCHEMA.folderTrustFeature.type).toBe('boolean');
+ expect(SETTINGS_SCHEMA.folderTrustFeature.category).toBe('General');
+ expect(SETTINGS_SCHEMA.folderTrustFeature.default).toBe(false);
+ expect(SETTINGS_SCHEMA.folderTrustFeature.showInDialog).toBe(true);
+ });
+ });
+});
diff --git a/packages/cli/src/config/settingsSchema.ts b/packages/cli/src/config/settingsSchema.ts
new file mode 100644
index 00000000..dc2582ec
--- /dev/null
+++ b/packages/cli/src/config/settingsSchema.ts
@@ -0,0 +1,516 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import {
+ MCPServerConfig,
+ BugCommandSettings,
+ TelemetrySettings,
+ AuthType,
+ ChatCompressionSettings,
+} from '@google/gemini-cli-core';
+import { CustomTheme } from '../ui/themes/theme.js';
+
+export interface SettingDefinition {
+ type: 'boolean' | 'string' | 'number' | 'array' | 'object';
+ label: string;
+ category: string;
+ requiresRestart: boolean;
+ default: boolean | string | number | string[] | object | undefined;
+ description?: string;
+ parentKey?: string;
+ childKey?: string;
+ key?: string;
+ properties?: SettingsSchema;
+ showInDialog?: boolean;
+}
+
+export interface SettingsSchema {
+ [key: string]: SettingDefinition;
+}
+
+export type MemoryImportFormat = 'tree' | 'flat';
+export type DnsResolutionOrder = 'ipv4first' | 'verbatim';
+
+/**
+ * The canonical schema for all settings.
+ * The structure of this object defines the structure of the `Settings` type.
+ * `as const` is crucial for TypeScript to infer the most specific types possible.
+ */
+export const SETTINGS_SCHEMA = {
+ // UI Settings
+ theme: {
+ type: 'string',
+ label: 'Theme',
+ category: 'UI',
+ requiresRestart: false,
+ default: undefined as string | undefined,
+ description: 'The color theme for the UI.',
+ showInDialog: false,
+ },
+ customThemes: {
+ type: 'object',
+ label: 'Custom Themes',
+ category: 'UI',
+ requiresRestart: false,
+ default: {} as Record<string, CustomTheme>,
+ description: 'Custom theme definitions.',
+ showInDialog: false,
+ },
+ hideWindowTitle: {
+ type: 'boolean',
+ label: 'Hide Window Title',
+ category: 'UI',
+ requiresRestart: true,
+ default: false,
+ description: 'Hide the window title bar',
+ showInDialog: true,
+ },
+ hideTips: {
+ type: 'boolean',
+ label: 'Hide Tips',
+ category: 'UI',
+ requiresRestart: false,
+ default: false,
+ description: 'Hide helpful tips in the UI',
+ showInDialog: true,
+ },
+ hideBanner: {
+ type: 'boolean',
+ label: 'Hide Banner',
+ category: 'UI',
+ requiresRestart: false,
+ default: false,
+ description: 'Hide the application banner',
+ showInDialog: true,
+ },
+ showMemoryUsage: {
+ type: 'boolean',
+ label: 'Show Memory Usage',
+ category: 'UI',
+ requiresRestart: false,
+ default: false,
+ description: 'Display memory usage information in the UI',
+ showInDialog: true,
+ },
+
+ usageStatisticsEnabled: {
+ type: 'boolean',
+ label: 'Enable Usage Statistics',
+ category: 'General',
+ requiresRestart: true,
+ default: false,
+ description: 'Enable collection of usage statistics',
+ showInDialog: true,
+ },
+ autoConfigureMaxOldSpaceSize: {
+ type: 'boolean',
+ label: 'Auto Configure Max Old Space Size',
+ category: 'General',
+ requiresRestart: true,
+ default: false,
+ description: 'Automatically configure Node.js memory limits',
+ showInDialog: true,
+ },
+ preferredEditor: {
+ type: 'string',
+ label: 'Preferred Editor',
+ category: 'General',
+ requiresRestart: false,
+ default: undefined as string | undefined,
+ description: 'The preferred editor to open files in.',
+ showInDialog: false,
+ },
+ maxSessionTurns: {
+ type: 'number',
+ label: 'Max Session Turns',
+ category: 'General',
+ requiresRestart: false,
+ default: undefined as number | undefined,
+ description:
+ 'Maximum number of user/model/tool turns to keep in a session.',
+ showInDialog: false,
+ },
+ memoryImportFormat: {
+ type: 'string',
+ label: 'Memory Import Format',
+ category: 'General',
+ requiresRestart: false,
+ default: undefined as MemoryImportFormat | undefined,
+ description: 'The format to use when importing memory.',
+ showInDialog: false,
+ },
+ memoryDiscoveryMaxDirs: {
+ type: 'number',
+ label: 'Memory Discovery Max Dirs',
+ category: 'General',
+ requiresRestart: false,
+ default: undefined as number | undefined,
+ description: 'Maximum number of directories to search for memory.',
+ showInDialog: false,
+ },
+ contextFileName: {
+ type: 'object',
+ label: 'Context File Name',
+ category: 'General',
+ requiresRestart: false,
+ default: undefined as string | string[] | undefined,
+ description: 'The name of the context file.',
+ showInDialog: false,
+ },
+ vimMode: {
+ type: 'boolean',
+ label: 'Vim Mode',
+ category: 'Mode',
+ requiresRestart: false,
+ default: false,
+ description: 'Enable Vim keybindings',
+ showInDialog: true,
+ },
+ ideMode: {
+ type: 'boolean',
+ label: 'IDE Mode',
+ category: 'Mode',
+ requiresRestart: true,
+ default: false,
+ description: 'Enable IDE integration mode',
+ showInDialog: true,
+ },
+
+ accessibility: {
+ type: 'object',
+ label: 'Accessibility',
+ category: 'Accessibility',
+ requiresRestart: true,
+ default: {},
+ description: 'Accessibility settings.',
+ showInDialog: false,
+ properties: {
+ disableLoadingPhrases: {
+ type: 'boolean',
+ label: 'Disable Loading Phrases',
+ category: 'Accessibility',
+ requiresRestart: true,
+ default: false,
+ description: 'Disable loading phrases for accessibility',
+ showInDialog: true,
+ },
+ },
+ },
+ checkpointing: {
+ type: 'object',
+ label: 'Checkpointing',
+ category: 'Checkpointing',
+ requiresRestart: true,
+ default: {},
+ description: 'Session checkpointing settings.',
+ showInDialog: false,
+ properties: {
+ enabled: {
+ type: 'boolean',
+ label: 'Enable Checkpointing',
+ category: 'Checkpointing',
+ requiresRestart: true,
+ default: false,
+ description: 'Enable session checkpointing for recovery',
+ showInDialog: false,
+ },
+ },
+ },
+ fileFiltering: {
+ type: 'object',
+ label: 'File Filtering',
+ category: 'File Filtering',
+ requiresRestart: true,
+ default: {},
+ description: 'Settings for git-aware file filtering.',
+ showInDialog: false,
+ properties: {
+ respectGitIgnore: {
+ type: 'boolean',
+ label: 'Respect .gitignore',
+ category: 'File Filtering',
+ requiresRestart: true,
+ default: true,
+ description: 'Respect .gitignore files when searching',
+ showInDialog: true,
+ },
+ respectGeminiIgnore: {
+ type: 'boolean',
+ label: 'Respect .geminiignore',
+ category: 'File Filtering',
+ requiresRestart: true,
+ default: true,
+ description: 'Respect .geminiignore files when searching',
+ showInDialog: true,
+ },
+ enableRecursiveFileSearch: {
+ type: 'boolean',
+ label: 'Enable Recursive File Search',
+ category: 'File Filtering',
+ requiresRestart: true,
+ default: true,
+ description: 'Enable recursive file search functionality',
+ showInDialog: true,
+ },
+ },
+ },
+
+ disableAutoUpdate: {
+ type: 'boolean',
+ label: 'Disable Auto Update',
+ category: 'Updates',
+ requiresRestart: false,
+ default: false,
+ description: 'Disable automatic updates',
+ showInDialog: true,
+ },
+
+ selectedAuthType: {
+ type: 'string',
+ label: 'Selected Auth Type',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as AuthType | undefined,
+ description: 'The currently selected authentication type.',
+ showInDialog: false,
+ },
+ useExternalAuth: {
+ type: 'boolean',
+ label: 'Use External Auth',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as boolean | undefined,
+ description: 'Whether to use an external authentication flow.',
+ showInDialog: false,
+ },
+ sandbox: {
+ type: 'object',
+ label: 'Sandbox',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as boolean | string | undefined,
+ description:
+ 'Sandbox execution environment (can be a boolean or a path string).',
+ showInDialog: false,
+ },
+ coreTools: {
+ type: 'array',
+ label: 'Core Tools',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as string[] | undefined,
+ description: 'Paths to core tool definitions.',
+ showInDialog: false,
+ },
+ excludeTools: {
+ type: 'array',
+ label: 'Exclude Tools',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as string[] | undefined,
+ description: 'Tool names to exclude from discovery.',
+ showInDialog: false,
+ },
+ toolDiscoveryCommand: {
+ type: 'string',
+ label: 'Tool Discovery Command',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as string | undefined,
+ description: 'Command to run for tool discovery.',
+ showInDialog: false,
+ },
+ toolCallCommand: {
+ type: 'string',
+ label: 'Tool Call Command',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as string | undefined,
+ description: 'Command to run for tool calls.',
+ showInDialog: false,
+ },
+ mcpServerCommand: {
+ type: 'string',
+ label: 'MCP Server Command',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as string | undefined,
+ description: 'Command to start an MCP server.',
+ showInDialog: false,
+ },
+ mcpServers: {
+ type: 'object',
+ label: 'MCP Servers',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: {} as Record<string, MCPServerConfig>,
+ description: 'Configuration for MCP servers.',
+ showInDialog: false,
+ },
+ allowMCPServers: {
+ type: 'array',
+ label: 'Allow MCP Servers',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as string[] | undefined,
+ description: 'A whitelist of MCP servers to allow.',
+ showInDialog: false,
+ },
+ excludeMCPServers: {
+ type: 'array',
+ label: 'Exclude MCP Servers',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as string[] | undefined,
+ description: 'A blacklist of MCP servers to exclude.',
+ showInDialog: false,
+ },
+ telemetry: {
+ type: 'object',
+ label: 'Telemetry',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as TelemetrySettings | undefined,
+ description: 'Telemetry configuration.',
+ showInDialog: false,
+ },
+ bugCommand: {
+ type: 'object',
+ label: 'Bug Command',
+ category: 'Advanced',
+ requiresRestart: false,
+ default: undefined as BugCommandSettings | undefined,
+ description: 'Configuration for the bug report command.',
+ showInDialog: false,
+ },
+ summarizeToolOutput: {
+ type: 'object',
+ label: 'Summarize Tool Output',
+ category: 'Advanced',
+ requiresRestart: false,
+ default: undefined as Record<string, { tokenBudget?: number }> | undefined,
+ description: 'Settings for summarizing tool output.',
+ showInDialog: false,
+ },
+ ideModeFeature: {
+ type: 'boolean',
+ label: 'IDE Mode Feature Flag',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as boolean | undefined,
+ description: 'Internal feature flag for IDE mode.',
+ showInDialog: false,
+ },
+ dnsResolutionOrder: {
+ type: 'string',
+ label: 'DNS Resolution Order',
+ category: 'Advanced',
+ requiresRestart: true,
+ default: undefined as DnsResolutionOrder | undefined,
+ description: 'The DNS resolution order.',
+ showInDialog: false,
+ },
+ excludedProjectEnvVars: {
+ type: 'array',
+ label: 'Excluded Project Environment Variables',
+ category: 'Advanced',
+ requiresRestart: false,
+ default: ['DEBUG', 'DEBUG_MODE'] as string[],
+ description: 'Environment variables to exclude from project context.',
+ showInDialog: false,
+ },
+ disableUpdateNag: {
+ type: 'boolean',
+ label: 'Disable Update Nag',
+ category: 'Updates',
+ requiresRestart: false,
+ default: false,
+ description: 'Disable update notification prompts.',
+ showInDialog: false,
+ },
+ includeDirectories: {
+ type: 'array',
+ label: 'Include Directories',
+ category: 'General',
+ requiresRestart: false,
+ default: [] as string[],
+ description: 'Additional directories to include in the workspace context.',
+ showInDialog: false,
+ },
+ loadMemoryFromIncludeDirectories: {
+ type: 'boolean',
+ label: 'Load Memory From Include Directories',
+ category: 'General',
+ requiresRestart: false,
+ default: false,
+ description: 'Whether to load memory files from include directories.',
+ showInDialog: true,
+ },
+ model: {
+ type: 'string',
+ label: 'Model',
+ category: 'General',
+ requiresRestart: false,
+ default: undefined as string | undefined,
+ description: 'The Gemini model to use for conversations.',
+ showInDialog: false,
+ },
+ hasSeenIdeIntegrationNudge: {
+ type: 'boolean',
+ label: 'Has Seen IDE Integration Nudge',
+ category: 'General',
+ requiresRestart: false,
+ default: false,
+ description: 'Whether the user has seen the IDE integration nudge.',
+ showInDialog: false,
+ },
+ folderTrustFeature: {
+ type: 'boolean',
+ label: 'Folder Trust Feature',
+ category: 'General',
+ requiresRestart: false,
+ default: false,
+ description: 'Enable folder trust feature for enhanced security.',
+ showInDialog: true,
+ },
+ folderTrust: {
+ type: 'boolean',
+ label: 'Folder Trust',
+ category: 'General',
+ requiresRestart: false,
+ default: false,
+ description: 'Setting to track whether Folder trust is enabled.',
+ showInDialog: true,
+ },
+ chatCompression: {
+ type: 'object',
+ label: 'Chat Compression',
+ category: 'General',
+ requiresRestart: false,
+ default: undefined as ChatCompressionSettings | undefined,
+ description: 'Chat compression settings.',
+ showInDialog: false,
+ },
+ showLineNumbers: {
+ type: 'boolean',
+ label: 'Show Line Numbers',
+ category: 'General',
+ requiresRestart: false,
+ default: false,
+ description: 'Show line numbers in the chat.',
+ showInDialog: true,
+ },
+} as const;
+
+type InferSettings<T extends SettingsSchema> = {
+ -readonly [K in keyof T]?: T[K] extends { properties: SettingsSchema }
+ ? InferSettings<T[K]['properties']>
+ : T[K]['default'] extends boolean
+ ? boolean
+ : T[K]['default'];
+};
+
+export type Settings = InferSettings<typeof SETTINGS_SCHEMA>;