Skip to content

Commit 3576d74

Browse files
authored
tools: simplify virtual tool enablement (#396)
Make the virtual tool setting configure the threshold value, and unify EXP behind it.
1 parent 22d5ee4 commit 3576d74

File tree

8 files changed

+32
-34
lines changed

8 files changed

+32
-34
lines changed

package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,13 +2669,15 @@
26692669
],
26702670
"description": "%github.copilot.config.summarizeAgentConversationHistory.enabled%"
26712671
},
2672-
"github.copilot.chat.virtualTools.enabled": {
2673-
"type": "boolean",
2674-
"default": false,
2672+
"github.copilot.chat.virtualTools.threshold": {
2673+
"type": "number",
2674+
"minimum": 0,
2675+
"maximum": 128,
2676+
"default": 128,
26752677
"tags": [
26762678
"experimental"
26772679
],
2678-
"description": "%github.copilot.config.virtualTools.enabled%"
2680+
"markdownDescription": "%github.copilot.config.virtualTools.threshold%"
26792681
},
26802682
"github.copilot.chat.azureModels": {
26812683
"type": "object",
@@ -3683,4 +3685,4 @@
36833685
"string_decoder": "npm:[email protected]",
36843686
"node-gyp": "npm:[email protected]"
36853687
}
3686-
}
3688+
}

package.nls.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
"github.copilot.config.agent.thinkingTool": "Enables the thinking tool that allows Copilot to think deeply about your request before generating a response in agent mode.",
134134
"github.copilot.config.setupTests.enabled": "Enables the `/setupTests` intent and prompting in `/tests` generation.",
135135
"github.copilot.config.byok.ollamaEndpoint": "The endpoint to use for the Ollama when accessed via bring your own key. Defaults to localhost.",
136-
"github.copilot.config.virtualTools.enabled": "Enables the virtual tools feature.",
136+
"github.copilot.config.virtualTools.threshold": "This setting defines the tool count over which virtual tools should be used. Virtual tools group similar sets of tools together and they allow the model to activate them on-demand. Certain tool groups will optimistically be pre-activated. We are actively developing this feature and you experience degraded tool calling once the threshold is hit.\n\nMay be set to `0` to disable virtual tools.",
137137
"github.copilot.command.fixTestFailure": "Fix Test Failure",
138138
"copilot.description": "Ask Copilot",
139139
"copilot.edits.description": "Edit files in your workspace",

src/extension/tools/common/virtualTools/toolGrouping.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,19 @@ import { ITelemetryService } from '../../../../platform/telemetry/common/telemet
1010
import { equals as arraysEqual } from '../../../../util/vs/base/common/arrays';
1111
import { CancellationToken } from '../../../../util/vs/base/common/cancellation';
1212
import { Iterable } from '../../../../util/vs/base/common/iterator';
13+
import { IObservable } from '../../../../util/vs/base/common/observableInternal';
1314
import { IInstantiationService } from '../../../../util/vs/platform/instantiation/common/instantiation';
1415
import { LanguageModelTextPart, LanguageModelToolResult } from '../../../../vscodeTypes';
1516
import { VIRTUAL_TOOL_NAME_PREFIX, VirtualTool } from './virtualTool';
1617
import { VirtualToolGrouper } from './virtualToolGrouper';
1718
import * as Constant from './virtualToolsConstants';
1819
import { IToolCategorization, IToolGrouping } from './virtualToolTypes';
1920

