Repository navigation
fix(sse): resolve OpencodeExecutor target format through the provider alias - #11047
Conversation
51d57c8 to
5fc00bb
Compare
… alias
PROVIDER_MODELS is keyed by a provider's public alias (e.g. "oc"), not
its raw registry id ("opencode") -- OpencodeExecutor.execute() called
getModelTargetFormat() with the raw id, so it silently missed every
registry entry and fell back to "openai" for buildUrl()/buildHeaders(),
while chatCore's own (correctly aliased) request-body translation still
switched to the Responses API shape for targetFormat:"openai-responses"
models. Net effect: a Responses-shaped body got sent to the
/chat/completions URL, and upstream returned a degenerate empty response.
Surfaced live by cheaper-inference#10874, which added the first targetFormat:"openai-responses"
entries to the opencode provider's registry (oc/muse-spark-1.2 and
oc/muse-spark-1.2-contributor-free) -- no prior model in this registry
exercised this code path, so the alias mismatch was never triggered
before. Extracted the alias resolution into resolveOpencodeTargetFormat(),
mirroring chatCore/targetFormat.ts's own resolveChatCoreTargetFormat().
5fc00bb to
a6fdcc5
Compare
|
Thanks for the careful diagnosis and the cleanly-typed fix with real regression tests — this is exactly the right area, and the write-up is very clear. One thing to verify before this can land: |
ae2de45
into
cheaper-inference:release/v3.8.50
|
Verified against Since the PR is already merged, this is dead weight but harmless — leaving it in place. The regression test it added is genuinely good and could be resubmitted as a doc-only/hardening PR if a real repro ever surfaces. No revert opened unless you'd prefer to drop the no-op from production. |
… alias (cheaper-inference#11047) ⭐5 — OpencodeExecutor buscava targetFormat com o id bruto do provider em vez do alias público ("oc"), caindo em default openai → corpo Responses no URL chat/completions (400). resolveOpencodeTargetFormat resolve via PROVIDER_ID_TO_ALIAS. TDD 4/4 + 32/32 irmãos, lint/tsc limpos. Fecha cheaper-inference#11046. Base-red cheaper-inference#9985 inherited.
Summary
#10874 added
targetFormat: "openai-responses"to the Muse Spark entries in theopencodeprovider registry. That broke every request to those models: HTTP 400, empty message,finish_reason: null.Turns out
PROVIDER_MODELSis keyed by a provider's public alias ("oc"for this one), not its raw registry id ("opencode").OpencodeExecutor.execute()looks up the target format with the raw id, misses the registry entry, and falls back to"openai"— sobuildUrl()keeps pointing at/chat/completions. MeanwhilechatCore's own resolution (which does alias correctly) already switched the request body to the Responses API shape. Result: a Responses-shaped body lands on the Chat Completions URL, and upstream has nothing sane to answer with.This never showed up before because no model in this registry had ever used
targetFormat— the alias bug was just sitting there, never exercised.Fix: pulled the alias-resolving lookup into its own function (
resolveOpencodeTargetFormat), same patternchatCore/targetFormat.tsalready uses, and pointedexecute()at it instead of the raw call.Related Issues
Validation
open-sse/executors/opencode.ts)node --import tsx/esm --test tests/unit/opencode-target-format-alias-11045.test.ts— 4/4npm run lintclean — the 2 pre-existingno-explicit-anyin this file are untouchedtsc --noEmit— no new errorsrelease/v3.8.50tipTests Added Or Updated
tests/unit/opencode-target-format-alias-11045.test.ts:resolveOpencodeTargetFormatresolves the muse-spark entries via the alias"openai"for a model with no registrytargetFormat"openai"for a provider with no alias mappingOpencodeExecutor.buildUrlactually returns/responsesonce_requestFormatis resolved through the alias (live-bug repro)Coverage Notes
Only touches
open-sse/executors/opencode.ts, covered by the new tests plus the full existing executor suite for this file.Reviewer Notes
Same pattern other executors already use (
github.ts,default.tshardcode their alias as a literal since it's a fixed 1:1 mapping for those providers). This one resolves it dynamically viaPROVIDER_ID_TO_ALIASinstead of hardcoding"oc", so it keeps working if the alias ever changes.