symfonic.services.conversation.values¶
values ¶
Frozen value types shared by every conversation service.
These are the vocabulary the rest of the package speaks. Two of them encode a compatibility contract rather than a convenience:
- :class:
SessionIdentityreproduces the legacy engine'sthread_idderivation exactly, because a transcript written before the migration must be read back under the key that wrote it, and - :class:
SessionRecordrenders to the legacy manager's five-key row, because a rollback reads those rows with the legacy reader.
The checkpoint-shaped values (:class:CheckpointRef,
:class:SafeBoundaryMarker) live in
:mod:symfonic.services.conversation.refs, which imports this module rather
than the other way round: the checkpoint vocabulary is built on the thread-key
vocabulary, never the reverse.
SessionIdentity
dataclass
¶
Tenant + sub-tenant + session, and the thread key they derive.
as_configurable ¶
The graph-runner config shape. checkpoint_id only when resuming.
Source code in src/symfonic/services/conversation/values.py
SessionRecord
dataclass
¶
SessionRecord(session_id: str, tenant_id: str, created_at: datetime, last_active: datetime, message_count: int = 0, extra: tuple[tuple[str, Any], ...] = ())
One session row, in the migrated shape, with a legacy projection.
extra carries any key the legacy path wrote that this package does not
model. Dropping it would make a rollback lossy, which is the one thing the
bidirectional assumption forbids.
to_legacy_dict ¶
Exactly the keys the legacy SessionManager wrote, same types.
Source code in src/symfonic/services/conversation/values.py
TranscriptRow
dataclass
¶
TranscriptRow(index: int, role: TranscriptRole, content: str, message_id: str | None = None, timestamp: datetime | None = None)
One verbatim transcript row on the public surface.
index is the ordinal within the speaker-filtered view that produced
it, and timestamp is checkpoint granularity — None when the source
cannot resolve one. Both were load-bearing on the legacy surface.
tenant_segment_is_provable ¶
Whether this key's tenant segment is provably the whole tenant id.
The derivation puts exactly two separators in a key. A key carrying more
could have come from either an exempt session id (t:_:https://x) or a
separator-bearing tenant the legacy path never validated
(acme:eu:_:s1), and nothing in the key itself distinguishes the two.
Positional parsing stays deterministic for both — but attribution does
not, so this predicate gates naming a tenant, never reading the state.