Skip to content

Commit aeabf14

Browse files
authored
Unselected servers/tools in agent mode are not restored (microsoft#254004)
1 parent 39ca06b commit aeabf14

File tree

1 file changed

+37
-59
lines changed

1 file changed

+37
-59
lines changed

src/vs/workbench/contrib/chat/browser/chatSelectedTools.ts

Lines changed: 37 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import { CancellationToken } from '../../../../base/common/cancellation.js';
77
import { Disposable } from '../../../../base/common/lifecycle.js';
88
import { derived, IObservable, observableFromEvent, ObservableMap } from '../../../../base/common/observable.js';
9-
import { isObject } from '../../../../base/common/types.js';
109
import { URI } from '../../../../base/common/uri.js';
1110
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
1211
import { ObservableMemento, observableMemento } from '../../../../platform/observable/common/observableMemento.js';
@@ -37,7 +36,7 @@ export enum ToolsScope {
3736

3837
export class ChatSelectedTools extends Disposable {
3938

40-
private readonly _selectedTools: ObservableMemento<IToolAndToolSetEnablementMap>;
39+
private readonly _selectedTools: ObservableMemento<StoredData>;
4140

4241
private readonly _sessionStates = new ObservableMap<string, IToolAndToolSetEnablementMap | undefined>();
4342

@@ -64,48 +63,8 @@ export class ChatSelectedTools extends Disposable {
6463
) {
6564
super();
6665

67-
const storedTools = observableMemento<IToolAndToolSetEnablementMap>({
68-
defaultValue: new Map(),
69-
toStorage: (value) => {
70-
const data = {
71-
disabledToolSets: [] as string[],
72-
disabledTools: [] as string[],
73-
};
74-
for (const [item, enabled] of value) {
75-
if (!enabled) {
76-
if (item instanceof ToolSet) {
77-
data.disabledToolSets.push(item.id);
78-
} else {
79-
data.disabledTools.push(item.id);
80-
}
81-
}
82-
}
83-
return JSON.stringify(data);
84-
},
85-
fromStorage: (value) => {
86-
const obj = JSON.parse(value) as StoredData;
87-
const map = new Map<IToolData | ToolSet, boolean>();
88-
if (!obj || !isObject(obj)) {
89-
return map;
90-
}
91-
if (Array.isArray(obj.disabledToolSets)) {
92-
for (const toolSetId of obj.disabledToolSets) {
93-
const toolset = this._toolsService.getToolSet(toolSetId);
94-
if (toolset) {
95-
map.set(toolset, false);
96-
}
97-
}
98-
}
99-
if (Array.isArray(obj.disabledTools)) {
100-
for (const toolId of obj.disabledTools) {
101-
const tool = this._toolsService.getTool(toolId);
102-
if (tool) {
103-
map.set(tool, false);
104-
}
105-
}
106-
}
107-
return map;
108-
},
66+
const storedTools = observableMemento<StoredData>({
67+
defaultValue: { disabledToolSets: [], disabledTools: [] },
10968
key: 'chat/selectedTools',
11069
});
11170

@@ -119,27 +78,36 @@ export class ChatSelectedTools extends Disposable {
11978
*/
12079
get entriesMap(): IObservable<IToolAndToolSetEnablementMap> {
12180
return derived(r => {
81+
const map = new Map<IToolData | ToolSet, boolean>();
82+
12283
const currentMode = this._mode.read(r);
12384

12485
let currentMap = this._sessionStates.get(currentMode.id);
125-
let defaultEnablement = false;
12686
if (!currentMap && currentMode.kind === ChatModeKind.Agent && currentMode.customTools) {
12787
currentMap = this._toolsService.toToolAndToolSetEnablementMap(currentMode.customTools.read(r));
12888
}
129-
if (!currentMap) {
130-
currentMap = this._selectedTools.read(r);
131-
defaultEnablement = true;
132-
}
89+
if (currentMap) {
90+
for (const tool of this._allTools.read(r)) {
91+
if (tool.canBeReferencedInPrompt) {
92+
map.set(tool, currentMap.get(tool) === true); // false if not present
93+
}
94+
}
95+
for (const toolSet of this._toolsService.toolSets.read(r)) {
96+
map.set(toolSet, currentMap.get(toolSet) === true); // false if not present
97+
}
98+
} else {
99+
const currData = this._selectedTools.read(r);
100+
const disabledToolSets = new Set(currData.disabledToolSets ?? []);
101+
const disabledTools = new Set(currData.disabledTools ?? []);
133102

134-
// create a complete map of all tools and tool sets
135-
const map = new Map<IToolData | ToolSet, boolean>();
136-
const tools = this._allTools.read(r).filter(t => t.canBeReferencedInPrompt);
137-
for (const tool of tools) {
138-
map.set(tool, currentMap.get(tool) ?? defaultEnablement);
139-
}
140-
const toolSets = this._toolsService.toolSets.read(r);
141-
for (const toolSet of toolSets) {
142-
map.set(toolSet, currentMap.get(toolSet) ?? defaultEnablement);
103+
for (const tool of this._allTools.read(r)) {
104+
if (tool.canBeReferencedInPrompt) {
105+
map.set(tool, !disabledTools.has(tool.id));
106+
}
107+
}
108+
for (const toolSet of this._toolsService.toolSets.read(r)) {
109+
map.set(toolSet, !disabledToolSets.has(toolSet.id));
110+
}
143111
}
144112
return map;
145113
});
@@ -180,7 +148,17 @@ export class ChatSelectedTools extends Disposable {
180148
this.updateCustomModeTools(mode.uri.get(), enablementMap);
181149
return;
182150
}
183-
this._selectedTools.set(enablementMap, undefined);
151+
const storedData = { disabledToolSets: [] as string[], disabledTools: [] as string[] };
152+
for (const [item, enabled] of enablementMap) {
153+
if (!enabled) {
154+
if (item instanceof ToolSet) {
155+
storedData.disabledToolSets.push(item.id);
156+
} else {
157+
storedData.disabledTools.push(item.id);
158+
}
159+
}
160+
}
161+
this._selectedTools.set(storedData, undefined);
184162
}
185163

186164
async updateCustomModeTools(uri: URI, enablementMap: IToolAndToolSetEnablementMap): Promise<void> {

0 commit comments

Comments
 (0)