devsper_providers/
mock.rs1use devsper_core::{LlmProvider, LlmRequest, LlmResponse, StopReason};
2use anyhow::Result;
3use async_trait::async_trait;
4
5pub struct MockProvider {
7 pub response: String,
8}
9
10impl MockProvider {
11 pub fn new(response: impl Into<String>) -> Self {
12 Self {
13 response: response.into(),
14 }
15 }
16}
17
18#[async_trait]
19impl LlmProvider for MockProvider {
20 async fn generate(&self, req: LlmRequest) -> Result<LlmResponse> {
21 Ok(LlmResponse {
22 content: self.response.clone(),
23 tool_calls: vec![],
24 input_tokens: req
25 .messages
26 .iter()
27 .map(|m| m.content.len() as u32 / 4)
28 .sum(),
29 output_tokens: self.response.len() as u32 / 4,
30 model: req.model.clone(),
31 stop_reason: StopReason::EndTurn,
32 })
33 }
34
35 fn name(&self) -> &str {
36 "mock"
37 }
38
39 fn supports_model(&self, model: &str) -> bool {
40 model.starts_with("mock")
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use devsper_core::{LlmMessage, LlmRole};
48
49 #[tokio::test]
50 async fn mock_returns_canned_response() {
51 let p = MockProvider::new("hello world");
52 let req = LlmRequest {
53 model: "mock".to_string(),
54 messages: vec![LlmMessage {
55 role: LlmRole::User,
56 content: "hi".to_string(),
57 }],
58 tools: vec![],
59 max_tokens: None,
60 temperature: None,
61 system: None,
62 };
63 let res = p.generate(req).await.unwrap();
64 assert_eq!(res.content, "hello world");
65 assert_eq!(res.model, "mock");
66 }
67}