mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-20 07:12:43 +01:00
chain of thought API (#259939)
* cot api and rendering * working progress streaminig * streaming working * collapsable thinking block * some better styling * fix merge conflict * some cleaned up styling, removing copilot css * label updates * some vibe coded timer work * fix anotha merge conflict * thinking part with timer better * render tools inside thinking container * render markdown in container * revert and remove majority ui changes * fix some merge conflicts * some cleanup * hygiene
This commit is contained in:
@@ -25,6 +25,7 @@ export const enum MarshalledId {
|
||||
ChatViewContext,
|
||||
LanguageModelToolResult,
|
||||
LanguageModelTextPart,
|
||||
LanguageModelThinkingPart,
|
||||
LanguageModelPromptTsxPart,
|
||||
LanguageModelDataPart,
|
||||
ChatSessionContext,
|
||||
|
||||
@@ -251,6 +251,10 @@ const _allApiProposals = {
|
||||
languageModelSystem: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.languageModelSystem.d.ts',
|
||||
},
|
||||
languageModelThinkingPart: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.languageModelThinkingPart.d.ts',
|
||||
version: 1
|
||||
},
|
||||
languageModelToolResultAudience: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.languageModelToolResultAudience.d.ts',
|
||||
},
|
||||
|
||||
@@ -1843,6 +1843,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
ChatResponseAnchorPart: extHostTypes.ChatResponseAnchorPart,
|
||||
ChatResponseProgressPart: extHostTypes.ChatResponseProgressPart,
|
||||
ChatResponseProgressPart2: extHostTypes.ChatResponseProgressPart2,
|
||||
ChatResponseThinkingProgressPart: extHostTypes.ChatResponseThinkingProgressPart,
|
||||
ChatResponseReferencePart: extHostTypes.ChatResponseReferencePart,
|
||||
ChatResponseReferencePart2: extHostTypes.ChatResponseReferencePart,
|
||||
ChatResponseCodeCitationPart: extHostTypes.ChatResponseCodeCitationPart,
|
||||
@@ -1880,6 +1881,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
LanguageModelPartAudience: extHostTypes.LanguageModelPartAudience,
|
||||
ToolResultAudience: extHostTypes.LanguageModelPartAudience, // back compat
|
||||
LanguageModelToolCallPart: extHostTypes.LanguageModelToolCallPart,
|
||||
LanguageModelThinkingPart: extHostTypes.LanguageModelThinkingPart,
|
||||
LanguageModelError: extHostTypes.LanguageModelError,
|
||||
LanguageModelToolResult: extHostTypes.LanguageModelToolResult,
|
||||
LanguageModelToolResult2: extHostTypes.LanguageModelToolResult2,
|
||||
|
||||
@@ -191,6 +191,14 @@ export class ChatAgentResponseStream {
|
||||
_report(dto, task);
|
||||
return this;
|
||||
},
|
||||
thinkingProgress(value, id?, metadata?) {
|
||||
throwIfDone(this.thinkingProgress);
|
||||
checkProposedApiEnabled(that._extension, 'chatParticipantAdditions');
|
||||
const part = new extHostTypes.ChatResponseThinkingProgressPart(value, id, metadata);
|
||||
const dto = typeConvert.ChatResponseThinkingProgressPart.from(part);
|
||||
_report(dto);
|
||||
return this;
|
||||
},
|
||||
warning(value) {
|
||||
throwIfDone(this.progress);
|
||||
checkProposedApiEnabled(that._extension, 'chatParticipantAdditions');
|
||||
@@ -296,6 +304,7 @@ export class ChatAgentResponseStream {
|
||||
part instanceof extHostTypes.ChatResponseCodeCitationPart ||
|
||||
part instanceof extHostTypes.ChatResponseMovePart ||
|
||||
part instanceof extHostTypes.ChatResponseExtensionsPart ||
|
||||
part instanceof extHostTypes.ChatResponseThinkingProgressPart ||
|
||||
part instanceof extHostTypes.ChatResponsePullRequestPart ||
|
||||
part instanceof extHostTypes.ChatResponseProgressPart2
|
||||
) {
|
||||
@@ -308,6 +317,9 @@ export class ChatAgentResponseStream {
|
||||
} else if (part instanceof extHostTypes.ChatResponseProgressPart2) {
|
||||
const dto = part.task ? typeConvert.ChatTask.from(part) : typeConvert.ChatResponseProgressPart.from(part);
|
||||
_report(dto, part.task);
|
||||
} else if (part instanceof extHostTypes.ChatResponseThinkingProgressPart) {
|
||||
const dto = typeConvert.ChatResponseThinkingProgressPart.from(part);
|
||||
_report(dto);
|
||||
} else if (part instanceof extHostTypes.ChatResponseAnchorPart) {
|
||||
const dto = typeConvert.ChatResponseAnchorPart.from(part);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ type LanguageModelProviderData = {
|
||||
readonly provider: vscode.LanguageModelChatProvider2;
|
||||
};
|
||||
|
||||
type LMResponsePart = vscode.LanguageModelTextPart | vscode.LanguageModelToolCallPart | vscode.LanguageModelDataPart;
|
||||
type LMResponsePart = vscode.LanguageModelTextPart | vscode.LanguageModelToolCallPart | vscode.LanguageModelDataPart | vscode.LanguageModelThinkingPart;
|
||||
|
||||
class LanguageModelResponseStream {
|
||||
|
||||
@@ -102,6 +102,9 @@ class LanguageModelResponse {
|
||||
let out: LMResponsePart;
|
||||
if (fragment.part.type === 'text') {
|
||||
out = new extHostTypes.LanguageModelTextPart(fragment.part.value, fragment.part.audience);
|
||||
} else if (fragment.part.type === 'thinking') {
|
||||
out = new extHostTypes.LanguageModelThinkingPart(fragment.part.value, fragment.part.id, fragment.part.metadata);
|
||||
|
||||
} else if (fragment.part.type === 'data') {
|
||||
out = new extHostTypes.LanguageModelDataPart(fragment.part.data.buffer, fragment.part.mimeType, fragment.part.audience);
|
||||
} else {
|
||||
@@ -301,6 +304,8 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
|
||||
part = { type: 'text', value: fragment.part.value, audience: fragment.part.audience };
|
||||
} else if (fragment.part instanceof extHostTypes.LanguageModelDataPart) {
|
||||
part = { type: 'data', mimeType: fragment.part.mimeType, data: VSBuffer.wrap(fragment.part.data), audience: fragment.part.audience };
|
||||
} else if (fragment.part instanceof extHostTypes.LanguageModelThinkingPart) {
|
||||
part = { type: 'thinking', value: fragment.part.value, id: fragment.part.id, metadata: fragment.part.metadata };
|
||||
}
|
||||
|
||||
if (!part) {
|
||||
|
||||
@@ -41,7 +41,7 @@ import { IViewBadge } from '../../common/views.js';
|
||||
import { IChatAgentRequest, IChatAgentResult } from '../../contrib/chat/common/chatAgents.js';
|
||||
import { IChatRequestDraft } from '../../contrib/chat/common/chatEditingService.js';
|
||||
import { IChatRequestVariableEntry, isImageVariableEntry } from '../../contrib/chat/common/chatVariableEntries.js';
|
||||
import { IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatMoveMessage, IChatMultiDiffData, IChatPrepareToolInvocationPart, IChatProgressMessage, IChatPullRequestContent, IChatResponseCodeblockUriPart, IChatTaskDto, IChatTaskResult, IChatTextEdit, IChatTreeData, IChatUserActionEvent, IChatWarningMessage } from '../../contrib/chat/common/chatService.js';
|
||||
import { IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatMoveMessage, IChatMultiDiffData, IChatPrepareToolInvocationPart, IChatProgressMessage, IChatPullRequestContent, IChatResponseCodeblockUriPart, IChatTaskDto, IChatTaskResult, IChatTextEdit, IChatThinkingPart, IChatTreeData, IChatUserActionEvent, IChatWarningMessage } from '../../contrib/chat/common/chatService.js';
|
||||
import { IToolResult, IToolResultInputOutputDetails, IToolResultOutputDetails, ToolDataSource } from '../../contrib/chat/common/languageModelToolsService.js';
|
||||
import * as chatProvider from '../../contrib/chat/common/languageModels.js';
|
||||
import { IChatMessageDataPart, IChatResponseDataPart, IChatResponsePromptTsxPart, IChatResponseTextPart } from '../../contrib/chat/common/languageModels.js';
|
||||
@@ -2699,6 +2699,20 @@ export namespace ChatResponseProgressPart {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace ChatResponseThinkingProgressPart {
|
||||
export function from(part: vscode.ChatResponseThinkingProgressPart): Dto<IChatThinkingPart> {
|
||||
return {
|
||||
kind: 'thinking',
|
||||
value: part.value,
|
||||
id: part.id,
|
||||
metadata: part.metadata
|
||||
};
|
||||
}
|
||||
export function to(part: Dto<IChatThinkingPart>): vscode.ChatResponseThinkingProgressPart {
|
||||
return new types.ChatResponseThinkingProgressPart(part.value);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace ChatResponseWarningPart {
|
||||
export function from(part: vscode.ChatResponseWarningPart): Dto<IChatWarningMessage> {
|
||||
return {
|
||||
@@ -2999,6 +3013,8 @@ export namespace ChatResponsePart {
|
||||
return ChatResponseReferencePart.from(part);
|
||||
} else if (part instanceof types.ChatResponseProgressPart) {
|
||||
return ChatResponseProgressPart.from(part);
|
||||
} else if (part instanceof types.ChatResponseThinkingProgressPart) {
|
||||
return ChatResponseThinkingProgressPart.from(part);
|
||||
} else if (part instanceof types.ChatResponseFileTreePart) {
|
||||
return ChatResponseFilesPart.from(part);
|
||||
} else if (part instanceof types.ChatResponseMultiDiffPart) {
|
||||
@@ -3260,7 +3276,9 @@ export namespace ChatAgentResult {
|
||||
if (value.$mid === MarshalledId.LanguageModelToolResult) {
|
||||
return new types.LanguageModelToolResult(cloneAndChange(value.content, reviveMetadata));
|
||||
} else if (value.$mid === MarshalledId.LanguageModelTextPart) {
|
||||
return new types.LanguageModelTextPart(value.value, value.audience);
|
||||
return new types.LanguageModelTextPart(value.value);
|
||||
} else if (value.$mid === MarshalledId.LanguageModelThinkingPart) {
|
||||
return new types.LanguageModelThinkingPart(value.value, value.id, value.metadata);
|
||||
} else if (value.$mid === MarshalledId.LanguageModelPromptTsxPart) {
|
||||
return new types.LanguageModelPromptTsxPart(value.value);
|
||||
}
|
||||
|
||||
@@ -4648,6 +4648,17 @@ export class ChatResponseProgressPart2 {
|
||||
}
|
||||
}
|
||||
|
||||
export class ChatResponseThinkingProgressPart {
|
||||
value: string;
|
||||
id?: string;
|
||||
metadata?: string;
|
||||
constructor(value: string, id?: string, metadata?: string) {
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
}
|
||||
|
||||
export class ChatResponseWarningPart {
|
||||
value: vscode.MarkdownString;
|
||||
constructor(value: string | vscode.MarkdownString) {
|
||||
@@ -5096,6 +5107,28 @@ export enum ChatImageMimeType {
|
||||
BMP = 'image/bmp',
|
||||
}
|
||||
|
||||
export class LanguageModelThinkingPart implements vscode.LanguageModelThinkingPart {
|
||||
value: string;
|
||||
id?: string;
|
||||
metadata?: string;
|
||||
|
||||
constructor(value: string, id?: string, metadata?: string) {
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
$mid: MarshalledId.LanguageModelThinkingPart,
|
||||
value: this.value,
|
||||
id: this.id,
|
||||
metadata: this.metadata,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class LanguageModelPromptTsxPart {
|
||||
value: unknown;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { $, clearNode } from '../../../../../base/browser/dom.js';
|
||||
import { Emitter } from '../../../../../base/common/event.js';
|
||||
import { Disposable } from '../../../../../base/common/lifecycle.js';
|
||||
import { IChatThinkingPart } from '../../common/chatService.js';
|
||||
import { IChatContentPartRenderContext, IChatContentPart } from './chatContentParts.js';
|
||||
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
|
||||
import { MarkdownString } from '../../../../../base/common/htmlContent.js';
|
||||
import { MarkdownRenderer, IMarkdownRenderResult } from '../../../../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js';
|
||||
|
||||
export class ChatThinkingContentPart extends Disposable implements IChatContentPart {
|
||||
readonly domNode: HTMLElement;
|
||||
public readonly codeblocks: undefined;
|
||||
public readonly codeblocksPartId: undefined;
|
||||
|
||||
private readonly _onDidChangeHeight = this._register(new Emitter<void>());
|
||||
readonly onDidChangeHeight = this._onDidChangeHeight.event;
|
||||
|
||||
private currentThinkingValue: string;
|
||||
private readonly renderer: MarkdownRenderer;
|
||||
private textContainer!: HTMLElement;
|
||||
private markdownResult: IMarkdownRenderResult | undefined;
|
||||
|
||||
constructor(
|
||||
content: IChatThinkingPart,
|
||||
_context: IChatContentPartRenderContext,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.renderer = instantiationService.createInstance(MarkdownRenderer, {});
|
||||
this.currentThinkingValue = this.parseContent(content.value || '');
|
||||
|
||||
this.domNode = $('.chat-thinking-box');
|
||||
this.domNode.tabIndex = 0;
|
||||
this.renderContent();
|
||||
}
|
||||
|
||||
private parseContent(content: string): string {
|
||||
// Remove <|im_sep|>**** and similar markers
|
||||
return content
|
||||
.replace(/<\|im_sep\|>\*{4,}/g, '')
|
||||
.replace(/<\|lim_sep\|>\*{4,}/g, '')
|
||||
.trim();
|
||||
}
|
||||
|
||||
private renderContent(): void {
|
||||
this.textContainer = $('.chat-thinking-text.markdown-content');
|
||||
this.domNode.appendChild(this.textContainer);
|
||||
|
||||
if (this.currentThinkingValue) {
|
||||
this.renderMarkdown(this.currentThinkingValue);
|
||||
}
|
||||
}
|
||||
|
||||
private renderMarkdown(content: string): void {
|
||||
if (this.markdownResult) {
|
||||
this.markdownResult.dispose();
|
||||
this.markdownResult = undefined;
|
||||
}
|
||||
|
||||
const cleanedContent = this.parseContent(content);
|
||||
if (!cleanedContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearNode(this.textContainer);
|
||||
this.markdownResult = this.renderer.render(new MarkdownString(cleanedContent));
|
||||
this.textContainer.appendChild(this.markdownResult.element);
|
||||
}
|
||||
|
||||
hasSameContent(other: any): boolean {
|
||||
if (other.kind !== 'thinking') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
if (this.markdownResult) {
|
||||
this.markdownResult.dispose();
|
||||
this.markdownResult = undefined;
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ import { IChatAgentMetadata } from '../common/chatAgents.js';
|
||||
import { ChatContextKeys } from '../common/chatContextKeys.js';
|
||||
import { IChatTextEditGroup } from '../common/chatModel.js';
|
||||
import { chatSubcommandLeader } from '../common/chatParserTypes.js';
|
||||
import { ChatAgentVoteDirection, ChatAgentVoteDownReason, ChatErrorLevel, IChatChangesSummary, IChatConfirmation, IChatContentReference, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatPullRequestContent, IChatMultiDiffData, IChatTask, IChatTaskSerialized, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop } from '../common/chatService.js';
|
||||
import { ChatAgentVoteDirection, ChatAgentVoteDownReason, ChatErrorLevel, IChatChangesSummary, IChatConfirmation, IChatContentReference, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatPullRequestContent, IChatMultiDiffData, IChatTask, IChatTaskSerialized, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop, IChatThinkingPart } from '../common/chatService.js';
|
||||
import { IChatChangesSummaryPart, IChatCodeCitations, IChatErrorDetailsPart, IChatReferences, IChatRendererContent, IChatRequestViewModel, IChatResponseViewModel, IChatViewModel, IChatWorkingProgress, isRequestVM, isResponseVM } from '../common/chatViewModel.js';
|
||||
import { getNWords } from '../common/chatWordCounter.js';
|
||||
import { CodeBlockModelCollection } from '../common/codeBlockModelCollection.js';
|
||||
@@ -86,6 +86,7 @@ import { alert } from '../../../../base/browser/ui/aria/aria.js';
|
||||
import { CodiconActionViewItem } from '../../notebook/browser/view/cellParts/cellActionView.js';
|
||||
import { ChatPullRequestContentPart } from './chatContentParts/chatPullRequestContentPart.js';
|
||||
import { ChatCheckpointFileChangesSummaryContentPart } from './chatContentParts/chatChangesSummaryPart.js';
|
||||
import { ChatThinkingContentPart } from './chatContentParts/chatThinkingContentPart.js';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
@@ -1144,6 +1145,8 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
||||
return this.renderChatErrorDetails(context, content, templateData);
|
||||
} else if (content.kind === 'elicitation') {
|
||||
return this.renderElicitation(context, content, templateData);
|
||||
} else if (content.kind === 'thinking') {
|
||||
return this.renderThinking(context, content, templateData);
|
||||
} else if (content.kind === 'changesSummary') {
|
||||
return this.renderChangesSummary(content, context, templateData);
|
||||
}
|
||||
@@ -1341,6 +1344,18 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
||||
return part;
|
||||
}
|
||||
|
||||
private renderThinking(context: IChatContentPartRenderContext, thinking: IChatThinkingPart, templateData: IChatListItemTemplate): IChatContentPart {
|
||||
const thinkingPart = templateData.instantiationService.createInstance(
|
||||
ChatThinkingContentPart,
|
||||
thinking,
|
||||
context
|
||||
);
|
||||
|
||||
thinkingPart.domNode.classList.add('chat-thinking-part');
|
||||
|
||||
return thinkingPart;
|
||||
}
|
||||
|
||||
private renderChangesSummary(content: IChatChangesSummaryPart, context: IChatContentPartRenderContext, templateData: IChatListItemTemplate): IChatContentPart {
|
||||
const part = this.instantiationService.createInstance(ChatCheckpointFileChangesSummaryContentPart, content, context);
|
||||
part.addDisposable(part.onDidChangeHeight(() => { this.updateItemHeight(templateData); }));
|
||||
|
||||
@@ -2466,3 +2466,21 @@ have to be updated for changes to the rules above, or to support more deeply nes
|
||||
color: var(--vscode-foreground);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
||||
.interactive-session .interactive-response .chat-thinking-box {
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 4px;
|
||||
padding: 0px 8px;
|
||||
margin: 4px 0;
|
||||
background-color: var(--vscode-editor-background);
|
||||
|
||||
.chat-thinking-text {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import { CellUri, ICellEditOperation } from '../../notebook/common/notebookCommo
|
||||
import { IChatAgentCommand, IChatAgentData, IChatAgentResult, IChatAgentService, reviveSerializedAgent } from './chatAgents.js';
|
||||
import { IChatEditingService, IChatEditingSession } from './chatEditingService.js';
|
||||
import { ChatRequestTextPart, IParsedChatRequest, reviveParsedChatRequest } from './chatParserTypes.js';
|
||||
import { ChatAgentVoteDirection, ChatAgentVoteDownReason, IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatClearToPreviousToolInvocation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatEditingSessionAction, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatLocationData, IChatMarkdownContent, IChatMultiDiffData, IChatNotebookEdit, IChatPrepareToolInvocationPart, IChatProgress, IChatProgressMessage, IChatPullRequestContent, IChatResponseCodeblockUriPart, IChatResponseProgressFileTreeData, IChatTask, IChatTaskSerialized, IChatTextEdit, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop, IChatUsedContext, IChatWarningMessage, isIUsedContext, ChatResponseClearToPreviousToolInvocationReason } from './chatService.js';
|
||||
import { ChatAgentVoteDirection, ChatAgentVoteDownReason, IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatClearToPreviousToolInvocation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatEditingSessionAction, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatLocationData, IChatMarkdownContent, IChatMultiDiffData, IChatNotebookEdit, IChatPrepareToolInvocationPart, IChatProgress, IChatProgressMessage, IChatPullRequestContent, IChatResponseCodeblockUriPart, IChatResponseProgressFileTreeData, IChatTask, IChatTaskSerialized, IChatTextEdit, IChatThinkingPart, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop, IChatUsedContext, IChatWarningMessage, isIUsedContext, ChatResponseClearToPreviousToolInvocationReason } from './chatService.js';
|
||||
import { IChatRequestVariableEntry } from './chatVariableEntries.js';
|
||||
import { ChatAgentLocation, ChatModeKind } from './constants.js';
|
||||
|
||||
@@ -118,6 +118,7 @@ export type IChatProgressHistoryResponseContent =
|
||||
| IChatNotebookEditGroup
|
||||
| IChatConfirmation
|
||||
| IChatExtensionsContent
|
||||
| IChatThinkingPart
|
||||
| IChatPullRequestContent;
|
||||
|
||||
/**
|
||||
@@ -365,6 +366,7 @@ class AbstractResponse implements IResponse {
|
||||
case 'undoStop':
|
||||
case 'prepareToolInvocation':
|
||||
case 'elicitation':
|
||||
case 'thinking':
|
||||
case 'multiDiffData':
|
||||
// Ignore
|
||||
continue;
|
||||
@@ -518,6 +520,20 @@ export class Response extends AbstractResponse implements IDisposable {
|
||||
this._responseParts[idx] = { ...lastResponsePart, content: appendMarkdownString(lastResponsePart.content, progress.content) };
|
||||
}
|
||||
this._updateRepr(quiet);
|
||||
} else if (progress.kind === 'thinking') {
|
||||
|
||||
// TODO: @justschen merge thinking and markdown handling
|
||||
const lastResponsePart = this._responseParts
|
||||
.filter(p => p.kind !== 'textEditGroup')
|
||||
.at(-1);
|
||||
|
||||
if (!lastResponsePart || lastResponsePart.kind !== 'thinking' || !canMergeMarkdownStrings(new MarkdownString(lastResponsePart.value), new MarkdownString(progress.value))) {
|
||||
this._responseParts.push(progress);
|
||||
} else {
|
||||
const idx = this._responseParts.indexOf(lastResponsePart);
|
||||
this._responseParts[idx] = { ...lastResponsePart, value: appendMarkdownString(new MarkdownString(lastResponsePart.value), new MarkdownString(progress.value)).value };
|
||||
}
|
||||
this._updateRepr(quiet);
|
||||
} else if (progress.kind === 'textEdit' || progress.kind === 'notebookEdit') {
|
||||
// If the progress.uri is a cell Uri, its possible its part of the inline chat.
|
||||
// Old approach of notebook inline chat would not start and end with notebook Uri, so we need to check for old approach.
|
||||
@@ -1736,6 +1752,13 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
return item.treeData;
|
||||
} else if (item.kind === 'markdownContent') {
|
||||
return item.content;
|
||||
} else if (item.kind === 'thinking') {
|
||||
return {
|
||||
kind: 'thinking',
|
||||
value: item.value,
|
||||
id: item.id,
|
||||
metadata: item.metadata
|
||||
};
|
||||
} else {
|
||||
return item as any; // TODO
|
||||
}
|
||||
|
||||
@@ -271,6 +271,13 @@ export interface IChatElicitationRequest {
|
||||
onDidRequestHide: Event<void>;
|
||||
}
|
||||
|
||||
export interface IChatThinkingPart {
|
||||
kind: 'thinking';
|
||||
value: string;
|
||||
id?: string;
|
||||
metadata?: string;
|
||||
}
|
||||
|
||||
export interface IChatTerminalToolInvocationData {
|
||||
kind: 'terminal';
|
||||
commandLine: {
|
||||
@@ -391,6 +398,7 @@ export type IChatProgress =
|
||||
| IChatPullRequestContent
|
||||
| IChatUndoStop
|
||||
| IChatPrepareToolInvocationPart
|
||||
| IChatThinkingPart
|
||||
| IChatTaskSerialized
|
||||
| IChatElicitationRequest;
|
||||
|
||||
|
||||
@@ -123,6 +123,13 @@ export interface IChatResponseToolUsePart {
|
||||
parameters: any;
|
||||
}
|
||||
|
||||
export interface IChatResponseThinkingPart {
|
||||
type: 'thinking';
|
||||
value: string;
|
||||
id?: string;
|
||||
metadata?: string;
|
||||
}
|
||||
|
||||
export interface IChatResponsePullRequestPart {
|
||||
type: 'pullRequest';
|
||||
uri: URI;
|
||||
@@ -132,9 +139,9 @@ export interface IChatResponsePullRequestPart {
|
||||
linkTag: string;
|
||||
}
|
||||
|
||||
export type IExtendedChatResponsePart = IChatResponsePullRequestPart;
|
||||
export type IChatResponsePart = IChatResponseTextPart | IChatResponseToolUsePart | IChatResponseDataPart | IChatResponseThinkingPart;
|
||||
|
||||
export type IChatResponsePart = IChatResponseTextPart | IChatResponseToolUsePart | IChatResponseDataPart;
|
||||
export type IExtendedChatResponsePart = IChatResponsePullRequestPart;
|
||||
|
||||
export interface IChatResponseFragment {
|
||||
index: number;
|
||||
|
||||
@@ -149,7 +149,7 @@ declare module 'vscode' {
|
||||
constructor(value: ChatResponseDiffEntry[], title: string);
|
||||
}
|
||||
|
||||
export type ExtendedChatResponsePart = ChatResponsePart | ChatResponseTextEditPart | ChatResponseNotebookEditPart | ChatResponseConfirmationPart | ChatResponseCodeCitationPart | ChatResponseReferencePart2 | ChatResponseMovePart | ChatResponseExtensionsPart | ChatResponsePullRequestPart | ChatPrepareToolInvocationPart | ChatToolInvocationPart | ChatResponseMultiDiffPart;
|
||||
export type ExtendedChatResponsePart = ChatResponsePart | ChatResponseTextEditPart | ChatResponseNotebookEditPart | ChatResponseConfirmationPart | ChatResponseCodeCitationPart | ChatResponseReferencePart2 | ChatResponseMovePart | ChatResponseExtensionsPart | ChatResponsePullRequestPart | ChatPrepareToolInvocationPart | ChatToolInvocationPart | ChatResponseMultiDiffPart | ChatResponseThinkingProgressPart;
|
||||
export class ChatResponseWarningPart {
|
||||
value: MarkdownString;
|
||||
constructor(value: string | MarkdownString);
|
||||
@@ -161,6 +161,23 @@ declare module 'vscode' {
|
||||
constructor(value: string, task?: (progress: Progress<ChatResponseWarningPart | ChatResponseReferencePart>) => Thenable<string | void>);
|
||||
}
|
||||
|
||||
/**
|
||||
* A specialized progress part for displaying thinking/reasoning steps.
|
||||
*/
|
||||
export class ChatResponseThinkingProgressPart extends ChatResponseProgressPart {
|
||||
value: string;
|
||||
id?: string;
|
||||
metadata?: string;
|
||||
task?: (progress: Progress<LanguageModelThinkingPart>) => Thenable<string | void>;
|
||||
|
||||
/**
|
||||
* Creates a new thinking progress part.
|
||||
* @param value An initial progress message
|
||||
* @param task A task that will emit thinking parts during its execution
|
||||
*/
|
||||
constructor(value: string, id?: string, metadata?: string, task?: (progress: Progress<LanguageModelThinkingPart>) => Thenable<string | void>);
|
||||
}
|
||||
|
||||
export class ChatResponseReferencePart2 {
|
||||
/**
|
||||
* The reference target.
|
||||
@@ -256,6 +273,8 @@ declare module 'vscode' {
|
||||
*/
|
||||
progress(value: string, task?: (progress: Progress<ChatResponseWarningPart | ChatResponseReferencePart>) => Thenable<string | void>): void;
|
||||
|
||||
thinkingProgress(value: string, id?: string, metadata?: string): void;
|
||||
|
||||
textEdit(target: Uri, edits: TextEdit | TextEdit[]): void;
|
||||
|
||||
textEdit(target: Uri, isDone: true): void;
|
||||
|
||||
+1
-1
@@ -139,6 +139,6 @@ declare module 'vscode' {
|
||||
|
||||
export interface ChatResponseFragment2 {
|
||||
index: number;
|
||||
part: LanguageModelTextPart | LanguageModelToolCallPart | LanguageModelDataPart;
|
||||
part: LanguageModelTextPart | LanguageModelToolCallPart | LanguageModelDataPart | LanguageModelThinkingPart;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// version: 1
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
/**
|
||||
* A language model response part containing thinking/reasoning content.
|
||||
* Thinking tokens represent the model's internal reasoning process that
|
||||
* typically streams before the final response.
|
||||
*/
|
||||
export class LanguageModelThinkingPart {
|
||||
/**
|
||||
* The thinking/reasoning text content.
|
||||
*/
|
||||
value: string;
|
||||
|
||||
/**
|
||||
* Optional unique identifier for this thinking sequence.
|
||||
* This ID is typically provided at the end of the thinking stream
|
||||
* and can be used for retrieval or reference purposes.
|
||||
*/
|
||||
id?: string;
|
||||
|
||||
/**
|
||||
* Optional metadata associated with this thinking sequence.
|
||||
*/
|
||||
metadata?: string;
|
||||
|
||||
/**
|
||||
* Construct a thinking part with the given content.
|
||||
* @param value The thinking text content.
|
||||
* @param id Optional unique identifier for this thinking sequence.
|
||||
* @param metadata Optional metadata associated with this thinking sequence.
|
||||
*/
|
||||
constructor(value: string, id?: string, metadata?: string);
|
||||
}
|
||||
|
||||
export interface LanguageModelChatResponse {
|
||||
/**
|
||||
* An async iterable that is a stream of text, thinking, and tool-call parts forming the overall response.
|
||||
* This includes {@link LanguageModelThinkingPart} which represents the model's internal reasoning process.
|
||||
*/
|
||||
stream: AsyncIterable<LanguageModelTextPart | LanguageModelThinkingPart | LanguageModelToolCallPart | unknown>;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user