Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
7 changes: 7 additions & 0 deletions src/vs/server/node/server.cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { PipeCommand } from '../../workbench/api/node/extHostCLIServer.js';
import { hasStdinWithoutTty, getStdinFilePath, readFromStdin } from '../../platform/environment/node/stdin.js';
import { DeferredPromise } from '../../base/common/async.js';
import { FileAccess } from '../../base/common/network.js';
import { hasAgentCommand } from './server.cliAgent.js';

/*
* Implements a standalone CLI app that opens VS Code from a remote terminal.
Expand Down Expand Up @@ -95,6 +96,12 @@ export async function main(desc: ProductDescription, args: string[]): Promise<vo
return;
}

if (hasAgentCommand(args)) {
console.error(`The 'agent' command is not supported by the remote CLI.`);
process.exitCode = 1;
return;
}

// take the local options and remove the ones that don't apply
const options: OptionDescriptions<Required<RemoteParsedArgs>> = { ...OPTIONS, gitCredential: { type: 'string' }, openExternal: { type: 'boolean' } };
const isSupported = cliCommand ? isSupportedForCmd : isSupportedForPipe;
Expand Down
45 changes: 45 additions & 0 deletions src/vs/server/node/server.cliAgent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { OPTIONS, type Option } from '../../platform/environment/node/argv.js';

export function hasAgentCommand(args: readonly string[]): boolean {
let valueForOption = false;
for (const arg of args) {
if (valueForOption) {
valueForOption = false;
continue;
}
if (arg === '--') {
return false;
}
if (arg === 'agent') {
return true;
}
Comment thread
connor4312 marked this conversation as resolved.
const option = getOption(arg);
if (option?.type === 'string' || option?.type === 'string[]') {
valueForOption = true;
}
}
return false;
}

function getOption(arg: string): Option<'boolean'> | Option<'string'> | Option<'string[]'> | undefined {
if (!arg.startsWith('-') || arg.includes('=')) {
return undefined;
}
const id = arg.startsWith('--') ? arg.slice(2) : arg.slice(1);
for (const [optionId, option] of Object.entries(OPTIONS)) {
if (option.type !== 'subcommand' && (id === option.alias || id === optionId)) {
Comment thread
Copilot marked this conversation as resolved.
Outdated
return option;
}
}
for (const [optionId, option] of Object.entries(OPTIONS['agent'].options)) {
if (id === option.alias || id === optionId) {
return option;
}
}
return undefined;
}
32 changes: 32 additions & 0 deletions src/vs/server/test/node/server.cliAgent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import assert from 'assert';
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../base/test/common/utils.js';
import { hasAgentCommand } from '../../node/server.cliAgent.js';

suite('Server CLI agent command guard', () => {
ensureNoDisposablesAreLeakedInTestSuite();

test('detects agent endpoints', () => {
assert.strictEqual(hasAgentCommand(['agent', 'endpoints', '--user-data-dir', '/home/tester/.vscode-remote']), true);
});

test('detects agent after global native CLI options', () => {
assert.strictEqual(hasAgentCommand(['--cli-data-dir', '/x', 'agent', 'endpoints', '--user-data-dir', '/y']), true);
});

test('ignores non-agent commands', () => {
assert.strictEqual(hasAgentCommand(['--version']), false);
});

test('does not treat a global option value as an agent command', () => {
assert.strictEqual(hasAgentCommand(['--profile', 'agent']), false);
});

test('does not detect agent after the option terminator', () => {
assert.strictEqual(hasAgentCommand(['--', 'agent', 'endpoints']), false);
});
});
Loading