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