Skip to content

Commit b1c67ca

Browse files
authored
Cleanup scrubbing (#2205)
1 parent b1b7aea commit b1c67ca

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

src/extension/prompt/node/chatMLFetcher.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Raw } from '@vscode/prompt-tsx';
77
import { ClientHttp2Stream } from 'http2';
88
import type { CancellationToken } from 'vscode';
99
import { IAuthenticationService } from '../../../platform/authentication/common/authentication';
10+
import { CopilotToken } from '../../../platform/authentication/common/copilotToken';
1011
import { FetchStreamRecorder, IChatMLFetcher, IFetchMLOptions, Source } from '../../../platform/chat/common/chatMLFetcher';
1112
import { IChatQuotaService } from '../../../platform/chat/common/chatQuotaService';
1213
import { ChatFetchError, ChatFetchResponseType, ChatFetchRetriableError, ChatLocation, ChatResponse, ChatResponses } from '../../../platform/chat/common/commonTypes';
@@ -25,6 +26,7 @@ import { sendEngineMessagesTelemetry } from '../../../platform/networking/node/c
2526
import { sendCommunicationErrorTelemetry } from '../../../platform/networking/node/stream';
2627
import { ChatFailKind, ChatRequestCanceled, ChatRequestFailed, ChatResults, FetchResponseKind } from '../../../platform/openai/node/fetch';
2728
import { IRequestLogger } from '../../../platform/requestLogger/node/requestLogger';
29+
import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService';
2830
import { ITelemetryService, TelemetryProperties } from '../../../platform/telemetry/common/telemetry';
2931
import { TelemetryData } from '../../../platform/telemetry/common/telemetryData';
3032
import { calculateLineRepetitionStats, isRepetitive } from '../../../util/common/anomalyDetection';
@@ -37,7 +39,6 @@ import { generateUuid } from '../../../util/vs/base/common/uuid';
3739
import { isBYOKModel } from '../../byok/node/openAIEndpoint';
3840
import { EXTENSION_ID } from '../../common/constants';
3941
import { ChatMLFetcherTelemetrySender as Telemetry } from './chatMLFetcherTelemetry';
40-
import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService';
4142

4243
export 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(/(logged in as )([^\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(/(?<=logged in as )(?!<login>)[^\s]+/ig, '!<login>!'); // marking fallback with !
11011105
}
11021106
}
11031107

0 commit comments

Comments
 (0)