59from pydantic
import BaseModel, ConfigDict, Field, field_validator
77 """Validated mirror of the ``*_meta.json`` sidecar."""
79 model_config = ConfigDict(extra=
"allow")
81 session_name: str =
""
83 last_modified: str =
""
85 reasoning_effort: str =
""
86 system_prompt: str =
""
87 stats: dict[str, Any] = Field(default_factory=dict)
88 chat_logs: list[str] = Field(default_factory=list)
89 ui: dict[str, Any] = Field(default_factory=dict)
90 last_turn_max_prompt_tokens: int = 0
91 rollover_hint_shown: bool =
False
93 token_profile: str =
"balanced"
94 max_react_iterations: int |
None =
None
95 cache_turn_snapshots: list[Any] = Field(default_factory=list)
96 active_plan_id: str |
None =
None
97 provider_name: str = Field(default=
"")
98 generation_options: dict = Field(default_factory=dict)
99 endpoint_name: str = Field(default=
"")
100 sandbox_root_override: str |
None =
None
103 legacy_event_slugs: list[str] = Field(default_factory=list)
105 """Ordered, validated, deduplicated name-slugs this session wrote events
106 under before earlier renames.
108 CONSTRAINED to the canonical ``event_bootstrap._slug`` grammar by
109 :meth:`_validate_legacy_event_slugs` — these are persisted PATH SEGMENTS, so
110 an unconstrained value would be untrusted path input.
112 Declaring it here is necessary but NOT sufficient:
113 ``load_session_metadata`` returns the RAW dict when model validation fails,
114 so this contract is bypassable. Every consumer re-validates at use — see
115 ``event_bootstrap.event_read_dirs`` and ``session._validated_event_slugs``.
118 superseded_by: str |
None =
None
119 """Set on the OLD record when a rename supersedes it (never deleted).
121 A rename writes both files under the NEW name while the old record stays on
122 disk with the SAME ``session_id``. Marking the old one at rename-commit time
123 makes it non-canonical by construction, so the current record can never lose
124 its identity — or its event history — to its own stale snapshot by load
128 @field_validator("legacy_event_slugs", mode="before")
131 """Keep only canonical slugs, in order, deduplicated. Never raises.
133 Fail-closed by dropping: an invalid alias is ignored rather than
134 rejecting the whole record, because a single bad alias must not make a
135 user's session unloadable.
137 if not isinstance(value, (list, tuple)):
142 if _valid_alias(item)
and item
not in out: