1use chrono::{DateTime, Utc};
2use locus_core_rs::domain::models::{AvecState, PsiRange, SttpNode};
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::application::memory_composition::{
7 CompositeInputItem, CompositeNodeFromTextOptions, CompositeNodeFromTextRequest,
8 CompositeNodeFromTextResult, CompositeRole, CompositeRoleAvecOverrides,
9 MemoryDailyRollupRequest, MemoryRecallWithExplainResult, MemoryTransformThenRecallRequest,
10 MemoryTransformThenRecallResult,
11};
12use crate::domain::memory::{
13 FallbackPolicy, MemoryAggregateRequest, MemoryAggregateResult, MemoryExplainRequest,
14 MemoryExplainResult, MemoryFilter, MemoryFindRequest, MemoryFindResult, MemoryGroupBy,
15 MemoryPage, MemoryRecallRequest, MemoryRecallResult, MemorySchemaResult, MemoryScope,
16 MemoryScoring, MemorySort, MemoryTransformOperation, MemoryTransformRequest,
17 MemoryTransformResult, MetricRange, NumericStats, RetrievalPath, StrictnessMode,
18};
19use crate::domain::reflex::{
20 MemoryAction, MemoryPersistHint, MemoryPropositions, MemoryReflex, MemoryReflexKind, ReflexGate,
21};
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24#[serde(rename_all = "camelCase")]
25pub struct AvecStateDto {
26 pub stability: f32,
27 pub friction: f32,
28 pub logic: f32,
29 pub autonomy: f32,
30 pub psi: f32,
31}
32
33impl From<AvecStateDto> for AvecState {
34 fn from(value: AvecStateDto) -> Self {
35 Self {
36 stability: value.stability,
37 friction: value.friction,
38 logic: value.logic,
39 autonomy: value.autonomy,
40 }
41 }
42}
43
44impl From<AvecState> for AvecStateDto {
45 fn from(value: AvecState) -> Self {
46 Self {
47 stability: value.stability,
48 friction: value.friction,
49 logic: value.logic,
50 autonomy: value.autonomy,
51 psi: value.psi(),
52 }
53 }
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57#[serde(rename_all = "camelCase")]
58pub struct PsiRangeDto {
59 pub min: f32,
60 pub max: f32,
61 pub average: f32,
62}
63
64impl From<PsiRange> for PsiRangeDto {
65 fn from(value: PsiRange) -> Self {
66 Self {
67 min: value.min,
68 max: value.max,
69 average: value.average,
70 }
71 }
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct MemoryScopeDto {
77 pub tenant_id: Option<String>,
78 pub session_ids: Option<Vec<String>>,
79 pub tiers: Option<Vec<String>>,
80 pub from_utc: Option<DateTime<Utc>>,
81 pub to_utc: Option<DateTime<Utc>>,
82}
83
84impl From<MemoryScopeDto> for MemoryScope {
85 fn from(value: MemoryScopeDto) -> Self {
86 Self {
87 tenant_id: value.tenant_id,
88 session_ids: value.session_ids,
89 tiers: value.tiers,
90 from_utc: value.from_utc,
91 to_utc: value.to_utc,
92 }
93 }
94}
95
96impl From<MemoryScope> for MemoryScopeDto {
97 fn from(value: MemoryScope) -> Self {
98 Self {
99 tenant_id: value.tenant_id,
100 session_ids: value.session_ids,
101 tiers: value.tiers,
102 from_utc: value.from_utc,
103 to_utc: value.to_utc,
104 }
105 }
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109#[serde(rename_all = "camelCase")]
110pub struct MemoryFilterDto {
111 pub has_embedding: Option<bool>,
112 pub embedding_model: Option<String>,
113 pub psi: Option<MetricRange>,
114 pub rho: Option<MetricRange>,
115 pub kappa: Option<MetricRange>,
116 pub text_contains: Option<String>,
117 pub tags_contains: Option<Vec<String>>,
118 pub has_tag: Option<String>,
119 pub indexed_tags: Option<Vec<String>>,
120 pub tag_prefix: Option<String>,
121 pub has_semantic_links: Option<bool>,
122 pub link_rel: Option<String>,
123 pub link_target: Option<String>,
124 pub links_to_ref: Option<String>,
125}
126
127impl From<MemoryFilterDto> for MemoryFilter {
128 fn from(value: MemoryFilterDto) -> Self {
129 Self {
130 has_embedding: value.has_embedding,
131 embedding_model: value.embedding_model,
132 psi: value.psi,
133 rho: value.rho,
134 kappa: value.kappa,
135 text_contains: value.text_contains,
136 tags_contains: value.tags_contains,
137 has_tag: value.has_tag,
138 indexed_tags: value.indexed_tags,
139 tag_prefix: value.tag_prefix,
140 has_semantic_links: value.has_semantic_links,
141 link_rel: value.link_rel,
142 link_target: value.link_target,
143 links_to_ref: value.links_to_ref,
144 }
145 }
146}
147
148impl From<MemoryFilter> for MemoryFilterDto {
149 fn from(value: MemoryFilter) -> Self {
150 Self {
151 has_embedding: value.has_embedding,
152 embedding_model: value.embedding_model,
153 psi: value.psi,
154 rho: value.rho,
155 kappa: value.kappa,
156 text_contains: value.text_contains,
157 tags_contains: value.tags_contains,
158 has_tag: value.has_tag,
159 indexed_tags: value.indexed_tags,
160 tag_prefix: value.tag_prefix,
161 has_semantic_links: value.has_semantic_links,
162 link_rel: value.link_rel,
163 link_target: value.link_target,
164 links_to_ref: value.links_to_ref,
165 }
166 }
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize)]
170#[serde(rename_all = "camelCase")]
171pub struct MemoryPageDto {
172 pub limit: usize,
173 pub cursor: Option<String>,
174}
175
176impl From<MemoryPageDto> for MemoryPage {
177 fn from(value: MemoryPageDto) -> Self {
178 Self {
179 limit: value.limit,
180 cursor: value.cursor,
181 }
182 }
183}
184
185impl From<MemoryPage> for MemoryPageDto {
186 fn from(value: MemoryPage) -> Self {
187 Self {
188 limit: value.limit,
189 cursor: value.cursor,
190 }
191 }
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
195#[serde(rename_all = "camelCase")]
196pub struct MemoryScoringDto {
197 pub resonance_weight: f32,
198 pub semantic_weight: f32,
199 pub lexical_weight: f32,
200 pub alpha: f32,
201 pub beta: f32,
202 #[serde(default)]
203 pub gamma: f32,
204 pub fallback_policy: FallbackPolicy,
205 pub strictness: StrictnessMode,
206}
207
208impl From<MemoryScoringDto> for MemoryScoring {
209 fn from(value: MemoryScoringDto) -> Self {
210 Self {
211 resonance_weight: value.resonance_weight,
212 semantic_weight: value.semantic_weight,
213 lexical_weight: value.lexical_weight,
214 alpha: value.alpha,
215 beta: value.beta,
216 gamma: value.gamma,
217 fallback_policy: value.fallback_policy,
218 strictness: value.strictness,
219 }
220 }
221}
222
223impl From<MemoryScoring> for MemoryScoringDto {
224 fn from(value: MemoryScoring) -> Self {
225 Self {
226 resonance_weight: value.resonance_weight,
227 semantic_weight: value.semantic_weight,
228 lexical_weight: value.lexical_weight,
229 alpha: value.alpha,
230 beta: value.beta,
231 gamma: value.gamma,
232 fallback_policy: value.fallback_policy,
233 strictness: value.strictness,
234 }
235 }
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize)]
239#[serde(rename_all = "camelCase")]
240pub struct MemoryFindRequestDto {
241 pub scope: MemoryScopeDto,
242 pub filter: MemoryFilterDto,
243 pub page: MemoryPageDto,
244 pub sort: MemorySort,
245}
246
247impl From<MemoryFindRequestDto> for MemoryFindRequest {
248 fn from(value: MemoryFindRequestDto) -> Self {
249 Self {
250 scope: value.scope.into(),
251 filter: value.filter.into(),
252 page: value.page.into(),
253 sort: value.sort,
254 }
255 }
256}
257
258#[derive(Debug, Clone, Serialize, Deserialize)]
259#[serde(rename_all = "camelCase")]
260pub struct MemoryRecallRequestDto {
261 pub scope: MemoryScopeDto,
262 pub filter: MemoryFilterDto,
263 pub page: MemoryPageDto,
264 pub scoring: MemoryScoringDto,
265 pub current_avec: Option<AvecStateDto>,
266 pub query_text: Option<String>,
267 pub query_embedding: Option<Vec<f32>>,
268 pub query_tag_embedding: Option<Vec<f32>>,
269}
270
271impl From<MemoryRecallRequestDto> for MemoryRecallRequest {
272 fn from(value: MemoryRecallRequestDto) -> Self {
273 Self {
274 scope: value.scope.into(),
275 filter: value.filter.into(),
276 page: value.page.into(),
277 scoring: value.scoring.into(),
278 current_avec: value.current_avec.map(Into::into),
279 query_text: value.query_text,
280 query_embedding: value.query_embedding,
281 query_tag_embedding: value.query_tag_embedding,
282 }
283 }
284}
285
286#[derive(Debug, Clone, Serialize)]
287#[serde(rename_all = "camelCase")]
288pub struct MemoryNodeDto {
289 pub raw: String,
290 pub session_id: String,
291 pub tier: String,
292 pub timestamp: DateTime<Utc>,
293 pub compression_depth: i32,
294 pub parent_node_id: Option<String>,
295 pub sync_key: String,
296 pub context_summary: Option<String>,
297 pub embedding_model: Option<String>,
298 pub embedding_dimensions: Option<usize>,
299 pub embedded_at: Option<DateTime<Utc>>,
300 pub rho: f32,
301 pub kappa: f32,
302 pub psi: f32,
303 pub user_avec: AvecStateDto,
304 pub model_avec: AvecStateDto,
305 pub compression_avec: Option<AvecStateDto>,
306 pub updated_at: DateTime<Utc>,
307}
308
309impl From<SttpNode> for MemoryNodeDto {
310 fn from(value: SttpNode) -> Self {
311 Self {
312 raw: value.raw,
313 session_id: value.session_id,
314 tier: value.tier,
315 timestamp: value.timestamp,
316 compression_depth: value.compression_depth,
317 parent_node_id: value.parent_node_id,
318 sync_key: value.sync_key,
319 context_summary: value.context_summary,
320 embedding_model: value.embedding_model,
321 embedding_dimensions: value.embedding_dimensions,
322 embedded_at: value.embedded_at,
323 rho: value.rho,
324 kappa: value.kappa,
325 psi: value.psi,
326 user_avec: value.user_avec.into(),
327 model_avec: value.model_avec.into(),
328 compression_avec: value.compression_avec.map(Into::into),
329 updated_at: value.updated_at,
330 }
331 }
332}
333
334#[derive(Debug, Clone, Serialize)]
335#[serde(rename_all = "camelCase")]
336pub struct MemoryFindResponseDto {
337 pub nodes: Vec<MemoryNodeDto>,
338 pub retrieved: usize,
339 pub has_more: bool,
340 pub next_cursor: Option<String>,
341}
342
343impl From<MemoryFindResult> for MemoryFindResponseDto {
344 fn from(value: MemoryFindResult) -> Self {
345 Self {
346 nodes: value.nodes.into_iter().map(Into::into).collect(),
347 retrieved: value.retrieved,
348 has_more: value.has_more,
349 next_cursor: value.next_cursor,
350 }
351 }
352}
353
354#[derive(Debug, Clone, Serialize)]
355#[serde(rename_all = "camelCase")]
356pub struct MemoryRecallResponseDto {
357 pub nodes: Vec<MemoryNodeDto>,
358 pub retrieved: usize,
359 pub psi_range: PsiRangeDto,
360 pub retrieval_path: RetrievalPath,
361 pub has_more: bool,
362 pub next_cursor: Option<String>,
363}
364
365impl From<MemoryRecallResult> for MemoryRecallResponseDto {
366 fn from(value: MemoryRecallResult) -> Self {
367 Self {
368 nodes: value.nodes.into_iter().map(Into::into).collect(),
369 retrieved: value.retrieved,
370 psi_range: value.psi_range.into(),
371 retrieval_path: value.retrieval_path,
372 has_more: value.has_more,
373 next_cursor: value.next_cursor,
374 }
375 }
376}
377
378#[derive(Debug, Clone, Serialize, Deserialize)]
379#[serde(rename_all = "camelCase")]
380pub struct NumericStatsDto {
381 pub min: f32,
382 pub max: f32,
383 pub average: f32,
384}
385
386impl From<NumericStats> for NumericStatsDto {
387 fn from(value: NumericStats) -> Self {
388 Self {
389 min: value.min,
390 max: value.max,
391 average: value.average,
392 }
393 }
394}
395
396#[derive(Debug, Clone, Serialize, Deserialize)]
397#[serde(rename_all = "camelCase")]
398pub struct MemoryAggregateRequestDto {
399 pub scope: MemoryScopeDto,
400 pub filter: MemoryFilterDto,
401 pub group_by: MemoryGroupBy,
402 pub max_groups: usize,
403 pub max_nodes: usize,
404}
405
406impl From<MemoryAggregateRequestDto> for MemoryAggregateRequest {
407 fn from(value: MemoryAggregateRequestDto) -> Self {
408 Self {
409 scope: value.scope.into(),
410 filter: value.filter.into(),
411 group_by: value.group_by,
412 max_groups: value.max_groups,
413 max_nodes: value.max_nodes,
414 }
415 }
416}
417
418#[derive(Debug, Clone, Serialize)]
419#[serde(rename_all = "camelCase")]
420pub struct MemoryAggregateGroupDto {
421 pub key: String,
422 pub node_count: usize,
423 pub embedding_coverage: f32,
424 pub avg_user_avec: AvecStateDto,
425 pub avg_model_avec: AvecStateDto,
426 pub avg_compression_avec: Option<AvecStateDto>,
427 pub psi_stats: NumericStatsDto,
428 pub rho_stats: NumericStatsDto,
429 pub kappa_stats: NumericStatsDto,
430}
431
432#[derive(Debug, Clone, Serialize)]
433#[serde(rename_all = "camelCase")]
434pub struct MemoryAggregateResponseDto {
435 pub groups: Vec<MemoryAggregateGroupDto>,
436 pub total_groups: usize,
437 pub scanned_nodes: usize,
438}
439
440impl From<MemoryAggregateResult> for MemoryAggregateResponseDto {
441 fn from(value: MemoryAggregateResult) -> Self {
442 Self {
443 groups: value
444 .groups
445 .into_iter()
446 .map(|group| MemoryAggregateGroupDto {
447 key: group.key,
448 node_count: group.node_count,
449 embedding_coverage: group.embedding_coverage,
450 avg_user_avec: group.avg_user_avec.into(),
451 avg_model_avec: group.avg_model_avec.into(),
452 avg_compression_avec: group.avg_compression_avec.map(Into::into),
453 psi_stats: group.psi_stats.into(),
454 rho_stats: group.rho_stats.into(),
455 kappa_stats: group.kappa_stats.into(),
456 })
457 .collect(),
458 total_groups: value.total_groups,
459 scanned_nodes: value.scanned_nodes,
460 }
461 }
462}
463
464#[derive(Debug, Clone, Serialize, Deserialize)]
465#[serde(rename_all = "camelCase")]
466pub struct MemoryTransformRequestDto {
467 pub scope: MemoryScopeDto,
468 pub filter: MemoryFilterDto,
469 pub operation: MemoryTransformOperation,
470 pub dry_run: bool,
471 pub batch_size: usize,
472 pub max_nodes: usize,
473 pub provider_id: Option<String>,
474 pub model: Option<String>,
475}
476
477impl From<MemoryTransformRequestDto> for MemoryTransformRequest {
478 fn from(value: MemoryTransformRequestDto) -> Self {
479 Self {
480 scope: value.scope.into(),
481 filter: value.filter.into(),
482 operation: value.operation,
483 dry_run: value.dry_run,
484 batch_size: value.batch_size,
485 max_nodes: value.max_nodes,
486 provider_id: value.provider_id,
487 model: value.model,
488 }
489 }
490}
491
492#[derive(Debug, Clone, Serialize)]
493#[serde(rename_all = "camelCase")]
494pub struct MemoryTransformResponseDto {
495 pub scanned: usize,
496 pub selected: usize,
497 pub updated: usize,
498 pub skipped: usize,
499 pub failed: usize,
500 pub duplicate: usize,
501 pub started_at: DateTime<Utc>,
502 pub completed_at: DateTime<Utc>,
503 pub failures: Vec<String>,
504}
505
506impl From<MemoryTransformResult> for MemoryTransformResponseDto {
507 fn from(value: MemoryTransformResult) -> Self {
508 Self {
509 scanned: value.scanned,
510 selected: value.selected,
511 updated: value.updated,
512 skipped: value.skipped,
513 failed: value.failed,
514 duplicate: value.duplicate,
515 started_at: value.started_at,
516 completed_at: value.completed_at,
517 failures: value.failures,
518 }
519 }
520}
521
522#[derive(Debug, Clone, Serialize, Deserialize)]
523#[serde(rename_all = "camelCase")]
524pub struct MemoryDailyRollupRequestDto {
525 pub scope: MemoryScopeDto,
526 pub filter: MemoryFilterDto,
527 pub max_days: usize,
528 pub max_nodes: usize,
529}
530
531impl From<MemoryDailyRollupRequestDto> for MemoryDailyRollupRequest {
532 fn from(value: MemoryDailyRollupRequestDto) -> Self {
533 Self {
534 scope: value.scope.into(),
535 filter: value.filter.into(),
536 max_days: value.max_days,
537 max_nodes: value.max_nodes,
538 }
539 }
540}
541
542#[derive(Debug, Clone, Serialize)]
543#[serde(rename_all = "camelCase")]
544pub struct MemoryRecallWithExplainResponseDto {
545 pub recall: MemoryRecallResponseDto,
546 pub explain: MemoryExplainResponseDto,
547}
548
549impl From<MemoryRecallWithExplainResult> for MemoryRecallWithExplainResponseDto {
550 fn from(value: MemoryRecallWithExplainResult) -> Self {
551 Self {
552 recall: value.recall.into(),
553 explain: value.explain.into(),
554 }
555 }
556}
557
558#[derive(Debug, Clone, Serialize, Deserialize)]
559#[serde(rename_all = "camelCase")]
560pub struct MemoryTransformThenRecallRequestDto {
561 pub transform: MemoryTransformRequestDto,
562 pub recall: MemoryRecallRequestDto,
563}
564
565impl From<MemoryTransformThenRecallRequestDto> for MemoryTransformThenRecallRequest {
566 fn from(value: MemoryTransformThenRecallRequestDto) -> Self {
567 Self {
568 transform: value.transform.into(),
569 recall: value.recall.into(),
570 }
571 }
572}
573
574#[derive(Debug, Clone, Serialize)]
575#[serde(rename_all = "camelCase")]
576pub struct MemoryTransformThenRecallResponseDto {
577 pub transform: MemoryTransformResponseDto,
578 pub recall: MemoryRecallResponseDto,
579}
580
581impl From<MemoryTransformThenRecallResult> for MemoryTransformThenRecallResponseDto {
582 fn from(value: MemoryTransformThenRecallResult) -> Self {
583 Self {
584 transform: value.transform.into(),
585 recall: value.recall.into(),
586 }
587 }
588}
589
590#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
591#[serde(rename_all = "snake_case")]
592pub enum CompositeRoleDto {
593 User,
594 Model,
595 Document,
596 Conversation,
597}
598
599impl From<CompositeRoleDto> for CompositeRole {
600 fn from(value: CompositeRoleDto) -> Self {
601 match value {
602 CompositeRoleDto::User => CompositeRole::User,
603 CompositeRoleDto::Model => CompositeRole::Model,
604 CompositeRoleDto::Document => CompositeRole::Document,
605 CompositeRoleDto::Conversation => CompositeRole::Conversation,
606 }
607 }
608}
609
610impl From<CompositeRole> for CompositeRoleDto {
611 fn from(value: CompositeRole) -> Self {
612 match value {
613 CompositeRole::User => CompositeRoleDto::User,
614 CompositeRole::Model => CompositeRoleDto::Model,
615 CompositeRole::Document => CompositeRoleDto::Document,
616 CompositeRole::Conversation => CompositeRoleDto::Conversation,
617 }
618 }
619}
620
621#[derive(Debug, Clone, Serialize, Deserialize)]
622#[serde(rename_all = "camelCase")]
623pub struct CompositeInputItemDto {
624 pub role: CompositeRoleDto,
625 pub text: String,
626 pub avec_override: Option<AvecStateDto>,
627 #[serde(default)]
628 pub context: Vec<CompositeInputItemDto>,
629}
630
631impl From<CompositeInputItemDto> for CompositeInputItem {
632 fn from(value: CompositeInputItemDto) -> Self {
633 Self {
634 role: value.role.into(),
635 text: value.text,
636 avec_override: value.avec_override.map(Into::into),
637 context: value.context.into_iter().map(Into::into).collect(),
638 }
639 }
640}
641
642impl From<CompositeInputItem> for CompositeInputItemDto {
643 fn from(value: CompositeInputItem) -> Self {
644 Self {
645 role: value.role.into(),
646 text: value.text,
647 avec_override: value.avec_override.map(Into::into),
648 context: value.context.into_iter().map(Into::into).collect(),
649 }
650 }
651}
652
653#[derive(Debug, Clone, Default, Serialize, Deserialize)]
654#[serde(rename_all = "camelCase")]
655pub struct CompositeRoleAvecOverridesDto {
656 pub user: Option<AvecStateDto>,
657 pub model: Option<AvecStateDto>,
658 pub document: Option<AvecStateDto>,
659 pub conversation: Option<AvecStateDto>,
660}
661
662impl From<CompositeRoleAvecOverridesDto> for CompositeRoleAvecOverrides {
663 fn from(value: CompositeRoleAvecOverridesDto) -> Self {
664 Self {
665 user: value.user.map(Into::into),
666 model: value.model.map(Into::into),
667 document: value.document.map(Into::into),
668 conversation: value.conversation.map(Into::into),
669 }
670 }
671}
672
673impl From<CompositeRoleAvecOverrides> for CompositeRoleAvecOverridesDto {
674 fn from(value: CompositeRoleAvecOverrides) -> Self {
675 Self {
676 user: value.user.map(Into::into),
677 model: value.model.map(Into::into),
678 document: value.document.map(Into::into),
679 conversation: value.conversation.map(Into::into),
680 }
681 }
682}
683
684#[derive(Debug, Clone, Serialize, Deserialize)]
685#[serde(rename_all = "camelCase")]
686pub struct CompositeNodeFromTextOptionsDto {
687 pub role_avec: CompositeRoleAvecOverridesDto,
688 pub global_avec: Option<AvecStateDto>,
689 pub allow_llm_avec_fallback: bool,
690 pub max_recursion_depth: usize,
691}
692
693impl From<CompositeNodeFromTextOptionsDto> for CompositeNodeFromTextOptions {
694 fn from(value: CompositeNodeFromTextOptionsDto) -> Self {
695 Self {
696 role_avec: value.role_avec.into(),
697 global_avec: value.global_avec.map(Into::into),
698 allow_llm_avec_fallback: value.allow_llm_avec_fallback,
699 max_recursion_depth: value.max_recursion_depth,
700 }
701 }
702}
703
704impl From<CompositeNodeFromTextOptions> for CompositeNodeFromTextOptionsDto {
705 fn from(value: CompositeNodeFromTextOptions) -> Self {
706 Self {
707 role_avec: value.role_avec.into(),
708 global_avec: value.global_avec.map(Into::into),
709 allow_llm_avec_fallback: value.allow_llm_avec_fallback,
710 max_recursion_depth: value.max_recursion_depth,
711 }
712 }
713}
714
715#[derive(Debug, Clone, Serialize, Deserialize)]
716#[serde(rename_all = "camelCase")]
717pub struct CompositeNodeFromTextRequestDto {
718 pub items: Vec<CompositeInputItemDto>,
719 pub options: CompositeNodeFromTextOptionsDto,
720}
721
722impl From<CompositeNodeFromTextRequestDto> for CompositeNodeFromTextRequest {
723 fn from(value: CompositeNodeFromTextRequestDto) -> Self {
724 Self {
725 items: value.items.into_iter().map(Into::into).collect(),
726 options: value.options.into(),
727 }
728 }
729}
730
731#[derive(Debug, Clone, Serialize)]
732#[serde(rename_all = "camelCase")]
733pub struct CompositeNodeFromTextResponseDto {
734 pub content: Value,
735 pub resolved_avec_count: usize,
736 pub unresolved_avec_count: usize,
737 pub requires_llm_avec: bool,
738}
739
740impl From<CompositeNodeFromTextResult> for CompositeNodeFromTextResponseDto {
741 fn from(value: CompositeNodeFromTextResult) -> Self {
742 Self {
743 content: value.content,
744 resolved_avec_count: value.resolved_avec_count,
745 unresolved_avec_count: value.unresolved_avec_count,
746 requires_llm_avec: value.requires_llm_avec,
747 }
748 }
749}
750
751#[derive(Debug, Clone, Serialize, Deserialize)]
752#[serde(rename_all = "camelCase")]
753pub struct MemoryExplainRequestDto {
754 pub recall: MemoryRecallRequestDto,
755}
756
757impl From<MemoryExplainRequestDto> for MemoryExplainRequest {
758 fn from(value: MemoryExplainRequestDto) -> Self {
759 Self {
760 recall: value.recall.into(),
761 }
762 }
763}
764
765#[derive(Debug, Clone, Serialize)]
766#[serde(rename_all = "camelCase")]
767pub struct MemoryExplainStageDto {
768 pub stage: String,
769 pub count: usize,
770}
771
772#[derive(Debug, Clone, Serialize)]
773#[serde(rename_all = "camelCase")]
774pub struct MemoryExplainResponseDto {
775 pub retrieval_path: RetrievalPath,
776 pub fallback_triggered: bool,
777 pub fallback_reason: Option<String>,
778 pub stages: Vec<MemoryExplainStageDto>,
779 pub scoring: MemoryScoringDto,
780}
781
782impl From<MemoryExplainResult> for MemoryExplainResponseDto {
783 fn from(value: MemoryExplainResult) -> Self {
784 Self {
785 retrieval_path: value.retrieval_path,
786 fallback_triggered: value.fallback_triggered,
787 fallback_reason: value.fallback_reason,
788 stages: value
789 .stages
790 .into_iter()
791 .map(|stage| MemoryExplainStageDto {
792 stage: stage.stage,
793 count: stage.count,
794 })
795 .collect(),
796 scoring: value.scoring.into(),
797 }
798 }
799}
800
801#[derive(Debug, Clone, Serialize)]
802#[serde(rename_all = "camelCase")]
803pub struct MemorySchemaResponseDto {
804 pub schema_version: String,
805 pub sort_fields: Vec<String>,
806 pub filter_fields: Vec<String>,
807 pub group_by_fields: Vec<String>,
808 pub fallback_policies: Vec<String>,
809 pub strictness_modes: Vec<String>,
810 pub transform_operations: Vec<String>,
811 pub evict_operations: Vec<String>,
812 pub reflex_actions: Vec<String>,
813 pub decision_types: Vec<String>,
814}
815
816impl From<MemorySchemaResult> for MemorySchemaResponseDto {
817 fn from(value: MemorySchemaResult) -> Self {
818 Self {
819 schema_version: value.schema_version,
820 sort_fields: value.sort_fields,
821 filter_fields: value.filter_fields,
822 group_by_fields: value.group_by_fields,
823 fallback_policies: value.fallback_policies,
824 strictness_modes: value.strictness_modes,
825 transform_operations: value.transform_operations,
826 evict_operations: value.evict_operations,
827 reflex_actions: value.reflex_actions,
828 decision_types: value.decision_types,
829 }
830 }
831}
832
833impl From<MemoryRecallRequest> for MemoryRecallRequestDto {
834 fn from(value: MemoryRecallRequest) -> Self {
835 Self {
836 scope: value.scope.into(),
837 filter: value.filter.into(),
838 page: value.page.into(),
839 scoring: value.scoring.into(),
840 current_avec: value.current_avec.map(Into::into),
841 query_text: value.query_text,
842 query_embedding: value.query_embedding,
843 query_tag_embedding: value.query_tag_embedding,
844 }
845 }
846}
847
848impl From<MemoryFindRequest> for MemoryFindRequestDto {
849 fn from(value: MemoryFindRequest) -> Self {
850 Self {
851 scope: value.scope.into(),
852 filter: value.filter.into(),
853 page: value.page.into(),
854 sort: value.sort,
855 }
856 }
857}
858
859impl From<MemoryAggregateRequest> for MemoryAggregateRequestDto {
860 fn from(value: MemoryAggregateRequest) -> Self {
861 Self {
862 scope: value.scope.into(),
863 filter: value.filter.into(),
864 group_by: value.group_by,
865 max_groups: value.max_groups,
866 max_nodes: value.max_nodes,
867 }
868 }
869}
870
871#[derive(Debug, Clone, Serialize, Deserialize)]
873#[serde(rename_all = "camelCase")]
874pub struct MemoryReflexResponseDto {
875 pub schema_version: String,
876 pub stimulus_id: String,
877 pub stimulus_text: String,
878 #[serde(default, skip_serializing_if = "Option::is_none")]
879 pub role: Option<String>,
880 pub scope: MemoryScopeDto,
881 pub kind: MemoryReflexKind,
882 pub action: MemoryAction,
883 pub topic: String,
884 pub salience: f32,
885 pub salience_label: String,
886 pub salience_confidence: f32,
887 pub confidence: f32,
888 pub propositions: MemoryPropositions,
889 pub gate: ReflexGate,
890 #[serde(default, skip_serializing_if = "Vec::is_empty")]
891 pub companions: Vec<MemoryAction>,
892 #[serde(default, skip_serializing_if = "Option::is_none")]
893 pub recall: Option<MemoryRecallRequestDto>,
894 #[serde(default, skip_serializing_if = "Option::is_none")]
895 pub find: Option<MemoryFindRequestDto>,
896 #[serde(default, skip_serializing_if = "Option::is_none")]
897 pub aggregate: Option<MemoryAggregateRequestDto>,
898 #[serde(default, skip_serializing_if = "Option::is_none")]
899 pub persist: Option<MemoryPersistHint>,
900 pub decider_id: String,
901 #[serde(default, skip_serializing_if = "Option::is_none")]
902 pub checkpoint: Option<String>,
903 #[serde(default)]
904 pub metadata: serde_json::Map<String, Value>,
905}
906
907impl From<MemoryReflex> for MemoryReflexResponseDto {
908 fn from(value: MemoryReflex) -> Self {
909 Self {
910 schema_version: value.schema_version,
911 stimulus_id: value.stimulus_id,
912 stimulus_text: value.stimulus_text,
913 role: value.role,
914 scope: value.scope.into(),
915 kind: value.kind,
916 action: value.action,
917 topic: value.topic,
918 salience: value.salience,
919 salience_label: value.salience_label,
920 salience_confidence: value.salience_confidence,
921 confidence: value.confidence,
922 propositions: value.propositions,
923 gate: value.gate,
924 companions: value.companions,
925 recall: value.recall.map(Into::into),
926 find: value.find.map(Into::into),
927 aggregate: value.aggregate.map(Into::into),
928 persist: value.persist,
929 decider_id: value.decider_id,
930 checkpoint: value.checkpoint,
931 metadata: value.metadata,
932 }
933 }
934}