| 642 | } |
| 643 | |
| 644 | fn normalize_stop_raw(mut raw: Value) -> Value { |
| 645 | if let Some(obj) = raw.as_object_mut() { |
| 646 | // `stop_hook_active` means a previous Stop hook requested a |
| 647 | // continuation; it is not a model finish reason. Codex emits a real |
| 648 | // SessionEnd event for terminal lifecycle work, so Stop only closes |
| 649 | // the current response/turn. |
| 650 | obj.entry("finish_reason".to_string()) |
| 651 | .or_insert_with(|| Value::String("stop".to_string())); |
| 652 | } |
| 653 | raw |
| 654 | } |
| 655 | |
| 656 | fn normalize_tool_raw(mut raw: Value) -> Value { |
| 657 | let Some(response) = raw.get("tool_response").cloned() else { |