Skip to content

Commit 33e1911

Browse files
roblourensCopilot
andauthored
Refactor AgentService instantiation (#331861)
* Refactor AgentService instantiation Create an agent-host application DI scope, construct AgentService through it, and remove child-to-parent service re-exports. Update tests to use the production construction path. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify Agent Host DI scope names Use explicit bootstrap and application names for service collections and instantiation services. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Share Agent Host service initialization Use one strict DI scope and centralize common base and provider service setup for both Agent Host entry points. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Streamline Agent Host runtime creation Expose one runtime factory that owns common file, session, DI, AgentService, diagnostics, and optional provider infrastructure initialization. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move AgentService composition to runtime Construct and register the AgentService core and collaborator graph outside AgentService, use one guarded initialization step for genuine back-references, and replace the test-only clock injection with virtual timers. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use one complete Agent Host runtime graph Remove optional provider-infrastructure setup, make BYOK policy explicit, and defer Claude SDK environment mutation until first use. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Agent Host integration fixtures Keep mock-provider configuration distinct from host-owned worktree settings and use an existing workspace for permission containment tests. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Restore Claude SDK initialization behavior Keep the AgentService DI refactor focused by leaving the existing Claude SDK environment setup unchanged. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c4f99fb commit 33e1911

14 files changed

Lines changed: 1119 additions & 878 deletions

src/vs/platform/agentHost/node/agentHostBootstrap.ts

Lines changed: 169 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,89 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { DisposableStore } from '../../../base/common/lifecycle.js';
7+
import { Event } from '../../../base/common/event.js';
8+
import { joinPath } from '../../../base/common/resources.js';
9+
import { URI } from '../../../base/common/uri.js';
10+
import { Schemas } from '../../../base/common/network.js';
11+
import { INativeEnvironmentService } from '../../environment/common/environment.js';
12+
import { IFileService } from '../../files/common/files.js';
13+
import { FileService } from '../../files/common/fileService.js';
14+
import { DiskFileSystemProvider } from '../../files/node/diskFileSystemProvider.js';
15+
import { IInstantiationService } from '../../instantiation/common/instantiation.js';
16+
import { InstantiationService } from '../../instantiation/common/instantiationService.js';
717
import { ServiceCollection } from '../../instantiation/common/serviceCollection.js';
8-
import { ILogService } from '../../log/common/log.js';
18+
import { ILoggerService, ILogService } from '../../log/common/log.js';
19+
import { IProductService } from '../../product/common/productService.js';
920
import { IRequestService } from '../../request/common/request.js';
21+
import { ITelemetryService } from '../../telemetry/common/telemetry.js';
22+
import { ISandboxHelperService } from '../../sandbox/common/sandboxHelperService.js';
23+
import { SandboxHelperService } from '../../sandbox/node/sandboxHelper.js';
24+
import { IWindowsMxcTerminalSandboxRuntime, WindowsMxcTerminalSandboxRuntime } from '../../sandbox/common/terminalSandboxMxcRuntime.js';
25+
import { IAgentPluginManager } from '../common/agentPluginManager.js';
26+
import { IDiffComputeService } from '../common/diffComputeService.js';
27+
import { IAgentEditAttributionService } from '../common/fileEditAttribution.js';
28+
import { IAgentHostGitService } from '../common/agentHostGitService.js';
29+
import { IAgentHostOTelService } from '../common/otel/agentHostOTelService.js';
30+
import { ISessionDataService } from '../common/sessionDataService.js';
31+
import { AgentHostFileMonitorService, IAgentHostFileMonitorService } from './agentHostFileMonitorService.js';
32+
import { AgentHostGitService } from './agentHostGitService.js';
33+
import { AgentHostOTelService } from './otel/agentHostOTelService.js';
1034
import { AgentHostProxyResolver, IAgentHostProxyResolver } from './agentHostProxyResolver.js';
1135
import { AgentHostRequestService } from './agentHostRequestService.js';
36+
import { createAgentHostTelemetryService, IAgentHostTelemetryService } from './agentHostTelemetryService.js';
37+
import { AgentService, IAgentServiceOptions } from './agentService.js';
38+
import { createAgentService } from './agentServiceComposition.js';
39+
import { INetworkDiagnosticsService, NetworkDiagnosticsService } from './networkDiagnosticsService.js';
40+
import { AgentPluginManager } from './agentPluginManager.js';
41+
import { NodeWorkerDiffComputeService } from './diffComputeService.js';
42+
import { AgentEditAttributionService } from './shared/agentEditAttributionService.js';
43+
import { EditArcReporterService, IEditArcReporterService } from './shared/editArcReporter.js';
44+
import { EditSurvivalReporterFactory, IEditSurvivalReporterFactory } from './shared/editSurvivalReporter.js';
45+
import { IAgentHostWorktreeIsolation, WorktreeIsolation } from './shared/worktreeIsolation.js';
46+
import { AgentSdkDownloader, IAgentSdkDownloader, type IAgentSdkDownloadProgress } from './agentSdkDownloader.js';
47+
import { IClaudeAgentSdkService, ClaudeAgentSdkService } from './claude/claudeAgentSdkService.js';
48+
import { ClaudeProxyService, IClaudeProxyService } from './claude/claudeProxyService.js';
49+
import { CodexProxyService, ICodexProxyService } from './codex/codexProxyService.js';
50+
import { IByokLmBridgeRegistry, NullByokLmBridgeRegistry } from './byokLmBridgeRegistry.js';
51+
import { ByokLmProxyService, IByokLmProxyService, NullByokLmProxyService } from './copilot/byokLmProxyService.js';
52+
import { registerPendingEditContentProvider } from './copilot/pendingEditContentStore.js';
53+
import { SessionDataService } from './sessionDataService.js';
54+
import { IAgentCustomizationSettingsRegistration } from '../common/agentCustomizationSettings.js';
55+
import { AgentHostLaunchKind } from '../common/agentHostTelemetry.js';
1256

1357
export interface IAgentHostNetworkServices {
1458
readonly proxyResolver: IAgentHostProxyResolver;
1559
readonly requestService: IRequestService;
1660
}
1761

62+
export interface ICreateAgentHostRuntimeOptions {
63+
readonly environmentService: INativeEnvironmentService;
64+
readonly productService: IProductService;
65+
readonly logService: ILogService;
66+
readonly loggerService: ILoggerService | undefined;
67+
readonly disposables: DisposableStore;
68+
readonly disableTelemetry?: boolean;
69+
readonly transientProxyConfiguration: boolean;
70+
readonly hostLaunchKind: AgentHostLaunchKind;
71+
readonly providerConfigurations: readonly IAgentCustomizationSettingsRegistration[];
72+
/**
73+
* The utility-process host has a renderer bridge; standalone hosts use the
74+
* unavailable variant but still register the same complete service graph.
75+
*/
76+
readonly byok: { readonly kind: 'renderer'; readonly bridgeRegistry: IByokLmBridgeRegistry } | { readonly kind: 'unavailable' };
77+
}
78+
79+
export interface IAgentHostRuntime {
80+
readonly instantiationService: IInstantiationService;
81+
readonly agentService: AgentService;
82+
readonly fileService: IFileService;
83+
readonly sessionDataService: ISessionDataService;
84+
readonly proxyResolver: IAgentHostProxyResolver;
85+
readonly telemetryService: IAgentHostTelemetryService;
86+
readonly agentSdkDownloader: AgentSdkDownloader;
87+
readonly sdkDownloadProgress: Event<IAgentSdkDownloadProgress>;
88+
}
89+
1890
/**
1991
* Register `IAgentHostProxyResolver` and `IRequestService` into the agent host's
2092
* DI container — the services that `IAgentSdkDownloader` (and proxy-aware
@@ -28,13 +100,106 @@ export interface IAgentHostNetworkServices {
28100
* configuration service.
29101
*/
30102
export function registerAgentHostNetworkServices(
31-
diServices: ServiceCollection,
103+
services: ServiceCollection,
32104
logService: ILogService,
33105
disposables: DisposableStore,
34106
): IAgentHostNetworkServices {
35107
const proxyResolver = disposables.add(new AgentHostProxyResolver(logService));
36-
diServices.set(IAgentHostProxyResolver, proxyResolver);
108+
services.set(IAgentHostProxyResolver, proxyResolver);
37109
const requestService = disposables.add(new AgentHostRequestService(logService, proxyResolver));
38-
diServices.set(IRequestService, requestService);
110+
services.set(IRequestService, requestService);
39111
return { proxyResolver, requestService };
40112
}
113+
114+
export async function createAgentHostRuntime(options: ICreateAgentHostRuntimeOptions): Promise<IAgentHostRuntime> {
115+
const { environmentService, productService, logService, loggerService, disposables } = options;
116+
const fileService = disposables.add(new FileService(logService));
117+
disposables.add(fileService.registerProvider(Schemas.file, disposables.add(new DiskFileSystemProvider(logService))));
118+
disposables.add(registerPendingEditContentProvider(fileService));
119+
const sessionDataService = new SessionDataService(URI.file(environmentService.userDataPath), fileService, logService);
120+
const services = new ServiceCollection(
121+
[INativeEnvironmentService, environmentService],
122+
[ILogService, logService],
123+
[IFileService, fileService],
124+
[ISessionDataService, sessionDataService],
125+
[IProductService, productService],
126+
);
127+
const networkServices = registerAgentHostNetworkServices(services, logService, disposables);
128+
const proxyResolver = networkServices.proxyResolver;
129+
const fetchFn = proxyResolver.fetch.bind(proxyResolver);
130+
const telemetryService = await createAgentHostTelemetryService({
131+
environmentService,
132+
productService,
133+
fileService,
134+
loggerService,
135+
logService,
136+
disposables,
137+
disableTelemetry: options.disableTelemetry,
138+
fetchFn,
139+
requestService: networkServices.requestService,
140+
});
141+
services.set(ITelemetryService, telemetryService);
142+
const instantiationService = new InstantiationService(services, /*strict*/ true);
143+
let agentService: AgentService | undefined;
144+
try {
145+
const fileMonitorService = disposables.add(instantiationService.createInstance(AgentHostFileMonitorService));
146+
services.set(IAgentHostFileMonitorService, fileMonitorService);
147+
services.set(IWindowsMxcTerminalSandboxRuntime, instantiationService.createInstance(WindowsMxcTerminalSandboxRuntime));
148+
services.set(ISandboxHelperService, new SandboxHelperService());
149+
services.set(IAgentHostGitService, instantiationService.createInstance(AgentHostGitService));
150+
const agentServiceOptions: IAgentServiceOptions = {
151+
rootConfigResource: joinPath(environmentService.appSettingsHome, 'globalStorage', 'agent-host-config.json'),
152+
providerConfigurations: options.providerConfigurations,
153+
hostLaunchKind: options.hostLaunchKind,
154+
storageResource: joinPath(environmentService.appSettingsHome, 'globalStorage', 'agent-host-storage.json'),
155+
debugLogsEnvironment: {
156+
logsHome: environmentService.logsHome,
157+
tmpDir: environmentService.tmpDir,
158+
},
159+
};
160+
agentService = createAgentService(agentServiceOptions, services, instantiationService, fetchFn, logService, productService);
161+
proxyResolver.bindConfigurationService(agentService.configurationService, options.transientProxyConfiguration);
162+
const networkDiagnosticsService = instantiationService.createInstance(NetworkDiagnosticsService);
163+
services.set(INetworkDiagnosticsService, networkDiagnosticsService);
164+
agentService.setNetworkDiagnosticsService(networkDiagnosticsService);
165+
services.set(IAgentPluginManager, new AgentPluginManager(URI.file(environmentService.userDataPath), fileService, logService));
166+
services.set(IDiffComputeService, disposables.add(instantiationService.createInstance(NodeWorkerDiffComputeService)));
167+
const editAttributionService = disposables.add(instantiationService.createInstance(AgentEditAttributionService, undefined, undefined));
168+
services.set(IAgentEditAttributionService, editAttributionService);
169+
agentService.setEditAttributionService(editAttributionService);
170+
services.set(IEditSurvivalReporterFactory, instantiationService.createInstance(EditSurvivalReporterFactory));
171+
services.set(IEditArcReporterService, disposables.add(instantiationService.createInstance(EditArcReporterService, undefined)));
172+
173+
const worktreeIsolation = disposables.add(instantiationService.createInstance(WorktreeIsolation, undefined));
174+
services.set(IAgentHostWorktreeIsolation, worktreeIsolation);
175+
agentService.setWorktreeIsolation(worktreeIsolation);
176+
177+
const agentSdkDownloader = disposables.add(instantiationService.createInstance(AgentSdkDownloader));
178+
services.set(IAgentSdkDownloader, agentSdkDownloader);
179+
services.set(IClaudeProxyService, disposables.add(instantiationService.createInstance(ClaudeProxyService)));
180+
services.set(IClaudeAgentSdkService, instantiationService.createInstance(ClaudeAgentSdkService));
181+
services.set(ICodexProxyService, disposables.add(instantiationService.createInstance(CodexProxyService)));
182+
services.set(IAgentHostOTelService, disposables.add(instantiationService.createInstance(AgentHostOTelService, fetchFn)));
183+
const byokBridgeRegistry = options.byok.kind === 'renderer' ? options.byok.bridgeRegistry : new NullByokLmBridgeRegistry();
184+
services.set(IByokLmBridgeRegistry, byokBridgeRegistry);
185+
const byokLmProxyService: IByokLmProxyService = options.byok.kind === 'renderer'
186+
? disposables.add(instantiationService.createInstance(ByokLmProxyService))
187+
: new NullByokLmProxyService();
188+
services.set(IByokLmProxyService, byokLmProxyService);
189+
190+
return {
191+
instantiationService,
192+
agentService,
193+
fileService,
194+
sessionDataService,
195+
proxyResolver,
196+
telemetryService,
197+
agentSdkDownloader,
198+
sdkDownloadProgress: agentSdkDownloader.onDidDownloadProgress,
199+
};
200+
} catch (error) {
201+
agentService?.dispose();
202+
instantiationService.dispose();
203+
throw error;
204+
}
205+
}

0 commit comments

Comments
 (0)