chatModes.ts ×23

Frontier kind: Code frontier

unlabeled · c_d4ca8d7136a6

10 tests · 50546 LOC · 228 files · introduces 0 tests · 104 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
23 ranges104 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
4341 ranges50546 lines · 228 files · Browse complete extent
All tests (intent)
10 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 104 introduced LOC across 23 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/chatModes.ts 104 introduced LOC · 23 ranges

Open complete file

91
92 constructor(
93 > private readonly sessionResource: URI, chatModes.ts
94 > @IChatAgentService private readonly chatAgentService: IChatAgentService,
95 > @IContextKeyService contextKeyService: IContextKeyService,
96 > @ILogService private readonly logService: ILogService,
97 > @IStorageService private readonly storageService: IStorageService,
98 > @IConfigurationService private readonly configurationService: IConfigurationService,
99 > @ICustomizationHarnessService private readonly customizationHarnessService: ICustomizationHarnessService,
100 > ) {
101 > super();
102 >
103 > const sessionType = getChatSessionType(sessionResource);
104 >
105 > this._storageKey = ChatModes.CUSTOM_MODES_STORAGE_KEY_PREFIX + sessionType;
106 > this.hasCustomModes = ChatContextKeys.Modes.hasCustomChatModes.bindTo(contextKeyService);
107 >
108 > // Load cached modes from storage first
109 > this.loadCachedModes();
110 >
111 > this._pendingRefresh = this.triggerRefresh();
112 > // When the harness service is the source, also react to its change events for our session type.
113 > this._register(this.customizationHarnessService.onDidChangeCustomAgents(e => {
114 if (e.sessionType === sessionType) {
115 this._pendingRefresh = this.triggerRefresh();
116 }
117 > })); chatModes.ts
118 > this._register(this.storageService.onWillSaveState(() => this.saveCachedModes()));
119 >
120 > // Builtin mode availability depends on configuration policy and tools-agent availability.
121 > this._register(this.configurationService.onDidChangeConfiguration(e => {
122 if (e.affectsConfiguration(ChatConfiguration.AgentEnabled)) {
123 this._onDidChange.fire();
124 }
125 > })); chatModes.ts
126 > let didHaveToolsAgent = this.chatAgentService.hasToolsAgent;
127 > this._register(this.chatAgentService.onDidChangeAgents(() => {
128 if (didHaveToolsAgent !== this.chatAgentService.hasToolsAgent) {
129 didHaveToolsAgent = this.chatAgentService.hasToolsAgent;
130 this._onDidChange.fire();
131 }
132 > })); chatModes.ts
133 > }
134
135 get builtin(): readonly IChatMode[] {
150
151 waitForPendingUpdates(): Promise<void> {
152 > return this._pendingRefresh; chatModes.ts
153 > }
154
155 private loadCachedModes(): void {
156 > try { chatModes.ts
157 > const cachedCustomModes = this.storageService.getObject(this._storageKey, StorageScope.WORKSPACE);
158 > if (cachedCustomModes) {
159 this.deserializeCachedModes(cachedCustomModes);
160 }
161 > } catch (error) { chatModes.ts
162 this.logService.error(error, 'Failed to load cached custom agents');
163 }
164 > } chatModes.ts
165
166 private deserializeCachedModes(cachedCustomModes: unknown): void {
216
217 private triggerRefresh(): Promise<void> {
218 > this._refreshCancellationSource?.cancel(); chatModes.ts
219 > this._refreshCancellationSource?.dispose();
220 > const refreshCancellationSource = this._refreshCancellationSource = new CancellationTokenSource();
221 > return this._refreshThrottler.trigger(async () => {
222 > try {
223 > await this.refreshCustomPromptModes(refreshCancellationSource.token);
224 > } finally {
225 > if (this._refreshCancellationSource === refreshCancellationSource) {
226 > this._refreshCancellationSource = undefined;
227 > }
228 > refreshCancellationSource.dispose();
229 > }
230 > });
231 > }
232
233 override dispose(): void {
234 > this._refreshCancellationSource?.cancel(); chatModes.ts
235 > this._refreshCancellationSource?.dispose();
236 > this._refreshCancellationSource = undefined;
237 > super.dispose();
238 > }
239
240 private async refreshCustomPromptModes(token: CancellationToken): Promise<void> {
241 > let hasChanges = false; chatModes.ts
242 > try {
243 > if (token.isCancellationRequested) {
244 return;
245 }
246 > const customModes = await this.customizationHarnessService.getCustomAgents(this.sessionResource, token); chatModes.ts
247 > if (token.isCancellationRequested) {
248 return;
249 }
250 > chatModes.ts
251 > // Create a new set of mode instances, reusing existing ones where possible
252 > const seenUris = new Set<string>();
253 > for (const customMode of customModes) {
254 if (!customMode.visibility.userInvocable || !customMode.enabled) {
255 continue;
272 }
273 }
274 > chatModes.ts
275 > // Clean up instances for modes that no longer exist
276 > for (const [uriString] of this._customModeInstances.entries()) {
277 if (!seenUris.has(uriString)) {
278 this._customModeInstances.delete(uriString);
280 }
281 }
282 > chatModes.ts
283 > this.hasCustomModes.set(this._customModeInstances.size > 0);
284 > } catch (error) {
285 if (isCancellationError(error)) {
286 return;
291 hasChanges = true;
292 }
293 > if (hasChanges) { chatModes.ts
294 this._onDidChange.fire();
295 }
296 > } chatModes.ts
297
298 private getBuiltinModes(): IChatMode[] {
329
330 constructor(
331 > @IInstantiationService private readonly instantiationService: IInstantiationService, chatModes.ts
332 > @IContextKeyService contextKeyService: IContextKeyService,
333 > @IConfigurationService private readonly configurationService: IConfigurationService,
334 > ) {
335 > super();
336 >
337 > this.agentModeDisabledByPolicy = ChatContextKeys.Modes.agentModeDisabledByPolicy.bindTo(contextKeyService);
338 >
339 > // Initialize the policy context key
340 > this.updateAgentModePolicyContextKey();
341 >
342 > // Listen for configuration changes that affect agent mode policy
343 > this._register(this.configurationService.onDidChangeConfiguration(e => {
344 if (e.affectsConfiguration(ChatConfiguration.AgentEnabled)) {
345 this.updateAgentModePolicyContextKey();
346 }
347 > })); chatModes.ts
348 > }
349
350 createModes(sessionResource: URI): IChatModes & IDisposable {
351 > return this.instantiationService.createInstance(ChatModes, sessionResource); chatModes.ts
352 > }
353
354 async getLocalModes(): Promise<IChatModes> {
355 > if (!this.localMode) { chatModes.ts
356 > this.localMode = (async () => {
357 > const modes = this._register(this.createModes(LocalChatSessionUri.getNewSessionUri())); // we make up a new session. Local mdes fall back to the promptService and are not actually tied to the session, so it doesn't matter which one we use here.
358 > await modes.waitForPendingUpdates();
359 > return modes;
360 > })();
361 > }
362 > return this.localMode;
363 > }
364
365 private updateAgentModePolicyContextKey(): void {
366 > this.agentModeDisabledByPolicy.set(this.isAgentModeDisabledByPolicy()); chatModes.ts
367 > }
368
369 private isAgentModeDisabledByPolicy(): boolean {
370 > return this.configurationService.inspect<boolean>(ChatConfiguration.AgentEnabled).policyValue === false; chatModes.ts
371 > }
372 }
373