Coverage for merco/context/recovery.py: 100%
21 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 14:04 +0800
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 14:04 +0800
1"""ContextCompressRecovery — compresses context when request body is too large."""
2from __future__ import annotations
4import logging
5from merco.core.pipeline import Recovery, RecoveryContext
7logger = logging.getLogger("merco.pipeline")
10class ContextCompressRecovery(Recovery):
11 """Compress context: triggered by 413/too-long keywords OR large context."""
13 name = "compress_context"
15 def __init__(self, min_context_bytes: int = 30000):
16 self.min_context_bytes = min_context_bytes
18 async def attempt(self, ctx: RecoveryContext) -> bool:
19 if ctx.compress_count >= ctx.max_compress:
20 return False
22 status = getattr(ctx.error, "status_code", None)
23 body = str(ctx.error).lower()
25 # Force trigger on explicit too-long errors, even for small contexts.
26 force = (
27 status == 413
28 or "context length" in body
29 or "maximum context" in body
30 or "prompt too long" in body
31 or ("too long" in body and "context" in body)
32 )
34 if not force:
35 if ctx.context_tokens > 0 and \
36 ctx.context_tokens * 4 < self.min_context_bytes:
37 return False
39 logger.info("→ 压缩上下文后重试 LLM(第 %d/%d 次)",
40 ctx.compress_count + 1, ctx.max_compress)
41 ctx.compress = True
42 ctx.extra_wait = max(ctx.extra_wait, 0.5)
43 return True