relay_knowledge/api/operations/
retrieval.rs1use serde::{Deserialize, Serialize};
2
3use crate::{
4 api::ApiMetadata,
5 domain::{
6 FreshnessPolicy, FusionDiagnostics, IndexStatus, RerankDiagnostics, RetrievalBackendStatus,
7 RetrievalBudgetUsed, RetrievalHit, RetrievalMode, RetrievedContextPack,
8 },
9 storage::{IndexCursor, IndexRefreshDiagnostics},
10};
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub struct HybridRetrievalRequest {
15 pub query: String,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub source_scope: Option<String>,
18 pub limit: usize,
19 pub freshness: FreshnessPolicy,
20}
21
22impl HybridRetrievalRequest {
23 pub fn new(query: impl Into<String>) -> Self {
25 Self {
26 query: query.into(),
27 source_scope: None,
28 limit: 10,
29 freshness: FreshnessPolicy::default(),
30 }
31 }
32}
33
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
36pub struct HybridRetrievalResponse {
37 pub metadata: ApiMetadata,
38 pub context_pack: RetrievedContextPack,
39 pub retrieval_mode: RetrievalMode,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub source_scope: Option<String>,
42 pub freshness: FreshnessPolicy,
43 pub results: Vec<RetrievalHit>,
44 pub fusion: FusionDiagnostics,
45 pub rerank: RerankDiagnostics,
46 #[serde(default, skip_serializing_if = "Vec::is_empty")]
47 pub backend_statuses: Vec<RetrievalBackendStatus>,
48 pub truncated: bool,
49 pub budget_used: RetrievalBudgetUsed,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub degraded_reason: Option<String>,
52 pub indexes: Vec<IndexStatus>,
53 #[serde(default)]
54 pub index_cursors: Vec<IndexCursor>,
55 #[serde(default)]
56 pub index_refresh: IndexRefreshDiagnostics,
57}
58
59#[cfg(test)]
60#[path = "retrieval_tests.rs"]
61mod tests;