fix(streaming): inspect run_conversation signature before passing persist_user_timestamp (#6935)
This commit is contained in:
1 parent
483772b44b
commit
4e5703fc62
2 files changed
+78
-3
No files matched your search
+20
-3
@@ -21,6 +21,7 @@ import threading
|
||||
import time
|
||||
import traceback
|
||||
import copy
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
@@ -307,6 +308,19 @@ def _install_streaming_cronjob_profile_wrapper() -> None:
|
||||
_STREAMING_CRONJOB_WRAPPER_INSTALLED = True
|
||||
|
||||
|
||||
def _supports_kwarg(func, kwarg_name: str) -> bool:
|
||||
"""Return True if callable `func` accepts `kwarg_name` (explicitly or via **kwargs)."""
|
||||
try:
|
||||
sig = inspect.signature(func)
|
||||
for param in sig.parameters.values():
|
||||
if param.kind == param.VAR_KEYWORD or param.name == kwarg_name:
|
||||
return True
|
||||
return False
|
||||
except Exception:
|
||||
return True
|
||||
|
||||
|
||||
|
||||
_PERSISTENT_MEMORY_FILES = (
|
||||
("memory", ("memories", "MEMORY.md")),
|
||||
("user", ("memories", "USER.md")),
|
||||
@@ -9884,8 +9898,9 @@ def _run_agent_streaming(
|
||||
),
|
||||
task_id=session_id,
|
||||
persist_user_message=msg_text,
|
||||
persist_user_timestamp=getattr(s, 'pending_started_at', None),
|
||||
)
|
||||
if _supports_kwarg(agent.run_conversation, 'persist_user_timestamp'):
|
||||
_run_conversation_kwargs['persist_user_timestamp'] = getattr(s, 'pending_started_at', None)
|
||||
# Only pass moa_config when a /moa override is actually active, so a
|
||||
# normal send never trips a TypeError on an older hermes-agent whose
|
||||
# run_conversation() predates the moa_config kwarg.
|
||||
@@ -10387,8 +10402,9 @@ def _run_agent_streaming(
|
||||
),
|
||||
task_id=session_id,
|
||||
persist_user_message=msg_text,
|
||||
persist_user_timestamp=getattr(s, 'pending_started_at', None),
|
||||
)
|
||||
if _supports_kwarg(agent.run_conversation, 'persist_user_timestamp'):
|
||||
_heal_kwargs['persist_user_timestamp'] = getattr(s, 'pending_started_at', None)
|
||||
if moa_config is not None:
|
||||
_heal_kwargs["moa_config"] = moa_config
|
||||
_heal_result = agent.run_conversation(**_heal_kwargs)
|
||||
@@ -11627,8 +11643,9 @@ def _run_agent_streaming(
|
||||
),
|
||||
task_id=session_id,
|
||||
persist_user_message=msg_text,
|
||||
persist_user_timestamp=getattr(s, 'pending_started_at', None),
|
||||
)
|
||||
if _supports_kwarg(_heal_agent.run_conversation, 'persist_user_timestamp'):
|
||||
_heal_kwargs2['persist_user_timestamp'] = getattr(s, 'pending_started_at', None)
|
||||
if moa_config is not None:
|
||||
_heal_kwargs2["moa_config"] = moa_config
|
||||
_heal_result = _heal_agent.run_conversation(**_heal_kwargs2)
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
Test for Issue #6935: Ensure agent.run_conversation() does not trip a TypeError
|
||||
when persist_user_timestamp is passed to agent implementations that do not accept it.
|
||||
"""
|
||||
from api.streaming import _supports_kwarg
|
||||
|
||||
|
||||
class LegacyAgentStub:
|
||||
"""Agent stub mimicking older hermes-agent whose run_conversation does NOT accept **kwargs or persist_user_timestamp."""
|
||||
def run_conversation(self, user_message, system_message=None, conversation_history=None, task_id=None, persist_user_message=None):
|
||||
return {"final_response": "ok", "messages": []}
|
||||
|
||||
|
||||
class ModernAgentWithKwargsStub:
|
||||
"""Agent stub whose run_conversation accepts **kwargs."""
|
||||
def run_conversation(self, **kwargs):
|
||||
return {"final_response": "ok", "messages": []}
|
||||
|
||||
|
||||
class ModernAgentWithExplicitParamStub:
|
||||
"""Agent stub whose run_conversation explicitly accepts persist_user_timestamp."""
|
||||
def run_conversation(self, user_message, persist_user_timestamp=None):
|
||||
return {"final_response": "ok", "messages": []}
|
||||
|
||||
|
||||
def test_supports_kwarg_detection():
|
||||
legacy_agent = LegacyAgentStub()
|
||||
modern_kwargs_agent = ModernAgentWithKwargsStub()
|
||||
modern_explicit_agent = ModernAgentWithExplicitParamStub()
|
||||
|
||||
assert _supports_kwarg(legacy_agent.run_conversation, "persist_user_timestamp") is False
|
||||
assert _supports_kwarg(modern_kwargs_agent.run_conversation, "persist_user_timestamp") is True
|
||||
assert _supports_kwarg(modern_explicit_agent.run_conversation, "persist_user_timestamp") is True
|
||||
|
||||
|
||||
def test_legacy_agent_run_conversation_kwargs_filtering():
|
||||
legacy_agent = LegacyAgentStub()
|
||||
kwargs = {
|
||||
"user_message": "Hello",
|
||||
"system_message": "System prompt",
|
||||
"conversation_history": [],
|
||||
"task_id": "test-session-123",
|
||||
"persist_user_message": "Hello",
|
||||
"persist_user_timestamp": 1700000000.0,
|
||||
}
|
||||
|
||||
if not _supports_kwarg(legacy_agent.run_conversation, "persist_user_timestamp"):
|
||||
kwargs.pop("persist_user_timestamp", None)
|
||||
|
||||
# Calling run_conversation with filtered kwargs must not raise TypeError
|
||||
result = legacy_agent.run_conversation(**kwargs)
|
||||
assert result["final_response"] == "ok"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_supports_kwarg_detection()
|
||||
test_legacy_agent_run_conversation_kwargs_filtering()
|
||||
print("All tests passed successfully!")
|
||||
Reference in new issue
Block a user