diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 1e5e325bf12..af61950f934 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1776,6 +1776,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I LanguageModelToolCallPart: extHostTypes.LanguageModelToolCallPart, LanguageModelError: extHostTypes.LanguageModelError, LanguageModelToolResult: extHostTypes.LanguageModelToolResult, + ExtendedLanguageModelToolResult: extHostTypes.ExtendedLanguageModelToolResult, LanguageModelChatToolMode: extHostTypes.LanguageModelChatToolMode, LanguageModelPromptTsxPart: extHostTypes.LanguageModelPromptTsxPart, NewSymbolName: extHostTypes.NewSymbolName, diff --git a/src/vs/workbench/api/common/extHostLanguageModelTools.ts b/src/vs/workbench/api/common/extHostLanguageModelTools.ts index b5ee1c0dc1c..57c38c0bd25 100644 --- a/src/vs/workbench/api/common/extHostLanguageModelTools.ts +++ b/src/vs/workbench/api/common/extHostLanguageModelTools.ts @@ -124,7 +124,7 @@ export class ExtHostLanguageModelTools implements ExtHostLanguageModelToolsShape throw new CancellationError(); } - return typeConvert.LanguageModelToolResult.from(extensionResult); + return typeConvert.LanguageModelToolResult.from(extensionResult, item.extension); } async $prepareToolInvocation(toolId: string, input: any, token: CancellationToken): Promise { diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index e0325f432f2..cde6b2dee05 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -59,6 +59,7 @@ import { LanguageModelTextPart, LanguageModelPromptTsxPart } from './extHostType import { MarshalledId } from '../../../base/common/marshallingIds.js'; import { IChatRequestDraft } from '../../contrib/chat/common/chatEditingService.js'; import { isWindows } from '../../../base/common/platform.js'; +import { checkProposedApiEnabled } from '../../services/extensions/common/extensions.js'; export namespace Command { @@ -2987,7 +2988,11 @@ export namespace LanguageModelToolResult { })); } - export function from(result: vscode.LanguageModelToolResult): IToolResult { + export function from(result: vscode.ExtendedLanguageModelToolResult, extension: IExtensionDescription): IToolResult { + if (result.toolResultMessage) { + checkProposedApiEnabled(extension, 'chatParticipantPrivate'); + } + return { content: result.content.map(item => { if (item instanceof types.LanguageModelTextPart) { @@ -3003,7 +3008,8 @@ export namespace LanguageModelToolResult { } else { throw new Error('Unknown LanguageModelToolResult part type'); } - }) + }), + toolResultMessage: MarkdownString.fromStrict(result.toolResultMessage) }; } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index a194ce57a64..826548dfdef 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4899,6 +4899,9 @@ export class LanguageModelToolResult { } } +export class ExtendedLanguageModelToolResult extends LanguageModelToolResult { +} + export enum LanguageModelChatToolMode { Auto = 1, Required = 2 diff --git a/src/vs/workbench/contrib/chat/browser/chatContentParts/chatToolInvocationPart.ts b/src/vs/workbench/contrib/chat/browser/chatContentParts/chatToolInvocationPart.ts index a863c4f1100..37bffeca2ca 100644 --- a/src/vs/workbench/contrib/chat/browser/chatContentParts/chatToolInvocationPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatContentParts/chatToolInvocationPart.ts @@ -125,7 +125,7 @@ class ChatToolInvocationSubPart extends Disposable { } if (toolInvocation.kind === 'toolInvocation' && !toolInvocation.isComplete) { - toolInvocation.isCompleteDeferred.p.then(() => this._onNeedsRerender.fire()); + toolInvocation.isCompletePromise.then(() => this._onNeedsRerender.fire()); } } } diff --git a/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts b/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts index 02389c3fc29..3792753099c 100644 --- a/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts +++ b/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts @@ -151,6 +151,7 @@ export class LanguageModelToolsService extends Disposable implements ILanguageMo let requestId: string | undefined; let store: DisposableStore | undefined; + let toolResult: IToolResult | undefined; try { if (dto.context) { store = new DisposableStore(); @@ -214,7 +215,7 @@ export class LanguageModelToolsService extends Disposable implements ILanguageMo throw new CancellationError(); } - const result = await tool.impl.invoke(dto, countTokens, token); + toolResult = await tool.impl.invoke(dto, countTokens, token); this._telemetryService.publicLog2( 'languageModelToolInvoked', { @@ -223,7 +224,7 @@ export class LanguageModelToolsService extends Disposable implements ILanguageMo toolId: tool.data.id, toolExtensionId: tool.data.extensionId?.value, }); - return result; + return toolResult; } catch (err) { const result = isCancellationError(err) ? 'userCancelled' : 'error'; this._telemetryService.publicLog2( @@ -236,7 +237,7 @@ export class LanguageModelToolsService extends Disposable implements ILanguageMo }); throw err; } finally { - toolInvocation?.isCompleteDeferred.complete(); + toolInvocation?.complete(toolResult); if (requestId && store) { this.cleanupCallDisposables(requestId, store); diff --git a/src/vs/workbench/contrib/chat/browser/media/chat.css b/src/vs/workbench/contrib/chat/browser/media/chat.css index f0148315808..38677d48d1b 100644 --- a/src/vs/workbench/contrib/chat/browser/media/chat.css +++ b/src/vs/workbench/contrib/chat/browser/media/chat.css @@ -1467,6 +1467,10 @@ have to be updated for changes to the rules above, or to support more deeply nes color: var(--vscode-descriptionForeground); font-size: 12px; margin: 0; + + code { + font-size: 11px; + } } } } diff --git a/src/vs/workbench/contrib/chat/common/chatProgressTypes/chatToolInvocation.ts b/src/vs/workbench/contrib/chat/common/chatProgressTypes/chatToolInvocation.ts index 2b216ac49bc..7389820780b 100644 --- a/src/vs/workbench/contrib/chat/common/chatProgressTypes/chatToolInvocation.ts +++ b/src/vs/workbench/contrib/chat/common/chatProgressTypes/chatToolInvocation.ts @@ -6,7 +6,7 @@ import { DeferredPromise } from '../../../../../base/common/async.js'; import { IMarkdownString } from '../../../../../base/common/htmlContent.js'; import { IChatToolInvocation, IChatToolInvocationSerialized } from '../chatService.js'; -import { IToolConfirmationMessages } from '../languageModelToolsService.js'; +import { IToolConfirmationMessages, IToolResult } from '../languageModelToolsService.js'; export class ChatToolInvocation implements IChatToolInvocation { public readonly kind: 'toolInvocation' = 'toolInvocation'; @@ -17,13 +17,8 @@ export class ChatToolInvocation implements IChatToolInvocation { } private _isCompleteDeferred = new DeferredPromise(); - public get isCompleteDeferred(): DeferredPromise { - return this._isCompleteDeferred; - } - - private _isCanceled: boolean | undefined; - public get isCanceled(): boolean | undefined { - return this._isCanceled; + public get isCompletePromise(): Promise { + return this._isCompleteDeferred.p; } private _confirmDeferred = new DeferredPromise(); @@ -38,7 +33,7 @@ export class ChatToolInvocation implements IChatToolInvocation { constructor( public readonly invocationMessage: string | IMarkdownString, - public readonly pastTenseMessage: string | IMarkdownString | undefined, + public pastTenseMessage: string | IMarkdownString | undefined, public readonly tooltip: string | IMarkdownString | undefined, private _confirmationMessages: IToolConfirmationMessages | undefined) { if (!_confirmationMessages) { @@ -57,6 +52,14 @@ export class ChatToolInvocation implements IChatToolInvocation { }); } + public complete(result: IToolResult | undefined): void { + if (result?.toolResultMessage) { + this.pastTenseMessage = result.toolResultMessage; + } + + this._isCompleteDeferred.complete(); + } + public get confirmationMessages(): IToolConfirmationMessages | undefined { return this._confirmationMessages; } diff --git a/src/vs/workbench/contrib/chat/common/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService.ts index 6788a38ec4d..127cae67f19 100644 --- a/src/vs/workbench/contrib/chat/common/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService.ts @@ -20,7 +20,7 @@ import { ChatModel, IChatModel, IChatRequestModel, IChatRequestVariableData, ICh import { IParsedChatRequest } from './chatParserTypes.js'; import { IChatParserContext } from './chatRequestParser.js'; import { IChatRequestVariableValue } from './chatVariables.js'; -import { IToolConfirmationMessages } from './languageModelToolsService.js'; +import { IToolConfirmationMessages, IToolResult } from './languageModelToolsService.js'; export interface IChatRequest { message: string; @@ -200,8 +200,9 @@ export interface IChatToolInvocation { pastTenseMessage: string | IMarkdownString | undefined; tooltip: string | IMarkdownString | undefined; + isCompletePromise: Promise; isComplete: boolean; - isCompleteDeferred: DeferredPromise; + complete(result: IToolResult): void; kind: 'toolInvocation'; } diff --git a/src/vs/workbench/contrib/chat/common/languageModelToolsService.ts b/src/vs/workbench/contrib/chat/common/languageModelToolsService.ts index 2e48c18bf08..16e0cfd5c40 100644 --- a/src/vs/workbench/contrib/chat/common/languageModelToolsService.ts +++ b/src/vs/workbench/contrib/chat/common/languageModelToolsService.ts @@ -47,6 +47,7 @@ export function isToolInvocationContext(obj: any): obj is IToolInvocationContext export interface IToolResult { content: (IToolResultPromptTsxPart | IToolResultTextPart)[]; + toolResultMessage?: string | IMarkdownString; } export interface IToolResultPromptTsxPart { diff --git a/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts b/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts index 37ff3a27ab5..9326b93f9ce 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts @@ -123,6 +123,10 @@ declare module 'vscode' { tooltip?: string | MarkdownString; } + export class ExtendedLanguageModelToolResult extends LanguageModelToolResult { + toolResultMessage?: string | MarkdownString; + } + // #region Chat participant detection export interface ChatParticipantMetadata {