mirror of
https://github.com/openai/codex.git
synced 2026-09-11 20:36:49 +00:00
## Why `shell-tool-mcp` and the Bash fork are no longer needed, but the patched zsh fork is still relevant for shell escalation and for the DotSlash-backed zsh-fork integration tests. Deleting the old `shell-tool-mcp` workflow also deleted the only pipeline that rebuilt those patched zsh binaries. This keeps the package removal, while preserving a small release path that can be reused whenever `codex-rs/shell-escalation/patches/zsh-exec-wrapper.patch` changes. ## What changed - removed the `shell-tool-mcp` workspace package, its npm packaging/release jobs, the Bash test fixture, and the remaining Bash-specific compatibility wiring - deleted the old `.github/workflows/shell-tool-mcp.yml` and `.github/workflows/shell-tool-mcp-ci.yml` workflows now that their responsibilities have been replaced or removed - kept the zsh patch under `codex-rs/shell-escalation/patches/zsh-exec-wrapper.patch` and updated the `codex-rs/shell-escalation` docs/code to describe the zsh-based flow directly - added `.github/workflows/rust-release-zsh.yml` to build only the three zsh binaries that `codex-rs/app-server/tests/suite/zsh` needs today: - `aarch64-apple-darwin` on `macos-15` - `x86_64-unknown-linux-musl` on `ubuntu-24.04` - `aarch64-unknown-linux-musl` on `ubuntu-24.04` - extracted the shared zsh build/smoke-test/stage logic into `.github/scripts/build-zsh-release-artifact.sh`, made that helper directly executable, and now invoke it directly from the workflow so the Linux and macOS jobs only keep the OS-specific setup in YAML - wired those standalone `codex-zsh-*.tar.gz` assets into `rust-release.yml` and added `.github/dotslash-zsh-config.json` so releases also publish a `codex-zsh` DotSlash file - updated the checked-in `codex-rs/app-server/tests/suite/zsh` fixture comments to explain that new releases come from the standalone zsh assets, while the checked-in fixture remains pinned to the latest historical release until a newer zsh artifact is published - tightened a couple of follow-on cleanups in `codex-rs/shell-escalation`: the `ExecParams::command` comment now describes the shell `-c`/`-lc` string more clearly, and the README now points at the same `git.code.sf.net` zsh source URL that the workflow uses ## Testing - `cargo test -p codex-shell-escalation` - `just argument-comment-lint` - `bash -n .github/scripts/build-zsh-release-artifact.sh` - attempted `cargo test -p codex-core`; unrelated existing failures remain, but the touched `tools::runtimes::shell::unix_escalation::*` coverage passed during that run
89 lines
2.6 KiB
Rust
89 lines
2.6 KiB
Rust
use std::collections::HashMap;
|
|
use std::os::fd::RawFd;
|
|
use std::path::PathBuf;
|
|
|
|
use codex_protocol::approvals::EscalationPermissions;
|
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
|
|
/// Exec wrappers read this to find the inherited FD for the escalation socket.
|
|
pub const ESCALATE_SOCKET_ENV_VAR: &str = "CODEX_ESCALATE_SOCKET";
|
|
|
|
/// Patched shells use this to wrap exec() calls.
|
|
pub const EXEC_WRAPPER_ENV_VAR: &str = "EXEC_WRAPPER";
|
|
|
|
/// The client sends this to the server to request an exec() call.
|
|
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
|
pub struct EscalateRequest {
|
|
/// The executable path from the intercepted exec call.
|
|
///
|
|
/// This may be relative, in which case it should be resolved against
|
|
/// `workdir`.
|
|
pub file: PathBuf,
|
|
/// The argv, including the program name (argv[0]).
|
|
pub argv: Vec<String>,
|
|
pub workdir: AbsolutePathBuf,
|
|
pub env: HashMap<String, String>,
|
|
}
|
|
|
|
/// The server sends this to the client to respond to an exec() request.
|
|
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
|
pub struct EscalateResponse {
|
|
pub action: EscalateAction,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub enum EscalationDecision {
|
|
Run,
|
|
Escalate(EscalationExecution),
|
|
Deny { reason: Option<String> },
|
|
}
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub enum EscalationExecution {
|
|
/// Rerun the intercepted command outside any sandbox wrapper.
|
|
Unsandboxed,
|
|
/// Rerun using the turn's current sandbox configuration.
|
|
TurnDefault,
|
|
/// Rerun using an explicit sandbox configuration attached to the request.
|
|
Permissions(EscalationPermissions),
|
|
}
|
|
|
|
impl EscalationDecision {
|
|
pub fn run() -> Self {
|
|
Self::Run
|
|
}
|
|
|
|
pub fn escalate(execution: EscalationExecution) -> Self {
|
|
Self::Escalate(execution)
|
|
}
|
|
|
|
pub fn deny(reason: Option<String>) -> Self {
|
|
Self::Deny { reason }
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
|
pub enum EscalateAction {
|
|
/// The command should be run directly by the client.
|
|
Run,
|
|
/// The command should be escalated to the server for execution.
|
|
Escalate,
|
|
/// The command should not be executed.
|
|
Deny { reason: Option<String> },
|
|
}
|
|
|
|
/// The client sends this to the server to forward its open FDs.
|
|
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
pub struct SuperExecMessage {
|
|
pub fds: Vec<RawFd>,
|
|
}
|
|
|
|
/// The server responds when the exec()'d command has exited.
|
|
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
pub struct SuperExecResult {
|
|
pub exit_code: i32,
|
|
}
|