Skip to content

Commit 0a5a76f

Browse files
authored
fix(chat): add message content to blank message request VSCODE-626 (#843)
1 parent beb8d72 commit 0a5a76f

File tree

3 files changed

+228
-98
lines changed

3 files changed

+228
-98
lines changed

src/participant/participant.ts

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as vscode from 'vscode';
22
import { getSimplifiedSchema, parseSchema } from 'mongodb-schema';
33
import type { Document } from 'bson';
44
import type { Reference } from 'mongodb-rag-core';
5+
import util from 'util';
56

67
import { createLogger } from '../logging';
78
import type ConnectionController from '../connectionController';
@@ -138,6 +139,12 @@ export default class ParticipantController {
138139
errorName = ParticipantErrorTypes.OTHER;
139140
}
140141

142+
log.error('Participant encountered an error', {
143+
command,
144+
error_code: errorCode,
145+
error_name: errorName,
146+
});
147+
141148
this._telemetryService.track(
142149
TelemetryEventTypes.PARTICIPANT_RESPONSE_FAILED,
143150
{
@@ -177,9 +184,26 @@ export default class ParticipantController {
177184
throw new Error('Copilot model not found');
178185
}
179186

187+
log.info('Sending request to model', {
188+
messages: modelInput.messages.map(
189+
(message: vscode.LanguageModelChatMessage) =>
190+
util.inspect({
191+
role: message.role,
192+
contentLength: message.content.length,
193+
})
194+
),
195+
});
180196
this._telemetryService.trackCopilotParticipantPrompt(modelInput.stats);
181197

182-
return await model.sendRequest(modelInput.messages, {}, token);
198+
const modelResponse = await model.sendRequest(
199+
modelInput.messages,
200+
{},
201+
token
202+
);
203+
204+
log.info('Model response received');
205+
206+
return modelResponse;
183207
}
184208

185209
async streamChatResponse({
@@ -267,6 +291,11 @@ export default class ParticipantController {
267291
identifier: codeBlockIdentifier,
268292
});
269293

294+
log.info('Streamed response to chat', {
295+
outputLength,
296+
hasCodeBlock,
297+
});
298+
270299
return {
271300
outputLength,
272301
hasCodeBlock,
@@ -376,6 +405,10 @@ export default class ParticipantController {
376405
token,
377406
});
378407

408+
log.info('Received intent response from model', {
409+
responseContentLength: responseContent.length,
410+
});
411+
379412
return Prompts.intent.getIntentFromModelResponse(responseContent);
380413
}
381414

@@ -738,14 +771,41 @@ export default class ParticipantController {
738771
request,
739772
connectionNames: this._getConnectionNames(),
740773
});
741-
const responseContentWithNamespace = await this.getChatResponseContent({
742-
modelInput: messagesWithNamespace,
743-
token,
744-
});
745-
const { databaseName, collectionName } =
746-
Prompts.namespace.extractDatabaseAndCollectionNameFromResponse(
747-
responseContentWithNamespace
748-
);
774+
775+
let {
776+
databaseName,
777+
collectionName,
778+
}: {
779+
databaseName: string | undefined;
780+
collectionName: string | undefined;
781+
} = {
782+
databaseName: undefined,
783+
collectionName: undefined,
784+
};
785+
786+
// When there's no user message content we can
787+
// skip the request to the model. This would happen with /schema.
788+
if (Prompts.doMessagesContainUserInput(messagesWithNamespace.messages)) {
789+
// VSCODE-626: When there's an empty message sent to the ai model,
790+
// it currently errors (not on insiders, only main VSCode).
791+
// Here we're defaulting to have some content as a workaround.
792+
// TODO: Remove this when the issue is fixed.
793+
messagesWithNamespace.messages[
794+
messagesWithNamespace.messages.length - 1
795+
].content =
796+
messagesWithNamespace.messages[
797+
messagesWithNamespace.messages.length - 1
798+
].content.trim() || 'see previous messages';
799+
800+
const responseContentWithNamespace = await this.getChatResponseContent({
801+
modelInput: messagesWithNamespace,
802+
token,
803+
});
804+
({ databaseName, collectionName } =
805+
Prompts.namespace.extractDatabaseAndCollectionNameFromResponse(
806+
responseContentWithNamespace
807+
));
808+
}
749809

750810
// See if there's a namespace set in the
751811
// chat metadata we can fallback to if the model didn't find it.
@@ -757,6 +817,11 @@ export default class ParticipantController {
757817
collectionName: collectionNameFromMetadata,
758818
} = this._chatMetadataStore.getChatMetadata(chatId) ?? {};
759819

820+
log.info('Namespaces found in chat', {
821+
databaseName: databaseName || databaseNameFromMetadata,
822+
collectionName: collectionName || collectionNameFromMetadata,
823+
});
824+
760825
return {
761826
databaseName: databaseName || databaseNameFromMetadata,
762827
collectionName: collectionName || collectionNameFromMetadata,
@@ -831,6 +896,8 @@ export default class ParticipantController {
831896
context: vscode.ChatContext;
832897
stream: vscode.ChatResponseStream;
833898
}): ChatResult {
899+
log.info('Participant asked user to connect');
900+
834901
stream.markdown(
835902
"Looks like you aren't currently connected, first let's get you connected to the cluster we'd like to create this query to run against.\n\n"
836903
);

src/participant/prompts/index.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type * as vscode from 'vscode';
1+
import * as vscode from 'vscode';
22

33
import { GenericPrompt } from './generic';
44
import { IntentPrompt } from './intent';
@@ -16,4 +16,22 @@ export class Prompts {
1616
public static isPromptEmpty(request: vscode.ChatRequest): boolean {
1717
return !request.prompt || request.prompt.trim().length === 0;
1818
}
19+
20+
// Check if any of the messages contain user input.
21+
// This is useful since when there's no user input in any
22+
// messages, we can skip some additional processing.
23+
public static doMessagesContainUserInput(
24+
messages: vscode.LanguageModelChatMessage[]
25+
): boolean {
26+
for (const message of messages) {
27+
if (
28+
message.role === vscode.LanguageModelChatMessageRole.User &&
29+
message.content.trim().length > 0
30+
) {
31+
return true;
32+
}
33+
}
34+
35+
return false;
36+
}
1937
}

0 commit comments

Comments
 (0)