Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,9 @@
"displayName": "Get Python Environment Information",
"modelDescription": "Provides details about the Python environment for a specified file or workspace, including environment type, Python version, run command, and installed packages with their versions. Use this tool to determine the correct command for executing Python code in this workspace.",
"toolReferenceName": "pythonGetEnvironmentInfo",
"tags": [],
"tags": [
"ms-python.python"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be used elsewhere.

],
"icon": "$(files)",
"canBeReferencedInPrompt": true,
"inputSchema": {
Expand All @@ -533,9 +535,12 @@
{
"name": "python_install_package",
"displayName": "Install Python Package",
"userDescription": "Installs Python packages in the given workspace",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wonder if its worth clarifying that it isn't the workspace but instead installed in the environment connected to the resource provided as an arg? Or do we think that will be too confusing? (also noticing the modelDescription is similar so this is likely a mistake I made earlier

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't do that for the model? hence not sure how useful it would be.
I would have thought more useful messages/info should be for the model vs user.
Are you suggesting we change this for the model as well.

As for user, I'm not sure it will make much sense to the user. I'm assuming the user would expect that behaviour out of the box.

"modelDescription": "Installs Python packages in the given workspace. Use this tool to install packages in the user's chosen environment.",
"toolReferenceName": "pythonInstallPackage",
"tags": [],
"tags": [
"ms-python.python"
],
"icon": "$(package)",
"canBeReferencedInPrompt": true,
"inputSchema": {
Expand Down Expand Up @@ -607,4 +612,4 @@
"vscode-jsonrpc": "^9.0.0-next.5",
"which": "^4.0.0"
}
}
}
48 changes: 41 additions & 7 deletions src/features/copilotTools.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
CancellationToken,
l10n,
LanguageModelTextPart,
LanguageModelTool,
LanguageModelToolInvocationOptions,
Expand Down Expand Up @@ -130,9 +131,8 @@ export class GetEnvironmentInfoTool implements LanguageModelTool<IResourceRefere
_options: LanguageModelToolInvocationPrepareOptions<IResourceReference>,
_token: CancellationToken,
): Promise<PreparedToolInvocation> {
const message = 'Preparing to fetch Python environment information...';
return {
invocationMessage: message,
invocationMessage: l10n.t('Fetching Python environment information'),
};
}
}
Expand All @@ -141,6 +141,7 @@ function BuildEnvironmentInfoContent(envInfo: EnvironmentInfo): LanguageModelTex
// Create a formatted string that looks like JSON but preserves comments
let envTypeDescriptor: string = `This environment is managed by ${envInfo.type} environment manager. Use the install tool to install packages into this environment.`;

// TODO: If this is setup as python.defaultInterpreterPath, then do not include this message.
if (envInfo.type === 'system') {
envTypeDescriptor =
'System pythons are pythons that ship with the OS or are installed globally. These python installs may be used by the OS for running services and core functionality. Confirm with the user before installing packages into this environment, as it can lead to issues with any services on the OS.';
Expand Down Expand Up @@ -242,13 +243,46 @@ export class InstallPackageTool implements LanguageModelTool<IInstallPackageInpu
options: LanguageModelToolInvocationPrepareOptions<IInstallPackageInput>,
_token: CancellationToken,
): Promise<PreparedToolInvocation> {
const packageList = options.input.packageList || [];
const packageCount = packageList.length;
const packageText = packageCount === 1 ? 'package' : 'packages';
const message = `Preparing to install Python ${packageText}: ${packageList.join(', ')}...`;
const workspacePath = options.input.resourcePath ? Uri.file(options.input.resourcePath) : undefined;

const packageCount = options.input.packageList.length;
let envName = '';
try {
const environment = await this.api.getEnvironment(workspacePath);
envName = environment?.displayName || '';
} catch {
//
}

let title = '';
let invocationMessage = '';
const message =
packageCount === 1
? ''
: l10n.t(`The following packages will be installed: {0}`, options.input.packageList.sort().join(', '));
if (envName) {
title =
packageCount === 1
? l10n.t(`Install {0} in {1}?`, options.input.packageList[0], envName)
: l10n.t(`Install packages in {0}?`, envName);
invocationMessage =
packageCount === 1
? l10n.t(`Installing {0} in {1}`, options.input.packageList[0], envName)
: l10n.t(`Installing packages {0} in {1}`, options.input.packageList.sort().join(', '), envName);
} else {
title =
options.input.packageList.length === 1
? l10n.t(`Install Python package '{0}'?`, options.input.packageList[0])
: l10n.t(`Install Python packages?`);
invocationMessage =
packageCount === 1
? l10n.t(`Installing Python package '{0}'`, options.input.packageList[0])
: l10n.t(`Installing Python packages: {0}`, options.input.packageList.sort().join(', '));
}

return {
invocationMessage: message,
confirmationMessages: { title, message },
invocationMessage,
};
}
}