floopy/types/routing.rs
1use std::collections::HashMap;
2
3use async_openai::types::chat::ChatCompletionRequestMessage;
4use serde::{Deserialize, Serialize};
5
6/// Outcome of a routing dry-run.
7#[derive(Debug, Clone, Deserialize)]
8pub struct RoutingExplainResult {
9 /// Provider/model the gateway would route to, or `None` when the
10 /// firewall blocks the request.
11 pub would_select: Option<HashMap<String, String>>,
12 /// Firewall verdict (`"allow"` / `"block_input"`).
13 pub firewall_decision: String,
14 /// Firewall reasoning, if any.
15 pub reasoning: Option<String>,
16 /// Matched routing rule id, if any.
17 pub routing_rule_id: Option<String>,
18}
19
20/// Arguments for [`crate::resources::Routing::explain`]. `messages` reuses
21/// the `async-openai` request-message type, so a request can be dry-run
22/// before it is sent.
23#[derive(Debug, Clone, Serialize)]
24pub struct RoutingExplainParams {
25 /// Model to plan for.
26 pub model: String,
27 /// Conversation to plan for.
28 pub messages: Vec<ChatCompletionRequestMessage>,
29 /// Optional sampling temperature.
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub temperature: Option<f64>,
32 /// Optional legacy output-token cap. Prefer [`Self::max_completion_tokens`];
33 /// the gateway coerces this into `max_completion_tokens` before forwarding
34 /// to any `OpenAI`-compatible provider.
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub max_tokens: Option<u32>,
37 /// Optional canonical output-token cap (the current `OpenAI` standard).
38 /// Takes precedence over [`Self::max_tokens`] when both are set.
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub max_completion_tokens: Option<u32>,
41 /// Optional nucleus-sampling top-p.
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub top_p: Option<f64>,
44}
45
46impl RoutingExplainParams {
47 /// A dry-run for `model` over `messages` with default sampling.
48 #[must_use]
49 pub fn new(model: impl Into<String>, messages: Vec<ChatCompletionRequestMessage>) -> Self {
50 Self {
51 model: model.into(),
52 messages,
53 temperature: None,
54 max_tokens: None,
55 max_completion_tokens: None,
56 top_p: None,
57 }
58 }
59}