Skip to content

feat(responses): opt-in upstream Responses WebSocket transport (#2816, carry of #2817) - #3216

Merged
lidge-jun merged 8 commits into
devfrom
codex/carry-2817-upstream-ws
Sep 1, 2026
Merged

feat(responses): opt-in upstream Responses WebSocket transport (#2816, carry of #2817)#3216
lidge-jun merged 8 commits into
devfrom
codex/carry-2817-upstream-ws

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • Maintainer carry of feat: support opt-in upstream Responses WebSockets #2817 by @gulup (git author jiangpeng) (6 commits merged onto current dev, authorship preserved), resolving Feature request: opt-in upstream Responses WebSocket transport for OpenAI-compatible providers #2816: an opt-in provider flag upstreamWebsocket that lets an HTTPS /responses upstream be dialed over WebSocket (wss) using the same relay Codex already uses for the canonical ChatGPT backend.
  • Opt-in with today's behavior as the default: the flag is absent/false unless set, and only the canonical ChatGPT endpoint uses WS without it. With it, only https: URLs whose path ends in /responses are eligible; http://, chat completions, images, and search stay on HTTP SSE. Any pre-open failure (constructor, send, upgrade timeout, oversized frame, 401/403/426/429/5xx close) falls back to the existing SSE path. Official WS response.done is mapped to SSE response.completed/failed/incomplete, with unknown or queued status failing closed.
  • Surfaces: GET/POST/PATCH /api/providers expose and persist the boolean, POST overwrite preserves an omitted value; docs on the provider pages. No dashboard toggle (dropped by the author on review).
  • Why a carry: the contributor branch was 139 commits behind dev and conflicted with the modelDisplayNames/retainModels POST carry-over block; resolved here keeping both omit-preserves. The macOS red on the PR head was the known server-auth websocket-passthrough timing case, with all Linux shards green.
  • No changes to src/router.ts, src/server/lifecycle.ts, src/server/responses/core.ts, or src/server/index.ts; no new startServer awaits; no request-body or token logging.

Closes #2816

Verification

  • bun x tsc --noEmit clean; bun run privacy:scan passed.
  • bun test tests/ws-upstream.test.ts tests/management-provider-validation.test.ts tests/core-lab-boundary.test.ts tests/cli-capabilities.test.ts -> 169 pass / 0 fail (opt-in matrix: flag off, HTTPS /responses, HTTP rejected, non-Responses, response.done completed/failed/unknown, WSS dial URL, POST/PATCH/overwrite preserve).
  • Full suite runs in CI on this PR.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features
    • Added an optional upstreamWebsocket provider setting for Responses requests.
    • Enabled providers can stream over secure WebSockets when supported, while preserving SSE and HTTP fallbacks.
    • Provider management APIs now support viewing, updating, validating, and persisting this setting.
  • Documentation
    • Added configuration guidance across supported languages, including endpoint behavior and defaults.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 1, 2026 20:31
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T20:37:05.712910Z bc884ea PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 1, 2026
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: 993395f1-ccac-47b4-84e0-37fc16b51b76

📥 Commits

Reviewing files that changed from the base of the PR and between f84dbf9 and bc884ea.

📒 Files selected for processing (15)
  • docs-site/src/content/docs/fr/reference/configuration/providers.md
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/tr/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-tw/reference/configuration/providers.md
  • src/config.ts
  • src/server/management/provider-routes.ts
  • src/server/responses/fetch-helpers.ts
  • src/server/responses/ws-upstream.ts
  • src/types/provider.ts
  • tests/management-provider-validation.test.ts
  • tests/ws-upstream.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

Adds an optional upstreamWebsocket provider setting. Eligible HTTPS openai-responses streams can use a provider-specific WebSocket endpoint and return SSE events. Management routes, schemas, documentation, routing, relay normalization, and tests support the setting.

Changes

Provider WebSocket Transport

Layer / File(s) Summary
Transport option contract and management
src/types/provider.ts, src/config.ts, src/server/management/provider-routes.ts, tests/management-provider-validation.test.ts, docs-site/src/content/docs/reference/configuration/providers.md, docs-site/src/content/docs/*/reference/configuration/providers.md
Adds optional upstreamWebsocket configuration. Provider management supports validation, GET exposure, PATCH updates, explicit false, and preservation when omitted during overwrites. Documentation covers provider-specific paths, HTTPS requirements, SSE conversion, and fallback behavior.
Configured upstream selection
src/server/responses/fetch-helpers.ts, src/server/responses/ws-upstream.ts, tests/ws-upstream.test.ts
Allows opted-in providers to use WebSockets only for HTTPS paths ending in /responses. HTTP hosts and non-Responses paths retain HTTP SSE behavior. Configured providers use their own WS endpoint, while the canonical ChatGPT backend keeps its existing selection behavior.
WebSocket relay normalization
src/server/responses/ws-upstream.ts, tests/ws-upstream.test.ts
Rewrites response.done into status-specific SSE terminal events. Missing or unrecognized terminal statuses become response.failed with a failed status. The relay enforces frame size limits and reuses encoded bytes when normalization does not change the event.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🔵 Low · up to bc884

The PR adds an opt-in WebSocket transport for eligible HTTPS Responses providers while preserving existing HTTP behavior by default. It is mergeable with owner awareness of a bounded concurrent-update race that can briefly restore an older transport setting during overlapping provider changes.

Suggested reviewers: ingwannu, luvs01

Sequence Diagram(s)

sequenceDiagram
  participant providerFetch
  participant shouldUseCodexWsUpstream
  participant codexWsUpstreamFetch
  participant OpenAICompatibleProvider
  participant SSEPipeline
  providerFetch->>shouldUseCodexWsUpstream: Check provider flag, URL, method, body, and stream
  shouldUseCodexWsUpstream->>providerFetch: Select WebSocket transport for eligible HTTPS /responses URL
  providerFetch->>codexWsUpstreamFetch: Send streaming Responses request
  codexWsUpstreamFetch->>OpenAICompatibleProvider: Dial provider-specific wss URL
  OpenAICompatibleProvider-->>codexWsUpstreamFetch: Return Responses WebSocket frames
  codexWsUpstreamFetch->>SSEPipeline: Normalize terminal events and re-encode frames as SSE
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 7 files. (8 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation satisfies issue #2816. It adds and persists upstreamWebsocket, limits the WebSocket path to eligible HTTPS /responses URLs, preserves canonical ChatGPT behavior, relays WebSocke…
Out of Scope Changes check ✅ Passed The changes remain within the linked issue scope. Updates to src/config.ts, src/types/provider.ts, provider management routes, WebSocket routing and relay logic, documentation, and related tests d…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: an opt-in upstream Responses WebSocket transport. It matches the provider flag, WebSocket routing, and relay changes in the pull request.
Full details: Linked Issues check

Explanation

The implementation satisfies issue #2816. It adds and persists upstreamWebsocket, limits the WebSocket path to eligible HTTPS /responses URLs, preserves canonical ChatGPT behavior, relays WebSocket frames as SSE, normalizes terminal events, and retains HTTP fallback behavior. The changes cover configuration, provider management routes, transport selection, documentation, and targeted tests.

Full details: Out of Scope Changes check

Explanation

The changes remain within the linked issue scope. Updates to src/config.ts, src/types/provider.ts, provider management routes, WebSocket routing and relay logic, documentation, and related tests directly support the provider-level WebSocket option. No unrelated product behavior or dashboard toggle was added.

Full details: Docstring Coverage

Explanation

Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 7 files. (8 skipped: 8 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/carry-2817-upstream-ws

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc884eaa40

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return false;
}
return parsed.protocol === "https:"
&& parsed.pathname.endsWith("/responses");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle valid trailing-slash Responses paths

When an opted-in provider uses a valid responsesPath such as /v1/responses/, createResponsesPassthroughAdapter preserves that path, but this predicate returns false because the pathname does not end exactly in /responses. Such providers silently remain on HTTP/SSE even though the existing Responses URL handling explicitly accepts a trailing slash; normalize trailing slashes or accept /responses/ here.

AGENTS.md reference: src/AGENTS.md:L10-L10

Useful? React with 👍 / 👎.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 72 / 80

이 PR은 #2816을 닫는 메인테이너 캐리입니다. 원본은 @gulup(jiangpeng)의 #2817이고, 현재 dev 위에 작성자 커밋 6개를 살려 얹은 뒤 modelDisplayNames/retainModels POST omit-preserve 충돌만 여기서 풀었습니다. 하는 일은 단순합니다. OpenAI-compatible 프로바이더에 opt-in 플래그 upstreamWebsocket을 주면, 이미 ChatGPT 백엔드가 쓰는 것과 같은 Responses WebSocket 릴레이로 HTTPS /responses 요청을 wss로 올립니다.

기본값은 꺼짐입니다. 플래그가 없거나 false면 예전과 같고, 켜도 https: 이고 pathname이 /responses로 끝나는 URL만 대상입니다. http://, chat completions, images, search는 HTTP SSE에 남습니다. 업그레이드 실패·타임아웃·과대 프레임·401/403/426/429/5xx 종료는 기존 SSE로 폴백합니다. WS 전용 단말 response.done은 status에 따라 SSE의 response.completed/failed/incomplete로 바꾸고, 알 수 없거나 비어 있는 status는 성공으로 치지 않고 fail-closed 합니다.

표면은 GET/POST/PATCH /api/providers에 boolean을 노출·저장하고, POST overwrite에서 생략 시 기존 값을 보존합니다(명시적 false는 유지). 대시보드 토글은 리뷰에서 의도적으로 뺐습니다. src/router.ts / lifecycle.ts / responses/core.ts / server/index.ts는 안 건드리고, 요청 본문·토큰 로깅도 없습니다.

현재 dev(HEAD f84dbf91e, #3215 keychain capability 직후) 방향과도 잘 맞습니다. 최근 랜드는 quota/catalog/keychain/oauth 쪽이 많았고, 이 조각은 기존 ws-upstream.ts 레인을 프로바이더 opt-in으로만 확장합니다. src/config.ts(+4)와 src/types/provider.ts(+12)에 필드 하나만 더하는 수준이라 types.ts/config.ts 분할 캠페인(#2805 등) 때문에 close-don't-rebase 할 대상은 아닙니다. 오히려 지금 머지하고 원본 #2817을 landed-via로 닫는 편이 큐가 깨끗합니다.

검증은 로컬에서 ws-upstream / management-provider-validation 등 169 pass를 주장하고, 이 리뷰 시점 CI는 대부분 pass이며 macos·test 2/4만 아직 pending입니다. PR 본문이 말한 macOS server-auth websocket-passthrough 타이밍 이슈가 다시 뜨는지만 보면 됩니다.

src/server/responses/ws-upstream.ts isResponsesWebsocketEligibleUrl - pathname이 /responses로 끝나는지만 봐서, baseUrl이 /v1/responses/처럼 trailing slash를 남기면 자격이 떨어질 수 있다(폴백은 SSE라 안전하지만 플래그를 켠 운영자 기대와 어긋날 수 있음).
src/server/responses/ws-upstream.ts wsUpstreamUrlFor - http(s?):ws$1: 치환은 https→wss로 맞지만, 자격 게이트 밖의 URL이 실수로 들어오면 ws://도 만들 수 있다(현재는 https 게이트가 막아 줌).
src/server/management/provider-routes.ts - GET이 upstreamWebsocket: p.upstreamWebsocket === true로 항상 boolean을 내보내서, 저장값이 없을 때도 false로 보인다. PATCH/omit-preserve와는 맞지만, “미설정”과 “명시 false”를 API 응답만으로 구분할 수는 없다(의도일 가능성 큼).

메인테이너의 판단이 필요한 지점

  • pending macOS / test 2/4가 그린이 된 뒤 바로 머지할지, 알려진 macOS flake면 Linux 그린만으로 랜딩할지
  • 머지 후 원본 #2817에 Landed via #3216 at <commit> + landed-via-maintainer로 닫을지(표준 leftover 처리)
  • trailing-slash /responses/를 자격에 넣을 follow-up을 지금 넣을지 나중에 둘지

너의 추천
CI 남은 칸이 초록(또는 macOS가 알려진 flake로 확인)이면 dev에 머지한다. 머지 직후 #2817 leftover를 landed-via로 닫고, #2816은 Closes로 같이 정리한다. config/types 가산이 작아서 분할 캠페인 때문에 닫을 이유는 없다.

이 댓글은 grok-bot이 작성했습니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant