Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/requestLogger/node/requestLogger.ts
13401 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type { RequestMetadata } from '@vscode/copilot-api';
7
import { HTMLTracer, IChatEndpointInfo, RenderPromptResult } from '@vscode/prompt-tsx';
8
import { AsyncLocalStorage } from 'async_hooks';
9
import type { Event } from 'vscode';
10
import type { LanguageModelToolResult2 } from '../../../vscodeTypes';
11
import type { IModelAPIResponse } from '../../endpoint/common/endpointProvider';
12
import { CapturingToken } from '../common/capturingToken';
13
import { ILoggedPendingRequest, IRequestLogger, LoggedInfo, LoggedRequest, PendingLoggedChatRequest } from '../common/requestLogger';
14
import { Disposable } from '../../../util/vs/base/common/lifecycle';
15
import { IChatEndpoint } from '../../../platform/networking/common/networking';
16
17
const requestLogStorage = new AsyncLocalStorage<CapturingToken>();
18
19
/**
20
* Correlation map for preserving CapturingToken across IPC boundaries.
21
*
22
* When requests cross the VS Code IPC boundary (e.g., BYOK providers),
23
* AsyncLocalStorage context is lost. This map allows correlating requests
24
* by storing the token before IPC and retrieving it on the other side.
25
*/
26
const capturingTokenCorrelationMap = new Map<string, CapturingToken>();
27
28
/**
29
* Get the current CapturingToken from AsyncLocalStorage.
30
* Returns undefined if not within a captureInvocation context.
31
*/
32
export function getCurrentCapturingToken(): CapturingToken | undefined {
33
return requestLogStorage.getStore();
34
}
35
36
/**
37
* Store the current CapturingToken with a correlation ID for cross-IPC retrieval.
38
* Call this before making a request that will cross IPC boundaries.
39
*/
40
export function storeCapturingTokenForCorrelation(correlationId: string): void {
41
const token = requestLogStorage.getStore();
42
if (token) {
43
capturingTokenCorrelationMap.set(correlationId, token);
44
}
45
}
46
47
/**
48
* Retrieve and remove a CapturingToken by correlation ID.
49
* Returns undefined if no token was stored for this ID.
50
*/
51
export function retrieveCapturingTokenByCorrelation(correlationId: string): CapturingToken | undefined {
52
const token = capturingTokenCorrelationMap.get(correlationId);
53
if (token) {
54
capturingTokenCorrelationMap.delete(correlationId);
55
}
56
return token;
57
}
58
59
/**
60
* Run a function within a CapturingToken context without going through IRequestLogger.
61
* Used to restore context after IPC boundary crossing.
62
*/
63
export function runWithCapturingToken<T>(token: CapturingToken, fn: () => T): T {
64
return requestLogStorage.run(token, fn);
65
}
66
67
export abstract class AbstractRequestLogger extends Disposable implements IRequestLogger {
68
declare _serviceBrand: undefined;
69
70
public get promptRendererTracing() {
71
return false;
72
}
73
74
public captureInvocation<T>(request: CapturingToken, fn: () => Promise<T>): Promise<T> {
75
return requestLogStorage.run(request, () => fn());
76
}
77
78
public abstract logModelListCall(id: string, requestMetadata: RequestMetadata, models: IModelAPIResponse[]): void;
79
public abstract logToolCall(id: string, name: string | undefined, args: unknown, response: LanguageModelToolResult2): void;
80
81
public logContentExclusionRules(_repos: string[], _rules: { patterns: string[]; ifAnyMatch: string[]; ifNoneMatch: string[] }[], _durationMs: number): void {
82
// no-op by default; concrete implementations can override
83
}
84
85
public logChatRequest(debugName: string, chatEndpoint: IChatEndpoint, chatParams: ILoggedPendingRequest): PendingLoggedChatRequest {
86
return new PendingLoggedChatRequest(this, debugName, chatEndpoint, chatParams);
87
}
88
89
public abstract addPromptTrace(elementName: string, endpoint: IChatEndpointInfo, result: RenderPromptResult, trace: HTMLTracer): void;
90
public abstract addEntry(entry: LoggedRequest): void;
91
public abstract getRequests(): LoggedInfo[];
92
public abstract getRequestById(id: string): LoggedInfo | undefined;
93
abstract onDidChangeRequests: Event<void>;
94
95
public enableWorkspaceEditTracing(): void {
96
// no-op by default; concrete implementations can override
97
}
98
99
public disableWorkspaceEditTracing(): void {
100
// no-op by default; concrete implementations can override
101
}
102
103
/** Current request being made to the LM. */
104
protected get currentRequest() {
105
return requestLogStorage.getStore();
106
}
107
}
108
109