Skip to content

fix(openai-chat): forward caller-selected service tier - #1512

Merged
lidge-jun merged 2 commits into
lidge-jun:devfrom
Yuxin-Qiao:codex/fix-1504-chat-service-tier
Aug 12, 2026
Merged

fix(openai-chat): forward caller-selected service tier#1512
lidge-jun merged 2 commits into
lidge-jun:devfrom
Yuxin-Qiao:codex/fix-1504-chat-service-tier

Conversation

@Yuxin-Qiao

@Yuxin-Qiao Yuxin-Qiao commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Refs #1504
Refs #1436

Verification

  • bun test --isolate --max-concurrency 1 tests/openai-chat-hardening.test.ts tests/service-tier-capability.test.ts — 50 passed, 0 failed, 84 assertions.
  • bun run typecheck — passed on the rebased head.
  • bun run privacy:scan — passed.
  • git diff --check — passed.
  • A repository-wide bun run test result is not claimed; the suite contains current baseline/environment failures unrelated to this narrow serializer change.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed; this is an internal request serialization fix.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.
  • Local CI is green.
  • Branch is on the latest dev commit.
  • Correct Codex and CodeRabbit findings are fixed.
  • Ready-for-review confirmation is present.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • New Features

    • Added support for forwarding the requested service tier for compatible chat providers.
    • Provider configurations can now enable or disable service-tier handling independently.
  • Bug Fixes

    • Service-tier settings are now correctly inherited when not explicitly configured.
    • The service tier is omitted when unsupported, disabled, or not provided.

Maintainer note (checklist reset by the follow-up push). Re-ticked against fresh evidence at 197c82ae9, not carried over: bun x tsc --noEmit exit 0 and tests/openai-chat-hardening.test.ts 39 pass / 0 fail on a Linux runner (Bun 1.3.14); branch rebased onto dev@d03755ee9; the one review finding (unconditional service_tier forwarding across 66 openai-chat providers) is fixed by the chatServiceTier opt-in in the follow-up commit.

@coderabbitai

coderabbitai Bot commented Aug 12, 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: Pro Plus

Run ID: 043eb69f-cede-400f-9559-4df6ca508807

📥 Commits

Reviewing files that changed from the base of the PR and between d03755e and 197c82a.

📒 Files selected for processing (6)
  • src/adapters/openai-chat.ts
  • src/providers/derive.ts
  • src/providers/registry.ts
  • src/router.ts
  • src/types.ts
  • tests/openai-chat-hardening.test.ts

📝 Walkthrough

Walkthrough

The change adds provider-level chatServiceTier configuration, propagates it from the registry, and conditionally forwards service_tier in Chat Completions requests. Tests cover enabled, disabled, explicit false, and missing caller values.

Changes

Chat service tier forwarding

Layer / File(s) Summary
Capability configuration
src/types.ts:1441-1449, src/providers/registry.ts:240-245, src/providers/derive.ts:242, src/providers/derive.ts:423, src/router.ts:353
OcxProviderConfig and ProviderRegistryEntry now support chatServiceTier. Provider derivation and routing inherit the registry value only when the provider configuration is unset.
Chat request forwarding and validation
src/adapters/openai-chat.ts:747-758, tests/openai-chat-hardening.test.ts:305-334
buildRequest forwards service_tier when chatServiceTier is enabled. Tests verify forwarding, omission when disabled or false, and omission when no tier is supplied.

Estimated code review effort: 2 (Simple) | ~15 minutes

Suggested reviewers: lidge-j, wibias

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: forwarding caller-selected service tiers in the OpenAI Chat adapter.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 12, 2026
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

4/4 boxes ticked.

This pull request has been marked Ready for Review.
The review-ready label marks this PR as ready; review automation runs independently. If no CodeRabbit review appears, comment @coderabbitai review to request one.
Maintainers notified: @lidge-jun @Ingwannu @Wibias

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

