fix(#5605): .env file loaded after settings are parsed (#6494)

This commit is contained in:
HugoMurillo
2025-08-19 13:07:42 -06:00
committed by GitHub
parent b24c5887c4
commit b9cf1ea3ce
2 changed files with 109 additions and 160 deletions

View File

@@ -70,6 +70,43 @@ export interface SettingsFile {
settings: Settings;
path: string;
}
function mergeSettings(
system: Settings,
user: Settings,
workspace: Settings,
): Settings {
// folderTrust is not supported at workspace level.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { folderTrust, ...workspaceWithoutFolderTrust } = workspace;
return {
...user,
...workspaceWithoutFolderTrust,
...system,
customThemes: {
...(user.customThemes || {}),
...(workspace.customThemes || {}),
...(system.customThemes || {}),
},
mcpServers: {
...(user.mcpServers || {}),
...(workspace.mcpServers || {}),
...(system.mcpServers || {}),
},
includeDirectories: [
...(system.includeDirectories || []),
...(user.includeDirectories || []),
...(workspace.includeDirectories || []),
],
chatCompression: {
...(system.chatCompression || {}),
...(user.chatCompression || {}),
...(workspace.chatCompression || {}),
},
};
}
export class LoadedSettings {
constructor(
system: SettingsFile,
@@ -96,39 +133,11 @@ export class LoadedSettings {
}
private computeMergedSettings(): Settings {
const system = this.system.settings;
const user = this.user.settings;
const workspace = this.workspace.settings;
// folderTrust is not supported at workspace level.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { folderTrust, ...workspaceWithoutFolderTrust } = workspace;
return {
...user,
...workspaceWithoutFolderTrust,
...system,
customThemes: {
...(user.customThemes || {}),
...(workspace.customThemes || {}),
...(system.customThemes || {}),
},
mcpServers: {
...(user.mcpServers || {}),
...(workspace.mcpServers || {}),
...(system.mcpServers || {}),
},
includeDirectories: [
...(system.includeDirectories || []),
...(user.includeDirectories || []),
...(workspace.includeDirectories || []),
],
chatCompression: {
...(system.chatCompression || {}),
...(user.chatCompression || {}),
...(workspace.chatCompression || {}),
},
};
return mergeSettings(
this.system.settings,
this.user.settings,
this.workspace.settings,
);
}
forScope(scope: SettingScope): SettingsFile {
@@ -339,10 +348,7 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
try {
if (fs.existsSync(systemSettingsPath)) {
const systemContent = fs.readFileSync(systemSettingsPath, 'utf-8');
const parsedSystemSettings = JSON.parse(
stripJsonComments(systemContent),
) as Settings;
systemSettings = resolveEnvVarsInObject(parsedSystemSettings);
systemSettings = JSON.parse(stripJsonComments(systemContent)) as Settings;
}
} catch (error: unknown) {
settingsErrors.push({
@@ -355,10 +361,7 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
try {
if (fs.existsSync(USER_SETTINGS_PATH)) {
const userContent = fs.readFileSync(USER_SETTINGS_PATH, 'utf-8');
const parsedUserSettings = JSON.parse(
stripJsonComments(userContent),
) as Settings;
userSettings = resolveEnvVarsInObject(parsedUserSettings);
userSettings = JSON.parse(stripJsonComments(userContent)) as Settings;
// Support legacy theme names
if (userSettings.theme && userSettings.theme === 'VS') {
userSettings.theme = DefaultLight.name;
@@ -378,10 +381,9 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
try {
if (fs.existsSync(workspaceSettingsPath)) {
const projectContent = fs.readFileSync(workspaceSettingsPath, 'utf-8');
const parsedWorkspaceSettings = JSON.parse(
workspaceSettings = JSON.parse(
stripJsonComments(projectContent),
) as Settings;
workspaceSettings = resolveEnvVarsInObject(parsedWorkspaceSettings);
if (workspaceSettings.theme && workspaceSettings.theme === 'VS') {
workspaceSettings.theme = DefaultLight.name;
} else if (
@@ -399,6 +401,22 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
}
}
// Create a temporary merged settings object to pass to loadEnvironment.
const tempMergedSettings = mergeSettings(
systemSettings,
userSettings,
workspaceSettings,
);
// loadEnviroment depends on settings so we have to create a temp version of
// the settings to avoid a cycle
loadEnvironment(tempMergedSettings);
// Now that the environment is loaded, resolve variables in the settings.
systemSettings = resolveEnvVarsInObject(systemSettings);
userSettings = resolveEnvVarsInObject(userSettings);
workspaceSettings = resolveEnvVarsInObject(workspaceSettings);
// Create LoadedSettings first
const loadedSettings = new LoadedSettings(
{
@@ -429,9 +447,6 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
delete loadedSettings.merged.chatCompression;
}
// Load environment with merged settings
loadEnvironment(loadedSettings.merged);
return loadedSettings;
}