diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index c09e72566e7..b119a46852e 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1972,6 +1972,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I McpStdioServerDefinition: extHostTypes.McpStdioServerDefinition, McpStdioServerDefinition2: extHostTypes.McpStdioServerDefinition, McpToolAvailability: extHostTypes.McpToolAvailability, + McpToolInvocationContentData: extHostTypes.McpToolInvocationContentData, SettingsSearchResultKind: extHostTypes.SettingsSearchResultKind, }; }; diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 10f15a6c485..b09ba368f8f 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -2815,6 +2815,19 @@ export namespace ChatResponseMovePart { export namespace ChatToolInvocationPart { export function from(part: vscode.ChatToolInvocationPart): IChatToolInvocationSerialized { + // Check if toolSpecificData is ChatMcpToolInvocationData (has input and output) + // If so, convert to resultDetails for rendering via ChatInputOutputMarkdownProgressPart + let resultDetails: IToolResultInputOutputDetails | undefined; + let toolSpecificData: any; + + if (part.toolSpecificData && isChatMcpToolInvocationData(part.toolSpecificData)) { + // Convert ChatMcpToolInvocationData to IToolResultInputOutputDetails + resultDetails = convertMcpToResultDetails(part.toolSpecificData, part.isError); + toolSpecificData = undefined; // MCP data goes to resultDetails, not toolSpecificData + } else { + toolSpecificData = part.toolSpecificData ? convertToolSpecificData(part.toolSpecificData) : undefined; + } + // Convert extension API ChatToolInvocationPart to internal serialized format return { kind: 'toolInvocationSerialized', @@ -2827,7 +2840,8 @@ export namespace ChatToolInvocationPart { isComplete: part.isComplete ?? true, source: ToolDataSource.External, // isError: part.isError ?? false, - toolSpecificData: part.toolSpecificData ? convertToolSpecificData(part.toolSpecificData) : undefined, + toolSpecificData, + resultDetails, presentation: part.presentation === 'hidden' ? ToolInvocationPresentation.Hidden : part.presentation === 'hiddenAfterComplete' @@ -2837,6 +2851,28 @@ export namespace ChatToolInvocationPart { }; } + function isChatMcpToolInvocationData(data: any): data is vscode.ChatMcpToolInvocationData { + return data !== null && typeof data === 'object' && + 'input' in data && typeof data.input === 'string' && + 'output' in data && Array.isArray(data.output); + } + + function convertMcpToResultDetails(data: vscode.ChatMcpToolInvocationData, isError?: boolean): IToolResultInputOutputDetails { + return { + input: data.input, + output: data.output.map((o) => { + const isText = o.mimeType.startsWith('text/'); + return { + type: 'embed' as const, + mimeType: o.mimeType, + value: isText ? VSBuffer.wrap(o.data).toString() : encodeBase64(VSBuffer.wrap(o.data)), + isText: isText, + }; + }), + isError: isError ?? false, + }; + } + function convertToolSpecificData(data: any): any { // Convert extension API terminal tool data to internal format if ('command' in data && 'language' in data) { diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index c142462a992..86ea71b91c8 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3166,6 +3166,15 @@ export class ChatResponseMultiDiffPart { } } +export class McpToolInvocationContentData { + mimeType: string; + data: Uint8Array; + constructor(data: Uint8Array, mimeType: string) { + this.data = data; + this.mimeType = mimeType; + } +} + export class ChatResponseExternalEditPart { applied: Thenable; didGetApplied!: (value: string) => void; diff --git a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts index 89da67be3e1..25457624e2c 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts @@ -120,6 +120,30 @@ declare module 'vscode' { language: string; } + export class McpToolInvocationContentData { + /** + * The mime type which determines how the data property is interpreted. + */ + mimeType: string; + + /** + * The byte data for this part. + */ + data: Uint8Array; + + /** + * Construct a generic data part with the given content. + * @param data The byte data for this part. + * @param mimeType The mime type of the data. + */ + constructor(data: Uint8Array, mimeType: string); + } + + export interface ChatMcpToolInvocationData { + input: string; + output: McpToolInvocationContentData[]; + } + export class ChatToolInvocationPart { toolName: string; toolCallId: string; @@ -129,7 +153,7 @@ declare module 'vscode' { pastTenseMessage?: string | MarkdownString; isConfirmed?: boolean; isComplete?: boolean; - toolSpecificData?: ChatTerminalToolInvocationData; + toolSpecificData?: ChatTerminalToolInvocationData | ChatMcpToolInvocationData; subAgentInvocationId?: string; presentation?: 'hidden' | 'hiddenAfterComplete' | undefined;