mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-10 14:27:00 -04:00
fix(read-lifecycle): harden CCR persistence (is None + import guard + try/except)
Address Copilot review feedback: - content_router.py: explicit `is None` check (truthiness override would discard falsy test doubles); guard the `get_compression_store` import so a stripped build without the module still runs read_lifecycle, matching smart_crusher's pattern. - read_lifecycle.py: wrap `store.store(...)` in try/except with a precomputed fallback hash so a transient backend failure can't break compress(), mirroring read_maturation.py. 22 tests pass; end-to-end via headroom.compress() still hits the store.
This commit is contained in:
parent
dde424783f
commit
55a0dfde67
2 changed files with 29 additions and 16 deletions
|
|
@ -2417,12 +2417,22 @@ class ContentRouter(Transform):
|
|||
"""
|
||||
# Pre-process: Read lifecycle management (stale/superseded detection)
|
||||
if self.config.read_lifecycle.enabled:
|
||||
from ..cache.compression_store import get_compression_store
|
||||
from .read_lifecycle import ReadLifecycleManager
|
||||
|
||||
# is None (not truthiness) so falsy test doubles are honored;
|
||||
# guarded import keeps read_lifecycle running in stripped builds.
|
||||
injected_store = kwargs.get("compression_store")
|
||||
if injected_store is None:
|
||||
try:
|
||||
from ..cache.compression_store import get_compression_store
|
||||
|
||||
injected_store = get_compression_store()
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
lifecycle_mgr = ReadLifecycleManager(
|
||||
self.config.read_lifecycle,
|
||||
compression_store=kwargs.get("compression_store") or get_compression_store(),
|
||||
compression_store=injected_store,
|
||||
)
|
||||
lifecycle_result = lifecycle_mgr.apply(
|
||||
messages,
|
||||
|
|
|
|||
|
|
@ -474,21 +474,24 @@ class ReadLifecycleManager:
|
|||
if content_bytes < self.config.min_size_bytes:
|
||||
return False, content, None
|
||||
|
||||
# Store original in CCR if available
|
||||
ccr_hash = None
|
||||
# Best-effort CCR persistence (mirrors read_maturation.py): a store
|
||||
# failure must not break compress().
|
||||
ccr_hash = hashlib.sha256(content.encode()).hexdigest()[:24]
|
||||
if self.store is not None:
|
||||
ccr_hash = self.store.store(
|
||||
original=content,
|
||||
compressed="",
|
||||
tool_name="Read",
|
||||
tool_call_id=classification.tool_call_id,
|
||||
compression_strategy=f"read_lifecycle:{classification.state.value}",
|
||||
)
|
||||
|
||||
# Generate marker
|
||||
if ccr_hash is None:
|
||||
# No CCR store — generate a content hash for reference
|
||||
ccr_hash = hashlib.sha256(content.encode()).hexdigest()[:24]
|
||||
try:
|
||||
ccr_hash = self.store.store(
|
||||
original=content,
|
||||
compressed="",
|
||||
tool_name="Read",
|
||||
tool_call_id=classification.tool_call_id,
|
||||
compression_strategy=f"read_lifecycle:{classification.state.value}",
|
||||
)
|
||||
except Exception as e: # noqa: BLE001 - storage failure must not break the request
|
||||
logger.warning(
|
||||
"read_lifecycle: CCR store failed for %s: %s",
|
||||
classification.tool_call_id,
|
||||
e,
|
||||
)
|
||||
|
||||
file_display = classification.file_path or "unknown"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue