Skip to content

Commit d710094

Browse files
author
Mateusz
committed
fix(compression): detect suffix-placed [COMPRESSED] markers in already-processed check
The _already_processed_skip_warning method used _COMPRESSED_MARKER_RE.match() which only matches at string start. When MarkerStyle.SUFFIX is configured, the [COMPRESSED...] marker is appended at the end, so .match() misses it and the output gets re-compressed on subsequent requests, causing cumulative degradation. Switch to .search() to detect the marker regardless of placement. Add two regression tests: - test_service_skips_outputs_with_compressed_suffix_marker_already_processed: verifies suffix-placed markers are detected and skip re-compression - test_service_skips_output_with_suffix_marker_on_second_pass: end-to-end test with MarkerStyle.SUFFIX enabled, confirming a second compression pass skips already-compressed output
1 parent d6c9bbf commit d710094

2 files changed

Lines changed: 82 additions & 1 deletion

File tree

src/core/services/tool_output_compression_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ def _already_processed_skip_warning(message: ChatMessage) -> str | None:
815815
return None
816816
if _COMPACTED_STUB_MARKER in message.content:
817817
return "skipped_already_processed_compaction"
818-
if _COMPRESSED_MARKER_RE.match(message.content):
818+
if _COMPRESSED_MARKER_RE.search(message.content):
819819
return "skipped_already_processed_compression"
820820
if (
821821
_SYSTEM_REMINDER_MARKER in message.content

tests/unit/core/services/test_tool_output_compression_service.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
CompressionRule,
1616
CompressionRulePredicate,
1717
DynamicCompressionConfig,
18+
MarkerStyle,
1819
OutputPatternRuleConfig,
1920
)
2021
from src.core.domain.dynamic_compression import ToolOutputContext
@@ -474,6 +475,86 @@ async def test_service_skips_outputs_with_compressed_marker_already_processed()
474475
assert "skipped_already_processed_compression" in result.records[0].warnings
475476

476477

478+
@pytest.mark.asyncio
479+
async def test_service_skips_outputs_with_compressed_suffix_marker_already_processed() -> (
480+
None
481+
):
482+
registry = CompressionStrategyRegistry()
483+
registry.register("half_trim", _HalfTrimStrategy())
484+
service = ToolOutputCompressionService(
485+
strategy_registry=registry,
486+
identity_resolver=ToolIdentityResolver(),
487+
selector=RuleBasedStrategySelector(),
488+
)
489+
previously_compressed = (
490+
"diff --git a/foo.py b/foo.py\n--- a/foo.py\n+++ b/foo.py\n"
491+
"[COMPRESSED level=balanced methods=ansi_normalize,diff_compact saved=2048B]"
492+
)
493+
messages = _build_tool_messages("git diff", previously_compressed)
494+
cfg = DynamicCompressionConfig(
495+
enabled=True,
496+
min_bytes=0,
497+
marker=CompressionMarkerConfig(enabled=False),
498+
methods={"half_trim": True},
499+
rules=[
500+
CompressionRule(
501+
name="default",
502+
priority=1,
503+
when=CompressionRulePredicate(command_signature="git"),
504+
pipeline=["half_trim"],
505+
)
506+
],
507+
)
508+
509+
result = await service.compress_messages(messages=messages, config=cfg)
510+
511+
assert result.messages[1].content == previously_compressed
512+
assert result.records[0].applied is False
513+
assert "skipped_already_processed_compression" in result.records[0].warnings
514+
515+
516+
@pytest.mark.asyncio
517+
async def test_service_skips_output_with_suffix_marker_on_second_pass() -> None:
518+
registry = CompressionStrategyRegistry()
519+
registry.register("half_trim", _HalfTrimStrategy())
520+
service = ToolOutputCompressionService(
521+
strategy_registry=registry,
522+
identity_resolver=ToolIdentityResolver(),
523+
selector=RuleBasedStrategySelector(),
524+
)
525+
original_content = "line-1\nline-2\nline-3\nline-4\nline-5\n"
526+
messages = _build_tool_messages("git diff", original_content)
527+
cfg = DynamicCompressionConfig(
528+
enabled=True,
529+
min_bytes=0,
530+
marker=CompressionMarkerConfig(
531+
enabled=True,
532+
style=MarkerStyle.SUFFIX,
533+
include_sizes=False,
534+
include_methods=False,
535+
),
536+
methods={"half_trim": True},
537+
rules=[
538+
CompressionRule(
539+
name="default",
540+
priority=1,
541+
when=CompressionRulePredicate(command_signature="git"),
542+
pipeline=["half_trim"],
543+
)
544+
],
545+
)
546+
547+
first_pass = await service.compress_messages(messages=messages, config=cfg)
548+
assert first_pass.records[0].applied is True
549+
first_content = first_pass.messages[1].content
550+
551+
second_pass = await service.compress_messages(
552+
messages=first_pass.messages, config=cfg
553+
)
554+
assert second_pass.records[0].applied is False
555+
assert second_pass.messages[1].content == first_content
556+
557+
477558
@pytest.mark.asyncio
478559
async def test_service_skips_artifact_preview_system_reminder_outputs() -> None:
479560
registry = CompressionStrategyRegistry()

0 commit comments

Comments
 (0)