1use anyhow::Result;
7use compact_str::CompactString;
8use futures_core::Stream;
9pub use limits::default_context_limit;
10pub use message::{Message, MessageBuilder, Role, estimate_tokens};
11pub use request::Request;
12pub use response::{
13 Choice, CompletionMeta, CompletionTokensDetails, Delta, FinishReason, Response, Usage,
14};
15pub use stream::StreamChunk;
16pub use tool::{FunctionCall, Tool, ToolCall, ToolChoice};
17
18mod limits;
19mod message;
20mod request;
21mod response;
22mod stream;
23mod tool;
24
25pub trait Model: Sized + Clone {
34 fn send(&self, request: &Request) -> impl Future<Output = Result<Response>> + Send;
36
37 fn stream(&self, request: Request) -> impl Stream<Item = Result<StreamChunk>> + Send;
39
40 fn context_limit(&self, model: &str) -> usize {
44 default_context_limit(model)
45 }
46
47 fn active_model(&self) -> CompactString;
49}
50
51impl Model for () {
53 async fn send(&self, _request: &Request) -> Result<Response> {
54 panic!("NoopModel::send called — not intended for real LLM calls");
55 }
56
57 #[allow(unreachable_code)]
58 fn stream(&self, _request: Request) -> impl Stream<Item = Result<StreamChunk>> + Send {
59 panic!("NoopModel::stream called — not intended for real LLM calls");
60 async_stream::stream! {
61 yield Err(anyhow::anyhow!("not implemented"));
62 }
63 }
64
65 fn context_limit(&self, _model: &str) -> usize {
66 0
67 }
68
69 fn active_model(&self) -> CompactString {
70 CompactString::new("")
71 }
72}