diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/chat.runInTerminal.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/chat.runInTerminal.test.ts index abc3cd4f3d3..b74382f9826 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/chat.runInTerminal.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/chat.runInTerminal.test.ts @@ -11,8 +11,8 @@ import { DeferredPromise, assertNoRpc, closeAllEditors, disposeAll } from '../ut const isWindows = process.platform === 'win32'; const isMacOS = process.platform === 'darwin'; const sandboxFileSystemSetting = isMacOS - ? 'chat.agent.sandboxFileSystem.mac' - : 'chat.agent.sandboxFileSystem.linux'; + ? 'chat.agent.sandbox.fileSystem.mac' + : 'chat.agent.sandbox.fileSystem.linux'; /** * Extracts all text content from a LanguageModelToolResult. @@ -274,12 +274,12 @@ function extractTextContent(result: vscode.LanguageModelToolResult): string { setup(async () => { const configuration = vscode.workspace.getConfiguration(); - await configuration.update('chat.agent.sandbox', true, vscode.ConfigurationTarget.Global); + await configuration.update('chat.agent.sandbox.enabled', 'on', vscode.ConfigurationTarget.Global); }); teardown(async () => { const configuration = vscode.workspace.getConfiguration(); - await configuration.update('chat.agent.sandbox', undefined, vscode.ConfigurationTarget.Global); + await configuration.update('chat.agent.sandbox.enabled', undefined, vscode.ConfigurationTarget.Global); }); // Flaky: #305722 @@ -296,7 +296,7 @@ function extractTextContent(result: vscode.LanguageModelToolResult): string { this.timeout(60000); const configuration = vscode.workspace.getConfiguration(); - await configuration.update('chat.agent.sandboxNetwork.allowedDomains', ['example.com'], vscode.ConfigurationTarget.Global); + await configuration.update('chat.agent.sandbox.allowedNetworkDomains', ['example.com'], vscode.ConfigurationTarget.Global); try { const output = await invokeRunInTerminal('curl -s --max-time 5 https://example.com'); const trimmed = output.trim(); @@ -306,7 +306,7 @@ function extractTextContent(result: vscode.LanguageModelToolResult): string { ]; assert.ok(acceptable.some(value => trimmed.includes(value) || trimmed === value), `Unexpected output: ${JSON.stringify(trimmed)}`); } finally { - await configuration.update('chat.agent.sandboxNetwork.allowedDomains', undefined, vscode.ConfigurationTarget.Global); + await configuration.update('chat.agent.sandbox.allowedNetworkDomains', undefined, vscode.ConfigurationTarget.Global); } }); @@ -347,7 +347,7 @@ function extractTextContent(result: vscode.LanguageModelToolResult): string { ? `/bin/bash: /tmp/${marker}.txt: Operation not permitted` : `/usr/bin/bash: line 1: /tmp/${marker}.txt: Read-only file system`; const sandboxBody = [ - `- If it would be reasonable to extend the sandbox rules, work with the user to update allowWrite for file system access problems in ${sandboxFileSystemSetting}, or to add required domains to chat.agent.sandboxNetwork.allowedDomains.`, + `- If it would be reasonable to extend the sandbox rules, work with the user to update allowWrite for file system access problems in ${sandboxFileSystemSetting}, or to add required domains to chat.agent.sandbox.allowedNetworkDomains.`, '- Otherwise, immediately retry the command with requestUnsandboxedExecution=true. Do NOT ask the user \u2014 setting this flag automatically shows a confirmation prompt to the user.', '', 'Here is the output of the command:', diff --git a/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts b/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts index 28ab1961345..575b9308981 100644 --- a/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts +++ b/src/vs/workbench/contrib/telemetry/browser/telemetry.contribution.ts @@ -445,6 +445,7 @@ class ConfigurationTelemetryContribution extends Disposable implements IWorkbenc }>('terminal.integrated.suggest.enabled', { settingValue: this.getValueToReport(key, target), source }); return; case TerminalContribSettingId.AgentSandboxEnabled: + case TerminalContribSettingId.DeprecatedAgentSandboxEnabled: this.telemetryService.publicLog2 Promi Registry.as(WorkbenchExtensions.ConfigurationMigration) .registerConfigurationMigrations([{ + key: TerminalContribSettingId.DeprecatedAgentSandboxEnabled, + migrateFn: (value: boolean, valueAccessor) => { + const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; + if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxEnabled) === undefined) { + configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxEnabled, { value: value ? 'on' : 'off' }]); + } + configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxEnabled, { value: undefined }]); + return configurationKeyValuePairs; + } + }, { + key: TerminalContribSettingId.DeprecatedAgentSandboxNetworkAllowedDomains, + migrateFn: (value: string[], valueAccessor) => { + const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; + if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkAllowedDomains) === undefined) { + configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkAllowedDomains, { value }]); + } + configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxNetworkAllowedDomains, { value: undefined }]); + return configurationKeyValuePairs; + } + }, { + key: TerminalContribSettingId.DeprecatedAgentSandboxNetworkDeniedDomains, + migrateFn: (value: string[], valueAccessor) => { + const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; + if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkDeniedDomains) === undefined) { + configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkDeniedDomains, { value }]); + } + configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxNetworkDeniedDomains, { value: undefined }]); + return configurationKeyValuePairs; + } + }, { + key: TerminalContribSettingId.DeprecatedAgentSandboxLinuxFileSystem, + migrateFn: (value: { denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }, valueAccessor) => { + const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; + if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxLinuxFileSystem) === undefined) { + configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxLinuxFileSystem, { value }]); + } + configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxLinuxFileSystem, { value: undefined }]); + return configurationKeyValuePairs; + } + }, { + key: TerminalContribSettingId.DeprecatedAgentSandboxMacFileSystem, + migrateFn: (value: { denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }, valueAccessor) => { + const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; + if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxMacFileSystem) === undefined) { + configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxMacFileSystem, { value }]); + } + configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxMacFileSystem, { value: undefined }]); + return configurationKeyValuePairs; + } + }, { key: TerminalSettingId.EnableBell, migrateFn: (enableBell, accessor) => { const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; @@ -725,70 +775,3 @@ Registry.as(WorkbenchExtensions.ConfigurationMi return configurationKeyValuePairs; } }]); - -Registry.as(WorkbenchExtensions.ConfigurationMigration) - .registerConfigurationMigrations([{ - key: TerminalContribSettingId.DeprecatedTerminalSandboxEnabled, - migrateFn: (value: boolean, valueAccessor) => { - const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; - if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxEnabled) === undefined) { - configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxEnabled, { value }]); - } - configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxEnabled, { value: undefined }]); - return configurationKeyValuePairs; - } - }, { - key: TerminalContribSettingId.DeprecatedTerminalSandboxNetwork, - migrateFn: (value: { allowedDomains?: string[]; deniedDomains?: string[] }, valueAccessor) => { - const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; - if (value?.allowedDomains !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkAllowedDomains) === undefined) { - configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkAllowedDomains, { value: value.allowedDomains }]); - } - if (value?.deniedDomains !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkDeniedDomains) === undefined) { - configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkDeniedDomains, { value: value.deniedDomains }]); - } - configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxNetwork, { value: undefined }]); - return configurationKeyValuePairs; - } - }, { - key: TerminalContribSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains, - migrateFn: (value: string[], valueAccessor) => { - const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; - if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkAllowedDomains) === undefined) { - configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkAllowedDomains, { value }]); - } - configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains, { value: undefined }]); - return configurationKeyValuePairs; - } - }, { - key: TerminalContribSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains, - migrateFn: (value: string[], valueAccessor) => { - const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; - if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkDeniedDomains) === undefined) { - configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkDeniedDomains, { value }]); - } - configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains, { value: undefined }]); - return configurationKeyValuePairs; - } - }, - { - key: TerminalContribSettingId.DeprecatedTerminalSandboxLinuxFileSystem, - migrateFn: (value: { denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }, valueAccessor) => { - const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; - if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxLinuxFileSystem) === undefined) { - configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxLinuxFileSystem, { value }]); - } - configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxLinuxFileSystem, { value: undefined }]); - return configurationKeyValuePairs; - } - }, { - key: TerminalContribSettingId.DeprecatedTerminalSandboxMacFileSystem, - migrateFn: (value: { denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }, valueAccessor) => { - const configurationKeyValuePairs: ConfigurationKeyValuePairs = []; - if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxMacFileSystem) === undefined) { - configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxMacFileSystem, { value }]); - } - configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxMacFileSystem, { value: undefined }]); - return configurationKeyValuePairs; - } - }]); diff --git a/src/vs/workbench/contrib/terminal/terminalContribExports.ts b/src/vs/workbench/contrib/terminal/terminalContribExports.ts index 5aad16c8002..37497a20a7a 100644 --- a/src/vs/workbench/contrib/terminal/terminalContribExports.ts +++ b/src/vs/workbench/contrib/terminal/terminalContribExports.ts @@ -47,12 +47,11 @@ export const enum TerminalContribSettingId { ShellIntegrationTimeout = TerminalChatAgentToolsSettingId.ShellIntegrationTimeout, OutputLocation = TerminalChatAgentToolsSettingId.OutputLocation, AgentSandboxEnabled = TerminalChatAgentToolsSettingId.AgentSandboxEnabled, - DeprecatedTerminalSandboxNetwork = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetwork, - DeprecatedTerminalSandboxEnabled = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled, - DeprecatedTerminalSandboxNetworkAllowedDomains = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains, - DeprecatedTerminalSandboxNetworkDeniedDomains = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains, - DeprecatedTerminalSandboxLinuxFileSystem = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxLinuxFileSystem, - DeprecatedTerminalSandboxMacFileSystem = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxMacFileSystem, + DeprecatedAgentSandboxEnabled = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled, + DeprecatedAgentSandboxNetworkAllowedDomains = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains, + DeprecatedAgentSandboxNetworkDeniedDomains = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains, + DeprecatedAgentSandboxLinuxFileSystem = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxLinuxFileSystem, + DeprecatedAgentSandboxMacFileSystem = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxMacFileSystem, AgentSandboxNetworkAllowedDomains = TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, AgentSandboxNetworkDeniedDomains = TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, AgentSandboxLinuxFileSystem = TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem, diff --git a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/terminal.chatAgentTools.contribution.ts b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/terminal.chatAgentTools.contribution.ts index f4c3891bc62..8f70bf0e886 100644 --- a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/terminal.chatAgentTools.contribution.ts +++ b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/terminal.chatAgentTools.contribution.ts @@ -140,11 +140,15 @@ export class ChatAgentToolsContribution extends Disposable implements IWorkbench this._register(this._configurationService.onDidChangeConfiguration(e => { if ( e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled) || + e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) || e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains) || + e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains) || e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains) || - e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) || - e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains) || - e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains) + e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains) || + e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem) || + e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxLinuxFileSystem) || + e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem) || + e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxMacFileSystem) ) { this._registerRunInTerminalTool(); } diff --git a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/runInTerminalTool.ts b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/runInTerminalTool.ts index 0152bd5faf3..a6abdf30da9 100644 --- a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/runInTerminalTool.ts +++ b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/runInTerminalTool.ts @@ -901,20 +901,20 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { private _getBlockedDomainReason(blockedDomains: string[], deniedDomains: string[] = []): string { if (deniedDomains.length === blockedDomains.length && deniedDomains.length > 0) { if (blockedDomains.length === 1) { - return localize('runInTerminal.unsandboxed.domain.reason.denied.single', "This command accesses {0}, which is blocked by chat.agent.sandboxNetwork.deniedDomains.", blockedDomains[0]); + return localize('runInTerminal.unsandboxed.domain.reason.denied.single', "This command accesses {0}, which is blocked by chat.agent.sandbox.deniedNetworkDomains.", blockedDomains[0]); } - return localize('runInTerminal.unsandboxed.domain.reason.denied.multi', "This command accesses {0} and {1} more domains that are blocked by chat.agent.sandboxNetwork.deniedDomains.", blockedDomains[0], blockedDomains.length - 1); + return localize('runInTerminal.unsandboxed.domain.reason.denied.multi', "This command accesses {0} and {1} more domains that are blocked by chat.agent.sandbox.deniedNetworkDomains.", blockedDomains[0], blockedDomains.length - 1); } if (deniedDomains.length > 0) { if (blockedDomains.length === 1) { - return localize('runInTerminal.unsandboxed.domain.reason.mixed.single', "This command accesses {0}, which is blocked by chat.agent.sandboxNetwork.deniedDomains or not added to chat.agent.sandboxNetwork.allowedDomains.", blockedDomains[0]); + return localize('runInTerminal.unsandboxed.domain.reason.mixed.single', "This command accesses {0}, which is blocked by chat.agent.sandbox.deniedNetworkDomains or not added to chat.agent.sandbox.allowedNetworkDomains.", blockedDomains[0]); } - return localize('runInTerminal.unsandboxed.domain.reason.mixed.multi', "This command accesses {0} and {1} more domains that are blocked by chat.agent.sandboxNetwork.deniedDomains or not added to chat.agent.sandboxNetwork.allowedDomains.", blockedDomains[0], blockedDomains.length - 1); + return localize('runInTerminal.unsandboxed.domain.reason.mixed.multi', "This command accesses {0} and {1} more domains that are blocked by chat.agent.sandbox.deniedNetworkDomains or not added to chat.agent.sandbox.allowedNetworkDomains.", blockedDomains[0], blockedDomains.length - 1); } if (blockedDomains.length === 1) { - return localize('runInTerminal.unsandboxed.domain.reason.single', "This command accesses {0}, which is not permitted by the current chat.agent.sandboxNetwork configuration.", blockedDomains[0]); + return localize('runInTerminal.unsandboxed.domain.reason.single', "This command accesses {0}, which is not permitted by the current chat.agent.sandbox configuration.", blockedDomains[0]); } - return localize('runInTerminal.unsandboxed.domain.reason.multi', "This command accesses {0} and {1} more domains that are not permitted by the current chat.agent.sandboxNetwork configuration.", blockedDomains[0], blockedDomains.length - 1); + return localize('runInTerminal.unsandboxed.domain.reason.multi', "This command accesses {0} and {1} more domains that are not permitted by the current chat.agent.sandbox configuration.", blockedDomains[0], blockedDomains.length - 1); } async invoke(invocation: IToolInvocation, _countTokens: CountTokensCallback, _progress: ToolProgress, token: CancellationToken): Promise { diff --git a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/common/terminalChatAgentToolsConfiguration.ts b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/common/terminalChatAgentToolsConfiguration.ts index 2ad17780a4c..7949d615548 100644 --- a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/common/terminalChatAgentToolsConfiguration.ts +++ b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/common/terminalChatAgentToolsConfiguration.ts @@ -20,11 +20,11 @@ export const enum TerminalChatAgentToolsSettingId { ShellIntegrationTimeout = 'chat.tools.terminal.shellIntegrationTimeout', AutoReplyToPrompts = 'chat.tools.terminal.autoReplyToPrompts', OutputLocation = 'chat.tools.terminal.outputLocation', - AgentSandboxEnabled = 'chat.agent.sandbox', - AgentSandboxNetworkAllowedDomains = 'chat.agent.sandboxNetwork.allowedDomains', - AgentSandboxNetworkDeniedDomains = 'chat.agent.sandboxNetwork.deniedDomains', - AgentSandboxLinuxFileSystem = 'chat.agent.sandboxFileSystem.linux', - AgentSandboxMacFileSystem = 'chat.agent.sandboxFileSystem.mac', + AgentSandboxEnabled = 'chat.agent.sandbox.enabled', + AgentSandboxNetworkAllowedDomains = 'chat.agent.sandbox.allowedNetworkDomains', + AgentSandboxNetworkDeniedDomains = 'chat.agent.sandbox.deniedNetworkDomains', + AgentSandboxLinuxFileSystem = 'chat.agent.sandbox.fileSystem.linux', + AgentSandboxMacFileSystem = 'chat.agent.sandbox.fileSystem.mac', PreventShellHistory = 'chat.tools.terminal.preventShellHistory', EnforceTimeoutFromModel = 'chat.tools.terminal.enforceTimeoutFromModel', DetachBackgroundProcesses = 'chat.tools.terminal.detachBackgroundProcesses', @@ -34,12 +34,11 @@ export const enum TerminalChatAgentToolsSettingId { TerminalProfileMacOs = 'chat.tools.terminal.terminalProfile.osx', TerminalProfileWindows = 'chat.tools.terminal.terminalProfile.windows', - DeprecatedTerminalSandboxEnabled = 'chat.tools.terminal.sandbox.enabled', - DeprecatedTerminalSandboxNetwork = 'chat.tools.terminal.sandbox.network', - DeprecatedTerminalSandboxNetworkAllowedDomains = 'chat.tools.terminal.sandbox.network.allowedDomains', - DeprecatedTerminalSandboxNetworkDeniedDomains = 'chat.tools.terminal.sandbox.network.deniedDomains', - DeprecatedTerminalSandboxLinuxFileSystem = 'chat.tools.terminal.sandbox.linuxFileSystem', - DeprecatedTerminalSandboxMacFileSystem = 'chat.tools.terminal.sandbox.macFileSystem', + DeprecatedAgentSandboxEnabled = 'chat.agent.sandbox', + DeprecatedAgentSandboxNetworkAllowedDomains = 'chat.agent.sandboxNetwork.allowedDomains', + DeprecatedAgentSandboxNetworkDeniedDomains = 'chat.agent.sandboxNetwork.deniedDomains', + DeprecatedAgentSandboxLinuxFileSystem = 'chat.agent.sandboxFileSystem.linux', + DeprecatedAgentSandboxMacFileSystem = 'chat.agent.sandboxFileSystem.mac', DeprecatedAutoApproveCompatible = 'chat.agent.terminal.autoApprove', DeprecatedAutoApprove1 = 'chat.agent.terminal.allowList', DeprecatedAutoApprove2 = 'chat.agent.terminal.denyList', @@ -47,6 +46,11 @@ export const enum TerminalChatAgentToolsSettingId { DeprecatedAutoApprove4 = 'github.copilot.chat.agent.terminal.denyList', } +export const enum TerminalChatAgentToolsSandboxEnabledValue { + Off = 'off', + On = 'on', +} + export interface ITerminalChatAgentToolsConfiguration { autoApprove: { [key: string]: boolean }; commandReportingAllowList: { [key: string]: boolean }; @@ -531,8 +535,13 @@ export const terminalChatAgentToolsConfiguration: IStringDictionary(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) ?? false; + return this._isSandboxEnabled(this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) ?? TerminalChatAgentToolsSandboxEnabledValue.Off); } private async _resolveSrtPath(): Promise { @@ -623,13 +623,13 @@ export class TerminalSandboxService extends Disposable implements ITerminalSandb await this._initTempDir(); } if (this._tempDir) { - const allowedDomainsSetting = this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains) ?? []; - const deniedDomainsSetting = this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains) ?? []; + const allowedDomainsSetting = this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains) ?? []; + const deniedDomainsSetting = this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains) ?? []; const linuxFileSystemSetting = this._os === OperatingSystem.Linux - ? this._getSettingValue<{ denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }>(TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxLinuxFileSystem) ?? {} + ? this._getSettingValue<{ denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }>(TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxLinuxFileSystem) ?? {} : {}; const macFileSystemSetting = this._os === OperatingSystem.Macintosh - ? this._getSettingValue<{ denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }>(TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxMacFileSystem) ?? {} + ? this._getSettingValue<{ denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }>(TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxMacFileSystem) ?? {} : {}; const configFileUri = URI.joinPath(this._tempDir, `vscode-sandbox-settings-${this._sandboxSettingsId}.json`); const linuxAllowWrite = this._updateAllowWritePathsWithWorkspaceFolders(linuxFileSystemSetting.allowWrite); @@ -708,8 +708,8 @@ export class TerminalSandboxService extends Disposable implements ITerminalSandb } public getResolvedNetworkDomains(): ITerminalSandboxResolvedNetworkDomains { - const allowedDomains = this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains) ?? []; - const deniedDomains = this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains) ?? []; + const allowedDomains = this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains) ?? []; + const deniedDomains = this._getSettingValue(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains) ?? []; return { allowedDomains, deniedDomains @@ -738,6 +738,10 @@ export class TerminalSandboxService extends Disposable implements ITerminalSandb } + private _isSandboxEnabled(value: TerminalChatAgentToolsSandboxEnabledValue | boolean): boolean { + return value === true || value === TerminalChatAgentToolsSandboxEnabledValue.On; + } + private _getSettingValue(settingId: TerminalChatAgentToolsSettingId, deprecatedSettingId?: TerminalChatAgentToolsSettingId): T | undefined { const setting = this._configurationService.inspect(settingId); const deprecatedSetting = deprecatedSettingId ? this._configurationService.inspect(deprecatedSettingId) : undefined; diff --git a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/terminalSandboxService.test.ts b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/terminalSandboxService.test.ts index 34b952ba332..33c026438ad 100644 --- a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/terminalSandboxService.test.ts +++ b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/terminalSandboxService.test.ts @@ -16,7 +16,7 @@ import { ILogService, NullLogService } from '../../../../../../platform/log/comm import { IProductService } from '../../../../../../platform/product/common/productService.js'; import { IRemoteAgentService } from '../../../../../services/remote/common/remoteAgentService.js'; import { URI } from '../../../../../../base/common/uri.js'; -import { TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js'; +import { TerminalChatAgentToolsSandboxEnabledValue, TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js'; import { Event, Emitter } from '../../../../../../base/common/event.js'; import { TestConfigurationService } from '../../../../../../platform/configuration/test/common/testConfigurationService.js'; import { VSBuffer } from '../../../../../../base/common/buffer.js'; @@ -174,7 +174,7 @@ suite('TerminalSandboxService - network domains', () => { workspaceContextService.setWorkspaceFolders([URI.file('/workspace-one')]); // Setup default configuration - configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, true); + configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, TerminalChatAgentToolsSandboxEnabledValue.On); configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, []); configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, []); @@ -406,7 +406,7 @@ suite('TerminalSandboxService - network domains', () => { if (key === TerminalChatAgentToolsSettingId.AgentSandboxEnabled) { return { value: undefined, - defaultValue: false, + defaultValue: TerminalChatAgentToolsSandboxEnabledValue.Off, userValue: undefined, userLocalValue: undefined, userRemoteValue: undefined, @@ -416,7 +416,7 @@ suite('TerminalSandboxService - network domains', () => { policyValue: undefined, } as ReturnType>; } - if (key === TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) { + if (key === TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) { return { value: true, defaultValue: false, @@ -437,13 +437,13 @@ suite('TerminalSandboxService - network domains', () => { strictEqual(await sandboxService.isEnabled(), false, 'Deprecated settings should not be used when only non-user scopes are set'); }); - test('should fall back to deprecated settings in user scope', async () => { + test('should fall back to deprecated chat.agent.sandbox setting in user scope', async () => { const originalInspect = configurationService.inspect.bind(configurationService); configurationService.inspect = (key: string) => { if (key === TerminalChatAgentToolsSettingId.AgentSandboxEnabled) { return { value: undefined, - defaultValue: false, + defaultValue: TerminalChatAgentToolsSandboxEnabledValue.Off, userValue: undefined, userLocalValue: undefined, userRemoteValue: undefined, @@ -453,7 +453,7 @@ suite('TerminalSandboxService - network domains', () => { policyValue: undefined, } as ReturnType>; } - if (key === TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) { + if (key === TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) { return { value: true, defaultValue: false, @@ -471,7 +471,7 @@ suite('TerminalSandboxService - network domains', () => { const sandboxService = store.add(instantiationService.createInstance(TerminalSandboxService)); - strictEqual(await sandboxService.isEnabled(), true, 'Deprecated settings should still be respected when only the user scope is set'); + strictEqual(await sandboxService.isEnabled(), true, 'Deprecated chat.agent.sandbox should still be respected when only the user scope is set'); }); test('should detect ssh style remotes as domains', async () => { diff --git a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/electron-browser/runInTerminalTool.test.ts b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/electron-browser/runInTerminalTool.test.ts index 2586070db53..df9449835f7 100644 --- a/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/electron-browser/runInTerminalTool.test.ts +++ b/src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/electron-browser/runInTerminalTool.test.ts @@ -42,7 +42,7 @@ import { ITerminalProfileResolverService } from '../../../../terminal/common/ter import type { ICommandLinePresenter } from '../../browser/tools/commandLinePresenter/commandLinePresenter.js'; import { createRunInTerminalToolData, RunInTerminalTool, type IRunInTerminalInputParams } from '../../browser/tools/runInTerminalTool.js'; import { ShellIntegrationQuality } from '../../browser/toolTerminalCreator.js'; -import { terminalChatAgentToolsConfiguration, TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js'; +import { terminalChatAgentToolsConfiguration, TerminalChatAgentToolsSandboxEnabledValue, TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js'; import { TerminalChatService } from '../../../chat/browser/terminalChatService.js'; import type { IMarkdownString } from '../../../../../../base/common/htmlContent.js'; import { IAgentSessionsService } from '../../../../chat/browser/agentSessions/agentSessionsService.js'; @@ -642,7 +642,7 @@ suite('RunInTerminalTool', () => { if (!confirmationMessage || typeof confirmationMessage === 'string') { throw new Error('Expected markdown confirmation message'); } - ok(confirmationMessage.value.includes('Reason for leaving the sandbox: This command accesses evil.com, which is blocked by chat.agent.sandboxNetwork.deniedDomains.')); + ok(confirmationMessage.value.includes('Reason for leaving the sandbox: This command accesses evil.com, which is blocked by chat.agent.sandbox.deniedNetworkDomains.')); }); test('should force confirmation for explicit unsandboxed execution requests', async () => { @@ -2166,7 +2166,7 @@ suite('ChatAgentToolsContribution - tool registration refresh', () => { // Enable sandbox and fire config change sandboxEnabled = true; - configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, true); + configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, TerminalChatAgentToolsSandboxEnabledValue.On); configurationService.onDidChangeConfigurationEmitter.fire({ affectsConfiguration: (key: string) => key === TerminalChatAgentToolsSettingId.AgentSandboxEnabled, affectedKeys: new Set([TerminalChatAgentToolsSettingId.AgentSandboxEnabled]),