PR #1521 includes this Chat Completions serialization fix (commit b7cf9df4f) together with the broader #1436 capability/catalog/runtime work. I am leaving this narrow PR open for maintainer choice; if #1521 is accepted, this PR can be closed as superseded.

@Yuxin-Qiao
Yuxin-Qiao force-pushed the codex/fix-1504-chat-service-tier branch from 070eca7 to a353594 Compare August 12, 2026 07:37
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

Rebased the fork branch onto current dev@d5824814853eea68ceb4417403b22000a935cef8; new head is a3535941d15b. Post-rebase local proof: Chat/service-tier focused suite 50/50, 84 assertions; typecheck, privacy scan, and diff check passed. GitHub hygiene, target, label, and resolve checks are green. Keeping this Draft pending maintainer choice/review; #1521 carries the same Chat serialization fix.

@Yuxin-Qiao
Yuxin-Qiao force-pushed the codex/fix-1504-chat-service-tier branch from a353594 to ab72f54 Compare August 12, 2026 08:55
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

Rebased and force-with-lease pushed onto current dev@cbbfdd8773e68a5dc2391ddeb32f33a225373c1a; new head is ab72f54. Fresh local proof: Chat/service-tier focused suite 50/50, 84 assertions; typecheck, privacy scan, and diff check passed. The PR description is updated; keeping Draft pending maintainer choice/review, with #1521 carrying the same serializer fix.

@Ingwannu

Copy link
Copy Markdown
Owner

The narrow serializer change is valid and appropriately scoped: parsed.options.serviceTier is currently captured upstream and this adapter silently drops it. The focused test proves the outbound Chat Completions body now preserves the caller-selected value.

However, #1521 contains the same serializer change together with the provider/model capability resolver and catalog/runtime gating. Keeping both open creates two competing landing paths for the same line. I recommend treating #1512 as the minimal fallback only: leave it draft while #1521 is reviewed, and close it as superseded if #1521 is accepted. If the broader capability PR is rejected or split, this two-file patch is a reasonable standalone candidate after exact-head CI and readiness completion.

Yuxin-Qiao and others added 2 commits August 12, 2026 23:34
Follow-up on top of @Yuxin-Qiao's forwarding commit.

The forwarding itself is right: the Responses parser records a
caller-supplied service_tier and this adapter dropped it, so the value
never reached the wire. But 66 registry providers share the openai-chat
adapter, and applyServiceTierGate only strips for openai-responses, so
forwarding unconditionally would put an OpenAI-specific field on every
one of them. Strict gateways reject unknown body fields, which turns a
caller-supplied tier into an upstream 400 on routes that work today.

prompt_cache_key directly below already solves this exact problem with an
opt-in flag, and its comment names the same hazard. service_tier now
follows that precedent: chatServiceTier on the registry entry, threaded
through derive and router the way promptCacheKey is.

supportsServiceTier is deliberately not reused — it governs the Responses
wire through applyServiceTierGate and means something different.

No registry entry opts in yet; that wants per-provider evidence that the
gateway documents the parameter, which is a separate change.
@lidge-jun
lidge-jun force-pushed the codex/fix-1504-chat-service-tier branch from ab72f54 to 197c82a Compare August 12, 2026 14:37
@lidge-jun

Copy link
Copy Markdown
Owner

Reviewed against current dev (d03755ee9) and rebased onto it. The forwarding itself is correct — the Responses parser records a caller-supplied service_tier at src/responses/parser.ts:679 and this adapter dropped it, so the value never reached the wire.

I pushed one commit on top of yours rather than changing it, because the forwarding needs a gate.

Why. 66 registry providers share the openai-chat adapter — groq, ollama, lm-studio, openrouter, together, mistral, vllm and so on. applyServiceTierGate (src/server/responses/core.ts:1442) only strips service_tier when the adapter is openai-responses, so it never fires here. Forwarding unconditionally puts an OpenAI-specific extension on every one of those routes, and strict gateways reject unknown body fields — a caller-supplied tier would turn requests that work today into upstream 400s.

