headroom/tests
Abhay Singh 7ff842da17
fix(proxy/openai): thread savings-profile kwargs into chat completions (#1606)
## Description

OpenAI-compatible `/v1/chat/completions` requests didn't receive the
same proxy
savings/profile kwargs as the other compression paths. The live chat
handler
(`handle_openai_chat` in `headroom/proxy/handlers/openai.py`) called
`openai_pipeline.apply()` with only `model_limit` / `context` /
`frozen_message_count` / `biases` / `compression_policy` — it never
passed
`proxy_pipeline_kwargs(self.config)`.

So when the proxy runs with `HEADROOM_SAVINGS_PROFILE=agent-90`, the
effective
config reports user/system-message compression and `target_ratio=0.10`,
but the
real chat path silently dropped all of it. OpenAI-compatible clients
such as
OpenCode kept protecting user messages and missed the configured
profile.

For contrast, `handlers/anthropic.py` passes
`**proxy_pipeline_kwargs(self.config)`
to every `apply()` call, and so does the dedicated OpenAI compress
endpoint in
this same module — only the two chat-completions `apply()` sites were
missing it.

Closes #1534

## Fix

Add `**proxy_pipeline_kwargs(self.config)` to both chat-path `apply()`
calls (the
token-mode branch and the non-token branch):

```python
lambda: self.openai_pipeline.apply(
    messages=messages,
    model=model,
    model_limit=context_limit,
    context=extract_user_query(messages),
    frozen_message_count=openai_frozen_count,
    biases=_hook_biases,
    compression_policy=compression_policy,
    **proxy_pipeline_kwargs(self.config),   # ← added
)
```

`proxy_pipeline_kwargs` is already imported in the module and is the
exact
helper the Anthropic handler and the OpenAI compress endpoint use, so
the chat
path now matches them.

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)

## Changes Made

