headroom/wiki
nangsontay e5b3a634df
fix(proxy): dedupe Codex WS request logging for accurate mixed-provider dashboards (#2189)
## Description

Running Claude Code (Anthropic) and Codex (OpenAI) against the **same**
Headroom proxy instance on one port produced incorrect, unstable
dashboard data. The proxy core is provider-isolated and
multi-provider-safe by design; the defect was in the observability
layer. The Codex `/v1/responses` **WebSocket** handler was the only path
in the proxy that wrote to the request logger by hand instead of through
the unified `emit_request_outcome` funnel, and it did so twice per
session close: the per-turn funnel record plus an unconditional
cumulative session-summary `RequestLog`. This PR removes the duplicate
summary log so Codex WS emits exactly one request log per turn, matching
the HTTP provider paths.

## 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)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- Dropped the duplicate cumulative session-summary `RequestLog` in the
Codex WS handler while preserving the per-turn `emit_request_outcome`
path.
- Preserved gated `request_messages` and `turn_id` on residual outcomes
so dashboard telemetry keeps the useful attribution without
double-counting tokens.
- Ensured explicit `--anyllm-provider` wins over a leaked
`HEADROOM_ANYLLM_PROVIDER` environment variable.
- Registered retry delay settings that had drifted out of the settings
registry.
- Hardened tests against developer-shell `HEADROOM_*` /
`ANTHROPIC_CUSTOM_HEADERS` leakage and stabilized several focused
proxy/wrap test fixtures.

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

```text
$ .venv/bin/pytest tests/ -q -p no:cacheprovider
8529 passed, 537 skipped, 5831 warnings in 276.25s (0:04:36)

$ .venv/bin/ruff check <touched files>
All checks passed!
```

## Real Behavior Proof

- Environment: macOS (Darwin 25.4.0), Python 3.13.14, pytest 9.0.3, ruff
via project venv, branch `fix/multi-provider-runtime`.
- Exact command / steps: Ran the full test suite without pytest cache
provider and Ruff on all touched files; used `git stash` to confirm the
stale fake-config failures pre-existed this change.
- Observed result: Full suite passed with no failures; Ruff passed;
Codex WS now routes end-of-session logging through
`emit_request_outcome`, emitting one request log per turn with the same
accounting model as Anthropic HTTP turns.
- Not tested: Live simultaneous Claude + Codex dashboard run. `mypy
headroom` was not run to completion; a scoped run reported one
pre-existing `settings_store.py:470` coercion error outside this diff.

## 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
- [ ] I have updated the CHANGELOG.md if applicable

## Screenshots (if applicable)

N/A - server-side observability fix; no UI markup changed.

## Additional Notes

- The proxy's multi-provider routing, header/auth isolation, and
per-model cache keying are already correct and unchanged here; only the
WS observability write path was double-counting.
- Architectural assessment:
`plans/reports/research-260714-0004-multi-provider-upstream-compression-report.md`;
root-cause + resolution trail:
`plans/reports/debug-assessment-260714-0011-dashboard-instability-mixed-claude-codex-report.md`.
- No live simultaneous Claude + Codex dashboard run was performed;
validation is from test coverage and code review of the WS logging path.

---------

Co-authored-by: JerrettDavis <mxjerrett@gmail.com>
2026-07-15 18:18:34 +00:00
..
overrides new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
plans fix: add anthropic pre-upstream timeouts 2026-04-21 09:48:32 +07:00
screenshots new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
stylesheets new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
agno.md docs: sync README + benchmarks with code (drop retired IntelligentContext/RollingWindow) (#1545) 2026-06-28 22:36:41 -07:00
api.md docs: sync README + benchmarks with code (drop retired IntelligentContext/RollingWindow) (#1545) 2026-06-28 22:36:41 -07:00
ARCHITECTURE.md docs: sync README + benchmarks with code (drop retired IntelligentContext/RollingWindow) (#1545) 2026-06-28 22:36:41 -07:00
benchmarks.md fix(telemetry): switch anonymous telemetry to opt-in (off by default) (#1223) 2026-06-20 21:26:04 -07:00
ccr.md docs: sync README + benchmarks with code (drop retired IntelligentContext/RollingWindow) (#1545) 2026-06-28 22:36:41 -07:00
cli.md fix(proxy): dedupe Codex WS request logging for accurate mixed-provider dashboards (#2189) 2026-07-15 18:18:34 +00:00
compression.md fix(cli): proxy/perf/wrap UX cleanup + perf --hours correctness 2026-05-07 16:43:35 -07:00
configuration.md fix(proxy): dedupe Codex WS request logging for accurate mixed-provider dashboards (#2189) 2026-07-15 18:18:34 +00:00
docker-install.md fix: align docker image versions with releases 2026-04-17 12:17:49 -05:00
errors.md new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
filesystem-contract.md docs: document HEADROOM_CONFIG_DIR / HEADROOM_WORKSPACE_DIR filesystem contract 2026-04-16 19:24:17 -05:00
getting-started.md docs: use headroom-ai package name in install commands (#1014) (#1257) 2026-06-22 19:25:00 -05:00
image-compression.md new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
index.md docs: sync README + benchmarks with code (drop retired IntelligentContext/RollingWindow) (#1545) 2026-06-28 22:36:41 -07:00
integration-guide.md fix(copilot): restore generic endpoint for non-subscription OAuth (#610) (#612) 2026-06-04 16:27:54 -07:00
langchain.md new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
LATENCY_BENCHMARKS.md new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
learn.md fix(cli): harden all CLI surfaces + fix docs accuracy (#1491) 2026-06-27 14:48:43 -07:00
LIMITATIONS.md docs: sync README + benchmarks with code (drop retired IntelligentContext/RollingWindow) (#1545) 2026-06-28 22:36:41 -07:00
macos-deployment.md docs: correct macOS troubleshooting Python floor to 3.10+ (#981) 2026-06-15 11:09:59 -05:00
mcp.md docs: document HEADROOM_CONFIG_DIR / HEADROOM_WORKSPACE_DIR filesystem contract 2026-04-16 19:24:17 -05:00
memory.md feat(memory): add opt-in Apple-GPU (MPS) embedding runtime (#766) 2026-06-11 12:59:20 -05:00
metrics.md fix(cli): harden all CLI surfaces + fix docs accuracy (#1491) 2026-06-27 14:48:43 -07:00
network-diff-capture.md feat: add differential network capture harness (#761) 2026-06-08 22:18:31 -07:00
persistent-installs.md docs: document HEADROOM_CONFIG_DIR / HEADROOM_WORKSPACE_DIR filesystem contract 2026-04-16 19:24:17 -05:00
proxy.md fix(proxy): dedupe Codex WS request logging for accurate mixed-provider dashboards (#2189) 2026-07-15 18:18:34 +00:00
quickstart.md fix(cli): harden all CLI surfaces + fix docs accuracy (#1491) 2026-06-27 14:48:43 -07:00
sdk.md new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
shared-context.md new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
strands.md docs: sync README + benchmarks with code (drop retired IntelligentContext/RollingWindow) (#1545) 2026-06-28 22:36:41 -07:00
text-compression.md new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
transforms.md docs: sync README + benchmarks with code (drop retired IntelligentContext/RollingWindow) (#1545) 2026-06-28 22:36:41 -07:00
troubleshooting.md fix: skip Magika backend on x86 CPUs without AVX2 (#1162) 2026-06-30 13:34:17 -05:00
typescript-sdk.md chore: remove committed node_modules + stray/internal markdown (repo hygiene) (#1528) 2026-06-27 23:32:54 -07:00
vertex.md chore: remove committed node_modules + stray/internal markdown (repo hygiene) (#1528) 2026-06-27 23:32:54 -07:00