mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
## Description Make the CCR retrieval store TTL configurable so long-running agent jobs can keep `headroom_retrieve` markers resolvable beyond the previous hard-coded 300-second window. Fixes #714 ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Add `HEADROOM_CCR_TTL_SECONDS` for the global CCR `CompressionStore` default TTL, with validation and fallback to 300 seconds. - Expose the effective CCR TTL as `store.default_ttl_seconds` from `/v1/retrieve/stats`. - Distinguish missing vs expired CCR retrieval failures in `/v1/retrieve`, `/v1/retrieve/{hash}`, tool-call handling, and CCR response handling. - Update CCR docs, README wording, and CHANGELOG for the user-facing TTL behavior. - Add regression tests for env-configured TTL, invalid env fallback, explicit TTL precedence, stats exposure, and expired retrieval detail. ## Reproduction Before this change, the proxy-global CCR store always used the default 300-second TTL when callers used `get_compression_store()` without an explicit `default_ttl`. A long-running agent job could receive a `<<ccr:...>>` marker and fail later with a generic not-found/expired response after the fixed 5-minute retention window. The new tests cover this by setting `HEADROOM_CCR_TTL_SECONDS`, creating CCR entries through the same global store used by the proxy, and asserting that stored entries and `/v1/retrieve/stats` use the configured retention. ## Real behavior proof Setup tested: - macOS 15.7.2 - Python 3.13.9 via `uv run --frozen --extra dev --extra proxy` - Local Headroom proxy subprocess: `python -m headroom.proxy.server` - Proxy config: `HEADROOM_TELEMETRY=off`, `HEADROOM_CACHE_ENABLED=false`, `HEADROOM_RATE_LIMIT_ENABLED=false` - Provider/model: no live upstream provider needed; exercised local `/v1/compress` -> `/v1/retrieve` CCR HTTP flow with model `gpt-4o` Exact steps run after the patch: 1. Start a real Headroom proxy process with `HEADROOM_CCR_TTL_SECONDS=7200`. 2. POST a 200-item tool-result payload to `/v1/compress`. 3. Extract the emitted `<<ccr:...>>` marker hash from the compressed messages. 4. GET `/v1/retrieve/stats`. 5. POST `/v1/retrieve` with the marker hash. 6. Repeat with `HEADROOM_CCR_TTL_SECONDS=1`, wait 1.5 seconds, and retrieve the same way to verify explicit expiration reporting. Observed result: ```json { "long_ttl": { "ccr_hash": "b473e632aa47", "retrieve_status": 200, "retrieved_content_has_result_199": true, "stats_default_ttl_seconds": 7200, "stats_entry_count": 1, "ttl_seconds": 7200 }, "short_ttl_expired": { "ccr_hash": "b473e632aa47", "retrieve_detail": "Entry expired (CCR TTL: 1 seconds; age: 2 seconds)", "retrieve_status": 404, "stats_default_ttl_seconds": 1, "stats_entry_count": 1, "ttl_seconds": 1 } } ``` What I did not test: - A live OpenRouter/OpenAI/Anthropic upstream request. - A durable/non-memory CCR backend. - A literal 5+ minute wall-clock wait; the process E2E used `7200` to prove configured retention and `1` second to prove expiration behavior quickly. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [x] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [x] Manual testing performed ## Test Output ```bash UV_SKIP_WHEEL_FILENAME_CHECK=1 uv run --frozen --extra dev --extra proxy pytest tests/test_compression_store.py tests/test_proxy_ccr.py tests/test_ccr_response_handler.py tests/test_ccr_response_handler_extra.py # 152 passed, 2 warnings in 12.87s UV_SKIP_WHEEL_FILENAME_CHECK=1 uv run --frozen --extra dev --extra proxy pytest tests/test_adapter_hooks.py tests/test_toin_feedback.py tests/test_toin_fixes.py # 55 passed, 13 skipped, 1 warning in 0.53s UV_SKIP_WHEEL_FILENAME_CHECK=1 uv run --frozen --extra dev --extra proxy ruff check . # All checks passed! UV_SKIP_WHEEL_FILENAME_CHECK=1 uv run --frozen --extra dev --extra proxy ruff format --check . # 776 files already formatted UV_SKIP_WHEEL_FILENAME_CHECK=1 uv run --frozen --extra dev --extra proxy mypy headroom # Success: no issues found in 346 source files ``` Existing warnings observed in the targeted tests were unrelated to this change: - AnthropicProvider tiktoken approximation warning in proxy CCR tests. - Deprecated `ToolIntelligenceNetwork.get_recommendation()` warning in existing TOIN assertions. ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) Not applicable. ## Additional Notes No new dependencies. Default behavior remains 300 seconds unless `HEADROOM_CCR_TTL_SECONDS` is set. |
||
|---|---|---|
| .. | ||
| app | ||
| components | ||
| content/docs | ||
| overrides | ||
| screenshots | ||
| spec | ||
| .gitignore | ||
| auth-modes.md | ||
| bedrock.md | ||
| bun.lock | ||
| next.config.mjs | ||
| observability.md | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| proxy.ts | ||
| README.md | ||
| rtk-architecture.md | ||
| source.config.ts | ||
| tsconfig.json | ||
docs
This is a Next.js application generated with Create Fumadocs.
Run development server:
npm run dev
# or
pnpm dev
# or
yarn dev
Open http://localhost:3000 with your browser to see the result.
Explore
In the project, you can see:
lib/source.ts: Code for content source adapter,loader()provides the interface to access your content.lib/layout.shared.tsx: Shared options for layouts, optional but preferred to keep.
| Route | Description |
|---|---|
app/(home) |
The route group for your landing page and other pages. |
app/docs |
The documentation layout and pages. |
app/api/search/route.ts |
The Route Handler for search. |
Fumadocs MDX
A source.config.ts config file has been included, you can customise different options like frontmatter schema.
Read the Introduction for further details.
Learn More
To learn more about Next.js and Fumadocs, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
- Fumadocs - learn about Fumadocs