fix(opencode): send ephemeral x-opencode-session header on one-shot requests
OpenCode Go strictly requires an x-opencode-session header on all requests to route requests efficiently and avoid HTTP 400 MissingSessionID. In turn chats and parented auxiliary calls, the header is derived from the conversation context or session ID. For stateless one-shot requests (commit messages, summaries, unparented auxiliary tasks), opencode_session_headers now falls back to generating an ephemeral session ID so one-shot requests to OpenCode succeed. Closes #105841
This commit is contained in:
@@ -18,6 +18,7 @@ matching per-model wire-format decision for the auxiliary client.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from typing import Any, Optional
|
||||
|
||||
OPENCODE_SESSION_HEADER = "x-opencode-session"
|
||||
@@ -100,7 +101,13 @@ def opencode_session_headers(
|
||||
)
|
||||
except Exception:
|
||||
key = str(session_id or "")
|
||||
return {OPENCODE_SESSION_HEADER: key} if key else {}
|
||||
if not key:
|
||||
# Stateless one-shot requests (commit messages, summaries, standalone prompts outside
|
||||
# a session) lack an ambient conversation or session id. OpenCode Go strictly requires
|
||||
# x-opencode-session on every request (HTTP 400 MissingSessionID if absent, #105841)
|
||||
# so generate an ephemeral session id fallback.
|
||||
key = f"oneshot-{uuid.uuid4().hex[:16]}"
|
||||
return {OPENCODE_SESSION_HEADER: key}
|
||||
|
||||
|
||||
def merge_opencode_session_headers(
|
||||
|
||||
@@ -147,3 +147,17 @@ def test_tui_gateway_oneshot_runtime_snapshot_carries_the_session(monkeypatch, o
|
||||
aux.call_llm(task="title_generation", main_runtime=_main_runtime_from_agent(agent), messages=_MSGS)
|
||||
|
||||
assert captured["extra_headers"]["x-opencode-session"] == "sess-desktop-1"
|
||||
|
||||
|
||||
def test_stateless_oneshot_still_sends_an_opencode_session_header(out_of_turn):
|
||||
"""A one-shot with no live session (Desktop commit-message generation from the review panel with
|
||||
no active chat, standalone aux calls) has no conversation identity at all, yet the relay rejects
|
||||
header-less requests with 400 MissingSessionID (#105841). It must carry an ephemeral key instead
|
||||
of nothing; non-OpenCode targets stay untouched."""
|
||||
from agent.opencode_affinity import opencode_session_headers
|
||||
|
||||
kwargs = aux._build_call_kwargs("opencode-go", "glm-5", _MSGS, base_url="https://opencode.ai/zen/go/v1")
|
||||
assert kwargs["extra_headers"]["x-opencode-session"]
|
||||
|
||||
assert opencode_session_headers("opencode-go", None, session_id=None).get("x-opencode-session")
|
||||
assert opencode_session_headers("openrouter", "https://openrouter.ai/api/v1", session_id=None) == {}
|
||||
|
||||
Reference in New Issue
Block a user