- `headroom/proxy/handlers/openai.py`: pass
`**proxy_pipeline_kwargs(self.config)` on both `apply()` call sites in
`handle_openai_chat` (token-mode and non-token branches).
- `tests/test_proxy/test_openai_chat_savings_profile.py`: new regression
test driving the chat handler with `savings_profile="agent-90"` and
asserting the profile knobs reach `apply()`.
- `CHANGELOG.md`: Bug Fixes entry under Unreleased.

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [ ] Type checking passes (`mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

The new test drives the real chat handler through the `create_app` +
`TestClient`
harness with a recording `apply()` stub. Before the fix it captures
exactly the
five kwargs the issue describes (no profile knobs); after the fix the
profile
knobs are present:

```text
# before the fix (openai.py reverted, test kept)
E   AssertionError: assert None is True
E    +  where None = {...}.get('compress_user_messages')
# captured kwargs were: biases, compression_policy, messages, model,
# model_limit, context, frozen_message_count  — no profile knobs
FAILED tests/test_proxy/test_openai_chat_savings_profile.py::test_chat_completions_threads_savings_profile_kwargs_into_apply

# after the fix
tests\test_proxy\test_openai_chat_savings_profile.py .
======================== 1 passed, 1 warning in 39.44s ========================
```

No regression in the existing chat backend-path suite:

```text
$ uv run pytest tests/test_proxy/test_openai_backend_path.py
======================== 5 passed, 1 warning in 15.78s ========================
$ uv run ruff check headroom/proxy/handlers/openai.py tests/test_proxy/test_openai_chat_savings_profile.py
All checks passed!
```

## Real Behavior Proof

- Environment: Windows 11, Python 3.12.11, headroom built from this
branch (`uv sync --extra dev`), proxy config
`savings_profile="agent-90"`, `optimize=True`, `backend="anyllm"` with a
mocked OpenAI upstream.
- Exact command / steps: started the app with `create_app(config)`,
replaced `proxy.openai_pipeline.apply` with a recording stub, and POSTed
a real `/v1/chat/completions` request with a large user message so the
compression decision fires. Inspected the kwargs the handler actually
passed to `apply()`.
- Observed result: before the fix the recorded `apply()` kwargs were
`{biases, compression_policy, messages, model, model_limit, context,
frozen_message_count}` — no profile knobs. After the fix the same call
also carries `compress_user_messages=True`,
`compress_system_messages=True`, `target_ratio=0.10`,
`min_tokens_to_compress=120` (the agent-90 profile), matching the
issue's "Expected".
- Not tested: did not stand up a real OpenAI/OpenCode upstream
end-to-end (no live key in this environment); the upstream is mocked and
the assertion is on the kwargs the proxy threads into the compression
pipeline, which is exactly what the bug was about. Did not run the full
`mypy headroom` pass (two-line kwarg addition, no new types).

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## 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
- [ ] 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

## Additional Notes

- Two-line change plus comments; no new dependencies. Reuses the
existing `proxy_pipeline_kwargs` helper, so behavior is consistent
across Anthropic, the OpenAI compress endpoint, and now the OpenAI chat
path.
- @chopratejas flagging you for review — this aligns the OpenAI chat
path with the savings-profile handling the other providers already had.

Co-authored-by: JD Davis <mxjerrett@gmail.com>
2026-07-07 11:27:54 -05:00
..
cli
fixtures
integrations/test_strands
parity
test_backends
test_cache
test_cli fix: detect and clear stale ANTHROPIC_BASE_URL from crashed wrap sessions (#1768) (#1837) 2026-07-06 08:35:40 -07:00
test_compression
test_dashboard
test_evals
test_install
test_integrations
test_learn
test_live
test_mcp_registry
test_memory
test_providers fix(proxy): strip 1m model suffix before upstream forwarding (#1840) 2026-07-06 08:33:45 -07:00
test_proxy fix(proxy/openai): thread savings-profile kwargs into chat completions (#1606) 2026-07-07 11:27:54 -05:00
test_scripts
test_storage
test_tokenizers
test_transforms fix(build): enable Intel macOS pip installs via ort-load-dynamic (#1538) 2026-07-06 18:33:34 -05:00
__init__.py
_dotenv.py
_mcp_stub.py
_skip_helpers.py
conftest.py
e2e_cortex_latency.py
e2e_cortex_mcp.py
e2e_cortex_proxy.py
e2e_cortex_proxy_mcp.py
e2e_cortex_quality.py
e2e_cortex_savings.py
e2e_real_compression.py
e2e_ws_codex_usage_headers.py
e2e_ws_responses_compression.py
repro_unsendable_panic.py
test_acceptance.py
test_adapter_hooks.py
test_adaptive_sizer.py
test_adversarial_grid.py
test_agent_savings.py feat(agent-savings): land coding + general workload personas on main (#1732) 2026-07-03 07:28:19 -07:00
test_anthropic_beta_session_sticky.py
test_anthropic_pre_upstream_backpressure.py
test_anthropic_stage_timings.py
test_audit_codex.py
test_audit_reads.py
test_auth_mode.py
test_azure_foundry_claude_compression.py
test_backend_anyllm.py
test_backend_bugs.py
test_backend_streaming_cache_metrics.py
test_banner_upstream_targets.py
test_bash_search_lossless_fold.py feat(content-router): lossless-excluded compaction (grep/log/json) + enable in coding/general personas (#1762) 2026-07-03 12:09:05 -07:00
test_bedrock_region.py
test_bedrock_streaming_input_tokens.py
test_binaries.py
test_bundled_tools_savings.py
test_cache_aligner_detector_only.py
test_cache_control_move_bust.py fix(proxy): keep cache_control bounded + stable so the freeze overlay stops busting (#1852) 2026-07-06 17:05:34 -07:00
test_cache_prefix_overlay.py fix(proxy): freeze must forward cached (compressed) prefix byte-identical — stop token-mode cache busting (#1850) 2026-07-06 14:54:39 -07:00
test_canonical_pipeline.py
test_ccr.py
test_ccr_batch_processor.py
test_ccr_batch_store.py
test_ccr_context_tracker.py
test_ccr_feedback.py
test_ccr_mcp_server.py
test_ccr_response_handler.py
test_ccr_response_handler_extra.py
test_ccr_row_drop_store_bridge.py
test_ccr_rust_marker_hash_bridge.py
test_ccr_sqlite_backend.py
test_ccr_tool_always_on.py
test_ccr_tool_injection.py
test_claude_session_branch_compare.py
test_claude_session_mode_benchmark.py
test_cli_dashboard.py
test_cli_doctor.py
test_cli_learn.py
test_cli_perf_format.py
test_cli_proxy_embedding_server.py
test_cli_proxy_env.py feat(content-router): lossless-first dispatch, cross-turn dedup, and A7 lossy-after-fold (#1818) 2026-07-06 08:32:06 -07:00
test_cli_proxy_improvements.py feat(proxy): add provider-only HTTP proxy (#1807) 2026-07-05 15:56:59 -07:00
test_cli_tools.py
test_cli_update.py
test_code_compressor_thread_safety.py
test_codex_client_stamp.py
test_codex_openai_contract_parity.py
test_codex_rate_limits.py
test_codex_responses_passthrough_bytes.py Wire OpenAI Responses output shaping (#1438) 2026-07-05 13:59:21 -07:00
test_codex_responses_waste_signals.py
test_codex_ws_compression_scheduler.py perf(proxy): cap compression workers to CPU count (#1803) 2026-07-05 14:01:23 -07:00
test_compaction_markdown_kv.py
test_compress_api.py
test_compress_failure.py
test_compression_cache.py
test_compression_decision.py
test_compression_determinism.py
test_compression_fidelity_regression.py
test_compression_observability.py
test_compression_policy.py
test_compression_policy_toin_gate.py
test_compression_safety_rails.py
test_compression_store.py
test_compression_summary.py
test_compression_summary_eval.py
test_compression_summary_hard_eval.py
test_compression_summary_integration.py
test_compression_summary_tool_eval.py
test_compression_units.py
test_compressor_config_exposure.py
test_config.py
test_content_router_exclude_tools.py
test_content_router_tool_role_reversibility.py
test_copilot_auth.py fix(copilot): normalize subscription routing host (#1836) 2026-07-06 06:23:48 -07:00
test_copilot_linux_secret.py
test_copilot_macos_keychain.py
test_copilot_quota.py
test_copilot_subscription_smoke.py
test_corrupt_golden_bytes_recovery.py
test_cortex_code_compression.py
test_cost_tracker_counterfactual.py
test_critical_fixes.py
test_critical_gaps.py
test_cross_turn_cache_safety.py fix(proxy): freeze must forward cached (compressed) prefix byte-identical — stop token-mode cache busting (#1850) 2026-07-06 14:54:39 -07:00
test_cross_turn_dedup.py feat(content-router): lossless-first dispatch, cross-turn dedup, and A7 lossy-after-fold (#1818) 2026-07-06 08:32:06 -07:00
test_dashboard_agent_usage.py
test_dashboard_cache_net_playwright.py
test_dashboard_cache_ttl_playwright.py
test_dashboard_token_savings.py
test_debug_dump_gating.py
test_docker_compose_persistence.py fix(docker): persist headroom workspace in compose (#1839) 2026-07-06 08:35:06 -07:00
test_evals_cjk_tokenization.py
test_evals_datasets.py
test_evals_metrics.py
test_exceptions.py
test_force_kompress_all.py
test_forwarded_headers.py
test_fsutil.py
test_gemini_compression_offload.py
test_gemini_function_response_waste.py
test_google_multimodal.py
test_google_multimodal_e2e.py
test_graph.py
test_graph_tokensave.py
test_handler_outcome_tag_invariant.py
test_header_isolation.py
test_hf_revision_pinning.py
test_hnsw_only.py
test_hooks.py
test_image_compression.py
test_image_compression_decision.py
test_image_compression_offload.py perf(proxy): offload image compression off event loop (#1612) 2026-07-02 23:17:47 -05:00
test_image_compressor.py
test_image_log_redaction.py
test_image_ocr_api_compat.py
test_issue_728_empty_tools_injection.py
test_issue_746_tool_search.py
test_issue_1601_remote_control_gate.py
test_kompress_must_keep.py
test_kompress_preload_deferral.py
test_kompress_request_nonblocking.py
test_lean_ctx_installer.py
test_litellm_optional.py
test_local_backend_init_race.py
test_log_compressor.py
test_lossless_excluded_compaction.py feat(content-router): lossless-excluded compaction (grep/log/json) + enable in coding/general personas (#1762) 2026-07-03 12:09:05 -07:00
test_lossless_first_dispatch.py feat(content-router): lossless-first dispatch, cross-turn dedup, and A7 lossy-after-fold (#1818) 2026-07-06 08:32:06 -07:00
test_lossless_mode.py fix(content-router): token-measure lossless folds at the acceptance gate (#1772) 2026-07-03 15:04:07 -07:00
test_lossless_then_lossy.py feat(content-router): lossless-first dispatch, cross-turn dedup, and A7 lossy-after-fold (#1818) 2026-07-06 08:32:06 -07:00
test_mcp_registry_opencode.py
test_mcp_stub.py
test_memory_auto_tail.py
test_memory_bridge.py
test_memory_decision.py
test_memory_eval.py
test_memory_handler_concurrent_init.py
test_memory_handler_native_ops.py
test_memory_handler_project_isolation.py
test_memory_injection_budget.py
test_memory_integration.py
test_memory_invariants.py
test_memory_query.py
test_memory_ranker.py
test_memory_storage_router.py
test_memory_sync.py
test_memory_system.py
test_memory_tool_mode.py
test_memory_tool_session_sticky.py
test_memory_tracker.py
test_memory_tracker_integration.py
test_memory_usage_integration.py
test_memory_wrapper.py
test_mid_turn_steering.py
test_ml_model_registry_lifecycle.py
test_models.py
test_netcost_gate.py
test_network_diff_capture.py
test_no_ccr_lossy.py feat(content-router): lossless-first dispatch, cross-turn dedup, and A7 lossy-after-fold (#1818) 2026-07-06 08:32:06 -07:00
test_oauth_bearer_routing.py
test_observability_metrics.py
test_observability_tracing.py
test_onnx_runtime.py
test_openai_beta_session_sticky.py
test_openai_codex_routing.py
test_openai_codex_ws_lifecycle.py fix(opencode): use local MCP config (#1383) 2026-07-06 06:22:15 -07:00
test_openai_codex_ws_timings.py
test_openai_responses_compression_units.py feat(content-router): lossless-excluded compaction (grep/log/json) + enable in coding/general personas (#1762) 2026-07-03 12:09:05 -07:00
test_openai_responses_context_compaction.py
test_openai_responses_output_shaper.py Wire OpenAI Responses output shaping (#1438) 2026-07-05 13:59:21 -07:00
test_openai_responses_t3_replay_regression.py
test_openai_streaming_backend.py
test_output_savings.py Wire OpenAI Responses output shaping (#1438) 2026-07-05 13:59:21 -07:00
test_output_savings_cli.py
test_output_shaper.py fix(opencode): use local MCP config (#1383) 2026-07-06 06:22:15 -07:00
test_owned_asset_encoding.py
test_package_init_lazy.py
test_parser.py
test_paths.py
test_paths_backward_compat.py
test_perf_cli_filtering.py
test_pid_alive.py
test_pipeline.py
test_plugin_manifests.py
test_plugins_hermes_retrieve.py
test_pr208_changes.py
test_pricing.py
test_pricing_litellm.py
test_probe_recorder.py
test_prometheus_stage_timing_concurrency.py
test_provider_aider.py
test_provider_claude.py
test_provider_codex_install.py
test_provider_codex_runtime.py
test_provider_codex_threads.py
test_provider_copilot_wrap.py
test_provider_cortex_code.py
test_provider_cursor.py
test_provider_model_fallback.py feat(anthropic): add Claude 5 family pricing & align current rates (#1767) 2026-07-03 12:09:35 -07:00
test_provider_openclaw_wrap.py
test_provider_package_init.py
test_provider_proxy_routes.py
test_provider_registry.py
test_provider_registry_extended.py
test_providers_opencode_config.py fix(opencode): expose headroom/* models in injected provider config (#1716) 2026-07-03 15:20:14 -07:00
test_providers_opencode_install.py
test_proxy_anthropic_cache_stability.py
test_proxy_anthropic_compression_diagnostics.py
test_proxy_anthropic_model_sanitization.py fix(proxy): strip 1m model suffix before upstream forwarding (#1840) 2026-07-06 08:33:45 -07:00
test_proxy_batch_integration.py
test_proxy_byte_faithful_forwarding.py
test_proxy_cache_ttl_metrics.py
test_proxy_ccr.py
test_proxy_codex_route_aliases.py
test_proxy_compress_endpoint.py
test_proxy_compression_executor.py perf(proxy): cap compression workers to CPU count (#1803) 2026-07-05 14:01:23 -07:00
test_proxy_compression_headers.py
test_proxy_copilot_auth_hooks.py
test_proxy_cors.py
test_proxy_count_tokens_integration.py
test_proxy_dashboard_stats_cache.py fix(dashboard): deduplicate repeated savings metrics (#1804) 2026-07-05 16:00:25 -07:00
test_proxy_debug_endpoints.py
test_proxy_disable_kompress.py
test_proxy_eager_preload_bind.py
test_proxy_gemini_integration.py
test_proxy_gemini_native_integration.py
test_proxy_google_cloudcode_route_aliases.py
test_proxy_handler_helpers.py fix(proxy): freeze must forward cached (compressed) prefix byte-identical — stop token-mode cache busting (#1850) 2026-07-06 14:54:39 -07:00
test_proxy_handlers_batch.py
test_proxy_hardening.py
test_proxy_healthchecks.py
test_proxy_hooks_regression.py
test_proxy_loop_exception_health.py fix(proxy): surface codex websocket loop failures in livez (#1727) 2026-07-03 13:33:55 -07:00
test_proxy_loopback_gating.py
test_proxy_memory_integration.py
test_proxy_mode_benchmark.py
test_proxy_modes.py
test_proxy_openai_cache_key_integration.py
test_proxy_openai_cache_stability.py fix(proxy): freeze must forward cached (compressed) prefix byte-identical — stop token-mode cache busting (#1850) 2026-07-06 14:54:39 -07:00
test_proxy_openai_responses_bypass.py
test_proxy_openai_responses_integration.py
test_proxy_package_init.py
test_proxy_passthrough_integration.py
test_proxy_passthrough_transient_retry.py fix(proxy): retry passthrough on transient upstream connection close (#1513) 2026-07-06 18:35:39 -05:00
test_proxy_per_provider_kompress.py
test_proxy_pipeline_lifecycle.py fix(proxy): cancel retry backoff on shutdown (#1834) 2026-07-06 06:24:47 -07:00
test_proxy_project_savings.py
test_proxy_retry_429.py fix(proxy): cancel retry backoff on shutdown (#1834) 2026-07-06 06:24:47 -07:00
test_proxy_savings_history.py perf(savings): batch tracker persistence off the request hot path (#1817) 2026-07-05 15:58:58 -07:00
test_proxy_scalability.py feat(proxy): add provider-only HTTP proxy (#1807) 2026-07-05 15:56:59 -07:00
test_proxy_semantic_cache_key.py
test_proxy_semantic_cache_key_integration.py
test_proxy_stats_recent_requests.py
test_proxy_streaming_ratelimit_headers.py
test_proxy_streaming_request_logger.py
test_proxy_streaming_resilience.py
test_proxy_system_prompt_immutable.py
test_proxy_telemetry_env.py
test_proxy_warmup.py
test_quality_retention.py
test_quota_registry.py
test_read_maturation.py
test_read_maturation_handler_nobust.py
test_realignment_live_multi_turn.py
test_release_version.py
test_release_workflows.py fix(build): enable Intel macOS pip installs via ort-load-dynamic (#1538) 2026-07-06 18:33:34 -05:00
test_relevance.py
test_relevance_extra.py
test_relevance_split.py feat(content-router): lossless-first dispatch, cross-turn dedup, and A7 lossy-after-fold (#1818) 2026-07-06 08:32:06 -07:00
test_reporting.py
test_request_outcome.py
test_reread_attribution.py
test_responses_pyo3_compression.py
test_responses_ws_pyo3_compression.py
test_rtk_installer.py
test_rtk_session_savings.py
test_runtime_env.py
test_rust_core_smoke.py
test_savings_ledger.py
test_search_compressor.py
test_security_validations.py
test_session_probes.py
test_shared_context.py
test_signals_keyword_parity.py
test_smart_crusher_toin_attachment.py
test_sqlite_graph_store.py
test_sqlite_vector_index.py
test_sse_thinking_blocks.py
test_sse_utf8_split.py
test_ssl_context.py
test_stage_timer.py
test_startup_log_noise.py
test_stateless_toin.py
test_stateless_writers.py
test_storage_backends.py
test_strands_tokenizer.py
test_streaming_usage_parser.py
test_subscription_base.py
test_subscription_client.py
test_subscription_tracker.py
test_subscription_tracker_rtk_wired.py
test_subscription_window_render.py
test_tag_protection_integration.py
test_tag_protector_invariant.py
test_telemetry.py
test_telemetry_context.py
test_telemetry_warning.py
test_text_compressors.py
test_toin.py
test_toin_feedback.py
test_toin_fixes.py
test_toin_full_integration.py
test_toin_integration.py
test_toin_observation_only.py
test_toin_publish.py
test_token_headroom_mode.py
test_tokenizer.py
test_tokenizers.py
test_tool_result_interceptors.py
test_transforms_content_detection.py
test_transforms_content_router.py
test_transforms_log_compressor.py
test_transforms_package.py
test_transforms_search_compressor.py
test_transforms_tabular.py
test_update_check.py
test_update_helpers.py
test_utils.py
test_verbosity_controller.py
test_verbosity_learn.py
test_vertex_claude_compression.py
test_ws_http_fallback.py
test_ws_memory_relay.py
test_ws_session_registry.py