@@ -45,7 +45,10 @@ import { processStreamWithIdentifiers } from './streamParsing';
4545import type { PromptIntent } from './prompts/intent' ;
4646import { isPlayground , getSelectedText , getAllText } from '../utils/playground' ;
4747import type { DataService } from 'mongodb-data-service' ;
48- import { ParticipantErrorTypes } from './participantErrorTypes' ;
48+ import {
49+ ParticipantErrorTypes ,
50+ type ExportToPlaygroundError ,
51+ } from './participantErrorTypes' ;
4952import type PlaygroundResultProvider from '../editors/playgroundResultProvider' ;
5053import { isExportToLanguageResult } from '../types/playgroundType' ;
5154import { PromptHistory } from './prompts/promptHistory' ;
@@ -345,26 +348,35 @@ export default class ParticipantController {
345348 token : vscode . CancellationToken ;
346349 language ?: string ;
347350 } ) : Promise < string | null > {
348- const chatResponse = await this . _getChatResponse ( {
349- modelInput,
350- token,
351- } ) ;
351+ try {
352+ const chatResponse = await this . _getChatResponse ( {
353+ modelInput,
354+ token,
355+ } ) ;
352356
353- const languageCodeBlockIdentifier = {
354- start : `\`\`\`${ language ? language : 'javascript' } ` ,
355- end : '```' ,
356- } ;
357+ const languageCodeBlockIdentifier = {
358+ start : `\`\`\`${ language ? language : 'javascript' } ` ,
359+ end : '```' ,
360+ } ;
357361
358- const runnableContent : string [ ] = [ ] ;
359- await processStreamWithIdentifiers ( {
360- processStreamFragment : ( ) => { } ,
361- onStreamIdentifier : ( content : string ) => {
362- runnableContent . push ( content . trim ( ) ) ;
363- } ,
364- inputIterable : chatResponse . text ,
365- identifier : languageCodeBlockIdentifier ,
366- } ) ;
367- return runnableContent . length ? runnableContent . join ( '' ) : null ;
362+ const runnableContent : string [ ] = [ ] ;
363+ await processStreamWithIdentifiers ( {
364+ processStreamFragment : ( ) => { } ,
365+ onStreamIdentifier : ( content : string ) => {
366+ runnableContent . push ( content . trim ( ) ) ;
367+ } ,
368+ inputIterable : chatResponse . text ,
369+ identifier : languageCodeBlockIdentifier ,
370+ } ) ;
371+ return runnableContent . length ? runnableContent . join ( '' ) : null ;
372+ } catch ( error ) {
373+ /** If anything goes wrong with the response or the stream, return null instead of throwing. */
374+ log . error (
375+ 'Error while streaming chat response with export to language' ,
376+ error
377+ ) ;
378+ return null ;
379+ }
368380 }
369381
370382 async streamChatResponseContentWithCodeActions ( {
@@ -1784,49 +1796,75 @@ export default class ParticipantController {
17841796 }
17851797
17861798 async exportCodeToPlayground ( ) : Promise < boolean > {
1787- const selectedText = getSelectedText ( ) ;
1788- const codeToExport = selectedText || getAllText ( ) ;
1799+ const codeToExport = getSelectedText ( ) || getAllText ( ) ;
17891800
17901801 try {
1791- const content = await vscode . window . withProgress (
1802+ const contentOrError = await vscode . window . withProgress <
1803+ { value : string } | { error : ExportToPlaygroundError }
1804+ > (
17921805 {
17931806 location : vscode . ProgressLocation . Notification ,
17941807 title : 'Exporting code to a playground...' ,
17951808 cancellable : true ,
17961809 } ,
1797- async ( progress , token ) : Promise < string | null > => {
1798- const modelInput = await Prompts . exportToPlayground . buildMessages ( {
1799- request : { prompt : codeToExport } ,
1800- } ) ;
1810+ async (
1811+ progress ,
1812+ token
1813+ ) : Promise < { value : string } | { error : ExportToPlaygroundError } > => {
1814+ let modelInput : ModelInput | undefined ;
1815+ try {
1816+ modelInput = await Prompts . exportToPlayground . buildMessages ( {
1817+ request : { prompt : codeToExport } ,
1818+ } ) ;
1819+ } catch ( error ) {
1820+ return { error : 'modelInput' } ;
1821+ }
18011822
18021823 const result = await Promise . race ( [
18031824 this . streamChatResponseWithExportToLanguage ( {
18041825 modelInput,
18051826 token,
18061827 } ) ,
1807- new Promise < null > ( ( resolve ) =>
1828+ new Promise < ExportToPlaygroundError > ( ( resolve ) =>
18081829 token . onCancellationRequested ( ( ) => {
18091830 log . info ( 'The export to a playground operation was canceled.' ) ;
1810- resolve ( null ) ;
1831+ resolve ( 'cancelled' ) ;
18111832 } )
18121833 ) ,
18131834 ] ) ;
18141835
1815- if ( result ?. includes ( "Sorry, I can't assist with that." ) ) {
1816- void vscode . window . showErrorMessage (
1817- 'Sorry, we were unable to generate the playground, please try again. If the error persists, try changing your selected code.'
1818- ) ;
1819- return null ;
1836+ if ( result === 'cancelled' ) {
1837+ return { error : 'cancelled' } ;
18201838 }
18211839
1822- return result ;
1840+ if ( ! result || result ?. includes ( "Sorry, I can't assist with that." ) ) {
1841+ return { error : 'streamChatResponseWithExportToLanguage' } ;
1842+ }
1843+
1844+ return { value : result } ;
18231845 }
18241846 ) ;
18251847
1826- if ( ! content ) {
1827- return true ;
1848+ if ( 'error' in contentOrError ) {
1849+ const { error } = contentOrError ;
1850+ if ( error === 'cancelled' ) {
1851+ return true ;
1852+ }
1853+
1854+ void vscode . window . showErrorMessage (
1855+ 'Failed to generate a MongoDB Playground. Please ensure your code block contains a MongoDB query.'
1856+ ) ;
1857+
1858+ // Content in this case is already equal to the failureType; this is just to make it explicit
1859+ // and avoid accidentally sending actual contents of the message.
1860+ this . _telemetryService . trackExportToPlaygroundFailed ( {
1861+ input_length : codeToExport ?. length ,
1862+ error_name : error ,
1863+ } ) ;
1864+ return false ;
18281865 }
18291866
1867+ const content = contentOrError . value ;
18301868 await vscode . commands . executeCommand (
18311869 EXTENSION_COMMANDS . OPEN_PARTICIPANT_CODE_IN_PLAYGROUND ,
18321870 {
0 commit comments