Spaces:
Running
Running
File size: 1,718 Bytes
414dc55 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | """The dual-output contract for one suspect turn.
``spoken`` is a distinct JSON string node, so hidden state physically cannot leak
into the dialogue shown to the player. ``internal`` is parsed for flavour and UI
cues only - it is ADVISORY. The deterministic director (engine.director) is the
sole authority on whether a lie was caught or a fact was truly revealed.
"""
from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field
from ..constants import DECEPTION_MAX, DECEPTION_MIN
from .enums import EvidenceReaction, Intent
class InternalState(BaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
# Ordered first so the small model "reasons" before committing to a line.
private_reasoning: str = ""
intent: Intent = Intent.DEFLECT
addressed_topic: str = ""
is_lying: bool = False
active_lie_id: str | None = None
lie_refs: tuple[str, ...] = ()
evidence_reaction: EvidenceReaction = EvidenceReaction.NONE
deception_level: int = Field(default=0, ge=DECEPTION_MIN, le=DECEPTION_MAX)
stress: float = Field(default=0.0, ge=0.0, le=1.0)
revealed_fact_ids: tuple[str, ...] = ()
contradicted_by_evidence: bool = False
consistency_flag: bool = True
slip: bool = False
class InterrogationTurn(BaseModel):
model_config = ConfigDict(frozen=True, extra="ignore")
spoken: str
narration: str = ""
internal: InternalState = InternalState()
@staticmethod
def safe_default(line: str = "I have nothing more to say about that.") -> InterrogationTurn:
"""A valid fallback turn used when generation or validation fails."""
return InterrogationTurn(spoken=line, internal=InternalState())
|