mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
## Description Closes #1956 Keep ChatGPT OAuth `/v1/responses` requests streaming when CCR retrieve tools are present. The buffered `stream:false` conversion is still used for regular OpenAI Responses CCR requests, but ChatGPT Codex routing now bypasses that conversion so the upstream receives the streaming request shape it expects. ## Type of Change - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update - [ ] Refactoring - [ ] Performance improvement - [ ] Test update - [ ] Other ## Changes Made - Extracted the OpenAI Responses CCR stream-buffering decision into a small helper. - Excluded ChatGPT OAuth/Codex-routed requests from the buffered `stream:false` path. - Added tests proving regular OpenAI CCR still buffers while ChatGPT OAuth CCR remains streaming. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check`) - [x] Formatting verified (`ruff format --check`) - [ ] Manual testing performed ### Test Output ```text $ python3 -m pytest tests/test_proxy_openai_responses_stream_ccr.py -q collected 3 items tests/test_proxy_openai_responses_stream_ccr.py ... [100%] ============================== 3 passed in 0.59s =============================== $ .venv/bin/ruff check headroom/proxy/handlers/openai.py tests/test_proxy_openai_responses_stream_ccr.py All checks passed! $ .venv/bin/ruff format --check headroom/proxy/handlers/openai.py tests/test_proxy_openai_responses_stream_ccr.py 2 files already formatted ``` ## Test verification (RED -> GREEN) RED, with the ChatGPT OAuth guard temporarily removed from the buffering decision: ```text tests/test_proxy_openai_responses_stream_ccr.py .F. [100%] FAILED tests/test_proxy_openai_responses_stream_ccr.py::test_responses_ccr_keeps_chatgpt_oauth_requests_streaming E AssertionError: assert not True E + where True = _should_buffer(tools=[{'type': 'function', 'name': 'headroom_retrieve'}], is_chatgpt_auth=True) ``` GREEN, with this patch applied: ```text tests/test_proxy_openai_responses_stream_ccr.py ... [100%] ============================== 3 passed in 0.59s =============================== ``` ## Real Behavior Proof - Environment: Linux, Python 3.12.3, pytest 9.1.1, ruff 0.14.14. - Exact command / steps: Removed the `not is_chatgpt_auth` guard from the CCR buffering decision, ran the targeted tests, restored the guard, and reran the tests plus targeted ruff checks. - Observed result: The ChatGPT OAuth streaming regression test fails without the guard and passes with the guard, while regular OpenAI CCR buffering remains covered. - Not tested: Full `uv run pytest`, full-project `uv run ruff check .`, full-project `uv run ruff format --check .`, and `uv run mypy headroom` were not run locally; `uv run --extra dev ruff` attempted to build the Rust extension in this worktree, so targeted checks used the existing `.venv/bin/ruff`. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have added tests that prove my fix is effective - [x] New and existing targeted tests pass locally with my changes - [x] Any dependent changes have been merged and published in downstream modules ## Screenshots (if applicable) N/A ## Additional Notes The existing buffered CCR path is preserved for non-ChatGPT OpenAI Responses requests.
36 lines
1.1 KiB
Python
36 lines
1.1 KiB
Python
from __future__ import annotations
|
|
|
|
from headroom.ccr import CCR_TOOL_NAME
|
|
from headroom.proxy.handlers.openai import _should_buffer_openai_responses_stream_ccr
|
|
|
|
_TOOL_TYPE_FUNCTION = "function"
|
|
_UNRELATED_TOOL_NAME = "unrelated_tool"
|
|
|
|
|
|
def _ccr_tool() -> dict[str, str]:
|
|
return {"type": _TOOL_TYPE_FUNCTION, "name": CCR_TOOL_NAME}
|
|
|
|
|
|
def _unrelated_tool() -> dict[str, str]:
|
|
return {"type": _TOOL_TYPE_FUNCTION, "name": _UNRELATED_TOOL_NAME}
|
|
|
|
|
|
def _should_buffer(*, tools: list[dict[str, str]], is_chatgpt_auth: bool) -> bool:
|
|
return _should_buffer_openai_responses_stream_ccr(
|
|
stream=True,
|
|
ccr_response_handler_enabled=True,
|
|
tools=tools,
|
|
is_chatgpt_auth=is_chatgpt_auth,
|
|
)
|
|
|
|
|
|
def test_responses_ccr_buffers_streaming_openai_requests() -> None:
|
|
assert _should_buffer(tools=[_ccr_tool()], is_chatgpt_auth=False)
|
|
|
|
|
|
def test_responses_ccr_keeps_chatgpt_oauth_requests_streaming() -> None:
|
|
assert not _should_buffer(tools=[_ccr_tool()], is_chatgpt_auth=True)
|
|
|
|
|
|
def test_responses_ccr_ignores_requests_without_retrieve_tool() -> None:
|
|
assert not _should_buffer(tools=[_unrelated_tool()], is_chatgpt_auth=False)
|