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}