1use kmp_domain::{
2 DimensionSelection, ResolutionTier, TemporalAxis, TemporalCoordinate, TemporalCursor,
3 TemporalDirection, TemporalInterval, TemporalSelection, TemporalWindow,
4};
5
6use crate::queries::{GetNodeDetailResult, GraphRelationshipView};
7
8pub const DEFAULT_TRACE_PAGE_ENTRIES: usize = 64;
9pub const DEFAULT_RELATE_PAGE_ENTRIES: usize = 32;
13pub const MAX_RELATE_PAGE_ENTRIES: usize = 256;
14pub const MAX_TRACE_PAGE_ENTRIES: usize = 256;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct MemoryIngestCommand {
18 pub about: String,
19 pub memory: MemoryData,
20 pub provenance: Option<MemoryProvenanceData>,
21 pub idempotency_key: String,
22 pub dry_run: bool,
23 pub label_policy: LabelPolicy,
24 pub receipt_context: Option<serde_json::Value>,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
32pub enum LabelPolicy {
33 #[default]
36 Warn,
37 Refuse,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
44pub struct ResemblingLabelData {
45 pub key: String,
46 pub value: String,
47 pub existing_key: String,
48 pub existing_value: String,
49 pub kind: String,
50 pub why: String,
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
54pub struct MemoryData {
55 pub dimensions: Vec<MemoryDimensionData>,
56 pub entries: Vec<MemoryEntryData>,
57 pub relations: Vec<MemoryRelationData>,
58 pub evidence: Vec<MemoryEvidenceData>,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
62pub struct MemoryDimensionData {
63 pub id: String,
64 pub kind: String,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub title: Option<String>,
67 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
68 pub metadata: std::collections::BTreeMap<String, String>,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
72pub struct MemoryEntryData {
73 pub id: String,
74 pub kind: String,
75 pub text: String,
76 pub coordinates: Vec<MemoryCoordinateData>,
77 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
78 pub metadata: std::collections::BTreeMap<String, String>,
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
82pub struct MemoryCoordinateData {
83 pub dimension: String,
84 pub scope_id: String,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub occurred_at: Option<String>,
87 #[serde(skip_serializing_if = "Option::is_none")]
88 pub observed_at: Option<String>,
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub ingested_at: Option<String>,
91 #[serde(skip_serializing_if = "Option::is_none")]
92 pub valid_from: Option<String>,
93 #[serde(skip_serializing_if = "Option::is_none")]
94 pub valid_until: Option<String>,
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub sequence: Option<u32>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub rank: Option<u32>,
99 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
100 pub metadata: std::collections::BTreeMap<String, String>,
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
104pub struct MemoryRelationData {
105 #[serde(rename = "from")]
106 pub source_ref: String,
107 #[serde(rename = "to")]
108 pub target_ref: String,
109 pub rel: String,
110 #[serde(rename = "class")]
111 pub semantic_class: String,
112 #[serde(skip_serializing_if = "Option::is_none")]
113 pub why: Option<String>,
114 #[serde(skip_serializing_if = "Option::is_none")]
115 pub evidence: Option<String>,
116 #[serde(skip_serializing_if = "Option::is_none")]
117 pub confidence: Option<String>,
118 #[serde(skip_serializing_if = "Option::is_none")]
119 pub sequence: Option<u32>,
120 #[serde(skip_serializing_if = "Option::is_none")]
121 pub motivation: Option<String>,
122 #[serde(skip_serializing_if = "Option::is_none")]
123 pub method: Option<String>,
124 #[serde(skip_serializing_if = "Option::is_none")]
125 pub decision_id: Option<String>,
126 #[serde(skip_serializing_if = "Option::is_none")]
127 pub caused_by_node_id: Option<String>,
128 #[serde(skip_serializing_if = "Option::is_none")]
129 pub coordinate: Option<MemoryCoordinateData>,
130}
131
132#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
133pub struct MemoryEvidenceData {
134 pub id: String,
135 pub supports: Vec<String>,
136 pub text: String,
137 #[serde(skip_serializing_if = "Option::is_none")]
138 pub source: Option<String>,
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub time: Option<String>,
141 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
142 pub metadata: std::collections::BTreeMap<String, String>,
143}
144
145#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
146pub struct MemoryProvenanceData {
147 pub source_kind: String,
148 pub source_agent: String,
149 pub observed_at: String,
150 pub correlation_id: Option<String>,
151 pub causation_id: Option<String>,
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
155pub struct MemoryAcceptedCounts {
156 pub entries: usize,
157 pub relations: usize,
158 pub evidence: usize,
159}
160
161#[derive(Debug, Clone, PartialEq, Eq)]
162pub struct MemoryIngestOutcome {
163 pub replayed: bool,
164 pub clocks: Option<super::WriteClocks>,
165 pub receipt_ref: Option<String>,
166 pub about: String,
167 pub memory_id: String,
168 pub accepted: MemoryAcceptedCounts,
169 pub read_after_write_ready: bool,
170 pub warnings: Vec<String>,
171 pub created_dimensions: Vec<String>,
174 pub resembling_labels: Vec<ResemblingLabelData>,
177}
178
179#[derive(Debug, Clone, PartialEq, Eq)]
180pub struct WakeMemoryQuery {
181 pub about: String,
182 pub role: String,
183 pub intent: String,
184 pub dimensions: DimensionSelection,
185 pub token_budget: u32,
186 pub depth: u32,
187 pub max_tier: Option<ResolutionTier>,
188 pub max_entries: Option<usize>,
192 pub temporal: TemporalSelection,
195}
196
197#[derive(Debug, Clone, PartialEq, Eq)]
198pub struct AskMemoryQuery {
199 pub about: String,
200 pub question: String,
201 pub asked_as: Option<String>,
205 pub answer_policy: MemoryAnswerPolicy,
206 pub dimensions: DimensionSelection,
207 pub token_budget: u32,
208 pub depth: u32,
209 pub max_tier: Option<ResolutionTier>,
210 pub max_entries: Option<usize>,
212 pub temporal: TemporalSelection,
216}
217
218#[derive(Debug, Clone, PartialEq, Eq)]
219pub struct TemporalMemoryQuery {
220 pub about: String,
221 pub direction: TemporalDirection,
222 pub entry_selection: Option<kmp_domain::TemporalEntrySelection>,
223 pub axis: TemporalAxis,
224 pub cursor: Option<TemporalCursor>,
225 pub interval: Option<TemporalInterval>,
226 pub dimensions: DimensionSelection,
227 pub window: TemporalWindow,
228 pub limit_entries: Option<usize>,
229 pub include: TemporalIncludeOptions,
230 pub token_budget: u32,
231 pub depth: u32,
232 pub max_tier: Option<ResolutionTier>,
233}
234
235#[derive(Debug, Clone, PartialEq, Eq)]
238pub struct RelateMemoryQuery {
239 pub about: String,
240 pub dimensions: DimensionSelection,
241 pub temporal: TemporalSelection,
244 pub token_budget: u32,
245 pub depth: u32,
246 pub max_tier: Option<ResolutionTier>,
247 pub page: RelatePageRequest,
248}
249
250#[derive(Debug, Clone, PartialEq, Eq, Default)]
251pub struct RelatePageRequest {
252 pub entries: Option<usize>,
253 pub cursor: Option<usize>,
254}
255
256impl RelatePageRequest {
257 pub fn offset(&self) -> usize {
258 self.cursor.unwrap_or_default()
259 }
260
261 pub fn entries_or_default(&self) -> usize {
262 self.entries.unwrap_or(DEFAULT_RELATE_PAGE_ENTRIES)
263 }
264}
265
266#[derive(Debug, Clone, PartialEq, Eq)]
267pub struct TraceMemoryQuery {
268 pub about: String,
269 pub from: String,
270 pub to: String,
271 pub role: String,
272 pub token_budget: u32,
273 pub page: TracePageRequest,
274}
275
276#[derive(Debug, Clone, PartialEq, Eq, Default)]
277pub struct TracePageRequest {
278 pub entries: Option<usize>,
279 pub cursor: Option<usize>,
280}
281
282impl TracePageRequest {
283 pub fn offset(&self) -> usize {
284 self.cursor.unwrap_or_default()
285 }
286
287 pub fn entries_or_default(&self) -> usize {
288 self.entries.unwrap_or(DEFAULT_TRACE_PAGE_ENTRIES)
289 }
290}
291
292#[derive(Debug, Clone, PartialEq, Eq)]
293pub struct InspectMemoryQuery {
294 pub about: String,
295 pub ref_id: String,
296 pub include_details: bool,
297 pub include_incoming: bool,
298 pub include_outgoing: bool,
299 pub include_raw: bool,
300}
301
302#[derive(Clone, PartialEq, Eq)]
303pub struct InspectMemoryResult {
304 pub detail: GetNodeDetailResult,
305 pub incoming: Vec<GraphRelationshipView>,
306 pub outgoing: Vec<GraphRelationshipView>,
307 pub evidence: Vec<InspectedEvidence>,
308 pub raw_coordinates: Vec<TemporalCoordinate>,
309 pub include_details: bool,
310 pub include_raw: bool,
311}
312
313#[derive(Clone, PartialEq, Eq)]
314pub struct InspectedEvidence {
315 pub detail: GetNodeDetailResult,
316 pub supports: Vec<String>,
317}
318
319#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
320pub enum MemoryAnswerPolicy {
321 #[default]
322 EvidenceOrUnknown,
323 ShowConflicts,
324 BestEffort,
325}
326
327#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
328pub struct TemporalIncludeOptions {
329 pub evidence: bool,
330 pub relations: bool,
331 pub raw_refs: bool,
332 pub dependencies: bool,
335}
336
337#[derive(Debug, Clone, PartialEq)]
338pub struct TemporalMemoryResult {
339 pub traversal: kmp_domain::TemporalTraversalResult,
340 pub source_bundle: kmp_domain::KmpBundle,
341 pub include: TemporalIncludeOptions,
342 pub quality: kmp_domain::BundleQualityMetrics,
343}
344
345#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)]
348pub struct EntryLabelData {
349 pub key: String,
350 pub value: String,
351}
352
353#[derive(Debug, Clone, PartialEq, Eq)]
357pub struct MemoryRelabelCommand {
358 pub about: String,
359 pub ref_id: String,
360 pub add: Vec<EntryLabelData>,
361 pub remove: Vec<EntryLabelData>,
362 pub why: String,
363 pub provenance: Option<MemoryProvenanceData>,
364 pub idempotency_key: String,
365 pub dry_run: bool,
366 pub label_policy: LabelPolicy,
367 pub intended_new: std::collections::BTreeSet<String>,
371}
372
373#[derive(Debug, Clone, PartialEq, Eq)]
374pub struct MemoryRelabelOutcome {
375 pub about: String,
376 pub ref_id: String,
377 pub added: Vec<EntryLabelData>,
378 pub removed: Vec<EntryLabelData>,
379 pub labels: Vec<EntryLabelData>,
381 pub created_dimensions: Vec<String>,
384 pub resembling_labels: Vec<ResemblingLabelData>,
387 pub read_after_write_ready: bool,
388 pub warnings: Vec<String>,
389}