Repository navigation
fix(providers): route opencode-zen GPT-5.6 family to the Responses API - #14230
diegosouzapw merged 2 commits into
Conversation
Upstream serves the GPT-5.6 trio only on /responses; /chat/completions answers 503 "Endpoint is unavailable" (live-verified 2026-09-19 against opencode.ai/zen/v1 with the same key on both endpoints, gpt-5.6-luna; sol/terra declared from the same upstream endpoint docs). The zen registry tagged muse-spark-1.2 with targetFormat:"openai-responses" but never the GPT-5.6 entries, so OpencodeExecutor.buildUrl() posted them to the chat endpoint. diegosouzapw#12196 made the same declaration for gpt-5.6-luna on opencode-go. Test: tests/unit/opencode-zen-gpt56-responses-format.test.ts, red without the registry change, green with it, muse-spark control included.
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
No unresolved review issues were identified.
Review effort: Lite
Findings: None
What changed in this PR
Routes OpenCode Zen GPT-5.6 models through the Responses API to prevent upstream 503 errors.
Changes:
- Tags Sol, Terra, and Luna with
openai-responses. - Adds regression tests for registry and format resolution.
- Adds a changelog entry.
| File | Description |
|---|---|
tests/unit/opencode-zen-gpt56-responses-format.test.ts |
Verifies target formats and resolution. |
open-sse/config/providers/registry/opencode/zen/index.ts |
Routes GPT-5.6 models through Responses API. |
changelog.d/fixes/14230-opencode-zen-gpt56-responses.md |
Documents the fix. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Thanks for the fix, Mike — confirmed the /responses vs /chat/completions split against the live upstream behavior you documented, and your new test is green on a clean checkout of the release tip. The control test pinning the working muse-spark entry is a nice touch (proves the assertion harness itself isn't vacuous). Merging this one; there's a near-identical PR (#14265) open for the same issue that I'm closing as subsumed by this one, with a link back here. |
|
Thanks @mhenke — merging via the release merge-train. Validated in local merge-train (mt-train10c) on the devbox @ train tip 4d841aa1c740bbaa03868dc0a403c62099a99a42 with the 72 sibling PRs of this batch: typecheck:core, file-size, complexity, cognitive-complexity, changelog-integrity green; changed-area node:test 831/831 (0 failing) and vitest 480/482 — the two reds are |
…strip #14252 added stripInternalBodyFields() at the shared pre-executor boundary so _omniroute* routing markers cannot leak upstream. The same helper also removes the four _native*Passthrough markers — but those are read INSIDE the executor (codex.ts:1259, xai.ts:130), which deletes them itself. Stripping them a layer early turned every Responses-native request into a translated one, which then lost client fields to the #2608 allowlist; 'metadata' is how it surfaced. Executor-consumed markers are now a named list the boundary keeps and the serialization strip (applyFingerprint) still removes, so the leak fix stands. Bisected to 1fb7c9d on a clean checkout. Also aligns opencode-executor's auth expectation with #14230, which routed Zen GPT-5.6 through /v1/responses where #12633's x-api-key rule applies. Refs #14496.
Both were red on the pure release tip and both pin behavior a merged PR changed on purpose. - opencode-executor "omits accept header when stream is false": #14230 routed the whole opencode-zen GPT-5.6 family to the Responses API (targetFormat:"openai-responses"), and #12633 established that Zen's /v1/responses endpoint authenticates with `x-api-key` rather than Bearer — unlike /chat/completions on the same host. The header therefore moved legitimately; the absent Accept header this case is actually about is unchanged. - domain-branch-hardening "quotaCache covers empty quotas…" (2 assertions): #14276 made a window whose fraction the upstream never reported — `total: 0`, or an Infinity percentage — UNKNOWN instead of "0% remaining", so it can no longer reach the exhaustion threshold. That fix exists because Vertex spend telemetry was locking whole accounts out. The percentages still read 0/100 (the documented placeholder) and both branches the case exists to cover are still exercised. No assertion was dropped. Validated: opencode-executor 59/59, domain-branch-hardening 6/6, quota-cache-unknown-limits 6/6.
…6-luna (#14059) Maintainer rework (release drain 2026-09-28): reconciled with the release/v3.8.51 tip three times — kept the tip's opencode-zen Responses routing (#14230) and layered the PR's reasoning metadata on it; ported the provider-namespace fix onto the shared Codex alias-set helpers from #14720/#14964 (policy now checks modelIdForRegistry; rules editor strips any provider prefix, luna coerces a saved ultra to max) and fixed the tip's leftover STANDARD_EFFORTS reference in the simulator select. Red->green: luna-reasoning-effort-400 fails 2/5 on the tip, 5/5 here; new github/opencode-zen efforts case fails on the tip, passes here. Focused suites 114/114 (13 files) + api-key-routing-editor vitest 6/6; typecheck:core, open-sse typecheck and ESLint clean; eslint-suppressions.json byte-identical to the tip. Thank you @kang-heewon!
Summary
/v1/responses;/v1/chat/completionsanswers503 "Endpoint is unavailable". The registry tagged muse-spark-1.2 for the Responses API on this provider but never the GPT-5.6 entries, soOpencodeExecutor.buildUrl()posted them to the chat endpoint.Related Issues
Validation
Change type: provider. Focused loop: the new unit test, run red without the registry change and green with it, against
release/v3.8.51tip. ESLint on the two touched files is clean.node --testvia tsx on the new file; 2 pass / 0 fail)npm run lint(scoped to the touched files; full suite runs in CI)release/v3.8.51tip)Tests Added Or Updated
tests/unit/opencode-zen-gpt56-responses-format.test.ts(new): asserts the three registry entries carrytargetFormat: "openai-responses", thatresolveOpencodeTargetFormat()resolves them toopenai-responses(the valuebuildUrl()keys on), and a muse-spark control that pins the already-working entry.Coverage Notes
open-sse/and adds a unit test undertests/unit/that covers the registry and the target-format resolution path for the three models. Coverage inopen-sse/config/providers/registry/opencode/zen/index.tsmoves up.Reviewer Notes
POST https://opencode.ai/zen/v1/responseswithgpt-5.6-lunareturns 200 whilePOST https://opencode.ai/zen/v1/chat/completionsreturns the 503, same key on both calls. The sol and terra entries follow the same upstream endpoint docs; I verified luna against the live API.