Skip to main content

floopy/types/
export.rs

1use serde::Deserialize;
2
3/// One row of the decision export.
4#[derive(Debug, Clone, Deserialize)]
5pub struct ExportedDecisionRow {
6    /// The originating request id.
7    pub request_id: String,
8    /// Session the request belonged to, if any.
9    pub session_id: Option<String>,
10    /// Owning organization id.
11    pub organization_id: String,
12    /// Resolved upstream provider.
13    pub provider: Option<String>,
14    /// Resolved upstream model.
15    pub model: Option<String>,
16    /// Terminal status of the request.
17    pub status: String,
18    /// End-to-end latency in milliseconds.
19    pub latency_ms: Option<i64>,
20    /// Cost in micro-USD.
21    pub cost_micro_usd: Option<i64>,
22    /// Whether caching was enabled.
23    pub cache_enabled: Option<bool>,
24    /// Detected threat label, if any.
25    pub threat: Option<String>,
26    /// RFC3339 creation timestamp.
27    pub created_at: String,
28}
29
30/// The terminal record of the JSONL export: how many rows were emitted and
31/// whether the result was truncated.
32#[derive(Debug, Clone, Deserialize)]
33pub struct ExportTrailer {
34    /// Number of rows emitted before the trailer.
35    pub rows_emitted: i64,
36    /// Whether the export was truncated server-side.
37    pub truncated: bool,
38    /// Reason for truncation, if any.
39    pub reason: Option<String>,
40}
41
42/// Selects the export window and (server-side) format. The SDK always parses
43/// the JSONL stream; `format` is accepted for parity with the gateway.
44#[derive(Debug, Clone)]
45pub struct ExportDecisionsParams {
46    /// Inclusive lower bound (RFC3339). Required.
47    pub from: String,
48    /// Inclusive upper bound (RFC3339). Required.
49    pub to: String,
50    /// Optional server-side format hint (`"jsonl"` / `"csv"`).
51    pub format: Option<String>,
52}
53
54impl ExportDecisionsParams {
55    /// A window with the default (JSONL) format.
56    #[must_use]
57    pub fn new(from: impl Into<String>, to: impl Into<String>) -> Self {
58        Self {
59            from: from.into(),
60            to: to.into(),
61            format: None,
62        }
63    }
64
65    pub(crate) fn query(&self) -> Vec<(String, String)> {
66        let mut q = vec![
67            ("from".to_owned(), self.from.clone()),
68            ("to".to_owned(), self.to.clone()),
69        ];
70        if let Some(f) = &self.format {
71            q.push(("format".to_owned(), f.clone()));
72        }
73        q
74    }
75}