Skip to main content

locus_gateway/
http_models.rs

1use axum::Json;
2use axum::http::HeaderValue;
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Serialize)]
7#[serde(rename_all = "camelCase")]
8pub(crate) struct ErrorResponse {
9    pub(crate) error: String,
10}
11
12#[derive(Debug, Deserialize)]
13#[serde(rename_all = "camelCase")]
14pub(crate) struct CalibrateSessionHttpRequest {
15    pub(crate) session_id: String,
16    pub(crate) tenant_id: Option<String>,
17    pub(crate) stability: f32,
18    pub(crate) friction: f32,
19    pub(crate) logic: f32,
20    pub(crate) autonomy: f32,
21    pub(crate) trigger: Option<String>,
22}
23
24#[derive(Debug, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub(crate) struct StoreContextHttpRequest {
27    pub(crate) node: String,
28    pub(crate) session_id: String,
29    pub(crate) tenant_id: Option<String>,
30}
31
32#[derive(Debug, Deserialize)]
33#[serde(rename_all = "camelCase")]
34pub(crate) struct ScoreAvecHttpRequest {
35    pub(crate) text: String,
36    pub(crate) tenant_id: Option<String>,
37}
38
39#[derive(Debug, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub(crate) struct GetContextHttpRequest {
42    pub(crate) session_id: String,
43    pub(crate) tenant_id: Option<String>,
44    pub(crate) stability: f32,
45    pub(crate) friction: f32,
46    pub(crate) logic: f32,
47    pub(crate) autonomy: f32,
48    pub(crate) limit: Option<usize>,
49    pub(crate) from_utc: Option<DateTime<Utc>>,
50    pub(crate) to_utc: Option<DateTime<Utc>>,
51    pub(crate) tiers: Option<Vec<String>>,
52    pub(crate) query_text: Option<String>,
53    pub(crate) query_embedding: Option<Vec<f32>>,
54    pub(crate) alpha: Option<f32>,
55    pub(crate) beta: Option<f32>,
56}
57
58#[derive(Debug, Deserialize)]
59#[serde(rename_all = "camelCase")]
60pub(crate) struct GetEmbeddingContextHttpRequest {
61    pub(crate) session_id: String,
62    pub(crate) tenant_id: Option<String>,
63    pub(crate) stability: f32,
64    pub(crate) friction: f32,
65    pub(crate) logic: f32,
66    pub(crate) autonomy: f32,
67    pub(crate) limit: Option<usize>,
68    pub(crate) from_utc: Option<DateTime<Utc>>,
69    pub(crate) to_utc: Option<DateTime<Utc>>,
70    pub(crate) tiers: Option<Vec<String>>,
71    pub(crate) rag_query_text: Option<String>,
72    pub(crate) rag_embedding: Option<Vec<f32>>,
73    pub(crate) avec_query_text: Option<String>,
74    pub(crate) avec_embedding: Option<Vec<f32>>,
75    pub(crate) rag_weight: Option<f32>,
76    pub(crate) avec_weight: Option<f32>,
77    pub(crate) alpha: Option<f32>,
78    pub(crate) beta: Option<f32>,
79}
80
81#[derive(Debug, Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub(crate) struct CreateMonthlyRollupHttpRequest {
84    pub(crate) session_id: String,
85    pub(crate) tenant_id: Option<String>,
86    pub(crate) start_date_utc: DateTime<Utc>,
87    pub(crate) end_date_utc: DateTime<Utc>,
88    pub(crate) source_session_id: Option<String>,
89    pub(crate) parent_node_id: Option<String>,
90    pub(crate) persist: Option<bool>,
91    pub(crate) limit: Option<usize>,
92}
93
94#[derive(Debug, Deserialize)]
95#[serde(rename_all = "camelCase")]
96pub(crate) struct BatchRekeyHttpRequest {
97    pub(crate) node_ids: Vec<String>,
98    pub(crate) target_session_id: String,
99    pub(crate) target_tenant_id: Option<String>,
100    pub(crate) dry_run: Option<bool>,
101    pub(crate) allow_merge: Option<bool>,
102}
103
104#[derive(Debug, Deserialize)]
105#[serde(rename_all = "camelCase")]
106pub(crate) struct EmbeddingMigrationFilterHttp {
107    pub(crate) session_id: Option<String>,
108    pub(crate) from_utc: Option<DateTime<Utc>>,
109    pub(crate) to_utc: Option<DateTime<Utc>>,
110    pub(crate) tiers: Option<Vec<String>>,
111    pub(crate) has_embedding: Option<bool>,
112    pub(crate) embedding_model: Option<String>,
113    pub(crate) sync_keys: Option<Vec<String>>,
114}
115
116#[derive(Debug, Deserialize)]
117#[serde(rename_all = "snake_case")]
118pub(crate) enum EmbeddingMigrationModeHttp {
119    MissingOnly,
120    ReindexAll,
121}
122
123#[derive(Debug, Deserialize)]
124#[serde(rename_all = "camelCase")]
125pub(crate) struct EmbeddingMigrationPreviewHttpRequest {
126    pub(crate) tenant_id: Option<String>,
127    pub(crate) filter: Option<EmbeddingMigrationFilterHttp>,
128    pub(crate) sample_limit: Option<usize>,
129    pub(crate) max_nodes: Option<usize>,
130}
131
132#[derive(Debug, Deserialize)]
133#[serde(rename_all = "camelCase")]
134pub(crate) struct EmbeddingMigrationRunHttpRequest {
135    pub(crate) tenant_id: Option<String>,
136    pub(crate) filter: Option<EmbeddingMigrationFilterHttp>,
137    pub(crate) mode: Option<EmbeddingMigrationModeHttp>,
138    pub(crate) dry_run: Option<bool>,
139    pub(crate) batch_size: Option<usize>,
140    pub(crate) max_nodes: Option<usize>,
141}
142
143#[derive(Debug, Deserialize)]
144#[serde(rename_all = "camelCase")]
145pub(crate) struct ListNodesQuery {
146    pub(crate) limit: Option<usize>,
147    pub(crate) session_id: Option<String>,
148    pub(crate) tenant_id: Option<String>,
149}
150
151#[derive(Debug, Deserialize)]
152#[serde(rename_all = "camelCase")]
153pub(crate) struct GetMoodsQuery {
154    pub(crate) target_mood: Option<String>,
155    pub(crate) blend: Option<f32>,
156    pub(crate) current_stability: Option<f32>,
157    pub(crate) current_friction: Option<f32>,
158    pub(crate) current_logic: Option<f32>,
159    pub(crate) current_autonomy: Option<f32>,
160}
161
162#[derive(Debug, Deserialize)]
163#[serde(rename_all = "camelCase")]
164pub(crate) struct GraphQuery {
165    pub(crate) limit: Option<usize>,
166    pub(crate) session_id: Option<String>,
167    pub(crate) tenant_id: Option<String>,
168}
169
170#[derive(Debug, Deserialize)]
171#[serde(rename_all = "camelCase")]
172pub(crate) struct RenameSessionHttpRequest {
173    pub(crate) source_session_id: String,
174    pub(crate) target_session_id: String,
175    pub(crate) tenant_id: Option<String>,
176    pub(crate) allow_merge: Option<bool>,
177}
178
179#[derive(Debug, Serialize)]
180#[serde(rename_all = "camelCase")]
181pub(crate) struct AvecStateDto {
182    pub(crate) stability: f32,
183    pub(crate) friction: f32,
184    pub(crate) logic: f32,
185    pub(crate) autonomy: f32,
186    pub(crate) psi: f32,
187}
188
189#[derive(Debug, Serialize)]
190#[serde(rename_all = "camelCase")]
191pub(crate) struct SttpNodeDto {
192    pub(crate) raw: String,
193    pub(crate) session_id: String,
194    pub(crate) tier: String,
195    pub(crate) timestamp: DateTime<Utc>,
196    pub(crate) compression_depth: i32,
197    pub(crate) parent_node_id: Option<String>,
198    pub(crate) user_avec: AvecStateDto,
199    pub(crate) model_avec: AvecStateDto,
200    pub(crate) compression_avec: Option<AvecStateDto>,
201    pub(crate) rho: f32,
202    pub(crate) kappa: f32,
203    pub(crate) psi: f32,
204    pub(crate) sync_key: String,
205    pub(crate) synthetic_id: String,
206}
207
208#[derive(Debug, Serialize)]
209#[serde(rename_all = "camelCase")]
210pub(crate) struct PsiRangeDto {
211    pub(crate) min: f32,
212    pub(crate) max: f32,
213    pub(crate) average: f32,
214}
215
216#[derive(Debug, Serialize)]
217#[serde(rename_all = "camelCase")]
218pub(crate) struct NumericRangeDto {
219    pub(crate) min: f32,
220    pub(crate) max: f32,
221    pub(crate) average: f32,
222}
223
224#[derive(Debug, Serialize)]
225#[serde(rename_all = "camelCase")]
226pub(crate) struct ConfidenceBandSummaryDto {
227    pub(crate) low: usize,
228    pub(crate) medium: usize,
229    pub(crate) high: usize,
230}
231
232#[derive(Debug, Serialize)]
233#[serde(rename_all = "camelCase")]
234pub(crate) struct CalibrationResultDto {
235    pub(crate) previous_avec: AvecStateDto,
236    pub(crate) delta: f32,
237    pub(crate) drift_classification: String,
238    pub(crate) trigger: String,
239    pub(crate) trigger_history: Vec<String>,
240    pub(crate) is_first_calibration: bool,
241}
242
243#[derive(Debug, Serialize)]
244#[serde(rename_all = "camelCase")]
245pub(crate) struct StoreResultDto {
246    pub(crate) node_id: String,
247    pub(crate) psi: f32,
248    pub(crate) valid: bool,
249    pub(crate) validation_error: Option<String>,
250    pub(crate) duplicate_skipped: bool,
251    pub(crate) upsert_status: String,
252}
253
254#[derive(Debug, Serialize)]
255#[serde(rename_all = "camelCase")]
256pub(crate) struct ScoreAvecResultDto {
257    pub(crate) provider: String,
258    pub(crate) model: String,
259    pub(crate) avec: AvecStateDto,
260}
261
262#[derive(Debug, Serialize)]
263#[serde(rename_all = "camelCase")]
264pub(crate) struct RenameSessionResultDto {
265    pub(crate) source_session_id: String,
266    pub(crate) target_session_id: String,
267    pub(crate) moved_nodes: usize,
268    pub(crate) moved_calibrations: usize,
269    pub(crate) scopes_applied: usize,
270}
271
272#[derive(Debug, Serialize)]
273#[serde(rename_all = "camelCase")]
274pub(crate) struct RetrieveResultDto {
275    pub(crate) nodes: Vec<SttpNodeDto>,
276    pub(crate) retrieved: usize,
277    pub(crate) psi_range: PsiRangeDto,
278}
279
280#[derive(Debug, Serialize)]
281#[serde(rename_all = "camelCase")]
282pub(crate) struct ListNodesResultDto {
283    pub(crate) nodes: Vec<SttpNodeDto>,
284    pub(crate) retrieved: usize,
285}
286
287#[derive(Debug, Serialize)]
288#[serde(rename_all = "camelCase")]
289pub(crate) struct MoodPresetDto {
290    pub(crate) name: String,
291    pub(crate) description: String,
292    pub(crate) avec: AvecStateDto,
293}
294
295#[derive(Debug, Serialize)]
296#[serde(rename_all = "camelCase")]
297pub(crate) struct MoodSwapPreviewDto {
298    pub(crate) target_mood: String,
299    pub(crate) blend: f32,
300    pub(crate) current: AvecStateDto,
301    pub(crate) target: AvecStateDto,
302    pub(crate) blended: AvecStateDto,
303}
304
305#[derive(Debug, Serialize)]
306#[serde(rename_all = "camelCase")]
307pub(crate) struct MoodCatalogResultDto {
308    pub(crate) presets: Vec<MoodPresetDto>,
309    pub(crate) apply_guide: String,
310    pub(crate) swap_preview: Option<MoodSwapPreviewDto>,
311}
312
313#[derive(Debug, Serialize)]
314#[serde(rename_all = "camelCase")]
315pub(crate) struct MonthlyRollupResultDto {
316    pub(crate) success: bool,
317    pub(crate) node_id: String,
318    pub(crate) raw_node: String,
319    pub(crate) error: Option<String>,
320    pub(crate) source_nodes: usize,
321    pub(crate) parent_reference: Option<String>,
322    pub(crate) user_average: AvecStateDto,
323    pub(crate) model_average: AvecStateDto,
324    pub(crate) compression_average: AvecStateDto,
325    pub(crate) rho_range: NumericRangeDto,
326    pub(crate) kappa_range: NumericRangeDto,
327    pub(crate) psi_range: NumericRangeDto,
328    pub(crate) rho_bands: ConfidenceBandSummaryDto,
329    pub(crate) kappa_bands: ConfidenceBandSummaryDto,
330}
331
332#[derive(Debug, Serialize)]
333#[serde(rename_all = "camelCase")]
334pub(crate) struct ScopeRekeyResultDto {
335    pub(crate) source_tenant_id: String,
336    pub(crate) source_session_id: String,
337    pub(crate) target_tenant_id: String,
338    pub(crate) target_session_id: String,
339    pub(crate) temporal_nodes: usize,
340    pub(crate) calibrations: usize,
341    pub(crate) target_temporal_nodes: usize,
342    pub(crate) target_calibrations: usize,
343    pub(crate) applied: bool,
344    pub(crate) conflict: bool,
345    pub(crate) message: Option<String>,
346}
347
348#[derive(Debug, Serialize)]
349#[serde(rename_all = "camelCase")]
350pub(crate) struct BatchRekeyResultDto {
351    pub(crate) dry_run: bool,
352    pub(crate) requested_node_ids: usize,
353    pub(crate) resolved_node_ids: usize,
354    pub(crate) missing_node_ids: Vec<String>,
355    pub(crate) scopes: Vec<ScopeRekeyResultDto>,
356    pub(crate) temporal_nodes_updated: usize,
357    pub(crate) calibrations_updated: usize,
358    pub(crate) updated_scopes: usize,
359    pub(crate) conflict_scopes: usize,
360}
361
362#[derive(Debug, Serialize)]
363#[serde(rename_all = "camelCase")]
364pub(crate) struct EmbeddingMigrationSampleDto {
365    pub(crate) sync_key: String,
366    pub(crate) session_id: String,
367    pub(crate) tier: String,
368    pub(crate) has_embedding: bool,
369    pub(crate) embedding_model: Option<String>,
370    pub(crate) embedding_dimensions: Option<usize>,
371    pub(crate) embedded_at: Option<DateTime<Utc>>,
372    pub(crate) updated_at: DateTime<Utc>,
373    pub(crate) context_summary: Option<String>,
374}
375
376#[derive(Debug, Serialize)]
377#[serde(rename_all = "camelCase")]
378pub(crate) struct EmbeddingMigrationPreviewResultDto {
379    pub(crate) total_candidates: usize,
380    pub(crate) sample: Vec<EmbeddingMigrationSampleDto>,
381    pub(crate) provider_available: bool,
382    pub(crate) provider_model: Option<String>,
383}
384
385#[derive(Debug, Serialize)]
386#[serde(rename_all = "camelCase")]
387pub(crate) struct EmbeddingMigrationRunResultDto {
388    pub(crate) scanned: usize,
389    pub(crate) selected: usize,
390    pub(crate) updated: usize,
391    pub(crate) skipped: usize,
392    pub(crate) failed: usize,
393    pub(crate) duplicate: usize,
394    pub(crate) started_at: DateTime<Utc>,
395    pub(crate) completed_at: DateTime<Utc>,
396    pub(crate) provider_model: Option<String>,
397    pub(crate) dry_run: bool,
398    pub(crate) mode: String,
399    pub(crate) failure_reasons: Vec<String>,
400}
401
402#[derive(Debug, Serialize)]
403pub(crate) struct GraphResponse {
404    pub(crate) sessions: Vec<serde_json::Value>,
405    pub(crate) nodes: Vec<serde_json::Value>,
406    pub(crate) edges: Vec<serde_json::Value>,
407    pub(crate) retrieved: usize,
408}
409
410pub(crate) type ApiResult<T> = Result<Json<T>, (axum::http::StatusCode, Json<ErrorResponse>)>;
411
412pub(crate) enum CorsAllowedOrigins {
413    Any,
414    Explicit(Vec<HeaderValue>),
415}