Skip to content

Commit 23fc07c

Browse files
authored
Simplify ChatModel more (#198344)
* Simplify ChatModel further * Simplify ChatModel more * Remove helper * Clean up * Fix addCompleteRequest * Fix updateRepr
1 parent f26376f commit 23fc07c

13 files changed

+269
-134
lines changed

src/vs/workbench/api/common/extHostTypeConverters.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,17 +2297,17 @@ export namespace InteractiveEditorResponseFeedbackKind {
22972297
export namespace ChatResponseProgress {
22982298
export function from(extension: IExtensionDescription, progress: vscode.ChatAgentExtendedProgress): extHostProtocol.IChatProgressDto {
22992299
if ('placeholder' in progress && 'resolvedContent' in progress) {
2300-
return { placeholder: progress.placeholder, kind: 'asyncContent' } satisfies extHostProtocol.IChatAsyncContentDto;
2300+
return { content: progress.placeholder, kind: 'asyncContent' } satisfies extHostProtocol.IChatAsyncContentDto;
23012301
} else if ('markdownContent' in progress) {
23022302
checkProposedApiEnabled(extension, 'chatAgents2Additions');
2303-
return { content: MarkdownString.from(progress.markdownContent), kind: 'content' };
2303+
return { content: MarkdownString.from(progress.markdownContent), kind: 'markdownContent' };
23042304
} else if ('content' in progress) {
23052305
if (typeof progress.content === 'string') {
23062306
return { content: progress.content, kind: 'content' };
23072307
}
23082308

23092309
checkProposedApiEnabled(extension, 'chatAgents2Additions');
2310-
return { content: MarkdownString.from(progress.content), kind: 'content' };
2310+
return { content: MarkdownString.from(progress.content), kind: 'markdownContent' };
23112311
} else if ('documents' in progress) {
23122312
return {
23132313
documents: progress.documents.map(d => ({

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import { ChatAccessibilityService } from 'vs/workbench/contrib/chat/browser/chat
4545
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
4646
import { AccessibilityVerbositySettingId, AccessibleViewProviderId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
4747
import { ChatWelcomeMessageModel } from 'vs/workbench/contrib/chat/common/chatModel';
48-
import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent';
48+
import { IMarkdownString, MarkdownString, isMarkdownString } from 'vs/base/common/htmlContent';
4949
import { ChatProviderService, IChatProviderService } from 'vs/workbench/contrib/chat/common/chatProvider';
5050
import { ChatSlashCommandService, IChatSlashCommandService } from 'vs/workbench/contrib/chat/common/chatSlashCommands';
5151
import { alertFocusChange } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions';
@@ -243,7 +243,11 @@ class ChatSlashStaticSlashCommandsContribution extends Disposable {
243243
const defaultAgent = chatAgentService.getDefaultAgent();
244244
const agents = chatAgentService.getAgents();
245245
if (defaultAgent?.metadata.helpTextPrefix) {
246-
progress.report({ content: defaultAgent.metadata.helpTextPrefix, kind: 'content' });
246+
if (isMarkdownString(defaultAgent.metadata.helpTextPrefix)) {
247+
progress.report({ content: defaultAgent.metadata.helpTextPrefix, kind: 'markdownContent' });
248+
} else {
249+
progress.report({ content: defaultAgent.metadata.helpTextPrefix, kind: 'content' });
250+
}
247251
progress.report({ content: '\n\n', kind: 'content' });
248252
}
249253

@@ -263,10 +267,14 @@ class ChatSlashStaticSlashCommandsContribution extends Disposable {
263267

264268
return agentLine + '\n' + commandText;
265269
}))).join('\n');
266-
progress.report({ content: new MarkdownString(agentText, { isTrusted: { enabledCommands: [SubmitAction.ID] } }), kind: 'content' });
270+
progress.report({ content: new MarkdownString(agentText, { isTrusted: { enabledCommands: [SubmitAction.ID] } }), kind: 'markdownContent' });
267271
if (defaultAgent?.metadata.helpTextPostfix) {
268272
progress.report({ content: '\n\n', kind: 'content' });
269-
progress.report({ content: defaultAgent.metadata.helpTextPostfix, kind: 'content' });
273+
if (isMarkdownString(defaultAgent.metadata.helpTextPostfix)) {
274+
progress.report({ content: defaultAgent.metadata.helpTextPostfix, kind: 'markdownContent' });
275+
} else {
276+
progress.report({ content: defaultAgent.metadata.helpTextPostfix, kind: 'content' });
277+
}
270278
}
271279
}));
272280
}

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

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ import { ChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatOptions
5555
import { CodeBlockPart, ICodeBlockData, ICodeBlockPart } from 'vs/workbench/contrib/chat/browser/codeBlockPart';
5656
import { IChatAgentMetadata } from 'vs/workbench/contrib/chat/common/chatAgents';
5757
import { CONTEXT_CHAT_RESPONSE_SUPPORT_ISSUE_REPORTING, CONTEXT_REQUEST, CONTEXT_RESPONSE, CONTEXT_RESPONSE_FILTERED, CONTEXT_RESPONSE_VOTE } from 'vs/workbench/contrib/chat/common/chatContextKeys';
58-
import { IPlaceholderMarkdownString } from 'vs/workbench/contrib/chat/common/chatModel';
58+
import { IChatProgressResponseContent } from 'vs/workbench/contrib/chat/common/chatModel';
5959
import { chatAgentLeader, chatSubcommandLeader } from 'vs/workbench/contrib/chat/common/chatParserTypes';
60-
import { IChatContentReference, IChatReplyFollowup, IChatResponseProgressFileTreeData, IChatService, InteractiveSessionVoteDirection } from 'vs/workbench/contrib/chat/common/chatService';
60+
import { IChatContentInlineReference, IChatContentReference, IChatReplyFollowup, IChatResponseProgressFileTreeData, IChatService, InteractiveSessionVoteDirection } from 'vs/workbench/contrib/chat/common/chatService';
6161
import { IChatResponseMarkdownRenderData, IChatResponseRenderData, IChatResponseViewModel, IChatWelcomeMessageViewModel, isRequestVM, isResponseVM, isWelcomeVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
6262
import { IWordCountResult, getNWords } from 'vs/workbench/contrib/chat/common/chatWordCounter';
6363
import { createFileIconThemableTreeContainerScope } from 'vs/workbench/contrib/files/browser/views/explorerView';
@@ -319,7 +319,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
319319
const markdown = 'kind' in element.message ?
320320
element.message.message :
321321
convertParsedRequestToMarkdown(element.message);
322-
this.basicRenderElement([new MarkdownString(markdown)], element, index, templateData);
322+
this.basicRenderElement([{ content: new MarkdownString(markdown), kind: 'markdownContent' }], element, index, templateData);
323323
} else {
324324
this.renderWelcomeMessage(element, templateData);
325325
}
@@ -400,7 +400,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
400400
}
401401
}
402402

403-
private basicRenderElement(value: ReadonlyArray<IMarkdownString | IChatResponseProgressFileTreeData>, element: ChatTreeItem, index: number, templateData: IChatListItemTemplate) {
403+
private basicRenderElement(value: ReadonlyArray<Exclude<IChatProgressResponseContent, IChatContentInlineReference>>, element: ChatTreeItem, index: number, templateData: IChatListItemTemplate) {
404404
const fillInIncompleteTokens = isResponseVM(element) && (!element.isComplete || element.isCanceled || element.errorDetails?.responseIsFiltered || element.errorDetails?.responseIsIncomplete);
405405

406406
dom.clearNode(templateData.value);
@@ -414,9 +414,11 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
414414

415415
let fileTreeIndex = 0;
416416
for (const data of value) {
417-
const result = 'value' in data
418-
? this.renderMarkdown(data, element, templateData, fillInIncompleteTokens)
419-
: this.renderTreeData(data, element, templateData, fileTreeIndex++);
417+
const result = data.kind === 'treeData'
418+
? this.renderTreeData(data.treeData, element, templateData, fileTreeIndex++)
419+
: data.kind === 'markdownContent'
420+
? this.renderMarkdown(data.content, element, templateData, fillInIncompleteTokens)
421+
: this.renderPlaceholder(new MarkdownString(data.content), templateData);
420422
templateData.value.appendChild(result.element);
421423
templateData.elementDisposables.add(result);
422424
}
@@ -519,10 +521,10 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
519521
const renderedPart = renderedParts[index];
520522
// Is this part completely new?
521523
if (!renderedPart) {
522-
if (isInteractiveProgressTreeData(part)) {
523-
partsToRender[index] = part;
524+
if (part.kind === 'treeData') {
525+
partsToRender[index] = part.treeData;
524526
} else {
525-
const wordCountResult = this.getDataForProgressiveRender(element, part, { renderedWordCount: 0, lastRenderTime: 0 });
527+
const wordCountResult = this.getDataForProgressiveRender(element, contentToMarkdown(part.content), { renderedWordCount: 0, lastRenderTime: 0 });
526528
if (wordCountResult !== undefined) {
527529
partsToRender[index] = {
528530
renderedWordCount: wordCountResult.actualWordCount,
@@ -535,13 +537,13 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
535537
}
536538

537539
// Did this part go from being a placeholder string to resolved tree data?
538-
else if (isInteractiveProgressTreeData(part) && !isInteractiveProgressTreeData(renderedPart)) {
539-
partsToRender[index] = part;
540+
else if (part.kind === 'treeData' && !isInteractiveProgressTreeData(renderedPart)) {
541+
partsToRender[index] = part.treeData;
540542
}
541543

542544
// Did this part's content change?
543-
else if (!isInteractiveProgressTreeData(part) && !isInteractiveProgressTreeData(renderedPart)) {
544-
const wordCountResult = this.getDataForProgressiveRender(element, part, renderedPart);
545+
else if (part.kind !== 'treeData' && !isInteractiveProgressTreeData(renderedPart)) {
546+
const wordCountResult = this.getDataForProgressiveRender(element, contentToMarkdown(part.content), renderedPart);
545547
// Check if there are any new words to render
546548
if (wordCountResult !== undefined && renderedPart.renderedWordCount !== wordCountResult?.actualWordCount) {
547549
partsToRender[index] = {
@@ -578,8 +580,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
578580
// Avoid doing progressive rendering for multiple markdown parts simultaneously
579581
else if (!hasRenderedOneMarkdownBlock) {
580582
const { value } = wordCountResults[index];
581-
const isPlaceholder = isPlaceholderMarkdown(renderableResponse[index]);
582-
result = isPlaceholder
583+
result = renderableResponse[index].kind === 'asyncContent'
583584
? this.renderPlaceholder(new MarkdownString(value), templateData)
584585
: this.renderMarkdown(new MarkdownString(value), element, templateData, true);
585586
hasRenderedOneMarkdownBlock = true;
@@ -1278,6 +1279,6 @@ function isInteractiveProgressTreeData(item: IChatResponseProgressFileTreeData |
12781279
return 'label' in item;
12791280
}
12801281

1281-
function isPlaceholderMarkdown(item: IPlaceholderMarkdownString | IMarkdownString | IChatResponseProgressFileTreeData): item is IPlaceholderMarkdownString {
1282-
return 'isPlaceholder' in item;
1282+
function contentToMarkdown(str: string | IMarkdownString): IMarkdownString {
1283+
return typeof str === 'string' ? { value: str } : str;
12831284
}

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as dom from 'vs/base/browser/dom';
7-
import { IMarkdownString, MarkdownString, isMarkdownString } from 'vs/base/common/htmlContent';
7+
import { MarkdownString } from 'vs/base/common/htmlContent';
88
import { revive } from 'vs/base/common/marshalling';
99
import { basename } from 'vs/base/common/resources';
1010
import { URI } from 'vs/base/common/uri';
1111
import { Location } from 'vs/editor/common/languages';
12+
import { IChatProgressResponseContent } from 'vs/workbench/contrib/chat/common/chatModel';
1213
import { ChatRequestTextPart, IParsedChatRequest } from 'vs/workbench/contrib/chat/common/chatParserTypes';
13-
import { IChatContentInlineReference, IChatResponseProgressFileTreeData } from 'vs/workbench/contrib/chat/common/chatService';
14+
import { IChatContentInlineReference } from 'vs/workbench/contrib/chat/common/chatService';
1415

1516
const variableRefUrl = 'http://_vscodedecoration_';
1617

@@ -59,21 +60,21 @@ function renderFileWidget(href: string, a: HTMLAnchorElement): void {
5960

6061
const contentRefUrl = 'http://_vscodecontentref_'; // must be lowercase for URI
6162

62-
export function reduceInlineContentReferences(response: ReadonlyArray<IMarkdownString | IChatResponseProgressFileTreeData | IChatContentInlineReference>): ReadonlyArray<IMarkdownString | IChatResponseProgressFileTreeData> {
63-
const result: (IMarkdownString | IChatResponseProgressFileTreeData)[] = [];
63+
export function reduceInlineContentReferences(response: ReadonlyArray<IChatProgressResponseContent>): ReadonlyArray<Exclude<IChatProgressResponseContent, IChatContentInlineReference>> {
64+
const result: Exclude<IChatProgressResponseContent, IChatContentInlineReference>[] = [];
6465
for (const item of response) {
6566
const previousItem = result[result.length - 1];
66-
if ('inlineReference' in item) {
67+
if (item.kind === 'inlineReference') {
6768
const location = 'uri' in item.inlineReference ? item.inlineReference : { uri: item.inlineReference };
6869
const printUri = URI.parse(contentRefUrl).with({ fragment: JSON.stringify(location) });
6970
const markdownText = `[${item.name || basename(location.uri)}](${printUri.toString()})`;
70-
if (isMarkdownString(previousItem)) {
71-
result[result.length - 1] = new MarkdownString(previousItem.value + markdownText, { isTrusted: previousItem.isTrusted });
71+
if (previousItem?.kind === 'markdownContent') {
72+
result[result.length - 1] = { content: new MarkdownString(previousItem.content.value + markdownText, { isTrusted: previousItem.content.isTrusted }), kind: 'markdownContent' };
7273
} else {
73-
result.push(new MarkdownString(markdownText));
74+
result.push({ content: new MarkdownString(markdownText), kind: 'markdownContent' });
7475
}
75-
} else if (isMarkdownString(item) && isMarkdownString(previousItem)) {
76-
result[result.length - 1] = new MarkdownString(previousItem.value + item.value, { isTrusted: previousItem.isTrusted });
76+
} else if (item.kind === 'markdownContent' && previousItem?.kind === 'markdownContent') {
77+
result[result.length - 1] = { content: new MarkdownString(previousItem.content.value + item.content.value, { isTrusted: previousItem.content.isTrusted }), kind: 'markdownContent' };
7778
} else {
7879
result.push(item);
7980
}

0 commit comments

Comments
 (0)