Skip to content

Commit 7406a9b

Browse files
authored
Show block cursor after response and before followups appear (microsoft#186684)
1 parent 5827187 commit 7406a9b

File tree

3 files changed

+30
-21
lines changed

3 files changed

+30
-21
lines changed

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

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -350,15 +350,10 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
350350
} else {
351351
const renderValue = this.getWordsForProgressiveRender(element);
352352
isFullyRendered = !!element.renderData?.isFullyRendered;
353-
if (isFullyRendered) {
354-
// We've reached the end of the available content, so do a normal render
355-
this.traceLayout('runProgressiveRender', `end progressive render, index=${index}`);
356-
if (element.isComplete) {
357-
this.traceLayout('runProgressiveRender', `and disposing renderData, response is complete, index=${index}`);
358-
element.renderData = undefined;
359-
} else {
360-
this.traceLayout('runProgressiveRender', `Rendered all available words, but model is not complete.`);
361-
}
353+
if (isFullyRendered && element.isComplete) {
354+
// Response is done and content is rendered, so do a normal render
355+
this.traceLayout('runProgressiveRender', `end progressive render, index=${index} and clearing renderData, response is complete, index=${index}`);
356+
element.renderData = undefined;
362357
disposables.clear();
363358
this.basicRenderElement(element.response.value, element, index, templateData);
364359
} else if (renderValue) {
@@ -368,11 +363,9 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
368363
isFullyRendered: renderValue.isFullString
369364
};
370365

371-
// Don't add the cursor if it will go after a codeblock, since this will always cause layout shifting
372-
// when the codeblock is the last thing in the response, and that happens often.
373-
const plusCursor = renderValue.value.match(/```\s*$/) ?
374-
renderValue.value :
375-
renderValue.value + ` ${ChatListItemRenderer.cursorCharacter}`;
366+
const plusCursor = (renderValue.value.match(/```\s*$/) ?
367+
renderValue.value + '\n\n' :
368+
renderValue.value) + ` ${ChatListItemRenderer.cursorCharacter}`;
376369
const result = this.renderMarkdown(new MarkdownString(plusCursor), element, disposables, templateData, true);
377370
// Doing the progressive render
378371
dom.clearNode(templateData.value);

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,16 @@ export class ChatResponseModel extends Disposable implements IChatResponseModel
157157
this._providerResponseId = providerResponseId;
158158
}
159159

160-
complete(errorDetails?: IChatResponseErrorDetails): void {
161-
this._isComplete = true;
160+
setErrorDetails(errorDetails?: IChatResponseErrorDetails): void {
162161
this._errorDetails = errorDetails;
163162
this._onDidChange.fire();
164163
}
165164

165+
complete(): void {
166+
this._isComplete = true;
167+
this._onDidChange.fire();
168+
}
169+
166170
cancel(): void {
167171
this._isComplete = true;
168172
this._isCanceled = true;
@@ -471,7 +475,7 @@ export class ChatModel extends Disposable implements IChatModel {
471475
}
472476
}
473477

474-
completeResponse(request: ChatRequestModel, rawResponse: IChatResponse): void {
478+
setResponse(request: ChatRequestModel, rawResponse: IChatResponse): void {
475479
if (!this._session) {
476480
throw new Error('completeResponse: No session');
477481
}
@@ -480,7 +484,15 @@ export class ChatModel extends Disposable implements IChatModel {
480484
request.response = new ChatResponseModel(new MarkdownString(''), this);
481485
}
482486

483-
request.response.complete(rawResponse.errorDetails);
487+
request.response.setErrorDetails(rawResponse.errorDetails);
488+
}
489+
490+
completeResponse(request: ChatRequestModel): void {
491+
if (!request.response) {
492+
throw new Error('Call setResponse before completeResponse');
493+
}
494+
495+
request.response.complete();
484496
}
485497

486498
setFollowups(request: ChatRequestModel, followups: IChatFollowup[] | undefined): void {
@@ -492,7 +504,7 @@ export class ChatModel extends Disposable implements IChatModel {
492504
request.response.setFollowups(followups);
493505
}
494506

495-
setResponse(request: ChatRequestModel, response: ChatResponseModel): void {
507+
setResponseModel(request: ChatRequestModel, response: ChatResponseModel): void {
496508
request.response = response;
497509
this._onDidChange.fire({ kind: 'addResponse', response });
498510
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,13 +449,17 @@ export class ChatService extends Disposable implements IChatService {
449449
requestType,
450450
slashCommand: usedSlashCommand?.command
451451
});
452-
model.completeResponse(request, rawResponse);
452+
model.setResponse(request, rawResponse);
453453
this.trace('sendRequest', `Provider returned response for session ${model.sessionId}`);
454454

455+
// TODO refactor this or rethink the API https://github.com/microsoft/vscode-copilot/issues/593
455456
if (provider.provideFollowups) {
456457
Promise.resolve(provider.provideFollowups(model.session!, CancellationToken.None)).then(followups => {
457458
model.setFollowups(request, withNullAsUndefined(followups));
459+
model.completeResponse(request);
458460
});
461+
} else {
462+
model.completeResponse(request);
459463
}
460464
}
461465
});
@@ -579,7 +583,7 @@ export class ChatService extends Disposable implements IChatService {
579583
model.acceptResponseProgress(request, {
580584
content: response.message,
581585
}, true);
582-
model.completeResponse(request, {
586+
model.setResponse(request, {
583587
session: model.session!,
584588
errorDetails: response.errorDetails,
585589
});

0 commit comments

Comments
 (0)