From 19135a67ad565a86b4e760247a4df895cb0ef8e8 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Fri, 15 Mar 2024 12:33:48 -0700 Subject: [PATCH] Support requesting kernel runtime states (#15371) * Support requesting kernel runtime states * lint --- package.json | 20 +++++++ src/extension.node.ts | 3 + src/standalone/chat/extesnion.ts | 97 ++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 src/standalone/chat/extesnion.ts diff --git a/package.json b/package.json index 058ae4c2a16..cd37b679c97 100644 --- a/package.json +++ b/package.json @@ -812,6 +812,18 @@ "icon": "$(debug-alt-small)", "enablement": "isWorkspaceTrusted && !jupyter.webExtension", "category": "Jupyter" + }, + { + "command": "jupyter.listPipPackages", + "title": "List Pip Packages", + "enablement": "isWorkspaceTrusted && !jupyter.webExtension", + "category": "Jupyter" + }, + { + "command": "jupyter.listVariables", + "title": "List Variables", + "enablement": "isWorkspaceTrusted && !jupyter.webExtension", + "category": "Jupyter" } ], "submenus": [ @@ -1447,6 +1459,14 @@ { "command": "jupyter.debugCellSymbols", "when": "config.jupyter.executionAnalysis.enabled" + }, + { + "command": "jupyter.listPipPackages", + "when": "false" + }, + { + "command": "jupyter.listVariables", + "when": "false" } ], "debug/variables/context": [ diff --git a/src/extension.node.ts b/src/extension.node.ts index 803e3846be2..60b1c2c07ee 100644 --- a/src/extension.node.ts +++ b/src/extension.node.ts @@ -97,6 +97,7 @@ import { activate as activateExecutionAnalysis, deactivate as deactivateExecutionAnalysis } from './standalone/executionAnalysis/extension'; +import { activate as activateChat, deactivate as deactivateChat } from './standalone/chat/extesnion'; import { setDisposableTracker } from './platform/common/utils/lifecycle'; import { sendTelemetryEvent } from './telemetry'; import { getVSCodeChannel } from './platform/common/application/applicationEnvironment'; @@ -162,6 +163,7 @@ export function deactivate(): Thenable { } deactivateExecutionAnalysis(); + deactivateChat(); return Promise.resolve(); } @@ -202,6 +204,7 @@ async function activateUnsafe( //=============================================== // dynamically load standalone plugins activateExecutionAnalysis(context).then(noop, noop); + activateChat(context).then(noop, noop); const api = buildApi(activationPromise, serviceManager, serviceContainer, context); return [api, activationPromise, serviceContainer]; diff --git a/src/standalone/chat/extesnion.ts b/src/standalone/chat/extesnion.ts new file mode 100644 index 00000000000..9fb67ae6821 --- /dev/null +++ b/src/standalone/chat/extesnion.ts @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import type { KernelMessage } from '@jupyterlab/services'; +import * as vscode from 'vscode'; +import { IKernel, IKernelProvider } from '../../kernels/types'; +import { execCodeInBackgroundThread } from '../api/kernels/backgroundExecution'; +import { ServiceContainer } from '../../platform/ioc/container'; +import { IControllerRegistration } from '../../notebooks/controllers/types'; + +export async function activate(context: vscode.ExtensionContext): Promise { + context.subscriptions.push( + vscode.commands.registerCommand('jupyter.listPipPackages', async (uri) => { + const documentUri = uri ?? vscode.window.activeNotebookEditor?.notebook.uri; + if (documentUri) { + const kernelProvider = ServiceContainer.instance.get(IKernelProvider); + const kernel = await kernelProvider.get(documentUri); + if (kernel) { + const token = new vscode.CancellationTokenSource().token; + try { + const result = await sendPipListRequest(kernel, token); + if (Array.isArray(result.content)) { + return result.content; + } + } catch (_) { + // ignore + } + } + } + + return []; + }) + ); + + context.subscriptions.push( + vscode.commands.registerCommand('jupyter.listVariables', async (uri) => { + const documentUri = uri ?? vscode.window.activeNotebookEditor?.notebook.uri; + + if (!documentUri) { + return []; + } + + const document = vscode.workspace.notebookDocuments.find( + (item) => item.uri.toString() === documentUri.toString() + ); + + if (!document) { + return []; + } + + const controllerRegistry = ServiceContainer.instance.get(IControllerRegistration); + const controller = controllerRegistry.getSelected(document); + if (!controller) { + return []; + } + + const variablesProvider = controller.controller.variableProvider; + + if (!variablesProvider) { + return []; + } + + const token = new vscode.CancellationTokenSource().token; + const variables = variablesProvider.provideVariables( + document, + undefined, + vscode.NotebookVariablesRequestKind.Named, + 0, + token + ); + + const resolvedVariables = []; + for await (const variable of variables) { + resolvedVariables.push(variable.variable); + } + return resolvedVariables; + }) + ); +} + +async function sendPipListRequest(kernel: IKernel, token: vscode.CancellationToken) { + const codeToExecute = `import subprocess +proc = subprocess.Popen(["pip", "list", "--format", "json"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) +stdout, stderr = proc.communicate() +return stdout +`.split('\n'); + + const content = await execCodeInBackgroundThread( + kernel, + codeToExecute, + token + ); + return { content } as KernelMessage.IInspectReplyMsg; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-function +export function deactivate() {}