feat(conversations): the recall hook and the user sink learn whose turn it is

This commit is contained in:
hh
2026-09-06 23:26:26 +02:00
parent d5aaa80822
commit 9e60d06829
4 changed files with 48 additions and 8 deletions
+19 -6
View File
@@ -25,6 +25,8 @@ class RecallContext:
text: str
kind: str
now: datetime
agent: str = ""
"""Agent whose turn it is; a setup with several tells them apart by it."""
@dataclass(slots=True)
@@ -40,7 +42,12 @@ class Envelope:
texts: EnvelopeTexts = field(default_factory=EnvelopeTexts)
def build(
self, *, now: datetime | None = None, text: str = "", kind: str = "master"
self,
*,
now: datetime | None = None,
text: str = "",
kind: str = "master",
agent: str = "",
) -> str:
now = now or datetime.now(UTC)
changes = self.watch.take() if self.watch is not None else []
@@ -59,20 +66,26 @@ class Envelope:
texts=self.texts,
)
self.last_at = now
block = self.recall_block(text=text, kind=kind, now=now)
block = self.recall_block(text=text, kind=kind, now=now, agent=agent)
return f"{out}\n{block}" if block else out
def recall_only(
self, *, text: str, kind: str, now: datetime | None = None
self, *, text: str, kind: str, now: datetime | None = None, agent: str = ""
) -> str | None:
block = self.recall_block(text=text, kind=kind, now=now or datetime.now(UTC))
block = self.recall_block(
text=text, kind=kind, now=now or datetime.now(UTC), agent=agent
)
return f"{self.texts.header}\n{block}" if block else None
def recall_block(self, *, text: str, kind: str, now: datetime) -> str | None:
def recall_block(
self, *, text: str, kind: str, now: datetime, agent: str = ""
) -> str | None:
if self.recall is None or not text.strip():
return None
try:
block = self.recall(RecallContext(text=text, kind=kind, now=now))
block = self.recall(
RecallContext(text=text, kind=kind, now=now, agent=agent)
)
except Exception: # noqa: BLE001
_log.exception("recall hook failed")
return None
@@ -51,6 +51,8 @@ class UserSaid:
title: str | None
text: str
at: datetime
agent: str = ""
"""Agent whose turn it is; a setup with several tells them apart by it."""
@dataclass(frozen=True, slots=True)
+5 -2
View File
@@ -336,9 +336,11 @@ class Turns(Seeds):
if self._envelope is None:
return None
if conv.kind == "master":
return self._envelope.build(text=text, kind="master")
return self._envelope.build(text=text, kind="master", agent=conv.agent_name)
if conv.kind == "branch":
return self._envelope.recall_only(text=text, kind="branch")
return self._envelope.recall_only(
text=text, kind="branch", agent=conv.agent_name
)
return None
async def _note_user(self, conv: Conversation, text: str) -> None:
@@ -350,6 +352,7 @@ class Turns(Seeds):
title=conv.title,
text=text,
at=datetime.now(UTC),
agent=conv.agent_name,
)
try:
result = self._user_sink(message)