Add async HTTP client wrapping the Ollama REST API with: - OllamaClient with generate, generate_stream, chat, embed, list_models, is_healthy - NDJSON streaming parser for /api/generate streaming responses - Serde types for all Ollama API endpoints - OllamaError enum with Http, Api, Deserialization, StreamIncomplete variants - OllamaClientConfig for timeout and connection pool settings - Integration into ModelGatewayServiceImpl (constructor now returns Result) - 48 tests (types serde, wiremock HTTP mocks, error handling, config) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
52 lines
1.4 KiB
Rust
52 lines
1.4 KiB
Rust
use thiserror::Error;
|
|
|
|
/// Errors that can occur when communicating with the Ollama API.
|
|
#[derive(Debug, Error)]
|
|
pub enum OllamaError {
|
|
/// HTTP-level error (connection refused, timeout, DNS, etc.).
|
|
#[error("HTTP error: {0}")]
|
|
Http(#[from] reqwest::Error),
|
|
|
|
/// Ollama returned a non-2xx status code.
|
|
#[error("Ollama API error (status {status}): {message}")]
|
|
Api { status: u16, message: String },
|
|
|
|
/// Failed to deserialize Ollama JSON response.
|
|
#[error("deserialization error: {0}")]
|
|
Deserialization(String),
|
|
|
|
/// Stream terminated unexpectedly without a done:true chunk.
|
|
#[error("stream ended unexpectedly")]
|
|
StreamIncomplete,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_error_display_api() {
|
|
let err = OllamaError::Api {
|
|
status: 404,
|
|
message: "model not found".to_string(),
|
|
};
|
|
let msg = format!("{err}");
|
|
assert!(msg.contains("404"));
|
|
assert!(msg.contains("model not found"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_error_display_deserialization() {
|
|
let err = OllamaError::Deserialization("unexpected EOF".to_string());
|
|
let msg = format!("{err}");
|
|
assert!(msg.contains("unexpected EOF"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_error_display_stream_incomplete() {
|
|
let err = OllamaError::StreamIncomplete;
|
|
let msg = format!("{err}");
|
|
assert!(msg.contains("stream ended unexpectedly"));
|
|
}
|
|
}
|