Skip to content

Commit ea217c6

Browse files
committed
fix feedback
1 parent d637f32 commit ea217c6

4 files changed

Lines changed: 52 additions & 1 deletion

File tree

src/client/chat/configurePythonEnvTool.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
IResourceReference,
2424
isCancellationError,
2525
raceCancellationError,
26+
waitForActiveEnvironmentChange,
2627
} from './utils';
2728
import { ITerminalHelper } from '../common/terminal/types';
2829
import { IRecommendedEnvironmentService } from '../interpreter/configuration/types';
@@ -133,7 +134,13 @@ export class ConfigurePythonEnvTool extends BaseTool<IConfigurePythonEnvToolArgu
133134
token: CancellationToken,
134135
): Promise<LanguageModelToolResult> {
135136
traceVerbose(`${ConfigurePythonEnvTool.toolName}: setting environment directly from pythonPath: ${pythonPath}`);
137+
// Subscribe to the change event BEFORE triggering the update so we don't miss it.
138+
// updateActiveEnvironmentPath only persists the setting; the active interpreter switch
139+
// is asynchronous, so we wait for the event before resolving env details to avoid
140+
// returning details for the previously-active interpreter.
141+
const activeChanged = waitForActiveEnvironmentChange(this.api, pythonPath, token);
136142
await raceCancellationError(this.api.updateActiveEnvironmentPath(pythonPath, resource), token);
143+
await raceCancellationError(activeChanged, token);
137144
const envPath = this.api.getActiveEnvironmentPath(resource);
138145
const environment = await raceCancellationError(this.api.resolveEnvironment(envPath), token);
139146
return getEnvDetailsForResponse(

src/client/chat/createVirtualEnvTool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import { hideEnvCreation } from '../pythonEnvironments/creation/provider/hideEnv
4545
import { BaseTool } from './baseTool';
4646

4747
interface ICreateVirtualEnvToolParams extends IResourceReference {
48-
packageList?: string[]; // Added only because we have ability to create a virtual env with list of packages same tool within the in Python Env extension.
48+
packageList?: string[]; // Added only because we have the ability to create a virtual env with a list of packages using the same tool within the Python Env extension.
4949
}
5050

5151
export class CreateVirtualEnvTool extends BaseTool<ICreateVirtualEnvToolParams>

src/client/chat/selectEnvTool.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
getToolResponseIfNotebook,
2727
IResourceReference,
2828
raceCancellationError,
29+
waitForActiveEnvironmentChange,
2930
} from './utils';
3031
import { ITerminalHelper } from '../common/terminal/types';
3132
import { raceTimeout } from '../common/utils/async';
@@ -72,15 +73,23 @@ export class SelectPythonEnvTool extends BaseTool<ISelectPythonEnvToolArguments>
7273
resource: Uri | undefined,
7374
token: CancellationToken,
7475
): Promise<LanguageModelToolResult> {
76+
const notebookResponse = getToolResponseIfNotebook(resource);
77+
if (notebookResponse) {
78+
return notebookResponse;
79+
}
80+
7581
// Fast path: if the caller provided a pythonPath, set it directly without any UI.
7682
if (options.input.pythonPath) {
7783
traceVerbose(
7884
`${SelectPythonEnvTool.toolName}: setting environment directly from pythonPath: ${options.input.pythonPath}`,
7985
);
86+
// Subscribe to the change event BEFORE triggering the update so we don't miss it.
87+
const activeChanged = waitForActiveEnvironmentChange(this.api, options.input.pythonPath, token);
8088
await raceCancellationError(
8189
this.api.updateActiveEnvironmentPath(options.input.pythonPath, resource),
8290
token,
8391
);
92+
await raceCancellationError(activeChanged, token);
8493
const env = await raceCancellationError(
8594
this.api.resolveEnvironment(this.api.getActiveEnvironmentPath(resource)),
8695
token,

src/client/chat/utils.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,41 @@ export function raceCancellationError<T>(promise: Promise<T>, token: Cancellatio
5858
});
5959
}
6060

61+
/**
62+
* Returns a promise that resolves once the active environment path changes to match the
63+
* provided `pythonPath` (matched against either the event's `path` or `id`). Resolves early
64+
* on cancellation or after `timeoutMs` to avoid hanging callers if the event is missed.
65+
* Callers must subscribe via this helper BEFORE invoking `updateActiveEnvironmentPath` to
66+
* avoid a race where the event fires before the listener is attached.
67+
*/
68+
export function waitForActiveEnvironmentChange(
69+
api: PythonExtension['environments'],
70+
pythonPath: string,
71+
token: CancellationToken,
72+
timeoutMs = 5000,
73+
): Promise<void> {
74+
return new Promise<void>((resolve) => {
75+
let settled = false;
76+
const settle = () => {
77+
if (settled) {
78+
return;
79+
}
80+
settled = true;
81+
listener.dispose();
82+
cancelRef.dispose();
83+
clearTimeout(timer);
84+
resolve();
85+
};
86+
const listener = api.onDidChangeActiveEnvironmentPath((e) => {
87+
if (e.path === pythonPath || e.id === pythonPath) {
88+
settle();
89+
}
90+
});
91+
const cancelRef = token.onCancellationRequested(() => settle());
92+
const timer = setTimeout(() => settle(), timeoutMs);
93+
});
94+
}
95+
6196
export async function getEnvDisplayName(
6297
discovery: IDiscoveryAPI,
6398
resource: Uri | undefined,

0 commit comments

Comments
 (0)