1use kmp_domain::{
2 DimensionSelection, ResolutionTier, TemporalAxis, TemporalCoordinate, TemporalCursor,
3 TemporalDirection, 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}
24
25#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
26pub struct MemoryData {
27 pub dimensions: Vec<MemoryDimensionData>,
28 pub entries: Vec<MemoryEntryData>,
29 pub relations: Vec<MemoryRelationData>,
30 pub evidence: Vec<MemoryEvidenceData>,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
34pub struct MemoryDimensionData {
35 pub id: String,
36 pub kind: String,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub title: Option<String>,
39 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
40 pub metadata: std::collections::BTreeMap<String, String>,
41}
42
43#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
44pub struct MemoryEntryData {
45 pub id: String,
46 pub kind: String,
47 pub text: String,
48 pub coordinates: Vec<MemoryCoordinateData>,
49 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
50 pub metadata: std::collections::BTreeMap<String, String>,
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
54pub struct MemoryCoordinateData {
55 pub dimension: String,
56 pub scope_id: String,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub occurred_at: Option<String>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub observed_at: Option<String>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub ingested_at: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub valid_from: Option<String>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub valid_until: Option<String>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub sequence: Option<u32>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub rank: Option<u32>,
71 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
72 pub metadata: std::collections::BTreeMap<String, String>,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
76pub struct MemoryRelationData {
77 #[serde(rename = "from")]
78 pub source_ref: String,
79 #[serde(rename = "to")]
80 pub target_ref: String,
81 pub rel: String,
82 #[serde(rename = "class")]
83 pub semantic_class: String,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub why: Option<String>,
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub evidence: Option<String>,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub confidence: Option<String>,
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub sequence: Option<u32>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub motivation: Option<String>,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub method: Option<String>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub decision_id: Option<String>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub caused_by_node_id: Option<String>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub coordinate: Option<MemoryCoordinateData>,
102}
103
104#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
105pub struct MemoryEvidenceData {
106 pub id: String,
107 pub supports: Vec<String>,
108 pub text: String,
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub source: Option<String>,
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub time: Option<String>,
113 #[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
114 pub metadata: std::collections::BTreeMap<String, String>,
115}
116
117#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
118pub struct MemoryProvenanceData {
119 pub source_kind: String,
120 pub source_agent: String,
121 pub observed_at: String,
122 pub correlation_id: Option<String>,
123 pub causation_id: Option<String>,
124}
125
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct MemoryAcceptedCounts {
128 pub entries: usize,
129 pub relations: usize,
130 pub evidence: usize,
131}
132
133#[derive(Debug, Clone, PartialEq, Eq)]
134pub struct MemoryIngestOutcome {
135 pub about: String,
136 pub memory_id: String,
137 pub accepted: MemoryAcceptedCounts,
138 pub read_after_write_ready: bool,
139 pub warnings: Vec<String>,
140}
141
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct WakeMemoryQuery {
144 pub about: String,
145 pub role: String,
146 pub intent: String,
147 pub dimensions: DimensionSelection,
148 pub token_budget: u32,
149 pub depth: u32,
150 pub max_tier: Option<ResolutionTier>,
151 pub max_entries: Option<usize>,
155 pub temporal: TemporalSelection,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq)]
161pub struct AskMemoryQuery {
162 pub about: String,
163 pub question: String,
164 pub asked_as: Option<String>,
168 pub answer_policy: MemoryAnswerPolicy,
169 pub dimensions: DimensionSelection,
170 pub token_budget: u32,
171 pub depth: u32,
172 pub max_tier: Option<ResolutionTier>,
173 pub max_entries: Option<usize>,
175 pub temporal: TemporalSelection,
179}
180
181#[derive(Debug, Clone, PartialEq, Eq)]
182pub struct TemporalMemoryQuery {
183 pub about: String,
184 pub direction: TemporalDirection,
185 pub axis: TemporalAxis,
186 pub cursor: TemporalCursor,
187 pub dimensions: DimensionSelection,
188 pub window: TemporalWindow,
189 pub limit_entries: Option<usize>,
190 pub include: TemporalIncludeOptions,
191 pub token_budget: u32,
192 pub depth: u32,
193 pub max_tier: Option<ResolutionTier>,
194}
195
196#[derive(Debug, Clone, PartialEq, Eq)]
199pub struct RelateMemoryQuery {
200 pub about: String,
201 pub dimensions: DimensionSelection,
202 pub temporal: TemporalSelection,
205 pub token_budget: u32,
206 pub depth: u32,
207 pub max_tier: Option<ResolutionTier>,
208 pub page: RelatePageRequest,
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, Default)]
212pub struct RelatePageRequest {
213 pub entries: Option<usize>,
214 pub cursor: Option<usize>,
215}
216
217impl RelatePageRequest {
218 pub fn offset(&self) -> usize {
219 self.cursor.unwrap_or_default()
220 }
221
222 pub fn entries_or_default(&self) -> usize {
223 self.entries.unwrap_or(DEFAULT_RELATE_PAGE_ENTRIES)
224 }
225}
226
227#[derive(Debug, Clone, PartialEq, Eq)]
228pub struct TraceMemoryQuery {
229 pub about: String,
230 pub from: String,
231 pub to: String,
232 pub role: String,
233 pub token_budget: u32,
234 pub page: TracePageRequest,
235}
236
237#[derive(Debug, Clone, PartialEq, Eq, Default)]
238pub struct TracePageRequest {
239 pub entries: Option<usize>,
240 pub cursor: Option<usize>,
241}
242
243impl TracePageRequest {
244 pub fn offset(&self) -> usize {
245 self.cursor.unwrap_or_default()
246 }
247
248 pub fn entries_or_default(&self) -> usize {
249 self.entries.unwrap_or(DEFAULT_TRACE_PAGE_ENTRIES)
250 }
251}
252
253#[derive(Debug, Clone, PartialEq, Eq)]
254pub struct InspectMemoryQuery {
255 pub about: String,
256 pub ref_id: String,
257 pub include_details: bool,
258 pub include_incoming: bool,
259 pub include_outgoing: bool,
260 pub include_raw: bool,
261}
262
263#[derive(Clone, PartialEq, Eq)]
264pub struct InspectMemoryResult {
265 pub detail: GetNodeDetailResult,
266 pub incoming: Vec<GraphRelationshipView>,
267 pub outgoing: Vec<GraphRelationshipView>,
268 pub evidence: Vec<InspectedEvidence>,
269 pub raw_coordinates: Vec<TemporalCoordinate>,
270 pub include_details: bool,
271 pub include_raw: bool,
272}
273
274#[derive(Clone, PartialEq, Eq)]
275pub struct InspectedEvidence {
276 pub detail: GetNodeDetailResult,
277 pub supports: Vec<String>,
278}
279
280#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
281pub enum MemoryAnswerPolicy {
282 #[default]
283 EvidenceOrUnknown,
284 ShowConflicts,
285 BestEffort,
286}
287
288#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
289pub struct TemporalIncludeOptions {
290 pub evidence: bool,
291 pub relations: bool,
292 pub raw_refs: bool,
293}
294
295#[derive(Debug, Clone, PartialEq)]
296pub struct TemporalMemoryResult {
297 pub traversal: kmp_domain::TemporalTraversalResult,
298 pub source_bundle: kmp_domain::KmpBundle,
299 pub include: TemporalIncludeOptions,
300 pub quality: kmp_domain::BundleQualityMetrics,
301}