1#[derive(Debug, Clone, Default)]
2pub struct SearchRequest {
3 pub query: Option<String>,
4 pub project: Option<String>,
5 pub memory_type: Option<String>,
6 pub limit: i64,
7 pub offset: i64,
8 pub include_stale: bool,
9 pub include_suppressed: bool,
10 pub branch: Option<String>,
11 pub multi_hop: bool,
12 pub explain: bool,
13}
14
15#[derive(Debug, Clone)]
16pub struct SearchRoutingPolicy {
17 pub plan_hash: String,
18 pub policy_version: String,
19 pub rerank_enabled: bool,
20 pub rerank_candidate_pool: u32,
21 pub rerank_output_k: u32,
22 pub use_multi_hop: bool,
23 pub raw_fallback_enabled: bool,
24 pub weights: SearchRoutingWeights,
25}
26
27#[derive(Debug, Clone, Copy)]
28pub struct SearchRoutingWeights {
29 pub fts: f64,
30 pub vector: f64,
31 pub entity: f64,
32 pub graph: f64,
33 pub temporal: f64,
34 pub fact: f64,
35 pub like_fallback: f64,
36 pub usage: f64,
37}
38
39impl SearchRoutingPolicy {
40 pub fn from_retrieval_plan(plan: &crate::retrieval_router::RetrievalPlan) -> Self {
41 let weight = |channel| channel_weight(plan, channel);
42 let temporal = weight(crate::retrieval_router::RetrievalChannel::Temporal);
43 Self {
44 plan_hash: plan.plan_hash.clone(),
45 policy_version: plan.policy_version.clone(),
46 rerank_enabled: plan.rerank_policy.enabled,
47 rerank_candidate_pool: plan.rerank_policy.candidate_pool,
48 rerank_output_k: plan.rerank_policy.output_k,
49 use_multi_hop: channel_enabled(
50 plan,
51 crate::retrieval_router::RetrievalChannel::GraphExpansion,
52 ),
53 raw_fallback_enabled: plan.abstention_policy.mode
54 != crate::retrieval_router::AbstentionMode::OnLowEvidence,
55 weights: SearchRoutingWeights {
56 fts: weight(crate::retrieval_router::RetrievalChannel::CanonicalFts),
57 vector: weight(crate::retrieval_router::RetrievalChannel::CanonicalVector),
58 entity: weight(crate::retrieval_router::RetrievalChannel::EntityGraph),
59 graph: weight(crate::retrieval_router::RetrievalChannel::GraphExpansion),
60 temporal,
61 fact: temporal,
64 like_fallback: if channel_enabled(
66 plan,
67 crate::retrieval_router::RetrievalChannel::CanonicalFts,
68 ) {
69 0.25
70 } else {
71 0.0
72 },
73 usage: 0.0,
76 },
77 }
78 }
79}
80
81fn channel_enabled(
82 plan: &crate::retrieval_router::RetrievalPlan,
83 channel: crate::retrieval_router::RetrievalChannel,
84) -> bool {
85 plan.channel_plans
86 .iter()
87 .any(|plan| plan.channel == channel && plan.enabled)
88}
89
90fn channel_weight(
91 plan: &crate::retrieval_router::RetrievalPlan,
92 channel: crate::retrieval_router::RetrievalChannel,
93) -> f64 {
94 plan.channel_plans
95 .iter()
96 .find(|plan| plan.channel == channel && plan.enabled)
97 .map(|plan| plan.weight)
98 .unwrap_or(0.0)
99}
100
101pub fn default_include_stale() -> bool {
106 false
107}
108
109pub fn default_include_suppressed() -> bool {
111 false
112}
113
114#[derive(Debug, Clone)]
115pub struct MultiHopMeta {
116 pub hops: u8,
117 pub entities_discovered: Vec<String>,
118}
119
120#[derive(Debug, Clone)]
121pub struct SearchResultSet {
122 pub memories: Vec<crate::memory::Memory>,
123 pub multi_hop: Option<MultiHopMeta>,
124 pub has_more: bool,
125 pub explain: Option<crate::retrieval::search::SearchExplain>,
126 pub raw_hits: Vec<crate::memory::raw_archive::RawMessage>,
128 pub raw_error: Option<String>,
130}
131
132#[derive(Debug, Clone)]
133pub(crate) struct SearchResultSetWithExplainDetails {
134 pub result: SearchResultSet,
135 pub explain_details: Option<crate::retrieval::search::SearchExplainDetails>,
136}
137
138#[derive(Debug, Clone, Default)]
139pub struct SaveMemoryRequest {
140 pub text: String,
141 pub title: Option<String>,
142 pub project: Option<String>,
143 pub session_id: Option<String>,
144 pub host: Option<String>,
145 pub topic_key: Option<String>,
146 pub memory_type: Option<String>,
147 pub files: Option<Vec<String>>,
148 pub scope: Option<String>,
149 pub created_at_epoch: Option<i64>,
150 pub branch: Option<String>,
151 pub local_path: Option<String>,
152 pub local_copy_enabled: Option<bool>,
153 pub claim_enabled: Option<bool>,
154 pub claim_source: Option<String>,
155 pub acknowledge_pattern: Option<String>,
156 pub idempotency_key: Option<String>,
159}
160
161#[derive(Debug, Clone)]
162pub struct LocalCopyResult {
163 pub status: String,
164 pub path: Option<String>,
165 pub reason: Option<String>,
166}
167
168#[derive(Debug, Clone)]
169pub struct SaveMemoryNextStep {
170 pub tool: String,
171 pub ids: Vec<i64>,
172 pub source: String,
173 pub reason: String,
174}
175
176#[derive(Debug, Clone)]
177pub struct SaveMemoryResult {
178 pub id: i64,
179 pub status: String,
180 pub memory_type: String,
181 pub project: String,
182 pub scope: String,
183 pub topic_key: Option<String>,
184 pub branch: Option<String>,
185 pub operation: String,
186 pub created_at_epoch: i64,
187 pub reference_time_epoch: i64,
188 pub updated_at_epoch: i64,
189 pub upserted: bool,
192 pub local_copy: LocalCopyResult,
193 pub local_status: String,
194 pub local_path: Option<String>,
195 pub claim_status: String,
196 pub claim_id: Option<i64>,
197 pub claim_error: Option<String>,
198 pub next_step: SaveMemoryNextStep,
199}