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 pub default_observation_to_ingestion: bool,
28 pub neighborhood_review: Option<String>,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
37pub enum LabelPolicy {
38 #[default]
41 Warn,
42 Refuse,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
49pub struct ResemblingLabelData {
50 pub key: String,
51 pub value: String,
52 pub existing_key: String,
53 pub existing_value: String,
54 pub kind: String,
55 pub why: String,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
59pub struct MemoryData {
60 pub dimensions: Vec<MemoryDimensionData>,
61 pub entries: Vec<MemoryEntryData>,
62 pub relations: Vec<MemoryRelationData>,
63 pub evidence: Vec<MemoryEvidenceData>,
64}
65
66#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
67pub struct MemoryDimensionData {
68 pub id: String,
69 pub kind: String,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub title: Option<String>,
72 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
73 pub metadata: std::collections::BTreeMap<String, String>,
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
77pub struct MemoryEntryData {
78 pub id: String,
79 pub kind: String,
80 pub text: String,
81 pub coordinates: Vec<MemoryCoordinateData>,
82 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
83 pub metadata: std::collections::BTreeMap<String, String>,
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
87pub struct MemoryCoordinateData {
88 pub dimension: String,
89 pub scope_id: String,
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub occurred_at: Option<String>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub observed_at: Option<String>,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub ingested_at: Option<String>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub valid_from: Option<String>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub valid_until: Option<String>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub sequence: Option<u32>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub rank: Option<u32>,
104 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
105 pub metadata: std::collections::BTreeMap<String, String>,
106}
107
108#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
109pub struct MemoryRelationData {
110 #[serde(skip_serializing_if = "Option::is_none")]
111 pub clocks: Option<super::MemoryRelationClocks>,
112 #[serde(rename = "from")]
113 pub source_ref: String,
114 #[serde(rename = "to")]
115 pub target_ref: String,
116 pub rel: String,
117 #[serde(rename = "class")]
118 pub semantic_class: String,
119 #[serde(skip_serializing_if = "Option::is_none")]
120 pub why: Option<String>,
121 #[serde(skip_serializing_if = "Option::is_none")]
122 pub evidence: Option<String>,
123 #[serde(skip_serializing_if = "Option::is_none")]
124 pub confidence: Option<String>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub sequence: Option<u32>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub motivation: Option<String>,
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub method: Option<String>,
131 #[serde(skip_serializing_if = "Option::is_none")]
132 pub decision_id: Option<String>,
133 #[serde(skip_serializing_if = "Option::is_none")]
134 pub caused_by_node_id: Option<String>,
135 #[serde(skip_serializing_if = "Option::is_none")]
136 pub coordinate: Option<MemoryCoordinateData>,
137}
138
139#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
140pub struct MemoryEvidenceData {
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub support_clocks: Option<super::EvidenceSupportClocks>,
143 pub id: String,
144 pub supports: Vec<String>,
145 pub text: String,
146 #[serde(skip_serializing_if = "Option::is_none")]
147 pub source: Option<String>,
148 #[serde(skip_serializing_if = "Option::is_none")]
149 pub time: Option<String>,
150 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
151 pub metadata: std::collections::BTreeMap<String, String>,
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
155pub struct MemoryProvenanceData {
156 pub source_kind: String,
157 pub source_agent: String,
158 pub observed_at: Option<String>,
159 pub correlation_id: Option<String>,
160 pub causation_id: Option<String>,
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
164pub struct MemoryAcceptedCounts {
165 pub entries: usize,
166 pub relations: usize,
167 pub evidence: usize,
168}
169
170#[derive(Debug, Clone, PartialEq, Eq)]
171pub struct MemoryIngestOutcome {
172 pub neighborhood: Option<super::WriteNeighborhood>,
173 pub replayed: bool,
174 pub clocks: Option<super::WriteClocks>,
175 pub receipt_ref: Option<String>,
176 pub about: String,
177 pub memory_id: String,
178 pub accepted: MemoryAcceptedCounts,
179 pub read_after_write_ready: bool,
180 pub warnings: Vec<String>,
181 pub created_dimensions: Vec<String>,
184 pub resembling_labels: Vec<ResemblingLabelData>,
187}
188
189#[derive(Debug, Clone, PartialEq, Eq)]
190pub struct WakeMemoryQuery {
191 pub about: String,
192 pub role: String,
193 pub intent: String,
194 pub dimensions: DimensionSelection,
195 pub token_budget: u32,
196 pub depth: u32,
197 pub max_tier: Option<ResolutionTier>,
198 pub max_entries: Option<usize>,
202 pub temporal: TemporalSelection,
205}
206
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub struct AskMemoryQuery {
209 pub about: String,
210 pub question: String,
211 pub asked_as: Option<String>,
215 pub answer_policy: MemoryAnswerPolicy,
216 pub dimensions: DimensionSelection,
217 pub token_budget: u32,
218 pub depth: u32,
219 pub max_tier: Option<ResolutionTier>,
220 pub max_entries: Option<usize>,
222 pub temporal: TemporalSelection,
226}
227
228#[derive(Debug, Clone, PartialEq, Eq)]
229pub struct TemporalMemoryQuery {
230 pub about: String,
231 pub direction: TemporalDirection,
232 pub entry_selection: Option<kmp_domain::TemporalEntrySelection>,
233 pub axis: TemporalAxis,
234 pub cursor: Option<TemporalCursor>,
235 pub interval: Option<TemporalInterval>,
236 pub dimensions: DimensionSelection,
237 pub window: TemporalWindow,
238 pub limit_entries: Option<usize>,
239 pub include: TemporalIncludeOptions,
240 pub token_budget: u32,
241 pub depth: u32,
242 pub max_tier: Option<ResolutionTier>,
243}
244
245#[derive(Debug, Clone, PartialEq, Eq)]
248pub struct RelateMemoryQuery {
249 pub about: String,
250 pub dimensions: DimensionSelection,
251 pub temporal: TemporalSelection,
254 pub token_budget: u32,
255 pub depth: u32,
256 pub max_tier: Option<ResolutionTier>,
257 pub page: RelatePageRequest,
258}
259
260#[derive(Debug, Clone, PartialEq, Eq, Default)]
261pub struct RelatePageRequest {
262 pub entries: Option<usize>,
263 pub cursor: Option<usize>,
264}
265
266impl RelatePageRequest {
267 pub fn offset(&self) -> usize {
268 self.cursor.unwrap_or_default()
269 }
270
271 pub fn entries_or_default(&self) -> usize {
272 self.entries.unwrap_or(DEFAULT_RELATE_PAGE_ENTRIES)
273 }
274}
275
276#[derive(Debug, Clone, PartialEq, Eq)]
277pub struct TraceMemoryQuery {
278 pub about: String,
279 pub from: String,
280 pub to: String,
281 pub role: String,
282 pub token_budget: u32,
283 pub page: TracePageRequest,
284}
285
286#[derive(Debug, Clone, PartialEq, Eq, Default)]
287pub struct TracePageRequest {
288 pub entries: Option<usize>,
289 pub cursor: Option<usize>,
290}
291
292impl TracePageRequest {
293 pub fn offset(&self) -> usize {
294 self.cursor.unwrap_or_default()
295 }
296
297 pub fn entries_or_default(&self) -> usize {
298 self.entries.unwrap_or(DEFAULT_TRACE_PAGE_ENTRIES)
299 }
300}
301
302#[derive(Debug, Clone, PartialEq, Eq)]
303pub struct InspectMemoryQuery {
304 pub about: String,
305 pub ref_id: String,
306 pub include_details: bool,
307 pub include_incoming: bool,
308 pub include_outgoing: bool,
309 pub include_raw: bool,
310 pub expect_revision: Option<u64>,
315}
316
317#[derive(Clone, PartialEq, Eq)]
318pub struct InspectMemoryResult {
319 pub detail: GetNodeDetailResult,
320 pub incoming: Vec<GraphRelationshipView>,
321 pub outgoing: Vec<GraphRelationshipView>,
322 pub evidence: Vec<InspectedEvidence>,
323 pub raw_coordinates: Vec<TemporalCoordinate>,
324 pub include_details: bool,
325 pub include_raw: bool,
326}
327
328#[derive(Clone, PartialEq, Eq)]
329pub struct InspectedEvidence {
330 pub detail: GetNodeDetailResult,
331 pub supports: Vec<String>,
332}
333
334#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
335pub enum MemoryAnswerPolicy {
336 #[default]
337 EvidenceOrUnknown,
338 ShowConflicts,
339 BestEffort,
340}
341
342#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
343pub struct TemporalIncludeOptions {
344 pub evidence: bool,
345 pub relations: bool,
346 pub raw_refs: bool,
347 pub dependencies: bool,
350}
351
352#[derive(Debug, Clone, PartialEq)]
353pub struct TemporalMemoryResult {
354 pub traversal: kmp_domain::TemporalTraversalResult,
355 pub source_bundle: kmp_domain::KmpBundle,
359 pub include: TemporalIncludeOptions,
360}
361
362#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)]
365pub struct EntryLabelData {
366 pub key: String,
367 pub value: String,
368}
369
370#[derive(Debug, Clone, PartialEq, Eq)]
374pub struct MemoryRelabelCommand {
375 pub about: String,
376 pub ref_id: String,
377 pub add: Vec<EntryLabelData>,
378 pub remove: Vec<EntryLabelData>,
379 pub why: String,
380 pub provenance: Option<MemoryProvenanceData>,
381 pub idempotency_key: String,
382 pub dry_run: bool,
383 pub label_policy: LabelPolicy,
384 pub intended_new: std::collections::BTreeSet<String>,
388}
389
390#[derive(Debug, Clone, PartialEq, Eq)]
391pub struct MemoryRelabelOutcome {
392 pub about: String,
393 pub ref_id: String,
394 pub added: Vec<EntryLabelData>,
395 pub removed: Vec<EntryLabelData>,
396 pub labels: Vec<EntryLabelData>,
398 pub created_dimensions: Vec<String>,
401 pub resembling_labels: Vec<ResemblingLabelData>,
404 pub read_after_write_ready: bool,
405 pub warnings: Vec<String>,
406}