feature: Add "!cmd" user shell execution

- protocol: add Op::RunUserShellCommand to model a user-initiated one-off command
- core: handle new Op by spawning a cancellable task that runs the command using the user’s default shell; stream output via ExecCommand* events; send TaskStarted/TaskComplete; track as current_task so Interrupt works
- tui: detect leading '!' in composer submission and dispatch Op::RunUserShellCommand instead of sending a user message

No changes to sandbox env var behavior; uses existing exec pipeline and event types.
This commit is contained in:
Abhishek Bhardwaj
2025-09-12 22:33:09 -07:00
parent e85742635f
commit 2f0bc514b7
10 changed files with 352 additions and 17 deletions

View File

@@ -176,6 +176,16 @@ pub enum Op {
/// Request to shut down codex instance.
Shutdown,
/// Execute a user-initiated one-off shell command (triggered by "!cmd").
///
/// The command string is executed using the user's default shell and may
/// include shell syntax (pipes, redirects, etc.). Output is streamed via
/// `ExecCommand*` events and the UI regains control upon `TaskComplete`.
RunUserShellCommand {
/// The raw command string after '!'
command: String,
},
}
/// Determines the conditions under which the user is consulted to approve
@@ -1052,6 +1062,10 @@ pub struct ExecCommandBeginEvent {
/// The command's working directory if not the default cwd for the agent.
pub cwd: PathBuf,
pub parsed_cmd: Vec<ParsedCommand>,
/// True when this exec was initiated directly by the user (e.g. bang command),
/// not by the agent/model. Defaults to false for backwards compatibility.
#[serde(default)]
pub is_user_shell_command: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize, TS)]