diff --git a/packages/types/src/vscode.ts b/packages/types/src/vscode.ts index 00f6bbbcba9..d9e6ad5d788 100644 --- a/packages/types/src/vscode.ts +++ b/packages/types/src/vscode.ts @@ -39,6 +39,7 @@ export const commandIds = [ "settingsButtonClicked", "openInNewTab", + "openInThisTab", "showHumanRelayDialog", "registerHumanRelayCallback", diff --git a/src/activate/registerCommands.ts b/src/activate/registerCommands.ts index 0534f247822..813c694422a 100644 --- a/src/activate/registerCommands.ts +++ b/src/activate/registerCommands.ts @@ -129,6 +129,7 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt return openClineInNewTab({ context, outputChannel }) }, openInNewTab: () => openClineInNewTab({ context, outputChannel }), + openInThisTab: () => openClineInThisTab({ context, outputChannel }), settingsButtonClicked: () => { const visibleProvider = getVisibleProviderOrLog(outputChannel) @@ -298,3 +299,68 @@ export const openClineInNewTab = async ({ context, outputChannel }: Omit) => { + const contextProxy = await ContextProxy.getInstance(context) + const codeIndexManager = CodeIndexManager.getInstance(context) + + // Get the existing MDM service instance to ensure consistent policy enforcement + let mdmService: MdmService | undefined + try { + mdmService = MdmService.getInstance() + } catch (error) { + // MDM service not initialized, which is fine - extension can work without it + mdmService = undefined + } + + const tabProvider = new ClineProvider(context, outputChannel, "editor", contextProxy, mdmService) + + // Get the active text editor's view column, or use the first column if no editor is active + const activeColumn = vscode.window.activeTextEditor?.viewColumn || vscode.ViewColumn.One + + // Create the webview panel in the current tab/column + const newPanel = vscode.window.createWebviewPanel( + ClineProvider.tabPanelId, + "Roo Code", + { viewColumn: activeColumn, preserveFocus: false }, + { + enableScripts: true, + retainContextWhenHidden: true, + localResourceRoots: [context.extensionUri], + }, + ) + + // Save as tab type panel + setPanel(newPanel, "tab") + + // Set the icon + newPanel.iconPath = { + light: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_light.png"), + dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "panel_dark.png"), + } + + await tabProvider.resolveWebviewView(newPanel) + + // Add listener for visibility changes to notify webview + newPanel.onDidChangeViewState( + (e) => { + const panel = e.webviewPanel + if (panel.visible) { + panel.webview.postMessage({ type: "action", action: "didBecomeVisible" }) + } + }, + null, + context.subscriptions, + ) + + // Handle panel closing events + newPanel.onDidDispose( + () => { + setPanel(undefined, "tab") + }, + null, + context.subscriptions, + ) + + return tabProvider +} diff --git a/src/package.json b/src/package.json index dfe4231f011..7d700c2b62c 100644 --- a/src/package.json +++ b/src/package.json @@ -115,6 +115,11 @@ "title": "%command.openInNewTab.title%", "category": "%configuration.title%" }, + { + "command": "roo-cline.openInThisTab", + "title": "%command.openInThisTab.title%", + "category": "%configuration.title%" + }, { "command": "roo-cline.explainCode", "title": "%command.explainCode.title%", diff --git a/src/package.nls.json b/src/package.nls.json index f1c132be651..f59076fbdb5 100644 --- a/src/package.nls.json +++ b/src/package.nls.json @@ -15,6 +15,7 @@ "command.settings.title": "Settings", "command.documentation.title": "Documentation", "command.openInNewTab.title": "Open In New Tab", + "command.openInThisTab.title": "Open In This Tab", "command.explainCode.title": "Explain Code", "command.fixCode.title": "Fix Code", "command.improveCode.title": "Improve Code",