The precedent is directly below your line: prompt_cache_key solves the same problem with an opt-in flag, and its comment in src/types.ts names the same hazard ("strict backends (Groq, Cerebras, etc.) reject unknown fields"). service_tier now follows it — chatServiceTier on the registry entry, threaded through derive.ts and router.ts exactly the way promptCacheKey is.

I deliberately did not reuse supportsServiceTier: that governs the Responses wire through applyServiceTierGate and means something different, so overloading it would make both flags harder to reason about.

Your test is kept and now asserts the opted-in case; two more assert that the field is dropped without the opt-in and that an opted-in provider with no caller tier still sends nothing. No registry entry opts in yet — that wants per-provider evidence that the gateway documents the parameter, which belongs in its own change.

Verification at the merged head (197c82ae9) on a Linux runner (Bun 1.3.14): bun x tsc --noEmit exit 0; tests/openai-chat-hardening.test.ts 39 pass / 0 fail. Red-before for your original test: tests-only diff on dev = 1 fail, full diff = 0 fail.

@lidge-jun
lidge-jun marked this pull request as ready for review August 12, 2026 14:38
@github-actions
github-actions Bot marked this pull request as draft August 12, 2026 14:38

@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: 197c82ae99

ℹ️ 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".

// unknown body fields. Forwarding unconditionally would turn a caller-supplied
// `service_tier` into an upstream 400 on those routes. `supportsServiceTier` is the
// Responses-wire flag (applyServiceTierGate) and deliberately does not gate this path.
if (provider.chatServiceTier && parsed.options.serviceTier !== undefined) {

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 Document the chat service-tier opt-in

When an operator configures an openai-chat custom gateway according to docs-site/src/content/docs/reference/configuration/providers.md:70, setting the documented supportsServiceTier: true still causes this condition to drop every caller-supplied tier because the new, distinct chatServiceTier option is undocumented and absent from the GUI payload. Add chatServiceTier to the provider documentation and translated references (and expose or preserve it in provider configuration flows), or make this adapter honor the existing documented capability for the chat wire.

AGENTS.md reference: AGENTS.md:L234-L235

Useful? React with 👍 / 👎.

@lidge-jun
lidge-jun marked this pull request as ready for review August 12, 2026 14:47
@github-actions
github-actions Bot marked this pull request as draft August 12, 2026 14:47

@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: 197c82ae99

ℹ️ 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".

Comment on lines +756 to +757
if (provider.chatServiceTier && parsed.options.serviceTier !== undefined) {
body.service_tier = parsed.options.serviceTier;

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 Preserve tiers from the Chat Completions ingress

When an OpenAI-compatible client sends service_tier to POST /v1/chat/completions, chatCompletionsToResponsesBody forwards neighboring fields such as parallel_tool_calls and prompt_cache_key but omits service_tier (src/chat/inbound.ts:274-286). Consequently the Responses parser leaves parsed.options.serviceTier undefined and this new serializer branch never runs, even for a provider with chatServiceTier: true. Copy the validated string into the translated body and add an endpoint-level regression test.

Useful? React with 👍 / 👎.

@lidge-jun
lidge-jun marked this pull request as ready for review August 12, 2026 15:19
@github-actions
github-actions Bot marked this pull request as draft August 12, 2026 15:19
@github-actions
github-actions Bot marked this pull request as ready for review August 12, 2026 15:20
@lidge-jun
lidge-jun merged commit bf36080 into lidge-jun:dev Aug 12, 2026
39 checks passed
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@github-actions[bot] Acknowledged. The PR readiness gate is complete at head SHA 197c82ae992fa0a9e6d53ac4459a4b2c2a0d01a8.


🧠 Learnings used
Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

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

Labels

bug Something isn't working review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants