@@ -7,6 +7,7 @@ import { Raw } from '@vscode/prompt-tsx';
77import { ClientHttp2Stream } from 'http2' ;
88import type { CancellationToken } from 'vscode' ;
99import { IAuthenticationService } from '../../../platform/authentication/common/authentication' ;
10+ import { CopilotToken } from '../../../platform/authentication/common/copilotToken' ;
1011import { FetchStreamRecorder , IChatMLFetcher , IFetchMLOptions , Source } from '../../../platform/chat/common/chatMLFetcher' ;
1112import { IChatQuotaService } from '../../../platform/chat/common/chatQuotaService' ;
1213import { ChatFetchError , ChatFetchResponseType , ChatFetchRetriableError , ChatLocation , ChatResponse , ChatResponses } from '../../../platform/chat/common/commonTypes' ;
@@ -25,6 +26,7 @@ import { sendEngineMessagesTelemetry } from '../../../platform/networking/node/c
2526import { sendCommunicationErrorTelemetry } from '../../../platform/networking/node/stream' ;
2627import { ChatFailKind , ChatRequestCanceled , ChatRequestFailed , ChatResults , FetchResponseKind } from '../../../platform/openai/node/fetch' ;
2728import { IRequestLogger } from '../../../platform/requestLogger/node/requestLogger' ;
29+ import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService' ;
2830import { ITelemetryService , TelemetryProperties } from '../../../platform/telemetry/common/telemetry' ;
2931import { TelemetryData } from '../../../platform/telemetry/common/telemetryData' ;
3032import { calculateLineRepetitionStats , isRepetitive } from '../../../util/common/anomalyDetection' ;
@@ -37,7 +39,6 @@ import { generateUuid } from '../../../util/vs/base/common/uuid';
3739import { isBYOKModel } from '../../byok/node/openAIEndpoint' ;
3840import { EXTENSION_ID } from '../../common/constants' ;
3941import { ChatMLFetcherTelemetrySender as Telemetry } from './chatMLFetcherTelemetry' ;
40- import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService' ;
4142
4243export interface IMadeChatRequestEvent {
4344 readonly messages : Raw . ChatMessage [ ] ;
@@ -152,6 +153,7 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
152153 let tokenCount = - 1 ;
153154 const streamRecorder = new FetchStreamRecorder ( finishedCb ) ;
154155 const enableRetryOnError = opts . enableRetryOnError ?? opts . enableRetryOnFilter ;
156+ let usernameToScrub : string | undefined ;
155157 try {
156158 let response : ChatResults | ChatRequestFailed | ChatRequestCanceled ;
157159 const payloadValidationResult = isValidChatPayload ( opts . messages , postOptions ) ;
@@ -163,12 +165,15 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
163165 reason : payloadValidationResult . reason ,
164166 } ;
165167 } else {
168+ const copilotToken = await this . _authenticationService . getCopilotToken ( ) ;
169+ usernameToScrub = copilotToken . username ;
166170 response = await this . _fetchAndStreamChat (
167171 chatEndpoint ,
168172 requestBody ,
169173 baseTelemetry ,
170174 streamRecorder . callback ,
171175 requestOptions . secretKey ,
176+ copilotToken ,
172177 opts . location ,
173178 ourRequestId ,
174179 postOptions . n ,
@@ -282,7 +287,7 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
282287 }
283288 } catch ( err : unknown ) {
284289 const timeToError = Date . now ( ) - baseTelemetry . issuedTime ;
285- const processed = this . processError ( err , ourRequestId ) ;
290+ const processed = this . processError ( err , ourRequestId , usernameToScrub ) ;
286291 let connectivityTestError = telemetryProperties . connectivityTestError ;
287292 if ( processed . type === ChatFetchResponseType . NetworkError && enableRetryOnError ) {
288293 // Keep existing handling of net::ERR_NETWORK_CHANGED: https://github.com/microsoft/vscode/issues/260297
@@ -293,7 +298,7 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
293298 this . _logService . info ( `Retrying chat request with ${ useFetcher || 'default' } fetcher after: ${ processed . reasonDetail || processed . reason } ` ) ;
294299 // Keep existing handling of net::ERR_NETWORK_CHANGED if setting is not enabled: https://github.com/microsoft/vscode/issues/260297
295300 const connectivity = ! isRetryNetworkErrorEnabled ? { retryRequest : true } : await this . _checkNetworkConnectivity ( useFetcher ) ;
296- connectivityTestError = connectivity . connectivityTestError ? this . scrubErrorDetail ( connectivity . connectivityTestError ) : undefined ;
301+ connectivityTestError = connectivity . connectivityTestError ? this . scrubErrorDetail ( connectivity . connectivityTestError , usernameToScrub ) : undefined ;
297302 if ( connectivity . retryRequest ) {
298303 streamRecorder . callback ( '' , 0 , { text : '' , retryReason : 'network_error' } ) ;
299304 const retryResult = await this . fetchMany ( {
@@ -412,6 +417,7 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
412417 baseTelemetryData : TelemetryData ,
413418 finishedCb : FinishedCallback ,
414419 secretKey : string | undefined ,
420+ copilotToken : CopilotToken ,
415421 location : ChatLocation ,
416422 ourRequestId : string ,
417423 nChoices : number | undefined ,
@@ -429,7 +435,7 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
429435 this . _logService . debug ( `modelMaxResponseTokens ${ request . max_tokens ?? 2048 } ` ) ;
430436 this . _logService . debug ( `chat model ${ chatEndpointInfo . model } ` ) ;
431437
432- secretKey ??= ( await this . _authenticationService . getCopilotToken ( ) ) . token ;
438+ secretKey ??= copilotToken . token ;
433439 if ( ! secretKey ) {
434440 // If no key is set we error
435441 const urlOrRequestMetadata = stringifyUrlOrRequestMetadata ( chatEndpointInfo . urlOrRequestMetadata ) ;
@@ -1029,7 +1035,7 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
10291035 return { type : ChatFetchResponseType . Failed , reason, requestId, serverRequestId } ;
10301036 }
10311037
1032- private processError ( err : unknown , requestId : string ) : ChatFetchError {
1038+ private processError ( err : unknown , requestId : string , usernameToScrub : string | undefined ) : ChatFetchError {
10331039 const fetcher = this . _fetcherService ;
10341040 // If we cancelled a network request, we don't want to log an error
10351041 if ( fetcher . isAbortError ( err ) ) {
@@ -1062,7 +1068,7 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
10621068 this . _logService . error ( errorsUtil . fromUnknown ( err ) , `Error on conversation request` ) ;
10631069 this . _telemetryService . sendGHTelemetryException ( err , 'Error on conversation request' ) ;
10641070 const errorDetail = fetcher . getUserMessageForFetcherError ( err ) ;
1065- const scrubbedErrorDetail = this . scrubErrorDetail ( errorDetail ) ;
1071+ const scrubbedErrorDetail = this . scrubErrorDetail ( errorDetail , usernameToScrub ) ;
10661072 if ( fetcher . isInternetDisconnectedError ( err ) ) {
10671073 return {
10681074 type : ChatFetchResponseType . NetworkError ,
@@ -1090,14 +1096,12 @@ export class ChatMLFetcherImpl extends AbstractChatMLFetcher {
10901096 }
10911097 }
10921098
1093- private scrubErrorDetail ( errorDetail : string ) {
1094- errorDetail = errorDetail . replaceAll ( / ( l o g g e d i n a s ) ( [ ^ \s ] + ) / ig, '$1<login>' ) ;
1095- const username = this . _authenticationService . copilotToken ?. username ;
1096- if ( ! username ) {
1097- return errorDetail ;
1099+ private scrubErrorDetail ( errorDetail : string , usernameToScrub : string | undefined ) {
1100+ if ( usernameToScrub ) {
1101+ const regex = new RegExp ( escapeRegExpCharacters ( usernameToScrub ) , 'ig' ) ;
1102+ errorDetail = errorDetail . replaceAll ( regex , '<login>' ) ;
10981103 }
1099- const regex = new RegExp ( escapeRegExpCharacters ( username ) , 'ig' ) ;
1100- return errorDetail . replaceAll ( regex , '<login>' ) ;
1104+ return errorDetail . replaceAll ( / (?< = l o g g e d i n a s ) (? ! < l o g i n > ) [ ^ \s ] + / ig, '!<login>!' ) ; // marking fallback with !
11011105 }
11021106}
11031107
0 commit comments