fix: keep the OpenCode keyless Authorization blank on the async aux client

_to_async_client rebuilds default_headers from scratch and dropped the blank
Authorization set by _create_openai_client, so every async aux call (the path
aux tasks actually take) for a free-tier OpenCode model still shipped the
keyless placeholder as a bearer and 401'd. Re-apply the same keyless policy on
the async twin.

Review finding: fourth client builder (_to_async_client) missed the keyless header policy.
This commit is contained in:
teknium1
2026-09-14 21:13:49 -07:00
committed by Teknium
parent e77060e081
commit d4e0df1e8d
2 changed files with 20 additions and 0 deletions
+6
View File
@@ -4369,6 +4369,12 @@ def _to_async_client(sync_client, model: str, is_vision: bool = False):
except Exception:
inferred = ""
headers = _endpoint_default_headers(sync_base_url, inferred, is_vision=is_vision, xai=True)
# Headers are rebuilt from scratch here, so re-apply the OpenCode keyless policy from
# _create_openai_client: the placeholder must never ship as a bearer (see #110831).
with contextlib.suppress(Exception):
from hermes_cli.models import OPENCODE_ZEN_FREE_KEYLESS_PLACEHOLDER, opencode_zen_free_headers
if sync_client.api_key == OPENCODE_ZEN_FREE_KEYLESS_PLACEHOLDER:
headers = {**(headers or {}), **opencode_zen_free_headers()}
if headers:
async_kwargs["default_headers"] = headers
_apply_required_codex_headers(async_kwargs, access_token=sync_client.api_key, base_url=sync_base_url)
@@ -111,3 +111,17 @@ def test_keyless_placeholder_blanks_authorization_under_paid_opencode_profile(mo
shared=False,
)
assert _zen_call_headers(mock_openai).get("Authorization") == ""
def test_async_aux_wrapper_keeps_keyless_authorization_blank():
"""``_to_async_client`` rebuilds default_headers; the keyless placeholder must stay
blanked on the async twin too, or every async aux call ships the placeholder bearer."""
import openai
import agent.auxiliary_client as aux
sync_client = aux._create_openai_client(api_key="opencode-zen-free-keyless", base_url=ZEN_V1)
async_client, _ = aux._to_async_client(sync_client, "x-preview-f-free")
request = async_client._build_request(
openai._models.FinalRequestOptions.construct(method="post", url="/chat/completions", json_data={})
)
assert request.headers.get("authorization") == ""