Unwrap rendered Codex Bash commands
This commit is contained in:
1 parent
b00e89795e
commit
26fe9895e7
1 file changed
+48
@@ -270,6 +270,7 @@ fn tool(item: &Value) -> Option<(String, String, Value)> {
|
|||||||
fn command_tool(item: &Value) -> (String, Value) {
|
fn command_tool(item: &Value) -> (String, Value) {
|
||||||
let command = item.get("command").cloned().unwrap_or(Value::Null);
|
let command = item.get("command").cloned().unwrap_or(Value::Null);
|
||||||
if let Some(script) = command.as_str() {
|
if let Some(script) = command.as_str() {
|
||||||
|
let script = rendered_bash_script(script).unwrap_or_else(|| script.to_string());
|
||||||
return ("Bash".to_string(), json!({"command": script}));
|
return ("Bash".to_string(), json!({"command": script}));
|
||||||
}
|
}
|
||||||
if let Some(argv) = command.as_array()
|
if let Some(argv) = command.as_array()
|
||||||
@@ -290,6 +291,39 @@ fn command_tool(item: &Value) -> (String, Value) {
|
|||||||
("Shell".to_string(), json!({"command": command}))
|
("Shell".to_string(), json!({"command": command}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// App-server renders the executor argv into one shell-quoted string. Unwrap only the exact Bash
|
||||||
|
/// form Codex currently emits; anything with another argument or quoting form stays visible rather
|
||||||
|
/// than being decoded into a command that was not actually run.
|
||||||
|
fn rendered_bash_script(command: &str) -> Option<String> {
|
||||||
|
let quoted = ["/usr/bin/bash -lc ", "/bin/bash -lc ", "bash -lc "]
|
||||||
|
.iter()
|
||||||
|
.find_map(|prefix| command.strip_prefix(prefix))?;
|
||||||
|
if !quoted.starts_with('\'') {
|
||||||
|
return (!quoted.is_empty() && !quoted.chars().any(char::is_whitespace))
|
||||||
|
.then(|| quoted.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rest = quoted;
|
||||||
|
let mut script = String::new();
|
||||||
|
loop {
|
||||||
|
rest = rest.strip_prefix('\'')?;
|
||||||
|
let end = rest.find('\'')?;
|
||||||
|
script.push_str(&rest[..end]);
|
||||||
|
rest = &rest[end + 1..];
|
||||||
|
if rest.is_empty() {
|
||||||
|
return Some(script);
|
||||||
|
}
|
||||||
|
if let Some(after_quote) = rest.strip_prefix("\\'") {
|
||||||
|
script.push('\'');
|
||||||
|
rest = after_quote;
|
||||||
|
} else {
|
||||||
|
let after_quote = rest.strip_prefix("\"'\"")?;
|
||||||
|
script.push('\'');
|
||||||
|
rest = after_quote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn shell_word(word: &Value) -> String {
|
fn shell_word(word: &Value) -> String {
|
||||||
let Some(word) = word.as_str() else {
|
let Some(word) = word.as_str() else {
|
||||||
return word.to_string();
|
return word.to_string();
|
||||||
@@ -539,6 +573,20 @@ mod tests {
|
|||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let rendered = tool(&json!({
|
||||||
|
"id": "rendered",
|
||||||
|
"type": "commandExecution",
|
||||||
|
"command": r#"/usr/bin/bash -lc 'printf '\''%s\n'\'' hello'"#
|
||||||
|
}));
|
||||||
|
assert_eq!(
|
||||||
|
rendered,
|
||||||
|
Some((
|
||||||
|
"rendered".to_string(),
|
||||||
|
"Bash".to_string(),
|
||||||
|
json!({"command": "printf '%s\\n' hello"})
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
let fish = tool(&line(
|
let fish = tool(&line(
|
||||||
r#"{"id":"fish","type":"commandExecution","command":["/usr/bin/fish","-c","pwd"]}"#,
|
r#"{"id":"fish","type":"commandExecution","command":["/usr/bin/fish","-c","pwd"]}"#,
|
||||||
));
|
));
|
||||||
|
|||||||
Reference in new issue
Block a user