scribe_selection/
selector.rs1use crate::token_budget::apply_token_budget_selection;
6use scribe_core::{Config, FileInfo, Result};
7
8#[derive(Debug, Clone)]
10pub struct SelectionCriteria<'a> {
11 pub files: Vec<FileInfo>,
13 pub token_budget: usize,
15 pub config: &'a Config,
17}
18
19#[derive(Debug, Clone)]
21pub struct SelectionResult {
22 pub files: Vec<FileInfo>,
24 pub total_tokens_used: usize,
26 pub budget: usize,
28 pub unused_tokens: usize,
30 pub total_files_considered: usize,
32}
33
34impl SelectionResult {
35 pub fn file_paths(&self) -> Vec<String> {
37 self.files.iter().map(|f| f.relative_path.clone()).collect()
38 }
39}
40
41pub struct CodeSelector;
42
43impl CodeSelector {
44 pub fn new() -> Self {
45 Self
46 }
47
48 pub async fn select(&self, criteria: SelectionCriteria<'_>) -> Result<SelectionResult> {
49 let total_files_considered = criteria.files.len();
50 let budget = criteria.token_budget;
51
52 let files =
53 apply_token_budget_selection(criteria.files, criteria.token_budget, criteria.config)
54 .await?;
55
56 let total_tokens_used: usize = files.iter().filter_map(|f| f.token_estimate).sum();
57 let unused_tokens = budget.saturating_sub(total_tokens_used);
58
59 Ok(SelectionResult {
60 files,
61 total_tokens_used,
62 budget,
63 unused_tokens,
64 total_files_considered,
65 })
66 }
67}
68
69impl Default for CodeSelector {
70 fn default() -> Self {
71 Self::new()
72 }
73}