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 receipt_ref: Option<String>,
164 pub about: String,
165 pub memory_id: String,
166 pub accepted: MemoryAcceptedCounts,
167 pub read_after_write_ready: bool,
168 pub warnings: Vec<String>,
169 pub created_dimensions: Vec<String>,
172 pub resembling_labels: Vec<ResemblingLabelData>,
175}
176
177#[derive(Debug, Clone, PartialEq, Eq)]
178pub struct WakeMemoryQuery {
179 pub about: String,
180 pub role: String,
181 pub intent: String,
182 pub dimensions: DimensionSelection,
183 pub token_budget: u32,
184 pub depth: u32,
185 pub max_tier: Option<ResolutionTier>,
186 pub max_entries: Option<usize>,
190 pub temporal: TemporalSelection,
193}
194
195#[derive(Debug, Clone, PartialEq, Eq)]
196pub struct AskMemoryQuery {
197 pub about: String,
198 pub question: String,
199 pub asked_as: Option<String>,
203 pub answer_policy: MemoryAnswerPolicy,
204 pub dimensions: DimensionSelection,
205 pub token_budget: u32,
206 pub depth: u32,
207 pub max_tier: Option<ResolutionTier>,
208 pub max_entries: Option<usize>,
210 pub temporal: TemporalSelection,
214}
215
216#[derive(Debug, Clone, PartialEq, Eq)]
217pub struct TemporalMemoryQuery {
218 pub about: String,
219 pub direction: TemporalDirection,
220 pub axis: TemporalAxis,
221 pub cursor: Option<TemporalCursor>,
222 pub interval: Option<TemporalInterval>,
223 pub dimensions: DimensionSelection,
224 pub window: TemporalWindow,
225 pub limit_entries: Option<usize>,
226 pub include: TemporalIncludeOptions,
227 pub token_budget: u32,
228 pub depth: u32,
229 pub max_tier: Option<ResolutionTier>,
230}
231
232#[derive(Debug, Clone, PartialEq, Eq)]
235pub struct RelateMemoryQuery {
236 pub about: String,
237 pub dimensions: DimensionSelection,
238 pub temporal: TemporalSelection,
241 pub token_budget: u32,
242 pub depth: u32,
243 pub max_tier: Option<ResolutionTier>,
244 pub page: RelatePageRequest,
245}
246
247#[derive(Debug, Clone, PartialEq, Eq, Default)]
248pub struct RelatePageRequest {
249 pub entries: Option<usize>,
250 pub cursor: Option<usize>,
251}
252
253impl RelatePageRequest {
254 pub fn offset(&self) -> usize {
255 self.cursor.unwrap_or_default()
256 }
257
258 pub fn entries_or_default(&self) -> usize {
259 self.entries.unwrap_or(DEFAULT_RELATE_PAGE_ENTRIES)
260 }
261}
262
263#[derive(Debug, Clone, PartialEq, Eq)]
264pub struct TraceMemoryQuery {
265 pub about: String,
266 pub from: String,
267 pub to: String,
268 pub role: String,
269 pub token_budget: u32,
270 pub page: TracePageRequest,
271}
272
273#[derive(Debug, Clone, PartialEq, Eq, Default)]
274pub struct TracePageRequest {
275 pub entries: Option<usize>,
276 pub cursor: Option<usize>,
277}
278
279impl TracePageRequest {
280 pub fn offset(&self) -> usize {
281 self.cursor.unwrap_or_default()
282 }
283
284 pub fn entries_or_default(&self) -> usize {
285 self.entries.unwrap_or(DEFAULT_TRACE_PAGE_ENTRIES)
286 }
287}
288
289#[derive(Debug, Clone, PartialEq, Eq)]
290pub struct InspectMemoryQuery {
291 pub about: String,
292 pub ref_id: String,
293 pub include_details: bool,
294 pub include_incoming: bool,
295 pub include_outgoing: bool,
296 pub include_raw: bool,
297}
298
299#[derive(Clone, PartialEq, Eq)]
300pub struct InspectMemoryResult {
301 pub detail: GetNodeDetailResult,
302 pub incoming: Vec<GraphRelationshipView>,
303 pub outgoing: Vec<GraphRelationshipView>,
304 pub evidence: Vec<InspectedEvidence>,
305 pub raw_coordinates: Vec<TemporalCoordinate>,
306 pub include_details: bool,
307 pub include_raw: bool,
308}
309
310#[derive(Clone, PartialEq, Eq)]
311pub struct InspectedEvidence {
312 pub detail: GetNodeDetailResult,
313 pub supports: Vec<String>,
314}
315
316#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
317pub enum MemoryAnswerPolicy {
318 #[default]
319 EvidenceOrUnknown,
320 ShowConflicts,
321 BestEffort,
322}
323
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
325pub struct TemporalIncludeOptions {
326 pub evidence: bool,
327 pub relations: bool,
328 pub raw_refs: bool,
329}
330
331#[derive(Debug, Clone, PartialEq)]
332pub struct TemporalMemoryResult {
333 pub traversal: kmp_domain::TemporalTraversalResult,
334 pub source_bundle: kmp_domain::KmpBundle,
335 pub include: TemporalIncludeOptions,
336 pub quality: kmp_domain::BundleQualityMetrics,
337}
338
339#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)]
342pub struct EntryLabelData {
343 pub key: String,
344 pub value: String,
345}
346
347#[derive(Debug, Clone, PartialEq, Eq)]
351pub struct MemoryRelabelCommand {
352 pub about: String,
353 pub ref_id: String,
354 pub add: Vec<EntryLabelData>,
355 pub remove: Vec<EntryLabelData>,
356 pub why: String,
357 pub provenance: Option<MemoryProvenanceData>,
358 pub idempotency_key: String,
359 pub dry_run: bool,
360 pub label_policy: LabelPolicy,
361 pub intended_new: std::collections::BTreeSet<String>,
365}
366
367#[derive(Debug, Clone, PartialEq, Eq)]
368pub struct MemoryRelabelOutcome {
369 pub about: String,
370 pub ref_id: String,
371 pub added: Vec<EntryLabelData>,
372 pub removed: Vec<EntryLabelData>,
373 pub labels: Vec<EntryLabelData>,
375 pub created_dimensions: Vec<String>,
378 pub resembling_labels: Vec<ResemblingLabelData>,
381 pub read_after_write_ready: bool,
382 pub warnings: Vec<String>,
383}