Merge pull request #160 from Prathap-P/fix/session_history

fix(channels): push session history into agent context on channel mes…
This commit is contained in:
Robby Manihani
2026-04-01 16:57:38 -07:00
committed by GitHub
2 changed files with 131 additions and 5 deletions
+16 -5
View File
@@ -63,6 +63,7 @@ class JarvisSystem:
tools: Optional[List[str]] = None,
system_prompt: Optional[str] = None,
operator_id: Optional[str] = None,
prior_messages: Optional[List[Message]] = None,
) -> Dict[str, Any]:
"""Execute a query through the system and return a result dict."""
if temperature is None:
@@ -106,6 +107,7 @@ class JarvisSystem:
max_tokens,
system_prompt=system_prompt,
operator_id=operator_id,
prior_messages=prior_messages,
)
# Direct engine mode
@@ -133,6 +135,7 @@ class JarvisSystem:
*,
system_prompt=None,
operator_id=None,
prior_messages=None,
) -> Dict[str, Any]:
"""Run through an agent."""
from openjarvis.agents._stubs import AgentContext
@@ -153,6 +156,11 @@ class JarvisSystem:
# Build context
ctx = AgentContext()
# Seed prior conversation turns (channel session history)
if prior_messages:
for msg in prior_messages:
ctx.conversation.add(msg)
# Inject memory context messages into the agent conversation
if messages and len(messages) > 1:
# Context messages were prepended by inject_context
@@ -297,7 +305,6 @@ class JarvisSystem:
A connected :class:`~openjarvis.channels._stubs.BaseChannel`
instance whose ``on_message`` method accepts a callable.
"""
from openjarvis.agents._stubs import AgentContext
from openjarvis.core.types import Message, Role
from openjarvis.sessions.session import SessionStore
@@ -320,14 +327,13 @@ class JarvisSystem:
channel_user_id=cm.sender,
)
# Rebuild prior conversation turns into AgentContext
ctx = AgentContext()
prior_msgs: List[Message] = []
for sm in session.messages:
try:
role = Role(sm.role)
except ValueError:
role = Role.USER
ctx.conversation.add(Message(role=role, content=sm.content))
prior_msgs.append(Message(role=role, content=sm.content))
reply = ""
try:
@@ -336,10 +342,15 @@ class JarvisSystem:
cm.content,
context=False,
agent=_system.agent_name,
prior_messages=prior_msgs,
)
reply = result.get("content", "")
else:
result = _system.ask(cm.content, context=False)
result = _system.ask(
cm.content,
context=False,
prior_messages=prior_msgs,
)
reply = result.get("content", "")
except Exception:
logger.exception("Channel message handler error")
+115
View File
@@ -0,0 +1,115 @@
"""Tests for wire_channel session history"""
from __future__ import annotations
from types import SimpleNamespace
from unittest.mock import MagicMock
import pytest
from openjarvis.core.config import JarvisConfig
from openjarvis.core.events import EventBus
from openjarvis.core.types import Role
from openjarvis.system import JarvisSystem
@pytest.fixture()
def minimal_system():
engine = MagicMock()
engine.generate.return_value = {"content": "ok", "usage": {}}
return JarvisSystem(
config=JarvisConfig(),
bus=EventBus(),
engine=engine,
engine_key="mock",
model="mock-model",
agent_name="none",
)
class TestWireChannelHistory:
def test_prior_messages_passed_to_ask(self, tmp_path, minimal_system):
"""Session history is forwarded as prior_messages to ask()."""
from openjarvis.sessions.session import SessionStore
db = tmp_path / "sessions.db"
store = SessionStore(db_path=db)
minimal_system.session_store = store
session_key = "telegram:chat123"
session = store.get_or_create(
session_key, channel="telegram", channel_user_id="u1"
)
store.save_message(session.session_id, "user", "hello", channel="telegram")
store.save_message(
session.session_id, "assistant", "hi there", channel="telegram"
)
captured: list = []
def capturing_ask(query, **kwargs):
captured.append(kwargs.get("prior_messages", []))
return {"content": "reply"}
minimal_system.ask = capturing_ask
bridge = MagicMock()
handler_ref: list = []
def capture_handler(fn):
handler_ref.append(fn)
bridge.on_message = capture_handler
minimal_system.wire_channel(bridge)
cm = SimpleNamespace(
channel="telegram",
conversation_id="chat123",
sender="u1",
content="second message",
)
handler_ref[0](cm)
assert len(captured) == 1
msgs = captured[0]
assert len(msgs) == 2
assert msgs[0].role == Role.USER
assert msgs[0].content == "hello"
assert msgs[1].role == Role.ASSISTANT
assert msgs[1].content == "hi there"
def test_empty_session_passes_empty_prior_messages(self, tmp_path, minimal_system):
"""First message in a new session passes prior_messages=[]."""
from openjarvis.sessions.session import SessionStore
db = tmp_path / "sessions.db"
store = SessionStore(db_path=db)
minimal_system.session_store = store
captured: list = []
def capturing_ask(query, **kwargs):
captured.append(kwargs.get("prior_messages", None))
return {"content": "reply"}
minimal_system.ask = capturing_ask
bridge = MagicMock()
handler_ref: list = []
def capture_handler(fn):
handler_ref.append(fn)
bridge.on_message = capture_handler
minimal_system.wire_channel(bridge)
cm = SimpleNamespace(
channel="telegram",
conversation_id="new-chat",
sender="u2",
content="first message",
)
handler_ref[0](cm)
assert len(captured) == 1
assert captured[0] == []