Skip to content

Commit

Permalink
add fix and better tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
gagik committed Dec 20, 2024
1 parent 30e1ace commit db0ce4f
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 33 deletions.
100 changes: 67 additions & 33 deletions src/participant/participant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,26 +345,31 @@ export default class ParticipantController {
token: vscode.CancellationToken;
language?: string;
}): Promise<string | null> {
const chatResponse = await this._getChatResponse({
modelInput,
token,
});
try {
const chatResponse = await this._getChatResponse({
modelInput,
token,
});

const languageCodeBlockIdentifier = {
start: `\`\`\`${language ? language : 'javascript'}`,
end: '```',
};
const languageCodeBlockIdentifier = {
start: `\`\`\`${language ? language : 'javascript'}`,
end: '```',
};

const runnableContent: string[] = [];
await processStreamWithIdentifiers({
processStreamFragment: () => {},
onStreamIdentifier: (content: string) => {
runnableContent.push(content.trim());
},
inputIterable: chatResponse.text,
identifier: languageCodeBlockIdentifier,
});
return runnableContent.length ? runnableContent.join('') : null;
const runnableContent: string[] = [];
await processStreamWithIdentifiers({
processStreamFragment: () => {},
onStreamIdentifier: (content: string) => {
runnableContent.push(content.trim());
},
inputIterable: chatResponse.text,
identifier: languageCodeBlockIdentifier,
});
return runnableContent.length ? runnableContent.join('') : null;
} catch (error) {
/** If anything goes wrong with the response or the stream, return null instead of throwing. */
return null;
}
}

