Add active upstream WebSocket ping and request compatibility filtering - #4
Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 6 |
| Duplication | -1 |
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
- Format the ping timer initialization consistently
There was a problem hiding this comment.
Pull Request Overview
The PR successfully implements the core requirements for WebSocket heartbeats and Codex compatibility filtering, and the changes are overall up to standards. However, while the implementation includes logic to handle Ping failures, there is no automated verification for these error paths or the processing of Pong frames.
A significant robustness gap was identified: the current implementation lacks a heartbeat timeout. Without checking for activity or Pong responses, the pump may remain active on a 'half-open' connection where the upstream is unresponsive but the TCP socket has not yet closed. It is recommended to implement a timeout and switch the timer behavior to prevent cumulative drift.
About this PR
- The unit tests focus primarily on the happy path. Error paths related to WebSocket transmission failures and the logic for processing received Pong frames remain untested.
Test suggestions
- Verify 'prompt_cache_options' is filtered out of initial response.create payloads.
- Verify 'prompt_cache_options' is filtered out of follow-up tool output payloads.
- Verify the WebSocket pump sends a Ping frame after the configured interval.
- Verify the WebSocket pump terminates the connection if sending a Ping fails.
- Verify that receiving a Pong frame is correctly processed (logged).
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Verify the WebSocket pump terminates the connection if sending a Ping fails.
2. Verify that receiving a Pong frame is correctly processed (logged).
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
There was a problem hiding this comment.
Pull request overview
This PR improves upstream connection stability and request compatibility in Threadline’s bridge between VS Code BYOK /v1/responses traffic and the Codex backend WebSocket protocol by (1) actively keeping retained upstream WebSockets alive with periodic client-initiated Ping frames and (2) normalizing outgoing response.create payloads by stripping a VS Code field that Codex does not accept.
Changes:
- Add a 30s periodic upstream WebSocket Ping in the pump loop, plus debug logging for sent Ping and received Pong frames.
- Extend upstream request normalization to remove
prompt_cache_optionsfrom outgoingresponse.createpayloads (initial and follow-up tool-output requests). - Add unit tests covering active Ping behavior and
prompt_cache_optionsfiltering.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/ws_pump.rs | Adds periodic upstream Ping keepalive behavior (with logging) and a unit test verifying a Ping is sent after the configured interval. |
| src/responses/upstream/original.rs | Filters out prompt_cache_options via existing unsupported-field normalization and adds assertions covering both initial and follow-up payload construction. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
prompt_cache_optionsfield before forwarding requests to the Codex backendMotivation
Some proxies, NAT devices, and firewalls close idle WebSocket connections. Periodic Ping frames help keep long-lived upstream connections alive without changing the existing reconnect behavior.
VS Code may also include
prompt_cache_optionsin Responses requests, but the Codex backend does not accept that field. Threadline now removes it through the existing unsupported-field normalization shared by initial requests and follow-up tool-output requests.Notes
prompt_cache_optionsis removed only from the upstream payload; all other request fields remain unchangedValidation