Parse Codex app-server patch payloads
This commit is contained in:
1 parent
10ce1a216b
commit
b00e89795e
1 file changed
+63
-28
@@ -305,34 +305,58 @@ fn shell_word(word: &Value) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn file_change_diff(item: &Value) -> String {
|
fn file_change_diff(item: &Value) -> String {
|
||||||
let Some(changes) = item.get("changes").and_then(Value::as_object) else {
|
match item.get("changes") {
|
||||||
return String::new();
|
// Current app-server protocol: [{path, kind: {type, move_path?}, diff}].
|
||||||
};
|
Some(Value::Array(changes)) => changes
|
||||||
changes
|
.iter()
|
||||||
.iter()
|
.filter_map(|change| {
|
||||||
.map(|(path, change)| {
|
let path = change.get("path")?.as_str()?;
|
||||||
let kind = change.get("type").and_then(Value::as_str);
|
let kind = change.pointer("/kind/type").and_then(Value::as_str);
|
||||||
let from = if kind == Some("add") {
|
let moved = change.pointer("/kind/move_path").and_then(Value::as_str);
|
||||||
"/dev/null"
|
let body = change
|
||||||
} else {
|
.get("diff")
|
||||||
path
|
|
||||||
};
|
|
||||||
let to = if kind == Some("delete") {
|
|
||||||
"/dev/null"
|
|
||||||
} else {
|
|
||||||
change
|
|
||||||
.get("move_path")
|
|
||||||
.and_then(Value::as_str)
|
.and_then(Value::as_str)
|
||||||
.unwrap_or(path)
|
.unwrap_or_default();
|
||||||
};
|
Some(render_file_diff(path, kind, moved, body))
|
||||||
let body = change
|
})
|
||||||
.get("unified_diff")
|
.collect::<Vec<_>>()
|
||||||
.and_then(Value::as_str)
|
.join("\n"),
|
||||||
.unwrap_or_default();
|
// Older exec protocol and durable Codex rollouts: {path: {type, unified_diff, ...}}.
|
||||||
format!("--- {from}\n+++ {to}\n{body}")
|
Some(Value::Object(changes)) => changes
|
||||||
})
|
.iter()
|
||||||
.collect::<Vec<_>>()
|
.map(|(path, change)| {
|
||||||
.join("\n")
|
render_file_diff(
|
||||||
|
path,
|
||||||
|
change.get("type").and_then(Value::as_str),
|
||||||
|
change.get("move_path").and_then(Value::as_str),
|
||||||
|
change
|
||||||
|
.get("unified_diff")
|
||||||
|
.and_then(Value::as_str)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n"),
|
||||||
|
_ => String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_file_diff(path: &str, kind: Option<&str>, moved: Option<&str>, body: &str) -> String {
|
||||||
|
// Some protocol revisions carry complete unified diffs and some carry only their hunks.
|
||||||
|
if body.starts_with("--- ") || body.starts_with("diff --git ") {
|
||||||
|
return body.to_string();
|
||||||
|
}
|
||||||
|
let from = if kind == Some("add") {
|
||||||
|
"/dev/null"
|
||||||
|
} else {
|
||||||
|
path
|
||||||
|
};
|
||||||
|
let to = if kind == Some("delete") {
|
||||||
|
"/dev/null"
|
||||||
|
} else {
|
||||||
|
moved.unwrap_or(path)
|
||||||
|
};
|
||||||
|
format!("--- {from}\n+++ {to}\n{body}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tool_output(item: &Value) -> String {
|
fn tool_output(item: &Value) -> String {
|
||||||
@@ -537,7 +561,7 @@ mod tests {
|
|||||||
assert!(started.is_empty());
|
assert!(started.is_empty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
translator.translate(&line(
|
translator.translate(&line(
|
||||||
r#"{"method":"item/completed","params":{"item":{"id":"patch-1","type":"fileChange","changes":{"src/main.rs":{"type":"update","unified_diff":"@@ -1 +1 @@\n-old\n+new\n","move_path":null}},"status":"completed","stdout":"Success"}}}"#
|
r#"{"method":"item/completed","params":{"item":{"id":"patch-1","type":"fileChange","changes":[{"path":"src/main.rs","kind":{"type":"update","move_path":null},"diff":"@@ -1 +1 @@\n-old\n+new\n"}],"status":"completed","stdout":"Success"}}}"#
|
||||||
)),
|
)),
|
||||||
vec![
|
vec![
|
||||||
patch_start(
|
patch_start(
|
||||||
@@ -552,6 +576,17 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn the_legacy_file_change_shape_remains_readable() {
|
||||||
|
let item = line(
|
||||||
|
r#"{"changes":{"old.rs":{"type":"update","unified_diff":"@@ -1 +1 @@\n-a\n+b\n","move_path":"new.rs"}}}"#,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
file_change_diff(&item),
|
||||||
|
"--- old.rs\n+++ new.rs\n@@ -1 +1 @@\n-a\n+b\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn translates_native_app_server_streaming_without_repeating_the_final_item() {
|
fn translates_native_app_server_streaming_without_repeating_the_final_item() {
|
||||||
let mut translator = Translator::default();
|
let mut translator = Translator::default();
|
||||||
|
|||||||
Reference in new issue
Block a user