From 434838df8bc5029d3f3bb338e82b6e922f27d8f6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Feb 2026 05:11:40 +0000 Subject: [PATCH 1/4] Initial plan From 8b7934f98f6f95df6fc090890570985b9c2d1def Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Feb 2026 05:17:40 +0000 Subject: [PATCH 2/4] Refactor string marker logic into runWorkspaceCommandAsync Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- .../src/extension.ts | 24 +++----- .../src/extension.ts | 21 +++---- .../src/runWorkspaceCommandAsync.ts | 58 +++++++++++++++++-- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts b/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts index 3e027fa5574..54540b6516d 100644 --- a/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts @@ -207,23 +207,17 @@ export function activate(context: vscode.ExtensionContext): void { let homeDir: string; if (vscode.env.remoteName) { - const markerPrefix: string = '<<>>'; - const markerSuffix: string = '<<>>'; - const output: string = await runWorkspaceCommandAsync({ + homeDir = await runWorkspaceCommandAsync({ terminalOptions: { name: 'debug-certificate-manager', hideFromUser: true }, - // Wrapping the desired node output in markers to trim uninteresting shell output. - commandLine: `node -p "'${markerPrefix}' + require('os').homedir() + '${markerSuffix}'"`, - terminal + commandLine: '', + terminal, + outputMarker: { + expression: "require('os').homedir()", + prefix: '<<>>', + suffix: '<<>>' + } }); - terminal.writeLine(`Running command to resolve home directory: ${output}`); - - const startIndex: number = output.lastIndexOf(markerPrefix); - const endIndex: number = output.lastIndexOf(markerSuffix); - if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) { - homeDir = output.substring(startIndex + markerPrefix.length, endIndex).trim(); - } else { - throw new Error('Failed to parse home directory from command output'); - } + terminal.writeLine(`Running command to resolve home directory: ${homeDir}`); } else { homeDir = require('os').homedir(); } diff --git a/vscode-extensions/playwright-local-browser-server-vscode-extension/src/extension.ts b/vscode-extensions/playwright-local-browser-server-vscode-extension/src/extension.ts index 251dac4e6e4..144a68bc212 100644 --- a/vscode-extensions/playwright-local-browser-server-vscode-extension/src/extension.ts +++ b/vscode-extensions/playwright-local-browser-server-vscode-extension/src/extension.ts @@ -45,22 +45,17 @@ async function writeExtensionInstalledFileAsync(terminal: ITerminal): Promise>>', + suffix: '<<>>' + } }); - const startIndex: number = output.indexOf(markerPrefix); - const endIndex: number = output.indexOf(markerSuffix); - if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) { - tempDir = output.substring(startIndex + markerPrefix.length, endIndex).trim(); - } else { - throw new Error('Failed to parse temp directory from command output'); - } - // For remote environments, use the vscode-remote scheme // The workspace folder should have the correct scheme already const workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.workspaceFolders?.[0]; diff --git a/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts b/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts index a84c376c055..9c3b5a428a8 100644 --- a/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts +++ b/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts @@ -5,15 +5,51 @@ import { ITerminal } from '@rushstack/terminal'; import * as vscode from 'vscode'; import { stripVTControlCharacters } from 'node:util'; +/** + * Options for extracting a specific value from the command output using markers. + * When provided, the command will be wrapped with the specified markers, and only + * the content between them will be returned. This is useful for extracting specific + * values from shell output that may contain additional noise. + */ +export interface IOutputMarkerOptions { + /** + * The expression to evaluate and wrap with markers. This will be inserted between + * the prefix and suffix markers in the command output. + */ + expression: string; + /** + * The prefix marker used to identify the start of the desired output. + */ + prefix: string; + /** + * The suffix marker used to identify the end of the desired output. + */ + suffix: string; +} + export async function runWorkspaceCommandAsync({ terminalOptions, commandLine, - terminal + terminal, + outputMarker }: { terminalOptions: vscode.TerminalOptions; commandLine: string; terminal: ITerminal; + /** + * Optional marker options for extracting specific output. When provided, the + * commandLine is constructed as: `node -p "'${prefix}' + ${expression} + '${suffix}'"` + * and the returned output will be only the content between the markers. + */ + outputMarker?: IOutputMarkerOptions; }): Promise { + // If outputMarker is provided, construct the command with markers + let effectiveCommandLine: string; + if (outputMarker) { + effectiveCommandLine = `node -p "'${outputMarker.prefix}' + ${outputMarker.expression} + '${outputMarker.suffix}'"`; + } else { + effectiveCommandLine = commandLine; + } const vsTerminal: vscode.Terminal = vscode.window.createTerminal(terminalOptions); // wait for shell to bootup and vs code shell integration to kick-in @@ -66,15 +102,29 @@ export async function runWorkspaceCommandAsync({ startExecutionDisposable.dispose(); if (event.exitCode === 0) { - resolve(outputStream); + // If outputMarker was provided, extract the content between markers + if (outputMarker) { + const startIndex: number = outputStream.lastIndexOf(outputMarker.prefix); + const endIndex: number = outputStream.lastIndexOf(outputMarker.suffix); + if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) { + const extractedOutput: string = outputStream + .substring(startIndex + outputMarker.prefix.length, endIndex) + .trim(); + resolve(extractedOutput); + } else { + reject(new Error('Failed to parse output from command: markers not found')); + } + } else { + resolve(outputStream); + } } else { reject(outputStream); } } ); - shellIntegration.executeCommand(commandLine); - terminal.writeLine(`Executing command: ${commandLine}`); + shellIntegration.executeCommand(effectiveCommandLine); + terminal.writeLine(`Executing command: ${effectiveCommandLine}`); }).finally(() => { vsTerminal.dispose(); }); From 82b974e15bfa607abc1611460441a654bc21ae39 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Feb 2026 05:18:44 +0000 Subject: [PATCH 3/4] Address code review: use indexOf instead of lastIndexOf for marker search Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- .../vscode-shared/src/runWorkspaceCommandAsync.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts b/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts index 9c3b5a428a8..a0bf32386b5 100644 --- a/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts +++ b/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts @@ -104,8 +104,8 @@ export async function runWorkspaceCommandAsync({ if (event.exitCode === 0) { // If outputMarker was provided, extract the content between markers if (outputMarker) { - const startIndex: number = outputStream.lastIndexOf(outputMarker.prefix); - const endIndex: number = outputStream.lastIndexOf(outputMarker.suffix); + const startIndex: number = outputStream.indexOf(outputMarker.prefix); + const endIndex: number = outputStream.indexOf(outputMarker.suffix); if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) { const extractedOutput: string = outputStream .substring(startIndex + outputMarker.prefix.length, endIndex) From a76b3cc6c3ad83b1fa49239ff59b2a9649fa6e7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Feb 2026 13:21:46 +0000 Subject: [PATCH 4/4] Refactor outputMarker to only extract from output, not construct command Co-authored-by: TheLarkInn <3408176+TheLarkInn@users.noreply.github.com> --- .../src/extension.ts | 9 ++++--- .../src/extension.ts | 9 ++++--- .../src/runWorkspaceCommandAsync.ts | 25 +++++-------------- 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts b/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts index 54540b6516d..bc35709db4a 100644 --- a/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts +++ b/vscode-extensions/debug-certificate-manager-vscode-extension/src/extension.ts @@ -207,14 +207,15 @@ export function activate(context: vscode.ExtensionContext): void { let homeDir: string; if (vscode.env.remoteName) { + const markerPrefix: string = '<<>>'; + const markerSuffix: string = '<<>>'; homeDir = await runWorkspaceCommandAsync({ terminalOptions: { name: 'debug-certificate-manager', hideFromUser: true }, - commandLine: '', + commandLine: `node -p "'${markerPrefix}' + require('os').homedir() + '${markerSuffix}'"`, terminal, outputMarker: { - expression: "require('os').homedir()", - prefix: '<<>>', - suffix: '<<>>' + prefix: markerPrefix, + suffix: markerSuffix } }); terminal.writeLine(`Running command to resolve home directory: ${homeDir}`); diff --git a/vscode-extensions/playwright-local-browser-server-vscode-extension/src/extension.ts b/vscode-extensions/playwright-local-browser-server-vscode-extension/src/extension.ts index 144a68bc212..e18bee18bd4 100644 --- a/vscode-extensions/playwright-local-browser-server-vscode-extension/src/extension.ts +++ b/vscode-extensions/playwright-local-browser-server-vscode-extension/src/extension.ts @@ -45,14 +45,15 @@ async function writeExtensionInstalledFileAsync(terminal: ITerminal): Promise>>', - suffix: '<<>>' + prefix: markerPrefix, + suffix: markerSuffix } }); diff --git a/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts b/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts index a0bf32386b5..8d00a91c42d 100644 --- a/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts +++ b/vscode-extensions/vscode-shared/src/runWorkspaceCommandAsync.ts @@ -7,16 +7,11 @@ import { stripVTControlCharacters } from 'node:util'; /** * Options for extracting a specific value from the command output using markers. - * When provided, the command will be wrapped with the specified markers, and only - * the content between them will be returned. This is useful for extracting specific + * When provided, the function will search for the markers in the command output and + * return only the content between them. This is useful for extracting specific * values from shell output that may contain additional noise. */ export interface IOutputMarkerOptions { - /** - * The expression to evaluate and wrap with markers. This will be inserted between - * the prefix and suffix markers in the command output. - */ - expression: string; /** * The prefix marker used to identify the start of the desired output. */ @@ -37,19 +32,11 @@ export async function runWorkspaceCommandAsync({ commandLine: string; terminal: ITerminal; /** - * Optional marker options for extracting specific output. When provided, the - * commandLine is constructed as: `node -p "'${prefix}' + ${expression} + '${suffix}'"` - * and the returned output will be only the content between the markers. + * Optional marker options for extracting specific output from the command result. + * When provided, the returned output will be only the content between the markers. */ outputMarker?: IOutputMarkerOptions; }): Promise { - // If outputMarker is provided, construct the command with markers - let effectiveCommandLine: string; - if (outputMarker) { - effectiveCommandLine = `node -p "'${outputMarker.prefix}' + ${outputMarker.expression} + '${outputMarker.suffix}'"`; - } else { - effectiveCommandLine = commandLine; - } const vsTerminal: vscode.Terminal = vscode.window.createTerminal(terminalOptions); // wait for shell to bootup and vs code shell integration to kick-in @@ -123,8 +110,8 @@ export async function runWorkspaceCommandAsync({ } ); - shellIntegration.executeCommand(effectiveCommandLine); - terminal.writeLine(`Executing command: ${effectiveCommandLine}`); + shellIntegration.executeCommand(commandLine); + terminal.writeLine(`Executing command: ${commandLine}`); }).finally(() => { vsTerminal.dispose(); });