Skip to content

Commit d6b3b49

Browse files
authored
chat: fix 'server options' button showing for non-mcp servers (microsoft#261128)
Closes microsoft#260818
1 parent f4c18a6 commit d6b3b49

File tree

10 files changed

+42
-23
lines changed

10 files changed

+42
-23
lines changed

src/vs/workbench/contrib/chat/browser/chatContentParts/chatConfirmationWidget.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export interface IChatConfirmationWidgetOptions {
4141
title: string | IMarkdownString;
4242
subtitle?: string | IMarkdownString;
4343
buttons: IChatConfirmationButton[];
44-
toolbarData?: { arg: any; partType: string };
44+
toolbarData?: { arg: any; partType: string; partSource?: string };
4545
}
4646

4747
export class ChatQueryTitlePart extends Disposable {
@@ -209,7 +209,10 @@ abstract class BaseChatConfirmationWidget extends Disposable {
209209

210210
// Create toolbar if actions are provided
211211
if (options?.toolbarData) {
212-
const overlay = contextKeyService.createOverlay([['chatConfirmationPartType', options.toolbarData.partType]]);
212+
const overlay = contextKeyService.createOverlay([
213+
['chatConfirmationPartType', options.toolbarData.partType],
214+
['chatConfirmationPartSource', options.toolbarData.partSource],
215+
]);
213216
const nestedInsta = this._register(instantiationService.createChild(new ServiceCollection([IContextKeyService, overlay])));
214217
this._register(nestedInsta.createInstance(
215218
MenuWorkbenchToolBar,

src/vs/workbench/contrib/chat/browser/chatContentParts/chatElicitationContentPart.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class ChatElicitationContentPart extends Disposable implements IChatConte
3131
{ label: elicitation.acceptButtonLabel, data: true },
3232
{ label: elicitation.rejectButtonLabel, data: false, isSecondary: true },
3333
];
34-
const confirmationWidget = this._register(this.instantiationService.createInstance(ChatConfirmationWidget, context.container, { title: elicitation.title, subtitle: elicitation.subtitle, buttons, message: this.getMessageToRender(elicitation), toolbarData: { partType: elicitation.source ? `${elicitation.source.type}Elicitation` : 'elicitation', arg: elicitation } }));
34+
const confirmationWidget = this._register(this.instantiationService.createInstance(ChatConfirmationWidget, context.container, { title: elicitation.title, subtitle: elicitation.subtitle, buttons, message: this.getMessageToRender(elicitation), toolbarData: { partType: 'elicitation', partSource: elicitation.source?.type, arg: elicitation } }));
3535
confirmationWidget.setShowButtons(elicitation.state === 'pending');
3636

3737
this._register(elicitation.onDidRequestHide(() => this.domNode.remove()));

src/vs/workbench/contrib/chat/browser/chatContentParts/toolInvocationParts/chatToolConfirmationSubPart.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export class ToolConfirmationSubPart extends BaseChatToolInvocationSubPart {
109109
confirmWidget = this._register(this.instantiationService.createInstance(
110110
ChatConfirmationWidget,
111111
this.context.container,
112-
{ title, subtitle: toolInvocation.originMessage, buttons, message, toolbarData: { arg: toolInvocation, partType: 'chatToolConfirmation' } }
112+
{ title, subtitle: toolInvocation.originMessage, buttons, message, toolbarData: { arg: toolInvocation, partType: 'chatToolConfirmation', partSource: toolInvocation.source.type } }
113113
));
114114
} else {
115115
const codeBlockRenderOptions: ICodeBlockRenderOptions = {
@@ -275,7 +275,7 @@ export class ToolConfirmationSubPart extends BaseChatToolInvocationSubPart {
275275
confirmWidget = this._register(this.instantiationService.createInstance(
276276
ChatCustomConfirmationWidget,
277277
this.context.container,
278-
{ title, subtitle: toolInvocation.originMessage, buttons, message: elements.root, toolbarData: { arg: toolInvocation, partType: 'chatToolConfirmation' } },
278+
{ title, subtitle: toolInvocation.originMessage, buttons, message: elements.root, toolbarData: { arg: toolInvocation, partType: 'chatToolConfirmation', partSource: toolInvocation.source?.type } },
279279
));
280280
}
281281

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Emitter } from '../../../../base/common/event.js';
77
import { IMarkdownString } from '../../../../base/common/htmlContent.js';
88
import { Disposable } from '../../../../base/common/lifecycle.js';
99
import { IChatElicitationRequest } from '../common/chatService.js';
10+
import { ToolDataSource } from '../common/languageModelToolsService.js';
1011

1112
export class ChatElicitationRequestPart extends Disposable implements IChatElicitationRequest {
1213
public readonly kind = 'elicitation';
@@ -24,7 +25,7 @@ export class ChatElicitationRequestPart extends Disposable implements IChatElici
2425
public readonly rejectButtonLabel: string,
2526
public readonly accept: () => Promise<void>,
2627
public readonly reject: () => Promise<void>,
27-
public readonly source?: { type: 'mcp'; definitionId: string },
28+
public readonly source?: ToolDataSource,
2829
) {
2930
super();
3031
}

src/vs/workbench/contrib/chat/common/chatProgressTypes/chatToolInvocation.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { IMarkdownString } from '../../../../../base/common/htmlContent.js';
99
import { observableValue } from '../../../../../base/common/observable.js';
1010
import { localize } from '../../../../../nls.js';
1111
import { IChatExtensionsContent, IChatToolInputInvocationData, IChatTodoListContent, IChatToolInvocation, IChatToolInvocationSerialized, type IChatTerminalToolInvocationData } from '../chatService.js';
12-
import { IPreparedToolInvocation, isToolResultOutputDetails, IToolConfirmationMessages, IToolData, IToolProgressStep, IToolResult } from '../languageModelToolsService.js';
12+
import { IPreparedToolInvocation, isToolResultOutputDetails, IToolConfirmationMessages, IToolData, IToolProgressStep, IToolResult, ToolDataSource } from '../languageModelToolsService.js';
1313

1414
export class ChatToolInvocation implements IChatToolInvocation {
1515
public readonly kind: 'toolInvocation' = 'toolInvocation';
@@ -45,6 +45,7 @@ export class ChatToolInvocation implements IChatToolInvocation {
4545
private _confirmationMessages: IToolConfirmationMessages | undefined;
4646
public readonly presentation: IPreparedToolInvocation['presentation'];
4747
public readonly toolId: string;
48+
public readonly source: ToolDataSource;
4849

4950
public readonly toolSpecificData?: IChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatTodoListContent;
5051

@@ -60,6 +61,7 @@ export class ChatToolInvocation implements IChatToolInvocation {
6061
this.presentation = preparedInvocation?.presentation;
6162
this.toolSpecificData = preparedInvocation?.toolSpecificData;
6263
this.toolId = toolData.id;
64+
this.source = toolData.source;
6365

6466
if (!this._confirmationMessages) {
6567
// No confirmation needed
@@ -107,6 +109,7 @@ export class ChatToolInvocation implements IChatToolInvocation {
107109
originMessage: this.originMessage,
108110
isConfirmed: this._isConfirmed,
109111
isComplete: this._isComplete,
112+
source: this.source,
110113
resultDetails: isToolResultOutputDetails(this._resultDetails)
111114
? { output: { type: 'data', mimeType: this._resultDetails.output.mimeType, base64Data: encodeBase64(this._resultDetails.output.value) } }
112115
: this._resultDetails,

src/vs/workbench/contrib/chat/common/chatService.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { IChatParserContext } from './chatRequestParser.js';
2424
import { IChatRequestVariableEntry } from './chatVariableEntries.js';
2525
import { IChatRequestVariableValue } from './chatVariables.js';
2626
import { ChatAgentLocation, ChatModeKind } from './constants.js';
27-
import { IPreparedToolInvocation, IToolConfirmationMessages, IToolResult, IToolResultInputOutputDetails } from './languageModelToolsService.js';
27+
import { IPreparedToolInvocation, IToolConfirmationMessages, IToolResult, IToolResultInputOutputDetails, ToolDataSource } from './languageModelToolsService.js';
2828

2929
export interface IChatRequest {
3030
message: string;
@@ -263,7 +263,7 @@ export interface IChatElicitationRequest {
263263
acceptButtonLabel: string;
264264
rejectButtonLabel: string;
265265
subtitle?: string | IMarkdownString;
266-
source?: { type: 'mcp'; definitionId: string };
266+
source?: ToolDataSource;
267267
state: 'pending' | 'accepted' | 'rejected';
268268
acceptedResult?: Record<string, unknown>;
269269
accept(): Promise<void>;
@@ -319,6 +319,7 @@ export interface IChatToolInvocation {
319319
invocationMessage: string | IMarkdownString;
320320
pastTenseMessage: string | IMarkdownString | undefined;
321321
resultDetails: IToolResult['toolResultDetails'];
322+
source: ToolDataSource;
322323
progress: IObservable<{ message?: string | IMarkdownString; progress: number }>;
323324
readonly toolId: string;
324325
readonly toolCallId: string;
@@ -351,6 +352,7 @@ export interface IChatToolInvocationSerialized {
351352
isComplete: boolean;
352353
toolCallId: string;
353354
toolId: string;
355+
source: ToolDataSource;
354356
kind: 'toolInvocationSerialized';
355357
}
356358

src/vs/workbench/contrib/mcp/browser/mcpCommands.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,12 @@ export class McpConfirmationServerOptionsCommand extends Action2 {
174174
f1: false,
175175
menu: [{
176176
id: MenuId.ChatConfirmationMenu,
177-
when: ContextKeyExpr.or(
178-
ContextKeyExpr.equals('chatConfirmationPartType', 'chatToolConfirmation'),
179-
ContextKeyExpr.equals('chatConfirmationPartType', 'mcpElicitation'),
177+
when: ContextKeyExpr.and(
178+
ContextKeyExpr.equals('chatConfirmationPartSource', 'mcp'),
179+
ContextKeyExpr.or(
180+
ContextKeyExpr.equals('chatConfirmationPartType', 'chatToolConfirmation'),
181+
ContextKeyExpr.equals('chatConfirmationPartType', 'elicitation'),
182+
),
180183
),
181184
group: 'navigation'
182185
}],
@@ -191,7 +194,7 @@ export class McpConfirmationServerOptionsCommand extends Action2 {
191194
accessor.get(ICommandService).executeCommand(McpCommandIds.ServerOptions, tool.source.definitionId);
192195
}
193196
} else if (arg.kind === 'elicitation') {
194-
if (arg.source) {
197+
if (arg.source?.type === 'mcp') {
195198
accessor.get(ICommandService).executeCommand(McpCommandIds.ServerOptions, arg.source.definitionId);
196199
}
197200
} else {

src/vs/workbench/contrib/mcp/browser/mcpElicitationService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ChatElicitationRequestPart } from '../../chat/browser/chatElicitationRe
1414
import { ChatModel } from '../../chat/common/chatModel.js';
1515
import { IChatService } from '../../chat/common/chatService.js';
1616
import { IMcpElicitationService, IMcpServer, IMcpToolCallContext } from '../common/mcpTypes.js';
17+
import { mcpServerToSourceData } from '../common/mcpTypesUtils.js';
1718
import { MCP } from '../common/modelContextProtocol.js';
1819

1920
const noneItem: IQuickPickItem = { id: undefined, label: localize('mcp.elicit.enum.none', 'None'), description: localize('mcp.elicit.enum.none.description', 'No selection'), alwaysShow: true };
@@ -52,7 +53,7 @@ export class McpElicitationService implements IMcpElicitationService {
5253
part.state = 'rejected';
5354
return Promise.resolve();
5455
},
55-
{ type: 'mcp', definitionId: server.definition.id },
56+
mcpServerToSourceData(server),
5657
);
5758
chatModel.acceptResponseProgress(request, part);
5859
}

src/vs/workbench/contrib/mcp/common/mcpLanguageModelToolContribution.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { ChatResponseResource, getAttachableImageExtension } from '../../chat/co
2525
import { CountTokensCallback, ILanguageModelToolsService, IPreparedToolInvocation, IToolData, IToolImpl, IToolInvocation, IToolInvocationPreparationContext, IToolResult, IToolResultInputOutputDetails, ToolDataSource, ToolProgress, ToolSet } from '../../chat/common/languageModelToolsService.js';
2626
import { IMcpRegistry } from './mcpRegistryTypes.js';
2727
import { IMcpServer, IMcpService, IMcpTool, LazyCollectionState, McpResourceURI, McpServerCacheState } from './mcpTypes.js';
28+
import { mcpServerToSourceData } from './mcpTypesUtils.js';
2829

2930
interface ISyncedToolData {
3031
toolData: IToolData;
@@ -65,15 +66,7 @@ export class McpLanguageModelToolContribution extends Disposable implements IWor
6566

6667
const store = new DisposableStore();
6768
const toolSet = new Lazy(() => {
68-
const metadata = server.serverMetadata.get();
69-
const source: ToolDataSource = {
70-
type: 'mcp',
71-
serverLabel: metadata?.serverName,
72-
instructions: metadata?.serverInstructions,
73-
label: server.definition.label,
74-
collectionId: server.collection.id,
75-
definitionId: server.definition.id
76-
};
69+
const source = mcpServerToSourceData(server);
7770
const toolSet = store.add(this._toolsService.createToolSet(
7871
source,
7972
server.definition.id, server.definition.label,

src/vs/workbench/contrib/mcp/common/mcpTypesUtils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { CancellationToken } from '../../../../base/common/cancellation.js';
88
import { CancellationError } from '../../../../base/common/errors.js';
99
import { DisposableStore } from '../../../../base/common/lifecycle.js';
1010
import { autorun } from '../../../../base/common/observable.js';
11+
import { ToolDataSource } from '../../chat/common/languageModelToolsService.js';
1112
import { IMcpServer, IMcpServerStartOpts, IMcpService, McpConnectionState, McpServerCacheState } from './mcpTypes.js';
1213

1314
/**
@@ -72,3 +73,15 @@ export function startServerAndWaitForLiveTools(server: IMcpServer, opts?: IMcpSe
7273
});
7374
}).finally(() => store.dispose());
7475
}
76+
77+
export function mcpServerToSourceData(server: IMcpServer): ToolDataSource {
78+
const metadata = server.serverMetadata.get();
79+
return {
80+
type: 'mcp',
81+
serverLabel: metadata?.serverName,
82+
instructions: metadata?.serverInstructions,
83+
label: server.definition.label,
84+
collectionId: server.collection.id,
85+
definitionId: server.definition.id
86+
};
87+
}

0 commit comments

Comments
 (0)