mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Remove unused legacy shell tools (#22246)
## Why Recent session history showed no active use of the raw `shell`, `local_shell`, or `container.exec` execution surfaces. Keeping those handlers/specs wired into core leaves duplicate shell execution paths alongside the supported `shell_command` and unified exec tools. ## What changed - Removed the raw `shell` handler/spec and its `ShellToolCallParams` protocol helper. - Removed the legacy `local_shell` and `container.exec` handler/spec plumbing while preserving persisted-history compatibility for old response items. - Normalized model/config `default` and `local` shell selections to `shell_command`. - Pruned tests that exercised removed raw-shell/local-shell/apply-patch variants and kept coverage on `shell_command`, unified exec, and freeform `apply_patch`. ## Verification - `git diff --check` - `cargo test -p codex-protocol` - `cargo test -p codex-tools` - `cargo test -p codex-core tools::handlers::shell` - `cargo test -p codex-core tools::spec` - `cargo test -p codex-core tools::router` - `cargo test -p codex-core active_call_preserves_triggering_command_context` - `cargo test -p codex-core guardian_tests` - `cargo test -p codex-core --test all shell_serialization` - `cargo test -p codex-core --test all apply_patch_cli` - `cargo test -p codex-core --test all shell_command_` - `cargo test -p codex-core --test all local_shell` - `cargo test -p codex-core --test all otel::` - `cargo test -p codex-core --test all hooks::` - `just fix -p codex-core` - `just fix -p codex-tools`
This commit is contained in:
committed by
GitHub
Unverified
parent
7c7b4861d8
commit
83decfa300
@@ -62,11 +62,8 @@ pub use plan::PlanHandler;
|
||||
pub use request_permissions::RequestPermissionsHandler;
|
||||
pub use request_plugin_install::RequestPluginInstallHandler;
|
||||
pub use request_user_input::RequestUserInputHandler;
|
||||
pub use shell::ContainerExecHandler;
|
||||
pub use shell::LocalShellHandler;
|
||||
pub use shell::ShellCommandHandler;
|
||||
pub(crate) use shell::ShellCommandHandlerOptions;
|
||||
pub use shell::ShellHandler;
|
||||
pub use test_sync::TestSyncHandler;
|
||||
pub use tool_search::ToolSearchHandler;
|
||||
pub use unified_exec::ExecCommandHandler;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use codex_features::Feature;
|
||||
use codex_protocol::models::ShellCommandToolCallParams;
|
||||
use codex_protocol::models::ShellToolCallParams;
|
||||
use serde_json::Value as JsonValue;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -9,8 +8,6 @@ use crate::exec_policy::ExecApprovalRequest;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolOutput;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::events::ToolEmitter;
|
||||
use crate::tools::events::ToolEventCtx;
|
||||
@@ -19,12 +16,7 @@ use crate::tools::handlers::apply_patch::intercept_apply_patch;
|
||||
use crate::tools::handlers::implicit_granted_permissions;
|
||||
use crate::tools::handlers::normalize_and_validate_additional_permissions;
|
||||
use crate::tools::handlers::parse_arguments;
|
||||
use crate::tools::handlers::rewrite_function_arguments;
|
||||
use crate::tools::handlers::updated_hook_command;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::orchestrator::ToolOrchestrator;
|
||||
use crate::tools::registry::PostToolUsePayload;
|
||||
use crate::tools::registry::PreToolUsePayload;
|
||||
use crate::tools::runtimes::shell::ShellRequest;
|
||||
use crate::tools::runtimes::shell::ShellRuntime;
|
||||
use crate::tools::runtimes::shell::ShellRuntimeBackend;
|
||||
@@ -33,36 +25,10 @@ use codex_protocol::models::AdditionalPermissionProfile;
|
||||
use codex_protocol::protocol::ExecCommandSource;
|
||||
use codex_tools::ToolName;
|
||||
|
||||
mod container_exec;
|
||||
mod local_shell;
|
||||
mod shell_command;
|
||||
mod shell_handler;
|
||||
|
||||
pub use container_exec::ContainerExecHandler;
|
||||
pub use local_shell::LocalShellHandler;
|
||||
pub use shell_command::ShellCommandHandler;
|
||||
pub(crate) use shell_command::ShellCommandHandlerOptions;
|
||||
pub use shell_handler::ShellHandler;
|
||||
|
||||
fn shell_function_payload_command(payload: &ToolPayload) -> Option<String> {
|
||||
let ToolPayload::Function { arguments } = payload else {
|
||||
return None;
|
||||
};
|
||||
|
||||
parse_arguments::<ShellToolCallParams>(arguments)
|
||||
.ok()
|
||||
.map(|params| codex_shell_command::parse_command::shlex_join(¶ms.command))
|
||||
}
|
||||
|
||||
fn local_shell_payload_command(payload: &ToolPayload) -> Option<String> {
|
||||
let ToolPayload::LocalShell { params } = payload else {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(codex_shell_command::parse_command::shlex_join(
|
||||
¶ms.command,
|
||||
))
|
||||
}
|
||||
|
||||
fn shell_command_payload_command(payload: &ToolPayload) -> Option<String> {
|
||||
let ToolPayload::Function { arguments } = payload else {
|
||||
@@ -88,53 +54,6 @@ struct RunExecLikeArgs {
|
||||
shell_runtime_backend: ShellRuntimeBackend,
|
||||
}
|
||||
|
||||
fn shell_function_pre_tool_use_payload(invocation: &ToolInvocation) -> Option<PreToolUsePayload> {
|
||||
shell_function_payload_command(&invocation.payload).map(|command| PreToolUsePayload {
|
||||
tool_name: HookToolName::bash(),
|
||||
tool_input: serde_json::json!({ "command": command }),
|
||||
})
|
||||
}
|
||||
|
||||
fn rewrite_shell_function_updated_hook_input(
|
||||
mut invocation: ToolInvocation,
|
||||
updated_input: JsonValue,
|
||||
tool_name: &str,
|
||||
) -> Result<ToolInvocation, FunctionCallError> {
|
||||
let ToolPayload::Function { arguments } = invocation.payload else {
|
||||
return Err(FunctionCallError::RespondToModel(format!(
|
||||
"hook input rewrite received unsupported {tool_name} payload"
|
||||
)));
|
||||
};
|
||||
let command = shlex::split(updated_hook_command(&updated_input)?).ok_or_else(|| {
|
||||
FunctionCallError::RespondToModel(
|
||||
"hook returned shell input with an invalid command string".to_string(),
|
||||
)
|
||||
})?;
|
||||
invocation.payload = ToolPayload::Function {
|
||||
arguments: rewrite_function_arguments(&arguments, tool_name, |arguments| {
|
||||
arguments.insert(
|
||||
"command".to_string(),
|
||||
JsonValue::Array(command.into_iter().map(JsonValue::String).collect()),
|
||||
);
|
||||
})?,
|
||||
};
|
||||
Ok(invocation)
|
||||
}
|
||||
|
||||
fn shell_function_post_tool_use_payload(
|
||||
invocation: &ToolInvocation,
|
||||
result: &FunctionToolOutput,
|
||||
) -> Option<PostToolUsePayload> {
|
||||
let tool_response = result.post_tool_use_response(&invocation.call_id, &invocation.payload)?;
|
||||
let command = shell_function_payload_command(&invocation.payload)?;
|
||||
Some(PostToolUsePayload {
|
||||
tool_name: HookToolName::bash(),
|
||||
tool_use_id: invocation.call_id.clone(),
|
||||
tool_input: serde_json::json!({ "command": command }),
|
||||
tool_response,
|
||||
})
|
||||
}
|
||||
|
||||
async fn run_exec_like(args: RunExecLikeArgs) -> Result<FunctionToolOutput, FunctionCallError> {
|
||||
let RunExecLikeArgs {
|
||||
tool_name,
|
||||
@@ -289,15 +208,7 @@ async fn run_exec_like(args: RunExecLikeArgs) -> Result<FunctionToolOutput, Func
|
||||
exec_approval_requirement,
|
||||
};
|
||||
let mut orchestrator = ToolOrchestrator::new();
|
||||
let mut runtime = {
|
||||
use ShellRuntimeBackend::*;
|
||||
match shell_runtime_backend {
|
||||
Generic => ShellRuntime::new(),
|
||||
backend @ (ShellCommandClassic | ShellCommandZshFork) => {
|
||||
ShellRuntime::for_shell_command(backend)
|
||||
}
|
||||
}
|
||||
};
|
||||
let mut runtime = ShellRuntime::for_shell_command(shell_runtime_backend);
|
||||
let tool_ctx = ToolCtx {
|
||||
session: session.clone(),
|
||||
turn: turn.clone(),
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
use codex_protocol::models::ShellToolCallParams;
|
||||
use codex_tools::ToolName;
|
||||
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::handlers::parse_arguments_with_base_path;
|
||||
use crate::tools::handlers::resolve_workdir_base_path;
|
||||
use crate::tools::registry::PostToolUsePayload;
|
||||
use crate::tools::registry::PreToolUsePayload;
|
||||
use crate::tools::registry::ToolExecutor;
|
||||
use crate::tools::registry::ToolHandler;
|
||||
use crate::tools::runtimes::shell::ShellRuntimeBackend;
|
||||
|
||||
use super::RunExecLikeArgs;
|
||||
use super::rewrite_shell_function_updated_hook_input;
|
||||
use super::run_exec_like;
|
||||
use super::shell_function_post_tool_use_payload;
|
||||
use super::shell_function_pre_tool_use_payload;
|
||||
use super::shell_handler::ShellHandler;
|
||||
|
||||
pub struct ContainerExecHandler;
|
||||
|
||||
impl ToolExecutor<ToolInvocation> for ContainerExecHandler {
|
||||
type Output = FunctionToolOutput;
|
||||
|
||||
fn tool_name(&self) -> ToolName {
|
||||
ToolName::plain("container.exec")
|
||||
}
|
||||
|
||||
async fn handle(&self, invocation: ToolInvocation) -> Result<Self::Output, FunctionCallError> {
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
tracker,
|
||||
call_id,
|
||||
payload,
|
||||
..
|
||||
} = invocation;
|
||||
|
||||
let arguments = match payload {
|
||||
ToolPayload::Function { arguments } => arguments,
|
||||
_ => {
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
"unsupported payload for container.exec handler".to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let cwd = resolve_workdir_base_path(&arguments, &turn.cwd)?;
|
||||
let params: ShellToolCallParams = parse_arguments_with_base_path(&arguments, &cwd)?;
|
||||
let prefix_rule = params.prefix_rule.clone();
|
||||
let exec_params =
|
||||
ShellHandler::to_exec_params(¶ms, turn.as_ref(), session.conversation_id);
|
||||
run_exec_like(RunExecLikeArgs {
|
||||
tool_name: ToolName::plain("container.exec"),
|
||||
exec_params,
|
||||
hook_command: codex_shell_command::parse_command::shlex_join(¶ms.command),
|
||||
additional_permissions: params.additional_permissions.clone(),
|
||||
prefix_rule,
|
||||
session,
|
||||
turn,
|
||||
tracker,
|
||||
call_id,
|
||||
freeform: false,
|
||||
shell_runtime_backend: ShellRuntimeBackend::Generic,
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolHandler for ContainerExecHandler {
|
||||
fn matches_kind(&self, payload: &ToolPayload) -> bool {
|
||||
matches!(payload, ToolPayload::Function { .. })
|
||||
}
|
||||
|
||||
fn pre_tool_use_payload(&self, invocation: &ToolInvocation) -> Option<PreToolUsePayload> {
|
||||
shell_function_pre_tool_use_payload(invocation)
|
||||
}
|
||||
|
||||
fn with_updated_hook_input(
|
||||
&self,
|
||||
invocation: ToolInvocation,
|
||||
updated_input: serde_json::Value,
|
||||
) -> Result<ToolInvocation, FunctionCallError> {
|
||||
rewrite_shell_function_updated_hook_input(invocation, updated_input, "container.exec")
|
||||
}
|
||||
|
||||
fn post_tool_use_payload(
|
||||
&self,
|
||||
invocation: &ToolInvocation,
|
||||
result: &Self::Output,
|
||||
) -> Option<PostToolUsePayload> {
|
||||
shell_function_post_tool_use_payload(invocation, result)
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
use codex_tools::ToolName;
|
||||
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolOutput;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::handlers::updated_hook_command;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::registry::PostToolUsePayload;
|
||||
use crate::tools::registry::PreToolUsePayload;
|
||||
use crate::tools::registry::ToolExecutor;
|
||||
use crate::tools::registry::ToolHandler;
|
||||
use crate::tools::runtimes::shell::ShellRuntimeBackend;
|
||||
use codex_tools::ToolSpec;
|
||||
|
||||
use super::super::shell_spec::create_local_shell_tool;
|
||||
use super::RunExecLikeArgs;
|
||||
use super::local_shell_payload_command;
|
||||
use super::run_exec_like;
|
||||
use super::shell_handler::ShellHandler;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LocalShellHandler {
|
||||
include_spec: bool,
|
||||
}
|
||||
|
||||
impl LocalShellHandler {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self { include_spec: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolExecutor<ToolInvocation> for LocalShellHandler {
|
||||
type Output = FunctionToolOutput;
|
||||
|
||||
fn tool_name(&self) -> ToolName {
|
||||
ToolName::plain("local_shell")
|
||||
}
|
||||
|
||||
fn spec(&self) -> Option<ToolSpec> {
|
||||
self.include_spec.then(create_local_shell_tool)
|
||||
}
|
||||
|
||||
fn supports_parallel_tool_calls(&self) -> bool {
|
||||
self.include_spec
|
||||
}
|
||||
|
||||
async fn handle(&self, invocation: ToolInvocation) -> Result<Self::Output, FunctionCallError> {
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
tracker,
|
||||
call_id,
|
||||
payload,
|
||||
..
|
||||
} = invocation;
|
||||
|
||||
let ToolPayload::LocalShell { params } = payload else {
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
"unsupported payload for local_shell handler".to_string(),
|
||||
));
|
||||
};
|
||||
|
||||
let exec_params =
|
||||
ShellHandler::to_exec_params(¶ms, turn.as_ref(), session.conversation_id);
|
||||
run_exec_like(RunExecLikeArgs {
|
||||
tool_name: ToolName::plain("local_shell"),
|
||||
exec_params,
|
||||
hook_command: codex_shell_command::parse_command::shlex_join(¶ms.command),
|
||||
additional_permissions: None,
|
||||
prefix_rule: None,
|
||||
session,
|
||||
turn,
|
||||
tracker,
|
||||
call_id,
|
||||
freeform: false,
|
||||
shell_runtime_backend: ShellRuntimeBackend::Generic,
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolHandler for LocalShellHandler {
|
||||
fn matches_kind(&self, payload: &ToolPayload) -> bool {
|
||||
matches!(payload, ToolPayload::LocalShell { .. })
|
||||
}
|
||||
|
||||
fn pre_tool_use_payload(&self, invocation: &ToolInvocation) -> Option<PreToolUsePayload> {
|
||||
local_shell_payload_command(&invocation.payload).map(|command| PreToolUsePayload {
|
||||
tool_name: HookToolName::bash(),
|
||||
tool_input: serde_json::json!({ "command": command }),
|
||||
})
|
||||
}
|
||||
|
||||
fn with_updated_hook_input(
|
||||
&self,
|
||||
mut invocation: ToolInvocation,
|
||||
updated_input: serde_json::Value,
|
||||
) -> Result<ToolInvocation, FunctionCallError> {
|
||||
let command = updated_hook_command(&updated_input)?;
|
||||
invocation.payload = match invocation.payload {
|
||||
ToolPayload::LocalShell { mut params } => {
|
||||
params.command = shlex::split(command).ok_or_else(|| {
|
||||
FunctionCallError::RespondToModel(
|
||||
"hook returned shell input with an invalid command string".to_string(),
|
||||
)
|
||||
})?;
|
||||
ToolPayload::LocalShell { params }
|
||||
}
|
||||
payload => payload,
|
||||
};
|
||||
Ok(invocation)
|
||||
}
|
||||
|
||||
fn post_tool_use_payload(
|
||||
&self,
|
||||
invocation: &ToolInvocation,
|
||||
result: &Self::Output,
|
||||
) -> Option<PostToolUsePayload> {
|
||||
let tool_response =
|
||||
result.post_tool_use_response(&invocation.call_id, &invocation.payload)?;
|
||||
let command = local_shell_payload_command(&invocation.payload)?;
|
||||
Some(PostToolUsePayload {
|
||||
tool_name: HookToolName::bash(),
|
||||
tool_use_id: invocation.call_id.clone(),
|
||||
tool_input: serde_json::json!({ "command": command }),
|
||||
tool_response,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::models::ShellToolCallParams;
|
||||
use codex_tools::ToolName;
|
||||
|
||||
use crate::exec::ExecCapturePolicy;
|
||||
use crate::exec::ExecParams;
|
||||
use crate::exec_env::create_env;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::handlers::parse_arguments_with_base_path;
|
||||
use crate::tools::handlers::resolve_workdir_base_path;
|
||||
use crate::tools::registry::PostToolUsePayload;
|
||||
use crate::tools::registry::PreToolUsePayload;
|
||||
use crate::tools::registry::ToolExecutor;
|
||||
use crate::tools::registry::ToolHandler;
|
||||
use crate::tools::runtimes::shell::ShellRuntimeBackend;
|
||||
use codex_tools::ToolSpec;
|
||||
|
||||
use super::super::shell_spec::ShellToolOptions;
|
||||
use super::super::shell_spec::create_shell_tool;
|
||||
use super::RunExecLikeArgs;
|
||||
use super::rewrite_shell_function_updated_hook_input;
|
||||
use super::run_exec_like;
|
||||
use super::shell_function_post_tool_use_payload;
|
||||
use super::shell_function_pre_tool_use_payload;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ShellHandler {
|
||||
options: Option<ShellToolOptions>,
|
||||
}
|
||||
|
||||
impl ShellHandler {
|
||||
pub(crate) fn new(options: ShellToolOptions) -> Self {
|
||||
Self {
|
||||
options: Some(options),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn to_exec_params(
|
||||
params: &ShellToolCallParams,
|
||||
turn_context: &TurnContext,
|
||||
thread_id: ThreadId,
|
||||
) -> ExecParams {
|
||||
ExecParams {
|
||||
command: params.command.clone(),
|
||||
cwd: turn_context.resolve_path(params.workdir.clone()),
|
||||
expiration: params.timeout_ms.into(),
|
||||
capture_policy: ExecCapturePolicy::ShellTool,
|
||||
env: create_env(&turn_context.shell_environment_policy, Some(thread_id)),
|
||||
network: turn_context.network.clone(),
|
||||
sandbox_permissions: params.sandbox_permissions.unwrap_or_default(),
|
||||
windows_sandbox_level: turn_context.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: turn_context
|
||||
.config
|
||||
.permissions
|
||||
.windows_sandbox_private_desktop,
|
||||
justification: params.justification.clone(),
|
||||
arg0: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolExecutor<ToolInvocation> for ShellHandler {
|
||||
type Output = FunctionToolOutput;
|
||||
|
||||
fn tool_name(&self) -> ToolName {
|
||||
ToolName::plain("shell")
|
||||
}
|
||||
|
||||
fn spec(&self) -> Option<ToolSpec> {
|
||||
self.options.map(create_shell_tool)
|
||||
}
|
||||
|
||||
fn supports_parallel_tool_calls(&self) -> bool {
|
||||
self.options.is_some()
|
||||
}
|
||||
|
||||
async fn handle(&self, invocation: ToolInvocation) -> Result<Self::Output, FunctionCallError> {
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
tracker,
|
||||
call_id,
|
||||
payload,
|
||||
..
|
||||
} = invocation;
|
||||
|
||||
let arguments = match payload {
|
||||
ToolPayload::Function { arguments } => arguments,
|
||||
_ => {
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
"unsupported payload for shell handler".to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let cwd = resolve_workdir_base_path(&arguments, &turn.cwd)?;
|
||||
let params: ShellToolCallParams = parse_arguments_with_base_path(&arguments, &cwd)?;
|
||||
let prefix_rule = params.prefix_rule.clone();
|
||||
let exec_params =
|
||||
ShellHandler::to_exec_params(¶ms, turn.as_ref(), session.conversation_id);
|
||||
run_exec_like(RunExecLikeArgs {
|
||||
tool_name: ToolName::plain("shell"),
|
||||
exec_params,
|
||||
hook_command: codex_shell_command::parse_command::shlex_join(¶ms.command),
|
||||
additional_permissions: params.additional_permissions.clone(),
|
||||
prefix_rule,
|
||||
session,
|
||||
turn,
|
||||
tracker,
|
||||
call_id,
|
||||
freeform: false,
|
||||
shell_runtime_backend: ShellRuntimeBackend::Generic,
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolHandler for ShellHandler {
|
||||
fn matches_kind(&self, payload: &ToolPayload) -> bool {
|
||||
matches!(payload, ToolPayload::Function { .. })
|
||||
}
|
||||
|
||||
fn pre_tool_use_payload(&self, invocation: &ToolInvocation) -> Option<PreToolUsePayload> {
|
||||
shell_function_pre_tool_use_payload(invocation)
|
||||
}
|
||||
|
||||
fn with_updated_hook_input(
|
||||
&self,
|
||||
invocation: ToolInvocation,
|
||||
updated_input: serde_json::Value,
|
||||
) -> Result<ToolInvocation, FunctionCallError> {
|
||||
rewrite_shell_function_updated_hook_input(invocation, updated_input, "shell")
|
||||
}
|
||||
|
||||
fn post_tool_use_payload(
|
||||
&self,
|
||||
invocation: &ToolInvocation,
|
||||
result: &Self::Output,
|
||||
) -> Option<PostToolUsePayload> {
|
||||
shell_function_post_tool_use_payload(invocation, result)
|
||||
}
|
||||
}
|
||||
@@ -11,20 +11,11 @@ pub struct CommandToolOptions {
|
||||
pub exec_permission_approvals_enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct ShellToolOptions {
|
||||
pub exec_permission_approvals_enabled: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn create_exec_command_tool(options: CommandToolOptions) -> ToolSpec {
|
||||
create_exec_command_tool_with_environment_id(options, /*include_environment_id*/ false)
|
||||
}
|
||||
|
||||
pub fn create_local_shell_tool() -> ToolSpec {
|
||||
ToolSpec::LocalShell {}
|
||||
}
|
||||
|
||||
pub(crate) fn create_exec_command_tool_with_environment_id(
|
||||
options: CommandToolOptions,
|
||||
include_environment_id: bool,
|
||||
@@ -153,69 +144,6 @@ pub fn create_write_stdin_tool() -> ToolSpec {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_shell_tool(options: ShellToolOptions) -> ToolSpec {
|
||||
let mut properties = BTreeMap::from([
|
||||
(
|
||||
"command".to_string(),
|
||||
JsonSchema::array(
|
||||
JsonSchema::string(/*description*/ None),
|
||||
Some("The command to execute".to_string()),
|
||||
),
|
||||
),
|
||||
(
|
||||
"workdir".to_string(),
|
||||
JsonSchema::string(Some(
|
||||
"The working directory to execute the command in".to_string(),
|
||||
)),
|
||||
),
|
||||
(
|
||||
"timeout_ms".to_string(),
|
||||
JsonSchema::number(Some(
|
||||
"The timeout for the command in milliseconds".to_string(),
|
||||
)),
|
||||
),
|
||||
]);
|
||||
properties.extend(create_approval_parameters(
|
||||
options.exec_permission_approvals_enabled,
|
||||
));
|
||||
|
||||
let description = if cfg!(windows) {
|
||||
format!(
|
||||
r#"Runs a Powershell command (Windows) and returns its output. Arguments to `shell` will be passed to CreateProcessW(). Most commands should be prefixed with ["powershell.exe", "-Command"].
|
||||
|
||||
Examples of valid command strings:
|
||||
|
||||
- ls -a (show hidden): ["powershell.exe", "-Command", "Get-ChildItem -Force"]
|
||||
- recursive find by name: ["powershell.exe", "-Command", "Get-ChildItem -Recurse -Filter *.py"]
|
||||
- recursive grep: ["powershell.exe", "-Command", "Get-ChildItem -Path C:\\myrepo -Recurse | Select-String -Pattern 'TODO' -CaseSensitive"]
|
||||
- ps aux | grep python: ["powershell.exe", "-Command", "Get-Process | Where-Object {{ $_.ProcessName -like '*python*' }}"]
|
||||
- setting an env var: ["powershell.exe", "-Command", "$env:FOO='bar'; echo $env:FOO"]
|
||||
- running an inline Python script: ["powershell.exe", "-Command", "@'\\nprint('Hello, world!')\\n'@ | python -"]
|
||||
|
||||
{}"#,
|
||||
windows_shell_guidance()
|
||||
)
|
||||
} else {
|
||||
r#"Runs a shell command and returns its output.
|
||||
- The arguments to `shell` will be passed to execvp(). Most terminal commands should be prefixed with ["bash", "-lc"].
|
||||
- Always set the `workdir` param when using the shell function. Do not use `cd` unless absolutely necessary."#
|
||||
.to_string()
|
||||
};
|
||||
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: "shell".to_string(),
|
||||
description,
|
||||
strict: false,
|
||||
defer_loading: None,
|
||||
parameters: JsonSchema::object(
|
||||
properties,
|
||||
Some(vec!["command".to_string()]),
|
||||
Some(false.into()),
|
||||
),
|
||||
output_schema: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_shell_command_tool(options: CommandToolOptions) -> ToolSpec {
|
||||
let mut properties = BTreeMap::from([
|
||||
(
|
||||
|
||||
@@ -6,91 +6,6 @@ fn windows_shell_guidance_description() -> String {
|
||||
format!("\n\n{}", windows_shell_guidance())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shell_tool_matches_expected_spec() {
|
||||
let tool = create_shell_tool(ShellToolOptions {
|
||||
exec_permission_approvals_enabled: false,
|
||||
});
|
||||
|
||||
let description = if cfg!(windows) {
|
||||
r#"Runs a Powershell command (Windows) and returns its output. Arguments to `shell` will be passed to CreateProcessW(). Most commands should be prefixed with ["powershell.exe", "-Command"].
|
||||
|
||||
Examples of valid command strings:
|
||||
|
||||
- ls -a (show hidden): ["powershell.exe", "-Command", "Get-ChildItem -Force"]
|
||||
- recursive find by name: ["powershell.exe", "-Command", "Get-ChildItem -Recurse -Filter *.py"]
|
||||
- recursive grep: ["powershell.exe", "-Command", "Get-ChildItem -Path C:\\myrepo -Recurse | Select-String -Pattern 'TODO' -CaseSensitive"]
|
||||
- ps aux | grep python: ["powershell.exe", "-Command", "Get-Process | Where-Object { $_.ProcessName -like '*python*' }"]
|
||||
- setting an env var: ["powershell.exe", "-Command", "$env:FOO='bar'; echo $env:FOO"]
|
||||
- running an inline Python script: ["powershell.exe", "-Command", "@'\\nprint('Hello, world!')\\n'@ | python -"]"#
|
||||
.to_string()
|
||||
+ &windows_shell_guidance_description()
|
||||
} else {
|
||||
r#"Runs a shell command and returns its output.
|
||||
- The arguments to `shell` will be passed to execvp(). Most terminal commands should be prefixed with ["bash", "-lc"].
|
||||
- Always set the `workdir` param when using the shell function. Do not use `cd` unless absolutely necessary."#
|
||||
.to_string()
|
||||
};
|
||||
|
||||
let properties = BTreeMap::from([
|
||||
(
|
||||
"command".to_string(),
|
||||
JsonSchema::array(JsonSchema::string(/*description*/ None), Some("The command to execute".to_string())),
|
||||
),
|
||||
(
|
||||
"workdir".to_string(),
|
||||
JsonSchema::string(Some("The working directory to execute the command in".to_string())),
|
||||
),
|
||||
(
|
||||
"timeout_ms".to_string(),
|
||||
JsonSchema::number(Some("The timeout for the command in milliseconds".to_string())),
|
||||
),
|
||||
(
|
||||
"sandbox_permissions".to_string(),
|
||||
JsonSchema::string(Some(
|
||||
"Sandbox permissions for the command. Set to \"require_escalated\" to request running without sandbox restrictions; defaults to \"use_default\"."
|
||||
.to_string(),
|
||||
)),
|
||||
),
|
||||
(
|
||||
"justification".to_string(),
|
||||
JsonSchema::string(Some(
|
||||
r#"Only set if sandbox_permissions is \"require_escalated\".
|
||||
Request approval from the user to run this command outside the sandbox.
|
||||
Phrased as a simple question that summarizes the purpose of the
|
||||
command as it relates to the task at hand - e.g. 'Do you want to
|
||||
fetch and pull the latest version of this git branch?'"#
|
||||
.to_string(),
|
||||
)),
|
||||
),
|
||||
(
|
||||
"prefix_rule".to_string(),
|
||||
JsonSchema::array(JsonSchema::string(/*description*/ None), Some(
|
||||
r#"Only specify when sandbox_permissions is `require_escalated`.
|
||||
Suggest a prefix command pattern that will allow you to fulfill similar requests from the user in the future.
|
||||
Should be a short but reasonable prefix, e.g. [\"git\", \"pull\"] or [\"uv\", \"run\"] or [\"pytest\"]."#
|
||||
.to_string(),
|
||||
)),
|
||||
),
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
tool,
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: "shell".to_string(),
|
||||
description,
|
||||
strict: false,
|
||||
defer_loading: None,
|
||||
parameters: JsonSchema::object(
|
||||
properties,
|
||||
Some(vec!["command".to_string()]),
|
||||
Some(false.into())
|
||||
),
|
||||
output_schema: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_command_tool_matches_expected_spec() {
|
||||
let tool = create_exec_command_tool(CommandToolOptions {
|
||||
@@ -224,77 +139,6 @@ fn write_stdin_tool_matches_expected_spec() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shell_tool_with_request_permission_includes_additional_permissions() {
|
||||
let tool = create_shell_tool(ShellToolOptions {
|
||||
exec_permission_approvals_enabled: true,
|
||||
});
|
||||
|
||||
let mut properties = BTreeMap::from([
|
||||
(
|
||||
"command".to_string(),
|
||||
JsonSchema::array(
|
||||
JsonSchema::string(/*description*/ None),
|
||||
Some("The command to execute".to_string()),
|
||||
),
|
||||
),
|
||||
(
|
||||
"workdir".to_string(),
|
||||
JsonSchema::string(Some(
|
||||
"The working directory to execute the command in".to_string(),
|
||||
)),
|
||||
),
|
||||
(
|
||||
"timeout_ms".to_string(),
|
||||
JsonSchema::number(Some(
|
||||
"The timeout for the command in milliseconds".to_string(),
|
||||
)),
|
||||
),
|
||||
]);
|
||||
properties.extend(create_approval_parameters(
|
||||
/*exec_permission_approvals_enabled*/ true,
|
||||
));
|
||||
|
||||
let description = if cfg!(windows) {
|
||||
format!(
|
||||
r#"Runs a Powershell command (Windows) and returns its output. Arguments to `shell` will be passed to CreateProcessW(). Most commands should be prefixed with ["powershell.exe", "-Command"].
|
||||
|
||||
Examples of valid command strings:
|
||||
|
||||
- ls -a (show hidden): ["powershell.exe", "-Command", "Get-ChildItem -Force"]
|
||||
- recursive find by name: ["powershell.exe", "-Command", "Get-ChildItem -Recurse -Filter *.py"]
|
||||
- recursive grep: ["powershell.exe", "-Command", "Get-ChildItem -Path C:\\myrepo -Recurse | Select-String -Pattern 'TODO' -CaseSensitive"]
|
||||
- ps aux | grep python: ["powershell.exe", "-Command", "Get-Process | Where-Object {{ $_.ProcessName -like '*python*' }}"]
|
||||
- setting an env var: ["powershell.exe", "-Command", "$env:FOO='bar'; echo $env:FOO"]
|
||||
- running an inline Python script: ["powershell.exe", "-Command", "@'\\nprint('Hello, world!')\\n'@ | python -"]
|
||||
|
||||
{}"#,
|
||||
windows_shell_guidance()
|
||||
)
|
||||
} else {
|
||||
r#"Runs a shell command and returns its output.
|
||||
- The arguments to `shell` will be passed to execvp(). Most terminal commands should be prefixed with ["bash", "-lc"].
|
||||
- Always set the `workdir` param when using the shell function. Do not use `cd` unless absolutely necessary."#
|
||||
.to_string()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
tool,
|
||||
ToolSpec::Function(ResponsesApiTool {
|
||||
name: "shell".to_string(),
|
||||
description,
|
||||
strict: false,
|
||||
defer_loading: None,
|
||||
parameters: JsonSchema::object(
|
||||
properties,
|
||||
Some(vec!["command".to_string()]),
|
||||
Some(false.into())
|
||||
),
|
||||
output_schema: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_permissions_tool_includes_full_permission_schema() {
|
||||
let tool =
|
||||
|
||||
@@ -16,7 +16,6 @@ use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolCallSource;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::handlers::LocalShellHandler;
|
||||
use crate::tools::handlers::ShellCommandHandler;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::registry::ToolHandler;
|
||||
@@ -203,44 +202,6 @@ fn shell_command_handler_rejects_login_when_disallowed() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn local_shell_pre_tool_use_payload_uses_joined_command() {
|
||||
let payload = ToolPayload::LocalShell {
|
||||
params: codex_protocol::models::ShellToolCallParams {
|
||||
command: vec![
|
||||
"bash".to_string(),
|
||||
"-lc".to_string(),
|
||||
"printf hi".to_string(),
|
||||
],
|
||||
workdir: None,
|
||||
timeout_ms: None,
|
||||
sandbox_permissions: None,
|
||||
additional_permissions: None,
|
||||
prefix_rule: None,
|
||||
justification: None,
|
||||
},
|
||||
};
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
let handler = LocalShellHandler::default();
|
||||
|
||||
assert_eq!(
|
||||
handler.pre_tool_use_payload(&ToolInvocation {
|
||||
session: session.into(),
|
||||
turn: turn.into(),
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
tracker: Arc::new(Mutex::new(TurnDiffTracker::new())),
|
||||
call_id: "call-41".to_string(),
|
||||
tool_name: codex_tools::ToolName::plain("local_shell"),
|
||||
source: crate::tools::context::ToolCallSource::Direct,
|
||||
payload,
|
||||
}),
|
||||
Some(crate::tools::registry::PreToolUsePayload {
|
||||
tool_name: HookToolName::bash(),
|
||||
tool_input: json!({ "command": "bash -lc 'printf hi'" }),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn shell_command_pre_tool_use_payload_uses_raw_command() {
|
||||
let payload = ToolPayload::Function {
|
||||
|
||||
@@ -229,7 +229,7 @@ async fn register_call_with_default_shell_trigger(
|
||||
"turn-1".to_string(),
|
||||
GuardianNetworkAccessTrigger {
|
||||
call_id: "call-1".to_string(),
|
||||
tool_name: "shell".to_string(),
|
||||
tool_name: "shell_command".to_string(),
|
||||
command: vec!["curl".to_string(), "https://example.com".to_string()],
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
@@ -249,7 +249,7 @@ async fn active_call_preserves_triggering_command_context() {
|
||||
let service = NetworkApprovalService::default();
|
||||
let expected = GuardianNetworkAccessTrigger {
|
||||
call_id: "call-1".to_string(),
|
||||
tool_name: "shell".to_string(),
|
||||
tool_name: "shell_command".to_string(),
|
||||
command: vec!["curl".to_string(), "https://example.com".to_string()],
|
||||
cwd: test_path_buf("/repo").abs(),
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
|
||||
@@ -180,7 +180,7 @@ impl ToolCallRuntime {
|
||||
if call.tool_name.namespace.is_none()
|
||||
&& matches!(
|
||||
call.tool_name.name.as_str(),
|
||||
"shell" | "container.exec" | "local_shell" | "shell_command" | "unified_exec"
|
||||
"shell_command" | "unified_exec"
|
||||
)
|
||||
{
|
||||
format!("Wall time: {secs:.1} seconds\naborted by user")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::sandboxing::SandboxPermissions;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::context::SharedTurnDiffTracker;
|
||||
@@ -12,10 +11,8 @@ use crate::tools::spec::build_specs_with_discoverable_tools;
|
||||
use codex_extension_api::ExtensionToolExecutor;
|
||||
use codex_mcp::ToolInfo;
|
||||
use codex_protocol::dynamic_tools::DynamicToolSpec;
|
||||
use codex_protocol::models::LocalShellAction;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::models::SearchToolCallParams;
|
||||
use codex_protocol::models::ShellToolCallParams;
|
||||
use codex_tools::DiscoverableTool;
|
||||
use codex_tools::ToolName;
|
||||
use codex_tools::ToolSpec;
|
||||
@@ -141,35 +138,6 @@ impl ToolRouter {
|
||||
call_id,
|
||||
payload: ToolPayload::Custom { input },
|
||||
})),
|
||||
ResponseItem::LocalShellCall {
|
||||
id,
|
||||
call_id,
|
||||
action,
|
||||
..
|
||||
} => {
|
||||
let call_id = call_id
|
||||
.or(id)
|
||||
.ok_or(FunctionCallError::MissingLocalShellCallId)?;
|
||||
|
||||
match action {
|
||||
LocalShellAction::Exec(exec) => {
|
||||
let params = ShellToolCallParams {
|
||||
command: exec.command,
|
||||
workdir: exec.working_directory,
|
||||
timeout_ms: exec.timeout_ms,
|
||||
sandbox_permissions: Some(SandboxPermissions::UseDefault),
|
||||
additional_permissions: None,
|
||||
prefix_rule: None,
|
||||
justification: None,
|
||||
};
|
||||
Ok(Some(ToolCall {
|
||||
tool_name: ToolName::plain("local_shell"),
|
||||
call_id,
|
||||
payload: ToolPayload::LocalShell { params },
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ async fn parallel_support_does_not_match_namespaced_local_tool_names() -> anyhow
|
||||
},
|
||||
);
|
||||
|
||||
let parallel_tool_name = ["shell", "local_shell", "exec_command", "shell_command"]
|
||||
let parallel_tool_name = ["exec_command", "shell_command"]
|
||||
.into_iter()
|
||||
.find(|name| {
|
||||
router.tool_supports_parallel(&ToolCall {
|
||||
@@ -399,7 +399,6 @@ fn namespace_function_names(specs: &[ToolSpec], namespace_name: &str) -> Vec<Str
|
||||
ToolSpec::Function(_)
|
||||
| ToolSpec::Freeform(_)
|
||||
| ToolSpec::ToolSearch { .. }
|
||||
| ToolSpec::LocalShell {}
|
||||
| ToolSpec::ImageGeneration { .. }
|
||||
| ToolSpec::WebSearch { .. }
|
||||
| ToolSpec::Namespace(_) => None,
|
||||
|
||||
@@ -62,19 +62,8 @@ pub struct ShellRequest {
|
||||
}
|
||||
|
||||
/// Selects `ShellRuntime` behavior for different callers.
|
||||
///
|
||||
/// Note: `Generic` is not the same as `ShellCommandClassic`.
|
||||
/// `Generic` means "no `shell_command`-specific backend behavior" (used by the
|
||||
/// generic `shell` tool path). The `ShellCommand*` variants are only for the
|
||||
/// `shell_command` tool family.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub(crate) enum ShellRuntimeBackend {
|
||||
/// Tool-agnostic/default runtime path.
|
||||
///
|
||||
/// Uses the normal `ShellRuntime` execution flow without enabling any
|
||||
/// `shell_command`-specific backend selection.
|
||||
#[default]
|
||||
Generic,
|
||||
/// Legacy backend for the `shell_command` tool.
|
||||
///
|
||||
/// Keeps `shell_command` on the standard shell runtime flow without the
|
||||
@@ -88,7 +77,6 @@ pub(crate) enum ShellRuntimeBackend {
|
||||
ShellCommandZshFork,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ShellRuntime {
|
||||
backend: ShellRuntimeBackend,
|
||||
}
|
||||
@@ -102,12 +90,6 @@ pub(crate) struct ApprovalKey {
|
||||
}
|
||||
|
||||
impl ShellRuntime {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
backend: ShellRuntimeBackend::Generic,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn for_shell_command(backend: ShellRuntimeBackend) -> Self {
|
||||
Self { backend }
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ use crate::tools::code_mode::execute_spec::create_code_mode_tool;
|
||||
use crate::tools::handlers::ApplyPatchHandler;
|
||||
use crate::tools::handlers::CodeModeExecuteHandler;
|
||||
use crate::tools::handlers::CodeModeWaitHandler;
|
||||
use crate::tools::handlers::ContainerExecHandler;
|
||||
use crate::tools::handlers::CreateGoalHandler;
|
||||
use crate::tools::handlers::DynamicToolHandler;
|
||||
use crate::tools::handlers::ExecCommandHandler;
|
||||
@@ -10,7 +9,6 @@ use crate::tools::handlers::ExecCommandHandlerOptions;
|
||||
use crate::tools::handlers::GetGoalHandler;
|
||||
use crate::tools::handlers::ListMcpResourceTemplatesHandler;
|
||||
use crate::tools::handlers::ListMcpResourcesHandler;
|
||||
use crate::tools::handlers::LocalShellHandler;
|
||||
use crate::tools::handlers::McpHandler;
|
||||
use crate::tools::handlers::PlanHandler;
|
||||
use crate::tools::handlers::ReadMcpResourceHandler;
|
||||
@@ -19,7 +17,6 @@ use crate::tools::handlers::RequestPluginInstallHandler;
|
||||
use crate::tools::handlers::RequestUserInputHandler;
|
||||
use crate::tools::handlers::ShellCommandHandler;
|
||||
use crate::tools::handlers::ShellCommandHandlerOptions;
|
||||
use crate::tools::handlers::ShellHandler;
|
||||
use crate::tools::handlers::TestSyncHandler;
|
||||
use crate::tools::handlers::ToolSearchHandler;
|
||||
use crate::tools::handlers::UpdateGoalHandler;
|
||||
@@ -39,7 +36,6 @@ use crate::tools::handlers::multi_agents_v2::ListAgentsHandler as ListAgentsHand
|
||||
use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2;
|
||||
use crate::tools::handlers::multi_agents_v2::WaitAgentHandler as WaitAgentHandlerV2;
|
||||
use crate::tools::handlers::shell_spec::ShellToolOptions;
|
||||
use crate::tools::handlers::view_image_spec::ViewImageToolOptions;
|
||||
use crate::tools::hosted_spec::WebSearchToolOptions;
|
||||
use crate::tools::hosted_spec::create_image_generation_tool;
|
||||
@@ -252,14 +248,6 @@ fn collect_handler_tools(
|
||||
let include_environment_id =
|
||||
matches!(config.environment_mode, ToolEnvironmentMode::Multiple);
|
||||
match &config.shell_type {
|
||||
ConfigShellToolType::Default => {
|
||||
handlers.push(Arc::new(ShellHandler::new(ShellToolOptions {
|
||||
exec_permission_approvals_enabled,
|
||||
})));
|
||||
}
|
||||
ConfigShellToolType::Local => {
|
||||
handlers.push(Arc::new(LocalShellHandler::new()));
|
||||
}
|
||||
ConfigShellToolType::UnifiedExec => {
|
||||
handlers.push(Arc::new(ExecCommandHandler::new(
|
||||
ExecCommandHandlerOptions {
|
||||
@@ -271,7 +259,9 @@ fn collect_handler_tools(
|
||||
handlers.push(Arc::new(WriteStdinHandler));
|
||||
}
|
||||
ConfigShellToolType::Disabled => {}
|
||||
ConfigShellToolType::ShellCommand => {
|
||||
ConfigShellToolType::Default
|
||||
| ConfigShellToolType::Local
|
||||
| ConfigShellToolType::ShellCommand => {
|
||||
handlers.push(Arc::new(ShellCommandHandler::new(
|
||||
ShellCommandHandlerOptions {
|
||||
backend_config: config.shell_command_backend,
|
||||
@@ -287,34 +277,15 @@ fn collect_handler_tools(
|
||||
&& config.shell_type != ConfigShellToolType::Disabled
|
||||
{
|
||||
match &config.shell_type {
|
||||
ConfigShellToolType::Default => {
|
||||
handlers.push(Arc::new(ContainerExecHandler));
|
||||
handlers.push(Arc::new(LocalShellHandler::default()));
|
||||
handlers.push(Arc::new(ShellCommandHandler::from(
|
||||
config.shell_command_backend,
|
||||
)));
|
||||
}
|
||||
ConfigShellToolType::Local => {
|
||||
handlers.push(Arc::new(ShellHandler::default()));
|
||||
handlers.push(Arc::new(ContainerExecHandler));
|
||||
handlers.push(Arc::new(ShellCommandHandler::from(
|
||||
config.shell_command_backend,
|
||||
)));
|
||||
}
|
||||
ConfigShellToolType::UnifiedExec => {
|
||||
handlers.push(Arc::new(ShellHandler::default()));
|
||||
handlers.push(Arc::new(ContainerExecHandler));
|
||||
handlers.push(Arc::new(LocalShellHandler::default()));
|
||||
handlers.push(Arc::new(ShellCommandHandler::from(
|
||||
config.shell_command_backend,
|
||||
)));
|
||||
}
|
||||
ConfigShellToolType::ShellCommand => {
|
||||
handlers.push(Arc::new(ShellHandler::default()));
|
||||
handlers.push(Arc::new(ContainerExecHandler));
|
||||
handlers.push(Arc::new(LocalShellHandler::default()));
|
||||
}
|
||||
ConfigShellToolType::Disabled => {}
|
||||
ConfigShellToolType::Default
|
||||
| ConfigShellToolType::Local
|
||||
| ConfigShellToolType::ShellCommand
|
||||
| ConfigShellToolType::Disabled => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2770,7 +2770,6 @@ fn strip_descriptions_tool(spec: &mut ToolSpec) {
|
||||
}
|
||||
}
|
||||
ToolSpec::Freeform(FreeformTool { .. })
|
||||
| ToolSpec::LocalShell {}
|
||||
| ToolSpec::ImageGeneration { .. }
|
||||
| ToolSpec::WebSearch { .. } => {}
|
||||
}
|
||||
|
||||
@@ -182,8 +182,8 @@ fn assert_contains_tool_names(tools: &[ToolSpec], expected_subset: &[&str]) {
|
||||
|
||||
fn shell_tool_name(config: &ToolsConfig) -> Option<&'static str> {
|
||||
match config.shell_type {
|
||||
ConfigShellToolType::Default => Some("shell"),
|
||||
ConfigShellToolType::Local => Some("local_shell"),
|
||||
ConfigShellToolType::Default => Some("shell_command"),
|
||||
ConfigShellToolType::Local => Some("shell_command"),
|
||||
ConfigShellToolType::UnifiedExec => None,
|
||||
ConfigShellToolType::Disabled => None,
|
||||
ConfigShellToolType::ShellCommand => Some("shell_command"),
|
||||
|
||||
@@ -111,15 +111,6 @@ fn tool_dispatch_payload(payload: &ToolPayload) -> ToolDispatchPayload {
|
||||
ToolPayload::Custom { input } => ToolDispatchPayload::Custom {
|
||||
input: input.clone(),
|
||||
},
|
||||
ToolPayload::LocalShell { params } => ToolDispatchPayload::LocalShell {
|
||||
command: params.command.clone(),
|
||||
workdir: params.workdir.clone(),
|
||||
timeout_ms: params.timeout_ms,
|
||||
sandbox_permissions: params.sandbox_permissions,
|
||||
prefix_rule: params.prefix_rule.clone(),
|
||||
additional_permissions: params.additional_permissions.clone(),
|
||||
justification: params.justification.clone(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ impl ToolSearchInfo {
|
||||
LoadableToolSpec::Namespace(namespace)
|
||||
}
|
||||
ToolSpec::ToolSearch { .. }
|
||||
| ToolSpec::LocalShell {}
|
||||
| ToolSpec::ImageGeneration { .. }
|
||||
| ToolSpec::WebSearch { .. }
|
||||
| ToolSpec::Freeform(_) => return None,
|
||||
|
||||
Reference in New Issue
Block a user