fix(core): conditionally expose additional_permissions in shell tool (#23729)

Co-authored-by: Sandy Tao <sandytao520@icloud.com>
This commit is contained in:
Gal Zahavi
2026-03-24 18:46:15 -07:00
committed by GitHub
parent 578d656de9
commit a6c7affedb
9 changed files with 64 additions and 42 deletions

View File

@@ -233,13 +233,19 @@ export {
export function getShellDefinition(
enableInteractiveShell: boolean,
enableEfficiency: boolean,
enableToolSandboxing: boolean = false,
): ToolDefinition {
return {
base: getShellDeclaration(enableInteractiveShell, enableEfficiency),
base: getShellDeclaration(
enableInteractiveShell,
enableEfficiency,
enableToolSandboxing,
),
overrides: (modelId) =>
getToolSet(modelId).run_shell_command(
enableInteractiveShell,
enableEfficiency,
enableToolSandboxing,
),
};
}

View File

@@ -69,7 +69,7 @@ describe('coreTools snapshots for specific models', () => {
{ name: 'list_directory', definition: LS_DEFINITION },
{
name: 'run_shell_command',
definition: getShellDefinition(true, true),
definition: getShellDefinition(true, true, true),
},
{ name: 'replace', definition: EDIT_DEFINITION },
{ name: 'google_web_search', definition: WEB_SEARCH_DEFINITION },

View File

@@ -81,6 +81,7 @@ export function getCommandDescription(): string {
export function getShellDeclaration(
enableInteractiveShell: boolean,
enableEfficiency: boolean,
enableToolSandboxing: boolean = false,
): FunctionDeclaration {
return {
name: SHELL_TOOL_NAME,
@@ -110,35 +111,39 @@ export function getShellDeclaration(
description:
'Set to true if this command should be run in the background (e.g. for long-running servers or watchers). The command will be started, allowed to run for a brief moment to check for immediate errors, and then moved to the background.',
},
[PARAM_ADDITIONAL_PERMISSIONS]: {
type: 'object',
description:
'Sandbox permissions for the command. Use this to request additional sandboxed filesystem or network permissions if a previous command failed with "Operation not permitted".',
properties: {
network: {
type: 'boolean',
description:
'Set to true to enable network access for this command.',
},
fileSystem: {
type: 'object',
properties: {
read: {
type: 'array',
items: { type: 'string' },
description:
'List of additional absolute paths to allow reading.',
},
write: {
type: 'array',
items: { type: 'string' },
description:
'List of additional absolute paths to allow writing.',
...(enableToolSandboxing
? {
[PARAM_ADDITIONAL_PERMISSIONS]: {
type: 'object',
description:
'Sandbox permissions for the command. Use this to request additional sandboxed filesystem or network permissions if a previous command failed with "Operation not permitted".',
properties: {
network: {
type: 'boolean',
description:
'Set to true to enable network access for this command.',
},
fileSystem: {
type: 'object',
properties: {
read: {
type: 'array',
items: { type: 'string' },
description:
'List of additional absolute paths to allow reading.',
},
write: {
type: 'array',
items: { type: 'string' },
description:
'List of additional absolute paths to allow writing.',
},
},
},
},
},
},
},
},
}
: {}),
},
required: [SHELL_PARAM_COMMAND],
},

View File

@@ -332,8 +332,16 @@ export const DEFAULT_LEGACY_SET: CoreToolSet = {
},
},
run_shell_command: (enableInteractiveShell, enableEfficiency) =>
getShellDeclaration(enableInteractiveShell, enableEfficiency),
run_shell_command: (
enableInteractiveShell,
enableEfficiency,
enableToolSandboxing,
) =>
getShellDeclaration(
enableInteractiveShell,
enableEfficiency,
enableToolSandboxing,
),
replace: {
name: EDIT_TOOL_NAME,

View File

@@ -338,8 +338,16 @@ export const GEMINI_3_SET: CoreToolSet = {
},
},
run_shell_command: (enableInteractiveShell, enableEfficiency) =>
getShellDeclaration(enableInteractiveShell, enableEfficiency),
run_shell_command: (
enableInteractiveShell,
enableEfficiency,
enableToolSandboxing,
) =>
getShellDeclaration(
enableInteractiveShell,
enableEfficiency,
enableToolSandboxing,
),
replace: {
name: EDIT_TOOL_NAME,

View File

@@ -37,6 +37,7 @@ export interface CoreToolSet {
run_shell_command: (
enableInteractiveShell: boolean,
enableEfficiency: boolean,
enableToolSandboxing: boolean,
) => FunctionDeclaration;
replace: FunctionDeclaration;
google_web_search: FunctionDeclaration;

View File

@@ -137,6 +137,7 @@ describe('ShellTool', () => {
getShellToolInactivityTimeout: vi.fn().mockReturnValue(1000),
getEnableInteractiveShell: vi.fn().mockReturnValue(false),
getEnableShellOutputEfficiency: vi.fn().mockReturnValue(true),
getSandboxEnabled: vi.fn().mockReturnValue(false),
sanitizationConfig: {},
sandboxManager: new NoopSandboxManager(),
} as unknown as Config;

View File

@@ -696,6 +696,7 @@ export class ShellTool extends BaseDeclarativeTool<
const definition = getShellDefinition(
context.config.getEnableInteractiveShell(),
context.config.getEnableShellOutputEfficiency(),
context.config.getSandboxEnabled(),
);
super(
ShellTool.Name,
@@ -745,6 +746,7 @@ export class ShellTool extends BaseDeclarativeTool<
const definition = getShellDefinition(
this.context.config.getEnableInteractiveShell(),
this.context.config.getEnableShellOutputEfficiency(),
this.context.config.getSandboxEnabled(),
);
return resolveToolDeclaration(definition, modelId);
}