fix(auxiliary): treat a content-filtered Codex aux partial as length
An incomplete response with incomplete_details.reason=content_filter kept finish_reason 'content_filter'. The aux consumers (context compressor truncation guard, micro_compaction, MCP sampling) only reject 'length', so a filtered partial summary was committed as if it were complete. No aux consumer reads 'content_filter', so map every provider-incomplete response to 'length' (completed tool calls still stay 'tool_calls').
This commit is contained in:
@@ -1155,12 +1155,10 @@ def _parse_codex_final_response(
|
||||
)
|
||||
# Aux consumers speak Chat Completions: "length" activates their existing
|
||||
# partial-summary rejection/fallback, whereas Codex's "incomplete" does not.
|
||||
# A final_answer phase cannot override the provider's incomplete status, but completed
|
||||
# tool calls stay "tool_calls" so dispatchers (e.g. MCP sampling) still run them.
|
||||
status = _lower_or_none(normalized_final.status)
|
||||
reason = str(_field(normalized_final.incomplete_details, "reason", "") or "").strip().lower()
|
||||
# Any provider-incomplete response (token cap or content_filter) is a partial no aux consumer
|
||||
# may commit; completed tool calls stay "tool_calls" so dispatchers (e.g. MCP sampling) still run them.
|
||||
if finish_reason != "tool_calls" and (
|
||||
finish_reason == "incomplete" or (status == "incomplete" and reason != "content_filter")
|
||||
finish_reason == "incomplete" or _lower_or_none(normalized_final.status) == "incomplete"
|
||||
):
|
||||
finish_reason = "length"
|
||||
text_parts = [message.content] if message.content else []
|
||||
|
||||
@@ -99,6 +99,8 @@ _CODEX_REASONING_ONLY = SimpleNamespace(
|
||||
id="tool-call-like-output-text-beside-commentary"),
|
||||
pytest.param("", "incomplete", [_message("PARTIAL")], "max_output_tokens", "PARTIAL", "length", id="token-cap"),
|
||||
pytest.param("", "incomplete", [_TOOL_CALL], "max_output_tokens", None, "tool_calls", id="token-cap-after-tool-call"),
|
||||
# Compressor only rejects "length": a content-filtered partial must not be committed as a summary.
|
||||
pytest.param("", "incomplete", [_message("CF")], "content_filter", "CF", "length", id="content-filter"),
|
||||
# Commentary + unphased text is incomplete whether or not the unphased text looks like a tool call.
|
||||
pytest.param("", "completed", [_message("NOTE", phase="commentary"), _message(_LEAK_LIKE_ANSWER, phase=None)],
|
||||
None, _LEAK_LIKE_ANSWER, "length", id="tool-call-like-beside-commentary"),
|
||||
|
||||
Reference in New Issue
Block a user