20-
export function computeToolGroupingMinThreshold(experimentationService: IExperimentationService, configurationService: IConfigurationService): number {
21-
let threshold = HARD_TOOL_LIMIT;
22-
23-
const override = experimentationService.getTreatmentVariable<number>('vscode', 'copilotchat.virtualToolThreshold');
24-
if (override) {
25-
threshold = override;
26-
} else if (configurationService.getExperimentBasedConfig(ConfigKey.VirtualTools, experimentationService)) {
27-
threshold = Constant.START_GROUPING_AFTER_TOOL_COUNT;
28-
}
29-
30-
return threshold;
21+
export function computeToolGroupingMinThreshold(experimentationService: IExperimentationService, configurationService: IConfigurationService): IObservable<number> {
22+
return configurationService.getExperimentBasedConfigObservable(ConfigKey.VirtualToolThreshold, experimentationService).map(configured => {
23+
const value = configured ?? HARD_TOOL_LIMIT;
24+
return value <= 0 ? Infinity : value;
25+
});
3126
}
3227

3328
export class ToolGrouping implements IToolGrouping {
@@ -51,7 +46,7 @@ export class ToolGrouping implements IToolGrouping {
5146
}
5247

5348
public get isEnabled() {
54-
return this._tools.length >= computeToolGroupingMinThreshold(this._experimentationService, this._configurationService);
49+
return this._tools.length >= computeToolGroupingMinThreshold(this._experimentationService, this._configurationService).get();
5550
}
5651

5752
constructor(

src/extension/tools/common/virtualTools/toolGroupingService.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,22 @@
66
import type { LanguageModelToolInformation } from 'vscode';
77
import { IConfigurationService } from '../../../../platform/configuration/common/configurationService';
88
import { IExperimentationService } from '../../../../platform/telemetry/common/nullExperimentationService';
9+
import { IObservable } from '../../../../util/vs/base/common/observableInternal';
910
import { IInstantiationService } from '../../../../util/vs/platform/instantiation/common/instantiation';
1011
import { computeToolGroupingMinThreshold, ToolGrouping } from './toolGrouping';
1112
import { IToolGrouping, IToolGroupingService } from './virtualToolTypes';
1213

1314
export class ToolGroupingService implements IToolGroupingService {
1415
declare readonly _serviceBrand: undefined;
1516

17+
public threshold: IObservable<number>;
18+
1619
constructor(
1720
@IInstantiationService private readonly _instantiationService: IInstantiationService,
18-
@IConfigurationService private readonly _configurationService: IConfigurationService,
19-
@IExperimentationService private readonly _experimentationService: IExperimentationService
20-
) { }
21-
22-
public get threshold() {
23-
return computeToolGroupingMinThreshold(this._experimentationService, this._configurationService);
21+
@IConfigurationService configurationService: IConfigurationService,
22+
@IExperimentationService experimentationService: IExperimentationService
23+
) {
24+
this.threshold = computeToolGroupingMinThreshold(experimentationService, configurationService);
2425
}
2526

2627
create(tools: readonly LanguageModelToolInformation[]): IToolGrouping {

src/extension/tools/common/virtualTools/virtualToolTypes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { LanguageModelToolInformation, LanguageModelToolResult } from 'vsco
77
import { createServiceIdentifier } from '../../../../util/common/services';
88
import { CancellationToken } from '../../../../util/vs/base/common/cancellation';
99
import { VirtualTool } from './virtualTool';
10+
import { IObservable } from '../../../../util/vs/base/common/observableInternal';
1011

1112
export interface IToolGrouping {
1213
/**
@@ -60,7 +61,7 @@ export interface IToolGroupingService {
6061
/**
6162
* The current tool count threshold for grouping to kick in.
6263
*/
63-
threshold: number;
64+
threshold: IObservable<number>;
6465
/**
6566
* Creates a tool grouping for a request, based on its conversation and the
6667
* initial set of tools.

src/extension/tools/vscode-node/tools.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
import * as vscode from 'vscode';
77
import { Disposable } from '../../../util/vs/base/common/lifecycle';
8+
import { autorun } from '../../../util/vs/base/common/observableInternal';
89
import { getContributedToolName } from '../common/toolNames';
910
import { IToolsService } from '../common/toolsService';
10-
11-
import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService';
1211
import { IToolGroupingCache, IToolGroupingService } from '../common/virtualTools/virtualToolTypes';
12+
1313
import '../node/allTools';
1414
import './allTools';
1515

@@ -18,7 +18,6 @@ export class ToolsContribution extends Disposable {
1818
@IToolsService toolsService: IToolsService,
1919
@IToolGroupingCache toolGrouping: IToolGroupingCache,
2020
@IToolGroupingService toolGroupingService: IToolGroupingService,
21-
@IExperimentationService experimentationService: IExperimentationService
2221
) {
2322
super();
2423

@@ -31,8 +30,8 @@ export class ToolsContribution extends Disposable {
3130
vscode.window.showInformationMessage('Tool groups have been reset. They will be regenerated on the next agent request.');
3231
}));
3332

34-
experimentationService.initializePromise.then(() => {
35-
vscode.commands.executeCommand('setContext', 'chat.toolGroupingThreshold', toolGroupingService.threshold);
36-
});
33+
this._register(autorun(reader => {
34+
vscode.commands.executeCommand('setContext', 'chat.toolGroupingThreshold', toolGroupingService.threshold.read(reader));
35+
}));
3736
}
3837
}

src/platform/configuration/common/configurationService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ export namespace ConfigKey {
767767
export const NewWorkspaceCreationAgentEnabled = defineSetting<boolean>('chat.newWorkspaceCreation.enabled', true);
768768
export const NewWorkspaceUseContext7 = defineSetting<boolean>('chat.newWorkspace.useContext7', false);
769769
export const SummarizeAgentConversationHistory = defineExpSetting<boolean>('chat.summarizeAgentConversationHistory.enabled', true);
770-
export const VirtualTools = defineExpSetting<boolean>('chat.virtualTools.enabled', false);
770+
export const VirtualToolThreshold = defineExpSetting<number>('chat.virtualTools.threshold', HARD_TOOL_LIMIT);
771771
export const CurrentEditorAgentContext = defineSetting<boolean>('chat.agent.currentEditorContext.enabled', true);
772772
/** BYOK */
773773
export const OllamaEndpoint = defineSetting<string>('chat.byok.ollamaEndpoint', 'http://localhost:11434');

test/base/extHostContext/simulationExtHostToolsService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import { ToolsContribution } from '../../../src/extension/tools/vscode-node/tool
1414
import { ToolsService } from '../../../src/extension/tools/vscode-node/toolsService';
1515
import { packageJson } from '../../../src/platform/env/common/packagejson';
1616
import { ILogService } from '../../../src/platform/log/common/logService';
17-
import { NullExperimentationService } from '../../../src/platform/telemetry/common/nullExperimentationService';
1817
import { raceTimeout } from '../../../src/util/vs/base/common/async';
1918
import { CancellationError } from '../../../src/util/vs/base/common/errors';
2019
import { Iterable } from '../../../src/util/vs/base/common/iterator';
20+
import { observableValue } from '../../../src/util/vs/base/common/observableInternal';
2121
import { IInstantiationService } from '../../../src/util/vs/platform/instantiation/common/instantiation';
2222
import { logger } from '../../simulationLogger';
2323

@@ -64,7 +64,7 @@ export class SimulationExtHostToolsService extends BaseToolsService implements I
6464
}
6565

6666
private ensureToolsRegistered() {
67-
this._lmToolRegistration ??= new ToolsContribution(this, {} as any, { threshold: Infinity } as any, new NullExperimentationService());
67+
this._lmToolRegistration ??= new ToolsContribution(this, {} as any, { threshold: observableValue(this, 128) } as any);
6868
}
6969

7070
getCopilotTool(name: string): ICopilotTool<any> | undefined {

0 commit comments

Comments
 (0)