Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion plugins/memory/honcho/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -1168,9 +1168,33 @@ def set_peer_card(self, session_key: str, card: list[str], peer: str = "user") -
if peer_id is None:
logger.warning("Could not resolve peer '%s' for set_peer_card in session '%s'", peer, session_key)
return None
if peer_id == session.assistant_peer_id:
peer_obj = self._get_or_create_peer(session.assistant_peer_id)
result = peer_obj.set_card(card)
logger.info("Updated self peer card for %s (%d facts)", peer_id, len(card))
return result

# Keep write semantics aligned with get_peer_card/search_context:
# when the assistant observes the user, honcho_profile reads the
# assistant's local card about the target peer via
# assistant.get_card(target=<user>). Updating the target peer's
# self-card only makes the immediate write response look green but
# a subsequent read returns empty. Write the observer-target card
# that the tool will read back.
if self._ai_observe_others:
observer = self._get_or_create_peer(session.assistant_peer_id)
result = observer.set_card(card, target=peer_id)
logger.info(
"Updated observer peer card for %s about %s (%d facts)",
session.assistant_peer_id,
peer_id,
len(card),
)
return result

peer_obj = self._get_or_create_peer(peer_id)
result = peer_obj.set_card(card)
logger.info("Updated peer card for %s (%d facts)", peer_id, len(card))
logger.info("Updated self peer card for %s (%d facts)", peer_id, len(card))
return result
except Exception as e:
logger.error("Failed to set peer card: %s", e)
Expand Down
34 changes: 34 additions & 0 deletions tests/honcho_plugin/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,40 @@ def test_get_peer_card_uses_direct_peer_lookup(self):
assert mgr.get_peer_card(session.key) == ["Name: Robert"]
assistant_peer.get_card.assert_called_once_with(target=session.user_peer_id)

def test_set_peer_card_updates_same_observer_target_card_read_by_profile(self):
mgr, session = self._make_cached_manager()
assistant_peer = MagicMock()
assistant_peer.set_card.return_value = ["Name: Robert"]
mgr._get_or_create_peer = MagicMock(return_value=assistant_peer)

assert mgr.set_peer_card(session.key, ["Name: Robert"]) == ["Name: Robert"]
mgr._get_or_create_peer.assert_called_once_with(session.assistant_peer_id)
assistant_peer.set_card.assert_called_once_with(
["Name: Robert"],
target=session.user_peer_id,
)

def test_set_peer_card_updates_ai_self_card_when_target_is_ai(self):
mgr, session = self._make_cached_manager()
assistant_peer = MagicMock()
assistant_peer.set_card.return_value = ["Role: Assistant"]
mgr._get_or_create_peer = MagicMock(return_value=assistant_peer)

assert mgr.set_peer_card(session.key, ["Role: Assistant"], peer="ai") == ["Role: Assistant"]
mgr._get_or_create_peer.assert_called_once_with(session.assistant_peer_id)
assistant_peer.set_card.assert_called_once_with(["Role: Assistant"])

def test_set_peer_card_unified_mode_updates_user_self_card(self):
mgr, session = self._make_cached_manager()
mgr._ai_observe_others = False
user_peer = MagicMock()
user_peer.set_card.return_value = ["Name: Robert"]
mgr._get_or_create_peer = MagicMock(return_value=user_peer)

assert mgr.set_peer_card(session.key, ["Name: Robert"]) == ["Name: Robert"]
mgr._get_or_create_peer.assert_called_once_with(session.user_peer_id)
user_peer.set_card.assert_called_once_with(["Name: Robert"])

def test_search_context_uses_assistant_perspective_with_target(self):
mgr, session = self._make_cached_manager()
assistant_peer = MagicMock()
Expand Down