fix(agent/sync): avoid double /v1/ prefix in model sync URL
When APP_AI_BASIC_URL already ends with /v1 (e.g. openrouter.ai/api/v1), appending /v1/models produces /v1/v1/models. Detect trailing /v1 and only append /models in that case.
This commit is contained in:
parent
c7a8bc0458
commit
283835eb26
@ -19,7 +19,12 @@ pub async fn list_accessible_models(
|
|||||||
base_url: &str,
|
base_url: &str,
|
||||||
api_key: &str,
|
api_key: &str,
|
||||||
) -> Result<std::collections::HashSet<String>, AgentError> {
|
) -> Result<std::collections::HashSet<String>, AgentError> {
|
||||||
let url = format!("{}/v1/models", base_url.trim_end_matches('/'));
|
let base = base_url.trim_end_matches('/');
|
||||||
|
let url = if base.ends_with("/v1") {
|
||||||
|
format!("{}/models", base)
|
||||||
|
} else {
|
||||||
|
format!("{}/v1/models", base)
|
||||||
|
};
|
||||||
let resp = client
|
let resp = client
|
||||||
.get(&url)
|
.get(&url)
|
||||||
.header("Authorization", format!("Bearer {}", api_key))
|
.header("Authorization", format!("Bearer {}", api_key))
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
//! Synchronizes AI model metadata from the upstream AI endpoint
|
//! Synchronizes AI model metadata from the upstream AI endpoint
|
||||||
//! (`GET /v1/models`) into the local database.
|
//! (`GET /v1/models`) into the local database.
|
||||||
//!
|
//!
|
||||||
@ -495,10 +496,9 @@ async fn sync_models_from_upstream(
|
|||||||
pricing_created += 1;
|
pricing_created += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
capabilities_created +=
|
capabilities_created += upsert_capabilities(db, version_record.id, &model)
|
||||||
upsert_capabilities(db, version_record.id, &model)
|
.await
|
||||||
.await
|
.unwrap_or(0);
|
||||||
.unwrap_or(0);
|
|
||||||
|
|
||||||
if upsert_parameter_profile(db, version_record.id, &model)
|
if upsert_parameter_profile(db, version_record.id, &model)
|
||||||
.await
|
.await
|
||||||
@ -526,7 +526,12 @@ async fn list_upstream_models(
|
|||||||
base_url: &str,
|
base_url: &str,
|
||||||
api_key: &str,
|
api_key: &str,
|
||||||
) -> Result<Vec<UpstreamModel>, AppError> {
|
) -> Result<Vec<UpstreamModel>, AppError> {
|
||||||
let url = format!("{}/v1/models", base_url.trim_end_matches('/'));
|
let base = base_url.trim_end_matches('/');
|
||||||
|
let url = if base.ends_with("/v1") {
|
||||||
|
format!("{}/models", base)
|
||||||
|
} else {
|
||||||
|
format!("{}/v1/models", base)
|
||||||
|
};
|
||||||
let resp = client
|
let resp = client
|
||||||
.get(&url)
|
.get(&url)
|
||||||
.header("Authorization", format!("Bearer {}", api_key))
|
.header("Authorization", format!("Bearer {}", api_key))
|
||||||
@ -559,7 +564,9 @@ async fn list_upstream_models(
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_ai_client(config: &config::AppConfig) -> Result<(reqwest::Client, String, String), AppError> {
|
fn build_ai_client(
|
||||||
|
config: &config::AppConfig,
|
||||||
|
) -> Result<(reqwest::Client, String, String), AppError> {
|
||||||
let api_key = config
|
let api_key = config
|
||||||
.ai_api_key()
|
.ai_api_key()
|
||||||
.map_err(|e| AppError::InternalServerError(format!("AI API key not configured: {}", e)))?;
|
.map_err(|e| AppError::InternalServerError(format!("AI API key not configured: {}", e)))?;
|
||||||
@ -638,18 +645,15 @@ impl AppService {
|
|||||||
|
|
||||||
/// Perform a single sync pass. Errors are logged and silently swallowed
|
/// Perform a single sync pass. Errors are logged and silently swallowed
|
||||||
/// so the periodic task never stops.
|
/// so the periodic task never stops.
|
||||||
async fn sync_once(
|
async fn sync_once(db: &AppDatabase, ai_api_key: Option<String>, ai_base_url: Option<String>) {
|
||||||
db: &AppDatabase,
|
let (http_client, base_url, api_key) =
|
||||||
ai_api_key: Option<String>,
|
match build_ai_client_from_parts(ai_api_key, ai_base_url) {
|
||||||
ai_base_url: Option<String>,
|
Ok(c) => c,
|
||||||
) {
|
Err(msg) => {
|
||||||
let (http_client, base_url, api_key) = match build_ai_client_from_parts(ai_api_key, ai_base_url) {
|
tracing::warn!(error = %msg, "Model sync: AI client config error");
|
||||||
Ok(c) => c,
|
return;
|
||||||
Err(msg) => {
|
}
|
||||||
tracing::warn!(error = %msg, "Model sync: AI client config error");
|
};
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let upstream_models = match list_upstream_models(&http_client, &base_url, &api_key).await {
|
let upstream_models = match list_upstream_models(&http_client, &base_url, &api_key).await {
|
||||||
Ok(models) => models,
|
Ok(models) => models,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user