Skip to content

fix(api-server): expose session id on buffered /new failure responses - #690

Open
wcy12378 wants to merge 1 commit into
OpenBMB:mainfrom
wcy12378:codex/fix-api-new-failure-header
Open

wcy12378 wants to merge 1 commit into
OpenBMB:mainfrom
wcy12378:codex/fix-api-new-failure-header

Conversation

@wcy12378

Copy link
Copy Markdown

Summary

An inline /new <message> request creates the session binding (api_server:chat=<chatId>:s_<uuid>) in ApiServerSessionMapper.resolve() before the gateway is contacted. When the buffered turn then fails, the response carried no X-Hermes-Session-Id header:

  • bufferedTurn preflight gateway-unavailable → 503 without the header
  • submitTurn throwing mid-turn → 500 without the header
  • streamTurn preflight gateway-unavailable → 503 without the header

The caller never learns the generated chat id, the retained reset binding becomes unreachable, and headerless retries resolve to fresh :general sessions — silently forking the conversation history. Retries that supply the returned token do reach the reset session, so exposing the token is the "return a usable session token" recovery path from #502.

Closes #502.

Change

Set X-Hermes-Session-Id once in handleChatCompletions right after the turn is admitted, so every response for the turn carries the session id — success and failure paths alike. This also removes the two redundant per-path setHeader calls (buffered success, streaming pre-flight) without changing their observable behavior.

Scope note: the bare /new ack path (no trailing message) returns before this point and is intentionally untouched — it is covered by #679.

Tests

New tests/adapters/channel/api-server-session-header.spec.ts (in-memory handleRequest fixtures, deterministic mapper UUID):

  1. buffered inline /new failure exposes the session id and retries reach the reset session — 500 response carries the header; a retry that echoes it hits the same :s_ session instead of :general.
  2. buffered gateway-unavailable inline /new exposes the session id — 503 carries the header, binding retained.
  3. streaming preflight gateway-unavailable inline /new exposes the session id — 503 carries the header, binding retained.
  4. buffered success still exposes the session id — control.

Validation (Windows, Node v24.15.0, node --import tsx --test):

  • Baseline (main 1732d07, tests only): 4 tests, 1 pass / 3 fail — the three failure-path tests fail against the old code, reproducing the issue.
  • With this fix: 4/4 pass.
  • pnpm exec tsc -p tsconfig.json --noEmit: clean.

An inline '/new <message>' request creates the session binding before
the gateway is contacted. When the buffered turn then fails
(gateway unavailable or submit error), the response carried no
X-Hermes-Session-Id, so the caller never learned the chat id, the
retained reset binding became unreachable, and headerless retries
forked into fresh :general sessions instead of the reset one.

Set the session header once for the whole turn (success and failure
paths alike) so a failed /new returns a usable session token and a
retry with that header reaches the same reset session.

Closes OpenBMB#502.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failed headerless inline /new leaves an unreachable binding and forks retries

1 participant