Download packages/a2a-server/src/config/settings.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 5.84 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/a2a-server/src/config/settings.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/a2a-server/src/config/settings.ts
-
curl -L -o settings.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/a2a-server/src/config/settings.ts
5.84 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import * as fs from 'node:fs'; | |
| import * as path from 'node:path'; | |
| import { | |
| type MCPServerConfig, | |
| debugLogger, | |
| GEMINI_DIR, | |
| getErrorMessage, | |
| type TelemetrySettings, | |
| homedir, | |
| checkPathTrust, | |
| isHeadlessMode, | |
| } from '@google/gemini-cli-core'; | |
| import stripJsonComments from 'strip-json-comments'; | |
| export const USER_SETTINGS_DIR = path.join(homedir(), GEMINI_DIR); | |
| export const USER_SETTINGS_PATH = path.join(USER_SETTINGS_DIR, 'settings.json'); | |
| // TODO: Ensure full compatibility with V2 nested settings structure (settings.schema.json). | |
| // This involves updating the interface and implementing migration logic to support legacy V1 (flat) settings, | |
| // similar to how packages/cli/src/config/settings.ts handles it. | |
| export interface Settings { | |
| mcpServers?: Record<string, MCPServerConfig>; | |
| tools?: { | |
| allowed?: string[]; | |
| exclude?: string[]; | |
| core?: string[]; | |
| }; | |
| telemetry?: TelemetrySettings; | |
| showMemoryUsage?: boolean; | |
| checkpointing?: CheckpointingSettings; | |
| folderTrust?: boolean; | |
| general?: { | |
| previewFeatures?: boolean; | |
| }; | |
| // Git-aware file filtering settings | |
| fileFiltering?: { | |
| respectGitIgnore?: boolean; | |
| respectGeminiIgnore?: boolean; | |
| enableRecursiveFileSearch?: boolean; | |
| customIgnoreFilePaths?: string[]; | |
| }; | |
| experimental?: { | |
| enableAgents?: boolean; | |
| }; | |
| policyPaths?: string[]; | |
| adminPolicyPaths?: string[]; | |
| } | |
| export interface SettingsError { | |
| message: string; | |
| path: string; | |
| } | |
| export interface CheckpointingSettings { | |
| enabled?: boolean; | |
| } | |
| /** | |
| * Loads settings from user and workspace directories. | |
| * Project settings override user settings if the workspace is trusted. | |
| * | |
| * How is it different to gemini-cli/cli: Returns already merged settings rather | |
| * than `LoadedSettings` (unnecessary since we are not modifying users | |
| * settings.json). | |
| */ | |
| export function loadSettings( | |
| workspaceDir: string, | |
| isTrustedOverride?: boolean, | |
| ): Settings { | |
| let userSettings: Settings = {}; | |
| let workspaceSettings: Settings = {}; | |
| const settingsErrors: SettingsError[] = []; | |
| // Load user settings | |
| try { | |
| if (fs.existsSync(USER_SETTINGS_PATH)) { | |
| const userContent = fs.readFileSync(USER_SETTINGS_PATH, 'utf-8'); | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| const parsedUserSettings = JSON.parse( | |
| stripJsonComments(userContent), | |
| ) as Settings; | |
| userSettings = resolveEnvVarsInObject(parsedUserSettings); | |
| } | |
| } catch (error: unknown) { | |
| settingsErrors.push({ | |
| message: getErrorMessage(error), | |
| path: USER_SETTINGS_PATH, | |
| }); | |
| } | |
| let isTrusted = isTrustedOverride; | |
| if (isTrusted === undefined) { | |
| const { isTrusted: trustResult } = checkPathTrust({ | |
| path: workspaceDir, | |
| isFolderTrustEnabled: userSettings.folderTrust ?? true, | |
| isHeadless: isHeadlessMode(), | |
| }); | |
| isTrusted = trustResult ?? false; | |
| } | |
| const workspaceSettingsPath = path.join( | |
| workspaceDir, | |
| GEMINI_DIR, | |
| 'settings.json', | |
| ); | |
| // Load workspace settings only if trusted | |
| if (isTrusted) { | |
| try { | |
| if (fs.existsSync(workspaceSettingsPath)) { | |
| const projectContent = fs.readFileSync(workspaceSettingsPath, 'utf-8'); | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| const parsedWorkspaceSettings = JSON.parse( | |
| stripJsonComments(projectContent), | |
| ) as Settings; | |
| workspaceSettings = resolveEnvVarsInObject(parsedWorkspaceSettings); | |
| } | |
| } catch (error: unknown) { | |
| settingsErrors.push({ | |
| message: getErrorMessage(error), | |
| path: workspaceSettingsPath, | |
| }); | |
| } | |
| } | |
| if (settingsErrors.length > 0) { | |
| debugLogger.error('Errors loading settings:'); | |
| for (const error of settingsErrors) { | |
| debugLogger.error(` Path: ${error.path}`); | |
| debugLogger.error(` Message: ${error.message}`); | |
| } | |
| } | |
| // If there are overlapping keys, the values of workspaceSettings will | |
| // override values from userSettings | |
| const mergedSettings = { | |
| ...userSettings, | |
| ...workspaceSettings, | |
| }; | |
| // Security: ensure policyPaths and adminPolicyPaths are only loaded from trusted, user-level | |
| // configuration and cannot be overridden by workspace-level settings, even if the | |
| // workspace is trusted. | |
| mergedSettings.policyPaths = userSettings.policyPaths; | |
| mergedSettings.adminPolicyPaths = userSettings.adminPolicyPaths; | |
| return mergedSettings; | |
| } | |
| function resolveEnvVarsInString(value: string): string { | |
| const envVarRegex = /\$(?:(\w+)|{([^}]+)})/g; // Find $VAR_NAME or ${VAR_NAME} | |
| return value.replace( | |
| envVarRegex, | |
| (match: string, varName1: string, varName2: string) => { | |
| const varName = varName1 || varName2; | |
| const envValue = process?.env?.[varName]; | |
| if (typeof envValue === 'string') { | |
| return envValue; | |
| } | |
| return match; | |
| }, | |
| ); | |
| } | |
| function resolveEnvVarsInObject<T>(obj: T): T { | |
| if ( | |
| obj === null || | |
| obj === undefined || | |
| typeof obj === 'boolean' || | |
| typeof obj === 'number' | |
| ) { | |
| return obj; | |
| } | |
| if (typeof obj === 'string') { | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| return resolveEnvVarsInString(obj) as unknown as T; | |
| } | |
| if (Array.isArray(obj)) { | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-unsafe-return | |
| return obj.map((item) => resolveEnvVarsInObject(item)) as unknown as T; | |
| } | |
| if (typeof obj === 'object') { | |
| const newObj = { ...obj } as T; | |
| for (const key in newObj) { | |
| if (Object.prototype.hasOwnProperty.call(newObj, key)) { | |
| newObj[key] = resolveEnvVarsInObject(newObj[key]); | |
| } | |
| } | |
| return newObj; | |
| } | |
| return obj; | |
| } | |