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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//! Rolling-context data model for the SM context engine (DOC-14 §7.1).
//!
//! Why: the Session Manager keeps an *infinite* conversation by storing the last
//! N rounds verbatim and folding everything older into a growing compressed
//! summary (§7). That requires a small, serialisable data model — a [`Round`]
//! (one operator turn + the SM reply + any tool traces), a [`ToolTrace`] for the
//! delegated-tool calls inside a round, and the [`SmConversation`] container that
//! holds the compressed block, the bounded recent-rounds window, a monotonic
//! round counter, and a running token estimate that drives the compaction
//! trigger. Splitting the pure data types into their own file keeps the engine
//! (`engine.rs`) and the compaction/persistence logic focused and under the SLOC
//! cap.
//! What: defines [`ToolTrace`], [`Round`], and [`SmConversation`] — all
//! `serde`-serialisable for the atomic state file (§7.4) — plus a couple of tiny
//! constructors/helpers used by the engine and tests. No I/O, no LLM, no clock
//! reads here: timestamps are passed IN so callers (and tests) stay deterministic.
//! Test: `model_tests.rs` covers `Round::new`, the round token/char accounting,
//! and `SmConversation` serde round-trips.
use VecDeque;
use ;
use ;
/// A single delegated-tool invocation captured inside a conversation round.
///
/// Why: the SM delegates work to t-mpm sessions and tools; §7.1 records the tool
/// traces alongside the user/assistant text so a compaction call can preserve
/// "what was actually done" (session ids, commands) rather than only the prose.
/// Keeping it a small typed struct (not a bare string) lets future tickets add
/// structured fields without breaking the state-file schema.
/// What: a `name` (the tool/verb invoked) and a `summary` (a short human-readable
/// description of the call + its result). Both are plain owned strings so the
/// round is trivially serialisable and cloneable.
/// Test: `tool_trace_serde_roundtrip` in `model_tests.rs`.
/// One verbatim conversation round: operator turn + SM reply + tool traces.
///
/// Why: §7.1 keeps the last N rounds verbatim so the SM has exact recent context;
/// a round bundles the operator message, the SM's reply, the wall-clock time the
/// round closed, and any tool calls made while answering. Timestamps are stored
/// (not derived) so persistence is faithful and tests are deterministic.
/// What: `user` + `assistant` text, a `ts` close timestamp ([`DateTime<Utc>`] to
/// match the SM memory module's chrono convention), and a `tool_calls` vector.
/// Test: `round_new_sets_fields`, `round_char_len_sums_all_parts`,
/// `round_serde_roundtrip` in `model_tests.rs`.
/// The SM's live conversation state: compressed history + recent verbatim window.
///
/// Why: this is the §7.1 data model — the in-memory (and on-disk, §7.4) buffer
/// that gives the SM effectively infinite context. `compressed_context` grows as
/// old rounds are folded in; `recent_rounds` is the bounded verbatim window;
/// `total_rounds` is a monotonic counter that never decreases even as rounds are
/// evicted; `token_estimate` is the running trigger input (§7.2).
/// What: a `serde`-serialisable struct with the four §7.1 fields. It carries no
/// behaviour beyond tiny accessors/mutators the engine drives — the trigger,
/// compaction, and assembly logic live in sibling modules so this type stays a
/// plain, persistable value.
/// Test: `conversation_default_is_empty`, `conversation_serde_roundtrip`, and the
/// engine/persist tests that drive its fields.