fix(honcho): honour contextTokens cap on summary/peer context calls
Salvage of #70951 (Willkons / Alice-Willk-bot). Two of three session.context() sites never forwarded the configured cap, so Honcho always returned honcho_chat_summary_long. Adds the missing get_session_context tokens= regression the sweeper asked for on that PR.
This commit is contained in:
@@ -104,7 +104,8 @@ class SessionContextMixin:
|
||||
if session.honcho_session_id not in self._sessions_cache:
|
||||
return
|
||||
ctx = self._authed_call(
|
||||
"session summary fetch", lambda: self._sdk_session(session.honcho_session_id).context(summary=True),
|
||||
"session summary fetch",
|
||||
lambda: self._sdk_session(session.honcho_session_id).context(summary=True, tokens=self._context_tokens),
|
||||
)
|
||||
if ctx.summary and getattr(ctx.summary, "content", None):
|
||||
result["summary"] = ctx.summary.content
|
||||
@@ -161,7 +162,8 @@ class SessionContextMixin:
|
||||
ctx = self._authed_call(
|
||||
"session context fetch",
|
||||
lambda: self._sdk_session(session.honcho_session_id).context(
|
||||
summary=True, peer_target=target_peer_id or observer_peer_id, peer_perspective=observer_peer_id,
|
||||
summary=True, tokens=self._context_tokens,
|
||||
peer_target=target_peer_id or observer_peer_id, peer_perspective=observer_peer_id,
|
||||
),
|
||||
)
|
||||
result: dict[str, Any] = {}
|
||||
|
||||
@@ -1234,3 +1234,99 @@ class TestGetSessionContextFallback:
|
||||
assert peer_id == "user-peer"
|
||||
assert target == "user-peer"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# contextTokens must reach session.context() (salvage of #70951)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestContextTokensForwarded:
|
||||
"""Honcho picks short vs long summary from the tokens= budget.
|
||||
|
||||
Regression: get_prefetch_context and get_session_context called
|
||||
context(summary=True) without tokens=, so a configured contextTokens
|
||||
cap was ignored and every turn got honcho_chat_summary_long.
|
||||
"""
|
||||
|
||||
def _manager(self, context_tokens=4000):
|
||||
mgr = HonchoSessionManager(context_tokens=context_tokens)
|
||||
session = HonchoSession(
|
||||
key="cli:test",
|
||||
user_peer_id="robert",
|
||||
assistant_peer_id="hermes",
|
||||
honcho_session_id="sess-1",
|
||||
)
|
||||
mgr._cache[session.key] = session
|
||||
honcho_session = MagicMock()
|
||||
honcho_session.context.return_value = SimpleNamespace(
|
||||
summary=SimpleNamespace(content="short summary"),
|
||||
peer_representation="rep",
|
||||
peer_card=["fact"],
|
||||
messages=[],
|
||||
)
|
||||
mgr._sessions_cache[session.honcho_session_id] = honcho_session
|
||||
mgr._fetch_peer_context = MagicMock(
|
||||
return_value={"representation": "", "card": []}
|
||||
)
|
||||
return mgr, session, honcho_session
|
||||
|
||||
def test_get_prefetch_context_passes_context_tokens_to_summary_call(self):
|
||||
mgr, session, honcho_session = self._manager()
|
||||
|
||||
result = mgr.get_prefetch_context(session.key)
|
||||
|
||||
assert result["summary"] == "short summary"
|
||||
honcho_session.context.assert_called_once_with(summary=True, tokens=4000)
|
||||
|
||||
def test_get_session_context_passes_context_tokens_to_cached_session_call(self):
|
||||
"""Sweeper gap on #70951: the cached session-level context() path
|
||||
must forward tokens= alongside its peer arguments."""
|
||||
mgr, session, honcho_session = self._manager()
|
||||
|
||||
result = mgr.get_session_context(session.key, peer="user")
|
||||
|
||||
assert result["summary"] == "short summary"
|
||||
honcho_session.context.assert_called_once_with(
|
||||
summary=True,
|
||||
tokens=4000,
|
||||
peer_target=session.user_peer_id,
|
||||
peer_perspective=session.assistant_peer_id,
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# contextTokens must reach session.context() (salvage of #70951 via #92964)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestContextTokensForwarded:
|
||||
"""Honcho picks the short or long summary from the tokens= budget. get_prefetch_context and
|
||||
get_session_context called context(summary=True) without it, so a configured contextTokens
|
||||
cap was ignored and every turn got the long summary."""
|
||||
|
||||
def _manager(self, context_tokens=4000):
|
||||
mgr = HonchoSessionManager(context_tokens=context_tokens)
|
||||
session = HonchoSession(key="cli:test", user_peer_id="robert", assistant_peer_id="hermes",
|
||||
honcho_session_id="sess-1")
|
||||
mgr._cache[session.key] = session
|
||||
honcho_session = MagicMock()
|
||||
honcho_session.context.return_value = SimpleNamespace(
|
||||
summary=SimpleNamespace(content="short summary"), peer_representation="rep", peer_card=["fact"],
|
||||
messages=[])
|
||||
mgr._sessions_cache[session.honcho_session_id] = honcho_session
|
||||
mgr._fetch_peer_context = MagicMock(return_value={"representation": "", "card": []})
|
||||
return mgr, session, honcho_session
|
||||
|
||||
def test_get_prefetch_context_passes_context_tokens_to_summary_call(self):
|
||||
mgr, session, honcho_session = self._manager()
|
||||
result = mgr.get_prefetch_context(session.key)
|
||||
assert result["summary"] == "short summary"
|
||||
honcho_session.context.assert_called_once_with(summary=True, tokens=4000)
|
||||
|
||||
def test_get_session_context_passes_context_tokens_to_cached_session_call(self):
|
||||
mgr, session, honcho_session = self._manager()
|
||||
result = mgr.get_session_context(session.key, peer="user")
|
||||
assert result["summary"] == "short summary"
|
||||
honcho_session.context.assert_called_once_with(
|
||||
summary=True, tokens=4000, peer_target=session.user_peer_id, peer_perspective=session.assistant_peer_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user