fix(agent/sync): handle multiple /v1/models response formats
The upstream AI endpoint returns an OpenAI-compatible format, but the
response body parsing was fragile. Make it resilient:
1. Try standard OpenAI format: { "data": [{id}, ...] }
2. Try raw array: [{id}, ...]
3. Try alternate format: { "models": [{id}, ...] }
4. Log actual response body (first 500 chars) when all formats fail
Also adds a warning log with the raw response on parse failure so
future debugging is straightforward.
This commit is contained in:
parent
30713786bf
commit
a8e3b0f5a8
@ -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::<ModelsListResponse>(&body) {
|
||||
return Ok(parsed.data.into_iter().map(|m| m.id).collect());
|
||||
}
|
||||
|
||||
// Try raw array: [{"id": "..."}, ...]
|
||||
if let Ok(parsed) = serde_json::from_str::<Vec<ModelEntry>>(&body) {
|
||||
return Ok(parsed.into_iter().map(|m| m.id).collect());
|
||||
}
|
||||
|
||||
// Try { "models": [{"id": "..."}, ...] }
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ModelsAltResponse {
|
||||
models: Vec<ModelEntry>,
|
||||
}
|
||||
if let Ok(parsed) = serde_json::from_str::<ModelsAltResponse>(&body) {
|
||||
return Ok(parsed.models.into_iter().map(|m| m.id).collect());
|
||||
}
|
||||
|
||||
tracing::warn!(body = %body.chars().take(500).collect::<String>(), "list_accessible_models: unknown response format");
|
||||
Err(AppError::InternalServerError(format!(
|
||||
"unexpected /v1/models response format (first 200 chars): {}",
|
||||
body.chars().take(200).collect::<String>()
|
||||
)))
|
||||
}
|
||||
|
||||
impl AppService {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user