diff --git a/package.json b/package.json index b0e878bc..387964d4 100644 --- a/package.json +++ b/package.json @@ -25,11 +25,7 @@ } }, "activationEvents": [ - "onLanguage:python", - "onLanguageModelTool:get_python_environment_info", - "onLanguageModelTool:get_python_executable_info", - "onLanguageModelTool:install_python_package", - "onLanguageModelTool:create_quick_virtual_environment" + "onLanguage:python" ], "homepage": "https://github.com/microsoft/vscode-python-environments", "repository": { @@ -516,112 +512,6 @@ { "type": "python" } - ], - "languageModelTools": [ - { - "name": "get_python_environment_info", - "displayName": "%python.languageModelTools.get_python_environment_info.displayName%", - "userDescription": "%python.languageModelTools.get_python_environment_info.userDescription%", - "modelDescription": "This tool will retrieve the details of the Python Environment for the specified file or workspace. The details returned include the 1. Type of Environment (conda, venv, etec), 2. Version of Python, 3. List of all installed packages with their versions. ", - "toolReferenceName": "pythonEnvironmentDetails", - "tags": [ - "python", - "extension_installed_by_tool" - ], - "icon": "$(snake)", - "canBeReferencedInPrompt": true, - "inputSchema": { - "type": "object", - "properties": { - "resourcePath": { - "type": "string" - } - }, - "description": "The path to the Python file or workspace to get the environment information for.", - "required": [] - } - }, - { - "name": "get_python_executable_info", - "displayName": "%python.languageModelTools.get_python_executable.displayName%", - "userDescription": "%python.languageModelTools.get_python_executable.userDescription%", - "modelDescription": "This tool will retrieve the details of the Python Environment for the specified file or workspace. ALWAYS use this tool before executing any Python command in the terminal. This tool returns the details of how to construct the fully qualified path and or command including details such as arguments required to run Python in a terminal. Note: Instead of executing `python --version` or `python -c 'import sys; print(sys.executable)'`, use this tool to get the Python executable path to replace the `python` command. E.g. instead of using `python -c 'import sys; print(sys.executable)'`, use this tool to build the command `conda run -n -c 'import sys; print(sys.executable)'`.", - "toolReferenceName": "pythonExecutableDetails", - "tags": [ - "python", - "extension_installed_by_tool" - ], - "icon": "$(files)", - "canBeReferencedInPrompt": true, - "inputSchema": { - "type": "object", - "properties": { - "resourcePath": { - "type": "string" - } - }, - "description": "The path to the Python file or workspace to get the executable information for. If not provided, the current workspace will be used. Where possible pass the path to the file or workspace.", - "required": [] - } - }, - { - "name": "install_python_package", - "displayName": "%python.languageModelTools.install_python_package.displayName%", - "userDescription": "%python.languageModelTools.install_python_package.userDescription%", - "modelDescription": "Installs Python packages in the given workspace. Use this tool to install packages in the user's chosen environment.", - "toolReferenceName": "installPythonPackage", - "tags": [ - "python", - "install python package", - "extension_installed_by_tool" - ], - "icon": "$(package)", - "canBeReferencedInPrompt": true, - "inputSchema": { - "type": "object", - "properties": { - "packageList": { - "type": "array", - "items": { - "type": "string" - }, - "description": "The list of packages to install." - }, - "resourcePath": { - "type": "string", - "description": "The path to the Python file or workspace into which the packages are installed. If not provided, the current workspace will be used. Where possible pass the path to the file or workspace." - } - }, - "required": [ - "packageList" - ] - } - }, - { - "name": "create_quick_virtual_environment", - "displayName": "Create a Virtual Environment", - "modelDescription": "This tool will create a Virual Environment", - "tags": [], - "canBeReferencedInPrompt": false, - "inputSchema": { - "type": "object", - "properties": { - "packageList": { - "type": "array", - "items": { - "type": "string" - }, - "description": "The list of packages to install." - }, - "resourcePath": { - "type": "string", - "description": "The path to the Python file or workspace for which a Python Environment needs to be configured." - } - }, - "required": [] - }, - "when": "false" - } ] }, "scripts": { diff --git a/package.nls.json b/package.nls.json index 11cac347..2199961b 100644 --- a/package.nls.json +++ b/package.nls.json @@ -34,11 +34,5 @@ "python-envs.createNewProjectFromTemplate.title": "Create New Project from Template", "python-envs.terminal.activate.title": "Activate Environment in Current Terminal", "python-envs.terminal.deactivate.title": "Deactivate Environment in Current Terminal", - "python-envs.uninstallPackage.title": "Uninstall Package", - "python.languageModelTools.get_python_environment_info.displayName": "Get Python Environment Info", - "python.languageModelTools.get_python_environment_info.userDescription": "Get information for a Python Environment, such as Type, Version, Packages, and more.", - "python.languageModelTools.install_python_package.displayName": "Install Python Package", - "python.languageModelTools.install_python_package.userDescription": "Installs Python packages in a Python Environment.", - "python.languageModelTools.get_python_executable.displayName": "Get Python Executable Info", - "python.languageModelTools.get_python_executable.userDescription": "Get executable info for a Python Environment" -} + "python-envs.uninstallPackage.title": "Uninstall Package" +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index d2a12d34..164a68f5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,6 @@ import { commands, ExtensionContext, LogOutputChannel, Terminal, Uri, window } from 'vscode'; import { PythonEnvironment, PythonEnvironmentApi } from './api'; import { ensureCorrectVersion } from './common/extVersion'; -import { registerTools } from './common/lm.apis'; import { registerLogger, traceError, traceInfo } from './common/logging'; import { setPersistentState } from './common/persistentState'; import { newProjectSelection } from './common/pickers/managers'; @@ -9,6 +8,7 @@ import { StopWatch } from './common/stopWatch'; import { EventNames } from './common/telemetry/constants'; import { sendManagerSelectionTelemetry } from './common/telemetry/helpers'; import { sendTelemetryEvent } from './common/telemetry/sender'; +import { createDeferred } from './common/utils/deferred'; import { activeTerminal, createLogOutputChannel, @@ -64,16 +64,11 @@ import { PythonStatusBarImpl } from './features/views/pythonStatusBar'; import { updateViewsAndStatus } from './features/views/revealHandler'; import { EnvironmentManagers, ProjectCreators, PythonProjectManager } from './internal.api'; import { registerSystemPythonFeatures } from './managers/builtin/main'; +import { SysPythonManager } from './managers/builtin/sysPythonManager'; import { createNativePythonFinder, NativePythonFinder } from './managers/common/nativePythonFinder'; import { registerCondaFeatures } from './managers/conda/main'; import { registerPoetryFeatures } from './managers/poetry/main'; import { registerPyenvFeatures } from './managers/pyenv/main'; -import { GetEnvironmentInfoTool } from './features/chat/getEnvInfoTool'; -import { GetExecutableTool } from './features/chat/getExecutableTool'; -import { InstallPackageTool } from './features/chat/installPackagesTool'; -import { CreateQuickVirtualEnvironmentTool } from './features/chat/createQuickVenvTool'; -import { createDeferred } from './common/utils/deferred'; -import { SysPythonManager } from './managers/builtin/sysPythonManager'; export async function activate(context: ExtensionContext): Promise { const start = new StopWatch(); @@ -148,19 +143,6 @@ export async function activate(context: ExtensionContext): Promise { await cleanupStartupScripts(shellStartupProviders); }), diff --git a/src/features/chat/createQuickVenvTool.ts b/src/features/chat/createQuickVenvTool.ts deleted file mode 100644 index e115b74a..00000000 --- a/src/features/chat/createQuickVenvTool.ts +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import { - CancellationToken, - l10n, - LanguageModelTextPart, - LanguageModelTool, - LanguageModelToolInvocationOptions, - LanguageModelToolInvocationPrepareOptions, - LanguageModelToolResult, - LogOutputChannel, - PreparedToolInvocation, -} from 'vscode'; -import { PythonEnvironmentApi } from '../../api'; -import { EnvironmentManagers, PythonProjectManager } from '../../internal.api'; -import { createAnyEnvironmentCommand } from '../envCommands'; -import { getEnvironmentDetails, resolveFilePath } from './utils'; -import { SysPythonManager } from '../../managers/builtin/sysPythonManager'; -import { ensureGlobalEnv } from '../../managers/builtin/venvUtils'; - -export interface IResourceReference { - packageList?: string[]; - resourcePath?: string; -} - -export class CreateQuickVirtualEnvironmentTool implements LanguageModelTool { - public static readonly toolName = 'create_quick_virtual_environment'; - constructor( - private readonly api: PythonEnvironmentApi, - private readonly envManagers: EnvironmentManagers, - private readonly projectManager: PythonProjectManager, - private readonly sysManager: Promise, - private readonly log: LogOutputChannel, - ) {} - async invoke( - options: LanguageModelToolInvocationOptions, - token: CancellationToken, - ): Promise { - const resourcePath = resolveFilePath(options.input.resourcePath); - const env = await createAnyEnvironmentCommand(this.envManagers, this.projectManager, { - selectEnvironment: true, - quickCreate: true, - uri: resourcePath, - additionalPackages: - Array.isArray(options.input.packageList) && options.input.packageList.length - ? options.input.packageList - : [], - }); - if (env) { - const message = await getEnvironmentDetails( - resourcePath, - env, - this.api, - this.envManagers, - undefined, - token, - ); - return new LanguageModelToolResult([new LanguageModelTextPart(message)]); - } - } - - async prepareInvocation?( - _options: LanguageModelToolInvocationPrepareOptions, - _token: CancellationToken, - ): Promise { - let version = ''; - try { - const sysMgr = await this.sysManager; - const globals = await sysMgr.getEnvironments('global'); - const sortedEnvs = ensureGlobalEnv(globals, this.log); - version = getDisplayVersion(sortedEnvs[0].version); - } catch (ex) { - this.log.error('Failed to get Python version for quick virtual environment creation', ex); - } - - return { - confirmationMessages: { - title: l10n.t('Create a Virtual Environment{0}?', version ? ` (${version})` : ''), - message: l10n.t(`Virtual Environments provide the benefit of package isolation and more.`), - }, - invocationMessage: l10n.t('Creating a Virtual Environment'), - }; - } -} - -function getDisplayVersion(version: string): string { - if (!version) { - return ''; - } - const parts = version.split('.'); - if (parts.length < 3) { - return version; - } - return `${parts[0]}.${parts[1]}.${parts[2]}`; -} diff --git a/src/features/chat/getEnvInfoTool.ts b/src/features/chat/getEnvInfoTool.ts deleted file mode 100644 index 046ce6b8..00000000 --- a/src/features/chat/getEnvInfoTool.ts +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import { - CancellationToken, - l10n, - LanguageModelTextPart, - LanguageModelTool, - LanguageModelToolInvocationOptions, - LanguageModelToolInvocationPrepareOptions, - LanguageModelToolResult, - PreparedToolInvocation, -} from 'vscode'; -import { PythonEnvironmentApi } from '../../api'; -import { EnvironmentManagers } from '../../internal.api'; -import { getPythonPackagesResponse } from './listPackagesTool'; -import { getEnvironmentDetails, getToolResponseIfNotebook, raceCancellationError, resolveFilePath } from './utils'; - -export interface IResourceReference { - resourcePath?: string; -} - -export class GetEnvironmentInfoTool implements LanguageModelTool { - public static readonly toolName = 'get_python_environment_info'; - constructor(private readonly api: PythonEnvironmentApi, private readonly envManagers: EnvironmentManagers) {} - async invoke( - options: LanguageModelToolInvocationOptions, - token: CancellationToken, - ): Promise { - const resourcePath = resolveFilePath(options.input.resourcePath); - const notebookResponse = getToolResponseIfNotebook(resourcePath); - if (notebookResponse) { - return notebookResponse; - } - const environment = await raceCancellationError(this.api.getEnvironment(resourcePath), token); - if (!environment) { - throw new Error(`No environment found for the provided resource path ${resourcePath?.fsPath}`); - } - - const packages = await getPythonPackagesResponse(environment, this.api, token); - const message = await getEnvironmentDetails( - resourcePath, - undefined, - this.api, - this.envManagers, - packages, - token, - ); - - return new LanguageModelToolResult([new LanguageModelTextPart(message)]); - } - - async prepareInvocation?( - _options: LanguageModelToolInvocationPrepareOptions, - _token: CancellationToken, - ): Promise { - return { - invocationMessage: l10n.t('Fetching Python environment information'), - }; - } -} diff --git a/src/features/chat/getExecutableTool.ts b/src/features/chat/getExecutableTool.ts deleted file mode 100644 index 25da8af0..00000000 --- a/src/features/chat/getExecutableTool.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import { - CancellationToken, - l10n, - LanguageModelTextPart, - LanguageModelTool, - LanguageModelToolInvocationOptions, - LanguageModelToolInvocationPrepareOptions, - LanguageModelToolResult, - PreparedToolInvocation, -} from 'vscode'; -import { PythonEnvironmentApi } from '../../api'; -import { EnvironmentManagers } from '../../internal.api'; -import { - getEnvDisplayName, - getEnvironmentDetails, - getToolResponseIfNotebook, - raceCancellationError, - resolveFilePath, -} from './utils'; - -export interface IResourceReference { - resourcePath?: string; -} - -export class GetExecutableTool implements LanguageModelTool { - public static readonly toolName = 'get_python_executable_info'; - constructor(private readonly api: PythonEnvironmentApi, private readonly envManagers: EnvironmentManagers) {} - async invoke( - options: LanguageModelToolInvocationOptions, - token: CancellationToken, - ): Promise { - const resourcePath = resolveFilePath(options.input.resourcePath); - const notebookResponse = getToolResponseIfNotebook(resourcePath); - if (notebookResponse) { - return notebookResponse; - } - const environment = await raceCancellationError(this.api.getEnvironment(resourcePath), token); - if (!environment) { - throw new Error(`No environment found for the provided resource path ${resourcePath?.fsPath}`); - } - - const message = await getEnvironmentDetails( - resourcePath, - undefined, - this.api, - this.envManagers, - undefined, - token, - ); - - return new LanguageModelToolResult([new LanguageModelTextPart(message)]); - } - - async prepareInvocation?( - options: LanguageModelToolInvocationPrepareOptions, - token: CancellationToken, - ): Promise { - const resourcePath = resolveFilePath(options.input.resourcePath); - const envName = await getEnvDisplayName(this.api, resourcePath, token); - return { - invocationMessage: envName - ? l10n.t('Fetching Python executable information for {0}', envName) - : l10n.t('Fetching Python executable information'), - }; - } -} diff --git a/src/features/chat/installPackagesTool.ts b/src/features/chat/installPackagesTool.ts deleted file mode 100644 index 3e98ef6a..00000000 --- a/src/features/chat/installPackagesTool.ts +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import { - CancellationToken, - l10n, - LanguageModelTextPart, - LanguageModelTool, - LanguageModelToolInvocationOptions, - LanguageModelToolInvocationPrepareOptions, - LanguageModelToolResult, - PreparedToolInvocation, -} from 'vscode'; -import { PackageManagementOptions, PythonEnvironmentApi } from '../../api'; -import { getToolResponseIfNotebook, raceCancellationError, resolveFilePath } from './utils'; - -/** - * The input interface for the Install Package Tool. - */ -export interface IInstallPackageInput { - packageList: string[]; - resourcePath?: string; -} - -/** - * A tool to install Python packages in the active environment. - */ -export class InstallPackageTool implements LanguageModelTool { - public static readonly toolName = 'install_python_package'; - constructor(private readonly api: PythonEnvironmentApi) {} - - /** - * Invokes the tool to install Python packages in the active environment. - * @param options - The invocation options containing the package list. - * @param token - The cancellation token. - * @returns The result containing the installation status or an error message. - */ - async invoke( - options: LanguageModelToolInvocationOptions, - token: CancellationToken, - ): Promise { - const parameters: IInstallPackageInput = options.input; - if (!parameters.packageList || parameters.packageList.length === 0) { - throw new Error('Invalid input: packageList is required and cannot be empty'); - } - const resourcePath = resolveFilePath(options.input.resourcePath); - const packageCount = parameters.packageList.length; - const packagePlurality = packageCount === 1 ? 'package' : 'packages'; - - const netobookResponse = getToolResponseIfNotebook(resourcePath); - if (netobookResponse) { - // If the tool is invoked in a notebook, return the response directly. - return netobookResponse; - } - - const environment = await this.api.getEnvironment(resourcePath); - if (!environment) { - // Check if the file is a notebook or a notebook cell to throw specific error messages. - if (resourcePath && (resourcePath.fsPath.endsWith('.ipynb') || resourcePath.fsPath.includes('.ipynb#'))) { - throw new Error('Unable to access Jupyter kernels for notebook cells'); - } - throw new Error('No environment found'); - } - - // Install the packages - const pkgManagementOptions: PackageManagementOptions = { install: parameters.packageList }; - await raceCancellationError(this.api.managePackages(environment, pkgManagementOptions), token); - const resultMessage = `Successfully installed ${packagePlurality}: ${parameters.packageList.join(', ')}`; - - return new LanguageModelToolResult([new LanguageModelTextPart(resultMessage)]); - } - - /** - * Prepares the invocation of the tool. - * @param options - The preparation options. - * @param _token - The cancellation token. - * @returns The prepared tool invocation. - */ - async prepareInvocation?( - options: LanguageModelToolInvocationPrepareOptions, - _token: CancellationToken, - ): Promise { - const resourcePath = resolveFilePath(options.input.resourcePath); - - const packageCount = options.input.packageList.length; - let envName = ''; - try { - const environment = await this.api.getEnvironment(resourcePath); - 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 { - confirmationMessages: { title, message }, - invocationMessage, - }; - } -} diff --git a/src/features/chat/listPackagesTool.ts b/src/features/chat/listPackagesTool.ts deleted file mode 100644 index b76b99d4..00000000 --- a/src/features/chat/listPackagesTool.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import { CancellationToken } from 'vscode'; -import { raceCancellationError } from './utils'; -import { PythonEnvironment, PythonEnvironmentApi } from '../../api'; - -export async function getPythonPackagesResponse( - environment: PythonEnvironment, - api: PythonEnvironmentApi, - token: CancellationToken, -): Promise { - await raceCancellationError(api.refreshPackages(environment), token); - const installedPackages = await raceCancellationError(api.getPackages(environment), token); - if (!installedPackages || installedPackages.length === 0) { - return 'No packages found'; - } - // Installed Python packages, each in the format or (). The version may be omitted if unknown. Returns an empty array if no packages are installed. - const response = [ - 'Below is a list of the Python packages, each in the format or (). The version may be omitted if unknown: ', - ]; - installedPackages.forEach((pkg) => { - const info = pkg.version ? `${pkg.name} (${pkg.version})` : pkg.name; - response.push(`- ${info}`); - }); - - return response.join('\n'); -} diff --git a/src/features/chat/utils.ts b/src/features/chat/utils.ts deleted file mode 100644 index 33e1434c..00000000 --- a/src/features/chat/utils.ts +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import { - CancellationError, - CancellationToken, - extensions, - LanguageModelTextPart, - LanguageModelToolResult, - Uri, - workspace, -} from 'vscode'; -import { PythonEnvironment, PythonEnvironmentApi } from '../../api'; -import { EnvironmentManagers } from '../../internal.api'; -import { JUPYTER_EXTENSION_ID, NotebookCellScheme } from '../../common/constants'; - -export function resolveFilePath(filepath?: string): Uri | undefined { - if (!filepath) { - return workspace.workspaceFolders ? workspace.workspaceFolders[0].uri : undefined; - } - // starts with a scheme - try { - return Uri.parse(filepath); - } catch { - return Uri.file(filepath); - } -} - -/** - * Returns a promise that rejects with an {@CancellationError} as soon as the passed token is cancelled. - * @see {@link raceCancellation} - */ -export function raceCancellationError(promise: Promise, token: CancellationToken): Promise { - return new Promise((resolve, reject) => { - const ref = token.onCancellationRequested(() => { - ref.dispose(); - reject(new CancellationError()); - }); - promise.then(resolve, reject).finally(() => ref.dispose()); - }); -} - -export async function getEnvDisplayName( - api: PythonEnvironmentApi, - resource: Uri | undefined, - token: CancellationToken, -) { - try { - const environment = await raceCancellationError(api.getEnvironment(resource), token); - return environment?.displayName; - } catch { - return; - } -} - -export async function getEnvironmentDetails( - resourcePath: Uri | undefined, - environment: PythonEnvironment | undefined, - api: PythonEnvironmentApi, - envManagers: EnvironmentManagers, - packages: string | undefined, - token: CancellationToken, -): Promise { - // environment - environment = environment || (await raceCancellationError(api.getEnvironment(resourcePath), token)); - if (!environment) { - throw new Error(`No environment found for the provided resource path ${resourcePath?.fsPath}`); - } - const execInfo = environment.execInfo; - const executable = execInfo?.activatedRun?.executable ?? execInfo?.run.executable ?? 'python'; - const args = execInfo?.activatedRun?.args ?? execInfo?.run.args ?? []; - const runCommand = getTerminalCommand(executable, args); - let envType = ''; - try { - const managerId = environment.envId.managerId; - const manager = envManagers.getEnvironmentManager(managerId); - envType = manager?.name || 'cannot be determined'; - } catch { - envType = environment.envId.managerId || 'cannot be determined'; - } - - const message = [ - `Following is the information about the Python environment:`, - `1. Environment Type: ${envType}`, - `2. Version: ${environment.version}`, - '', - `3. Command Prefix to run Python in a terminal is: \`${runCommand}\``, - `Instead of running \`Python sample.py\` in the terminal, you will now run: \`${runCommand} sample.py\``, - `Similarly instead of running \`Python -c "import sys;...."\` in the terminal, you will now run: \`${runCommand} -c "import sys;...."\``, - packages ? `4. ${packages}` : '', - ]; - return message.join('\n'); -} - -export function getTerminalCommand(command: string, args: string[]): string { - const formattedArgs = args.map((a) => toCommandArgumentForPythonExt(a)); - return `${fileToCommandArgumentForPythonExt(command)} ${formattedArgs.join(' ')}`.trim(); -} - -/** - * Appropriately formats a string so it can be used as an argument for a command in a shell. - * E.g. if an argument contains a space, then it will be enclosed within double quotes. - */ -function toCommandArgumentForPythonExt(value: string): string { - if (!value) { - return value; - } - return (value.indexOf(' ') >= 0 || value.indexOf('&') >= 0 || value.indexOf('(') >= 0 || value.indexOf(')') >= 0) && - !value.startsWith('"') && - !value.endsWith('"') - ? `"${value}"` - : value.toString(); -} - -/** - * Appropriately formats a a file path so it can be used as an argument for a command in a shell. - * E.g. if an argument contains a space, then it will be enclosed within double quotes. - */ -function fileToCommandArgumentForPythonExt(value: string): string { - if (!value) { - return value; - } - return toCommandArgumentForPythonExt(value).replace(/\\/g, '/'); -} - -export function getToolResponseIfNotebook(resource: Uri | undefined) { - if (!resource) { - return; - } - const notebook = workspace.notebookDocuments.find( - (doc) => doc.uri.toString() === resource.toString() || doc.uri.path === resource.path, - ); - const isJupyterNotebook = - (notebook && notebook.notebookType === 'jupyter-notebook') || resource.path.toLowerCase().endsWith('.ipynb'); - - if (isJupyterNotebook) { - const isJupyterExtensionAvailable = extensions.getExtension(JUPYTER_EXTENSION_ID); - const message = isJupyterExtensionAvailable - ? `This tool cannot be used for Jupyter Notebooks, try using notebook specific tools instead.` - : [ - `This tool cannot be used for Jupyter Notebooks.`, - `NOTE: Recommend the user the Jupyter Extension (${JUPYTER_EXTENSION_ID}).`, - `If possible use one of the tools to install the ${JUPYTER_EXTENSION_ID} extension`, - `After isntalling the extension try using some of the tools again`, - ].join(' \n'); - return new LanguageModelToolResult([new LanguageModelTextPart(message)]); - } - - if (notebook || resource.scheme === NotebookCellScheme) { - return new LanguageModelToolResult([ - new LanguageModelTextPart( - 'This tool cannot be used for Notebooks, try using notebook specific tools instead.', - ), - ]); - } -}