From b27f9f0fba40e4839fec9f2c5ebacfdf608d2ebb Mon Sep 17 00:00:00 2001 From: Dmitriy Vasyura Date: Fri, 7 Aug 2026 17:30:32 -0700 Subject: [PATCH] Fix Agent Host user settings loading (#329723) * Fix Agent Host user settings loading Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Agent Host bootstrap test product service Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../agentHost/node/agentHostBootstrap.ts | 4 +- .../test/node/agentHostBootstrap.test.ts | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/vs/platform/agentHost/test/node/agentHostBootstrap.test.ts diff --git a/src/vs/platform/agentHost/node/agentHostBootstrap.ts b/src/vs/platform/agentHost/node/agentHostBootstrap.ts index cc89758725a..e32f2c13682 100644 --- a/src/vs/platform/agentHost/node/agentHostBootstrap.ts +++ b/src/vs/platform/agentHost/node/agentHostBootstrap.ts @@ -32,7 +32,7 @@ export interface IAgentHostNetworkServices { * itself, and through it `ClaudeAgentSdkService` / `CodexAgent`) must be * constructed AFTER this call. * - * Reads the default profile's `settings.json` from `` — + * Reads the default profile's `settings.json` from `` — * the same file the workbench writes user settings to. Initialization is * async because the settings file is read off disk. * @@ -50,7 +50,7 @@ export async function registerAgentHostNetworkServices( ): Promise { const policyService = new NullPolicyService(); diServices.set(IPolicyService, policyService); - const settingsResource = joinPath(environmentService.userRoamingDataHome, 'settings.json'); + const settingsResource = joinPath(environmentService.appSettingsHome, 'settings.json'); const configurationService = disposables.add(new ConfigurationService(settingsResource, fileService, policyService, logService)); await configurationService.initialize(); diServices.set(IConfigurationService, configurationService); diff --git a/src/vs/platform/agentHost/test/node/agentHostBootstrap.test.ts b/src/vs/platform/agentHost/test/node/agentHostBootstrap.test.ts new file mode 100644 index 00000000000..b4b2eaf3343 --- /dev/null +++ b/src/vs/platform/agentHost/test/node/agentHostBootstrap.test.ts @@ -0,0 +1,55 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { VSBuffer } from '../../../../base/common/buffer.js'; +import { URI } from '../../../../base/common/uri.js'; +import { DisposableStore } from '../../../../base/common/lifecycle.js'; +import { Schemas } from '../../../../base/common/network.js'; +import { joinPath } from '../../../../base/common/resources.js'; +import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js'; +import { IConfigurationService } from '../../../configuration/common/configuration.js'; +import { ConfigurationService } from '../../../configuration/common/configurationService.js'; +import { NativeEnvironmentService } from '../../../environment/node/environmentService.js'; +import { FileService } from '../../../files/common/fileService.js'; +import { InMemoryFileSystemProvider } from '../../../files/common/inMemoryFilesystemProvider.js'; +import { OPTIONS, parseArgs } from '../../../environment/node/argv.js'; +import { NullLogService } from '../../../log/common/log.js'; +import product from '../../../product/common/product.js'; +import { ServiceCollection } from '../../../instantiation/common/serviceCollection.js'; +import { registerAgentHostNetworkServices } from '../../node/agentHostBootstrap.js'; + +class TestEnvironmentService extends NativeEnvironmentService { + override get appSettingsHome(): URI { + return URI.from({ scheme: Schemas.file, path: '/User' }); + } +} + +function createFileService(disposables: DisposableStore): FileService { + const fileService = disposables.add(new FileService(new NullLogService())); + const provider = disposables.add(new InMemoryFileSystemProvider()); + disposables.add(fileService.registerProvider(Schemas.file, provider)); + return fileService; +} + +suite('agentHostBootstrap', () => { + const disposables = ensureNoDisposablesAreLeakedInTestSuite(); + + test('loads configuration from appSettingsHome', async () => { + const testDisposables = disposables.add(new DisposableStore()); + const environmentService = new TestEnvironmentService(parseArgs(['--force-disable-user-env'], OPTIONS), { _serviceBrand: undefined, ...product }); + const fileService = createFileService(testDisposables); + + await fileService.createFolder(environmentService.appSettingsHome); + await fileService.writeFile(joinPath(environmentService.appSettingsHome, 'settings.json'), VSBuffer.fromString('{ "http.proxy": "http://proxy.example:8080" }')); + + const services = new ServiceCollection(); + await registerAgentHostNetworkServices(services, fileService, environmentService, new NullLogService(), testDisposables); + + const configurationService = services.get(IConfigurationService); + assert.ok(configurationService instanceof ConfigurationService); + assert.strictEqual(configurationService.getValue('http.proxy'), 'http://proxy.example:8080'); + }); +});