返回 CodeWhale
format_helpers.rs
根目录 / crates / tui / src / tui / format_helpers.rs
1 //! Small string builders that compose status-bar / footer chips and
2 //! one-off informational messages.
3 //!
4 //! Each helper is a pure function over a small slice of `App` or
5 //! response data. Grouped here so the composer/footer renderer doesn't
6 //! need to scroll past their bodies, and so the labels can be unit
7 //! tested in isolation.
8
9 use crate::models::Usage;
10
11 /// Build the multi-line "Cache warmup complete: …" status message
12 /// shown after a prefix-cache warmup turn finishes. Handles all four
13 /// combinations of `prompt_cache_hit_tokens` / `prompt_cache_miss_tokens`
14 /// being present or absent so we never report "0% cache hit" for an
15 /// API call that didn't surface telemetry at all.
16 pub(super) fn cache_warmup_result(usage: &Usage) -> String {
17 let cache = match (
18 usage.prompt_cache_hit_tokens,
19 usage.prompt_cache_miss_tokens,
20 ) {
21 (Some(hit), Some(miss)) => format!("Cache warmup complete: hit {hit} | miss {miss}"),
22 (Some(hit), None) => format!("Cache warmup complete: hit {hit} | miss unavailable"),
23 (None, Some(miss)) => format!("Cache warmup complete: hit unavailable | miss {miss}"),
24 (None, None) => "Cache warmup complete: cache telemetry unavailable".to_string(),
25 };
26 format!(
27 "{cache}\nNote: the first warmup is usually a miss. Later requests that reuse the same stable prefix may hit the provider cache; a hit is not guaranteed."
28 )
29 }
30
31 /// Render the response body for `/models` / `models list` — the current
32 /// model is starred and other available models follow underneath.
33 pub(super) fn available_models_message(current_model: &str, models: &[String]) -> String {
34 let mut lines = vec![format!("Available models ({})", models.len())];
35 for model in models {
36 if model == current_model {
37 lines.push(format!("* {model} (current)"));
38 } else {
39 lines.push(format!(" {model}"));
40 }
41 }
42 lines.join("\n")
43 }
44
45 #[cfg(test)]
46 mod tests {
47 use super::*;
48
49 #[test]
50 fn available_models_message_marks_current_model() {
51 let models = vec![
52 "deepseek-v4-pro".to_string(),
53 "deepseek-v4-flash".to_string(),
54 ];
55 let msg = available_models_message("deepseek-v4-pro", &models);
56 assert!(msg.contains("* deepseek-v4-pro (current)"), "got: {msg}");
57 assert!(msg.contains(" deepseek-v4-flash"), "got: {msg}");
58 assert!(msg.starts_with("Available models (2)"), "got: {msg}");
59 }
60
61 #[test]
62 fn cache_warmup_result_handles_missing_telemetry() {
63 let usage = Usage {
64 prompt_cache_hit_tokens: None,
65 prompt_cache_miss_tokens: None,
66 ..Default::default()
67 };
68 let msg = cache_warmup_result(&usage);
69 assert!(msg.contains("cache telemetry unavailable"), "got: {msg}");
70 }
71 }
72
72 lines RUST