Skip to main content

a3s_code_core/llm/
mod.rs

1//! LLM client abstraction layer
2//!
3//! Provides a unified interface for interacting with LLM providers
4//! (Anthropic Claude, OpenAI, Zhipu AI GLM, and OpenAI-compatible providers).
5
6pub mod anthropic;
7pub mod factory;
8pub mod http;
9pub mod openai;
10pub mod structured;
11mod types;
12pub mod zhipu;
13
14// Re-export public types
15pub use anthropic::AnthropicClient;
16pub use factory::{create_client_with_config, LlmConfig};
17pub use http::{
18    clear_http_metrics_callback, default_http_client, set_http_metrics_callback, HttpClient,
19    HttpMetricsCallback, HttpMetricsRecord, HttpResponse, StreamingHttpResponse,
20};
21pub use openai::OpenAiClient;
22pub use types::*;
23pub use zhipu::ZhipuClient;
24
25use anyhow::Result;
26use async_trait::async_trait;
27use tokio::sync::mpsc;
28use tokio_util::sync::CancellationToken;
29
30/// LLM client trait
31#[async_trait]
32pub trait LlmClient: Send + Sync {
33    /// Complete a conversation (non-streaming)
34    async fn complete(
35        &self,
36        messages: &[Message],
37        system: Option<&str>,
38        tools: &[ToolDefinition],
39    ) -> Result<LlmResponse>;
40
41    /// Complete a conversation with streaming
42    /// Returns a receiver for streaming events.
43    /// The cancel_token is checked during the HTTP request; if cancelled, the request is aborted.
44    async fn complete_streaming(
45        &self,
46        messages: &[Message],
47        system: Option<&str>,
48        tools: &[ToolDefinition],
49        cancel_token: CancellationToken,
50    ) -> Result<mpsc::Receiver<StreamEvent>>;
51
52    /// Report the strongest provider-native structured-output enforcement this
53    /// client supports. Used by [`structured`] to decide whether to force a
54    /// tool call, request a native `response_format`, or fall back to
55    /// prompt-and-parse. Defaults to no native support.
56    fn native_structured_support(&self) -> structured::NativeStructuredSupport {
57        structured::NativeStructuredSupport::None
58    }
59
60    /// Complete a conversation while honoring a structured-output directive
61    /// (forced `tool_choice` and/or native `response_format`).
62    ///
63    /// The default implementation ignores the directive and behaves exactly
64    /// like [`LlmClient::complete`], so existing clients keep working unchanged;
65    /// providers that support native structured output override this.
66    async fn complete_structured(
67        &self,
68        messages: &[Message],
69        system: Option<&str>,
70        tools: &[ToolDefinition],
71        _directive: &structured::StructuredDirective,
72    ) -> Result<LlmResponse> {
73        self.complete(messages, system, tools).await
74    }
75
76    /// Streaming counterpart of [`LlmClient::complete_structured`]. Defaults to
77    /// [`LlmClient::complete_streaming`], ignoring the directive.
78    async fn complete_streaming_structured(
79        &self,
80        messages: &[Message],
81        system: Option<&str>,
82        tools: &[ToolDefinition],
83        _directive: &structured::StructuredDirective,
84        cancel_token: CancellationToken,
85    ) -> Result<mpsc::Receiver<StreamEvent>> {
86        self.complete_streaming(messages, system, tools, cancel_token)
87            .await
88    }
89}
90
91// Include test modules — these reference internal types via crate paths
92#[cfg(test)]
93#[path = "tests.rs"]
94mod tests_file;