use cersei::prelude::*;
use cersei::provider::{CompletionStream, ProviderCapabilities};
use tokio::sync::mpsc;
struct EchoProvider;
#[async_trait]
impl Provider for EchoProvider {
fn name(&self) -> &str {
"echo"
}
fn context_window(&self, _model: &str) -> u64 {
4096
}
fn capabilities(&self, _model: &str) -> ProviderCapabilities {
ProviderCapabilities {
streaming: true,
tool_use: false, vision: false,
thinking: false,
system_prompt: true,
caching: false,
}
}
async fn complete(&self, request: CompletionRequest) -> cersei_types::Result<CompletionStream> {
let last_msg = request
.messages
.last()
.and_then(|m| m.get_text())
.unwrap_or("(empty)")
.to_string();
let response_text = format!(
"[Echo] Received: \"{}\"\nModel: {}\nSystem: {}\nTools available: {}",
last_msg,
request.model,
request.system.as_deref().unwrap_or("(none)"),
request.tools.len()
);
let (tx, rx) = mpsc::channel(16);
tokio::spawn(async move {
let _ = tx
.send(StreamEvent::MessageStart {
id: "echo-1".into(),
model: "echo".into(),
})
.await;
let _ = tx
.send(StreamEvent::ContentBlockStart {
index: 0,
block_type: "text".into(),
id: None,
name: None,
})
.await;
for word in response_text.split_inclusive(' ') {
let _ = tx
.send(StreamEvent::TextDelta {
index: 0,
text: word.to_string(),
})
.await;
tokio::time::sleep(std::time::Duration::from_millis(20)).await;
}
let _ = tx.send(StreamEvent::ContentBlockStop { index: 0 }).await;
let _ = tx
.send(StreamEvent::MessageDelta {
stop_reason: Some(StopReason::EndTurn),
usage: Some(Usage {
input_tokens: last_msg.len() as u64 / 4,
output_tokens: response_text.len() as u64 / 4,
..Default::default()
}),
})
.await;
let _ = tx.send(StreamEvent::MessageStop).await;
});
Ok(CompletionStream::new(rx))
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
println!("\x1b[36m── Echo Provider (mock) ──\x1b[0m\n");
let output = Agent::builder()
.provider(EchoProvider)
.tools(cersei::tools::filesystem())
.system_prompt("You are a test assistant.")
.max_turns(1)
.permission_policy(AllowAll)
.run_with("Hello from the custom provider example!")
.await?;
println!("{}", output.text());
println!(
"\nTurns: {}, Tokens: {}in/{}out",
output.turns, output.usage.input_tokens, output.usage.output_tokens
);
println!("\n\x1b[36m── OpenAI-Compatible Provider ──\x1b[0m\n");
println!("(Uncomment the Ollama section in the source to test with a local LLM)");
Ok(())
}