diff --git a/extensions/vscode-api-tests/testWorkspace2/.vscode/settings.json b/extensions/vscode-api-tests/testWorkspace2/.vscode/settings.json deleted file mode 100644 index bcb312b4a28c4..0000000000000 --- a/extensions/vscode-api-tests/testWorkspace2/.vscode/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "editor.minimap.enabled": false, // see https://github.com/microsoft/vscode/issues/115747 - "workbench.editor.languageDetection": false, - "typescript.disableAutomaticTypeAcquisition": true, - "json.schemaDownload.enable": false, - "npm.fetchOnlinePackageInfo": false, - "npm.autoDetect": "off", - "workbench.localHistory.enabled": false -} diff --git a/src/vs/platform/utilityProcess/electron-main/utilityProcess.ts b/src/vs/platform/utilityProcess/electron-main/utilityProcess.ts index 90b054ad13dd9..686cc51176037 100644 --- a/src/vs/platform/utilityProcess/electron-main/utilityProcess.ts +++ b/src/vs/platform/utilityProcess/electron-main/utilityProcess.ts @@ -235,7 +235,6 @@ export class UtilityProcess extends Disposable { const args = this.configuration.args ?? []; const execArgv = this.configuration.execArgv ?? []; const allowLoadingUnsignedLibraries = this.configuration.allowLoadingUnsignedLibraries; - const respondToAuthRequestsFromMainProcess = this.configuration.respondToAuthRequestsFromMainProcess; const stdio = 'pipe'; const env = this.createEnv(configuration); @@ -247,7 +246,6 @@ export class UtilityProcess extends Disposable { env, execArgv, allowLoadingUnsignedLibraries, - respondToAuthRequestsFromMainProcess, stdio }); diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts index 5f00d92b18088..23aa8c2cff639 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts @@ -759,6 +759,12 @@ export class DynamicSpeechAccessibilityConfiguration extends Disposable implemen 'minimum': 0, 'tags': ['accessibility'] }, + [AccessibilityVoiceSettingId.IgnoreCodeBlocks]: { + 'markdownDescription': localize('voice.ignoreCodeBlocks', "Whether to ignore code snippets from the text to speech in copilot chat."), + 'type': 'boolean', + 'default': true, + 'tags': ['accessibility'] + }, [AccessibilityVoiceSettingId.SpeechLanguage]: { 'markdownDescription': localize('voice.speechLanguage', "The language that text-to-speech and speech-to-text should use. Select `auto` to use the configured display language if possible. Note that not all display languages maybe supported by speech recognition and synthesizers."), 'type': 'string', @@ -774,7 +780,7 @@ export class DynamicSpeechAccessibilityConfiguration extends Disposable implemen 'enumDescriptions': [ localize('accessibility.voice.autoSynthesize.on', "Enable the feature. When a screen reader is enabled, note that this will disable aria updates."), localize('accessibility.voice.autoSynthesize.off', "Disable the feature."), - localize('accessibility.voice.autoSynthesize.auto', "When a screen reader is detected, disable the feature. Otherwise, enable the feature.") + localize('accessibility.voice.autoSynthesize.auto', "When a screen reader is detected, disable the feature. Otherwise, enable the feature."), ], 'markdownDescription': localize('autoSynthesize', "Whether a textual response should automatically be read out aloud when speech was used as input. For example in a chat session, a response is automatically synthesized when voice was used as chat request."), 'default': this.productService.quality !== 'stable' ? 'auto' : 'off', // TODO@bpasero decide on a default diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 52046a1aa8ee6..4e10047ceb16c 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -395,11 +395,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer= 0) { + const end = filtered.indexOf(delimiter, start + delimiter.length); + filtered = filtered.slice(0, start) + filtered.slice(end + delimiter.length); + start = filtered.indexOf(delimiter); + } + return filtered; + } + /** * Apply a progress update to the actual response content. */ diff --git a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts index e89738779e8fe..74dfd2b371d44 100644 --- a/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts +++ b/src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts @@ -787,7 +787,8 @@ class ChatSynthesizerSessions { constructor( @ISpeechService private readonly speechService: ISpeechService, - @IInstantiationService private readonly instantiationService: IInstantiationService + @IInstantiationService private readonly instantiationService: IInstantiationService, + @IConfigurationService private readonly configurationService: IConfigurationService ) { } async start(controller: IChatSynthesizerSessionController): Promise { @@ -835,11 +836,13 @@ class ChatSynthesizerSessions { private async *nextChatResponseChunk(response: IChatResponseModel, token: CancellationToken): AsyncIterable { let totalOffset = 0; let complete = false; + let isWithinCodeBlock = false; do { const responseLength = response.response.toString().length; - const { chunk, offset } = this.parseNextChatResponseChunk(response, totalOffset); + const { chunk, offset, codeBlockTerminated } = this.parseNextChatResponseChunk(response, totalOffset, isWithinCodeBlock); totalOffset = offset; complete = response.isComplete; + isWithinCodeBlock = !codeBlockTerminated; if (chunk) { yield chunk; @@ -855,10 +858,38 @@ class ChatSynthesizerSessions { } while (!token.isCancellationRequested && !complete); } - private parseNextChatResponseChunk(response: IChatResponseModel, offset: number): { readonly chunk: string | undefined; readonly offset: number } { - let chunk: string | undefined = undefined; + private withoutCodeBlocks(text: string): [string, boolean] { + const delimiter = '```'; + let start = text.indexOf(delimiter); + while (start >= 0) { + const end = text.indexOf(delimiter, start + delimiter.length); + if (end === -1) { + return [text.substring(0, start), false]; + } + text = text.slice(0, start) + text.slice(end + delimiter.length); + start = text.indexOf(delimiter); + } + return [text, true]; + } - const text = response.response.toString(); + private parseNextChatResponseChunk(response: IChatResponseModel, offset: number, isWithinCodeBlock = false): { readonly chunk: string | undefined; readonly offset: number; readonly codeBlockTerminated: boolean } { + let chunk: string | undefined = undefined; + const ignoreCodeBlocks = this.configurationService.getValue(AccessibilityVoiceSettingId.IgnoreCodeBlocks); + let text = response.response.toString(); + const delimiter = '```'; + let codeBlockTerminates = false; + const firstDelimiterIndex = text.indexOf(delimiter); + + if (ignoreCodeBlocks) { + if (isWithinCodeBlock && firstDelimiterIndex === -1) { + text = ''; + } else if (isWithinCodeBlock && firstDelimiterIndex >= 0) { + text = text.substring(firstDelimiterIndex + 1); + } + const [filteredText, terminated] = this.withoutCodeBlocks(text); + text = filteredText; + codeBlockTerminates = terminated; + } if (response.isComplete) { chunk = text.substring(offset); @@ -871,7 +902,8 @@ class ChatSynthesizerSessions { return { chunk: chunk ? renderStringAsPlaintext({ value: chunk }) : chunk, // convert markdown to plain text - offset + offset, + codeBlockTerminated: codeBlockTerminates }; } diff --git a/src/vs/workbench/contrib/speech/common/speechService.ts b/src/vs/workbench/contrib/speech/common/speechService.ts index 4df439533b5b0..03c9d1a305bd4 100644 --- a/src/vs/workbench/contrib/speech/common/speechService.ts +++ b/src/vs/workbench/contrib/speech/common/speechService.ts @@ -138,6 +138,7 @@ export const enum AccessibilityVoiceSettingId { SpeechTimeout = 'accessibility.voice.speechTimeout', AutoSynthesize = 'accessibility.voice.autoSynthesize', SpeechLanguage = 'accessibility.voice.speechLanguage', + IgnoreCodeBlocks = 'accessibility.voice.ignoreCodeBlocks' } export const SPEECH_LANGUAGE_CONFIG = AccessibilityVoiceSettingId.SpeechLanguage;