diff --git a/CHANGELOG.md b/CHANGELOG.md index 93fb8cdd..c87c3056 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Keep the default-off `HERMES_WEBUI_RUNTIME_ADAPTER=legacy-journal` chat-start path response-compatible with the legacy-direct path by not adding adapter-internal `run_id`, `status`, or `active_controls` fields to `/api/chat/start` responses. Fixes #2435. + ## [v0.51.82] — 2026-05-17 — Release BF (stage-375 — 2-PR batch — table renderer pipe protection + Catppuccin appearance skin) ### Added diff --git a/api/routes.py b/api/routes.py index 677a6677..779a0176 100644 --- a/api/routes.py +++ b/api/routes.py @@ -7800,9 +7800,6 @@ def _handle_chat_start(handler, body, diag=None): response = dict(result.payload) response.setdefault("stream_id", result.stream_id) response.setdefault("session_id", result.session_id) - response.setdefault("run_id", result.run_id) - response.setdefault("status", result.status) - response.setdefault("active_controls", result.active_controls) else: response = _start_chat_stream_for_session( s, diff --git a/tests/test_runtime_adapter_seam.py b/tests/test_runtime_adapter_seam.py index 296abd64..c261d54d 100644 --- a/tests/test_runtime_adapter_seam.py +++ b/tests/test_runtime_adapter_seam.py @@ -119,3 +119,22 @@ def test_chat_start_route_selects_adapter_only_when_flag_enabled(): assert "LegacyJournalRuntimeAdapter" in start_body assert "_start_chat_stream_for_session(" in start_body assert "HERMES_WEBUI_RUNTIME_ADAPTER" not in start_body, "route should use runtime_adapter_enabled(), not inline env checks" + + +def test_chat_start_adapter_path_preserves_legacy_response_shape(): + """The RuntimeAdapter seam must be invisible to /api/chat/start callers. + + The adapter can use run_id/status/controls internally, but the flagged + route must not add fields that the legacy-direct response does not expose. + """ + routes = importlib.import_module("api.routes") + src = (routes.Path(__file__).parent.parent / "api" / "routes.py").read_text(encoding="utf-8") + branch_start = src.index("if runtime_adapter_enabled():") + branch_end = src.index("else:", branch_start) + adapter_branch = src[branch_start:branch_end] + + assert 'response.setdefault("stream_id", result.stream_id)' in adapter_branch + assert 'response.setdefault("session_id", result.session_id)' in adapter_branch + assert 'response.setdefault("run_id", result.run_id)' not in adapter_branch + assert 'response.setdefault("status", result.status)' not in adapter_branch + assert 'response.setdefault("active_controls", result.active_controls)' not in adapter_branch