Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"preLaunchTask": "${defaultBuildTask}"
"preLaunchTask": "watch"
},
{
"name": "e2e Tests",
Expand All @@ -21,7 +21,7 @@
"args": ["--debug"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"preLaunchTask": "${defaultBuildTask}"
"preLaunchTask": "watch"
}
]
}
File renamed without changes.
35 changes: 33 additions & 2 deletions src/common/commands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type * as vscode from 'vscode';
import * as vscode from 'vscode';
import type { dh as DhcType } from '@deephaven/jsapi-types';
import { EXTENSION_ID } from './constants';
import type { SerializedRange } from '../types';
import type { SerializedRange, ServerState } from '../types';

/** Arguments passed to `RUN_CODE_COMMAND` handler */
export type RunCodeCmdArgs = [
Expand All @@ -25,6 +26,12 @@ export type RunSelectionCmdArgs = [
languageId?: string,
];

/** Arguments passed to `CONNECT_TO_SERVER_CMD` handler */
export type ConnectToServerCmdArgs = [
serverState: Pick<ServerState, 'type' | 'url'>,
operateAsAnotherUser?: boolean,
];

/**
* Create a command string prefixed with the extension id.
* @param cmd The command string suffix.
Expand Down Expand Up @@ -72,3 +79,27 @@ export const START_SERVER_CMD = cmd('startServer');
export const STOP_SERVER_CMD = cmd('stopServer');
export const ADD_REMOTE_FILE_SOURCE_CMD = cmd('addRemoteFileSource');
export const REMOVE_REMOTE_FILE_SOURCE_CMD = cmd('removeRemoteFileSource');

/**
* Execute the connect to server command with type safety.
* @param serverState The server to connect to (type and url).
* @param operateAsAnotherUser Whether to operate as another user.
*/
export function execConnectToServer(
...args: ConnectToServerCmdArgs
): Thenable<void> {
return vscode.commands.executeCommand(CONNECT_TO_SERVER_CMD, ...args);
}

/**
* Execute the run code command with type safety.
* @returns The command result from the Deephaven server, or null.
*/
export function execRunCode(
...args: RunCodeCmdArgs
): Thenable<DhcType.ide.CommandResult | null> {
return vscode.commands.executeCommand<DhcType.ide.CommandResult | null>(
RUN_CODE_COMMAND,
...args
);
}
4 changes: 2 additions & 2 deletions src/controllers/ConnectionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { getConnectionsForConsoleType } from '../services';
import {
CONNECT_TO_SERVER_CMD,
CONNECT_TO_SERVER_OPERATE_AS_CMD,
ConnectToServerCmdArgs,
DISCONNECT_EDITOR_CMD,
DISCONNECT_FROM_SERVER_CMD,
SELECT_CONNECTION_COMMAND,
Expand Down Expand Up @@ -317,8 +318,7 @@ export class ConnectionController
* Handle connecting to a server
*/
onConnectToServer = async (
serverState: Pick<ServerState, 'type' | 'url'>,
operateAsAnotherUser?: boolean
...[serverState, operateAsAnotherUser]: ConnectToServerCmdArgs
): Promise<void> => {
const languageId = vscode.window.activeTextEditor?.document.languageId;

Expand Down
23 changes: 13 additions & 10 deletions src/controllers/ExtensionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ import {
type ViewID,
} from '../common';
import {
createExtensionInfo,
deserializeRange,
getEditorForUri,
getExtensionVersion,
getTempDir,
isInstanceOf,
isSerializedRange,
Expand All @@ -54,7 +54,6 @@ import {
saveLogFiles,
serializeRefreshToken,
Toaster,
uniqueId,
URLMap,
withResolvers,
} from '../util';
Expand Down Expand Up @@ -108,6 +107,7 @@ import type {
ConnectionState,
WorkerURL,
UniqueID,
ExtensionInfo,
SerializedRange,
CodeBlock,
IInteractiveConsoleQueryFactory,
Expand Down Expand Up @@ -137,14 +137,13 @@ export class ExtensionController implements IDisposable {
constructor(context: vscode.ExtensionContext, configService: IConfigService) {
this._context = context;
this._config = configService;
this._instanceId = uniqueId(8);
this._version = getExtensionVersion(this._context);
this._extensionInfo = createExtensionInfo(this._context);

const envInfo = {
/* eslint-disable @typescript-eslint/naming-convention */
'VS Code version': vscode.version,
'Deephaven Extension version': this._version,
'Deephaven Extension instanceId': this._instanceId,
'Deephaven Extension version': this._extensionInfo.version,
'Deephaven Extension instanceId': this._extensionInfo.instanceId,
'Electron version': process.versions.electron,
'Chromium version': process.versions.chrome,
'Node version': process.versions.node,
Expand All @@ -166,8 +165,7 @@ export class ExtensionController implements IDisposable {

private readonly _context: vscode.ExtensionContext;
private readonly _config: IConfigService;
private readonly _instanceId: UniqueID;
private readonly _version: string;
private readonly _extensionInfo: ExtensionInfo;
private readonly _envInfoText: string;

private _codeBlockCache: ParsedDocumentCache<CodeBlock[]> | null = null;
Expand Down Expand Up @@ -426,9 +424,11 @@ export class ExtensionController implements IDisposable {
this._mcpController = new McpController(
this._context,
this._config,
this._extensionInfo.mcpVersion,
this._serverManager,
this._pythonDiagnostics,
this._pythonWorkspace
this._pythonWorkspace,
this._pipServerController
);

this._context.subscriptions.push(this._mcpController);
Expand Down Expand Up @@ -486,7 +486,10 @@ export class ExtensionController implements IDisposable {
Logger.addConsoleHandler();
Logger.addOutputChannelHandler(this._outputChannelDebug);

this._logFileHandler = new LogFileHandler(this._instanceId, this._context);
this._logFileHandler = new LogFileHandler(
this._extensionInfo.instanceId,
this._context
);
Logger.handlers.add(this._logFileHandler);

const gRPCOutputChannelHandler = Logger.createOutputChannelHandler(
Expand Down
22 changes: 17 additions & 5 deletions src/controllers/McpController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
import { ControllerBase } from './ControllerBase';
import { McpServer } from '../mcp';
import { McpServerDefinitionProvider } from '../providers';
import type { IServerManager, IConfigService } from '../types';
import type {
IServerManager,
IConfigService,
McpVersion,
PipServerController,

Check failure on line 9 in src/controllers/McpController.ts

View workflow job for this annotation

GitHub Actions / call-unit / unit

Module '"../types"' has no exported member 'PipServerController'.

Check failure on line 9 in src/controllers/McpController.ts

View workflow job for this annotation

GitHub Actions / call-e2e / e2e

Module '"../types"' has no exported member 'PipServerController'.
} from '../types';
import type { FilteredWorkspace } from '../services';
import { getExtensionVersion, isWindsurf, Logger } from '../util';
import { isWindsurf, Logger } from '../util';
import {
COPY_MCP_URL_CMD,
MCP_SERVER_NAME,
Expand All @@ -20,9 +25,11 @@
export class McpController extends ControllerBase {
private _context: vscode.ExtensionContext;
private _config: IConfigService;
private _mcpVersion: McpVersion;
private _serverManager: IServerManager;
private _pythonDiagnostics: vscode.DiagnosticCollection;
private _pythonWorkspace: FilteredWorkspace;
private _pipServerController: PipServerController | null;

private _mcpServer: McpServer | null = null;
private _mcpServerDefinitionProvider: McpServerDefinitionProvider | null =
Expand All @@ -32,17 +39,21 @@
constructor(
context: vscode.ExtensionContext,
config: IConfigService,
mcpVersion: McpVersion,
serverManager: IServerManager,
pythonDiagnostics: vscode.DiagnosticCollection,
pythonWorkspace: FilteredWorkspace
pythonWorkspace: FilteredWorkspace,
pipServerController: PipServerController | null
) {
super();

this._context = context;
this._config = config;
this._mcpVersion = mcpVersion;
this._serverManager = serverManager;
this._pythonDiagnostics = pythonDiagnostics;
this._pythonWorkspace = pythonWorkspace;
this._pipServerController = pipServerController;

// Register copy MCP URL command
this.registerCommand(COPY_MCP_URL_CMD, this.copyUrl, this);
Expand Down Expand Up @@ -98,7 +109,8 @@
this._mcpServer = new McpServer(
this._pythonDiagnostics,
this._pythonWorkspace,
this._serverManager
this._serverManager,
this._pipServerController
);
this.disposables.push(this._mcpServer);

Expand Down Expand Up @@ -135,7 +147,7 @@

// Register provider for VS Code Copilot
this._mcpServerDefinitionProvider = new McpServerDefinitionProvider(
getExtensionVersion(this._context),
this._mcpVersion,
this._mcpServer
);
this.disposables.push(this._mcpServerDefinitionProvider);
Expand Down
20 changes: 18 additions & 2 deletions src/mcp/McpServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@
import { McpServer as SdkMcpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import * as http from 'http';
import type { IServerManager, McpTool, McpToolSpec } from '../types';
import type {
IServerManager,
McpTool,
McpToolSpec,
PipServerController,

Check failure on line 9 in src/mcp/McpServer.ts

View workflow job for this annotation

GitHub Actions / call-unit / unit

Module '"../types"' has no exported member 'PipServerController'.

Check failure on line 9 in src/mcp/McpServer.ts

View workflow job for this annotation

GitHub Actions / call-e2e / e2e

Module '"../types"' has no exported member 'PipServerController'.
} from '../types';
import { MCP_SERVER_NAME } from '../common';
import {
createCheckPythonEnvTool,
createListConnectionsTool,
createListServersTool,
createRunCodeFromUriTool,
createRunCodeTool,
createStartPipServerTool,
} from './tools';
import { withResolvers } from '../util';
import { DisposableBase, type FilteredWorkspace } from '../services';
import { createConnectToServerTool } from './tools/connectToServer';

/**
* MCP Server for Deephaven extension.
Expand All @@ -24,27 +33,34 @@
readonly pythonDiagnostics: vscode.DiagnosticCollection;
readonly pythonWorkspace: FilteredWorkspace;
readonly serverManager: IServerManager;
readonly pipServerController: PipServerController | null;

constructor(
pythonDiagnostics: vscode.DiagnosticCollection,
pythonWorkspace: FilteredWorkspace,
serverManager: IServerManager
serverManager: IServerManager,
pipServerController: PipServerController | null
) {
super();

this.pythonDiagnostics = pythonDiagnostics;
this.pythonWorkspace = pythonWorkspace;
this.serverManager = serverManager;
this.pipServerController = pipServerController;

// Create an MCP server
this.server = new SdkMcpServer({
name: MCP_SERVER_NAME,
version: '1.0.0',
});

this.registerTool(createConnectToServerTool(this));
this.registerTool(createRunCodeTool(this));
this.registerTool(createRunCodeFromUriTool(this));
this.registerTool(createListConnectionsTool(this));
this.registerTool(createListServersTool(this));
this.registerTool(createCheckPythonEnvTool(this));
this.registerTool(createStartPipServerTool(this));
}

private registerTool<Spec extends McpToolSpec>({
Expand Down
Loading
Loading