From 97ebe00eab50feab784f7a6cb449cf0c2bf464ec Mon Sep 17 00:00:00 2001 From: Dhruvi Sompura Date: Fri, 31 Jan 2025 12:07:13 -0800 Subject: [PATCH] Display active runtime metadata in console pane (#6156) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses #5999 Adds a new feature flag called `positron.multipleConsoleSessions`. When the feature flag is on users can now view details for an active session by clicking on the new info icon button that lives in the console pane action bar. A modal popup will render, containing the details of the session, such as name, state, id, interpreter path, and environment management tool. The popup provides a link to the session logs in the output pane. When clicked, the user is taken to the output pane and shown the kernel channel for their interpreter. This is a first pass for the info panel - additional information may be added based off feedback! Follow up work to add additional links to other channels is covered in #6149. ### Release Notes #### New Features - N/A #### Bug Fixes - N/A ### QA Notes - [ ] Verify the info button is only shown when the feature flag is on and there is an active session for the console instance - Note: An issue has been noted where the popup is not rendered if the console pane height is smaller than the height of the popup (#3061) - [ ] Verify the session status shown in the popup updates in real time ### Screenshots **Feature Flag** Screenshot 2025-01-29 at 2 19 30 PM **Popup** Screenshot 2025-01-29 at 4 38 16 PM **Real-Time Session State Updates** https://github.com/user-attachments/assets/16b0b81f-7b48-43d0-9f54-047e6e2af4be --- .../browser/components/actionBar.tsx | 4 + .../components/consoleInstanceInfoButton.css | 32 +++++ .../components/consoleInstanceInfoButton.tsx | 135 ++++++++++++++++++ .../browser/components/runtimeSession.tsx | 4 +- .../browser/components/runtimeSessionCard.tsx | 4 +- ...itronMultipleConsoleSessionsFeatureFlag.ts | 47 ++++++ 6 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 src/vs/workbench/contrib/positronConsole/browser/components/consoleInstanceInfoButton.css create mode 100644 src/vs/workbench/contrib/positronConsole/browser/components/consoleInstanceInfoButton.tsx create mode 100644 src/vs/workbench/services/runtimeSession/common/positronMultipleConsoleSessionsFeatureFlag.ts diff --git a/src/vs/workbench/contrib/positronConsole/browser/components/actionBar.tsx b/src/vs/workbench/contrib/positronConsole/browser/components/actionBar.tsx index 11b62373717..575fe2bfd84 100644 --- a/src/vs/workbench/contrib/positronConsole/browser/components/actionBar.tsx +++ b/src/vs/workbench/contrib/positronConsole/browser/components/actionBar.tsx @@ -25,6 +25,8 @@ import { PositronConsoleState } from '../../../../services/positronConsole/brows import { RuntimeExitReason, RuntimeState } from '../../../../services/languageRuntime/common/languageRuntimeService.js'; import { ILanguageRuntimeSession, RuntimeStartMode } from '../../../../services/runtimeSession/common/runtimeSessionService.js'; import { ConsoleInstanceMenuButton } from './consoleInstanceMenuButton.js'; +import { multipleConsoleSessionsFeatureEnabled } from '../../../../services/runtimeSession/common/positronMultipleConsoleSessionsFeatureFlag.js'; +import { ConsoleInstanceInfoButton } from './consoleInstanceInfoButton.js'; /** * Constants. @@ -101,6 +103,7 @@ export const ActionBar = (props: ActionBarProps) => { // Constants. const showDeveloperUI = IsDevelopmentContext.getValue(positronConsoleContext.contextKeyService); + const multiSessionsEnabled = multipleConsoleSessionsFeatureEnabled(positronConsoleContext.configurationService); // State hooks. const [activePositronConsoleInstance, setActivePositronConsoleInstance] = @@ -382,6 +385,7 @@ export const ActionBar = (props: ActionBarProps) => { ariaLabel={positronRestartConsole} onPressed={restartConsoleHandler} /> + {multiSessionsEnabled && } {showDeveloperUI && { + // Hooks. + const positronConsoleContext = usePositronConsoleContext(); + + // Reference hooks. + const ref = useRef(undefined!); + + const handlePressed = () => { + if (!positronConsoleContext.activePositronConsoleInstance) { + return; + } + + // Create the renderer. + const renderer = new PositronModalReactRenderer({ + keybindingService: positronConsoleContext.keybindingService, + layoutService: positronConsoleContext.workbenchLayoutService, + container: positronConsoleContext.workbenchLayoutService.getContainer(DOM.getWindow(ref.current)), + parent: ref.current + }); + + renderer.render( + + ); + } + + // Render. + return ( + + ) +}; + +interface ConsoleInstanceInfoModalPopupProps { + anchorElement: HTMLElement; + renderer: PositronModalReactRenderer; + session: ILanguageRuntimeSession; +} + +const ConsoleInstanceInfoModalPopup = (props: ConsoleInstanceInfoModalPopupProps) => { + const [sessionState, setSessionState] = useState(() => props.session.getRuntimeState()); + + // Main useEffect hook. + useEffect(() => { + const disposableStore = new DisposableStore(); + disposableStore.add(props.session.onDidChangeRuntimeState(state => { + setSessionState(state); + })); + return () => disposableStore.dispose(); + }, []); + + const showKernelOutputChannelClickHandler = () => { + props.session.showOutput(); + } + + // Render. + return ( + +
+
+

{props.session.metadata.sessionName}

+
+

+ {(() => localize( + 'positron.console.info.sessionId', 'Session ID: {0}', + props.session.sessionId + ))()} +

+

{(() => localize( + 'positron.console.info.state', 'State: {0}', + sessionState))()} +

+
+
+

{(() => localize( + 'positron.console.info.runtimePath', 'Path: {0}', + props.session.runtimeMetadata.runtimePath))()} +

+

{(() => localize( + 'positron.console.info.runtimeSource', 'Source: {0}', + props.session.runtimeMetadata.runtimeSource))()} +

+
+
+
+ + {showKernelOutputChannel} + +
+
+
+ ) +}; diff --git a/src/vs/workbench/contrib/positronRuntimeSessions/browser/components/runtimeSession.tsx b/src/vs/workbench/contrib/positronRuntimeSessions/browser/components/runtimeSession.tsx index 17ad2c44b68..07b8abd8160 100644 --- a/src/vs/workbench/contrib/positronRuntimeSessions/browser/components/runtimeSession.tsx +++ b/src/vs/workbench/contrib/positronRuntimeSessions/browser/components/runtimeSession.tsx @@ -34,7 +34,7 @@ interface RuntimeSessionProps { */ export const RuntimeSession = (props: RuntimeSessionProps) => { - const [sessionState, setSessionState] = useState(props.session.getRuntimeState()); + const [sessionState, setSessionState] = useState(() => props.session.getRuntimeState()); const [expanded, setExpanded] = useState(false); // Main useEffect hook. @@ -44,7 +44,7 @@ export const RuntimeSession = (props: RuntimeSessionProps) => { setSessionState(state); })); return () => disposableStore.dispose(); - }); + }, []); // Render. return ( diff --git a/src/vs/workbench/contrib/positronRuntimeSessions/browser/components/runtimeSessionCard.tsx b/src/vs/workbench/contrib/positronRuntimeSessions/browser/components/runtimeSessionCard.tsx index 72856743388..a76b49a3700 100644 --- a/src/vs/workbench/contrib/positronRuntimeSessions/browser/components/runtimeSessionCard.tsx +++ b/src/vs/workbench/contrib/positronRuntimeSessions/browser/components/runtimeSessionCard.tsx @@ -30,7 +30,7 @@ interface runtimeSessionCardProps { */ export const RuntimeSessionCard = (props: runtimeSessionCardProps) => { - const [sessionState, setSessionState] = useState(props.session.getRuntimeState()); + const [sessionState, setSessionState] = useState(() => props.session.getRuntimeState()); const shutdownSession = () => { props.session.shutdown(RuntimeExitReason.Shutdown); @@ -59,7 +59,7 @@ export const RuntimeSessionCard = (props: runtimeSessionCardProps) => { setSessionState(state); })); return () => disposableStore.dispose(); - }); + }, []); return ( diff --git a/src/vs/workbench/services/runtimeSession/common/positronMultipleConsoleSessionsFeatureFlag.ts b/src/vs/workbench/services/runtimeSession/common/positronMultipleConsoleSessionsFeatureFlag.ts new file mode 100644 index 00000000000..ca91127d8a3 --- /dev/null +++ b/src/vs/workbench/services/runtimeSession/common/positronMultipleConsoleSessionsFeatureFlag.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (C) 2025 Posit Software, PBC. All rights reserved. + * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from '../../../../nls.js'; +import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js'; +import { ConfigurationScope, Extensions, IConfigurationRegistry } from '../../../../platform/configuration/common/configurationRegistry.js'; +import { Registry } from '../../../../platform/registry/common/platform.js'; +import { positronConfigurationNodeBase } from '../../languageRuntime/common/languageRuntime.js'; + +// Key for the multiple sessions setting +export const USE_POSITRON_MULTIPLE_CONSOLE_SESSIONS_CONFIG_KEY = + 'positron.multipleConsoleSessions'; + +/** + * Retrieves the value of the configuration setting that determines whether to enable + * multiple sessions feature. + * @param configurationService The configuration service + * @returns Whether to enablet the multiple sessions feature + */ +export function multipleConsoleSessionsFeatureEnabled( + configurationService: IConfigurationService +) { + return Boolean( + configurationService.getValue(USE_POSITRON_MULTIPLE_CONSOLE_SESSIONS_CONFIG_KEY) + ); +} + +// Register the configuration setting +const configurationRegistry = Registry.as( + Extensions.Configuration +); +configurationRegistry.registerConfiguration({ + ...positronConfigurationNodeBase, + scope: ConfigurationScope.MACHINE_OVERRIDABLE, + properties: { + [USE_POSITRON_MULTIPLE_CONSOLE_SESSIONS_CONFIG_KEY]: { + type: 'boolean', + default: false, + markdownDescription: localize( + 'positron.enableMultipleConsoleSessionsFeature', + '**CAUTION**: Enable experimental Positron multiple console sessions features which may result in unexpected behaviour. Please restart Positron if you change this option.' + ), + }, + }, +});