Skip to content

Commit d625cb6

Browse files
committed
chore: eliminate duplication
1 parent f28266d commit d625cb6

File tree

2 files changed

+17
-45
lines changed

2 files changed

+17
-45
lines changed

crates/rullm-cli/src/args.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use clap_complete::engine::ArgValueCompleter;
77
use std::ffi::OsStr;
88

99
use crate::api_keys::ApiKeys;
10-
use crate::commands::models::load_cached_models;
10+
use crate::commands::models::load_models_cache;
1111
use crate::commands::{Commands, ModelsCache};
1212
use crate::config::{self, Config};
1313
use crate::constants::{BINARY_NAME, KEYS_CONFIG_FILE};
@@ -185,14 +185,16 @@ pub fn model_completer(current: &OsStr) -> Vec<CompletionCandidate> {
185185
// Predefined providers or aliases
186186
const PROVIDED: &[&str] = &["openai/", "anthropic/", "google/"];
187187

188+
let cli_config = CliConfig::load();
188189
let cur_str = current.to_string_lossy();
189190

190191
// If there is a slash already, offer all cached models that start with input
191192
if cur_str.contains('/') {
192193
if let Some((provider, _)) = cur_str.split_once('/') {
193194
// Load cached models
194-
if let Ok(entries) = load_cached_models() {
195+
if let Ok(Some(entries)) = load_models_cache(&cli_config) {
195196
let mut v: Vec<CompletionCandidate> = entries
197+
.models
196198
.into_iter()
197199
.filter(|m| m.starts_with(cur_str.as_ref()))
198200
.map(|m| m.into())

crates/rullm-cli/src/commands/models.rs

Lines changed: 13 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
use std::path::PathBuf;
2-
31
use anyhow::Result;
42
use chrono::Utc;
53
use clap::{Args, Subcommand};
64
use clap_complete::engine::ArgValueCompleter;
7-
use etcetera::BaseStrategy;
85
use rullm_core::{LlmError, SimpleLlm, SimpleLlmClient};
96

107
use crate::{
@@ -74,12 +71,12 @@ impl ModelsArgs {
7471
ModelsAction::Update { model } => {
7572
let model_str = resolve_model(&cli.model, model, &cli_config.config.default_model)?;
7673
let client = client::from_model(&model_str, cli, cli_config)?;
77-
update_models(&client, output_level)
74+
update_models(cli_config, &client, output_level)
7875
.await
7976
.map_err(anyhow::Error::from)?;
8077
}
8178
ModelsAction::Clear => {
82-
clear_models_cache(output_level)?;
79+
clear_models_cache(cli_config, output_level)?;
8380
}
8481
}
8582

@@ -106,7 +103,7 @@ pub fn show_cached_models(cli_config: &CliConfig, output_level: OutputLevel) ->
106103
}
107104

108105
// Check if cache is stale (older than 24 hours)
109-
if let Ok(Some(cache)) = load_models_cache() {
106+
if let Ok(Some(cache)) = load_models_cache(cli_config) {
110107
let now = Utc::now();
111108
let cache_age = now.signed_duration_since(cache.last_updated);
112109

@@ -150,10 +147,10 @@ pub async fn set_default_model(
150147
Ok(())
151148
}
152149

153-
pub fn clear_models_cache(output_level: OutputLevel) -> Result<()> {
150+
pub fn clear_models_cache(cli_config: &CliConfig, output_level: OutputLevel) -> Result<()> {
154151
use std::fs;
155152

156-
let path = get_models_cache_path()?;
153+
let path = cli_config.data_base_path.join(MODEL_FILE_NAME);
157154

158155
if path.exists() {
159156
fs::remove_file(&path)?;
@@ -166,6 +163,7 @@ pub fn clear_models_cache(output_level: OutputLevel) -> Result<()> {
166163
}
167164

168165
pub async fn update_models(
166+
cli_config: &mut CliConfig,
169167
client: &SimpleLlmClient,
170168
output_level: OutputLevel,
171169
) -> Result<(), LlmError> {
@@ -183,7 +181,7 @@ pub async fn update_models(
183181
&format!("Fetched {} models. Caching", models.len()),
184182
output_level,
185183
);
186-
if let Err(e) = cache_models(client.provider_name(), &models) {
184+
if let Err(e) = cache_models(cli_config, client.provider_name(), &models) {
187185
crate::output::error(&format!("Failed to cache: {e}"), output_level);
188186
}
189187
}
@@ -196,10 +194,12 @@ pub async fn update_models(
196194
Ok(())
197195
}
198196

199-
fn cache_models(provider_name: &str, models: &[String]) -> Result<()> {
197+
fn cache_models(cli_config: &CliConfig, provider_name: &str, models: &[String]) -> Result<()> {
200198
use std::fs;
201199

202-
let path = get_models_cache_path()?;
200+
let path = cli_config.data_base_path.join(MODEL_FILE_NAME);
201+
// TODO: we shouldn't need to do this here, this should be done while cli_config is created
202+
// TODO: Remove if we already do this.
203203
if let Some(parent) = path.parent() {
204204
fs::create_dir_all(parent)?;
205205
}
@@ -216,19 +216,10 @@ fn cache_models(provider_name: &str, models: &[String]) -> Result<()> {
216216
Ok(())
217217
}
218218

219-
/// Helper function to get models cache path, eliminating duplication
220-
fn get_models_cache_path() -> Result<PathBuf> {
221-
use crate::constants::BINARY_NAME;
222-
use etcetera::choose_base_strategy;
223-
224-
let strategy = choose_base_strategy()?;
225-
Ok(strategy.data_dir().join(BINARY_NAME).join(MODEL_FILE_NAME))
226-
}
227-
228-
pub(crate) fn load_models_cache() -> Result<Option<ModelsCache>> {
219+
pub(crate) fn load_models_cache(cli_config: &CliConfig) -> Result<Option<ModelsCache>> {
229220
use std::fs;
230221

231-
let path = get_models_cache_path()?;
222+
let path = cli_config.data_base_path.join(MODEL_FILE_NAME);
232223

233224
if !path.exists() {
234225
return Ok(None);
@@ -244,24 +235,3 @@ pub(crate) fn load_models_cache() -> Result<Option<ModelsCache>> {
244235
// Old format doesn't have timestamp info
245236
Ok(None)
246237
}
247-
248-
pub fn load_cached_models() -> Result<Vec<String>> {
249-
use std::fs;
250-
251-
let path = get_models_cache_path()?;
252-
253-
if !path.exists() {
254-
return Ok(Vec::new());
255-
}
256-
257-
let content = fs::read_to_string(path)?;
258-
259-
// Try to parse as new format first
260-
if let Ok(cache) = serde_json::from_str::<ModelsCache>(&content) {
261-
return Ok(cache.models);
262-
}
263-
264-
// Fallback to old format (simple array)
265-
let entries: Vec<String> = serde_json::from_str(&content)?;
266-
Ok(entries)
267-
}

0 commit comments

Comments
 (0)