rover/summarizer/
backend.rs1use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5
6use crate::summarizer::error::BackendError;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub enum CompactMode {
12 Extractive,
13 Abstractive,
14 Headlines,
15}
16
17impl CompactMode {
18 pub fn as_str(self) -> &'static str {
20 match self {
21 CompactMode::Extractive => "extractive",
22 CompactMode::Abstractive => "abstractive",
23 CompactMode::Headlines => "headlines",
24 }
25 }
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
30#[serde(rename_all = "snake_case")]
31pub enum Style {
32 Bullet,
33 Prose,
34 Executive,
35}
36
37impl Style {
38 pub fn as_str(self) -> &'static str {
39 match self {
40 Style::Bullet => "bullet",
41 Style::Prose => "prose",
42 Style::Executive => "executive",
43 }
44 }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
49#[serde(rename_all = "snake_case")]
50pub enum PreserveSection {
51 Code,
52 Tables,
53 Quotes,
54 Lists,
55}
56
57impl PreserveSection {
58 pub fn as_str(self) -> &'static str {
59 match self {
60 PreserveSection::Code => "code",
61 PreserveSection::Tables => "tables",
62 PreserveSection::Quotes => "quotes",
63 PreserveSection::Lists => "lists",
64 }
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct CompactOpts {
82 pub mode: CompactMode,
83 pub style: Style,
84 pub target_tokens: Option<usize>,
85 pub focus: Option<String>,
86 pub preserve: Vec<PreserveSection>,
87 pub backend_name: String,
91}
92
93#[async_trait]
94pub trait SummarizerBackend: Send + Sync {
95 async fn compact(&self, content: &str, opts: &CompactOpts) -> Result<String, BackendError>;
96
97 fn name(&self) -> &str;
99
100 fn model_id(&self) -> &str {
105 ""
106 }
107
108 fn uses_model_prompt(&self) -> bool {
112 false
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn enums_round_trip_through_as_str() {
122 assert_eq!(CompactMode::Extractive.as_str(), "extractive");
123 assert_eq!(CompactMode::Abstractive.as_str(), "abstractive");
124 assert_eq!(CompactMode::Headlines.as_str(), "headlines");
125 assert_eq!(Style::Bullet.as_str(), "bullet");
126 assert_eq!(Style::Prose.as_str(), "prose");
127 assert_eq!(Style::Executive.as_str(), "executive");
128 assert_eq!(PreserveSection::Code.as_str(), "code");
129 }
130
131 #[test]
132 fn compact_opts_is_clonable() {
133 let o = CompactOpts {
134 mode: CompactMode::Abstractive,
135 style: Style::Prose,
136 target_tokens: Some(500),
137 focus: Some("api shape".to_string()),
138 preserve: vec![PreserveSection::Code],
139 backend_name: "fast".to_string(),
140 };
141 let cloned = o.clone();
142 assert_eq!(o, cloned);
143 }
144}