fix(streaming): preserve profile env for checkpoints
This commit is contained in:
1 parent
4ea762ae0d
commit
524ed6cce3
3 files changed
+54
-1
No files matched your search
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Streaming checkpoint saves now run under the session's profile environment, so periodic background checkpoints no longer risk falling back to the process-global profile when a WebUI tab is using a non-default profile.
|
||||||
|
|
||||||
## [v0.51.134] — 2026-05-25 — Release DF (stage-batch16 — single-PR Windows path defaults)
|
## [v0.51.134] — 2026-05-25 — Release DF (stage-batch16 — single-PR Windows path defaults)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
+13
-1
@@ -2557,6 +2557,18 @@ def _drop_checkpointed_current_user_from_context(messages, msg_text):
|
|||||||
return history
|
return history
|
||||||
|
|
||||||
|
|
||||||
|
def _save_streaming_checkpoint(session):
|
||||||
|
"""Persist a streaming checkpoint under the session's profile context."""
|
||||||
|
from api import profiles as profiles_api
|
||||||
|
|
||||||
|
with profiles_api.profile_env_for_background_worker(
|
||||||
|
session,
|
||||||
|
"streaming checkpoint",
|
||||||
|
logger_override=logger,
|
||||||
|
):
|
||||||
|
session.save(skip_index=True)
|
||||||
|
|
||||||
|
|
||||||
def _normalize_fresh_chat_text(text):
|
def _normalize_fresh_chat_text(text):
|
||||||
text = _strip_workspace_prefix(str(text or ''), include_legacy=True)
|
text = _strip_workspace_prefix(str(text or ''), include_legacy=True)
|
||||||
text = re.sub(r"\s+", " ", text).strip().lower()
|
text = re.sub(r"\s+", " ", text).strip().lower()
|
||||||
@@ -4552,7 +4564,7 @@ def _run_agent_streaming(
|
|||||||
cur = _checkpoint_activity[0]
|
cur = _checkpoint_activity[0]
|
||||||
if cur > last_saved_activity:
|
if cur > last_saved_activity:
|
||||||
with _agent_lock:
|
with _agent_lock:
|
||||||
s.save(skip_index=True)
|
_save_streaming_checkpoint(s)
|
||||||
last_saved_activity = cur
|
last_saved_activity = cur
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug("Periodic checkpoint save failed: %s", e)
|
logger.debug("Periodic checkpoint save failed: %s", e)
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
"""Regression coverage for #2848 checkpoint saves in background threads."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def test_checkpoint_save_uses_session_profile_env(monkeypatch, tmp_path):
|
||||||
|
"""Checkpoint saves run on their own thread, outside request TLS.
|
||||||
|
|
||||||
|
They must route profile-scoped helpers through the session's profile instead
|
||||||
|
of falling back to the process-global/default profile.
|
||||||
|
"""
|
||||||
|
from api.models import Session
|
||||||
|
from api.streaming import _save_streaming_checkpoint
|
||||||
|
import api.config as config
|
||||||
|
import api.profiles as profiles
|
||||||
|
|
||||||
|
profile_home = tmp_path / "profiles" / "maiko"
|
||||||
|
profile_home.mkdir(parents=True)
|
||||||
|
captured = {}
|
||||||
|
|
||||||
|
monkeypatch.setattr(profiles, "get_hermes_home_for_profile", lambda profile: profile_home)
|
||||||
|
monkeypatch.setattr(profiles, "get_profile_runtime_env", lambda home: {"HERMES_CONFIG_PATH": str(Path(home) / "config.yaml")})
|
||||||
|
|
||||||
|
def fake_save(self, *args, **kwargs):
|
||||||
|
captured["kwargs"] = kwargs
|
||||||
|
captured["thread_env"] = dict(getattr(config._thread_ctx, "env", {}) or {})
|
||||||
|
|
||||||
|
monkeypatch.setattr(Session, "save", fake_save)
|
||||||
|
|
||||||
|
session = Session(session_id="issue2848", profile="maiko")
|
||||||
|
|
||||||
|
_save_streaming_checkpoint(session)
|
||||||
|
|
||||||
|
assert captured["kwargs"] == {"skip_index": True}
|
||||||
|
assert captured["thread_env"]["HERMES_HOME"] == str(profile_home)
|
||||||
|
assert captured["thread_env"]["HERMES_CONFIG_PATH"] == str(profile_home / "config.yaml")
|
||||||
Reference in new issue
Block a user