diff --git a/libs/service/agent/sync.rs b/libs/service/agent/sync.rs index db92a58..020a903 100644 --- a/libs/service/agent/sync.rs +++ b/libs/service/agent/sync.rs @@ -680,6 +680,10 @@ struct ModelEntry { } /// List accessible model IDs from the AI endpoint. +/// Supports multiple response formats: +/// - OpenAI: `{ "data": [{"id": "..."}, ...] }` +/// - Array: `[{"id": "..."}, ...]` +/// - Custom: `{ "models": [{"id": "..."}, ...] }` async fn list_accessible_models( client: &reqwest::Client, base_url: &str, @@ -693,12 +697,35 @@ async fn list_accessible_models( .await .map_err(|e| AppError::InternalServerError(format!("failed to list models: {}", e)))?; - let body: ModelsListResponse = resp - .json() + let body = resp + .text() .await - .map_err(|e| AppError::InternalServerError(format!("failed to parse models response: {}", e)))?; + .map_err(|e| AppError::InternalServerError(format!("failed to read models body: {}", e)))?; - Ok(body.data.into_iter().map(|m| m.id).collect()) + // Try OpenAI format: { "data": [{"id": "..."}, ...] } + if let Ok(parsed) = serde_json::from_str::(&body) { + return Ok(parsed.data.into_iter().map(|m| m.id).collect()); + } + + // Try raw array: [{"id": "..."}, ...] + if let Ok(parsed) = serde_json::from_str::>(&body) { + return Ok(parsed.into_iter().map(|m| m.id).collect()); + } + + // Try { "models": [{"id": "..."}, ...] } + #[derive(Debug, Deserialize)] + struct ModelsAltResponse { + models: Vec, + } + if let Ok(parsed) = serde_json::from_str::(&body) { + return Ok(parsed.models.into_iter().map(|m| m.id).collect()); + } + + tracing::warn!(body = %body.chars().take(500).collect::(), "list_accessible_models: unknown response format"); + Err(AppError::InternalServerError(format!( + "unexpected /v1/models response format (first 200 chars): {}", + body.chars().take(200).collect::() + ))) } impl AppService {