refactor: share token count utilities

This commit is contained in:
leookun
2026-08-24 23:41:16 +08:00
parent 5509ac45ca
commit b61059590f
4 changed files with 47 additions and 33 deletions
+2 -22
View File
@@ -14,7 +14,7 @@ use crate::{
proxy::{self, CursorProxy}, proxy::{self, CursorProxy},
CursorSessionRegistry, CursorSessionRegistry,
}, },
model::ProviderModel, model::{format_token_count, parse_token_count, ProviderModel},
Error, Result, Error, Result,
}; };
@@ -214,7 +214,7 @@ fn context_options(model: &ProviderModel) -> Vec<(String, String)> {
let value = tokens.to_string(); let value = tokens.to_string();
let duplicate = contexts let duplicate = contexts
.iter() .iter()
.any(|(existing, _)| parse_context_tokens(existing) == Some(tokens)); .any(|(existing, _)| parse_token_count(existing) == Some(tokens));
if !duplicate { if !duplicate {
contexts.push((value, format!("{} (Custom)", format_token_count(tokens)))); contexts.push((value, format!("{} (Custom)", format_token_count(tokens))));
} }
@@ -222,26 +222,6 @@ fn context_options(model: &ProviderModel) -> Vec<(String, String)> {
contexts contexts
} }
fn parse_context_tokens(value: &str) -> Option<u64> {
let value = value.trim().to_ascii_lowercase();
let (number, multiplier) = match value.chars().last()? {
'k' => (&value[..value.len() - 1], 1_000),
'm' => (&value[..value.len() - 1], 1_000_000),
_ => (value.as_str(), 1),
};
number.parse::<u64>().ok()?.checked_mul(multiplier)
}
fn format_token_count(tokens: u64) -> String {
if tokens >= 1_000_000 && tokens.is_multiple_of(1_000_000) {
format!("{}M", tokens / 1_000_000)
} else if tokens >= 1_000 && tokens.is_multiple_of(1_000) {
format!("{}K", tokens / 1_000)
} else {
tokens.to_string()
}
}
pub async fn available_models( pub async fn available_models(
State(registry): State<CursorSessionRegistry>, State(registry): State<CursorSessionRegistry>,
Extension(proxy): Extension<CursorProxy>, Extension(proxy): Extension<CursorProxy>,
+4 -11
View File
@@ -1,6 +1,9 @@
use crate::{ use crate::{
cursor::proto::agent::v1 as pb, cursor::proto::agent::v1 as pb,
model::{ModelLatency, ModelSpec, ReasoningSpec, SubagentKind, SubagentModelOverride}, model::{
parse_token_count, ModelLatency, ModelSpec, ReasoningSpec, SubagentKind,
SubagentModelOverride,
},
Error, Result, Error, Result,
}; };
@@ -136,16 +139,6 @@ fn parse_bool(parameter: &pb::requested_model::ModelParameterValue) -> Result<bo
} }
} }
fn parse_token_count(value: &str) -> Option<u64> {
let value = value.trim().to_ascii_lowercase();
let (number, multiplier) = match value.chars().last()? {
'k' => (&value[..value.len() - 1], 1_000),
'm' => (&value[..value.len() - 1], 1_000_000),
_ => (value.as_str(), 1),
};
number.parse::<u64>().ok()?.checked_mul(multiplier)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
+2
View File
@@ -9,6 +9,7 @@ mod projection;
mod provider; mod provider;
mod run; mod run;
mod runtime_tag; mod runtime_tag;
mod token_count;
mod tool; mod tool;
mod usage; mod usage;
@@ -23,5 +24,6 @@ pub use projection::*;
pub use provider::*; pub use provider::*;
pub use run::*; pub use run::*;
pub use runtime_tag::*; pub use runtime_tag::*;
pub(crate) use token_count::*;
pub use tool::*; pub use tool::*;
pub use usage::*; pub use usage::*;
+39
View File
@@ -0,0 +1,39 @@
pub(crate) fn parse_token_count(value: &str) -> Option<u64> {
let value = value.trim().to_ascii_lowercase();
let (number, multiplier) = match value.chars().last()? {
'k' => (&value[..value.len() - 1], 1_000),
'm' => (&value[..value.len() - 1], 1_000_000),
_ => (value.as_str(), 1),
};
number.parse::<u64>().ok()?.checked_mul(multiplier)
}
pub(crate) fn format_token_count(tokens: u64) -> String {
if tokens >= 1_000_000 && tokens.is_multiple_of(1_000_000) {
format!("{}M", tokens / 1_000_000)
} else if tokens >= 1_000 && tokens.is_multiple_of(1_000) {
format!("{}K", tokens / 1_000)
} else {
tokens.to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn token_counts_parse_plain_and_abbreviated_values() {
assert_eq!(parse_token_count("272000"), Some(272_000));
assert_eq!(parse_token_count("272K"), Some(272_000));
assert_eq!(parse_token_count("1m"), Some(1_000_000));
assert_eq!(parse_token_count("invalid"), None);
}
#[test]
fn token_counts_format_exact_thousands_and_millions() {
assert_eq!(format_token_count(272_000), "272K");
assert_eq!(format_token_count(1_000_000), "1M");
assert_eq!(format_token_count(272_001), "272001");
}
}