fix(compression): preserve clarify responses

This commit is contained in:
Crypto Intern 2026-08-07 17:23:47 +00:00 committed by kshitij
parent 98e96e1a60
commit d6511aecb6
2 changed files with 86 additions and 0 deletions

View File

@ -1314,6 +1314,41 @@ def _summarize_tool_result_unguarded(tool_name: str, tool_args: str, tool_conten
return "[todo] updated task list"
if tool_name == "clarify":
response_prefix = "[clarify] user responded: "
max_summary_chars = 200
truncation_marker = "...[truncated]"
# Idempotence: a later pressure-pruning pass may see the summary
# produced by an earlier pass. Preserve it instead of trying to parse
# the summary text as the original JSON result.
if content.startswith(response_prefix):
if len(content) <= max_summary_chars:
return content
return (
content[: max_summary_chars - len(truncation_marker)].rstrip()
+ truncation_marker
)
try:
result = json.loads(content)
except (json.JSONDecodeError, TypeError):
result = {}
response = result.get("user_response") if isinstance(result, dict) else None
resolved = (
isinstance(response, str) and bool(response)
) or (
isinstance(response, list)
and bool(response)
and all(isinstance(item, str) and item for item in response)
)
if resolved:
summary = response_prefix + json.dumps(response, ensure_ascii=False)
if len(summary) > max_summary_chars:
summary = (
summary[: max_summary_chars - len(truncation_marker)].rstrip()
+ truncation_marker
)
return summary
return "[clarify] asked user a question"
if tool_name == "text_to_speech":

View File

@ -61,6 +61,57 @@ class TestSummarizeToolResultWebExtract:
assert summary == "[web_extract] https://example.com/h (500 chars)"
class TestSummarizeToolResultClarify:
def test_preserves_resolved_user_response_without_metadata(self):
content = json.dumps({
"question": "When should I deploy?",
"choices_offered": ["Friday", "Monday"],
"user_response": "Friday",
})
summary = _summarize_tool_result("clarify", "{}", content)
assert summary == '[clarify] user responded: "Friday"'
def test_preserves_multi_select_user_response(self):
content = json.dumps({
"question": "Which checks should I run?",
"choices_offered": ["lint", "tests", "types"],
"user_response": ["lint", "tests"],
})
summary = _summarize_tool_result("clarify", "{}", content)
assert summary == '[clarify] user responded: ["lint", "tests"]'
def test_long_response_is_bounded_and_survives_repeated_pruning(self):
content = json.dumps({
"question": "Describe the deployment constraints",
"choices_offered": None,
"user_response": "A" * 1_000,
})
first_summary = _summarize_tool_result("clarify", "{}", content)
second_summary = _summarize_tool_result("clarify", "{}", first_summary)
assert len(first_summary) == 200
assert first_summary.startswith('[clarify] user responded: "AAA')
assert first_summary.endswith("...[truncated]")
assert second_summary == first_summary
@pytest.mark.parametrize(
"content",
[
json.dumps({"error": "Failed to get user input: internal details"}),
json.dumps({"question": "Q?", "user_response": ""}),
json.dumps({"question": "Q?", "user_response": {"internal": "value"}}),
"not json",
],
)
def test_does_not_expose_unresolved_or_internal_content(self, content):
summary = _summarize_tool_result("clarify", "{}", content)
assert summary == "[clarify] asked user a question"
class TestShouldCompress: