symfonic.capabilities.memory.conversation¶
conversation ¶
Reading legacy's working layer as conversation turns (design §2c).
WorkingWindow needs a :class:~.working.ConversationSource; legacy keeps
the conversation as MemoryEntry rows in its working layer. The design's
rule for this seam is that a turn's identity, speaker and order must not be
fabricated out of those rows — and reading the producer showed none of the
three has to be:
turn_idandspeakerare framework-reserved metadata keys (engine._RESERVED_AUTO_TURN_METADATA_KEYS), written on every auto-turn write, and an adopter cannot override them, so they carry framework meaning;rehydrate_from_messageswrites the same shape on purpose, so a replayed row is indistinguishable from a live one;get_contextdocuments chronological order, oldest first.
Identity and speaker are therefore read, and order is what the producer states
by the sequence it returns. What this module must never do is supply one of
them when the producer did not — see :meth:LegacyConversationSource.recent.
LegacyConversationSource ¶
A :class:~.working.ConversationSource over legacy's working layer.
Holds the layer rather than reaching for a global, so two agents in one process read two conversations.
Source code in src/symfonic/capabilities/memory/conversation.py
recent
async
¶
The last limit turns at scope, oldest first.
Rows with no turn_id are excluded, not repaired. The obvious
repair — fall back to entry.id — is wrong in a way nothing
downstream could detect: the engine writes the user utterance and the
assistant reply under the same turn_id, so row ids would split one
turn into two, and the rendered block would look exactly the same.
A missing speaker is left empty instead, because the window's own
rule is that a turn declaring no speaker is never excluded — applying
speaker exclusion to rows that predate the field would delete a
conversation's history the day an operator set the knob.
turn is the row's position in what the producer returned. Positions
are not renumbered after an exclusion: renumbering would turn turn
into a count of admitted rows rather than a place in the conversation.