1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
8pub struct ChoiceQuestion {
9 pub instructions: String,
10 pub criteria: HashMap<String, String>,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
15pub struct ScoreQuestion {
16 pub instructions: String,
17 pub criteria: Vec<String>,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
22pub struct NoulQuestion {
23 pub instructions: String,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
28#[serde(tag = "type")]
29pub enum Question {
30 #[serde(rename = "choice")]
31 Choice(ChoiceQuestion),
32 #[serde(rename = "score")]
33 Score(ScoreQuestion),
34 #[serde(rename = "noul")]
35 Noul(NoulQuestion),
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
40pub struct ChoiceAnswer {
41 pub choice: String,
42 pub confidence: f64,
43 #[serde(default)]
44 pub probabilities: Option<HashMap<String, f64>>,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
49pub struct ScoreAnswer {
50 pub score: f64,
52 pub confidence: f64,
53 #[serde(default)]
55 pub legend: Option<serde_json::Value>,
56 #[serde(default)]
57 pub probabilities: Option<HashMap<String, f64>>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
62pub struct NoulAnswer {
63 pub noul: f64,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
68#[serde(tag = "type")]
69pub enum Answer {
70 #[serde(rename = "choice")]
71 Choice(ChoiceAnswer),
72 #[serde(rename = "score")]
73 Score(ScoreAnswer),
74 #[serde(rename = "noul")]
75 Noul(NoulAnswer),
76}
77
78impl Answer {
79 pub fn as_choice(&self) -> Option<&ChoiceAnswer> {
80 match self {
81 Answer::Choice(a) => Some(a),
82 _ => None,
83 }
84 }
85
86 pub fn as_score(&self) -> Option<&ScoreAnswer> {
87 match self {
88 Answer::Score(a) => Some(a),
89 _ => None,
90 }
91 }
92
93 pub fn as_noul(&self) -> Option<&NoulAnswer> {
94 match self {
95 Answer::Noul(a) => Some(a),
96 _ => None,
97 }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
103pub struct JevUsage {
104 #[serde(default)]
105 pub input_tokens: u32,
106 #[serde(default)]
107 pub output_tokens: u32,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
112pub struct JevResponse {
113 pub model: String,
114 pub answers: HashMap<String, Answer>,
115 #[serde(default)]
116 pub usage: JevUsage,
117 #[serde(default)]
118 pub is_mock: bool,
119 #[serde(default)]
121 pub degraded_reason: String,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
126pub struct TestTriageResult {
127 pub category: String,
128 pub confidence: f64,
129 pub skip_llm: bool,
130 pub skip_llm_prob: f64,
131 pub severity_score: f64,
132 pub action_recommendation: String,
133 pub recommendation: String,
134 pub is_mock: bool,
135 #[serde(default)]
137 pub degraded_reason: String,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
142pub struct AbortGateResult {
143 pub should_abort: bool,
144 pub abort_probability: f64,
145 pub action: String,
146 pub viability_score: f64,
147 pub reasoning_summary: String,
148 pub summary: String,
149 pub is_mock: bool,
150 #[serde(default)]
152 pub degraded_reason: String,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
157pub struct ModelRouteResult {
158 pub selected_tier: String,
159 pub confidence: f64,
160 pub complexity_score: f64,
161 pub recommended_model: String,
162 pub rationale: String,
163 pub is_mock: bool,
164 #[serde(default)]
166 pub degraded_reason: String,
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
171pub struct VerificationResult {
172 pub is_verified: bool,
173 pub satisfaction_probability: f64,
174 pub rigor_score: f64,
175 pub confidence: f64,
176 pub needs_rework: bool,
177 pub is_mock: bool,
178 #[serde(default)]
180 pub degraded_reason: String,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
185pub struct ReasoningEffortResult {
186 pub effort: String,
187 pub confidence: f64,
188 pub complexity_score: f64,
189 pub rationale: String,
190 pub provider: String,
191 pub provider_params: serde_json::Value,
192 pub is_reasoning_supported: bool,
193 pub cache_safe_recommendation: String,
194 pub lease_steps: u32,
195 pub is_mock: bool,
196 #[serde(default)]
198 pub degraded_reason: String,
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
203pub struct NudgeGateResult {
204 pub should_nudge: bool,
205 pub nudge_probability: f64,
206 pub waiting_probability: f64,
207 pub progress_probability: f64,
208 pub workflow_phase: String,
209 pub suggested_nudge_prompt: String,
210 pub rationale: String,
211 pub is_mock: bool,
212 #[serde(default)]
214 pub degraded_reason: String,
215}
216
217#[derive(Debug)]
219pub enum JevError {
220 Http(reqwest::Error),
221 Json(serde_json::Error),
222 Config(String),
223 Api { status: u16, message: String },
224}
225
226impl std::fmt::Display for JevError {
227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 match self {
229 JevError::Http(e) => write!(f, "HTTP error: {}", e),
230 JevError::Json(e) => write!(f, "JSON serialization error: {}", e),
231 JevError::Config(m) => write!(f, "Configuration error: {}", m),
232 JevError::Api { status, message } => {
233 write!(f, "API error (HTTP {}): {}", status, message)
234 }
235 }
236 }
237}
238
239impl std::error::Error for JevError {}
240
241impl From<reqwest::Error> for JevError {
242 fn from(e: reqwest::Error) -> Self {
243 JevError::Http(e)
244 }
245}
246
247impl From<serde_json::Error> for JevError {
248 fn from(e: serde_json::Error) -> Self {
249 JevError::Json(e)
250 }
251}