async streamChatResponseContentWithCodeActions({
Expand Down Expand Up @@ -1784,8 +1789,7 @@ export default class ParticipantController {
}

async exportCodeToPlayground(): Promise<boolean> {
const selectedText = getSelectedText();
const codeToExport = selectedText || getAllText();
const codeToExport = getSelectedText() || getAllText();

try {
const content = await vscode.window.withProgress(
Expand All @@ -1795,27 +1799,50 @@ export default class ParticipantController {
cancellable: true,
},
async (progress, token): Promise<string | null> => {
const modelInput = await Prompts.exportToPlayground.buildMessages({
request: { prompt: codeToExport },
});
let modelInput: ModelInput | undefined;
try {
modelInput = await Prompts.exportToPlayground.buildMessages({
request: { prompt: codeToExport },
});
} catch (error) {
void vscode.window.showErrorMessage(
'Failed to generate a MongoDB Playground. Please ensure your code block contains a MongoDB query.'
);

this._telemetryService.trackExportToPlaygroundFailed({
input_length: codeToExport?.length,
details: 'modelInput',
});
return null;
}

const result = await Promise.race([
this.streamChatResponseWithExportToLanguage({
modelInput,
token,
}),
new Promise<null>((resolve) =>
new Promise<'cancelled'>((resolve) =>
token.onCancellationRequested(() => {
log.info('The export to a playground operation was canceled.');
resolve(null);
resolve('cancelled');
})
),
]);

if (result?.includes("Sorry, I can't assist with that.")) {
if (result === 'cancelled') {
return null;
}

if (!result || result?.includes("Sorry, I can't assist with that.")) {
void vscode.window.showErrorMessage(
'Sorry, we were unable to generate the playground, please try again. If the error persists, try changing your selected code.'
'Failed to generate a MongoDB Playground. Please ensure your code block contains a MongoDB query.'
);

this._telemetryService.trackExportToPlaygroundFailed({
input_length: codeToExport?.length,
details: 'streamChatResponseWithExportToLanguage',
});

return null;
}

Expand All @@ -1827,12 +1854,19 @@ export default class ParticipantController {
return true;
}

await vscode.commands.executeCommand(
EXTENSION_COMMANDS.OPEN_PARTICIPANT_CODE_IN_PLAYGROUND,
{
runnableContent: content,
}
);
try {
await vscode.commands.executeCommand(
EXTENSION_COMMANDS.OPEN_PARTICIPANT_CODE_IN_PLAYGROUND,
{
runnableContent: content,
}
);
} catch (error) {
this._telemetryService.trackExportToPlaygroundFailed({
input_length: content.length,
details: 'executeCommand',
});
}

return true;
} catch (error) {
Expand Down
14 changes: 14 additions & 0 deletions src/telemetry/telemetryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ type DocumentEditedTelemetryEventProperties = {
source: DocumentSource;
};

type ExportToPlaygroundFailedEventProperties = {
input_length: number | undefined;
details: string;
};

type PlaygroundExportedToLanguageTelemetryEventProperties = {
language?: string;
exported_code_length: number;
Expand Down Expand Up @@ -106,6 +111,7 @@ type ParticipantResponseFailedProperties = {
command: ParticipantResponseType;
error_code?: string;
error_name: ParticipantErrorTypes;
error_details?: string;
};

export type InternalPromptPurpose = 'intent' | 'namespace' | undefined;
Expand Down Expand Up @@ -171,6 +177,7 @@ type TelemetryEventProperties =
| PlaygroundSavedTelemetryEventProperties
| PlaygroundLoadedTelemetryEventProperties
| KeytarSecretsMigrationFailedProperties
| ExportToPlaygroundFailedEventProperties
| SavedConnectionsLoadedProperties
| ParticipantFeedbackProperties
| ParticipantResponseFailedProperties
Expand All @@ -193,6 +200,7 @@ export enum TelemetryEventTypes {
PLAYGROUND_EXPORTED_TO_LANGUAGE = 'Playground Exported To Language',
PLAYGROUND_CREATED = 'Playground Created',
KEYTAR_SECRETS_MIGRATION_FAILED = 'Keytar Secrets Migration Failed',
EXPORT_TO_PLAYGROUND_FAILED = 'Export To Playground Failed',
SAVED_CONNECTIONS_LOADED = 'Saved Connections Loaded',
PARTICIPANT_FEEDBACK = 'Participant Feedback',
PARTICIPANT_WELCOME_SHOWN = 'Participant Welcome Shown',
Expand Down Expand Up @@ -346,6 +354,12 @@ export default class TelemetryService {
);
}

trackExportToPlaygroundFailed(
props: ExportToPlaygroundFailedEventProperties
): void {
this.track(TelemetryEventTypes.EXPORT_TO_PLAYGROUND_FAILED, props);
}

trackCommandRun(command: ExtensionCommand): void {
this.track(TelemetryEventTypes.EXTENSION_COMMAND_RUN, { command });
}
Expand Down
31 changes: 31 additions & 0 deletions src/test/suite/participant/participant.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,37 @@ Schema:
);
});

test('tracks failures with export to playground and not as a failed prompt', async function () {
const editor = vscode.window.activeTextEditor;
if (!editor) {
throw new Error('Window active text editor is undefined');
}

const testDocumentUri = editor.document.uri;
const edit = new vscode.WorkspaceEdit();
const code = `
THIS IS SOME ERROR CAUSING CODE.
`;
edit.replace(testDocumentUri, getFullRange(editor.document), code);
await vscode.workspace.applyEdit(edit);

await testParticipantController.exportCodeToPlayground();
sendRequestStub.rejects();
const messages = sendRequestStub.firstCall.args[0];
expect(getMessageContent(messages[1])).to.equal(code.trim());
expect(telemetryTrackStub).calledWith(
TelemetryEventTypes.EXPORT_TO_PLAYGROUND_FAILED,
{
input_length: code.trim().length,
details: 'streamChatResponseWithExportToLanguage',
}
);

expect(telemetryTrackStub).not.calledWith(
TelemetryEventTypes.PARTICIPANT_RESPONSE_FAILED
);
});

test('exports selected lines of code to a playground', async function () {
const editor = vscode.window.activeTextEditor;
if (!editor) {
Expand Down
1 change: 1 addition & 0 deletions src/views/webview-app/overview-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ const OverviewPage: React.FC = () => {
<FileInputBackendProvider
createFileInputBackend={createElectronFileInputBackend(
dialogProvider,
// @ts-expect-error Type for this may not be accurate.

Check failure on line 129 in src/views/webview-app/overview-page.tsx

View workflow job for this annotation

GitHub Actions / Test and Build (ubuntu-latest)

Unused '@ts-expect-error' directive.

Check failure on line 129 in src/views/webview-app/overview-page.tsx

View workflow job for this annotation

GitHub Actions / Test and Build (windows-2019)

Unused '@ts-expect-error' directive.

Check failure on line 129 in src/views/webview-app/overview-page.tsx

View workflow job for this annotation

GitHub Actions / Test and Build (macos-latest)

Unused '@ts-expect-error' directive.
null
)}
>
Expand Down

0 comments on commit db0ce4f

Please sign in to comment.