Skip to content

Commit 7ef6d0c

Browse files
committed
Ensure notebook tools are recommended when attempting to use Python tools for Notebooks
1 parent 020f203 commit 7ef6d0c

File tree

5 files changed

+39
-6
lines changed

5 files changed

+39
-6
lines changed

src/client/chat/configurePythonEnvTool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { PythonExtension, ResolvedEnvironment } from '../api/types';
1919
import { IServiceContainer } from '../ioc/types';
2020
import { ICodeExecutionService } from '../terminals/types';
2121
import { TerminalCodeExecutionProvider } from '../terminals/codeExecution/terminalCodeExecution';
22-
import { getEnvironmentDetails, raceCancellationError } from './utils';
22+
import { getEnvironmentDetails, raceCancellationError, throwIfNotebookUri } from './utils';
2323
import { resolveFilePath } from './utils';
2424
import { IRecommendedEnvironmentService } from '../interpreter/configuration/types';
2525
import { ITerminalHelper } from '../common/terminal/types';
@@ -135,6 +135,7 @@ export class ConfigurePythonEnvTool implements LanguageModelTool<IResourceRefere
135135
return {};
136136
}
137137
const resource = resolveFilePath(options.input.resourcePath);
138+
throwIfNotebookUri(resource);
138139
const recommededEnv = await this.recommendedEnvService.getRecommededEnvironment(resource);
139140
// Already selected workspace env, hence nothing to do.
140141
if (recommededEnv?.reason === 'workspaceUserSelected' && workspace.workspaceFolders?.length) {

src/client/chat/getExecutableTool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { PythonExtension } from '../api/types';
1616
import { IServiceContainer } from '../ioc/types';
1717
import { ICodeExecutionService } from '../terminals/types';
1818
import { TerminalCodeExecutionProvider } from '../terminals/codeExecution/terminalCodeExecution';
19-
import { getEnvDisplayName, getEnvironmentDetails, raceCancellationError } from './utils';
19+
import { getEnvDisplayName, getEnvironmentDetails, raceCancellationError, throwIfNotebookUri } from './utils';
2020
import { resolveFilePath } from './utils';
2121
import { traceError } from '../logging';
2222
import { ITerminalHelper } from '../common/terminal/types';
@@ -72,6 +72,7 @@ export class GetExecutableTool implements LanguageModelTool<IResourceReference>
7272
token: CancellationToken,
7373
): Promise<PreparedToolInvocation> {
7474
const resourcePath = resolveFilePath(options.input.resourcePath);
75+
throwIfNotebookUri(resourcePath);
7576
const envName = await raceCancellationError(getEnvDisplayName(this.discovery, resourcePath, this.api), token);
7677
return {
7778
invocationMessage: envName

src/client/chat/getPythonEnvTool.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { IServiceContainer } from '../ioc/types';
1717
import { ICodeExecutionService } from '../terminals/types';
1818
import { TerminalCodeExecutionProvider } from '../terminals/codeExecution/terminalCodeExecution';
1919
import { IProcessServiceFactory, IPythonExecutionFactory } from '../common/process/types';
20-
import { getEnvironmentDetails, raceCancellationError } from './utils';
20+
import { getEnvironmentDetails, raceCancellationError, throwIfNotebookUri } from './utils';
2121
import { resolveFilePath } from './utils';
2222
import { getPythonPackagesResponse } from './listPackagesTool';
2323
import { ITerminalHelper } from '../common/terminal/types';
@@ -91,9 +91,11 @@ export class GetEnvironmentInfoTool implements LanguageModelTool<IResourceRefere
9191
}
9292

9393
async prepareInvocation?(
94-
_options: LanguageModelToolInvocationPrepareOptions<IResourceReference>,
94+
options: LanguageModelToolInvocationPrepareOptions<IResourceReference>,
9595
_token: CancellationToken,
9696
): Promise<PreparedToolInvocation> {
97+
const resourcePath = resolveFilePath(options.input.resourcePath);
98+
throwIfNotebookUri(resourcePath);
9799
return {
98100
invocationMessage: l10n.t('Fetching Python environment information'),
99101
};

src/client/chat/installPackagesTool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from 'vscode';
1515
import { PythonExtension } from '../api/types';
1616
import { IServiceContainer } from '../ioc/types';
17-
import { getEnvDisplayName, raceCancellationError } from './utils';
17+
import { getEnvDisplayName, raceCancellationError, throwIfNotebookUri } from './utils';
1818
import { resolveFilePath } from './utils';
1919
import { IModuleInstaller } from '../common/installer/types';
2020
import { ModuleInstallerType } from '../pythonEnvironments/info';
@@ -84,6 +84,7 @@ export class InstallPackagesTool implements LanguageModelTool<IInstallPackageArg
8484
): Promise<PreparedToolInvocation> {
8585
const resourcePath = resolveFilePath(options.input.resourcePath);
8686
const packageCount = options.input.packageList.length;
87+
throwIfNotebookUri(resourcePath);
8788

8889
const envName = await raceCancellationError(getEnvDisplayName(this.discovery, resourcePath, this.api), token);
8990
let title = '';

src/client/chat/utils.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
import { CancellationError, CancellationToken, Uri, workspace } from 'vscode';
4+
import { CancellationError, CancellationToken, extensions, NotebookDocument, Uri, workspace } from 'vscode';
55
import { IDiscoveryAPI } from '../pythonEnvironments/base/locator';
66
import { PythonExtension, ResolvedEnvironment } from '../api/types';
77
import { ITerminalHelper, TerminalShellType } from '../common/terminal/types';
88
import { TerminalCodeExecutionProvider } from '../terminals/codeExecution/terminalCodeExecution';
99
import { Conda } from '../pythonEnvironments/common/environmentManagers/conda';
10+
import { JUPYTER_EXTENSION_ID } from '../common/constants';
1011

1112
export function resolveFilePath(filepath?: string): Uri | undefined {
1213
if (!filepath) {
@@ -115,3 +116,30 @@ async function getCondaRunCommand(environment: ResolvedEnvironment) {
115116
}
116117
return { command: cmd[0], args: cmd.slice(1) };
117118
}
119+
120+
export function throwIfNotebookUri(resource: Uri | undefined) {
121+
if (!resource) {
122+
return;
123+
}
124+
const notebook = workspace.notebookDocuments.find(
125+
(doc) => doc.uri.toString() === resource.toString() || doc.uri.path === resource.path,
126+
);
127+
if ((notebook && isJupyterNotebook(notebook)) || resource.path.toLowerCase().endsWith('.ipynb')) {
128+
const isJupyterExtensionAvailable = extensions.getExtension(JUPYTER_EXTENSION_ID);
129+
if (isJupyterExtensionAvailable) {
130+
throw new Error(
131+
'This tool cannot be used for Jupyter Notebooks, try using notebook specific tools instead.',
132+
);
133+
}
134+
throw new Error(
135+
`This tool cannot be used for Jupyter Notebooks. Install the Jupyter Extension (${JUPYTER_EXTENSION_ID}) & try using notebook specific tools instead.`,
136+
);
137+
}
138+
if (notebook) {
139+
throw new Error('This tool cannot be used for Notebooks, try using notebook specific tools instead.');
140+
}
141+
}
142+
143+
function isJupyterNotebook(notebook: NotebookDocument) {
144+
return notebook.notebookType === 'jupyter-notebook';
145+
}

0 commit comments

Comments
 (0)