@@ -45,7 +45,10 @@ import { processStreamWithIdentifiers } from './streamParsing';
45
45
import type { PromptIntent } from './prompts/intent' ;
46
46
import { isPlayground , getSelectedText , getAllText } from '../utils/playground' ;
47
47
import type { DataService } from 'mongodb-data-service' ;
48
- import { ParticipantErrorTypes } from './participantErrorTypes' ;
48
+ import {
49
+ ParticipantErrorTypes ,
50
+ type ExportToPlaygroundError ,
51
+ } from './participantErrorTypes' ;
49
52
import type PlaygroundResultProvider from '../editors/playgroundResultProvider' ;
50
53
import { isExportToLanguageResult } from '../types/playgroundType' ;
51
54
import { PromptHistory } from './prompts/promptHistory' ;
@@ -345,26 +348,35 @@ export default class ParticipantController {
345
348
token : vscode . CancellationToken ;
346
349
language ?: string ;
347
350
} ) : 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
+ } ) ;
352
356
353
- const languageCodeBlockIdentifier = {
354
- start : `\`\`\`${ language ? language : 'javascript' } ` ,
355
- end : '```' ,
356
- } ;
357
+ const languageCodeBlockIdentifier = {
358
+ start : `\`\`\`${ language ? language : 'javascript' } ` ,
359
+ end : '```' ,
360
+ } ;
357
361
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
+ }
368
380
}
369
381
370
382
async streamChatResponseContentWithCodeActions ( {
@@ -1784,49 +1796,75 @@ export default class ParticipantController {
1784
1796
}
1785
1797
1786
1798
async exportCodeToPlayground ( ) : Promise < boolean > {
1787
- const selectedText = getSelectedText ( ) ;
1788
- const codeToExport = selectedText || getAllText ( ) ;
1799
+ const codeToExport = getSelectedText ( ) || getAllText ( ) ;
1789
1800
1790
1801
try {
1791
- const content = await vscode . window . withProgress (
1802
+ const contentOrError = await vscode . window . withProgress <
1803
+ { value : string } | { error : ExportToPlaygroundError }
1804
+ > (
1792
1805
{
1793
1806
location : vscode . ProgressLocation . Notification ,
1794
1807
title : 'Exporting code to a playground...' ,
1795
1808
cancellable : true ,
1796
1809
} ,
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
+ }
1801
1822
1802
1823
const result = await Promise . race ( [
1803
1824
this . streamChatResponseWithExportToLanguage ( {
1804
1825
modelInput,
1805
1826
token,
1806
1827
} ) ,
1807
- new Promise < null > ( ( resolve ) =>
1828
+ new Promise < ExportToPlaygroundError > ( ( resolve ) =>
1808
1829
token . onCancellationRequested ( ( ) => {
1809
1830
log . info ( 'The export to a playground operation was canceled.' ) ;
1810
- resolve ( null ) ;
1831
+ resolve ( 'cancelled' ) ;
1811
1832
} )
1812
1833
) ,
1813
1834
] ) ;
1814
1835
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' } ;
1820
1838
}
1821
1839
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 } ;
1823
1845
}
1824
1846
) ;
1825
1847
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 ;
1828
1865
}
1829
1866
1867
+ const content = contentOrError . value ;
1830
1868
await vscode . commands . executeCommand (
1831
1869
EXTENSION_COMMANDS . OPEN_PARTICIPANT_CODE_IN_PLAYGROUND ,
1832
1870
{
0 commit comments